diff --git a/README.md b/README.md index 3f05cefa..0ce69e97 100644 --- a/README.md +++ b/README.md @@ -66,6 +66,7 @@ used by the tests and examples and are not required to build the library. - Added `glfwSetWindowSizeLimits` and `glfwSetWindowAspectRatio` for setting absolute and relative window size limits + - Added `GLFW_NO_API` for creating window without contexts - Added `GLFW_TRUE` and `GLFW_FALSE` as client API independent boolean values - Removed dependency on external OpenGL or OpenGL ES headers - [Cocoa] Removed support for OS X 10.6 diff --git a/include/GLFW/glfw3.h b/include/GLFW/glfw3.h index 7b31a7d0..ccb72d0e 100644 --- a/include/GLFW/glfw3.h +++ b/include/GLFW/glfw3.h @@ -613,6 +613,15 @@ extern "C" { * the user, as appropriate. */ #define GLFW_FORMAT_UNAVAILABLE 0x00010009 +/*! @brief The specified window does not have an OpenGL or OpenGL ES context. + * + * A window that does not have an OpenGL or OpenGL ES context was passed to + * a function that requires it to have one. + * + * @par Analysis + * Application programmer error. Fix the offending call. + */ +#define GLFW_NO_WINDOW_CONTEXT 0x0001000A /*! @} */ #define GLFW_FOCUSED 0x00020001 @@ -650,6 +659,7 @@ extern "C" { #define GLFW_OPENGL_PROFILE 0x00022008 #define GLFW_CONTEXT_RELEASE_BEHAVIOR 0x00022009 +#define GLFW_NO_API 0 #define GLFW_OPENGL_API 0x00030001 #define GLFW_OPENGL_ES_API 0x00030002 diff --git a/src/cocoa_window.m b/src/cocoa_window.m index e8c846e0..7a371495 100644 --- a/src/cocoa_window.m +++ b/src/cocoa_window.m @@ -887,10 +887,11 @@ int _glfwPlatformCreateWindow(_GLFWwindow* window, if (!createWindow(window, wndconfig)) return GLFW_FALSE; - if (!_glfwCreateContext(window, ctxconfig, fbconfig)) - return GLFW_FALSE; - - [window->nsgl.context setView:window->ns.view]; + if (ctxconfig->api != GLFW_NO_API) + { + if (!_glfwCreateContext(window, ctxconfig, fbconfig)) + return GLFW_FALSE; + } if (wndconfig->monitor) { @@ -909,7 +910,8 @@ void _glfwPlatformDestroyWindow(_GLFWwindow* window) if (window->monitor) leaveFullscreenMode(window); - _glfwDestroyContext(window); + if (window->context.api != GLFW_NO_API) + _glfwDestroyContext(window); [window->ns.object setDelegate:nil]; [window->ns.delegate release]; diff --git a/src/context.c b/src/context.c index e145ae35..9db0b827 100644 --- a/src/context.c +++ b/src/context.c @@ -89,7 +89,8 @@ static GLFWbool parseVersionString(int* api, int* major, int* minor, int* rev) GLFWbool _glfwIsValidContextConfig(const _GLFWctxconfig* ctxconfig) { - if (ctxconfig->api != GLFW_OPENGL_API && + if (ctxconfig->api != GLFW_NO_API && + ctxconfig->api != GLFW_OPENGL_API && ctxconfig->api != GLFW_OPENGL_ES_API) { _glfwInputError(GLFW_INVALID_ENUM, "Invalid client API"); @@ -536,7 +537,15 @@ int _glfwStringInExtensionString(const char* string, const char* extensions) GLFWAPI void glfwMakeContextCurrent(GLFWwindow* handle) { _GLFWwindow* window = (_GLFWwindow*) handle; + _GLFW_REQUIRE_INIT(); + + if (window->context.api == GLFW_NO_API) + { + _glfwInputError(GLFW_NO_WINDOW_CONTEXT, NULL); + return; + } + _glfwPlatformMakeContextCurrent(window); } @@ -549,7 +558,15 @@ GLFWAPI GLFWwindow* glfwGetCurrentContext(void) GLFWAPI void glfwSwapBuffers(GLFWwindow* handle) { _GLFWwindow* window = (_GLFWwindow*) handle; + _GLFW_REQUIRE_INIT(); + + if (window->context.api == GLFW_NO_API) + { + _glfwInputError(GLFW_NO_WINDOW_CONTEXT, NULL); + return; + } + _glfwPlatformSwapBuffers(window); } diff --git a/src/egl_context.c b/src/egl_context.c index cac0ae78..1912c803 100644 --- a/src/egl_context.c +++ b/src/egl_context.c @@ -112,12 +112,6 @@ static GLFWbool chooseFBConfigs(const _GLFWctxconfig* ctxconfig, const EGLConfig n = nativeConfigs[i]; _GLFWfbconfig* u = usableConfigs + usableCount; -#if defined(_GLFW_X11) - // Only consider EGLConfigs with associated visuals - if (!getConfigAttrib(n, EGL_NATIVE_VISUAL_ID)) - continue; -#endif // _GLFW_X11 - // Only consider RGB(A) EGLConfigs if (!(getConfigAttrib(n, EGL_COLOR_BUFFER_TYPE) & EGL_RGB_BUFFER)) continue; @@ -126,6 +120,12 @@ static GLFWbool chooseFBConfigs(const _GLFWctxconfig* ctxconfig, if (!(getConfigAttrib(n, EGL_SURFACE_TYPE) & EGL_WINDOW_BIT)) continue; +#if defined(_GLFW_X11) + // Only consider EGLConfigs with associated Visuals + if (!getConfigAttrib(n, EGL_NATIVE_VISUAL_ID)) + continue; +#endif // _GLFW_X11 + if (ctxconfig->api == GLFW_OPENGL_ES_API) { if (ctxconfig->major == 1) @@ -311,55 +311,6 @@ int _glfwCreateContext(_GLFWwindow* window, return GLFW_FALSE; } -#if defined(_GLFW_X11) - // Retrieve the visual corresponding to the chosen EGL config - { - EGLint count = 0; - int mask; - EGLint redBits, greenBits, blueBits, alphaBits, visualID = 0; - XVisualInfo info; - - _glfw_eglGetConfigAttrib(_glfw.egl.display, config, - EGL_NATIVE_VISUAL_ID, &visualID); - - info.screen = _glfw.x11.screen; - mask = VisualScreenMask; - - if (visualID) - { - // The X window visual must match the EGL config - info.visualid = visualID; - mask |= VisualIDMask; - } - else - { - // Some EGL drivers do not implement the EGL_NATIVE_VISUAL_ID - // attribute, so attempt to find the closest match - - _glfw_eglGetConfigAttrib(_glfw.egl.display, config, - EGL_RED_SIZE, &redBits); - _glfw_eglGetConfigAttrib(_glfw.egl.display, config, - EGL_GREEN_SIZE, &greenBits); - _glfw_eglGetConfigAttrib(_glfw.egl.display, config, - EGL_BLUE_SIZE, &blueBits); - _glfw_eglGetConfigAttrib(_glfw.egl.display, config, - EGL_ALPHA_SIZE, &alphaBits); - - info.depth = redBits + greenBits + blueBits + alphaBits; - mask |= VisualDepthMask; - } - - window->egl.visual = XGetVisualInfo(_glfw.x11.display, - mask, &info, &count); - if (!window->egl.visual) - { - _glfwInputError(GLFW_PLATFORM_ERROR, - "EGL: Failed to retrieve visual for EGLConfig"); - return GLFW_FALSE; - } - } -#endif // _GLFW_X11 - if (ctxconfig->api == GLFW_OPENGL_ES_API) { if (!_glfw_eglBindAPI(EGL_OPENGL_ES_API)) @@ -453,6 +404,19 @@ int _glfwCreateContext(_GLFWwindow* window, return GLFW_FALSE; } + window->egl.surface = + _glfw_eglCreateWindowSurface(_glfw.egl.display, + config, + (EGLNativeWindowType)_GLFW_EGL_NATIVE_WINDOW, + NULL); + if (window->egl.surface == EGL_NO_SURFACE) + { + _glfwInputError(GLFW_PLATFORM_ERROR, + "EGL: Failed to create window surface: %s", + getErrorString(_glfw_eglGetError())); + return GLFW_FALSE; + } + window->egl.config = config; // Load the appropriate client library @@ -541,14 +505,6 @@ void _glfwDestroyContext(_GLFWwindow* window) } } -#if defined(_GLFW_X11) - if (window->egl.visual) - { - XFree(window->egl.visual); - window->egl.visual = NULL; - } -#endif // _GLFW_X11 - if (window->egl.surface) { _glfw_eglDestroySurface(_glfw.egl.display, window->egl.surface); @@ -564,16 +520,56 @@ void _glfwDestroyContext(_GLFWwindow* window) // Analyzes the specified context for possible recreation // +#if defined(_GLFW_WIN32) int _glfwAnalyzeContext(const _GLFWwindow* window, const _GLFWctxconfig* ctxconfig, const _GLFWfbconfig* fbconfig) { -#if defined(_GLFW_WIN32) return _GLFW_RECREATION_NOT_NEEDED; -#else - return 0; -#endif } +#endif // _GLFW_WIN32 + +// Returns the Visual and depth of the chosen EGLConfig +// +#if defined(_GLFW_X11) +GLFWbool _glfwChooseVisual(const _GLFWctxconfig* ctxconfig, + const _GLFWfbconfig* fbconfig, + Visual** visual, int* depth) +{ + XVisualInfo* result; + XVisualInfo desired; + EGLConfig native; + EGLint visualID = 0, count = 0; + const long vimask = VisualScreenMask | VisualIDMask; + + if (!chooseFBConfigs(ctxconfig, fbconfig, &native)) + { + _glfwInputError(GLFW_FORMAT_UNAVAILABLE, + "EGL: Failed to find a suitable EGLConfig"); + return GLFW_FALSE; + } + + _glfw_eglGetConfigAttrib(_glfw.egl.display, native, + EGL_NATIVE_VISUAL_ID, &visualID); + + desired.screen = _glfw.x11.screen; + desired.visualid = visualID; + + result = XGetVisualInfo(_glfw.x11.display, vimask, &desired, &count); + if (!result) + { + _glfwInputError(GLFW_PLATFORM_ERROR, + "EGL: Failed to retrieve Visual for EGLConfig"); + return GLFW_FALSE; + } + + *visual = result->visual; + *depth = result->depth; + + XFree(result); + return GLFW_TRUE; +} +#endif // _GLFW_X11 ////////////////////////////////////////////////////////////////////////// @@ -584,21 +580,6 @@ void _glfwPlatformMakeContextCurrent(_GLFWwindow* window) { if (window) { - if (window->egl.surface == EGL_NO_SURFACE) - { - window->egl.surface = - _glfw_eglCreateWindowSurface(_glfw.egl.display, - window->egl.config, - (EGLNativeWindowType)_GLFW_EGL_NATIVE_WINDOW, - NULL); - if (window->egl.surface == EGL_NO_SURFACE) - { - _glfwInputError(GLFW_PLATFORM_ERROR, - "EGL: Failed to create window surface: %s", - getErrorString(_glfw_eglGetError())); - } - } - _glfw_eglMakeCurrent(_glfw.egl.display, window->egl.surface, window->egl.surface, @@ -667,6 +648,13 @@ GLFWAPI EGLContext glfwGetEGLContext(GLFWwindow* handle) { _GLFWwindow* window = (_GLFWwindow*) handle; _GLFW_REQUIRE_INIT_OR_RETURN(EGL_NO_CONTEXT); + + if (window->context.api == GLFW_NO_API) + { + _glfwInputError(GLFW_NO_WINDOW_CONTEXT, NULL); + return EGL_NO_CONTEXT; + } + return window->egl.context; } @@ -674,6 +662,13 @@ GLFWAPI EGLSurface glfwGetEGLSurface(GLFWwindow* handle) { _GLFWwindow* window = (_GLFWwindow*) handle; _GLFW_REQUIRE_INIT_OR_RETURN(EGL_NO_SURFACE); + + if (window->context.api == GLFW_NO_API) + { + _glfwInputError(GLFW_NO_WINDOW_CONTEXT, NULL); + return EGL_NO_SURFACE; + } + return window->egl.surface; } diff --git a/src/egl_context.h b/src/egl_context.h index c3b5d650..6bcddd4a 100644 --- a/src/egl_context.h +++ b/src/egl_context.h @@ -147,10 +147,6 @@ typedef struct _GLFWcontextEGL EGLContext context; EGLSurface surface; -#if defined(_GLFW_X11) - XVisualInfo* visual; -#endif - void* client; } _GLFWcontextEGL; @@ -193,8 +189,15 @@ int _glfwCreateContext(_GLFWwindow* window, const _GLFWctxconfig* ctxconfig, const _GLFWfbconfig* fbconfig); void _glfwDestroyContext(_GLFWwindow* window); +#if defined(_GLFW_WIN32) int _glfwAnalyzeContext(const _GLFWwindow* window, const _GLFWctxconfig* ctxconfig, const _GLFWfbconfig* fbconfig); +#endif /*_GLFW_WIN32*/ +#if defined(_GLFW_X11) +GLFWbool _glfwChooseVisual(const _GLFWctxconfig* ctxconfig, + const _GLFWfbconfig* fbconfig, + Visual** visual, int* depth); +#endif /*_GLFW_X11*/ #endif // _glfw3_egl_context_h_ diff --git a/src/glx_context.c b/src/glx_context.c index 8f8123ef..e660037d 100644 --- a/src/glx_context.c +++ b/src/glx_context.c @@ -79,10 +79,6 @@ static GLFWbool chooseFBConfig(const _GLFWfbconfig* desired, GLXFBConfig* result const GLXFBConfig n = nativeConfigs[i]; _GLFWfbconfig* u = usableConfigs + usableCount; - // Only consider GLXFBConfigs with associated visuals - if (!getFBConfigAttrib(n, GLX_VISUAL_ID)) - continue; - // Only consider RGBA GLXFBConfigs if (!(getFBConfigAttrib(n, GLX_RENDER_TYPE) & GLX_RGBA_BIT)) continue; @@ -192,12 +188,12 @@ int _glfwInitContextAPI(void) dlsym(_glfw.glx.handle, "glXQueryExtensionsString"); _glfw.glx.CreateNewContext = dlsym(_glfw.glx.handle, "glXCreateNewContext"); - _glfw.glx.GetVisualFromFBConfig = - dlsym(_glfw.glx.handle, "glXGetVisualFromFBConfig"); _glfw.glx.GetProcAddress = dlsym(_glfw.glx.handle, "glXGetProcAddress"); _glfw.glx.GetProcAddressARB = dlsym(_glfw.glx.handle, "glXGetProcAddressARB"); + _glfw.glx.GetVisualFromFBConfig = + dlsym(_glfw.glx.handle, "glXGetVisualFromFBConfig"); if (!_glfw_glXQueryExtension(_glfw.x11.display, &_glfw.glx.errorBase, @@ -326,15 +322,6 @@ int _glfwCreateContext(_GLFWwindow* window, return GLFW_FALSE; } - window->glx.visual = _glfw_glXGetVisualFromFBConfig(_glfw.x11.display, - native); - if (!window->glx.visual) - { - _glfwInputError(GLFW_PLATFORM_ERROR, - "GLX: Failed to retrieve visual for GLXFBConfig"); - return GLFW_FALSE; - } - if (ctxconfig->api == GLFW_OPENGL_ES_API) { if (!_glfw.glx.ARB_create_context || @@ -485,12 +472,6 @@ int _glfwCreateContext(_GLFWwindow* window, // void _glfwDestroyContext(_GLFWwindow* window) { - if (window->glx.visual) - { - XFree(window->glx.visual); - window->glx.visual = NULL; - } - if (window->glx.context) { _glfw_glXDestroyContext(_glfw.x11.display, window->glx.context); @@ -498,6 +479,37 @@ void _glfwDestroyContext(_GLFWwindow* window) } } +// Returns the Visual and depth of the chosen GLXFBConfig +// +GLFWbool _glfwChooseVisual(const _GLFWctxconfig* ctxconfig, + const _GLFWfbconfig* fbconfig, + Visual** visual, int* depth) +{ + GLXFBConfig native; + XVisualInfo* result; + + if (!chooseFBConfig(fbconfig, &native)) + { + _glfwInputError(GLFW_FORMAT_UNAVAILABLE, + "GLX: Failed to find a suitable GLXFBConfig"); + return GLFW_FALSE; + } + + result = _glfw_glXGetVisualFromFBConfig(_glfw.x11.display, native); + if (!result) + { + _glfwInputError(GLFW_PLATFORM_ERROR, + "GLX: Failed to retrieve Visual for GLXFBConfig"); + return GLFW_FALSE; + } + + *visual = result->visual; + *depth = result->depth; + + XFree(result); + return GLFW_TRUE; +} + ////////////////////////////////////////////////////////////////////////// ////// GLFW platform API ////// @@ -573,6 +585,13 @@ GLFWAPI GLXContext glfwGetGLXContext(GLFWwindow* handle) { _GLFWwindow* window = (_GLFWwindow*) handle; _GLFW_REQUIRE_INIT_OR_RETURN(NULL); + + if (window->context.api == GLFW_NO_API) + { + _glfwInputError(GLFW_NO_WINDOW_CONTEXT, NULL); + return NULL; + } + return window->glx.context; } diff --git a/src/glx_context.h b/src/glx_context.h index 7fa5b63d..a53e70d5 100644 --- a/src/glx_context.h +++ b/src/glx_context.h @@ -111,10 +111,7 @@ typedef XVisualInfo* (*PFNGLXGETVISUALFROMFBCONFIGPROC)(Display*,GLXFBConfig); // typedef struct _GLFWcontextGLX { - // Rendering context GLXContext context; - // Visual of selected GLXFBConfig - XVisualInfo* visual; } _GLFWcontextGLX; @@ -171,5 +168,8 @@ int _glfwCreateContext(_GLFWwindow* window, const _GLFWctxconfig* ctxconfig, const _GLFWfbconfig* fbconfig); void _glfwDestroyContext(_GLFWwindow* window); +GLFWbool _glfwChooseVisual(const _GLFWctxconfig* ctxconfig, + const _GLFWfbconfig* fbconfig, + Visual** visual, int* depth); #endif // _glfw3_glx_context_h_ diff --git a/src/init.c b/src/init.c index 0109f4c4..811fccec 100644 --- a/src/init.c +++ b/src/init.c @@ -72,6 +72,8 @@ static const char* getErrorString(int error) return "A platform-specific error occurred"; case GLFW_FORMAT_UNAVAILABLE: return "The requested format is unavailable"; + case GLFW_NO_WINDOW_CONTEXT: + return "The specified window has no context"; } return "ERROR: UNKNOWN ERROR TOKEN PASSED TO glfwErrorString"; diff --git a/src/mir_window.c b/src/mir_window.c index 23cfa520..aed69341 100644 --- a/src/mir_window.c +++ b/src/mir_window.c @@ -462,8 +462,11 @@ int _glfwPlatformCreateWindow(_GLFWwindow* window, const _GLFWctxconfig* ctxconfig, const _GLFWfbconfig* fbconfig) { - if (!_glfwCreateContext(window, ctxconfig, fbconfig)) - return GLFW_FALSE; + if (ctxconfig->api != GLFW_NO_API) + { + if (!_glfwCreateContext(window, ctxconfig, fbconfig)) + return GLFW_FALSE; + } if (wndconfig->monitor) { diff --git a/src/nsgl_context.m b/src/nsgl_context.m index e064f963..87a977bc 100644 --- a/src/nsgl_context.m +++ b/src/nsgl_context.m @@ -219,6 +219,7 @@ int _glfwCreateContext(_GLFWwindow* window, return GLFW_FALSE; } + [window->nsgl.context setView:window->ns.view]; return GLFW_TRUE; } @@ -291,6 +292,13 @@ GLFWAPI id glfwGetNSGLContext(GLFWwindow* handle) { _GLFWwindow* window = (_GLFWwindow*) handle; _GLFW_REQUIRE_INIT_OR_RETURN(nil); + + if (window->context.api == GLFW_NO_API) + { + _glfwInputError(GLFW_NO_WINDOW_CONTEXT, NULL); + return NULL; + } + return window->nsgl.context; } diff --git a/src/wgl_context.c b/src/wgl_context.c index 0bce17e7..2233d654 100644 --- a/src/wgl_context.c +++ b/src/wgl_context.c @@ -672,6 +672,13 @@ GLFWAPI HGLRC glfwGetWGLContext(GLFWwindow* handle) { _GLFWwindow* window = (_GLFWwindow*) handle; _GLFW_REQUIRE_INIT_OR_RETURN(NULL); + + if (window->context.api == GLFW_NO_API) + { + _glfwInputError(GLFW_NO_WINDOW_CONTEXT, NULL); + return NULL; + } + return window->wgl.context; } diff --git a/src/win32_window.c b/src/win32_window.c index 2f2db36e..141f3a60 100644 --- a/src/win32_window.c +++ b/src/win32_window.c @@ -665,10 +665,7 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg, // Creates the GLFW window and rendering context // -static GLFWbool createWindow(_GLFWwindow* window, - const _GLFWwndconfig* wndconfig, - const _GLFWctxconfig* ctxconfig, - const _GLFWfbconfig* fbconfig) +static int createWindow(_GLFWwindow* window, const _GLFWwndconfig* wndconfig) { int xpos, ypos, fullWidth, fullHeight; WCHAR* wideTitle; @@ -742,9 +739,6 @@ static GLFWbool createWindow(_GLFWwindow* window, DragAcceptFiles(window->win32.handle, TRUE); - if (!_glfwCreateContext(window, ctxconfig, fbconfig)) - return GLFW_FALSE; - window->win32.minwidth = GLFW_DONT_CARE; window->win32.minheight = GLFW_DONT_CARE; window->win32.maxwidth = GLFW_DONT_CARE; @@ -759,8 +753,6 @@ static GLFWbool createWindow(_GLFWwindow* window, // static void destroyWindow(_GLFWwindow* window) { - _glfwDestroyContext(window); - if (window->win32.handle) { DestroyWindow(window->win32.handle); @@ -830,43 +822,53 @@ int _glfwPlatformCreateWindow(_GLFWwindow* window, { int status; - if (!createWindow(window, wndconfig, ctxconfig, fbconfig)) + if (!createWindow(window, wndconfig)) return GLFW_FALSE; - status = _glfwAnalyzeContext(window, ctxconfig, fbconfig); - - if (status == _GLFW_RECREATION_IMPOSSIBLE) - return GLFW_FALSE; - - if (status == _GLFW_RECREATION_REQUIRED) + if (ctxconfig->api != GLFW_NO_API) { - // Some window hints require us to re-create the context using WGL - // extensions retrieved through the current context, as we cannot check - // for WGL extensions or retrieve WGL entry points before we have a - // current context (actually until we have implicitly loaded the ICD) - - // Yes, this is strange, and yes, this is the proper way on Win32 - - // As Windows only allows you to set the pixel format once for a - // window, we need to destroy the current window and create a new one - // to be able to use the new pixel format - - // Technically, it may be possible to keep the old window around if - // we're just creating an OpenGL 3.0+ context with the same pixel - // format, but it's not worth the added code complexity - - // First we clear the current context (the one we just created) - // This is usually done by glfwDestroyWindow, but as we're not doing - // full GLFW window destruction, it's duplicated here - _glfwPlatformMakeContextCurrent(NULL); - - // Next destroy the Win32 window and WGL context (without resetting or - // destroying the GLFW window object) - destroyWindow(window); - - // ...and then create them again, this time with better APIs - if (!createWindow(window, wndconfig, ctxconfig, fbconfig)) + if (!_glfwCreateContext(window, ctxconfig, fbconfig)) return GLFW_FALSE; + + status = _glfwAnalyzeContext(window, ctxconfig, fbconfig); + + if (status == _GLFW_RECREATION_IMPOSSIBLE) + return GLFW_FALSE; + + if (status == _GLFW_RECREATION_REQUIRED) + { + // Some window hints require us to re-create the context using WGL + // extensions retrieved through the current context, as we cannot + // check for WGL extensions or retrieve WGL entry points before we + // have a current context (actually until we have implicitly loaded + // the vendor ICD) + + // Yes, this is strange, and yes, this is the proper way on Win32 + + // As Windows only allows you to set the pixel format once for + // a window, we need to destroy the current window and create a new + // one to be able to use the new pixel format + + // Technically, it may be possible to keep the old window around if + // we're just creating an OpenGL 3.0+ context with the same pixel + // format, but it's not worth the added code complexity + + // First we clear the current context (the one we just created) + // This is usually done by glfwDestroyWindow, but as we're not doing + // full GLFW window destruction, it's duplicated here + _glfwPlatformMakeContextCurrent(NULL); + + // Next destroy the Win32 window and WGL context (without resetting + // or destroying the GLFW window object) + _glfwDestroyContext(window); + destroyWindow(window); + + // ...and then create them again, this time with better APIs + if (!createWindow(window, wndconfig)) + return GLFW_FALSE; + if (!_glfwCreateContext(window, ctxconfig, fbconfig)) + return GLFW_FALSE; + } } if (window->monitor) @@ -884,6 +886,9 @@ void _glfwPlatformDestroyWindow(_GLFWwindow* window) if (window->monitor) leaveFullscreenMode(window); + if (window->context.api != GLFW_NO_API) + _glfwDestroyContext(window); + destroyWindow(window); } diff --git a/src/window.c b/src/window.c index 08426f85..345bc14a 100644 --- a/src/window.c +++ b/src/window.c @@ -142,6 +142,15 @@ GLFWAPI GLFWwindow* glfwCreateWindow(int width, int height, wndconfig.monitor = (_GLFWmonitor*) monitor; ctxconfig.share = (_GLFWwindow*) share; + if (ctxconfig.share) + { + if (ctxconfig.share->context.api == GLFW_NO_API) + { + _glfwInputError(GLFW_NO_WINDOW_CONTEXT, NULL); + return NULL; + } + } + if (wndconfig.monitor) { wndconfig.resizable = GLFW_TRUE; @@ -181,26 +190,29 @@ GLFWAPI GLFWwindow* glfwCreateWindow(int width, int height, return NULL; } - _glfwPlatformMakeContextCurrent(window); - - // Retrieve the actual (as opposed to requested) context attributes - if (!_glfwRefreshContextAttribs(&ctxconfig)) + if (ctxconfig.api != GLFW_NO_API) { - glfwDestroyWindow((GLFWwindow*) window); - _glfwPlatformMakeContextCurrent(previous); - return NULL; - } + _glfwPlatformMakeContextCurrent(window); - // Verify the context against the requested parameters - if (!_glfwIsValidContext(&ctxconfig)) - { - glfwDestroyWindow((GLFWwindow*) window); - _glfwPlatformMakeContextCurrent(previous); - return NULL; - } + // Retrieve the actual (as opposed to requested) context attributes + if (!_glfwRefreshContextAttribs(&ctxconfig)) + { + glfwDestroyWindow((GLFWwindow*) window); + _glfwPlatformMakeContextCurrent(previous); + return NULL; + } - // Restore the previously current context (or NULL) - _glfwPlatformMakeContextCurrent(previous); + // Verify the context against the requested parameters + if (!_glfwIsValidContext(&ctxconfig)) + { + glfwDestroyWindow((GLFWwindow*) window); + _glfwPlatformMakeContextCurrent(previous); + return NULL; + } + + // Restore the previously current context (or NULL) + _glfwPlatformMakeContextCurrent(previous); + } if (wndconfig.monitor) { diff --git a/src/wl_window.c b/src/wl_window.c index d192f665..8aa7b99f 100644 --- a/src/wl_window.c +++ b/src/wl_window.c @@ -238,8 +238,11 @@ int _glfwPlatformCreateWindow(_GLFWwindow* window, const _GLFWctxconfig* ctxconfig, const _GLFWfbconfig* fbconfig) { - if (!_glfwCreateContext(window, ctxconfig, fbconfig)) - return GLFW_FALSE; + if (ctxconfig->api != GLFW_NO_API) + { + if (!_glfwCreateContext(window, ctxconfig, fbconfig)) + return GLFW_FALSE; + } if (!createSurface(window, wndconfig)) return GLFW_FALSE; diff --git a/src/x11_platform.h b/src/x11_platform.h index 5f94d0f8..d778e5b4 100644 --- a/src/x11_platform.h +++ b/src/x11_platform.h @@ -62,10 +62,8 @@ #include "xkb_unicode.h" #if defined(_GLFW_GLX) - #define _GLFW_X11_CONTEXT_VISUAL window->glx.visual #include "glx_context.h" #elif defined(_GLFW_EGL) - #define _GLFW_X11_CONTEXT_VISUAL window->egl.visual #define _GLFW_EGL_NATIVE_WINDOW window->x11.handle #define _GLFW_EGL_NATIVE_DISPLAY _glfw.x11.display #include "egl_context.h" diff --git a/src/x11_window.c b/src/x11_window.c index 309a5f30..e6c71d16 100644 --- a/src/x11_window.c +++ b/src/x11_window.c @@ -248,17 +248,16 @@ static char** parseUriList(char* text, int* count) // Create the X11 window (and its colormap) // static GLFWbool createWindow(_GLFWwindow* window, - const _GLFWwndconfig* wndconfig) + const _GLFWwndconfig* wndconfig, + Visual* visual, int depth) { - XVisualInfo* vi = _GLFW_X11_CONTEXT_VISUAL; - // Every window needs a colormap // Create one based on the visual used by the current context // TODO: Decouple this from context creation window->x11.colormap = XCreateColormap(_glfw.x11.display, _glfw.x11.root, - vi->visual, + visual, AllocNone); // Create the actual window @@ -279,10 +278,10 @@ static GLFWbool createWindow(_GLFWwindow* window, _glfw.x11.root, 0, 0, wndconfig->width, wndconfig->height, - 0, // Border width - vi->depth, // Color depth + 0, // Border width + depth, // Color depth InputOutput, - vi->visual, + visual, wamask, &wa); @@ -1467,12 +1466,21 @@ int _glfwPlatformCreateWindow(_GLFWwindow* window, const _GLFWctxconfig* ctxconfig, const _GLFWfbconfig* fbconfig) { - if (!_glfwCreateContext(window, ctxconfig, fbconfig)) + Visual* visual; + int depth; + + if (!_glfwChooseVisual(ctxconfig, fbconfig, &visual, &depth)) return GLFW_FALSE; - if (!createWindow(window, wndconfig)) + if (!createWindow(window, wndconfig, visual, depth)) return GLFW_FALSE; + if (ctxconfig->api != GLFW_NO_API) + { + if (!_glfwCreateContext(window, ctxconfig, fbconfig)) + return GLFW_FALSE; + } + if (wndconfig->monitor) { _glfwPlatformShowWindow(window); @@ -1493,7 +1501,8 @@ void _glfwPlatformDestroyWindow(_GLFWwindow* window) window->x11.ic = NULL; } - _glfwDestroyContext(window); + if (window->context.api != GLFW_NO_API) + _glfwDestroyContext(window); if (window->x11.handle) {