diff --git a/panda/src/glxdisplay/glxGraphicsPipe.cxx b/panda/src/glxdisplay/glxGraphicsPipe.cxx index 0500934b1b..7a4c885ffb 100644 --- a/panda/src/glxdisplay/glxGraphicsPipe.cxx +++ b/panda/src/glxdisplay/glxGraphicsPipe.cxx @@ -23,8 +23,6 @@ #include "frameBufferProperties.h" #include "mutexHolder.h" -#include - TypeHandle glxGraphicsPipe::_type_handle; bool glxGraphicsPipe::_error_handlers_installed = false; @@ -164,14 +162,17 @@ make_gsg(const FrameBufferProperties &properties) { } FrameBufferProperties new_properties = properties; - XVisualInfo *visual = choose_visual(new_properties); + GLXFBConfig fbconfig = choose_fbconfig(new_properties); + if (fbconfig == None) { + return NULL; + } // Attempt to create a GL context. - GLXContext context = glXCreateContext(_display, visual, None, GL_TRUE); + GLXContext context = + glXCreateNewContext(_display, fbconfig, GLX_RGBA_TYPE, NULL, GL_TRUE); if (context == NULL) { glxdisplay_cat.error() << "Could not create GL context.\n"; - XFree(visual); return NULL; } @@ -179,7 +180,7 @@ make_gsg(const FrameBufferProperties &properties) { PT(glxGraphicsStateGuardian) gsg = new glxGraphicsStateGuardian(new_properties); gsg->_context = context; - gsg->_visual = visual; + gsg->_fbconfig = fbconfig; gsg->_display = _display; return gsg.p(); @@ -200,17 +201,17 @@ make_window(GraphicsStateGuardian *gsg) { } //////////////////////////////////////////////////////////////////// -// Function: glxGraphicsPipe::choose visual +// Function: glxGraphicsPipe::choose_fbconfig // Access: Private -// Description: Selects an appropriate X visual for the given frame -// buffer properties. Returns the visual pointer if -// successful, or NULL otherwise. +// Description: Selects an appropriate GLXFBConfig for the given +// frame buffer properties. Returns the selected +// fbconfig if successful, or None otherwise. // // If successful, this may modify properties to reflect // the actual visual chosen. //////////////////////////////////////////////////////////////////// -XVisualInfo *glxGraphicsPipe:: -choose_visual(FrameBufferProperties &properties) const { +GLXFBConfig glxGraphicsPipe:: +choose_fbconfig(FrameBufferProperties &properties) const { int frame_buffer_mode = 0; int want_depth_bits = 0; int want_color_bits = 0; @@ -237,29 +238,29 @@ choose_visual(FrameBufferProperties &properties) const { } */ - XVisualInfo *visual = - try_for_visual(frame_buffer_mode, want_depth_bits, want_color_bits); + GLXFBConfig fbconfig = + try_for_fbconfig(frame_buffer_mode, want_depth_bits, want_color_bits); // This is the severity level at which we'll report the details of - // the visual we actually do find. Normally, it's debug-level + // the fbconfig we actually do find. Normally, it's debug-level // information: we don't care about that much detail. - NotifySeverity show_visual_severity = NS_debug; + NotifySeverity show_fbconfig_severity = NS_debug; - if (visual == NULL) { + if (fbconfig == NULL) { glxdisplay_cat.info() - << "glxGraphicsWindow::choose_visual() - visual with requested\n" - << " capabilities not found; trying for lesser visual.\n"; + << "glxGraphicsWindow::choose_fbconfig() - fbconfig with requested " + << "capabilities not found; trying for lesser fbconfig.\n"; - // If we're unable to get the visual we asked for, however, we + // If we're unable to get the fbconfig we asked for, however, we // probably *do* care to know the details about what we actually // got, even if we don't have debug mode set. So we'll report the - // visual at a higher level. - show_visual_severity = NS_info; + // fbconfig at a higher level. + show_fbconfig_severity = NS_info; bool special_size_request = (want_depth_bits != 1 || want_color_bits != 1); - // We try to be smart about choosing a close match for the visual. + // We try to be smart about choosing a close match for the fbconfig. // First, we'll eliminate some of the more esoteric options one at // a time, then two at a time, and finally we'll try just the bare // minimum. @@ -268,10 +269,10 @@ choose_visual(FrameBufferProperties &properties) const { // Actually, first we'll eliminate all of the minimum sizes, to // try to open a window with all of the requested options, but // maybe not as many bits in some options as we'd like. - visual = try_for_visual(frame_buffer_mode, 1, 1); + fbconfig = try_for_fbconfig(frame_buffer_mode, 1, 1); } - if (visual == NULL) { + if (fbconfig == NULL) { // Ok, not good enough. Now try to eliminate options, but keep // as many bits as we asked for. @@ -311,11 +312,11 @@ choose_visual(FrameBufferProperties &properties) const { tried_masks.insert(frame_buffer_mode); int i; - for (i = 0; visual == NULL && strip_properties[i] != 0; i++) { + for (i = 0; fbconfig == NULL && strip_properties[i] != 0; i++) { int new_frame_buffer_mode = frame_buffer_mode & ~strip_properties[i]; if (tried_masks.insert(new_frame_buffer_mode).second) { - visual = try_for_visual(new_frame_buffer_mode, want_depth_bits, - want_color_bits); + fbconfig = try_for_fbconfig(new_frame_buffer_mode, want_depth_bits, + want_color_bits); } } @@ -323,53 +324,53 @@ choose_visual(FrameBufferProperties &properties) const { tried_masks.clear(); tried_masks.insert(frame_buffer_mode); - if (visual == NULL) { + if (fbconfig == NULL) { // Try once more, this time eliminating all of the size // requests. - for (i = 0; visual == NULL && strip_properties[i] != 0; i++) { + for (i = 0; fbconfig == NULL && strip_properties[i] != 0; i++) { int new_frame_buffer_mode = frame_buffer_mode & ~strip_properties[i]; if (tried_masks.insert(new_frame_buffer_mode).second) { - visual = try_for_visual(new_frame_buffer_mode, 1, 1); + fbconfig = try_for_fbconfig(new_frame_buffer_mode, 1, 1); } } } } - if (visual == NULL) { + if (fbconfig == NULL) { // Here's our last-ditch desparation attempt: give us any GLX - // visual at all! - visual = try_for_visual(0, 1, 1); + // fbconfig at all! + fbconfig = try_for_fbconfig(0, 1, 1); } - if (visual == NULL) { + if (fbconfig == NULL) { glxdisplay_cat.error() - << "Could not get any GLX visual.\n"; + << "Could not get any GLX fbconfig.\n"; return NULL; } } } glxdisplay_cat.info() - << "Got visual 0x" << hex << (int)visual->visualid << dec << ".\n"; + << "Selected suitable GLX fbconfig.\n"; // Now update our frambuffer_mode and bit depth appropriately. int render_mode, double_buffer, stereo, red_size, green_size, blue_size, alpha_size, ared_size, agreen_size, ablue_size, aalpha_size, depth_size, stencil_size; - glXGetConfig(_display, visual, GLX_RGBA, &render_mode); - glXGetConfig(_display, visual, GLX_DOUBLEBUFFER, &double_buffer); - glXGetConfig(_display, visual, GLX_STEREO, &stereo); - glXGetConfig(_display, visual, GLX_RED_SIZE, &red_size); - glXGetConfig(_display, visual, GLX_GREEN_SIZE, &green_size); - glXGetConfig(_display, visual, GLX_BLUE_SIZE, &blue_size); - glXGetConfig(_display, visual, GLX_ALPHA_SIZE, &alpha_size); - glXGetConfig(_display, visual, GLX_ACCUM_RED_SIZE, &ared_size); - glXGetConfig(_display, visual, GLX_ACCUM_GREEN_SIZE, &agreen_size); - glXGetConfig(_display, visual, GLX_ACCUM_BLUE_SIZE, &ablue_size); - glXGetConfig(_display, visual, GLX_ACCUM_ALPHA_SIZE, &aalpha_size); - glXGetConfig(_display, visual, GLX_DEPTH_SIZE, &depth_size); - glXGetConfig(_display, visual, GLX_STENCIL_SIZE, &stencil_size); + glXGetFBConfigAttrib(_display, fbconfig, GLX_RGBA, &render_mode); + glXGetFBConfigAttrib(_display, fbconfig, GLX_DOUBLEBUFFER, &double_buffer); + glXGetFBConfigAttrib(_display, fbconfig, GLX_STEREO, &stereo); + glXGetFBConfigAttrib(_display, fbconfig, GLX_RED_SIZE, &red_size); + glXGetFBConfigAttrib(_display, fbconfig, GLX_GREEN_SIZE, &green_size); + glXGetFBConfigAttrib(_display, fbconfig, GLX_BLUE_SIZE, &blue_size); + glXGetFBConfigAttrib(_display, fbconfig, GLX_ALPHA_SIZE, &alpha_size); + glXGetFBConfigAttrib(_display, fbconfig, GLX_ACCUM_RED_SIZE, &ared_size); + glXGetFBConfigAttrib(_display, fbconfig, GLX_ACCUM_GREEN_SIZE, &agreen_size); + glXGetFBConfigAttrib(_display, fbconfig, GLX_ACCUM_BLUE_SIZE, &ablue_size); + glXGetFBConfigAttrib(_display, fbconfig, GLX_ACCUM_ALPHA_SIZE, &aalpha_size); + glXGetFBConfigAttrib(_display, fbconfig, GLX_DEPTH_SIZE, &depth_size); + glXGetFBConfigAttrib(_display, fbconfig, GLX_STENCIL_SIZE, &stencil_size); frame_buffer_mode = 0; if (double_buffer) { @@ -398,9 +399,9 @@ choose_visual(FrameBufferProperties &properties) const { properties.set_color_bits(red_size + green_size + blue_size + alpha_size); properties.set_depth_bits(depth_size); - if (glxdisplay_cat.is_on(show_visual_severity)) { - glxdisplay_cat.out(show_visual_severity) - << "GLX Visual Info (# bits of each):" << endl + if (glxdisplay_cat.is_on(show_fbconfig_severity)) { + glxdisplay_cat.out(show_fbconfig_severity) + << "GLX Fbconfig Info (# bits of each):" << endl << " RGBA: " << red_size << " " << green_size << " " << blue_size << " " << alpha_size << endl << " Accum RGBA: " << ared_size << " " << agreen_size << " " @@ -411,26 +412,26 @@ choose_visual(FrameBufferProperties &properties) const { << " Stereo? " << stereo << endl; } - return visual; + return fbconfig; } //////////////////////////////////////////////////////////////////// -// Function: glxGraphicsPipe::try_for_visual +// Function: glxGraphicsPipe::try_for_fbconfig // Access: Private -// Description: Attempt to get the requested visual, if it is +// Description: Attempt to get the requested fbconfig, if it is // available. It's just a wrapper around -// glXChooseVisual(). It returns the visual information -// if possible, or NULL if it is not. +// glXChooseFBConfig(). It returns the fbconfig +// information if possible, or NULL if it is not. //////////////////////////////////////////////////////////////////// -XVisualInfo *glxGraphicsPipe:: -try_for_visual(int framebuffer_mode, - int want_depth_bits, int want_color_bits) const { +GLXFBConfig glxGraphicsPipe:: +try_for_fbconfig(int framebuffer_mode, + int want_depth_bits, int want_color_bits) const { static const int max_attrib_list = 32; int attrib_list[max_attrib_list]; int n=0; glxdisplay_cat.debug() - << "Trying for visual with: RGB(" << want_color_bits << ")"; + << "Trying for fbconfig with: RGB(" << want_color_bits << ")"; int want_color_component_bits; if (framebuffer_mode & FrameBufferProperties::FM_alpha) { @@ -439,7 +440,6 @@ try_for_visual(int framebuffer_mode, want_color_component_bits = max(want_color_bits / 3, 1); } - attrib_list[n++] = GLX_RGBA; attrib_list[n++] = GLX_RED_SIZE; attrib_list[n++] = want_color_component_bits; attrib_list[n++] = GLX_GREEN_SIZE; @@ -455,10 +455,12 @@ try_for_visual(int framebuffer_mode, if (framebuffer_mode & FrameBufferProperties::FM_double_buffer) { glxdisplay_cat.debug(false) << " DOUBLEBUFFER"; attrib_list[n++] = GLX_DOUBLEBUFFER; + attrib_list[n++] = true; } if (framebuffer_mode & FrameBufferProperties::FM_stereo) { glxdisplay_cat.debug(false) << " STEREO"; attrib_list[n++] = GLX_STEREO; + attrib_list[n++] = true; } if (framebuffer_mode & FrameBufferProperties::FM_depth) { glxdisplay_cat.debug(false) << " DEPTH(" << want_depth_bits << ")"; @@ -496,17 +498,29 @@ try_for_visual(int framebuffer_mode, nassertr(n < max_attrib_list, NULL); attrib_list[n] = (int)None; - XVisualInfo *vinfo = glXChooseVisual(_display, _screen, attrib_list); + int num_configs = 0; + GLXFBConfig *configs = + glXChooseFBConfig(_display, _screen, attrib_list, &num_configs); if (glxdisplay_cat.is_debug()) { - if (vinfo != NULL) { - glxdisplay_cat.debug(false) << ", match found!\n"; + if (configs != NULL) { + glxdisplay_cat.debug(false) + << ", " << num_configs << " matches found!\n"; } else { glxdisplay_cat.debug(false) << ", no match.\n"; } } - return vinfo; + if (configs == NULL || num_configs == 0) { + return None; + } + + // Pick the first matching fbconfig; this will be the "best" one + // according to the GLX specifics. + GLXFBConfig fbconfig = configs[0]; + XFree(configs); + + return fbconfig; } //////////////////////////////////////////////////////////////////// diff --git a/panda/src/glxdisplay/glxGraphicsPipe.h b/panda/src/glxdisplay/glxGraphicsPipe.h index 37b7e485f2..3d0a42bd01 100644 --- a/panda/src/glxdisplay/glxGraphicsPipe.h +++ b/panda/src/glxdisplay/glxGraphicsPipe.h @@ -23,7 +23,6 @@ #include "graphicsWindow.h" #include "graphicsPipe.h" -class glxGraphicsWindow; class FrameBufferProperties; #ifdef CPPPARSER @@ -32,6 +31,8 @@ typedef int Display; typedef int Window; typedef int XErrorEvent; typedef int XVisualInfo; +typedef int GLXFBConfig; +typedef int GLXPbuffer; typedef int Atom; typedef int XIM; typedef int XIC; @@ -40,6 +41,20 @@ typedef int XIC; #include #endif // CPPPARSER +#ifndef GLX_VERSION_1_3 + // Pre-glx 1.3, these GLXFBConfig definitions might have been + // defined as SGI extensions. + #define GLX_RGBA_TYPE GLX_RGBA_TYPE_SGIX + #define GLXFBConfig GLXFBConfigSGIX + #define glXChooseFBConfig glXChooseFBConfigSGIX + #define glXCreateNewContext glXCreateContextWithConfigSGIX + #define glXGetVisualFromFBConfig glXGetVisualFromFBConfigSGIX + #define glXGetFBConfigAttrib glXGetFBConfigAttribSGIX + #define glXCreatePbuffer glXCreateGLXPbufferSGIX + #define glXDestroyPbuffer glXDestroyGLXPbufferSGIX +#endif // GLX_VERSION_1_3 + + //////////////////////////////////////////////////////////////////// // Class : glxGraphicsPipe // Description : This graphics pipe represents the interface for @@ -66,9 +81,9 @@ protected: virtual PT(GraphicsWindow) make_window(GraphicsStateGuardian *gsg); private: - XVisualInfo *choose_visual(FrameBufferProperties &properties) const; - XVisualInfo *try_for_visual(int framebuffer_mode, - int want_depth_bits, int want_color_bits) const; + GLXFBConfig choose_fbconfig(FrameBufferProperties &properties) const; + GLXFBConfig try_for_fbconfig(int framebuffer_mode, + int want_depth_bits, int want_color_bits) const; static void install_error_handlers(); static int error_handler(Display *display, XErrorEvent *error); diff --git a/panda/src/glxdisplay/glxGraphicsStateGuardian.cxx b/panda/src/glxdisplay/glxGraphicsStateGuardian.cxx index 522e8c48a3..a31c205e48 100644 --- a/panda/src/glxdisplay/glxGraphicsStateGuardian.cxx +++ b/panda/src/glxdisplay/glxGraphicsStateGuardian.cxx @@ -31,7 +31,6 @@ glxGraphicsStateGuardian(const FrameBufferProperties &properties) : GLGraphicsStateGuardian(properties) { _context = (GLXContext)NULL; - _visual = (XVisualInfo *)NULL; _display = NULL; } @@ -42,11 +41,6 @@ glxGraphicsStateGuardian(const FrameBufferProperties &properties) : //////////////////////////////////////////////////////////////////// glxGraphicsStateGuardian:: ~glxGraphicsStateGuardian() { - if (_visual != (XVisualInfo *)NULL) { - XFree(_visual); - _visual = (XVisualInfo *)NULL; - } - if (_context != (GLXContext)NULL) { glXDestroyContext(_display, _context); _context = (GLXContext)NULL; diff --git a/panda/src/glxdisplay/glxGraphicsStateGuardian.h b/panda/src/glxdisplay/glxGraphicsStateGuardian.h index fc2b849587..6b1d2bed47 100644 --- a/panda/src/glxdisplay/glxGraphicsStateGuardian.h +++ b/panda/src/glxdisplay/glxGraphicsStateGuardian.h @@ -22,9 +22,7 @@ #include "pandabase.h" #include "glGraphicsStateGuardian.h" - -#include -#include +#include "glxGraphicsPipe.h" //////////////////////////////////////////////////////////////////// // Class : glxGraphicsStateGuardian @@ -37,7 +35,7 @@ public: virtual ~glxGraphicsStateGuardian(); GLXContext _context; - XVisualInfo *_visual; + GLXFBConfig _fbconfig; Display *_display; public: diff --git a/panda/src/glxdisplay/glxGraphicsWindow.cxx b/panda/src/glxdisplay/glxGraphicsWindow.cxx index c709500f89..42f8bfcb0d 100644 --- a/panda/src/glxdisplay/glxGraphicsWindow.cxx +++ b/panda/src/glxdisplay/glxGraphicsWindow.cxx @@ -406,6 +406,24 @@ open_window() { return false; } + glxGraphicsPipe *glx_pipe; + DCAST_INTO_R(glx_pipe, _pipe, false); + glxGraphicsStateGuardian *glxgsg; + DCAST_INTO_R(glxgsg, _gsg, false); + + XVisualInfo *visual_info = + glXGetVisualFromFBConfig(_display, glxgsg->_fbconfig); + if (visual_info == NULL) { + // No X visual for this fbconfig; how can we open the window? + glxdisplay_cat.error() + << "Cannot open window without an X visual.\n"; + return false; + } + Visual *visual = visual_info->visual; + int depth = visual_info->depth; + XFree(visual_info); + + if (!_properties.has_origin()) { _properties.set_origin(0, 0); } @@ -413,14 +431,9 @@ open_window() { _properties.set_size(100, 100); } - glxGraphicsPipe *glx_pipe; - DCAST_INTO_R(glx_pipe, _pipe, false); - glxGraphicsStateGuardian *glxgsg; - DCAST_INTO_R(glxgsg, _gsg, false); - Window root_window = glx_pipe->get_root(); - setup_colormap(glxgsg->_visual); + setup_colormap(glxgsg->_fbconfig); _event_mask = ButtonPressMask | ButtonReleaseMask | @@ -444,9 +457,7 @@ open_window() { (_display, root_window, _properties.get_x_origin(), _properties.get_y_origin(), _properties.get_x_size(), _properties.get_y_size(), - 0, - glxgsg->_visual->depth, InputOutput, glxgsg->_visual->visual, - attrib_mask, &wa); + 0, depth, InputOutput, visual, attrib_mask, &wa); if (_xwindow == (Window)0) { glxdisplay_cat.error() @@ -565,21 +576,29 @@ set_wm_properties(const WindowProperties &properties) { //////////////////////////////////////////////////////////////////// // Function: glxGraphicsWindow::setup_colormap // Access: Private -// Description: Allocates a colormap appropriate to the visual and +// Description: Allocates a colormap appropriate to the fbconfig and // stores in in the _colormap method. //////////////////////////////////////////////////////////////////// void glxGraphicsWindow:: -setup_colormap(XVisualInfo *visual) { +setup_colormap(GLXFBConfig fbconfig) { + XVisualInfo *visual_info = glXGetVisualFromFBConfig(_display, fbconfig); + if (visual_info == NULL) { + // No X visual; no need to set up a colormap. + return; + } + int visual_class = visual_info->c_class; + Visual *visual = visual_info->visual; + XFree(visual_info); + glxGraphicsPipe *glx_pipe; DCAST_INTO_V(glx_pipe, _pipe); Window root_window = glx_pipe->get_root(); - int visual_class = visual->c_class; int rc, is_rgb; switch (visual_class) { case PseudoColor: - rc = glXGetConfig(_display, visual, GLX_RGBA, &is_rgb); + rc = glXGetFBConfigAttrib(_display, fbconfig, GLX_RGBA, &is_rgb); if (rc == 0 && is_rgb) { glxdisplay_cat.warning() << "mesa pseudocolor not supported.\n"; @@ -588,19 +607,19 @@ setup_colormap(XVisualInfo *visual) { } else { _colormap = XCreateColormap(_display, root_window, - visual->visual, AllocAll); + visual, AllocAll); } break; case TrueColor: case DirectColor: _colormap = XCreateColormap(_display, root_window, - visual->visual, AllocNone); + visual, AllocNone); break; case StaticColor: case StaticGray: case GrayScale: _colormap = XCreateColormap(_display, root_window, - visual->visual, AllocNone); + visual, AllocNone); break; default: glxdisplay_cat.error() diff --git a/panda/src/glxdisplay/glxGraphicsWindow.h b/panda/src/glxdisplay/glxGraphicsWindow.h index 9340286b06..d98a36cd9b 100644 --- a/panda/src/glxdisplay/glxGraphicsWindow.h +++ b/panda/src/glxdisplay/glxGraphicsWindow.h @@ -21,14 +21,10 @@ #include "pandabase.h" +#include "glxGraphicsPipe.h" #include "graphicsWindow.h" #include "buttonHandle.h" -#include -#include - -class glxGraphicsPipe; - //////////////////////////////////////////////////////////////////// // Class : glxGraphicsWindow // Description : An interface to the glx system for managing GL @@ -55,7 +51,7 @@ protected: private: void set_wm_properties(const WindowProperties &properties); - void setup_colormap(XVisualInfo *visual); + void setup_colormap(GLXFBConfig fbconfig); void handle_keystroke(XKeyEvent &event); void handle_keypress(XKeyEvent &event); void handle_keyrelease(XKeyEvent &event);