summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorJosé Fonseca <[email protected]>2010-12-02 16:28:36 +0000
committerJosé Fonseca <[email protected]>2010-12-02 16:28:36 +0000
commit14e2dc9c66b332b2527201e65a4dbe2ded968669 (patch)
tree951e1e2b7eb7fd08950fc722948552063e7ca360 /src
parent63c05c96e798e68fdec93e6a1184ec06d3713d98 (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.c109
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;
}
/**