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.54 by cebix, 2001-07-06T22:00:39Z vs.
Revision 1.61 by cebix, 2001-07-14T15:02:47Z

# Line 67 | Line 67 | using std::sort;
67   #include "user_strings.h"
68   #include "video.h"
69  
70 < #define DEBUG 1
70 > #define DEBUG 0
71   #include "debug.h"
72  
73  
# Line 80 | Line 80 | enum {
80   // Constants
81   const char KEYCODE_FILE_NAME[] = DATADIR "/keycodes";
82  
83 < static const int win_eventmask = KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask | PointerMotionMask | ExposureMask | StructureNotifyMask;
83 > static const int win_eventmask = KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask | PointerMotionMask | EnterWindowMask | ExposureMask | StructureNotifyMask;
84   static const int dga_eventmask = KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask | PointerMotionMask | StructureNotifyMask;
85  
86  
# Line 93 | Line 93 | static int display_type = DISPLAY_WINDOW
93   static bool local_X11;                                                          // Flag: X server running on local machine?
94   static uint8 *the_buffer = NULL;                                        // Mac frame buffer (where MacOS draws into)
95   static uint8 *the_buffer_copy = NULL;                           // Copy of Mac frame buffer (for refreshed modes)
96 + static uint32 the_buffer_size;                                          // Size of allocated the_buffer
97  
98   static bool redraw_thread_active = false;                       // Flag: Redraw thread installed
99   #ifdef HAVE_PTHREADS
# Line 183 | Line 184 | static void (*video_refresh)(void);
184  
185   // Prototypes
186   static void *redraw_func(void *arg);
186 static int event2keycode(XKeyEvent &ev);
187  
188   // From main_unix.cpp
189   extern char *x_display_name;
# Line 209 | Line 209 | static bool find_visual_for_depth(video_
209   {
210          D(bug("have_visual_for_depth(%d)\n", 1 << depth));
211  
212 +        // 1-bit works always and uses default visual
213 +        if (depth == VDEPTH_1BIT) {
214 +                vis = DefaultVisual(x_display, screen);
215 +                visualInfo.visualid = XVisualIDFromVisual(vis);
216 +                int num = 0;
217 +                XVisualInfo *vi = XGetVisualInfo(x_display, VisualIDMask, &visualInfo, &num);
218 +                visualInfo = vi[0];
219 +                XFree(vi);
220 +                xdepth = visualInfo.depth;
221 +                color_class = visualInfo.c_class;
222 +                D(bug(" found visual ID 0x%02x, depth %d\n", visualInfo.visualid, xdepth));
223 +                return true;
224 +        }
225 +
226          // Calculate minimum and maximum supported X depth
227          int min_depth = 1, max_depth = 32;
228          switch (depth) {
215                case VDEPTH_1BIT:       // 1-bit works always
216                        min_depth = 1;
217                        max_depth = 32;
218                        break;
229   #ifdef ENABLE_VOSF
230                  case VDEPTH_2BIT:
231                  case VDEPTH_4BIT:       // VOSF blitters can convert 2/4/8-bit -> 8/16/32-bit
# Line 293 | Line 303 | static bool find_visual_for_depth(video_
303                  case DirectColor: D(bug("DirectColor\n")); break;
304          }
305   #endif
306 +        return true;
307   }
308  
309   // Add mode to list of supported modes
# Line 340 | Line 351 | static void set_mac_frame_buffer(video_d
351          InitFrameBufferMapping();
352   #else
353          VideoMonitor.mac_frame_base = Host2MacAddr(the_buffer);
343        D(bug("Host frame buffer = %p, ", the_buffer));
354   #endif
355          D(bug("VideoMonitor.mac_frame_base = %08x\n", VideoMonitor.mac_frame_base));
356   }
# Line 429 | Line 439 | public:
439          virtual void toggle_mouse_grab(void) {}
440          virtual void mouse_moved(int x, int y) { ADBMouseMoved(x, y); }
441  
442 +        void disable_mouse_accel(void);
443 +        void restore_mouse_accel(void);
444 +
445          virtual void grab_mouse(void) {}
446          virtual void ungrab_mouse(void) {}
447  
448   public:
449          bool init_ok;   // Initialization succeeded (we can't use exceptions because of -fomit-frame-pointer)
450          Window w;               // The window we draw into
451 +
452 +        int orig_accel_numer, orig_accel_denom, orig_threshold; // Original mouse acceleration
453   };
454  
455   class driver_window;
# Line 478 | Line 493 | driver_base::driver_base()
493   {
494          the_buffer = NULL;
495          the_buffer_copy = NULL;
496 +        XGetPointerControl(x_display, &orig_accel_numer, &orig_accel_denom, &orig_threshold);
497   }
498  
499   driver_base::~driver_base()
500   {
501          ungrab_mouse();
502 +        restore_mouse_accel();
503  
504          if (w) {
505                  XUnmapWindow(x_display, w);
# Line 506 | Line 523 | driver_base::~driver_base()
523          }
524   #ifdef ENABLE_VOSF
525          else {
526 <                if (the_buffer != (uint8 *)VM_MAP_FAILED) {
527 <                        vm_release(the_buffer, the_buffer_size);
526 >                if (the_host_buffer) {
527 >                        D(bug(" freeing the_host_buffer at %p\n", the_host_buffer));
528 >                        free(the_host_buffer);
529 >                        the_host_buffer = NULL;
530 >                }
531 >                if (the_buffer) {
532 >                        D(bug(" freeing the_buffer at %p\n", the_buffer));
533 >                        free(the_buffer);
534                          the_buffer = NULL;
535                  }
536 <                if (the_buffer_copy != (uint8 *)VM_MAP_FAILED) {
537 <                        vm_release(the_buffer_copy, the_buffer_size);
536 >                if (the_buffer_copy) {
537 >                        D(bug(" freeing the_buffer_copy at %p\n", the_buffer_copy));
538 >                        free(the_buffer_copy);
539                          the_buffer_copy = NULL;
540                  }
541          }
# Line 521 | Line 545 | driver_base::~driver_base()
545   // Palette has changed
546   void driver_base::update_palette(void)
547   {
548 <        if (cmap[0] && cmap[1]) {
548 >        if (color_class == PseudoColor || color_class == DirectColor) {
549                  int num = vis->map_entries;
550                  if (!IsDirectMode(VideoMonitor.mode) && color_class == DirectColor)
551                          return; // Indexed mode on true color screen, don't set CLUT
# Line 531 | Line 555 | void driver_base::update_palette(void)
555          XSync(x_display, false);
556   }
557  
558 + // Disable mouse acceleration
559 + void driver_base::disable_mouse_accel(void)
560 + {
561 +        XChangePointerControl(x_display, True, False, 1, 1, 0);
562 + }
563 +
564 + // Restore mouse acceleration to original value
565 + void driver_base::restore_mouse_accel(void)
566 + {
567 +        XChangePointerControl(x_display, True, True, orig_accel_numer, orig_accel_denom, orig_threshold);
568 + }
569 +
570  
571   /*
572   *  Windowed display driver
# Line 538 | Line 574 | void driver_base::update_palette(void)
574  
575   // Open display
576   driver_window::driver_window(const video_mode &mode)
577 < : gc(0), img(NULL), have_shm(false), mouse_grabbed(false), mac_cursor(0)
577 > : gc(0), img(NULL), have_shm(false), mac_cursor(0), mouse_grabbed(false)
578   {
579          int width = mode.x, height = mode.y;
580          int aligned_width = (width + 15) & ~15;
# Line 547 | Line 583 | driver_window::driver_window(const video
583          // Set absolute mouse mode
584          ADBSetRelMouseMode(mouse_grabbed);
585  
586 <        // Create window
586 >        // Create window (setting backround_pixel, border_pixel and colormap is
587 >        // mandatory when using a non-default visual; in 1-bit mode we use the
588 >        // default visual, so we can also use the default colormap)
589          XSetWindowAttributes wattr;
590          wattr.event_mask = eventmask = win_eventmask;
591 <        wattr.background_pixel = black_pixel;
592 <        wattr.colormap = (mode.depth == VDEPTH_1BIT && color_class == PseudoColor ? DefaultColormap(x_display, screen) : cmap[0]);
591 >        wattr.background_pixel = (vis == DefaultVisual(x_display, screen) ? black_pixel : 0);
592 >        wattr.border_pixel = 0;
593 >        wattr.colormap = (mode.depth == VDEPTH_1BIT ? DefaultColormap(x_display, screen) : cmap[0]);
594          w = XCreateWindow(x_display, rootwin, 0, 0, width, height, 0, xdepth,
595 <                InputOutput, vis, CWEventMask | CWBackPixel | (color_class == PseudoColor || color_class == DirectColor ? CWColormap : 0), &wattr);
595 >                InputOutput, vis, CWEventMask | CWBackPixel | CWBorderPixel | CWColormap, &wattr);
596 >        D(bug(" window created\n"));
597  
598          // Set window name/class
599          set_window_name(w, STR_WINDOW_TITLE);
# Line 577 | Line 617 | driver_window::driver_window(const video
617                          XFree(hints);
618                  }
619          }
620 +        D(bug(" window attributes set\n"));
621          
622          // Show window
623          XMapWindow(x_display, w);
624          wait_mapped(w);
625 +        D(bug(" window mapped\n"));
626  
627          // 1-bit mode is big-endian; if the X server is little-endian, we can't
628          // use SHM because that doesn't allow changing the image byte order
# Line 591 | Line 633 | driver_window::driver_window(const video
633  
634                  // Create SHM image ("height + 2" for safety)
635                  img = XShmCreateImage(x_display, vis, mode.depth == VDEPTH_1BIT ? 1 : xdepth, mode.depth == VDEPTH_1BIT ? XYBitmap : ZPixmap, 0, &shminfo, width, height);
636 +                D(bug(" shm image created\n"));
637                  shminfo.shmid = shmget(IPC_PRIVATE, (aligned_height + 2) * img->bytes_per_line, IPC_CREAT | 0777);
638                  the_buffer_copy = (uint8 *)shmat(shminfo.shmid, 0, 0);
639                  shminfo.shmaddr = img->data = (char *)the_buffer_copy;
# Line 605 | Line 648 | driver_window::driver_window(const video
648                  if (shm_error) {
649                          shmdt(shminfo.shmaddr);
650                          XDestroyImage(img);
651 +                        img = NULL;
652                          shminfo.shmid = -1;
653                  } else {
654                          have_shm = true;
655                          shmctl(shminfo.shmid, IPC_RMID, 0);
656                  }
657 +                D(bug(" shm image attached\n"));
658          }
659          
660          // Create normal X image if SHM doesn't work ("height + 2" for safety)
# Line 617 | Line 662 | driver_window::driver_window(const video
662                  int bytes_per_row = (mode.depth == VDEPTH_1BIT ? aligned_width/8 : TrivialBytesPerRow(aligned_width, DepthModeForPixelDepth(xdepth)));
663                  the_buffer_copy = (uint8 *)malloc((aligned_height + 2) * bytes_per_row);
664                  img = XCreateImage(x_display, vis, mode.depth == VDEPTH_1BIT ? 1 : xdepth, mode.depth == VDEPTH_1BIT ? XYBitmap : ZPixmap, 0, (char *)the_buffer_copy, aligned_width, aligned_height, 32, bytes_per_row);
665 +                D(bug(" X image created\n"));
666          }
667  
668          if (need_msb_image) {
# Line 625 | Line 671 | driver_window::driver_window(const video
671          }
672  
673   #ifdef ENABLE_VOSF
674 +        use_vosf = true;
675          // Allocate memory for frame buffer (SIZE is extended to page-boundary)
676          the_host_buffer = the_buffer_copy;
677          the_buffer_size = page_extend((aligned_height + 2) * img->bytes_per_line);
678          the_buffer_copy = (uint8 *)vm_acquire(the_buffer_size);
679          the_buffer = (uint8 *)vm_acquire(the_buffer_size);
680 +        D(bug("the_buffer = %p, the_buffer_copy = %p, the_host_buffer = %p\n", the_buffer, the_buffer_copy, the_host_buffer));
681   #else
682          // Allocate memory for frame buffer
683          the_buffer = (uint8 *)malloc((aligned_height + 2) * img->bytes_per_line);
684 +        D(bug("the_buffer = %p, the_buffer_copy = %p\n", the_buffer, the_buffer_copy));
685   #endif
686  
687          // Create GC
# Line 668 | Line 717 | driver_window::driver_window(const video
717   // Close display
718   driver_window::~driver_window()
719   {
671        if (img)
672                XDestroyImage(img);
720          if (have_shm) {
721                  XShmDetach(x_display, &shminfo);
722 + #ifdef ENABLE_VOSF
723 +                the_host_buffer = NULL; // don't free() in driver_base dtor
724 + #else
725                  the_buffer_copy = NULL; // don't free() in driver_base dtor
726 + #endif
727 +        }
728 + #ifdef ENABLE_VOSF
729 +        if (use_vosf) {
730 +                // don't free() memory mapped buffers in driver_base dtor
731 +                if (the_buffer != VM_MAP_FAILED) {
732 +                        D(bug(" releasing the_buffer at %p\n", the_buffer));
733 +                        vm_release(the_buffer, the_buffer_size);
734 +                        the_buffer = NULL;
735 +                }
736 +                if (the_buffer_copy != VM_MAP_FAILED) {
737 +                        D(bug(" releasing the_buffer_copy at %p\n", the_buffer_copy));
738 +                        vm_release(the_buffer_copy, the_buffer_size);
739 +                        the_buffer_copy = NULL;
740 +                }
741 +        }
742 + #endif
743 +        if (img) {
744 +                if (!have_shm)
745 +                        img->data = NULL;
746 +                XDestroyImage(img);
747 +        }
748 +        if (have_shm) {
749 +                shmdt(shminfo.shmaddr);
750 +                shmctl(shminfo.shmid, IPC_RMID, 0);
751          }
752          if (gc)
753                  XFreeGC(x_display, gc);
# Line 699 | Line 774 | void driver_window::grab_mouse(void)
774                  Delay_usec(100000);
775          }
776          if (result == GrabSuccess) {
702                ADBSetRelMouseMode(mouse_grabbed = true);
777                  XStoreName(x_display, w, GetString(STR_WINDOW_TITLE_GRABBED));
778 <                XSync(x_display, false);
778 >                ADBSetRelMouseMode(mouse_grabbed = true);
779 >                disable_mouse_accel();
780          }
781   }
782  
# Line 712 | Line 787 | void driver_window::ungrab_mouse(void)
787                  XUngrabPointer(x_display, CurrentTime);
788                  XStoreName(x_display, w, GetString(STR_WINDOW_TITLE));
789                  ADBSetRelMouseMode(mouse_grabbed = false);
790 +                restore_mouse_accel();
791          }
792   }
793  
# Line 807 | Line 883 | void driver_dga::suspend(void)
883   #endif
884          XUngrabPointer(x_display, CurrentTime);
885          XUngrabKeyboard(x_display, CurrentTime);
886 +        restore_mouse_accel();
887          XUnmapWindow(x_display, w);
888          wait_unmapped(w);
889  
# Line 836 | Line 913 | void driver_dga::resume(void)
913          XWarpPointer(x_display, None, rootwin, 0, 0, 0, 0, 0, 0);
914          XGrabKeyboard(x_display, rootwin, True, GrabModeAsync, GrabModeAsync, CurrentTime);
915          XGrabPointer(x_display, rootwin, True, PointerMotionMask | ButtonPressMask | ButtonReleaseMask, GrabModeAsync, GrabModeAsync, None, None, CurrentTime);
916 +        disable_mouse_accel();
917   #ifdef ENABLE_XF86_DGA
918          XF86DGADirectVideo(x_display, screen, XF86DGADirectGraphics | XF86DGADirectKeyb | XF86DGADirectMouse);
919          XF86DGASetViewPort(x_display, screen, 0, 0);
# Line 982 | Line 1060 | driver_fbdev::driver_fbdev(const video_m
1060          XGrabPointer(x_display, w, True,
1061                  PointerMotionMask | ButtonPressMask | ButtonReleaseMask,
1062                  GrabModeAsync, GrabModeAsync, w, None, CurrentTime);
1063 +        disable_mouse_accel();
1064          
1065          // Calculate bytes per row
1066          int bytes_per_row = TrivialBytesPerRow(mode.x, mode.depth);
1067          
1068          // Map frame buffer
1069 <        if ((the_buffer = (uint8 *) mmap(NULL, height * bytes_per_row, PROT_READ | PROT_WRITE, MAP_PRIVATE, fbdev_fd, fb_offset)) == MAP_FAILED) {
1070 <                if ((the_buffer = (uint8 *) mmap(NULL, height * bytes_per_row, PROT_READ | PROT_WRITE, MAP_SHARED, fbdev_fd, fb_offset)) == MAP_FAILED) {
1069 >        the_buffer_size = height * bytes_per_row;
1070 >        if ((the_buffer = (uint8 *) mmap(NULL, the_buffer_size, PROT_READ | PROT_WRITE, MAP_PRIVATE, fbdev_fd, fb_offset)) == MAP_FAILED) {
1071 >                if ((the_buffer = (uint8 *) mmap(NULL, the_buffer_size, PROT_READ | PROT_WRITE, MAP_SHARED, fbdev_fd, fb_offset)) == MAP_FAILED) {
1072                          char str[256];
1073                          sprintf(str, GetString(STR_FBDEV_MMAP_ERR), strerror(errno));
1074                          ErrorAlert(str);
# Line 1027 | Line 1107 | driver_fbdev::driver_fbdev(const video_m
1107   // Close display
1108   driver_fbdev::~driver_fbdev()
1109   {
1110 +        if (!use_vosf) {
1111 +                if (the_buffer != MAP_FAILED) {
1112 +                        // don't free() the screen buffer in driver_base dtor
1113 +                        munmap(the_buffer, the_buffer_size);
1114 +                        the_buffer = NULL;
1115 +                }
1116 +        }
1117 + #ifdef ENABLE_VOSF
1118 +        else {
1119 +                if (the_host_buffer != MAP_FAILED) {
1120 +                        // don't free() the screen buffer in driver_base dtor
1121 +                        munmap(the_host_buffer, the_buffer_size);
1122 +                        the_host_buffer = NULL;
1123 +                }
1124 +                if (the_buffer_copy != VM_MAP_FAILED) {
1125 +                        vm_release(the_buffer_copy, the_buffer_size);
1126 +                        the_buffer_copy = NULL;
1127 +                }
1128 +                if (the_buffer != VM_MAP_FAILED) {
1129 +                        vm_release(the_buffer, the_buffer_size);
1130 +                        the_buffer = NULL;
1131 +                }
1132 +        }
1133 + #endif
1134   }
1135   #endif
1136  
# Line 1096 | Line 1200 | driver_xf86dga::driver_xf86dga(const vid
1200          XWarpPointer(x_display, None, rootwin, 0, 0, 0, 0, 0, 0);
1201          XGrabKeyboard(x_display, rootwin, True, GrabModeAsync, GrabModeAsync, CurrentTime);
1202          XGrabPointer(x_display, rootwin, True, PointerMotionMask | ButtonPressMask | ButtonReleaseMask, GrabModeAsync, GrabModeAsync, None, None, CurrentTime);
1203 +        disable_mouse_accel();
1204  
1205          int v_width, v_bank, v_size;
1206          XF86DGAGetVideo(x_display, screen, (char **)&the_buffer, &v_width, &v_bank, &v_size);
# Line 1112 | Line 1217 | driver_xf86dga::driver_xf86dga(const vid
1217  
1218          // Init blitting routines
1219          int bytes_per_row = TrivialBytesPerRow((v_width + 7) & ~7, mode.depth);
1220 < #ifdef VIDEO_VOSF
1220 > #if VIDEO_VOSF
1221   #if REAL_ADDRESSING || DIRECT_ADDRESSING
1222          // Screen_blitter_init() returns TRUE if VOSF is mandatory
1223          // i.e. the framebuffer update function is not Blit_Copy_Raw
# Line 1143 | Line 1248 | driver_xf86dga::driver_xf86dga(const vid
1248   driver_xf86dga::~driver_xf86dga()
1249   {
1250          XF86DGADirectVideo(x_display, screen, 0);
1251 +        if (!use_vosf) {
1252 +                // don't free() the screen buffer in driver_base dtor
1253 +                the_buffer = NULL;
1254 +        }
1255 + #ifdef ENABLE_VOSF
1256 +        else {
1257 +                // don't free() the screen buffer in driver_base dtor
1258 +                the_host_buffer = NULL;
1259 +                
1260 +                if (the_buffer_copy != VM_MAP_FAILED) {
1261 +                        vm_release(the_buffer_copy, the_buffer_size);
1262 +                        the_buffer_copy = NULL;
1263 +                }
1264 +                if (the_buffer != VM_MAP_FAILED) {
1265 +                        vm_release(the_buffer, the_buffer_size);
1266 +                        the_buffer = NULL;
1267 +                }
1268 +        }
1269 + #endif
1270   #ifdef ENABLE_XF86_VIDMODE
1271          if (has_vidmode)
1272                  XF86VidModeSwitchToMode(x_display, screen, x_video_modes[0]);
# Line 1240 | Line 1364 | static void keycode_init(void)
1364   // Open display for specified mode
1365   static bool video_open(const video_mode &mode)
1366   {
1367 +        D(bug("video_open()\n"));
1368 +
1369          // Find best available X visual
1370          if (!find_visual_for_depth(mode.depth)) {
1371                  ErrorAlert(STR_NO_XVISUAL_ERR);
# Line 1250 | Line 1376 | static bool video_open(const video_mode
1376          if (color_class == PseudoColor || color_class == DirectColor) {
1377                  cmap[0] = XCreateColormap(x_display, rootwin, vis, AllocAll);
1378                  cmap[1] = XCreateColormap(x_display, rootwin, vis, AllocAll);
1379 +        } else {
1380 +                cmap[0] = XCreateColormap(x_display, rootwin, vis, AllocNone);
1381 +                cmap[1] = XCreateColormap(x_display, rootwin, vis, AllocNone);
1382          }
1383  
1384          // Find pixel format of direct modes
# Line 1271 | Line 1400 | static bool video_open(const video_mode
1400                          --bloss;
1401          }
1402  
1403 <        // Preset palette pixel values for gamma table
1403 >        // Preset palette pixel values for CLUT or gamma table
1404          if (color_class == DirectColor) {
1405                  int num = vis->map_entries;
1406                  for (int i=0; i<num; i++) {
1407                          int c = (i * 256) / num;
1408                          palette[i].pixel = map_rgb(c, c, c);
1409 +                        palette[i].flags = DoRed | DoGreen | DoBlue;
1410 +                }
1411 +        } else if (color_class == PseudoColor) {
1412 +                for (int i=0; i<256; i++) {
1413 +                        palette[i].pixel = i;
1414 +                        palette[i].flags = DoRed | DoGreen | DoBlue;
1415                  }
1416          }
1417  
# Line 1287 | Line 1422 | static bool video_open(const video_mode
1422                  palette[i].red = c * 0x0101;
1423                  palette[i].green = c * 0x0101;
1424                  palette[i].blue = c * 0x0101;
1290                if (color_class == PseudoColor)
1291                        palette[i].pixel = i;
1292                palette[i].flags = DoRed | DoGreen | DoBlue;
1425          }
1426 <        if (cmap[0] && cmap[1]) {
1426 >        if (color_class == PseudoColor || color_class == DirectColor) {
1427                  XStoreColors(x_display, cmap[0], palette, num);
1428                  XStoreColors(x_display, cmap[1], palette, num);
1429          }
1430  
1431   #ifdef ENABLE_VOSF
1432          // Load gray ramp to 8->16/32 expand map
1433 <        if (!IsDirectMode(mode) && (color_class == TrueColor || color_class == DirectColor))
1433 >        if (!IsDirectMode(mode) && xdepth > 8)
1434                  for (int i=0; i<256; i++)
1435                          ExpandMap[i] = map_rgb(i, i, i);
1436   #endif
# Line 1329 | Line 1461 | static bool video_open(const video_mode
1461  
1462   #ifdef ENABLE_VOSF
1463          if (use_vosf) {
1464 <                // Initialize the mainBuffer structure
1465 <                if (!video_init_buffer()) {
1464 >                // Initialize the VOSF system
1465 >                if (!video_vosf_init()) {
1466                          ErrorAlert(STR_VOSF_INIT_ERR);
1467                  return false;
1468                  }
1337
1338                // Initialize the handler for SIGSEGV
1339                if (!sigsegv_install_handler(screen_fault_handler)) {
1340                        ErrorAlert("Could not initialize Video on SEGV signals");
1341                        return false;
1342                }
1469          }
1470   #endif
1471          
# Line 1538 | Line 1664 | bool VideoInit(bool classic)
1664   // Close display
1665   static void video_close(void)
1666   {
1667 +        D(bug("video_close()\n"));
1668 +
1669          // Stop redraw thread
1670   #ifdef HAVE_PTHREADS
1671          if (redraw_thread_active) {
# Line 1553 | Line 1681 | static void video_close(void)
1681          // Unlock frame buffer
1682          UNLOCK_FRAME_BUFFER;
1683          XSync(x_display, false);
1684 +        D(bug(" frame buffer unlocked\n"));
1685  
1686   #ifdef ENABLE_VOSF
1558        // Deinitialize VOSF
1687          if (use_vosf) {
1688 <                if (mainBuffer.pageInfo) {
1689 <                        free(mainBuffer.pageInfo);
1562 <                        mainBuffer.pageInfo = NULL;
1563 <                }
1564 <                if (mainBuffer.dirtyPages) {
1565 <                        free(mainBuffer.dirtyPages);
1566 <                        mainBuffer.dirtyPages = NULL;
1567 <                }
1688 >                // Deinitialize VOSF
1689 >                video_vosf_exit();
1690          }
1691   #endif
1692  
# Line 1662 | Line 1784 | void video_set_palette(uint8 *pal, int n
1784                  p->red = pal[c*3 + 0] * 0x0101;
1785                  p->green = pal[c*3 + 1] * 0x0101;
1786                  p->blue = pal[c*3 + 2] * 0x0101;
1665                if (color_class == PseudoColor)
1666                        p->pixel = i;
1667                p->flags = DoRed | DoGreen | DoBlue;
1787                  p++;
1788          }
1789  
1790   #ifdef ENABLE_VOSF
1791          // Recalculate pixel color expansion map
1792 <        if (!IsDirectMode(VideoMonitor.mode) && (color_class == TrueColor || color_class == DirectColor)) {
1792 >        if (!IsDirectMode(VideoMonitor.mode) && xdepth > 8) {
1793                  for (int i=0; i<256; i++) {
1794                          int c = i & (num_in-1); // If there are less than 256 colors, we repeat the first entries (this makes color expansion easier)
1795                          ExpandMap[i] = map_rgb(pal[c*3+0], pal[c*3+1], pal[c*3+2]);
# Line 1883 | Line 2002 | static void handle_events(void)
2002                  XNextEvent(x_display, &event);
2003  
2004                  switch (event.type) {
2005 +
2006                          // Mouse button
2007                          case ButtonPress: {
2008                                  unsigned int button = event.xbutton.button;
# Line 1915 | Line 2035 | static void handle_events(void)
2035                                  drv->mouse_moved(event.xmotion.x, event.xmotion.y);
2036                                  break;
2037  
2038 +                        // Mouse entered window
2039 +                        case EnterNotify:
2040 +                                if (event.xcrossing.mode != NotifyGrab && event.xcrossing.mode != NotifyUngrab)
2041 +                                        drv->mouse_moved(event.xmotion.x, event.xmotion.y);
2042 +                                break;
2043 +
2044                          // Keyboard
2045                          case KeyPress: {
2046                                  int code = -1;
# Line 2092 | Line 2218 | static void update_display_dynamic(int t
2218   static void update_display_static(driver_window *drv)
2219   {
2220          // Incremental update code
2221 <        int wide = 0, high = 0, x1, x2, y1, y2, i, j;
2221 >        unsigned wide = 0, high = 0, x1, x2, y1, y2, i, j;
2222          int bytes_per_row = VideoMonitor.mode.bytes_per_row;
2223          int bytes_per_pixel = VideoMonitor.mode.bytes_per_row / VideoMonitor.mode.x;
2224          uint8 *p, *p2;
# Line 2251 | Line 2377 | static void video_refresh_dga(void)
2377   {
2378          // Quit DGA mode if requested
2379          possibly_quit_dga_mode();
2254        
2255        // Handle X events
2256        handle_events();
2257        
2258        // Handle palette changes
2259        handle_palette_changes();
2380   }
2381  
2382   #ifdef ENABLE_VOSF
# Line 2266 | Line 2386 | static void video_refresh_dga_vosf(void)
2386          // Quit DGA mode if requested
2387          possibly_quit_dga_mode();
2388          
2269        // Handle X events
2270        handle_events();
2271        
2272        // Handle palette changes
2273        handle_palette_changes();
2274        
2389          // Update display (VOSF variant)
2390          static int tick_counter = 0;
2391          if (++tick_counter >= frame_skip) {
# Line 2290 | Line 2404 | static void video_refresh_window_vosf(vo
2404          // Ungrab mouse if requested
2405          possibly_ungrab_mouse();
2406          
2293        // Handle X events
2294        handle_events();
2295        
2296        // Handle palette changes
2297        handle_palette_changes();
2298        
2407          // Update display (VOSF variant)
2408          static int tick_counter = 0;
2409          if (++tick_counter >= frame_skip) {
# Line 2315 | Line 2423 | static void video_refresh_window_static(
2423          // Ungrab mouse if requested
2424          possibly_ungrab_mouse();
2425  
2318        // Handle X events
2319        handle_events();
2320        
2321        // Handle_palette changes
2322        handle_palette_changes();
2323        
2426          // Update display (static variant)
2427          static int tick_counter = 0;
2428          if (++tick_counter >= frame_skip) {
# Line 2334 | Line 2436 | static void video_refresh_window_dynamic
2436          // Ungrab mouse if requested
2437          possibly_ungrab_mouse();
2438  
2337        // Handle X events
2338        handle_events();
2339        
2340        // Handle_palette changes
2341        handle_palette_changes();
2342        
2439          // Update display (dynamic variant)
2440          static int tick_counter = 0;
2441          tick_counter++;
# Line 2375 | Line 2471 | static void VideoRefreshInit(void)
2471          }
2472   }
2473  
2474 + // This function is called on non-threaded platforms from a timer interrupt
2475   void VideoRefresh(void)
2476   {
2477          // We need to check redraw_thread_active to inhibit refreshed during
2478          // mode changes on non-threaded platforms
2479 <        if (redraw_thread_active)
2480 <                video_refresh();
2479 >        if (!redraw_thread_active)
2480 >                return;
2481 >
2482 >        // Handle X events
2483 >        handle_events();
2484 >
2485 >        // Handle palette changes
2486 >        handle_palette_changes();
2487 >
2488 >        // Update display
2489 >        video_refresh();
2490   }
2491  
2492 + const int VIDEO_REFRESH_HZ = 60;
2493 + const int VIDEO_REFRESH_DELAY = 1000000 / VIDEO_REFRESH_HZ;
2494 +
2495   #ifdef HAVE_PTHREADS
2496   static void *redraw_func(void *arg)
2497   {
2498 +        int fd = ConnectionNumber(x_display);
2499 +
2500          uint64 start = GetTicks_usec();
2501          int64 ticks = 0;
2502 <        uint64 next = GetTicks_usec();
2502 >        uint64 next = GetTicks_usec() + VIDEO_REFRESH_DELAY;
2503 >
2504          while (!redraw_thread_cancel) {
2505 <                video_refresh();
2394 <                next += 16667;
2505 >
2506                  int64 delay = next - GetTicks_usec();
2507 <                if (delay > 0)
2508 <                        Delay_usec(delay);
2509 <                else if (delay < -16667)
2507 >                if (delay < -VIDEO_REFRESH_DELAY) {
2508 >
2509 >                        // We are lagging far behind, so we reset the delay mechanism
2510                          next = GetTicks_usec();
2511 <                ticks++;
2511 >
2512 >                } else if (delay <= 0) {
2513 >
2514 >                        // Delay expired, refresh display
2515 >                        handle_events();
2516 >                        handle_palette_changes();
2517 >                        video_refresh();
2518 >                        next += VIDEO_REFRESH_DELAY;
2519 >                        ticks++;
2520 >
2521 >                } else {
2522 >
2523 >                        // No display refresh pending, check for X events
2524 >                        fd_set readfds;
2525 >                        FD_ZERO(&readfds);
2526 >                        FD_SET(fd, &readfds);
2527 >                        struct timeval timeout;
2528 >                        timeout.tv_sec = 0;
2529 >                        timeout.tv_usec = delay;
2530 >                        if (select(fd+1, &readfds, NULL, NULL, &timeout) > 0)
2531 >                                handle_events();
2532 >                }
2533          }
2534 +
2535          uint64 end = GetTicks_usec();
2536 <        // printf("%Ld ticks in %Ld usec = %Ld ticks/sec\n", ticks, end - start, ticks * 1000000 / (end - start));
2536 >        D(bug("%Ld refreshes in %Ld usec = %f refreshes/sec\n", ticks, end - start, ticks * 1000000.0 / (end - start)));
2537          return NULL;
2538   }
2539   #endif

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines