Mesa (master): st/wgl: fix implementation of wglCreateContextAttribsARB()

Jose Fonseca jrfonseca at kemper.freedesktop.org
Fri May 30 17:52:53 UTC 2014


Module: Mesa
Branch: master
Commit: bd36cbfa5aa31817a04335a7c364224d0db64428
URL:    http://cgit.freedesktop.org/mesa/mesa/commit/?id=bd36cbfa5aa31817a04335a7c364224d0db64428

Author: Brian Paul <brianp at vmware.com>
Date:   Tue May 20 14:56:41 2014 -0600

st/wgl: fix implementation of wglCreateContextAttribsARB()

wglCreateContextAttribsARB() didn't work previously since it returned
a context ID that wasn't allocated by OPENGL32.DLL.  So if that context
ID was later passed to wglMakeCurrent(), etc. it was rejected.

Now when wglCreateContextAttribsARB() is called we actually call
wglCreateContext() in order to get a valid context ID.  Then we
replace the context data which was created with new context data
which reflects the arguments passed to wglCreateContextAttribsARB().

If there were a DrvCreateContextAttribs() function in the ICD this
work-around wouldn't be necessary.

Reviewed-by: Charmaine Lee <charmainel at vmware.com>

Conflicts:
	src/gallium/state_trackers/wgl/stw_ext_extensionsstring.c
	src/gallium/state_trackers/wgl/stw_getprocaddress.c

---

 src/gallium/state_trackers/wgl/stw_context.c     |   47 ++++++++--
 src/gallium/state_trackers/wgl/stw_context.h     |    7 +-
 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 43186fa..99debfd 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 e03ceb8..c66c166 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 4dd00bb..0049896 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;
 }




More information about the mesa-commit mailing list