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.8 by cebix, 1999-10-21T16:07:36Z vs.
Revision 1.17 by cebix, 2000-07-22T16:07:21Z

# 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 45 | Line 60
60   #include "user_strings.h"
61   #include "video.h"
62  
63 < #define DEBUG 1
63 > #define DEBUG 0
64   #include "debug.h"
65  
51 #if ENABLE_XF86_DGA
52 #include <X11/extensions/xf86dga.h>
53 #endif
54
55 #if ENABLE_FBDEV_DGA
56 #include <sys/mman.h>
57 #endif
58
59
66  
67   // Display types
68   enum {
# Line 64 | Line 70 | enum {
70          DISPLAY_DGA             // DGA fullscreen display
71   };
72  
67
73   // Constants
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 bool local_X11;                                                          // Flag: X server running on local machine?
85   static uint8 *the_buffer;                                                       // Mac frame buffer
86 +
87 + #ifdef HAVE_PTHREADS
88   static bool redraw_thread_active = false;                       // Flag: Redraw thread installed
89   static volatile bool redraw_thread_cancel = false;      // Flag: Cancel Redraw thread
90   static pthread_t redraw_thread;                                         // Redraw thread
91 + #endif
92  
93   static bool has_dga = false;                                            // Flag: Video DGA capable
94 + static bool has_vidmode = false;                                        // Flag: VidMode extension available
95  
96   static bool ctrl_down = false;                                          // Flag: Ctrl key pressed
97   static bool caps_on = false;                                            // Flag: Caps Lock on
# Line 105 | Line 118 | static int eventmask;
118   static const int win_eventmask = KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask | PointerMotionMask | EnterWindowMask | ExposureMask;
119   static const int dga_eventmask = KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask | PointerMotionMask;
120  
108 static pthread_mutex_t palette_lock = PTHREAD_MUTEX_INITIALIZER;        // Mutex to protect palette
121   static XColor palette[256];                                                     // Color palette for 8-bit mode
122   static bool palette_changed = false;                            // Flag: Palette changed, redraw thread must set new colors
123 + #ifdef HAVE_PTHREADS
124 + static pthread_mutex_t palette_lock = PTHREAD_MUTEX_INITIALIZER;        // Mutex to protect palette
125 + #endif
126  
127   // Variables for window mode
128   static GC the_gc;
129   static XImage *img = NULL;
130   static XShmSegmentInfo shminfo;
116 static XImage *cursor_image, *cursor_mask_image;
117 static Pixmap cursor_map, cursor_mask_map;
131   static Cursor mac_cursor;
119 static GC cursor_gc, cursor_mask_gc;
132   static uint8 *the_buffer_copy = NULL;                           // Copy of Mac frame buffer
121 static uint8 the_cursor[64];                                            // Cursor image data
133   static bool have_shm = false;                                           // Flag: SHM extensions available
134 + static bool updt_box[17][17];                                           // Flag for Update
135 + static int nr_boxes;
136 + static const int sm_uptd[] = {4,1,6,3,0,5,2,7};
137 + static int sm_no_boxes[] = {1,8,32,64,128,300};
138  
139   // Variables for XF86 DGA mode
140   static int current_dga_cmap;                                            // Number (0 or 1) of currently installed DGA colormap
141   static Window suspend_win;                                                      // "Suspend" window
142   static void *fb_save = NULL;                                            // Saved frame buffer for suspend
143 + #ifdef HAVE_PTHREADS
144   static pthread_mutex_t frame_buffer_lock = PTHREAD_MUTEX_INITIALIZER;   // Mutex to protect frame buffer
145 + #endif
146  
147   // Variables for fbdev DGA mode
148   const char FBDEVICE_FILE_NAME[] = "/dev/fb";
149   static int fbdev_fd;
150  
151 + #ifdef ENABLE_XF86_VIDMODE
152 + // Variables for XF86 VidMode support
153 + static XF86VidModeModeInfo **x_video_modes;                     // Array of all available modes
154 + static int num_x_video_modes;
155 + #endif
156 +
157  
158   // Prototypes
159   static void *redraw_func(void *arg);
# Line 138 | Line 161 | static int event2keycode(XKeyEvent *ev);
161  
162  
163   // From main_unix.cpp
164 + extern char *x_display_name;
165   extern Display *x_display;
166  
167   // From sys_unix.cpp
# Line 151 | Line 175 | extern void SysMountFirstFloppy(void);
175   // Set VideoMonitor according to video mode
176   void set_video_monitor(int width, int height, int bytes_per_row, bool native_byte_order)
177   {
178 + #if !REAL_ADDRESSING
179          int layout = FLAYOUT_DIRECT;
180          switch (depth) {
181                  case 1:
182                          layout = FLAYOUT_DIRECT;
158                        VideoMonitor.mode = VMODE_1BIT;
183                          break;
184                  case 8:
185                          layout = FLAYOUT_DIRECT;
162                        VideoMonitor.mode = VMODE_8BIT;
186                          break;
187                  case 15:
188                          layout = FLAYOUT_HOST_555;
166                        VideoMonitor.mode = VMODE_16BIT;
189                          break;
190                  case 16:
191                          layout = FLAYOUT_HOST_565;
170                        VideoMonitor.mode = VMODE_16BIT;
192                          break;
193                  case 24:
194                  case 32:
195                          layout = FLAYOUT_HOST_888;
175                        VideoMonitor.mode = VMODE_32BIT;
196                          break;
197          }
178        VideoMonitor.x = width;
179        VideoMonitor.y = height;
180        VideoMonitor.bytes_per_row = bytes_per_row;
198          if (native_byte_order)
199                  MacFrameLayout = layout;
200          else
201                  MacFrameLayout = FLAYOUT_DIRECT;
202 + #endif
203 +        switch (depth) {
204 +                case 1:
205 +                        VideoMonitor.mode = VMODE_1BIT;
206 +                        break;
207 +                case 8:
208 +                        VideoMonitor.mode = VMODE_8BIT;
209 +                        break;
210 +                case 15:
211 +                        VideoMonitor.mode = VMODE_16BIT;
212 +                        break;
213 +                case 16:
214 +                        VideoMonitor.mode = VMODE_16BIT;
215 +                        break;
216 +                case 24:
217 +                case 32:
218 +                        VideoMonitor.mode = VMODE_32BIT;
219 +                        break;
220 +        }
221 +        VideoMonitor.x = width;
222 +        VideoMonitor.y = height;
223 +        VideoMonitor.bytes_per_row = bytes_per_row;
224   }
225  
226   // Trap SHM errors
# Line 200 | Line 239 | static int error_handler(Display *d, XEr
239   // Init window mode
240   static bool init_window(int width, int height)
241   {
242 +        int aligned_width = (width + 15) & ~15;
243 +        int aligned_height = (height + 15) & ~15;
244 +
245          // Set absolute mouse mode
246          ADBSetRelMouseMode(false);
247  
248          // Read frame skip prefs
249          frame_skip = PrefsFindInt32("frameskip");
208        if (frame_skip == 0)
209                frame_skip = 1;
250  
251          // Create window
252          XSetWindowAttributes wattr;
253          wattr.event_mask = eventmask = win_eventmask;
254          wattr.background_pixel = black_pixel;
255          wattr.border_pixel = black_pixel;
256 <        wattr.backing_store = Always;
256 >        wattr.backing_store = NotUseful;
257 >        wattr.save_under = false;
258          wattr.backing_planes = xdepth;
259  
260          XSync(x_display, false);
# Line 245 | Line 286 | static bool init_window(int width, int h
286          
287          // Try to create and attach SHM image
288          have_shm = false;
289 <        if (depth != 1 && XShmQueryExtension(x_display)) {
289 >        if (depth != 1 && local_X11 && XShmQueryExtension(x_display)) {
290  
291                  // Create SHM image ("height + 2" for safety)
292                  img = XShmCreateImage(x_display, vis, depth, depth == 1 ? XYBitmap : ZPixmap, 0, &shminfo, width, height);
293 <                shminfo.shmid = shmget(IPC_PRIVATE, (height + 2) * img->bytes_per_line, IPC_CREAT | 0777);
294 <                the_buffer = (uint8 *)shmat(shminfo.shmid, 0, 0);
295 <                shminfo.shmaddr = img->data = (char *)the_buffer;
293 >                shminfo.shmid = shmget(IPC_PRIVATE, (aligned_height + 2) * img->bytes_per_line, IPC_CREAT | 0777);
294 >                the_buffer_copy = (uint8 *)shmat(shminfo.shmid, 0, 0);
295 >                shminfo.shmaddr = img->data = (char *)the_buffer_copy;
296                  shminfo.readOnly = False;
297  
298                  // Try to attach SHM image, catching errors
# Line 272 | Line 313 | static bool init_window(int width, int h
313          
314          // Create normal X image if SHM doesn't work ("height + 2" for safety)
315          if (!have_shm) {
316 <                int bytes_per_row = width;
316 >                int bytes_per_row = aligned_width;
317                  switch (depth) {
318                          case 1:
319                                  bytes_per_row /= 8;
# Line 286 | Line 327 | static bool init_window(int width, int h
327                                  bytes_per_row *= 4;
328                                  break;
329                  }
330 <                the_buffer = (uint8 *)malloc((height + 2) * bytes_per_row);
331 <                img = XCreateImage(x_display, vis, depth, depth == 1 ? XYBitmap : ZPixmap, 0, (char *)the_buffer, width, height, 32, bytes_per_row);
330 >                the_buffer_copy = (uint8 *)malloc((aligned_height + 2) * bytes_per_row);
331 >                img = XCreateImage(x_display, vis, depth, depth == 1 ? XYBitmap : ZPixmap, 0, (char *)the_buffer_copy, aligned_width, aligned_height, 32, bytes_per_row);
332          }
333  
334          // 1-Bit mode is big-endian
# Line 296 | Line 337 | static bool init_window(int width, int h
337                  img->bitmap_bit_order = MSBFirst;
338          }
339  
340 <        // Allocate memory for frame buffer copy
341 <        the_buffer_copy = (uint8 *)malloc((height + 2) * img->bytes_per_line);
340 >        // Allocate memory for frame buffer
341 >        the_buffer = (uint8 *)malloc((aligned_height + 2) * img->bytes_per_line);
342  
343          // Create GC
344          the_gc = XCreateGC(x_display, the_win, 0, 0);
345          XSetState(x_display, the_gc, black_pixel, white_pixel, GXcopy, AllPlanes);
346  
347 <        // Create cursor
348 <        cursor_image = XCreateImage(x_display, vis, 1, XYPixmap, 0, (char *)the_cursor, 16, 16, 16, 2);
349 <        cursor_image->byte_order = MSBFirst;
350 <        cursor_image->bitmap_bit_order = MSBFirst;
351 <        cursor_mask_image = XCreateImage(x_display, vis, 1, XYPixmap, 0, (char *)the_cursor+32, 16, 16, 16, 2);
352 <        cursor_mask_image->byte_order = MSBFirst;
312 <        cursor_mask_image->bitmap_bit_order = MSBFirst;
313 <        cursor_map = XCreatePixmap(x_display, the_win, 16, 16, 1);
314 <        cursor_mask_map = XCreatePixmap(x_display, the_win, 16, 16, 1);
315 <        cursor_gc = XCreateGC(x_display, cursor_map, 0, 0);
316 <        cursor_mask_gc = XCreateGC(x_display, cursor_mask_map, 0, 0);
317 <        mac_cursor = XCreatePixmapCursor(x_display, cursor_map, cursor_mask_map, &black, &white, 0, 0);
347 >        // Create no_cursor
348 >        mac_cursor = XCreatePixmapCursor(x_display,
349 >           XCreatePixmap(x_display, the_win, 1, 1, 1),
350 >           XCreatePixmap(x_display, the_win, 1, 1, 1),
351 >           &black, &white, 0, 0);
352 >        XDefineCursor(x_display, the_win, mac_cursor);
353  
354          // Set VideoMonitor
355   #ifdef WORDS_BIGENDIAN
# Line 325 | Line 360 | static bool init_window(int width, int h
360          
361   #if REAL_ADDRESSING
362          VideoMonitor.mac_frame_base = (uint32)the_buffer;
328        MacFrameLayout = FLAYOUT_DIRECT;
363   #else
364          VideoMonitor.mac_frame_base = MacFrameBaseMac;
365   #endif
# Line 335 | Line 369 | static bool init_window(int width, int h
369   // Init fbdev DGA display
370   static bool init_fbdev_dga(char *in_fb_name)
371   {
372 < #if ENABLE_FBDEV_DGA
372 > #ifdef ENABLE_FBDEV_DGA
373          // Find the maximum depth available
374          int ndepths, max_depth(0);
375          int *depths = XListDepths(x_display, screen, &ndepths);
376          if (depths == NULL) {
377 <                fprintf(stderr, "Error: could not determine the maximal depth available\n");
377 >                printf("FATAL: Could not determine the maximal depth available\n");
378                  return false;
379          } else {
380                  while (ndepths-- > 0) {
# Line 429 | Line 463 | static bool init_fbdev_dga(char *in_fb_n
463          
464          // Set colormap
465          if (depth == 8) {
466 <                XSetWindowColormap(x_display, the_win, cmap[current_dga_cmap = 0]);
466 >                XSetWindowColormap(x_display, the_win, cmap[0]);
467                  XSetWMColormapWindows(x_display, the_win, &the_win, 1);
468          }
469          
# Line 461 | Line 495 | static bool init_fbdev_dga(char *in_fb_n
495          set_video_monitor(width, height, bytes_per_row, true);
496   #if REAL_ADDRESSING
497          VideoMonitor.mac_frame_base = (uint32)the_buffer;
464        MacFrameLayout = FLAYOUT_DIRECT;
498   #else
499          VideoMonitor.mac_frame_base = MacFrameBaseMac;
500   #endif
468        
469        printf("FbDev DGA with %s in %d-bit mode enabled\n", fb_name, fb_depth);
501          return true;
502   #else
503          ErrorAlert("Basilisk II has been compiled with fbdev DGA support disabled.");
# Line 477 | Line 508 | static bool init_fbdev_dga(char *in_fb_n
508   // Init XF86 DGA display
509   static bool init_xf86_dga(int width, int height)
510   {
511 < #if ENABLE_XF86_DGA
511 > #ifdef ENABLE_XF86_DGA
512          // Set relative mouse mode
513          ADBSetRelMouseMode(true);
514  
515 + #ifdef ENABLE_XF86_VIDMODE
516 +        // Switch to best mode
517 +        if (has_vidmode) {
518 +                int best = 0;
519 +                for (int i=1; i<num_x_video_modes; i++) {
520 +                        if (x_video_modes[i]->hdisplay >= width && x_video_modes[i]->vdisplay >= height &&
521 +                                x_video_modes[i]->hdisplay <= x_video_modes[best]->hdisplay && x_video_modes[i]->vdisplay <= x_video_modes[best]->vdisplay) {
522 +                                best = i;
523 +                        }
524 +                }
525 +                XF86VidModeSwitchToMode(x_display, screen, x_video_modes[best]);
526 +                XF86VidModeSetViewPort(x_display, screen, 0, 0);
527 +        }
528 + #endif
529 +
530          // Create window
531          XSetWindowAttributes wattr;
532          wattr.event_mask = eventmask = dga_eventmask;
# Line 610 | Line 656 | static void keycode_init(void)
656  
657   bool VideoInit(bool classic)
658   {
659 +        // Check if X server runs on local machine
660 +        local_X11 = (strncmp(XDisplayName(x_display_name), ":", 1) == 0)
661 +                 || (strncmp(XDisplayName(x_display_name), "unix:", 5) == 0);
662 +    
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);
# Line 620 | Line 674 | bool VideoInit(bool classic)
674          // Get screen depth
675          xdepth = DefaultDepth(x_display, screen);
676          
677 < #if ENABLE_FBDEV_DGA
677 > #ifdef ENABLE_FBDEV_DGA
678          // Frame buffer name
679          char fb_name[20];
680          
# Line 630 | Line 684 | bool VideoInit(bool classic)
684          else
685                  has_dga = false;
686   #endif
687 <        
688 < #if ENABLE_XF86_DGA
687 >
688 > #ifdef ENABLE_XF86_DGA
689          // DGA available?
690 <        int event_base, error_base;
691 <        if (XF86DGAQueryExtension(x_display, &event_base, &error_base)) {
690 >        int dga_event_base, dga_error_base;
691 >        if (local_X11 && 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;
# Line 642 | Line 696 | bool VideoInit(bool classic)
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 707 | 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 < #if ENABLE_FBDEV_DGA
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) {
# Line 731 | Line 793 | bool VideoInit(bool classic)
793                                  return false;
794                          break;
795                  case DISPLAY_DGA:
796 < #if ENABLE_FBDEV_DGA
796 > #ifdef ENABLE_FBDEV_DGA
797                          if (!init_fbdev_dga(fb_name))
798   #else
799                          if (!init_xf86_dga(width, height))
# Line 740 | Line 802 | bool VideoInit(bool classic)
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 753 | Line 817 | bool VideoInit(bool classic)
817                  MacFrameLayout = FLAYOUT_NONE;
818   #endif
819  
756        // 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 768 | 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 777 | 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_XF86_DGA
861 > #ifdef ENABLE_XF86_DGA
862                  if (display_type == DISPLAY_DGA) {
863                          XF86DGADirectVideo(x_display, screen, 0);
864                          XUngrabPointer(x_display, CurrentTime);
# Line 793 | Line 866 | void VideoExit(void)
866                  }
867   #endif
868  
869 < #if ENABLE_FBDEV_DGA
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
803                
804                if (the_buffer_copy) {
805                        free(the_buffer_copy);
806                        the_buffer_copy = NULL;
807                }
881  
882                  XFlush(x_display);
883                  XSync(x_display, false);
# Line 812 | 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 838 | 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 851 | 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 865 | 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 873 | Line 962 | void video_set_palette(uint8 *pal)
962   *  Suspend/resume emulator
963   */
964  
965 < #if ENABLE_XF86_DGA || ENABLE_FBDEV_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 881 | 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 890 | 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 < #if ENABLE_XF86_DGA
984 > #ifdef ENABLE_XF86_DGA
985                  XF86DGADirectVideo(x_display, screen, 0);
986   #endif
987                  XUngrabPointer(x_display, CurrentTime);
# Line 931 | 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 < #if ENABLE_XF86_DGA
1025 > #ifdef ENABLE_XF86_DGA
1026          XF86DGADirectVideo(x_display, screen, XF86DGADirectGraphics | XF86DGADirectKeyb | XF86DGADirectMouse);
1027          XF86DGASetViewPort(x_display, screen, 0, 0);
1028   #endif
# Line 944 | Line 1035 | static void resume_emul(void)
1035                  fb_save = NULL;
1036          }
1037          
1038 + #ifdef ENABLE_XF86_DGA
1039          if (depth == 8)
948 #if ENABLE_XF86_DGA
1040                  XF86DGAInstallColormap(x_display, screen, cmap[current_dga_cmap]);
1041   #endif
951 #if ENABLE_FBDEV_DGA
952                XSetWindowColormap(x_display, the_win, cmap[current_dga_cmap]);
953 #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 1016 | 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_XF86_DGA || ENABLE_FBDEV_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 1142 | 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 1182 | Line 1285 | static void handle_events(void)
1285                                                  if (code == 0x36)
1286                                                          ctrl_down = true;
1287                                          } else {
1288 < #if ENABLE_XF86_DGA || ENABLE_FBDEV_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 1207 | 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 >                                        if (frame_skip == 0) {  // Dynamic refresh
1315 >                                                int x1, y1;
1316 >                                                for (y1=0; y1<16; y1++)
1317 >                                                for (x1=0; x1<16; x1++)
1318 >                                                        updt_box[x1][y1] = true;
1319 >                                                nr_boxes = 16 * 16;
1320 >                                        } else
1321 >                                                memset(the_buffer_copy, 0, VideoMonitor.bytes_per_row * VideoMonitor.y);
1322 >                                }
1323                                  break;
1324                  }
1325          }
# Line 1219 | Line 1330 | static void handle_events(void)
1330   *  Window display update
1331   */
1332  
1333 < static void update_display(void)
1333 > // Dynamic display update (variable frame rate for each box)
1334 > static void update_display_dynamic(int ticker)
1335 > {
1336 >        int y1, y2, y2s, y2a, i, x1, xm, xmo, ymo, yo, yi, yil, xi;
1337 >        int xil = 0;
1338 >        int rxm = 0, rxmo = 0;
1339 >        int bytes_per_row = VideoMonitor.bytes_per_row;
1340 >        int bytes_per_pixel = VideoMonitor.bytes_per_row / VideoMonitor.x;
1341 >        int rx = VideoMonitor.bytes_per_row / 16;
1342 >        int ry = VideoMonitor.y / 16;
1343 >        int max_box;
1344 >
1345 >        y2s = sm_uptd[ticker % 8];
1346 >        y2a = 8;
1347 >        for (i = 0; i < 6; i++)
1348 >                if (ticker % (2 << i))
1349 >                        break;
1350 >        max_box = sm_no_boxes[i];
1351 >
1352 >        if (y2a) {
1353 >                for (y1=0; y1<16; y1++) {
1354 >                        for (y2=y2s; y2 < ry; y2 += y2a) {
1355 >                                i = ((y1 * ry) + y2) * bytes_per_row;
1356 >                                for (x1=0; x1<16; x1++, i += rx) {
1357 >                                        if (updt_box[x1][y1] == false) {
1358 >                                                if (memcmp(&the_buffer_copy[i], &the_buffer[i], rx)) {
1359 >                                                        updt_box[x1][y1] = true;
1360 >                                                        nr_boxes++;
1361 >                                                }
1362 >                                        }
1363 >                                }
1364 >                        }
1365 >                }
1366 >        }
1367 >
1368 >        if ((nr_boxes <= max_box) && (nr_boxes)) {
1369 >                for (y1=0; y1<16; y1++) {
1370 >                        for (x1=0; x1<16; x1++) {
1371 >                                if (updt_box[x1][y1] == true) {
1372 >                                        if (rxm == 0)
1373 >                                                xm = x1;
1374 >                                        rxm += rx;
1375 >                                        updt_box[x1][y1] = false;
1376 >                                }
1377 >                                if (((updt_box[x1+1][y1] == false) || (x1 == 15)) && (rxm)) {
1378 >                                        if ((rxmo != rxm) || (xmo != xm) || (yo != y1 - 1)) {
1379 >                                                if (rxmo) {
1380 >                                                        xi = xmo * rx;
1381 >                                                        yi = ymo * ry;
1382 >                                                        xil = rxmo;
1383 >                                                        yil = (yo - ymo +1) * ry;
1384 >                                                }
1385 >                                                rxmo = rxm;
1386 >                                                xmo = xm;
1387 >                                                ymo = y1;
1388 >                                        }
1389 >                                        rxm = 0;
1390 >                                        yo = y1;
1391 >                                }      
1392 >                                if (xil) {
1393 >                                        i = (yi * bytes_per_row) + xi;
1394 >                                        for (y2=0; y2 < yil; y2++, i += bytes_per_row)
1395 >                                                memcpy(&the_buffer_copy[i], &the_buffer[i], xil);
1396 >                                        if (depth == 1) {
1397 >                                                if (have_shm)
1398 >                                                        XShmPutImage(x_display, the_win, the_gc, img, xi * 8, yi, xi * 8, yi, xil * 8, yil, 0);
1399 >                                                else
1400 >                                                        XPutImage(x_display, the_win, the_gc, img, xi * 8, yi, xi * 8, yi, xil * 8, yil);
1401 >                                        } else {
1402 >                                                if (have_shm)
1403 >                                                        XShmPutImage(x_display, the_win, the_gc, img, xi / bytes_per_pixel, yi, xi / bytes_per_pixel, yi, xil / bytes_per_pixel, yil, 0);
1404 >                                                else
1405 >                                                        XPutImage(x_display, the_win, the_gc, img, xi / bytes_per_pixel, yi, xi / bytes_per_pixel, yi, xil / bytes_per_pixel, yil);
1406 >                                        }
1407 >                                        xil = 0;
1408 >                                }
1409 >                                if ((x1 == 15) && (y1 == 15) && (rxmo)) {
1410 >                                        x1--;
1411 >                                        xi = xmo * rx;
1412 >                                        yi = ymo * ry;
1413 >                                        xil = rxmo;
1414 >                                        yil = (yo - ymo +1) * ry;
1415 >                                        rxmo = 0;
1416 >                                }
1417 >                        }
1418 >                }
1419 >                nr_boxes = 0;
1420 >        }
1421 > }
1422 >
1423 > // Static display update (fixed frame rate, but incremental)
1424 > static void update_display_static(void)
1425   {
1224        // In classic mode, copy the frame buffer from Mac RAM
1225        if (classic_mode)
1226                memcpy(the_buffer, Mac2HostAddr(0x3fa700), VideoMonitor.bytes_per_row * VideoMonitor.y);
1227        
1426          // Incremental update code
1427          int wide = 0, high = 0, x1, x2, y1, y2, i, j;
1428          int bytes_per_row = VideoMonitor.bytes_per_row;
# Line 1285 | Line 1483 | static void update_display(void)
1483                          if (high && wide) {
1484                                  for (j=y1; j<=y2; j++) {
1485                                          i = j * bytes_per_row + (x1 >> 3);
1486 <                                        memcpy(&the_buffer_copy[i], &the_buffer[i], wide >> 3);
1486 >                                        memcpy(the_buffer_copy + i, the_buffer + i, wide >> 3);
1487                                  }
1488                          }
1489  
# Line 1324 | Line 1522 | static void update_display(void)
1522                          if (high && wide) {
1523                                  for (j=y1; j<=y2; j++) {
1524                                          i = j * bytes_per_row + x1 * bytes_per_pixel;
1525 <                                        memcpy(&the_buffer_copy[i], &the_buffer[i], bytes_per_pixel * wide);
1525 >                                        memcpy(the_buffer_copy + i, the_buffer + i, bytes_per_pixel * wide);
1526                                  }
1527                          }
1528                  }
# Line 1337 | Line 1535 | static void update_display(void)
1535                  else
1536                          XPutImage(x_display, the_win, the_gc, img, x1, y1, x1, y1, wide, high);
1537          }
1340
1341        // Has the Mac started? (cursor data is not valid otherwise)
1342        if (HasMacStarted()) {
1343
1344                // Set new cursor image if it was changed
1345                if (memcmp(the_cursor, Mac2HostAddr(0x844), 64)) {
1346                        memcpy(the_cursor, Mac2HostAddr(0x844), 64);
1347                        memcpy(cursor_image->data, the_cursor, 32);
1348                        memcpy(cursor_mask_image->data, the_cursor+32, 32);
1349                        XFreeCursor(x_display, mac_cursor);
1350                        XPutImage(x_display, cursor_map, cursor_gc, cursor_image, 0, 0, 0, 0, 16, 16);
1351                        XPutImage(x_display, cursor_mask_map, cursor_mask_gc, cursor_mask_image, 0, 0, 0, 0, 16, 16);
1352                        mac_cursor = XCreatePixmapCursor(x_display, cursor_map, cursor_mask_map, &black, &white, ReadMacInt8(0x885), ReadMacInt8(0x887));
1353                        XDefineCursor(x_display, the_win, mac_cursor);
1354                }
1355        }
1538   }
1539  
1540  
# Line 1360 | Line 1542 | static void update_display(void)
1542   *  Thread for screen refresh, input handling etc.
1543   */
1544  
1545 < static void *redraw_func(void *arg)
1545 > void VideoRefresh(void)
1546   {
1547 <        int tick_counter = 0;
1548 <
1549 <        while (!redraw_thread_cancel) {
1550 <
1551 <                // Wait
1552 < #ifdef HAVE_NANOSLEEP
1553 <                struct timespec req = {0, 16666667};
1372 <                nanosleep(&req, NULL);
1373 < #else
1374 <                usleep(16667);
1547 > #if defined(ENABLE_XF86_DGA) || defined(ENABLE_FBDEV_DGA)
1548 >        // Quit DGA mode if requested
1549 >        if (quit_full_screen) {
1550 >                quit_full_screen = false;
1551 >                if (display_type == DISPLAY_DGA) {
1552 > #ifdef ENABLE_XF86_DGA
1553 >                        XF86DGADirectVideo(x_display, screen, 0);
1554   #endif
1555 <
1556 < #if ENABLE_XF86_DGA
1557 <                // Quit DGA mode if requested
1558 <                if (quit_full_screen) {
1380 <                        quit_full_screen = false;
1381 <                        if (display_type == DISPLAY_DGA) {
1382 <                                XF86DGADirectVideo(x_display, screen, 0);
1383 <                                XUngrabPointer(x_display, CurrentTime);
1384 <                                XUngrabKeyboard(x_display, CurrentTime);
1385 <                                XUnmapWindow(x_display, the_win);
1386 <                                XSync(x_display, false);
1387 <                        }
1555 >                        XUngrabPointer(x_display, CurrentTime);
1556 >                        XUngrabKeyboard(x_display, CurrentTime);
1557 >                        XUnmapWindow(x_display, the_win);
1558 >                        XSync(x_display, false);
1559                  }
1560 +        }
1561   #endif
1562  
1563 < #if ENABLE_FBDEV_DGA
1564 <                // Quit DGA mode if requested
1393 <                if (quit_full_screen) {
1394 <                        quit_full_screen = false;
1395 <                        if (display_type == DISPLAY_DGA) {
1396 <                                XUngrabPointer(x_display, CurrentTime);
1397 <                                XUngrabKeyboard(x_display, CurrentTime);
1398 <                                XUnmapWindow(x_display, the_win);
1399 <                                XSync(x_display, false);
1400 <                        }
1401 <                }
1402 < #endif
1403 <                // Handle X events
1404 <                handle_events();
1563 >        // Handle X events
1564 >        handle_events();
1565  
1566 <                // Handle palette changes
1567 <                pthread_mutex_lock(&palette_lock);
1568 <                if (palette_changed) {
1409 <                        palette_changed = false;
1410 <                        if (depth == 8) {
1411 <                                XStoreColors(x_display, cmap[0], palette, 256);
1412 <                                XStoreColors(x_display, cmap[1], palette, 256);
1413 <                                
1414 < #if ENABLE_XF86_DGA
1415 <                                if (display_type == DISPLAY_DGA) {
1416 <                                        current_dga_cmap ^= 1;
1417 <                                        XF86DGAInstallColormap(x_display, screen, cmap[current_dga_cmap]);
1418 <                                }
1566 >        // Handle palette changes
1567 > #ifdef HAVE_PTHREADS
1568 >        pthread_mutex_lock(&palette_lock);
1569   #endif
1570 +        if (palette_changed) {
1571 +                palette_changed = false;
1572 +                if (depth == 8) {
1573 +                        XStoreColors(x_display, cmap[0], palette, 256);
1574 +                        XStoreColors(x_display, cmap[1], palette, 256);
1575                                  
1576 < #if ENABLE_FBDEV_DGA
1577 <                                if (display_type == DISPLAY_DGA)
1578 <                                        XSetWindowColormap(x_display, the_win, cmap[current_dga_cmap]);
1579 < #endif
1576 > #ifdef ENABLE_XF86_DGA
1577 >                        if (display_type == DISPLAY_DGA) {
1578 >                                current_dga_cmap ^= 1;
1579 >                                XF86DGAInstallColormap(x_display, screen, cmap[current_dga_cmap]);
1580                          }
1581 + #endif
1582                  }
1583 <                pthread_mutex_unlock(&palette_lock);
1583 >        }
1584 > #ifdef HAVE_PTHREADS
1585 >        pthread_mutex_unlock(&palette_lock);
1586 > #endif
1587  
1588 <                // In window mode, update display and mouse pointer
1589 <                if (display_type == DISPLAY_WINDOW) {
1590 <                        tick_counter++;
1591 <                        if (tick_counter >= frame_skip) {
1592 <                                tick_counter = 0;
1593 <                                update_display();
1594 <                        }
1588 >        // In window mode, update display
1589 >        static int tick_counter = 0;
1590 >        if (display_type == DISPLAY_WINDOW) {
1591 >                tick_counter++;
1592 >                if (frame_skip == 0)
1593 >                        update_display_dynamic(tick_counter);
1594 >                else if (tick_counter >= frame_skip) {
1595 >                        tick_counter = 0;
1596 >                        update_display_static();
1597                  }
1598          }
1599 + }
1600 +
1601 + #ifdef HAVE_PTHREADS
1602 + static void *redraw_func(void *arg)
1603 + {
1604 +        while (!redraw_thread_cancel) {
1605 + #ifdef HAVE_NANOSLEEP
1606 +                struct timespec req = {0, 16666667};
1607 +                nanosleep(&req, NULL);
1608 + #else
1609 +                usleep(16667);
1610 + #endif
1611 +                VideoRefresh();
1612 +        }
1613          return NULL;
1614   }
1615 + #endif

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines