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;
}
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;
* OTHER DEALINGS IN THE SOFTWARE.
*/
+#include <stdio.h>
+#include <assert.h>
#include <windows.h>
#define WGL_WGLEXT_PROTOTYPES
#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;
default:
/* bad attribute */
SetLastError(ERROR_INVALID_PARAMETER);
- return NULL;
+ return 0;
}
}
}
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;
}