From a08bfd9891992710a43db882c01a7131ae732fd8 Mon Sep 17 00:00:00 2001 From: Doug Binks Date: Wed, 3 Jun 2020 19:46:22 +0100 Subject: [PATCH] User Contexts API with Win32 implementation. --- include/GLFW/glfw3.h | 27 ++++++++++++++++++++ src/context.c | 23 +++++++++++++++++ src/internal.h | 6 +++++ src/wgl_context.c | 56 +++++++++++++++++++++++++++++++++++++++++ src/wgl_context.h | 5 ++++ tests/CMakeLists.txt | 3 ++- tests/usercontext.c | 60 ++++++++++++++++++++++++++++++++++++++++++++ 7 files changed, 179 insertions(+), 1 deletion(-) create mode 100644 tests/usercontext.c diff --git a/include/GLFW/glfw3.h b/include/GLFW/glfw3.h index 6db5b579..afc6ca0c 100644 --- a/include/GLFW/glfw3.h +++ b/include/GLFW/glfw3.h @@ -1276,6 +1276,18 @@ typedef struct GLFWmonitor GLFWmonitor; */ typedef struct GLFWwindow GLFWwindow; +/*! @brief Opaque user OpenGL context object. + * + * Opaque user OpenGL context object. + * + * @see @ref user_gl_context + * + * @since Added in version 3.3. + * + * @ingroup window + */ +typedef struct GLFWusercontext GLFWusercontext; + /*! @brief Opaque cursor object. * * Opaque cursor object. @@ -5772,6 +5784,21 @@ GLFWAPI int glfwExtensionSupported(const char* extension); */ GLFWAPI GLFWglproc glfwGetProcAddress(const char* procname); +/*! @brief Create a new OpenGL user context for a window +* +*/ +GLFWAPI GLFWusercontext* glfwCreateUserContext(GLFWwindow* window); + +/*! @brief Delete an OpenGL user context +* +*/ +GLFWAPI void glfwDestroyUserContext(GLFWusercontext* context); + +/*! @brief Make an OpenGL user context +* +*/ +GLFWAPI void glfwMakeUserContextCurrent(GLFWusercontext* context); + /*! @brief Returns whether the Vulkan loader and an ICD have been found. * * This function returns whether the Vulkan loader and any minimally functional diff --git a/src/context.c b/src/context.c index 48311e5f..c6a808cb 100644 --- a/src/context.c +++ b/src/context.c @@ -758,3 +758,26 @@ GLFWAPI GLFWglproc glfwGetProcAddress(const char* procname) return window->context.getProcAddress(procname); } +GLFWAPI GLFWusercontext* glfwCreateUserContext(GLFWwindow* handle) +{ + _GLFWusercontext* context; + _GLFWwindow* window = (_GLFWwindow*)handle; + + context = _glfwPlatformCreateUserContext(window); + + return (GLFWusercontext*)context; +} + +GLFWAPI void glfwDestroyUserContext(GLFWusercontext* handle) +{ + _GLFWusercontext* context = (_GLFWusercontext*)handle; + + _glfwPlatformDestroyUserContext(context); +} + +GLFWAPI void glfwMakeUserContextCurrent(GLFWusercontext* handle) +{ + _GLFWusercontext* context = (_GLFWusercontext*)handle; + + _glfwPlatformMakeUserContextCurrent(context); +} diff --git a/src/internal.h b/src/internal.h index 6d7587c8..a16c8a8c 100644 --- a/src/internal.h +++ b/src/internal.h @@ -75,6 +75,7 @@ typedef struct _GLFWmapping _GLFWmapping; typedef struct _GLFWjoystick _GLFWjoystick; typedef struct _GLFWtls _GLFWtls; typedef struct _GLFWmutex _GLFWmutex; +typedef struct _GLFWusercontext _GLFWusercontext; typedef void (* _GLFWmakecontextcurrentfun)(_GLFWwindow*); typedef void (* _GLFWswapbuffersfun)(_GLFWwindow*); @@ -681,6 +682,11 @@ void _glfwPlatformWaitEvents(void); void _glfwPlatformWaitEventsTimeout(double timeout); void _glfwPlatformPostEmptyEvent(void); +_GLFWusercontext* _glfwPlatformCreateUserContext(_GLFWwindow* window); +void _glfwPlatformDestroyUserContext(_GLFWusercontext* context); +void _glfwPlatformMakeUserContextCurrent(_GLFWusercontext* context); + + void _glfwPlatformGetRequiredInstanceExtensions(char** extensions); int _glfwPlatformGetPhysicalDevicePresentationSupport(VkInstance instance, VkPhysicalDevice device, diff --git a/src/wgl_context.c b/src/wgl_context.c index 4f9a6ffe..16bd167c 100644 --- a/src/wgl_context.c +++ b/src/wgl_context.c @@ -776,6 +776,62 @@ GLFWbool _glfwCreateContextWGL(_GLFWwindow* window, #undef setAttrib +////////////////////////////////////////////////////////////////////////// +////// GLFW platform API ////// +////////////////////////////////////////////////////////////////////////// + +_GLFWusercontext* _glfwPlatformCreateUserContext(_GLFWwindow* window) +{ + _GLFWusercontext* context; + context = calloc(1, sizeof(_GLFWusercontext)); + + context->handle = wglCreateContext(window->context.wgl.dc); + context->window = window; + if (!context->handle) + { + _glfwInputErrorWin32(GLFW_VERSION_UNAVAILABLE, + "WGL: Failed to create user OpenGL context"); + free(context); + return GLFW_FALSE; + } + + if (!wglShareLists(window->context.wgl.handle,context->handle)) + { + _glfwInputErrorWin32(GLFW_PLATFORM_ERROR, + "WGL: Failed to enable sharing with window OpenGL context and user context"); + free(context); + return GLFW_FALSE; + } + return context; +} + +void _glfwPlatformDestroyUserContext(_GLFWusercontext* context) +{ + wglDeleteContext(context->handle); + free(context); +} + +void _glfwPlatformMakeUserContextCurrent(_GLFWusercontext* context) +{ + if(context) + { + if(!wglMakeCurrent(context->window->context.wgl.dc,context->handle)) + { + _glfwInputErrorWin32(GLFW_PLATFORM_ERROR, + "WGL: Failed to set current user context"); + } + } + else + { + if (!wglMakeCurrent(NULL, NULL)) + { + _glfwInputErrorWin32(GLFW_PLATFORM_ERROR, + "WGL: Failed to clear current context"); + } + } +} + + ////////////////////////////////////////////////////////////////////////// ////// GLFW native API ////// ////////////////////////////////////////////////////////////////////////// diff --git a/src/wgl_context.h b/src/wgl_context.h index 2cf7e4e5..6cb6d050 100644 --- a/src/wgl_context.h +++ b/src/wgl_context.h @@ -151,6 +151,11 @@ typedef struct _GLFWlibraryWGL } _GLFWlibraryWGL; +typedef struct _GLFWusercontext +{ + _GLFWwindow* window; + HGLRC handle; +} _GLFWusercontext; GLFWbool _glfwInitWGL(void); void _glfwTerminateWGL(void); diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index e36ed56c..d79e5b87 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -28,6 +28,7 @@ add_executable(iconify iconify.c ${GETOPT} ${GLAD_GL}) add_executable(monitors monitors.c ${GETOPT} ${GLAD_GL}) add_executable(reopen reopen.c ${GLAD_GL}) add_executable(cursor cursor.c ${GLAD_GL}) +add_executable(usercontext usercontext.c ${GLAD_GL}) add_executable(empty WIN32 MACOSX_BUNDLE empty.c ${TINYCTHREAD} ${GLAD_GL}) add_executable(gamma WIN32 MACOSX_BUNDLE gamma.c ${GLAD_GL}) @@ -52,7 +53,7 @@ endif() set(GUI_ONLY_BINARIES empty gamma icon inputlag joysticks opacity tearing threads timeout title triangle-vulkan windows) set(CONSOLE_BINARIES clipboard events msaa glfwinfo iconify monitors reopen - cursor) + cursor usercontext) set_target_properties(${GUI_ONLY_BINARIES} ${CONSOLE_BINARIES} PROPERTIES C_STANDARD 99 diff --git a/tests/usercontext.c b/tests/usercontext.c new file mode 100644 index 00000000..58916430 --- /dev/null +++ b/tests/usercontext.c @@ -0,0 +1,60 @@ +#include +#include + +int main(void) +{ + GLFWwindow* window; + GLFWusercontext* usercontext; + + /* Initialize the library */ + if (!glfwInit()) + return -1; + + /* Create a windowed mode window and its OpenGL context */ + window = glfwCreateWindow(640, 480, "User Context", NULL, NULL); + if (!window) + { + glfwTerminate(); + return -1; + } + + /* Make the window's context current */ + glfwMakeContextCurrent(window); + gladLoadGL(glfwGetProcAddress); + + /* make a new context */ + usercontext = glfwCreateUserContext(window); + if (!usercontext) + { + glfwTerminate(); + return -1; + } + + /* set the user context current */ + glfwMakeContextCurrent(NULL); + glfwMakeUserContextCurrent(usercontext); + + /* set the window context current */ + glfwMakeUserContextCurrent(NULL); + glfwMakeContextCurrent(window); + + glClearColor( 0.4f, 0.3f, 0.4f, 0.0f ); + + + /* Loop until the user closes the window */ + while (!glfwWindowShouldClose(window)) + { + /* Render here */ + glClear(GL_COLOR_BUFFER_BIT); + + /* Swap front and back buffers */ + glfwSwapBuffers(window); + + /* Poll for and process events */ + glfwPollEvents(); + } + + glfwDestroyUserContext(usercontext); + glfwTerminate(); + return 0; +} \ No newline at end of file