diff options
author | Brian Paul <[email protected]> | 2014-05-20 14:56:41 -0600 |
---|---|---|
committer | José Fonseca <[email protected]> | 2014-05-30 18:52:39 +0100 |
commit | bd36cbfa5aa31817a04335a7c364224d0db64428 (patch) | |
tree | 272c4198146d3547010f8801b6d4738ee6524f75 | |
parent | fa55c2402c11aaccfc30b198b22b136142574a9c (diff) |
st/wgl: fix implementation of wglCreateContextAttribsARB()
wglCreateContextAttribsARB() didn't work previously since it returned
a context ID that wasn't allocated by OPENGL32.DLL. So if that context
ID was later passed to wglMakeCurrent(), etc. it was rejected.
Now when wglCreateContextAttribsARB() is called we actually call
wglCreateContext() in order to get a valid context ID. Then we
replace the context data which was created with new context data
which reflects the arguments passed to wglCreateContextAttribsARB().
If there were a DrvCreateContextAttribs() function in the ICD this
work-around wouldn't be necessary.
Reviewed-by: Charmaine Lee <[email protected]>
Conflicts:
src/gallium/state_trackers/wgl/stw_ext_extensionsstring.c
src/gallium/state_trackers/wgl/stw_getprocaddress.c
-rw-r--r-- | src/gallium/state_trackers/wgl/stw_context.c | 47 | ||||
-rw-r--r-- | src/gallium/state_trackers/wgl/stw_context.h | 7 | ||||
-rw-r--r-- | src/gallium/state_trackers/wgl/stw_ext_context.c | 104 |
3 files changed, 136 insertions, 22 deletions
diff --git a/src/gallium/state_trackers/wgl/stw_context.c b/src/gallium/state_trackers/wgl/stw_context.c index 43186fa2690..99debfddadc 100644 --- a/src/gallium/state_trackers/wgl/stw_context.c +++ b/src/gallium/state_trackers/wgl/stw_context.c @@ -128,16 +128,23 @@ DrvCreateLayerContext( INT iLayerPlane ) { return stw_create_context_attribs(hdc, iLayerPlane, 0, 1, 0, 0, - WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB); + WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB, + 0); } + +/** + * Called via DrvCreateContext(), DrvCreateLayerContext() and + * wglCreateContextAttribsARB() to actually create a rendering context. + * \param handle the desired DHGLRC handle to use for the context, or zero + * if a new handle should be allocated. + * \return the handle for the new context or zero if there was a problem. + */ DHGLRC -stw_create_context_attribs( - HDC hdc, - INT iLayerPlane, - DHGLRC hShareContext, - int majorVersion, int minorVersion, - int contextFlags, int profileMask) +stw_create_context_attribs(HDC hdc, INT iLayerPlane, DHGLRC hShareContext, + int majorVersion, int minorVersion, + int contextFlags, int profileMask, + DHGLRC handle) { int iPixelFormat; struct stw_framebuffer *fb; @@ -236,7 +243,31 @@ stw_create_context_attribs( } pipe_mutex_lock( stw_dev->ctx_mutex ); - ctx->dhglrc = handle_table_add(stw_dev->ctx_table, ctx); + if (handle) { + /* We're replacing the context data for this handle. See the + * wglCreateContextAttribsARB() function. + */ + struct stw_context *old_ctx = + stw_lookup_context_locked((unsigned) handle); + if (old_ctx) { + /* free the old context data associated with this handle */ + if (old_ctx->hud) { + hud_destroy(old_ctx->hud); + } + ctx->st->destroy(old_ctx->st); + FREE(old_ctx); + } + + /* replace table entry */ + handle_table_set(stw_dev->ctx_table, (unsigned) handle, ctx); + } + else { + /* create new table entry */ + handle = (DHGLRC) handle_table_add(stw_dev->ctx_table, ctx); + } + + ctx->dhglrc = handle; + pipe_mutex_unlock( stw_dev->ctx_mutex ); if (!ctx->dhglrc) goto no_hglrc; diff --git a/src/gallium/state_trackers/wgl/stw_context.h b/src/gallium/state_trackers/wgl/stw_context.h index e03ceb806e6..c66c166de2e 100644 --- a/src/gallium/state_trackers/wgl/stw_context.h +++ b/src/gallium/state_trackers/wgl/stw_context.h @@ -46,8 +46,11 @@ struct stw_context struct hud_context *hud; }; -DHGLRC stw_create_context_attribs( HDC hdc, INT iLayerPlane, DHGLRC hShareContext, - int majorVersion, int minorVersion, int contextFlags, int profileMask ); +DHGLRC stw_create_context_attribs(HDC hdc, INT iLayerPlane, + DHGLRC hShareContext, + int majorVersion, int minorVersion, + int contextFlags, int profileMask, + DHGLRC handle); DHGLRC stw_get_current_context( void ); diff --git a/src/gallium/state_trackers/wgl/stw_ext_context.c b/src/gallium/state_trackers/wgl/stw_ext_context.c index 4dd00bb4f94..0049896b8df 100644 --- a/src/gallium/state_trackers/wgl/stw_ext_context.c +++ b/src/gallium/state_trackers/wgl/stw_ext_context.c @@ -22,6 +22,8 @@ * OTHER DEALINGS IN THE SOFTWARE. */ +#include <stdio.h> +#include <assert.h> #include <windows.h> #define WGL_WGLEXT_PROTOTYPES @@ -31,10 +33,31 @@ #include "stw_icd.h" #include "stw_context.h" +#include "stw_device.h" + +/** + * The implementation of this function is tricky. The OPENGL32.DLL library + * remaps the context IDs returned by our stw_create_context_attribs() + * function to different values returned to the caller of wglCreateContext(). + * That is, DHGLRC (driver) handles are not equivalent to HGLRC (public) + * handles. + * + * So we need to generate a new HGLRC ID here. We do that by calling + * the regular wglCreateContext() function. Then, we replace the newly- + * created stw_context with a new stw_context that reflects the arguments + * to this function. + */ HGLRC WINAPI wglCreateContextAttribsARB(HDC hDC, HGLRC hShareContext, const int *attribList) { + typedef HGLRC (*wglCreateContext_t)(HDC hdc); + typedef BOOL (*wglDeleteContext_t)(HGLRC hglrc); + HGLRC context; + static HMODULE opengl_lib = 0; + static wglCreateContext_t wglCreateContext_func = 0; + static wglDeleteContext_t wglDeleteContext_func = 0; + int majorVersion = 1, minorVersion = 0, layerPlane = 0; int contextFlags = 0x0; int profileMask = WGL_CONTEXT_CORE_PROFILE_BIT_ARB; @@ -67,7 +90,7 @@ wglCreateContextAttribsARB(HDC hDC, HGLRC hShareContext, const int *attribList) default: /* bad attribute */ SetLastError(ERROR_INVALID_PARAMETER); - return NULL; + return 0; } } } @@ -77,46 +100,103 @@ wglCreateContextAttribsARB(HDC hDC, HGLRC hShareContext, const int *attribList) case 1: if (minorVersion < 0 || minorVersion > 5) { SetLastError(ERROR_INVALID_VERSION_ARB); - return NULL; + return 0; } break; case 2: if (minorVersion < 0 || minorVersion > 1) { SetLastError(ERROR_INVALID_VERSION_ARB); - return NULL; + return 0; } break; case 3: if (minorVersion < 0 || minorVersion > 3) { SetLastError(ERROR_INVALID_VERSION_ARB); - return NULL; + return 0; } break; case 4: if (minorVersion < 0 || minorVersion > 2) { SetLastError(ERROR_INVALID_VERSION_ARB); - return NULL; + return 0; } break; default: - return NULL; + return 0; } if ((contextFlags & WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB) && majorVersion < 3) { SetLastError(ERROR_INVALID_VERSION_ARB); - return NULL; + return 0; } /* check profileMask */ if (profileMask != WGL_CONTEXT_CORE_PROFILE_BIT_ARB && profileMask != WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB) { SetLastError(ERROR_INVALID_PROFILE_ARB); - return NULL; + return 0; + } + + /* Get pointer to OPENGL32.DLL's wglCreate/DeleteContext() functions */ + if (opengl_lib == 0) { + /* Open the OPENGL32.DLL library */ + opengl_lib = LoadLibraryA("OPENGL32.DLL"); + if (!opengl_lib) { + fprintf(stderr, "wgl: LoadLibrary(OPENGL32.DLL) failed\n"); + fflush(stderr); + return 0; + } + + /* Get pointer to wglCreateContext() function */ + wglCreateContext_func = (wglCreateContext_t) + GetProcAddress(opengl_lib, "wglCreateContext"); + if (!wglCreateContext_func) { + fprintf(stderr, "wgl: failed to get wglCreateContext()\n"); + fflush(stderr); + return 0; + } + + /* Get pointer to wglDeleteContext() function */ + wglDeleteContext_func = (wglDeleteContext_t) + GetProcAddress(opengl_lib, "wglDeleteContext"); + if (!wglDeleteContext_func) { + fprintf(stderr, "wgl: failed to get wglDeleteContext()\n"); + fflush(stderr); + return 0; + } + } + + /* Call wglCreateContext to get a valid context ID */ + context = wglCreateContext_func(hDC); + + if (context) { + /* Now replace the context we just created with a new one that reflects + * the attributes passed to this function. + */ + DHGLRC dhglrc, c, share_dhglrc = 0; + + /* Convert public HGLRC to driver DHGLRC */ + if (stw_dev && stw_dev->callbacks.wglCbGetDhglrc) { + dhglrc = stw_dev->callbacks.wglCbGetDhglrc(context); + if (hShareContext) + share_dhglrc = stw_dev->callbacks.wglCbGetDhglrc(hShareContext); + } + else { + /* not using ICD */ + dhglrc = (DHGLRC) context; + share_dhglrc = (DHGLRC) hShareContext; + } + + c = stw_create_context_attribs(hDC, layerPlane, share_dhglrc, + majorVersion, minorVersion, + contextFlags, profileMask, + dhglrc); + if (!c) { + wglDeleteContext_func(context); + context = 0; + } } - return (HGLRC) stw_create_context_attribs(hDC, layerPlane, - (DHGLRC) (UINT_PTR) hShareContext, - majorVersion, minorVersion, - contextFlags, profileMask); + return context; } |