1 /* ______ ___ ___
2 * /\ _ \ /\_ \ /\_ \
3 * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___
4 * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\
5 * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \
6 * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/
7 * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/
8 * /\____/
9 * \_/__/
10 *
11 * DGA 2.0 graphics driver.
12 *
13 * By Angelo Mottola.
14 *
15 * See readme.txt for copyright information.
16 */
17
18 #include "allegro.h"
19 #include "allegro/internal/aintern.h"
20 #include "allegro/platform/aintunix.h"
21 #include "xwin.h"
22
23 #if (defined ALLEGRO_XWINDOWS_WITH_XF86DGA2) && ((!defined ALLEGRO_WITH_MODULES) || (defined ALLEGRO_MODULE))
24
25 #include <X11/Xlib.h>
26 #include <X11/extensions/Xxf86dga.h>
27
28
29 #define RESYNC() XDGASync(_xwin.display, _xwin.screen);
30
31
32 static XDGADevice *dga_device = NULL;
33 static char _xdga2_driver_desc[256] = EMPTY_STRING;
34 static Colormap _dga_cmap = 0;
35 static int dga_event_base;
36 static int keyboard_got_focus = FALSE;
37
38
39 static int _xdga2_find_mode(int w, int h, int vw, int vh, int depth);
40 static void _xdga2_handle_input(void);
41 static BITMAP *_xdga2_gfxdrv_init(int w, int h, int vw, int vh, int color_depth);
42 static BITMAP *_xdga2_soft_gfxdrv_init(int w, int h, int vw, int vh, int color_depth);
43 static void _xdga2_gfxdrv_exit(BITMAP *bmp);
44 static int _xdga2_poll_scroll(void);
45 static int _xdga2_request_scroll(int x, int y);
46 static int _xdga2_request_video_bitmap(BITMAP *bmp);
47 static int _xdga2_scroll_screen(int x, int y);
48 static void _xdga2_set_palette_range(AL_CONST PALETTE p, int from, int to, int vsync);
49 static void _xdga2_acquire(BITMAP *bmp);
50 static GFX_MODE_LIST *_xdga2_fetch_mode_list(void);
51
52 #ifdef ALLEGRO_NO_ASM
53 uintptr_t _xdga2_write_line(BITMAP *bmp, int line);
54 #else
55 uintptr_t _xdga2_write_line_asm(BITMAP *bmp, int line);
56 #endif
57
58
59 static void (*_orig_hline) (BITMAP *bmp, int x1, int y, int x2, int color);
60 static void (*_orig_vline) (BITMAP *bmp, int x, int y1, int y2, int color);
61 static void (*_orig_rectfill) (BITMAP *bmp, int x1, int y1, int x2, int y2, int color);
62 static void (*_orig_draw_sprite) (BITMAP *bmp, BITMAP *sprite, int x, int y);
63 static void (*_orig_masked_blit) (BITMAP *source, BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height);
64
65 static void _xaccel_hline(BITMAP *bmp, int x1, int y, int x2, int color);
66 static void _xaccel_vline(BITMAP *bmp, int x, int y1, int y2, int color);
67 static void _xaccel_rectfill(BITMAP *bmp, int x1, int y1, int x2, int y2, int color);
68 static void _xaccel_clear_to_color(BITMAP *bmp, int color);
69 static void _xaccel_blit_to_self(BITMAP *source, BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height);
70 static void _xaccel_draw_sprite(BITMAP *bmp, BITMAP *sprite, int x, int y);
71 static void _xaccel_masked_blit(BITMAP *source, BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height);
72
73 #define DGA_MAX_EVENTS 5
74
75
76 GFX_DRIVER gfx_xdga2 =
77 {
78 GFX_XDGA2,
79 empty_string,
80 empty_string,
81 "DGA 2.0",
82 _xdga2_gfxdrv_init,
83 _xdga2_gfxdrv_exit,
84 _xdga2_scroll_screen,
85 _xwin_vsync,
86 _xdga2_set_palette_range,
87 _xdga2_request_scroll,
88 _xdga2_poll_scroll,
89 NULL,
90 NULL, NULL, NULL,
91 _xdga2_request_video_bitmap,
92 NULL, NULL,
93 NULL, NULL, NULL, NULL,
94 NULL,
95 NULL, NULL,
96 NULL,
97 _xdga2_fetch_mode_list,
98 640, 480,
99 TRUE,
100 0, 0,
101 0,
102 0,
103 FALSE
104 };
105
106
107
108 GFX_DRIVER gfx_xdga2_soft =
109 {
110 GFX_XDGA2_SOFT,
111 empty_string,
112 empty_string,
113 "DGA 2.0 soft",
114 _xdga2_soft_gfxdrv_init,
115 _xdga2_gfxdrv_exit,
116 _xdga2_scroll_screen,
117 _xwin_vsync,
118 _xdga2_set_palette_range,
119 _xdga2_request_scroll,
120 _xdga2_poll_scroll,
121 NULL,
122 NULL, NULL, NULL,
123 _xdga2_request_video_bitmap,
124 NULL, NULL,
125 NULL, NULL, NULL, NULL,
126 NULL,
127 NULL, NULL,
128 NULL,
129 _xdga2_fetch_mode_list,
130 640, 480,
131 TRUE,
132 0, 0,
133 0,
134 0,
135 FALSE
136 };
137
138
139
140 /* _xdga2_fetch_mode_list:
141 * Creates list of available DGA2 video modes.
142 */
_xdga2_private_fetch_mode_list(void)143 static GFX_MODE_LIST *_xdga2_private_fetch_mode_list(void)
144 {
145 XDGAMode *mode;
146 int bpp, num_modes, stored_modes, i, j, already_there;
147 GFX_MODE_LIST *mode_list;
148 GFX_MODE *tmp;
149
150 mode = XDGAQueryModes(_xwin.display, _xwin.screen, &num_modes);
151 if (!mode)
152 return NULL;
153
154 mode_list = _AL_MALLOC(sizeof(GFX_MODE_LIST));
155 if (!mode_list)
156 goto error;
157 mode_list->mode = NULL;
158
159 stored_modes = 0;
160 for (i=0; i<num_modes; i++) {
161 bpp = (mode[i].depth == 24) ? mode[i].bitsPerPixel : mode[i].depth;
162 already_there = FALSE;
163 for (j=0; j<stored_modes; j++) {
164 if ((mode_list->mode[j].width == mode[i].viewportWidth) &&
165 (mode_list->mode[j].height == mode[i].viewportHeight) &&
166 (mode_list->mode[j].bpp == bpp)) {
167 already_there = TRUE;
168 break;
169 }
170 }
171 if (!already_there) {
172 tmp = _AL_REALLOC(mode_list->mode, sizeof(GFX_MODE) * (stored_modes + 1));
173 if (!tmp)
174 goto error;
175 mode_list->mode = tmp;
176 mode_list->mode[stored_modes].width = mode[i].viewportWidth;
177 mode_list->mode[stored_modes].height = mode[i].viewportHeight;
178 mode_list->mode[stored_modes].bpp = bpp;
179 stored_modes++;
180 }
181 }
182
183 tmp = _AL_REALLOC(mode_list->mode, sizeof(GFX_MODE) * (stored_modes + 1));
184 if (!tmp)
185 goto error;
186 mode_list->mode = tmp;
187 mode_list->mode[stored_modes].width = 0;
188 mode_list->mode[stored_modes].height = 0;
189 mode_list->mode[stored_modes].bpp = 0;
190 mode_list->num_modes = stored_modes;
191
192 XFree(mode);
193 return mode_list;
194
195 error:
196 if (mode_list) {
197 _AL_FREE(mode_list->mode);
198 _AL_FREE(mode_list);
199 }
200 XFree(mode);
201 return NULL;
202 }
203
204
205
_xdga2_fetch_mode_list(void)206 static GFX_MODE_LIST *_xdga2_fetch_mode_list(void)
207 {
208 GFX_MODE_LIST *list;
209 XLOCK ();
210 list = _xdga2_private_fetch_mode_list();
211 XUNLOCK ();
212 return list;
213 }
214
215
216
217 /* _xdga2_find_mode:
218 * Returns id number of specified video mode if available, 0 otherwise.
219 */
_xdga2_find_mode(int w,int h,int vw,int vh,int depth)220 static int _xdga2_find_mode(int w, int h, int vw, int vh, int depth)
221 {
222 XDGAMode *mode;
223 int num_modes;
224 int bpp, i, found;
225
226 mode = XDGAQueryModes(_xwin.display, _xwin.screen, &num_modes);
227 if (!mode)
228 return 0;
229
230 /* Let's first try setting also requested refresh rate */
231 for (i=0; i<num_modes; i++) {
232 bpp = mode[i].depth;
233 if (bpp == 24) bpp = mode[i].bitsPerPixel;
234
235 if ((mode[i].viewportWidth == w) &&
236 (mode[i].viewportHeight == h) &&
237 (mode[i].imageWidth >= vw) &&
238 (mode[i].imageHeight >= vh) &&
239 (mode[i].verticalRefresh >= _refresh_rate_request) &&
240 (bpp == depth)) break;
241 }
242
243 if (i == num_modes) {
244 /* No modes were found, so now we don't care about refresh rate */
245 for (i=0; i<num_modes; i++) {
246 bpp = mode[i].depth;
247 if (bpp == 24) bpp = mode[i].bitsPerPixel;
248
249 if ((mode[i].viewportWidth == w) &&
250 (mode[i].viewportHeight == h) &&
251 (mode[i].imageWidth >= vw) &&
252 (mode[i].imageHeight >= vh) &&
253 (bpp == depth)) break;
254 }
255 if (i == num_modes) {
256 /* No way out: mode not found */
257 XFree(mode);
258 return 0;
259 }
260 }
261
262 found = mode[i].num;
263 XFree(mode);
264 return found;
265 }
266
267
268
269 /* _xdga2_handle_input:
270 * Handles DGA events pending from queue.
271 */
_xdga2_handle_input(void)272 static void _xdga2_handle_input(void)
273 {
274 int i, events, events_queued;
275 static XDGAEvent event[DGA_MAX_EVENTS + 1];
276 XDGAEvent *cur_event;
277 XKeyEvent key;
278 int dx, dy, dz = 0;
279 static int mouse_buttons = 0;
280
281 if (_xwin.display == 0)
282 return;
283
284 XSync(_xwin.display, False);
285
286 /* How much events are available in the queue. */
287 events = events_queued = XEventsQueued(_xwin.display, QueuedAlready);
288 if (events <= 0)
289 return;
290
291 /* Limit amount of events we read at once. */
292 if (events > DGA_MAX_EVENTS)
293 events = DGA_MAX_EVENTS;
294
295 /* Read pending events. */
296 for (i = 0; i < events; i++)
297 XNextEvent(_xwin.display, (XEvent *)&event[i]);
298
299 /* see xwin.c */
300 if (events_queued > events && event[i - 1].type == dga_event_base+KeyRelease) {
301 XNextEvent(_xwin.display, (XEvent *)&event[i]);
302 events++;
303 }
304
305 /* Process all events. */
306 for (i = 0; i < events; i++) {
307 /* see xwin.c */
308 if (event[i].type == dga_event_base+KeyRelease && (i + 1) < events) {
309 if (event[i + 1].type == dga_event_base+KeyPress) {
310 if (event[i].xkey.keycode == event[i + 1].xkey.keycode &&
311 event[i].xkey.time == event[i + 1].xkey.time)
312 continue;
313 }
314 }
315
316 cur_event = &event[i];
317 switch (cur_event->type - dga_event_base) {
318
319 case KeyPress:
320 XDGAKeyEventToXKeyEvent(&cur_event->xkey, &key);
321 key.type -= dga_event_base;
322 _xwin_keyboard_handler(&key, TRUE);
323 break;
324
325 case KeyRelease:
326 XDGAKeyEventToXKeyEvent(&cur_event->xkey, &key);
327 key.type -= dga_event_base;
328 _xwin_keyboard_handler(&key, TRUE);
329 break;
330
331 case ButtonPress:
332 if (cur_event->xbutton.button == Button1)
333 mouse_buttons |= 1;
334 else if (cur_event->xbutton.button == Button3)
335 mouse_buttons |= 2;
336 else if (cur_event->xbutton.button == Button2)
337 mouse_buttons |= 4;
338 else if (cur_event->xbutton.button == Button4)
339 dz = 1;
340 else if (cur_event->xbutton.button == Button5)
341 dz = -1;
342 if (_xwin_mouse_interrupt)
343 (*_xwin_mouse_interrupt)(0, 0, dz, 0, mouse_buttons);
344 break;
345
346 case ButtonRelease:
347 if (cur_event->xbutton.button == Button1)
348 mouse_buttons &= ~1;
349 else if (cur_event->xbutton.button == Button3)
350 mouse_buttons &= ~2;
351 else if (cur_event->xbutton.button == Button2)
352 mouse_buttons &= ~4;
353 if (_xwin_mouse_interrupt)
354 (*_xwin_mouse_interrupt)(0, 0, 0, 0, mouse_buttons);
355 break;
356
357 case MotionNotify:
358 dx = cur_event->xmotion.dx;
359 dy = cur_event->xmotion.dy;
360 if (((dx != 0) || (dy != 0)) && _xwin_mouse_interrupt) {
361 (*_xwin_mouse_interrupt)(dx, dy, 0, 0, mouse_buttons);
362 }
363 break;
364
365 default:
366 break;
367 }
368 }
369 }
370
371
372
373 /* _xdga2_display_is_local:
374 * Tests that display connection is local.
375 * (Note: this is duplicated in xwin.c).
376 */
_xdga2_private_display_is_local(void)377 static int _xdga2_private_display_is_local(void)
378 {
379 char *name;
380
381 if (_xwin.display == 0)
382 return 0;
383
384 /* Get display name and test for local display. */
385 name = XDisplayName(0);
386
387 return (((name == 0) || (name[0] == ':') || (strncmp(name, "unix:", 5) == 0)) ? 1 : 0);
388 }
389
390
391
392 /* _xdga2_gfxdrv_init_drv:
393 * Initializes driver and creates screen bitmap.
394 */
_xdga2_private_gfxdrv_init_drv(GFX_DRIVER * drv,int w,int h,int vw,int vh,int depth,int accel)395 static BITMAP *_xdga2_private_gfxdrv_init_drv(GFX_DRIVER *drv, int w, int h, int vw, int vh, int depth, int accel)
396 {
397 int dga_error_base, dga_major_version, dga_minor_version;
398 int mode, mask, red_shift = 0, green_shift = 0, blue_shift = 0;
399 long input_mask;
400 char tmp1[128], tmp2[128];
401 BITMAP *bmp;
402
403 /* This is just to test if the system driver has been installed properly */
404 if (_xwin.window == None)
405 return NULL;
406
407 /* Test that display is local. */
408 if (!_xdga2_private_display_is_local()) {
409 ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("This driver needs local display"));
410 return NULL;
411 }
412
413 /* Choose convenient size. */
414 if ((w == 0) && (h == 0)) {
415 w = 640;
416 h = 480;
417 }
418
419 if ((w < 80) || (h < 80) || (w > 4096) || (h > 4096)) {
420 ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Unsupported screen size"));
421 return NULL;
422 }
423
424 if (vw < w)
425 vw = w;
426 if (vh < h)
427 vh = h;
428
429 if (1
430 #ifdef ALLEGRO_COLOR8
431 && (depth != 8)
432 #endif
433 #ifdef ALLEGRO_COLOR16
434 && (depth != 15)
435 && (depth != 16)
436 #endif
437 #ifdef ALLEGRO_COLOR24
438 && (depth != 24)
439 #endif
440 #ifdef ALLEGRO_COLOR32
441 && (depth != 32)
442 #endif
443 ) {
444 ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Unsupported color depth"));
445 return NULL;
446 }
447
448 /* Checks presence of DGA extension */
449 if (!XDGAQueryExtension(_xwin.display, &dga_event_base, &dga_error_base) ||
450 !XDGAQueryVersion(_xwin.display, &dga_major_version, &dga_minor_version)) {
451 ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("DGA extension is not supported"));
452 return NULL;
453 }
454
455 /* Works only with DGA 2.0 or newer */
456 if (dga_major_version < 2) {
457 ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("DGA 2.0 or newer is required"));
458 return NULL;
459 }
460
461 /* Attempts to access the framebuffer */
462 if (!XDGAOpenFramebuffer(_xwin.display, _xwin.screen)) {
463 ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Can not open framebuffer"));
464 return NULL;
465 }
466
467 /* Finds suitable video mode number */
468 mode = _xdga2_find_mode(w, h, vw, vh, depth);
469 if (!mode) {
470 ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Resolution not supported"));
471 return NULL;
472 }
473
474 /* Sets DGA video mode */
475 dga_device = XDGASetMode(_xwin.display, _xwin.screen, mode);
476 if (dga_device == NULL) {
477 ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Can not switch to DGA mode"));
478 return NULL;
479 }
480 _xwin.in_dga_mode = 2;
481 _set_current_refresh_rate(dga_device->mode.verticalRefresh);
482 set_display_switch_mode(SWITCH_NONE);
483
484 /* Installs DGA color map */
485 if (_dga_cmap) {
486 XFreeColormap(_xwin.display, _dga_cmap);
487 _dga_cmap = 0;
488 }
489 if ((dga_device->mode.visualClass == PseudoColor)
490 || (dga_device->mode.visualClass == GrayScale)
491 || (dga_device->mode.visualClass == DirectColor))
492 _dga_cmap = XDGACreateColormap(_xwin.display, _xwin.screen, dga_device, AllocAll);
493 else
494 _dga_cmap = XDGACreateColormap(_xwin.display, _xwin.screen, dga_device, AllocNone);
495 XDGAInstallColormap(_xwin.display, _xwin.screen, _dga_cmap);
496
497 /* Sets up direct color shifts */
498 if (depth != 8) {
499 for (mask = dga_device->mode.redMask, red_shift = 0; (mask & 1) == 0;
500 mask >>= 1, red_shift++);
501 for (mask = dga_device->mode.greenMask, green_shift = 0; (mask & 1) == 0;
502 mask >>= 1, green_shift++);
503 for (mask = dga_device->mode.blueMask, blue_shift = 0; (mask & 1) == 0;
504 mask >>= 1, blue_shift++);
505 }
506 switch (depth) {
507
508 case 15:
509 _rgb_r_shift_15 = red_shift;
510 _rgb_g_shift_15 = green_shift;
511 _rgb_b_shift_15 = blue_shift;
512 break;
513
514 case 16:
515 _rgb_r_shift_16 = red_shift;
516 _rgb_g_shift_16 = green_shift;
517 _rgb_b_shift_16 = blue_shift;
518 break;
519
520 case 24:
521 _rgb_r_shift_24 = red_shift;
522 _rgb_g_shift_24 = green_shift;
523 _rgb_b_shift_24 = blue_shift;
524 break;
525
526 case 32:
527 _rgb_r_shift_32 = red_shift;
528 _rgb_g_shift_32 = green_shift;
529 _rgb_b_shift_32 = blue_shift;
530 break;
531 }
532
533 /* Enables input */
534 XSync(_xwin.display, True);
535 input_mask = KeyPressMask | KeyReleaseMask | ButtonPressMask
536 | ButtonReleaseMask | PointerMotionMask;
537 XDGASelectInput(_xwin.display, _xwin.screen, input_mask);
538 if (_xwin_keyboard_focused) {
539 (*_xwin_keyboard_focused)(FALSE, 0);
540 keyboard_got_focus = TRUE;
541 }
542 _mouse_on = TRUE;
543
544 /* Creates screen bitmap */
545 drv->linear = TRUE;
546 bmp = _make_bitmap(dga_device->mode.imageWidth, dga_device->mode.imageHeight,
547 (uintptr_t)dga_device->data, drv, depth,
548 dga_device->mode.bytesPerScanline);
549 if (!bmp) {
550 ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Not enough memory"));
551 return NULL;
552 }
553 drv->w = bmp->cr = w;
554 drv->h = bmp->cb = h;
555 drv->vid_mem = dga_device->mode.imageWidth * dga_device->mode.imageHeight
556 * BYTES_PER_PIXEL(depth);
557
558 if (accel) {
559 /* Hardware acceleration has been requested */
560
561 /* Updates line switcher to accommodate framebuffer synchronization */
562 #ifdef ALLEGRO_NO_ASM
563 bmp->write_bank = _xdga2_write_line;
564 bmp->read_bank = _xdga2_write_line;
565 #else
566 bmp->write_bank = _xdga2_write_line_asm;
567 bmp->read_bank = _xdga2_write_line_asm;
568 #endif
569
570 _screen_vtable.acquire = _xdga2_acquire;
571
572 /* Checks for hardware acceleration support */
573 if (dga_device->mode.flags & XDGASolidFillRect) {
574 /* XDGAFillRectangle is available */
575 _orig_hline = _screen_vtable.hline;
576 _orig_vline = _screen_vtable.vline;
577 _orig_rectfill = _screen_vtable.rectfill;
578 _screen_vtable.hline = _xaccel_hline;
579 _screen_vtable.vline = _xaccel_vline;
580 _screen_vtable.rectfill = _xaccel_rectfill;
581 _screen_vtable.clear_to_color = _xaccel_clear_to_color;
582 gfx_capabilities |= (GFX_HW_HLINE | GFX_HW_FILL);
583 }
584 if (dga_device->mode.flags & XDGABlitRect) {
585 /* XDGACopyArea is available */
586 _screen_vtable.blit_to_self = _xaccel_blit_to_self;
587 _screen_vtable.blit_to_self_forward = _xaccel_blit_to_self;
588 _screen_vtable.blit_to_self_backward = _xaccel_blit_to_self;
589 gfx_capabilities |= GFX_HW_VRAM_BLIT;
590 }
591 if (dga_device->mode.flags & XDGABlitTransRect) {
592 /* XDGACopyTransparentArea is available */
593 _orig_draw_sprite = _screen_vtable.draw_sprite;
594 _orig_masked_blit = _screen_vtable.masked_blit;
595 _screen_vtable.masked_blit = _xaccel_masked_blit;
596 _screen_vtable.draw_sprite = _xaccel_draw_sprite;
597 if (_screen_vtable.color_depth == 8)
598 _screen_vtable.draw_256_sprite = _xaccel_draw_sprite;
599 gfx_capabilities |= GFX_HW_VRAM_BLIT_MASKED;
600 }
601
602 RESYNC();
603 }
604
605 /* Checks for triple buffering */
606 if (dga_device->mode.viewportFlags & XDGAFlipRetrace)
607 gfx_capabilities |= GFX_CAN_TRIPLE_BUFFER;
608
609 /* Sets up driver description */
610 uszprintf(_xdga2_driver_desc, sizeof(_xdga2_driver_desc),
611 uconvert_ascii("X-Windows DGA 2.0 graphics%s", tmp1),
612 uconvert_ascii(accel ? (gfx_capabilities ? " (accelerated)" : "") : " (software only)", tmp2));
613 drv->desc = _xdga2_driver_desc;
614
615 return bmp;
616 }
617
_xdga2_gfxdrv_init_drv(GFX_DRIVER * drv,int w,int h,int vw,int vh,int depth,int accel)618 static BITMAP *_xdga2_gfxdrv_init_drv(GFX_DRIVER *drv, int w, int h, int vw, int vh, int depth, int accel)
619 {
620 BITMAP *bmp;
621 XLOCK();
622 bmp = _xdga2_private_gfxdrv_init_drv(drv, w, h, vw, vh, depth, accel);
623 XUNLOCK();
624 if (!bmp)
625 _xdga2_gfxdrv_exit(bmp);
626 else
627 _xwin_input_handler = _xdga2_handle_input;
628 return bmp;
629 }
630
631
632
633 /* _xdga2_gfxdrv_init:
634 * Creates screen bitmap.
635 */
_xdga2_gfxdrv_init(int w,int h,int vw,int vh,int color_depth)636 static BITMAP *_xdga2_gfxdrv_init(int w, int h, int vw, int vh, int color_depth)
637 {
638 return _xdga2_gfxdrv_init_drv(&gfx_xdga2, w, h, vw, vh, color_depth, TRUE);
639 }
640
641
642
643 /* _xdga2_soft_gfxdrv_init:
644 * Creates screen bitmap (software only mode).
645 */
_xdga2_soft_gfxdrv_init(int w,int h,int vw,int vh,int color_depth)646 static BITMAP *_xdga2_soft_gfxdrv_init(int w, int h, int vw, int vh, int color_depth)
647 {
648 return _xdga2_gfxdrv_init_drv(&gfx_xdga2_soft, w, h, vw, vh, color_depth, FALSE);
649 }
650
651
652
653 /* _xdga2_gfxdrv_exit:
654 * Shuts down gfx driver.
655 */
_xdga2_gfxdrv_exit(BITMAP * bmp)656 static void _xdga2_gfxdrv_exit(BITMAP *bmp)
657 {
658 XLOCK();
659
660 if (_xwin.in_dga_mode) {
661 _xwin_input_handler = 0;
662
663 XDGACloseFramebuffer(_xwin.display, _xwin.screen);
664 XDGASetMode(_xwin.display, _xwin.screen, 0);
665 _xwin.in_dga_mode = 0;
666
667 if (_dga_cmap) {
668 XFreeColormap(_xwin.display, _dga_cmap);
669 _dga_cmap = 0;
670 }
671
672 XInstallColormap(_xwin.display, _xwin.colormap);
673
674 set_display_switch_mode(SWITCH_BACKGROUND);
675 }
676
677 XUNLOCK();
678 }
679
680
681
682 /* _xdga2_poll_scroll:
683 * Returns true if there are pending scrolling requests left.
684 */
_xdga2_poll_scroll(void)685 static int _xdga2_poll_scroll(void)
686 {
687 int result;
688
689 XLOCK();
690 result = XDGAGetViewportStatus(_xwin.display, _xwin.screen);
691 XUNLOCK();
692 return result;
693 }
694
695
696
697 /* _xdga2_request_scroll:
698 * Starts a screen scroll but doesn't wait for the retrace.
699 */
_xdga2_request_scroll(int x,int y)700 static int _xdga2_request_scroll(int x, int y)
701 {
702 XLOCK();
703
704 if (x < 0) x = 0;
705 else if (x > dga_device->mode.maxViewportX)
706 x = dga_device->mode.maxViewportX;
707 if (y < 0) y = 0;
708 else if (y > dga_device->mode.maxViewportY)
709 y = dga_device->mode.maxViewportY;
710
711 XDGASetViewport(_xwin.display, _xwin.screen, x, y, XDGAFlipRetrace);
712
713 XUNLOCK();
714
715 return 0;
716 }
717
718
719
720 /* _xdga2_request_video_bitmap:
721 * Page flips to display specified bitmap, but doesn't wait for retrace.
722 */
_xdga2_request_video_bitmap(BITMAP * bmp)723 static int _xdga2_request_video_bitmap(BITMAP *bmp)
724 {
725 XLOCK();
726 XDGASetViewport(_xwin.display, _xwin.screen, bmp->x_ofs, bmp->y_ofs, XDGAFlipRetrace);
727 XUNLOCK();
728 return 0;
729 }
730
731
732
733 /* _xdga2_scroll_screen:
734 * Scrolls DGA viewport.
735 */
_xdga2_scroll_screen(int x,int y)736 static int _xdga2_scroll_screen(int x, int y)
737 {
738 if (x < 0) x = 0;
739 else if (x > dga_device->mode.maxViewportX)
740 x = dga_device->mode.maxViewportX;
741 if (y < 0) y = 0;
742 else if (y > dga_device->mode.maxViewportY)
743 y = dga_device->mode.maxViewportY;
744 if ((_xwin.scroll_x == x) && (_xwin.scroll_y == y))
745 return 0;
746
747 XLOCK();
748
749 _xwin.scroll_x = x;
750 _xwin.scroll_y = y;
751
752 if (_wait_for_vsync)
753 while (XDGAGetViewportStatus(_xwin.display, _xwin.screen))
754 ;
755
756 XDGASetViewport(_xwin.display, _xwin.screen, x, y, XDGAFlipRetrace);
757
758 XUNLOCK();
759
760 return 0;
761 }
762
763
764
765 /* _xdga2_set_palette_range:
766 * Sets palette entries.
767 */
_xdga2_set_palette_range(AL_CONST PALETTE p,int from,int to,int vsync)768 static void _xdga2_set_palette_range(AL_CONST PALETTE p, int from, int to, int vsync)
769 {
770 int i;
771 static XColor color[256];
772
773 XLOCK();
774
775 if (vsync) {
776 XSync(_xwin.display, False);
777 }
778
779 if (dga_device->mode.depth == 8) {
780 for (i = from; i <= to; i++) {
781 color[i].flags = DoRed | DoGreen | DoBlue;
782 color[i].pixel = i;
783 color[i].red = ((p[i].r & 0x3F) * 65535L) / 0x3F;
784 color[i].green = ((p[i].g & 0x3F) * 65535L) / 0x3F;
785 color[i].blue = ((p[i].b & 0x3F) * 65535L) / 0x3F;
786 }
787 XStoreColors(_xwin.display, _dga_cmap, color + from, to - from + 1);
788 XSync(_xwin.display, False);
789 }
790
791 XUNLOCK();
792 }
793
794
795
796 /* _xdga2_lock:
797 * Synchronizes with framebuffer.
798 */
_xdga2_lock(BITMAP * bmp)799 void _xdga2_lock(BITMAP *bmp)
800 {
801 XLOCK();
802 RESYNC();
803 XUNLOCK();
804 bmp->id |= BMP_ID_LOCKED;
805 }
806
807
808
809 /* _xdga2_acquire:
810 * Video bitmap acquire function; synchronizes with framebuffer if needed.
811 */
_xdga2_acquire(BITMAP * bmp)812 static void _xdga2_acquire(BITMAP *bmp)
813 {
814 if (!(bmp->id & BMP_ID_LOCKED))
815 _xdga2_lock(bmp);
816 }
817
818
819 #ifdef ALLEGRO_NO_ASM
820
821 /* _xdga2_write_line:
822 * Returns new line and synchronizes framebuffer if needed.
823 */
_xdga2_write_line(BITMAP * bmp,int line)824 uintptr_t _xdga2_write_line(BITMAP *bmp, int line)
825 {
826 if (!(bmp->id & BMP_ID_LOCKED))
827 _xdga2_lock(bmp);
828
829 return (uintptr_t)(bmp->line[line]);
830 }
831
832 #endif
833
834
835 /* _xaccel_hline:
836 * Accelerated hline.
837 */
_xaccel_hline(BITMAP * bmp,int x1,int y,int x2,int color)838 static void _xaccel_hline(BITMAP *bmp, int x1, int y, int x2, int color)
839 {
840 int tmp;
841
842 if (_drawing_mode != DRAW_MODE_SOLID) {
843 _orig_hline(bmp, x1, y, x2, color);
844 return;
845 }
846
847 if (x1 > x2) {
848 tmp = x1;
849 x1 = x2;
850 x2 = tmp;
851 }
852
853 if (bmp->clip) {
854 if ((y < bmp->ct) || (y >= bmp->cb))
855 return;
856
857 if (x1 < bmp->cl)
858 x1 = bmp->cl;
859
860 if (x2 >= bmp->cr)
861 x2 = bmp->cr-1;
862
863 if (x2 < x1)
864 return;
865 }
866
867 x1 += bmp->x_ofs;
868 y += bmp->y_ofs;
869 x2 += bmp->x_ofs;
870
871 XLOCK();
872 XDGAFillRectangle(_xwin.display, _xwin.screen, x1, y, (x2 - x1) + 1, 1, color);
873 XUNLOCK();
874 bmp->id &= ~BMP_ID_LOCKED;
875 }
876
877
878
879 /* _xaccel_vline:
880 * Accelerated vline.
881 */
_xaccel_vline(BITMAP * bmp,int x,int y1,int y2,int color)882 static void _xaccel_vline(BITMAP *bmp, int x, int y1, int y2, int color)
883 {
884 int tmp;
885
886 if (_drawing_mode != DRAW_MODE_SOLID) {
887 _orig_vline(bmp, x, y1, y2, color);
888 return;
889 }
890
891 if (y1 > y2) {
892 tmp = y1;
893 y1 = y2;
894 y2 = tmp;
895 }
896
897 if (bmp->clip) {
898 if ((x < bmp->cl) || (x >= bmp->cr))
899 return;
900
901 if (y1 < bmp->ct)
902 y1 = bmp->ct;
903
904 if (y2 >= bmp->cb)
905 y2 = bmp->cb-1;
906
907 if (y2 < y1)
908 return;
909 }
910
911 x += bmp->x_ofs;
912 y1 += bmp->y_ofs;
913 y2 += bmp->y_ofs;
914
915 XLOCK();
916 XDGAFillRectangle(_xwin.display, _xwin.screen, x, y1, 1, (y2 - y1) + 1, color);
917 XUNLOCK();
918 bmp->id &= ~BMP_ID_LOCKED;
919 }
920
921
922
923 /* _xaccel_rectfill:
924 * Accelerated rectfill.
925 */
_xaccel_rectfill(BITMAP * bmp,int x1,int y1,int x2,int y2,int color)926 static void _xaccel_rectfill(BITMAP *bmp, int x1, int y1, int x2, int y2, int color)
927 {
928 int tmp;
929
930 if (_drawing_mode != DRAW_MODE_SOLID) {
931 _orig_rectfill(bmp, x1, y1, x2, y2, color);
932 return;
933 }
934
935 if (x2 < x1) {
936 tmp = x1;
937 x1 = x2;
938 x2 = tmp;
939 }
940
941 if (y2 < y1) {
942 tmp = y1;
943 y1 = y2;
944 y2 = tmp;
945 }
946
947 if (bmp->clip) {
948 if (x1 < bmp->cl)
949 x1 = bmp->cl;
950
951 if (x2 >= bmp->cr)
952 x2 = bmp->cr-1;
953
954 if (x2 < x1)
955 return;
956
957 if (y1 < bmp->ct)
958 y1 = bmp->ct;
959
960 if (y2 >= bmp->cb)
961 y2 = bmp->cb-1;
962
963 if (y2 < y1)
964 return;
965 }
966
967 x1 += bmp->x_ofs;
968 y1 += bmp->y_ofs;
969 x2 += bmp->x_ofs;
970 y2 += bmp->y_ofs;
971
972 XLOCK();
973 XDGAFillRectangle(_xwin.display, _xwin.screen, x1, y1, (x2 - x1) + 1, (y2 - y1) + 1, color);
974 XUNLOCK();
975 bmp->id &= ~BMP_ID_LOCKED;
976 }
977
978
979
980 /* _xaccel_clear_to_color:
981 * Accelerated clear_to_color.
982 */
_xaccel_clear_to_color(BITMAP * bmp,int color)983 static void _xaccel_clear_to_color(BITMAP *bmp, int color)
984 {
985 int x1, y1, x2, y2;
986
987 x1 = bmp->cl + bmp->x_ofs;
988 y1 = bmp->ct + bmp->y_ofs;
989 x2 = bmp->cr + bmp->x_ofs;
990 y2 = bmp->cb + bmp->y_ofs;
991
992 XLOCK();
993 XDGAFillRectangle(_xwin.display, _xwin.screen, x1, y1, x2 - x1, y2 - y1, color);
994 XUNLOCK();
995 bmp->id &= ~BMP_ID_LOCKED;
996 }
997
998
999
1000 /* _xaccel_blit_to_self:
1001 * Accelerated vram -> vram blit.
1002 */
_xaccel_blit_to_self(BITMAP * source,BITMAP * dest,int source_x,int source_y,int dest_x,int dest_y,int width,int height)1003 static void _xaccel_blit_to_self(BITMAP *source, BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height)
1004 {
1005 source_x += source->x_ofs;
1006 source_y += source->y_ofs;
1007 dest_x += dest->x_ofs;
1008 dest_y += dest->y_ofs;
1009
1010 XLOCK();
1011 XDGACopyArea(_xwin.display, _xwin.screen, source_x, source_y, width, height, dest_x, dest_y);
1012 XUNLOCK();
1013 dest->id &= ~BMP_ID_LOCKED;
1014 }
1015
1016
1017
1018 /* _xaccel_draw_sprite:
1019 * Accelerated draw_sprite.
1020 */
_xaccel_draw_sprite(BITMAP * bmp,BITMAP * sprite,int x,int y)1021 static void _xaccel_draw_sprite(BITMAP *bmp, BITMAP *sprite, int x, int y)
1022 {
1023 int sx, sy, w, h;
1024
1025 if (is_video_bitmap(sprite)) {
1026 sx = 0;
1027 sy = 0;
1028 w = sprite->w;
1029 h = sprite->h;
1030
1031 if (bmp->clip) {
1032 if (x < bmp->cl) {
1033 sx += bmp->cl - x;
1034 w -= bmp->cl - x;
1035 x = bmp->cl;
1036 }
1037
1038 if (y < bmp->ct) {
1039 sy += bmp->ct - y;
1040 h -= bmp->ct - y;
1041 y = bmp->ct;
1042 }
1043
1044 if (x + w > bmp->cr)
1045 w = bmp->cr - x;
1046
1047 if (w <= 0)
1048 return;
1049
1050 if (y + h > bmp->cb)
1051 h = bmp->cb - y;
1052
1053 if (h <= 0)
1054 return;
1055 }
1056
1057 sx += sprite->x_ofs;
1058 sy += sprite->y_ofs;
1059 x += bmp->x_ofs;
1060 y += bmp->y_ofs;
1061
1062 XLOCK();
1063 XDGACopyTransparentArea(_xwin.display, _xwin.screen, sx, sy, w, h, x, y, sprite->vtable->mask_color);
1064 XUNLOCK();
1065 bmp->id &= ~BMP_ID_LOCKED;
1066 }
1067 else
1068 _orig_draw_sprite(bmp, sprite, x, y);
1069 }
1070
1071
1072
1073 /* _xaccel_masked_blit:
1074 * Accelerated masked_blit.
1075 */
_xaccel_masked_blit(BITMAP * source,BITMAP * dest,int source_x,int source_y,int dest_x,int dest_y,int width,int height)1076 static void _xaccel_masked_blit(BITMAP *source, BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height)
1077 {
1078 if (is_video_bitmap(source)) {
1079 source_x += source->x_ofs;
1080 source_y += source->y_ofs;
1081 dest_x += dest->x_ofs;
1082 dest_y += dest->y_ofs;
1083
1084 XLOCK();
1085 XDGACopyTransparentArea(_xwin.display, _xwin.screen, source_x, source_y, width, height, dest_x, dest_y, source->vtable->mask_color);
1086 XUNLOCK();
1087 dest->id &= ~BMP_ID_LOCKED;
1088 }
1089 else
1090 _orig_masked_blit(source, dest, source_x, source_y, dest_x, dest_y, width, height);
1091 }
1092
1093
1094
1095 #ifdef ALLEGRO_MODULE
1096
1097 /* _module_init:
1098 * Called when loaded as a dynamically linked module.
1099 */
_module_init(int system_driver)1100 void _module_init(int system_driver)
1101 {
1102 if (system_driver != SYSTEM_XWINDOWS) return;
1103 _unix_register_gfx_driver(GFX_XDGA2_SOFT, &gfx_xdga2_soft, FALSE, FALSE);
1104 _unix_register_gfx_driver(GFX_XDGA2, &gfx_xdga2, FALSE, FALSE);
1105 }
1106
1107 #endif
1108
1109
1110 #endif
1111