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.24 by cebix, 2000-10-11T17:55:06Z vs.
Revision 1.35 by gbeauche, 2001-01-11T18:00:40Z

# Line 53 | Line 53
53   #endif
54  
55   #ifdef ENABLE_VOSF
56 # include <math.h> // log()
56   # include <unistd.h>
57   # include <signal.h>
58   # include <fcntl.h>
# Line 123 | Line 122 | static Colormap cmap[2];                                                       // Two co
122   static XColor black, white;
123   static unsigned long black_pixel, white_pixel;
124   static int eventmask;
125 < static const int win_eventmask = KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask | PointerMotionMask | EnterWindowMask | ExposureMask;
126 < static const int dga_eventmask = KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask | PointerMotionMask;
125 > static const int win_eventmask = KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask | PointerMotionMask | EnterWindowMask | ExposureMask | StructureNotifyMask;
126 > static const int dga_eventmask = KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask | PointerMotionMask | StructureNotifyMask;
127 > static Atom WM_DELETE_WINDOW = (Atom)0;
128  
129   static XColor palette[256];                                                     // Color palette for 8-bit mode
130   static bool palette_changed = false;                            // Flag: Palette changed, redraw thread must set new colors
131   #ifdef HAVE_PTHREADS
132   static pthread_mutex_t palette_lock = PTHREAD_MUTEX_INITIALIZER;        // Mutex to protect palette
133 + #define LOCK_PALETTE pthread_mutex_lock(&palette_lock)
134 + #define UNLOCK_PALETTE pthread_mutex_unlock(&palette_lock)
135 + #else
136 + #define LOCK_PALETTE
137 + #define UNLOCK_PALETTE
138   #endif
139  
140   // Variables for window mode
# Line 150 | Line 155 | static Window suspend_win;                                                     // "Sus
155   static void *fb_save = NULL;                                            // Saved frame buffer for suspend
156   #ifdef HAVE_PTHREADS
157   static pthread_mutex_t frame_buffer_lock = PTHREAD_MUTEX_INITIALIZER;   // Mutex to protect frame buffer
158 + #define LOCK_FRAME_BUFFER pthread_mutex_lock(&frame_buffer_lock);
159 + #define UNLOCK_FRAME_BUFFER pthread_mutex_unlock(&frame_buffer_lock);
160 + #else
161 + #define LOCK_FRAME_BUFFER
162 + #define UNLOCK_FRAME_BUFFER
163   #endif
164  
165   // Variables for fbdev DGA mode
# Line 169 | Line 179 | static const bool use_vosf = false;
179   #endif
180  
181   #ifdef ENABLE_VOSF
182 < static uint8 * the_host_buffer;                                         // Host frame buffer in VOSF mode
182 > // Variables for Video on SEGV support (taken from the Win32 port)
183 > static uint8 *the_host_buffer;                                          // Host frame buffer in VOSF mode
184   static uint32 the_buffer_size;                                          // Size of allocated the_buffer
174 #endif
185  
176 #ifdef ENABLE_VOSF
177 // Variables for Video on SEGV support (taken from the Win32 port)
186   struct ScreenPageInfo {
187      int top, bottom;                    // Mapping between this virtual page and Mac scanlines
188   };
# Line 189 | Line 197 | struct ScreenInfo {
197      int pageBits;                               // Shift count to get the page number
198      uint32 pageCount;                   // Number of pages allocated to the screen
199      
200 <    uint8 * dirtyPages;                 // Table of flags set if page was altered
200 >    char * dirtyPages;                  // Table of flags set if page was altered
201      ScreenPageInfo * pageInfo;  // Table of mappings page -> Mac scanlines
202   };
203  
204   static ScreenInfo mainBuffer;
205  
206 < #define PFLAG_SET(page)                 mainBuffer.dirtyPages[page] = 1
207 < #define PFLAG_CLEAR(page)               mainBuffer.dirtyPages[page] = 0
208 < #define PFLAG_ISSET(page)               mainBuffer.dirtyPages[page]
209 < #define PFLAG_ISCLEAR(page)             (mainBuffer.dirtyPages[page] == 0)
206 > #define PFLAG_SET_VALUE                 0x00
207 > #define PFLAG_CLEAR_VALUE               0x01
208 > #define PFLAG_SET_VALUE_4               0x00000000
209 > #define PFLAG_CLEAR_VALUE_4             0x01010101
210 > #define PFLAG_SET(page)                 mainBuffer.dirtyPages[page] = PFLAG_SET_VALUE
211 > #define PFLAG_CLEAR(page)               mainBuffer.dirtyPages[page] = PFLAG_CLEAR_VALUE
212 > #define PFLAG_ISSET(page)               (mainBuffer.dirtyPages[page] == PFLAG_SET_VALUE)
213 > #define PFLAG_ISCLEAR(page)             (mainBuffer.dirtyPages[page] != PFLAG_SET_VALUE)
214 >
215   #ifdef UNALIGNED_PROFITABLE
216 < # define PFLAG_ISCLEAR_4(page)  (*((uint32 *)(mainBuffer.dirtyPages + page)) == 0)
216 > # define PFLAG_ISSET_4(page)    (*((uint32 *)(mainBuffer.dirtyPages + (page))) == PFLAG_SET_VALUE_4)
217 > # define PFLAG_ISCLEAR_4(page)  (*((uint32 *)(mainBuffer.dirtyPages + (page))) == PFLAG_CLEAR_VALUE_4)
218 > #else
219 > # define PFLAG_ISSET_4(page) \
220 >                PFLAG_ISSET(page  ) && PFLAG_ISSET(page+1) \
221 >        &&      PFLAG_ISSET(page+2) && PFLAG_ISSET(page+3)
222 > # define PFLAG_ISCLEAR_4(page) \
223 >                PFLAG_ISCLEAR(page  ) && PFLAG_ISCLEAR(page+1) \
224 >        &&      PFLAG_ISCLEAR(page+2) && PFLAG_ISCLEAR(page+3)
225 > #endif
226 >
227 > // Set the selected page range [ first_page, last_page [ into the SET state
228 > #define PFLAG_SET_RANGE(first_page, last_page) \
229 >        memset(mainBuffer.dirtyPages + (first_page), PFLAG_SET_VALUE, \
230 >                (last_page) - (first_page))
231 >
232 > // Set the selected page range [ first_page, last_page [ into the CLEAR state
233 > #define PFLAG_CLEAR_RANGE(first_page, last_page) \
234 >        memset(mainBuffer.dirtyPages + (first_page), PFLAG_CLEAR_VALUE, \
235 >                (last_page) - (first_page))
236 >
237 > #define PFLAG_SET_ALL \
238 >        PFLAG_SET_RANGE(0, mainBuffer.pageCount)
239 >
240 > #define PFLAG_CLEAR_ALL \
241 >        PFLAG_CLEAR_RANGE(0, mainBuffer.pageCount)
242 >
243 > // Set the following macro definition to 1 if your system
244 > // provides a really fast strchr() implementation
245 > //#define HAVE_FAST_STRCHR 0
246 >
247 > static inline int find_next_page_set(int page)
248 > {
249 > #if HAVE_FAST_STRCHR
250 >        char *match = strchr(mainBuffer.dirtyPages + page, PFLAG_SET_VALUE);
251 >        return match ? match - mainBuffer.dirtyPages : mainBuffer.pageCount;
252   #else
253 < # define PFLAG_ISCLEAR_4(page)  \
254 <                (mainBuffer.dirtyPages[page  ] == 0) \
255 <        &&      (mainBuffer.dirtyPages[page+1] == 0) \
256 <        &&      (mainBuffer.dirtyPages[page+2] == 0) \
257 <        &&      (mainBuffer.dirtyPages[page+3] == 0)
253 >        while (PFLAG_ISCLEAR_4(page))
254 >                page += 4;
255 >        while (PFLAG_ISCLEAR(page))
256 >                page++;
257 >        return page;
258   #endif
259 < #define PFLAG_CLEAR_ALL                 memset(mainBuffer.dirtyPages, 0, mainBuffer.pageCount)
260 < #define PFLAG_SET_ALL                   memset(mainBuffer.dirtyPages, 1, mainBuffer.pageCount)
259 > }
260 >
261 > static inline int find_next_page_clear(int page)
262 > {
263 > #if HAVE_FAST_STRCHR
264 >        char *match = strchr(mainBuffer.dirtyPages + page, PFLAG_CLEAR_VALUE);
265 >        return match ? match - mainBuffer.dirtyPages : mainBuffer.pageCount;
266 > #else
267 >        while (PFLAG_ISSET_4(page))
268 >                page += 4;
269 >        while (PFLAG_ISSET(page))
270 >                page++;
271 >        return page;
272 > #endif
273 > }
274  
275   static int zero_fd = -1;
276   static bool Screen_fault_handler_init();
277   static struct sigaction vosf_sa;
278  
279   #ifdef HAVE_PTHREADS
280 < static pthread_mutex_t Screen_draw_lock = PTHREAD_MUTEX_INITIALIZER;    // Mutex to protect frame buffer (dirtyPages in fact)
280 > static pthread_mutex_t vosf_lock = PTHREAD_MUTEX_INITIALIZER;   // Mutex to protect frame buffer (dirtyPages in fact)
281 > #define LOCK_VOSF pthread_mutex_lock(&vosf_lock);
282 > #define UNLOCK_VOSF pthread_mutex_unlock(&vosf_lock);
283 > #else
284 > #define LOCK_VOSF
285 > #define UNLOCK_VOSF
286   #endif
287  
288 < #endif
288 > static int log_base_2(uint32 x)
289 > {
290 >        uint32 mask = 0x80000000;
291 >        int l = 31;
292 >        while (l >= 0 && (x & mask) == 0) {
293 >                mask >>= 1;
294 >                l--;
295 >        }
296 >        return l;
297 > }
298 > #endif /* ENABLE_VOSF */
299  
300   // VideoRefresh function
301   void VideoRefreshInit(void);
# Line 227 | Line 303 | static void (*video_refresh)(void);
303  
304   // Prototypes
305   static void *redraw_func(void *arg);
306 < static int event2keycode(XKeyEvent *ev);
306 > static int event2keycode(XKeyEvent &ev);
307  
308  
309   // From main_unix.cpp
# Line 297 | Line 373 | void set_video_monitor(int width, int he
373          VideoMonitor.bytes_per_row = bytes_per_row;
374   }
375  
376 + // Set window name and class
377 + static void set_window_name(Window w, int name)
378 + {
379 +        const char *str = GetString(name);
380 +        XStoreName(x_display, w, str);
381 +        XSetIconName(x_display, w, str);
382 +
383 +        XClassHint *hints;
384 +        hints = XAllocClassHint();
385 +        if (hints) {
386 +                hints->res_name = "BasiliskII";
387 +                hints->res_class = "BasiliskII";
388 +                XSetClassHint(x_display, w, hints);
389 +                XFree(hints);
390 +        }
391 + }
392 +
393 + // Set window input focus flag
394 + static void set_window_focus(Window w)
395 + {
396 +        XWMHints *hints = XAllocWMHints();
397 +        if (hints) {
398 +                hints->input = True;
399 +                hints->initial_state = NormalState;
400 +                hints->flags = InputHint | StateHint;
401 +                XSetWMHints(x_display, w, hints);
402 +                XFree(hints);
403 +        }
404 + }
405 +
406 + // Set WM_DELETE_WINDOW protocol on window (preventing it from being destroyed by the WM when clicking on the "close" widget)
407 + static void set_window_delete_protocol(Window w)
408 + {
409 +        WM_DELETE_WINDOW = XInternAtom(x_display, "WM_DELETE_WINDOW", false);
410 +        XSetWMProtocols(x_display, w, &WM_DELETE_WINDOW, 1);
411 + }
412 +
413 + // Wait until window is mapped/unmapped
414 + void wait_mapped(Window w)
415 + {
416 +        XEvent e;
417 +        do {
418 +                XMaskEvent(x_display, StructureNotifyMask, &e);
419 +        } while ((e.type != MapNotify) || (e.xmap.event != w));
420 + }
421 +
422 + void wait_unmapped(Window w)
423 + {
424 +        XEvent e;
425 +        do {
426 +                XMaskEvent(x_display, StructureNotifyMask, &e);
427 +        } while ((e.type != UnmapNotify) || (e.xmap.event != w));
428 + }
429 +
430   // Trap SHM errors
431   static bool shm_error = false;
432   static int (*old_error_handler)(Display *, XErrorEvent *);
# Line 326 | Line 456 | static bool init_window(int width, int h
456          XSetWindowAttributes wattr;
457          wattr.event_mask = eventmask = win_eventmask;
458          wattr.background_pixel = black_pixel;
459 <        wattr.border_pixel = black_pixel;
330 <        wattr.backing_store = NotUseful;
331 <        wattr.save_under = false;
332 <        wattr.backing_planes = xdepth;
459 >        wattr.colormap = cmap[0];
460  
334        XSync(x_display, false);
461          the_win = XCreateWindow(x_display, rootwin, 0, 0, width, height, 0, xdepth,
462 <                InputOutput, vis, CWEventMask | CWBackPixel | CWBorderPixel |
337 <                CWBackingStore | CWBackingPlanes, &wattr);
338 <        XSync(x_display, false);
339 <        XStoreName(x_display, the_win, GetString(STR_WINDOW_TITLE));
340 <        XMapRaised(x_display, the_win);
341 <        XSync(x_display, false);
462 >                InputOutput, vis, CWEventMask | CWBackPixel | (depth == 8 ? CWColormap : 0), &wattr);
463  
464 <        // Set colormap
465 <        if (depth == 8) {
466 <                XSetWindowColormap(x_display, the_win, cmap[0]);
467 <                XSetWMColormapWindows(x_display, the_win, &the_win, 1);
468 <        }
464 >        // Set window name/class
465 >        set_window_name(the_win, STR_WINDOW_TITLE);
466 >
467 >        // Indicate that we want keyboard input
468 >        set_window_focus(the_win);
469 >
470 >        // Set delete protocol property
471 >        set_window_delete_protocol(the_win);
472  
473          // Make window unresizable
474 <        XSizeHints *hints;
475 <        if ((hints = XAllocSizeHints()) != NULL) {
476 <                hints->min_width = width;
477 <                hints->max_width = width;
478 <                hints->min_height = height;
479 <                hints->max_height = height;
480 <                hints->flags = PMinSize | PMaxSize;
481 <                XSetWMNormalHints(x_display, the_win, hints);
482 <                XFree((char *)hints);
474 >        {
475 >                XSizeHints *hints = XAllocSizeHints();
476 >                if (hints) {
477 >                        hints->min_width = width;
478 >                        hints->max_width = width;
479 >                        hints->min_height = height;
480 >                        hints->max_height = height;
481 >                        hints->flags = PMinSize | PMaxSize;
482 >                        XSetWMNormalHints(x_display, the_win, hints);
483 >                        XFree(hints);
484 >                }
485          }
486          
487 +        // Show window
488 +        XMapWindow(x_display, the_win);
489 +        wait_mapped(the_win);
490 +
491          // Try to create and attach SHM image
492          have_shm = false;
493          if (depth != 1 && local_X11 && XShmQueryExtension(x_display)) {
# Line 440 | Line 570 | static bool init_window(int width, int h
570          // Set VideoMonitor
571          bool native_byte_order;
572   #ifdef WORDS_BIGENDIAN
573 <        native_byte_order = (img->bitmap_bit_order == MSBFirst);
573 >        native_byte_order = (XImageByteOrder(x_display) == MSBFirst);
574   #else
575 <        native_byte_order = (img->bitmap_bit_order == LSBFirst);
575 >        native_byte_order = (XImageByteOrder(x_display) == LSBFirst);
576   #endif
577   #ifdef ENABLE_VOSF
578          do_update_framebuffer = GET_FBCOPY_FUNC(depth, native_byte_order, DISPLAY_WINDOW);
# Line 529 | Line 659 | static bool init_fbdev_dga(char *in_fb_n
659          
660          // Create window
661          XSetWindowAttributes wattr;
662 <        wattr.override_redirect = True;
663 <        wattr.backing_store             = NotUseful;
664 <        wattr.background_pixel  = white_pixel;
665 <        wattr.border_pixel              = black_pixel;
536 <        wattr.event_mask                = eventmask = dga_eventmask;
662 >        wattr.event_mask = eventmask = dga_eventmask;
663 >        wattr.background_pixel = white_pixel;
664 >        wattr.override_redirect = True;
665 >        wattr.colormap = cmap[0];
666          
538        XSync(x_display, false);
667          the_win = XCreateWindow(x_display, rootwin,
668                  0, 0, width, height,
669                  0, xdepth, InputOutput, vis,
670 <                CWEventMask|CWBackPixel|CWBorderPixel|CWOverrideRedirect|CWBackingStore,
670 >                CWEventMask | CWBackPixel | CWOverrideRedirect | (depth == 8 ? CWColormap : 0),
671                  &wattr);
672 <        XSync(x_display, false);
672 >
673 >        // Set window name/class
674 >        set_window_name(the_win, STR_WINDOW_TITLE);
675 >
676 >        // Indicate that we want keyboard input
677 >        set_window_focus(the_win);
678 >
679 >        // Show window
680          XMapRaised(x_display, the_win);
681 <        XSync(x_display, false);
681 >        wait_mapped(the_win);
682          
683          // Grab mouse and keyboard
684          XGrabKeyboard(x_display, the_win, True,
# Line 552 | Line 687 | static bool init_fbdev_dga(char *in_fb_n
687                  PointerMotionMask | ButtonPressMask | ButtonReleaseMask,
688                  GrabModeAsync, GrabModeAsync, the_win, None, CurrentTime);
689          
555        // Set colormap
556        if (depth == 8) {
557                XSetWindowColormap(x_display, the_win, cmap[0]);
558                XSetWMColormapWindows(x_display, the_win, &the_win, 1);
559        }
560        
690          // Set VideoMonitor
691          int bytes_per_row = width;
692          switch (depth) {
# Line 637 | Line 766 | static bool init_xf86_dga(int width, int
766                  }
767                  XF86VidModeSwitchToMode(x_display, screen, x_video_modes[best]);
768                  XF86VidModeSetViewPort(x_display, screen, 0, 0);
769 +                XSync(x_display, false);
770          }
771   #endif
772  
773          // Create window
774          XSetWindowAttributes wattr;
775          wattr.event_mask = eventmask = dga_eventmask;
646        wattr.border_pixel = black_pixel;
776          wattr.override_redirect = True;
777  
649        XSync(x_display, false);
778          the_win = XCreateWindow(x_display, rootwin, 0, 0, width, height, 0, xdepth,
779 <                InputOutput, vis, CWEventMask | CWBorderPixel | CWOverrideRedirect, &wattr);
780 <        XSync(x_display, false);
781 <        XStoreName(x_display, the_win, GetString(STR_WINDOW_TITLE));
779 >                InputOutput, vis, CWEventMask | CWOverrideRedirect, &wattr);
780 >
781 >        // Set window name/class
782 >        set_window_name(the_win, STR_WINDOW_TITLE);
783 >
784 >        // Indicate that we want keyboard input
785 >        set_window_focus(the_win);
786 >
787 >        // Show window
788          XMapRaised(x_display, the_win);
789 <        XSync(x_display, false);
789 >        wait_mapped(the_win);
790  
791          // Establish direct screen connection
792          XMoveResizeWindow(x_display, the_win, 0, 0, width, height);
# Line 669 | Line 803 | static bool init_xf86_dga(int width, int
803          // Set colormap
804          if (depth == 8) {
805                  XSetWindowColormap(x_display, the_win, cmap[current_dga_cmap = 0]);
672                XSetWMColormapWindows(x_display, the_win, &the_win, 1);
806                  XF86DGAInstallColormap(x_display, screen, cmap[current_dga_cmap]);
807          }
808 +        XSync(x_display, false);
809  
810          // Set VideoMonitor
811          int bytes_per_row = (v_width + 7) & ~7;
# Line 804 | Line 938 | bool VideoInitBuffer()
938  
939                  mainBuffer.pageSize     = page_size;
940                  mainBuffer.pageCount    = (mainBuffer.memLength + page_mask)/mainBuffer.pageSize;
941 <                mainBuffer.pageBits     = int( log(mainBuffer.pageSize) / log(2.0) );
941 >                mainBuffer.pageBits     = log_base_2(mainBuffer.pageSize);
942  
943                  if (mainBuffer.dirtyPages != 0)
944                          free(mainBuffer.dirtyPages);
945  
946 <                mainBuffer.dirtyPages = (uint8 *) malloc(mainBuffer.pageCount);
946 >                mainBuffer.dirtyPages = (char *) malloc(mainBuffer.pageCount + 2);
947  
948                  if (mainBuffer.pageInfo != 0)
949                          free(mainBuffer.pageInfo);
# Line 820 | Line 954 | bool VideoInitBuffer()
954                          return false;
955  
956                  PFLAG_CLEAR_ALL;
957 +                // Safety net to insure the loops in the update routines will terminate
958 +                // See a discussion in <video_vosf.h> for further details
959 +                PFLAG_CLEAR(mainBuffer.pageCount);
960 +                PFLAG_SET(mainBuffer.pageCount+1);
961  
962                  uint32 a = 0;
963                  for (int i = 0; i < mainBuffer.pageCount; i++) {
# Line 872 | Line 1010 | bool VideoInit(bool classic)
1010          keycode_init();
1011  
1012          // Read prefs
1013 <        mouse_wheel_mode = PrefsFindInt16("mousewheelmode");
1014 <        mouse_wheel_lines = PrefsFindInt16("mousewheellines");
1013 >        mouse_wheel_mode = PrefsFindInt32("mousewheelmode");
1014 >        mouse_wheel_lines = PrefsFindInt32("mousewheellines");
1015  
1016          // Find screen and root window
1017          screen = XDefaultScreen(x_display);
# Line 1010 | Line 1148 | bool VideoInit(bool classic)
1148                          break;
1149          }
1150  
1013 #ifdef HAVE_PTHREADS
1151          // Lock down frame buffer
1152 <        pthread_mutex_lock(&frame_buffer_lock);
1016 < #endif
1152 >        LOCK_FRAME_BUFFER;
1153  
1154   #if !REAL_ADDRESSING && !DIRECT_ADDRESSING
1155          // Set variables for UAE memory mapping
# Line 1078 | Line 1214 | void VideoExit(void)
1214          }
1215   #endif
1216  
1081 #ifdef HAVE_PTHREADS
1217          // Unlock frame buffer
1218 <        pthread_mutex_unlock(&frame_buffer_lock);
1084 < #endif
1218 >        UNLOCK_FRAME_BUFFER;
1219  
1220          // Close window and server connection
1221          if (x_display != NULL) {
# Line 1184 | Line 1318 | void VideoInterrupt(void)
1318          if (emerg_quit)
1319                  QuitEmulator();
1320  
1187 #ifdef HAVE_PTHREADS
1321          // Temporarily give up frame buffer lock (this is the point where
1322          // we are suspended when the user presses Ctrl-Tab)
1323 <        pthread_mutex_unlock(&frame_buffer_lock);
1324 <        pthread_mutex_lock(&frame_buffer_lock);
1192 < #endif
1323 >        UNLOCK_FRAME_BUFFER;
1324 >        LOCK_FRAME_BUFFER;
1325   }
1326  
1327  
# Line 1199 | Line 1331 | void VideoInterrupt(void)
1331  
1332   void video_set_palette(uint8 *pal)
1333   {
1334 < #ifdef HAVE_PTHREDS
1203 <        pthread_mutex_lock(&palette_lock);
1204 < #endif
1334 >        LOCK_PALETTE;
1335  
1336          // Convert colors to XColor array
1337          for (int i=0; i<256; i++) {
# Line 1215 | Line 1345 | void video_set_palette(uint8 *pal)
1345          // Tell redraw thread to change palette
1346          palette_changed = true;
1347  
1348 < #ifdef HAVE_PTHREADS
1219 <        pthread_mutex_unlock(&palette_lock);
1220 < #endif
1348 >        UNLOCK_PALETTE;
1349   }
1350  
1351  
# Line 1233 | Line 1361 | static void suspend_emul(void)
1361                  ADBKeyUp(0x36);
1362                  ctrl_down = false;
1363  
1236 #ifdef HAVE_PTHREADS
1364                  // Lock frame buffer (this will stop the MacOS thread)
1365 <                pthread_mutex_lock(&frame_buffer_lock);
1239 < #endif
1365 >                LOCK_FRAME_BUFFER;
1366  
1367                  // Save frame buffer
1368                  fb_save = malloc(VideoMonitor.y * VideoMonitor.bytes_per_row);
# Line 1250 | Line 1376 | static void suspend_emul(void)
1376                  XUngrabPointer(x_display, CurrentTime);
1377                  XUngrabKeyboard(x_display, CurrentTime);
1378                  XUnmapWindow(x_display, the_win);
1379 <                XSync(x_display, false);
1379 >                wait_unmapped(the_win);
1380  
1381                  // Open "suspend" window
1382                  XSetWindowAttributes wattr;
1383                  wattr.event_mask = KeyPressMask;
1384                  wattr.background_pixel = black_pixel;
1259                wattr.border_pixel = black_pixel;
1260                wattr.backing_store = Always;
1261                wattr.backing_planes = xdepth;
1262                wattr.colormap = DefaultColormap(x_display, screen);
1385                  
1264                XSync(x_display, false);
1386                  suspend_win = XCreateWindow(x_display, rootwin, 0, 0, 512, 1, 0, xdepth,
1387 <                        InputOutput, vis, CWEventMask | CWBackPixel | CWBorderPixel |
1388 <                        CWBackingStore | CWBackingPlanes | (xdepth == 8 ? CWColormap : 0), &wattr);
1389 <                XSync(x_display, false);
1390 <                XStoreName(x_display, suspend_win, GetString(STR_SUSPEND_WINDOW_TITLE));
1270 <                XMapRaised(x_display, suspend_win);
1271 <                XSync(x_display, false);
1387 >                        InputOutput, vis, CWEventMask | CWBackPixel, &wattr);
1388 >                set_window_name(suspend_win, STR_SUSPEND_WINDOW_TITLE);
1389 >                set_window_focus(suspend_win);
1390 >                XMapWindow(x_display, suspend_win);
1391                  emul_suspended = true;
1392          }
1393   }
# Line 1281 | Line 1400 | static void resume_emul(void)
1400  
1401          // Reopen full screen display
1402          XMapRaised(x_display, the_win);
1403 +        wait_mapped(the_win);
1404          XWarpPointer(x_display, None, rootwin, 0, 0, 0, 0, 0, 0);
1285        XSync(x_display, false);
1405          XGrabKeyboard(x_display, rootwin, 1, GrabModeAsync, GrabModeAsync, CurrentTime);
1406          XGrabPointer(x_display, rootwin, 1, PointerMotionMask | ButtonPressMask | ButtonReleaseMask, GrabModeAsync, GrabModeAsync, None, None, CurrentTime);
1407   #ifdef ENABLE_XF86_DGA
# Line 1296 | Line 1415 | static void resume_emul(void)
1415          // not necessary.
1416   #ifdef ENABLE_VOSF
1417          if (use_vosf) {
1418 < #ifdef HAVE_PTHREADS
1300 <                pthread_mutex_lock(&Screen_draw_lock);
1301 < #endif
1418 >                LOCK_VOSF;
1419                  PFLAG_SET_ALL;
1420 < #ifdef HAVE_PTHREADS
1304 <                pthread_mutex_unlock(&Screen_draw_lock);
1305 < #endif
1420 >                UNLOCK_VOSF;
1421                  memset(the_buffer_copy, 0, VideoMonitor.bytes_per_row * VideoMonitor.y);
1422          }
1423   #endif
# Line 1323 | Line 1438 | static void resume_emul(void)
1438                  XF86DGAInstallColormap(x_display, screen, cmap[current_dga_cmap]);
1439   #endif
1440  
1326 #ifdef HAVE_PTHREADS
1441          // Unlock frame buffer (and continue MacOS thread)
1442 <        pthread_mutex_unlock(&frame_buffer_lock);
1442 >        UNLOCK_FRAME_BUFFER;
1443          emul_suspended = false;
1330 #endif
1444   }
1445   #endif
1446  
# Line 1481 | Line 1594 | static int kc_decode(KeySym ks)
1594          return -1;
1595   }
1596  
1597 < static int event2keycode(XKeyEvent *ev)
1597 > static int event2keycode(XKeyEvent &ev)
1598   {
1599          KeySym ks;
1600          int as;
1601          int i = 0;
1602  
1603          do {
1604 <                ks = XLookupKeysym(ev, i++);
1604 >                ks = XLookupKeysym(&ev, i++);
1605                  as = kc_decode(ks);
1606                  if (as != -1)
1607                          return as;
# Line 1504 | Line 1617 | static int event2keycode(XKeyEvent *ev)
1617  
1618   static void handle_events(void)
1619   {
1620 <        XEvent event;
1621 <        for (;;) {
1622 <                if (!XCheckMaskEvent(x_display, eventmask, &event))
1510 <                        break;
1620 >        while (XPending(x_display)) {
1621 >                XEvent event;
1622 >                XNextEvent(x_display, &event);
1623  
1624                  switch (event.type) {
1625                          // Mouse button
1626                          case ButtonPress: {
1627 <                                unsigned int button = ((XButtonEvent *)&event)->button;
1627 >                                unsigned int button = event.xbutton.button;
1628                                  if (button < 4)
1629                                          ADBMouseDown(button - 1);
1630                                  else if (button < 6) {  // Wheel mouse
# Line 1531 | Line 1643 | static void handle_events(void)
1643                                  break;
1644                          }
1645                          case ButtonRelease: {
1646 <                                unsigned int button = ((XButtonEvent *)&event)->button;
1646 >                                unsigned int button = event.xbutton.button;
1647                                  if (button < 4)
1648                                          ADBMouseUp(button - 1);
1649                                  break;
# Line 1539 | Line 1651 | static void handle_events(void)
1651  
1652                          // Mouse moved
1653                          case EnterNotify:
1542                                ADBMouseMoved(((XMotionEvent *)&event)->x, ((XMotionEvent *)&event)->y);
1543                                break;
1654                          case MotionNotify:
1655 <                                ADBMouseMoved(((XMotionEvent *)&event)->x, ((XMotionEvent *)&event)->y);
1655 >                                ADBMouseMoved(event.xmotion.x, event.xmotion.y);
1656                                  break;
1657  
1658                          // Keyboard
1659                          case KeyPress: {
1660                                  int code;
1661                                  if (use_keycodes) {
1662 <                                        event2keycode((XKeyEvent *)&event);     // This is called to process the hotkeys
1663 <                                        code = keycode_table[((XKeyEvent *)&event)->keycode & 0xff];
1662 >                                        event2keycode(event.xkey);      // This is called to process the hotkeys
1663 >                                        code = keycode_table[event.xkey.keycode & 0xff];
1664                                  } else
1665 <                                        code = event2keycode((XKeyEvent *)&event);
1665 >                                        code = event2keycode(event.xkey);
1666                                  if (code != -1) {
1667                                          if (!emul_suspended) {
1668                                                  if (code == 0x39) {     // Caps Lock pressed
# Line 1579 | Line 1689 | static void handle_events(void)
1689                          case KeyRelease: {
1690                                  int code;
1691                                  if (use_keycodes) {
1692 <                                        event2keycode((XKeyEvent *)&event);     // This is called to process the hotkeys
1693 <                                        code = keycode_table[((XKeyEvent *)&event)->keycode & 0xff];
1692 >                                        event2keycode(event.xkey);      // This is called to process the hotkeys
1693 >                                        code = keycode_table[event.xkey.keycode & 0xff];
1694                                  } else
1695 <                                        code = event2keycode((XKeyEvent *)&event);
1695 >                                        code = event2keycode(event.xkey);
1696                                  if (code != -1 && code != 0x39) {       // Don't propagate Caps Lock releases
1697                                          ADBKeyUp(code);
1698                                          if (code == 0x36)
# Line 1596 | Line 1706 | static void handle_events(void)
1706                                  if (display_type == DISPLAY_WINDOW) {
1707   #ifdef ENABLE_VOSF
1708                                          if (use_vosf) {                 // VOSF refresh
1709 < #ifdef HAVE_PTHREADS
1600 <                                                pthread_mutex_lock(&Screen_draw_lock);
1601 < #endif
1709 >                                                LOCK_VOSF;
1710                                                  PFLAG_SET_ALL;
1711 < #ifdef HAVE_PTHREADS
1604 <                                                pthread_mutex_unlock(&Screen_draw_lock);
1605 < #endif
1711 >                                                UNLOCK_VOSF;
1712                                                  memset(the_buffer_copy, 0, VideoMonitor.bytes_per_row * VideoMonitor.y);
1713                                          }
1714                                          else
# Line 1617 | Line 1723 | static void handle_events(void)
1723                                                  memset(the_buffer_copy, 0, VideoMonitor.bytes_per_row * VideoMonitor.y);
1724                                  }
1725                                  break;
1726 +
1727 +                        // Window "close" widget clicked
1728 +                        case ClientMessage:
1729 +                                if (event.xclient.format == 32 && event.xclient.data.l[0] == WM_DELETE_WINDOW) {
1730 +                                        ADBKeyDown(0x7f);       // Power key
1731 +                                        ADBKeyUp(0x7f);
1732 +                                }
1733 +                                break;
1734                  }
1735          }
1736   }
# Line 1766 | Line 1880 | static void update_display_static(void)
1880                                  for (i=(VideoMonitor.x>>3); i>(x2>>3); i--) {
1881                                          p--; p2--;
1882                                          if (*p != *p2) {
1883 <                                                x2 = i << 3;
1883 >                                                x2 = (i << 3) + 7;
1884                                                  break;
1885                                          }
1886                                  }
1887                          }
1888 <                        wide = x2 - x1;
1888 >                        wide = x2 - x1 + 1;
1889  
1890                          // Update copy of the_buffer
1891                          if (high && wide) {
# Line 1835 | Line 1949 | static void update_display_static(void)
1949   *      Screen refresh functions
1950   */
1951  
1952 < // The specialisations hereunder are meant to enable VOSF with DGA in direct
1953 < // addressing mode in case the address spaces (RAM, ROM, FrameBuffer) could
1954 < // not get mapped correctly with respect to the predetermined host frame
1955 < // buffer base address.
1956 < //
1843 < // Hmm, in other words, when in direct addressing mode and DGA is requested,
1844 < // we first try to "triple allocate" the address spaces according to the real
1845 < // host frame buffer address. Then, if it fails, we will use a temporary
1846 < // frame buffer thus making the real host frame buffer updated when pages
1847 < // of the temp frame buffer are altered.
1848 < //
1849 < // As a side effect, a little speed gain in screen updates could be noticed
1850 < // for other modes than DGA.
1851 < //
1852 < // The following two functions below are inline so that a clever compiler
1853 < // could specialise the code according to the current screen depth and
1854 < // display type. A more clever compiler would the job by itself though...
1855 < // (update_display_vosf is inlined as well)
1952 > // We suggest the compiler to inline the next two functions so that it
1953 > // may specialise the code according to the current screen depth and
1954 > // display type. A clever compiler would do that job by itself though...
1955 >
1956 > // NOTE: update_display_vosf is inlined too
1957  
1958   static inline void possibly_quit_dga_mode()
1959   {
# Line 1873 | Line 1974 | static inline void possibly_quit_dga_mod
1974  
1975   static inline void handle_palette_changes(int depth, int display_type)
1976   {
1977 < #ifdef HAVE_PTHREADS
1978 <        pthread_mutex_lock(&palette_lock);
1878 < #endif
1977 >        LOCK_PALETTE;
1978 >
1979          if (palette_changed) {
1980                  palette_changed = false;
1981                  if (depth == 8) {
1982                          XStoreColors(x_display, cmap[0], palette, 256);
1983                          XStoreColors(x_display, cmap[1], palette, 256);
1984 +                        XSync(x_display, false);
1985                                  
1986   #ifdef ENABLE_XF86_DGA
1987                          if (display_type == DISPLAY_DGA) {
# Line 1890 | Line 1991 | static inline void handle_palette_change
1991   #endif
1992                  }
1993          }
1994 < #ifdef HAVE_PTHREADS
1995 <        pthread_mutex_unlock(&palette_lock);
1895 < #endif
1994 >
1995 >        UNLOCK_PALETTE;
1996   }
1997  
1998   static void video_refresh_dga(void)
# Line 1924 | Line 2024 | static void video_refresh_dga_vosf(void)
2024          static int tick_counter = 0;
2025          if (++tick_counter >= frame_skip) {
2026                  tick_counter = 0;
2027 < #ifdef HAVE_PTHREADS
1928 <                pthread_mutex_lock(&Screen_draw_lock);
1929 < #endif
2027 >                LOCK_VOSF;
2028                  update_display_dga_vosf();
2029 < #ifdef HAVE_PTHREADS
1932 <                pthread_mutex_unlock(&Screen_draw_lock);
1933 < #endif
2029 >                UNLOCK_VOSF;
2030          }
2031   }
2032   #endif
# Line 1950 | Line 2046 | static void video_refresh_window_vosf(vo
2046          static int tick_counter = 0;
2047          if (++tick_counter >= frame_skip) {
2048                  tick_counter = 0;
2049 < #ifdef HAVE_PTHREADS
1954 <                pthread_mutex_lock(&Screen_draw_lock);
1955 < #endif
2049 >                LOCK_VOSF;
2050                  update_display_window_vosf();
2051 < #ifdef HAVE_PTHREADS
1958 <                pthread_mutex_unlock(&Screen_draw_lock);
1959 < #endif
2051 >                UNLOCK_VOSF;
2052          }
2053   }
2054   #endif // def ENABLE_VOSF
# Line 2026 | Line 2118 | void VideoRefresh(void)
2118          video_refresh();
2119   }
2120  
2029 #if 0
2030 void VideoRefresh(void)
2031 {
2032 #if defined(ENABLE_XF86_DGA) || defined(ENABLE_FBDEV_DGA)
2033        // Quit DGA mode if requested
2034        if (quit_full_screen) {
2035                quit_full_screen = false;
2036                if (display_type == DISPLAY_DGA) {
2037 #ifdef ENABLE_XF86_DGA
2038                        XF86DGADirectVideo(x_display, screen, 0);
2039 #endif
2040                        XUngrabPointer(x_display, CurrentTime);
2041                        XUngrabKeyboard(x_display, CurrentTime);
2042                        XUnmapWindow(x_display, the_win);
2043                        XSync(x_display, false);
2044                }
2045        }
2046 #endif
2047
2048        // Handle X events
2049        handle_events();
2050
2051        // Handle palette changes
2052 #ifdef HAVE_PTHREADS
2053        pthread_mutex_lock(&palette_lock);
2054 #endif
2055        if (palette_changed) {
2056                palette_changed = false;
2057                if (depth == 8) {
2058                        XStoreColors(x_display, cmap[0], palette, 256);
2059                        XStoreColors(x_display, cmap[1], palette, 256);
2060                                
2061 #ifdef ENABLE_XF86_DGA
2062                        if (display_type == DISPLAY_DGA) {
2063                                current_dga_cmap ^= 1;
2064                                XF86DGAInstallColormap(x_display, screen, cmap[current_dga_cmap]);
2065                        }
2066 #endif
2067                }
2068        }
2069 #ifdef HAVE_PTHREADS
2070        pthread_mutex_unlock(&palette_lock);
2071 #endif
2072
2073        // In window mode, update display
2074        static int tick_counter = 0;
2075        if (display_type == DISPLAY_WINDOW) {
2076                tick_counter++;
2077                if (frame_skip == 0)
2078                        update_display_dynamic(tick_counter);
2079                else if (tick_counter >= frame_skip) {
2080                        tick_counter = 0;
2081                        update_display_static();
2082                }
2083        }
2084 }
2085 #endif
2086
2121   #ifdef HAVE_PTHREADS
2122   static void *redraw_func(void *arg)
2123   {
# Line 2091 | Line 2125 | static void *redraw_func(void *arg)
2125          int64 ticks = 0;
2126          uint64 next = GetTicks_usec();
2127          while (!redraw_thread_cancel) {
2094 //              VideoRefresh();
2128                  video_refresh();
2129                  next += 16667;
2130                  int64 delay = next - GetTicks_usec();
# Line 2102 | Line 2135 | static void *redraw_func(void *arg)
2135                  ticks++;
2136          }
2137          uint64 end = GetTicks_usec();
2138 <        printf("%Ld ticks in %Ld usec = %Ld ticks/sec\n", ticks, end - start, (end - start) / ticks);
2138 >        printf("%Ld ticks in %Ld usec = %Ld ticks/sec\n", ticks, end - start, ticks * 1000000 / (end - start));
2139          return NULL;
2140   }
2141   #endif

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines