00001
00002
00003
00004
00005
00006
00007
00008
00009 #include <string.h>
00010 #include <stdio.h>
00011
00012 #include <allegro.h>
00013 #include <xalleg.h>
00014
00015 #include <allegro/platform/aintunix.h>
00016
00017 #include "alleggl.h"
00018 #include "allglint.h"
00019 #include "glvtable.h"
00020
00021
00022 #ifndef XLOCK
00023 #define OLD_ALLEGRO
00024 #define XLOCK() DISABLE()
00025 #undef XUNLOCK
00026 #define XUNLOCK() ENABLE()
00027 #endif
00028
00029 #define PREFIX_I "agl-x INFO: "
00030 #define PREFIX_E "agl-x ERROR: "
00031
00032
00033 #ifdef ALLEGRO_XWINDOWS_WITH_XPM
00034 #include <X11/xpm.h>
00035 extern void *allegro_icon;
00036 #endif
00037
00038
00039 static BITMAP *allegro_gl_x_windowed_init(int w, int h, int vw, int vh,
00040 int color_depth);
00041 static void allegro_gl_x_exit(BITMAP *bmp);
00042 #ifdef ALLEGROGL_HAVE_XF86VIDMODE
00043 static GFX_MODE_LIST* allegro_gl_x_fetch_mode_list(void);
00044 #endif
00045 static void allegro_gl_x_vsync(void);
00046 static void allegro_gl_x_hide_mouse(void);
00047
00048 static BITMAP *allegro_gl_screen = NULL;
00049
00050
00051
00052
00053
00054
00055
00056 #if GET_ALLEGRO_VERSION() >= MAKE_VER(4, 2, 1)
00057 static Window backup_allegro_window = None;
00058 static Colormap backup_allegro_colormap = None;
00059 #endif
00060
00061
00062 #ifdef ALLEGROGL_HAVE_XF86VIDMODE
00063 static BITMAP *allegro_gl_x_fullscreen_init(int w, int h, int vw, int vh,
00064 int color_depth);
00065
00066 GFX_DRIVER gfx_allegro_gl_fullscreen =
00067 {
00068 GFX_OPENGL_FULLSCREEN,
00069 empty_string,
00070 empty_string,
00071 "AllegroGL Fullscreen (X)",
00072 allegro_gl_x_fullscreen_init,
00073 allegro_gl_x_exit,
00074 NULL,
00075 allegro_gl_x_vsync,
00076 NULL,
00077 NULL, NULL, NULL,
00078 allegro_gl_create_video_bitmap,
00079 allegro_gl_destroy_video_bitmap,
00080 NULL, NULL,
00081 NULL, NULL,
00082 allegro_gl_set_mouse_sprite,
00083 allegro_gl_show_mouse,
00084 allegro_gl_x_hide_mouse,
00085 allegro_gl_move_mouse,
00086 allegro_gl_drawing_mode,
00087 NULL, NULL,
00088 allegro_gl_set_blender_mode,
00089 allegro_gl_x_fetch_mode_list,
00090 0, 0,
00091 0,
00092 0, 0,
00093 0,
00094 0,
00095 FALSE
00096 };
00097 #endif
00098
00099
00100
00101 GFX_DRIVER gfx_allegro_gl_windowed =
00102 {
00103 GFX_OPENGL_WINDOWED,
00104 empty_string,
00105 empty_string,
00106 "AllegroGL Windowed (X)",
00107 allegro_gl_x_windowed_init,
00108 allegro_gl_x_exit,
00109 NULL,
00110 allegro_gl_x_vsync,
00111 NULL,
00112 NULL, NULL, NULL,
00113 allegro_gl_create_video_bitmap,
00114 allegro_gl_destroy_video_bitmap,
00115 NULL, NULL,
00116 NULL, NULL,
00117 allegro_gl_set_mouse_sprite,
00118 allegro_gl_show_mouse,
00119 allegro_gl_x_hide_mouse,
00120 allegro_gl_move_mouse,
00121 allegro_gl_drawing_mode,
00122 NULL, NULL,
00123 allegro_gl_set_blender_mode,
00124 NULL,
00125 0, 0,
00126 0,
00127 0, 0,
00128 0,
00129 0,
00130 TRUE
00131 };
00132
00133
00134
00135 static struct allegro_gl_driver allegro_gl_x;
00136
00137 static XVisualInfo *allegro_gl_x_windowed_choose_visual (void);
00138 static int allegro_gl_x_create_window (int fullscreen);
00139 static BITMAP *allegro_gl_x_windowed_create_screen (GFX_DRIVER *drv, int w, int h, int depth);
00140
00141 static int decode_visual (XVisualInfo *v, struct allegro_gl_display_info *i);
00142 struct {
00143 int fullscreen;
00144 GLXContext ctx;
00145 int major, minor;
00146 int error_base, event_base;
00147 int use_glx_window;
00148 GLXWindow window;
00149 } _glxwin;
00150
00151 static void (*old_window_redrawer)(int, int, int, int);
00152 extern void (*_xwin_window_redrawer)(int, int, int, int);
00153 static int (*old_x_error_handler)(Display*, XErrorEvent*);
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164 static void allegro_gl_redraw_window(int x, int y, int w, int h)
00165 {
00166
00167 return;
00168 }
00169
00170
00171
00172 #ifdef ALLEGRO_XWINDOWS_WITH_XCURSOR
00173
00174
00175
00176 static void _xwin_hide_x_mouse(void)
00177 {
00178 unsigned long gcmask;
00179 XGCValues gcvalues;
00180 Pixmap pixmap;
00181
00182 XUndefineCursor(_xwin.display, _xwin.window);
00183
00184 if (_xwin.cursor != None) {
00185 XFreeCursor(_xwin.display, _xwin.cursor);
00186 _xwin.cursor = None;
00187 }
00188
00189 if (_xwin.xcursor_image != None) {
00190 XcursorImageDestroy(_xwin.xcursor_image);
00191 _xwin.xcursor_image = None;
00192 }
00193
00194 pixmap = XCreatePixmap(_xwin.display, _xwin.window, 1, 1, 1);
00195 if (pixmap != None) {
00196 GC temp_gc;
00197 XColor color;
00198
00199 gcmask = GCFunction | GCForeground | GCBackground;
00200 gcvalues.function = GXcopy;
00201 gcvalues.foreground = 0;
00202 gcvalues.background = 0;
00203 temp_gc = XCreateGC(_xwin.display, pixmap, gcmask, &gcvalues);
00204 XDrawPoint(_xwin.display, pixmap, temp_gc, 0, 0);
00205 XFreeGC(_xwin.display, temp_gc);
00206 color.pixel = 0;
00207 color.red = color.green = color.blue = 0;
00208 color.flags = DoRed | DoGreen | DoBlue;
00209 _xwin.cursor = XCreatePixmapCursor(_xwin.display, pixmap, pixmap, &color, &color, 0, 0);
00210 XDefineCursor(_xwin.display, _xwin.window, _xwin.cursor);
00211 XFreePixmap(_xwin.display, pixmap);
00212 }
00213 else {
00214 _xwin.cursor = XCreateFontCursor(_xwin.display, _xwin.cursor_shape);
00215 XDefineCursor(_xwin.display, _xwin.window, _xwin.cursor);
00216 }
00217 }
00218 #endif
00219
00220
00221
00222
00223
00224
00225 static void hide_mouse(void)
00226 {
00227 #ifdef ALLEGRO_XWINDOWS_WITH_XCURSOR
00228 if (_xwin.support_argb_cursor) {
00229 XLOCK();
00230 _xwin_hide_x_mouse();
00231 XUNLOCK();
00232 }
00233 #endif
00234 return;
00235 }
00236
00237
00238
00239
00240
00241
00242 static void allegro_gl_x_hide_mouse(void)
00243 {
00244 if (_xwin.hw_cursor_ok) {
00245 hide_mouse();
00246 }
00247 else {
00248 allegro_gl_hide_mouse();
00249 }
00250 }
00251
00252
00253
00254
00255
00256
00257 static BITMAP *allegro_gl_x_create_screen(int w, int h, int vw, int vh,
00258 int depth, int fullscreen)
00259 {
00260 int _keyboard_was_installed = FALSE;
00261 int _mouse_was_installed = FALSE;
00262
00263
00264 if (!_unix_bg_man->multi_threaded) {
00265 ustrzcpy (allegro_gl_error, AGL_ERROR_SIZE,
00266 get_config_text("Fatal Error : pthread support is not enabled"));
00267 return NULL;
00268 }
00269
00270 if (keyboard_driver) {
00271 _keyboard_was_installed = TRUE;
00272 remove_keyboard();
00273 TRACE(PREFIX_I "x_create_screen: Removing Keyboard...\n");
00274 }
00275
00276 if (mouse_driver) {
00277 _mouse_was_installed = TRUE;
00278 remove_mouse();
00279 TRACE(PREFIX_I "x_create_screen: Removing Mouse...\n");
00280 }
00281
00282 XLOCK();
00283
00284 if (!glXQueryExtension(_xwin.display, &_glxwin.error_base,
00285 &_glxwin.event_base)) {
00286
00287 ustrzcpy (allegro_error, ALLEGRO_ERROR_SIZE,
00288 get_config_text("GLX Extension not supported by display"));
00289 XUNLOCK();
00290 goto failure;
00291 }
00292
00293 sscanf(glXQueryServerString(_xwin.display, _xwin.screen, GLX_VERSION),
00294 "%i.%i", &_glxwin.major, &_glxwin.minor);
00295
00296 if ((w == 0) && (h == 0)) {
00297 w = 640;
00298 h = 480;
00299 }
00300
00301 if ((vw > w) || (vh > h)) {
00302 ustrzcpy (allegro_error, ALLEGRO_ERROR_SIZE,
00303 get_config_text ("OpenGL drivers do not support virtual screens"));
00304 XUNLOCK();
00305 goto failure;
00306 }
00307
00308 allegro_gl_display_info.w = w;
00309 allegro_gl_display_info.h = h;
00310
00311 old_window_redrawer = _xwin_window_redrawer;
00312 _xwin_window_redrawer = allegro_gl_redraw_window;
00313 _glxwin.fullscreen = FALSE;
00314 _glxwin.use_glx_window = FALSE;
00315
00316 if (allegro_gl_x_create_window(fullscreen)) {
00317 if (fullscreen) {
00318 ustrzcpy (allegro_error, ALLEGRO_ERROR_SIZE,
00319 get_config_text ("Unable to switch in GLX fullscreen"));
00320 }
00321 else {
00322 ustrzcpy (allegro_error, ALLEGRO_ERROR_SIZE,
00323 get_config_text ("Unable to create GLX window"));
00324 }
00325 XUNLOCK();
00326 allegro_gl_x_exit(NULL);
00327 goto failure;
00328 }
00329
00330
00331 set_color_depth(allegro_gl_display_info.colour_depth);
00332
00333
00334
00335
00336
00337 __allegro_gl_set_allegro_image_format(FALSE);
00338
00339 if (fullscreen) {
00340 #ifdef ALLEGROGL_HAVE_XF86VIDMODE
00341 allegro_gl_screen =
00342 allegro_gl_x_windowed_create_screen (&gfx_allegro_gl_fullscreen,
00343 allegro_gl_display_info.w, allegro_gl_display_info.h,
00344 _color_depth);
00345 #endif
00346 }
00347 else {
00348 allegro_gl_screen =
00349 allegro_gl_x_windowed_create_screen (&gfx_allegro_gl_windowed,
00350 allegro_gl_display_info.w, allegro_gl_display_info.h,
00351 _color_depth);
00352 }
00353
00354 if (!allegro_gl_screen) {
00355 ustrzcpy (allegro_error, ALLEGRO_ERROR_SIZE,
00356 get_config_text ("Error creating screen bitmap"));
00357 XUNLOCK();
00358 allegro_gl_x_exit(NULL);
00359 goto failure;
00360 }
00361
00362 __allegro_gl_valid_context = TRUE;
00363 __allegro_gl_driver = &allegro_gl_x;
00364
00365
00366 TRACE(PREFIX_I "OpenGL Version: %s\n", (AL_CONST char*)glGetString(GL_VERSION));
00367 TRACE(PREFIX_I "OpenGL Vendor: %s\n", (AL_CONST char*)glGetString(GL_VENDOR));
00368 TRACE(PREFIX_I "OpenGL Renderer: %s\n", (AL_CONST char*)glGetString(GL_RENDERER));
00369
00370
00371 allegro_gl_info.is_mesa_driver = FALSE;
00372 if (strstr((AL_CONST char*)glGetString(GL_VERSION),"Mesa")) {
00373 AGL_LOG(1, "OpenGL driver based on Mesa\n");
00374 allegro_gl_info.is_mesa_driver = TRUE;
00375 }
00376
00377
00378 TRACE(PREFIX_I "GLX Version: %d.%d\n", _glxwin.major, _glxwin.minor);
00379
00380 #ifdef LOGLEVEL
00381 if (glXIsDirect(_xwin.display, _glxwin.ctx)) {
00382 AGL_LOG(1, "GLX Direct Rendering is enabled\n");
00383 }
00384 else {
00385 AGL_LOG(1, "GLX Direct Rendering is disabled\n");
00386 }
00387 #endif
00388
00389
00390 AGL_LOG(1, "glX Extensions:\n");
00391 #ifdef LOGLEVEL
00392 __allegro_gl_print_extensions(
00393 (AL_CONST char*)glXQueryExtensionsString(_xwin.display, _xwin.screen));
00394 #endif
00395
00396 __allegro_gl_manage_extensions();
00397
00398
00399 __allegro_gl__glvtable_update_vtable (&allegro_gl_screen->vtable);
00400 memcpy(&_screen_vtable, allegro_gl_screen->vtable, sizeof(GFX_VTABLE));
00401 allegro_gl_screen->vtable = &_screen_vtable;
00402
00403 XUNLOCK();
00404
00405 if (_keyboard_was_installed) {
00406 TRACE(PREFIX_I "x_create_screen: Installing Keyboard...\n");
00407 install_keyboard();
00408 }
00409
00410 if (_mouse_was_installed) {
00411 TRACE(PREFIX_I "x_create_screen: Installing Mouse...\n");
00412 install_mouse();
00413 }
00414 gfx_capabilities |= GFX_HW_CURSOR;
00415
00416 return allegro_gl_screen;
00417
00418 failure:
00419 if (_keyboard_was_installed) {
00420 install_keyboard();
00421 }
00422
00423 if (_mouse_was_installed) {
00424 install_mouse();
00425 }
00426
00427 return NULL;
00428 }
00429
00430
00431
00432
00433
00434
00435 static BITMAP *allegro_gl_x_windowed_init(int w, int h, int vw, int vh,
00436 int depth)
00437 {
00438 return allegro_gl_x_create_screen(w, h, vw, vh, depth, FALSE);
00439 }
00440
00441
00442
00443 #ifdef ALLEGROGL_HAVE_XF86VIDMODE
00444
00445
00446
00447 static BITMAP *allegro_gl_x_fullscreen_init(int w, int h, int vw, int vh,
00448 int depth)
00449 {
00450 return allegro_gl_x_create_screen(w, h, vw, vh, depth, TRUE);
00451 }
00452
00453
00454
00455
00456
00457
00458 static void free_modelines(XF86VidModeModeInfo **modesinfo, int num_modes)
00459 {
00460 int i;
00461
00462 for (i = 0; i < num_modes; i++)
00463 if (modesinfo[i]->privsize > 0)
00464 XFree(modesinfo[i]->private);
00465 XFree(modesinfo);
00466 }
00467 #endif
00468
00469
00470
00471
00472
00473
00474 static void allegro_gl_x_exit(BITMAP *bmp)
00475 {
00476 #ifdef ALLEGROGL_HAVE_XF86VIDMODE
00477 XSetWindowAttributes setattr;
00478 #endif
00479
00480 XLOCK();
00481
00482
00483 glXWaitGL();
00484
00485 __allegro_gl_unmanage_extensions();
00486
00487 if (_glxwin.ctx) {
00488 if (!allegro_gl_info.is_ati_r200_chip) {
00489
00490
00491
00492
00493
00494
00495
00496
00497 if (!glXMakeCurrent(_xwin.display, None, NULL)) {
00498 ustrzcpy (allegro_error, ALLEGRO_ERROR_SIZE,
00499 get_config_text ("Could not release drawing context.\n"));
00500 }
00501 }
00502
00503 glXDestroyContext(_xwin.display, _glxwin.ctx);
00504 _glxwin.ctx = NULL;
00505 }
00506
00507 if (_xwin.mouse_grabbed) {
00508 XUngrabPointer(_xwin.display, CurrentTime);
00509 _xwin.mouse_grabbed = 0;
00510 }
00511
00512 if (_xwin.keyboard_grabbed) {
00513 XUngrabKeyboard(_xwin.display, CurrentTime);
00514 _xwin.keyboard_grabbed = 0;
00515 }
00516
00517 #ifdef ALLEGROGL_HAVE_XF86VIDMODE
00518 if (_glxwin.fullscreen) {
00519 if (_xwin.mode_switched) {
00520 XF86VidModeLockModeSwitch(_xwin.display, _xwin.screen, False);
00521 XF86VidModeSwitchToMode(_xwin.display, _xwin.screen,
00522 _xwin.modesinfo[0]);
00523 XF86VidModeSetViewPort(_xwin.display, _xwin.screen, 0, 0);
00524 _xwin.mode_switched = 0;
00525 }
00526 if (_xwin.override_redirected) {
00527 setattr.override_redirect = False;
00528 XChangeWindowAttributes(_xwin.display, _xwin.window,
00529 CWOverrideRedirect, &setattr);
00530 _xwin.override_redirected = 0;
00531 }
00532
00533
00534 free_modelines(_xwin.modesinfo, _xwin.num_modes);
00535 _xwin.num_modes = 0;
00536 _xwin.modesinfo = NULL;
00537 }
00538 #endif
00539
00540
00541
00542
00543
00544 ASSERT(allegro_gl_screen == screen);
00545 allegro_gl_screen = NULL;
00546
00547
00548
00549
00550 XUnmapWindow(_xwin.display, _xwin.window);
00551
00552 if (_glxwin.use_glx_window) {
00553 glXDestroyWindow(_xwin.display, _glxwin.window);
00554 _glxwin.window = 0;
00555 _glxwin.use_glx_window = FALSE;
00556 }
00557
00558 __allegro_gl_valid_context = FALSE;
00559
00560 _xwin_window_redrawer = old_window_redrawer;
00561 XSetErrorHandler(old_x_error_handler);
00562
00563
00564 #if GET_ALLEGRO_VERSION() >= MAKE_VER(4, 2, 1)
00565
00566 if (backup_allegro_window != None) {
00567 XUninstallColormap(_xwin.display, _xwin.colormap);
00568 XFreeColormap(_xwin.display, _xwin.colormap);
00569 _xwin.colormap = backup_allegro_colormap;
00570
00571 XDestroyWindow(_xwin.display, _xwin.window);
00572 _xwin.window = backup_allegro_window;
00573 backup_allegro_window = None;
00574 XMapWindow(_xwin.display, _xwin.window);
00575 }
00576 #endif
00577
00578 XUNLOCK();
00579 }
00580
00581
00582
00583
00584
00585
00586 static int get_shift (int mask)
00587 {
00588 int i = 0, j = 1;
00589 if (!mask) return -1;
00590 while (!(j & mask)) {
00591 i++;
00592 j <<= 1;
00593 }
00594 return i;
00595 }
00596
00597
00598
00599 static int decode_fbconfig (GLXFBConfig fbc, struct allegro_gl_display_info *i) {
00600 int render_type, visual_type, buffer_size, sbuffers, samples;
00601 int drawable_type, renderable;
00602 XVisualInfo *v;
00603
00604 TRACE(PREFIX_I "decode_fbconfig: Decoding:\n");
00605 i->rmethod = 2;
00606
00607 if (glXGetFBConfigAttrib (_xwin.display, fbc, GLX_RENDER_TYPE,
00608 &render_type)
00609 || glXGetFBConfigAttrib (_xwin.display, fbc, GLX_X_RENDERABLE,
00610 &renderable)
00611 || glXGetFBConfigAttrib (_xwin.display, fbc, GLX_DRAWABLE_TYPE,
00612 &drawable_type)
00613 || glXGetFBConfigAttrib (_xwin.display, fbc, GLX_X_VISUAL_TYPE,
00614 &visual_type)
00615 || glXGetFBConfigAttrib (_xwin.display, fbc, GLX_BUFFER_SIZE,
00616 &buffer_size)
00617 || glXGetFBConfigAttrib (_xwin.display, fbc, GLX_DEPTH_SIZE,
00618 &i->depth_size)
00619 || glXGetFBConfigAttrib (_xwin.display, fbc, GLX_STEREO,
00620 &i->stereo)
00621 || glXGetFBConfigAttrib (_xwin.display, fbc, GLX_RED_SIZE,
00622 &i->pixel_size.rgba.r)
00623 || glXGetFBConfigAttrib (_xwin.display, fbc, GLX_GREEN_SIZE,
00624 &i->pixel_size.rgba.g)
00625 || glXGetFBConfigAttrib (_xwin.display, fbc, GLX_BLUE_SIZE,
00626 &i->pixel_size.rgba.b)
00627 || glXGetFBConfigAttrib (_xwin.display, fbc, GLX_ALPHA_SIZE,
00628 &i->pixel_size.rgba.a)
00629 || glXGetFBConfigAttrib (_xwin.display, fbc, GLX_DOUBLEBUFFER,
00630 &i->doublebuffered)
00631 || glXGetFBConfigAttrib (_xwin.display, fbc, GLX_AUX_BUFFERS,
00632 &i->aux_buffers)
00633 || glXGetFBConfigAttrib (_xwin.display, fbc, GLX_STENCIL_SIZE,
00634 &i->stencil_size)
00635 || glXGetFBConfigAttrib (_xwin.display, fbc, GLX_ACCUM_RED_SIZE,
00636 &i->accum_size.rgba.r)
00637 || glXGetFBConfigAttrib (_xwin.display, fbc, GLX_ACCUM_GREEN_SIZE,
00638 &i->accum_size.rgba.g)
00639 || glXGetFBConfigAttrib (_xwin.display, fbc, GLX_ACCUM_BLUE_SIZE,
00640 &i->accum_size.rgba.b)
00641 || glXGetFBConfigAttrib (_xwin.display, fbc, GLX_ACCUM_ALPHA_SIZE,
00642 &i->accum_size.rgba.a)) {
00643 TRACE(PREFIX_I "decode_fbconfig: Incomplete glX mode ...\n");
00644 return -1;
00645 }
00646
00647 if (!(render_type & GLX_RGBA_BIT) && !(render_type & GLX_RGBA_FLOAT_BIT)) {
00648 TRACE(PREFIX_I "decode_fbconfig: Not RGBA mode\n");
00649 return -1;
00650 }
00651
00652 if (!(drawable_type & GLX_WINDOW_BIT)) {
00653 TRACE(PREFIX_I "decode_fbconfig: Cannot render to a window.\n");
00654 return -1;
00655 }
00656
00657 if (renderable == False) {
00658 TRACE(PREFIX_I "decode_fbconfig: GLX windows not supported.\n");
00659 return -1;
00660 }
00661
00662 if (visual_type != GLX_TRUE_COLOR && visual_type != GLX_DIRECT_COLOR) {
00663 TRACE(PREFIX_I "decode_fbconfig: visual type other than TrueColor and "
00664 "DirectColor.\n");
00665 return -1;
00666 }
00667
00668
00669 i->float_depth = 0;
00670
00671 i->float_color = (render_type & GLX_RGBA_FLOAT_BIT);
00672
00673 v = glXGetVisualFromFBConfig(_xwin.display, fbc);
00674 if (!v) {
00675 TRACE(PREFIX_I "decode_fbconfig: Cannot get associated visual for the "
00676 "FBConfig.\n");
00677 return -1;
00678 }
00679 i->r_shift = get_shift (v->red_mask);
00680 i->g_shift = get_shift (v->green_mask);
00681 i->b_shift = get_shift (v->blue_mask);
00682 i->a_shift = 0;
00683
00684
00685 if ((visual_type == GLX_DIRECT_COLOR)
00686 && ((i->r_shift == -1) || (i->g_shift == -1) || (i->b_shift == -1))
00687 && (i->pixel_size.rgba.r + i->pixel_size.rgba.g + i->pixel_size.rgba.b
00688 <= 12)) {
00689
00690 XFree(v);
00691 return -1;
00692 }
00693
00694 i->colour_depth = 0;
00695
00696 if (i->pixel_size.rgba.r == 3
00697 && i->pixel_size.rgba.g == 3
00698 && i->pixel_size.rgba.b == 2) {
00699 i->colour_depth = 8;
00700 }
00701
00702 if (i->pixel_size.rgba.r == 5
00703 && i->pixel_size.rgba.b == 5) {
00704 if (i->pixel_size.rgba.g == 5) {
00705 i->colour_depth = 15;
00706 }
00707 if (i->pixel_size.rgba.g == 6) {
00708 i->colour_depth = 16;
00709 }
00710 }
00711
00712 if (i->pixel_size.rgba.r == 8
00713 && i->pixel_size.rgba.g == 8
00714 && i->pixel_size.rgba.b == 8) {
00715 if (i->pixel_size.rgba.a == 0) {
00716 i->colour_depth = 24;
00717 }
00718 if (i->pixel_size.rgba.a == 8) {
00719 i->colour_depth = 32;
00720
00721 i->a_shift = 48 - i->r_shift - i->g_shift - i->b_shift;
00722 }
00723 }
00724
00725 i->allegro_format = (i->colour_depth != 0)
00726 && (i->g_shift == i->pixel_size.rgba.b)
00727 && (i->r_shift * i->b_shift == 0)
00728 && (i->r_shift + i->b_shift
00729 == i->pixel_size.rgba.b + i->pixel_size.rgba.g);
00730
00731 if (glXGetConfig(_xwin.display, v, GLX_SAMPLE_BUFFERS, &sbuffers)) {
00732
00733 i->sample_buffers = 0;
00734 }
00735 else {
00736 i->sample_buffers = sbuffers;
00737 }
00738 if (glXGetConfig(_xwin.display, v, GLX_SAMPLES, &samples)) {
00739
00740 i->samples = 0;
00741 }
00742 else {
00743 i->samples = samples;
00744 }
00745
00746 XFree(v);
00747
00748 TRACE(PREFIX_I "Color Depth: %i\n", buffer_size);
00749 TRACE(PREFIX_I "RGBA Type: %s point\n", i->float_color ? "floating" : "fixed");
00750 TRACE(PREFIX_I "RGBA: %i.%i.%i.%i\n", i->pixel_size.rgba.r, i->pixel_size.rgba.g,
00751 i->pixel_size.rgba.b, i->pixel_size.rgba.a);
00752 TRACE(PREFIX_I "Accum: %i.%i.%i.%i\n", i->accum_size.rgba.r, i->accum_size.rgba.g,
00753 i->accum_size.rgba.b, i->accum_size.rgba.a);
00754 TRACE(PREFIX_I "DblBuf: %i Zbuf: %i Stereo: %i Aux: %i Stencil: %i\n",
00755 i->doublebuffered, i->depth_size, i->stereo,
00756 i->aux_buffers, i->stencil_size);
00757 TRACE(PREFIX_I "Shift: %i.%i.%i.%i\n", i->r_shift, i->g_shift, i->b_shift,
00758 i->a_shift);
00759 TRACE(PREFIX_I "Sample Buffers: %i Samples: %i\n", i->sample_buffers, i->samples);
00760 TRACE(PREFIX_I "Decoded bpp: %i\n", i->colour_depth);
00761
00762 return 0;
00763 }
00764
00765
00766
00767 int allegro_gl_x_windowed_choose_fbconfig (GLXFBConfig *ret_fbconfig) {
00768 int num_fbconfigs, i;
00769 GLXFBConfig *fbconfig;
00770 struct allegro_gl_display_info dinfo;
00771
00772 fbconfig = glXGetFBConfigs (_xwin.display, _xwin.screen, &num_fbconfigs);
00773 if (!fbconfig || !num_fbconfigs)
00774 return FALSE;
00775
00776 TRACE(PREFIX_I "x_windowed_choose_fbconfig: %i formats.\n", num_fbconfigs);
00777 __allegro_gl_reset_scorer();
00778
00779 for (i = 0; i < num_fbconfigs; i++) {
00780 TRACE(PREFIX_I "x_windowed_choose_fbconfig: Mode %i\n", i);
00781 if (decode_fbconfig (*(fbconfig + i), &dinfo) != -1) {
00782 __allegro_gl_score_config (i, &dinfo);
00783 }
00784 }
00785
00786 i = __allegro_gl_best_config();
00787 TRACE(PREFIX_I "x_windowed_choose_fbconfig: Best FBConfig is: %i\n", i);
00788
00789 if (i < 0) {
00790 XFree(fbconfig);
00791 return FALSE;
00792 }
00793
00794 *ret_fbconfig = *(fbconfig + i);
00795 XFree(fbconfig);
00796
00797 return TRUE;
00798 }
00799
00800
00801
00802
00803
00804
00805 static XVisualInfo *allegro_gl_x_windowed_choose_visual (void)
00806 {
00807 int num_visuals, i;
00808 XVisualInfo *vinfo;
00809 struct allegro_gl_display_info dinfo;
00810 static XVisualInfo ret_vinfo;
00811
00812 vinfo = XGetVisualInfo (_xwin.display, 0, NULL, &num_visuals);
00813 if (!vinfo) return NULL;
00814
00815 TRACE(PREFIX_I "x_windowed_choose_visual: %i formats.\n", num_visuals);
00816 __allegro_gl_reset_scorer();
00817
00818 for (i = 0; i < num_visuals; i++) {
00819 TRACE(PREFIX_I "x_windowed_choose_visual: Mode %i\n", i);
00820 if (decode_visual (vinfo + i, &dinfo) != -1) {
00821 __allegro_gl_score_config (i, &dinfo);
00822 }
00823 }
00824
00825 i = __allegro_gl_best_config();
00826 TRACE(PREFIX_I "x_windowed_choose_visual: Best config is: %i\n", i);
00827
00828 if (i < 0) return NULL;
00829
00830 memcpy (&ret_vinfo, vinfo+i, sizeof ret_vinfo);
00831 XFree (vinfo);
00832
00833 return &ret_vinfo;
00834 }
00835
00836
00837
00838 #ifdef ALLEGROGL_HAVE_XF86VIDMODE
00839
00840
00841
00842
00843 static int get_xf86_modes(XF86VidModeModeInfo ***modesinfo, int *num_modes)
00844 {
00845 int vid_event_base, vid_error_base;
00846 int vid_major_version, vid_minor_version;
00847
00848
00849 if (!XF86VidModeQueryExtension(_xwin.display, &vid_event_base,
00850 &vid_error_base)
00851 || !XF86VidModeQueryVersion(_xwin.display, &vid_major_version,
00852 &vid_minor_version)) {
00853
00854 ustrzcpy (allegro_gl_error, AGL_ERROR_SIZE,
00855 get_config_text("VidMode extension is not supported"));
00856 return -1;
00857 }
00858
00859 if (!XF86VidModeGetAllModeLines(_xwin.display, _xwin.screen, num_modes,
00860 modesinfo)) {
00861 ustrzcpy (allegro_gl_error, AGL_ERROR_SIZE,
00862 get_config_text("Can not Get ModeLines"));
00863 return -1;
00864 }
00865
00866 return 0;
00867 }
00868 #endif
00869
00870
00871 static int allegro_gl_x_error_handler(Display *display, XErrorEvent *err_event)
00872 {
00873 char buffer[256];
00874
00875 XGetErrorText(display, err_event->error_code, buffer, 256);
00876 TRACE(PREFIX_E "%s\n", buffer);
00877 return 0;
00878 }
00879
00880
00881
00882
00883
00884
00885 static int allegro_gl_x_create_window (int fullscreen)
00886 {
00887 Window root;
00888 XVisualInfo *visinfo;
00889 XSetWindowAttributes setattr;
00890 unsigned long valuemask = CWBackPixel | CWBorderPixel | CWColormap
00891 | CWEventMask;
00892 XSizeHints *hints;
00893 #ifdef ALLEGROGL_HAVE_XF86VIDMODE
00894 int bestmode=0;
00895 #endif
00896 GLXFBConfig fbconfig;
00897 int use_fbconfig;
00898
00899 if (_xwin.display == 0) {
00900 return -1;
00901 }
00902
00903 old_x_error_handler = XSetErrorHandler(allegro_gl_x_error_handler);
00904
00905
00906 __allegro_gl_fill_in_info();
00907
00908 #ifdef ALLEGROGL_HAVE_XF86VIDMODE
00909 if (fullscreen) {
00910 int i;
00911 _xwin.num_modes = 0;
00912 _xwin.modesinfo = NULL;
00913 _glxwin.fullscreen = TRUE;
00914
00915 if (get_xf86_modes(&_xwin.modesinfo, &_xwin.num_modes)) {
00916 TRACE(PREFIX_E "x_create_window: Can't get XF86VidMode info.\n");
00917 XSetErrorHandler(old_x_error_handler);
00918 return -1;
00919 }
00920
00921
00922 for (i = 0; i < _xwin.num_modes; i++)
00923 {
00924 if ((_xwin.modesinfo[i]->hdisplay == allegro_gl_display_info.w)
00925 && (_xwin.modesinfo[i]->vdisplay == allegro_gl_display_info.h))
00926 bestmode = i;
00927 }
00928 }
00929 #endif
00930
00931 use_fbconfig = (_glxwin.major > 1 || (_glxwin.major == 1 && _glxwin.minor >= 3));
00932
00933 if (use_fbconfig) {
00934 TRACE(PREFIX_I "x_create_window: using FBConfig routines\n");
00935
00936 if (!allegro_gl_x_windowed_choose_fbconfig(&fbconfig)) {
00937 TRACE(PREFIX_I "x_create_window: Failed using FBConfig, switching "
00938 "back to VisualInfo routines\n");
00939 use_fbconfig = FALSE;
00940 goto old_choose_visual;
00941 }
00942
00943
00944 if (decode_fbconfig(fbconfig, &allegro_gl_display_info)) {
00945 TRACE(PREFIX_E "x_create_window: Cannot decode FBConfig, switching "
00946 "back to VisualInfo routines\n");
00947 use_fbconfig = FALSE;
00948 goto old_choose_visual;
00949 }
00950
00951 visinfo = glXGetVisualFromFBConfig(_xwin.display, fbconfig);
00952 if (!visinfo) {
00953 TRACE(PREFIX_I "x_create_window: Failed to convert FBConfig to "
00954 "visual, switching back to VisualInfo routines\n");
00955 use_fbconfig = FALSE;
00956 goto old_choose_visual;
00957 }
00958 }
00959 else {
00960 old_choose_visual:
00961 TRACE(PREFIX_I "x_create_window: using VisualInfo routines\n");
00962
00963
00964 visinfo = allegro_gl_x_windowed_choose_visual();
00965 if (!visinfo) {
00966 TRACE(PREFIX_E "x_create_window: Can not get visual.\n");
00967 XSetErrorHandler(old_x_error_handler);
00968 return -1;
00969 }
00970
00971
00972 if (decode_visual (visinfo, &allegro_gl_display_info)) {
00973 TRACE(PREFIX_E "x_create_window: Can not decode visual.\n");
00974 XSetErrorHandler(old_x_error_handler);
00975 return -1;
00976 }
00977 }
00978
00979
00980 switch (visinfo->class) {
00981 case TrueColor:
00982 AGL_LOG (1, "x.c: visual class: TrueColor\n");
00983 break;
00984 case DirectColor:
00985 AGL_LOG (1, "x.c: visual class: DirectColor\n");
00986 break;
00987 default:
00988 AGL_LOG (1, "x.c: visual class: invalid(!)\n");
00989 }
00990
00991 root = RootWindow (_xwin.display, _xwin.screen);
00992
00993
00994 setattr.background_pixel = XBlackPixel (_xwin.display, _xwin.screen);
00995 setattr.border_pixel = XBlackPixel (_xwin.display, _xwin.screen);
00996 setattr.colormap = XCreateColormap (_xwin.display, root, visinfo->visual, AllocNone);
00997 setattr.event_mask =
00998 ( KeyPressMask | KeyReleaseMask
00999 | EnterWindowMask | LeaveWindowMask
01000 | FocusChangeMask | ExposureMask
01001 | ButtonPressMask | ButtonReleaseMask | PointerMotionMask
01002
01003 );
01004
01005 #ifdef ALLEGROGL_HAVE_XF86VIDMODE
01006 if (fullscreen) {
01007 setattr.override_redirect = True;
01008 if (!XF86VidModeSwitchToMode(_xwin.display, _xwin.screen,
01009 _xwin.modesinfo[bestmode])) {
01010
01011 ustrzcpy (allegro_gl_error, AGL_ERROR_SIZE,
01012 get_config_text("Can not set XF86VidMode mode"));
01013 XSetErrorHandler(old_x_error_handler);
01014 return -1;
01015 }
01016
01017 XF86VidModeSetViewPort(_xwin.display, _xwin.screen, 0, 0);
01018
01019
01020 XF86VidModeLockModeSwitch(_xwin.display, _xwin.screen, True);
01021 _xwin.mode_switched = 1;
01022
01023 allegro_gl_display_info.x = 0;
01024 allegro_gl_display_info.y = 0;
01025 allegro_gl_display_info.w = _xwin.modesinfo[bestmode]->hdisplay;
01026 allegro_gl_display_info.h = _xwin.modesinfo[bestmode]->vdisplay;
01027
01028 valuemask |= CWOverrideRedirect;
01029 _xwin.override_redirected = 1;
01030 }
01031 #endif
01032
01033 #if GET_ALLEGRO_VERSION() >= MAKE_VER(4, 2, 1)
01034
01035 if (backup_allegro_window == None) {
01036 backup_allegro_window = _xwin.window;
01037 backup_allegro_colormap = _xwin.colormap;
01038 _xwin.colormap = None;
01039 XUnmapWindow(_xwin.display, _xwin.window);
01040 }
01041 else
01042 #endif
01043 XDestroyWindow (_xwin.display, _xwin.window);
01044
01045 _xwin.window = XCreateWindow (
01046 _xwin.display, root,
01047 allegro_gl_display_info.x, allegro_gl_display_info.y,
01048 allegro_gl_display_info.w, allegro_gl_display_info.h, 0,
01049 visinfo->depth,
01050 InputOutput,
01051 visinfo->visual,
01052 valuemask, &setattr
01053 );
01054
01055
01056
01057
01058 hints = XAllocSizeHints();
01059 if (hints) {
01060
01061 hints->flags = PMinSize | PMaxSize | PBaseSize;
01062 hints->min_width = hints->max_width = hints->base_width
01063 = allegro_gl_display_info.w;
01064 hints->min_height = hints->max_height = hints->base_height
01065 = allegro_gl_display_info.h;
01066
01067 XSetWMNormalHints(_xwin.display, _xwin.window, hints);
01068 XFree(hints);
01069 }
01070
01071
01072
01073
01074
01075 Atom wm_delete_window = XInternAtom(_xwin.display, "WM_DELETE_WINDOW",
01076 False);
01077 XSetWMProtocols(_xwin.display, _xwin.window, &wm_delete_window, 1);
01078
01079
01080 if (use_fbconfig)
01081 _glxwin.ctx = glXCreateNewContext (_xwin.display, fbconfig, GLX_RGBA_TYPE, NULL, True);
01082 else
01083 _glxwin.ctx = glXCreateContext (_xwin.display, visinfo, NULL, True);
01084
01085 if (use_fbconfig) {
01086 _glxwin.window = glXCreateWindow(_xwin.display, fbconfig, _xwin.window, 0);
01087 if (!_glxwin.window) {
01088 ustrzcpy (allegro_gl_error, AGL_ERROR_SIZE,
01089 get_config_text("Cannot create GLX window."));
01090 XSetErrorHandler(old_x_error_handler);
01091 return -1;
01092 }
01093 _glxwin.use_glx_window = TRUE;
01094 }
01095
01096 if (!_glxwin.ctx) {
01097 ustrzcpy (allegro_gl_error, AGL_ERROR_SIZE,
01098 get_config_text("Can not create GLX context."));
01099 XSetErrorHandler(old_x_error_handler);
01100 return -1;
01101 }
01102 else {
01103 Bool ret;
01104
01105 if (use_fbconfig)
01106 ret = glXMakeContextCurrent(_xwin.display, _glxwin.window, _glxwin.window, _glxwin.ctx);
01107 else
01108 ret = glXMakeCurrent (_xwin.display, _xwin.window, _glxwin.ctx);
01109
01110 if (!ret) {
01111 ustrzcpy (allegro_gl_error, AGL_ERROR_SIZE,
01112 get_config_text("Cannot make GLX context current."));
01113 XSetErrorHandler(old_x_error_handler);
01114 return -1;
01115 }
01116 }
01117
01118
01119
01120
01121
01122 {
01123 XWindowAttributes getattr;
01124 XGetWindowAttributes(_xwin.display, _xwin.window, &getattr);
01125 _xwin.visual = getattr.visual;
01126 _xwin.window_depth = getattr.depth;
01127 _xwin.window_width = allegro_gl_display_info.w;
01128 _xwin.window_height = allegro_gl_display_info.h;
01129 _xwin.screen_depth = getattr.depth;
01130 _xwin.screen_width = allegro_gl_display_info.w;
01131 _xwin.screen_height = allegro_gl_display_info.h;
01132 }
01133
01134
01135 if (_xwin.colormap != None) {
01136 XUninstallColormap(_xwin.display, _xwin.colormap);
01137 XFreeColormap(_xwin.display, _xwin.colormap);
01138 }
01139
01140
01141 if (_xwin.visual->class == DirectColor) {
01142 _xwin.colormap = XCreateColormap(_xwin.display, _xwin.window,
01143 _xwin.visual, AllocAll);
01144 }
01145 else {
01146 _xwin.colormap = XCreateColormap(_xwin.display, _xwin.window,
01147 _xwin.visual, AllocNone);
01148 }
01149 XSetWindowColormap(_xwin.display, _xwin.window, _xwin.colormap);
01150 XInstallColormap(_xwin.display, _xwin.colormap);
01151
01152
01153 if (_xwin.visual->class == DirectColor) {
01154 XColor color;
01155 int rsize, gsize, bsize;
01156 int rmax, gmax, bmax;
01157 int rshift, gshift, bshift;
01158 int r, g, b;
01159
01160 AGL_LOG (1, "x.c: Using DirectColor visual, setting palette...\n");
01161
01162 rsize = 1 << allegro_gl_display_info.pixel_size.rgba.r;
01163 gsize = 1 << allegro_gl_display_info.pixel_size.rgba.g;
01164 bsize = 1 << allegro_gl_display_info.pixel_size.rgba.b;
01165
01166 rshift = allegro_gl_display_info.r_shift;
01167 bshift = allegro_gl_display_info.b_shift;
01168 gshift = allegro_gl_display_info.g_shift;
01169
01170 rmax = rsize - 1;
01171 gmax = gsize - 1;
01172 bmax = bsize - 1;
01173
01174 color.flags = DoRed | DoGreen | DoBlue;
01175 for (r = 0; r < rsize; r++) {
01176 for (g = 0; g < gsize; g++) {
01177 for (b = 0; b < bsize; b++) {
01178 color.pixel = (r << rshift) | (g << gshift) | (b << bshift);
01179 color.red = ((rmax <= 0) ? 0 : ((r * 65535L) / rmax));
01180 color.green = ((gmax <= 0) ? 0 : ((g * 65535L) / gmax));
01181 color.blue = ((bmax <= 0) ? 0 : ((b * 65535L) / bmax));
01182 XStoreColor(_xwin.display, _xwin.colormap, &color);
01183 }
01184 }
01185 }
01186 }
01187
01188
01189 {
01190 XClassHint hint;
01191 XWMHints wm_hints;
01192
01193
01194 XStoreName(_xwin.display, _xwin.window, _xwin.window_title);
01195
01196
01197 hint.res_name = _xwin.application_name;
01198 hint.res_class = _xwin.application_class;
01199 XSetClassHint(_xwin.display, _xwin.window, &hint);
01200
01201 wm_hints.flags = InputHint | StateHint;
01202 wm_hints.input = True;
01203 wm_hints.initial_state = NormalState;
01204
01205 #ifdef ALLEGRO_XWINDOWS_WITH_XPM
01206 if (allegro_icon) {
01207 wm_hints.flags |= IconPixmapHint | IconMaskHint | WindowGroupHint;
01208 XpmCreatePixmapFromData(_xwin.display, _xwin.window, allegro_icon,&wm_hints.icon_pixmap, &wm_hints.icon_mask, NULL);
01209 }
01210 #endif
01211
01212 XSetWMHints(_xwin.display, _xwin.window, &wm_hints);
01213 }
01214
01215
01216 XMapWindow(_xwin.display, _xwin.window);
01217
01218
01219 #ifdef ALLEGROGL_HAVE_XF86VIDMODE
01220 if (fullscreen) {
01221 AL_CONST char *fc = NULL;
01222 char tmp1[64], tmp2[128];
01223 int c = 0;
01224 int h = allegro_gl_display_info.h;
01225 int w = allegro_gl_display_info.w;
01226
01227
01228
01229 fc = get_config_string(uconvert_ascii("graphics", tmp1),
01230 uconvert_ascii("force_centering", tmp2), NULL);
01231 if ((fc) && ((c = ugetc(fc)) != 0) && ((c == 'y') || (c == 'Y')
01232 || (c == '1'))) {
01233
01234 XWarpPointer(_xwin.display, None, _xwin.window, 0, 0, 0, 0, 0, 0);
01235 XWarpPointer(_xwin.display, None, _xwin.window, 0, 0, 0, 0,
01236 w - 1, 0);
01237 XWarpPointer(_xwin.display, None, _xwin.window, 0, 0, 0, 0,
01238 0, h - 1);
01239 XWarpPointer(_xwin.display, None, _xwin.window, 0, 0, 0, 0,
01240 w - 1, h - 1);
01241 }
01242 XWarpPointer(_xwin.display, None, _xwin.window, 0, 0, 0, 0,
01243 w / 2, h / 2);
01244 XSync(_xwin.display, False);
01245
01246
01247 if (XGrabKeyboard(_xwin.display, _xwin.window, False, GrabModeAsync,
01248 GrabModeAsync, CurrentTime) != GrabSuccess) {
01249 ustrzcpy (allegro_gl_error, AGL_ERROR_SIZE,
01250 get_config_text("Can not grab keyboard"));
01251 XSetErrorHandler(old_x_error_handler);
01252 return -1;
01253 }
01254 _xwin.keyboard_grabbed = 1;
01255
01256 if (XGrabPointer(_xwin.display, _xwin.window, False,
01257 PointerMotionMask | ButtonPressMask | ButtonReleaseMask,
01258 GrabModeAsync, GrabModeAsync, _xwin.window, None, CurrentTime)
01259 != GrabSuccess) {
01260
01261 ustrzcpy (allegro_gl_error, AGL_ERROR_SIZE,
01262 get_config_text("Can not grab mouse"));
01263 XSetErrorHandler(old_x_error_handler);
01264 return -1;
01265 }
01266 _xwin.mouse_grabbed = 1;
01267 }
01268 #endif
01269
01270
01271
01272 if (_xwin.cursor != None) {
01273 XUndefineCursor(_xwin.display, _xwin.window);
01274 XFreeCursor(_xwin.display, _xwin.cursor);
01275 }
01276
01277 {
01278
01279 Pixmap pixmap = XCreatePixmap(_xwin.display, _xwin.window, 1, 1, 1);
01280 if (pixmap != None) {
01281 GC temp_gc;
01282 XColor color;
01283 XGCValues gcvalues;
01284
01285 int gcmask = GCFunction | GCForeground | GCBackground;
01286 gcvalues.function = GXcopy;
01287 gcvalues.foreground = 0;
01288 gcvalues.background = 0;
01289 temp_gc = XCreateGC(_xwin.display, pixmap, gcmask, &gcvalues);
01290 XDrawPoint(_xwin.display, pixmap, temp_gc, 0, 0);
01291 XFreeGC(_xwin.display, temp_gc);
01292 color.pixel = 0;
01293 color.red = color.green = color.blue = 0;
01294 color.flags = DoRed | DoGreen | DoBlue;
01295 _xwin.cursor = XCreatePixmapCursor(_xwin.display, pixmap, pixmap,
01296 &color, &color, 0, 0);
01297 XDefineCursor(_xwin.display, _xwin.window, _xwin.cursor);
01298 XFreePixmap(_xwin.display, pixmap);
01299 }
01300 else {
01301 _xwin.cursor = XCreateFontCursor(_xwin.display, _xwin.cursor_shape);
01302 XDefineCursor(_xwin.display, _xwin.window, _xwin.cursor);
01303 }
01304 }
01305
01306
01307 {
01308 XEvent event;
01309 do {
01310 XNextEvent(_xwin.display, &event);
01311 } while ((event.type != Expose) || (event.xexpose.count != 0));
01312 }
01313
01314 return 0;
01315 }
01316
01317
01318
01319 static BITMAP *allegro_gl_x_windowed_create_screen (GFX_DRIVER *drv, int w, int h, int depth)
01320 {
01321 BITMAP *bmp;
01322 int is_linear = drv->linear;
01323
01324 drv->linear = 1;
01325 bmp = _make_bitmap (w, h, 0, drv, depth, 0);
01326 bmp->id = BMP_ID_VIDEO | BMP_ID_MASK;
01327 drv->linear = is_linear;
01328
01329 if (bmp == 0) {
01330 ustrzcpy (allegro_gl_error, AGL_ERROR_SIZE,
01331 get_config_text("Not enough memory"));
01332 return NULL;
01333 }
01334
01335 drv->w = w;
01336 drv->h = h;
01337
01338 return bmp;
01339 }
01340
01341
01342
01343
01344
01345
01346 static int decode_visual (XVisualInfo *v, struct allegro_gl_display_info *i)
01347 {
01348 int rgba, buffer_size, use_gl, sbuffers, samples;
01349
01350 TRACE(PREFIX_I "decode_visual: Decoding:\n");
01351 i->rmethod = 2;
01352
01353
01354
01355 if (v->class != TrueColor && v->class != DirectColor)
01356 return -1;
01357
01358 if (glXGetConfig (_xwin.display, v, GLX_RGBA, &rgba)
01359 || glXGetConfig (_xwin.display, v, GLX_USE_GL, &use_gl)
01360 || glXGetConfig (_xwin.display, v, GLX_BUFFER_SIZE, &buffer_size)
01361 || glXGetConfig (_xwin.display, v, GLX_RED_SIZE, &i->pixel_size.rgba.r)
01362 || glXGetConfig (_xwin.display, v, GLX_GREEN_SIZE, &i->pixel_size.rgba.g)
01363 || glXGetConfig (_xwin.display, v, GLX_BLUE_SIZE, &i->pixel_size.rgba.b)
01364 || glXGetConfig (_xwin.display, v, GLX_ALPHA_SIZE, &i->pixel_size.rgba.a)
01365 || glXGetConfig (_xwin.display, v, GLX_DOUBLEBUFFER, &i->doublebuffered)
01366 || glXGetConfig (_xwin.display, v, GLX_STEREO, &i->stereo)
01367 || glXGetConfig (_xwin.display, v, GLX_AUX_BUFFERS, &i->aux_buffers)
01368 || glXGetConfig (_xwin.display, v, GLX_DEPTH_SIZE, &i->depth_size)
01369 || glXGetConfig (_xwin.display, v, GLX_STENCIL_SIZE, &i->stencil_size)
01370 || glXGetConfig (_xwin.display, v, GLX_ACCUM_RED_SIZE,
01371 &i->accum_size.rgba.r)
01372 || glXGetConfig (_xwin.display, v, GLX_ACCUM_GREEN_SIZE,
01373 &i->accum_size.rgba.g)
01374 || glXGetConfig (_xwin.display, v, GLX_ACCUM_BLUE_SIZE,
01375 &i->accum_size.rgba.b)
01376 || glXGetConfig (_xwin.display, v, GLX_ACCUM_ALPHA_SIZE,
01377 &i->accum_size.rgba.a)) {
01378 TRACE(PREFIX_I "x_create_window: Incomplete glX mode ...\n");
01379 return -1;
01380 }
01381
01382 if (!rgba) {
01383 TRACE(PREFIX_I "x_create_window: Not RGBA mode\n");
01384 return -1;
01385 }
01386
01387 if (!use_gl) {
01388 ustrzcpy (allegro_gl_error, AGL_ERROR_SIZE,
01389 get_config_text("OpenGL Unsupported"));
01390 return -1;
01391 }
01392
01393 i->r_shift = get_shift (v->red_mask);
01394 i->g_shift = get_shift (v->green_mask);
01395 i->b_shift = get_shift (v->blue_mask);
01396 i->a_shift = 0;
01397
01398
01399 if ((v->class == DirectColor)
01400 && ((i->r_shift == -1) || (i->g_shift == -1) || (i->b_shift == -1))
01401 && (i->pixel_size.rgba.r + i->pixel_size.rgba.g + i->pixel_size.rgba.b
01402 <= 12)) {
01403
01404 return -1;
01405 }
01406
01407 i->float_color = 0;
01408 i->float_depth = 0;
01409
01410 i->colour_depth = 0;
01411
01412 if (i->pixel_size.rgba.r == 3
01413 && i->pixel_size.rgba.g == 3
01414 && i->pixel_size.rgba.b == 2) {
01415 i->colour_depth = 8;
01416 }
01417
01418 if (i->pixel_size.rgba.r == 5
01419 && i->pixel_size.rgba.b == 5) {
01420 if (i->pixel_size.rgba.g == 5) {
01421 i->colour_depth = 15;
01422 }
01423 if (i->pixel_size.rgba.g == 6) {
01424 i->colour_depth = 16;
01425 }
01426 }
01427
01428 if (i->pixel_size.rgba.r == 8
01429 && i->pixel_size.rgba.g == 8
01430 && i->pixel_size.rgba.b == 8) {
01431 if (i->pixel_size.rgba.a == 0) {
01432 i->colour_depth = 24;
01433 }
01434 if (i->pixel_size.rgba.a == 8) {
01435 i->colour_depth = 32;
01436
01437 i->a_shift = 48 - i->r_shift - i->g_shift - i->b_shift;
01438 }
01439 }
01440
01441 i->allegro_format = (i->colour_depth != 0)
01442 && (i->g_shift == i->pixel_size.rgba.b)
01443 && (i->r_shift * i->b_shift == 0)
01444 && (i->r_shift + i->b_shift
01445 == i->pixel_size.rgba.b + i->pixel_size.rgba.g);
01446
01447 if (glXGetConfig(_xwin.display, v, GLX_SAMPLE_BUFFERS, &sbuffers)
01448 == GLX_BAD_ATTRIBUTE) {
01449
01450 i->sample_buffers = 0;
01451 }
01452 else {
01453 i->sample_buffers = sbuffers;
01454 }
01455 if (glXGetConfig(_xwin.display, v, GLX_SAMPLES, &samples)
01456 == GLX_BAD_ATTRIBUTE) {
01457
01458 i->samples = 0;
01459 }
01460 else {
01461 i->samples = samples;
01462 }
01463
01464
01465 TRACE(PREFIX_I "Color Depth: %i\n", buffer_size);
01466 TRACE(PREFIX_I "RGBA: %i.%i.%i.%i\n", i->pixel_size.rgba.r, i->pixel_size.rgba.g,
01467 i->pixel_size.rgba.b, i->pixel_size.rgba.a);
01468 TRACE(PREFIX_I "Accum: %i.%i.%i.%i\n", i->accum_size.rgba.r, i->accum_size.rgba.g,
01469 i->accum_size.rgba.b, i->accum_size.rgba.a);
01470 TRACE(PREFIX_I "DblBuf: %i Zbuf: %i Stereo: %i Aux: %i Stencil: %i\n",
01471 i->doublebuffered, i->depth_size, i->stereo,
01472 i->aux_buffers, i->stencil_size);
01473 TRACE(PREFIX_I "Shift: %i.%i.%i.%i\n", i->r_shift, i->g_shift, i->b_shift,
01474 i->a_shift);
01475 TRACE(PREFIX_I "Sample Buffers: %i Samples: %i\n", i->sample_buffers, i->samples);
01476 TRACE(PREFIX_I "Decoded bpp: %i\n", i->colour_depth);
01477
01478 return 0;
01479 }
01480
01481
01482
01483 #ifdef ALLEGROGL_HAVE_XF86VIDMODE
01484
01485
01486
01487
01488 static GFX_MODE_LIST* allegro_gl_x_fetch_mode_list(void)
01489 {
01490 int num_modes = 0;
01491 XF86VidModeModeInfo **modesinfo = NULL;
01492 GFX_MODE_LIST *mode_list;
01493 int i;
01494
01495 XLOCK();
01496
01497 if (get_xf86_modes(&modesinfo, &num_modes)) {
01498 XUNLOCK();
01499 return NULL;
01500 }
01501
01502
01503 mode_list = malloc(sizeof(GFX_MODE_LIST));
01504 if (!mode_list) {
01505 free_modelines(modesinfo, num_modes);
01506 XUNLOCK();
01507 return NULL;
01508 }
01509
01510 mode_list->mode = malloc(sizeof(GFX_MODE) * (num_modes + 1));
01511 if (!mode_list->mode) {
01512 free(mode_list);
01513 free_modelines(modesinfo, num_modes);
01514 XUNLOCK();
01515 return NULL;
01516 }
01517
01518
01519 for (i = 0; i < num_modes; i++) {
01520 mode_list->mode[i].width = modesinfo[i]->hdisplay;
01521 mode_list->mode[i].height = modesinfo[i]->vdisplay;
01522
01523
01524
01525
01526 mode_list->mode[i].bpp = desktop_color_depth();
01527 }
01528
01529 mode_list->mode[num_modes].width = 0;
01530 mode_list->mode[num_modes].height = 0;
01531 mode_list->mode[num_modes].bpp = 0;
01532 mode_list->num_modes = num_modes;
01533
01534 free_modelines(modesinfo, num_modes);
01535
01536 XUNLOCK();
01537 return mode_list;
01538 }
01539 #endif
01540
01541
01542
01543
01544
01545
01546 static void allegro_gl_x_vsync(void)
01547 {
01548 XLOCK();
01549 if (allegro_gl_extensions_GLX.SGI_video_sync) {
01550 unsigned int count;
01551
01552 glXGetVideoSyncSGI(&count);
01553 glXWaitVideoSyncSGI(2, (count+1) & 1, &count);
01554 }
01555 XUNLOCK();
01556 }
01557
01558
01559
01560
01561
01562
01563
01564
01565
01566
01567 static void flip (void)
01568 {
01569 XLOCK();
01570 if (_glxwin.use_glx_window)
01571 glXSwapBuffers (_xwin.display, _glxwin.window);
01572 else
01573 glXSwapBuffers (_xwin.display, _xwin.window);
01574 XUNLOCK();
01575 }
01576
01577
01578
01579
01580
01581
01582 static void gl_on (void)
01583 {
01584 #ifdef OLD_ALLEGRO
01585 DISABLE();
01586 #endif
01587 }
01588
01589
01590
01591 static void gl_off (void)
01592 {
01593 #ifdef OLD_ALLEGRO
01594 ENABLE();
01595 _xwin_handle_input();
01596 #endif
01597 }
01598
01599
01600
01601
01602
01603
01604
01605 static struct allegro_gl_driver allegro_gl_x = {
01606 flip,
01607 gl_on,
01608 gl_off,
01609 NULL
01610 };
01611