00001
00002
00003
00004
00005
00006 #include <string.h>
00007
00008 #include <allegro.h>
00009 #include <xalleg.h>
00010
00011 #include <allegro/platform/aintunix.h>
00012
00013 #include "alleggl.h"
00014 #include "allglint.h"
00015 #include "glvtable.h"
00016
00017
00018 #ifndef XLOCK
00019 #define OLD_ALLEGRO
00020 #define XLOCK() DISABLE()
00021 #undef XUNLOCK
00022 #define XUNLOCK() ENABLE()
00023 #endif
00024
00025
00026 static BITMAP *allegro_gl_x_windowed_init(int w, int h, int vw, int vh,
00027 int color_depth);
00028 static void allegro_gl_x_exit(BITMAP *bmp);
00029 static GFX_MODE_LIST* allegro_gl_x_fetch_mode_list(void);
00030 static void allegro_gl_x_vsync(void);
00031
00032
00033 #ifdef ALLEGROGL_HAVE_XF86VIDMODE
00034 static BITMAP *allegro_gl_x_fullscreen_init(int w, int h, int vw, int vh,
00035 int color_depth);
00036
00037 GFX_DRIVER gfx_allegro_gl_fullscreen =
00038 {
00039 GFX_OPENGL_FULLSCREEN,
00040 empty_string,
00041 empty_string,
00042 "AllegroGL Fullscreen (X)",
00043 allegro_gl_x_fullscreen_init,
00044 allegro_gl_x_exit,
00045 NULL,
00046 allegro_gl_x_vsync,
00047 NULL,
00048 NULL, NULL, NULL,
00049 allegro_gl_create_video_bitmap,
00050 allegro_gl_destroy_video_bitmap,
00051 NULL, NULL,
00052 NULL, NULL,
00053 allegro_gl_set_mouse_sprite,
00054 allegro_gl_show_mouse,
00055 allegro_gl_hide_mouse,
00056 allegro_gl_move_mouse,
00057 NULL,
00058 NULL, NULL,
00059 allegro_gl_x_fetch_mode_list,
00060 0, 0,
00061 0,
00062 0, 0,
00063 0,
00064 0,
00065 FALSE
00066 };
00067 #endif
00068
00069
00070
00071 GFX_DRIVER gfx_allegro_gl_windowed =
00072 {
00073 GFX_OPENGL_WINDOWED,
00074 empty_string,
00075 empty_string,
00076 "AllegroGL Windowed (X)",
00077 allegro_gl_x_windowed_init,
00078 allegro_gl_x_exit,
00079 NULL,
00080 allegro_gl_x_vsync,
00081 NULL,
00082 NULL, NULL, NULL,
00083 allegro_gl_create_video_bitmap,
00084 allegro_gl_destroy_video_bitmap,
00085 NULL, NULL,
00086 NULL, NULL,
00087 allegro_gl_set_mouse_sprite,
00088 allegro_gl_show_mouse,
00089 allegro_gl_hide_mouse,
00090 allegro_gl_move_mouse,
00091 NULL,
00092 NULL, NULL,
00093 NULL,
00094 0, 0,
00095 0,
00096 0, 0,
00097 0,
00098 0,
00099 TRUE
00100 };
00101
00102
00103
00104 static struct allegro_gl_driver allegro_gl_x;
00105
00106 static XVisualInfo *allegro_gl_x_windowed_choose_visual (void);
00107 static int allegro_gl_x_create_window (int fullscreen);
00108 static BITMAP *allegro_gl_x_windowed_create_screen (GFX_DRIVER *drv, int w, int h, int depth);
00109
00110 static int decode_visual (XVisualInfo *v, struct allegro_gl_display_info *i);
00111 struct {
00112 int fullscreen;
00113 GLXContext ctx;
00114 int major, minor;
00115 int error_base, event_base;
00116 } _glxwin;
00117
00118 static void (*old_window_redrawer)(int, int, int, int);
00119 extern void (*_xwin_window_redrawer)(int, int, int, int);
00120 static int (*old_x_error_handler)(Display*, XErrorEvent*);
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131 static void allegro_gl_redraw_window(int x, int y, int w, int h)
00132 {
00133
00134 return;
00135 }
00136
00137
00138
00139
00140
00141
00142 static BITMAP *allegro_gl_x_create_screen(int w, int h, int vw, int vh,
00143 int depth, int fullscreen)
00144 {
00145 int _keyboard_was_installed = FALSE;
00146 int _mouse_was_installed = FALSE;
00147
00148
00149 if (!_unix_bg_man->multi_threaded) {
00150 ustrzcpy (allegro_gl_error, AGL_ERROR_SIZE,
00151 get_config_text("Fatal Error : pthread support is not enabled"));
00152 return NULL;
00153 }
00154
00155 if (keyboard_driver) {
00156 _keyboard_was_installed = TRUE;
00157 remove_keyboard();
00158 TRACE("* Note * x_create_screen: Removing Keyboard...\n");
00159 }
00160
00161 if (mouse_driver) {
00162 _mouse_was_installed = TRUE;
00163 remove_mouse();
00164 TRACE("* Note * x_create_screen: Removing Mouse...\n");
00165 }
00166
00167 XLOCK();
00168
00169 if (!glXQueryExtension(_xwin.display, &_glxwin.error_base,
00170 &_glxwin.event_base)) {
00171
00172 ustrzcpy (allegro_error, ALLEGRO_ERROR_SIZE,
00173 get_config_text("GLX Extension not supported by display"));
00174 XUNLOCK();
00175 goto failure;
00176 }
00177
00178 if ((w == 0) && (h == 0)) {
00179 w = 640;
00180 h = 480;
00181 }
00182
00183 if ((vw > w) || (vh > h)) {
00184 ustrzcpy (allegro_error, ALLEGRO_ERROR_SIZE,
00185 get_config_text ("OpenGL drivers do not support virtual screens"));
00186 XUNLOCK();
00187 goto failure;
00188 }
00189
00190 allegro_gl_display_info.w = w;
00191 allegro_gl_display_info.h = h;
00192
00193 old_window_redrawer = _xwin_window_redrawer;
00194 _xwin_window_redrawer = allegro_gl_redraw_window;
00195 _glxwin.fullscreen = FALSE;
00196
00197 if (allegro_gl_x_create_window(fullscreen)) {
00198 if (fullscreen) {
00199 ustrzcpy (allegro_error, ALLEGRO_ERROR_SIZE,
00200 get_config_text ("Unable to switch in GLX fullscreen"));
00201 }
00202 else {
00203 ustrzcpy (allegro_error, ALLEGRO_ERROR_SIZE,
00204 get_config_text ("Unable to create GLX window"));
00205 }
00206 XUNLOCK();
00207 allegro_gl_x_exit(NULL);
00208 goto failure;
00209 }
00210
00211
00212 set_color_depth(allegro_gl_display_info.colour_depth);
00213
00214
00215
00216
00217
00218 __allegro_gl_set_allegro_image_format(FALSE);
00219
00220 if (fullscreen) {
00221 #ifdef ALLEGROGL_HAVE_XF86VIDMODE
00222 allegro_gl_screen =
00223 allegro_gl_x_windowed_create_screen (&gfx_allegro_gl_fullscreen,
00224 allegro_gl_display_info.w, allegro_gl_display_info.h,
00225 _color_depth);
00226 #endif
00227 }
00228 else {
00229 allegro_gl_screen =
00230 allegro_gl_x_windowed_create_screen (&gfx_allegro_gl_windowed,
00231 allegro_gl_display_info.w, allegro_gl_display_info.h,
00232 _color_depth);
00233 }
00234
00235 if (!allegro_gl_screen) {
00236 ustrzcpy (allegro_error, ALLEGRO_ERROR_SIZE,
00237 get_config_text ("Error creating screen bitmap"));
00238 XUNLOCK();
00239 allegro_gl_x_exit(NULL);
00240 goto failure;
00241 }
00242
00243 XUNLOCK();
00244
00245 __allegro_gl_valid_context = TRUE;
00246 __allegro_gl_driver = &allegro_gl_x;
00247
00248
00249 TRACE("\n\nOpenGL Version: %s\nVendor: %s\nRenderer: %s\n",
00250 (AL_CONST char*)glGetString(GL_VERSION),
00251 (AL_CONST char*)glGetString(GL_VENDOR),
00252 (AL_CONST char*)glGetString(GL_RENDERER));
00253
00254
00255 allegro_gl_info.is_mesa_driver = FALSE;
00256 if (strstr((AL_CONST char*)glGetString(GL_VERSION),"Mesa")) {
00257 AGL_LOG(1, "OpenGL driver based on Mesa\n");
00258 allegro_gl_info.is_mesa_driver = TRUE;
00259 }
00260
00261
00262 glXQueryVersion(_xwin.display, &_glxwin.major, &_glxwin.minor);
00263 TRACE("GLX Version: %d.%d\n", _glxwin.major, _glxwin.minor);
00264
00265 #ifdef LOGLEVEL
00266 if (glXIsDirect(_xwin.display, _glxwin.ctx)) {
00267 AGL_LOG(1, "GLX Direct Rendering is enabled\n\n");
00268 }
00269 else {
00270 AGL_LOG(1, "GLX Direct Rendering is disabled\n\n");
00271 }
00272 #endif
00273
00274
00275 AGL_LOG(1, "glX Extensions :\n");
00276 #ifdef LOGLEVEL
00277 __allegro_gl_print_extensions(
00278 (AL_CONST char*)glXQueryExtensionsString(_xwin.display, _xwin.screen));
00279 #endif
00280
00281 __allegro_gl_manage_extensions();
00282
00283
00284 __allegro_gl__glvtable_update_vtable (&allegro_gl_screen->vtable);
00285 __allegro_gl_init_screen_mode();
00286 memcpy(&_screen_vtable, allegro_gl_screen->vtable, sizeof(GFX_VTABLE));
00287 allegro_gl_screen->vtable = &_screen_vtable;
00288
00289 if (_keyboard_was_installed) {
00290 install_keyboard();
00291 TRACE("* Note * x_create_screen: Installing Keyboard...\n");
00292 }
00293
00294 if (_mouse_was_installed) {
00295 install_mouse();
00296 TRACE("* Note * x_create_screen: Installing Mouse...\n");
00297 }
00298 gfx_capabilities |= GFX_HW_CURSOR;
00299
00300 return allegro_gl_screen;
00301
00302 failure:
00303 if (_keyboard_was_installed) {
00304 install_keyboard();
00305 }
00306
00307 if (_mouse_was_installed) {
00308 install_mouse();
00309 }
00310
00311 return NULL;
00312 }
00313
00314
00315
00316
00317
00318
00319 static BITMAP *allegro_gl_x_windowed_init(int w, int h, int vw, int vh,
00320 int depth)
00321 {
00322 return allegro_gl_x_create_screen(w, h, vw, vh, depth, FALSE);
00323 }
00324
00325
00326
00327 #ifdef ALLEGROGL_HAVE_XF86VIDMODE
00328
00329
00330
00331 static BITMAP *allegro_gl_x_fullscreen_init(int w, int h, int vw, int vh,
00332 int depth)
00333 {
00334 return allegro_gl_x_create_screen(w, h, vw, vh, depth, TRUE);
00335 }
00336
00337
00338
00339
00340
00341
00342 static void free_modelines(XF86VidModeModeInfo **modesinfo, int num_modes)
00343 {
00344 int i;
00345
00346 for (i = 0; i < num_modes; i++)
00347 if (modesinfo[i]->privsize > 0)
00348 XFree(modesinfo[i]->private);
00349 XFree(modesinfo);
00350 }
00351 #endif
00352
00353
00354
00355
00356
00357
00358 static void allegro_gl_x_exit(BITMAP *bmp)
00359 {
00360 #ifdef ALLEGROGL_HAVE_XF86VIDMODE
00361 XSetWindowAttributes setattr;
00362 #endif
00363
00364
00365
00366 glXWaitGL();
00367 XLOCK();
00368
00369 __allegro_gl_unmanage_extensions();
00370
00371 if (_glxwin.ctx) {
00372 if (!allegro_gl_info.is_ati_r200_chip) {
00373
00374
00375
00376
00377
00378
00379
00380
00381 if (!glXMakeCurrent(_xwin.display, None, NULL)) {
00382 ustrzcpy (allegro_error, ALLEGRO_ERROR_SIZE,
00383 get_config_text ("Could not release drawing context.\n"));
00384 }
00385 }
00386
00387 glXDestroyContext(_xwin.display, _glxwin.ctx);
00388 _glxwin.ctx = NULL;
00389 }
00390
00391 if (_xwin.mouse_grabbed) {
00392 XUngrabPointer(_xwin.display, CurrentTime);
00393 _xwin.mouse_grabbed = 0;
00394 }
00395
00396 if (_xwin.keyboard_grabbed) {
00397 XUngrabKeyboard(_xwin.display, CurrentTime);
00398 _xwin.keyboard_grabbed = 0;
00399 }
00400
00401 #ifdef ALLEGROGL_HAVE_XF86VIDMODE
00402 if (_glxwin.fullscreen) {
00403 if (_xwin.mode_switched) {
00404 XF86VidModeLockModeSwitch(_xwin.display, _xwin.screen, False);
00405 XF86VidModeSwitchToMode(_xwin.display, _xwin.screen,
00406 _xwin.modesinfo[0]);
00407 XF86VidModeSetViewPort(_xwin.display, _xwin.screen, 0, 0);
00408 _xwin.mode_switched = 0;
00409 }
00410 if (_xwin.override_redirected) {
00411 setattr.override_redirect = False;
00412 XChangeWindowAttributes(_xwin.display, _xwin.window,
00413 CWOverrideRedirect, &setattr);
00414 _xwin.override_redirected = 0;
00415 }
00416
00417
00418 free_modelines(_xwin.modesinfo, _xwin.num_modes);
00419 _xwin.num_modes = 0;
00420 _xwin.modesinfo = NULL;
00421 }
00422 #endif
00423 __allegro_gl_release_screen();
00424
00425
00426
00427
00428 XUnmapWindow(_xwin.display, _xwin.window);
00429
00430 __allegro_gl_valid_context = FALSE;
00431
00432 _xwin_window_redrawer = old_window_redrawer;
00433 XSetErrorHandler(old_x_error_handler);
00434
00435 XUNLOCK();
00436 }
00437
00438
00439
00440
00441
00442
00443 static XVisualInfo *allegro_gl_x_windowed_choose_visual (void)
00444 {
00445 int num_visuals, i;
00446 XVisualInfo *vinfo;
00447 struct allegro_gl_display_info dinfo;
00448 static XVisualInfo ret_vinfo;
00449
00450 vinfo = XGetVisualInfo (_xwin.display, 0, NULL, &num_visuals);
00451 if (!vinfo) return NULL;
00452
00453 TRACE("* Note * x_windowed_choose_visual: %i formats.\n", num_visuals);
00454 __allegro_gl_reset_scorer();
00455
00456 for (i = 0; i < num_visuals; i++) {
00457 TRACE("* Note * x_windowed_choose_visual: Mode %i\n", i);
00458 if (decode_visual (vinfo + i, &dinfo) != -1) {
00459 __allegro_gl_score_config (i, &dinfo);
00460 }
00461 }
00462
00463 i = __allegro_gl_best_config();
00464 TRACE("* Note * x_windowed_choose_visual: Best config is: %i\n", i);
00465
00466 if (i < 0) return NULL;
00467
00468 memcpy (&ret_vinfo, vinfo+i, sizeof ret_vinfo);
00469 XFree (vinfo);
00470
00471 return &ret_vinfo;
00472 }
00473
00474
00475
00476 #ifdef ALLEGROGL_HAVE_XF86VIDMODE
00477
00478
00479
00480
00481 static int get_xf86_modes(XF86VidModeModeInfo ***modesinfo, int *num_modes)
00482 {
00483 int vid_event_base, vid_error_base;
00484 int vid_major_version, vid_minor_version;
00485
00486
00487 if (!XF86VidModeQueryExtension(_xwin.display, &vid_event_base,
00488 &vid_error_base)
00489 || !XF86VidModeQueryVersion(_xwin.display, &vid_major_version,
00490 &vid_minor_version)) {
00491
00492 ustrzcpy (allegro_gl_error, AGL_ERROR_SIZE,
00493 get_config_text("VidMode extension is not supported"));
00494 return -1;
00495 }
00496
00497 if (!XF86VidModeGetAllModeLines(_xwin.display, _xwin.screen, num_modes,
00498 modesinfo)) {
00499 ustrzcpy (allegro_gl_error, AGL_ERROR_SIZE,
00500 get_config_text("Can not Get ModeLines"));
00501 return -1;
00502 }
00503
00504 return 0;
00505 }
00506 #endif
00507
00508
00509 static int allegro_gl_x_error_handler(Display *display, XErrorEvent *err_event)
00510 {
00511 char buffer[256];
00512
00513 XGetErrorText(display, err_event->error_code, buffer, 256);
00514 TRACE("X Error caught : %s\n", buffer);
00515 return 0;
00516 }
00517
00518
00519
00520
00521
00522
00523
00524 static int allegro_gl_x_create_window (int fullscreen)
00525 {
00526 Window root;
00527 XVisualInfo *visinfo;
00528 XSetWindowAttributes setattr;
00529 unsigned long valuemask = CWBackPixel | CWBorderPixel | CWColormap
00530 | CWEventMask;
00531 XSizeHints *hints;
00532 #ifdef ALLEGROGL_HAVE_XF86VIDMODE
00533 int bestmode=0;
00534 #endif
00535
00536 if (_xwin.display == 0) {
00537 return -1;
00538 }
00539
00540 old_x_error_handler = XSetErrorHandler(allegro_gl_x_error_handler);
00541
00542
00543 __allegro_gl_fill_in_info();
00544
00545 #ifdef ALLEGROGL_HAVE_XF86VIDMODE
00546 if (fullscreen) {
00547 int i;
00548 _xwin.num_modes = 0;
00549 _xwin.modesinfo = NULL;
00550 _glxwin.fullscreen = TRUE;
00551
00552 if (get_xf86_modes(&_xwin.modesinfo, &_xwin.num_modes)) {
00553 TRACE("** ERROR ** x_create_window: Can't get XF86VidMode info.\n");
00554 XSetErrorHandler(old_x_error_handler);
00555 return -1;
00556 }
00557
00558
00559 for (i = 0; i < _xwin.num_modes; i++)
00560 {
00561 if ((_xwin.modesinfo[i]->hdisplay == allegro_gl_display_info.w)
00562 && (_xwin.modesinfo[i]->vdisplay == allegro_gl_display_info.h))
00563 bestmode = i;
00564 }
00565 }
00566 #endif
00567
00568
00569 root = RootWindow (_xwin.display, _xwin.screen);
00570 visinfo = allegro_gl_x_windowed_choose_visual();
00571 if (!visinfo) {
00572 TRACE("** ERROR ** x_create_window: Can not get visual.\n");
00573 XSetErrorHandler(old_x_error_handler);
00574 return -1;
00575 }
00576
00577
00578 if (decode_visual (visinfo, &allegro_gl_display_info)) {
00579 TRACE("** ERROR ** x_create_window: Can not decode visual.\n");
00580 XSetErrorHandler(old_x_error_handler);
00581 return -1;
00582 }
00583
00584
00585
00586 switch (visinfo->class) {
00587 case TrueColor:
00588 AGL_LOG (1, "x.c: visual class: TrueColor\n");
00589 break;
00590 case DirectColor:
00591 AGL_LOG (1, "x.c: visual class: DirectColor\n");
00592 break;
00593 default:
00594 AGL_LOG (1, "x.c: visual class: invalid(!)\n");
00595 }
00596
00597
00598
00599 setattr.background_pixel = XBlackPixel (_xwin.display, _xwin.screen);
00600 setattr.border_pixel = XBlackPixel (_xwin.display, _xwin.screen);
00601 setattr.colormap = XCreateColormap (_xwin.display, root, visinfo->visual, AllocNone);
00602 setattr.event_mask =
00603 ( KeyPressMask | KeyReleaseMask
00604 | EnterWindowMask | LeaveWindowMask
00605 | FocusChangeMask | ExposureMask
00606 | ButtonPressMask | ButtonReleaseMask | PointerMotionMask
00607
00608 );
00609
00610 #ifdef ALLEGROGL_HAVE_XF86VIDMODE
00611 if (fullscreen) {
00612 setattr.override_redirect = True;
00613 if (!XF86VidModeSwitchToMode(_xwin.display, _xwin.screen,
00614 _xwin.modesinfo[bestmode])) {
00615
00616 ustrzcpy (allegro_gl_error, AGL_ERROR_SIZE,
00617 get_config_text("Can not set XF86VidMode mode"));
00618 XSetErrorHandler(old_x_error_handler);
00619 return -1;
00620 }
00621
00622 XF86VidModeSetViewPort(_xwin.display, _xwin.screen, 0, 0);
00623
00624
00625 XF86VidModeLockModeSwitch(_xwin.display, _xwin.screen, True);
00626 _xwin.mode_switched = 1;
00627
00628 allegro_gl_display_info.x = 0;
00629 allegro_gl_display_info.y = 0;
00630 allegro_gl_display_info.w = _xwin.modesinfo[bestmode]->hdisplay;
00631 allegro_gl_display_info.h = _xwin.modesinfo[bestmode]->vdisplay;
00632
00633 valuemask |= CWOverrideRedirect;
00634 _xwin.override_redirected = 1;
00635 }
00636 #endif
00637
00638 XDestroyWindow (_xwin.display, _xwin.window);
00639
00640 _xwin.window = XCreateWindow (
00641 _xwin.display, root,
00642 allegro_gl_display_info.x, allegro_gl_display_info.y,
00643 allegro_gl_display_info.w, allegro_gl_display_info.h, 0,
00644 visinfo->depth,
00645 InputOutput,
00646 visinfo->visual,
00647 valuemask, &setattr
00648 );
00649
00650
00651
00652
00653 hints = XAllocSizeHints();
00654 if (hints) {
00655
00656 hints->flags = PMinSize | PMaxSize | PBaseSize;
00657 hints->min_width = hints->max_width = hints->base_width
00658 = allegro_gl_display_info.w;
00659 hints->min_height = hints->max_height = hints->base_height
00660 = allegro_gl_display_info.h;
00661
00662 XSetWMNormalHints(_xwin.display, _xwin.window, hints);
00663 XFree(hints);
00664 }
00665
00666
00667 _glxwin.ctx = glXCreateContext (_xwin.display, visinfo, NULL, True);
00668 if (!_glxwin.ctx) {
00669 ustrzcpy (allegro_gl_error, AGL_ERROR_SIZE,
00670 get_config_text("Can not create GLX context."));
00671 XSetErrorHandler(old_x_error_handler);
00672 return -1;
00673 }
00674 else {
00675 if (!glXMakeCurrent (_xwin.display, _xwin.window, _glxwin.ctx)) {
00676 ustrzcpy (allegro_gl_error, AGL_ERROR_SIZE,
00677 get_config_text("Can not make GLX context current."));
00678 XSetErrorHandler(old_x_error_handler);
00679 return -1;
00680 }
00681 }
00682
00683
00684
00685
00686
00687
00688 {
00689 XWindowAttributes getattr;
00690 XGetWindowAttributes(_xwin.display, _xwin.window, &getattr);
00691 _xwin.visual = getattr.visual;
00692 _xwin.window_depth = getattr.depth;
00693 _xwin.window_width = allegro_gl_display_info.w;
00694 _xwin.window_height = allegro_gl_display_info.h;
00695 _xwin.screen_depth = getattr.depth;
00696 _xwin.screen_width = allegro_gl_display_info.w;
00697 _xwin.screen_height = allegro_gl_display_info.h;
00698 }
00699
00700
00701 if (_xwin.colormap != None) {
00702 XUninstallColormap(_xwin.display, _xwin.colormap);
00703 XFreeColormap(_xwin.display, _xwin.colormap);
00704 }
00705
00706
00707 if (_xwin.visual->class == DirectColor) {
00708 _xwin.colormap = XCreateColormap(_xwin.display, _xwin.window,
00709 _xwin.visual, AllocAll);
00710 }
00711 else {
00712 _xwin.colormap = XCreateColormap(_xwin.display, _xwin.window,
00713 _xwin.visual, AllocNone);
00714 }
00715 XSetWindowColormap(_xwin.display, _xwin.window, _xwin.colormap);
00716 XInstallColormap(_xwin.display, _xwin.colormap);
00717
00718
00719 if (_xwin.visual->class == DirectColor) {
00720 XColor color;
00721 int rsize, gsize, bsize;
00722 int rmax, gmax, bmax;
00723 int rshift, gshift, bshift;
00724 int r, g, b;
00725
00726 AGL_LOG (1, "x.c: Using DirectColor visual, setting palette...\n");
00727
00728 rsize = 1 << allegro_gl_display_info.pixel_size.rgba.r;
00729 gsize = 1 << allegro_gl_display_info.pixel_size.rgba.g;
00730 bsize = 1 << allegro_gl_display_info.pixel_size.rgba.b;
00731
00732 rshift = allegro_gl_display_info.r_shift;
00733 bshift = allegro_gl_display_info.b_shift;
00734 gshift = allegro_gl_display_info.g_shift;
00735
00736 rmax = rsize - 1;
00737 gmax = gsize - 1;
00738 bmax = bsize - 1;
00739
00740 color.flags = DoRed | DoGreen | DoBlue;
00741 for (r = 0; r < rsize; r++) {
00742 for (g = 0; g < gsize; g++) {
00743 for (b = 0; b < bsize; b++) {
00744 color.pixel = (r << rshift) | (g << gshift) | (b << bshift);
00745 color.red = ((rmax <= 0) ? 0 : ((r * 65535L) / rmax));
00746 color.green = ((gmax <= 0) ? 0 : ((g * 65535L) / gmax));
00747 color.blue = ((bmax <= 0) ? 0 : ((b * 65535L) / bmax));
00748 XStoreColor(_xwin.display, _xwin.colormap, &color);
00749 }
00750 }
00751 }
00752 }
00753
00754
00755 {
00756 XClassHint hint;
00757 XWMHints wm_hints;
00758
00759
00760 XStoreName(_xwin.display, _xwin.window, _xwin.window_title);
00761
00762
00763 hint.res_name = _xwin.application_name;
00764 hint.res_class = _xwin.application_class;
00765 XSetClassHint(_xwin.display, _xwin.window, &hint);
00766
00767 wm_hints.flags = InputHint | StateHint;
00768 wm_hints.input = True;
00769 wm_hints.initial_state = NormalState;
00770 XSetWMHints(_xwin.display, _xwin.window, &wm_hints);
00771 }
00772
00773
00774
00775 XMapWindow(_xwin.display, _xwin.window);
00776
00777 #ifdef ALLEGROGL_HAVE_XF86VIDMODE
00778 if (fullscreen) {
00779 AL_CONST char *fc = NULL;
00780 char tmp1[64], tmp2[128];
00781 int c = 0;
00782 int h = allegro_gl_display_info.h;
00783 int w = allegro_gl_display_info.w;
00784
00785
00786
00787 fc = get_config_string(uconvert_ascii("graphics", tmp1),
00788 uconvert_ascii("force_centering", tmp2), NULL);
00789 if ((fc) && ((c = ugetc(fc)) != 0) && ((c == 'y') || (c == 'Y')
00790 || (c == '1'))) {
00791
00792 XWarpPointer(_xwin.display, None, _xwin.window, 0, 0, 0, 0, 0, 0);
00793 XWarpPointer(_xwin.display, None, _xwin.window, 0, 0, 0, 0,
00794 w - 1, 0);
00795 XWarpPointer(_xwin.display, None, _xwin.window, 0, 0, 0, 0,
00796 0, h - 1);
00797 XWarpPointer(_xwin.display, None, _xwin.window, 0, 0, 0, 0,
00798 w - 1, h - 1);
00799 }
00800 XWarpPointer(_xwin.display, None, _xwin.window, 0, 0, 0, 0,
00801 w / 2, h / 2);
00802 XSync(_xwin.display, False);
00803
00804
00805 if (XGrabKeyboard(_xwin.display, _xwin.window, False, GrabModeAsync,
00806 GrabModeAsync, CurrentTime) != GrabSuccess) {
00807 ustrzcpy (allegro_gl_error, AGL_ERROR_SIZE,
00808 get_config_text("Can not grab keyboard"));
00809 XSetErrorHandler(old_x_error_handler);
00810 return -1;
00811 }
00812 _xwin.keyboard_grabbed = 1;
00813
00814 if (XGrabPointer(_xwin.display, _xwin.window, False,
00815 PointerMotionMask | ButtonPressMask | ButtonReleaseMask,
00816 GrabModeAsync, GrabModeAsync, _xwin.window, None, CurrentTime)
00817 != GrabSuccess) {
00818
00819 ustrzcpy (allegro_gl_error, AGL_ERROR_SIZE,
00820 get_config_text("Can not grab mouse"));
00821 XSetErrorHandler(old_x_error_handler);
00822 return -1;
00823 }
00824 _xwin.mouse_grabbed = 1;
00825 }
00826 #endif
00827
00828
00829
00830 if (_xwin.cursor != None) {
00831 XUndefineCursor(_xwin.display, _xwin.window);
00832 XFreeCursor(_xwin.display, _xwin.cursor);
00833 }
00834
00835 {
00836
00837 Pixmap pixmap = XCreatePixmap(_xwin.display, _xwin.window, 1, 1, 1);
00838 if (pixmap != None) {
00839 GC temp_gc;
00840 XColor color;
00841 XGCValues gcvalues;
00842
00843 int gcmask = GCFunction | GCForeground | GCBackground;
00844 gcvalues.function = GXcopy;
00845 gcvalues.foreground = 0;
00846 gcvalues.background = 0;
00847 temp_gc = XCreateGC(_xwin.display, pixmap, gcmask, &gcvalues);
00848 XDrawPoint(_xwin.display, pixmap, temp_gc, 0, 0);
00849 XFreeGC(_xwin.display, temp_gc);
00850 color.pixel = 0;
00851 color.red = color.green = color.blue = 0;
00852 color.flags = DoRed | DoGreen | DoBlue;
00853 _xwin.cursor = XCreatePixmapCursor(_xwin.display, pixmap, pixmap,
00854 &color, &color, 0, 0);
00855 XDefineCursor(_xwin.display, _xwin.window, _xwin.cursor);
00856 XFreePixmap(_xwin.display, pixmap);
00857 }
00858 else {
00859 _xwin.cursor = XCreateFontCursor(_xwin.display, _xwin.cursor_shape);
00860 XDefineCursor(_xwin.display, _xwin.window, _xwin.cursor);
00861 }
00862 }
00863
00864
00865 {
00866 XEvent event;
00867 do {
00868 XNextEvent(_xwin.display, &event);
00869 } while ((event.type != Expose) || (event.xexpose.count != 0));
00870 }
00871
00872 return 0;
00873 }
00874
00875
00876
00877 static BITMAP *allegro_gl_x_windowed_create_screen (GFX_DRIVER *drv, int w, int h, int depth)
00878 {
00879 BITMAP *bmp;
00880 int is_linear = drv->linear;
00881
00882 drv->linear = 1;
00883 bmp = _make_bitmap (w, h, 0, drv, depth, 0);
00884 bmp->id = BMP_ID_VIDEO | BMP_ID_MASK;
00885 drv->linear = is_linear;
00886
00887 if (bmp == 0) {
00888 ustrzcpy (allegro_gl_error, AGL_ERROR_SIZE,
00889 get_config_text("Not enough memory"));
00890 return NULL;
00891 }
00892
00893 drv->w = w;
00894 drv->h = h;
00895
00896 return bmp;
00897 }
00898
00899
00900
00901
00902
00903
00904 static int get_shift (int mask)
00905 {
00906 int i = 0, j = 1;
00907 if (!mask) return -1;
00908 while (!(j & mask)) {
00909 i++;
00910 j <<= 1;
00911 }
00912 return i;
00913 }
00914
00915
00916
00917
00918
00919
00920 static int decode_visual (XVisualInfo *v, struct allegro_gl_display_info *i)
00921 {
00922 int rgba, buffer_size, use_gl, sbuffers, samples;
00923
00924 TRACE("* Note * decode_visual: Decoding:\n");
00925 i->rmethod = 2;
00926
00927
00928
00929 if (v->class != TrueColor && v->class != DirectColor)
00930 return -1;
00931
00932 if (glXGetConfig (_xwin.display, v, GLX_RGBA, &rgba)
00933 || glXGetConfig (_xwin.display, v, GLX_USE_GL, &use_gl)
00934 || glXGetConfig (_xwin.display, v, GLX_BUFFER_SIZE, &buffer_size)
00935 || glXGetConfig (_xwin.display, v, GLX_RED_SIZE, &i->pixel_size.rgba.r)
00936 || glXGetConfig (_xwin.display, v, GLX_GREEN_SIZE, &i->pixel_size.rgba.g)
00937 || glXGetConfig (_xwin.display, v, GLX_BLUE_SIZE, &i->pixel_size.rgba.b)
00938 || glXGetConfig (_xwin.display, v, GLX_ALPHA_SIZE, &i->pixel_size.rgba.a)
00939 || glXGetConfig (_xwin.display, v, GLX_DOUBLEBUFFER, &i->doublebuffered)
00940 || glXGetConfig (_xwin.display, v, GLX_STEREO, &i->stereo)
00941 || glXGetConfig (_xwin.display, v, GLX_AUX_BUFFERS, &i->aux_buffers)
00942 || glXGetConfig (_xwin.display, v, GLX_DEPTH_SIZE, &i->depth_size)
00943 || glXGetConfig (_xwin.display, v, GLX_STENCIL_SIZE, &i->stencil_size)
00944 || glXGetConfig (_xwin.display, v, GLX_ACCUM_RED_SIZE,
00945 &i->accum_size.rgba.r)
00946 || glXGetConfig (_xwin.display, v, GLX_ACCUM_GREEN_SIZE,
00947 &i->accum_size.rgba.g)
00948 || glXGetConfig (_xwin.display, v, GLX_ACCUM_BLUE_SIZE,
00949 &i->accum_size.rgba.b)
00950 || glXGetConfig (_xwin.display, v, GLX_ACCUM_ALPHA_SIZE,
00951 &i->accum_size.rgba.a)) {
00952 TRACE("* Note * x_create_window: Incomplete glX mode ...\n");
00953 return -1;
00954 }
00955
00956 if (!rgba) {
00957 TRACE("* Note * x_create_window: Not RGBA mode\n");
00958 return -1;
00959 }
00960
00961 if (!use_gl) {
00962 ustrzcpy (allegro_gl_error, AGL_ERROR_SIZE,
00963 get_config_text("OpenGL Unsupported"));
00964 return -1;
00965 }
00966
00967 i->r_shift = get_shift (v->red_mask);
00968 i->g_shift = get_shift (v->green_mask);
00969 i->b_shift = get_shift (v->blue_mask);
00970 i->a_shift = 0;
00971
00972
00973 if ((v->class == DirectColor)
00974 && ((i->r_shift == -1) || (i->g_shift == -1) || (i->b_shift == -1))
00975 && (i->pixel_size.rgba.r + i->pixel_size.rgba.g + i->pixel_size.rgba.b
00976 <= 12)) {
00977
00978 return -1;
00979 }
00980
00981
00982 i->colour_depth = 0;
00983
00984 if (i->pixel_size.rgba.r == 3
00985 && i->pixel_size.rgba.g == 3
00986 && i->pixel_size.rgba.b == 2) {
00987 i->colour_depth = 8;
00988 }
00989
00990 if (i->pixel_size.rgba.r == 5
00991 && i->pixel_size.rgba.b == 5) {
00992 if (i->pixel_size.rgba.g == 5) {
00993 i->colour_depth = 15;
00994 }
00995 if (i->pixel_size.rgba.g == 6) {
00996 i->colour_depth = 16;
00997 }
00998 }
00999
01000 if (i->pixel_size.rgba.r == 8
01001 && i->pixel_size.rgba.g == 8
01002 && i->pixel_size.rgba.b == 8) {
01003 if (i->pixel_size.rgba.a == 0) {
01004 i->colour_depth = 24;
01005 }
01006 if (i->pixel_size.rgba.a == 8) {
01007 i->colour_depth = 32;
01008
01009 i->a_shift = 48 - i->r_shift - i->g_shift - i->b_shift;
01010 }
01011 }
01012
01013 i->allegro_format = (i->colour_depth != 0)
01014 && (i->g_shift == i->pixel_size.rgba.b)
01015 && (i->r_shift * i->b_shift == 0)
01016 && (i->r_shift + i->b_shift
01017 == i->pixel_size.rgba.b + i->pixel_size.rgba.g);
01018
01019 if (glXGetConfig(_xwin.display, v, GLX_SAMPLE_BUFFERS, &sbuffers)
01020 == GLX_BAD_ATTRIBUTE) {
01021
01022 i->sample_buffers = 0;
01023 }
01024 else {
01025 i->sample_buffers = sbuffers;
01026 }
01027 if (glXGetConfig(_xwin.display, v, GLX_SAMPLES, &samples)
01028 == GLX_BAD_ATTRIBUTE) {
01029
01030 i->samples = 0;
01031 }
01032 else {
01033 i->samples = samples;
01034 }
01035
01036
01037 TRACE("\tColor Depth: %i ", buffer_size);
01038 TRACE("RGBA: %i.%i.%i.%i ", i->pixel_size.rgba.r, i->pixel_size.rgba.g,
01039 i->pixel_size.rgba.b, i->pixel_size.rgba.a);
01040 TRACE("Accum: %i.%i.%i.%i\n\t", i->accum_size.rgba.r, i->accum_size.rgba.g,
01041 i->accum_size.rgba.b, i->accum_size.rgba.a);
01042 TRACE("DblBuf: %i Zbuf: %i Stereo: %i Aux: %i Stencil: %i ",
01043 i->doublebuffered, i->depth_size, i->stereo,
01044 i->aux_buffers, i->stencil_size);
01045 TRACE("Shift: %i.%i.%i.%i\n\t", i->r_shift, i->g_shift, i->b_shift,
01046 i->a_shift);
01047 TRACE("Sample Buffers: %i Samples: %i\n\t", i->sample_buffers, i->samples);
01048 TRACE("Decoded bpp: %i\n", i->colour_depth);
01049
01050 return 0;
01051 }
01052
01053
01054
01055 #ifdef ALLEGROGL_HAVE_XF86VIDMODE
01056
01057
01058
01059
01060 static GFX_MODE_LIST* allegro_gl_x_fetch_mode_list(void)
01061 {
01062 int num_modes = 0;
01063 XF86VidModeModeInfo **modesinfo = NULL;
01064 GFX_MODE_LIST *mode_list;
01065 int i;
01066
01067 XLOCK();
01068
01069 if (get_xf86_modes(&modesinfo, &num_modes)) {
01070 XUNLOCK();
01071 return NULL;
01072 }
01073
01074
01075 mode_list = malloc(sizeof(GFX_MODE_LIST));
01076 if (!mode_list) {
01077 free_modelines(modesinfo, num_modes);
01078 XUNLOCK();
01079 return NULL;
01080 }
01081
01082 mode_list->mode = malloc(sizeof(GFX_MODE) * (num_modes + 1));
01083 if (!mode_list->mode) {
01084 free(mode_list);
01085 free_modelines(modesinfo, num_modes);
01086 XUNLOCK();
01087 return NULL;
01088 }
01089
01090
01091 for (i = 0; i < num_modes; i++) {
01092 mode_list->mode[i].width = modesinfo[i]->hdisplay;
01093 mode_list->mode[i].height = modesinfo[i]->vdisplay;
01094
01095
01096
01097
01098 mode_list->mode[i].bpp = desktop_color_depth();
01099 }
01100
01101 mode_list->mode[num_modes].width = 0;
01102 mode_list->mode[num_modes].height = 0;
01103 mode_list->mode[num_modes].bpp = 0;
01104 mode_list->num_modes = num_modes;
01105
01106 free_modelines(modesinfo, num_modes);
01107
01108 XUNLOCK();
01109 return mode_list;
01110 }
01111 #endif
01112
01113
01114
01115
01116
01117
01118 static void allegro_gl_x_vsync(void)
01119 {
01120 if (allegro_gl_extensions_GLX.SGI_video_sync) {
01121 unsigned int count;
01122
01123 glXGetVideoSyncSGI(&count);
01124 glXWaitVideoSyncSGI(2, (count+1) & 1, &count);
01125 }
01126 }
01127
01128
01129
01130
01131
01132
01133
01134
01135
01136
01137 static void flip (void)
01138 {
01139 glXSwapBuffers (_xwin.display, _xwin.window);
01140 }
01141
01142
01143
01144
01145
01146
01147 static void gl_on (void)
01148 {
01149 #ifdef OLD_ALLEGRO
01150 DISABLE();
01151 #endif
01152 }
01153
01154
01155
01156 static void gl_off (void)
01157 {
01158 #ifdef OLD_ALLEGRO
01159 ENABLE();
01160 _xwin_handle_input();
01161 #endif
01162 }
01163
01164
01165
01166
01167
01168
01169
01170 static struct allegro_gl_driver allegro_gl_x = {
01171 flip,
01172 gl_on,
01173 gl_off,
01174 NULL
01175 };
01176