15 #include <allegro/platform/aintunix.h> 24 #define XLOCK() DISABLE() 26 #define XUNLOCK() ENABLE() 29 #define PREFIX_I "agl-x INFO: " 30 #define PREFIX_E "agl-x ERROR: " 33 #ifdef ALLEGRO_XWINDOWS_WITH_XPM 35 extern void *allegro_icon;
39 static BITMAP *allegro_gl_x_windowed_init(
int w,
int h,
int vw,
int vh,
41 static void allegro_gl_x_exit(BITMAP *bmp);
42 #ifdef ALLEGROGL_HAVE_XF86VIDMODE 43 static GFX_MODE_LIST* allegro_gl_x_fetch_mode_list(
void);
45 static void allegro_gl_x_vsync(
void);
46 static void allegro_gl_x_hide_mouse(
void);
56 #if GET_ALLEGRO_VERSION() >= MAKE_VER(4, 2, 1) 57 static Window backup_allegro_window = None;
58 static Colormap backup_allegro_colormap = None;
62 static BITMAP *allegro_gl_x_fullscreen_init(
int w,
int h,
int vw,
int vh,
65 GFX_DRIVER gfx_allegro_gl_fullscreen =
70 "AllegroGL Fullscreen (X)",
71 allegro_gl_x_fullscreen_init,
81 allegro_gl_set_mouse_sprite,
82 allegro_gl_show_mouse,
83 allegro_gl_x_hide_mouse,
84 allegro_gl_move_mouse,
85 allegro_gl_drawing_mode,
87 allegro_gl_set_blender_mode,
88 #ifdef ALLEGROGL_HAVE_XF86VIDMODE 89 allegro_gl_x_fetch_mode_list,
103 GFX_DRIVER gfx_allegro_gl_windowed =
108 "AllegroGL Windowed (X)",
109 allegro_gl_x_windowed_init,
119 allegro_gl_set_mouse_sprite,
120 allegro_gl_show_mouse,
121 allegro_gl_x_hide_mouse,
122 allegro_gl_move_mouse,
123 allegro_gl_drawing_mode,
125 allegro_gl_set_blender_mode,
137 static struct allegro_gl_driver allegro_gl_x;
139 static XVisualInfo *allegro_gl_x_windowed_choose_visual (
void);
140 static int allegro_gl_x_create_window (
int fullscreen);
141 static BITMAP *allegro_gl_x_windowed_create_screen (GFX_DRIVER *drv,
int w,
int h,
int depth);
143 static int decode_visual (XVisualInfo *v,
struct allegro_gl_display_info *i);
148 int error_base, event_base;
153 static void (*old_window_redrawer)(int, int, int, int);
154 extern void (*_xwin_window_redrawer)(int, int, int, int);
155 static int (*old_x_error_handler)(Display*, XErrorEvent*);
166 static void allegro_gl_redraw_window(
int x,
int y,
int w,
int h)
174 #ifdef ALLEGRO_XWINDOWS_WITH_XCURSOR 178 static void _xwin_hide_x_mouse(
void)
180 unsigned long gcmask;
184 XUndefineCursor(_xwin.display, _xwin.window);
186 if (_xwin.cursor != None) {
187 XFreeCursor(_xwin.display, _xwin.cursor);
191 if (_xwin.xcursor_image != None) {
192 XcursorImageDestroy(_xwin.xcursor_image);
193 _xwin.xcursor_image = None;
196 pixmap = XCreatePixmap(_xwin.display, _xwin.window, 1, 1, 1);
197 if (pixmap != None) {
201 gcmask = GCFunction | GCForeground | GCBackground;
202 gcvalues.function = GXcopy;
203 gcvalues.foreground = 0;
204 gcvalues.background = 0;
205 temp_gc = XCreateGC(_xwin.display, pixmap, gcmask, &gcvalues);
206 XDrawPoint(_xwin.display, pixmap, temp_gc, 0, 0);
207 XFreeGC(_xwin.display, temp_gc);
209 color.red = color.green = color.blue = 0;
210 color.flags = DoRed | DoGreen | DoBlue;
211 _xwin.cursor = XCreatePixmapCursor(_xwin.display, pixmap, pixmap, &color, &color, 0, 0);
212 XDefineCursor(_xwin.display, _xwin.window, _xwin.cursor);
213 XFreePixmap(_xwin.display, pixmap);
216 _xwin.cursor = XCreateFontCursor(_xwin.display, _xwin.cursor_shape);
217 XDefineCursor(_xwin.display, _xwin.window, _xwin.cursor);
227 static void hide_mouse(
void)
229 #ifdef ALLEGRO_XWINDOWS_WITH_XCURSOR 230 if (_xwin.support_argb_cursor) {
232 _xwin_hide_x_mouse();
244 static void allegro_gl_x_hide_mouse(
void)
246 if (_xwin.hw_cursor_ok) {
250 allegro_gl_hide_mouse();
259 static BITMAP *allegro_gl_x_create_screen(
int w,
int h,
int vw,
int vh,
260 int depth,
int fullscreen)
262 int _keyboard_was_installed = FALSE;
263 int _mouse_was_installed = FALSE;
264 int create_window_ret;
267 if (!_unix_bg_man->multi_threaded) {
268 ustrzcpy (allegro_gl_error, AGL_ERROR_SIZE,
269 get_config_text(
"Fatal Error : pthread support is not enabled"));
273 if (keyboard_driver) {
274 _keyboard_was_installed = TRUE;
276 TRACE(PREFIX_I
"x_create_screen: Removing Keyboard...\n");
280 _mouse_was_installed = TRUE;
282 TRACE(PREFIX_I
"x_create_screen: Removing Mouse...\n");
287 if (!glXQueryExtension(_xwin.display, &_glxwin.error_base,
288 &_glxwin.event_base)) {
290 ustrzcpy (allegro_error, ALLEGRO_ERROR_SIZE,
291 get_config_text(
"GLX Extension not supported by display"));
296 sscanf(glXQueryServerString(_xwin.display, _xwin.screen, GLX_VERSION),
297 "%i.%i", &_glxwin.major, &_glxwin.minor);
299 if ((w == 0) && (h == 0)) {
304 if ((vw > w) || (vh > h)) {
305 ustrzcpy (allegro_error, ALLEGRO_ERROR_SIZE,
306 get_config_text (
"OpenGL drivers do not support virtual screens"));
311 allegro_gl_display_info.w = w;
312 allegro_gl_display_info.h = h;
314 old_window_redrawer = _xwin_window_redrawer;
315 _xwin_window_redrawer = allegro_gl_redraw_window;
316 _glxwin.fullscreen = FALSE;
317 _glxwin.use_glx_window = FALSE;
319 create_window_ret = allegro_gl_x_create_window(fullscreen);
320 if (create_window_ret) {
321 if (fullscreen && create_window_ret == -2) {
322 ustrzcpy (allegro_error, ALLEGRO_ERROR_SIZE,
323 get_config_text (
"Unable to switch in GLX fullscreen"));
325 else if (create_window_ret == -2) {
326 ustrzcpy (allegro_error, ALLEGRO_ERROR_SIZE,
327 get_config_text (
"Unable to create GLX window"));
330 allegro_gl_x_exit(NULL);
335 set_color_depth(allegro_gl_display_info.colour_depth);
341 __allegro_gl_set_allegro_image_format(FALSE);
345 allegro_gl_x_windowed_create_screen (&gfx_allegro_gl_fullscreen,
346 allegro_gl_display_info.w, allegro_gl_display_info.h,
351 allegro_gl_x_windowed_create_screen (&gfx_allegro_gl_windowed,
352 allegro_gl_display_info.w, allegro_gl_display_info.h,
357 ustrzcpy (allegro_error, ALLEGRO_ERROR_SIZE,
358 get_config_text (
"Error creating screen bitmap"));
360 allegro_gl_x_exit(NULL);
364 __allegro_gl_valid_context = TRUE;
365 __allegro_gl_driver = &allegro_gl_x;
368 TRACE(PREFIX_I
"OpenGL Version: %s\n", (AL_CONST
char*)glGetString(GL_VERSION));
369 TRACE(PREFIX_I
"OpenGL Vendor: %s\n", (AL_CONST
char*)glGetString(GL_VENDOR));
370 TRACE(PREFIX_I
"OpenGL Renderer: %s\n", (AL_CONST
char*)glGetString(GL_RENDERER));
373 allegro_gl_info.is_mesa_driver = FALSE;
374 if (strstr((AL_CONST
char*)glGetString(GL_VERSION),
"Mesa")) {
375 AGL_LOG(1,
"OpenGL driver based on Mesa\n");
376 allegro_gl_info.is_mesa_driver = TRUE;
380 TRACE(PREFIX_I
"GLX Version: %d.%d\n", _glxwin.major, _glxwin.minor);
383 if (glXIsDirect(_xwin.display, _glxwin.ctx)) {
384 AGL_LOG(1,
"GLX Direct Rendering is enabled\n");
387 AGL_LOG(1,
"GLX Direct Rendering is disabled\n");
392 AGL_LOG(1,
"glX Extensions:\n");
394 __allegro_gl_print_extensions(
395 (AL_CONST
char*)glXQueryExtensionsString(_xwin.display, _xwin.screen));
398 __allegro_gl_manage_extensions();
407 if (_keyboard_was_installed) {
408 TRACE(PREFIX_I
"x_create_screen: Installing Keyboard...\n");
412 if (_mouse_was_installed) {
413 TRACE(PREFIX_I
"x_create_screen: Installing Mouse...\n");
416 gfx_capabilities |= GFX_HW_CURSOR;
421 if (_keyboard_was_installed) {
425 if (_mouse_was_installed) {
437 static BITMAP *allegro_gl_x_windowed_init(
int w,
int h,
int vw,
int vh,
440 return allegro_gl_x_create_screen(w, h, vw, vh, depth, FALSE);
448 static BITMAP *allegro_gl_x_fullscreen_init(
int w,
int h,
int vw,
int vh,
451 return allegro_gl_x_create_screen(w, h, vw, vh, depth, TRUE);
456 #ifdef ALLEGROGL_HAVE_XF86VIDMODE 460 static void free_modelines(XF86VidModeModeInfo **modesinfo,
int num_modes)
464 for (i = 0; i < num_modes; i++)
465 if (modesinfo[i]->privsize > 0)
466 XFree(modesinfo[i]->
private);
476 static void allegro_gl_x_exit(BITMAP *bmp)
478 #ifdef ALLEGROGL_HAVE_XF86VIDMODE 479 XSetWindowAttributes setattr;
487 __allegro_gl_unmanage_extensions();
490 if (!allegro_gl_info.is_ati_r200_chip) {
499 if (!glXMakeCurrent(_xwin.display, None, NULL)) {
500 ustrzcpy (allegro_error, ALLEGRO_ERROR_SIZE,
501 get_config_text (
"Could not release drawing context.\n"));
505 glXDestroyContext(_xwin.display, _glxwin.ctx);
509 if (_xwin.mouse_grabbed) {
510 XUngrabPointer(_xwin.display, CurrentTime);
511 _xwin.mouse_grabbed = 0;
514 if (_xwin.keyboard_grabbed) {
515 XUngrabKeyboard(_xwin.display, CurrentTime);
516 _xwin.keyboard_grabbed = 0;
519 #ifdef ALLEGROGL_HAVE_XF86VIDMODE 520 if (_glxwin.fullscreen) {
521 if (_xwin.mode_switched) {
522 XF86VidModeLockModeSwitch(_xwin.display, _xwin.screen, False);
523 XF86VidModeSwitchToMode(_xwin.display, _xwin.screen,
525 XF86VidModeSetViewPort(_xwin.display, _xwin.screen, 0, 0);
526 _xwin.mode_switched = 0;
528 if (_xwin.override_redirected) {
529 setattr.override_redirect = False;
530 XChangeWindowAttributes(_xwin.display, _xwin.window,
531 CWOverrideRedirect, &setattr);
532 _xwin.override_redirected = 0;
536 free_modelines(_xwin.modesinfo, _xwin.num_modes);
538 _xwin.modesinfo = NULL;
552 if (_xwin.window != None)
553 XUnmapWindow(_xwin.display, _xwin.window);
555 if (_glxwin.use_glx_window) {
556 glXDestroyWindow(_xwin.display, _glxwin.window);
558 _glxwin.use_glx_window = FALSE;
561 __allegro_gl_valid_context = FALSE;
563 _xwin_window_redrawer = old_window_redrawer;
564 XSetErrorHandler(old_x_error_handler);
567 #if GET_ALLEGRO_VERSION() >= MAKE_VER(4, 2, 1) 569 if (backup_allegro_window != None) {
570 if (_xwin.colormap != None) {
571 XUninstallColormap(_xwin.display, _xwin.colormap);
572 XFreeColormap(_xwin.display, _xwin.colormap);
574 _xwin.colormap = backup_allegro_colormap;
576 if (_xwin.window != None)
577 XDestroyWindow(_xwin.display, _xwin.window);
578 _xwin.window = backup_allegro_window;
579 backup_allegro_window = None;
580 XMapWindow(_xwin.display, _xwin.window);
592 static int get_shift (
int mask)
595 if (!mask)
return -1;
596 while (!(j & mask)) {
605 static int decode_fbconfig (GLXFBConfig fbc,
struct allegro_gl_display_info *i) {
606 int render_type, visual_type, buffer_size, sbuffers, samples;
607 int drawable_type, renderable;
610 TRACE(PREFIX_I
"decode_fbconfig: Decoding:\n");
613 if (glXGetFBConfigAttrib (_xwin.display, fbc, GLX_RENDER_TYPE,
615 || glXGetFBConfigAttrib (_xwin.display, fbc, GLX_X_RENDERABLE,
617 || glXGetFBConfigAttrib (_xwin.display, fbc, GLX_DRAWABLE_TYPE,
619 || glXGetFBConfigAttrib (_xwin.display, fbc, GLX_X_VISUAL_TYPE,
621 || glXGetFBConfigAttrib (_xwin.display, fbc, GLX_BUFFER_SIZE,
623 || glXGetFBConfigAttrib (_xwin.display, fbc, GLX_DEPTH_SIZE,
625 || glXGetFBConfigAttrib (_xwin.display, fbc, GLX_STEREO,
627 || glXGetFBConfigAttrib (_xwin.display, fbc, GLX_RED_SIZE,
628 &i->pixel_size.rgba.r)
629 || glXGetFBConfigAttrib (_xwin.display, fbc, GLX_GREEN_SIZE,
630 &i->pixel_size.rgba.g)
631 || glXGetFBConfigAttrib (_xwin.display, fbc, GLX_BLUE_SIZE,
632 &i->pixel_size.rgba.b)
633 || glXGetFBConfigAttrib (_xwin.display, fbc, GLX_ALPHA_SIZE,
634 &i->pixel_size.rgba.a)
635 || glXGetFBConfigAttrib (_xwin.display, fbc, GLX_DOUBLEBUFFER,
637 || glXGetFBConfigAttrib (_xwin.display, fbc, GLX_AUX_BUFFERS,
639 || glXGetFBConfigAttrib (_xwin.display, fbc, GLX_STENCIL_SIZE,
641 || glXGetFBConfigAttrib (_xwin.display, fbc, GLX_ACCUM_RED_SIZE,
642 &i->accum_size.rgba.r)
643 || glXGetFBConfigAttrib (_xwin.display, fbc, GLX_ACCUM_GREEN_SIZE,
644 &i->accum_size.rgba.g)
645 || glXGetFBConfigAttrib (_xwin.display, fbc, GLX_ACCUM_BLUE_SIZE,
646 &i->accum_size.rgba.b)
647 || glXGetFBConfigAttrib (_xwin.display, fbc, GLX_ACCUM_ALPHA_SIZE,
648 &i->accum_size.rgba.a)) {
649 TRACE(PREFIX_I
"decode_fbconfig: Incomplete glX mode ...\n");
653 if (!(render_type & GLX_RGBA_BIT) && !(render_type & GLX_RGBA_FLOAT_BIT)) {
654 TRACE(PREFIX_I
"decode_fbconfig: Not RGBA mode\n");
658 if (!(drawable_type & GLX_WINDOW_BIT)) {
659 TRACE(PREFIX_I
"decode_fbconfig: Cannot render to a window.\n");
663 if (renderable == False) {
664 TRACE(PREFIX_I
"decode_fbconfig: GLX windows not supported.\n");
668 if (visual_type != GLX_TRUE_COLOR && visual_type != GLX_DIRECT_COLOR) {
669 TRACE(PREFIX_I
"decode_fbconfig: visual type other than TrueColor and " 677 i->float_color = (render_type & GLX_RGBA_FLOAT_BIT);
679 v = glXGetVisualFromFBConfig(_xwin.display, fbc);
681 TRACE(PREFIX_I
"decode_fbconfig: Cannot get associated visual for the " 685 i->r_shift = get_shift (v->red_mask);
686 i->g_shift = get_shift (v->green_mask);
687 i->b_shift = get_shift (v->blue_mask);
691 if ((visual_type == GLX_DIRECT_COLOR)
692 && ((i->r_shift == -1) || (i->g_shift == -1) || (i->b_shift == -1))
693 && (i->pixel_size.rgba.r + i->pixel_size.rgba.g + i->pixel_size.rgba.b
702 if (i->pixel_size.rgba.r == 3
703 && i->pixel_size.rgba.g == 3
704 && i->pixel_size.rgba.b == 2) {
708 if (i->pixel_size.rgba.r == 5
709 && i->pixel_size.rgba.b == 5) {
710 if (i->pixel_size.rgba.g == 5) {
711 i->colour_depth = 15;
713 if (i->pixel_size.rgba.g == 6) {
714 i->colour_depth = 16;
718 if (i->pixel_size.rgba.r == 8
719 && i->pixel_size.rgba.g == 8
720 && i->pixel_size.rgba.b == 8) {
721 if (i->pixel_size.rgba.a == 0) {
722 i->colour_depth = 24;
724 if (i->pixel_size.rgba.a == 8) {
725 i->colour_depth = 32;
727 i->a_shift = 48 - i->r_shift - i->g_shift - i->b_shift;
731 i->allegro_format = (i->colour_depth != 0)
732 && (i->g_shift == i->pixel_size.rgba.b)
733 && (i->r_shift * i->b_shift == 0)
734 && (i->r_shift + i->b_shift
735 == i->pixel_size.rgba.b + i->pixel_size.rgba.g);
737 if (glXGetConfig(_xwin.display, v, GLX_SAMPLE_BUFFERS, &sbuffers)) {
739 i->sample_buffers = 0;
742 i->sample_buffers = sbuffers;
744 if (glXGetConfig(_xwin.display, v, GLX_SAMPLES, &samples)) {
749 i->samples = samples;
754 TRACE(PREFIX_I
"Color Depth: %i\n", buffer_size);
755 TRACE(PREFIX_I
"RGBA Type: %s point\n", i->float_color ?
"floating" :
"fixed");
756 TRACE(PREFIX_I
"RGBA: %i.%i.%i.%i\n", i->pixel_size.rgba.r, i->pixel_size.rgba.g,
757 i->pixel_size.rgba.b, i->pixel_size.rgba.a);
758 TRACE(PREFIX_I
"Accum: %i.%i.%i.%i\n", i->accum_size.rgba.r, i->accum_size.rgba.g,
759 i->accum_size.rgba.b, i->accum_size.rgba.a);
760 TRACE(PREFIX_I
"DblBuf: %i Zbuf: %i Stereo: %i Aux: %i Stencil: %i\n",
761 i->doublebuffered, i->depth_size, i->stereo,
762 i->aux_buffers, i->stencil_size);
763 TRACE(PREFIX_I
"Shift: %i.%i.%i.%i\n", i->r_shift, i->g_shift, i->b_shift,
765 TRACE(PREFIX_I
"Sample Buffers: %i Samples: %i\n", i->sample_buffers, i->samples);
766 TRACE(PREFIX_I
"Decoded bpp: %i\n", i->colour_depth);
773 int allegro_gl_x_windowed_choose_fbconfig (GLXFBConfig *ret_fbconfig) {
774 int num_fbconfigs, i;
775 GLXFBConfig *fbconfig;
776 struct allegro_gl_display_info dinfo;
778 fbconfig = glXGetFBConfigs (_xwin.display, _xwin.screen, &num_fbconfigs);
779 if (!fbconfig || !num_fbconfigs)
782 TRACE(PREFIX_I
"x_windowed_choose_fbconfig: %i formats.\n", num_fbconfigs);
783 __allegro_gl_reset_scorer();
785 for (i = 0; i < num_fbconfigs; i++) {
786 TRACE(PREFIX_I
"x_windowed_choose_fbconfig: Mode %i\n", i);
787 if (decode_fbconfig (*(fbconfig + i), &dinfo) != -1) {
788 __allegro_gl_score_config (i, &dinfo);
792 i = __allegro_gl_best_config();
793 TRACE(PREFIX_I
"x_windowed_choose_fbconfig: Best FBConfig is: %i\n", i);
800 *ret_fbconfig = *(fbconfig + i);
811 static XVisualInfo *allegro_gl_x_windowed_choose_visual (
void)
815 struct allegro_gl_display_info dinfo;
816 static XVisualInfo ret_vinfo;
818 vinfo = XGetVisualInfo (_xwin.display, 0, NULL, &num_visuals);
819 if (!vinfo)
return NULL;
821 TRACE(PREFIX_I
"x_windowed_choose_visual: %i formats.\n", num_visuals);
822 __allegro_gl_reset_scorer();
824 for (i = 0; i < num_visuals; i++) {
825 TRACE(PREFIX_I
"x_windowed_choose_visual: Mode %i\n", i);
826 if (decode_visual (vinfo + i, &dinfo) != -1) {
827 __allegro_gl_score_config (i, &dinfo);
831 i = __allegro_gl_best_config();
832 TRACE(PREFIX_I
"x_windowed_choose_visual: Best config is: %i\n", i);
834 if (i < 0)
return NULL;
836 memcpy (&ret_vinfo, vinfo+i,
sizeof ret_vinfo);
844 #ifdef ALLEGROGL_HAVE_XF86VIDMODE 849 static int get_xf86_modes(XF86VidModeModeInfo ***modesinfo,
int *num_modes)
851 int vid_event_base, vid_error_base;
852 int vid_major_version, vid_minor_version;
855 if (!XF86VidModeQueryExtension(_xwin.display, &vid_event_base,
857 || !XF86VidModeQueryVersion(_xwin.display, &vid_major_version,
858 &vid_minor_version)) {
860 ustrzcpy (allegro_gl_error, AGL_ERROR_SIZE,
861 get_config_text(
"VidMode extension is not supported"));
865 if (!XF86VidModeGetAllModeLines(_xwin.display, _xwin.screen, num_modes,
867 ustrzcpy (allegro_gl_error, AGL_ERROR_SIZE,
868 get_config_text(
"Can not Get ModeLines"));
877 static int allegro_gl_x_error_handler(Display *display, XErrorEvent *err_event)
881 XGetErrorText(display, err_event->error_code, buffer, 256);
882 TRACE(PREFIX_E
"%s\n", buffer);
891 static int allegro_gl_x_create_window (
int fullscreen)
894 XVisualInfo *visinfo;
895 XSetWindowAttributes setattr;
896 unsigned long valuemask = CWBackPixel | CWBorderPixel | CWColormap
899 GLXFBConfig fbconfig;
902 if (_xwin.display == 0) {
906 old_x_error_handler = XSetErrorHandler(allegro_gl_x_error_handler);
909 __allegro_gl_fill_in_info();
911 use_fbconfig = (_glxwin.major > 1 || (_glxwin.major == 1 && _glxwin.minor >= 3));
914 TRACE(PREFIX_I
"x_create_window: using FBConfig routines\n");
916 if (!allegro_gl_x_windowed_choose_fbconfig(&fbconfig)) {
917 TRACE(PREFIX_I
"x_create_window: Failed using FBConfig, switching " 918 "back to VisualInfo routines\n");
919 use_fbconfig = FALSE;
920 goto old_choose_visual;
924 if (decode_fbconfig(fbconfig, &allegro_gl_display_info)) {
925 TRACE(PREFIX_E
"x_create_window: Cannot decode FBConfig, switching " 926 "back to VisualInfo routines\n");
927 use_fbconfig = FALSE;
928 goto old_choose_visual;
931 visinfo = glXGetVisualFromFBConfig(_xwin.display, fbconfig);
933 TRACE(PREFIX_I
"x_create_window: Failed to convert FBConfig to " 934 "visual, switching back to VisualInfo routines\n");
935 use_fbconfig = FALSE;
936 goto old_choose_visual;
941 TRACE(PREFIX_I
"x_create_window: using VisualInfo routines\n");
944 visinfo = allegro_gl_x_windowed_choose_visual();
946 TRACE(PREFIX_E
"x_create_window: Can not get visual.\n");
947 XSetErrorHandler(old_x_error_handler);
952 if (decode_visual (visinfo, &allegro_gl_display_info)) {
953 TRACE(PREFIX_E
"x_create_window: Can not decode visual.\n");
954 XSetErrorHandler(old_x_error_handler);
960 switch (visinfo->class) {
962 AGL_LOG (1,
"x.c: visual class: TrueColor\n");
965 AGL_LOG (1,
"x.c: visual class: DirectColor\n");
968 AGL_LOG (1,
"x.c: visual class: invalid(!)\n");
974 #if GET_ALLEGRO_VERSION() >= MAKE_VER(4, 2, 1) 976 if (backup_allegro_window == None) {
977 backup_allegro_window = _xwin.window;
978 backup_allegro_colormap = _xwin.colormap;
979 _xwin.colormap = None;
980 XUnmapWindow(_xwin.display, _xwin.window);
984 XDestroyWindow (_xwin.display, _xwin.window);
988 root = RootWindow (_xwin.display, _xwin.screen);
991 setattr.background_pixel = XBlackPixel (_xwin.display, _xwin.screen);
992 setattr.border_pixel = XBlackPixel (_xwin.display, _xwin.screen);
993 setattr.colormap = XCreateColormap (_xwin.display, root, visinfo->visual, AllocNone);
995 ( KeyPressMask | KeyReleaseMask
996 | EnterWindowMask | LeaveWindowMask
997 | FocusChangeMask | ExposureMask
998 | ButtonPressMask | ButtonReleaseMask | PointerMotionMask
1002 #ifdef ALLEGROGL_HAVE_XF86VIDMODE 1006 _xwin.num_modes = 0;
1007 _xwin.modesinfo = NULL;
1008 _glxwin.fullscreen = TRUE;
1010 if (get_xf86_modes(&_xwin.modesinfo, &_xwin.num_modes)) {
1011 ustrzcpy (allegro_gl_error, AGL_ERROR_SIZE,
1012 get_config_text(
"x_create_window: Can't get" 1013 "XF86VidMode info.\n"));
1014 XSetErrorHandler(old_x_error_handler);
1019 for (i = 0; i < _xwin.num_modes; i++)
1021 if ((_xwin.modesinfo[i]->hdisplay == allegro_gl_display_info.w)
1022 && (_xwin.modesinfo[i]->vdisplay == allegro_gl_display_info.h))
1026 setattr.override_redirect = True;
1027 if (!XF86VidModeSwitchToMode(_xwin.display, _xwin.screen,
1028 _xwin.modesinfo[bestmode])) {
1030 ustrzcpy (allegro_gl_error, AGL_ERROR_SIZE,
1031 get_config_text(
"Can not set XF86VidMode mode"));
1032 XSetErrorHandler(old_x_error_handler);
1036 XF86VidModeSetViewPort(_xwin.display, _xwin.screen, 0, 0);
1039 XF86VidModeLockModeSwitch(_xwin.display, _xwin.screen, True);
1040 _xwin.mode_switched = 1;
1042 allegro_gl_display_info.x = 0;
1043 allegro_gl_display_info.y = 0;
1044 allegro_gl_display_info.w = _xwin.modesinfo[bestmode]->hdisplay;
1045 allegro_gl_display_info.h = _xwin.modesinfo[bestmode]->vdisplay;
1047 valuemask |= CWOverrideRedirect;
1048 _xwin.override_redirected = 1;
1051 _xwin.window = XCreateWindow (
1052 _xwin.display, root,
1053 allegro_gl_display_info.x, allegro_gl_display_info.y,
1054 allegro_gl_display_info.w, allegro_gl_display_info.h, 0,
1061 #else //ALLEGROGL_HAVE_XF86VIDMODE 1065 int fs_width = DisplayWidth(_xwin.display, _xwin.screen);
1066 int fs_height = DisplayHeight(_xwin.display, _xwin.screen);
1068 if (fs_width != allegro_gl_display_info.w
1069 || fs_height != allegro_gl_display_info.h) {
1070 TRACE(PREFIX_E
"Only desktop resolution fullscreen available.");
1071 ustrzcpy (allegro_gl_error, AGL_ERROR_SIZE,
1072 get_config_text(
"Compiled without Xf86VidMode extension support.\n" 1073 "Only desktop resolution fullscreen available."));
1074 XSetErrorHandler(old_x_error_handler);
1078 _glxwin.fullscreen = TRUE;
1081 _xwin.window = XCreateWindow(_xwin.display, root,
1082 allegro_gl_display_info.x, allegro_gl_display_info.y,
1083 fs_width, fs_height, 0,
1087 valuemask, &setattr);
1090 XMapRaised(_xwin.display, _xwin.window);
1093 XRaiseWindow(_xwin.display, _xwin.fs_window);
1096 _xwin.window = XCreateWindow (
1097 _xwin.display, root,
1098 allegro_gl_display_info.x, allegro_gl_display_info.y,
1099 allegro_gl_display_info.w, allegro_gl_display_info.h, 0,
1106 #endif //ALLEGROGL_HAVE_XF86VIDMODE 1111 hints = XAllocSizeHints();
1114 hints->flags = PMinSize | PMaxSize | PBaseSize;
1115 hints->min_width = hints->max_width = hints->base_width
1116 = allegro_gl_display_info.w;
1117 hints->min_height = hints->max_height = hints->base_height
1118 = allegro_gl_display_info.h;
1120 XSetWMNormalHints(_xwin.display, _xwin.window, hints);
1129 Atom wm_delete_window = XInternAtom(_xwin.display,
"WM_DELETE_WINDOW", False);
1130 XSetWMProtocols(_xwin.display, _xwin.window, &wm_delete_window, 1);
1135 _glxwin.ctx = glXCreateNewContext (_xwin.display, fbconfig, GLX_RGBA_TYPE, NULL, True);
1137 _glxwin.ctx = glXCreateContext (_xwin.display, visinfo, NULL, True);
1140 _glxwin.window = glXCreateWindow(_xwin.display, fbconfig, _xwin.window, 0);
1141 if (!_glxwin.window) {
1142 ustrzcpy (allegro_gl_error, AGL_ERROR_SIZE,
1143 get_config_text(
"Cannot create GLX window."));
1144 XSetErrorHandler(old_x_error_handler);
1147 _glxwin.use_glx_window = TRUE;
1151 ustrzcpy (allegro_gl_error, AGL_ERROR_SIZE,
1152 get_config_text(
"Can not create GLX context."));
1153 XSetErrorHandler(old_x_error_handler);
1160 ret = glXMakeContextCurrent(_xwin.display, _glxwin.window, _glxwin.window, _glxwin.ctx);
1162 ret = glXMakeCurrent (_xwin.display, _xwin.window, _glxwin.ctx);
1165 ustrzcpy (allegro_gl_error, AGL_ERROR_SIZE,
1166 get_config_text(
"Cannot make GLX context current."));
1167 XSetErrorHandler(old_x_error_handler);
1177 XWindowAttributes getattr;
1178 XGetWindowAttributes(_xwin.display, _xwin.window, &getattr);
1179 _xwin.visual = getattr.visual;
1180 _xwin.window_depth = getattr.depth;
1181 _xwin.window_width = allegro_gl_display_info.w;
1182 _xwin.window_height = allegro_gl_display_info.h;
1183 _xwin.screen_depth = getattr.depth;
1184 _xwin.screen_width = allegro_gl_display_info.w;
1185 _xwin.screen_height = allegro_gl_display_info.h;
1189 if (_xwin.colormap != None) {
1190 XUninstallColormap(_xwin.display, _xwin.colormap);
1191 XFreeColormap(_xwin.display, _xwin.colormap);
1195 if (_xwin.visual->class == DirectColor) {
1196 _xwin.colormap = XCreateColormap(_xwin.display, _xwin.window,
1197 _xwin.visual, AllocAll);
1200 _xwin.colormap = XCreateColormap(_xwin.display, _xwin.window,
1201 _xwin.visual, AllocNone);
1203 XSetWindowColormap(_xwin.display, _xwin.window, _xwin.colormap);
1204 XInstallColormap(_xwin.display, _xwin.colormap);
1207 if (_xwin.visual->class == DirectColor) {
1209 int rsize, gsize, bsize;
1210 int rmax, gmax, bmax;
1211 int rshift, gshift, bshift;
1214 AGL_LOG (1,
"x.c: Using DirectColor visual, setting palette...\n");
1216 rsize = 1 << allegro_gl_display_info.pixel_size.rgba.r;
1217 gsize = 1 << allegro_gl_display_info.pixel_size.rgba.g;
1218 bsize = 1 << allegro_gl_display_info.pixel_size.rgba.b;
1220 rshift = allegro_gl_display_info.r_shift;
1221 bshift = allegro_gl_display_info.b_shift;
1222 gshift = allegro_gl_display_info.g_shift;
1228 color.flags = DoRed | DoGreen | DoBlue;
1229 for (r = 0; r < rsize; r++) {
1230 for (g = 0; g < gsize; g++) {
1231 for (b = 0; b < bsize; b++) {
1232 color.pixel = (r << rshift) | (g << gshift) | (b << bshift);
1233 color.red = ((rmax <= 0) ? 0 : ((r * 65535L) / rmax));
1234 color.green = ((gmax <= 0) ? 0 : ((g * 65535L) / gmax));
1235 color.blue = ((bmax <= 0) ? 0 : ((b * 65535L) / bmax));
1236 XStoreColor(_xwin.display, _xwin.colormap, &color);
1248 XStoreName(_xwin.display, _xwin.window, _xwin.window_title);
1251 hint.res_name = _xwin.application_name;
1252 hint.res_class = _xwin.application_class;
1253 XSetClassHint(_xwin.display, _xwin.window, &hint);
1255 wm_hints.flags = InputHint | StateHint;
1256 wm_hints.input = True;
1257 wm_hints.initial_state = NormalState;
1259 #ifdef ALLEGRO_XWINDOWS_WITH_XPM 1261 wm_hints.flags |= IconPixmapHint | IconMaskHint | WindowGroupHint;
1262 XpmCreatePixmapFromData(_xwin.display, _xwin.window, allegro_icon,&wm_hints.icon_pixmap, &wm_hints.icon_mask, NULL);
1266 XSetWMHints(_xwin.display, _xwin.window, &wm_hints);
1270 XMapWindow(_xwin.display, _xwin.window);
1274 AL_CONST
char *fc = NULL;
1275 char tmp1[64], tmp2[128];
1277 int h = allegro_gl_display_info.h;
1278 int w = allegro_gl_display_info.w;
1282 fc = get_config_string(uconvert_ascii(
"graphics", tmp1),
1283 uconvert_ascii(
"force_centering", tmp2), NULL);
1284 if ((fc) && ((c = ugetc(fc)) != 0) && ((c ==
'y') || (c ==
'Y')
1287 XWarpPointer(_xwin.display, None, _xwin.window, 0, 0, 0, 0, 0, 0);
1288 XWarpPointer(_xwin.display, None, _xwin.window, 0, 0, 0, 0,
1290 XWarpPointer(_xwin.display, None, _xwin.window, 0, 0, 0, 0,
1292 XWarpPointer(_xwin.display, None, _xwin.window, 0, 0, 0, 0,
1295 XWarpPointer(_xwin.display, None, _xwin.window, 0, 0, 0, 0,
1297 XSync(_xwin.display, False);
1300 if (XGrabKeyboard(_xwin.display, _xwin.window, False, GrabModeAsync,
1301 GrabModeAsync, CurrentTime) != GrabSuccess) {
1302 ustrzcpy (allegro_gl_error, AGL_ERROR_SIZE,
1303 get_config_text(
"Can not grab keyboard"));
1304 XSetErrorHandler(old_x_error_handler);
1307 _xwin.keyboard_grabbed = 1;
1309 if (XGrabPointer(_xwin.display, _xwin.window, False,
1310 PointerMotionMask | ButtonPressMask | ButtonReleaseMask,
1311 GrabModeAsync, GrabModeAsync, _xwin.window, None, CurrentTime)
1314 ustrzcpy (allegro_gl_error, AGL_ERROR_SIZE,
1315 get_config_text(
"Can not grab mouse"));
1316 XSetErrorHandler(old_x_error_handler);
1319 _xwin.mouse_grabbed = 1;
1324 if (_xwin.cursor != None) {
1325 XUndefineCursor(_xwin.display, _xwin.window);
1326 XFreeCursor(_xwin.display, _xwin.cursor);
1331 Pixmap pixmap = XCreatePixmap(_xwin.display, _xwin.window, 1, 1, 1);
1332 if (pixmap != None) {
1337 int gcmask = GCFunction | GCForeground | GCBackground;
1338 gcvalues.function = GXcopy;
1339 gcvalues.foreground = 0;
1340 gcvalues.background = 0;
1341 temp_gc = XCreateGC(_xwin.display, pixmap, gcmask, &gcvalues);
1342 XDrawPoint(_xwin.display, pixmap, temp_gc, 0, 0);
1343 XFreeGC(_xwin.display, temp_gc);
1345 color.red = color.green = color.blue = 0;
1346 color.flags = DoRed | DoGreen | DoBlue;
1347 _xwin.cursor = XCreatePixmapCursor(_xwin.display, pixmap, pixmap,
1348 &color, &color, 0, 0);
1349 XDefineCursor(_xwin.display, _xwin.window, _xwin.cursor);
1350 XFreePixmap(_xwin.display, pixmap);
1353 _xwin.cursor = XCreateFontCursor(_xwin.display, _xwin.cursor_shape);
1354 XDefineCursor(_xwin.display, _xwin.window, _xwin.cursor);
1363 if (XCheckTypedEvent(_xwin.display, Expose, &e)) {
1364 if (e.xexpose.count == 0)
break;
1374 static BITMAP *allegro_gl_x_windowed_create_screen (GFX_DRIVER *drv,
int w,
int h,
int depth)
1377 int is_linear = drv->linear;
1380 bmp = _make_bitmap (w, h, 0, drv, depth, 0);
1381 bmp->id = BMP_ID_VIDEO | BMP_ID_MASK;
1382 drv->linear = is_linear;
1385 ustrzcpy (allegro_gl_error, AGL_ERROR_SIZE,
1386 get_config_text(
"Not enough memory"));
1401 static int decode_visual (XVisualInfo *v,
struct allegro_gl_display_info *i)
1403 int rgba, buffer_size, use_gl, sbuffers, samples;
1405 TRACE(PREFIX_I
"decode_visual: Decoding:\n");
1410 if (v->class != TrueColor && v->class != DirectColor)
1413 if (glXGetConfig (_xwin.display, v, GLX_RGBA, &rgba)
1414 || glXGetConfig (_xwin.display, v, GLX_USE_GL, &use_gl)
1415 || glXGetConfig (_xwin.display, v, GLX_BUFFER_SIZE, &buffer_size)
1416 || glXGetConfig (_xwin.display, v, GLX_RED_SIZE, &i->pixel_size.rgba.r)
1417 || glXGetConfig (_xwin.display, v, GLX_GREEN_SIZE, &i->pixel_size.rgba.g)
1418 || glXGetConfig (_xwin.display, v, GLX_BLUE_SIZE, &i->pixel_size.rgba.b)
1419 || glXGetConfig (_xwin.display, v, GLX_ALPHA_SIZE, &i->pixel_size.rgba.a)
1420 || glXGetConfig (_xwin.display, v, GLX_DOUBLEBUFFER, &i->doublebuffered)
1421 || glXGetConfig (_xwin.display, v, GLX_STEREO, &i->stereo)
1422 || glXGetConfig (_xwin.display, v, GLX_AUX_BUFFERS, &i->aux_buffers)
1423 || glXGetConfig (_xwin.display, v, GLX_DEPTH_SIZE, &i->depth_size)
1424 || glXGetConfig (_xwin.display, v, GLX_STENCIL_SIZE, &i->stencil_size)
1425 || glXGetConfig (_xwin.display, v, GLX_ACCUM_RED_SIZE,
1426 &i->accum_size.rgba.r)
1427 || glXGetConfig (_xwin.display, v, GLX_ACCUM_GREEN_SIZE,
1428 &i->accum_size.rgba.g)
1429 || glXGetConfig (_xwin.display, v, GLX_ACCUM_BLUE_SIZE,
1430 &i->accum_size.rgba.b)
1431 || glXGetConfig (_xwin.display, v, GLX_ACCUM_ALPHA_SIZE,
1432 &i->accum_size.rgba.a)) {
1433 TRACE(PREFIX_I
"x_create_window: Incomplete glX mode ...\n");
1438 TRACE(PREFIX_I
"x_create_window: Not RGBA mode\n");
1443 ustrzcpy (allegro_gl_error, AGL_ERROR_SIZE,
1444 get_config_text(
"OpenGL Unsupported"));
1448 i->r_shift = get_shift (v->red_mask);
1449 i->g_shift = get_shift (v->green_mask);
1450 i->b_shift = get_shift (v->blue_mask);
1454 if ((v->class == DirectColor)
1455 && ((i->r_shift == -1) || (i->g_shift == -1) || (i->b_shift == -1))
1456 && (i->pixel_size.rgba.r + i->pixel_size.rgba.g + i->pixel_size.rgba.b
1465 i->colour_depth = 0;
1467 if (i->pixel_size.rgba.r == 3
1468 && i->pixel_size.rgba.g == 3
1469 && i->pixel_size.rgba.b == 2) {
1470 i->colour_depth = 8;
1473 if (i->pixel_size.rgba.r == 5
1474 && i->pixel_size.rgba.b == 5) {
1475 if (i->pixel_size.rgba.g == 5) {
1476 i->colour_depth = 15;
1478 if (i->pixel_size.rgba.g == 6) {
1479 i->colour_depth = 16;
1483 if (i->pixel_size.rgba.r == 8
1484 && i->pixel_size.rgba.g == 8
1485 && i->pixel_size.rgba.b == 8) {
1486 if (i->pixel_size.rgba.a == 0) {
1487 i->colour_depth = 24;
1489 if (i->pixel_size.rgba.a == 8) {
1490 i->colour_depth = 32;
1492 i->a_shift = 48 - i->r_shift - i->g_shift - i->b_shift;
1496 i->allegro_format = (i->colour_depth != 0)
1497 && (i->g_shift == i->pixel_size.rgba.b)
1498 && (i->r_shift * i->b_shift == 0)
1499 && (i->r_shift + i->b_shift
1500 == i->pixel_size.rgba.b + i->pixel_size.rgba.g);
1502 if (glXGetConfig(_xwin.display, v, GLX_SAMPLE_BUFFERS, &sbuffers)
1503 == GLX_BAD_ATTRIBUTE) {
1505 i->sample_buffers = 0;
1508 i->sample_buffers = sbuffers;
1510 if (glXGetConfig(_xwin.display, v, GLX_SAMPLES, &samples)
1511 == GLX_BAD_ATTRIBUTE) {
1516 i->samples = samples;
1520 TRACE(PREFIX_I
"Color Depth: %i\n", buffer_size);
1521 TRACE(PREFIX_I
"RGBA: %i.%i.%i.%i\n", i->pixel_size.rgba.r, i->pixel_size.rgba.g,
1522 i->pixel_size.rgba.b, i->pixel_size.rgba.a);
1523 TRACE(PREFIX_I
"Accum: %i.%i.%i.%i\n", i->accum_size.rgba.r, i->accum_size.rgba.g,
1524 i->accum_size.rgba.b, i->accum_size.rgba.a);
1525 TRACE(PREFIX_I
"DblBuf: %i Zbuf: %i Stereo: %i Aux: %i Stencil: %i\n",
1526 i->doublebuffered, i->depth_size, i->stereo,
1527 i->aux_buffers, i->stencil_size);
1528 TRACE(PREFIX_I
"Shift: %i.%i.%i.%i\n", i->r_shift, i->g_shift, i->b_shift,
1530 TRACE(PREFIX_I
"Sample Buffers: %i Samples: %i\n", i->sample_buffers, i->samples);
1531 TRACE(PREFIX_I
"Decoded bpp: %i\n", i->colour_depth);
1538 #ifdef ALLEGROGL_HAVE_XF86VIDMODE 1543 static GFX_MODE_LIST* allegro_gl_x_fetch_mode_list(
void)
1546 XF86VidModeModeInfo **modesinfo = NULL;
1547 GFX_MODE_LIST *mode_list;
1552 if (get_xf86_modes(&modesinfo, &num_modes)) {
1558 mode_list = malloc(
sizeof(GFX_MODE_LIST));
1560 free_modelines(modesinfo, num_modes);
1565 mode_list->mode = malloc(
sizeof(GFX_MODE) * (num_modes + 1));
1566 if (!mode_list->mode) {
1568 free_modelines(modesinfo, num_modes);
1574 for (i = 0; i < num_modes; i++) {
1575 mode_list->mode[i].width = modesinfo[i]->hdisplay;
1576 mode_list->mode[i].height = modesinfo[i]->vdisplay;
1581 mode_list->mode[i].bpp = desktop_color_depth();
1584 mode_list->mode[num_modes].width = 0;
1585 mode_list->mode[num_modes].height = 0;
1586 mode_list->mode[num_modes].bpp = 0;
1587 mode_list->num_modes = num_modes;
1589 free_modelines(modesinfo, num_modes);
1601 static void allegro_gl_x_vsync(
void)
1604 if (allegro_gl_extensions_GLX.SGI_video_sync) {
1607 glXGetVideoSyncSGI(&count);
1608 glXWaitVideoSyncSGI(2, (count+1) & 1, &count);
1622 static void flip (
void)
1625 if (_glxwin.use_glx_window)
1626 glXSwapBuffers (_xwin.display, _glxwin.window);
1628 glXSwapBuffers (_xwin.display, _xwin.window);
1637 static void gl_on (
void)
1646 static void gl_off (
void)
1650 _xwin_handle_input();
1660 static struct allegro_gl_driver allegro_gl_x = {
#define GFX_OPENGL_FULLSCREEN
Fullscreen OpenGL graphics driver for Allegro.
#define GFX_OPENGL_WINDOWED
Windowed OpenGL graphics driver for Allegro.
void allegro_gl_destroy_video_bitmap(BITMAP *bmp)
destroy_video_bitmap() overload.
Main header file for AllegroGL.
BITMAP * allegro_gl_screen
Direct-mode GL `screen' bitmap.
BITMAP * allegro_gl_create_video_bitmap(int w, int h)
create_video_bitmap() overload.