wgl: Unreference the current framebuffer after the make_current call.

To prevent a dangling pointer dereference.
This commit is contained in:
José Fonseca 2010-12-02 16:28:36 +00:00
parent 63c05c96e7
commit 14e2dc9c66

View file

@ -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;
}
}
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;
}
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 (fb->iPixelFormat != ctx->iPixelFormat) {
SetLastError(ERROR_INVALID_PIXEL_FORMAT);
goto fail;
}
/* Bind the new framebuffer */
ctx->hdc = hdc;
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);
}
fail:
if (fb) {
stw_framebuffer_release(fb);
}
/* 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);
}
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)
goto fail;
}
if(fb->iPixelFormat != ctx->iPixelFormat)
goto fail;
/* Bind the new framebuffer */
ctx->hdc = hdc;
if (!stw_dev->stapi->make_current(stw_dev->stapi, ctx->st, fb->stfb, fb->stfb))
goto fail;
stw_framebuffer_reference(&ctx->current_framebuffer, fb);
success:
assert(fb);
if(fb) {
stw_framebuffer_release(fb);
}
return TRUE;
fail:
if(fb)
stw_framebuffer_release(fb);
stw_dev->stapi->make_current(stw_dev->stapi, NULL, NULL, NULL);
return FALSE;
return ret;
}
/**