1 |
|
/* |
2 |
|
* video_x.cpp - Video/graphics emulation, X11 specific stuff |
3 |
|
* |
4 |
< |
* Basilisk II (C) 1997-2001 Christian Bauer |
4 |
> |
* Basilisk II (C) 1997-2002 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 |
184 |
|
|
185 |
|
// Prototypes |
186 |
|
static void *redraw_func(void *arg); |
187 |
– |
static int event2keycode(XKeyEvent &ev); |
187 |
|
|
188 |
|
// From main_unix.cpp |
189 |
|
extern char *x_display_name; |
209 |
|
{ |
210 |
|
D(bug("have_visual_for_depth(%d)\n", 1 << depth)); |
211 |
|
|
212 |
+ |
// 1-bit works always and uses default visual |
213 |
+ |
if (depth == VDEPTH_1BIT) { |
214 |
+ |
vis = DefaultVisual(x_display, screen); |
215 |
+ |
visualInfo.visualid = XVisualIDFromVisual(vis); |
216 |
+ |
int num = 0; |
217 |
+ |
XVisualInfo *vi = XGetVisualInfo(x_display, VisualIDMask, &visualInfo, &num); |
218 |
+ |
visualInfo = vi[0]; |
219 |
+ |
XFree(vi); |
220 |
+ |
xdepth = visualInfo.depth; |
221 |
+ |
color_class = visualInfo.c_class; |
222 |
+ |
D(bug(" found visual ID 0x%02x, depth %d\n", visualInfo.visualid, xdepth)); |
223 |
+ |
return true; |
224 |
+ |
} |
225 |
+ |
|
226 |
|
// Calculate minimum and maximum supported X depth |
227 |
|
int min_depth = 1, max_depth = 32; |
228 |
|
switch (depth) { |
216 |
– |
case VDEPTH_1BIT: // 1-bit works always and uses default visual |
217 |
– |
min_depth = max_depth = DefaultDepth(x_display, screen); |
218 |
– |
break; |
229 |
|
#ifdef ENABLE_VOSF |
230 |
|
case VDEPTH_2BIT: |
231 |
|
case VDEPTH_4BIT: // VOSF blitters can convert 2/4/8-bit -> 8/16/32-bit |
303 |
|
case DirectColor: D(bug("DirectColor\n")); break; |
304 |
|
} |
305 |
|
#endif |
306 |
+ |
return true; |
307 |
|
} |
308 |
|
|
309 |
|
// Add mode to list of supported modes |
523 |
|
} |
524 |
|
#ifdef ENABLE_VOSF |
525 |
|
else { |
526 |
+ |
// the_buffer shall always be mapped through vm_acquire() so that we can vm_protect() it at will |
527 |
+ |
if (the_buffer != VM_MAP_FAILED) { |
528 |
+ |
D(bug(" releasing the_buffer at %p (%d bytes)\n", the_buffer, the_buffer_size)); |
529 |
+ |
vm_release(the_buffer, the_buffer_size); |
530 |
+ |
the_buffer = NULL; |
531 |
+ |
} |
532 |
|
if (the_host_buffer) { |
533 |
+ |
D(bug(" freeing the_host_buffer at %p\n", the_host_buffer)); |
534 |
|
free(the_host_buffer); |
535 |
|
the_host_buffer = NULL; |
536 |
|
} |
519 |
– |
if (the_buffer) { |
520 |
– |
free(the_buffer); |
521 |
– |
the_buffer = NULL; |
522 |
– |
} |
537 |
|
if (the_buffer_copy) { |
538 |
+ |
D(bug(" freeing the_buffer_copy at %p\n", the_buffer_copy)); |
539 |
|
free(the_buffer_copy); |
540 |
|
the_buffer_copy = NULL; |
541 |
|
} |
575 |
|
|
576 |
|
// Open display |
577 |
|
driver_window::driver_window(const video_mode &mode) |
578 |
< |
: gc(0), img(NULL), have_shm(false), mouse_grabbed(false), mac_cursor(0) |
578 |
> |
: gc(0), img(NULL), have_shm(false), mac_cursor(0), mouse_grabbed(false) |
579 |
|
{ |
580 |
|
int width = mode.x, height = mode.y; |
581 |
|
int aligned_width = (width + 15) & ~15; |
584 |
|
// Set absolute mouse mode |
585 |
|
ADBSetRelMouseMode(mouse_grabbed); |
586 |
|
|
587 |
< |
// Create window (setting backround_pixel, border_pixel and colormap is |
587 |
> |
// Create window (setting background_pixel, border_pixel and colormap is |
588 |
|
// mandatory when using a non-default visual; in 1-bit mode we use the |
589 |
|
// default visual, so we can also use the default colormap) |
590 |
|
XSetWindowAttributes wattr; |
594 |
|
wattr.colormap = (mode.depth == VDEPTH_1BIT ? DefaultColormap(x_display, screen) : cmap[0]); |
595 |
|
w = XCreateWindow(x_display, rootwin, 0, 0, width, height, 0, xdepth, |
596 |
|
InputOutput, vis, CWEventMask | CWBackPixel | CWBorderPixel | CWColormap, &wattr); |
597 |
+ |
D(bug(" window created\n")); |
598 |
|
|
599 |
|
// Set window name/class |
600 |
|
set_window_name(w, STR_WINDOW_TITLE); |
618 |
|
XFree(hints); |
619 |
|
} |
620 |
|
} |
621 |
+ |
D(bug(" window attributes set\n")); |
622 |
|
|
623 |
|
// Show window |
624 |
|
XMapWindow(x_display, w); |
625 |
|
wait_mapped(w); |
626 |
+ |
D(bug(" window mapped\n")); |
627 |
|
|
628 |
|
// 1-bit mode is big-endian; if the X server is little-endian, we can't |
629 |
|
// use SHM because that doesn't allow changing the image byte order |
634 |
|
|
635 |
|
// Create SHM image ("height + 2" for safety) |
636 |
|
img = XShmCreateImage(x_display, vis, mode.depth == VDEPTH_1BIT ? 1 : xdepth, mode.depth == VDEPTH_1BIT ? XYBitmap : ZPixmap, 0, &shminfo, width, height); |
637 |
+ |
D(bug(" shm image created\n")); |
638 |
|
shminfo.shmid = shmget(IPC_PRIVATE, (aligned_height + 2) * img->bytes_per_line, IPC_CREAT | 0777); |
639 |
|
the_buffer_copy = (uint8 *)shmat(shminfo.shmid, 0, 0); |
640 |
|
shminfo.shmaddr = img->data = (char *)the_buffer_copy; |
655 |
|
have_shm = true; |
656 |
|
shmctl(shminfo.shmid, IPC_RMID, 0); |
657 |
|
} |
658 |
+ |
D(bug(" shm image attached\n")); |
659 |
|
} |
660 |
|
|
661 |
|
// Create normal X image if SHM doesn't work ("height + 2" for safety) |
663 |
|
int bytes_per_row = (mode.depth == VDEPTH_1BIT ? aligned_width/8 : TrivialBytesPerRow(aligned_width, DepthModeForPixelDepth(xdepth))); |
664 |
|
the_buffer_copy = (uint8 *)malloc((aligned_height + 2) * bytes_per_row); |
665 |
|
img = XCreateImage(x_display, vis, mode.depth == VDEPTH_1BIT ? 1 : xdepth, mode.depth == VDEPTH_1BIT ? XYBitmap : ZPixmap, 0, (char *)the_buffer_copy, aligned_width, aligned_height, 32, bytes_per_row); |
666 |
+ |
D(bug(" X image created\n")); |
667 |
|
} |
668 |
|
|
669 |
|
if (need_msb_image) { |
676 |
|
// Allocate memory for frame buffer (SIZE is extended to page-boundary) |
677 |
|
the_host_buffer = the_buffer_copy; |
678 |
|
the_buffer_size = page_extend((aligned_height + 2) * img->bytes_per_line); |
658 |
– |
the_buffer_copy = (uint8 *)vm_acquire(the_buffer_size); |
679 |
|
the_buffer = (uint8 *)vm_acquire(the_buffer_size); |
680 |
+ |
the_buffer_copy = (uint8 *)malloc(the_buffer_size); |
681 |
|
D(bug("the_buffer = %p, the_buffer_copy = %p, the_host_buffer = %p\n", the_buffer, the_buffer_copy, the_host_buffer)); |
682 |
|
#else |
683 |
|
// Allocate memory for frame buffer |
726 |
|
the_buffer_copy = NULL; // don't free() in driver_base dtor |
727 |
|
#endif |
728 |
|
} |
729 |
< |
#ifdef ENABLE_VOSF |
730 |
< |
if (use_vosf) { |
731 |
< |
// don't free() memory mapped buffers in driver_base dtor |
711 |
< |
if (the_buffer != VM_MAP_FAILED) { |
712 |
< |
vm_release(the_buffer, the_buffer_size); |
713 |
< |
the_buffer = NULL; |
714 |
< |
} |
715 |
< |
if (the_buffer_copy != VM_MAP_FAILED) { |
716 |
< |
vm_release(the_buffer_copy, the_buffer_size); |
717 |
< |
the_buffer_copy = NULL; |
718 |
< |
} |
719 |
< |
} |
720 |
< |
#endif |
721 |
< |
if (img) |
729 |
> |
if (img) { |
730 |
> |
if (!have_shm) |
731 |
> |
img->data = NULL; |
732 |
|
XDestroyImage(img); |
733 |
+ |
} |
734 |
|
if (have_shm) { |
735 |
|
shmdt(shminfo.shmaddr); |
736 |
|
shmctl(shminfo.shmid, IPC_RMID, 0); |
1072 |
|
// Allocate memory for frame buffer (SIZE is extended to page-boundary) |
1073 |
|
the_host_buffer = the_buffer; |
1074 |
|
the_buffer_size = page_extend((height + 2) * bytes_per_row); |
1075 |
< |
the_buffer_copy = (uint8 *)vm_acquire(the_buffer_size); |
1075 |
> |
the_buffer_copy = (uint8 *)malloc(the_buffer_size); |
1076 |
|
the_buffer = (uint8 *)vm_acquire(the_buffer_size); |
1077 |
|
} |
1078 |
|
#else |
1107 |
|
munmap(the_host_buffer, the_buffer_size); |
1108 |
|
the_host_buffer = NULL; |
1109 |
|
} |
1099 |
– |
if (the_buffer_copy != VM_MAP_FAILED) { |
1100 |
– |
vm_release(the_buffer_copy, the_buffer_size); |
1101 |
– |
the_buffer_copy = NULL; |
1102 |
– |
} |
1103 |
– |
if (the_buffer != VM_MAP_FAILED) { |
1104 |
– |
vm_release(the_buffer, the_buffer_size); |
1105 |
– |
the_buffer = NULL; |
1106 |
– |
} |
1110 |
|
} |
1111 |
|
#endif |
1112 |
|
} |
1205 |
|
// Allocate memory for frame buffer (SIZE is extended to page-boundary) |
1206 |
|
the_host_buffer = the_buffer; |
1207 |
|
the_buffer_size = page_extend((height + 2) * bytes_per_row); |
1208 |
< |
the_buffer_copy = (uint8 *)vm_acquire(the_buffer_size); |
1208 |
> |
the_buffer_copy = (uint8 *)malloc(the_buffer_size); |
1209 |
|
the_buffer = (uint8 *)vm_acquire(the_buffer_size); |
1210 |
|
} |
1211 |
|
#else |
1234 |
|
else { |
1235 |
|
// don't free() the screen buffer in driver_base dtor |
1236 |
|
the_host_buffer = NULL; |
1234 |
– |
|
1235 |
– |
if (the_buffer_copy != VM_MAP_FAILED) { |
1236 |
– |
vm_release(the_buffer_copy, the_buffer_size); |
1237 |
– |
the_buffer_copy = NULL; |
1238 |
– |
} |
1239 |
– |
if (the_buffer != VM_MAP_FAILED) { |
1240 |
– |
vm_release(the_buffer, the_buffer_size); |
1241 |
– |
the_buffer = NULL; |
1242 |
– |
} |
1237 |
|
} |
1238 |
|
#endif |
1239 |
|
#ifdef ENABLE_XF86_VIDMODE |
1333 |
|
// Open display for specified mode |
1334 |
|
static bool video_open(const video_mode &mode) |
1335 |
|
{ |
1336 |
+ |
D(bug("video_open()\n")); |
1337 |
+ |
|
1338 |
|
// Find best available X visual |
1339 |
|
if (!find_visual_for_depth(mode.depth)) { |
1340 |
|
ErrorAlert(STR_NO_XVISUAL_ERR); |
1633 |
|
// Close display |
1634 |
|
static void video_close(void) |
1635 |
|
{ |
1636 |
+ |
D(bug("video_close()\n")); |
1637 |
+ |
|
1638 |
|
// Stop redraw thread |
1639 |
|
#ifdef HAVE_PTHREADS |
1640 |
|
if (redraw_thread_active) { |
1650 |
|
// Unlock frame buffer |
1651 |
|
UNLOCK_FRAME_BUFFER; |
1652 |
|
XSync(x_display, false); |
1653 |
+ |
D(bug(" frame buffer unlocked\n")); |
1654 |
|
|
1655 |
|
#ifdef ENABLE_VOSF |
1656 |
|
if (use_vosf) { |
2187 |
|
static void update_display_static(driver_window *drv) |
2188 |
|
{ |
2189 |
|
// Incremental update code |
2190 |
< |
int wide = 0, high = 0, x1, x2, y1, y2, i, j; |
2190 |
> |
unsigned wide = 0, high = 0, x1, x2, y1, y2, i, j; |
2191 |
|
int bytes_per_row = VideoMonitor.mode.bytes_per_row; |
2192 |
|
int bytes_per_pixel = VideoMonitor.mode.bytes_per_row / VideoMonitor.mode.x; |
2193 |
|
uint8 *p, *p2; |