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-2004 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 |
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" |
123 |
|
static int keycode_table[256]; // X keycode -> Mac keycode translation table |
124 |
|
|
125 |
|
// X11 variables |
126 |
+ |
char *x_display_name = NULL; // X11 display name |
127 |
+ |
Display *x_display = NULL; // X11 display handle |
128 |
|
static int screen; // Screen number |
129 |
|
static Window rootwin; // Root window and our window |
130 |
|
static int num_depths = 0; // Number of available X depths |
134 |
|
static int eventmask; |
135 |
|
|
136 |
|
static int xdepth; // Depth of X screen |
137 |
+ |
static VisualFormat visualFormat; |
138 |
|
static XVisualInfo visualInfo; |
139 |
|
static Visual *vis; |
140 |
|
static int color_class; |
192 |
|
// From main_unix.cpp |
193 |
|
extern char *x_display_name; |
194 |
|
extern Display *x_display; |
195 |
+ |
extern void *vm_acquire_mac(size_t size); |
196 |
|
|
197 |
|
// From sys_unix.cpp |
198 |
|
extern void SysMountFirstFloppy(void); |
199 |
|
|
200 |
+ |
// From clip_unix.cpp |
201 |
+ |
extern void ClipboardSelectionClear(XSelectionClearEvent *); |
202 |
+ |
extern void ClipboardSelectionRequest(XSelectionRequestEvent *); |
203 |
+ |
|
204 |
|
|
205 |
|
/* |
206 |
|
* monitor_desc subclass for X11 display |
223 |
|
* Utility functions |
224 |
|
*/ |
225 |
|
|
226 |
+ |
// Map video_mode depth ID to numerical depth value |
227 |
+ |
static inline int depth_of_video_mode(video_mode const & mode) |
228 |
+ |
{ |
229 |
+ |
int depth = -1; |
230 |
+ |
switch (mode.depth) { |
231 |
+ |
case VDEPTH_1BIT: |
232 |
+ |
depth = 1; |
233 |
+ |
break; |
234 |
+ |
case VDEPTH_2BIT: |
235 |
+ |
depth = 2; |
236 |
+ |
break; |
237 |
+ |
case VDEPTH_4BIT: |
238 |
+ |
depth = 4; |
239 |
+ |
break; |
240 |
+ |
case VDEPTH_8BIT: |
241 |
+ |
depth = 8; |
242 |
+ |
break; |
243 |
+ |
case VDEPTH_16BIT: |
244 |
+ |
depth = 16; |
245 |
+ |
break; |
246 |
+ |
case VDEPTH_32BIT: |
247 |
+ |
depth = 32; |
248 |
+ |
break; |
249 |
+ |
default: |
250 |
+ |
abort(); |
251 |
+ |
} |
252 |
+ |
return depth; |
253 |
+ |
} |
254 |
+ |
|
255 |
|
// Map RGB color to pixel value (this only works in TrueColor/DirectColor visuals) |
256 |
|
static inline uint32 map_rgb(uint8 red, uint8 green, uint8 blue) |
257 |
|
{ |
735 |
|
// Allocate memory for frame buffer (SIZE is extended to page-boundary) |
736 |
|
the_host_buffer = the_buffer_copy; |
737 |
|
the_buffer_size = page_extend((aligned_height + 2) * img->bytes_per_line); |
738 |
< |
the_buffer = (uint8 *)vm_acquire(the_buffer_size); |
738 |
> |
the_buffer = (uint8 *)vm_acquire_mac(the_buffer_size); |
739 |
|
the_buffer_copy = (uint8 *)malloc(the_buffer_size); |
740 |
|
D(bug("the_buffer = %p, the_buffer_copy = %p, the_host_buffer = %p\n", the_buffer, the_buffer_copy, the_host_buffer)); |
741 |
|
#else |
763 |
|
native_byte_order = (XImageByteOrder(x_display) == LSBFirst); |
764 |
|
#endif |
765 |
|
#ifdef ENABLE_VOSF |
766 |
< |
Screen_blitter_init(&visualInfo, native_byte_order, mode.depth); |
766 |
> |
Screen_blitter_init(visualFormat, native_byte_order, depth_of_video_mode(mode)); |
767 |
|
#endif |
768 |
|
|
769 |
|
// Set frame buffer base |
1124 |
|
#if REAL_ADDRESSING || DIRECT_ADDRESSING |
1125 |
|
// Screen_blitter_init() returns TRUE if VOSF is mandatory |
1126 |
|
// i.e. the framebuffer update function is not Blit_Copy_Raw |
1127 |
< |
use_vosf = Screen_blitter_init(&visualInfo, true, mode.depth); |
1127 |
> |
use_vosf = Screen_blitter_init(visualFormat, true, mode.depth); |
1128 |
|
|
1129 |
|
if (use_vosf) { |
1130 |
|
// Allocate memory for frame buffer (SIZE is extended to page-boundary) |
1131 |
|
the_host_buffer = the_buffer; |
1132 |
|
the_buffer_size = page_extend((height + 2) * bytes_per_row); |
1133 |
|
the_buffer_copy = (uint8 *)malloc(the_buffer_size); |
1134 |
< |
the_buffer = (uint8 *)vm_acquire(the_buffer_size); |
1134 |
> |
the_buffer = (uint8 *)vm_acquire_mac(the_buffer_size); |
1135 |
|
} |
1136 |
|
#else |
1137 |
|
use_vosf = false; |
1264 |
|
#if REAL_ADDRESSING || DIRECT_ADDRESSING |
1265 |
|
// Screen_blitter_init() returns TRUE if VOSF is mandatory |
1266 |
|
// i.e. the framebuffer update function is not Blit_Copy_Raw |
1267 |
< |
use_vosf = Screen_blitter_init(&visualInfo, native_byte_order, mode.depth); |
1267 |
> |
use_vosf = Screen_blitter_init(visualFormat, native_byte_order, depth_of_video_mode(mode)); |
1268 |
|
|
1269 |
|
if (use_vosf) { |
1270 |
|
// Allocate memory for frame buffer (SIZE is extended to page-boundary) |
1271 |
|
the_host_buffer = the_buffer; |
1272 |
|
the_buffer_size = page_extend((height + 2) * bytes_per_row); |
1273 |
|
the_buffer_copy = (uint8 *)malloc(the_buffer_size); |
1274 |
< |
the_buffer = (uint8 *)vm_acquire(the_buffer_size); |
1274 |
> |
the_buffer = (uint8 *)vm_acquire_mac(the_buffer_size); |
1275 |
|
} |
1276 |
|
#else |
1277 |
|
use_vosf = false; |
1353 |
|
|
1354 |
|
// Search for server vendor string, then read keycodes |
1355 |
|
const char *vendor = ServerVendor(x_display); |
1356 |
+ |
// Force use of MacX mappings on MacOS X with Apple's X server |
1357 |
+ |
int dummy; |
1358 |
+ |
if (XQueryExtension(x_display, "Apple-DRI", &dummy, &dummy, &dummy)) |
1359 |
+ |
vendor = "MacX"; |
1360 |
|
bool vendor_found = false; |
1361 |
|
char line[256]; |
1362 |
|
while (fgets(line, 255, f)) { |
1410 |
|
return false; |
1411 |
|
} |
1412 |
|
|
1413 |
+ |
// Build up visualFormat structure |
1414 |
+ |
visualFormat.depth = visualInfo.depth; |
1415 |
+ |
visualFormat.Rmask = visualInfo.red_mask; |
1416 |
+ |
visualFormat.Gmask = visualInfo.green_mask; |
1417 |
+ |
visualFormat.Bmask = visualInfo.blue_mask; |
1418 |
+ |
|
1419 |
|
// Create color maps |
1420 |
|
if (color_class == PseudoColor || color_class == DirectColor) { |
1421 |
|
cmap[0] = XCreateColormap(x_display, rootwin, vis, AllocAll); |
2051 |
|
|
2052 |
|
static void handle_events(void) |
2053 |
|
{ |
2054 |
< |
while (XPending(x_display)) { |
2054 |
> |
for (;;) { |
2055 |
|
XEvent event; |
2056 |
< |
XNextEvent(x_display, &event); |
2056 |
> |
XDisplayLock(); |
2057 |
|
|
2058 |
+ |
if (!XCheckMaskEvent(x_display, eventmask, &event)) { |
2059 |
+ |
// Handle clipboard events |
2060 |
+ |
if (XCheckTypedEvent(x_display, SelectionRequest, &event)) |
2061 |
+ |
ClipboardSelectionRequest(&event.xselectionrequest); |
2062 |
+ |
else if (XCheckTypedEvent(x_display, SelectionClear, &event)) |
2063 |
+ |
ClipboardSelectionClear(&event.xselectionclear); |
2064 |
+ |
|
2065 |
+ |
// Window "close" widget clicked |
2066 |
+ |
else if (XCheckTypedEvent(x_display, ClientMessage, &event)) { |
2067 |
+ |
if (event.xclient.format == 32 && event.xclient.data.l[0] == WM_DELETE_WINDOW) { |
2068 |
+ |
ADBKeyDown(0x7f); // Power key |
2069 |
+ |
ADBKeyUp(0x7f); |
2070 |
+ |
} |
2071 |
+ |
} |
2072 |
+ |
XDisplayUnlock(); |
2073 |
+ |
break; |
2074 |
+ |
} |
2075 |
+ |
|
2076 |
|
switch (event.type) { |
2077 |
|
|
2078 |
|
// Mouse button |
2180 |
|
memset(the_buffer_copy, 0, mode.bytes_per_row * mode.y); |
2181 |
|
} |
2182 |
|
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; |
2183 |
|
} |
2184 |
+ |
|
2185 |
+ |
XDisplayUnlock(); |
2186 |
|
} |
2187 |
|
} |
2188 |
|
|
2227 |
|
} |
2228 |
|
} |
2229 |
|
|
2230 |
+ |
XDisplayLock(); |
2231 |
|
if ((nr_boxes <= max_box) && (nr_boxes)) { |
2232 |
|
for (y1=0; y1<16; y1++) { |
2233 |
|
for (x1=0; x1<16; x1++) { |
2281 |
|
} |
2282 |
|
nr_boxes = 0; |
2283 |
|
} |
2284 |
+ |
XDisplayUnlock(); |
2285 |
|
} |
2286 |
|
|
2287 |
|
// Static display update (fixed frame rate, but incremental) |
2391 |
|
} |
2392 |
|
|
2393 |
|
// Refresh display |
2394 |
+ |
XDisplayLock(); |
2395 |
|
if (high && wide) { |
2396 |
|
if (drv->have_shm) |
2397 |
|
XShmPutImage(x_display, drv->w, drv->gc, drv->img, x1, y1, x1, y1, wide, high, 0); |
2398 |
|
else |
2399 |
|
XPutImage(x_display, drv->w, drv->gc, drv->img, x1, y1, x1, y1, wide, high); |
2400 |
|
} |
2401 |
+ |
XDisplayUnlock(); |
2402 |
|
} |
2403 |
|
|
2404 |
|
|
2440 |
|
|
2441 |
|
if (x_palette_changed) { |
2442 |
|
x_palette_changed = false; |
2443 |
+ |
XDisplayLock(); |
2444 |
|
drv->update_palette(); |
2445 |
+ |
XDisplayUnlock(); |
2446 |
|
} |
2447 |
|
|
2448 |
|
UNLOCK_PALETTE; |
2484 |
|
if (++tick_counter >= frame_skip) { |
2485 |
|
tick_counter = 0; |
2486 |
|
if (mainBuffer.dirty) { |
2487 |
+ |
XDisplayLock(); |
2488 |
|
LOCK_VOSF; |
2489 |
|
update_display_window_vosf(static_cast<driver_window *>(drv)); |
2490 |
|
UNLOCK_VOSF; |
2491 |
|
XSync(x_display, false); // Let the server catch up |
2492 |
+ |
XDisplayUnlock(); |
2493 |
|
} |
2494 |
|
} |
2495 |
|
} |