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