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