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.68 by gbeauche, 2002-09-28T12:42:39Z vs.
Revision 1.81 by gbeauche, 2005-06-11T06:52:22Z

# Line 1 | Line 1
1   /*
2   *  video_x.cpp - Video/graphics emulation, X11 specific stuff
3   *
4 < *  Basilisk II (C) 1997-2002 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 62 | Line 62
62   #include "prefs.h"
63   #include "user_strings.h"
64   #include "video.h"
65 + #include "video_blit.h"
66  
67   #define DEBUG 0
68   #include "debug.h"
# Line 98 | 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 122 | Line 124 | static bool use_keycodes = false;                                      //
124   static int keycode_table[256];                                          // X keycode -> Mac keycode translation table
125  
126   // X11 variables
127 + char *x_display_name = NULL;                                            // X11 display name
128 + Display *x_display = NULL;                                                      // X11 display handle
129   static int screen;                                                                      // Screen number
130   static Window rootwin;                                                          // Root window and our window
131   static int num_depths = 0;                                                      // Number of available X depths
# Line 131 | Line 135 | static unsigned long black_pixel, white_
135   static int eventmask;
136  
137   static int xdepth;                                                                      // Depth of X screen
138 + static VisualFormat visualFormat;
139   static XVisualInfo visualInfo;
140   static Visual *vis;
141   static int color_class;
# Line 188 | Line 193 | static void *redraw_func(void *arg);
193   // From main_unix.cpp
194   extern char *x_display_name;
195   extern Display *x_display;
196 + extern void *vm_acquire_mac(size_t size);
197  
198   // From sys_unix.cpp
199   extern void SysMountFirstFloppy(void);
200  
201 + // From clip_unix.cpp
202 + extern void ClipboardSelectionClear(XSelectionClearEvent *);
203 + extern void ClipboardSelectionRequest(XSelectionRequestEvent *);
204 +
205  
206   /*
207   *  monitor_desc subclass for X11 display
# Line 214 | Line 224 | public:
224   *  Utility functions
225   */
226  
227 + // Map video_mode depth ID to numerical depth value
228 + static inline int depth_of_video_mode(video_mode const & mode)
229 + {
230 +        int depth = -1;
231 +        switch (mode.depth) {
232 +        case VDEPTH_1BIT:
233 +                depth = 1;
234 +                break;
235 +        case VDEPTH_2BIT:
236 +                depth = 2;
237 +                break;
238 +        case VDEPTH_4BIT:
239 +                depth = 4;
240 +                break;
241 +        case VDEPTH_8BIT:
242 +                depth = 8;
243 +                break;
244 +        case VDEPTH_16BIT:
245 +                depth = 16;
246 +                break;
247 +        case VDEPTH_32BIT:
248 +                depth = 32;
249 +                break;
250 +        default:
251 +                abort();
252 +        }
253 +        return depth;
254 + }
255 +
256   // Map RGB color to pixel value (this only works in TrueColor/DirectColor visuals)
257   static inline uint32 map_rgb(uint8 red, uint8 green, uint8 blue)
258   {
# Line 503 | Line 542 | private:
542          int mouse_last_x, mouse_last_y; // Last mouse position (for relative mode)
543   };
544  
545 + class driver_dga;
546 + static void update_display_dga_vosf(driver_dga *drv);
547 +
548 + class driver_dga : public driver_base {
549 +        friend void update_display_dga_vosf(driver_dga *drv);
550 +
551 + public:
552 +        driver_dga(X11_monitor_desc &monitor);
553 +        ~driver_dga();
554 +
555 +        void suspend(void);
556 +        void resume(void);
557 +
558 + protected:
559 +        struct FakeXImage {
560 +                int width, height;              // size of image
561 +                int depth;                              // depth of image
562 +                int bytes_per_line;             // accelerator to next line
563 +
564 +                FakeXImage(int w, int h, int d)
565 +                        : width(w), height(h), depth(d)
566 +                        { bytes_per_line = TrivialBytesPerRow(width, DepthModeForPixelDepth(depth)); }
567 +        };
568 +        FakeXImage *img;
569 +
570 + private:
571 +        Window suspend_win;             // "Suspend" information window
572 +        void *fb_save;                  // Saved frame buffer for suspend/resume
573 + };
574 +
575   static driver_base *drv = NULL; // Pointer to currently used driver object
576  
577   #ifdef ENABLE_VOSF
# Line 697 | Line 766 | driver_window::driver_window(X11_monitor
766          // Allocate memory for frame buffer (SIZE is extended to page-boundary)
767          the_host_buffer = the_buffer_copy;
768          the_buffer_size = page_extend((aligned_height + 2) * img->bytes_per_line);
769 <        the_buffer = (uint8 *)vm_acquire(the_buffer_size);
769 >        the_buffer = (uint8 *)vm_acquire_mac(the_buffer_size);
770          the_buffer_copy = (uint8 *)malloc(the_buffer_size);
771          D(bug("the_buffer = %p, the_buffer_copy = %p, the_host_buffer = %p\n", the_buffer, the_buffer_copy, the_host_buffer));
772   #else
# Line 725 | Line 794 | driver_window::driver_window(X11_monitor
794          native_byte_order = (XImageByteOrder(x_display) == LSBFirst);
795   #endif
796   #ifdef ENABLE_VOSF
797 <        Screen_blitter_init(&visualInfo, native_byte_order, mode.depth);
797 >        Screen_blitter_init(visualFormat, native_byte_order, depth_of_video_mode(mode));
798   #endif
799  
800          // Set frame buffer base
# Line 844 | Line 913 | void driver_window::mouse_moved(int x, i
913   *  DGA display driver base class
914   */
915  
847 class driver_dga : public driver_base {
848 public:
849        driver_dga(X11_monitor_desc &monitor);
850        ~driver_dga();
851
852        void suspend(void);
853        void resume(void);
854
855 private:
856        Window suspend_win;             // "Suspend" information window
857        void *fb_save;                  // Saved frame buffer for suspend/resume
858 };
859
916   driver_dga::driver_dga(X11_monitor_desc &m)
917 < : driver_base(m), suspend_win(0), fb_save(NULL)
917 >        : driver_base(m), suspend_win(0), fb_save(NULL), img(NULL)
918   {
919   }
920  
# Line 866 | Line 922 | driver_dga::~driver_dga()
922   {
923          XUngrabPointer(x_display, CurrentTime);
924          XUngrabKeyboard(x_display, CurrentTime);
925 +
926 +        if (img)
927 +                delete img;
928   }
929  
930   // Suspend emulation
# Line 1086 | Line 1145 | driver_fbdev::driver_fbdev(X11_monitor_d
1145   #if REAL_ADDRESSING || DIRECT_ADDRESSING
1146          // Screen_blitter_init() returns TRUE if VOSF is mandatory
1147          // i.e. the framebuffer update function is not Blit_Copy_Raw
1148 <        use_vosf = Screen_blitter_init(&visualInfo, true, mode.depth);
1148 >        use_vosf = Screen_blitter_init(visualFormat, true, mode.depth);
1149          
1150          if (use_vosf) {
1151            // Allocate memory for frame buffer (SIZE is extended to page-boundary)
1152            the_host_buffer = the_buffer;
1153            the_buffer_size = page_extend((height + 2) * bytes_per_row);
1154            the_buffer_copy = (uint8 *)malloc(the_buffer_size);
1155 <          the_buffer = (uint8 *)vm_acquire(the_buffer_size);
1155 >          the_buffer = (uint8 *)vm_acquire_mac(the_buffer_size);
1156 >
1157 >          // Fake image for DGA/VOSF mode to know about display bounds
1158 >          img = new FakeXImage(width, height, depth_of_video_mode(mode));
1159          }
1160   #else
1161          use_vosf = false;
# Line 1226 | Line 1288 | driver_xf86dga::driver_xf86dga(X11_monit
1288   #if REAL_ADDRESSING || DIRECT_ADDRESSING
1289          // Screen_blitter_init() returns TRUE if VOSF is mandatory
1290          // i.e. the framebuffer update function is not Blit_Copy_Raw
1291 <        use_vosf = Screen_blitter_init(&visualInfo, native_byte_order, mode.depth);
1291 >        use_vosf = Screen_blitter_init(visualFormat, native_byte_order, depth_of_video_mode(mode));
1292          
1293          if (use_vosf) {
1294            // Allocate memory for frame buffer (SIZE is extended to page-boundary)
1295            the_host_buffer = the_buffer;
1296            the_buffer_size = page_extend((height + 2) * bytes_per_row);
1297            the_buffer_copy = (uint8 *)malloc(the_buffer_size);
1298 <          the_buffer = (uint8 *)vm_acquire(the_buffer_size);
1298 >          the_buffer = (uint8 *)vm_acquire_mac(the_buffer_size);
1299 >
1300 >          // Fake image for DGA/VOSF mode to know about display bounds
1301 >          img = new FakeXImage((v_width + 7) & ~7, height, depth_of_video_mode(mode));
1302          }
1303   #else
1304          use_vosf = false;
# Line 1315 | Line 1380 | static void keycode_init(void)
1380  
1381                  // Search for server vendor string, then read keycodes
1382                  const char *vendor = ServerVendor(x_display);
1383 +                // Force use of MacX mappings on MacOS X with Apple's X server
1384 +                int dummy;
1385 +                if (XQueryExtension(x_display, "Apple-DRI", &dummy, &dummy, &dummy))
1386 +                        vendor = "MacX";
1387                  bool vendor_found = false;
1388                  char line[256];
1389                  while (fgets(line, 255, f)) {
# Line 1368 | Line 1437 | bool X11_monitor_desc::video_open(void)
1437                  return false;
1438          }
1439  
1440 +        // Build up visualFormat structure
1441 +        visualFormat.fullscreen = (display_type == DISPLAY_DGA);
1442 +        visualFormat.depth = visualInfo.depth;
1443 +        visualFormat.Rmask = visualInfo.red_mask;
1444 +        visualFormat.Gmask = visualInfo.green_mask;
1445 +        visualFormat.Bmask = visualInfo.blue_mask;
1446 +
1447          // Create color maps
1448          if (color_class == PseudoColor || color_class == DirectColor) {
1449                  cmap[0] = XCreateColormap(x_display, rootwin, vis, AllocAll);
# Line 1473 | Line 1549 | bool X11_monitor_desc::video_open(void)
1549          LOCK_FRAME_BUFFER;
1550  
1551          // Start redraw/input thread
1552 < #ifdef HAVE_PTHREADS
1552 > #ifdef USE_PTHREADS_SERVICES
1553          redraw_thread_cancel = false;
1554          Set_pthread_attr(&redraw_thread_attr, 0);
1555          redraw_thread_active = (pthread_create(&redraw_thread, &redraw_thread_attr, redraw_func, NULL) == 0);
# Line 1669 | Line 1745 | void X11_monitor_desc::video_close(void)
1745          D(bug("video_close()\n"));
1746  
1747          // Stop redraw thread
1748 < #ifdef HAVE_PTHREADS
1748 > #ifdef USE_PTHREADS_SERVICES
1749          if (redraw_thread_active) {
1750                  redraw_thread_cancel = true;
1751 < #ifdef HAVE_PTHREAD_CANCEL
1676 <                pthread_cancel(redraw_thread);
1677 < #endif
1751 >                redraw_thread_cancel_ack = false;
1752                  pthread_join(redraw_thread, NULL);
1753 +                while (!redraw_thread_cancel_ack) ;
1754          }
1755   #endif
1756          redraw_thread_active = false;
# Line 2003 | Line 2078 | static int event2keycode(XKeyEvent &ev,
2078  
2079   static void handle_events(void)
2080   {
2081 <        while (XPending(x_display)) {
2081 >        for (;;) {
2082                  XEvent event;
2083 <                XNextEvent(x_display, &event);
2083 >                XDisplayLock();
2084  
2085 +                if (!XCheckMaskEvent(x_display, eventmask, &event)) {
2086 +                        // Handle clipboard events
2087 +                        if (XCheckTypedEvent(x_display, SelectionRequest, &event))
2088 +                                ClipboardSelectionRequest(&event.xselectionrequest);
2089 +                        else if (XCheckTypedEvent(x_display, SelectionClear, &event))
2090 +                                ClipboardSelectionClear(&event.xselectionclear);
2091 +
2092 +                        // Window "close" widget clicked
2093 +                        else if (XCheckTypedEvent(x_display, ClientMessage, &event)) {
2094 +                                if (event.xclient.format == 32 && event.xclient.data.l[0] == WM_DELETE_WINDOW) {
2095 +                                        ADBKeyDown(0x7f);       // Power key
2096 +                                        ADBKeyUp(0x7f);
2097 +                                }
2098 +                        }
2099 +                        XDisplayUnlock();
2100 +                        break;
2101 +                }
2102 +                
2103                  switch (event.type) {
2104  
2105                          // Mouse button
# Line 2114 | Line 2207 | static void handle_events(void)
2207                                                  memset(the_buffer_copy, 0, mode.bytes_per_row * mode.y);
2208                                  }
2209                                  break;
2117
2118                        // Window "close" widget clicked
2119                        case ClientMessage:
2120                                if (event.xclient.format == 32 && event.xclient.data.l[0] == WM_DELETE_WINDOW) {
2121                                        ADBKeyDown(0x7f);       // Power key
2122                                        ADBKeyUp(0x7f);
2123                                }
2124                                break;
2210                  }
2211 +
2212 +                XDisplayUnlock();
2213          }
2214   }
2215  
# Line 2167 | Line 2254 | static void update_display_dynamic(int t
2254                  }
2255          }
2256  
2257 +        XDisplayLock();
2258          if ((nr_boxes <= max_box) && (nr_boxes)) {
2259                  for (y1=0; y1<16; y1++) {
2260                          for (x1=0; x1<16; x1++) {
# Line 2220 | Line 2308 | static void update_display_dynamic(int t
2308                  }
2309                  nr_boxes = 0;
2310          }
2311 +        XDisplayUnlock();
2312   }
2313  
2314   // Static display update (fixed frame rate, but incremental)
# Line 2329 | Line 2418 | static void update_display_static(driver
2418          }
2419  
2420          // Refresh display
2421 +        XDisplayLock();
2422          if (high && wide) {
2423                  if (drv->have_shm)
2424                          XShmPutImage(x_display, drv->w, drv->gc, drv->img, x1, y1, x1, y1, wide, high, 0);
2425                  else
2426                          XPutImage(x_display, drv->w, drv->gc, drv->img, x1, y1, x1, y1, wide, high);
2427          }
2428 +        XDisplayUnlock();
2429   }
2430  
2431  
# Line 2376 | Line 2467 | static inline void handle_palette_change
2467  
2468          if (x_palette_changed) {
2469                  x_palette_changed = false;
2470 +                XDisplayLock();
2471                  drv->update_palette();
2472 +                XDisplayUnlock();
2473          }
2474  
2475          UNLOCK_PALETTE;
# Line 2401 | Line 2494 | static void video_refresh_dga_vosf(void)
2494                  tick_counter = 0;
2495                  if (mainBuffer.dirty) {
2496                          LOCK_VOSF;
2497 <                        update_display_dga_vosf();
2497 >                        update_display_dga_vosf(static_cast<driver_dga *>(drv));
2498                          UNLOCK_VOSF;
2499                  }
2500          }
# Line 2418 | Line 2511 | static void video_refresh_window_vosf(vo
2511          if (++tick_counter >= frame_skip) {
2512                  tick_counter = 0;
2513                  if (mainBuffer.dirty) {
2514 +                        XDisplayLock();
2515                          LOCK_VOSF;
2516                          update_display_window_vosf(static_cast<driver_window *>(drv));
2517                          UNLOCK_VOSF;
2518                          XSync(x_display, false); // Let the server catch up
2519 +                        XDisplayUnlock();
2520                  }
2521          }
2522   }
# Line 2501 | Line 2596 | void VideoRefresh(void)
2596   const int VIDEO_REFRESH_HZ = 60;
2597   const int VIDEO_REFRESH_DELAY = 1000000 / VIDEO_REFRESH_HZ;
2598  
2599 < #ifdef HAVE_PTHREADS
2599 > #ifdef USE_PTHREADS_SERVICES
2600   static void *redraw_func(void *arg)
2601   {
2602          int fd = ConnectionNumber(x_display);
# Line 2542 | Line 2637 | static void *redraw_func(void *arg)
2637          }
2638  
2639          uint64 end = GetTicks_usec();
2640 <        D(bug("%Ld refreshes in %Ld usec = %f refreshes/sec\n", ticks, end - start, ticks * 1000000.0 / (end - start)));
2640 >        D(bug("%lld refreshes in %lld usec = %f refreshes/sec\n", ticks, end - start, ticks * 1000000.0 / (end - start)));
2641 >
2642 >        redraw_thread_cancel_ack = true;
2643          return NULL;
2644   }
2645   #endif

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines