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.9 by cebix, 1999-10-21T16:40:49Z vs.
Revision 1.16 by cebix, 2000-07-13T16:12:33Z

# 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;
# Line 120 | Line 135 | static GC cursor_gc, cursor_mask_gc;
135   static uint8 *the_buffer_copy = NULL;                           // Copy of Mac frame buffer
136   static uint8 the_cursor[64];                                            // Cursor image data
137   static bool have_shm = false;                                           // Flag: SHM extensions available
138 + static bool updt_box[17][17];                                           // Flag for Update
139 + static int nr_boxes;
140 + static const int sm_uptd[] = {4,1,6,3,0,5,2,7};
141 + static int sm_no_boxes[] = {1,8,32,64,128,300};
142  
143   // Variables for XF86 DGA mode
144   static int current_dga_cmap;                                            // Number (0 or 1) of currently installed DGA colormap
145   static Window suspend_win;                                                      // "Suspend" window
146   static void *fb_save = NULL;                                            // Saved frame buffer for suspend
147 + #ifdef HAVE_PTHREADS
148   static pthread_mutex_t frame_buffer_lock = PTHREAD_MUTEX_INITIALIZER;   // Mutex to protect frame buffer
149 + #endif
150  
151   // Variables for fbdev DGA mode
152   const char FBDEVICE_FILE_NAME[] = "/dev/fb";
153   static int fbdev_fd;
154  
155 + #ifdef ENABLE_XF86_VIDMODE
156 + // Variables for XF86 VidMode support
157 + static XF86VidModeModeInfo **x_video_modes;                     // Array of all available modes
158 + static int num_x_video_modes;
159 + #endif
160 +
161  
162   // Prototypes
163   static void *redraw_func(void *arg);
# Line 138 | Line 165 | static int event2keycode(XKeyEvent *ev);
165  
166  
167   // From main_unix.cpp
168 + extern char *x_display_name;
169   extern Display *x_display;
170  
171   // From sys_unix.cpp
# Line 151 | Line 179 | extern void SysMountFirstFloppy(void);
179   // Set VideoMonitor according to video mode
180   void set_video_monitor(int width, int height, int bytes_per_row, bool native_byte_order)
181   {
182 + #if !REAL_ADDRESSING
183          int layout = FLAYOUT_DIRECT;
184          switch (depth) {
185                  case 1:
186                          layout = FLAYOUT_DIRECT;
158                        VideoMonitor.mode = VMODE_1BIT;
187                          break;
188                  case 8:
189                          layout = FLAYOUT_DIRECT;
162                        VideoMonitor.mode = VMODE_8BIT;
190                          break;
191                  case 15:
192                          layout = FLAYOUT_HOST_555;
166                        VideoMonitor.mode = VMODE_16BIT;
193                          break;
194                  case 16:
195                          layout = FLAYOUT_HOST_565;
170                        VideoMonitor.mode = VMODE_16BIT;
196                          break;
197                  case 24:
198                  case 32:
199                          layout = FLAYOUT_HOST_888;
175                        VideoMonitor.mode = VMODE_32BIT;
200                          break;
201          }
178        VideoMonitor.x = width;
179        VideoMonitor.y = height;
180        VideoMonitor.bytes_per_row = bytes_per_row;
202          if (native_byte_order)
203                  MacFrameLayout = layout;
204          else
205                  MacFrameLayout = FLAYOUT_DIRECT;
206 + #endif
207 +        switch (depth) {
208 +                case 1:
209 +                        VideoMonitor.mode = VMODE_1BIT;
210 +                        break;
211 +                case 8:
212 +                        VideoMonitor.mode = VMODE_8BIT;
213 +                        break;
214 +                case 15:
215 +                        VideoMonitor.mode = VMODE_16BIT;
216 +                        break;
217 +                case 16:
218 +                        VideoMonitor.mode = VMODE_16BIT;
219 +                        break;
220 +                case 24:
221 +                case 32:
222 +                        VideoMonitor.mode = VMODE_32BIT;
223 +                        break;
224 +        }
225 +        VideoMonitor.x = width;
226 +        VideoMonitor.y = height;
227 +        VideoMonitor.bytes_per_row = bytes_per_row;
228   }
229  
230   // Trap SHM errors
# Line 200 | Line 243 | static int error_handler(Display *d, XEr
243   // Init window mode
244   static bool init_window(int width, int height)
245   {
246 +        int aligned_width = (width + 15) & ~15;
247 +        int aligned_height = (height + 15) & ~15;
248 +
249          // Set absolute mouse mode
250          ADBSetRelMouseMode(false);
251  
252          // Read frame skip prefs
253          frame_skip = PrefsFindInt32("frameskip");
208        if (frame_skip == 0)
209                frame_skip = 1;
254  
255          // Create window
256          XSetWindowAttributes wattr;
257          wattr.event_mask = eventmask = win_eventmask;
258          wattr.background_pixel = black_pixel;
259          wattr.border_pixel = black_pixel;
260 <        wattr.backing_store = Always;
260 >        wattr.backing_store = NotUseful;
261 >        wattr.save_under = false;
262          wattr.backing_planes = xdepth;
263  
264          XSync(x_display, false);
# Line 245 | Line 290 | static bool init_window(int width, int h
290          
291          // Try to create and attach SHM image
292          have_shm = false;
293 <        if (depth != 1 && XShmQueryExtension(x_display)) {
293 >        if (depth != 1 && local_X11 && XShmQueryExtension(x_display)) {
294  
295                  // Create SHM image ("height + 2" for safety)
296                  img = XShmCreateImage(x_display, vis, depth, depth == 1 ? XYBitmap : ZPixmap, 0, &shminfo, width, height);
297 <                shminfo.shmid = shmget(IPC_PRIVATE, (height + 2) * img->bytes_per_line, IPC_CREAT | 0777);
298 <                the_buffer = (uint8 *)shmat(shminfo.shmid, 0, 0);
299 <                shminfo.shmaddr = img->data = (char *)the_buffer;
297 >                shminfo.shmid = shmget(IPC_PRIVATE, (aligned_height + 2) * img->bytes_per_line, IPC_CREAT | 0777);
298 >                the_buffer_copy = (uint8 *)shmat(shminfo.shmid, 0, 0);
299 >                shminfo.shmaddr = img->data = (char *)the_buffer_copy;
300                  shminfo.readOnly = False;
301  
302                  // Try to attach SHM image, catching errors
# Line 272 | Line 317 | static bool init_window(int width, int h
317          
318          // Create normal X image if SHM doesn't work ("height + 2" for safety)
319          if (!have_shm) {
320 <                int bytes_per_row = width;
320 >                int bytes_per_row = aligned_width;
321                  switch (depth) {
322                          case 1:
323                                  bytes_per_row /= 8;
# Line 286 | Line 331 | static bool init_window(int width, int h
331                                  bytes_per_row *= 4;
332                                  break;
333                  }
334 <                the_buffer = (uint8 *)malloc((height + 2) * bytes_per_row);
335 <                img = XCreateImage(x_display, vis, depth, depth == 1 ? XYBitmap : ZPixmap, 0, (char *)the_buffer, width, height, 32, bytes_per_row);
334 >                the_buffer_copy = (uint8 *)malloc((aligned_height + 2) * bytes_per_row);
335 >                img = XCreateImage(x_display, vis, depth, depth == 1 ? XYBitmap : ZPixmap, 0, (char *)the_buffer_copy, aligned_width, aligned_height, 32, bytes_per_row);
336          }
337  
338          // 1-Bit mode is big-endian
# Line 296 | Line 341 | static bool init_window(int width, int h
341                  img->bitmap_bit_order = MSBFirst;
342          }
343  
344 <        // Allocate memory for frame buffer copy
345 <        the_buffer_copy = (uint8 *)malloc((height + 2) * img->bytes_per_line);
344 >        // Allocate memory for frame buffer
345 >        the_buffer = (uint8 *)malloc((aligned_height + 2) * img->bytes_per_line);
346  
347          // Create GC
348          the_gc = XCreateGC(x_display, the_win, 0, 0);
349          XSetState(x_display, the_gc, black_pixel, white_pixel, GXcopy, AllPlanes);
350  
351 <        // Create cursor
352 <        cursor_image = XCreateImage(x_display, vis, 1, XYPixmap, 0, (char *)the_cursor, 16, 16, 16, 2);
353 <        cursor_image->byte_order = MSBFirst;
354 <        cursor_image->bitmap_bit_order = MSBFirst;
355 <        cursor_mask_image = XCreateImage(x_display, vis, 1, XYPixmap, 0, (char *)the_cursor+32, 16, 16, 16, 2);
356 <        cursor_mask_image->byte_order = MSBFirst;
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);
351 >        // Create no_cursor
352 >        mac_cursor = XCreatePixmapCursor(x_display,
353 >           XCreatePixmap(x_display, the_win, 1, 1, 1),
354 >           XCreatePixmap(x_display, the_win, 1, 1, 1),
355 >           &black, &white, 0, 0);
356 >        XDefineCursor(x_display, the_win, mac_cursor);
357  
358          // Set VideoMonitor
359   #ifdef WORDS_BIGENDIAN
# Line 325 | Line 364 | static bool init_window(int width, int h
364          
365   #if REAL_ADDRESSING
366          VideoMonitor.mac_frame_base = (uint32)the_buffer;
328        MacFrameLayout = FLAYOUT_DIRECT;
367   #else
368          VideoMonitor.mac_frame_base = MacFrameBaseMac;
369   #endif
# Line 335 | Line 373 | static bool init_window(int width, int h
373   // Init fbdev DGA display
374   static bool init_fbdev_dga(char *in_fb_name)
375   {
376 < #if ENABLE_FBDEV_DGA
376 > #ifdef ENABLE_FBDEV_DGA
377          // Find the maximum depth available
378          int ndepths, max_depth(0);
379          int *depths = XListDepths(x_display, screen, &ndepths);
# Line 461 | Line 499 | static bool init_fbdev_dga(char *in_fb_n
499          set_video_monitor(width, height, bytes_per_row, true);
500   #if REAL_ADDRESSING
501          VideoMonitor.mac_frame_base = (uint32)the_buffer;
464        MacFrameLayout = FLAYOUT_DIRECT;
502   #else
503          VideoMonitor.mac_frame_base = MacFrameBaseMac;
504   #endif
# Line 475 | Line 512 | static bool init_fbdev_dga(char *in_fb_n
512   // Init XF86 DGA display
513   static bool init_xf86_dga(int width, int height)
514   {
515 < #if ENABLE_XF86_DGA
515 > #ifdef ENABLE_XF86_DGA
516          // Set relative mouse mode
517          ADBSetRelMouseMode(true);
518  
519 + #ifdef ENABLE_XF86_VIDMODE
520 +        // Switch to best mode
521 +        if (has_vidmode) {
522 +                int best = 0;
523 +                for (int i=1; i<num_x_video_modes; i++) {
524 +                        if (x_video_modes[i]->hdisplay >= width && x_video_modes[i]->vdisplay >= height &&
525 +                                x_video_modes[i]->hdisplay <= x_video_modes[best]->hdisplay && x_video_modes[i]->vdisplay <= x_video_modes[best]->vdisplay) {
526 +                                best = i;
527 +                        }
528 +                }
529 +                XF86VidModeSwitchToMode(x_display, screen, x_video_modes[best]);
530 +                XF86VidModeSetViewPort(x_display, screen, 0, 0);
531 +        }
532 + #endif
533 +
534          // Create window
535          XSetWindowAttributes wattr;
536          wattr.event_mask = eventmask = dga_eventmask;
# Line 608 | Line 660 | static void keycode_init(void)
660  
661   bool VideoInit(bool classic)
662   {
663 +        // Check if X server runs on local machine
664 +        local_X11 = (strncmp(XDisplayName(x_display_name), ":", 1) == 0)
665 +                 || (strncmp(XDisplayName(x_display_name), "unix:", 5) == 0);
666 +    
667          // Init keycode translation
668          keycode_init();
669  
670 +        // Read prefs
671 +        mouse_wheel_mode = PrefsFindInt16("mousewheelmode");
672 +        mouse_wheel_lines = PrefsFindInt16("mousewheellines");
673 +
674          // Find screen and root window
675          screen = XDefaultScreen(x_display);
676          rootwin = XRootWindow(x_display, screen);
# Line 618 | Line 678 | bool VideoInit(bool classic)
678          // Get screen depth
679          xdepth = DefaultDepth(x_display, screen);
680          
681 < #if ENABLE_FBDEV_DGA
681 > #ifdef ENABLE_FBDEV_DGA
682          // Frame buffer name
683          char fb_name[20];
684          
# Line 628 | Line 688 | bool VideoInit(bool classic)
688          else
689                  has_dga = false;
690   #endif
691 <        
692 < #if ENABLE_XF86_DGA
691 >
692 > #ifdef ENABLE_XF86_DGA
693          // DGA available?
694 <        int event_base, error_base;
695 <        if (XF86DGAQueryExtension(x_display, &event_base, &error_base)) {
694 >        int dga_event_base, dga_error_base;
695 >        if (local_X11 && XF86DGAQueryExtension(x_display, &dga_event_base, &dga_error_base)) {
696                  int dga_flags = 0;
697                  XF86DGAQueryDirectVideo(x_display, screen, &dga_flags);
698                  has_dga = dga_flags & XF86DGADirectPresent;
# Line 640 | Line 700 | bool VideoInit(bool classic)
700                  has_dga = false;
701   #endif
702  
703 + #ifdef ENABLE_XF86_VIDMODE
704 +        // VidMode available?
705 +        int vm_event_base, vm_error_base;
706 +        has_vidmode = XF86VidModeQueryExtension(x_display, &vm_event_base, &vm_error_base);
707 +        if (has_vidmode)
708 +                XF86VidModeGetAllModeLines(x_display, screen, &num_x_video_modes, &x_video_modes);
709 + #endif
710 +        
711          // Find black and white colors
712          XParseColor(x_display, DefaultColormap(x_display, screen), "rgb:00/00/00", &black);
713          XAllocColor(x_display, DefaultColormap(x_display, screen), &black);
# Line 705 | Line 773 | bool VideoInit(bool classic)
773          if (mode_str) {
774                  if (sscanf(mode_str, "win/%d/%d", &width, &height) == 2)
775                          display_type = DISPLAY_WINDOW;
776 < #if ENABLE_FBDEV_DGA
776 > #ifdef ENABLE_FBDEV_DGA
777                  else if (has_dga && sscanf(mode_str, "dga/%19s", fb_name) == 1) {
778   #else
779                  else if (has_dga && sscanf(mode_str, "dga/%d/%d", &width, &height) == 2) {
# Line 729 | Line 797 | bool VideoInit(bool classic)
797                                  return false;
798                          break;
799                  case DISPLAY_DGA:
800 < #if ENABLE_FBDEV_DGA
800 > #ifdef ENABLE_FBDEV_DGA
801                          if (!init_fbdev_dga(fb_name))
802   #else
803                          if (!init_xf86_dga(width, height))
# Line 738 | Line 806 | bool VideoInit(bool classic)
806                          break;
807          }
808  
809 + #ifdef HAVE_PTHREADS
810          // Lock down frame buffer
811          pthread_mutex_lock(&frame_buffer_lock);
812 + #endif
813  
814   #if !REAL_ADDRESSING
815          // Set variables for UAE memory mapping
# Line 751 | Line 821 | bool VideoInit(bool classic)
821                  MacFrameLayout = FLAYOUT_NONE;
822   #endif
823  
754        // Start redraw/input thread
824          XSync(x_display, false);
825 +
826 + #ifdef HAVE_PTHREADS
827 +        // Start redraw/input thread
828          redraw_thread_active = (pthread_create(&redraw_thread, NULL, redraw_func, NULL) == 0);
829 <        if (!redraw_thread_active)
829 >        if (!redraw_thread_active) {
830                  printf("FATAL: cannot create redraw thread\n");
831 <        return redraw_thread_active;
831 >                return false;
832 >        }
833 > #endif
834 >        return true;
835   }
836  
837  
# Line 766 | Line 841 | bool VideoInit(bool classic)
841  
842   void VideoExit(void)
843   {
844 + #ifdef HAVE_PTHREADS
845          // Stop redraw thread
846          if (redraw_thread_active) {
847                  redraw_thread_cancel = true;
# Line 775 | Line 851 | void VideoExit(void)
851                  pthread_join(redraw_thread, NULL);
852                  redraw_thread_active = false;
853          }
854 + #endif
855  
856 + #ifdef HAVE_PTHREADS
857          // Unlock frame buffer
858          pthread_mutex_unlock(&frame_buffer_lock);
859 + #endif
860  
861          // Close window and server connection
862          if (x_display != NULL) {
863                  XSync(x_display, false);
864  
865 < #if ENABLE_XF86_DGA
865 > #ifdef ENABLE_XF86_DGA
866                  if (display_type == DISPLAY_DGA) {
867                          XF86DGADirectVideo(x_display, screen, 0);
868                          XUngrabPointer(x_display, CurrentTime);
# Line 791 | Line 870 | void VideoExit(void)
870                  }
871   #endif
872  
873 < #if ENABLE_FBDEV_DGA
873 > #ifdef ENABLE_XF86_VIDMODE
874 >                if (has_vidmode && display_type == DISPLAY_DGA)
875 >                        XF86VidModeSwitchToMode(x_display, screen, x_video_modes[0]);
876 > #endif
877 >
878 > #ifdef ENABLE_FBDEV_DGA
879                  if (display_type == DISPLAY_DGA) {
880                          XUngrabPointer(x_display, CurrentTime);
881                          XUngrabKeyboard(x_display, CurrentTime);
882                          close(fbdev_fd);
883                  }
884   #endif
801                
802                if (the_buffer_copy) {
803                        free(the_buffer_copy);
804                        the_buffer_copy = NULL;
805                }
885  
886                  XFlush(x_display);
887                  XSync(x_display, false);
# Line 810 | Line 889 | void VideoExit(void)
889                          XFreeColormap(x_display, cmap[0]);
890                          XFreeColormap(x_display, cmap[1]);
891                  }
892 +
893 +                if (the_buffer) {
894 +                        free(the_buffer);
895 +                        the_buffer = NULL;
896 +                }
897 +
898 +                if (!have_shm && the_buffer_copy) {
899 +                        free(the_buffer_copy);
900 +                        the_buffer_copy = NULL;
901 +                }
902          }
903   }
904  
# Line 836 | Line 925 | void VideoInterrupt(void)
925          if (emerg_quit)
926                  QuitEmulator();
927  
928 + #ifdef HAVE_PTHREADS
929          // Temporarily give up frame buffer lock (this is the point where
930          // we are suspended when the user presses Ctrl-Tab)
931          pthread_mutex_unlock(&frame_buffer_lock);
932          pthread_mutex_lock(&frame_buffer_lock);
933 + #endif
934   }
935  
936  
# Line 849 | Line 940 | void VideoInterrupt(void)
940  
941   void video_set_palette(uint8 *pal)
942   {
943 + #ifdef HAVE_PTHREDS
944          pthread_mutex_lock(&palette_lock);
945 + #endif
946  
947          // Convert colors to XColor array
948          for (int i=0; i<256; i++) {
# Line 863 | Line 956 | void video_set_palette(uint8 *pal)
956          // Tell redraw thread to change palette
957          palette_changed = true;
958  
959 + #ifdef HAVE_PTHREADS
960          pthread_mutex_unlock(&palette_lock);
961 + #endif
962   }
963  
964  
# Line 871 | Line 966 | void video_set_palette(uint8 *pal)
966   *  Suspend/resume emulator
967   */
968  
969 < #if ENABLE_XF86_DGA || ENABLE_FBDEV_DGA
969 > #if defined(ENABLE_XF86_DGA) || defined(ENABLE_FBDEV_DGA)
970   static void suspend_emul(void)
971   {
972          if (display_type == DISPLAY_DGA) {
# Line 879 | Line 974 | static void suspend_emul(void)
974                  ADBKeyUp(0x36);
975                  ctrl_down = false;
976  
977 + #ifdef HAVE_PTHREADS
978                  // Lock frame buffer (this will stop the MacOS thread)
979                  pthread_mutex_lock(&frame_buffer_lock);
980 + #endif
981  
982                  // Save frame buffer
983                  fb_save = malloc(VideoMonitor.y * VideoMonitor.bytes_per_row);
# Line 888 | Line 985 | static void suspend_emul(void)
985                          memcpy(fb_save, the_buffer, VideoMonitor.y * VideoMonitor.bytes_per_row);
986  
987                  // Close full screen display
988 < #if ENABLE_XF86_DGA
988 > #ifdef ENABLE_XF86_DGA
989                  XF86DGADirectVideo(x_display, screen, 0);
990   #endif
991                  XUngrabPointer(x_display, CurrentTime);
# Line 929 | Line 1026 | static void resume_emul(void)
1026          XSync(x_display, false);
1027          XGrabKeyboard(x_display, rootwin, 1, GrabModeAsync, GrabModeAsync, CurrentTime);
1028          XGrabPointer(x_display, rootwin, 1, PointerMotionMask | ButtonPressMask | ButtonReleaseMask, GrabModeAsync, GrabModeAsync, None, None, CurrentTime);
1029 < #if ENABLE_XF86_DGA
1029 > #ifdef ENABLE_XF86_DGA
1030          XF86DGADirectVideo(x_display, screen, XF86DGADirectGraphics | XF86DGADirectKeyb | XF86DGADirectMouse);
1031          XF86DGASetViewPort(x_display, screen, 0, 0);
1032   #endif
# Line 942 | Line 1039 | static void resume_emul(void)
1039                  fb_save = NULL;
1040          }
1041          
1042 + #ifdef ENABLE_XF86_DGA
1043          if (depth == 8)
946 #if ENABLE_XF86_DGA
1044                  XF86DGAInstallColormap(x_display, screen, cmap[current_dga_cmap]);
1045   #endif
1046  
1047 + #ifdef HAVE_PTHREADS
1048          // Unlock frame buffer (and continue MacOS thread)
1049          pthread_mutex_unlock(&frame_buffer_lock);
1050          emul_suspended = false;
1051 + #endif
1052   }
1053   #endif
1054  
# Line 1011 | Line 1110 | static int kc_decode(KeySym ks)
1110                  case XK_period: case XK_greater: return 0x2f;
1111                  case XK_slash: case XK_question: return 0x2c;
1112  
1113 < #if ENABLE_XF86_DGA || ENABLE_FBDEV_DGA
1113 > #if defined(ENABLE_XF86_DGA) || defined(ENABLE_FBDEV_DGA)
1114                  case XK_Tab: if (ctrl_down) {suspend_emul(); return -1;} else return 0x30;
1115   #else
1116                  case XK_Tab: return 0x30;
# Line 1137 | Line 1236 | static void handle_events(void)
1236                                  unsigned int button = ((XButtonEvent *)&event)->button;
1237                                  if (button < 4)
1238                                          ADBMouseDown(button - 1);
1239 +                                else if (button < 6) {  // Wheel mouse
1240 +                                        if (mouse_wheel_mode == 0) {
1241 +                                                int key = (button == 5) ? 0x79 : 0x74;  // Page up/down
1242 +                                                ADBKeyDown(key);
1243 +                                                ADBKeyUp(key);
1244 +                                        } else {
1245 +                                                int key = (button == 5) ? 0x3d : 0x3e;  // Cursor up/down
1246 +                                                for(int i=0; i<mouse_wheel_lines; i++) {
1247 +                                                        ADBKeyDown(key);
1248 +                                                        ADBKeyUp(key);
1249 +                                                }
1250 +                                        }
1251 +                                }
1252                                  break;
1253                          }
1254                          case ButtonRelease: {
# Line 1177 | Line 1289 | static void handle_events(void)
1289                                                  if (code == 0x36)
1290                                                          ctrl_down = true;
1291                                          } else {
1292 < #if ENABLE_XF86_DGA || ENABLE_FBDEV_DGA
1292 > #if defined(ENABLE_XF86_DGA) || defined(ENABLE_FBDEV_DGA)
1293                                                  if (code == 0x31)
1294                                                          resume_emul();  // Space wakes us up
1295   #endif
# Line 1202 | Line 1314 | static void handle_events(void)
1314  
1315                          // Hidden parts exposed, force complete refresh of window
1316                          case Expose:
1317 <                                if (display_type == DISPLAY_WINDOW)
1318 <                                        memset(the_buffer_copy, 0, VideoMonitor.bytes_per_row * VideoMonitor.y);
1317 >                                if (display_type == DISPLAY_WINDOW) {
1318 >                                        if (frame_skip == 0) {  // Dynamic refresh
1319 >                                                int x1, y1;
1320 >                                                for (y1=0; y1<16; y1++)
1321 >                                                for (x1=0; x1<16; x1++)
1322 >                                                        updt_box[x1][y1] = true;
1323 >                                                nr_boxes = 16 * 16;
1324 >                                        } else
1325 >                                                memset(the_buffer_copy, 0, VideoMonitor.bytes_per_row * VideoMonitor.y);
1326 >                                }
1327                                  break;
1328                  }
1329          }
# Line 1214 | Line 1334 | static void handle_events(void)
1334   *  Window display update
1335   */
1336  
1337 < static void update_display(void)
1337 > // Dynamic display update (variable frame rate for each box)
1338 > static void update_display_dynamic(int ticker)
1339 > {
1340 >        int y1, y2, y2s, y2a, i, x1, xm, xmo, ymo, yo, yi, yil, xic, xicl, xi;
1341 >        int xil = 0;
1342 >        int rxm = 0, rxmo = 0;
1343 >        int bytes_per_row = VideoMonitor.bytes_per_row;
1344 >        int bytes_per_pixel = VideoMonitor.bytes_per_row / VideoMonitor.x;
1345 >        int rx = VideoMonitor.bytes_per_row / 16;
1346 >        int ry = VideoMonitor.y / 16;
1347 >        int max_box;
1348 >
1349 >        y2s = sm_uptd[ticker % 8];
1350 >        y2a = 8;
1351 >        for (i = 0; i < 6; i++)
1352 >                if (ticker % (2 << i))
1353 >                        break;
1354 >        max_box = sm_no_boxes[i];
1355 >
1356 >        if (y2a) {
1357 >                for (y1=0; y1<16; y1++) {
1358 >                        for (y2=y2s; y2 < ry; y2 += y2a) {
1359 >                                i = ((y1 * ry) + y2) * bytes_per_row;
1360 >                                for (x1=0; x1<16; x1++, i += rx) {
1361 >                                        if (updt_box[x1][y1] == false) {
1362 >                                                if (memcmp(&the_buffer_copy[i], &the_buffer[i], rx)) {
1363 >                                                        updt_box[x1][y1] = true;
1364 >                                                        nr_boxes++;
1365 >                                                }
1366 >                                        }
1367 >                                }
1368 >                        }
1369 >                }
1370 >        }
1371 >
1372 >        if ((nr_boxes <= max_box) && (nr_boxes)) {
1373 >                for (y1=0; y1<16; y1++) {
1374 >                        for (x1=0; x1<16; x1++) {
1375 >                                if (updt_box[x1][y1] == true) {
1376 >                                        if (rxm == 0)
1377 >                                                xm = x1;
1378 >                                        rxm += rx;
1379 >                                        updt_box[x1][y1] = false;
1380 >                                }
1381 >                                if (((updt_box[x1+1][y1] == false) || (x1 == 15)) && (rxm)) {
1382 >                                        if ((rxmo != rxm) || (xmo != xm) || (yo != y1 - 1)) {
1383 >                                                if (rxmo) {
1384 >                                                        xi = xmo * rx;
1385 >                                                        yi = ymo * ry;
1386 >                                                        xil = rxmo;
1387 >                                                        yil = (yo - ymo +1) * ry;
1388 >                                                }
1389 >                                                rxmo = rxm;
1390 >                                                xmo = xm;
1391 >                                                ymo = y1;
1392 >                                        }
1393 >                                        rxm = 0;
1394 >                                        yo = y1;
1395 >                                }      
1396 >                                if (xil) {
1397 >                                        i = (yi * bytes_per_row) + xi;
1398 >                                        for (y2=0; y2 < yil; y2++, i += bytes_per_row)
1399 >                                                memcpy(&the_buffer_copy[i], &the_buffer[i], xil);
1400 >                                        if (depth == 1) {
1401 >                                                if (have_shm)
1402 >                                                        XShmPutImage(x_display, the_win, the_gc, img, xi * 8, yi, xi * 8, yi, xil * 8, yil, 0);
1403 >                                                else
1404 >                                                        XPutImage(x_display, the_win, the_gc, img, xi * 8, yi, xi * 8, yi, xil * 8, yil);
1405 >                                        } else {
1406 >                                                if (have_shm)
1407 >                                                        XShmPutImage(x_display, the_win, the_gc, img, xi / bytes_per_pixel, yi, xi / bytes_per_pixel, yi, xil / bytes_per_pixel, yil, 0);
1408 >                                                else
1409 >                                                        XPutImage(x_display, the_win, the_gc, img, xi / bytes_per_pixel, yi, xi / bytes_per_pixel, yi, xil / bytes_per_pixel, yil);
1410 >                                        }
1411 >                                        xil = 0;
1412 >                                }
1413 >                                if ((x1 == 15) && (y1 == 15) && (rxmo)) {
1414 >                                        x1--;
1415 >                                        xi = xmo * rx;
1416 >                                        yi = ymo * ry;
1417 >                                        xil = rxmo;
1418 >                                        yil = (yo - ymo +1) * ry;
1419 >                                        rxmo = 0;
1420 >                                }
1421 >                        }
1422 >                }
1423 >                nr_boxes = 0;
1424 >        }
1425 > }
1426 >
1427 > // Static display update (fixed frame rate, but incremental)
1428 > static void update_display_static(void)
1429   {
1219        // In classic mode, copy the frame buffer from Mac RAM
1220        if (classic_mode)
1221                memcpy(the_buffer, Mac2HostAddr(0x3fa700), VideoMonitor.bytes_per_row * VideoMonitor.y);
1222        
1430          // Incremental update code
1431          int wide = 0, high = 0, x1, x2, y1, y2, i, j;
1432          int bytes_per_row = VideoMonitor.bytes_per_row;
# Line 1280 | Line 1487 | static void update_display(void)
1487                          if (high && wide) {
1488                                  for (j=y1; j<=y2; j++) {
1489                                          i = j * bytes_per_row + (x1 >> 3);
1490 <                                        memcpy(&the_buffer_copy[i], &the_buffer[i], wide >> 3);
1490 >                                        memcpy(the_buffer_copy + i, the_buffer + i, wide >> 3);
1491                                  }
1492                          }
1493  
# Line 1319 | Line 1526 | static void update_display(void)
1526                          if (high && wide) {
1527                                  for (j=y1; j<=y2; j++) {
1528                                          i = j * bytes_per_row + x1 * bytes_per_pixel;
1529 <                                        memcpy(&the_buffer_copy[i], &the_buffer[i], bytes_per_pixel * wide);
1529 >                                        memcpy(the_buffer_copy + i, the_buffer + i, bytes_per_pixel * wide);
1530                                  }
1531                          }
1532                  }
# Line 1332 | Line 1539 | static void update_display(void)
1539                  else
1540                          XPutImage(x_display, the_win, the_gc, img, x1, y1, x1, y1, wide, high);
1541          }
1335
1336        // Has the Mac started? (cursor data is not valid otherwise)
1337        if (HasMacStarted()) {
1338
1339                // Set new cursor image if it was changed
1340                if (memcmp(the_cursor, Mac2HostAddr(0x844), 64)) {
1341                        memcpy(the_cursor, Mac2HostAddr(0x844), 64);
1342                        memcpy(cursor_image->data, the_cursor, 32);
1343                        memcpy(cursor_mask_image->data, the_cursor+32, 32);
1344                        XFreeCursor(x_display, mac_cursor);
1345                        XPutImage(x_display, cursor_map, cursor_gc, cursor_image, 0, 0, 0, 0, 16, 16);
1346                        XPutImage(x_display, cursor_mask_map, cursor_mask_gc, cursor_mask_image, 0, 0, 0, 0, 16, 16);
1347                        mac_cursor = XCreatePixmapCursor(x_display, cursor_map, cursor_mask_map, &black, &white, ReadMacInt8(0x885), ReadMacInt8(0x887));
1348                        XDefineCursor(x_display, the_win, mac_cursor);
1349                }
1350        }
1542   }
1543  
1544  
# Line 1355 | Line 1546 | static void update_display(void)
1546   *  Thread for screen refresh, input handling etc.
1547   */
1548  
1549 < static void *redraw_func(void *arg)
1549 > void VideoRefresh(void)
1550   {
1551 <        int tick_counter = 0;
1552 <
1553 <        while (!redraw_thread_cancel) {
1554 <
1555 <                // Wait
1556 < #ifdef HAVE_NANOSLEEP
1557 <                struct timespec req = {0, 16666667};
1367 <                nanosleep(&req, NULL);
1368 < #else
1369 <                usleep(16667);
1551 > #if defined(ENABLE_XF86_DGA) || defined(ENABLE_FBDEV_DGA)
1552 >        // Quit DGA mode if requested
1553 >        if (quit_full_screen) {
1554 >                quit_full_screen = false;
1555 >                if (display_type == DISPLAY_DGA) {
1556 > #ifdef ENABLE_XF86_DGA
1557 >                        XF86DGADirectVideo(x_display, screen, 0);
1558   #endif
1559 <
1560 < #if ENABLE_XF86_DGA
1561 <                // Quit DGA mode if requested
1562 <                if (quit_full_screen) {
1375 <                        quit_full_screen = false;
1376 <                        if (display_type == DISPLAY_DGA) {
1377 <                                XF86DGADirectVideo(x_display, screen, 0);
1378 <                                XUngrabPointer(x_display, CurrentTime);
1379 <                                XUngrabKeyboard(x_display, CurrentTime);
1380 <                                XUnmapWindow(x_display, the_win);
1381 <                                XSync(x_display, false);
1382 <                        }
1559 >                        XUngrabPointer(x_display, CurrentTime);
1560 >                        XUngrabKeyboard(x_display, CurrentTime);
1561 >                        XUnmapWindow(x_display, the_win);
1562 >                        XSync(x_display, false);
1563                  }
1564 +        }
1565   #endif
1566  
1567 < #if ENABLE_FBDEV_DGA
1568 <                // Quit DGA mode if requested
1569 <                if (quit_full_screen) {
1570 <                        quit_full_screen = false;
1567 >        // Handle X events
1568 >        handle_events();
1569 >
1570 >        // Handle palette changes
1571 > #ifdef HAVE_PTHREADS
1572 >        pthread_mutex_lock(&palette_lock);
1573 > #endif
1574 >        if (palette_changed) {
1575 >                palette_changed = false;
1576 >                if (depth == 8) {
1577 >                        XStoreColors(x_display, cmap[0], palette, 256);
1578 >                        XStoreColors(x_display, cmap[1], palette, 256);
1579 >                                
1580 > #ifdef ENABLE_XF86_DGA
1581                          if (display_type == DISPLAY_DGA) {
1582 <                                XUngrabPointer(x_display, CurrentTime);
1583 <                                XUngrabKeyboard(x_display, CurrentTime);
1393 <                                XUnmapWindow(x_display, the_win);
1394 <                                XSync(x_display, false);
1582 >                                current_dga_cmap ^= 1;
1583 >                                XF86DGAInstallColormap(x_display, screen, cmap[current_dga_cmap]);
1584                          }
1585 + #endif
1586                  }
1587 +        }
1588 + #ifdef HAVE_PTHREADS
1589 +        pthread_mutex_unlock(&palette_lock);
1590   #endif
1398                // Handle X events
1399                handle_events();
1591  
1592 <                // Handle palette changes
1593 <                pthread_mutex_lock(&palette_lock);
1594 <                if (palette_changed) {
1595 <                        palette_changed = false;
1596 <                        if (depth == 8) {
1597 <                                XStoreColors(x_display, cmap[0], palette, 256);
1598 <                                XStoreColors(x_display, cmap[1], palette, 256);
1599 <                                
1600 < #if ENABLE_XF86_DGA
1410 <                                if (display_type == DISPLAY_DGA) {
1411 <                                        current_dga_cmap ^= 1;
1412 <                                        XF86DGAInstallColormap(x_display, screen, cmap[current_dga_cmap]);
1413 <                                }
1414 < #endif
1415 <                        }
1592 >        // In window mode, update display
1593 >        static int tick_counter = 0;
1594 >        if (display_type == DISPLAY_WINDOW) {
1595 >                tick_counter++;
1596 >                if (frame_skip == 0)
1597 >                        update_display_dynamic(tick_counter);
1598 >                else if (tick_counter >= frame_skip) {
1599 >                        tick_counter = 0;
1600 >                        update_display_static();
1601                  }
1602 <                pthread_mutex_unlock(&palette_lock);
1602 >        }
1603 > }
1604  
1605 <                // In window mode, update display and mouse pointer
1606 <                if (display_type == DISPLAY_WINDOW) {
1607 <                        tick_counter++;
1608 <                        if (tick_counter >= frame_skip) {
1609 <                                tick_counter = 0;
1610 <                                update_display();
1611 <                        }
1612 <                }
1605 > #ifdef HAVE_PTHREADS
1606 > static void *redraw_func(void *arg)
1607 > {
1608 >        while (!redraw_thread_cancel) {
1609 > #ifdef HAVE_NANOSLEEP
1610 >                struct timespec req = {0, 16666667};
1611 >                nanosleep(&req, NULL);
1612 > #else
1613 >                usleep(16667);
1614 > #endif
1615 >                VideoRefresh();
1616          }
1617          return NULL;
1618   }
1619 + #endif

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines