diff options
author | José Fonseca <[email protected]> | 2010-12-02 16:28:36 +0000 |
---|---|---|
committer | José Fonseca <[email protected]> | 2010-12-02 16:28:36 +0000 |
commit | 14e2dc9c66b332b2527201e65a4dbe2ded968669 (patch) | |
tree | 951e1e2b7eb7fd08950fc722948552063e7ca360 /src | |
parent | 63c05c96e798e68fdec93e6a1184ec06d3713d98 (diff) |
wgl: Unreference the current framebuffer after the make_current call.
To prevent a dangling pointer dereference.
Diffstat (limited to 'src')
-rw-r--r-- | src/gallium/state_trackers/wgl/stw_context.c | 109 |
1 files changed, 58 insertions, 51 deletions
diff --git a/src/gallium/state_trackers/wgl/stw_context.c b/src/gallium/state_trackers/wgl/stw_context.c index 86c0a28e8da..cd4f3c8b3e2 100644 --- a/src/gallium/state_trackers/wgl/stw_context.c +++ b/src/gallium/state_trackers/wgl/stw_context.c @@ -264,75 +264,82 @@ stw_make_current( struct stw_context *curctx = NULL; struct stw_context *ctx = NULL; struct stw_framebuffer *fb = NULL; + BOOL ret = FALSE; if (!stw_dev) - goto fail; + return FALSE; curctx = stw_current_context(); if (curctx != NULL) { - if (curctx->dhglrc != dhglrc) + if (curctx->dhglrc == dhglrc) { + if (curctx->hdc == hdc) { + /* Return if already current. */ + return TRUE; + } + } else { curctx->st->flush(curctx->st, PIPE_FLUSH_RENDER_CACHE, NULL); - - /* Return if already current. */ - if (curctx->dhglrc == dhglrc && curctx->hdc == hdc) { - ctx = curctx; - fb = stw_framebuffer_from_hdc( hdc ); - goto success; } - - stw_framebuffer_reference(&curctx->current_framebuffer, NULL); } - if (hdc == NULL || dhglrc == 0) { - return stw_dev->stapi->make_current(stw_dev->stapi, NULL, NULL, NULL); - } - - pipe_mutex_lock( stw_dev->ctx_mutex ); - ctx = stw_lookup_context_locked( dhglrc ); - pipe_mutex_unlock( stw_dev->ctx_mutex ); - if(!ctx) - goto fail; - - fb = stw_framebuffer_from_hdc( hdc ); - if (fb) { - stw_framebuffer_update(fb); - } - 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(hdc); - if(iPixelFormat) - fb = stw_framebuffer_create( hdc, iPixelFormat ); - if(!fb) + if (dhglrc) { + pipe_mutex_lock( stw_dev->ctx_mutex ); + ctx = stw_lookup_context_locked( dhglrc ); + pipe_mutex_unlock( stw_dev->ctx_mutex ); + if (!ctx) { goto fail; - } - - if(fb->iPixelFormat != ctx->iPixelFormat) - goto fail; + } - /* Bind the new framebuffer */ - ctx->hdc = hdc; + fb = stw_framebuffer_from_hdc( hdc ); + if (fb) { + stw_framebuffer_update(fb); + } + 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(hdc); + if (iPixelFormat) + fb = stw_framebuffer_create( hdc, iPixelFormat ); + if (!fb) + goto fail; + } - if (!stw_dev->stapi->make_current(stw_dev->stapi, ctx->st, fb->stfb, fb->stfb)) - goto fail; + if (fb->iPixelFormat != ctx->iPixelFormat) { + SetLastError(ERROR_INVALID_PIXEL_FORMAT); + goto fail; + } - stw_framebuffer_reference(&ctx->current_framebuffer, fb); + /* Bind the new framebuffer */ + ctx->hdc = hdc; -success: - assert(fb); - if(fb) { - stw_framebuffer_release(fb); + 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); } - return TRUE; - fail: - if(fb) + + if (fb) { stw_framebuffer_release(fb); - stw_dev->stapi->make_current(stw_dev->stapi, NULL, NULL, NULL); - return FALSE; + } + + /* 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; + } + + /* Unreference the previous framebuffer if any. It must be done after + * make_current, as it can be referenced inside. + */ + if (curctx && curctx != ctx) { + stw_framebuffer_reference(&curctx->current_framebuffer, NULL); + } + + return ret; } /** |