From 1a99827432cec6057f1e0655653a05a0c6f698a2 Mon Sep 17 00:00:00 2001 From: Camilla Berglund Date: Sun, 22 Apr 2012 21:49:38 +0200 Subject: [PATCH 1/5] Moved the type declarations. --- src/internal.h | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/src/internal.h b/src/internal.h index 6398bdc5..c20b1c9a 100644 --- a/src/internal.h +++ b/src/internal.h @@ -51,6 +51,17 @@ #define GLFW_STICK 2 +//======================================================================== +// Internal type declarations +//======================================================================== + +typedef struct _GLFWhints _GLFWhints; +typedef struct _GLFWwndconfig _GLFWwndconfig; +typedef struct _GLFWfbconfig _GLFWfbconfig; +typedef struct _GLFWwindow _GLFWwindow; +typedef struct _GLFWlibrary _GLFWlibrary; + + //------------------------------------------------------------------------ // Platform specific definitions goes in platform.h (which also includes // glfw.h) @@ -75,12 +86,6 @@ #error "No supported platform selected" #endif -typedef struct _GLFWhints _GLFWhints; -typedef struct _GLFWwndconfig _GLFWwndconfig; -typedef struct _GLFWfbconfig _GLFWfbconfig; -typedef struct _GLFWwindow _GLFWwindow; -typedef struct _GLFWlibrary _GLFWlibrary; - //------------------------------------------------------------------------ // Window hints, set by glfwOpenWindowHint and consumed by glfwOpenWindow From 49dfbe86b217a3cd94e8951f9c62d24dcb4ad43e Mon Sep 17 00:00:00 2001 From: Camilla Berglund Date: Mon, 23 Apr 2012 12:48:57 +0200 Subject: [PATCH 2/5] Moved the majority of GLX code into opengl module. --- src/x11_opengl.c | 550 +++++++++++++++++++++++++++++++++++++++++++++ src/x11_platform.h | 7 +- src/x11_window.c | 520 +----------------------------------------- 3 files changed, 558 insertions(+), 519 deletions(-) diff --git a/src/x11_opengl.c b/src/x11_opengl.c index fd8bd313..825cacc2 100644 --- a/src/x11_opengl.c +++ b/src/x11_opengl.c @@ -30,15 +30,565 @@ #include "internal.h" +#include + // This is the only glXGetProcAddress variant not declared by glxext.h void (*glXGetProcAddressEXT(const GLubyte* procName))(); +//======================================================================== +// Initialize GLX-specific extensions +//======================================================================== + +static void initGLXExtensions(_GLFWwindow* window) +{ + if (_glfwPlatformExtensionSupported("GLX_EXT_swap_control")) + { + window->GLX.SwapIntervalEXT = (PFNGLXSWAPINTERVALEXTPROC) + _glfwPlatformGetProcAddress("glXSwapIntervalEXT"); + + if (window->GLX.SwapIntervalEXT) + window->GLX.EXT_swap_control = GL_TRUE; + } + + if (_glfwPlatformExtensionSupported("GLX_SGI_swap_control")) + { + window->GLX.SwapIntervalSGI = (PFNGLXSWAPINTERVALSGIPROC) + _glfwPlatformGetProcAddress("glXSwapIntervalSGI"); + + if (window->GLX.SwapIntervalSGI) + window->GLX.SGI_swap_control = GL_TRUE; + } + + if (_glfwPlatformExtensionSupported("GLX_SGIX_fbconfig")) + { + window->GLX.GetFBConfigAttribSGIX = (PFNGLXGETFBCONFIGATTRIBSGIXPROC) + _glfwPlatformGetProcAddress("glXGetFBConfigAttribSGIX"); + window->GLX.ChooseFBConfigSGIX = (PFNGLXCHOOSEFBCONFIGSGIXPROC) + _glfwPlatformGetProcAddress("glXChooseFBConfigSGIX"); + window->GLX.CreateContextWithConfigSGIX = (PFNGLXCREATECONTEXTWITHCONFIGSGIXPROC) + _glfwPlatformGetProcAddress("glXCreateContextWithConfigSGIX"); + window->GLX.GetVisualFromFBConfigSGIX = (PFNGLXGETVISUALFROMFBCONFIGSGIXPROC) + _glfwPlatformGetProcAddress("glXGetVisualFromFBConfigSGIX"); + + if (window->GLX.GetFBConfigAttribSGIX && + window->GLX.ChooseFBConfigSGIX && + window->GLX.CreateContextWithConfigSGIX && + window->GLX.GetVisualFromFBConfigSGIX) + { + window->GLX.SGIX_fbconfig = GL_TRUE; + } + } + + if (_glfwPlatformExtensionSupported("GLX_ARB_multisample")) + window->GLX.ARB_multisample = GL_TRUE; + + if (_glfwPlatformExtensionSupported("GLX_ARB_create_context")) + { + window->GLX.CreateContextAttribsARB = (PFNGLXCREATECONTEXTATTRIBSARBPROC) + _glfwPlatformGetProcAddress("glXCreateContextAttribsARB"); + + if (window->GLX.CreateContextAttribsARB) + window->GLX.ARB_create_context = GL_TRUE; + } + + if (_glfwPlatformExtensionSupported("GLX_ARB_create_context_robustness")) + window->GLX.ARB_create_context_robustness = GL_TRUE; + + if (_glfwPlatformExtensionSupported("GLX_ARB_create_context_profile")) + window->GLX.ARB_create_context_profile = GL_TRUE; + + if (_glfwPlatformExtensionSupported("GLX_EXT_create_context_es2_profile")) + window->GLX.EXT_create_context_es2_profile = GL_TRUE; +} + + +//======================================================================== +// Returns the specified attribute of the specified GLXFBConfig +// NOTE: Do not call this unless we have found GLX 1.3+ or GLX_SGIX_fbconfig +//======================================================================== + +static int getFBConfigAttrib(_GLFWwindow* window, GLXFBConfig fbconfig, int attrib) +{ + int value; + + if (window->GLX.SGIX_fbconfig) + { + window->GLX.GetFBConfigAttribSGIX(_glfwLibrary.X11.display, + fbconfig, attrib, &value); + } + else + glXGetFBConfigAttrib(_glfwLibrary.X11.display, fbconfig, attrib, &value); + + return value; +} + + +//======================================================================== +// Return a list of available and usable framebuffer configs +//======================================================================== + +static _GLFWfbconfig* getFBConfigs(_GLFWwindow* window, unsigned int* found) +{ + GLXFBConfig* fbconfigs; + _GLFWfbconfig* result; + int i, count = 0; + + *found = 0; + + if (_glfwLibrary.GLX.majorVersion == 1 && _glfwLibrary.GLX.minorVersion < 3) + { + if (!window->GLX.SGIX_fbconfig) + { + _glfwSetError(GLFW_OPENGL_UNAVAILABLE, + "X11/GLX: GLXFBConfig support not found"); + return NULL; + } + } + + if (window->GLX.SGIX_fbconfig) + { + fbconfigs = window->GLX.ChooseFBConfigSGIX(_glfwLibrary.X11.display, + _glfwLibrary.X11.screen, + NULL, + &count); + if (!count) + { + _glfwSetError(GLFW_OPENGL_UNAVAILABLE, + "X11/GLX: No GLXFBConfigs returned"); + return NULL; + } + } + else + { + fbconfigs = glXGetFBConfigs(_glfwLibrary.X11.display, + _glfwLibrary.X11.screen, + &count); + if (!count) + { + _glfwSetError(GLFW_OPENGL_UNAVAILABLE, + "X11/GLX: No GLXFBConfigs returned"); + return NULL; + } + } + + result = (_GLFWfbconfig*) malloc(sizeof(_GLFWfbconfig) * count); + if (!result) + { + _glfwSetError(GLFW_OUT_OF_MEMORY, + "X11/GLX: Failed to allocate _GLFWfbconfig array"); + return NULL; + } + + for (i = 0; i < count; i++) + { + if (!getFBConfigAttrib(window, fbconfigs[i], GLX_DOUBLEBUFFER) || + !getFBConfigAttrib(window, fbconfigs[i], GLX_VISUAL_ID)) + { + // Only consider double-buffered GLXFBConfigs with associated visuals + continue; + } + + if (!(getFBConfigAttrib(window, + fbconfigs[i], + GLX_RENDER_TYPE) & GLX_RGBA_BIT)) + { + // Only consider RGBA GLXFBConfigs + continue; + } + + if (!(getFBConfigAttrib(window, fbconfigs[i], GLX_DRAWABLE_TYPE) & GLX_WINDOW_BIT)) + { + // Only consider window GLXFBConfigs + continue; + } + + result[*found].redBits = getFBConfigAttrib(window, fbconfigs[i], GLX_RED_SIZE); + result[*found].greenBits = getFBConfigAttrib(window, fbconfigs[i], GLX_GREEN_SIZE); + result[*found].blueBits = getFBConfigAttrib(window, fbconfigs[i], GLX_BLUE_SIZE); + + result[*found].alphaBits = getFBConfigAttrib(window, fbconfigs[i], GLX_ALPHA_SIZE); + result[*found].depthBits = getFBConfigAttrib(window, fbconfigs[i], GLX_DEPTH_SIZE); + result[*found].stencilBits = getFBConfigAttrib(window, fbconfigs[i], GLX_STENCIL_SIZE); + + result[*found].accumRedBits = getFBConfigAttrib(window, fbconfigs[i], GLX_ACCUM_RED_SIZE); + result[*found].accumGreenBits = getFBConfigAttrib(window, fbconfigs[i], GLX_ACCUM_GREEN_SIZE); + result[*found].accumBlueBits = getFBConfigAttrib(window, fbconfigs[i], GLX_ACCUM_BLUE_SIZE); + result[*found].accumAlphaBits = getFBConfigAttrib(window, fbconfigs[i], GLX_ACCUM_ALPHA_SIZE); + + result[*found].auxBuffers = getFBConfigAttrib(window, fbconfigs[i], GLX_AUX_BUFFERS); + result[*found].stereo = getFBConfigAttrib(window, fbconfigs[i], GLX_STEREO); + + if (window->GLX.ARB_multisample) + result[*found].samples = getFBConfigAttrib(window, fbconfigs[i], GLX_SAMPLES); + else + result[*found].samples = 0; + + result[*found].platformID = (GLFWintptr) getFBConfigAttrib(window, fbconfigs[i], GLX_FBCONFIG_ID); + + (*found)++; + } + + XFree(fbconfigs); + + return result; +} + + +//======================================================================== +// Error handler for BadMatch errors when requesting context with +// unavailable OpenGL versions using the GLX_ARB_create_context extension +//======================================================================== + +static int errorHandler(Display *display, XErrorEvent* event) +{ + return 0; +} + + +//======================================================================== +// Read back framebuffer parameters from the context +//======================================================================== + +static void refreshContextParams(_GLFWwindow* window, GLXFBConfigID fbconfigID) +{ + int dummy; + GLXFBConfig* fbconfig; + + int attribs[] = { GLX_FBCONFIG_ID, fbconfigID, None }; + + if (window->GLX.SGIX_fbconfig) + { + fbconfig = window->GLX.ChooseFBConfigSGIX(_glfwLibrary.X11.display, + _glfwLibrary.X11.screen, + attribs, + &dummy); + } + else + { + fbconfig = glXChooseFBConfig(_glfwLibrary.X11.display, + _glfwLibrary.X11.screen, + attribs, + &dummy); + } + + if (fbconfig == NULL) + { + // This should never ever happen + // TODO: Flag this as an error and propagate up + _glfwSetError(GLFW_PLATFORM_ERROR, "X11/GLX: Cannot find known " + "GLXFBConfig by ID. This cannot " + "happen. Have a nice day.\n"); + abort(); + } + + // There is no clear definition of an "accelerated" context on X11/GLX, and + // true sounds better than false, so we hardcode true here + window->accelerated = GL_TRUE; + + window->redBits = getFBConfigAttrib(window, *fbconfig, GLX_RED_SIZE); + window->greenBits = getFBConfigAttrib(window, *fbconfig, GLX_GREEN_SIZE); + window->blueBits = getFBConfigAttrib(window, *fbconfig, GLX_BLUE_SIZE); + + window->alphaBits = getFBConfigAttrib(window, *fbconfig, GLX_ALPHA_SIZE); + window->depthBits = getFBConfigAttrib(window, *fbconfig, GLX_DEPTH_SIZE); + window->stencilBits = getFBConfigAttrib(window, *fbconfig, GLX_STENCIL_SIZE); + + window->accumRedBits = getFBConfigAttrib(window, *fbconfig, GLX_ACCUM_RED_SIZE); + window->accumGreenBits = getFBConfigAttrib(window, *fbconfig, GLX_ACCUM_GREEN_SIZE); + window->accumBlueBits = getFBConfigAttrib(window, *fbconfig, GLX_ACCUM_BLUE_SIZE); + window->accumAlphaBits = getFBConfigAttrib(window, *fbconfig, GLX_ACCUM_ALPHA_SIZE); + + window->auxBuffers = getFBConfigAttrib(window, *fbconfig, GLX_AUX_BUFFERS); + window->stereo = getFBConfigAttrib(window, *fbconfig, GLX_STEREO) ? GL_TRUE : GL_FALSE; + + // Get FSAA buffer sample count + if (window->GLX.ARB_multisample) + window->samples = getFBConfigAttrib(window, *fbconfig, GLX_SAMPLES); + else + window->samples = 0; + + XFree(fbconfig); +} + + +//======================================================================== +// Create the actual OpenGL context +//======================================================================== + +#define setGLXattrib(attribs, index, attribName, attribValue) \ + attribs[index++] = attribName; \ + attribs[index++] = attribValue; + +static int createContext(_GLFWwindow* window, + const _GLFWwndconfig* wndconfig, + GLXFBConfigID fbconfigID) +{ + int attribs[40]; + int dummy, index; + GLXFBConfig* fbconfig; + GLXContext share = NULL; + + if (wndconfig->share) + share = wndconfig->share->GLX.context; + + // Retrieve the previously selected GLXFBConfig + { + index = 0; + + setGLXattrib(attribs, index, GLX_FBCONFIG_ID, (int) fbconfigID); + setGLXattrib(attribs, index, None, None); + + if (window->GLX.SGIX_fbconfig) + { + fbconfig = window->GLX.ChooseFBConfigSGIX(_glfwLibrary.X11.display, + _glfwLibrary.X11.screen, + attribs, + &dummy); + } + else + { + fbconfig = glXChooseFBConfig(_glfwLibrary.X11.display, + _glfwLibrary.X11.screen, + attribs, + &dummy); + } + + if (fbconfig == NULL) + { + _glfwSetError(GLFW_PLATFORM_ERROR, + "X11/GLX: Failed to retrieve the selected GLXFBConfig"); + return GL_FALSE; + } + } + + // Retrieve the corresponding visual + if (window->GLX.SGIX_fbconfig) + { + window->GLX.visual = window->GLX.GetVisualFromFBConfigSGIX(_glfwLibrary.X11.display, + *fbconfig); + } + else + { + window->GLX.visual = glXGetVisualFromFBConfig(_glfwLibrary.X11.display, + *fbconfig); + } + + if (window->GLX.visual == NULL) + { + XFree(fbconfig); + + _glfwSetError(GLFW_PLATFORM_ERROR, + "X11/GLX: Failed to retrieve visual for GLXFBConfig"); + return GL_FALSE; + } + + if (window->GLX.ARB_create_context) + { + index = 0; + + if (wndconfig->glMajor != 1 || wndconfig->glMinor != 0) + { + // Request an explicitly versioned context + + setGLXattrib(attribs, index, GLX_CONTEXT_MAJOR_VERSION_ARB, wndconfig->glMajor); + setGLXattrib(attribs, index, GLX_CONTEXT_MINOR_VERSION_ARB, wndconfig->glMinor); + } + + if (wndconfig->glForward || wndconfig->glDebug || wndconfig->glRobustness) + { + int flags = 0; + + if (wndconfig->glForward) + flags |= GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB; + + if (wndconfig->glDebug) + flags |= GLX_CONTEXT_DEBUG_BIT_ARB; + + if (wndconfig->glRobustness) + flags |= GLX_CONTEXT_ROBUST_ACCESS_BIT_ARB; + + setGLXattrib(attribs, index, GLX_CONTEXT_FLAGS_ARB, flags); + } + + if (wndconfig->glProfile) + { + int flags = 0; + + if (!window->GLX.ARB_create_context_profile) + { + _glfwSetError(GLFW_VERSION_UNAVAILABLE, + "X11/GLX: An OpenGL profile requested but " + "GLX_ARB_create_context_profile is unavailable"); + return GL_FALSE; + } + + if (wndconfig->glProfile == GLFW_OPENGL_ES2_PROFILE && + !window->GLX.EXT_create_context_es2_profile) + { + _glfwSetError(GLFW_VERSION_UNAVAILABLE, + "X11/GLX: OpenGL ES 2.x profile requested but " + "GLX_EXT_create_context_es2_profile is unavailable"); + return GL_FALSE; + } + + if (wndconfig->glProfile == GLFW_OPENGL_CORE_PROFILE) + flags = GLX_CONTEXT_CORE_PROFILE_BIT_ARB; + else if (wndconfig->glProfile == GLFW_OPENGL_COMPAT_PROFILE) + flags = GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB; + else if (wndconfig->glProfile == GLFW_OPENGL_ES2_PROFILE) + flags = GLX_CONTEXT_ES2_PROFILE_BIT_EXT; + + setGLXattrib(attribs, index, GLX_CONTEXT_PROFILE_MASK_ARB, flags); + } + + if (wndconfig->glRobustness) + { + int strategy; + + if (!window->GLX.ARB_create_context_robustness) + { + _glfwSetError(GLFW_VERSION_UNAVAILABLE, + "X11/GLX: An OpenGL robustness strategy was " + "requested but GLX_ARB_create_context_robustness " + "is unavailable"); + return GL_FALSE; + } + + if (wndconfig->glRobustness == GLFW_OPENGL_NO_RESET_NOTIFICATION) + strategy = GLX_NO_RESET_NOTIFICATION_ARB; + else if (wndconfig->glRobustness == GLFW_OPENGL_LOSE_CONTEXT_ON_RESET) + strategy = GLX_LOSE_CONTEXT_ON_RESET_ARB; + + setGLXattrib(attribs, + index, + GLX_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB, + strategy); + } + + setGLXattrib(attribs, index, None, None); + + // This is the only place we set an Xlib error handler, and we only do + // it because glXCreateContextAttribsARB generates a BadMatch error if + // the requested OpenGL version is unavailable (instead of a civilized + // response like returning NULL) + XSetErrorHandler(errorHandler); + + window->GLX.context = + window->GLX.CreateContextAttribsARB(_glfwLibrary.X11.display, + *fbconfig, + share, + True, + attribs); + + // We are done, so unset the error handler again (see above) + XSetErrorHandler(NULL); + } + else + { + if (window->GLX.SGIX_fbconfig) + { + window->GLX.context = + window->GLX.CreateContextWithConfigSGIX(_glfwLibrary.X11.display, + *fbconfig, + GLX_RGBA_TYPE, + share, + True); + } + else + { + window->GLX.context = glXCreateNewContext(_glfwLibrary.X11.display, + *fbconfig, + GLX_RGBA_TYPE, + share, + True); + } + } + + XFree(fbconfig); + + if (window->GLX.context == NULL) + { + // TODO: Handle all the various error codes here + + _glfwSetError(GLFW_PLATFORM_ERROR, + "X11/GLX: Failed to create OpenGL context"); + return GL_FALSE; + } + + refreshContextParams(window, fbconfigID); + + return GL_TRUE; +} + +#undef setGLXattrib + + ////////////////////////////////////////////////////////////////////////// ////// GLFW internal API ////// ////////////////////////////////////////////////////////////////////////// +//======================================================================== +// Prepare for creation of the OpenGL context +//======================================================================== + +int _glfwCreateContext(_GLFWwindow* window, + const _GLFWwndconfig* wndconfig, + const _GLFWfbconfig* fbconfig) +{ + _GLFWfbconfig closest; + + initGLXExtensions(window); + + // Choose the best available fbconfig + { + unsigned int fbcount; + _GLFWfbconfig* fbconfigs; + const _GLFWfbconfig* result; + + fbconfigs = getFBConfigs(window, &fbcount); + if (!fbconfigs) + { + _glfwSetError(GLFW_PLATFORM_ERROR, + "X11/GLX: No usable GLXFBConfigs found"); + return GL_FALSE; + } + + result = _glfwChooseFBConfig(fbconfig, fbconfigs, fbcount); + if (!result) + { + _glfwSetError(GLFW_PLATFORM_ERROR, + "X11/GLX: No GLXFBConfig matched the criteria"); + + free(fbconfigs); + return GL_FALSE; + } + + closest = *result; + free(fbconfigs); + } + + return createContext(window, wndconfig, closest.platformID); +} + + +//======================================================================== +// Destroy the OpenGL context +//======================================================================== + +void _glfwDestroyContext(_GLFWwindow* window) +{ + if (window->GLX.context) + { + // Release and destroy the context + glXMakeCurrent(_glfwLibrary.X11.display, None, NULL); + glXDestroyContext(_glfwLibrary.X11.display, window->GLX.context); + window->GLX.context = NULL; + } +} + + //======================================================================== // Make the OpenGL context associated with the specified window current //======================================================================== diff --git a/src/x11_platform.h b/src/x11_platform.h index 013ca4e0..96fb64fa 100644 --- a/src/x11_platform.h +++ b/src/x11_platform.h @@ -113,7 +113,6 @@ typedef intptr_t GLFWintptr; //------------------------------------------------------------------------ typedef struct _GLFWcontextGLX { - GLXFBConfigID fbconfigID; // ID of selected GLXFBConfig GLXContext context; // OpenGL rendering context XVisualInfo* visual; // Visual for selected GLXFBConfig @@ -283,6 +282,12 @@ GLFWGLOBAL struct { // Time void _glfwInitTimer(void); +// OpenGL support +int _glfwCreateContext(_GLFWwindow* window, + const _GLFWwndconfig* wndconfig, + const _GLFWfbconfig* fbconfig); +void _glfwDestroyContext(_GLFWwindow* window); + // Fullscreen support int _glfwGetClosestVideoMode(int* width, int* height, int* rate); void _glfwSetVideoModeMODE(int mode, int rate); diff --git a/src/x11_window.c b/src/x11_window.c index ccd99a60..a5e7b0d8 100644 --- a/src/x11_window.c +++ b/src/x11_window.c @@ -43,17 +43,6 @@ #define Button6 6 #define Button7 7 -//======================================================================== -// Error handler for BadMatch errors when requesting context with -// unavailable OpenGL versions using the GLX_ARB_create_context extension -//======================================================================== - -static int errorHandler(Display *display, XErrorEvent* event) -{ - return 0; -} - - //======================================================================== // Checks whether the event is a MapNotify for the specified window //======================================================================== @@ -98,417 +87,6 @@ static int translateChar(XKeyEvent* event) } -//======================================================================== -// Returns the specified attribute of the specified GLXFBConfig -// NOTE: Do not call this unless we have found GLX 1.3+ or GLX_SGIX_fbconfig -//======================================================================== - -static int getFBConfigAttrib(_GLFWwindow* window, GLXFBConfig fbconfig, int attrib) -{ - int value; - - if (window->GLX.SGIX_fbconfig) - { - window->GLX.GetFBConfigAttribSGIX(_glfwLibrary.X11.display, - fbconfig, attrib, &value); - } - else - glXGetFBConfigAttrib(_glfwLibrary.X11.display, fbconfig, attrib, &value); - - return value; -} - - -//======================================================================== -// Return a list of available and usable framebuffer configs -//======================================================================== - -static _GLFWfbconfig* getFBConfigs(_GLFWwindow* window, unsigned int* found) -{ - GLXFBConfig* fbconfigs; - _GLFWfbconfig* result; - int i, count = 0; - - *found = 0; - - if (_glfwLibrary.GLX.majorVersion == 1 && _glfwLibrary.GLX.minorVersion < 3) - { - if (!window->GLX.SGIX_fbconfig) - { - _glfwSetError(GLFW_OPENGL_UNAVAILABLE, - "X11/GLX: GLXFBConfig support not found"); - return NULL; - } - } - - if (window->GLX.SGIX_fbconfig) - { - fbconfigs = window->GLX.ChooseFBConfigSGIX(_glfwLibrary.X11.display, - _glfwLibrary.X11.screen, - NULL, - &count); - if (!count) - { - _glfwSetError(GLFW_OPENGL_UNAVAILABLE, - "X11/GLX: No GLXFBConfigs returned"); - return NULL; - } - } - else - { - fbconfigs = glXGetFBConfigs(_glfwLibrary.X11.display, - _glfwLibrary.X11.screen, - &count); - if (!count) - { - _glfwSetError(GLFW_OPENGL_UNAVAILABLE, - "X11/GLX: No GLXFBConfigs returned"); - return NULL; - } - } - - result = (_GLFWfbconfig*) malloc(sizeof(_GLFWfbconfig) * count); - if (!result) - { - _glfwSetError(GLFW_OUT_OF_MEMORY, - "X11/GLX: Failed to allocate _GLFWfbconfig array"); - return NULL; - } - - for (i = 0; i < count; i++) - { - if (!getFBConfigAttrib(window, fbconfigs[i], GLX_DOUBLEBUFFER) || - !getFBConfigAttrib(window, fbconfigs[i], GLX_VISUAL_ID)) - { - // Only consider double-buffered GLXFBConfigs with associated visuals - continue; - } - - if (!(getFBConfigAttrib(window, - fbconfigs[i], - GLX_RENDER_TYPE) & GLX_RGBA_BIT)) - { - // Only consider RGBA GLXFBConfigs - continue; - } - - if (!(getFBConfigAttrib(window, fbconfigs[i], GLX_DRAWABLE_TYPE) & GLX_WINDOW_BIT)) - { - // Only consider window GLXFBConfigs - continue; - } - - result[*found].redBits = getFBConfigAttrib(window, fbconfigs[i], GLX_RED_SIZE); - result[*found].greenBits = getFBConfigAttrib(window, fbconfigs[i], GLX_GREEN_SIZE); - result[*found].blueBits = getFBConfigAttrib(window, fbconfigs[i], GLX_BLUE_SIZE); - - result[*found].alphaBits = getFBConfigAttrib(window, fbconfigs[i], GLX_ALPHA_SIZE); - result[*found].depthBits = getFBConfigAttrib(window, fbconfigs[i], GLX_DEPTH_SIZE); - result[*found].stencilBits = getFBConfigAttrib(window, fbconfigs[i], GLX_STENCIL_SIZE); - - result[*found].accumRedBits = getFBConfigAttrib(window, fbconfigs[i], GLX_ACCUM_RED_SIZE); - result[*found].accumGreenBits = getFBConfigAttrib(window, fbconfigs[i], GLX_ACCUM_GREEN_SIZE); - result[*found].accumBlueBits = getFBConfigAttrib(window, fbconfigs[i], GLX_ACCUM_BLUE_SIZE); - result[*found].accumAlphaBits = getFBConfigAttrib(window, fbconfigs[i], GLX_ACCUM_ALPHA_SIZE); - - result[*found].auxBuffers = getFBConfigAttrib(window, fbconfigs[i], GLX_AUX_BUFFERS); - result[*found].stereo = getFBConfigAttrib(window, fbconfigs[i], GLX_STEREO); - - if (window->GLX.ARB_multisample) - result[*found].samples = getFBConfigAttrib(window, fbconfigs[i], GLX_SAMPLES); - else - result[*found].samples = 0; - - result[*found].platformID = (GLFWintptr) getFBConfigAttrib(window, fbconfigs[i], GLX_FBCONFIG_ID); - - (*found)++; - } - - XFree(fbconfigs); - - return result; -} - - -//======================================================================== -// Create the OpenGL context -//======================================================================== - -#define setGLXattrib(attribs, index, attribName, attribValue) \ - attribs[index++] = attribName; \ - attribs[index++] = attribValue; - -static int createContext(_GLFWwindow* window, - const _GLFWwndconfig* wndconfig, - GLXFBConfigID fbconfigID) -{ - int attribs[40]; - int dummy, index; - GLXFBConfig* fbconfig; - GLXContext share = NULL; - - if (wndconfig->share) - share = wndconfig->share->GLX.context; - - // Retrieve the previously selected GLXFBConfig - { - index = 0; - - setGLXattrib(attribs, index, GLX_FBCONFIG_ID, (int) fbconfigID); - setGLXattrib(attribs, index, None, None); - - if (window->GLX.SGIX_fbconfig) - { - fbconfig = window->GLX.ChooseFBConfigSGIX(_glfwLibrary.X11.display, - _glfwLibrary.X11.screen, - attribs, - &dummy); - } - else - { - fbconfig = glXChooseFBConfig(_glfwLibrary.X11.display, - _glfwLibrary.X11.screen, - attribs, - &dummy); - } - - if (fbconfig == NULL) - { - _glfwSetError(GLFW_PLATFORM_ERROR, - "X11/GLX: Failed to retrieve the selected GLXFBConfig"); - return GL_FALSE; - } - } - - // Retrieve the corresponding visual - if (window->GLX.SGIX_fbconfig) - { - window->GLX.visual = window->GLX.GetVisualFromFBConfigSGIX(_glfwLibrary.X11.display, - *fbconfig); - } - else - { - window->GLX.visual = glXGetVisualFromFBConfig(_glfwLibrary.X11.display, - *fbconfig); - } - - if (window->GLX.visual == NULL) - { - XFree(fbconfig); - - _glfwSetError(GLFW_PLATFORM_ERROR, - "X11/GLX: Failed to retrieve visual for GLXFBConfig"); - return GL_FALSE; - } - - if (window->GLX.ARB_create_context) - { - index = 0; - - if (wndconfig->glMajor != 1 || wndconfig->glMinor != 0) - { - // Request an explicitly versioned context - - setGLXattrib(attribs, index, GLX_CONTEXT_MAJOR_VERSION_ARB, wndconfig->glMajor); - setGLXattrib(attribs, index, GLX_CONTEXT_MINOR_VERSION_ARB, wndconfig->glMinor); - } - - if (wndconfig->glForward || wndconfig->glDebug || wndconfig->glRobustness) - { - int flags = 0; - - if (wndconfig->glForward) - flags |= GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB; - - if (wndconfig->glDebug) - flags |= GLX_CONTEXT_DEBUG_BIT_ARB; - - if (wndconfig->glRobustness) - flags |= GLX_CONTEXT_ROBUST_ACCESS_BIT_ARB; - - setGLXattrib(attribs, index, GLX_CONTEXT_FLAGS_ARB, flags); - } - - if (wndconfig->glProfile) - { - int flags = 0; - - if (!window->GLX.ARB_create_context_profile) - { - _glfwSetError(GLFW_VERSION_UNAVAILABLE, - "X11/GLX: An OpenGL profile requested but " - "GLX_ARB_create_context_profile is unavailable"); - return GL_FALSE; - } - - if (wndconfig->glProfile == GLFW_OPENGL_ES2_PROFILE && - !window->GLX.EXT_create_context_es2_profile) - { - _glfwSetError(GLFW_VERSION_UNAVAILABLE, - "X11/GLX: OpenGL ES 2.x profile requested but " - "GLX_EXT_create_context_es2_profile is unavailable"); - return GL_FALSE; - } - - if (wndconfig->glProfile == GLFW_OPENGL_CORE_PROFILE) - flags = GLX_CONTEXT_CORE_PROFILE_BIT_ARB; - else if (wndconfig->glProfile == GLFW_OPENGL_COMPAT_PROFILE) - flags = GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB; - else if (wndconfig->glProfile == GLFW_OPENGL_ES2_PROFILE) - flags = GLX_CONTEXT_ES2_PROFILE_BIT_EXT; - - setGLXattrib(attribs, index, GLX_CONTEXT_PROFILE_MASK_ARB, flags); - } - - if (wndconfig->glRobustness) - { - int strategy; - - if (!window->GLX.ARB_create_context_robustness) - { - _glfwSetError(GLFW_VERSION_UNAVAILABLE, - "X11/GLX: An OpenGL robustness strategy was " - "requested but GLX_ARB_create_context_robustness " - "is unavailable"); - return GL_FALSE; - } - - if (wndconfig->glRobustness == GLFW_OPENGL_NO_RESET_NOTIFICATION) - strategy = GLX_NO_RESET_NOTIFICATION_ARB; - else if (wndconfig->glRobustness == GLFW_OPENGL_LOSE_CONTEXT_ON_RESET) - strategy = GLX_LOSE_CONTEXT_ON_RESET_ARB; - - setGLXattrib(attribs, - index, - GLX_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB, - strategy); - } - - setGLXattrib(attribs, index, None, None); - - // This is the only place we set an Xlib error handler, and we only do - // it because glXCreateContextAttribsARB generates a BadMatch error if - // the requested OpenGL version is unavailable (instead of a civilized - // response like returning NULL) - XSetErrorHandler(errorHandler); - - window->GLX.context = - window->GLX.CreateContextAttribsARB(_glfwLibrary.X11.display, - *fbconfig, - share, - True, - attribs); - - // We are done, so unset the error handler again (see above) - XSetErrorHandler(NULL); - } - else - { - if (window->GLX.SGIX_fbconfig) - { - window->GLX.context = - window->GLX.CreateContextWithConfigSGIX(_glfwLibrary.X11.display, - *fbconfig, - GLX_RGBA_TYPE, - share, - True); - } - else - { - window->GLX.context = glXCreateNewContext(_glfwLibrary.X11.display, - *fbconfig, - GLX_RGBA_TYPE, - share, - True); - } - } - - XFree(fbconfig); - - if (window->GLX.context == NULL) - { - // TODO: Handle all the various error codes here - - _glfwSetError(GLFW_PLATFORM_ERROR, - "X11/GLX: Failed to create OpenGL context"); - return GL_FALSE; - } - - window->GLX.fbconfigID = fbconfigID; - - return GL_TRUE; -} - -#undef setGLXattrib - - -//======================================================================== -// Initialize GLX-specific extensions -//======================================================================== - -static void initGLXExtensions(_GLFWwindow* window) -{ - if (_glfwPlatformExtensionSupported("GLX_EXT_swap_control")) - { - window->GLX.SwapIntervalEXT = (PFNGLXSWAPINTERVALEXTPROC) - _glfwPlatformGetProcAddress("glXSwapIntervalEXT"); - - if (window->GLX.SwapIntervalEXT) - window->GLX.EXT_swap_control = GL_TRUE; - } - - if (_glfwPlatformExtensionSupported("GLX_SGI_swap_control")) - { - window->GLX.SwapIntervalSGI = (PFNGLXSWAPINTERVALSGIPROC) - _glfwPlatformGetProcAddress("glXSwapIntervalSGI"); - - if (window->GLX.SwapIntervalSGI) - window->GLX.SGI_swap_control = GL_TRUE; - } - - if (_glfwPlatformExtensionSupported("GLX_SGIX_fbconfig")) - { - window->GLX.GetFBConfigAttribSGIX = (PFNGLXGETFBCONFIGATTRIBSGIXPROC) - _glfwPlatformGetProcAddress("glXGetFBConfigAttribSGIX"); - window->GLX.ChooseFBConfigSGIX = (PFNGLXCHOOSEFBCONFIGSGIXPROC) - _glfwPlatformGetProcAddress("glXChooseFBConfigSGIX"); - window->GLX.CreateContextWithConfigSGIX = (PFNGLXCREATECONTEXTWITHCONFIGSGIXPROC) - _glfwPlatformGetProcAddress("glXCreateContextWithConfigSGIX"); - window->GLX.GetVisualFromFBConfigSGIX = (PFNGLXGETVISUALFROMFBCONFIGSGIXPROC) - _glfwPlatformGetProcAddress("glXGetVisualFromFBConfigSGIX"); - - if (window->GLX.GetFBConfigAttribSGIX && - window->GLX.ChooseFBConfigSGIX && - window->GLX.CreateContextWithConfigSGIX && - window->GLX.GetVisualFromFBConfigSGIX) - { - window->GLX.SGIX_fbconfig = GL_TRUE; - } - } - - if (_glfwPlatformExtensionSupported("GLX_ARB_multisample")) - window->GLX.ARB_multisample = GL_TRUE; - - if (_glfwPlatformExtensionSupported("GLX_ARB_create_context")) - { - window->GLX.CreateContextAttribsARB = (PFNGLXCREATECONTEXTATTRIBSARBPROC) - _glfwPlatformGetProcAddress("glXCreateContextAttribsARB"); - - if (window->GLX.CreateContextAttribsARB) - window->GLX.ARB_create_context = GL_TRUE; - } - - if (_glfwPlatformExtensionSupported("GLX_ARB_create_context_robustness")) - window->GLX.ARB_create_context_robustness = GL_TRUE; - - if (_glfwPlatformExtensionSupported("GLX_ARB_create_context_profile")) - window->GLX.ARB_create_context_profile = GL_TRUE; - - if (_glfwPlatformExtensionSupported("GLX_EXT_create_context_es2_profile")) - window->GLX.EXT_create_context_es2_profile = GL_TRUE; -} - - //======================================================================== // Create the X11 window (and its colormap) //======================================================================== @@ -1339,42 +917,10 @@ int _glfwPlatformOpenWindow(_GLFWwindow* window, const _GLFWwndconfig* wndconfig, const _GLFWfbconfig* fbconfig) { - _GLFWfbconfig closest; - window->refreshRate = wndconfig->refreshRate; window->resizable = wndconfig->resizable; - initGLXExtensions(window); - - // Choose the best available fbconfig - { - unsigned int fbcount; - _GLFWfbconfig* fbconfigs; - const _GLFWfbconfig* result; - - fbconfigs = getFBConfigs(window, &fbcount); - if (!fbconfigs) - { - _glfwSetError(GLFW_PLATFORM_ERROR, - "X11/GLX: No usable GLXFBConfigs found"); - return GL_FALSE; - } - - result = _glfwChooseFBConfig(fbconfig, fbconfigs, fbcount); - if (!result) - { - _glfwSetError(GLFW_PLATFORM_ERROR, - "X11/GLX: No GLXFBConfig matched the criteria"); - - free(fbconfigs); - return GL_FALSE; - } - - closest = *result; - free(fbconfigs); - } - - if (!createContext(window, wndconfig, (GLXFBConfigID) closest.platformID)) + if (!_glfwCreateContext(window, wndconfig, fbconfig)) return GL_FALSE; if (!createWindow(window, wndconfig)) @@ -1431,13 +977,7 @@ void _glfwPlatformCloseWindow(_GLFWwindow* window) if (window->mode == GLFW_FULLSCREEN) leaveFullscreenMode(window); - if (window->GLX.context) - { - // Release and destroy the context - glXMakeCurrent(_glfwLibrary.X11.display, None, NULL); - glXDestroyContext(_glfwLibrary.X11.display, window->GLX.context); - window->GLX.context = NULL; - } + _glfwDestroyContext(window); if (window->GLX.visual) { @@ -1604,8 +1144,6 @@ void _glfwPlatformRestoreWindow(_GLFWwindow* window) void _glfwPlatformRefreshWindowParams(void) { - int dummy; - GLXFBConfig* fbconfig; #if defined(_GLFW_HAS_XRANDR) XRRScreenConfiguration* sc; #endif /*_GLFW_HAS_XRANDR*/ @@ -1616,58 +1154,6 @@ void _glfwPlatformRefreshWindowParams(void) #endif /*_GLFW_HAS_XF86VIDMODE*/ _GLFWwindow* window = _glfwLibrary.currentWindow; - int attribs[] = { GLX_FBCONFIG_ID, window->GLX.fbconfigID, None }; - - if (window->GLX.SGIX_fbconfig) - { - fbconfig = window->GLX.ChooseFBConfigSGIX(_glfwLibrary.X11.display, - _glfwLibrary.X11.screen, - attribs, - &dummy); - } - else - { - fbconfig = glXChooseFBConfig(_glfwLibrary.X11.display, - _glfwLibrary.X11.screen, - attribs, - &dummy); - } - - if (fbconfig == NULL) - { - // This should never ever happen - // TODO: Flag this as an error and propagate up - fprintf(stderr, "Cannot find known GLXFBConfig by ID. " - "This cannot happen. Have a nice day.\n"); - abort(); - } - - // There is no clear definition of an "accelerated" context on X11/GLX, and - // true sounds better than false, so we hardcode true here - window->accelerated = GL_TRUE; - - window->redBits = getFBConfigAttrib(window, *fbconfig, GLX_RED_SIZE); - window->greenBits = getFBConfigAttrib(window, *fbconfig, GLX_GREEN_SIZE); - window->blueBits = getFBConfigAttrib(window, *fbconfig, GLX_BLUE_SIZE); - - window->alphaBits = getFBConfigAttrib(window, *fbconfig, GLX_ALPHA_SIZE); - window->depthBits = getFBConfigAttrib(window, *fbconfig, GLX_DEPTH_SIZE); - window->stencilBits = getFBConfigAttrib(window, *fbconfig, GLX_STENCIL_SIZE); - - window->accumRedBits = getFBConfigAttrib(window, *fbconfig, GLX_ACCUM_RED_SIZE); - window->accumGreenBits = getFBConfigAttrib(window, *fbconfig, GLX_ACCUM_GREEN_SIZE); - window->accumBlueBits = getFBConfigAttrib(window, *fbconfig, GLX_ACCUM_BLUE_SIZE); - window->accumAlphaBits = getFBConfigAttrib(window, *fbconfig, GLX_ACCUM_ALPHA_SIZE); - - window->auxBuffers = getFBConfigAttrib(window, *fbconfig, GLX_AUX_BUFFERS); - window->stereo = getFBConfigAttrib(window, *fbconfig, GLX_STEREO) ? GL_TRUE : GL_FALSE; - - // Get FSAA buffer sample count - if (window->GLX.ARB_multisample) - window->samples = getFBConfigAttrib(window, *fbconfig, GLX_SAMPLES); - else - window->samples = 0; - // Retrieve refresh rate if possible if (_glfwLibrary.X11.RandR.available) { @@ -1694,8 +1180,6 @@ void _glfwPlatformRefreshWindowParams(void) // Zero means unknown according to the GLFW spec window->refreshRate = 0; } - - XFree(fbconfig); } From 9614b9b22f458ab4449b3e9584cf8c73bab2884e Mon Sep 17 00:00:00 2001 From: Camilla Berglund Date: Mon, 23 Apr 2012 13:00:49 +0200 Subject: [PATCH 3/5] Moved OpenGL init and terminate to opengl module. --- src/x11_init.c | 58 +++------------------------------------ src/x11_opengl.c | 68 ++++++++++++++++++++++++++++++++++++++++++++++ src/x11_platform.h | 2 ++ 3 files changed, 74 insertions(+), 54 deletions(-) diff --git a/src/x11_init.c b/src/x11_init.c index d59fbcc6..6b2f473e 100644 --- a/src/x11_init.c +++ b/src/x11_init.c @@ -36,33 +36,6 @@ #include -//======================================================================== -// Dynamically load libraries -//======================================================================== - -static void initLibraries(void) -{ -#ifdef _GLFW_DLOPEN_LIBGL - int i; - char* libGL_names[ ] = - { - "libGL.so", - "libGL.so.1", - "/usr/lib/libGL.so", - "/usr/lib/libGL.so.1", - NULL - }; - - for (i = 0; libGL_names[i] != NULL; i++) - { - _glfwLibrary.GLX.libGL = dlopen(libGL_names[i], RTLD_LAZY | RTLD_GLOBAL); - if (_glfwLibrary.GLX.libGL) - break; - } -#endif -} - - //======================================================================== // Translate an X11 key code to a GLFW key code. //======================================================================== @@ -561,22 +534,6 @@ static GLboolean initDisplay(void) _glfwLibrary.X11.RandR.available = GL_FALSE; #endif /*_GLFW_HAS_XRANDR*/ - // Check if GLX is supported on this display - if (!glXQueryExtension(_glfwLibrary.X11.display, NULL, NULL)) - { - _glfwSetError(GLFW_OPENGL_UNAVAILABLE, "X11/GLX: GLX supported not found"); - return GL_FALSE; - } - - if (!glXQueryVersion(_glfwLibrary.X11.display, - &_glfwLibrary.GLX.majorVersion, - &_glfwLibrary.GLX.minorVersion)) - { - _glfwSetError(GLFW_OPENGL_UNAVAILABLE, - "X11/GLX: Failed to query GLX version"); - return GL_FALSE; - } - // Check if Xkb is supported on this display #if defined(_GLFW_HAS_XKB) _glfwLibrary.X11.Xkb.majorVersion = 1; @@ -739,15 +696,15 @@ int _glfwPlatformInit(void) if (!initDisplay()) return GL_FALSE; + if (!_glfwInitOpenGL()) + return GL_FALSE; + initGammaRamp(); initEWMH(); _glfwLibrary.X11.cursor = createNULLCursor(); - // Try to load libGL.so if necessary - initLibraries(); - _glfwInitJoysticks(); // Start the timer @@ -773,14 +730,7 @@ int _glfwPlatformTerminate(void) _glfwTerminateJoysticks(); - // Unload libGL.so if necessary -#ifdef _GLFW_DLOPEN_LIBGL - if (_glfwLibrary.GLX.libGL != NULL) - { - dlclose(_glfwLibrary.GLX.libGL); - _glfwLibrary.GLX.libGL = NULL; - } -#endif + _glfwTerminateOpenGL(); // Free clipboard memory if (_glfwLibrary.X11.selection.string) diff --git a/src/x11_opengl.c b/src/x11_opengl.c index 825cacc2..a09f00fd 100644 --- a/src/x11_opengl.c +++ b/src/x11_opengl.c @@ -529,6 +529,74 @@ static int createContext(_GLFWwindow* window, ////// GLFW internal API ////// ////////////////////////////////////////////////////////////////////////// +//======================================================================== +// Initialize GLX +//======================================================================== + +int _glfwInitOpenGL(void) +{ +#ifdef _GLFW_DLOPEN_LIBGL + int i; + char* libGL_names[ ] = + { + "libGL.so", + "libGL.so.1", + "/usr/lib/libGL.so", + "/usr/lib/libGL.so.1", + NULL + }; + + for (i = 0; libGL_names[i] != NULL; i++) + { + _glfwLibrary.GLX.libGL = dlopen(libGL_names[i], RTLD_LAZY | RTLD_GLOBAL); + if (_glfwLibrary.GLX.libGL) + break; + } + + if (!_glfwLibrary.GLX.libGL) + { + _glfwSetError(GLFW_PLATFORM_ERROR, "X11/GLX: Failed to find libGL"); + return GL_FALSE; + } +#endif + + // Check if GLX is supported on this display + if (!glXQueryExtension(_glfwLibrary.X11.display, NULL, NULL)) + { + _glfwSetError(GLFW_OPENGL_UNAVAILABLE, "X11/GLX: GLX supported not found"); + return GL_FALSE; + } + + if (!glXQueryVersion(_glfwLibrary.X11.display, + &_glfwLibrary.GLX.majorVersion, + &_glfwLibrary.GLX.minorVersion)) + { + _glfwSetError(GLFW_OPENGL_UNAVAILABLE, + "X11/GLX: Failed to query GLX version"); + return GL_FALSE; + } + + return GL_TRUE; +} + + +//======================================================================== +// Terminate GLX +//======================================================================== + +void _glfwTerminateOpenGL(void) +{ + // Unload libGL.so if necessary +#ifdef _GLFW_DLOPEN_LIBGL + if (_glfwLibrary.GLX.libGL != NULL) + { + dlclose(_glfwLibrary.GLX.libGL); + _glfwLibrary.GLX.libGL = NULL; + } +#endif +} + + //======================================================================== // Prepare for creation of the OpenGL context //======================================================================== diff --git a/src/x11_platform.h b/src/x11_platform.h index 96fb64fa..bf959f85 100644 --- a/src/x11_platform.h +++ b/src/x11_platform.h @@ -283,6 +283,8 @@ GLFWGLOBAL struct { void _glfwInitTimer(void); // OpenGL support +int _glfwInitOpenGL(void); +void _glfwTerminateOpenGL(void); int _glfwCreateContext(_GLFWwindow* window, const _GLFWwndconfig* wndconfig, const _GLFWfbconfig* fbconfig); From f77c8f8b218edfe591b0370d61b69e581db4ddba Mon Sep 17 00:00:00 2001 From: Camilla Berglund Date: Mon, 23 Apr 2012 13:08:34 +0200 Subject: [PATCH 4/5] Made GLX extension management global instead of per-window. --- src/x11_opengl.c | 218 +++++++++++++++++++++------------------------ src/x11_platform.h | 34 +++---- 2 files changed, 121 insertions(+), 131 deletions(-) diff --git a/src/x11_opengl.c b/src/x11_opengl.c index a09f00fd..5ec47ee5 100644 --- a/src/x11_opengl.c +++ b/src/x11_opengl.c @@ -37,73 +37,6 @@ void (*glXGetProcAddressEXT(const GLubyte* procName))(); -//======================================================================== -// Initialize GLX-specific extensions -//======================================================================== - -static void initGLXExtensions(_GLFWwindow* window) -{ - if (_glfwPlatformExtensionSupported("GLX_EXT_swap_control")) - { - window->GLX.SwapIntervalEXT = (PFNGLXSWAPINTERVALEXTPROC) - _glfwPlatformGetProcAddress("glXSwapIntervalEXT"); - - if (window->GLX.SwapIntervalEXT) - window->GLX.EXT_swap_control = GL_TRUE; - } - - if (_glfwPlatformExtensionSupported("GLX_SGI_swap_control")) - { - window->GLX.SwapIntervalSGI = (PFNGLXSWAPINTERVALSGIPROC) - _glfwPlatformGetProcAddress("glXSwapIntervalSGI"); - - if (window->GLX.SwapIntervalSGI) - window->GLX.SGI_swap_control = GL_TRUE; - } - - if (_glfwPlatformExtensionSupported("GLX_SGIX_fbconfig")) - { - window->GLX.GetFBConfigAttribSGIX = (PFNGLXGETFBCONFIGATTRIBSGIXPROC) - _glfwPlatformGetProcAddress("glXGetFBConfigAttribSGIX"); - window->GLX.ChooseFBConfigSGIX = (PFNGLXCHOOSEFBCONFIGSGIXPROC) - _glfwPlatformGetProcAddress("glXChooseFBConfigSGIX"); - window->GLX.CreateContextWithConfigSGIX = (PFNGLXCREATECONTEXTWITHCONFIGSGIXPROC) - _glfwPlatformGetProcAddress("glXCreateContextWithConfigSGIX"); - window->GLX.GetVisualFromFBConfigSGIX = (PFNGLXGETVISUALFROMFBCONFIGSGIXPROC) - _glfwPlatformGetProcAddress("glXGetVisualFromFBConfigSGIX"); - - if (window->GLX.GetFBConfigAttribSGIX && - window->GLX.ChooseFBConfigSGIX && - window->GLX.CreateContextWithConfigSGIX && - window->GLX.GetVisualFromFBConfigSGIX) - { - window->GLX.SGIX_fbconfig = GL_TRUE; - } - } - - if (_glfwPlatformExtensionSupported("GLX_ARB_multisample")) - window->GLX.ARB_multisample = GL_TRUE; - - if (_glfwPlatformExtensionSupported("GLX_ARB_create_context")) - { - window->GLX.CreateContextAttribsARB = (PFNGLXCREATECONTEXTATTRIBSARBPROC) - _glfwPlatformGetProcAddress("glXCreateContextAttribsARB"); - - if (window->GLX.CreateContextAttribsARB) - window->GLX.ARB_create_context = GL_TRUE; - } - - if (_glfwPlatformExtensionSupported("GLX_ARB_create_context_robustness")) - window->GLX.ARB_create_context_robustness = GL_TRUE; - - if (_glfwPlatformExtensionSupported("GLX_ARB_create_context_profile")) - window->GLX.ARB_create_context_profile = GL_TRUE; - - if (_glfwPlatformExtensionSupported("GLX_EXT_create_context_es2_profile")) - window->GLX.EXT_create_context_es2_profile = GL_TRUE; -} - - //======================================================================== // Returns the specified attribute of the specified GLXFBConfig // NOTE: Do not call this unless we have found GLX 1.3+ or GLX_SGIX_fbconfig @@ -113,10 +46,10 @@ static int getFBConfigAttrib(_GLFWwindow* window, GLXFBConfig fbconfig, int attr { int value; - if (window->GLX.SGIX_fbconfig) + if (_glfwLibrary.GLX.SGIX_fbconfig) { - window->GLX.GetFBConfigAttribSGIX(_glfwLibrary.X11.display, - fbconfig, attrib, &value); + _glfwLibrary.GLX.GetFBConfigAttribSGIX(_glfwLibrary.X11.display, + fbconfig, attrib, &value); } else glXGetFBConfigAttrib(_glfwLibrary.X11.display, fbconfig, attrib, &value); @@ -139,7 +72,7 @@ static _GLFWfbconfig* getFBConfigs(_GLFWwindow* window, unsigned int* found) if (_glfwLibrary.GLX.majorVersion == 1 && _glfwLibrary.GLX.minorVersion < 3) { - if (!window->GLX.SGIX_fbconfig) + if (!_glfwLibrary.GLX.SGIX_fbconfig) { _glfwSetError(GLFW_OPENGL_UNAVAILABLE, "X11/GLX: GLXFBConfig support not found"); @@ -147,12 +80,12 @@ static _GLFWfbconfig* getFBConfigs(_GLFWwindow* window, unsigned int* found) } } - if (window->GLX.SGIX_fbconfig) + if (_glfwLibrary.GLX.SGIX_fbconfig) { - fbconfigs = window->GLX.ChooseFBConfigSGIX(_glfwLibrary.X11.display, - _glfwLibrary.X11.screen, - NULL, - &count); + fbconfigs = _glfwLibrary.GLX.ChooseFBConfigSGIX(_glfwLibrary.X11.display, + _glfwLibrary.X11.screen, + NULL, + &count); if (!count) { _glfwSetError(GLFW_OPENGL_UNAVAILABLE, @@ -220,7 +153,7 @@ static _GLFWfbconfig* getFBConfigs(_GLFWwindow* window, unsigned int* found) result[*found].auxBuffers = getFBConfigAttrib(window, fbconfigs[i], GLX_AUX_BUFFERS); result[*found].stereo = getFBConfigAttrib(window, fbconfigs[i], GLX_STEREO); - if (window->GLX.ARB_multisample) + if (_glfwLibrary.GLX.ARB_multisample) result[*found].samples = getFBConfigAttrib(window, fbconfigs[i], GLX_SAMPLES); else result[*found].samples = 0; @@ -258,12 +191,12 @@ static void refreshContextParams(_GLFWwindow* window, GLXFBConfigID fbconfigID) int attribs[] = { GLX_FBCONFIG_ID, fbconfigID, None }; - if (window->GLX.SGIX_fbconfig) + if (_glfwLibrary.GLX.SGIX_fbconfig) { - fbconfig = window->GLX.ChooseFBConfigSGIX(_glfwLibrary.X11.display, - _glfwLibrary.X11.screen, - attribs, - &dummy); + fbconfig = _glfwLibrary.GLX.ChooseFBConfigSGIX(_glfwLibrary.X11.display, + _glfwLibrary.X11.screen, + attribs, + &dummy); } else { @@ -304,7 +237,7 @@ static void refreshContextParams(_GLFWwindow* window, GLXFBConfigID fbconfigID) window->stereo = getFBConfigAttrib(window, *fbconfig, GLX_STEREO) ? GL_TRUE : GL_FALSE; // Get FSAA buffer sample count - if (window->GLX.ARB_multisample) + if (_glfwLibrary.GLX.ARB_multisample) window->samples = getFBConfigAttrib(window, *fbconfig, GLX_SAMPLES); else window->samples = 0; @@ -340,12 +273,12 @@ static int createContext(_GLFWwindow* window, setGLXattrib(attribs, index, GLX_FBCONFIG_ID, (int) fbconfigID); setGLXattrib(attribs, index, None, None); - if (window->GLX.SGIX_fbconfig) + if (_glfwLibrary.GLX.SGIX_fbconfig) { - fbconfig = window->GLX.ChooseFBConfigSGIX(_glfwLibrary.X11.display, - _glfwLibrary.X11.screen, - attribs, - &dummy); + fbconfig = _glfwLibrary.GLX.ChooseFBConfigSGIX(_glfwLibrary.X11.display, + _glfwLibrary.X11.screen, + attribs, + &dummy); } else { @@ -364,10 +297,10 @@ static int createContext(_GLFWwindow* window, } // Retrieve the corresponding visual - if (window->GLX.SGIX_fbconfig) + if (_glfwLibrary.GLX.SGIX_fbconfig) { - window->GLX.visual = window->GLX.GetVisualFromFBConfigSGIX(_glfwLibrary.X11.display, - *fbconfig); + window->GLX.visual = _glfwLibrary.GLX.GetVisualFromFBConfigSGIX(_glfwLibrary.X11.display, + *fbconfig); } else { @@ -384,7 +317,7 @@ static int createContext(_GLFWwindow* window, return GL_FALSE; } - if (window->GLX.ARB_create_context) + if (_glfwLibrary.GLX.ARB_create_context) { index = 0; @@ -416,7 +349,7 @@ static int createContext(_GLFWwindow* window, { int flags = 0; - if (!window->GLX.ARB_create_context_profile) + if (!_glfwLibrary.GLX.ARB_create_context_profile) { _glfwSetError(GLFW_VERSION_UNAVAILABLE, "X11/GLX: An OpenGL profile requested but " @@ -425,7 +358,7 @@ static int createContext(_GLFWwindow* window, } if (wndconfig->glProfile == GLFW_OPENGL_ES2_PROFILE && - !window->GLX.EXT_create_context_es2_profile) + !_glfwLibrary.GLX.EXT_create_context_es2_profile) { _glfwSetError(GLFW_VERSION_UNAVAILABLE, "X11/GLX: OpenGL ES 2.x profile requested but " @@ -447,7 +380,7 @@ static int createContext(_GLFWwindow* window, { int strategy; - if (!window->GLX.ARB_create_context_robustness) + if (!_glfwLibrary.GLX.ARB_create_context_robustness) { _glfwSetError(GLFW_VERSION_UNAVAILABLE, "X11/GLX: An OpenGL robustness strategy was " @@ -476,25 +409,25 @@ static int createContext(_GLFWwindow* window, XSetErrorHandler(errorHandler); window->GLX.context = - window->GLX.CreateContextAttribsARB(_glfwLibrary.X11.display, - *fbconfig, - share, - True, - attribs); + _glfwLibrary.GLX.CreateContextAttribsARB(_glfwLibrary.X11.display, + *fbconfig, + share, + True, + attribs); // We are done, so unset the error handler again (see above) XSetErrorHandler(NULL); } else { - if (window->GLX.SGIX_fbconfig) + if (_glfwLibrary.GLX.SGIX_fbconfig) { window->GLX.context = - window->GLX.CreateContextWithConfigSGIX(_glfwLibrary.X11.display, - *fbconfig, - GLX_RGBA_TYPE, - share, - True); + _glfwLibrary.GLX.CreateContextWithConfigSGIX(_glfwLibrary.X11.display, + *fbconfig, + GLX_RGBA_TYPE, + share, + True); } else { @@ -576,6 +509,65 @@ int _glfwInitOpenGL(void) return GL_FALSE; } + if (_glfwPlatformExtensionSupported("GLX_EXT_swap_control")) + { + _glfwLibrary.GLX.SwapIntervalEXT = (PFNGLXSWAPINTERVALEXTPROC) + _glfwPlatformGetProcAddress("glXSwapIntervalEXT"); + + if (_glfwLibrary.GLX.SwapIntervalEXT) + _glfwLibrary.GLX.EXT_swap_control = GL_TRUE; + } + + if (_glfwPlatformExtensionSupported("GLX_SGI_swap_control")) + { + _glfwLibrary.GLX.SwapIntervalSGI = (PFNGLXSWAPINTERVALSGIPROC) + _glfwPlatformGetProcAddress("glXSwapIntervalSGI"); + + if (_glfwLibrary.GLX.SwapIntervalSGI) + _glfwLibrary.GLX.SGI_swap_control = GL_TRUE; + } + + if (_glfwPlatformExtensionSupported("GLX_SGIX_fbconfig")) + { + _glfwLibrary.GLX.GetFBConfigAttribSGIX = (PFNGLXGETFBCONFIGATTRIBSGIXPROC) + _glfwPlatformGetProcAddress("glXGetFBConfigAttribSGIX"); + _glfwLibrary.GLX.ChooseFBConfigSGIX = (PFNGLXCHOOSEFBCONFIGSGIXPROC) + _glfwPlatformGetProcAddress("glXChooseFBConfigSGIX"); + _glfwLibrary.GLX.CreateContextWithConfigSGIX = (PFNGLXCREATECONTEXTWITHCONFIGSGIXPROC) + _glfwPlatformGetProcAddress("glXCreateContextWithConfigSGIX"); + _glfwLibrary.GLX.GetVisualFromFBConfigSGIX = (PFNGLXGETVISUALFROMFBCONFIGSGIXPROC) + _glfwPlatformGetProcAddress("glXGetVisualFromFBConfigSGIX"); + + if (_glfwLibrary.GLX.GetFBConfigAttribSGIX && + _glfwLibrary.GLX.ChooseFBConfigSGIX && + _glfwLibrary.GLX.CreateContextWithConfigSGIX && + _glfwLibrary.GLX.GetVisualFromFBConfigSGIX) + { + _glfwLibrary.GLX.SGIX_fbconfig = GL_TRUE; + } + } + + if (_glfwPlatformExtensionSupported("GLX_ARB_multisample")) + _glfwLibrary.GLX.ARB_multisample = GL_TRUE; + + if (_glfwPlatformExtensionSupported("GLX_ARB_create_context")) + { + _glfwLibrary.GLX.CreateContextAttribsARB = (PFNGLXCREATECONTEXTATTRIBSARBPROC) + _glfwPlatformGetProcAddress("glXCreateContextAttribsARB"); + + if (_glfwLibrary.GLX.CreateContextAttribsARB) + _glfwLibrary.GLX.ARB_create_context = GL_TRUE; + } + + if (_glfwPlatformExtensionSupported("GLX_ARB_create_context_robustness")) + _glfwLibrary.GLX.ARB_create_context_robustness = GL_TRUE; + + if (_glfwPlatformExtensionSupported("GLX_ARB_create_context_profile")) + _glfwLibrary.GLX.ARB_create_context_profile = GL_TRUE; + + if (_glfwPlatformExtensionSupported("GLX_EXT_create_context_es2_profile")) + _glfwLibrary.GLX.EXT_create_context_es2_profile = GL_TRUE; + return GL_TRUE; } @@ -607,8 +599,6 @@ int _glfwCreateContext(_GLFWwindow* window, { _GLFWfbconfig closest; - initGLXExtensions(window); - // Choose the best available fbconfig { unsigned int fbcount; @@ -693,14 +683,14 @@ void _glfwPlatformSwapInterval(int interval) { _GLFWwindow* window = _glfwLibrary.currentWindow; - if (window->GLX.EXT_swap_control) + if (_glfwLibrary.GLX.EXT_swap_control) { - window->GLX.SwapIntervalEXT(_glfwLibrary.X11.display, - window->X11.handle, - interval); + _glfwLibrary.GLX.SwapIntervalEXT(_glfwLibrary.X11.display, + window->X11.handle, + interval); } - else if (window->GLX.SGI_swap_control) - window->GLX.SwapIntervalSGI(interval); + else if (_glfwLibrary.GLX.SGI_swap_control) + _glfwLibrary.GLX.SwapIntervalSGI(interval); } diff --git a/src/x11_platform.h b/src/x11_platform.h index bf959f85..d45ad9a3 100644 --- a/src/x11_platform.h +++ b/src/x11_platform.h @@ -116,23 +116,6 @@ typedef struct _GLFWcontextGLX GLXContext context; // OpenGL rendering context XVisualInfo* visual; // Visual for selected GLXFBConfig - // GLX extensions - PFNGLXSWAPINTERVALSGIPROC SwapIntervalSGI; - PFNGLXSWAPINTERVALEXTPROC SwapIntervalEXT; - PFNGLXGETFBCONFIGATTRIBSGIXPROC GetFBConfigAttribSGIX; - PFNGLXCHOOSEFBCONFIGSGIXPROC ChooseFBConfigSGIX; - PFNGLXCREATECONTEXTWITHCONFIGSGIXPROC CreateContextWithConfigSGIX; - PFNGLXGETVISUALFROMFBCONFIGSGIXPROC GetVisualFromFBConfigSGIX; - PFNGLXCREATECONTEXTATTRIBSARBPROC CreateContextAttribsARB; - GLboolean SGIX_fbconfig; - GLboolean SGI_swap_control; - GLboolean EXT_swap_control; - GLboolean ARB_multisample; - GLboolean ARB_create_context; - GLboolean ARB_create_context_profile; - GLboolean ARB_create_context_robustness; - GLboolean EXT_create_context_es2_profile; - } _GLFWcontextGLX; @@ -256,6 +239,23 @@ typedef struct _GLFWlibraryGLX // Server-side GLX version int majorVersion, minorVersion; + // GLX extensions + PFNGLXSWAPINTERVALSGIPROC SwapIntervalSGI; + PFNGLXSWAPINTERVALEXTPROC SwapIntervalEXT; + PFNGLXGETFBCONFIGATTRIBSGIXPROC GetFBConfigAttribSGIX; + PFNGLXCHOOSEFBCONFIGSGIXPROC ChooseFBConfigSGIX; + PFNGLXCREATECONTEXTWITHCONFIGSGIXPROC CreateContextWithConfigSGIX; + PFNGLXGETVISUALFROMFBCONFIGSGIXPROC GetVisualFromFBConfigSGIX; + PFNGLXCREATECONTEXTATTRIBSARBPROC CreateContextAttribsARB; + GLboolean SGIX_fbconfig; + GLboolean SGI_swap_control; + GLboolean EXT_swap_control; + GLboolean ARB_multisample; + GLboolean ARB_create_context; + GLboolean ARB_create_context_profile; + GLboolean ARB_create_context_robustness; + GLboolean EXT_create_context_es2_profile; + #if defined(_GLFW_DLOPEN_LIBGL) void* libGL; // dlopen handle for libGL.so #endif From a22fbf7e9b0561e07ce6abdb1c345a3e30a1fa1d Mon Sep 17 00:00:00 2001 From: Camilla Berglund Date: Mon, 23 Apr 2012 22:31:55 +0200 Subject: [PATCH 5/5] Moved remaining X visual management into opengl module. --- src/x11_opengl.c | 16 ++++++++++++++++ src/x11_platform.h | 1 + src/x11_window.c | 13 ++++--------- 3 files changed, 21 insertions(+), 9 deletions(-) diff --git a/src/x11_opengl.c b/src/x11_opengl.c index 5ec47ee5..35dc6d0f 100644 --- a/src/x11_opengl.c +++ b/src/x11_opengl.c @@ -637,6 +637,12 @@ int _glfwCreateContext(_GLFWwindow* window, void _glfwDestroyContext(_GLFWwindow* window) { + if (window->GLX.visual) + { + XFree(window->GLX.visual); + window->GLX.visual = NULL; + } + if (window->GLX.context) { // Release and destroy the context @@ -647,6 +653,16 @@ void _glfwDestroyContext(_GLFWwindow* window) } +//======================================================================== +// Return the X visual associated with the specified context +//======================================================================== + +XVisualInfo* _glfwGetContextVisual(_GLFWwindow* window) +{ + return window->GLX.visual; +} + + //======================================================================== // Make the OpenGL context associated with the specified window current //======================================================================== diff --git a/src/x11_platform.h b/src/x11_platform.h index d45ad9a3..4d432f80 100644 --- a/src/x11_platform.h +++ b/src/x11_platform.h @@ -289,6 +289,7 @@ int _glfwCreateContext(_GLFWwindow* window, const _GLFWwndconfig* wndconfig, const _GLFWfbconfig* fbconfig); void _glfwDestroyContext(_GLFWwindow* window); +XVisualInfo* _glfwGetContextVisual(_GLFWwindow* window); // Fullscreen support int _glfwGetClosestVideoMode(int* width, int* height, int* rate); diff --git a/src/x11_window.c b/src/x11_window.c index a5e7b0d8..9ec54493 100644 --- a/src/x11_window.c +++ b/src/x11_window.c @@ -97,13 +97,14 @@ static GLboolean createWindow(_GLFWwindow* window, XEvent event; unsigned long wamask; XSetWindowAttributes wa; + XVisualInfo* visual = _glfwGetContextVisual(window); // Every window needs a colormap // Create one based on the visual used by the current context window->X11.colormap = XCreateColormap(_glfwLibrary.X11.display, _glfwLibrary.X11.root, - window->GLX.visual->visual, + visual->visual, AllocNone); // Create the actual window @@ -133,9 +134,9 @@ static GLboolean createWindow(_GLFWwindow* window, 0, 0, // Upper left corner of this window on root window->width, window->height, 0, // Border width - window->GLX.visual->depth, // Color depth + visual->depth, // Color depth InputOutput, - window->GLX.visual->visual, + visual->visual, wamask, &wa ); @@ -979,12 +980,6 @@ void _glfwPlatformCloseWindow(_GLFWwindow* window) _glfwDestroyContext(window); - if (window->GLX.visual) - { - XFree(window->GLX.visual); - window->GLX.visual = NULL; - } - if (window->X11.handle) { XUnmapWindow(_glfwLibrary.X11.display, window->X11.handle);