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