1 /* ______ ___ ___
2 * /\ _ \ /\_ \ /\_ \
3 * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___
4 * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\
5 * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \
6 * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/
7 * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/
8 * /\____/
9 * \_/__/
10 *
11 * Wrappers for Xlib functions.
12 *
13 * By Michael Bukin.
14 *
15 * Video mode switching by Peter Wang and Benjamin Stover.
16 *
17 * X icon selection by Evert Glebbeek
18 *
19 * See readme.txt for copyright information.
20 */
21
22
23 #include "allegro.h"
24 #include "allegro/internal/aintern.h"
25 #include "allegro/platform/aintunix.h"
26 #include "xwin.h"
27
28 #include <string.h>
29 #include <X11/Xlib.h>
30 #include <X11/Xutil.h>
31 #include <X11/cursorfont.h>
32 #include <X11/keysym.h>
33
34 #ifdef ALLEGRO_XWINDOWS_WITH_SHM
35 #include <sys/ipc.h>
36 #include <sys/shm.h>
37 #include <X11/extensions/XShm.h>
38 #endif
39
40 #ifdef ALLEGRO_XWINDOWS_WITH_XF86VIDMODE
41 #include <X11/extensions/xf86vmode.h>
42 #endif
43
44 #ifdef ALLEGRO_XWINDOWS_WITH_XCURSOR
45 #include <X11/Xcursor/Xcursor.h>
46 #endif
47
48
49 #ifdef ALLEGRO_XWINDOWS_WITH_XPM
50 #include <X11/xpm.h>
51 #endif
52 #include "icon.xpm"
53
54
55 #define XWIN_DEFAULT_WINDOW_TITLE "Allegro application"
56 #define XWIN_DEFAULT_APPLICATION_NAME "allegro"
57 #define XWIN_DEFAULT_APPLICATION_CLASS "Allegro"
58
59
60 struct _xwin_type _xwin =
61 {
62 0, /* display */
63 0, /* lock count */
64 0, /* screen */
65 None, /* window */
66 None, /* gc */
67 0, /* visual */
68 None, /* colormap */
69 0, /* ximage */
70 #ifdef ALLEGRO_XWINDOWS_WITH_XCURSOR
71 None, /* ARGB cursor image */
72 XcursorFalse,/* Are ARGB cursors supported? */
73 #endif
74 None, /* cursor */
75 XC_heart, /* cursor_shape */
76 1, /* hw_cursor_ok */
77
78 0, /* screen_to_buffer */
79 0, /* set_colors */
80
81 0, /* screen_data */
82 0, /* screen_line */
83 0, /* buffer_line */
84
85 0, /* scroll_x */
86 0, /* scroll_y */
87
88 320, /* window_width */
89 200, /* window_height */
90 8, /* window_depth */
91
92 320, /* screen_width */
93 200, /* screen_height */
94 8, /* screen_depth */
95
96 320, /* virtual width */
97 200, /* virtual_height */
98
99 0, /* mouse_warped */
100 { 0 }, /* keycode_to_scancode */
101
102 0, /* matching formats */
103 0, /* fast_visual_depth */
104 0, /* visual_is_truecolor */
105
106 1, /* rsize */
107 1, /* gsize */
108 1, /* bsize */
109 0, /* rshift */
110 0, /* gshift */
111 0, /* bshift */
112
113 { 0 }, /* cmap */
114 { 0 }, /* rmap */
115 { 0 }, /* gmap */
116 { 0 }, /* bmap */
117
118 #ifdef ALLEGRO_XWINDOWS_WITH_SHM
119 { 0, 0, 0, 0 }, /* shminfo */
120 #endif
121 0, /* use_shm */
122
123 0, /* in_dga_mode */
124
125 0, /* keyboard_grabbed */
126 0, /* mouse_grabbed */
127
128 #ifdef ALLEGRO_XWINDOWS_WITH_XF86VIDMODE
129 0, /* modesinfo */
130 0, /* num_modes */
131 0, /* mode_switched */
132 0, /* override_redirected */
133 #endif
134
135 XWIN_DEFAULT_WINDOW_TITLE, /* window_title */
136 XWIN_DEFAULT_APPLICATION_NAME, /* application_name */
137 XWIN_DEFAULT_APPLICATION_CLASS, /* application_class */
138
139 FALSE, /* drawing_mode_ok */
140
141 #ifdef ALLEGRO_MULTITHREADED
142 NULL, /* mutex */
143 #endif
144
145 NULL, /* window close hook */
146 #ifdef ALLEGRO_XWINDOWS_WITH_XF86VIDMODE
147 0, /* orig_modeinfo */
148 #endif
149 None, /* fs_window */
150 None /* wm_window */
151 };
152
153 void *allegro_icon = icon_xpm;
154
155 int _xwin_last_line = -1;
156 int _xwin_in_gfx_call = 0;
157
158 static COLORCONV_BLITTER_FUNC *blitter_func = NULL;
159 static int use_bgr_palette_hack = FALSE; /* use BGR hack for color conversion palette? */
160
161 #ifndef ALLEGRO_MULTITHREADED
162 int _xwin_missed_input;
163 #endif
164
165 #define X_MAX_EVENTS 50
166 #define MOUSE_WARP_DELAY 200
167
168 static char _xwin_driver_desc[256] = EMPTY_STRING;
169
170 /* This is used to intercept window closing requests. */
171 static Atom wm_delete_window;
172
173 #define PREFIX_I "al-xwin INFO: "
174 #define PREFIX_W "al-xwin WARNING: "
175 #define PREFIX_E "al-xwin ERROR: "
176
177
178 /* Forward declarations for private functions. */
179 static int _xwin_private_open_display(char *name);
180 static int _xwin_private_create_window(void);
181 static void _xwin_private_destroy_window(void);
182 static void _xwin_private_select_screen_to_buffer_function(void);
183 static void _xwin_private_select_set_colors_function(void);
184 static void _xwin_private_setup_driver_desc(GFX_DRIVER *drv);
185 static BITMAP *_xwin_private_create_screen(GFX_DRIVER *drv, int w, int h,
186 int vw, int vh, int depth, int fullscreen);
187 static void _xwin_private_destroy_screen(void);
188 static BITMAP *_xwin_private_create_screen_bitmap(GFX_DRIVER *drv,
189 unsigned char *frame_buffer,
190 int bytes_per_buffer_line);
191 static void _xwin_private_create_mapping_tables(void);
192 static void _xwin_private_create_mapping(unsigned long *map, int ssize, int dsize, int dshift);
193 static int _xwin_private_display_is_local(void);
194 static int _xwin_private_create_ximage(int w, int h);
195 static void _xwin_private_destroy_ximage(void);
196 static void _xwin_private_prepare_visual(void);
197 static int _xwin_private_matching_formats(void);
198 static void _xwin_private_hack_shifts(void);
199 static int _xwin_private_colorconv_usable(void);
200 static int _xwin_private_fast_visual_depth(void);
201 static void _xwin_private_set_matching_colors(AL_CONST PALETTE p, int from, int to);
202 static void _xwin_private_set_truecolor_colors(AL_CONST PALETTE p, int from, int to);
203 static void _xwin_private_set_palette_colors(AL_CONST PALETTE p, int from, int to);
204 static void _xwin_private_set_palette_range(AL_CONST PALETTE p, int from, int to);
205 static void _xwin_private_set_window_defaults(void);
206 static void _xwin_private_flush_buffers(void);
207 static void _xwin_private_process_event(XEvent *event);
208 static void _xwin_private_set_warped_mouse_mode(int permanent);
209 static void _xwin_private_redraw_window(int x, int y, int w, int h);
210 static int _xwin_private_scroll_screen(int x, int y);
211 static void _xwin_private_update_screen(int x, int y, int w, int h);
212 static void _xwin_private_set_window_title(AL_CONST char *name);
213 static void _xwin_private_set_window_name(AL_CONST char *name, AL_CONST char *group);
214 static int _xwin_private_get_pointer_mapping(unsigned char map[], int nmap);
215
216 static void _xwin_private_fast_colorconv(int sx, int sy, int sw, int sh);
217
218 static void _xwin_private_fast_truecolor_8_to_8(int sx, int sy, int sw, int sh);
219 static void _xwin_private_fast_truecolor_8_to_16(int sx, int sy, int sw, int sh);
220 static void _xwin_private_fast_truecolor_8_to_24(int sx, int sy, int sw, int sh);
221 static void _xwin_private_fast_truecolor_8_to_32(int sx, int sy, int sw, int sh);
222 static void _xwin_private_fast_truecolor_15_to_8(int sx, int sy, int sw, int sh);
223 static void _xwin_private_fast_truecolor_15_to_16(int sx, int sy, int sw, int sh);
224 static void _xwin_private_fast_truecolor_15_to_24(int sx, int sy, int sw, int sh);
225 static void _xwin_private_fast_truecolor_15_to_32(int sx, int sy, int sw, int sh);
226 static void _xwin_private_fast_truecolor_16_to_8(int sx, int sy, int sw, int sh);
227 static void _xwin_private_fast_truecolor_16_to_16(int sx, int sy, int sw, int sh);
228 static void _xwin_private_fast_truecolor_16_to_24(int sx, int sy, int sw, int sh);
229 static void _xwin_private_fast_truecolor_16_to_32(int sx, int sy, int sw, int sh);
230 static void _xwin_private_fast_truecolor_24_to_8(int sx, int sy, int sw, int sh);
231 static void _xwin_private_fast_truecolor_24_to_16(int sx, int sy, int sw, int sh);
232 static void _xwin_private_fast_truecolor_24_to_24(int sx, int sy, int sw, int sh);
233 static void _xwin_private_fast_truecolor_24_to_32(int sx, int sy, int sw, int sh);
234 static void _xwin_private_fast_truecolor_32_to_8(int sx, int sy, int sw, int sh);
235 static void _xwin_private_fast_truecolor_32_to_16(int sx, int sy, int sw, int sh);
236 static void _xwin_private_fast_truecolor_32_to_24(int sx, int sy, int sw, int sh);
237 static void _xwin_private_fast_truecolor_32_to_32(int sx, int sy, int sw, int sh);
238
239 static void _xwin_private_slow_truecolor_8(int sx, int sy, int sw, int sh);
240 static void _xwin_private_slow_truecolor_15(int sx, int sy, int sw, int sh);
241 static void _xwin_private_slow_truecolor_16(int sx, int sy, int sw, int sh);
242 static void _xwin_private_slow_truecolor_24(int sx, int sy, int sw, int sh);
243 static void _xwin_private_slow_truecolor_32(int sx, int sy, int sw, int sh);
244
245 static void _xwin_private_fast_palette_8_to_8(int sx, int sy, int sw, int sh);
246 static void _xwin_private_fast_palette_8_to_16(int sx, int sy, int sw, int sh);
247 static void _xwin_private_fast_palette_8_to_32(int sx, int sy, int sw, int sh);
248 static void _xwin_private_fast_palette_15_to_8(int sx, int sy, int sw, int sh);
249 static void _xwin_private_fast_palette_15_to_16(int sx, int sy, int sw, int sh);
250 static void _xwin_private_fast_palette_15_to_32(int sx, int sy, int sw, int sh);
251 static void _xwin_private_fast_palette_16_to_8(int sx, int sy, int sw, int sh);
252 static void _xwin_private_fast_palette_16_to_16(int sx, int sy, int sw, int sh);
253 static void _xwin_private_fast_palette_16_to_32(int sx, int sy, int sw, int sh);
254 static void _xwin_private_fast_palette_24_to_8(int sx, int sy, int sw, int sh);
255 static void _xwin_private_fast_palette_24_to_16(int sx, int sy, int sw, int sh);
256 static void _xwin_private_fast_palette_24_to_32(int sx, int sy, int sw, int sh);
257 static void _xwin_private_fast_palette_32_to_8(int sx, int sy, int sw, int sh);
258 static void _xwin_private_fast_palette_32_to_16(int sx, int sy, int sw, int sh);
259 static void _xwin_private_fast_palette_32_to_32(int sx, int sy, int sw, int sh);
260
261 static void _xwin_private_slow_palette_8(int sx, int sy, int sw, int sh);
262 static void _xwin_private_slow_palette_15(int sx, int sy, int sw, int sh);
263 static void _xwin_private_slow_palette_16(int sx, int sy, int sw, int sh);
264 static void _xwin_private_slow_palette_24(int sx, int sy, int sw, int sh);
265 static void _xwin_private_slow_palette_32(int sx, int sy, int sw, int sh);
266
267 #ifdef ALLEGRO_XWINDOWS_WITH_XF86VIDMODE
268 static void _xvidmode_private_set_fullscreen(int w, int h, int *vidmode_width,
269 int *vidmode_height);
270 static void _xvidmode_private_unset_fullscreen(void);
271 #endif
272
273 uintptr_t _xwin_write_line(BITMAP *bmp, int line);
274 void _xwin_unwrite_line(BITMAP *bmp);
275 #ifndef ALLEGRO_NO_ASM
276 uintptr_t _xwin_write_line_asm(BITMAP *bmp, int line);
277 void _xwin_unwrite_line_asm(BITMAP *bmp);
278 #endif
279
280
281
282 /* _xwin_open_display:
283 * Wrapper for XOpenDisplay.
284 */
_xwin_private_open_display(char * name)285 static int _xwin_private_open_display(char *name)
286 {
287 if (_xwin.display != 0)
288 return -1;
289
290 _xwin.display = XOpenDisplay(name);
291 _xwin.screen = ((_xwin.display == 0) ? 0 : XDefaultScreen(_xwin.display));
292
293 return ((_xwin.display != 0) ? 0 : -1);
294 }
295
_xwin_open_display(char * name)296 int _xwin_open_display(char *name)
297 {
298 int result;
299 XLOCK();
300 result = _xwin_private_open_display(name);
301 XUNLOCK();
302 return result;
303 }
304
305
306
307 /* _xwin_close_display:
308 * Wrapper for XCloseDisplay.
309 */
_xwin_close_display(void)310 void _xwin_close_display(void)
311 {
312 Display *dpy;
313
314 if (!_unix_bg_man->multi_threaded) {
315 XLOCK();
316 }
317
318 if (_xwin.display != 0) {
319 _xwin_destroy_window();
320 dpy = _xwin.display;
321 _xwin.display = 0;
322 XCloseDisplay(dpy);
323 }
324
325 if (!_unix_bg_man->multi_threaded) {
326 XUNLOCK();
327 }
328 }
329
330
331
332 /* _xwin_hide_x_mouse:
333 * Create invisible X cursor.
334 */
_xwin_hide_x_mouse(void)335 static void _xwin_hide_x_mouse(void)
336 {
337 unsigned long gcmask;
338 XGCValues gcvalues;
339 Pixmap pixmap;
340
341 XUndefineCursor(_xwin.display, _xwin.window);
342
343 if (_xwin.cursor != None) {
344 XFreeCursor(_xwin.display, _xwin.cursor);
345 _xwin.cursor = None;
346 }
347
348 #ifdef ALLEGRO_XWINDOWS_WITH_XCURSOR
349 if (_xwin.xcursor_image != None) {
350 XcursorImageDestroy(_xwin.xcursor_image);
351 _xwin.xcursor_image = None;
352 }
353 #endif
354
355 pixmap = XCreatePixmap(_xwin.display, _xwin.window, 1, 1, 1);
356 if (pixmap != None) {
357 GC temp_gc;
358 XColor color;
359
360 gcmask = GCFunction | GCForeground | GCBackground;
361 gcvalues.function = GXcopy;
362 gcvalues.foreground = 0;
363 gcvalues.background = 0;
364 temp_gc = XCreateGC(_xwin.display, pixmap, gcmask, &gcvalues);
365 XDrawPoint(_xwin.display, pixmap, temp_gc, 0, 0);
366 XFreeGC(_xwin.display, temp_gc);
367 color.pixel = 0;
368 color.red = color.green = color.blue = 0;
369 color.flags = DoRed | DoGreen | DoBlue;
370 _xwin.cursor = XCreatePixmapCursor(_xwin.display, pixmap, pixmap, &color, &color, 0, 0);
371 XDefineCursor(_xwin.display, _xwin.window, _xwin.cursor);
372 XFreePixmap(_xwin.display, pixmap);
373 }
374 else {
375 _xwin.cursor = XCreateFontCursor(_xwin.display, _xwin.cursor_shape);
376 XDefineCursor(_xwin.display, _xwin.window, _xwin.cursor);
377 }
378 }
379
380
381
382 /* _xwin_wait_mapped:
383 * Wait for a window to become mapped.
384 */
_xwin_wait_mapped(Window win)385 static void _xwin_wait_mapped(Window win)
386 {
387 /* Note:
388 * The busy loop below is just a hack to work around my broken X11.
389 * A call to XMaskEvent will block indefinitely and no Allegro
390 * programs (which create a window) will start up at all. Replacing
391 * XMaskEvent with a busy loop calling XCheckMaskEvent repeatedly
392 * somehow works though..
393 */
394 while (1) {
395 XEvent e;
396 if (XCheckTypedEvent(_xwin.display, MapNotify, &e)) {
397 if (e.xmap.event == win) break;
398 }
399 rest(1);
400 }
401 }
402
403
404
405 /* _xwin_create_window:
406 * We use 3 windows:
407 * - fs_window (for fullscreen)
408 * - wm_window (window managed)
409 * - window (the real window)
410 *
411 * Two of which will be created here: wm_window and window. The fullscreen
412 * window gets (re)created when needed, because reusing it causes trouble see
413 * http://sourceforge.net/tracker/index.php?func=detail&aid=1441740&group_id=5665&atid=105665
414 * The real window uses wm_window as parent initially and will be reparented
415 * to the (freshly created) fullscreen window when requested and reparented
416 * back again in screen_destroy.
417 *
418 * Idea/concept of three windows borrowed from SDL. But somehow SDL manages
419 * to reuse the fullscreen window too.
420 */
_xwin_private_create_window(void)421 static int _xwin_private_create_window(void)
422 {
423 unsigned long gcmask;
424 XGCValues gcvalues;
425 XSetWindowAttributes setattr;
426 XWindowAttributes getattr;
427
428 if (_xwin.display == 0)
429 return -1;
430
431 _mouse_on = FALSE;
432
433 /* Create the managed window. */
434 setattr.background_pixel = XBlackPixel(_xwin.display, _xwin.screen);
435 setattr.border_pixel = XBlackPixel(_xwin.display, _xwin.screen);
436 setattr.event_mask = (KeyPressMask | KeyReleaseMask | StructureNotifyMask
437 | EnterWindowMask | LeaveWindowMask
438 | FocusChangeMask | ExposureMask | PropertyChangeMask
439 | ButtonPressMask | ButtonReleaseMask | PointerMotionMask
440 /*| MappingNotifyMask (SubstructureRedirectMask?)*/);
441 _xwin.wm_window = XCreateWindow(_xwin.display,
442 XDefaultRootWindow(_xwin.display),
443 0, 0, 320, 200, 0,
444 CopyFromParent, InputOutput, CopyFromParent,
445 CWBackPixel | CWBorderPixel | CWEventMask,
446 &setattr);
447
448 /* Get associated visual and window depth (bits per pixel). */
449 XGetWindowAttributes(_xwin.display, _xwin.wm_window, &getattr);
450 _xwin.visual = getattr.visual;
451 _xwin.window_depth = getattr.depth;
452
453 /* Create and install colormap. */
454 if ((_xwin.visual->class == PseudoColor)
455 || (_xwin.visual->class == GrayScale)
456 || (_xwin.visual->class == DirectColor))
457 {
458 _xwin.colormap = XCreateColormap(_xwin.display, _xwin.wm_window, _xwin.visual, AllocAll);
459 }
460 else {
461 _xwin.colormap = XCreateColormap(_xwin.display, _xwin.wm_window, _xwin.visual, AllocNone);
462 }
463 XSetWindowColormap(_xwin.display, _xwin.wm_window, _xwin.colormap);
464 XInstallColormap(_xwin.display, _xwin.colormap);
465
466 /* Create the real / drawing window (reuses setattr). */
467 setattr.colormap = _xwin.colormap;
468 _xwin.window = XCreateWindow(_xwin.display,
469 _xwin.wm_window,
470 0, 0, 320, 200, 0,
471 CopyFromParent, InputOutput, CopyFromParent,
472 CWBackPixel | CWBorderPixel | CWEventMask |
473 CWColormap, &setattr);
474
475 /* Map the real / drawing window it won't appear untill the parent does */
476 XMapWindow(_xwin.display, _xwin.window);
477
478 /* Set WM_DELETE_WINDOW atom in WM_PROTOCOLS property (to get window_delete requests). */
479 wm_delete_window = XInternAtom(_xwin.display, "WM_DELETE_WINDOW", False);
480 XSetWMProtocols(_xwin.display, _xwin.wm_window, &wm_delete_window, 1);
481
482 /* Set default window parameters. */
483 (*_xwin_window_defaultor)();
484
485 /* Create graphics context. */
486 gcmask = GCFunction | GCForeground | GCBackground | GCFillStyle | GCPlaneMask;
487 gcvalues.function = GXcopy;
488 gcvalues.foreground = setattr.border_pixel;
489 gcvalues.background = setattr.border_pixel;
490 gcvalues.fill_style = FillSolid;
491 gcvalues.plane_mask = AllPlanes;
492 _xwin.gc = XCreateGC(_xwin.display, _xwin.window, gcmask, &gcvalues);
493
494 /* Create invisible X cursor. */
495 _xwin_hide_x_mouse();
496
497 #ifdef ALLEGRO_XWINDOWS_WITH_XCURSOR
498 /* Detect if ARGB cursors are supported */
499 _xwin.support_argb_cursor = XcursorSupportsARGB(_xwin.display);
500 #endif
501 _xwin.hw_cursor_ok = 0;
502
503 return 0;
504 }
505
_xwin_create_window(void)506 int _xwin_create_window(void)
507 {
508 int result;
509 XLOCK();
510 result = (*_xwin_window_creator)();
511 XUNLOCK();
512 return result;
513 }
514
515
516
517 /* _xwin_destroy_window:
518 * Wrapper for XDestroyWindow.
519 */
_xwin_private_destroy_window(void)520 static void _xwin_private_destroy_window(void)
521 {
522 _xwin_private_destroy_screen();
523
524 if (_xwin.cursor != None) {
525 XUndefineCursor(_xwin.display, _xwin.window);
526 XFreeCursor(_xwin.display, _xwin.cursor);
527 _xwin.cursor = None;
528 }
529
530 #ifdef ALLEGRO_XWINDOWS_WITH_XCURSOR
531 if (_xwin.xcursor_image != None) {
532 XcursorImageDestroy(_xwin.xcursor_image);
533 _xwin.xcursor_image = None;
534 }
535 #endif
536
537 _xwin.visual = 0;
538
539 if (_xwin.gc != None) {
540 XFreeGC(_xwin.display, _xwin.gc);
541 _xwin.gc = None;
542 }
543
544 if (_xwin.colormap != None) {
545 XUninstallColormap(_xwin.display, _xwin.colormap);
546 XFreeColormap(_xwin.display, _xwin.colormap);
547 _xwin.colormap = None;
548 }
549
550 if (_xwin.window != None) {
551 XUnmapWindow(_xwin.display, _xwin.window);
552 XDestroyWindow(_xwin.display, _xwin.window);
553 _xwin.window = None;
554 }
555
556 if (_xwin.wm_window != None) {
557 XDestroyWindow(_xwin.display, _xwin.wm_window);
558 _xwin.wm_window = None;
559 }
560 }
561
_xwin_destroy_window(void)562 void _xwin_destroy_window(void)
563 {
564 XLOCK();
565 _xwin_private_destroy_window();
566 XUNLOCK();
567 }
568
569
570
571 typedef void (*_XWIN_SCREEN_TO_BUFFER)(int x, int y, int w, int h);
572 static _XWIN_SCREEN_TO_BUFFER _xwin_screen_to_buffer_function[5][10] =
573 {
574 {
575 _xwin_private_slow_truecolor_8,
576 _xwin_private_fast_truecolor_8_to_8,
577 _xwin_private_fast_truecolor_8_to_16,
578 _xwin_private_fast_truecolor_8_to_24,
579 _xwin_private_fast_truecolor_8_to_32,
580 _xwin_private_slow_palette_8,
581 _xwin_private_fast_palette_8_to_8,
582 _xwin_private_fast_palette_8_to_16,
583 0,
584 _xwin_private_fast_palette_8_to_32
585 },
586 {
587 _xwin_private_slow_truecolor_15,
588 _xwin_private_fast_truecolor_15_to_8,
589 _xwin_private_fast_truecolor_15_to_16,
590 _xwin_private_fast_truecolor_15_to_24,
591 _xwin_private_fast_truecolor_15_to_32,
592 _xwin_private_slow_palette_15,
593 _xwin_private_fast_palette_15_to_8,
594 _xwin_private_fast_palette_15_to_16,
595 0,
596 _xwin_private_fast_palette_15_to_32
597 },
598 {
599 _xwin_private_slow_truecolor_16,
600 _xwin_private_fast_truecolor_16_to_8,
601 _xwin_private_fast_truecolor_16_to_16,
602 _xwin_private_fast_truecolor_16_to_24,
603 _xwin_private_fast_truecolor_16_to_32,
604 _xwin_private_slow_palette_16,
605 _xwin_private_fast_palette_16_to_8,
606 _xwin_private_fast_palette_16_to_16,
607 0,
608 _xwin_private_fast_palette_16_to_32
609 },
610 {
611 _xwin_private_slow_truecolor_24,
612 _xwin_private_fast_truecolor_24_to_8,
613 _xwin_private_fast_truecolor_24_to_16,
614 _xwin_private_fast_truecolor_24_to_24,
615 _xwin_private_fast_truecolor_24_to_32,
616 _xwin_private_slow_palette_24,
617 _xwin_private_fast_palette_24_to_8,
618 _xwin_private_fast_palette_24_to_16,
619 0,
620 _xwin_private_fast_palette_24_to_32
621 },
622 {
623 _xwin_private_slow_truecolor_32,
624 _xwin_private_fast_truecolor_32_to_8,
625 _xwin_private_fast_truecolor_32_to_16,
626 _xwin_private_fast_truecolor_32_to_24,
627 _xwin_private_fast_truecolor_32_to_32,
628 _xwin_private_slow_palette_32,
629 _xwin_private_fast_palette_32_to_8,
630 _xwin_private_fast_palette_32_to_16,
631 0,
632 _xwin_private_fast_palette_32_to_32
633 },
634 };
635
636
637
638 /* _xwin_select_screen_to_buffer_function:
639 * Select which function should be used for updating frame buffer with screen data.
640 */
_xwin_private_select_screen_to_buffer_function(void)641 static void _xwin_private_select_screen_to_buffer_function(void)
642 {
643 int i, j;
644
645 if (_xwin.matching_formats) {
646 _xwin.screen_to_buffer = 0;
647 }
648 else {
649 switch (_xwin.screen_depth) {
650 case 8: i = 0; break;
651 case 15: i = 1; break;
652 case 16: i = 2; break;
653 case 24: i = 3; break;
654 case 32: i = 4; break;
655 default: i = 0; break;
656 }
657 switch (_xwin.fast_visual_depth) {
658 case 0: j = 0; break;
659 case 8: j = 1; break;
660 case 16: j = 2; break;
661 case 24: j = 3; break;
662 case 32: j = 4; break;
663 default: j = 0; break;
664 }
665 if (!_xwin.visual_is_truecolor)
666 j += 5;
667
668 if (_xwin_private_colorconv_usable()) {
669 TRACE(PREFIX_I "Using generic color conversion blitter (%u, %u).\n",
670 _xwin.screen_depth, _xwin.fast_visual_depth);
671 blitter_func = _get_colorconv_blitter(_xwin.screen_depth,
672 _xwin.fast_visual_depth);
673 _xwin.screen_to_buffer = _xwin_private_fast_colorconv;
674 }
675 else {
676 _xwin.screen_to_buffer = _xwin_screen_to_buffer_function[i][j];
677 }
678 }
679 }
680
681
682
683 /* _xwin_select_set_colors_function:
684 * Select which function should be used for setting hardware colors.
685 */
_xwin_private_select_set_colors_function(void)686 static void _xwin_private_select_set_colors_function(void)
687 {
688 if (_xwin.screen_depth != 8) {
689 _xwin.set_colors = 0;
690 }
691 else {
692 if (_xwin.matching_formats) {
693 _xwin.set_colors = _xwin_private_set_matching_colors;
694 }
695 else if (_xwin.visual_is_truecolor) {
696 _xwin.set_colors = _xwin_private_set_truecolor_colors;
697 }
698 else {
699 _xwin.set_colors = _xwin_private_set_palette_colors;
700 }
701 }
702 }
703
704
705
706 /* _xwin_setup_driver_desc:
707 * Sets up the X-Windows driver description string.
708 */
_xwin_private_setup_driver_desc(GFX_DRIVER * drv)709 static void _xwin_private_setup_driver_desc(GFX_DRIVER *drv)
710 {
711 char tmp1[256], tmp2[128], tmp3[128], tmp4[128];
712
713 /* Prepare driver description. */
714 if (_xwin.matching_formats) {
715 uszprintf(_xwin_driver_desc, sizeof(_xwin_driver_desc),
716 uconvert_ascii("X-Windows graphics, in matching, %d bpp %s", tmp1),
717 _xwin.window_depth,
718 uconvert_ascii("real depth", tmp2));
719 }
720 else {
721 uszprintf(_xwin_driver_desc, sizeof(_xwin_driver_desc),
722 uconvert_ascii("X-Windows graphics, in %s %s, %d bpp %s", tmp1),
723 uconvert_ascii((_xwin.fast_visual_depth ? "fast" : "slow"), tmp2),
724 uconvert_ascii((_xwin.visual_is_truecolor ? "truecolor" : "paletted"), tmp3),
725 _xwin.window_depth,
726 uconvert_ascii("real depth", tmp4));
727 }
728 drv->desc = _xwin_driver_desc;
729 }
730
731
732
733 /* _xwin_create_screen:
734 * Creates screen data and other resources.
735 */
_xwin_private_create_screen(GFX_DRIVER * drv,int w,int h,int vw,int vh,int depth,int fullscreen)736 static BITMAP *_xwin_private_create_screen(GFX_DRIVER *drv, int w, int h,
737 int vw, int vh, int depth, int fullscreen)
738 {
739 if (_xwin.window == None) {
740 ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("No window"));
741 return 0;
742 }
743
744 /* Choose convenient size. */
745 if ((w == 0) && (h == 0)) {
746 w = 320;
747 h = 200;
748 }
749
750 if (vw < w)
751 vw = w;
752 if (vh < h)
753 vh = h;
754
755 if (1
756 #ifdef ALLEGRO_COLOR8
757 && (depth != 8)
758 #endif
759 #ifdef ALLEGRO_COLOR16
760 && (depth != 15)
761 && (depth != 16)
762 #endif
763 #ifdef ALLEGRO_COLOR24
764 && (depth != 24)
765 #endif
766 #ifdef ALLEGRO_COLOR32
767 && (depth != 32)
768 #endif
769 ) {
770 ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Unsupported color depth"));
771 return 0;
772 }
773
774 /* Save dimensions. */
775 _xwin.window_width = w;
776 _xwin.window_height = h;
777 _xwin.screen_width = w;
778 _xwin.screen_height = h;
779 _xwin.screen_depth = depth;
780 _xwin.virtual_width = vw;
781 _xwin.virtual_height = vh;
782
783 /* Resize the (real) window */
784 XResizeWindow(_xwin.display, _xwin.window, w, h);
785
786 if (fullscreen) {
787 XSetWindowAttributes setattr;
788 /* Local width and height vars used for fullscreen window size and for
789 * storing the video_mode size which is then used to center the window.
790 */
791 int fs_width = DisplayWidth(_xwin.display, _xwin.screen);
792 int fs_height = DisplayHeight(_xwin.display, _xwin.screen);
793
794 /* Create the fullscreen window. */
795 setattr.override_redirect = True;
796 setattr.background_pixel = XBlackPixel(_xwin.display, _xwin.screen);
797 setattr.border_pixel = XBlackPixel(_xwin.display, _xwin.screen);
798 setattr.event_mask = StructureNotifyMask;
799 setattr.colormap = _xwin.colormap;
800 _xwin.fs_window = XCreateWindow(_xwin.display,
801 XDefaultRootWindow(_xwin.display),
802 0, 0, fs_width, fs_height, 0,
803 CopyFromParent, InputOutput,
804 CopyFromParent, CWOverrideRedirect |
805 CWBackPixel | CWColormap | CWBorderPixel |
806 CWEventMask, &setattr);
807
808 /* Map the fullscreen window. */
809 XMapRaised(_xwin.display, _xwin.fs_window);
810 _xwin_wait_mapped(_xwin.fs_window);
811
812 /* Make sure we got to the top of the window stack. */
813 XRaiseWindow(_xwin.display, _xwin.fs_window);
814
815 /* Reparent the real window. */
816 XReparentWindow(_xwin.display, _xwin.window, _xwin.fs_window, 0, 0);
817
818 /* Grab the keyboard and mouse. */
819 if (XGrabKeyboard(_xwin.display, XDefaultRootWindow(_xwin.display), False,
820 GrabModeAsync, GrabModeAsync, CurrentTime) != GrabSuccess) {
821 ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Can not grab keyboard"));
822 return 0;
823 }
824 _xwin.keyboard_grabbed = 1;
825 if (XGrabPointer(_xwin.display, _xwin.window, False,
826 PointerMotionMask | ButtonPressMask | ButtonReleaseMask,
827 GrabModeAsync, GrabModeAsync, _xwin.window, None, CurrentTime) != GrabSuccess) {
828 ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Can not grab mouse"));
829 return 0;
830 }
831 _xwin.mouse_grabbed = 1;
832
833 #ifdef ALLEGRO_XWINDOWS_WITH_XF86VIDMODE
834 /* Try to switch video mode. This must be done after the pointer is
835 * grabbed, because otherwise it can be outside the window negating the
836 * XF86VidModeSetViewPort done in set_fullscreen. This makes the old
837 * center the window hack unnescesarry. Notice that since the XF86VM
838 * extension requests do not go through the regular X output buffer? We
839 * need to make sure that all above requests are processed first.
840 */
841 XSync(_xwin.display, False);
842 _xvidmode_private_set_fullscreen(w, h, &fs_width, &fs_height);
843 #endif
844
845 /* Center the window (if necessary). */
846 if ((fs_width != w) || (fs_height != h))
847 XMoveWindow(_xwin.display, _xwin.window, (fs_width - w) / 2,
848 (fs_height - h) / 2);
849
850 /* Last: center the cursor. */
851 XWarpPointer(_xwin.display, None, _xwin.window, 0, 0, 0, 0, w / 2, h / 2);
852 }
853 else {
854 XSizeHints *hints = XAllocSizeHints();;
855
856 /* Resize managed window. */
857 XResizeWindow(_xwin.display, _xwin.wm_window, w, h);
858
859 /* Set size and position hints for Window Manager. */
860 if (hints) {
861 hints->flags = PMinSize | PMaxSize | PBaseSize;
862 hints->min_width = hints->max_width = hints->base_width = w;
863 hints->min_height = hints->max_height = hints->base_height = h;
864 XSetWMNormalHints(_xwin.display, _xwin.wm_window, hints);
865
866 XFree(hints);
867 }
868
869 /* Map the window managed window. */
870 XMapWindow(_xwin.display, _xwin.wm_window);
871 _xwin_wait_mapped(_xwin.wm_window);
872 }
873
874 /* Create XImage with the size of virtual screen. */
875 if (_xwin_private_create_ximage(vw, vh) != 0) {
876 ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Can not create XImage"));
877 return 0;
878 }
879
880 /* Prepare visual for further use. */
881 _xwin_private_prepare_visual();
882
883 /* Test that frame buffer is fast (can be accessed directly). */
884 _xwin.fast_visual_depth = _xwin_private_fast_visual_depth();
885
886 /* Create screen bitmap from frame buffer. */
887 return _xwin_private_create_screen_bitmap(drv,
888 (unsigned char *)_xwin.ximage->data + _xwin.ximage->xoffset,
889 _xwin.ximage->bytes_per_line);
890 }
891
_xwin_create_screen(GFX_DRIVER * drv,int w,int h,int vw,int vh,int depth,int fullscreen)892 BITMAP *_xwin_create_screen(GFX_DRIVER *drv, int w, int h,
893 int vw, int vh, int depth, int fullscreen)
894 {
895 BITMAP *bmp;
896 XLOCK();
897 bmp = _xwin_private_create_screen(drv, w, h, vw, vh, depth, fullscreen);
898 if (bmp == 0) {
899 _xwin_private_destroy_screen();
900 }
901 XUNLOCK();
902 return bmp;
903 }
904
905
906
907 /* _xwin_destroy_screen:
908 * Destroys screen resources.
909 */
_xwin_private_destroy_screen(void)910 static void _xwin_private_destroy_screen(void)
911 {
912 if (_xwin.buffer_line != 0) {
913 _AL_FREE(_xwin.buffer_line);
914 _xwin.buffer_line = 0;
915 }
916
917 if (_xwin.screen_line != 0) {
918 _AL_FREE(_xwin.screen_line);
919 _xwin.screen_line = 0;
920 }
921
922 if (_xwin.screen_data != 0) {
923 _AL_FREE(_xwin.screen_data);
924 _xwin.screen_data = 0;
925 }
926
927 _xwin_private_destroy_ximage();
928
929 if (_xwin.mouse_grabbed) {
930 XUngrabPointer(_xwin.display, CurrentTime);
931 _xwin.mouse_grabbed = 0;
932 }
933
934 if (_xwin.keyboard_grabbed) {
935 XUngrabKeyboard(_xwin.display, CurrentTime);
936 _xwin.keyboard_grabbed = 0;
937 }
938
939 #ifdef ALLEGRO_XWINDOWS_WITH_XF86VIDMODE
940 _xvidmode_private_unset_fullscreen();
941 #endif
942
943 /* whack color-conversion blitter */
944 if (blitter_func) {
945 _release_colorconv_blitter(blitter_func);
946 blitter_func = NULL;
947 }
948
949 if (_xwin.fs_window != None) {
950 /* Reparent the real window! */
951 XReparentWindow(_xwin.display, _xwin.window, _xwin.wm_window, 0, 0);
952 XUnmapWindow(_xwin.display, _xwin.fs_window);
953 XDestroyWindow(_xwin.display, _xwin.fs_window);
954 _xwin.fs_window = None;
955 }
956 else {
957 XUnmapWindow(_xwin.display, _xwin.wm_window);
958 }
959
960 (*_xwin_window_defaultor)();
961 }
962
_xwin_destroy_screen(void)963 void _xwin_destroy_screen(void)
964 {
965 XLOCK();
966 _xwin_private_destroy_screen();
967 XUNLOCK();
968 }
969
970
971
972 /* _xwin_create_screen_bitmap:
973 * Create screen bitmap from frame buffer.
974 */
_xwin_private_create_screen_bitmap(GFX_DRIVER * drv,unsigned char * frame_buffer,int bytes_per_buffer_line)975 static BITMAP *_xwin_private_create_screen_bitmap(GFX_DRIVER *drv,
976 unsigned char *frame_buffer,
977 int bytes_per_buffer_line)
978 {
979 int line;
980 int bytes_per_screen_line;
981 BITMAP *bmp;
982
983 /* Test that Allegro and X-Windows pixel formats are the same. */
984 _xwin.matching_formats = _xwin_private_matching_formats();
985
986 /* Create mapping tables for color components. */
987 _xwin_private_create_mapping_tables();
988
989 /* Determine how to update frame buffer with screen data. */
990 _xwin_private_select_screen_to_buffer_function();
991
992 /* Determine how to set colors in "hardware". */
993 _xwin_private_select_set_colors_function();
994
995 /* Create line accelerators for screen data. */
996 _xwin.screen_line = _AL_MALLOC_ATOMIC(_xwin.virtual_height * sizeof(unsigned char*));
997 if (_xwin.screen_line == 0) {
998 ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Not enough memory"));
999 return 0;
1000 }
1001
1002 /* If formats match, then use frame buffer as screen data, otherwise malloc. */
1003 if (_xwin.matching_formats) {
1004 bytes_per_screen_line = bytes_per_buffer_line;
1005 _xwin.screen_data = 0;
1006 _xwin.screen_line[0] = frame_buffer;
1007 }
1008 else {
1009 bytes_per_screen_line = _xwin.virtual_width * BYTES_PER_PIXEL(_xwin.screen_depth);
1010 _xwin.screen_data = _AL_MALLOC_ATOMIC(_xwin.virtual_height * bytes_per_screen_line);
1011 if (_xwin.screen_data == 0) {
1012 ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Not enough memory"));
1013 return 0;
1014 }
1015 _xwin.screen_line[0] = _xwin.screen_data;
1016 }
1017
1018 /* Initialize line starts. */
1019 for (line = 1; line < _xwin.virtual_height; line++)
1020 _xwin.screen_line[line] = _xwin.screen_line[line - 1] + bytes_per_screen_line;
1021
1022 /* Create line accelerators for frame buffer. */
1023 if (!_xwin.matching_formats && _xwin.fast_visual_depth) {
1024 _xwin.buffer_line = _AL_MALLOC(_xwin.virtual_height * sizeof(unsigned char*));
1025 if (_xwin.buffer_line == 0) {
1026 ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Not enough memory"));
1027 return 0;
1028 }
1029
1030 _xwin.buffer_line[0] = frame_buffer;
1031 for (line = 1; line < _xwin.virtual_height; line++)
1032 _xwin.buffer_line[line] = _xwin.buffer_line[line - 1] + bytes_per_buffer_line;
1033 }
1034
1035 /* Create bitmap. */
1036 bmp = _make_bitmap(_xwin.virtual_width, _xwin.virtual_height,
1037 (uintptr_t) (_xwin.screen_line[0]), drv,
1038 _xwin.screen_depth, bytes_per_screen_line);
1039 if (bmp == 0) {
1040 ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Not enough memory"));
1041 return 0;
1042 }
1043
1044 /* Fixup bitmap fields. */
1045 drv->w = bmp->cr = _xwin.screen_width;
1046 drv->h = bmp->cb = _xwin.screen_height;
1047 drv->vid_mem = _xwin.virtual_width * _xwin.virtual_height * BYTES_PER_PIXEL(_xwin.screen_depth);
1048
1049 /* Need some magic for updating frame buffer. */
1050 #ifndef ALLEGRO_NO_ASM
1051 bmp->write_bank = _xwin_write_line_asm;
1052 bmp->vtable->unwrite_bank = _xwin_unwrite_line_asm;
1053 #else
1054 bmp->write_bank = _xwin_write_line;
1055 bmp->vtable->unwrite_bank = _xwin_unwrite_line;
1056 #endif
1057
1058 /* Replace entries in vtable with magical wrappers. */
1059 _xwin_replace_vtable(bmp->vtable);
1060
1061 /* The drawing mode may not be ok for direct updates anymore. */
1062 _xwin_drawing_mode();
1063
1064 /* Initialize other fields in _xwin structure. */
1065 _xwin_last_line = -1;
1066 _xwin_in_gfx_call = 0;
1067 _xwin.scroll_x = 0;
1068 _xwin.scroll_y = 0;
1069
1070 /* Setup driver description string. */
1071 _xwin_private_setup_driver_desc(drv);
1072
1073 return bmp;
1074 }
1075
1076
1077
1078 /* _xwin_create_mapping_tables:
1079 * Create mapping between Allegro color component and X-Windows color component.
1080 */
_xwin_private_create_mapping_tables(void)1081 static void _xwin_private_create_mapping_tables(void)
1082 {
1083 if (!_xwin.matching_formats) {
1084 if (_xwin.visual_is_truecolor) {
1085 switch (_xwin.screen_depth) {
1086 case 8:
1087 /* Will be modified later in set_palette. */
1088 _xwin_private_create_mapping(_xwin.rmap, 256, 0, 0);
1089 _xwin_private_create_mapping(_xwin.gmap, 256, 0, 0);
1090 _xwin_private_create_mapping(_xwin.bmap, 256, 0, 0);
1091 break;
1092 case 15:
1093 _xwin_private_create_mapping(_xwin.rmap, 32, _xwin.rsize, _xwin.rshift);
1094 _xwin_private_create_mapping(_xwin.gmap, 32, _xwin.gsize, _xwin.gshift);
1095 _xwin_private_create_mapping(_xwin.bmap, 32, _xwin.bsize, _xwin.bshift);
1096 break;
1097 case 16:
1098 _xwin_private_create_mapping(_xwin.rmap, 32, _xwin.rsize, _xwin.rshift);
1099 _xwin_private_create_mapping(_xwin.gmap, 64, _xwin.gsize, _xwin.gshift);
1100 _xwin_private_create_mapping(_xwin.bmap, 32, _xwin.bsize, _xwin.bshift);
1101 break;
1102 case 24:
1103 case 32:
1104 _xwin_private_create_mapping(_xwin.rmap, 256, _xwin.rsize, _xwin.rshift);
1105 _xwin_private_create_mapping(_xwin.gmap, 256, _xwin.gsize, _xwin.gshift);
1106 _xwin_private_create_mapping(_xwin.bmap, 256, _xwin.bsize, _xwin.bshift);
1107 break;
1108 }
1109 }
1110 else {
1111 int i;
1112
1113 /* Might be modified later in set_palette. */
1114 for (i = 0; i < 256; i++)
1115 _xwin.rmap[i] = _xwin.gmap[i] = _xwin.bmap[i] = 0;
1116 }
1117 }
1118 }
1119
1120
1121
1122 /* _xwin_create_mapping:
1123 * Create mapping between Allegro color component and X-Windows color component.
1124 */
_xwin_private_create_mapping(unsigned long * map,int ssize,int dsize,int dshift)1125 static void _xwin_private_create_mapping(unsigned long *map, int ssize, int dsize, int dshift)
1126 {
1127 int i, smax, dmax;
1128
1129 smax = ssize - 1;
1130 dmax = dsize - 1;
1131 for (i = 0; i < ssize; i++)
1132 map[i] = ((dmax * i) / smax) << dshift;
1133 for (; i < 256; i++)
1134 map[i] = map[i % ssize];
1135 }
1136
1137
1138
1139 /* _xwin_display_is_local:
1140 * Tests that display connection is local.
1141 * (Note: this is duplicated in xdga2.c).
1142 */
_xwin_private_display_is_local(void)1143 static int _xwin_private_display_is_local(void)
1144 {
1145 char *name;
1146
1147 if (_xwin.display == 0)
1148 return 0;
1149
1150 /* Get display name and test for local display. */
1151 name = XDisplayName(0);
1152
1153 return (((name == 0) || (name[0] == ':') || (strncmp(name, "unix:", 5) == 0)) ? 1 : 0);
1154 }
1155
1156
1157
1158 /* _xwin_create_ximage:
1159 * Create XImage for accessing window.
1160 */
_xwin_private_create_ximage(int w,int h)1161 static int _xwin_private_create_ximage(int w, int h)
1162 {
1163 XImage *image = 0; /* I'm mage or I'm old? */
1164
1165 if (_xwin.display == 0)
1166 return -1;
1167
1168 #ifdef ALLEGRO_XWINDOWS_WITH_SHM
1169 if (_xwin_private_display_is_local() && XShmQueryExtension(_xwin.display))
1170 _xwin.use_shm = 1;
1171 else
1172 _xwin.use_shm = 0;
1173 #else
1174 _xwin.use_shm = 0;
1175 #endif
1176
1177 #ifdef ALLEGRO_XWINDOWS_WITH_SHM
1178 if (_xwin.use_shm) {
1179 /* Try to create shared memory XImage. */
1180 image = XShmCreateImage(_xwin.display, _xwin.visual, _xwin.window_depth,
1181 ZPixmap, 0, &_xwin.shminfo, w, h);
1182 do {
1183 if (image != 0) {
1184 /* Create shared memory segment. */
1185 _xwin.shminfo.shmid = shmget(IPC_PRIVATE, image->bytes_per_line * image->height,
1186 IPC_CREAT | 0777);
1187 if (_xwin.shminfo.shmid != -1) {
1188 /* Attach shared memory to our address space. */
1189 _xwin.shminfo.shmaddr = image->data = shmat(_xwin.shminfo.shmid, 0, 0);
1190 if (_xwin.shminfo.shmaddr != (char*) -1) {
1191 _xwin.shminfo.readOnly = True;
1192
1193 /* Attach shared memory to the X-server address space. */
1194 if (XShmAttach(_xwin.display, &_xwin.shminfo)) {
1195 XSync(_xwin.display, False);
1196 break;
1197 }
1198
1199 shmdt(_xwin.shminfo.shmaddr);
1200 }
1201 shmctl(_xwin.shminfo.shmid, IPC_RMID, 0);
1202 }
1203 XDestroyImage(image);
1204 image = 0;
1205 }
1206 _xwin.use_shm = 0;
1207 } while (0);
1208 }
1209 #endif
1210
1211 if (image == 0) {
1212 /* Try to create ordinary XImage. */
1213 #if 0
1214 Pixmap pixmap;
1215
1216 pixmap = XCreatePixmap(_xwin.display, _xwin.window, w, h, _xwin.window_depth);
1217 if (pixmap != None) {
1218 image = XGetImage(_xwin.display, pixmap, 0, 0, w, h, AllPlanes, ZPixmap);
1219 XFreePixmap(_xwin.display, pixmap);
1220 }
1221 #else
1222 image = XCreateImage(_xwin.display, _xwin.visual, _xwin.window_depth,
1223 ZPixmap, 0, 0, w, h, 32, 0);
1224 if (image != 0) {
1225 image->data = _AL_MALLOC_ATOMIC(image->bytes_per_line * image->height);
1226 if (image->data == 0) {
1227 XDestroyImage(image);
1228 image = 0;
1229 }
1230 }
1231 #endif
1232 }
1233
1234 _xwin.ximage = image;
1235
1236 return ((image != 0) ? 0 : -1);
1237 }
1238
1239
1240
1241 /* _xwin_destroy_ximage:
1242 * Destroy XImage.
1243 */
_xwin_private_destroy_ximage(void)1244 static void _xwin_private_destroy_ximage(void)
1245 {
1246 if (_xwin.ximage != 0) {
1247 #ifdef ALLEGRO_XWINDOWS_WITH_SHM
1248 if (_xwin.use_shm) {
1249 XShmDetach(_xwin.display, &_xwin.shminfo);
1250 shmdt(_xwin.shminfo.shmaddr);
1251 shmctl(_xwin.shminfo.shmid, IPC_RMID, 0);
1252 }
1253 #endif
1254 XDestroyImage(_xwin.ximage);
1255 _xwin.ximage = 0;
1256 }
1257 }
1258
1259
1260
1261 /* _xwin_prepare_visual:
1262 * Prepare visual for further use.
1263 */
_xwin_private_prepare_visual(void)1264 static void _xwin_private_prepare_visual(void)
1265 {
1266 int i, r, g, b;
1267 int rmax, gmax, bmax;
1268 unsigned long mask;
1269 XColor color;
1270
1271 if ((_xwin.visual->class == TrueColor)
1272 || (_xwin.visual->class == DirectColor)) {
1273 /* Use TrueColor and DirectColor visuals as truecolor. */
1274
1275 /* Red shift and size. */
1276 for (mask = _xwin.visual->red_mask, i = 0; (mask & 1) != 1; mask >>= 1)
1277 i++;
1278 _xwin.rshift = i;
1279 for (i = 0; mask != 0; mask >>= 1)
1280 i++;
1281 _xwin.rsize = 1 << i;
1282
1283 /* Green shift and size. */
1284 for (mask = _xwin.visual->green_mask, i = 0; (mask & 1) != 1; mask >>= 1)
1285 i++;
1286 _xwin.gshift = i;
1287 for (i = 0; mask != 0; mask >>= 1)
1288 i++;
1289 _xwin.gsize = 1 << i;
1290
1291 /* Blue shift and size. */
1292 for (mask = _xwin.visual->blue_mask, i = 0; (mask & 1) != 1; mask >>= 1)
1293 i++;
1294 _xwin.bshift = i;
1295 for (i = 0; mask != 0; mask >>= 1)
1296 i++;
1297 _xwin.bsize = 1 << i;
1298
1299 /* Convert DirectColor visual into true color visual. */
1300 if (_xwin.visual->class == DirectColor) {
1301 color.flags = DoRed;
1302 rmax = _xwin.rsize - 1;
1303 gmax = _xwin.gsize - 1;
1304 bmax = _xwin.bsize - 1;
1305 for (i = 0; i < _xwin.rsize; i++) {
1306 color.pixel = i << _xwin.rshift;
1307 color.red = ((rmax <= 0) ? 0 : ((i * 65535L) / rmax));
1308 XStoreColor(_xwin.display, _xwin.colormap, &color);
1309 }
1310 color.flags = DoGreen;
1311 for (i = 0; i < _xwin.gsize; i++) {
1312 color.pixel = i << _xwin.gshift;
1313 color.green = ((gmax <= 0) ? 0 : ((i * 65535L) / gmax));
1314 XStoreColor(_xwin.display, _xwin.colormap, &color);
1315 }
1316 color.flags = DoBlue;
1317 for (i = 0; i < _xwin.bsize; i++) {
1318 color.pixel = i << _xwin.bshift;
1319 color.blue = ((bmax <= 0) ? 0 : ((i * 65535L) / bmax));
1320 XStoreColor(_xwin.display, _xwin.colormap, &color);
1321 }
1322 }
1323
1324 _xwin.visual_is_truecolor = 1;
1325 }
1326 else if ((_xwin.visual->class == PseudoColor)
1327 || (_xwin.visual->class == GrayScale)) {
1328 /* Convert read-write palette visual into true color visual. */
1329 b = _xwin.window_depth / 3;
1330 r = (_xwin.window_depth - b) / 2;
1331 g = _xwin.window_depth - r - b;
1332
1333 _xwin.rsize = 1 << r;
1334 _xwin.gsize = 1 << g;
1335 _xwin.bsize = 1 << b;
1336 _xwin.rshift = g + b;
1337 _xwin.gshift = b;
1338 _xwin.bshift = 0;
1339
1340 _xwin.visual_is_truecolor = 1;
1341
1342 rmax = _xwin.rsize - 1;
1343 gmax = _xwin.gsize - 1;
1344 bmax = _xwin.bsize - 1;
1345
1346 color.flags = DoRed | DoGreen | DoBlue;
1347 for (r = 0; r < _xwin.rsize; r++) {
1348 for (g = 0; g < _xwin.gsize; g++) {
1349 for (b = 0; b < _xwin.bsize; b++) {
1350 color.pixel = (r << _xwin.rshift) | (g << _xwin.gshift) | (b << _xwin.bshift);
1351 color.red = ((rmax <= 0) ? 0 : ((r * 65535L) / rmax));
1352 color.green = ((gmax <= 0) ? 0 : ((g * 65535L) / gmax));
1353 color.blue = ((bmax <= 0) ? 0 : ((b * 65535L) / bmax));
1354 XStoreColor(_xwin.display, _xwin.colormap, &color);
1355 }
1356 }
1357 }
1358 }
1359 else {
1360 /* All other visual types are paletted. */
1361 _xwin.rsize = 1;
1362 _xwin.bsize = 1;
1363 _xwin.gsize = 1;
1364 _xwin.rshift = 0;
1365 _xwin.gshift = 0;
1366 _xwin.bshift = 0;
1367
1368 _xwin.visual_is_truecolor = 0;
1369
1370 /* Make fixed palette and create mapping RRRRGGGGBBBB -> palette index. */
1371 for (r = 0; r < 16; r++) {
1372 for (g = 0; g < 16; g++) {
1373 for (b = 0; b < 16; b++) {
1374 color.red = (r * 65535L) / 15;
1375 color.green = (g * 65535L) / 15;
1376 color.blue = (b * 65535L) / 15;
1377 XAllocColor(_xwin.display, _xwin.colormap, &color);
1378 _xwin.cmap[(r << 8) | (g << 4) | b] = color.pixel;
1379 }
1380 }
1381 }
1382 }
1383 }
1384
1385
1386
1387 /* _xwin_matching_formats:
1388 * Find if color formats match.
1389 */
_xwin_private_matching_formats(void)1390 static int _xwin_private_matching_formats(void)
1391 {
1392 if (_xwin.fast_visual_depth == 0)
1393 return 0;
1394
1395 if (_xwin.screen_depth == 8) {
1396 /* For matching 8 bpp modes visual must be PseudoColor or GrayScale. */
1397 if (((_xwin.visual->class != PseudoColor)
1398 && (_xwin.visual->class != GrayScale))
1399 || (_xwin.fast_visual_depth != 8)
1400 || (_xwin.window_depth != 8))
1401 return 0;
1402 }
1403 else if ((_xwin.visual->class != TrueColor)
1404 && (_xwin.visual->class != DirectColor)) {
1405 /* For matching true color modes visual must be TrueColor or DirectColor. */
1406 return 0;
1407 }
1408 else if (_xwin.screen_depth == 15) {
1409 if ((_xwin.fast_visual_depth != 16)
1410 || (_xwin.rsize != 32) || (_xwin.gsize != 32) || (_xwin.bsize != 32)
1411 || ((_xwin.rshift != 0) && (_xwin.rshift != 10))
1412 || ((_xwin.bshift != 0) && (_xwin.bshift != 10))
1413 || (_xwin.gshift != 5))
1414 return 0;
1415 _rgb_r_shift_15 = _xwin.rshift;
1416 _rgb_g_shift_15 = _xwin.gshift;
1417 _rgb_b_shift_15 = _xwin.bshift;
1418 }
1419 else if (_xwin.screen_depth == 16) {
1420 if ((_xwin.fast_visual_depth != 16)
1421 || (_xwin.rsize != 32) || (_xwin.gsize != 64) || (_xwin.bsize != 32)
1422 || ((_xwin.rshift != 0) && (_xwin.rshift != 11))
1423 || ((_xwin.bshift != 0) && (_xwin.bshift != 11))
1424 || (_xwin.gshift != 5))
1425 return 0;
1426 _rgb_r_shift_16 = _xwin.rshift;
1427 _rgb_g_shift_16 = _xwin.gshift;
1428 _rgb_b_shift_16 = _xwin.bshift;
1429 }
1430 else if (_xwin.screen_depth == 24){
1431 if ((_xwin.fast_visual_depth != 24)
1432 || (_xwin.rsize != 256) || (_xwin.gsize != 256) || (_xwin.bsize != 256)
1433 || ((_xwin.rshift != 0) && (_xwin.rshift != 16))
1434 || ((_xwin.bshift != 0) && (_xwin.bshift != 16))
1435 || (_xwin.gshift != 8))
1436 return 0;
1437 _rgb_r_shift_24 = _xwin.rshift;
1438 _rgb_g_shift_24 = _xwin.gshift;
1439 _rgb_b_shift_24 = _xwin.bshift;
1440 }
1441 else if (_xwin.screen_depth == 32) {
1442 if ((_xwin.fast_visual_depth != 32)
1443 || (_xwin.rsize != 256) || (_xwin.gsize != 256) || (_xwin.bsize != 256)
1444 || ((_xwin.rshift != 0) && (_xwin.rshift != 16))
1445 || ((_xwin.bshift != 0) && (_xwin.bshift != 16))
1446 || (_xwin.gshift != 8))
1447 return 0;
1448 _rgb_r_shift_32 = _xwin.rshift;
1449 _rgb_g_shift_32 = _xwin.gshift;
1450 _rgb_b_shift_32 = _xwin.bshift;
1451 }
1452 else {
1453 /* How did you get in here? */
1454 return 0;
1455 }
1456
1457 return 1;
1458 }
1459
1460
1461
1462 /* _xwin_private_hack_shifts:
1463 * Make Allegro draw in BGR format if X uses BGR instead of RGB.
1464 */
_xwin_private_hack_shifts(void)1465 static void _xwin_private_hack_shifts(void)
1466 {
1467 switch(_xwin.screen_depth) {
1468 case 8:
1469 use_bgr_palette_hack = TRUE;
1470 break;
1471 case 15:
1472 _rgb_r_shift_15 = 10;
1473 _rgb_g_shift_15 = 5;
1474 _rgb_b_shift_15 = 0;
1475 break;
1476 case 16:
1477 _rgb_r_shift_16 = 11;
1478 _rgb_g_shift_16 = 5;
1479 _rgb_b_shift_16 = 0;
1480 break;
1481 case 24:
1482 _rgb_r_shift_24 = 16;
1483 _rgb_g_shift_24 = 8;
1484 _rgb_b_shift_24 = 0;
1485 break;
1486 case 32:
1487 _rgb_r_shift_32 = 16;
1488 _rgb_g_shift_32 = 8;
1489 _rgb_b_shift_32 = 0;
1490 break;
1491 }
1492 }
1493
1494
1495
1496 /* _xwin_private_colorconv_usable:
1497 * Find out if generic color conversion blitter can be used.
1498 */
_xwin_private_colorconv_usable(void)1499 static int _xwin_private_colorconv_usable(void)
1500 {
1501 use_bgr_palette_hack = FALSE; /* make sure this is initialized */
1502
1503 if (_xwin.fast_visual_depth == 0) {
1504 return 0;
1505 }
1506 else if (_xwin.fast_visual_depth == 8) {
1507 #if 0
1508 /* TODO: check this out later. */
1509
1510 /* For usable 8 bpp modes visual must be PseudoColor or GrayScale. */
1511 if ((_xwin.visual->class == PseudoColor)
1512 || (_xwin.visual->class == GrayScale))
1513 return 1;
1514 #else
1515 return 0;
1516 #endif
1517 }
1518 else if ((_xwin.visual->class != TrueColor)
1519 && (_xwin.visual->class != DirectColor)) {
1520 /* For usable true color modes visual must be TrueColor or DirectColor. */
1521 return 0;
1522 }
1523 else if ((_xwin.fast_visual_depth == 16)
1524 && (_xwin.rsize == 32) && ((_xwin.gsize == 32) || (_xwin.gsize == 64)) && (_xwin.bsize == 32)
1525 && ((_xwin.rshift == 0) || (_xwin.rshift == 10) || (_xwin.rshift == 11))
1526 && ((_xwin.bshift == 0) || (_xwin.bshift == 10) || (_xwin.bshift == 11))
1527 && (_xwin.gshift == 5)) {
1528 if (_xwin.bshift == 0)
1529 _xwin_private_hack_shifts();
1530 return 1;
1531 }
1532 else if ((_xwin.fast_visual_depth == 24)
1533 && (_xwin.rsize == 256) && (_xwin.gsize == 256) && (_xwin.bsize == 256)
1534 && ((_xwin.rshift == 0) || (_xwin.rshift == 16))
1535 && ((_xwin.bshift == 0) || (_xwin.bshift == 16))
1536 && (_xwin.gshift == 8)) {
1537 if (_xwin.bshift == 0)
1538 _xwin_private_hack_shifts();
1539 return 1;
1540 }
1541 else if ((_xwin.fast_visual_depth == 32)
1542 && (_xwin.rsize == 256) && (_xwin.gsize == 256) && (_xwin.bsize == 256)
1543 && ((_xwin.rshift == 0) || (_xwin.rshift == 16))
1544 && ((_xwin.bshift == 0) || (_xwin.bshift == 16))
1545 && (_xwin.gshift == 8)) {
1546 if (_xwin.bshift == 0)
1547 _xwin_private_hack_shifts();
1548 return 1;
1549 }
1550
1551 /* Too bad... Muahahaha! */
1552 return 0;
1553 }
1554
1555
1556
1557 /* _xwin_fast_visual_depth:
1558 * Find which depth is fast (when XImage can be accessed directly).
1559 */
_xwin_private_fast_visual_depth(void)1560 static int _xwin_private_fast_visual_depth(void)
1561 {
1562 int ok, x, sizex;
1563 int test_depth;
1564 uint8_t *p8;
1565 uint16_t *p16;
1566 uint32_t *p32;
1567
1568 if (_xwin.ximage == 0)
1569 return 0;
1570
1571 /* Use first line of XImage for test. */
1572 p8 = (uint8_t *) _xwin.ximage->data + _xwin.ximage->xoffset;
1573 p16 = (uint16_t*) p8;
1574 p32 = (uint32_t*) p8;
1575
1576 sizex = _xwin.ximage->bytes_per_line - _xwin.ximage->xoffset;
1577
1578 if ((_xwin.window_depth < 1) || (_xwin.window_depth > 32)) {
1579 return 0;
1580 }
1581 else if (_xwin.window_depth > 16) {
1582 test_depth = 32;
1583 sizex /= sizeof (uint32_t);
1584 }
1585 else if (_xwin.window_depth > 8) {
1586 test_depth = 16;
1587 sizex /= sizeof (uint16_t);
1588 }
1589 else {
1590 test_depth = 8;
1591 }
1592 if (sizex > _xwin.ximage->width)
1593 sizex = _xwin.ximage->width;
1594
1595 /* Need at least two pixels wide line for test. */
1596 if (sizex < 2)
1597 return 0;
1598
1599 ok = 1;
1600 for (x = 0; x < sizex; x++) {
1601 int bit;
1602
1603 for (bit = -1; bit < _xwin.window_depth; bit++) {
1604 unsigned long color = ((bit < 0) ? 0 : ((unsigned long) 1 << bit));
1605
1606 /* Write color through XImage API. */
1607 XPutPixel(_xwin.ximage, x, 0, color);
1608
1609 /* Read color with direct access. */
1610 switch (test_depth) {
1611 case 8:
1612 if (p8[x] != color)
1613 ok = 0;
1614 break;
1615 case 16:
1616 if (p16[x] != color)
1617 ok = 0;
1618 break;
1619 case 32:
1620 if (p32[x] != color)
1621 ok = 0;
1622 break;
1623 default:
1624 ok = 0;
1625 break;
1626 }
1627 XPutPixel(_xwin.ximage, x, 0, 0);
1628
1629 if (!ok)
1630 return 0;
1631 }
1632 }
1633
1634 return test_depth;
1635 }
1636
1637
1638
1639 /* _xwin_enable_hardware_cursor:
1640 * enable the hardware cursor; this disables the mouse mickey warping hack
1641 */
_xwin_enable_hardware_cursor(int mode)1642 void _xwin_enable_hardware_cursor(int mode)
1643 {
1644 #ifdef ALLEGRO_XWINDOWS_WITH_XCURSOR
1645 if (_xwin.support_argb_cursor) {
1646 _xwin.hw_cursor_ok = mode;
1647 }
1648 else
1649 #endif
1650 {
1651 _xwin.hw_cursor_ok = 0;
1652 }
1653
1654 /* Switch to non-warped mode */
1655 if (_xwin.hw_cursor_ok) {
1656 _xwin.mouse_warped = 0;
1657 /* Move X-cursor to Allegro cursor. */
1658 XLOCK();
1659 XWarpPointer(_xwin.display, _xwin.window, _xwin.window,
1660 0, 0, _xwin.window_width, _xwin.window_height,
1661 _mouse_x - (_xwin_mouse_extended_range ? _xwin.scroll_x : 0),
1662 _mouse_y - (_xwin_mouse_extended_range ? _xwin.scroll_y : 0));
1663 XUNLOCK();
1664 }
1665 }
1666
1667
1668
1669 #ifdef ALLEGRO_XWINDOWS_WITH_XCURSOR
1670
1671 /* _xwin_set_mouse_sprite:
1672 * Set custom X cursor (if supported).
1673 */
_xwin_set_mouse_sprite(struct BITMAP * sprite,int xfocus,int yfocus)1674 int _xwin_set_mouse_sprite(struct BITMAP *sprite, int xfocus, int yfocus)
1675 {
1676 #define GET_PIXEL_DATA(depth, getpix) \
1677 case depth: \
1678 c = 0; \
1679 for (iy = 0; iy < sprite->h; iy++) { \
1680 for(ix = 0; ix < sprite->w; ix++) { \
1681 col = getpix(sprite, ix, iy); \
1682 if (col == (MASK_COLOR_ ## depth)) { \
1683 r = g = b = a = 0; \
1684 } \
1685 else { \
1686 r = getr ## depth(col); \
1687 g = getg ## depth(col); \
1688 b = getb ## depth(col); \
1689 a = 255; \
1690 } \
1691 _xwin.xcursor_image->pixels[c++] = \
1692 (a<<24)|(r<<16)|(g<<8)|(b); \
1693 } \
1694 }
1695
1696 if (!_xwin.support_argb_cursor) {
1697 return -1;
1698 }
1699
1700 if (_xwin.xcursor_image != None) {
1701 XLOCK();
1702 XcursorImageDestroy(_xwin.xcursor_image);
1703 XUNLOCK();
1704 _xwin.xcursor_image = None;
1705 }
1706
1707 if (sprite) {
1708 int ix, iy;
1709 int r = 0, g = 0, b = 0, a = 0, c, col;
1710
1711 _xwin.xcursor_image = XcursorImageCreate(sprite->w, sprite->h);
1712 if (_xwin.xcursor_image == None) {
1713 return -1;
1714 }
1715
1716 switch (bitmap_color_depth(sprite)) {
1717 GET_PIXEL_DATA(8, _getpixel)
1718 break;
1719
1720 GET_PIXEL_DATA(15, _getpixel15)
1721 break;
1722
1723 GET_PIXEL_DATA(16, _getpixel16)
1724 break;
1725
1726 GET_PIXEL_DATA(24, _getpixel24)
1727 break;
1728
1729 GET_PIXEL_DATA(32, _getpixel32)
1730 break;
1731 } /* End switch */
1732
1733 _xwin.xcursor_image->xhot = xfocus;
1734 _xwin.xcursor_image->yhot = yfocus;
1735
1736 return 0;
1737 }
1738
1739 return -1;
1740
1741 #undef GET_PIXEL_DATA
1742 }
1743
1744
1745
1746 /* _xwin_show_mouse:
1747 * Show the custom X cursor (if supported)
1748 */
_xwin_show_mouse(struct BITMAP * bmp,int x,int y)1749 int _xwin_show_mouse(struct BITMAP *bmp, int x, int y)
1750 {
1751 /* Only draw on screen */
1752 if (!is_same_bitmap(bmp, screen))
1753 return -1;
1754
1755 if (!_xwin.support_argb_cursor) {
1756 return -1;
1757 }
1758
1759 if (_xwin.xcursor_image == None) {
1760 return -1;
1761 }
1762
1763 /* Hardware cursor is disabled (mickey mode) */
1764 if (!_xwin.hw_cursor_ok) {
1765 return -1;
1766 }
1767
1768 XLOCK();
1769 if (_xwin.cursor != None) {
1770 XUndefineCursor(_xwin.display, _xwin.window);
1771 XFreeCursor(_xwin.display, _xwin.cursor);
1772 }
1773
1774 _xwin.cursor = XcursorImageLoadCursor(_xwin.display, _xwin.xcursor_image);
1775 XDefineCursor(_xwin.display, _xwin.window, _xwin.cursor);
1776
1777 XUNLOCK();
1778 return 0;
1779 }
1780
1781
1782
1783 /* _xwin_hide_mouse:
1784 * Hide the custom X cursor (if supported)
1785 */
_xwin_hide_mouse(void)1786 void _xwin_hide_mouse(void)
1787 {
1788 if (_xwin.support_argb_cursor) {
1789 XLOCK();
1790 _xwin_hide_x_mouse();
1791 XUNLOCK();
1792 }
1793 return;
1794 }
1795
1796
1797
1798 /* _xwin_move_mouse:
1799 * Get mouse move notification. Not that we need it...
1800 */
_xwin_move_mouse(int x,int y)1801 void _xwin_move_mouse(int x, int y)
1802 {
1803 }
1804
1805 #endif /* ALLEGRO_XWINDOWS_WITH_XCURSOR */
1806
1807
1808
1809 /*
1810 * Functions for copying screen data to frame buffer.
1811 */
_xwin_private_fast_colorconv(int sx,int sy,int sw,int sh)1812 static void _xwin_private_fast_colorconv(int sx, int sy, int sw, int sh)
1813 {
1814 GRAPHICS_RECT src_rect, dest_rect;
1815
1816 /* set up source and destination rectangles */
1817 src_rect.height = sh;
1818 src_rect.width = sw;
1819 src_rect.pitch = _xwin.screen_line[1] - _xwin.screen_line[0];
1820 src_rect.data = _xwin.screen_line[sy] + sx * BYTES_PER_PIXEL(_xwin.screen_depth);
1821
1822 dest_rect.height = sh;
1823 dest_rect.width = sw;
1824 dest_rect.pitch = _xwin.buffer_line[1] - _xwin.buffer_line[0];
1825 dest_rect.data = _xwin.buffer_line[sy] + sx * BYTES_PER_PIXEL(_xwin.fast_visual_depth);
1826
1827 /* Update frame buffer with screen contents. */
1828 ASSERT(blitter_func);
1829 blitter_func(&src_rect, &dest_rect);
1830 }
1831
1832 #ifdef ALLEGRO_LITTLE_ENDIAN
1833 #define DEFAULT_RGB_R_POS_24 (DEFAULT_RGB_R_SHIFT_24/8)
1834 #define DEFAULT_RGB_G_POS_24 (DEFAULT_RGB_G_SHIFT_24/8)
1835 #define DEFAULT_RGB_B_POS_24 (DEFAULT_RGB_B_SHIFT_24/8)
1836 #elif defined ALLEGRO_BIG_ENDIAN
1837 #define DEFAULT_RGB_R_POS_24 (2-DEFAULT_RGB_R_SHIFT_24/8)
1838 #define DEFAULT_RGB_G_POS_24 (2-DEFAULT_RGB_G_SHIFT_24/8)
1839 #define DEFAULT_RGB_B_POS_24 (2-DEFAULT_RGB_B_SHIFT_24/8)
1840 #else
1841 #error endianess not defined
1842 #endif
1843
1844 #define MAKE_FAST_TRUECOLOR(name,stype,dtype,rshift,gshift,bshift,rmask,gmask,bmask) \
1845 static void name(int sx, int sy, int sw, int sh) \
1846 { \
1847 int y, x; \
1848 for (y = sy; y < (sy + sh); y++) { \
1849 stype *s = (stype*) (_xwin.screen_line[y]) + sx; \
1850 dtype *d = (dtype*) (_xwin.buffer_line[y]) + sx; \
1851 for (x = sw - 1; x >= 0; x--) { \
1852 unsigned long color = *s++; \
1853 *d++ = (_xwin.rmap[(color >> (rshift)) & (rmask)] \
1854 | _xwin.gmap[(color >> (gshift)) & (gmask)] \
1855 | _xwin.bmap[(color >> (bshift)) & (bmask)]); \
1856 } \
1857 } \
1858 }
1859
1860 #define MAKE_FAST_TRUECOLOR24(name,dtype) \
1861 static void name(int sx, int sy, int sw, int sh) \
1862 { \
1863 int x, y; \
1864 for (y = sy; y < (sy + sh); y++) { \
1865 unsigned char *s = _xwin.screen_line[y] + 3 * sx; \
1866 dtype *d = (dtype*) (_xwin.buffer_line[y]) + sx; \
1867 for (x = sw - 1; x >= 0; s += 3, x--) { \
1868 *d++ = (_xwin.rmap[s[DEFAULT_RGB_R_POS_24]] \
1869 | _xwin.gmap[s[DEFAULT_RGB_G_POS_24]] \
1870 | _xwin.bmap[s[DEFAULT_RGB_B_POS_24]]); \
1871 } \
1872 } \
1873 }
1874
1875 #define MAKE_FAST_TRUECOLOR_TO24(name,stype,rshift,gshift,bshift,rmask,gmask,bmask) \
1876 static void name(int sx, int sy, int sw, int sh) \
1877 { \
1878 int x, y; \
1879 for (y = sy; y < (sy + sh); y++) { \
1880 stype *s = (stype*) (_xwin.screen_line[y]) + sx; \
1881 unsigned char *d = _xwin.buffer_line[y] + 3 * sx; \
1882 for (x = sw - 1; x >= 0; d += 3, x--) { \
1883 unsigned long color = *s++; \
1884 color = (_xwin.rmap[(color >> (rshift)) & (rmask)] \
1885 | _xwin.gmap[(color >> (gshift)) & (gmask)] \
1886 | _xwin.bmap[(color >> (bshift)) & (bmask)]); \
1887 WRITE3BYTES(d, color); \
1888 } \
1889 } \
1890 }
1891
1892 #define MAKE_FAST_TRUECOLOR24_TO24(name) \
1893 static void name(int sx, int sy, int sw, int sh) \
1894 { \
1895 int x, y; \
1896 for (y = sy; y < (sy + sh); y++) { \
1897 unsigned char *s = _xwin.screen_line[y] + 3 * sx; \
1898 unsigned char *d = _xwin.buffer_line[y] + 3 * sx; \
1899 for (x = sw - 1; x >= 0; s += 3, d += 3, x--) { \
1900 unsigned long color = _xwin.rmap[s[DEFAULT_RGB_R_POS_24]] \
1901 | _xwin.gmap[s[DEFAULT_RGB_G_POS_24]] \
1902 | _xwin.bmap[s[DEFAULT_RGB_B_POS_24]]; \
1903 WRITE3BYTES(d, color); \
1904 } \
1905 } \
1906 }
1907
1908 MAKE_FAST_TRUECOLOR(_xwin_private_fast_truecolor_8_to_8,
1909 unsigned char, unsigned char, 0, 0, 0, 0xFF, 0xFF, 0xFF);
1910 MAKE_FAST_TRUECOLOR(_xwin_private_fast_truecolor_8_to_16,
1911 unsigned char, unsigned short, 0, 0, 0, 0xFF, 0xFF, 0xFF);
1912 MAKE_FAST_TRUECOLOR(_xwin_private_fast_truecolor_8_to_32,
1913 unsigned char, uint32_t, 0, 0, 0, 0xFF, 0xFF, 0xFF);
1914
1915 MAKE_FAST_TRUECOLOR(_xwin_private_fast_truecolor_15_to_8,
1916 unsigned short, unsigned char, 0, 5, 10, 0x1F, 0x1F, 0x1F);
1917 MAKE_FAST_TRUECOLOR(_xwin_private_fast_truecolor_15_to_16,
1918 unsigned short, unsigned short, 0, 5, 10, 0x1F, 0x1F, 0x1F);
1919 MAKE_FAST_TRUECOLOR(_xwin_private_fast_truecolor_15_to_32,
1920 unsigned short, uint32_t, 0, 5, 10, 0x1F, 0x1F, 0x1F);
1921
1922 MAKE_FAST_TRUECOLOR(_xwin_private_fast_truecolor_16_to_8,
1923 unsigned short, unsigned char, 0, 5, 11, 0x1F, 0x3F, 0x1F);
1924 MAKE_FAST_TRUECOLOR(_xwin_private_fast_truecolor_16_to_16,
1925 unsigned short, unsigned short, 0, 5, 11, 0x1F, 0x3F, 0x1F);
1926 MAKE_FAST_TRUECOLOR(_xwin_private_fast_truecolor_16_to_32,
1927 unsigned short, uint32_t, 0, 5, 11, 0x1F, 0x3F, 0x1F);
1928
1929 MAKE_FAST_TRUECOLOR(_xwin_private_fast_truecolor_32_to_8,
1930 uint32_t, unsigned char, 0, 8, 16, 0xFF, 0xFF, 0xFF);
1931 MAKE_FAST_TRUECOLOR(_xwin_private_fast_truecolor_32_to_16,
1932 uint32_t, unsigned short, 0, 8, 16, 0xFF, 0xFF, 0xFF);
1933 MAKE_FAST_TRUECOLOR(_xwin_private_fast_truecolor_32_to_32,
1934 uint32_t, uint32_t, 0, 8, 16, 0xFF, 0xFF, 0xFF);
1935
1936 MAKE_FAST_TRUECOLOR24(_xwin_private_fast_truecolor_24_to_8,
1937 unsigned char);
1938 MAKE_FAST_TRUECOLOR24(_xwin_private_fast_truecolor_24_to_16,
1939 unsigned short);
1940 MAKE_FAST_TRUECOLOR24(_xwin_private_fast_truecolor_24_to_32,
1941 uint32_t);
1942
1943 MAKE_FAST_TRUECOLOR_TO24(_xwin_private_fast_truecolor_8_to_24,
1944 unsigned char, 0, 0, 0, 0xFF, 0xFF, 0xFF);
1945 MAKE_FAST_TRUECOLOR_TO24(_xwin_private_fast_truecolor_15_to_24,
1946 unsigned short, 0, 5, 10, 0x1F, 0x1F, 0x1F);
1947 MAKE_FAST_TRUECOLOR_TO24(_xwin_private_fast_truecolor_16_to_24,
1948 unsigned short, 0, 5, 11, 0x1F, 0x3F, 0x1F);
1949 MAKE_FAST_TRUECOLOR_TO24(_xwin_private_fast_truecolor_32_to_24,
1950 uint32_t, 0, 8, 16, 0xFF, 0xFF, 0xFF);
1951
1952 MAKE_FAST_TRUECOLOR24_TO24(_xwin_private_fast_truecolor_24_to_24);
1953
1954 #define MAKE_FAST_PALETTE8(name,dtype) \
1955 static void name(int sx, int sy, int sw, int sh) \
1956 { \
1957 int x, y; \
1958 for (y = sy; y < (sy + sh); y++) { \
1959 unsigned char *s = _xwin.screen_line[y] + sx; \
1960 dtype *d = (dtype*) (_xwin.buffer_line[y]) + sx; \
1961 for (x = sw - 1; x >= 0; x--) { \
1962 unsigned long color = *s++; \
1963 *d++ = _xwin.cmap[(_xwin.rmap[color] \
1964 | _xwin.gmap[color] \
1965 | _xwin.bmap[color])]; \
1966 } \
1967 } \
1968 }
1969
1970 #define MAKE_FAST_PALETTE(name,stype,dtype,rshift,gshift,bshift) \
1971 static void name(int sx, int sy, int sw, int sh) \
1972 { \
1973 int x, y; \
1974 for (y = sy; y < (sy + sh); y++) { \
1975 stype *s = (stype*) (_xwin.screen_line[y]) + sx; \
1976 dtype *d = (dtype*) (_xwin.buffer_line[y]) + sx; \
1977 for (x = sw - 1; x >= 0; x--) { \
1978 unsigned long color = *s++; \
1979 *d++ = _xwin.cmap[((((color >> (rshift)) & 0x0F) << 8) \
1980 | (((color >> (gshift)) & 0x0F) << 4) \
1981 | ((color >> (bshift)) & 0x0F))]; \
1982 } \
1983 } \
1984 }
1985
1986 #define MAKE_FAST_PALETTE24(name,dtype) \
1987 static void name(int sx, int sy, int sw, int sh) \
1988 { \
1989 int x, y; \
1990 for (y = sy; y < (sy + sh); y++) { \
1991 unsigned char *s = _xwin.screen_line[y] + 3 * sx; \
1992 dtype *d = (dtype*) (_xwin.buffer_line[y]) + sx; \
1993 for (x = sw - 1; x >= 0; s += 3, x--) { \
1994 *d++ = _xwin.cmap[((((unsigned long) s[DEFAULT_RGB_R_POS_24] << 4) & 0xF00) \
1995 | ((unsigned long) s[DEFAULT_RGB_G_POS_24] & 0xF0) \
1996 | (((unsigned long) s[DEFAULT_RGB_B_POS_24] >> 4) & 0x0F))];\
1997 } \
1998 } \
1999 }
2000
2001 MAKE_FAST_PALETTE8(_xwin_private_fast_palette_8_to_8,
2002 unsigned char);
2003 MAKE_FAST_PALETTE8(_xwin_private_fast_palette_8_to_16,
2004 unsigned short);
2005 MAKE_FAST_PALETTE8(_xwin_private_fast_palette_8_to_32,
2006 uint32_t);
2007
2008 MAKE_FAST_PALETTE(_xwin_private_fast_palette_15_to_8,
2009 unsigned short, unsigned char, 1, 6, 11);
2010 MAKE_FAST_PALETTE(_xwin_private_fast_palette_15_to_16,
2011 unsigned short, unsigned short, 1, 6, 11);
2012 MAKE_FAST_PALETTE(_xwin_private_fast_palette_15_to_32,
2013 unsigned short, uint32_t, 1, 6, 11);
2014
2015 MAKE_FAST_PALETTE(_xwin_private_fast_palette_16_to_8,
2016 unsigned short, unsigned char, 1, 7, 12);
2017 MAKE_FAST_PALETTE(_xwin_private_fast_palette_16_to_16,
2018 unsigned short, unsigned short, 1, 7, 12);
2019 MAKE_FAST_PALETTE(_xwin_private_fast_palette_16_to_32,
2020 unsigned short, uint32_t, 1, 7, 12);
2021
2022 MAKE_FAST_PALETTE(_xwin_private_fast_palette_32_to_8,
2023 uint32_t, unsigned char, 4, 12, 20);
2024 MAKE_FAST_PALETTE(_xwin_private_fast_palette_32_to_16,
2025 uint32_t, unsigned short, 4, 12, 20);
2026 MAKE_FAST_PALETTE(_xwin_private_fast_palette_32_to_32,
2027 uint32_t, uint32_t, 4, 12, 20);
2028
2029 MAKE_FAST_PALETTE24(_xwin_private_fast_palette_24_to_8,
2030 unsigned char);
2031 MAKE_FAST_PALETTE24(_xwin_private_fast_palette_24_to_16,
2032 unsigned short);
2033 MAKE_FAST_PALETTE24(_xwin_private_fast_palette_24_to_32,
2034 uint32_t);
2035
2036 #define MAKE_SLOW_TRUECOLOR(name,stype,rshift,gshift,bshift,rmask,gmask,bmask) \
2037 static void name(int sx, int sy, int sw, int sh) \
2038 { \
2039 int x, y; \
2040 for (y = sy; y < (sy + sh); y++) { \
2041 stype *s = (stype*) (_xwin.screen_line[y]) + sx; \
2042 for (x = sx; x < (sx + sw); x++) { \
2043 unsigned long color = *s++; \
2044 XPutPixel (_xwin.ximage, x, y, \
2045 (_xwin.rmap[(color >> (rshift)) & (rmask)] \
2046 | _xwin.gmap[(color >> (gshift)) & (gmask)] \
2047 | _xwin.bmap[(color >> (bshift)) & (bmask)])); \
2048 } \
2049 } \
2050 }
2051
2052 #define MAKE_SLOW_TRUECOLOR24(name) \
2053 static void name(int sx, int sy, int sw, int sh) \
2054 { \
2055 int x, y; \
2056 for (y = sy; y < (sy + sh); y++) { \
2057 unsigned char *s = _xwin.screen_line[y] + 3 * sx; \
2058 for (x = sx; x < (sx + sw); s += 3, x++) { \
2059 XPutPixel(_xwin.ximage, x, y, \
2060 (_xwin.rmap[s[DEFAULT_RGB_R_POS_24]] \
2061 | _xwin.gmap[s[DEFAULT_RGB_G_POS_24]] \
2062 | _xwin.bmap[s[DEFAULT_RGB_B_POS_24]])); \
2063 } \
2064 } \
2065 }
2066
2067 MAKE_SLOW_TRUECOLOR(_xwin_private_slow_truecolor_8, unsigned char, 0, 0, 0, 0xFF, 0xFF, 0xFF);
2068 MAKE_SLOW_TRUECOLOR(_xwin_private_slow_truecolor_15, unsigned short, 0, 5, 10, 0x1F, 0x1F, 0x1F);
2069 MAKE_SLOW_TRUECOLOR(_xwin_private_slow_truecolor_16, unsigned short, 0, 5, 11, 0x1F, 0x3F, 0x1F);
2070 MAKE_SLOW_TRUECOLOR(_xwin_private_slow_truecolor_32, uint32_t, 0, 8, 16, 0xFF, 0xFF, 0xFF);
2071 MAKE_SLOW_TRUECOLOR24(_xwin_private_slow_truecolor_24);
2072
2073 #define MAKE_SLOW_PALETTE8(name) \
2074 static void name(int sx, int sy, int sw, int sh) \
2075 { \
2076 int x, y; \
2077 for (y = sy; y < (sy + sh); y++) { \
2078 unsigned char *s = _xwin.screen_line[y] + sx; \
2079 for (x = sx; x < (sx + sw); x++) { \
2080 unsigned long color = *s++; \
2081 XPutPixel(_xwin.ximage, x, y, \
2082 _xwin.cmap[(_xwin.rmap[color] \
2083 | _xwin.gmap[color] \
2084 | _xwin.bmap[color])]); \
2085 } \
2086 } \
2087 }
2088
2089 #define MAKE_SLOW_PALETTE(name,stype,rshift,gshift,bshift) \
2090 static void name(int sx, int sy, int sw, int sh) \
2091 { \
2092 int x, y; \
2093 for (y = sy; y < (sy + sh); y++) { \
2094 stype *s = (stype*) (_xwin.screen_line[y]) + sx; \
2095 for (x = sx; x < (sx + sw); x++) { \
2096 unsigned long color = *s++; \
2097 XPutPixel(_xwin.ximage, x, y, \
2098 _xwin.cmap[((((color >> (rshift)) & 0x0F) << 8) \
2099 | (((color >> (gshift)) & 0x0F) << 4) \
2100 | ((color >> (bshift)) & 0x0F))]); \
2101 } \
2102 } \
2103 }
2104
2105 #define MAKE_SLOW_PALETTE24(name) \
2106 static void name(int sx, int sy, int sw, int sh) \
2107 { \
2108 int x, y; \
2109 for (y = sy; y < (sy + sh); y++) { \
2110 unsigned char *s = _xwin.screen_line[y] + 3 * sx; \
2111 for (x = sx; x < (sx + sw); s += 3, x++) { \
2112 XPutPixel(_xwin.ximage, x, y, \
2113 _xwin.cmap[((((unsigned long) s[DEFAULT_RGB_R_POS_24] << 4) & 0xF00) \
2114 | ((unsigned long) s[DEFAULT_RGB_G_POS_24] & 0xF0) \
2115 | (((unsigned long) s[DEFAULT_RGB_B_POS_24] >> 4) & 0x0F))]); \
2116 } \
2117 } \
2118 }
2119
2120 MAKE_SLOW_PALETTE8(_xwin_private_slow_palette_8);
2121 MAKE_SLOW_PALETTE(_xwin_private_slow_palette_15, unsigned short, 1, 6, 11);
2122 MAKE_SLOW_PALETTE(_xwin_private_slow_palette_16, unsigned short, 1, 7, 12);
2123 MAKE_SLOW_PALETTE(_xwin_private_slow_palette_32, uint32_t, 4, 12, 20);
2124 MAKE_SLOW_PALETTE24(_xwin_private_slow_palette_24);
2125
2126 /*
2127 * Functions for setting "hardware" colors in 8bpp modes.
2128 */
_xwin_private_set_matching_colors(AL_CONST PALETTE p,int from,int to)2129 static void _xwin_private_set_matching_colors(AL_CONST PALETTE p, int from, int to)
2130 {
2131 int i;
2132 static XColor color[256];
2133
2134 for (i = from; i <= to; i++) {
2135 color[i].flags = DoRed | DoGreen | DoBlue;
2136 color[i].pixel = i;
2137 color[i].red = ((p[i].r & 0x3F) * 65535L) / 0x3F;
2138 color[i].green = ((p[i].g & 0x3F) * 65535L) / 0x3F;
2139 color[i].blue = ((p[i].b & 0x3F) * 65535L) / 0x3F;
2140 }
2141 XStoreColors(_xwin.display, _xwin.colormap, color + from, to - from + 1);
2142 }
2143
_xwin_private_set_truecolor_colors(AL_CONST PALETTE p,int from,int to)2144 static void _xwin_private_set_truecolor_colors(AL_CONST PALETTE p, int from, int to)
2145 {
2146 int i, rmax, gmax, bmax;
2147
2148 rmax = _xwin.rsize - 1;
2149 gmax = _xwin.gsize - 1;
2150 bmax = _xwin.bsize - 1;
2151 for (i = from; i <= to; i++) {
2152 _xwin.rmap[i] = (((p[i].r & 0x3F) * rmax) / 0x3F) << _xwin.rshift;
2153 _xwin.gmap[i] = (((p[i].g & 0x3F) * gmax) / 0x3F) << _xwin.gshift;
2154 _xwin.bmap[i] = (((p[i].b & 0x3F) * bmax) / 0x3F) << _xwin.bshift;
2155 }
2156 }
2157
_xwin_private_set_palette_colors(AL_CONST PALETTE p,int from,int to)2158 static void _xwin_private_set_palette_colors(AL_CONST PALETTE p, int from, int to)
2159 {
2160 int i;
2161
2162 for (i = from; i <= to; i++) {
2163 _xwin.rmap[i] = (((p[i].r & 0x3F) * 15) / 0x3F) << 8;
2164 _xwin.gmap[i] = (((p[i].g & 0x3F) * 15) / 0x3F) << 4;
2165 _xwin.bmap[i] = (((p[i].b & 0x3F) * 15) / 0x3F);
2166 }
2167 }
2168
_xwin_private_set_palette_range(AL_CONST PALETTE p,int from,int to)2169 static void _xwin_private_set_palette_range(AL_CONST PALETTE p, int from, int to)
2170 {
2171 RGB *pal;
2172 int c;
2173 unsigned char temp;
2174
2175 if (_xwin.set_colors != 0) {
2176 if (blitter_func) {
2177 if (use_bgr_palette_hack && (from >= 0) && (to < 256)) {
2178 pal = _AL_MALLOC_ATOMIC(sizeof(RGB)*256);
2179 ASSERT(pal);
2180 ASSERT(p);
2181 if (!pal || !p)
2182 return; /* ... in shame and disgrace */
2183 memcpy(&pal[from], &p[from], sizeof(RGB)*(to-from+1));
2184 for (c = from; c <= to; c++) {
2185 temp = pal[c].r;
2186 pal[c].r = pal[c].b;
2187 pal[c].b = temp;
2188 }
2189 _set_colorconv_palette(pal, from, to);
2190 _AL_FREE(pal);
2191 }
2192 else {
2193 _set_colorconv_palette(p, from, to);
2194 }
2195 }
2196
2197 /* Set "hardware" colors. */
2198 (*(_xwin.set_colors))(p, from, to);
2199
2200 /* Update XImage and window. */
2201 if (!_xwin.matching_formats)
2202 _xwin_private_update_screen(0, 0, _xwin.virtual_width, _xwin.virtual_height);
2203 }
2204 }
2205
_xwin_set_palette_range(AL_CONST PALETTE p,int from,int to,int vsync)2206 void _xwin_set_palette_range(AL_CONST PALETTE p, int from, int to, int vsync)
2207 {
2208 if (vsync) {
2209 _xwin_vsync();
2210 }
2211
2212 XLOCK();
2213 _xwin_private_set_palette_range(p, from, to);
2214 XUNLOCK();
2215 }
2216
2217
2218
2219 /* _xwin_set_window_defaults:
2220 * Set default window parameters.
2221 */
_xwin_private_set_window_defaults(void)2222 static void _xwin_private_set_window_defaults(void)
2223 {
2224 XClassHint hint;
2225 XWMHints wm_hints;
2226
2227 if (_xwin.wm_window == None)
2228 return;
2229
2230 /* Set window title. */
2231 XStoreName(_xwin.display, _xwin.wm_window, _xwin.window_title);
2232
2233 /* Set hints. */
2234 hint.res_name = _xwin.application_name;
2235 hint.res_class = _xwin.application_class;
2236 XSetClassHint(_xwin.display, _xwin.wm_window, &hint);
2237
2238 wm_hints.flags = InputHint | StateHint | WindowGroupHint;
2239 wm_hints.input = True;
2240 wm_hints.initial_state = NormalState;
2241 wm_hints.window_group = _xwin.wm_window;
2242
2243 #ifdef ALLEGRO_XWINDOWS_WITH_XPM
2244 if (allegro_icon) {
2245 wm_hints.flags |= IconPixmapHint | IconMaskHint;
2246 XpmCreatePixmapFromData(_xwin.display, _xwin.wm_window, allegro_icon,
2247 &wm_hints.icon_pixmap, &wm_hints.icon_mask, NULL);
2248 }
2249 #endif
2250
2251 XSetWMHints(_xwin.display, _xwin.wm_window, &wm_hints);
2252 }
2253
2254
2255
2256 /* _xwin_flush_buffers:
2257 * Flush input and output X-buffers.
2258 */
_xwin_private_flush_buffers(void)2259 static void _xwin_private_flush_buffers(void)
2260 {
2261 if (_xwin.display != 0)
2262 XSync(_xwin.display, False);
2263 }
2264
_xwin_flush_buffers(void)2265 void _xwin_flush_buffers(void)
2266 {
2267 XLOCK();
2268 _xwin_private_flush_buffers();
2269 XUNLOCK();
2270 }
2271
2272
2273
2274 /* _xwin_vsync:
2275 * Emulation of vsync.
2276 */
_xwin_vsync(void)2277 void _xwin_vsync(void)
2278 {
2279 if (_timer_installed) {
2280 int prev = retrace_count;
2281
2282 XLOCK();
2283 XSync(_xwin.display, False);
2284 XUNLOCK();
2285
2286 do {
2287 rest(1);
2288 } while (retrace_count == prev);
2289 }
2290 else {
2291 /* This does not wait for the VBI - but it waits until X11 has
2292 * synchronized, i.e. until actual changes are visible. So it
2293 * has a similar effect.
2294 */
2295 XLOCK();
2296 XSync(_xwin.display, False);
2297 XUNLOCK();
2298 }
2299 }
2300
2301
2302 /* _xwin_process_event:
2303 * Process one event.
2304 */
_xwin_private_process_event(XEvent * event)2305 static void _xwin_private_process_event(XEvent *event)
2306 {
2307 int dx, dy, dz = 0, dw = 0;
2308 static int mouse_buttons = 0;
2309 static int mouse_savedx = 0;
2310 static int mouse_savedy = 0;
2311 static int mouse_warp_now = 0;
2312 static int mouse_was_warped = 0;
2313
2314 switch (event->type) {
2315 case KeyPress:
2316 _xwin_keyboard_handler(&event->xkey, FALSE);
2317 break;
2318 case KeyRelease:
2319 _xwin_keyboard_handler(&event->xkey, FALSE);
2320 break;
2321 case FocusIn:
2322 _switch_in();
2323 _xwin_keyboard_focus_handler(&event->xfocus);
2324 break;
2325 case FocusOut:
2326 _switch_out();
2327 _xwin_keyboard_focus_handler(&event->xfocus);
2328 break;
2329 case ButtonPress:
2330 /* Mouse button pressed. */
2331 if (event->xbutton.button == Button1)
2332 mouse_buttons |= 1;
2333 else if (event->xbutton.button == Button3)
2334 mouse_buttons |= 2;
2335 else if (event->xbutton.button == Button2)
2336 mouse_buttons |= 4;
2337 else if (event->xbutton.button == Button4) {
2338 dz = 1;
2339 }
2340 else if (event->xbutton.button == Button5) {
2341 dz = -1;
2342 }
2343 else if (event->xbutton.button == 6) {
2344 dw = -1;
2345 }
2346 else if (event->xbutton.button == 7) {
2347 dw = 1;
2348 }
2349 else if (event->xbutton.button == 8)
2350 mouse_buttons |= 8;
2351 else if (event->xbutton.button == 9)
2352 mouse_buttons |= 16;
2353 if (_xwin_mouse_interrupt)
2354 (*_xwin_mouse_interrupt)(0, 0, dz, dw, mouse_buttons);
2355 break;
2356 case ButtonRelease:
2357 /* Mouse button released. */
2358 if (event->xbutton.button == Button1)
2359 mouse_buttons &= ~1;
2360 else if (event->xbutton.button == Button3)
2361 mouse_buttons &= ~2;
2362 else if (event->xbutton.button == Button2)
2363 mouse_buttons &= ~4;
2364 else if (event->xbutton.button == 8)
2365 mouse_buttons &= ~8;
2366 else if (event->xbutton.button == 9)
2367 mouse_buttons &= ~16;
2368 if (_xwin_mouse_interrupt)
2369 (*_xwin_mouse_interrupt)(0, 0, 0, 0, mouse_buttons);
2370 break;
2371 case MotionNotify:
2372 /* Mouse moved. */
2373 dx = event->xmotion.x - mouse_savedx;
2374 dy = event->xmotion.y - mouse_savedy;
2375 /* Discard some events after warp. */
2376 if (mouse_was_warped && ((dx != 0) || (dy != 0)) && (mouse_was_warped++ < 16))
2377 break;
2378 mouse_savedx = event->xmotion.x;
2379 mouse_savedy = event->xmotion.y;
2380 mouse_was_warped = 0;
2381 if (!_xwin.mouse_warped) {
2382 /* Move Allegro cursor to X-cursor. */
2383 dx = event->xmotion.x - (_mouse_x - (_xwin_mouse_extended_range ? _xwin.scroll_x : 0));
2384 dy = event->xmotion.y - (_mouse_y - (_xwin_mouse_extended_range ? _xwin.scroll_y : 0));
2385 }
2386 if (((dx != 0) || (dy != 0)) && _xwin_mouse_interrupt) {
2387 if (_xwin.mouse_warped && (mouse_warp_now++ & 4)) {
2388 /* Warp X-cursor to the center of the window. */
2389 mouse_savedx = _xwin.window_width / 2;
2390 mouse_savedy = _xwin.window_height / 2;
2391 mouse_was_warped = 1;
2392 XWarpPointer(_xwin.display, _xwin.window, _xwin.window,
2393 0, 0, _xwin.window_width, _xwin.window_height,
2394 mouse_savedx, mouse_savedy);
2395 }
2396 /* Move Allegro cursor. */
2397 (*_xwin_mouse_interrupt)(dx, dy, 0, 0, mouse_buttons);
2398 }
2399 break;
2400 case EnterNotify:
2401 /* Mouse entered window. */
2402 _mouse_on = TRUE;
2403 _xwin_mouse_enter_notify();
2404 mouse_savedx = event->xcrossing.x;
2405 mouse_savedy = event->xcrossing.y;
2406 mouse_was_warped = 0;
2407 if (!_xwin.mouse_warped) {
2408 /* Move Allegro cursor to X-cursor. */
2409 dx = event->xcrossing.x - (_mouse_x - (_xwin_mouse_extended_range ? _xwin.scroll_x : 0));
2410 dy = event->xcrossing.y - (_mouse_y - (_xwin_mouse_extended_range ? _xwin.scroll_y : 0));
2411 if (((dx != 0) || (dy != 0)) && _xwin_mouse_interrupt)
2412 (*_xwin_mouse_interrupt)(dx, dy, 0, 0, mouse_buttons);
2413 }
2414 else if (_xwin_mouse_interrupt)
2415 (*_xwin_mouse_interrupt)(0, 0, 0, 0, mouse_buttons);
2416 break;
2417 case LeaveNotify:
2418 _mouse_on = FALSE;
2419 if (_xwin_mouse_interrupt)
2420 (*_xwin_mouse_interrupt)(0, 0, 0, 0, mouse_buttons);
2421 _xwin_mouse_leave_notify();
2422 break;
2423 case Expose:
2424 /* Request to redraw part of the window. */
2425 (*_xwin_window_redrawer)(event->xexpose.x, event->xexpose.y,
2426 event->xexpose.width, event->xexpose.height);
2427 break;
2428 case MappingNotify:
2429 /* Keyboard mapping changed. */
2430 if (event->xmapping.request == MappingKeyboard)
2431 _xwin_get_keyboard_mapping();
2432 break;
2433 case ClientMessage:
2434 /* Window close request */
2435 if ((Atom)event->xclient.data.l[0] == wm_delete_window) {
2436 if (_xwin.close_button_callback)
2437 _xwin.close_button_callback();
2438 }
2439 break;
2440 }
2441 }
2442
2443
2444
2445 /* _xwin_handle_input:
2446 * Handle events from the queue.
2447 */
_xwin_private_handle_input(void)2448 void _xwin_private_handle_input(void)
2449 {
2450 int i, events, events_queued;
2451 static XEvent event[X_MAX_EVENTS + 1]; /* +1 for possible extra event, see below. */
2452
2453 if (_xwin.display == 0)
2454 return;
2455
2456 /* Switch mouse to non-warped mode if mickeys were not used recently (~2 seconds). */
2457 if (_xwin.mouse_warped && (_xwin.mouse_warped++ > MOUSE_WARP_DELAY)) {
2458 _xwin.mouse_warped = 0;
2459 /* Move X-cursor to Allegro cursor. */
2460 XWarpPointer(_xwin.display, _xwin.window, _xwin.window,
2461 0, 0, _xwin.window_width, _xwin.window_height,
2462 _mouse_x - (_xwin_mouse_extended_range ? _xwin.scroll_x : 0),
2463 _mouse_y - (_xwin_mouse_extended_range ? _xwin.scroll_y : 0));
2464 }
2465
2466 /* Flush X-buffers. */
2467 _xwin_private_flush_buffers();
2468
2469 /* How much events are available in the queue. */
2470 events = events_queued = XEventsQueued(_xwin.display, QueuedAlready);
2471 if (events <= 0)
2472 return;
2473
2474 /* Limit amount of events we read at once. */
2475 if (events > X_MAX_EVENTS)
2476 events = X_MAX_EVENTS;
2477
2478 /* Read pending events. */
2479 for (i = 0; i < events; i++)
2480 XNextEvent(_xwin.display, &event[i]);
2481
2482 /* Can't have a KeyRelease as last event, since it might be only half
2483 * of a key repeat pair. Also see comment below.
2484 */
2485 if (events_queued > events && event[i - 1].type == KeyRelease) {
2486 XNextEvent(_xwin.display, &event[i]);
2487 events++;
2488 }
2489
2490 /* Process all events. */
2491 for (i = 0; i < events; i++) {
2492
2493 /* Hack to make Allegro's key[] array work despite of key repeat.
2494 * If a KeyRelease is sent at the same time as a KeyPress following
2495 * it with the same keycode, we ignore the release event.
2496 */
2497 if (event[i].type == KeyRelease && (i + 1) < events) {
2498 if (event[i + 1].type == KeyPress) {
2499 if (event[i].xkey.keycode == event[i + 1].xkey.keycode &&
2500 event[i].xkey.time == event[i + 1].xkey.time)
2501 continue;
2502 }
2503 }
2504
2505 _xwin_private_process_event(&event[i]);
2506 }
2507 }
2508
_xwin_handle_input(void)2509 void _xwin_handle_input(void)
2510 {
2511 #ifndef ALLEGRO_MULTITHREADED
2512 if (_xwin.lock_count) {
2513 ++_xwin_missed_input;
2514 return;
2515 }
2516 #endif
2517
2518 XLOCK();
2519
2520 if (_xwin_input_handler)
2521 _xwin_input_handler();
2522 else
2523 _xwin_private_handle_input();
2524
2525 XUNLOCK();
2526 }
2527
2528
2529
2530 /* _xwin_set_warped_mouse_mode:
2531 * Switch mouse handling into warped mode.
2532 */
_xwin_private_set_warped_mouse_mode(int permanent)2533 static void _xwin_private_set_warped_mouse_mode(int permanent)
2534 {
2535 /* Don't enable warp mode if the hardware cursor is being displayed */
2536 if (!_xwin.hw_cursor_ok)
2537 _xwin.mouse_warped = ((permanent) ? 1 : (MOUSE_WARP_DELAY*7/8));
2538 }
2539
_xwin_set_warped_mouse_mode(int permanent)2540 void _xwin_set_warped_mouse_mode(int permanent)
2541 {
2542 XLOCK();
2543 _xwin_private_set_warped_mouse_mode(permanent);
2544 XUNLOCK();
2545 }
2546
2547
2548
2549 /* _xwin_redraw_window:
2550 * Redraws part of the window.
2551 */
_xwin_private_redraw_window(int x,int y,int w,int h)2552 static void _xwin_private_redraw_window(int x, int y, int w, int h)
2553 {
2554 if (_xwin.window == None)
2555 return;
2556
2557 /* Clip updated region. */
2558 if (x >= _xwin.screen_width)
2559 return;
2560 if (x < 0) {
2561 w += x;
2562 x = 0;
2563 }
2564 if (w >= (_xwin.screen_width - x))
2565 w = _xwin.screen_width - x;
2566 if (w <= 0)
2567 return;
2568
2569 if (y >= _xwin.screen_height)
2570 return;
2571 if (y < 0) {
2572 h += y;
2573 y = 0;
2574 }
2575 if (h >= (_xwin.screen_height - y))
2576 h = _xwin.screen_height - y;
2577 if (h <= 0)
2578 return;
2579
2580 if (!_xwin.ximage)
2581 XFillRectangle(_xwin.display, _xwin.window, _xwin.gc, x, y, w, h);
2582 else {
2583 #ifdef ALLEGRO_XWINDOWS_WITH_SHM
2584 if (_xwin.use_shm)
2585 XShmPutImage(_xwin.display, _xwin.window, _xwin.gc, _xwin.ximage,
2586 x + _xwin.scroll_x, y + _xwin.scroll_y, x, y, w, h, False);
2587 else
2588 #endif
2589 XPutImage(_xwin.display, _xwin.window, _xwin.gc, _xwin.ximage,
2590 x + _xwin.scroll_x, y + _xwin.scroll_y, x, y, w, h);
2591 }
2592 }
2593
_xwin_redraw_window(int x,int y,int w,int h)2594 void _xwin_redraw_window(int x, int y, int w, int h)
2595 {
2596 _xwin_lock(NULL);
2597 (*_xwin_window_redrawer)(x, y, w, h);
2598 _xwin_unlock(NULL);
2599 }
2600
2601
2602
2603 /* _xwin_scroll_screen:
2604 * Scroll visible screen in window.
2605 */
_xwin_private_scroll_screen(int x,int y)2606 static int _xwin_private_scroll_screen(int x, int y)
2607 {
2608 _xwin.scroll_x = x;
2609 _xwin.scroll_y = y;
2610 (*_xwin_window_redrawer)(0, 0, _xwin.screen_width, _xwin.screen_height);
2611 _xwin_private_flush_buffers();
2612
2613 return 0;
2614 }
2615
_xwin_scroll_screen(int x,int y)2616 int _xwin_scroll_screen(int x, int y)
2617 {
2618 int result;
2619
2620 if (x < 0)
2621 x = 0;
2622 else if (x >= (_xwin.virtual_width - _xwin.screen_width))
2623 x = _xwin.virtual_width - _xwin.screen_width;
2624 if (y < 0)
2625 y = 0;
2626 else if (y >= (_xwin.virtual_height - _xwin.screen_height))
2627 y = _xwin.virtual_height - _xwin.screen_height;
2628 if ((_xwin.scroll_x == x) && (_xwin.scroll_y == y))
2629 return 0;
2630
2631 _xwin_lock(NULL);
2632 result = _xwin_private_scroll_screen(x, y);
2633 _xwin_unlock(NULL);
2634 return result;
2635 }
2636
2637
2638
2639 /* _xwin_update_screen:
2640 * Update part of the screen.
2641 */
_xwin_private_update_screen(int x,int y,int w,int h)2642 static void _xwin_private_update_screen(int x, int y, int w, int h)
2643 {
2644 /* Update frame buffer with screen contents. */
2645 if (_xwin.screen_to_buffer != 0) {
2646 /* Clip updated region. */
2647 if (x >= _xwin.virtual_width)
2648 return;
2649 if (x < 0) {
2650 w += x;
2651 x = 0;
2652 }
2653 if (w >= (_xwin.virtual_width - x))
2654 w = _xwin.virtual_width - x;
2655 if (w <= 0)
2656 return;
2657
2658 if (y >= _xwin.virtual_height)
2659 return;
2660 if (y < 0) {
2661 h += y;
2662 y = 0;
2663 }
2664 if (h >= (_xwin.virtual_height - y))
2665 h = _xwin.virtual_height - y;
2666 if (h <= 0)
2667 return;
2668
2669 (*(_xwin.screen_to_buffer))(x, y, w, h);
2670 }
2671
2672 /* Update window. */
2673 (*_xwin_window_redrawer)(x - _xwin.scroll_x, y - _xwin.scroll_y, w, h);
2674 }
2675
_xwin_update_screen(int x,int y,int w,int h)2676 void _xwin_update_screen(int x, int y, int w, int h)
2677 {
2678 _xwin_lock(NULL);
2679 _xwin_private_update_screen(x, y, w, h);
2680 _xwin_unlock(NULL);
2681 }
2682
2683
2684
2685 /* _xwin_set_window_title:
2686 * Wrapper for XStoreName.
2687 */
_xwin_private_set_window_title(AL_CONST char * name)2688 static void _xwin_private_set_window_title(AL_CONST char *name)
2689 {
2690 if (!name)
2691 _al_sane_strncpy(_xwin.window_title, XWIN_DEFAULT_WINDOW_TITLE, sizeof(_xwin.window_title));
2692 else
2693 _al_sane_strncpy(_xwin.window_title, name, sizeof(_xwin.window_title));
2694
2695 if (_xwin.wm_window != None)
2696 XStoreName(_xwin.display, _xwin.wm_window, _xwin.window_title);
2697 }
2698
_xwin_set_window_title(AL_CONST char * name)2699 void _xwin_set_window_title(AL_CONST char *name)
2700 {
2701 XLOCK();
2702 _xwin_private_set_window_title(name);
2703 XUNLOCK();
2704 }
2705
2706
2707
2708 /* _xwin_sysdrv_set_window_name:
2709 * Sets window name and group.
2710 */
_xwin_private_set_window_name(AL_CONST char * name,AL_CONST char * group)2711 static void _xwin_private_set_window_name(AL_CONST char *name, AL_CONST char *group)
2712 {
2713 XClassHint hint;
2714
2715 if (!name)
2716 _al_sane_strncpy(_xwin.application_name, XWIN_DEFAULT_APPLICATION_NAME, sizeof(_xwin.application_name));
2717 else
2718 _al_sane_strncpy(_xwin.application_name, name, sizeof(_xwin.application_name));
2719
2720 if (!group)
2721 _al_sane_strncpy(_xwin.application_class, XWIN_DEFAULT_APPLICATION_CLASS, sizeof(_xwin.application_class));
2722 else
2723 _al_sane_strncpy(_xwin.application_class, group, sizeof(_xwin.application_class));
2724
2725 if (_xwin.window != None) {
2726 hint.res_name = _xwin.application_name;
2727 hint.res_class = _xwin.application_class;
2728 XSetClassHint(_xwin.display, _xwin.window, &hint);
2729 }
2730 }
2731
xwin_set_window_name(AL_CONST char * name,AL_CONST char * group)2732 void xwin_set_window_name(AL_CONST char *name, AL_CONST char *group)
2733 {
2734 char tmp1[128], tmp2[128];
2735
2736 do_uconvert(name, U_CURRENT, tmp1, U_ASCII, sizeof(tmp1));
2737 do_uconvert(group, U_CURRENT, tmp2, U_ASCII, sizeof(tmp2));
2738
2739 XLOCK();
2740 _xwin_private_set_window_name(tmp1, tmp2);
2741 XUNLOCK();
2742 }
2743
2744
2745
2746 /* _xwin_get_pointer_mapping:
2747 * Wrapper for XGetPointerMapping.
2748 */
_xwin_private_get_pointer_mapping(unsigned char map[],int nmap)2749 static int _xwin_private_get_pointer_mapping(unsigned char map[], int nmap)
2750 {
2751 return ((_xwin.display == 0) ? -1 : XGetPointerMapping(_xwin.display, map, nmap));
2752 }
2753
_xwin_get_pointer_mapping(unsigned char map[],int nmap)2754 int _xwin_get_pointer_mapping(unsigned char map[], int nmap)
2755 {
2756 int num;
2757 XLOCK();
2758 num = _xwin_private_get_pointer_mapping(map, nmap);
2759 XUNLOCK();
2760 return num;
2761 }
2762
2763
2764
2765 /* _xwin_write_line:
2766 * Update last selected line and select new line.
2767 */
_xwin_write_line(BITMAP * bmp,int line)2768 uintptr_t _xwin_write_line(BITMAP *bmp, int line)
2769 {
2770 int new_line = line + bmp->y_ofs;
2771 if ((new_line != _xwin_last_line) && (!_xwin_in_gfx_call) && (_xwin_last_line >= 0))
2772 _xwin_update_screen(0, _xwin_last_line, _xwin.virtual_width, 1);
2773 _xwin_last_line = new_line;
2774 return (uintptr_t) (bmp->line[line]);
2775 }
2776
2777
2778
2779 /* _xwin_unwrite_line:
2780 * Update last selected line.
2781 */
_xwin_unwrite_line(BITMAP * bmp)2782 void _xwin_unwrite_line(BITMAP *bmp)
2783 {
2784 if ((!_xwin_in_gfx_call) && (_xwin_last_line >= 0))
2785 _xwin_update_screen(0, _xwin_last_line, _xwin.virtual_width, 1);
2786 _xwin_last_line = -1;
2787 }
2788
2789
2790
2791 /*
2792 * Support for XF86VidMode extension.
2793 */
2794 #ifdef ALLEGRO_XWINDOWS_WITH_XF86VIDMODE
2795 /* qsort comparison function for sorting the modes */
cmpmodes(const void * va,const void * vb)2796 static int cmpmodes(const void *va, const void *vb)
2797 {
2798 const XF86VidModeModeInfo *a = *(const XF86VidModeModeInfo **)va;
2799 const XF86VidModeModeInfo *b = *(const XF86VidModeModeInfo **)vb;
2800
2801 if (a->hdisplay == b->hdisplay)
2802 return b->vdisplay - a->vdisplay;
2803 else
2804 return b->hdisplay - a->hdisplay;
2805 }
2806
2807 /* _xvidmode_private_set_fullscreen:
2808 * Attempt to switch to a better matching video mode.
2809 * Matching code for non exact match (smallest bigger res) rather shamelessly
2810 * taken from SDL.
2811 */
_xvidmode_private_set_fullscreen(int w,int h,int * vidmode_width,int * vidmode_height)2812 static void _xvidmode_private_set_fullscreen(int w, int h, int *vidmode_width,
2813 int *vidmode_height)
2814 {
2815 int vid_event_base, vid_error_base;
2816 int vid_major_version, vid_minor_version;
2817 int i;
2818
2819 /* Test that display is local. */
2820 if (!_xwin_private_display_is_local())
2821 return;
2822
2823 /* Test for presence of VidMode extension. */
2824 if (!XF86VidModeQueryExtension(_xwin.display, &vid_event_base, &vid_error_base)
2825 || !XF86VidModeQueryVersion(_xwin.display, &vid_major_version, &vid_minor_version))
2826 return;
2827
2828 /* Get list of modelines. */
2829 if (!XF86VidModeGetAllModeLines(_xwin.display, _xwin.screen,
2830 &_xwin.num_modes, &_xwin.modesinfo))
2831 return;
2832
2833 /* Remember the mode to restore. */
2834 _xwin.orig_modeinfo = _xwin.modesinfo[0];
2835
2836 /* Search for an exact matching video mode. */
2837 for (i = 0; i < _xwin.num_modes; i++) {
2838 if ((_xwin.modesinfo[i]->hdisplay == w) &&
2839 (_xwin.modesinfo[i]->vdisplay == h))
2840 break;
2841 }
2842
2843 /* Search for a non exact match (smallest bigger res). */
2844 if (i == _xwin.num_modes) {
2845 int best_width = 0, best_height = 0;
2846 qsort(_xwin.modesinfo, _xwin.num_modes, sizeof(void *), cmpmodes);
2847 for (i = _xwin.num_modes-1; i > 0; i--) {
2848 if (!best_width) {
2849 if ((_xwin.modesinfo[i]->hdisplay >= w) &&
2850 (_xwin.modesinfo[i]->vdisplay >= h)) {
2851 best_width = _xwin.modesinfo[i]->hdisplay;
2852 best_height = _xwin.modesinfo[i]->vdisplay;
2853 }
2854 }
2855 else {
2856 if ((_xwin.modesinfo[i]->hdisplay != best_width) ||
2857 (_xwin.modesinfo[i]->vdisplay != best_height)) {
2858 i++;
2859 break;
2860 }
2861 }
2862 }
2863 }
2864
2865 /* Switch video mode. */
2866 if ((_xwin.modesinfo[i] == _xwin.orig_modeinfo) ||
2867 !XF86VidModeSwitchToMode(_xwin.display, _xwin.screen,
2868 _xwin.modesinfo[i])) {
2869 *vidmode_width = _xwin.orig_modeinfo->hdisplay;
2870 *vidmode_height = _xwin.orig_modeinfo->vdisplay;
2871 _xwin.orig_modeinfo = NULL;
2872 }
2873 else {
2874 *vidmode_width = _xwin.modesinfo[i]->hdisplay;
2875 *vidmode_height = _xwin.modesinfo[i]->vdisplay;
2876 /* Only kept / set for compatibility with apps which check this. */
2877 _xwin.mode_switched = 1;
2878 }
2879
2880 /* Lock mode switching. */
2881 XF86VidModeLockModeSwitch(_xwin.display, _xwin.screen, True);
2882
2883 /* Set viewport. */
2884 XF86VidModeSetViewPort(_xwin.display, _xwin.screen, 0, 0);
2885 }
2886
2887
2888
2889 /* free_modelines:
2890 * Free mode lines.
2891 */
free_modelines(XF86VidModeModeInfo ** modesinfo,int num_modes)2892 static void free_modelines(XF86VidModeModeInfo **modesinfo, int num_modes)
2893 {
2894 int i;
2895
2896 for (i = 0; i < num_modes; i++)
2897 if (modesinfo[i]->privsize > 0)
2898 XFree(modesinfo[i]->private);
2899 XFree(modesinfo);
2900 }
2901
2902
2903
2904 /* _xvidmode_private_unset_fullscreen:
2905 * Restore original video mode and window attributes.
2906 */
_xvidmode_private_unset_fullscreen(void)2907 static void _xvidmode_private_unset_fullscreen(void)
2908 {
2909 if (_xwin.num_modes > 0) {
2910 /* Unlock mode switching. */
2911 XF86VidModeLockModeSwitch(_xwin.display, _xwin.screen, False);
2912
2913 if (_xwin.orig_modeinfo) {
2914 /* Restore the original video mode. */
2915 XF86VidModeSwitchToMode(_xwin.display, _xwin.screen,
2916 _xwin.orig_modeinfo);
2917 _xwin.orig_modeinfo = 0;
2918 /* only kept / set for compatibility with apps which check this */
2919 _xwin.mode_switched = 0;
2920 }
2921
2922 /* Free modelines. */
2923 free_modelines(_xwin.modesinfo, _xwin.num_modes);
2924 _xwin.num_modes = 0;
2925 _xwin.modesinfo = 0;
2926 }
2927 }
2928 #endif
2929
2930
2931
2932 /* _xwin_private_fetch_mode_list:
2933 * Generates a list of valid video modes.
2934 */
_xwin_private_fetch_mode_list(void)2935 static GFX_MODE_LIST *_xwin_private_fetch_mode_list(void)
2936 {
2937 int num_modes = 1, num_bpp = 0;
2938 GFX_MODE_LIST *mode_list;
2939 int i, j;
2940 #ifdef ALLEGRO_XWINDOWS_WITH_XF86VIDMODE
2941 int has_vidmode = 0;
2942 int vid_event_base, vid_error_base;
2943 int vid_major_version, vid_minor_version;
2944 XF86VidModeModeInfo **modesinfo;
2945
2946 /* Test that display is local. */
2947 if (_xwin_private_display_is_local() &&
2948 /* Test for presence of VidMode extension. */
2949 XF86VidModeQueryExtension(_xwin.display, &vid_event_base, &vid_error_base) &&
2950 XF86VidModeQueryVersion(_xwin.display, &vid_major_version, &vid_minor_version) &&
2951 /* Get list of modelines. */
2952 XF86VidModeGetAllModeLines(_xwin.display, _xwin.screen, &num_modes, &modesinfo))
2953 has_vidmode = 1;
2954 #endif
2955
2956 /* Calculate the number of color depths we have to support. */
2957 #ifdef ALLEGRO_COLOR8
2958 num_bpp++;
2959 #endif
2960 #ifdef ALLEGRO_COLOR16
2961 num_bpp += 2; /* 15, 16 */
2962 #endif
2963 #ifdef ALLEGRO_COLOR24
2964 num_bpp++;
2965 #endif
2966 #ifdef ALLEGRO_COLOR32
2967 num_bpp++;
2968 #endif
2969 if (num_bpp == 0) /* ha! */
2970 return 0;
2971
2972 /* Allocate space for mode list. */
2973 mode_list = _AL_MALLOC(sizeof(GFX_MODE_LIST));
2974 if (!mode_list) {
2975 #ifdef ALLEGRO_XWINDOWS_WITH_XF86VIDMODE
2976 if (has_vidmode)
2977 free_modelines(modesinfo, num_modes);
2978 #endif
2979 return 0;
2980 }
2981
2982 mode_list->mode = _AL_MALLOC(sizeof(GFX_MODE) * ((num_modes * num_bpp) + 1));
2983 if (!mode_list->mode) {
2984 _AL_FREE(mode_list);
2985 #ifdef ALLEGRO_XWINDOWS_WITH_XF86VIDMODE
2986 if (has_vidmode)
2987 free_modelines(modesinfo, num_modes);
2988 #endif
2989 return 0;
2990 }
2991
2992 /* Fill in mode list. */
2993 j = 0;
2994 for (i = 0; i < num_modes; i++) {
2995
2996 #define ADD_SCREEN_MODE(BPP) \
2997 mode_list->mode[j].width = DisplayWidth(_xwin.display, _xwin.screen); \
2998 mode_list->mode[j].height = DisplayHeight(_xwin.display, _xwin.screen); \
2999 mode_list->mode[j].bpp = BPP; \
3000 j++
3001 #ifdef ALLEGRO_XWINDOWS_WITH_XF86VIDMODE
3002 #define ADD_VIDMODE_MODE(BPP) \
3003 mode_list->mode[j].width = modesinfo[i]->hdisplay; \
3004 mode_list->mode[j].height = modesinfo[i]->vdisplay; \
3005 mode_list->mode[j].bpp = BPP; \
3006 j++
3007 #define ADD_MODE(BPP) \
3008 if (has_vidmode) { \
3009 ADD_VIDMODE_MODE(BPP); \
3010 } else { \
3011 ADD_SCREEN_MODE(BPP); \
3012 }
3013 #else
3014 #define ADD_MODE(BPP) ADD_SCREEN_MODE(BPP)
3015 #endif
3016
3017 #ifdef ALLEGRO_COLOR8
3018 ADD_MODE(8);
3019 #endif
3020 #ifdef ALLEGRO_COLOR16
3021 ADD_MODE(15);
3022 ADD_MODE(16);
3023 #endif
3024 #ifdef ALLEGRO_COLOR24
3025 ADD_MODE(24);
3026 #endif
3027 #ifdef ALLEGRO_COLOR32
3028 ADD_MODE(32);
3029 #endif
3030 }
3031
3032 mode_list->mode[j].width = 0;
3033 mode_list->mode[j].height = 0;
3034 mode_list->mode[j].bpp = 0;
3035 mode_list->num_modes = j;
3036
3037 #ifdef ALLEGRO_XWINDOWS_WITH_XF86VIDMODE
3038 if (has_vidmode)
3039 free_modelines(modesinfo, num_modes);
3040 #endif
3041
3042 return mode_list;
3043 }
3044
3045
3046
3047 /* _xwin_fetch_mode_list:
3048 * Fetch mode list.
3049 */
_xwin_fetch_mode_list(void)3050 GFX_MODE_LIST *_xwin_fetch_mode_list(void)
3051 {
3052 GFX_MODE_LIST *list;
3053 XLOCK();
3054 list = _xwin_private_fetch_mode_list();
3055 XUNLOCK();
3056 return list;
3057 }
3058
3059
3060
3061 /* Hook functions */
3062 int (*_xwin_window_creator)(void) = &_xwin_private_create_window;
3063 void (*_xwin_window_defaultor)(void) = &_xwin_private_set_window_defaults;
3064 void (*_xwin_window_redrawer)(int, int, int, int) = &_xwin_private_redraw_window;
3065 void (*_xwin_input_handler)(void) = 0;
3066
3067 void (*_xwin_keyboard_callback)(int, int) = 0;
3068