diff options
-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; } |