[Mesa-dev] [PATCH 2/3] st/wgl: add support for WGL_ARB_make_current_read

Brian Paul brianp at vmware.com
Fri Mar 24 21:42:22 UTC 2017


This adds the wglMakeContextCurrentARB() and wglMakeContextCurrentARB()
functions.
---
 src/gallium/state_trackers/wgl/stw_context.c       | 77 ++++++++++++++++++----
 src/gallium/state_trackers/wgl/stw_context.h       |  5 +-
 src/gallium/state_trackers/wgl/stw_ext_context.c   | 15 +++++
 .../state_trackers/wgl/stw_ext_extensionsstring.c  |  1 +
 .../state_trackers/wgl/stw_ext_rendertexture.c     |  5 +-
 .../state_trackers/wgl/stw_getprocaddress.c        |  3 +
 src/gallium/state_trackers/wgl/stw_wgl.c           |  7 ++
 src/gallium/state_trackers/wgl/stw_wgl.h           | 10 +++
 8 files changed, 107 insertions(+), 16 deletions(-)

diff --git a/src/gallium/state_trackers/wgl/stw_context.c b/src/gallium/state_trackers/wgl/stw_context.c
index 85cffa6..18273ac 100644
--- a/src/gallium/state_trackers/wgl/stw_context.c
+++ b/src/gallium/state_trackers/wgl/stw_context.c
@@ -187,6 +187,7 @@ stw_create_context_attribs(HDC hdc, INT iLayerPlane, DHGLRC hShareContext,
       goto no_ctx;
 
    ctx->hdc = hdc;
+   ctx->hReadDC = hdc;
    ctx->iPixelFormat = iPixelFormat;
    ctx->shared = shareCtx != NULL;
 
@@ -357,7 +358,7 @@ DrvReleaseContext(DHGLRC dhglrc)
    if (ctx != stw_current_context())
       return FALSE;
 
-   if (stw_make_current( NULL, 0 ) == FALSE)
+   if (stw_make_current( NULL, NULL, 0 ) == FALSE)
       return FALSE;
 
    return TRUE;
@@ -389,9 +390,20 @@ stw_get_current_dc( void )
    return ctx->hdc;
 }
 
+HDC
+stw_get_current_read_dc( void )
+{
+   struct stw_context *ctx;
+
+   ctx = stw_current_context();
+   if (!ctx)
+      return NULL;
+
+   return ctx->hReadDC;
+}
 
 BOOL
-stw_make_current(HDC hdc, DHGLRC dhglrc)
+stw_make_current(HDC hdc, HDC hReadDC, DHGLRC dhglrc)
 {
    struct stw_context *old_ctx = NULL;
    struct stw_context *ctx = NULL;
@@ -403,7 +415,7 @@ stw_make_current(HDC hdc, DHGLRC dhglrc)
    old_ctx = stw_current_context();
    if (old_ctx != NULL) {
       if (old_ctx->dhglrc == dhglrc) {
-         if (old_ctx->hdc == hdc) {
+         if (old_ctx->hdc == hdc && old_ctx->hReadDC == hReadDC) {
             /* Return if already current. */
             return TRUE;
          }
@@ -421,6 +433,7 @@ stw_make_current(HDC hdc, DHGLRC dhglrc)
 
    if (dhglrc) {
       struct stw_framebuffer *fb = NULL;
+      struct stw_framebuffer *fbRead = NULL;
       stw_lock_contexts(stw_dev);
       ctx = stw_lookup_context_locked( dhglrc );
       stw_unlock_contexts(stw_dev);
@@ -454,6 +467,7 @@ stw_make_current(HDC hdc, DHGLRC dhglrc)
 
       /* Bind the new framebuffer */
       ctx->hdc = hdc;
+      ctx->hReadDC = hReadDC;
 
       struct stw_framebuffer *old_fb = ctx->current_framebuffer;
       if (old_fb != fb) {
@@ -462,12 +476,47 @@ stw_make_current(HDC hdc, DHGLRC dhglrc)
       }
       stw_framebuffer_unlock(fb);
 
-      /* Note: when we call this function we will wind up in the
-       * stw_st_framebuffer_validate_locked() function which will incur
-       * a recursive fb->mutex lock.
-       */
-      ret = stw_dev->stapi->make_current(stw_dev->stapi, ctx->st,
-                                         fb->stfb, fb->stfb);
+      if (hReadDC) {
+         if (hReadDC == hDrawDC) {
+            fbRead = fb;
+         }
+         else {
+            fbRead = stw_framebuffer_from_hdc( hReadDC );
+
+            if (fbRead) {
+               stw_framebuffer_update(fbRead);
+            }
+            else {
+               /* Applications should call SetPixelFormat before creating a
+                * context, but not all do, and the opengl32 runtime seems to
+                * use a default pixel format in some cases, so we must create
+                * a framebuffer for those here.
+                */
+               int iPixelFormat = GetPixelFormat(hReadDC);
+               if (iPixelFormat)
+                  fbRead = stw_framebuffer_create( hReadDC, iPixelFormat );
+               if (!fbRead)
+                  goto fail;
+            }
+
+            if (fbRead->iPixelFormat != ctx->iPixelFormat) {
+               stw_framebuffer_unlock(fbRead);
+               SetLastError(ERROR_INVALID_PIXEL_FORMAT);
+               goto fail;
+            }
+            stw_framebuffer_unlock(fbRead);
+         }
+         ret = stw_dev->stapi->make_current(stw_dev->stapi, ctx->st,
+                                            fb->stfb, fbRead->stfb);
+      }
+      else {
+         /* Note: when we call this function we will wind up in the
+          * stw_st_framebuffer_validate_locked() function which will incur
+          * a recursive fb->mutex lock.
+          */
+         ret = stw_dev->stapi->make_current(stw_dev->stapi, ctx->st,
+                                            fb->stfb, fb->stfb);
+      }
 
       if (old_fb && old_fb != fb) {
          stw_lock_framebuffers(stw_dev);
@@ -477,14 +526,16 @@ stw_make_current(HDC hdc, DHGLRC dhglrc)
       }
 
 fail:
-      /* fb must be unlocked at this point. */
-      assert(!stw_own_mutex(&fb->mutex));
+      if (fb) {
+         /* fb must be unlocked at this point. */
+         assert(!stw_own_mutex(&fb->mutex));
+      }
 
       /* On failure, make the thread's current rendering context not current
        * before returning.
        */
       if (!ret) {
-         stw_make_current(NULL, 0);
+         stw_make_current(NULL, NULL, 0);
       }
    } else {
       ret = stw_dev->stapi->make_current(stw_dev->stapi, NULL, NULL, NULL);
@@ -870,7 +921,7 @@ DrvSetContext(HDC hdc, DHGLRC dhglrc, PFN_SETPROCTABLE pfnSetProcTable)
 {
    PGLCLTPROCTABLE r = (PGLCLTPROCTABLE)&cpt;
 
-   if (!stw_make_current(hdc, dhglrc))
+   if (!stw_make_current(hdc, hdc, dhglrc))
       r = NULL;
 
    return r;
diff --git a/src/gallium/state_trackers/wgl/stw_context.h b/src/gallium/state_trackers/wgl/stw_context.h
index 0f180c8..d0e7f2c 100644
--- a/src/gallium/state_trackers/wgl/stw_context.h
+++ b/src/gallium/state_trackers/wgl/stw_context.h
@@ -40,6 +40,7 @@ struct stw_context
    DHGLRC dhglrc;
    int iPixelFormat;
    HDC hdc;
+   HDC hReadDC;
    BOOL shared;
 
    struct stw_framebuffer *current_framebuffer;
@@ -59,7 +60,9 @@ struct stw_context *stw_current_context(void);
 
 HDC stw_get_current_dc( void );
 
-BOOL stw_make_current( HDC hdc, DHGLRC dhglrc );
+HDC stw_get_current_read_dc( void );
+
+BOOL stw_make_current( HDC hdc, HDC hReadDC, DHGLRC dhglrc );
 
 void stw_notify_current_locked( struct stw_framebuffer *fb );
 
diff --git a/src/gallium/state_trackers/wgl/stw_ext_context.c b/src/gallium/state_trackers/wgl/stw_ext_context.c
index 4c58316..6326d20 100644
--- a/src/gallium/state_trackers/wgl/stw_ext_context.c
+++ b/src/gallium/state_trackers/wgl/stw_ext_context.c
@@ -195,3 +195,18 @@ wglCreateContextAttribsARB(HDC hDC, HGLRC hShareContext, const int *attribList)
 
    return context;
 }
+
+
+/** Defined by WGL_ARB_make_current_read */
+BOOL APIENTRY
+wglMakeContextCurrentARB(HDC hDrawDC, HDC hReadDC, HGLRC hglrc)
+{
+   DHGLRC dhglrc = 0;
+
+   if (stw_dev && stw_dev->callbacks.wglCbGetDhglrc) {
+      /* Convert HGLRC to DHGLRC */
+      dhglrc = stw_dev->callbacks.wglCbGetDhglrc(hglrc);
+   }
+
+   return stw_make_current(hDrawDC, hReadDC, dhglrc);
+}
diff --git a/src/gallium/state_trackers/wgl/stw_ext_extensionsstring.c b/src/gallium/state_trackers/wgl/stw_ext_extensionsstring.c
index 86b93fb..06af8b1 100644
--- a/src/gallium/state_trackers/wgl/stw_ext_extensionsstring.c
+++ b/src/gallium/state_trackers/wgl/stw_ext_extensionsstring.c
@@ -44,6 +44,7 @@ static const char *stw_extension_string =
    "WGL_ARB_render_texture "
    "WGL_EXT_create_context_es_profile "
    "WGL_EXT_create_context_es2_profile "
+   "WGL_ARB_make_current_read "
 /*   "WGL_EXT_swap_interval " */
    "WGL_EXT_extensions_string";
 
diff --git a/src/gallium/state_trackers/wgl/stw_ext_rendertexture.c b/src/gallium/state_trackers/wgl/stw_ext_rendertexture.c
index 9d76696..5503102 100644
--- a/src/gallium/state_trackers/wgl/stw_ext_rendertexture.c
+++ b/src/gallium/state_trackers/wgl/stw_ext_rendertexture.c
@@ -104,6 +104,7 @@ BOOL WINAPI
 wglBindTexImageARB(HPBUFFERARB hPbuffer, int iBuffer)
 {
    HDC prevDrawable = stw_get_current_dc();
+   HDC prevReadable = stw_get_current_read_dc();
    HDC dc;
    struct stw_context *curctx = stw_current_context();
    struct stw_framebuffer *fb;
@@ -172,7 +173,7 @@ wglBindTexImageARB(HPBUFFERARB hPbuffer, int iBuffer)
    pixelFormatSave = fb->iPixelFormat;
    fb->iPixelFormat = curctx->iPixelFormat;
    dc = wglGetPbufferDCARB(hPbuffer);
-   retVal = stw_make_current(dc, curctx->dhglrc);
+   retVal = stw_make_current(dc, dc, curctx->dhglrc);
    fb->iPixelFormat = pixelFormatSave;
    if (!retVal) {
       debug_printf("stw_make_current(#1) failed in wglBindTexImageARB()\n");
@@ -185,7 +186,7 @@ wglBindTexImageARB(HPBUFFERARB hPbuffer, int iBuffer)
                                   fb->textureFace, texFormat);
 
    /* rebind previous drawing surface */
-   retVal = stw_make_current(prevDrawable, curctx->dhglrc);
+   retVal = stw_make_current(prevDrawable, prevReadable, curctx->dhglrc);
    if (!retVal) {
       debug_printf("stw_make_current(#2) failed in wglBindTexImageARB()\n");
    }
diff --git a/src/gallium/state_trackers/wgl/stw_getprocaddress.c b/src/gallium/state_trackers/wgl/stw_getprocaddress.c
index 66718c5..9273d10 100644
--- a/src/gallium/state_trackers/wgl/stw_getprocaddress.c
+++ b/src/gallium/state_trackers/wgl/stw_getprocaddress.c
@@ -79,6 +79,9 @@ static const struct stw_extension_entry stw_extension_entries[] = {
    STW_EXTENSION_ENTRY( wglReleaseTexImageARB ),
    STW_EXTENSION_ENTRY( wglSetPbufferAttribARB ),
 
+   /*  WGL_ARB_make_current_read */
+   STW_EXTENSION_ENTRY( wglMakeContextCurrentARB ),
+   STW_EXTENSION_ENTRY( wglGetCurrentReadDCARB ),
    { NULL, NULL }
 };
 
diff --git a/src/gallium/state_trackers/wgl/stw_wgl.c b/src/gallium/state_trackers/wgl/stw_wgl.c
index 5146e6a..de4b4f6 100644
--- a/src/gallium/state_trackers/wgl/stw_wgl.c
+++ b/src/gallium/state_trackers/wgl/stw_wgl.c
@@ -99,6 +99,13 @@ wglGetCurrentDC( VOID )
    return stw_get_current_dc();
 }
 
+WINGDIAPI HDC APIENTRY
+wglGetCurrentReadDCARB( VOID )
+{
+   return stw_get_current_read_dc();
+}
+
+
 WINGDIAPI BOOL APIENTRY
 wglMakeCurrent(
    HDC hdc,
diff --git a/src/gallium/state_trackers/wgl/stw_wgl.h b/src/gallium/state_trackers/wgl/stw_wgl.h
index 31a391d..92d70b5 100644
--- a/src/gallium/state_trackers/wgl/stw_wgl.h
+++ b/src/gallium/state_trackers/wgl/stw_wgl.h
@@ -59,6 +59,16 @@ wglSetPixelFormat(HDC hdc,
                   int iPixelFormat,
                   CONST PIXELFORMATDESCRIPTOR *ppfd);
 
+WINGDIAPI HDC APIENTRY
+wglGetCurrentReadDCARB( VOID );
+
+WINGDIAPI BOOL APIENTRY
+wglMakeContextCurrentARB(
+   HDC hDrawDC,
+   HDC hReadDC,
+   HGLRC hglrc );
+
+
 #ifndef WGL_SWAPMULTIPLE_MAX
 
 typedef struct _WGLSWAP
-- 
1.9.1



More information about the mesa-dev mailing list