summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/gallium/state_trackers/wgl/stw_context.c47
-rw-r--r--src/gallium/state_trackers/wgl/stw_context.h7
-rw-r--r--src/gallium/state_trackers/wgl/stw_ext_context.c104
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;
}