mirror of
https://github.com/glfw/glfw.git
synced 2024-11-22 10:05:10 +00:00
Add GLFW_NO_API for creating context-less windows
This commit is contained in:
parent
0fda5b7b80
commit
496f559c9a
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
@ -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];
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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_
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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_
|
||||
|
@ -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";
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
46
src/window.c
46
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)
|
||||
{
|
||||
|
@ -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;
|
||||
|
@ -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"
|
||||
|
@ -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)
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user