diff --git a/src/context.c b/src/context.c index d8f1a46f..438d8201 100644 --- a/src/context.c +++ b/src/context.c @@ -92,169 +92,6 @@ static GLboolean parseGLVersion(int* api, int* major, int* minor, int* rev) ////// GLFW internal API ////// ////////////////////////////////////////////////////////////////////////// -//======================================================================== -// Return the available framebuffer config closest to the desired values -// This is based on the manual GLX Visual selection from 2.6 -//======================================================================== - -const _GLFWfbconfig* _glfwChooseFBConfig(const _GLFWfbconfig* desired, - const _GLFWfbconfig* alternatives, - unsigned int count) -{ - unsigned int i; - unsigned int missing, leastMissing = UINT_MAX; - unsigned int colorDiff, leastColorDiff = UINT_MAX; - unsigned int extraDiff, leastExtraDiff = UINT_MAX; - const _GLFWfbconfig* current; - const _GLFWfbconfig* closest = NULL; - - for (i = 0; i < count; i++) - { - current = alternatives + i; - - if (desired->stereo > 0 && current->stereo == 0) - { - // Stereo is a hard constraint - continue; - } - - // Count number of missing buffers - { - missing = 0; - - if (desired->alphaBits > 0 && current->alphaBits == 0) - missing++; - - if (desired->depthBits > 0 && current->depthBits == 0) - missing++; - - if (desired->stencilBits > 0 && current->stencilBits == 0) - missing++; - - if (desired->auxBuffers > 0 && current->auxBuffers < desired->auxBuffers) - missing += desired->auxBuffers - current->auxBuffers; - - if (desired->samples > 0 && current->samples == 0) - { - // Technically, several multisampling buffers could be - // involved, but that's a lower level implementation detail and - // not important to us here, so we count them as one - missing++; - } - } - - // These polynomials make many small channel size differences matter - // less than one large channel size difference - - // Calculate color channel size difference value - { - colorDiff = 0; - - if (desired->redBits > 0) - { - colorDiff += (desired->redBits - current->redBits) * - (desired->redBits - current->redBits); - } - - if (desired->greenBits > 0) - { - colorDiff += (desired->greenBits - current->greenBits) * - (desired->greenBits - current->greenBits); - } - - if (desired->blueBits > 0) - { - colorDiff += (desired->blueBits - current->blueBits) * - (desired->blueBits - current->blueBits); - } - } - - // Calculate non-color channel size difference value - { - extraDiff = 0; - - if (desired->alphaBits > 0) - { - extraDiff += (desired->alphaBits - current->alphaBits) * - (desired->alphaBits - current->alphaBits); - } - - if (desired->depthBits > 0) - { - extraDiff += (desired->depthBits - current->depthBits) * - (desired->depthBits - current->depthBits); - } - - if (desired->stencilBits > 0) - { - extraDiff += (desired->stencilBits - current->stencilBits) * - (desired->stencilBits - current->stencilBits); - } - - if (desired->accumRedBits > 0) - { - extraDiff += (desired->accumRedBits - current->accumRedBits) * - (desired->accumRedBits - current->accumRedBits); - } - - if (desired->accumGreenBits > 0) - { - extraDiff += (desired->accumGreenBits - current->accumGreenBits) * - (desired->accumGreenBits - current->accumGreenBits); - } - - if (desired->accumBlueBits > 0) - { - extraDiff += (desired->accumBlueBits - current->accumBlueBits) * - (desired->accumBlueBits - current->accumBlueBits); - } - - if (desired->accumAlphaBits > 0) - { - extraDiff += (desired->accumAlphaBits - current->accumAlphaBits) * - (desired->accumAlphaBits - current->accumAlphaBits); - } - - if (desired->samples > 0) - { - extraDiff += (desired->samples - current->samples) * - (desired->samples - current->samples); - } - - if (desired->sRGB) - { - if (!current->sRGB) - extraDiff++; - } - } - - // Figure out if the current one is better than the best one found so far - // Least number of missing buffers is the most important heuristic, - // then color buffer size match and lastly size match for other buffers - - if (missing < leastMissing) - closest = current; - else if (missing == leastMissing) - { - if ((colorDiff < leastColorDiff) || - (colorDiff == leastColorDiff && extraDiff < leastExtraDiff)) - { - closest = current; - } - } - - if (current == closest) - { - leastMissing = missing; - leastColorDiff = colorDiff; - leastExtraDiff = extraDiff; - } - } - - return closest; -} - - //======================================================================== // Checks whether the client API part of the window config is sane //======================================================================== diff --git a/src/egl_context.c b/src/egl_context.c index eb2815f1..34c1f2f8 100644 --- a/src/egl_context.c +++ b/src/egl_context.c @@ -32,6 +32,7 @@ #include #include +#include //======================================================================== @@ -52,139 +53,62 @@ static _GLFW_TLS _GLFWwindow* _glfwCurrentWindow = NULL; -//======================================================================== -// Returns the specified attribute of the specified EGLConfig -//======================================================================== - -static int getConfigAttrib(EGLConfig config, int attrib) -{ - int value; - eglGetConfigAttrib(_glfw.egl.display, config, attrib, &value); - return value; -} - +////////////////////////////////////////////////////////////////////////// +////// GLFW internal API ////// +////////////////////////////////////////////////////////////////////////// //======================================================================== -// Return a list of available and usable framebuffer configs +// Initialize EGL //======================================================================== -static _GLFWfbconfig* getFBConfigs(_GLFWwindow* window, - const _GLFWwndconfig* wndconfig, - unsigned int* found) +int _glfwInitOpenGL(void) { - EGLConfig* configs; - _GLFWfbconfig* result; - int i, count = 0; - - *found = 0; - - eglGetConfigs(_glfw.egl.display, NULL, 0, &count); - - configs = (EGLConfig*) malloc(sizeof(EGLConfig) * count); - if (!configs) - { - _glfwInputError(GLFW_OUT_OF_MEMORY, NULL); - return NULL; - } - - eglGetConfigs(_glfw.egl.display, configs, count, &count); - if (!count) + _glfw.egl.display = eglGetDisplay(_GLFW_EGL_NATIVE_DISPLAY); + if (_glfw.egl.display == EGL_NO_DISPLAY) { - free(configs); - - _glfwInputError(GLFW_API_UNAVAILABLE, "EGL: No EGLConfigs returned"); - return NULL; + _glfwInputError(GLFW_API_UNAVAILABLE, "EGL: Failed to get EGL display"); + return GL_FALSE; } - result = (_GLFWfbconfig*) malloc(sizeof(_GLFWfbconfig) * count); - if (!result) + if (!eglInitialize(_glfw.egl.display, + &_glfw.egl.versionMajor, + &_glfw.egl.versionMinor)) { - free(configs); - - _glfwInputError(GLFW_OUT_OF_MEMORY, NULL); - return NULL; + _glfwInputError(GLFW_API_UNAVAILABLE, "EGL: Failed to initialize EGL"); + return GL_FALSE; } - for (i = 0; i < count; i++) - { - _GLFWfbconfig* f = result + *found; - -#if defined(_GLFW_X11) - if (!getConfigAttrib(configs[i], EGL_NATIVE_VISUAL_ID)) - { - // Only consider EGLConfigs with associated visuals - continue; - } -#endif // _GLFW_X11 - - if (!(getConfigAttrib(configs[i], EGL_COLOR_BUFFER_TYPE) & EGL_RGB_BUFFER)) - { - // Only consider RGB(A) EGLConfigs - continue; - } - - if (!(getConfigAttrib(configs[i], EGL_SURFACE_TYPE) & EGL_WINDOW_BIT)) - { - // Only consider window EGLConfigs - continue; - } - - if (wndconfig->clientAPI == GLFW_OPENGL_ES_API) - { - if (wndconfig->glMajor == 1) - { - if (!(getConfigAttrib(configs[i], EGL_RENDERABLE_TYPE) & EGL_OPENGL_ES_BIT)) - continue; - } - else - { - if (!(getConfigAttrib(configs[i], EGL_RENDERABLE_TYPE) & EGL_OPENGL_ES2_BIT)) - continue; - } - } - else if (wndconfig->clientAPI == GLFW_OPENGL_API) - { - if (!(getConfigAttrib(configs[i], EGL_RENDERABLE_TYPE) & EGL_OPENGL_BIT)) - continue; - } - - f->redBits = getConfigAttrib(configs[i], EGL_RED_SIZE); - f->greenBits = getConfigAttrib(configs[i], EGL_GREEN_SIZE); - f->blueBits = getConfigAttrib(configs[i], EGL_BLUE_SIZE); - - f->alphaBits = getConfigAttrib(configs[i], EGL_ALPHA_SIZE); - f->depthBits = getConfigAttrib(configs[i], EGL_DEPTH_SIZE); - f->stencilBits = getConfigAttrib(configs[i], EGL_STENCIL_SIZE); - - f->samples = getConfigAttrib(configs[i], EGL_SAMPLES); + if (_glfwPlatformExtensionSupported("EGL_KHR_create_context")) + _glfw.egl.KHR_create_context = GL_TRUE; - // NOTE: There does not appear to be any way to request sRGB - // framebuffers for OpenGL or GLES contexts; only for OpenVG ones - f->sRGB = GL_FALSE; + return GL_TRUE; +} - f->platformID = (GLFWintptr) getConfigAttrib(configs[i], EGL_CONFIG_ID); - (*found)++; - } +//======================================================================== +// Terminate EGL +//======================================================================== - free(configs); - return result; +void _glfwTerminateOpenGL(void) +{ + eglTerminate(_glfw.egl.display); } //======================================================================== -// Create the actual OpenGL(|ES) context +// Prepare for creation of the OpenGL context //======================================================================== #define setEGLattrib(attribName, attribValue) \ { \ attribs[index++] = attribName; \ attribs[index++] = attribValue; \ + assert(index < sizeof(attribs) / sizeof(attribs[0])); \ } -static int createContext(_GLFWwindow* window, - const _GLFWwndconfig* wndconfig, - EGLint fbconfigID) +int _glfwCreateContext(_GLFWwindow* window, + const _GLFWwndconfig* wndconfig, + const _GLFWfbconfig* fbconfig) { int attribs[40]; EGLint count; @@ -198,7 +122,28 @@ static int createContext(_GLFWwindow* window, { int index = 0; - setEGLattrib(EGL_CONFIG_ID, fbconfigID); + setEGLattrib(EGL_COLOR_BUFFER_TYPE, EGL_RGB_BUFFER); + + if (fbconfig->redBits) + setEGLattrib(EGL_RED_SIZE, fbconfig->redBits); + if (fbconfig->greenBits) + setEGLattrib(EGL_GREEN_SIZE, fbconfig->greenBits); + if (fbconfig->blueBits) + setEGLattrib(EGL_BLUE_SIZE, fbconfig->blueBits); + if (fbconfig->alphaBits) + setEGLattrib(EGL_BLUE_SIZE, fbconfig->alphaBits); + + if (fbconfig->depthBits) + setEGLattrib(EGL_DEPTH_SIZE, fbconfig->depthBits); + if (fbconfig->stencilBits) + setEGLattrib(EGL_STENCIL_SIZE, fbconfig->stencilBits); + + if (fbconfig->samples) + { + setEGLattrib(EGL_SAMPLE_BUFFERS, 1); + setEGLattrib(EGL_SAMPLES, fbconfig->samples); + } + setEGLattrib(EGL_NONE, EGL_NONE); eglChooseConfig(_glfw.egl.display, attribs, &config, 1, &count); @@ -351,90 +296,6 @@ static int createContext(_GLFWwindow* window, #undef setEGLattrib -////////////////////////////////////////////////////////////////////////// -////// GLFW internal API ////// -////////////////////////////////////////////////////////////////////////// - -//======================================================================== -// Initialize EGL -//======================================================================== - -int _glfwInitOpenGL(void) -{ - _glfw.egl.display = eglGetDisplay(_GLFW_EGL_NATIVE_DISPLAY); - if (_glfw.egl.display == EGL_NO_DISPLAY) - { - _glfwInputError(GLFW_API_UNAVAILABLE, "EGL: Failed to get EGL display"); - return GL_FALSE; - } - - if (!eglInitialize(_glfw.egl.display, - &_glfw.egl.versionMajor, - &_glfw.egl.versionMinor)) - { - _glfwInputError(GLFW_API_UNAVAILABLE, "EGL: Failed to initialize EGL"); - return GL_FALSE; - } - - if (_glfwPlatformExtensionSupported("EGL_KHR_create_context")) - _glfw.egl.KHR_create_context = GL_TRUE; - - return GL_TRUE; -} - - -//======================================================================== -// Terminate EGL -//======================================================================== - -void _glfwTerminateOpenGL(void) -{ - eglTerminate(_glfw.egl.display); -} - - -//======================================================================== -// Prepare for creation of the OpenGL context -//======================================================================== - -int _glfwCreateContext(_GLFWwindow* window, - const _GLFWwndconfig* wndconfig, - const _GLFWfbconfig* fbconfig) -{ - _GLFWfbconfig closest; - - // Choose the best available fbconfig - { - unsigned int fbcount; - _GLFWfbconfig* fbconfigs; - const _GLFWfbconfig* result; - - fbconfigs = getFBConfigs(window, wndconfig, &fbcount); - if (!fbconfigs) - { - _glfwInputError(GLFW_PLATFORM_ERROR, - "EGL: No usable EGLFBConfigs found"); - return GL_FALSE; - } - - result = _glfwChooseFBConfig(fbconfig, fbconfigs, fbcount); - if (!result) - { - _glfwInputError(GLFW_PLATFORM_ERROR, - "EGL: No EGLFBConfig matched the criteria"); - - free(fbconfigs); - return GL_FALSE; - } - - closest = *result; - free(fbconfigs); - } - - return createContext(window, wndconfig, closest.platformID); -} - - //======================================================================== // Destroy the OpenGL context //======================================================================== diff --git a/src/glx_context.c b/src/glx_context.c index 8021e050..7b57f632 100644 --- a/src/glx_context.c +++ b/src/glx_context.c @@ -32,6 +32,7 @@ #include #include +#include // This is the only glXGetProcAddress variant not declared by glxext.h @@ -66,241 +67,283 @@ static _GLFW_TLS _GLFWwindow* _glfwCurrentWindow = NULL; //======================================================================== -// Returns the specified attribute of the specified GLXFBConfig -// NOTE: Do not call this unless we have found GLX 1.3+ or GLX_SGIX_fbconfig +// Error handler used when creating a context with the GLX_ARB_create_context +// extension set //======================================================================== -static int getFBConfigAttrib(_GLFWwindow* window, GLXFBConfig fbconfig, int attrib) +static int errorHandler(Display *display, XErrorEvent* event) { - int value; + _glfwErrorCode = event->error_code; + return 0; +} + + +//======================================================================== +// Create the OpenGL context using legacy API +//======================================================================== +static GLXContext createLegacyContext(_GLFWwindow* window, + GLXFBConfig fbconfig, + GLXContext share) +{ if (_glfw.glx.SGIX_fbconfig) { - _glfw.glx.GetFBConfigAttribSGIX(_glfw.x11.display, - fbconfig, attrib, &value); + return _glfw.glx.CreateContextWithConfigSGIX(_glfw.x11.display, + fbconfig, + GLX_RGBA_TYPE, + share, + True); } else - glXGetFBConfigAttrib(_glfw.x11.display, fbconfig, attrib, &value); - - return value; + { + return glXCreateNewContext(_glfw.x11.display, + fbconfig, + GLX_RGBA_TYPE, + share, + True); + } } +////////////////////////////////////////////////////////////////////////// +////// GLFW internal API ////// +////////////////////////////////////////////////////////////////////////// + //======================================================================== -// Return a list of available and usable framebuffer configs +// Initialize GLX //======================================================================== -static _GLFWfbconfig* getFBConfigs(_GLFWwindow* window, unsigned int* found) +int _glfwInitOpenGL(void) { - GLXFBConfig* fbconfigs; - _GLFWfbconfig* result; - int i, count = 0; - const char* vendor; - GLboolean trustWindowBit = GL_TRUE; - - *found = 0; +#ifdef _GLFW_DLOPEN_LIBGL + int i; + char* libGL_names[ ] = + { + "libGL.so", + "libGL.so.1", + "/usr/lib/libGL.so", + "/usr/lib/libGL.so.1", + NULL + }; - if (_glfw.glx.versionMajor == 1 && _glfw.glx.versionMinor < 3) + for (i = 0; libGL_names[i] != NULL; i++) { - if (!_glfw.glx.SGIX_fbconfig) - { - _glfwInputError(GLFW_API_UNAVAILABLE, - "GLX: GLXFBConfig support not found"); - return NULL; - } + _glfw.glx.libGL = dlopen(libGL_names[i], RTLD_LAZY | RTLD_GLOBAL); + if (_glfw.glx.libGL) + break; } - vendor = glXGetClientString(_glfw.x11.display, GLX_VENDOR); + if (!_glfw.glx.libGL) + { + _glfwInputError(GLFW_PLATFORM_ERROR, "GLX: Failed to find libGL"); + return GL_FALSE; + } +#endif - if (strcmp(vendor, "Chromium") == 0) + // Check if GLX is supported on this display + if (!glXQueryExtension(_glfw.x11.display, + &_glfw.glx.errorBase, + &_glfw.glx.eventBase)) { - // HACK: This is a (hopefully temporary) workaround for Chromium - // (VirtualBox GL) not setting the window bit on any GLXFBConfigs - trustWindowBit = GL_FALSE; + _glfwInputError(GLFW_API_UNAVAILABLE, "GLX: GLX support not found"); + return GL_FALSE; } - if (_glfw.glx.SGIX_fbconfig) + if (!glXQueryVersion(_glfw.x11.display, + &_glfw.glx.versionMajor, + &_glfw.glx.versionMinor)) { - fbconfigs = _glfw.glx.ChooseFBConfigSGIX(_glfw.x11.display, - _glfw.x11.screen, - NULL, - &count); - if (!count) - { - _glfwInputError(GLFW_API_UNAVAILABLE, - "GLX: No GLXFBConfigs returned"); - return NULL; - } + _glfwInputError(GLFW_API_UNAVAILABLE, + "GLX: Failed to query GLX version"); + return GL_FALSE; } - else + + if (_glfwPlatformExtensionSupported("GLX_EXT_swap_control")) { - fbconfigs = glXGetFBConfigs(_glfw.x11.display, _glfw.x11.screen, &count); - if (!count) - { - _glfwInputError(GLFW_API_UNAVAILABLE, - "GLX: No GLXFBConfigs returned"); - return NULL; - } + _glfw.glx.SwapIntervalEXT = (PFNGLXSWAPINTERVALEXTPROC) + _glfwPlatformGetProcAddress("glXSwapIntervalEXT"); + + if (_glfw.glx.SwapIntervalEXT) + _glfw.glx.EXT_swap_control = GL_TRUE; } - result = (_GLFWfbconfig*) malloc(sizeof(_GLFWfbconfig) * count); - if (!result) + if (_glfwPlatformExtensionSupported("GLX_SGI_swap_control")) { - _glfwInputError(GLFW_OUT_OF_MEMORY, NULL); - return NULL; + _glfw.glx.SwapIntervalSGI = (PFNGLXSWAPINTERVALSGIPROC) + _glfwPlatformGetProcAddress("glXSwapIntervalSGI"); + + if (_glfw.glx.SwapIntervalSGI) + _glfw.glx.SGI_swap_control = GL_TRUE; } - for (i = 0; i < count; i++) + if (_glfwPlatformExtensionSupported("GLX_MESA_swap_control")) { - _GLFWfbconfig* f = result + *found; + _glfw.glx.SwapIntervalMESA = (PFNGLXSWAPINTERVALMESAPROC) + _glfwPlatformGetProcAddress("glXSwapIntervalMESA"); - if (!getFBConfigAttrib(window, fbconfigs[i], GLX_DOUBLEBUFFER) || - !getFBConfigAttrib(window, fbconfigs[i], GLX_VISUAL_ID)) - { - // Only consider double-buffered GLXFBConfigs with associated visuals - continue; - } + if (_glfw.glx.SwapIntervalMESA) + _glfw.glx.MESA_swap_control = GL_TRUE; + } - if (!(getFBConfigAttrib(window, - fbconfigs[i], - GLX_RENDER_TYPE) & GLX_RGBA_BIT)) - { - // Only consider RGBA GLXFBConfigs - continue; - } + if (_glfwPlatformExtensionSupported("GLX_SGIX_fbconfig")) + { + _glfw.glx.GetFBConfigAttribSGIX = (PFNGLXGETFBCONFIGATTRIBSGIXPROC) + _glfwPlatformGetProcAddress("glXGetFBConfigAttribSGIX"); + _glfw.glx.ChooseFBConfigSGIX = (PFNGLXCHOOSEFBCONFIGSGIXPROC) + _glfwPlatformGetProcAddress("glXChooseFBConfigSGIX"); + _glfw.glx.CreateContextWithConfigSGIX = (PFNGLXCREATECONTEXTWITHCONFIGSGIXPROC) + _glfwPlatformGetProcAddress("glXCreateContextWithConfigSGIX"); + _glfw.glx.GetVisualFromFBConfigSGIX = (PFNGLXGETVISUALFROMFBCONFIGSGIXPROC) + _glfwPlatformGetProcAddress("glXGetVisualFromFBConfigSGIX"); - if (!(getFBConfigAttrib(window, fbconfigs[i], GLX_DRAWABLE_TYPE) & GLX_WINDOW_BIT)) + if (_glfw.glx.GetFBConfigAttribSGIX && + _glfw.glx.ChooseFBConfigSGIX && + _glfw.glx.CreateContextWithConfigSGIX && + _glfw.glx.GetVisualFromFBConfigSGIX) { - if (trustWindowBit) - { - // Only consider window GLXFBConfigs - continue; - } + _glfw.glx.SGIX_fbconfig = GL_TRUE; } + } - f->redBits = getFBConfigAttrib(window, fbconfigs[i], GLX_RED_SIZE); - f->greenBits = getFBConfigAttrib(window, fbconfigs[i], GLX_GREEN_SIZE); - f->blueBits = getFBConfigAttrib(window, fbconfigs[i], GLX_BLUE_SIZE); - - f->alphaBits = getFBConfigAttrib(window, fbconfigs[i], GLX_ALPHA_SIZE); - f->depthBits = getFBConfigAttrib(window, fbconfigs[i], GLX_DEPTH_SIZE); - f->stencilBits = getFBConfigAttrib(window, fbconfigs[i], GLX_STENCIL_SIZE); - - f->accumRedBits = getFBConfigAttrib(window, fbconfigs[i], GLX_ACCUM_RED_SIZE); - f->accumGreenBits = getFBConfigAttrib(window, fbconfigs[i], GLX_ACCUM_GREEN_SIZE); - f->accumBlueBits = getFBConfigAttrib(window, fbconfigs[i], GLX_ACCUM_BLUE_SIZE); - f->accumAlphaBits = getFBConfigAttrib(window, fbconfigs[i], GLX_ACCUM_ALPHA_SIZE); - - f->auxBuffers = getFBConfigAttrib(window, fbconfigs[i], GLX_AUX_BUFFERS); - f->stereo = getFBConfigAttrib(window, fbconfigs[i], GLX_STEREO); - - if (_glfw.glx.ARB_multisample) - f->samples = getFBConfigAttrib(window, fbconfigs[i], GLX_SAMPLES); - else - f->samples = 0; + if (_glfwPlatformExtensionSupported("GLX_ARB_multisample")) + _glfw.glx.ARB_multisample = GL_TRUE; - if (_glfw.glx.ARB_framebuffer_sRGB) - f->sRGB = getFBConfigAttrib(window, fbconfigs[i], GLX_FRAMEBUFFER_SRGB_CAPABLE_ARB); - else - f->sRGB = GL_FALSE; + if (_glfwPlatformExtensionSupported("GLX_ARB_framebuffer_sRGB")) + _glfw.glx.ARB_framebuffer_sRGB = GL_TRUE; - f->platformID = (GLFWintptr) getFBConfigAttrib(window, fbconfigs[i], GLX_FBCONFIG_ID); + if (_glfwPlatformExtensionSupported("GLX_ARB_create_context")) + { + _glfw.glx.CreateContextAttribsARB = (PFNGLXCREATECONTEXTATTRIBSARBPROC) + _glfwPlatformGetProcAddress("glXCreateContextAttribsARB"); - (*found)++; + if (_glfw.glx.CreateContextAttribsARB) + _glfw.glx.ARB_create_context = GL_TRUE; } - XFree(fbconfigs); - - return result; -} + if (_glfwPlatformExtensionSupported("GLX_ARB_create_context_robustness")) + _glfw.glx.ARB_create_context_robustness = GL_TRUE; + if (_glfwPlatformExtensionSupported("GLX_ARB_create_context_profile")) + _glfw.glx.ARB_create_context_profile = GL_TRUE; -//======================================================================== -// Error handler used when creating a context with the GLX_ARB_create_context -// extension set -//======================================================================== + if (_glfwPlatformExtensionSupported("GLX_EXT_create_context_es2_profile")) + _glfw.glx.EXT_create_context_es2_profile = GL_TRUE; -static int errorHandler(Display *display, XErrorEvent* event) -{ - _glfwErrorCode = event->error_code; - return 0; + return GL_TRUE; } //======================================================================== -// Create the OpenGL context using legacy API +// Terminate GLX //======================================================================== -static void createLegacyContext(_GLFWwindow* window, - const _GLFWwndconfig* wndconfig, - GLXFBConfig fbconfig, - GLXContext share) +void _glfwTerminateOpenGL(void) { - if (_glfw.glx.SGIX_fbconfig) - { - window->glx.context = - _glfw.glx.CreateContextWithConfigSGIX(_glfw.x11.display, - fbconfig, - GLX_RGBA_TYPE, - share, - True); - } - else + // Unload libGL.so if necessary +#ifdef _GLFW_DLOPEN_LIBGL + if (_glfw.glx.libGL != NULL) { - window->glx.context = glXCreateNewContext(_glfw.x11.display, - fbconfig, - GLX_RGBA_TYPE, - share, - True); + dlclose(_glfw.glx.libGL); + _glfw.glx.libGL = NULL; } +#endif } //======================================================================== -// Create the OpenGL context +// Prepare for creation of the OpenGL context //======================================================================== #define setGLXattrib(attribName, attribValue) \ +{ \ attribs[index++] = attribName; \ - attribs[index++] = attribValue; + attribs[index++] = attribValue; \ + assert(index < sizeof(attribs) / sizeof(attribs[0])); \ +} -static int createContext(_GLFWwindow* window, - const _GLFWwndconfig* wndconfig, - GLXFBConfigID fbconfigID) +int _glfwCreateContext(_GLFWwindow* window, + const _GLFWwndconfig* wndconfig, + const _GLFWfbconfig* fbconfig) { int attribs[40]; - GLXFBConfig* fbconfig; + GLXFBConfig* native; GLXContext share = NULL; if (wndconfig->share) share = wndconfig->share->glx.context; - // Retrieve the previously selected GLXFBConfig + // Find a suitable GLXFBConfig { - int dummy, index = 0; + int count, index = 0; + + setGLXattrib(GLX_DOUBLEBUFFER, True); + setGLXattrib(GLX_X_RENDERABLE, True); + + if (fbconfig->redBits) + setGLXattrib(GLX_RED_SIZE, fbconfig->redBits); + if (fbconfig->greenBits) + setGLXattrib(GLX_GREEN_SIZE, fbconfig->greenBits); + if (fbconfig->blueBits) + setGLXattrib(GLX_BLUE_SIZE, fbconfig->blueBits); + if (fbconfig->alphaBits) + setGLXattrib(GLX_BLUE_SIZE, fbconfig->alphaBits); + + if (fbconfig->depthBits) + setGLXattrib(GLX_DEPTH_SIZE, fbconfig->depthBits); + if (fbconfig->stencilBits) + setGLXattrib(GLX_STENCIL_SIZE, fbconfig->stencilBits); + + if (fbconfig->auxBuffers) + setGLXattrib(GLX_AUX_BUFFERS, fbconfig->auxBuffers); + + if (fbconfig->accumRedBits) + setGLXattrib(GLX_ACCUM_RED_SIZE, fbconfig->accumRedBits); + if (fbconfig->accumGreenBits) + setGLXattrib(GLX_ACCUM_GREEN_SIZE, fbconfig->accumGreenBits); + if (fbconfig->accumBlueBits) + setGLXattrib(GLX_ACCUM_BLUE_SIZE, fbconfig->accumBlueBits); + if (fbconfig->accumAlphaBits) + setGLXattrib(GLX_ACCUM_BLUE_SIZE, fbconfig->accumAlphaBits); + + if (fbconfig->stereo) + setGLXattrib(GLX_STEREO, True); + + if (_glfw.glx.ARB_multisample) + { + if (fbconfig->samples) + { + setGLXattrib(GLX_SAMPLE_BUFFERS_ARB, 1); + setGLXattrib(GLX_SAMPLES_ARB, fbconfig->samples); + } + } + + if (_glfw.glx.ARB_framebuffer_sRGB) + { + if (fbconfig->sRGB) + setGLXattrib(GLX_FRAMEBUFFER_SRGB_CAPABLE_ARB, True); + } - setGLXattrib(GLX_FBCONFIG_ID, (int) fbconfigID); setGLXattrib(None, None); if (_glfw.glx.SGIX_fbconfig) { - fbconfig = _glfw.glx.ChooseFBConfigSGIX(_glfw.x11.display, - _glfw.x11.screen, - attribs, - &dummy); + native = _glfw.glx.ChooseFBConfigSGIX(_glfw.x11.display, + _glfw.x11.screen, + attribs, + &count); } else { - fbconfig = glXChooseFBConfig(_glfw.x11.display, - _glfw.x11.screen, - attribs, - &dummy); + native = glXChooseFBConfig(_glfw.x11.display, + _glfw.x11.screen, + attribs, + &count); } - if (fbconfig == NULL) + if (native == NULL) { _glfwInputError(GLFW_PLATFORM_ERROR, - "GLX: Failed to retrieve the selected GLXFBConfig"); + "GLX: Failed to find a suitable GLXFBConfig"); return GL_FALSE; } } @@ -309,17 +352,17 @@ static int createContext(_GLFWwindow* window, if (_glfw.glx.SGIX_fbconfig) { window->glx.visual = - _glfw.glx.GetVisualFromFBConfigSGIX(_glfw.x11.display, *fbconfig); + _glfw.glx.GetVisualFromFBConfigSGIX(_glfw.x11.display, *native); } else { window->glx.visual = glXGetVisualFromFBConfig(_glfw.x11.display, - *fbconfig); + *native); } if (window->glx.visual == NULL) { - XFree(fbconfig); + XFree(native); _glfwInputError(GLFW_PLATFORM_ERROR, "GLX: Failed to retrieve visual for GLXFBConfig"); @@ -332,6 +375,8 @@ static int createContext(_GLFWwindow* window, !_glfw.glx.ARB_create_context_profile || !_glfw.glx.EXT_create_context_es2_profile) { + XFree(native); + _glfwInputError(GLFW_VERSION_UNAVAILABLE, "GLX: OpenGL ES requested but " "GLX_EXT_create_context_es2_profile is unavailable"); @@ -343,6 +388,8 @@ static int createContext(_GLFWwindow* window, { if (!_glfw.glx.ARB_create_context) { + XFree(native); + _glfwInputError(GLFW_VERSION_UNAVAILABLE, "GLX: Forward compatibility requested but " "GLX_ARB_create_context_profile is unavailable"); @@ -355,6 +402,8 @@ static int createContext(_GLFWwindow* window, if (!_glfw.glx.ARB_create_context || !_glfw.glx.ARB_create_context_profile) { + XFree(native); + _glfwInputError(GLFW_VERSION_UNAVAILABLE, "GLX: An OpenGL profile requested but " "GLX_ARB_create_context_profile is unavailable"); @@ -428,7 +477,7 @@ static int createContext(_GLFWwindow* window, window->glx.context = _glfw.glx.CreateContextAttribsARB(_glfw.x11.display, - *fbconfig, + *native, share, True, attribs); @@ -446,14 +495,14 @@ static int createContext(_GLFWwindow* window, wndconfig->glProfile == GLFW_OPENGL_NO_PROFILE && wndconfig->glForward == GL_FALSE) { - createLegacyContext(window, wndconfig, *fbconfig, share); + window->glx.context = createLegacyContext(window, *native, share); } } } else - createLegacyContext(window, wndconfig, *fbconfig, share); + window->glx.context = createLegacyContext(window, *native, share); - XFree(fbconfig); + XFree(native); if (window->glx.context == NULL) { @@ -467,189 +516,6 @@ static int createContext(_GLFWwindow* window, #undef setGLXattrib -////////////////////////////////////////////////////////////////////////// -////// 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++) - { - _glfw.glx.libGL = dlopen(libGL_names[i], RTLD_LAZY | RTLD_GLOBAL); - if (_glfw.glx.libGL) - break; - } - - if (!_glfw.glx.libGL) - { - _glfwInputError(GLFW_PLATFORM_ERROR, "GLX: Failed to find libGL"); - return GL_FALSE; - } -#endif - - // Check if GLX is supported on this display - if (!glXQueryExtension(_glfw.x11.display, - &_glfw.glx.errorBase, - &_glfw.glx.eventBase)) - { - _glfwInputError(GLFW_API_UNAVAILABLE, "GLX: GLX support not found"); - return GL_FALSE; - } - - if (!glXQueryVersion(_glfw.x11.display, - &_glfw.glx.versionMajor, - &_glfw.glx.versionMinor)) - { - _glfwInputError(GLFW_API_UNAVAILABLE, - "GLX: Failed to query GLX version"); - return GL_FALSE; - } - - if (_glfwPlatformExtensionSupported("GLX_EXT_swap_control")) - { - _glfw.glx.SwapIntervalEXT = (PFNGLXSWAPINTERVALEXTPROC) - _glfwPlatformGetProcAddress("glXSwapIntervalEXT"); - - if (_glfw.glx.SwapIntervalEXT) - _glfw.glx.EXT_swap_control = GL_TRUE; - } - - if (_glfwPlatformExtensionSupported("GLX_SGI_swap_control")) - { - _glfw.glx.SwapIntervalSGI = (PFNGLXSWAPINTERVALSGIPROC) - _glfwPlatformGetProcAddress("glXSwapIntervalSGI"); - - if (_glfw.glx.SwapIntervalSGI) - _glfw.glx.SGI_swap_control = GL_TRUE; - } - - if (_glfwPlatformExtensionSupported("GLX_MESA_swap_control")) - { - _glfw.glx.SwapIntervalMESA = (PFNGLXSWAPINTERVALMESAPROC) - _glfwPlatformGetProcAddress("glXSwapIntervalMESA"); - - if (_glfw.glx.SwapIntervalMESA) - _glfw.glx.MESA_swap_control = GL_TRUE; - } - - if (_glfwPlatformExtensionSupported("GLX_SGIX_fbconfig")) - { - _glfw.glx.GetFBConfigAttribSGIX = (PFNGLXGETFBCONFIGATTRIBSGIXPROC) - _glfwPlatformGetProcAddress("glXGetFBConfigAttribSGIX"); - _glfw.glx.ChooseFBConfigSGIX = (PFNGLXCHOOSEFBCONFIGSGIXPROC) - _glfwPlatformGetProcAddress("glXChooseFBConfigSGIX"); - _glfw.glx.CreateContextWithConfigSGIX = (PFNGLXCREATECONTEXTWITHCONFIGSGIXPROC) - _glfwPlatformGetProcAddress("glXCreateContextWithConfigSGIX"); - _glfw.glx.GetVisualFromFBConfigSGIX = (PFNGLXGETVISUALFROMFBCONFIGSGIXPROC) - _glfwPlatformGetProcAddress("glXGetVisualFromFBConfigSGIX"); - - if (_glfw.glx.GetFBConfigAttribSGIX && - _glfw.glx.ChooseFBConfigSGIX && - _glfw.glx.CreateContextWithConfigSGIX && - _glfw.glx.GetVisualFromFBConfigSGIX) - { - _glfw.glx.SGIX_fbconfig = GL_TRUE; - } - } - - if (_glfwPlatformExtensionSupported("GLX_ARB_multisample")) - _glfw.glx.ARB_multisample = GL_TRUE; - - if (_glfwPlatformExtensionSupported("GLX_ARB_framebuffer_sRGB")) - _glfw.glx.ARB_framebuffer_sRGB = GL_TRUE; - - if (_glfwPlatformExtensionSupported("GLX_ARB_create_context")) - { - _glfw.glx.CreateContextAttribsARB = (PFNGLXCREATECONTEXTATTRIBSARBPROC) - _glfwPlatformGetProcAddress("glXCreateContextAttribsARB"); - - if (_glfw.glx.CreateContextAttribsARB) - _glfw.glx.ARB_create_context = GL_TRUE; - } - - if (_glfwPlatformExtensionSupported("GLX_ARB_create_context_robustness")) - _glfw.glx.ARB_create_context_robustness = GL_TRUE; - - if (_glfwPlatformExtensionSupported("GLX_ARB_create_context_profile")) - _glfw.glx.ARB_create_context_profile = GL_TRUE; - - if (_glfwPlatformExtensionSupported("GLX_EXT_create_context_es2_profile")) - _glfw.glx.EXT_create_context_es2_profile = GL_TRUE; - - return GL_TRUE; -} - - -//======================================================================== -// Terminate GLX -//======================================================================== - -void _glfwTerminateOpenGL(void) -{ - // Unload libGL.so if necessary -#ifdef _GLFW_DLOPEN_LIBGL - if (_glfw.glx.libGL != NULL) - { - dlclose(_glfw.glx.libGL); - _glfw.glx.libGL = NULL; - } -#endif -} - - -//======================================================================== -// Prepare for creation of the OpenGL context -//======================================================================== - -int _glfwCreateContext(_GLFWwindow* window, - const _GLFWwndconfig* wndconfig, - const _GLFWfbconfig* fbconfig) -{ - _GLFWfbconfig closest; - - // Choose the best available fbconfig - { - unsigned int fbcount; - _GLFWfbconfig* fbconfigs; - const _GLFWfbconfig* result; - - fbconfigs = getFBConfigs(window, &fbcount); - if (!fbconfigs) - return GL_FALSE; - - result = _glfwChooseFBConfig(fbconfig, fbconfigs, fbcount); - if (!result) - { - _glfwInputError(GLFW_PLATFORM_ERROR, - "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 //======================================================================== diff --git a/src/internal.h b/src/internal.h index a69b1ee0..269ff0c6 100644 --- a/src/internal.h +++ b/src/internal.h @@ -177,11 +177,8 @@ struct _GLFWwndconfig /*! @brief Framebuffer configuration. * - * This describes buffers and their sizes. It also contains - * a platform-specific ID used to map back to the backend API's object. - * - * It is used to pass framebuffer parameters from shared code to the - * platform API and also to enumerate and select available framebuffer configs. + * This describes buffers and their sizes. It is used to pass framebuffer + * parameters from shared code to the platform API. */ struct _GLFWfbconfig { @@ -199,7 +196,6 @@ struct _GLFWfbconfig GLboolean stereo; int samples; GLboolean sRGB; - GLFWintptr platformID; }; @@ -671,18 +667,6 @@ void _glfwSplitBPP(int bpp, int* red, int* green, int* blue); */ int _glfwStringInExtensionString(const char* string, const GLubyte* extensions); -/*! @brief Chooses the framebuffer config that best matches the desired one. - * @param[in] desired The desired framebuffer config. - * @param[in] alternatives The framebuffer configs supported by the system. - * @param[in] count The number of entries in the alternatives array. - * @return The framebuffer config most closely matching the desired one, or @c - * NULL if none fulfilled the hard constraints of the desired values. - * @ingroup utility - */ -const _GLFWfbconfig* _glfwChooseFBConfig(const _GLFWfbconfig* desired, - const _GLFWfbconfig* alternatives, - unsigned int count); - /*! @brief Checks and reads back properties from the current context. * @return @c GL_TRUE if successful, or @c GL_FALSE if the context is unusable. * @ingroup utility diff --git a/src/wgl_context.c b/src/wgl_context.c index 3fa0776f..8ec09049 100644 --- a/src/wgl_context.c +++ b/src/wgl_context.c @@ -32,6 +32,7 @@ #include #include +#include //======================================================================== @@ -64,7 +65,7 @@ static void initWGLExtensions(_GLFWwindow* window) { // This needs to include every function pointer loaded below window->wgl.SwapIntervalEXT = NULL; - window->wgl.GetPixelFormatAttribivARB = NULL; + window->wgl.ChoosePixelFormatARB = NULL; window->wgl.GetExtensionsStringARB = NULL; window->wgl.GetExtensionsStringEXT = NULL; window->wgl.CreateContextAttribsARB = NULL; @@ -135,215 +136,146 @@ static void initWGLExtensions(_GLFWwindow* window) if (_glfwPlatformExtensionSupported("WGL_ARB_pixel_format")) { - window->wgl.GetPixelFormatAttribivARB = (PFNWGLGETPIXELFORMATATTRIBIVARBPROC) - wglGetProcAddress("wglGetPixelFormatAttribivARB"); + window->wgl.ChoosePixelFormatARB = (PFNWGLCHOOSEPIXELFORMATARBPROC) + wglGetProcAddress("wglChoosePixelFormatARB"); - if (window->wgl.GetPixelFormatAttribivARB) + if (window->wgl.ChoosePixelFormatARB) window->wgl.ARB_pixel_format = GL_TRUE; } } +////////////////////////////////////////////////////////////////////////// +////// GLFW internal API ////// +////////////////////////////////////////////////////////////////////////// + //======================================================================== -// Returns the specified attribute of the specified pixel format -// NOTE: Do not call this unless we have found WGL_ARB_pixel_format +// Prepare for creation of the OpenGL context //======================================================================== -static int getPixelFormatAttrib(_GLFWwindow* window, int pixelFormat, int attrib) -{ - int value = 0; - - if (!window->wgl.GetPixelFormatAttribivARB(window->wgl.dc, - pixelFormat, - 0, 1, &attrib, &value)) - { - // NOTE: We should probably handle this error somehow - return 0; - } - - return value; +#define setWGLattrib(attribName, attribValue) \ +{ \ + attribs[index++] = attribName; \ + attribs[index++] = attribValue; \ + assert(index < sizeof(attribs) / sizeof(attribs[0])); \ } - -//======================================================================== -// Return a list of available and usable framebuffer configs -//======================================================================== - -static _GLFWfbconfig* getFBConfigs(_GLFWwindow* window, unsigned int* found) +int _glfwCreateContext(_GLFWwindow* window, + const _GLFWwndconfig* wndconfig, + const _GLFWfbconfig* fbconfig) { - _GLFWfbconfig* fbconfigs; + int attribs[40]; + int pixelFormat; PIXELFORMATDESCRIPTOR pfd; - int i, available; - - *found = 0; - - if (window->wgl.ARB_pixel_format) - { - available = getPixelFormatAttrib(window, - 1, - WGL_NUMBER_PIXEL_FORMATS_ARB); - } - else - { - available = DescribePixelFormat(window->wgl.dc, - 1, - sizeof(PIXELFORMATDESCRIPTOR), - NULL); - } + HGLRC share = NULL; - if (!available) - { - _glfwInputError(GLFW_API_UNAVAILABLE, "WGL: No pixel formats found"); - return NULL; - } + if (wndconfig->share) + share = wndconfig->share->wgl.context; - fbconfigs = (_GLFWfbconfig*) malloc(sizeof(_GLFWfbconfig) * available); - if (!fbconfigs) + window->wgl.dc = GetDC(window->win32.handle); + if (!window->wgl.dc) { - _glfwInputError(GLFW_OUT_OF_MEMORY, NULL); - return NULL; + _glfwInputError(GLFW_PLATFORM_ERROR, + "Win32: Failed to retrieve DC for window"); + return GL_FALSE; } - for (i = 1; i <= available; i++) + if (window->wgl.ARB_pixel_format) { - _GLFWfbconfig* f = fbconfigs + *found; - - if (window->wgl.ARB_pixel_format) + int index = 0; + UINT count; + + setWGLattrib(WGL_SUPPORT_OPENGL_ARB, TRUE); + setWGLattrib(WGL_DRAW_TO_WINDOW_ARB, TRUE); + setWGLattrib(WGL_PIXEL_TYPE_ARB, WGL_TYPE_RGBA_ARB); + setWGLattrib(WGL_DOUBLE_BUFFER_ARB, TRUE); + + if (fbconfig->redBits) + setWGLattrib(WGL_RED_BITS_ARB, fbconfig->redBits); + if (fbconfig->greenBits) + setWGLattrib(WGL_GREEN_BITS_ARB, fbconfig->greenBits); + if (fbconfig->blueBits) + setWGLattrib(WGL_BLUE_BITS_ARB, fbconfig->blueBits); + if (fbconfig->alphaBits) + setWGLattrib(WGL_BLUE_BITS_ARB, fbconfig->alphaBits); + + if (fbconfig->depthBits) + setWGLattrib(WGL_DEPTH_BITS_ARB, fbconfig->depthBits); + if (fbconfig->stencilBits) + setWGLattrib(WGL_STENCIL_BITS_ARB, fbconfig->stencilBits); + + if (fbconfig->auxBuffers) + setWGLattrib(WGL_AUX_BUFFERS_ARB, fbconfig->auxBuffers); + + if (fbconfig->accumRedBits) + setWGLattrib(WGL_ACCUM_RED_BITS_ARB, fbconfig->accumRedBits); + if (fbconfig->accumGreenBits) + setWGLattrib(WGL_ACCUM_GREEN_BITS_ARB, fbconfig->accumGreenBits); + if (fbconfig->accumBlueBits) + setWGLattrib(WGL_ACCUM_BLUE_BITS_ARB, fbconfig->accumBlueBits); + if (fbconfig->accumAlphaBits) + setWGLattrib(WGL_ACCUM_BLUE_BITS_ARB, fbconfig->accumAlphaBits); + + if (fbconfig->stereo) + setWGLattrib(WGL_STEREO_ARB, TRUE); + + if (window->wgl.ARB_multisample) { - // Get pixel format attributes through WGL_ARB_pixel_format - if (!getPixelFormatAttrib(window, i, WGL_SUPPORT_OPENGL_ARB) || - !getPixelFormatAttrib(window, i, WGL_DRAW_TO_WINDOW_ARB) || - !getPixelFormatAttrib(window, i, WGL_DOUBLE_BUFFER_ARB)) - { - continue; - } - - if (getPixelFormatAttrib(window, i, WGL_PIXEL_TYPE_ARB) != - WGL_TYPE_RGBA_ARB) + if (fbconfig->samples) { - continue; + setWGLattrib(WGL_SAMPLE_BUFFERS_ARB, 1); + setWGLattrib(WGL_SAMPLES_ARB, fbconfig->samples); } - - if (getPixelFormatAttrib(window, i, WGL_ACCELERATION_ARB) == - WGL_NO_ACCELERATION_ARB) - { - continue; - } - - f->redBits = getPixelFormatAttrib(window, i, WGL_RED_BITS_ARB); - f->greenBits = getPixelFormatAttrib(window, i, WGL_GREEN_BITS_ARB); - f->blueBits = getPixelFormatAttrib(window, i, WGL_BLUE_BITS_ARB); - f->alphaBits = getPixelFormatAttrib(window, i, WGL_ALPHA_BITS_ARB); - - f->depthBits = getPixelFormatAttrib(window, i, WGL_DEPTH_BITS_ARB); - f->stencilBits = getPixelFormatAttrib(window, i, WGL_STENCIL_BITS_ARB); - - f->accumRedBits = getPixelFormatAttrib(window, i, WGL_ACCUM_RED_BITS_ARB); - f->accumGreenBits = getPixelFormatAttrib(window, i, WGL_ACCUM_GREEN_BITS_ARB); - f->accumBlueBits = getPixelFormatAttrib(window, i, WGL_ACCUM_BLUE_BITS_ARB); - f->accumAlphaBits = getPixelFormatAttrib(window, i, WGL_ACCUM_ALPHA_BITS_ARB); - - f->auxBuffers = getPixelFormatAttrib(window, i, WGL_AUX_BUFFERS_ARB); - f->stereo = getPixelFormatAttrib(window, i, WGL_STEREO_ARB); - - if (window->wgl.ARB_multisample) - f->samples = getPixelFormatAttrib(window, i, WGL_SAMPLES_ARB); - else - f->samples = 0; - - if (window->wgl.ARB_framebuffer_sRGB) - f->sRGB = getPixelFormatAttrib(window, i, WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB); - else - f->sRGB = GL_FALSE; } - else - { - // Get pixel format attributes through old-fashioned PFDs - - if (!DescribePixelFormat(window->wgl.dc, - i, - sizeof(PIXELFORMATDESCRIPTOR), - &pfd)) - { - continue; - } - - if (!(pfd.dwFlags & PFD_DRAW_TO_WINDOW) || - !(pfd.dwFlags & PFD_SUPPORT_OPENGL) || - !(pfd.dwFlags & PFD_DOUBLEBUFFER)) - { - continue; - } - - if (!(pfd.dwFlags & PFD_GENERIC_ACCELERATED) && - (pfd.dwFlags & PFD_GENERIC_FORMAT)) - { - continue; - } - - if (pfd.iPixelType != PFD_TYPE_RGBA) - continue; - - f->redBits = pfd.cRedBits; - f->greenBits = pfd.cGreenBits; - f->blueBits = pfd.cBlueBits; - f->alphaBits = pfd.cAlphaBits; - - f->depthBits = pfd.cDepthBits; - f->stencilBits = pfd.cStencilBits; - - f->accumRedBits = pfd.cAccumRedBits; - f->accumGreenBits = pfd.cAccumGreenBits; - f->accumBlueBits = pfd.cAccumBlueBits; - f->accumAlphaBits = pfd.cAccumAlphaBits; - - f->auxBuffers = pfd.cAuxBuffers; - f->stereo = (pfd.dwFlags & PFD_STEREO) ? GL_TRUE : GL_FALSE; - // PFD pixel formats do not support FSAA - f->samples = 0; - - // PFD pixel formats do not support sRGB - f->sRGB = GL_FALSE; + if (window->wgl.ARB_framebuffer_sRGB) + { + if (fbconfig->sRGB) + setWGLattrib(WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB, TRUE); } - f->platformID = i; + setWGLattrib(0, 0); - (*found)++; + if (!window->wgl.ChoosePixelFormatARB(window->wgl.dc, + attribs, + NULL, + 1, + &pixelFormat, + &count)) + { + _glfwInputError(GLFW_PLATFORM_ERROR, + "WGL: Failed to find a suitable pixel format"); + return GL_FALSE; + } } - - if (*found == 0) + else { - _glfwInputError(GLFW_PLATFORM_ERROR, - "Win32/WGL: No usable pixel formats found"); - - free(fbconfigs); - return NULL; + ZeroMemory(&pfd, sizeof(pfd)); + pfd.nSize = sizeof(pfd); + pfd.nVersion = 1; + + pfd.dwFlags |= PFD_DRAW_TO_WINDOW | + PFD_SUPPORT_OPENGL | + PFD_DOUBLEBUFFER; + + if (fbconfig->stereo) + pfd.dwFlags |= PFD_STEREO; + + pfd.iPixelType = PFD_TYPE_RGBA; + pfd.cColorBits = fbconfig->redBits + + fbconfig->greenBits + + fbconfig->blueBits; + pfd.cAlphaBits = fbconfig->alphaBits; + pfd.cAccumBits = fbconfig->accumRedBits + + fbconfig->accumGreenBits + + fbconfig->accumBlueBits; + pfd.cDepthBits = fbconfig->depthBits; + pfd.cStencilBits = fbconfig->stencilBits; + pfd.cAuxBuffers = fbconfig->auxBuffers; + + pixelFormat = ChoosePixelFormat(window->wgl.dc, &pfd); } - return fbconfigs; -} - - -//======================================================================== -// Creates an OpenGL context on the specified device context -//======================================================================== - -#define setWGLattrib(attribName, attribValue) \ - attribs[index++] = attribName; \ - attribs[index++] = attribValue; - -static GLboolean createContext(_GLFWwindow* window, - const _GLFWwndconfig* wndconfig, - int pixelFormat) -{ - int attribs[40]; - PIXELFORMATDESCRIPTOR pfd; - HGLRC share = NULL; - - if (wndconfig->share) - share = wndconfig->share->wgl.context; - if (!DescribePixelFormat(window->wgl.dc, pixelFormat, sizeof(pfd), &pfd)) { _glfwInputError(GLFW_PLATFORM_ERROR, @@ -352,6 +284,14 @@ static GLboolean createContext(_GLFWwindow* window, return GL_FALSE; } + if (!(pfd.dwFlags & PFD_GENERIC_ACCELERATED) && + (pfd.dwFlags & PFD_GENERIC_FORMAT)) + { + _glfwInputError(GLFW_PLATFORM_ERROR, + "Win32: Failed to find an accelerated pixel format"); + return GL_FALSE; + } + if (!SetPixelFormat(window->wgl.dc, pixelFormat, &pfd)) { _glfwInputError(GLFW_PLATFORM_ERROR, @@ -453,56 +393,6 @@ static GLboolean createContext(_GLFWwindow* window, #undef setWGLattrib -////////////////////////////////////////////////////////////////////////// -////// GLFW internal API ////// -////////////////////////////////////////////////////////////////////////// - -//======================================================================== -// Prepare for creation of the OpenGL context -//======================================================================== - -int _glfwCreateContext(_GLFWwindow* window, - const _GLFWwndconfig* wndconfig, - const _GLFWfbconfig* fbconfig) -{ - _GLFWfbconfig closest; - - window->wgl.dc = GetDC(window->win32.handle); - if (!window->wgl.dc) - { - _glfwInputError(GLFW_PLATFORM_ERROR, - "Win32: Failed to retrieve DC for window"); - return GL_FALSE; - } - - // Choose the best available fbconfig - { - unsigned int fbcount; - _GLFWfbconfig* fbconfigs; - const _GLFWfbconfig* result; - - fbconfigs = getFBConfigs(window, &fbcount); - if (!fbconfigs) - return GL_FALSE; - - result = _glfwChooseFBConfig(fbconfig, fbconfigs, fbcount); - if (!result) - { - _glfwInputError(GLFW_FORMAT_UNAVAILABLE, - "Win32/WGL: No pixel format matched the criteria"); - - free(fbconfigs); - return GL_FALSE; - } - - closest = *result; - free(fbconfigs); - } - - return createContext(window, wndconfig, (int) closest.platformID); -} - - //======================================================================== // Destroy the OpenGL context //======================================================================== diff --git a/src/wgl_platform.h b/src/wgl_platform.h index 90428510..5983aef5 100644 --- a/src/wgl_platform.h +++ b/src/wgl_platform.h @@ -56,7 +56,7 @@ typedef struct _GLFWcontextWGL // Platform specific extensions (context specific) PFNWGLSWAPINTERVALEXTPROC SwapIntervalEXT; - PFNWGLGETPIXELFORMATATTRIBIVARBPROC GetPixelFormatAttribivARB; + PFNWGLCHOOSEPIXELFORMATARBPROC ChoosePixelFormatARB; PFNWGLGETEXTENSIONSSTRINGEXTPROC GetExtensionsStringEXT; PFNWGLGETEXTENSIONSSTRINGARBPROC GetExtensionsStringARB; PFNWGLCREATECONTEXTATTRIBSARBPROC CreateContextAttribsARB;