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.71 by gbeauche, 2004-06-23T14:30:48Z vs.
Revision 1.82 by gbeauche, 2006-01-03T22:03:27Z

# Line 1 | Line 1
1   /*
2   *  video_x.cpp - Video/graphics emulation, X11 specific stuff
3   *
4 < *  Basilisk II (C) 1997-2004 Christian Bauer
4 > *  Basilisk II (C) 1997-2005 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 99 | Line 99 | static bool redraw_thread_active = false
99   #ifdef HAVE_PTHREADS
100   static pthread_attr_t redraw_thread_attr;                       // Redraw thread attributes
101   static volatile bool redraw_thread_cancel;                      // Flag: Cancel Redraw thread
102 + static volatile bool redraw_thread_cancel_ack;          // Flag: Acknowledge for redraw thread cancellation
103   static pthread_t redraw_thread;                                         // Redraw thread
104   #endif
105  
# Line 139 | Line 140 | static XVisualInfo visualInfo;
140   static Visual *vis;
141   static int color_class;
142  
143 + static bool x_native_byte_order;                                                // XImage has native byte order?
144   static int rshift, rloss, gshift, gloss, bshift, bloss; // Pixel format of DirectColor/TrueColor modes
145  
146   static Colormap cmap[2] = {0, 0};                                       // Colormaps for indexed modes (DGA needs two of them)
147  
148 < static XColor x_palette[256];                                                   // Color palette to be used as CLUT and gamma table
148 > static XColor x_palette[256];                                           // Color palette to be used as CLUT and gamma table
149   static bool x_palette_changed = false;                          // Flag: Palette changed, redraw thread must set new colors
150  
151   #ifdef ENABLE_FBDEV_DGA
# Line 192 | Line 194 | static void *redraw_func(void *arg);
194   // From main_unix.cpp
195   extern char *x_display_name;
196   extern Display *x_display;
197 + extern void *vm_acquire_mac(size_t size);
198  
199   // From sys_unix.cpp
200   extern void SysMountFirstFloppy(void);
201  
202 + // From clip_unix.cpp
203 + extern void ClipboardSelectionClear(XSelectionClearEvent *);
204 + extern void ClipboardSelectionRequest(XSelectionRequestEvent *);
205 +
206  
207   /*
208   *  monitor_desc subclass for X11 display
# Line 248 | Line 255 | static inline int depth_of_video_mode(vi
255   }
256  
257   // Map RGB color to pixel value (this only works in TrueColor/DirectColor visuals)
258 < static inline uint32 map_rgb(uint8 red, uint8 green, uint8 blue)
258 > static inline uint32 map_rgb(uint8 red, uint8 green, uint8 blue, bool fix_byte_order = false)
259   {
260 <        return ((red >> rloss) << rshift) | ((green >> gloss) << gshift) | ((blue >> bloss) << bshift);
260 >        uint32 val = ((red >> rloss) << rshift) | ((green >> gloss) << gshift) | ((blue >> bloss) << bshift);
261 >        if (fix_byte_order && !x_native_byte_order) {
262 >                // We have to fix byte order in the ExpandMap[]
263 >                // NOTE: this is only an optimization since Screen_blitter_init()
264 >                // could be arranged to choose an NBO or OBO (with
265 >                // byteswapping) Blit_Expand_X_To_Y() function
266 >                switch (visualFormat.depth) {
267 >                case 15: case 16:
268 >                        val = do_byteswap_16(val);
269 >                        break;
270 >                case 24: case 32:
271 >                        val = do_byteswap_32(val);
272 >                        break;
273 >                }
274 >        }
275 >        return val;
276   }
277  
278   // Do we have a visual for handling the specified Mac depth? If so, set the
# Line 536 | Line 558 | private:
558          int mouse_last_x, mouse_last_y; // Last mouse position (for relative mode)
559   };
560  
561 + class driver_dga;
562 + static void update_display_dga_vosf(driver_dga *drv);
563 +
564 + class driver_dga : public driver_base {
565 +        friend void update_display_dga_vosf(driver_dga *drv);
566 +
567 + public:
568 +        driver_dga(X11_monitor_desc &monitor);
569 +        ~driver_dga();
570 +
571 +        void suspend(void);
572 +        void resume(void);
573 +
574 + protected:
575 +        struct FakeXImage {
576 +                int width, height;              // size of image
577 +                int depth;                              // depth of image
578 +                int bytes_per_line;             // accelerator to next line
579 +
580 +                FakeXImage(int w, int h, int d)
581 +                        : width(w), height(h), depth(d)
582 +                        { bytes_per_line = TrivialBytesPerRow(width, DepthModeForPixelDepth(depth)); }
583 +        };
584 +        FakeXImage *img;
585 +
586 + private:
587 +        Window suspend_win;             // "Suspend" information window
588 +        void *fb_save;                  // Saved frame buffer for suspend/resume
589 + };
590 +
591   static driver_base *drv = NULL; // Pointer to currently used driver object
592  
593   #ifdef ENABLE_VOSF
# Line 730 | Line 782 | driver_window::driver_window(X11_monitor
782          // Allocate memory for frame buffer (SIZE is extended to page-boundary)
783          the_host_buffer = the_buffer_copy;
784          the_buffer_size = page_extend((aligned_height + 2) * img->bytes_per_line);
785 <        the_buffer = (uint8 *)vm_acquire(the_buffer_size);
785 >        the_buffer = (uint8 *)vm_acquire_mac(the_buffer_size);
786          the_buffer_copy = (uint8 *)malloc(the_buffer_size);
787          D(bug("the_buffer = %p, the_buffer_copy = %p, the_host_buffer = %p\n", the_buffer, the_buffer_copy, the_host_buffer));
788   #else
# Line 751 | Line 803 | driver_window::driver_window(X11_monitor
803          XDefineCursor(x_display, w, mac_cursor);
804  
805          // Init blitting routines
754        bool native_byte_order;
755 #ifdef WORDS_BIGENDIAN
756        native_byte_order = (XImageByteOrder(x_display) == MSBFirst);
757 #else
758        native_byte_order = (XImageByteOrder(x_display) == LSBFirst);
759 #endif
806   #ifdef ENABLE_VOSF
807 <        Screen_blitter_init(visualFormat, native_byte_order, depth_of_video_mode(mode));
807 >        Screen_blitter_init(visualFormat, x_native_byte_order, depth_of_video_mode(mode));
808   #endif
809  
810          // Set frame buffer base
811 <        set_mac_frame_buffer(monitor, mode.depth, native_byte_order);
811 >        set_mac_frame_buffer(monitor, mode.depth, x_native_byte_order);
812  
813          // Everything went well
814          init_ok = true;
# Line 877 | Line 923 | void driver_window::mouse_moved(int x, i
923   *  DGA display driver base class
924   */
925  
880 class driver_dga : public driver_base {
881 public:
882        driver_dga(X11_monitor_desc &monitor);
883        ~driver_dga();
884
885        void suspend(void);
886        void resume(void);
887
888 private:
889        Window suspend_win;             // "Suspend" information window
890        void *fb_save;                  // Saved frame buffer for suspend/resume
891 };
892
926   driver_dga::driver_dga(X11_monitor_desc &m)
927 < : driver_base(m), suspend_win(0), fb_save(NULL)
927 >        : driver_base(m), suspend_win(0), fb_save(NULL), img(NULL)
928   {
929   }
930  
# Line 899 | Line 932 | driver_dga::~driver_dga()
932   {
933          XUngrabPointer(x_display, CurrentTime);
934          XUngrabKeyboard(x_display, CurrentTime);
935 +
936 +        if (img)
937 +                delete img;
938   }
939  
940   // Suspend emulation
# Line 1126 | Line 1162 | driver_fbdev::driver_fbdev(X11_monitor_d
1162            the_host_buffer = the_buffer;
1163            the_buffer_size = page_extend((height + 2) * bytes_per_row);
1164            the_buffer_copy = (uint8 *)malloc(the_buffer_size);
1165 <          the_buffer = (uint8 *)vm_acquire(the_buffer_size);
1165 >          the_buffer = (uint8 *)vm_acquire_mac(the_buffer_size);
1166 >
1167 >          // Fake image for DGA/VOSF mode to know about display bounds
1168 >          img = new FakeXImage(width, height, depth_of_video_mode(mode));
1169          }
1170   #else
1171          use_vosf = false;
# Line 1250 | Line 1289 | driver_xf86dga::driver_xf86dga(X11_monit
1289          // Init blitting routines
1290          int bytes_per_row = TrivialBytesPerRow((v_width + 7) & ~7, mode.depth);
1291   #if ENABLE_VOSF
1253        bool native_byte_order;
1254 #ifdef WORDS_BIGENDIAN
1255        native_byte_order = (XImageByteOrder(x_display) == MSBFirst);
1256 #else
1257        native_byte_order = (XImageByteOrder(x_display) == LSBFirst);
1258 #endif
1292   #if REAL_ADDRESSING || DIRECT_ADDRESSING
1293          // Screen_blitter_init() returns TRUE if VOSF is mandatory
1294          // i.e. the framebuffer update function is not Blit_Copy_Raw
1295 <        use_vosf = Screen_blitter_init(visualFormat, native_byte_order, depth_of_video_mode(mode));
1295 >        use_vosf = Screen_blitter_init(visualFormat, x_native_byte_order, depth_of_video_mode(mode));
1296          
1297          if (use_vosf) {
1298            // Allocate memory for frame buffer (SIZE is extended to page-boundary)
1299            the_host_buffer = the_buffer;
1300            the_buffer_size = page_extend((height + 2) * bytes_per_row);
1301            the_buffer_copy = (uint8 *)malloc(the_buffer_size);
1302 <          the_buffer = (uint8 *)vm_acquire(the_buffer_size);
1302 >          the_buffer = (uint8 *)vm_acquire_mac(the_buffer_size);
1303 >
1304 >          // Fake image for DGA/VOSF mode to know about display bounds
1305 >          img = new FakeXImage((v_width + 7) & ~7, height, depth_of_video_mode(mode));
1306          }
1307   #else
1308          use_vosf = false;
# Line 1348 | Line 1384 | static void keycode_init(void)
1384  
1385                  // Search for server vendor string, then read keycodes
1386                  const char *vendor = ServerVendor(x_display);
1387 +                // Force use of MacX mappings on MacOS X with Apple's X server
1388 +                int dummy;
1389 +                if (XQueryExtension(x_display, "Apple-DRI", &dummy, &dummy, &dummy))
1390 +                        vendor = "MacX";
1391                  bool vendor_found = false;
1392                  char line[256];
1393                  while (fgets(line, 255, f)) {
# Line 1401 | Line 1441 | bool X11_monitor_desc::video_open(void)
1441                  return false;
1442          }
1443  
1444 +        // Determine the byte order of an XImage content
1445 + #ifdef WORDS_BIGENDIAN
1446 +        x_native_byte_order = (XImageByteOrder(x_display) == MSBFirst);
1447 + #else
1448 +        x_native_byte_order = (XImageByteOrder(x_display) == LSBFirst);
1449 + #endif
1450 +
1451          // Build up visualFormat structure
1452 +        visualFormat.fullscreen = (display_type == DISPLAY_DGA);
1453          visualFormat.depth = visualInfo.depth;
1454          visualFormat.Rmask = visualInfo.red_mask;
1455          visualFormat.Gmask = visualInfo.green_mask;
# Line 1467 | Line 1515 | bool X11_monitor_desc::video_open(void)
1515          // Load gray ramp to 8->16/32 expand map
1516          if (!IsDirectMode(mode) && xdepth > 8)
1517                  for (int i=0; i<256; i++)
1518 <                        ExpandMap[i] = map_rgb(i, i, i);
1518 >                        ExpandMap[i] = map_rgb(i, i, i, true);
1519   #endif
1520  
1521          // Create display driver object of requested type
# Line 1512 | Line 1560 | bool X11_monitor_desc::video_open(void)
1560          LOCK_FRAME_BUFFER;
1561  
1562          // Start redraw/input thread
1563 < #ifdef HAVE_PTHREADS
1563 > #ifdef USE_PTHREADS_SERVICES
1564          redraw_thread_cancel = false;
1565          Set_pthread_attr(&redraw_thread_attr, 0);
1566          redraw_thread_active = (pthread_create(&redraw_thread, &redraw_thread_attr, redraw_func, NULL) == 0);
# Line 1708 | Line 1756 | void X11_monitor_desc::video_close(void)
1756          D(bug("video_close()\n"));
1757  
1758          // Stop redraw thread
1759 < #ifdef HAVE_PTHREADS
1759 > #ifdef USE_PTHREADS_SERVICES
1760          if (redraw_thread_active) {
1761                  redraw_thread_cancel = true;
1762 < #ifdef HAVE_PTHREAD_CANCEL
1715 <                pthread_cancel(redraw_thread);
1716 < #endif
1762 >                redraw_thread_cancel_ack = false;
1763                  pthread_join(redraw_thread, NULL);
1764 +                while (!redraw_thread_cancel_ack) ;
1765          }
1766   #endif
1767          redraw_thread_active = false;
# Line 1837 | Line 1884 | void X11_monitor_desc::set_palette(uint8
1884          if (!IsDirectMode(mode) && xdepth > 8) {
1885                  for (int i=0; i<256; i++) {
1886                          int c = i & (num_in-1); // If there are less than 256 colors, we repeat the first entries (this makes color expansion easier)
1887 <                        ExpandMap[i] = map_rgb(pal[c*3+0], pal[c*3+1], pal[c*3+2]);
1887 >                        ExpandMap[i] = map_rgb(pal[c*3+0], pal[c*3+1], pal[c*3+2], true);
1888                  }
1889  
1890                  // We have to redraw everything because the interpretation of pixel values changed
# Line 2042 | Line 2089 | static int event2keycode(XKeyEvent &ev,
2089  
2090   static void handle_events(void)
2091   {
2092 <        while (XPending(x_display)) {
2092 >        for (;;) {
2093                  XEvent event;
2094 <                XNextEvent(x_display, &event);
2094 >                XDisplayLock();
2095  
2096 +                if (!XCheckMaskEvent(x_display, eventmask, &event)) {
2097 +                        // Handle clipboard events
2098 +                        if (XCheckTypedEvent(x_display, SelectionRequest, &event))
2099 +                                ClipboardSelectionRequest(&event.xselectionrequest);
2100 +                        else if (XCheckTypedEvent(x_display, SelectionClear, &event))
2101 +                                ClipboardSelectionClear(&event.xselectionclear);
2102 +
2103 +                        // Window "close" widget clicked
2104 +                        else if (XCheckTypedEvent(x_display, ClientMessage, &event)) {
2105 +                                if (event.xclient.format == 32 && event.xclient.data.l[0] == WM_DELETE_WINDOW) {
2106 +                                        ADBKeyDown(0x7f);       // Power key
2107 +                                        ADBKeyUp(0x7f);
2108 +                                }
2109 +                        }
2110 +                        XDisplayUnlock();
2111 +                        break;
2112 +                }
2113 +                
2114                  switch (event.type) {
2115  
2116                          // Mouse button
# Line 2153 | Line 2218 | static void handle_events(void)
2218                                                  memset(the_buffer_copy, 0, mode.bytes_per_row * mode.y);
2219                                  }
2220                                  break;
2156
2157                        // Window "close" widget clicked
2158                        case ClientMessage:
2159                                if (event.xclient.format == 32 && event.xclient.data.l[0] == WM_DELETE_WINDOW) {
2160                                        ADBKeyDown(0x7f);       // Power key
2161                                        ADBKeyUp(0x7f);
2162                                }
2163                                break;
2221                  }
2222 +
2223 +                XDisplayUnlock();
2224          }
2225   }
2226  
# Line 2206 | Line 2265 | static void update_display_dynamic(int t
2265                  }
2266          }
2267  
2268 +        XDisplayLock();
2269          if ((nr_boxes <= max_box) && (nr_boxes)) {
2270                  for (y1=0; y1<16; y1++) {
2271                          for (x1=0; x1<16; x1++) {
# Line 2259 | Line 2319 | static void update_display_dynamic(int t
2319                  }
2320                  nr_boxes = 0;
2321          }
2322 +        XDisplayUnlock();
2323   }
2324  
2325   // Static display update (fixed frame rate, but incremental)
# Line 2368 | Line 2429 | static void update_display_static(driver
2429          }
2430  
2431          // Refresh display
2432 +        XDisplayLock();
2433          if (high && wide) {
2434                  if (drv->have_shm)
2435                          XShmPutImage(x_display, drv->w, drv->gc, drv->img, x1, y1, x1, y1, wide, high, 0);
2436                  else
2437                          XPutImage(x_display, drv->w, drv->gc, drv->img, x1, y1, x1, y1, wide, high);
2438          }
2439 +        XDisplayUnlock();
2440   }
2441  
2442  
# Line 2415 | Line 2478 | static inline void handle_palette_change
2478  
2479          if (x_palette_changed) {
2480                  x_palette_changed = false;
2481 +                XDisplayLock();
2482                  drv->update_palette();
2483 +                XDisplayUnlock();
2484          }
2485  
2486          UNLOCK_PALETTE;
# Line 2440 | Line 2505 | static void video_refresh_dga_vosf(void)
2505                  tick_counter = 0;
2506                  if (mainBuffer.dirty) {
2507                          LOCK_VOSF;
2508 <                        update_display_dga_vosf();
2508 >                        update_display_dga_vosf(static_cast<driver_dga *>(drv));
2509                          UNLOCK_VOSF;
2510                  }
2511          }
# Line 2457 | Line 2522 | static void video_refresh_window_vosf(vo
2522          if (++tick_counter >= frame_skip) {
2523                  tick_counter = 0;
2524                  if (mainBuffer.dirty) {
2525 +                        XDisplayLock();
2526                          LOCK_VOSF;
2527                          update_display_window_vosf(static_cast<driver_window *>(drv));
2528                          UNLOCK_VOSF;
2529                          XSync(x_display, false); // Let the server catch up
2530 +                        XDisplayUnlock();
2531                  }
2532          }
2533   }
# Line 2540 | Line 2607 | void VideoRefresh(void)
2607   const int VIDEO_REFRESH_HZ = 60;
2608   const int VIDEO_REFRESH_DELAY = 1000000 / VIDEO_REFRESH_HZ;
2609  
2610 < #ifdef HAVE_PTHREADS
2610 > #ifdef USE_PTHREADS_SERVICES
2611   static void *redraw_func(void *arg)
2612   {
2613          int fd = ConnectionNumber(x_display);
# Line 2581 | Line 2648 | static void *redraw_func(void *arg)
2648          }
2649  
2650          uint64 end = GetTicks_usec();
2651 <        D(bug("%Ld refreshes in %Ld usec = %f refreshes/sec\n", ticks, end - start, ticks * 1000000.0 / (end - start)));
2651 >        D(bug("%lld refreshes in %lld usec = %f refreshes/sec\n", ticks, end - start, ticks * 1000000.0 / (end - start)));
2652 >
2653 >        redraw_thread_cancel_ack = true;
2654          return NULL;
2655   }
2656   #endif

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines