X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fgallium%2Fstate_trackers%2Fwgl%2Fstw_context.c;h=a9e4024c236d01232fc2e656083fce1ff0f67e55;hb=e92caad74476b915bb73baedbddce8af89bd62b0;hp=9971f95a6fabe9a2181dcfbb8e210d0db53b64fa;hpb=25cccb5bec7145e054d1246be0dc386cebdcc58a;p=mesa.git diff --git a/src/gallium/state_trackers/wgl/stw_context.c b/src/gallium/state_trackers/wgl/stw_context.c index 9971f95a6fa..a9e4024c236 100644 --- a/src/gallium/state_trackers/wgl/stw_context.c +++ b/src/gallium/state_trackers/wgl/stw_context.c @@ -104,8 +104,11 @@ DrvShareLists(DHGLRC dhglrc1, DHGLRC dhglrc2) ctx1 = stw_lookup_context_locked( dhglrc1 ); ctx2 = stw_lookup_context_locked( dhglrc2 ); - if (ctx1 && ctx2 && ctx2->st->share) + if (ctx1 && ctx2 && ctx2->st->share) { ret = ctx2->st->share(ctx2->st, ctx1->st); + ctx1->shared = TRUE; + ctx2->shared = TRUE; + } stw_unlock_contexts(stw_dev); @@ -129,6 +132,25 @@ DrvCreateLayerContext(HDC hdc, INT iLayerPlane) } +/** + * Return the stw pixel format that most closely matches the pixel format + * on HDC. + * Used to get a pixel format when SetPixelFormat() hasn't been called before. + */ +static int +get_matching_pixel_format(HDC hdc) +{ + int iPixelFormat = GetPixelFormat(hdc); + PIXELFORMATDESCRIPTOR pfd; + + if (!iPixelFormat) + return 0; + if (!DescribePixelFormat(hdc, iPixelFormat, sizeof(pfd), &pfd)) + return 0; + return stw_pixelformat_choose(hdc, &pfd); +} + + /** * Called via DrvCreateContext(), DrvCreateLayerContext() and * wglCreateContextAttribsARB() to actually create a rendering context. @@ -167,7 +189,13 @@ stw_create_context_attribs(HDC hdc, INT iLayerPlane, DHGLRC hShareContext, iPixelFormat = fb->iPixelFormat; stw_framebuffer_unlock(fb); } else { - return 0; + /* 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 use that. + */ + iPixelFormat = get_matching_pixel_format(hdc); + if (!iPixelFormat) + return 0; } pfi = stw_pixelformat_get_info( iPixelFormat ); @@ -175,6 +203,7 @@ stw_create_context_attribs(HDC hdc, INT iLayerPlane, DHGLRC hShareContext, if (hShareContext != 0) { stw_lock_contexts(stw_dev); shareCtx = stw_lookup_context_locked( hShareContext ); + shareCtx->shared = TRUE; stw_unlock_contexts(stw_dev); } @@ -182,8 +211,10 @@ stw_create_context_attribs(HDC hdc, INT iLayerPlane, DHGLRC hShareContext, if (ctx == NULL) goto no_ctx; - ctx->hdc = hdc; + ctx->hDrawDC = hdc; + ctx->hReadDC = hdc; ctx->iPixelFormat = iPixelFormat; + ctx->shared = shareCtx != NULL; memset(&attribs, 0, sizeof(attribs)); attribs.visual = pfi->stvis; @@ -247,7 +278,7 @@ stw_create_context_attribs(HDC hdc, INT iLayerPlane, DHGLRC hShareContext, ctx->st->st_manager_private = (void *) ctx; if (ctx->st->cso_context) { - ctx->hud = hud_create(ctx->st->pipe, ctx->st->cso_context); + ctx->hud = hud_create(ctx->st->cso_context, NULL); } stw_lock_contexts(stw_dev); @@ -260,7 +291,7 @@ stw_create_context_attribs(HDC hdc, INT iLayerPlane, DHGLRC hShareContext, if (old_ctx) { /* free the old context data associated with this handle */ if (old_ctx->hud) { - hud_destroy(old_ctx->hud); + hud_destroy(old_ctx->hud, NULL); } ctx->st->destroy(old_ctx->st); FREE(old_ctx); @@ -285,7 +316,7 @@ stw_create_context_attribs(HDC hdc, INT iLayerPlane, DHGLRC hShareContext, no_hglrc: if (ctx->hud) { - hud_destroy(ctx->hud); + hud_destroy(ctx->hud, NULL); } ctx->st->destroy(ctx->st); no_st_ctx: @@ -317,7 +348,7 @@ DrvDeleteContext(DHGLRC dhglrc) stw_dev->stapi->make_current(stw_dev->stapi, NULL, NULL, NULL); if (ctx->hud) { - hud_destroy(ctx->hud); + hud_destroy(ctx->hud, NULL); } ctx->st->destroy(ctx->st); @@ -352,7 +383,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; @@ -381,16 +412,26 @@ stw_get_current_dc( void ) if (!ctx) return NULL; - return ctx->hdc; + return ctx->hDrawDC; } +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 hDrawDC, HDC hReadDC, DHGLRC dhglrc) { struct stw_context *old_ctx = NULL; struct stw_context *ctx = NULL; - struct stw_framebuffer *fb = NULL; BOOL ret = FALSE; if (!stw_dev) @@ -399,16 +440,25 @@ 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->hDrawDC == hDrawDC && old_ctx->hReadDC == hReadDC) { /* Return if already current. */ return TRUE; } } else { - old_ctx->st->flush(old_ctx->st, ST_FLUSH_FRONT, NULL); + if (old_ctx->shared) { + struct pipe_fence_handle *fence = NULL; + old_ctx->st->flush(old_ctx->st, + ST_FLUSH_FRONT | ST_FLUSH_WAIT, &fence); + } + else { + old_ctx->st->flush(old_ctx->st, ST_FLUSH_FRONT, NULL); + } } } 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); @@ -416,7 +466,8 @@ stw_make_current(HDC hdc, DHGLRC dhglrc) goto fail; } - fb = stw_framebuffer_from_hdc( hdc ); + /* This call locks fb's mutex */ + fb = stw_framebuffer_from_hdc( hDrawDC ); if (fb) { stw_framebuffer_update(fb); } @@ -426,51 +477,107 @@ stw_make_current(HDC hdc, DHGLRC dhglrc) * pixel format in some cases, so we must create a framebuffer for * those here. */ - int iPixelFormat = GetPixelFormat(hdc); + int iPixelFormat = get_matching_pixel_format(hDrawDC); if (iPixelFormat) - fb = stw_framebuffer_create( hdc, iPixelFormat ); + fb = stw_framebuffer_create( hDrawDC, iPixelFormat ); if (!fb) goto fail; } if (fb->iPixelFormat != ctx->iPixelFormat) { + stw_framebuffer_unlock(fb); SetLastError(ERROR_INVALID_PIXEL_FORMAT); goto fail; } /* Bind the new framebuffer */ - ctx->hdc = hdc; + ctx->hDrawDC = hDrawDC; + ctx->hReadDC = hReadDC; - /* 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); - stw_framebuffer_reference(&ctx->current_framebuffer, fb); - } else { - ret = stw_dev->stapi->make_current(stw_dev->stapi, NULL, NULL, NULL); - } + struct stw_framebuffer *old_fb = ctx->current_framebuffer; + if (old_fb != fb) { + stw_framebuffer_reference_locked(fb); + ctx->current_framebuffer = fb; + } + stw_framebuffer_unlock(fb); -fail: + 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 (fb) { - stw_framebuffer_unlock(fb); - } + if (old_fb && old_fb != fb) { + stw_lock_framebuffers(stw_dev); + stw_framebuffer_lock(old_fb); + stw_framebuffer_release_locked(old_fb); + stw_unlock_framebuffers(stw_dev); + } - /* On failure, make the thread's current rendering context not current - * before returning. - */ - if (!ret) { - stw_dev->stapi->make_current(stw_dev->stapi, NULL, NULL, NULL); - ctx = NULL; +fail: + 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, NULL, 0); + } + } else { + ret = stw_dev->stapi->make_current(stw_dev->stapi, NULL, NULL, NULL); } /* Unreference the previous framebuffer if any. It must be done after * make_current, as it can be referenced inside. */ if (old_ctx && old_ctx != ctx) { - stw_framebuffer_reference(&old_ctx->current_framebuffer, NULL); + struct stw_framebuffer *old_fb = old_ctx->current_framebuffer; + if (old_fb) { + old_ctx->current_framebuffer = NULL; + stw_lock_framebuffers(stw_dev); + stw_framebuffer_lock(old_fb); + stw_framebuffer_release_locked(old_fb); + stw_unlock_framebuffers(stw_dev); + } } return ret; @@ -839,7 +946,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;