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

Comparing BasiliskII/src/Unix/video_x.cpp (file contents):
Revision 1.1 by cebix, 1999-10-03T14:16:25Z vs.
Revision 1.13 by cebix, 2000-02-11T17:20:44Z

# Line 48 | Line 48
48   #define DEBUG 1
49   #include "debug.h"
50  
51 < #if ENABLE_DGA
51 > #if ENABLE_XF86_DGA
52   #include <X11/extensions/xf86dga.h>
53   #endif
54  
55 + #if ENABLE_XF86_VIDMODE
56 + #include <X11/extensions/xf86vmode.h>
57 + #endif
58 +
59 + #if ENABLE_FBDEV_DGA
60 + #include <sys/mman.h>
61 + #endif
62 +
63 +
64  
65   // Display types
66   enum {
# Line 59 | Line 68 | enum {
68          DISPLAY_DGA             // DGA fullscreen display
69   };
70  
62
71   // Constants
72 < const char KEYCODE_FILE_NAME[] = "/usr/local/lib/basilisk_ii_keycodes";
72 > const char KEYCODE_FILE_NAME[] = DATADIR "/keycodes";
73 > const char FBDEVICES_FILE_NAME[] = DATADIR "/fbdevices";
74  
75  
76   // Global variables
77 < static int32 frame_skip;
77 > static int32 frame_skip;                                                        // Prefs items
78 > static int16 mouse_wheel_mode = 1;
79 > static int16 mouse_wheel_lines = 3;
80 >
81   static int display_type = DISPLAY_WINDOW;                       // See enum above
82   static uint8 *the_buffer;                                                       // Mac frame buffer
83   static bool redraw_thread_active = false;                       // Flag: Redraw thread installed
# Line 73 | Line 85 | static volatile bool redraw_thread_cance
85   static pthread_t redraw_thread;                                         // Redraw thread
86  
87   static bool has_dga = false;                                            // Flag: Video DGA capable
88 + static bool has_vidmode = false;                                        // Flag: VidMode extension available
89  
90   static bool ctrl_down = false;                                          // Flag: Ctrl key pressed
91 + static bool caps_on = false;                                            // Flag: Caps Lock on
92   static bool quit_full_screen = false;                           // Flag: DGA close requested from redraw thread
93   static bool emerg_quit = false;                                         // Flag: Ctrl-Esc pressed, emergency quit requested from MacOS thread
94   static bool emul_suspended = false;                                     // Flag: Emulator suspended
# Line 113 | Line 127 | static GC cursor_gc, cursor_mask_gc;
127   static uint8 *the_buffer_copy = NULL;                           // Copy of Mac frame buffer
128   static uint8 the_cursor[64];                                            // Cursor image data
129   static bool have_shm = false;                                           // Flag: SHM extensions available
130 + static bool updt_box[17][17];                                           // Flag for Update
131 + static int nr_boxes;
132 + static const int sm_uptd[] = {4,1,6,3,0,5,2,7};
133 + static int sm_no_boxes[] = {1,8,32,64,128,300};
134  
135 < // Variables for DGA mode
135 > // Variables for XF86 DGA mode
136   static int current_dga_cmap;                                            // Number (0 or 1) of currently installed DGA colormap
137   static Window suspend_win;                                                      // "Suspend" window
138   static void *fb_save = NULL;                                            // Saved frame buffer for suspend
121
139   static pthread_mutex_t frame_buffer_lock = PTHREAD_MUTEX_INITIALIZER;   // Mutex to protect frame buffer
140  
141 + // Variables for fbdev DGA mode
142 + const char FBDEVICE_FILE_NAME[] = "/dev/fb";
143 + static int fbdev_fd;
144 +
145 + #if ENABLE_XF86_VIDMODE
146 + // Variables for XF86 VidMode support
147 + static XF86VidModeModeInfo **x_video_modes;                     // Array of all available modes
148 + static int num_x_video_modes;
149 + #endif
150 +
151  
152   // Prototypes
153   static void *redraw_func(void *arg);
# Line 141 | Line 168 | extern void SysMountFirstFloppy(void);
168   // Set VideoMonitor according to video mode
169   void set_video_monitor(int width, int height, int bytes_per_row, bool native_byte_order)
170   {
171 <        int layout;
171 >        int layout = FLAYOUT_DIRECT;
172          switch (depth) {
173                  case 1:
174                          layout = FLAYOUT_DIRECT;
# Line 190 | Line 217 | static int error_handler(Display *d, XEr
217   // Init window mode
218   static bool init_window(int width, int height)
219   {
220 +        int aligned_width = (width + 15) & ~15;
221 +        int aligned_height = (height + 15) & ~15;
222 +
223          // Set absolute mouse mode
224          ADBSetRelMouseMode(false);
225  
# Line 203 | Line 233 | static bool init_window(int width, int h
233          wattr.event_mask = eventmask = win_eventmask;
234          wattr.background_pixel = black_pixel;
235          wattr.border_pixel = black_pixel;
236 <        wattr.backing_store = Always;
236 >        wattr.backing_store = NotUseful;
237 >        wattr.save_under = false;
238          wattr.backing_planes = xdepth;
239  
240          XSync(x_display, false);
# Line 232 | Line 263 | static bool init_window(int width, int h
263                  XSetWMNormalHints(x_display, the_win, hints);
264                  XFree((char *)hints);
265          }
266 <
266 >        
267          // Try to create and attach SHM image
268          have_shm = false;
269          if (depth != 1 && XShmQueryExtension(x_display)) {
270  
271                  // Create SHM image ("height + 2" for safety)
272                  img = XShmCreateImage(x_display, vis, depth, depth == 1 ? XYBitmap : ZPixmap, 0, &shminfo, width, height);
273 <                shminfo.shmid = shmget(IPC_PRIVATE, (height + 2) * img->bytes_per_line, IPC_CREAT | 0777);
274 <                the_buffer = (uint8 *)shmat(shminfo.shmid, 0, 0);
275 <                shminfo.shmaddr = img->data = (char *)the_buffer;
273 >                shminfo.shmid = shmget(IPC_PRIVATE, (aligned_height + 2) * img->bytes_per_line, IPC_CREAT | 0777);
274 >                the_buffer_copy = (uint8 *)shmat(shminfo.shmid, 0, 0);
275 >                shminfo.shmaddr = img->data = (char *)the_buffer_copy;
276                  shminfo.readOnly = False;
277  
278                  // Try to attach SHM image, catching errors
# Line 259 | Line 290 | static bool init_window(int width, int h
290                          shmctl(shminfo.shmid, IPC_RMID, 0);
291                  }
292          }
293 <
293 >        
294          // Create normal X image if SHM doesn't work ("height + 2" for safety)
295          if (!have_shm) {
296 <                int bytes_per_row = width;
296 >                int bytes_per_row = aligned_width;
297                  switch (depth) {
298                          case 1:
299                                  bytes_per_row /= 8;
# Line 276 | Line 307 | static bool init_window(int width, int h
307                                  bytes_per_row *= 4;
308                                  break;
309                  }
310 <                the_buffer = (uint8 *)malloc((height + 2) * bytes_per_row);
311 <                img = XCreateImage(x_display, vis, depth, depth == 1 ? XYBitmap : ZPixmap, 0, (char *)the_buffer, width, height, 32, bytes_per_row);
310 >                the_buffer_copy = (uint8 *)malloc((aligned_height + 2) * bytes_per_row);
311 >                img = XCreateImage(x_display, vis, depth, depth == 1 ? XYBitmap : ZPixmap, 0, (char *)the_buffer_copy, aligned_width, aligned_height, 32, bytes_per_row);
312          }
313  
314          // 1-Bit mode is big-endian
# Line 287 | Line 318 | static bool init_window(int width, int h
318          }
319  
320          // Allocate memory for frame buffer copy
321 <        the_buffer_copy = (uint8 *)malloc((height + 2) * img->bytes_per_line);
321 >        the_buffer = (uint8 *)malloc((aligned_height + 2) * img->bytes_per_line);
322  
323          // Create GC
324          the_gc = XCreateGC(x_display, the_win, 0, 0);
325          XSetState(x_display, the_gc, black_pixel, white_pixel, GXcopy, AllPlanes);
326  
327 <        // Create cursor
328 <        cursor_image = XCreateImage(x_display, vis, 1, XYPixmap, 0, (char *)the_cursor, 16, 16, 16, 2);
329 <        cursor_image->byte_order = MSBFirst;
330 <        cursor_image->bitmap_bit_order = MSBFirst;
331 <        cursor_mask_image = XCreateImage(x_display, vis, 1, XYPixmap, 0, (char *)the_cursor+32, 16, 16, 16, 2);
332 <        cursor_mask_image->byte_order = MSBFirst;
302 <        cursor_mask_image->bitmap_bit_order = MSBFirst;
303 <        cursor_map = XCreatePixmap(x_display, the_win, 16, 16, 1);
304 <        cursor_mask_map = XCreatePixmap(x_display, the_win, 16, 16, 1);
305 <        cursor_gc = XCreateGC(x_display, cursor_map, 0, 0);
306 <        cursor_mask_gc = XCreateGC(x_display, cursor_mask_map, 0, 0);
307 <        mac_cursor = XCreatePixmapCursor(x_display, cursor_map, cursor_mask_map, &black, &white, 0, 0);
327 >        // Create no_cursor
328 >        mac_cursor = XCreatePixmapCursor (x_display,
329 >                                           XCreatePixmap (x_display, the_win, 1, 1, 1),
330 >                                           XCreatePixmap (x_display, the_win, 1, 1, 1),
331 >                                           &black, &white, 0, 0);
332 >        XDefineCursor (x_display, the_win, mac_cursor);
333  
334          // Set VideoMonitor
335   #ifdef WORDS_BIGENDIAN
# Line 312 | Line 337 | static bool init_window(int width, int h
337   #else
338          set_video_monitor(width, height, img->bytes_per_line, img->bitmap_bit_order == LSBFirst);
339   #endif
340 +        
341   #if REAL_ADDRESSING
342          VideoMonitor.mac_frame_base = (uint32)the_buffer;
343          MacFrameLayout = FLAYOUT_DIRECT;
# Line 321 | Line 347 | static bool init_window(int width, int h
347          return true;
348   }
349  
350 < // Init DGA display
351 < static bool init_dga(int width, int height)
350 > // Init fbdev DGA display
351 > static bool init_fbdev_dga(char *in_fb_name)
352   {
353 < #if ENABLE_DGA
353 > #if ENABLE_FBDEV_DGA
354 >        // Find the maximum depth available
355 >        int ndepths, max_depth(0);
356 >        int *depths = XListDepths(x_display, screen, &ndepths);
357 >        if (depths == NULL) {
358 >                printf("FATAL: Could not determine the maximal depth available\n");
359 >                return false;
360 >        } else {
361 >                while (ndepths-- > 0) {
362 >                        if (depths[ndepths] > max_depth)
363 >                                max_depth = depths[ndepths];
364 >                }
365 >        }
366 >        
367 >        // Get fbdevices file path from preferences
368 >        const char *fbd_path = PrefsFindString("fbdevicefile");
369 >        
370 >        // Open fbdevices file
371 >        FILE *fp = fopen(fbd_path ? fbd_path : FBDEVICES_FILE_NAME, "r");
372 >        if (fp == NULL) {
373 >                char str[256];
374 >                sprintf(str, GetString(STR_NO_FBDEVICE_FILE_ERR), fbd_path ? fbd_path : FBDEVICES_FILE_NAME, strerror(errno));
375 >                ErrorAlert(str);
376 >                return false;
377 >        }
378 >        
379 >        int fb_depth;           // supported depth
380 >        uint32 fb_offset;       // offset used for mmap(2)
381 >        char fb_name[20];
382 >        char line[256];
383 >        bool device_found = false;
384 >        while (fgets(line, 255, fp)) {
385 >                // Read line
386 >                int len = strlen(line);
387 >                if (len == 0)
388 >                        continue;
389 >                line[len - 1] = '\0';
390 >                
391 >                // Comments begin with "#" or ";"
392 >                if ((line[0] == '#') || (line[0] == ';') || (line[0] == '\0'))
393 >                        continue;
394 >                
395 >                if ((sscanf(line, "%19s %d %x", &fb_name, &fb_depth, &fb_offset) == 3)
396 >                && (strcmp(fb_name, in_fb_name) == 0) && (fb_depth == max_depth)) {
397 >                        device_found = true;
398 >                        break;
399 >                }
400 >        }
401 >        
402 >        // fbdevices file completely read
403 >        fclose(fp);
404 >        
405 >        // Frame buffer name not found ? Then, display warning
406 >        if (!device_found) {
407 >                char str[256];
408 >                sprintf(str, GetString(STR_FBDEV_NAME_ERR), in_fb_name, max_depth);
409 >                ErrorAlert(str);
410 >                return false;
411 >        }
412 >        
413 >        int width = DisplayWidth(x_display, screen);
414 >        int height = DisplayHeight(x_display, screen);
415 >        depth = fb_depth; // max_depth
416 >        
417 >        // Set relative mouse mode
418 >        ADBSetRelMouseMode(false);
419 >        
420 >        // Create window
421 >        XSetWindowAttributes wattr;
422 >        wattr.override_redirect = True;
423 >        wattr.backing_store             = NotUseful;
424 >        wattr.background_pixel  = white_pixel;
425 >        wattr.border_pixel              = black_pixel;
426 >        wattr.event_mask                = eventmask = dga_eventmask;
427 >        
428 >        XSync(x_display, false);
429 >        the_win = XCreateWindow(x_display, rootwin,
430 >                0, 0, width, height,
431 >                0, xdepth, InputOutput, vis,
432 >                CWEventMask|CWBackPixel|CWBorderPixel|CWOverrideRedirect|CWBackingStore,
433 >                &wattr);
434 >        XSync(x_display, false);
435 >        XMapRaised(x_display, the_win);
436 >        XSync(x_display, false);
437 >        
438 >        // Grab mouse and keyboard
439 >        XGrabKeyboard(x_display, the_win, True,
440 >                GrabModeAsync, GrabModeAsync, CurrentTime);
441 >        XGrabPointer(x_display, the_win, True,
442 >                PointerMotionMask | ButtonPressMask | ButtonReleaseMask,
443 >                GrabModeAsync, GrabModeAsync, the_win, None, CurrentTime);
444 >        
445 >        // Set colormap
446 >        if (depth == 8) {
447 >                XSetWindowColormap(x_display, the_win, cmap[0]);
448 >                XSetWMColormapWindows(x_display, the_win, &the_win, 1);
449 >        }
450 >        
451 >        // Set VideoMonitor
452 >        int bytes_per_row = width;
453 >        switch (depth) {
454 >                case 1:
455 >                        bytes_per_row = ((width | 7) & ~7) >> 3;
456 >                        break;
457 >                case 15:
458 >                case 16:
459 >                        bytes_per_row *= 2;
460 >                        break;
461 >                case 24:
462 >                case 32:
463 >                        bytes_per_row *= 4;
464 >                        break;
465 >        }
466 >        
467 >        if ((the_buffer = (uint8 *) mmap(NULL, height * bytes_per_row, PROT_READ | PROT_WRITE, MAP_PRIVATE, fbdev_fd, fb_offset)) == MAP_FAILED) {
468 >                if ((the_buffer = (uint8 *) mmap(NULL, height * bytes_per_row, PROT_READ | PROT_WRITE, MAP_SHARED, fbdev_fd, fb_offset)) == MAP_FAILED) {
469 >                        char str[256];
470 >                        sprintf(str, GetString(STR_FBDEV_MMAP_ERR), strerror(errno));
471 >                        ErrorAlert(str);
472 >                        return false;
473 >                }
474 >        }
475 >        
476 >        set_video_monitor(width, height, bytes_per_row, true);
477 > #if REAL_ADDRESSING
478 >        VideoMonitor.mac_frame_base = (uint32)the_buffer;
479 >        MacFrameLayout = FLAYOUT_DIRECT;
480 > #else
481 >        VideoMonitor.mac_frame_base = MacFrameBaseMac;
482 > #endif
483 >        return true;
484 > #else
485 >        ErrorAlert("Basilisk II has been compiled with fbdev DGA support disabled.");
486 >        return false;
487 > #endif
488 > }
489 >
490 > // Init XF86 DGA display
491 > static bool init_xf86_dga(int width, int height)
492 > {
493 > #if ENABLE_XF86_DGA
494          // Set relative mouse mode
495          ADBSetRelMouseMode(true);
496  
497 + #if ENABLE_XF86_VIDMODE
498 +        // Switch to best mode
499 +        if (has_vidmode) {
500 +                int best = 0;
501 +                for (int i=1; i<num_x_video_modes; i++) {
502 +                        if (x_video_modes[i]->hdisplay >= width && x_video_modes[i]->vdisplay >= height &&
503 +                                x_video_modes[i]->hdisplay <= x_video_modes[best]->hdisplay && x_video_modes[i]->vdisplay <= x_video_modes[best]->vdisplay) {
504 +                                best = i;
505 +                        }
506 +                }
507 +                XF86VidModeSwitchToMode(x_display, screen, x_video_modes[best]);
508 +                XF86VidModeSetViewPort(x_display, screen, 0, 0);
509 +        }
510 + #endif
511 +
512          // Create window
513          XSetWindowAttributes wattr;
514          wattr.event_mask = eventmask = dga_eventmask;
# Line 385 | Line 566 | static bool init_dga(int width, int heig
566   #endif
567          return true;
568   #else
569 <        ErrorAlert("Basilisk II has been compiled with DGA support disabled.");
569 >        ErrorAlert("Basilisk II has been compiled with XF86 DGA support disabled.");
570          return false;
571   #endif
572   }
# Line 460 | Line 641 | bool VideoInit(bool classic)
641          // Init keycode translation
642          keycode_init();
643  
644 +        // Read prefs
645 +        mouse_wheel_mode = PrefsFindInt16("mousewheelmode");
646 +        mouse_wheel_lines = PrefsFindInt16("mousewheellines");
647 +
648          // Find screen and root window
649          screen = XDefaultScreen(x_display);
650          rootwin = XRootWindow(x_display, screen);
651 <
651 >        
652          // Get screen depth
653          xdepth = DefaultDepth(x_display, screen);
654 +        
655 + #if ENABLE_FBDEV_DGA
656 +        // Frame buffer name
657 +        char fb_name[20];
658 +        
659 +        // Could do fbdev dga ?
660 +        if ((fbdev_fd = open(FBDEVICE_FILE_NAME, O_RDWR)) != -1)
661 +                has_dga = true;
662 +        else
663 +                has_dga = false;
664 + #endif
665  
666 < #if ENABLE_DGA
666 > #if ENABLE_XF86_DGA
667          // DGA available?
668 <        int dga_flags = 0;
669 <        XF86DGAQueryDirectVideo(x_display, screen, &dga_flags);
670 <        has_dga = dga_flags & XF86DGADirectPresent;
668 >        int dga_event_base, dga_error_base;
669 >        if (XF86DGAQueryExtension(x_display, &dga_event_base, &dga_error_base)) {
670 >                int dga_flags = 0;
671 >                XF86DGAQueryDirectVideo(x_display, screen, &dga_flags);
672 >                has_dga = dga_flags & XF86DGADirectPresent;
673 >        } else
674 >                has_dga = false;
675   #endif
676  
677 + #if ENABLE_XF86_VIDMODE
678 +        // VidMode available?
679 +        int vm_event_base, vm_error_base;
680 +        has_vidmode = XF86VidModeQueryExtension(x_display, &vm_event_base, &vm_error_base);
681 +        if (has_vidmode)
682 +                XF86VidModeGetAllModeLines(x_display, screen, &num_x_video_modes, &x_video_modes);
683 + #endif
684 +        
685          // Find black and white colors
686          XParseColor(x_display, DefaultColormap(x_display, screen), "rgb:00/00/00", &black);
687          XAllocColor(x_display, DefaultColormap(x_display, screen), &black);
# Line 539 | Line 747 | bool VideoInit(bool classic)
747          if (mode_str) {
748                  if (sscanf(mode_str, "win/%d/%d", &width, &height) == 2)
749                          display_type = DISPLAY_WINDOW;
750 <                else if (has_dga && strcmp(mode_str, "dga") == 0) {
750 > #if ENABLE_FBDEV_DGA
751 >                else if (has_dga && sscanf(mode_str, "dga/%19s", fb_name) == 1) {
752 > #else
753 >                else if (has_dga && sscanf(mode_str, "dga/%d/%d", &width, &height) == 2) {
754 > #endif
755                          display_type = DISPLAY_DGA;
756 +                        if (width > DisplayWidth(x_display, screen))
757 +                                width = DisplayWidth(x_display, screen);
758 +                        if (height > DisplayHeight(x_display, screen))
759 +                                height = DisplayHeight(x_display, screen);
760 +                }
761 +                if (width <= 0)
762                          width = DisplayWidth(x_display, screen);
763 +                if (height <= 0)
764                          height = DisplayHeight(x_display, screen);
546                }
765          }
766  
767          // Initialize according to display type
# Line 553 | Line 771 | bool VideoInit(bool classic)
771                                  return false;
772                          break;
773                  case DISPLAY_DGA:
774 <                        if (!init_dga(width, height))
774 > #if ENABLE_FBDEV_DGA
775 >                        if (!init_fbdev_dga(fb_name))
776 > #else
777 >                        if (!init_xf86_dga(width, height))
778 > #endif
779                                  return false;
780                          break;
781          }
# Line 603 | Line 825 | void VideoExit(void)
825          if (x_display != NULL) {
826                  XSync(x_display, false);
827  
828 < #if ENABLE_DGA
828 > #if ENABLE_XF86_DGA
829                  if (display_type == DISPLAY_DGA) {
830                          XF86DGADirectVideo(x_display, screen, 0);
831                          XUngrabPointer(x_display, CurrentTime);
# Line 611 | Line 833 | void VideoExit(void)
833                  }
834   #endif
835  
836 <                if (the_buffer_copy) {
837 <                        free(the_buffer_copy);
838 <                        the_buffer_copy = NULL;
836 > #if ENABLE_XF86_VIDMODE
837 >                if (has_vidmode && display_type == DISPLAY_DGA)
838 >                        XF86VidModeSwitchToMode(x_display, screen, x_video_modes[0]);
839 > #endif
840 >
841 > #if ENABLE_FBDEV_DGA
842 >                if (display_type == DISPLAY_DGA) {
843 >                        XUngrabPointer(x_display, CurrentTime);
844 >                        XUngrabKeyboard(x_display, CurrentTime);
845 >                        close(fbdev_fd);
846                  }
847 + #endif
848  
849                  XFlush(x_display);
850                  XSync(x_display, false);
# Line 622 | Line 852 | void VideoExit(void)
852                          XFreeColormap(x_display, cmap[0]);
853                          XFreeColormap(x_display, cmap[1]);
854                  }
855 +
856 +                if (the_buffer) {
857 +                        free(the_buffer);
858 +                        the_buffer = NULL;
859 +                }
860 +
861 +                if (!have_shm && the_buffer_copy) {
862 +                        free(the_buffer_copy);
863 +                        the_buffer_copy = NULL;
864 +                }
865          }
866   }
867  
# Line 683 | Line 923 | void video_set_palette(uint8 *pal)
923   *  Suspend/resume emulator
924   */
925  
926 < #if ENABLE_DGA
926 > #if ENABLE_XF86_DGA || ENABLE_FBDEV_DGA
927   static void suspend_emul(void)
928   {
929          if (display_type == DISPLAY_DGA) {
# Line 700 | Line 940 | static void suspend_emul(void)
940                          memcpy(fb_save, the_buffer, VideoMonitor.y * VideoMonitor.bytes_per_row);
941  
942                  // Close full screen display
943 + #if ENABLE_XF86_DGA
944                  XF86DGADirectVideo(x_display, screen, 0);
945 + #endif
946                  XUngrabPointer(x_display, CurrentTime);
947                  XUngrabKeyboard(x_display, CurrentTime);
948                  XUnmapWindow(x_display, the_win);
# Line 714 | Line 956 | static void suspend_emul(void)
956                  wattr.backing_store = Always;
957                  wattr.backing_planes = xdepth;
958                  wattr.colormap = DefaultColormap(x_display, screen);
959 +                
960                  XSync(x_display, false);
961                  suspend_win = XCreateWindow(x_display, rootwin, 0, 0, 512, 1, 0, xdepth,
962                          InputOutput, vis, CWEventMask | CWBackPixel | CWBorderPixel |
# Line 738 | Line 981 | static void resume_emul(void)
981          XSync(x_display, false);
982          XGrabKeyboard(x_display, rootwin, 1, GrabModeAsync, GrabModeAsync, CurrentTime);
983          XGrabPointer(x_display, rootwin, 1, PointerMotionMask | ButtonPressMask | ButtonReleaseMask, GrabModeAsync, GrabModeAsync, None, None, CurrentTime);
984 + #if ENABLE_XF86_DGA
985          XF86DGADirectVideo(x_display, screen, XF86DGADirectGraphics | XF86DGADirectKeyb | XF86DGADirectMouse);
986          XF86DGASetViewPort(x_display, screen, 0, 0);
987 + #endif
988          XSync(x_display, false);
989  
990          // Restore frame buffer
# Line 748 | Line 993 | static void resume_emul(void)
993                  free(fb_save);
994                  fb_save = NULL;
995          }
996 +        
997          if (depth == 8)
998 + #if ENABLE_XF86_DGA
999                  XF86DGAInstallColormap(x_display, screen, cmap[current_dga_cmap]);
1000 + #endif
1001  
1002          // Unlock frame buffer (and continue MacOS thread)
1003          pthread_mutex_unlock(&frame_buffer_lock);
# Line 815 | Line 1063 | static int kc_decode(KeySym ks)
1063                  case XK_period: case XK_greater: return 0x2f;
1064                  case XK_slash: case XK_question: return 0x2c;
1065  
1066 < #if ENABLE_DGA
1066 > #if ENABLE_XF86_DGA || ENABLE_FBDEV_DGA
1067                  case XK_Tab: if (ctrl_down) {suspend_emul(); return -1;} else return 0x30;
1068   #else
1069                  case XK_Tab: return 0x30;
# Line 941 | Line 1189 | static void handle_events(void)
1189                                  unsigned int button = ((XButtonEvent *)&event)->button;
1190                                  if (button < 4)
1191                                          ADBMouseDown(button - 1);
1192 +                                else if (button < 6) {  // Wheel mouse
1193 +                                        if (mouse_wheel_mode == 0) {
1194 +                                                int key = (button == 5) ? 0x79 : 0x74;  // Page up/down
1195 +                                                ADBKeyDown(key);
1196 +                                                ADBKeyUp(key);
1197 +                                        } else {
1198 +                                                int key = (button == 5) ? 0x3d : 0x3e;  // Cursor up/down
1199 +                                                for(int i=0; i<mouse_wheel_lines; i++) {
1200 +                                                        ADBKeyDown(key);
1201 +                                                        ADBKeyUp(key);
1202 +                                                }
1203 +                                        }
1204 +                                }
1205                                  break;
1206                          }
1207                          case ButtonRelease: {
# Line 968 | Line 1229 | static void handle_events(void)
1229                                          code = event2keycode((XKeyEvent *)&event);
1230                                  if (code != -1) {
1231                                          if (!emul_suspended) {
1232 <                                                ADBKeyDown(code);
1232 >                                                if (code == 0x39) {     // Caps Lock pressed
1233 >                                                        if (caps_on) {
1234 >                                                                ADBKeyUp(code);
1235 >                                                                caps_on = false;
1236 >                                                        } else {
1237 >                                                                ADBKeyDown(code);
1238 >                                                                caps_on = true;
1239 >                                                        }
1240 >                                                } else
1241 >                                                        ADBKeyDown(code);
1242                                                  if (code == 0x36)
1243                                                          ctrl_down = true;
1244                                          } else {
1245 < #if ENABLE_DGA
1245 > #if ENABLE_XF86_DGA || ENABLE_FBDEV_DGA
1246                                                  if (code == 0x31)
1247                                                          resume_emul();  // Space wakes us up
1248   #endif
# Line 987 | Line 1257 | static void handle_events(void)
1257                                          code = keycode_table[((XKeyEvent *)&event)->keycode & 0xff];
1258                                  } else
1259                                          code = event2keycode((XKeyEvent *)&event);
1260 <                                if (code != -1) {
1260 >                                if (code != -1 && code != 0x39) {       // Don't propagate Caps Lock releases
1261                                          ADBKeyUp(code);
1262                                          if (code == 0x36)
1263                                                  ctrl_down = false;
# Line 997 | Line 1267 | static void handle_events(void)
1267  
1268                          // Hidden parts exposed, force complete refresh of window
1269                          case Expose:
1270 <                                if (display_type == DISPLAY_WINDOW)
1271 <                                        memset(the_buffer_copy, 0, VideoMonitor.bytes_per_row * VideoMonitor.y);
1270 >                                if (display_type == DISPLAY_WINDOW) {
1271 >                                        int x1, y1;
1272 >                                        for (y1=0; y1<16; y1++)
1273 >                                        for (x1=0; x1<16; x1++)
1274 >                                                updt_box[x1][y1] = true;
1275 >                                        nr_boxes = 16 * 16;
1276 >                                }
1277                                  break;
1278                  }
1279          }
# Line 1009 | Line 1284 | static void handle_events(void)
1284   *  Window display update
1285   */
1286  
1287 < static void update_display(void)
1287 > static void update_display(int ticker)
1288   {
1289 <        // In classic mode, copy the frame buffer from Mac RAM
1290 <        if (classic_mode)
1291 <                memcpy(the_buffer, Mac2HostAddr(0x3fa700), VideoMonitor.bytes_per_row * VideoMonitor.y);
1017 <
1018 <        // Incremental update code
1019 <        int wide = 0, high = 0, x1, x2, y1, y2, i, j;
1289 >        int y1, y2, y2s, y2a, i, x1, xm, xmo, ymo, yo, yi, yil, xic, xicl, xi;
1290 >        int xil = 0;
1291 >        int rxm = 0, rxmo = 0;
1292          int bytes_per_row = VideoMonitor.bytes_per_row;
1293          int bytes_per_pixel = VideoMonitor.bytes_per_row / VideoMonitor.x;
1294 <        uint8 *p, *p2;
1295 <
1296 <        // Check for first line from top and first line from bottom that have changed
1297 <        y1 = 0;
1298 <        for (j=0; j<VideoMonitor.y; j++) {
1299 <                if (memcmp(&the_buffer[j * bytes_per_row], &the_buffer_copy[j * bytes_per_row], bytes_per_row)) {
1300 <                        y1 = j;
1301 <                        break;
1030 <                }
1031 <        }
1032 <        y2 = y1 - 1;
1033 <        for (j=VideoMonitor.y-1; j>=y1; j--) {
1034 <                if (memcmp(&the_buffer[j * bytes_per_row], &the_buffer_copy[j * bytes_per_row], bytes_per_row)) {
1035 <                        y2 = j;
1294 >        int rx = VideoMonitor.bytes_per_row / 16;
1295 >        int ry = VideoMonitor.y / 16;
1296 >        int max_box;
1297 >
1298 >        y2s = sm_uptd[ticker % 8];
1299 >        y2a = 8;
1300 >        for (i = 0; i < 6; i++)
1301 >                if (ticker % (2 << i))
1302                          break;
1303 <                }
1038 <        }
1039 <        high = y2 - y1 + 1;
1303 >        max_box = sm_no_boxes[i];
1304  
1305 <        // Check for first column from left and first column from right that have changed
1306 <        if (high) {
1307 <                if (depth == 1) {
1308 <                        x1 = VideoMonitor.x;
1309 <                        for (j=y1; j<=y2; j++) {
1310 <                                p = &the_buffer[j * bytes_per_row];
1311 <                                p2 = &the_buffer_copy[j * bytes_per_row];
1312 <                                for (i=0; i<(x1>>3); i++) {
1313 <                                        if (*p != *p2) {
1314 <                                                x1 = i << 3;
1051 <                                                break;
1052 <                                        }
1053 <                                        p++;
1054 <                                        p2++;
1055 <                                }
1056 <                        }
1057 <                        x2 = x1;
1058 <                        for (j=y1; j<=y2; j++) {
1059 <                                p = &the_buffer[j * bytes_per_row];
1060 <                                p2 = &the_buffer_copy[j * bytes_per_row];
1061 <                                p += bytes_per_row;
1062 <                                p2 += bytes_per_row;
1063 <                                for (i=(VideoMonitor.x>>3); i>(x2>>3); i--) {
1064 <                                        p--;
1065 <                                        p2--;
1066 <                                        if (*p != *p2) {
1067 <                                                x2 = i << 3;
1068 <                                                break;
1305 >        if (y2a) {
1306 >                for (y1=0; y1<16; y1++) {
1307 >                        for (y2=y2s; y2 < ry; y2 += y2a) {
1308 >                                i = ((y1 * ry) + y2) * bytes_per_row;
1309 >                                for (x1=0; x1<16; x1++, i += rx) {
1310 >                                        if (updt_box[x1][y1] == false) {
1311 >                                                if (memcmp(&the_buffer_copy[i], &the_buffer[i], rx)) {
1312 >                                                        updt_box[x1][y1] = true;
1313 >                                                        nr_boxes++;
1314 >                                                }
1315                                          }
1316                                  }
1317                          }
1318 <                        wide = x2 - x1;
1318 >                }
1319 >        }
1320  
1321 <                        // Update copy of the_buffer
1322 <                        if (high && wide) {
1323 <                                for (j=y1; j<=y2; j++) {
1324 <                                        i = j * bytes_per_row + (x1 >> 3);
1325 <                                        memcpy(&the_buffer_copy[i], &the_buffer[i], wide >> 3);
1321 >        if ((nr_boxes <= max_box) && (nr_boxes)) {
1322 >                for (y1=0; y1<16; y1++) {
1323 >                        for (x1=0; x1<16; x1++) {
1324 >                                if (updt_box[x1][y1] == true) {
1325 >                                        if (rxm == 0)
1326 >                                                xm = x1;
1327 >                                        rxm += rx;
1328 >                                        updt_box[x1][y1] = false;
1329                                  }
1330 <                        }
1331 <
1332 <                } else {
1333 <                        x1 = VideoMonitor.x;
1334 <                        for (j=y1; j<=y2; j++) {
1335 <                                p = &the_buffer[j * bytes_per_row];
1336 <                                p2 = &the_buffer_copy[j * bytes_per_row];
1337 <                                for (i=0; i<x1; i++) {
1338 <                                        if (memcmp(p, p2, bytes_per_pixel)) {
1339 <                                                x1 = i;
1340 <                                                break;
1330 >                                if (((updt_box[x1+1][y1] == false) || (x1 == 15)) && (rxm)) {
1331 >                                        if ((rxmo != rxm) || (xmo != xm) || (yo != y1 - 1)) {
1332 >                                                if (rxmo) {
1333 >                                                        xi = xmo * rx;
1334 >                                                        yi = ymo * ry;
1335 >                                                        xil = rxmo;
1336 >                                                        yil = (yo - ymo +1) * ry;
1337 >                                                }
1338 >                                                rxmo = rxm;
1339 >                                                xmo = xm;
1340 >                                                ymo = y1;
1341                                          }
1342 <                                        p += bytes_per_pixel;
1343 <                                        p2 += bytes_per_pixel;
1344 <                                }
1345 <                        }
1346 <                        x2 = x1;
1347 <                        for (j=y1; j<=y2; j++) {
1348 <                                p = &the_buffer[j * bytes_per_row];
1349 <                                p2 = &the_buffer_copy[j * bytes_per_row];
1350 <                                p += bytes_per_row;
1351 <                                p2 += bytes_per_row;
1352 <                                for (i=VideoMonitor.x; i>x2; i--) {
1353 <                                        p -= bytes_per_pixel;
1354 <                                        p2 -= bytes_per_pixel;
1355 <                                        if (memcmp(p, p2, bytes_per_pixel)) {
1356 <                                                x2 = i;
1357 <                                                break;
1342 >                                        rxm = 0;
1343 >                                        yo = y1;
1344 >                                }      
1345 >                                if (xil) {
1346 >                                        i = (yi * bytes_per_row) + xi;
1347 >                                        for (y2=0; y2 < yil; y2++, i += bytes_per_row)
1348 >                                                memcpy(&the_buffer_copy[i], &the_buffer[i], xil);
1349 >                                        if (depth == 1) {
1350 >                                                if (have_shm)
1351 >                                                        XShmPutImage(x_display, the_win, the_gc, img, xi * 8, yi, xi * 8, yi, xil * 8, yil, 0);
1352 >                                                else
1353 >                                                        XPutImage(x_display, the_win, the_gc, img, xi * 8, yi, xi * 8, yi, xil * 8, yil);
1354 >                                        } else {
1355 >                                                if (have_shm)
1356 >                                                        XShmPutImage(x_display, the_win, the_gc, img, xi / bytes_per_pixel, yi, xi / bytes_per_pixel, yi, xil / bytes_per_pixel, yil, 0);
1357 >                                                else
1358 >                                                        XPutImage(x_display, the_win, the_gc, img, xi / bytes_per_pixel, yi, xi / bytes_per_pixel, yi, xil / bytes_per_pixel, yil);
1359                                          }
1360 +                                        xil = 0;
1361                                  }
1362 <                        }
1363 <                        wide = x2 - x1;
1364 <
1365 <                        // Update copy of the_buffer
1366 <                        if (high && wide) {
1367 <                                for (j=y1; j<=y2; j++) {
1368 <                                        i = j * bytes_per_row + x1 * bytes_per_pixel;
1117 <                                        memcpy(&the_buffer_copy[i], &the_buffer[i], bytes_per_pixel * wide);
1362 >                                if ((x1 == 15) && (y1 == 15) && (rxmo)) {
1363 >                                        x1--;
1364 >                                        xi = xmo * rx;
1365 >                                        yi = ymo * ry;
1366 >                                        xil = rxmo;
1367 >                                        yil = (yo - ymo +1) * ry;
1368 >                                        rxmo = 0;
1369                                  }
1370                          }
1371                  }
1372 <        }
1122 <
1123 <        // Refresh display
1124 <        if (high && wide) {
1125 <                if (have_shm)
1126 <                        XShmPutImage(x_display, the_win, the_gc, img, x1, y1, x1, y1, wide, high, 0);
1127 <                else
1128 <                        XPutImage(x_display, the_win, the_gc, img, x1, y1, x1, y1, wide, high);
1129 <        }
1130 <
1131 <        // Has the Mac started? (cursor data is not valid otherwise)
1132 <        if (HasMacStarted()) {
1133 <
1134 <                // Set new cursor image if it was changed
1135 <                if (memcmp(the_cursor, Mac2HostAddr(0x844), 64)) {
1136 <                        memcpy(the_cursor, Mac2HostAddr(0x844), 64);
1137 <                        memcpy(cursor_image->data, the_cursor, 32);
1138 <                        memcpy(cursor_mask_image->data, the_cursor+32, 32);
1139 <                        XFreeCursor(x_display, mac_cursor);
1140 <                        XPutImage(x_display, cursor_map, cursor_gc, cursor_image, 0, 0, 0, 0, 16, 16);
1141 <                        XPutImage(x_display, cursor_mask_map, cursor_mask_gc, cursor_mask_image, 0, 0, 0, 0, 16, 16);
1142 <                        mac_cursor = XCreatePixmapCursor(x_display, cursor_map, cursor_mask_map, &black, &white, ReadMacInt8(0x885), ReadMacInt8(0x887));
1143 <                        XDefineCursor(x_display, the_win, mac_cursor);
1144 <                }
1372 >                nr_boxes = 0;
1373          }
1374   }
1375  
# Line 1164 | Line 1392 | static void *redraw_func(void *arg)
1392                  usleep(16667);
1393   #endif
1394  
1395 < #if ENABLE_DGA
1395 > #if ENABLE_XF86_DGA
1396                  // Quit DGA mode if requested
1397                  if (quit_full_screen) {
1398                          quit_full_screen = false;
# Line 1178 | Line 1406 | static void *redraw_func(void *arg)
1406                  }
1407   #endif
1408  
1409 + #if ENABLE_FBDEV_DGA
1410 +                // Quit DGA mode if requested
1411 +                if (quit_full_screen) {
1412 +                        quit_full_screen = false;
1413 +                        if (display_type == DISPLAY_DGA) {
1414 +                                XUngrabPointer(x_display, CurrentTime);
1415 +                                XUngrabKeyboard(x_display, CurrentTime);
1416 +                                XUnmapWindow(x_display, the_win);
1417 +                                XSync(x_display, false);
1418 +                        }
1419 +                }
1420 + #endif
1421                  // Handle X events
1422                  handle_events();
1423  
# Line 1188 | Line 1428 | static void *redraw_func(void *arg)
1428                          if (depth == 8) {
1429                                  XStoreColors(x_display, cmap[0], palette, 256);
1430                                  XStoreColors(x_display, cmap[1], palette, 256);
1431 < #if ENABLE_DGA
1431 >                                
1432 > #if ENABLE_XF86_DGA
1433                                  if (display_type == DISPLAY_DGA) {
1434                                          current_dga_cmap ^= 1;
1435                                          XF86DGAInstallColormap(x_display, screen, cmap[current_dga_cmap]);
# Line 1198 | Line 1439 | static void *redraw_func(void *arg)
1439                  }
1440                  pthread_mutex_unlock(&palette_lock);
1441  
1442 <                // In window mode, update display and mouse pointer
1442 >                // In window mode, update display
1443                  if (display_type == DISPLAY_WINDOW) {
1444                          tick_counter++;
1445 <                        if (tick_counter >= frame_skip) {
1205 <                                tick_counter = 0;
1206 <                                update_display();
1207 <                        }
1445 >                        update_display(tick_counter);
1446                  }
1447          }
1448          return NULL;

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines