ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/BasiliskII/src/Unix/video_x.cpp
(Generate patch)

Comparing BasiliskII/src/Unix/video_x.cpp (file contents):
Revision 1.1 by cebix, 1999-10-03T14:16:25Z vs.
Revision 1.15 by cebix, 2000-07-13T13:47:12Z

# Line 1 | Line 1
1   /*
2   *  video_x.cpp - Video/graphics emulation, X11 specific stuff
3   *
4 < *  Basilisk II (C) 1997-1999 Christian Bauer
4 > *  Basilisk II (C) 1997-2000 Christian Bauer
5   *
6   *  This program is free software; you can redistribute it and/or modify
7   *  it under the terms of the GNU General Public License as published by
# Line 34 | Line 34
34   #include <X11/extensions/XShm.h>
35   #include <sys/ipc.h>
36   #include <sys/shm.h>
37 #include <pthread.h>
37   #include <errno.h>
38  
39 + #ifdef HAVE_PTHREADS
40 + # include <pthread.h>
41 + #endif
42 +
43 + #ifdef ENABLE_XF86_DGA
44 + # include <X11/extensions/xf86dga.h>
45 + #endif
46 +
47 + #ifdef ENABLE_XF86_VIDMODE
48 + # include <X11/extensions/xf86vmode.h>
49 + #endif
50 +
51 + #ifdef ENABLE_FBDEV_DGA
52 + # include <sys/mman.h>
53 + #endif
54 +
55   #include "cpu_emulation.h"
56   #include "main.h"
57   #include "adb.h"
# Line 48 | Line 63
63   #define DEBUG 1
64   #include "debug.h"
65  
51 #if ENABLE_DGA
52 #include <X11/extensions/xf86dga.h>
53 #endif
54
66  
67   // Display types
68   enum {
# Line 59 | Line 70 | enum {
70          DISPLAY_DGA             // DGA fullscreen display
71   };
72  
62
73   // Constants
74 < const char KEYCODE_FILE_NAME[] = "/usr/local/lib/basilisk_ii_keycodes";
74 > const char KEYCODE_FILE_NAME[] = DATADIR "/keycodes";
75 > const char FBDEVICES_FILE_NAME[] = DATADIR "/fbdevices";
76  
77  
78   // Global variables
79 < static int32 frame_skip;
79 > static int32 frame_skip;                                                        // Prefs items
80 > static int16 mouse_wheel_mode = 1;
81 > static int16 mouse_wheel_lines = 3;
82 >
83   static int display_type = DISPLAY_WINDOW;                       // See enum above
84   static uint8 *the_buffer;                                                       // Mac frame buffer
85 +
86 + #ifdef HAVE_PTHREADS
87   static bool redraw_thread_active = false;                       // Flag: Redraw thread installed
88   static volatile bool redraw_thread_cancel = false;      // Flag: Cancel Redraw thread
89   static pthread_t redraw_thread;                                         // Redraw thread
90 + #endif
91  
92   static bool has_dga = false;                                            // Flag: Video DGA capable
93 + static bool has_vidmode = false;                                        // Flag: VidMode extension available
94  
95   static bool ctrl_down = false;                                          // Flag: Ctrl key pressed
96 + static bool caps_on = false;                                            // Flag: Caps Lock on
97   static bool quit_full_screen = false;                           // Flag: DGA close requested from redraw thread
98   static bool emerg_quit = false;                                         // Flag: Ctrl-Esc pressed, emergency quit requested from MacOS thread
99   static bool emul_suspended = false;                                     // Flag: Emulator suspended
# Line 98 | Line 117 | static int eventmask;
117   static const int win_eventmask = KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask | PointerMotionMask | EnterWindowMask | ExposureMask;
118   static const int dga_eventmask = KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask | PointerMotionMask;
119  
101 static pthread_mutex_t palette_lock = PTHREAD_MUTEX_INITIALIZER;        // Mutex to protect palette
120   static XColor palette[256];                                                     // Color palette for 8-bit mode
121   static bool palette_changed = false;                            // Flag: Palette changed, redraw thread must set new colors
122 + #ifdef HAVE_PTHREADS
123 + static pthread_mutex_t palette_lock = PTHREAD_MUTEX_INITIALIZER;        // Mutex to protect palette
124 + #endif
125  
126   // Variables for window mode
127   static GC the_gc;
# Line 113 | Line 134 | static GC cursor_gc, cursor_mask_gc;
134   static uint8 *the_buffer_copy = NULL;                           // Copy of Mac frame buffer
135   static uint8 the_cursor[64];                                            // Cursor image data
136   static bool have_shm = false;                                           // Flag: SHM extensions available
137 + static bool updt_box[17][17];                                           // Flag for Update
138 + static int nr_boxes;
139 + static const int sm_uptd[] = {4,1,6,3,0,5,2,7};
140 + static int sm_no_boxes[] = {1,8,32,64,128,300};
141  
142 < // Variables for DGA mode
142 > // Variables for XF86 DGA mode
143   static int current_dga_cmap;                                            // Number (0 or 1) of currently installed DGA colormap
144   static Window suspend_win;                                                      // "Suspend" window
145   static void *fb_save = NULL;                                            // Saved frame buffer for suspend
146 <
146 > #ifdef HAVE_PTHREADS
147   static pthread_mutex_t frame_buffer_lock = PTHREAD_MUTEX_INITIALIZER;   // Mutex to protect frame buffer
148 + #endif
149 +
150 + // Variables for fbdev DGA mode
151 + const char FBDEVICE_FILE_NAME[] = "/dev/fb";
152 + static int fbdev_fd;
153 +
154 + #ifdef ENABLE_XF86_VIDMODE
155 + // Variables for XF86 VidMode support
156 + static XF86VidModeModeInfo **x_video_modes;                     // Array of all available modes
157 + static int num_x_video_modes;
158 + #endif
159  
160  
161   // Prototypes
# Line 141 | Line 177 | extern void SysMountFirstFloppy(void);
177   // Set VideoMonitor according to video mode
178   void set_video_monitor(int width, int height, int bytes_per_row, bool native_byte_order)
179   {
180 <        int layout;
180 > #if !REAL_ADDRESSING
181 >        int layout = FLAYOUT_DIRECT;
182          switch (depth) {
183                  case 1:
184                          layout = FLAYOUT_DIRECT;
148                        VideoMonitor.mode = VMODE_1BIT;
185                          break;
186                  case 8:
187                          layout = FLAYOUT_DIRECT;
152                        VideoMonitor.mode = VMODE_8BIT;
188                          break;
189                  case 15:
190                          layout = FLAYOUT_HOST_555;
156                        VideoMonitor.mode = VMODE_16BIT;
191                          break;
192                  case 16:
193                          layout = FLAYOUT_HOST_565;
160                        VideoMonitor.mode = VMODE_16BIT;
194                          break;
195                  case 24:
196                  case 32:
197                          layout = FLAYOUT_HOST_888;
165                        VideoMonitor.mode = VMODE_32BIT;
198                          break;
199          }
168        VideoMonitor.x = width;
169        VideoMonitor.y = height;
170        VideoMonitor.bytes_per_row = bytes_per_row;
200          if (native_byte_order)
201                  MacFrameLayout = layout;
202          else
203                  MacFrameLayout = FLAYOUT_DIRECT;
204 + #endif
205 +        switch (depth) {
206 +                case 1:
207 +                        VideoMonitor.mode = VMODE_1BIT;
208 +                        break;
209 +                case 8:
210 +                        VideoMonitor.mode = VMODE_8BIT;
211 +                        break;
212 +                case 15:
213 +                        VideoMonitor.mode = VMODE_16BIT;
214 +                        break;
215 +                case 16:
216 +                        VideoMonitor.mode = VMODE_16BIT;
217 +                        break;
218 +                case 24:
219 +                case 32:
220 +                        VideoMonitor.mode = VMODE_32BIT;
221 +                        break;
222 +        }
223 +        VideoMonitor.x = width;
224 +        VideoMonitor.y = height;
225 +        VideoMonitor.bytes_per_row = bytes_per_row;
226   }
227  
228   // Trap SHM errors
# Line 190 | Line 241 | static int error_handler(Display *d, XEr
241   // Init window mode
242   static bool init_window(int width, int height)
243   {
244 +        int aligned_width = (width + 15) & ~15;
245 +        int aligned_height = (height + 15) & ~15;
246 +
247          // Set absolute mouse mode
248          ADBSetRelMouseMode(false);
249  
# Line 203 | Line 257 | static bool init_window(int width, int h
257          wattr.event_mask = eventmask = win_eventmask;
258          wattr.background_pixel = black_pixel;
259          wattr.border_pixel = black_pixel;
260 <        wattr.backing_store = Always;
260 >        wattr.backing_store = NotUseful;
261 >        wattr.save_under = false;
262          wattr.backing_planes = xdepth;
263  
264          XSync(x_display, false);
# Line 232 | Line 287 | static bool init_window(int width, int h
287                  XSetWMNormalHints(x_display, the_win, hints);
288                  XFree((char *)hints);
289          }
290 <
290 >        
291          // Try to create and attach SHM image
292          have_shm = false;
293          if (depth != 1 && XShmQueryExtension(x_display)) {
294  
295                  // Create SHM image ("height + 2" for safety)
296                  img = XShmCreateImage(x_display, vis, depth, depth == 1 ? XYBitmap : ZPixmap, 0, &shminfo, width, height);
297 <                shminfo.shmid = shmget(IPC_PRIVATE, (height + 2) * img->bytes_per_line, IPC_CREAT | 0777);
298 <                the_buffer = (uint8 *)shmat(shminfo.shmid, 0, 0);
299 <                shminfo.shmaddr = img->data = (char *)the_buffer;
297 >                shminfo.shmid = shmget(IPC_PRIVATE, (aligned_height + 2) * img->bytes_per_line, IPC_CREAT | 0777);
298 >                the_buffer_copy = (uint8 *)shmat(shminfo.shmid, 0, 0);
299 >                shminfo.shmaddr = img->data = (char *)the_buffer_copy;
300                  shminfo.readOnly = False;
301  
302                  // Try to attach SHM image, catching errors
# Line 259 | Line 314 | static bool init_window(int width, int h
314                          shmctl(shminfo.shmid, IPC_RMID, 0);
315                  }
316          }
317 <
317 >        
318          // Create normal X image if SHM doesn't work ("height + 2" for safety)
319          if (!have_shm) {
320 <                int bytes_per_row = width;
320 >                int bytes_per_row = aligned_width;
321                  switch (depth) {
322                          case 1:
323                                  bytes_per_row /= 8;
# Line 276 | Line 331 | static bool init_window(int width, int h
331                                  bytes_per_row *= 4;
332                                  break;
333                  }
334 <                the_buffer = (uint8 *)malloc((height + 2) * bytes_per_row);
335 <                img = XCreateImage(x_display, vis, depth, depth == 1 ? XYBitmap : ZPixmap, 0, (char *)the_buffer, width, height, 32, bytes_per_row);
334 >                the_buffer_copy = (uint8 *)malloc((aligned_height + 2) * bytes_per_row);
335 >                img = XCreateImage(x_display, vis, depth, depth == 1 ? XYBitmap : ZPixmap, 0, (char *)the_buffer_copy, aligned_width, aligned_height, 32, bytes_per_row);
336          }
337  
338          // 1-Bit mode is big-endian
# Line 287 | Line 342 | static bool init_window(int width, int h
342          }
343  
344          // Allocate memory for frame buffer copy
345 <        the_buffer_copy = (uint8 *)malloc((height + 2) * img->bytes_per_line);
345 >        the_buffer = (uint8 *)malloc((aligned_height + 2) * img->bytes_per_line);
346  
347          // Create GC
348          the_gc = XCreateGC(x_display, the_win, 0, 0);
349          XSetState(x_display, the_gc, black_pixel, white_pixel, GXcopy, AllPlanes);
350  
351 <        // Create cursor
352 <        cursor_image = XCreateImage(x_display, vis, 1, XYPixmap, 0, (char *)the_cursor, 16, 16, 16, 2);
353 <        cursor_image->byte_order = MSBFirst;
354 <        cursor_image->bitmap_bit_order = MSBFirst;
355 <        cursor_mask_image = XCreateImage(x_display, vis, 1, XYPixmap, 0, (char *)the_cursor+32, 16, 16, 16, 2);
356 <        cursor_mask_image->byte_order = MSBFirst;
302 <        cursor_mask_image->bitmap_bit_order = MSBFirst;
303 <        cursor_map = XCreatePixmap(x_display, the_win, 16, 16, 1);
304 <        cursor_mask_map = XCreatePixmap(x_display, the_win, 16, 16, 1);
305 <        cursor_gc = XCreateGC(x_display, cursor_map, 0, 0);
306 <        cursor_mask_gc = XCreateGC(x_display, cursor_mask_map, 0, 0);
307 <        mac_cursor = XCreatePixmapCursor(x_display, cursor_map, cursor_mask_map, &black, &white, 0, 0);
351 >        // Create no_cursor
352 >        mac_cursor = XCreatePixmapCursor (x_display,
353 >                                           XCreatePixmap (x_display, the_win, 1, 1, 1),
354 >                                           XCreatePixmap (x_display, the_win, 1, 1, 1),
355 >                                           &black, &white, 0, 0);
356 >        XDefineCursor (x_display, the_win, mac_cursor);
357  
358          // Set VideoMonitor
359   #ifdef WORDS_BIGENDIAN
# Line 312 | Line 361 | static bool init_window(int width, int h
361   #else
362          set_video_monitor(width, height, img->bytes_per_line, img->bitmap_bit_order == LSBFirst);
363   #endif
364 +        
365   #if REAL_ADDRESSING
366          VideoMonitor.mac_frame_base = (uint32)the_buffer;
317        MacFrameLayout = FLAYOUT_DIRECT;
367   #else
368          VideoMonitor.mac_frame_base = MacFrameBaseMac;
369   #endif
370          return true;
371   }
372  
373 < // Init DGA display
374 < static bool init_dga(int width, int height)
373 > // Init fbdev DGA display
374 > static bool init_fbdev_dga(char *in_fb_name)
375   {
376 < #if ENABLE_DGA
376 > #ifdef ENABLE_FBDEV_DGA
377 >        // Find the maximum depth available
378 >        int ndepths, max_depth(0);
379 >        int *depths = XListDepths(x_display, screen, &ndepths);
380 >        if (depths == NULL) {
381 >                printf("FATAL: Could not determine the maximal depth available\n");
382 >                return false;
383 >        } else {
384 >                while (ndepths-- > 0) {
385 >                        if (depths[ndepths] > max_depth)
386 >                                max_depth = depths[ndepths];
387 >                }
388 >        }
389 >        
390 >        // Get fbdevices file path from preferences
391 >        const char *fbd_path = PrefsFindString("fbdevicefile");
392 >        
393 >        // Open fbdevices file
394 >        FILE *fp = fopen(fbd_path ? fbd_path : FBDEVICES_FILE_NAME, "r");
395 >        if (fp == NULL) {
396 >                char str[256];
397 >                sprintf(str, GetString(STR_NO_FBDEVICE_FILE_ERR), fbd_path ? fbd_path : FBDEVICES_FILE_NAME, strerror(errno));
398 >                ErrorAlert(str);
399 >                return false;
400 >        }
401 >        
402 >        int fb_depth;           // supported depth
403 >        uint32 fb_offset;       // offset used for mmap(2)
404 >        char fb_name[20];
405 >        char line[256];
406 >        bool device_found = false;
407 >        while (fgets(line, 255, fp)) {
408 >                // Read line
409 >                int len = strlen(line);
410 >                if (len == 0)
411 >                        continue;
412 >                line[len - 1] = '\0';
413 >                
414 >                // Comments begin with "#" or ";"
415 >                if ((line[0] == '#') || (line[0] == ';') || (line[0] == '\0'))
416 >                        continue;
417 >                
418 >                if ((sscanf(line, "%19s %d %x", &fb_name, &fb_depth, &fb_offset) == 3)
419 >                && (strcmp(fb_name, in_fb_name) == 0) && (fb_depth == max_depth)) {
420 >                        device_found = true;
421 >                        break;
422 >                }
423 >        }
424 >        
425 >        // fbdevices file completely read
426 >        fclose(fp);
427 >        
428 >        // Frame buffer name not found ? Then, display warning
429 >        if (!device_found) {
430 >                char str[256];
431 >                sprintf(str, GetString(STR_FBDEV_NAME_ERR), in_fb_name, max_depth);
432 >                ErrorAlert(str);
433 >                return false;
434 >        }
435 >        
436 >        int width = DisplayWidth(x_display, screen);
437 >        int height = DisplayHeight(x_display, screen);
438 >        depth = fb_depth; // max_depth
439 >        
440 >        // Set relative mouse mode
441 >        ADBSetRelMouseMode(false);
442 >        
443 >        // Create window
444 >        XSetWindowAttributes wattr;
445 >        wattr.override_redirect = True;
446 >        wattr.backing_store             = NotUseful;
447 >        wattr.background_pixel  = white_pixel;
448 >        wattr.border_pixel              = black_pixel;
449 >        wattr.event_mask                = eventmask = dga_eventmask;
450 >        
451 >        XSync(x_display, false);
452 >        the_win = XCreateWindow(x_display, rootwin,
453 >                0, 0, width, height,
454 >                0, xdepth, InputOutput, vis,
455 >                CWEventMask|CWBackPixel|CWBorderPixel|CWOverrideRedirect|CWBackingStore,
456 >                &wattr);
457 >        XSync(x_display, false);
458 >        XMapRaised(x_display, the_win);
459 >        XSync(x_display, false);
460 >        
461 >        // Grab mouse and keyboard
462 >        XGrabKeyboard(x_display, the_win, True,
463 >                GrabModeAsync, GrabModeAsync, CurrentTime);
464 >        XGrabPointer(x_display, the_win, True,
465 >                PointerMotionMask | ButtonPressMask | ButtonReleaseMask,
466 >                GrabModeAsync, GrabModeAsync, the_win, None, CurrentTime);
467 >        
468 >        // Set colormap
469 >        if (depth == 8) {
470 >                XSetWindowColormap(x_display, the_win, cmap[0]);
471 >                XSetWMColormapWindows(x_display, the_win, &the_win, 1);
472 >        }
473 >        
474 >        // Set VideoMonitor
475 >        int bytes_per_row = width;
476 >        switch (depth) {
477 >                case 1:
478 >                        bytes_per_row = ((width | 7) & ~7) >> 3;
479 >                        break;
480 >                case 15:
481 >                case 16:
482 >                        bytes_per_row *= 2;
483 >                        break;
484 >                case 24:
485 >                case 32:
486 >                        bytes_per_row *= 4;
487 >                        break;
488 >        }
489 >        
490 >        if ((the_buffer = (uint8 *) mmap(NULL, height * bytes_per_row, PROT_READ | PROT_WRITE, MAP_PRIVATE, fbdev_fd, fb_offset)) == MAP_FAILED) {
491 >                if ((the_buffer = (uint8 *) mmap(NULL, height * bytes_per_row, PROT_READ | PROT_WRITE, MAP_SHARED, fbdev_fd, fb_offset)) == MAP_FAILED) {
492 >                        char str[256];
493 >                        sprintf(str, GetString(STR_FBDEV_MMAP_ERR), strerror(errno));
494 >                        ErrorAlert(str);
495 >                        return false;
496 >                }
497 >        }
498 >        
499 >        set_video_monitor(width, height, bytes_per_row, true);
500 > #if REAL_ADDRESSING
501 >        VideoMonitor.mac_frame_base = (uint32)the_buffer;
502 > #else
503 >        VideoMonitor.mac_frame_base = MacFrameBaseMac;
504 > #endif
505 >        return true;
506 > #else
507 >        ErrorAlert("Basilisk II has been compiled with fbdev DGA support disabled.");
508 >        return false;
509 > #endif
510 > }
511 >
512 > // Init XF86 DGA display
513 > static bool init_xf86_dga(int width, int height)
514 > {
515 > #ifdef ENABLE_XF86_DGA
516          // Set relative mouse mode
517          ADBSetRelMouseMode(true);
518  
519 + #ifdef ENABLE_XF86_VIDMODE
520 +        // Switch to best mode
521 +        if (has_vidmode) {
522 +                int best = 0;
523 +                for (int i=1; i<num_x_video_modes; i++) {
524 +                        if (x_video_modes[i]->hdisplay >= width && x_video_modes[i]->vdisplay >= height &&
525 +                                x_video_modes[i]->hdisplay <= x_video_modes[best]->hdisplay && x_video_modes[i]->vdisplay <= x_video_modes[best]->vdisplay) {
526 +                                best = i;
527 +                        }
528 +                }
529 +                XF86VidModeSwitchToMode(x_display, screen, x_video_modes[best]);
530 +                XF86VidModeSetViewPort(x_display, screen, 0, 0);
531 +        }
532 + #endif
533 +
534          // Create window
535          XSetWindowAttributes wattr;
536          wattr.event_mask = eventmask = dga_eventmask;
# Line 385 | Line 588 | static bool init_dga(int width, int heig
588   #endif
589          return true;
590   #else
591 <        ErrorAlert("Basilisk II has been compiled with DGA support disabled.");
591 >        ErrorAlert("Basilisk II has been compiled with XF86 DGA support disabled.");
592          return false;
593   #endif
594   }
# Line 460 | Line 663 | bool VideoInit(bool classic)
663          // Init keycode translation
664          keycode_init();
665  
666 +        // Read prefs
667 +        mouse_wheel_mode = PrefsFindInt16("mousewheelmode");
668 +        mouse_wheel_lines = PrefsFindInt16("mousewheellines");
669 +
670          // Find screen and root window
671          screen = XDefaultScreen(x_display);
672          rootwin = XRootWindow(x_display, screen);
673 <
673 >        
674          // Get screen depth
675          xdepth = DefaultDepth(x_display, screen);
676 +        
677 + #ifdef ENABLE_FBDEV_DGA
678 +        // Frame buffer name
679 +        char fb_name[20];
680 +        
681 +        // Could do fbdev dga ?
682 +        if ((fbdev_fd = open(FBDEVICE_FILE_NAME, O_RDWR)) != -1)
683 +                has_dga = true;
684 +        else
685 +                has_dga = false;
686 + #endif
687  
688 < #if ENABLE_DGA
688 > #ifdef ENABLE_XF86_DGA
689          // DGA available?
690 <        int dga_flags = 0;
691 <        XF86DGAQueryDirectVideo(x_display, screen, &dga_flags);
692 <        has_dga = dga_flags & XF86DGADirectPresent;
690 >        int dga_event_base, dga_error_base;
691 >        if (XF86DGAQueryExtension(x_display, &dga_event_base, &dga_error_base)) {
692 >                int dga_flags = 0;
693 >                XF86DGAQueryDirectVideo(x_display, screen, &dga_flags);
694 >                has_dga = dga_flags & XF86DGADirectPresent;
695 >        } else
696 >                has_dga = false;
697   #endif
698  
699 + #ifdef ENABLE_XF86_VIDMODE
700 +        // VidMode available?
701 +        int vm_event_base, vm_error_base;
702 +        has_vidmode = XF86VidModeQueryExtension(x_display, &vm_event_base, &vm_error_base);
703 +        if (has_vidmode)
704 +                XF86VidModeGetAllModeLines(x_display, screen, &num_x_video_modes, &x_video_modes);
705 + #endif
706 +        
707          // Find black and white colors
708          XParseColor(x_display, DefaultColormap(x_display, screen), "rgb:00/00/00", &black);
709          XAllocColor(x_display, DefaultColormap(x_display, screen), &black);
# Line 539 | Line 769 | bool VideoInit(bool classic)
769          if (mode_str) {
770                  if (sscanf(mode_str, "win/%d/%d", &width, &height) == 2)
771                          display_type = DISPLAY_WINDOW;
772 <                else if (has_dga && strcmp(mode_str, "dga") == 0) {
772 > #ifdef ENABLE_FBDEV_DGA
773 >                else if (has_dga && sscanf(mode_str, "dga/%19s", fb_name) == 1) {
774 > #else
775 >                else if (has_dga && sscanf(mode_str, "dga/%d/%d", &width, &height) == 2) {
776 > #endif
777                          display_type = DISPLAY_DGA;
778 +                        if (width > DisplayWidth(x_display, screen))
779 +                                width = DisplayWidth(x_display, screen);
780 +                        if (height > DisplayHeight(x_display, screen))
781 +                                height = DisplayHeight(x_display, screen);
782 +                }
783 +                if (width <= 0)
784                          width = DisplayWidth(x_display, screen);
785 +                if (height <= 0)
786                          height = DisplayHeight(x_display, screen);
546                }
787          }
788  
789          // Initialize according to display type
# Line 553 | Line 793 | bool VideoInit(bool classic)
793                                  return false;
794                          break;
795                  case DISPLAY_DGA:
796 <                        if (!init_dga(width, height))
796 > #ifdef ENABLE_FBDEV_DGA
797 >                        if (!init_fbdev_dga(fb_name))
798 > #else
799 >                        if (!init_xf86_dga(width, height))
800 > #endif
801                                  return false;
802                          break;
803          }
804  
805 + #ifdef HAVE_PTHREADS
806          // Lock down frame buffer
807          pthread_mutex_lock(&frame_buffer_lock);
808 + #endif
809  
810   #if !REAL_ADDRESSING
811          // Set variables for UAE memory mapping
# Line 571 | Line 817 | bool VideoInit(bool classic)
817                  MacFrameLayout = FLAYOUT_NONE;
818   #endif
819  
574        // Start redraw/input thread
820          XSync(x_display, false);
821 +
822 + #ifdef HAVE_PTHREADS
823 +        // Start redraw/input thread
824          redraw_thread_active = (pthread_create(&redraw_thread, NULL, redraw_func, NULL) == 0);
825 <        if (!redraw_thread_active)
825 >        if (!redraw_thread_active) {
826                  printf("FATAL: cannot create redraw thread\n");
827 <        return redraw_thread_active;
827 >                return false;
828 >        }
829 > #endif
830 >        return true;
831   }
832  
833  
# Line 586 | Line 837 | bool VideoInit(bool classic)
837  
838   void VideoExit(void)
839   {
840 + #ifdef HAVE_PTHREADS
841          // Stop redraw thread
842          if (redraw_thread_active) {
843                  redraw_thread_cancel = true;
# Line 595 | Line 847 | void VideoExit(void)
847                  pthread_join(redraw_thread, NULL);
848                  redraw_thread_active = false;
849          }
850 + #endif
851  
852 + #ifdef HAVE_PTHREADS
853          // Unlock frame buffer
854          pthread_mutex_unlock(&frame_buffer_lock);
855 + #endif
856  
857          // Close window and server connection
858          if (x_display != NULL) {
859                  XSync(x_display, false);
860  
861 < #if ENABLE_DGA
861 > #ifdef ENABLE_XF86_DGA
862                  if (display_type == DISPLAY_DGA) {
863                          XF86DGADirectVideo(x_display, screen, 0);
864                          XUngrabPointer(x_display, CurrentTime);
# Line 611 | Line 866 | void VideoExit(void)
866                  }
867   #endif
868  
869 <                if (the_buffer_copy) {
870 <                        free(the_buffer_copy);
871 <                        the_buffer_copy = NULL;
869 > #ifdef ENABLE_XF86_VIDMODE
870 >                if (has_vidmode && display_type == DISPLAY_DGA)
871 >                        XF86VidModeSwitchToMode(x_display, screen, x_video_modes[0]);
872 > #endif
873 >
874 > #ifdef ENABLE_FBDEV_DGA
875 >                if (display_type == DISPLAY_DGA) {
876 >                        XUngrabPointer(x_display, CurrentTime);
877 >                        XUngrabKeyboard(x_display, CurrentTime);
878 >                        close(fbdev_fd);
879                  }
880 + #endif
881  
882                  XFlush(x_display);
883                  XSync(x_display, false);
# Line 622 | Line 885 | void VideoExit(void)
885                          XFreeColormap(x_display, cmap[0]);
886                          XFreeColormap(x_display, cmap[1]);
887                  }
888 +
889 +                if (the_buffer) {
890 +                        free(the_buffer);
891 +                        the_buffer = NULL;
892 +                }
893 +
894 +                if (!have_shm && the_buffer_copy) {
895 +                        free(the_buffer_copy);
896 +                        the_buffer_copy = NULL;
897 +                }
898          }
899   }
900  
# Line 648 | Line 921 | void VideoInterrupt(void)
921          if (emerg_quit)
922                  QuitEmulator();
923  
924 + #ifdef HAVE_PTHREADS
925          // Temporarily give up frame buffer lock (this is the point where
926          // we are suspended when the user presses Ctrl-Tab)
927          pthread_mutex_unlock(&frame_buffer_lock);
928          pthread_mutex_lock(&frame_buffer_lock);
929 + #endif
930   }
931  
932  
# Line 661 | Line 936 | void VideoInterrupt(void)
936  
937   void video_set_palette(uint8 *pal)
938   {
939 + #ifdef HAVE_PTHREDS
940          pthread_mutex_lock(&palette_lock);
941 + #endif
942  
943          // Convert colors to XColor array
944          for (int i=0; i<256; i++) {
# Line 675 | Line 952 | void video_set_palette(uint8 *pal)
952          // Tell redraw thread to change palette
953          palette_changed = true;
954  
955 + #ifdef HAVE_PTHREADS
956          pthread_mutex_unlock(&palette_lock);
957 + #endif
958   }
959  
960  
# Line 683 | Line 962 | void video_set_palette(uint8 *pal)
962   *  Suspend/resume emulator
963   */
964  
965 < #if ENABLE_DGA
965 > #if defined(ENABLE_XF86_DGA) || defined(ENABLE_FBDEV_DGA)
966   static void suspend_emul(void)
967   {
968          if (display_type == DISPLAY_DGA) {
# Line 691 | Line 970 | static void suspend_emul(void)
970                  ADBKeyUp(0x36);
971                  ctrl_down = false;
972  
973 + #ifdef HAVE_PTHREADS
974                  // Lock frame buffer (this will stop the MacOS thread)
975                  pthread_mutex_lock(&frame_buffer_lock);
976 + #endif
977  
978                  // Save frame buffer
979                  fb_save = malloc(VideoMonitor.y * VideoMonitor.bytes_per_row);
# Line 700 | Line 981 | static void suspend_emul(void)
981                          memcpy(fb_save, the_buffer, VideoMonitor.y * VideoMonitor.bytes_per_row);
982  
983                  // Close full screen display
984 + #ifdef ENABLE_XF86_DGA
985                  XF86DGADirectVideo(x_display, screen, 0);
986 + #endif
987                  XUngrabPointer(x_display, CurrentTime);
988                  XUngrabKeyboard(x_display, CurrentTime);
989                  XUnmapWindow(x_display, the_win);
# Line 714 | Line 997 | static void suspend_emul(void)
997                  wattr.backing_store = Always;
998                  wattr.backing_planes = xdepth;
999                  wattr.colormap = DefaultColormap(x_display, screen);
1000 +                
1001                  XSync(x_display, false);
1002                  suspend_win = XCreateWindow(x_display, rootwin, 0, 0, 512, 1, 0, xdepth,
1003                          InputOutput, vis, CWEventMask | CWBackPixel | CWBorderPixel |
# Line 738 | Line 1022 | static void resume_emul(void)
1022          XSync(x_display, false);
1023          XGrabKeyboard(x_display, rootwin, 1, GrabModeAsync, GrabModeAsync, CurrentTime);
1024          XGrabPointer(x_display, rootwin, 1, PointerMotionMask | ButtonPressMask | ButtonReleaseMask, GrabModeAsync, GrabModeAsync, None, None, CurrentTime);
1025 + #ifdef ENABLE_XF86_DGA
1026          XF86DGADirectVideo(x_display, screen, XF86DGADirectGraphics | XF86DGADirectKeyb | XF86DGADirectMouse);
1027          XF86DGASetViewPort(x_display, screen, 0, 0);
1028 + #endif
1029          XSync(x_display, false);
1030  
1031          // Restore frame buffer
# Line 748 | Line 1034 | static void resume_emul(void)
1034                  free(fb_save);
1035                  fb_save = NULL;
1036          }
1037 +        
1038 + #ifdef ENABLE_XF86_DGA
1039          if (depth == 8)
1040                  XF86DGAInstallColormap(x_display, screen, cmap[current_dga_cmap]);
1041 + #endif
1042  
1043 + #ifdef HAVE_PTHREADS
1044          // Unlock frame buffer (and continue MacOS thread)
1045          pthread_mutex_unlock(&frame_buffer_lock);
1046          emul_suspended = false;
1047 + #endif
1048   }
1049   #endif
1050  
# Line 815 | Line 1106 | static int kc_decode(KeySym ks)
1106                  case XK_period: case XK_greater: return 0x2f;
1107                  case XK_slash: case XK_question: return 0x2c;
1108  
1109 < #if ENABLE_DGA
1109 > #if defined(ENABLE_XF86_DGA) || defined(ENABLE_FBDEV_DGA)
1110                  case XK_Tab: if (ctrl_down) {suspend_emul(); return -1;} else return 0x30;
1111   #else
1112                  case XK_Tab: return 0x30;
# Line 941 | Line 1232 | static void handle_events(void)
1232                                  unsigned int button = ((XButtonEvent *)&event)->button;
1233                                  if (button < 4)
1234                                          ADBMouseDown(button - 1);
1235 +                                else if (button < 6) {  // Wheel mouse
1236 +                                        if (mouse_wheel_mode == 0) {
1237 +                                                int key = (button == 5) ? 0x79 : 0x74;  // Page up/down
1238 +                                                ADBKeyDown(key);
1239 +                                                ADBKeyUp(key);
1240 +                                        } else {
1241 +                                                int key = (button == 5) ? 0x3d : 0x3e;  // Cursor up/down
1242 +                                                for(int i=0; i<mouse_wheel_lines; i++) {
1243 +                                                        ADBKeyDown(key);
1244 +                                                        ADBKeyUp(key);
1245 +                                                }
1246 +                                        }
1247 +                                }
1248                                  break;
1249                          }
1250                          case ButtonRelease: {
# Line 968 | Line 1272 | static void handle_events(void)
1272                                          code = event2keycode((XKeyEvent *)&event);
1273                                  if (code != -1) {
1274                                          if (!emul_suspended) {
1275 <                                                ADBKeyDown(code);
1275 >                                                if (code == 0x39) {     // Caps Lock pressed
1276 >                                                        if (caps_on) {
1277 >                                                                ADBKeyUp(code);
1278 >                                                                caps_on = false;
1279 >                                                        } else {
1280 >                                                                ADBKeyDown(code);
1281 >                                                                caps_on = true;
1282 >                                                        }
1283 >                                                } else
1284 >                                                        ADBKeyDown(code);
1285                                                  if (code == 0x36)
1286                                                          ctrl_down = true;
1287                                          } else {
1288 < #if ENABLE_DGA
1288 > #if defined(ENABLE_XF86_DGA) || defined(ENABLE_FBDEV_DGA)
1289                                                  if (code == 0x31)
1290                                                          resume_emul();  // Space wakes us up
1291   #endif
# Line 987 | Line 1300 | static void handle_events(void)
1300                                          code = keycode_table[((XKeyEvent *)&event)->keycode & 0xff];
1301                                  } else
1302                                          code = event2keycode((XKeyEvent *)&event);
1303 <                                if (code != -1) {
1303 >                                if (code != -1 && code != 0x39) {       // Don't propagate Caps Lock releases
1304                                          ADBKeyUp(code);
1305                                          if (code == 0x36)
1306                                                  ctrl_down = false;
# Line 997 | Line 1310 | static void handle_events(void)
1310  
1311                          // Hidden parts exposed, force complete refresh of window
1312                          case Expose:
1313 <                                if (display_type == DISPLAY_WINDOW)
1314 <                                        memset(the_buffer_copy, 0, VideoMonitor.bytes_per_row * VideoMonitor.y);
1313 >                                if (display_type == DISPLAY_WINDOW) {
1314 >                                        int x1, y1;
1315 >                                        for (y1=0; y1<16; y1++)
1316 >                                        for (x1=0; x1<16; x1++)
1317 >                                                updt_box[x1][y1] = true;
1318 >                                        nr_boxes = 16 * 16;
1319 >                                }
1320                                  break;
1321                  }
1322          }
# Line 1009 | Line 1327 | static void handle_events(void)
1327   *  Window display update
1328   */
1329  
1330 < static void update_display(void)
1330 > static void update_display(int ticker)
1331   {
1332 <        // In classic mode, copy the frame buffer from Mac RAM
1333 <        if (classic_mode)
1334 <                memcpy(the_buffer, Mac2HostAddr(0x3fa700), VideoMonitor.bytes_per_row * VideoMonitor.y);
1017 <
1018 <        // Incremental update code
1019 <        int wide = 0, high = 0, x1, x2, y1, y2, i, j;
1332 >        int y1, y2, y2s, y2a, i, x1, xm, xmo, ymo, yo, yi, yil, xic, xicl, xi;
1333 >        int xil = 0;
1334 >        int rxm = 0, rxmo = 0;
1335          int bytes_per_row = VideoMonitor.bytes_per_row;
1336          int bytes_per_pixel = VideoMonitor.bytes_per_row / VideoMonitor.x;
1337 <        uint8 *p, *p2;
1338 <
1339 <        // Check for first line from top and first line from bottom that have changed
1340 <        y1 = 0;
1341 <        for (j=0; j<VideoMonitor.y; j++) {
1342 <                if (memcmp(&the_buffer[j * bytes_per_row], &the_buffer_copy[j * bytes_per_row], bytes_per_row)) {
1343 <                        y1 = j;
1344 <                        break;
1030 <                }
1031 <        }
1032 <        y2 = y1 - 1;
1033 <        for (j=VideoMonitor.y-1; j>=y1; j--) {
1034 <                if (memcmp(&the_buffer[j * bytes_per_row], &the_buffer_copy[j * bytes_per_row], bytes_per_row)) {
1035 <                        y2 = j;
1337 >        int rx = VideoMonitor.bytes_per_row / 16;
1338 >        int ry = VideoMonitor.y / 16;
1339 >        int max_box;
1340 >
1341 >        y2s = sm_uptd[ticker % 8];
1342 >        y2a = 8;
1343 >        for (i = 0; i < 6; i++)
1344 >                if (ticker % (2 << i))
1345                          break;
1346 <                }
1038 <        }
1039 <        high = y2 - y1 + 1;
1346 >        max_box = sm_no_boxes[i];
1347  
1348 <        // Check for first column from left and first column from right that have changed
1349 <        if (high) {
1350 <                if (depth == 1) {
1351 <                        x1 = VideoMonitor.x;
1352 <                        for (j=y1; j<=y2; j++) {
1353 <                                p = &the_buffer[j * bytes_per_row];
1354 <                                p2 = &the_buffer_copy[j * bytes_per_row];
1355 <                                for (i=0; i<(x1>>3); i++) {
1356 <                                        if (*p != *p2) {
1357 <                                                x1 = i << 3;
1051 <                                                break;
1348 >        if (y2a) {
1349 >                for (y1=0; y1<16; y1++) {
1350 >                        for (y2=y2s; y2 < ry; y2 += y2a) {
1351 >                                i = ((y1 * ry) + y2) * bytes_per_row;
1352 >                                for (x1=0; x1<16; x1++, i += rx) {
1353 >                                        if (updt_box[x1][y1] == false) {
1354 >                                                if (memcmp(&the_buffer_copy[i], &the_buffer[i], rx)) {
1355 >                                                        updt_box[x1][y1] = true;
1356 >                                                        nr_boxes++;
1357 >                                                }
1358                                          }
1053                                        p++;
1054                                        p2++;
1359                                  }
1360                          }
1361 <                        x2 = x1;
1362 <                        for (j=y1; j<=y2; j++) {
1059 <                                p = &the_buffer[j * bytes_per_row];
1060 <                                p2 = &the_buffer_copy[j * bytes_per_row];
1061 <                                p += bytes_per_row;
1062 <                                p2 += bytes_per_row;
1063 <                                for (i=(VideoMonitor.x>>3); i>(x2>>3); i--) {
1064 <                                        p--;
1065 <                                        p2--;
1066 <                                        if (*p != *p2) {
1067 <                                                x2 = i << 3;
1068 <                                                break;
1069 <                                        }
1070 <                                }
1071 <                        }
1072 <                        wide = x2 - x1;
1361 >                }
1362 >        }
1363  
1364 <                        // Update copy of the_buffer
1365 <                        if (high && wide) {
1366 <                                for (j=y1; j<=y2; j++) {
1367 <                                        i = j * bytes_per_row + (x1 >> 3);
1368 <                                        memcpy(&the_buffer_copy[i], &the_buffer[i], wide >> 3);
1364 >        if ((nr_boxes <= max_box) && (nr_boxes)) {
1365 >                for (y1=0; y1<16; y1++) {
1366 >                        for (x1=0; x1<16; x1++) {
1367 >                                if (updt_box[x1][y1] == true) {
1368 >                                        if (rxm == 0)
1369 >                                                xm = x1;
1370 >                                        rxm += rx;
1371 >                                        updt_box[x1][y1] = false;
1372                                  }
1373 <                        }
1374 <
1375 <                } else {
1376 <                        x1 = VideoMonitor.x;
1377 <                        for (j=y1; j<=y2; j++) {
1378 <                                p = &the_buffer[j * bytes_per_row];
1379 <                                p2 = &the_buffer_copy[j * bytes_per_row];
1380 <                                for (i=0; i<x1; i++) {
1381 <                                        if (memcmp(p, p2, bytes_per_pixel)) {
1382 <                                                x1 = i;
1383 <                                                break;
1373 >                                if (((updt_box[x1+1][y1] == false) || (x1 == 15)) && (rxm)) {
1374 >                                        if ((rxmo != rxm) || (xmo != xm) || (yo != y1 - 1)) {
1375 >                                                if (rxmo) {
1376 >                                                        xi = xmo * rx;
1377 >                                                        yi = ymo * ry;
1378 >                                                        xil = rxmo;
1379 >                                                        yil = (yo - ymo +1) * ry;
1380 >                                                }
1381 >                                                rxmo = rxm;
1382 >                                                xmo = xm;
1383 >                                                ymo = y1;
1384                                          }
1385 <                                        p += bytes_per_pixel;
1386 <                                        p2 += bytes_per_pixel;
1387 <                                }
1388 <                        }
1389 <                        x2 = x1;
1390 <                        for (j=y1; j<=y2; j++) {
1391 <                                p = &the_buffer[j * bytes_per_row];
1392 <                                p2 = &the_buffer_copy[j * bytes_per_row];
1393 <                                p += bytes_per_row;
1394 <                                p2 += bytes_per_row;
1395 <                                for (i=VideoMonitor.x; i>x2; i--) {
1396 <                                        p -= bytes_per_pixel;
1397 <                                        p2 -= bytes_per_pixel;
1398 <                                        if (memcmp(p, p2, bytes_per_pixel)) {
1399 <                                                x2 = i;
1400 <                                                break;
1385 >                                        rxm = 0;
1386 >                                        yo = y1;
1387 >                                }      
1388 >                                if (xil) {
1389 >                                        i = (yi * bytes_per_row) + xi;
1390 >                                        for (y2=0; y2 < yil; y2++, i += bytes_per_row)
1391 >                                                memcpy(&the_buffer_copy[i], &the_buffer[i], xil);
1392 >                                        if (depth == 1) {
1393 >                                                if (have_shm)
1394 >                                                        XShmPutImage(x_display, the_win, the_gc, img, xi * 8, yi, xi * 8, yi, xil * 8, yil, 0);
1395 >                                                else
1396 >                                                        XPutImage(x_display, the_win, the_gc, img, xi * 8, yi, xi * 8, yi, xil * 8, yil);
1397 >                                        } else {
1398 >                                                if (have_shm)
1399 >                                                        XShmPutImage(x_display, the_win, the_gc, img, xi / bytes_per_pixel, yi, xi / bytes_per_pixel, yi, xil / bytes_per_pixel, yil, 0);
1400 >                                                else
1401 >                                                        XPutImage(x_display, the_win, the_gc, img, xi / bytes_per_pixel, yi, xi / bytes_per_pixel, yi, xil / bytes_per_pixel, yil);
1402                                          }
1403 +                                        xil = 0;
1404                                  }
1405 <                        }
1406 <                        wide = x2 - x1;
1407 <
1408 <                        // Update copy of the_buffer
1409 <                        if (high && wide) {
1410 <                                for (j=y1; j<=y2; j++) {
1411 <                                        i = j * bytes_per_row + x1 * bytes_per_pixel;
1117 <                                        memcpy(&the_buffer_copy[i], &the_buffer[i], bytes_per_pixel * wide);
1405 >                                if ((x1 == 15) && (y1 == 15) && (rxmo)) {
1406 >                                        x1--;
1407 >                                        xi = xmo * rx;
1408 >                                        yi = ymo * ry;
1409 >                                        xil = rxmo;
1410 >                                        yil = (yo - ymo +1) * ry;
1411 >                                        rxmo = 0;
1412                                  }
1413                          }
1414                  }
1415 <        }
1122 <
1123 <        // Refresh display
1124 <        if (high && wide) {
1125 <                if (have_shm)
1126 <                        XShmPutImage(x_display, the_win, the_gc, img, x1, y1, x1, y1, wide, high, 0);
1127 <                else
1128 <                        XPutImage(x_display, the_win, the_gc, img, x1, y1, x1, y1, wide, high);
1129 <        }
1130 <
1131 <        // Has the Mac started? (cursor data is not valid otherwise)
1132 <        if (HasMacStarted()) {
1133 <
1134 <                // Set new cursor image if it was changed
1135 <                if (memcmp(the_cursor, Mac2HostAddr(0x844), 64)) {
1136 <                        memcpy(the_cursor, Mac2HostAddr(0x844), 64);
1137 <                        memcpy(cursor_image->data, the_cursor, 32);
1138 <                        memcpy(cursor_mask_image->data, the_cursor+32, 32);
1139 <                        XFreeCursor(x_display, mac_cursor);
1140 <                        XPutImage(x_display, cursor_map, cursor_gc, cursor_image, 0, 0, 0, 0, 16, 16);
1141 <                        XPutImage(x_display, cursor_mask_map, cursor_mask_gc, cursor_mask_image, 0, 0, 0, 0, 16, 16);
1142 <                        mac_cursor = XCreatePixmapCursor(x_display, cursor_map, cursor_mask_map, &black, &white, ReadMacInt8(0x885), ReadMacInt8(0x887));
1143 <                        XDefineCursor(x_display, the_win, mac_cursor);
1144 <                }
1415 >                nr_boxes = 0;
1416          }
1417   }
1418  
# Line 1150 | Line 1421 | static void update_display(void)
1421   *  Thread for screen refresh, input handling etc.
1422   */
1423  
1424 < static void *redraw_func(void *arg)
1424 > void VideoRefresh(void)
1425   {
1426 <        int tick_counter = 0;
1426 > #if defined(ENABLE_XF86_DGA) || defined(ENABLE_FBDEV_DGA)
1427 >        // Quit DGA mode if requested
1428 >        if (quit_full_screen) {
1429 >                quit_full_screen = false;
1430 >                if (display_type == DISPLAY_DGA) {
1431 > #ifdef ENABLE_XF86_DGA
1432 >                        XF86DGADirectVideo(x_display, screen, 0);
1433 > #endif
1434 >                        XUngrabPointer(x_display, CurrentTime);
1435 >                        XUngrabKeyboard(x_display, CurrentTime);
1436 >                        XUnmapWindow(x_display, the_win);
1437 >                        XSync(x_display, false);
1438 >                }
1439 >        }
1440 > #endif
1441  
1442 <        while (!redraw_thread_cancel) {
1442 >        // Handle X events
1443 >        handle_events();
1444  
1445 <                // Wait
1446 < #ifdef HAVE_NANOSLEEP
1447 <                struct timespec req = {0, 16666667};
1162 <                nanosleep(&req, NULL);
1163 < #else
1164 <                usleep(16667);
1445 >        // Handle palette changes
1446 > #ifdef HAVE_PTHREADS
1447 >        pthread_mutex_lock(&palette_lock);
1448   #endif
1449 <
1450 < #if ENABLE_DGA
1451 <                // Quit DGA mode if requested
1452 <                if (quit_full_screen) {
1453 <                        quit_full_screen = false;
1449 >        if (palette_changed) {
1450 >                palette_changed = false;
1451 >                if (depth == 8) {
1452 >                        XStoreColors(x_display, cmap[0], palette, 256);
1453 >                        XStoreColors(x_display, cmap[1], palette, 256);
1454 >                                
1455 > #ifdef ENABLE_XF86_DGA
1456                          if (display_type == DISPLAY_DGA) {
1457 <                                XF86DGADirectVideo(x_display, screen, 0);
1458 <                                XUngrabPointer(x_display, CurrentTime);
1174 <                                XUngrabKeyboard(x_display, CurrentTime);
1175 <                                XUnmapWindow(x_display, the_win);
1176 <                                XSync(x_display, false);
1457 >                                current_dga_cmap ^= 1;
1458 >                                XF86DGAInstallColormap(x_display, screen, cmap[current_dga_cmap]);
1459                          }
1460 + #endif
1461                  }
1462 +        }
1463 + #ifdef HAVE_PTHREADS
1464 +        pthread_mutex_unlock(&palette_lock);
1465   #endif
1466  
1467 <                // Handle X events
1468 <                handle_events();
1467 >        // In window mode, update display
1468 >        static int tick_counter = 0;
1469 >        if (display_type == DISPLAY_WINDOW) {
1470 >                tick_counter++;
1471 >                update_display(tick_counter);
1472 >        }
1473 > }
1474  
1475 <                // Handle palette changes
1476 <                pthread_mutex_lock(&palette_lock);
1477 <                if (palette_changed) {
1478 <                        palette_changed = false;
1479 <                        if (depth == 8) {
1480 <                                XStoreColors(x_display, cmap[0], palette, 256);
1481 <                                XStoreColors(x_display, cmap[1], palette, 256);
1482 < #if ENABLE_DGA
1483 <                                if (display_type == DISPLAY_DGA) {
1193 <                                        current_dga_cmap ^= 1;
1194 <                                        XF86DGAInstallColormap(x_display, screen, cmap[current_dga_cmap]);
1195 <                                }
1475 > #ifdef HAVE_PTHREADS
1476 > static void *redraw_func(void *arg)
1477 > {
1478 >        while (!redraw_thread_cancel) {
1479 > #ifdef HAVE_NANOSLEEP
1480 >                struct timespec req = {0, 16666667};
1481 >                nanosleep(&req, NULL);
1482 > #else
1483 >                usleep(16667);
1484   #endif
1485 <                        }
1198 <                }
1199 <                pthread_mutex_unlock(&palette_lock);
1200 <
1201 <                // In window mode, update display and mouse pointer
1202 <                if (display_type == DISPLAY_WINDOW) {
1203 <                        tick_counter++;
1204 <                        if (tick_counter >= frame_skip) {
1205 <                                tick_counter = 0;
1206 <                                update_display();
1207 <                        }
1208 <                }
1485 >                VideoRefresh();
1486          }
1487          return NULL;
1488   }
1489 + #endif

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines