1
0
Fork 0
mirror of https://github.com/gwm17/glfw.git synced 2024-11-23 02:38:52 -05:00

Add GLFW_NO_API for creating context-less windows

This commit is contained in:
Camilla Berglund 2015-06-18 14:03:02 +02:00
parent 0fda5b7b80
commit 496f559c9a
17 changed files with 285 additions and 191 deletions

View File

@ -66,6 +66,7 @@ used by the tests and examples and are not required to build the library.
- Added `glfwSetWindowSizeLimits` and `glfwSetWindowAspectRatio` for setting - Added `glfwSetWindowSizeLimits` and `glfwSetWindowAspectRatio` for setting
absolute and relative window size limits 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 - Added `GLFW_TRUE` and `GLFW_FALSE` as client API independent boolean values
- Removed dependency on external OpenGL or OpenGL ES headers - Removed dependency on external OpenGL or OpenGL ES headers
- [Cocoa] Removed support for OS X 10.6 - [Cocoa] Removed support for OS X 10.6

View File

@ -613,6 +613,15 @@ extern "C" {
* the user, as appropriate. * the user, as appropriate.
*/ */
#define GLFW_FORMAT_UNAVAILABLE 0x00010009 #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 #define GLFW_FOCUSED 0x00020001
@ -650,6 +659,7 @@ extern "C" {
#define GLFW_OPENGL_PROFILE 0x00022008 #define GLFW_OPENGL_PROFILE 0x00022008
#define GLFW_CONTEXT_RELEASE_BEHAVIOR 0x00022009 #define GLFW_CONTEXT_RELEASE_BEHAVIOR 0x00022009
#define GLFW_NO_API 0
#define GLFW_OPENGL_API 0x00030001 #define GLFW_OPENGL_API 0x00030001
#define GLFW_OPENGL_ES_API 0x00030002 #define GLFW_OPENGL_ES_API 0x00030002

View File

@ -887,10 +887,11 @@ int _glfwPlatformCreateWindow(_GLFWwindow* window,
if (!createWindow(window, wndconfig)) if (!createWindow(window, wndconfig))
return GLFW_FALSE; return GLFW_FALSE;
if (!_glfwCreateContext(window, ctxconfig, fbconfig)) if (ctxconfig->api != GLFW_NO_API)
return GLFW_FALSE; {
if (!_glfwCreateContext(window, ctxconfig, fbconfig))
[window->nsgl.context setView:window->ns.view]; return GLFW_FALSE;
}
if (wndconfig->monitor) if (wndconfig->monitor)
{ {
@ -909,7 +910,8 @@ void _glfwPlatformDestroyWindow(_GLFWwindow* window)
if (window->monitor) if (window->monitor)
leaveFullscreenMode(window); leaveFullscreenMode(window);
_glfwDestroyContext(window); if (window->context.api != GLFW_NO_API)
_glfwDestroyContext(window);
[window->ns.object setDelegate:nil]; [window->ns.object setDelegate:nil];
[window->ns.delegate release]; [window->ns.delegate release];

View File

@ -89,7 +89,8 @@ static GLFWbool parseVersionString(int* api, int* major, int* minor, int* rev)
GLFWbool _glfwIsValidContextConfig(const _GLFWctxconfig* ctxconfig) 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) ctxconfig->api != GLFW_OPENGL_ES_API)
{ {
_glfwInputError(GLFW_INVALID_ENUM, "Invalid client 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) GLFWAPI void glfwMakeContextCurrent(GLFWwindow* handle)
{ {
_GLFWwindow* window = (_GLFWwindow*) handle; _GLFWwindow* window = (_GLFWwindow*) handle;
_GLFW_REQUIRE_INIT(); _GLFW_REQUIRE_INIT();
if (window->context.api == GLFW_NO_API)
{
_glfwInputError(GLFW_NO_WINDOW_CONTEXT, NULL);
return;
}
_glfwPlatformMakeContextCurrent(window); _glfwPlatformMakeContextCurrent(window);
} }
@ -549,7 +558,15 @@ GLFWAPI GLFWwindow* glfwGetCurrentContext(void)
GLFWAPI void glfwSwapBuffers(GLFWwindow* handle) GLFWAPI void glfwSwapBuffers(GLFWwindow* handle)
{ {
_GLFWwindow* window = (_GLFWwindow*) handle; _GLFWwindow* window = (_GLFWwindow*) handle;
_GLFW_REQUIRE_INIT(); _GLFW_REQUIRE_INIT();
if (window->context.api == GLFW_NO_API)
{
_glfwInputError(GLFW_NO_WINDOW_CONTEXT, NULL);
return;
}
_glfwPlatformSwapBuffers(window); _glfwPlatformSwapBuffers(window);
} }

View File

@ -112,12 +112,6 @@ static GLFWbool chooseFBConfigs(const _GLFWctxconfig* ctxconfig,
const EGLConfig n = nativeConfigs[i]; const EGLConfig n = nativeConfigs[i];
_GLFWfbconfig* u = usableConfigs + usableCount; _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 // Only consider RGB(A) EGLConfigs
if (!(getConfigAttrib(n, EGL_COLOR_BUFFER_TYPE) & EGL_RGB_BUFFER)) if (!(getConfigAttrib(n, EGL_COLOR_BUFFER_TYPE) & EGL_RGB_BUFFER))
continue; continue;
@ -126,6 +120,12 @@ static GLFWbool chooseFBConfigs(const _GLFWctxconfig* ctxconfig,
if (!(getConfigAttrib(n, EGL_SURFACE_TYPE) & EGL_WINDOW_BIT)) if (!(getConfigAttrib(n, EGL_SURFACE_TYPE) & EGL_WINDOW_BIT))
continue; 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->api == GLFW_OPENGL_ES_API)
{ {
if (ctxconfig->major == 1) if (ctxconfig->major == 1)
@ -311,55 +311,6 @@ int _glfwCreateContext(_GLFWwindow* window,
return GLFW_FALSE; 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 (ctxconfig->api == GLFW_OPENGL_ES_API)
{ {
if (!_glfw_eglBindAPI(EGL_OPENGL_ES_API)) if (!_glfw_eglBindAPI(EGL_OPENGL_ES_API))
@ -453,6 +404,19 @@ int _glfwCreateContext(_GLFWwindow* window,
return GLFW_FALSE; 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; window->egl.config = config;
// Load the appropriate client library // 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) if (window->egl.surface)
{ {
_glfw_eglDestroySurface(_glfw.egl.display, 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 // Analyzes the specified context for possible recreation
// //
#if defined(_GLFW_WIN32)
int _glfwAnalyzeContext(const _GLFWwindow* window, int _glfwAnalyzeContext(const _GLFWwindow* window,
const _GLFWctxconfig* ctxconfig, const _GLFWctxconfig* ctxconfig,
const _GLFWfbconfig* fbconfig) const _GLFWfbconfig* fbconfig)
{ {
#if defined(_GLFW_WIN32)
return _GLFW_RECREATION_NOT_NEEDED; 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)
{ {
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, _glfw_eglMakeCurrent(_glfw.egl.display,
window->egl.surface, window->egl.surface,
window->egl.surface, window->egl.surface,
@ -667,6 +648,13 @@ GLFWAPI EGLContext glfwGetEGLContext(GLFWwindow* handle)
{ {
_GLFWwindow* window = (_GLFWwindow*) handle; _GLFWwindow* window = (_GLFWwindow*) handle;
_GLFW_REQUIRE_INIT_OR_RETURN(EGL_NO_CONTEXT); _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; return window->egl.context;
} }
@ -674,6 +662,13 @@ GLFWAPI EGLSurface glfwGetEGLSurface(GLFWwindow* handle)
{ {
_GLFWwindow* window = (_GLFWwindow*) handle; _GLFWwindow* window = (_GLFWwindow*) handle;
_GLFW_REQUIRE_INIT_OR_RETURN(EGL_NO_SURFACE); _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; return window->egl.surface;
} }

View File

@ -147,10 +147,6 @@ typedef struct _GLFWcontextEGL
EGLContext context; EGLContext context;
EGLSurface surface; EGLSurface surface;
#if defined(_GLFW_X11)
XVisualInfo* visual;
#endif
void* client; void* client;
} _GLFWcontextEGL; } _GLFWcontextEGL;
@ -193,8 +189,15 @@ int _glfwCreateContext(_GLFWwindow* window,
const _GLFWctxconfig* ctxconfig, const _GLFWctxconfig* ctxconfig,
const _GLFWfbconfig* fbconfig); const _GLFWfbconfig* fbconfig);
void _glfwDestroyContext(_GLFWwindow* window); void _glfwDestroyContext(_GLFWwindow* window);
#if defined(_GLFW_WIN32)
int _glfwAnalyzeContext(const _GLFWwindow* window, int _glfwAnalyzeContext(const _GLFWwindow* window,
const _GLFWctxconfig* ctxconfig, const _GLFWctxconfig* ctxconfig,
const _GLFWfbconfig* fbconfig); 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_ #endif // _glfw3_egl_context_h_

View File

@ -79,10 +79,6 @@ static GLFWbool chooseFBConfig(const _GLFWfbconfig* desired, GLXFBConfig* result
const GLXFBConfig n = nativeConfigs[i]; const GLXFBConfig n = nativeConfigs[i];
_GLFWfbconfig* u = usableConfigs + usableCount; _GLFWfbconfig* u = usableConfigs + usableCount;
// Only consider GLXFBConfigs with associated visuals
if (!getFBConfigAttrib(n, GLX_VISUAL_ID))
continue;
// Only consider RGBA GLXFBConfigs // Only consider RGBA GLXFBConfigs
if (!(getFBConfigAttrib(n, GLX_RENDER_TYPE) & GLX_RGBA_BIT)) if (!(getFBConfigAttrib(n, GLX_RENDER_TYPE) & GLX_RGBA_BIT))
continue; continue;
@ -192,12 +188,12 @@ int _glfwInitContextAPI(void)
dlsym(_glfw.glx.handle, "glXQueryExtensionsString"); dlsym(_glfw.glx.handle, "glXQueryExtensionsString");
_glfw.glx.CreateNewContext = _glfw.glx.CreateNewContext =
dlsym(_glfw.glx.handle, "glXCreateNewContext"); dlsym(_glfw.glx.handle, "glXCreateNewContext");
_glfw.glx.GetVisualFromFBConfig =
dlsym(_glfw.glx.handle, "glXGetVisualFromFBConfig");
_glfw.glx.GetProcAddress = _glfw.glx.GetProcAddress =
dlsym(_glfw.glx.handle, "glXGetProcAddress"); dlsym(_glfw.glx.handle, "glXGetProcAddress");
_glfw.glx.GetProcAddressARB = _glfw.glx.GetProcAddressARB =
dlsym(_glfw.glx.handle, "glXGetProcAddressARB"); dlsym(_glfw.glx.handle, "glXGetProcAddressARB");
_glfw.glx.GetVisualFromFBConfig =
dlsym(_glfw.glx.handle, "glXGetVisualFromFBConfig");
if (!_glfw_glXQueryExtension(_glfw.x11.display, if (!_glfw_glXQueryExtension(_glfw.x11.display,
&_glfw.glx.errorBase, &_glfw.glx.errorBase,
@ -326,15 +322,6 @@ int _glfwCreateContext(_GLFWwindow* window,
return GLFW_FALSE; 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 (ctxconfig->api == GLFW_OPENGL_ES_API)
{ {
if (!_glfw.glx.ARB_create_context || if (!_glfw.glx.ARB_create_context ||
@ -485,12 +472,6 @@ int _glfwCreateContext(_GLFWwindow* window,
// //
void _glfwDestroyContext(_GLFWwindow* window) void _glfwDestroyContext(_GLFWwindow* window)
{ {
if (window->glx.visual)
{
XFree(window->glx.visual);
window->glx.visual = NULL;
}
if (window->glx.context) if (window->glx.context)
{ {
_glfw_glXDestroyContext(_glfw.x11.display, 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 ////// ////// GLFW platform API //////
@ -573,6 +585,13 @@ GLFWAPI GLXContext glfwGetGLXContext(GLFWwindow* handle)
{ {
_GLFWwindow* window = (_GLFWwindow*) handle; _GLFWwindow* window = (_GLFWwindow*) handle;
_GLFW_REQUIRE_INIT_OR_RETURN(NULL); _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; return window->glx.context;
} }

View File

@ -111,10 +111,7 @@ typedef XVisualInfo* (*PFNGLXGETVISUALFROMFBCONFIGPROC)(Display*,GLXFBConfig);
// //
typedef struct _GLFWcontextGLX typedef struct _GLFWcontextGLX
{ {
// Rendering context
GLXContext context; GLXContext context;
// Visual of selected GLXFBConfig
XVisualInfo* visual;
} _GLFWcontextGLX; } _GLFWcontextGLX;
@ -171,5 +168,8 @@ int _glfwCreateContext(_GLFWwindow* window,
const _GLFWctxconfig* ctxconfig, const _GLFWctxconfig* ctxconfig,
const _GLFWfbconfig* fbconfig); const _GLFWfbconfig* fbconfig);
void _glfwDestroyContext(_GLFWwindow* window); void _glfwDestroyContext(_GLFWwindow* window);
GLFWbool _glfwChooseVisual(const _GLFWctxconfig* ctxconfig,
const _GLFWfbconfig* fbconfig,
Visual** visual, int* depth);
#endif // _glfw3_glx_context_h_ #endif // _glfw3_glx_context_h_

View File

@ -72,6 +72,8 @@ static const char* getErrorString(int error)
return "A platform-specific error occurred"; return "A platform-specific error occurred";
case GLFW_FORMAT_UNAVAILABLE: case GLFW_FORMAT_UNAVAILABLE:
return "The requested format is 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"; return "ERROR: UNKNOWN ERROR TOKEN PASSED TO glfwErrorString";

View File

@ -462,8 +462,11 @@ int _glfwPlatformCreateWindow(_GLFWwindow* window,
const _GLFWctxconfig* ctxconfig, const _GLFWctxconfig* ctxconfig,
const _GLFWfbconfig* fbconfig) const _GLFWfbconfig* fbconfig)
{ {
if (!_glfwCreateContext(window, ctxconfig, fbconfig)) if (ctxconfig->api != GLFW_NO_API)
return GLFW_FALSE; {
if (!_glfwCreateContext(window, ctxconfig, fbconfig))
return GLFW_FALSE;
}
if (wndconfig->monitor) if (wndconfig->monitor)
{ {

View File

@ -219,6 +219,7 @@ int _glfwCreateContext(_GLFWwindow* window,
return GLFW_FALSE; return GLFW_FALSE;
} }
[window->nsgl.context setView:window->ns.view];
return GLFW_TRUE; return GLFW_TRUE;
} }
@ -291,6 +292,13 @@ GLFWAPI id glfwGetNSGLContext(GLFWwindow* handle)
{ {
_GLFWwindow* window = (_GLFWwindow*) handle; _GLFWwindow* window = (_GLFWwindow*) handle;
_GLFW_REQUIRE_INIT_OR_RETURN(nil); _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; return window->nsgl.context;
} }

View File

@ -672,6 +672,13 @@ GLFWAPI HGLRC glfwGetWGLContext(GLFWwindow* handle)
{ {
_GLFWwindow* window = (_GLFWwindow*) handle; _GLFWwindow* window = (_GLFWwindow*) handle;
_GLFW_REQUIRE_INIT_OR_RETURN(NULL); _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; return window->wgl.context;
} }

View File

@ -665,10 +665,7 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg,
// Creates the GLFW window and rendering context // Creates the GLFW window and rendering context
// //
static GLFWbool createWindow(_GLFWwindow* window, static int createWindow(_GLFWwindow* window, const _GLFWwndconfig* wndconfig)
const _GLFWwndconfig* wndconfig,
const _GLFWctxconfig* ctxconfig,
const _GLFWfbconfig* fbconfig)
{ {
int xpos, ypos, fullWidth, fullHeight; int xpos, ypos, fullWidth, fullHeight;
WCHAR* wideTitle; WCHAR* wideTitle;
@ -742,9 +739,6 @@ static GLFWbool createWindow(_GLFWwindow* window,
DragAcceptFiles(window->win32.handle, TRUE); DragAcceptFiles(window->win32.handle, TRUE);
if (!_glfwCreateContext(window, ctxconfig, fbconfig))
return GLFW_FALSE;
window->win32.minwidth = GLFW_DONT_CARE; window->win32.minwidth = GLFW_DONT_CARE;
window->win32.minheight = GLFW_DONT_CARE; window->win32.minheight = GLFW_DONT_CARE;
window->win32.maxwidth = GLFW_DONT_CARE; window->win32.maxwidth = GLFW_DONT_CARE;
@ -759,8 +753,6 @@ static GLFWbool createWindow(_GLFWwindow* window,
// //
static void destroyWindow(_GLFWwindow* window) static void destroyWindow(_GLFWwindow* window)
{ {
_glfwDestroyContext(window);
if (window->win32.handle) if (window->win32.handle)
{ {
DestroyWindow(window->win32.handle); DestroyWindow(window->win32.handle);
@ -830,43 +822,53 @@ int _glfwPlatformCreateWindow(_GLFWwindow* window,
{ {
int status; int status;
if (!createWindow(window, wndconfig, ctxconfig, fbconfig)) if (!createWindow(window, wndconfig))
return GLFW_FALSE; return GLFW_FALSE;
status = _glfwAnalyzeContext(window, ctxconfig, fbconfig); if (ctxconfig->api != GLFW_NO_API)
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 if (!_glfwCreateContext(window, ctxconfig, fbconfig))
// 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))
return GLFW_FALSE; 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) if (window->monitor)
@ -884,6 +886,9 @@ void _glfwPlatformDestroyWindow(_GLFWwindow* window)
if (window->monitor) if (window->monitor)
leaveFullscreenMode(window); leaveFullscreenMode(window);
if (window->context.api != GLFW_NO_API)
_glfwDestroyContext(window);
destroyWindow(window); destroyWindow(window);
} }

View File

@ -142,6 +142,15 @@ GLFWAPI GLFWwindow* glfwCreateWindow(int width, int height,
wndconfig.monitor = (_GLFWmonitor*) monitor; wndconfig.monitor = (_GLFWmonitor*) monitor;
ctxconfig.share = (_GLFWwindow*) share; 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) if (wndconfig.monitor)
{ {
wndconfig.resizable = GLFW_TRUE; wndconfig.resizable = GLFW_TRUE;
@ -181,26 +190,29 @@ GLFWAPI GLFWwindow* glfwCreateWindow(int width, int height,
return NULL; return NULL;
} }
_glfwPlatformMakeContextCurrent(window); if (ctxconfig.api != GLFW_NO_API)
// Retrieve the actual (as opposed to requested) context attributes
if (!_glfwRefreshContextAttribs(&ctxconfig))
{ {
glfwDestroyWindow((GLFWwindow*) window); _glfwPlatformMakeContextCurrent(window);
_glfwPlatformMakeContextCurrent(previous);
return NULL;
}
// Verify the context against the requested parameters // Retrieve the actual (as opposed to requested) context attributes
if (!_glfwIsValidContext(&ctxconfig)) if (!_glfwRefreshContextAttribs(&ctxconfig))
{ {
glfwDestroyWindow((GLFWwindow*) window); glfwDestroyWindow((GLFWwindow*) window);
_glfwPlatformMakeContextCurrent(previous); _glfwPlatformMakeContextCurrent(previous);
return NULL; return NULL;
} }
// Restore the previously current context (or NULL) // Verify the context against the requested parameters
_glfwPlatformMakeContextCurrent(previous); if (!_glfwIsValidContext(&ctxconfig))
{
glfwDestroyWindow((GLFWwindow*) window);
_glfwPlatformMakeContextCurrent(previous);
return NULL;
}
// Restore the previously current context (or NULL)
_glfwPlatformMakeContextCurrent(previous);
}
if (wndconfig.monitor) if (wndconfig.monitor)
{ {

View File

@ -238,8 +238,11 @@ int _glfwPlatformCreateWindow(_GLFWwindow* window,
const _GLFWctxconfig* ctxconfig, const _GLFWctxconfig* ctxconfig,
const _GLFWfbconfig* fbconfig) const _GLFWfbconfig* fbconfig)
{ {
if (!_glfwCreateContext(window, ctxconfig, fbconfig)) if (ctxconfig->api != GLFW_NO_API)
return GLFW_FALSE; {
if (!_glfwCreateContext(window, ctxconfig, fbconfig))
return GLFW_FALSE;
}
if (!createSurface(window, wndconfig)) if (!createSurface(window, wndconfig))
return GLFW_FALSE; return GLFW_FALSE;

View File

@ -62,10 +62,8 @@
#include "xkb_unicode.h" #include "xkb_unicode.h"
#if defined(_GLFW_GLX) #if defined(_GLFW_GLX)
#define _GLFW_X11_CONTEXT_VISUAL window->glx.visual
#include "glx_context.h" #include "glx_context.h"
#elif defined(_GLFW_EGL) #elif defined(_GLFW_EGL)
#define _GLFW_X11_CONTEXT_VISUAL window->egl.visual
#define _GLFW_EGL_NATIVE_WINDOW window->x11.handle #define _GLFW_EGL_NATIVE_WINDOW window->x11.handle
#define _GLFW_EGL_NATIVE_DISPLAY _glfw.x11.display #define _GLFW_EGL_NATIVE_DISPLAY _glfw.x11.display
#include "egl_context.h" #include "egl_context.h"

View File

@ -248,17 +248,16 @@ static char** parseUriList(char* text, int* count)
// Create the X11 window (and its colormap) // Create the X11 window (and its colormap)
// //
static GLFWbool createWindow(_GLFWwindow* window, 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 // Every window needs a colormap
// Create one based on the visual used by the current context // Create one based on the visual used by the current context
// TODO: Decouple this from context creation // TODO: Decouple this from context creation
window->x11.colormap = XCreateColormap(_glfw.x11.display, window->x11.colormap = XCreateColormap(_glfw.x11.display,
_glfw.x11.root, _glfw.x11.root,
vi->visual, visual,
AllocNone); AllocNone);
// Create the actual window // Create the actual window
@ -279,10 +278,10 @@ static GLFWbool createWindow(_GLFWwindow* window,
_glfw.x11.root, _glfw.x11.root,
0, 0, 0, 0,
wndconfig->width, wndconfig->height, wndconfig->width, wndconfig->height,
0, // Border width 0, // Border width
vi->depth, // Color depth depth, // Color depth
InputOutput, InputOutput,
vi->visual, visual,
wamask, wamask,
&wa); &wa);
@ -1467,12 +1466,21 @@ int _glfwPlatformCreateWindow(_GLFWwindow* window,
const _GLFWctxconfig* ctxconfig, const _GLFWctxconfig* ctxconfig,
const _GLFWfbconfig* fbconfig) const _GLFWfbconfig* fbconfig)
{ {
if (!_glfwCreateContext(window, ctxconfig, fbconfig)) Visual* visual;
int depth;
if (!_glfwChooseVisual(ctxconfig, fbconfig, &visual, &depth))
return GLFW_FALSE; return GLFW_FALSE;
if (!createWindow(window, wndconfig)) if (!createWindow(window, wndconfig, visual, depth))
return GLFW_FALSE; return GLFW_FALSE;
if (ctxconfig->api != GLFW_NO_API)
{
if (!_glfwCreateContext(window, ctxconfig, fbconfig))
return GLFW_FALSE;
}
if (wndconfig->monitor) if (wndconfig->monitor)
{ {
_glfwPlatformShowWindow(window); _glfwPlatformShowWindow(window);
@ -1493,7 +1501,8 @@ void _glfwPlatformDestroyWindow(_GLFWwindow* window)
window->x11.ic = NULL; window->x11.ic = NULL;
} }
_glfwDestroyContext(window); if (window->context.api != GLFW_NO_API)
_glfwDestroyContext(window);
if (window->x11.handle) if (window->x11.handle)
{ {