mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-05-09 04:38:03 +02:00
st/wgl: refactor framebuffer locking code
Split the old stw_framebuffer_reference() function into two new functions: stw_framebuffer_reference_locked() which increments the refcount and stw_framebuffer_release_locked() which decrements the refcount and destroys the buffer when the count hits zero. Original patch by Jose. Modified by Brian (clean-ups, lock assertion checks, etc). Reviewed-by: José Fonseca <jfonseca@vmware.com>
This commit is contained in:
parent
25cccb5bec
commit
128feef40e
4 changed files with 68 additions and 51 deletions
|
|
@ -390,7 +390,6 @@ stw_make_current(HDC hdc, DHGLRC dhglrc)
|
||||||
{
|
{
|
||||||
struct stw_context *old_ctx = NULL;
|
struct stw_context *old_ctx = NULL;
|
||||||
struct stw_context *ctx = NULL;
|
struct stw_context *ctx = NULL;
|
||||||
struct stw_framebuffer *fb = NULL;
|
|
||||||
BOOL ret = FALSE;
|
BOOL ret = FALSE;
|
||||||
|
|
||||||
if (!stw_dev)
|
if (!stw_dev)
|
||||||
|
|
@ -409,6 +408,7 @@ stw_make_current(HDC hdc, DHGLRC dhglrc)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dhglrc) {
|
if (dhglrc) {
|
||||||
|
struct stw_framebuffer *fb = NULL;
|
||||||
stw_lock_contexts(stw_dev);
|
stw_lock_contexts(stw_dev);
|
||||||
ctx = stw_lookup_context_locked( dhglrc );
|
ctx = stw_lookup_context_locked( dhglrc );
|
||||||
stw_unlock_contexts(stw_dev);
|
stw_unlock_contexts(stw_dev);
|
||||||
|
|
@ -416,6 +416,7 @@ stw_make_current(HDC hdc, DHGLRC dhglrc)
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* This call locks fb's mutex */
|
||||||
fb = stw_framebuffer_from_hdc( hdc );
|
fb = stw_framebuffer_from_hdc( hdc );
|
||||||
if (fb) {
|
if (fb) {
|
||||||
stw_framebuffer_update(fb);
|
stw_framebuffer_update(fb);
|
||||||
|
|
@ -434,6 +435,7 @@ stw_make_current(HDC hdc, DHGLRC dhglrc)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fb->iPixelFormat != ctx->iPixelFormat) {
|
if (fb->iPixelFormat != ctx->iPixelFormat) {
|
||||||
|
stw_framebuffer_unlock(fb);
|
||||||
SetLastError(ERROR_INVALID_PIXEL_FORMAT);
|
SetLastError(ERROR_INVALID_PIXEL_FORMAT);
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
@ -441,36 +443,53 @@ stw_make_current(HDC hdc, DHGLRC dhglrc)
|
||||||
/* Bind the new framebuffer */
|
/* Bind the new framebuffer */
|
||||||
ctx->hdc = hdc;
|
ctx->hdc = hdc;
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
/* Note: when we call this function we will wind up in the
|
/* Note: when we call this function we will wind up in the
|
||||||
* stw_st_framebuffer_validate_locked() function which will incur
|
* stw_st_framebuffer_validate_locked() function which will incur
|
||||||
* a recursive fb->mutex lock.
|
* a recursive fb->mutex lock.
|
||||||
*/
|
*/
|
||||||
ret = stw_dev->stapi->make_current(stw_dev->stapi, ctx->st,
|
ret = stw_dev->stapi->make_current(stw_dev->stapi, ctx->st,
|
||||||
fb->stfb, fb->stfb);
|
fb->stfb, fb->stfb);
|
||||||
stw_framebuffer_reference(&ctx->current_framebuffer, fb);
|
|
||||||
} else {
|
if (old_fb && old_fb != fb) {
|
||||||
ret = stw_dev->stapi->make_current(stw_dev->stapi, NULL, NULL, NULL);
|
stw_lock_framebuffers(stw_dev);
|
||||||
}
|
stw_framebuffer_lock(old_fb);
|
||||||
|
stw_framebuffer_release_locked(old_fb);
|
||||||
|
stw_unlock_framebuffers(stw_dev);
|
||||||
|
}
|
||||||
|
|
||||||
fail:
|
fail:
|
||||||
|
/* fb must be unlocked at this point. */
|
||||||
|
assert(!stw_own_mutex(&fb->mutex));
|
||||||
|
|
||||||
if (fb) {
|
/* On failure, make the thread's current rendering context not current
|
||||||
stw_framebuffer_unlock(fb);
|
* before returning.
|
||||||
}
|
*/
|
||||||
|
if (!ret) {
|
||||||
/* On failure, make the thread's current rendering context not current
|
stw_make_current(NULL, 0);
|
||||||
* before returning.
|
}
|
||||||
*/
|
} else {
|
||||||
if (!ret) {
|
ret = stw_dev->stapi->make_current(stw_dev->stapi, NULL, NULL, NULL);
|
||||||
stw_dev->stapi->make_current(stw_dev->stapi, NULL, NULL, NULL);
|
|
||||||
ctx = NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Unreference the previous framebuffer if any. It must be done after
|
/* Unreference the previous framebuffer if any. It must be done after
|
||||||
* make_current, as it can be referenced inside.
|
* make_current, as it can be referenced inside.
|
||||||
*/
|
*/
|
||||||
if (old_ctx && old_ctx != ctx) {
|
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;
|
return ret;
|
||||||
|
|
|
||||||
|
|
@ -67,6 +67,10 @@ struct stw_device
|
||||||
CRITICAL_SECTION ctx_mutex;
|
CRITICAL_SECTION ctx_mutex;
|
||||||
struct handle_table *ctx_table;
|
struct handle_table *ctx_table;
|
||||||
|
|
||||||
|
/* TODO: use an atomic counter to track the number of locked
|
||||||
|
* stw_framebuffer objects. Assert that the counter is zero when
|
||||||
|
* trying to lock this mutex.
|
||||||
|
*/
|
||||||
CRITICAL_SECTION fb_mutex;
|
CRITICAL_SECTION fb_mutex;
|
||||||
struct stw_framebuffer *fb_head;
|
struct stw_framebuffer *fb_head;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -67,14 +67,18 @@ stw_framebuffer_from_hwnd_locked(HWND hwnd)
|
||||||
* Decrement the reference count on the given stw_framebuffer object.
|
* Decrement the reference count on the given stw_framebuffer object.
|
||||||
* If the reference count hits zero, destroy the object.
|
* If the reference count hits zero, destroy the object.
|
||||||
*
|
*
|
||||||
* Note: Both stw_dev::fb_mutex and stw_framebuffer::mutex must already
|
* Note: Both stw_dev::fb_mutex and stw_framebuffer::mutex must already be
|
||||||
* be locked.
|
* locked. After this function completes, the fb's mutex will be unlocked.
|
||||||
*/
|
*/
|
||||||
static void
|
void
|
||||||
stw_framebuffer_destroy_locked(struct stw_framebuffer *fb)
|
stw_framebuffer_release_locked(struct stw_framebuffer *fb)
|
||||||
{
|
{
|
||||||
struct stw_framebuffer **link;
|
struct stw_framebuffer **link;
|
||||||
|
|
||||||
|
assert(fb);
|
||||||
|
assert(stw_own_mutex(&fb->mutex));
|
||||||
|
assert(stw_own_mutex(&stw_dev->fb_mutex));
|
||||||
|
|
||||||
/* check the reference count */
|
/* check the reference count */
|
||||||
fb->refcnt--;
|
fb->refcnt--;
|
||||||
if (fb->refcnt) {
|
if (fb->refcnt) {
|
||||||
|
|
@ -223,7 +227,7 @@ stw_call_window_proc(int nCode, WPARAM wParam, LPARAM lParam)
|
||||||
stw_lock_framebuffers(stw_dev);
|
stw_lock_framebuffers(stw_dev);
|
||||||
fb = stw_framebuffer_from_hwnd_locked( pParams->hwnd );
|
fb = stw_framebuffer_from_hwnd_locked( pParams->hwnd );
|
||||||
if (fb)
|
if (fb)
|
||||||
stw_framebuffer_destroy_locked(fb);
|
stw_framebuffer_release_locked(fb);
|
||||||
stw_unlock_framebuffers(stw_dev);
|
stw_unlock_framebuffers(stw_dev);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -303,33 +307,6 @@ stw_framebuffer_create(HDC hdc, int iPixelFormat)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Have ptr reference fb. The referenced framebuffer should be locked.
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
stw_framebuffer_reference(struct stw_framebuffer **ptr,
|
|
||||||
struct stw_framebuffer *fb)
|
|
||||||
{
|
|
||||||
struct stw_framebuffer *old_fb = *ptr;
|
|
||||||
|
|
||||||
if (old_fb == fb)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (fb)
|
|
||||||
fb->refcnt++;
|
|
||||||
if (old_fb) {
|
|
||||||
stw_lock_framebuffers(stw_dev);
|
|
||||||
|
|
||||||
stw_framebuffer_lock(old_fb);
|
|
||||||
stw_framebuffer_destroy_locked(old_fb);
|
|
||||||
|
|
||||||
stw_unlock_framebuffers(stw_dev);
|
|
||||||
}
|
|
||||||
|
|
||||||
*ptr = fb;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Update the framebuffer's size if necessary.
|
* Update the framebuffer's size if necessary.
|
||||||
*/
|
*/
|
||||||
|
|
@ -369,7 +346,7 @@ stw_framebuffer_cleanup(void)
|
||||||
next = fb->next;
|
next = fb->next;
|
||||||
|
|
||||||
stw_framebuffer_lock(fb);
|
stw_framebuffer_lock(fb);
|
||||||
stw_framebuffer_destroy_locked(fb);
|
stw_framebuffer_release_locked(fb);
|
||||||
|
|
||||||
fb = next;
|
fb = next;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -34,6 +34,7 @@
|
||||||
#include <GL/wglext.h>
|
#include <GL/wglext.h>
|
||||||
|
|
||||||
#include "util/u_debug.h"
|
#include "util/u_debug.h"
|
||||||
|
#include "stw_st.h"
|
||||||
|
|
||||||
|
|
||||||
struct pipe_resource;
|
struct pipe_resource;
|
||||||
|
|
@ -131,9 +132,24 @@ struct stw_framebuffer
|
||||||
struct stw_framebuffer *
|
struct stw_framebuffer *
|
||||||
stw_framebuffer_create(HDC hdc, int iPixelFormat);
|
stw_framebuffer_create(HDC hdc, int iPixelFormat);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Increase fb reference count. The referenced framebuffer should be locked.
|
||||||
|
*
|
||||||
|
* It's not necessary to hold stw_dev::fb_mutex global lock.
|
||||||
|
*/
|
||||||
|
static inline void
|
||||||
|
stw_framebuffer_reference_locked(struct stw_framebuffer *fb)
|
||||||
|
{
|
||||||
|
if (fb) {
|
||||||
|
assert(stw_own_mutex(&fb->mutex));
|
||||||
|
fb->refcnt++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
stw_framebuffer_reference(struct stw_framebuffer **ptr,
|
stw_framebuffer_release_locked(struct stw_framebuffer *fb);
|
||||||
struct stw_framebuffer *fb);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Search a framebuffer with a matching HWND.
|
* Search a framebuffer with a matching HWND.
|
||||||
|
|
@ -179,6 +195,7 @@ static inline void
|
||||||
stw_framebuffer_unlock(struct stw_framebuffer *fb)
|
stw_framebuffer_unlock(struct stw_framebuffer *fb)
|
||||||
{
|
{
|
||||||
assert(fb);
|
assert(fb);
|
||||||
|
assert(stw_own_mutex(&fb->mutex));
|
||||||
LeaveCriticalSection(&fb->mutex);
|
LeaveCriticalSection(&fb->mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue