diff options
Diffstat (limited to 'src/gallium/state_trackers/wgl/stw_ext_context.c')
-rw-r--r-- | src/gallium/state_trackers/wgl/stw_ext_context.c | 104 |
1 files changed, 92 insertions, 12 deletions
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; } |