diff --git a/src/gallium/state_trackers/wgl/stw_context.c b/src/gallium/state_trackers/wgl/stw_context.c index 85cffa63529..18273ac3e95 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 0f180c8e2ec..d0e7f2c9f94 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 4c58316a0e1..6326d20ba82 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 86b93fb2e28..06af8b1e994 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 9d766966771..5503102bc98 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 66718c59eb3..9273d103310 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 5146e6a5b79..de4b4f6f3b0 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 31a391d960e..92d70b5da9e 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