00001
00002
00003
00004
00005
00006 #include <string.h>
00007
00008 #include <allegro.h>
00009 #include <xalleg.h>
00010
00011 #include <allegro/platform/aintunix.h>
00012
00013 #include "alleggl.h"
00014 #include "allglint.h"
00015 #include "glvtable.h"
00016
00017
00018 #ifndef XLOCK
00019 #define OLD_ALLEGRO
00020 #define XLOCK() DISABLE()
00021 #undef XUNLOCK
00022 #define XUNLOCK() ENABLE()
00023 #endif
00024
00025
00026 #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,
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
00078 };
00079 #endif
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,
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,
00109 0, 0,
00110 0,
00111 0, 0,
00112 0,
00113 0,
00114 TRUE
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;
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
00140
00141
00142
00143
00144
00145
00146 static void allegro_gl_redraw_window(int x, int y, int w, int h)
00147 {
00148
00149 return;
00150 }
00151
00152
00153
00154 #ifdef ALLEGRO_XWINDOWS_WITH_XCURSOR
00155
00156
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
00205
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
00222
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
00237
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
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
00309 set_color_depth(allegro_gl_display_info.colour_depth);
00310
00311
00312
00313
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
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
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
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
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
00376 __allegro_gl_manage_extensions();
00377
00378
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
00413
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
00425
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
00436
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
00452
00453
00454 static void allegro_gl_x_exit(BITMAP *bmp)
00455 {
00456 #ifdef ALLEGROGL_HAVE_XF86VIDMODE
00457 XSetWindowAttributes setattr;
00458 #endif
00459
00460
00461
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
00470
00471
00472
00473
00474
00475
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
00514 free_modelines(_xwin.modesinfo, _xwin.num_modes);
00515 _xwin.num_modes = 0;
00516 _xwin.modesinfo = NULL;
00517 }
00518 #endif
00519
00520
00521
00522
00523
00524 ASSERT(allegro_gl_screen == screen);
00525 allegro_gl_screen = NULL;
00526
00527
00528
00529
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
00543
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
00580
00581
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
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
00623
00624
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
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
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
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
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
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
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
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
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
00756
00757
00758 hints = XAllocSizeHints();
00759 if (hints) {
00760
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
00772
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
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
00797
00798
00799
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
00813 if (_xwin.colormap != None) {
00814 XUninstallColormap(_xwin.display, _xwin.colormap);
00815 XFreeColormap(_xwin.display, _xwin.colormap);
00816 }
00817
00818
00819 if (_xwin.visual->class == DirectColor) {
00820 _xwin.colormap = XCreateColormap(_xwin.display, _xwin.window,
00821 _xwin.visual, AllocAll);
00822 }
00823 else {
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
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
00867 {
00868 XClassHint hint;
00869 XWMHints wm_hints;
00870
00871
00872 XStoreName(_xwin.display, _xwin.window, _xwin.window_title);
00873
00874
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
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
00907
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
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
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
00951 if (_xwin.cursor != None) {
00952 XUndefineCursor(_xwin.display, _xwin.window);
00953 XFreeCursor(_xwin.display, _xwin.cursor);
00954 }
00955
00956 {
00957
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
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
01023
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
01039
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
01049
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
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
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
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
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
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
01178
01179
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
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
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
01216
01217
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
01237
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
01253
01254
01255
01256
01257
01258 static void flip (void)
01259 {
01260 XLOCK();
01261 glXSwapBuffers (_xwin.display, _xwin.window);
01262 XUNLOCK();
01263 }
01264
01265
01266
01267
01268
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
01291
01292
01293 static struct allegro_gl_driver allegro_gl_x = {
01294 flip,
01295 gl_on,
01296 gl_off,
01297 NULL
01298 };
01299