x.c

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

Generated on Mon Apr 3 18:20:13 2006 for AllegroGL by  doxygen 1.4.6