summaryrefslogtreecommitdiff
path: root/src/gallium/state_trackers/wgl/stw_ext_context.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/gallium/state_trackers/wgl/stw_ext_context.c')
-rw-r--r--src/gallium/state_trackers/wgl/stw_ext_context.c104
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;
}