summaryrefslogtreecommitdiff
path: root/src/gallium/state_trackers/wgl/shared/stw_framebuffer.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/gallium/state_trackers/wgl/shared/stw_framebuffer.c')
-rw-r--r--src/gallium/state_trackers/wgl/shared/stw_framebuffer.c120
1 files changed, 80 insertions, 40 deletions
diff --git a/src/gallium/state_trackers/wgl/shared/stw_framebuffer.c b/src/gallium/state_trackers/wgl/shared/stw_framebuffer.c
index c0a42c1b7d..b8956bb550 100644
--- a/src/gallium/state_trackers/wgl/shared/stw_framebuffer.c
+++ b/src/gallium/state_trackers/wgl/shared/stw_framebuffer.c
@@ -45,6 +45,10 @@
#include "stw_tls.h"
+/**
+ * Search the framebuffer with the matching HWND while holding the
+ * stw_dev::fb_mutex global lock.
+ */
static INLINE struct stw_framebuffer *
stw_framebuffer_from_hwnd_locked(
HWND hwnd )
@@ -52,13 +56,20 @@ stw_framebuffer_from_hwnd_locked(
struct stw_framebuffer *fb;
for (fb = stw_dev->fb_head; fb != NULL; fb = fb->next)
- if (fb->hWnd == hwnd)
+ if (fb->hWnd == hwnd) {
+ pipe_mutex_lock(fb->mutex);
break;
+ }
return fb;
}
+/**
+ * Destroy this framebuffer. Both stw_dev::fb_mutex and stw_framebuffer::mutex
+ * must be held, by this order. Obviously no further access to fb can be done
+ * after this.
+ */
static INLINE void
stw_framebuffer_destroy_locked(
struct stw_framebuffer *fb )
@@ -74,12 +85,23 @@ stw_framebuffer_destroy_locked(
st_unreference_framebuffer(fb->stfb);
+ pipe_mutex_unlock( fb->mutex );
+
pipe_mutex_destroy( fb->mutex );
FREE( fb );
}
+void
+stw_framebuffer_release(
+ struct stw_framebuffer *fb)
+{
+ assert(fb);
+ pipe_mutex_unlock( fb->mutex );
+}
+
+
static INLINE void
stw_framebuffer_get_size( struct stw_framebuffer *fb )
{
@@ -134,38 +156,29 @@ stw_call_window_proc(
LPWINDOWPOS lpWindowPos = (LPWINDOWPOS)pParams->lParam;
if((lpWindowPos->flags & SWP_SHOWWINDOW) ||
!(lpWindowPos->flags & SWP_NOSIZE)) {
- pipe_mutex_lock( stw_dev->mutex );
- fb = stw_framebuffer_from_hwnd_locked( pParams->hwnd );
- pipe_mutex_unlock( stw_dev->mutex );
-
+ fb = stw_framebuffer_from_hwnd( pParams->hwnd );
if(fb) {
- pipe_mutex_lock( fb->mutex );
/* Size in WINDOWPOS includes the window frame, so get the size
* of the client area via GetClientRect. */
stw_framebuffer_get_size(fb);
- pipe_mutex_unlock( fb->mutex );
+ stw_framebuffer_release(fb);
}
}
}
else if (pParams->message == WM_DESTROY) {
- pipe_mutex_lock( stw_dev->mutex );
-
+ pipe_mutex_lock( stw_dev->fb_mutex );
fb = stw_framebuffer_from_hwnd_locked( pParams->hwnd );
if(fb)
stw_framebuffer_destroy_locked(fb);
-
- pipe_mutex_unlock( stw_dev->mutex );
+ pipe_mutex_unlock( stw_dev->fb_mutex );
}
return CallNextHookEx(tls_data->hCallWndProcHook, nCode, wParam, lParam);
}
-/**
- * Create a new framebuffer object which will correspond to the given HDC.
- */
struct stw_framebuffer *
-stw_framebuffer_create_locked(
+stw_framebuffer_create(
HDC hdc,
int iPixelFormat )
{
@@ -194,8 +207,16 @@ stw_framebuffer_create_locked(
pipe_mutex_init( fb->mutex );
+ /* This is the only case where we lock the stw_framebuffer::mutex before
+ * stw_dev::fb_mutex, since no other thread can know about this framebuffer
+ * and we must prevent any other thread from destroying it before we return.
+ */
+ pipe_mutex_lock( fb->mutex );
+
+ pipe_mutex_lock( stw_dev->fb_mutex );
fb->next = stw_dev->fb_head;
stw_dev->fb_head = fb;
+ pipe_mutex_unlock( stw_dev->fb_mutex );
return fb;
}
@@ -205,8 +226,8 @@ BOOL
stw_framebuffer_allocate(
struct stw_framebuffer *fb)
{
- pipe_mutex_lock( fb->mutex );
-
+ assert(fb);
+
if(!fb->stfb) {
const struct stw_pixelformat_info *pfi = fb->pfi;
enum pipe_format colorFormat, depthFormat, stencilFormat;
@@ -242,8 +263,6 @@ stw_framebuffer_allocate(
fb->must_resize = TRUE;
}
- pipe_mutex_unlock( fb->mutex );
-
return fb->stfb ? TRUE : FALSE;
}
@@ -280,24 +299,27 @@ stw_framebuffer_cleanup( void )
struct stw_framebuffer *fb;
struct stw_framebuffer *next;
- pipe_mutex_lock( stw_dev->mutex );
+ pipe_mutex_lock( stw_dev->fb_mutex );
fb = stw_dev->fb_head;
while (fb) {
next = fb->next;
+
+ pipe_mutex_lock(fb->mutex);
stw_framebuffer_destroy_locked(fb);
+
fb = next;
}
stw_dev->fb_head = NULL;
- pipe_mutex_unlock( stw_dev->mutex );
+ pipe_mutex_unlock( stw_dev->fb_mutex );
}
/**
* Given an hdc, return the corresponding stw_framebuffer.
*/
-struct stw_framebuffer *
+static INLINE struct stw_framebuffer *
stw_framebuffer_from_hdc_locked(
HDC hdc )
{
@@ -314,8 +336,10 @@ stw_framebuffer_from_hdc_locked(
return stw_framebuffer_from_hwnd_locked(hwnd);
for (fb = stw_dev->fb_head; fb != NULL; fb = fb->next)
- if (fb->hDC == hdc)
+ if (fb->hDC == hdc) {
+ pipe_mutex_lock(fb->mutex);
break;
+ }
return fb;
}
@@ -330,9 +354,26 @@ stw_framebuffer_from_hdc(
{
struct stw_framebuffer *fb;
- pipe_mutex_lock( stw_dev->mutex );
+ pipe_mutex_lock( stw_dev->fb_mutex );
fb = stw_framebuffer_from_hdc_locked(hdc);
- pipe_mutex_unlock( stw_dev->mutex );
+ pipe_mutex_unlock( stw_dev->fb_mutex );
+
+ return fb;
+}
+
+
+/**
+ * Given an hdc, return the corresponding stw_framebuffer.
+ */
+struct stw_framebuffer *
+stw_framebuffer_from_hwnd(
+ HWND hwnd )
+{
+ struct stw_framebuffer *fb;
+
+ pipe_mutex_lock( stw_dev->fb_mutex );
+ fb = stw_framebuffer_from_hwnd_locked(hwnd);
+ pipe_mutex_unlock( stw_dev->fb_mutex );
return fb;
}
@@ -352,22 +393,19 @@ stw_pixelformat_set(
if (index >= count)
return FALSE;
- pipe_mutex_lock( stw_dev->mutex );
-
fb = stw_framebuffer_from_hdc_locked(hdc);
if(fb) {
/* SetPixelFormat must be called only once */
- pipe_mutex_unlock( stw_dev->mutex );
+ stw_framebuffer_release( fb );
return FALSE;
}
- fb = stw_framebuffer_create_locked(hdc, iPixelFormat);
+ fb = stw_framebuffer_create(hdc, iPixelFormat);
if(!fb) {
- pipe_mutex_unlock( stw_dev->mutex );
return FALSE;
}
- pipe_mutex_unlock( stw_dev->mutex );
+ stw_framebuffer_release( fb );
/* Some applications mistakenly use the undocumented wglSetPixelFormat
* function instead of SetPixelFormat, so we call SetPixelFormat here to
@@ -384,13 +422,16 @@ int
stw_pixelformat_get(
HDC hdc )
{
+ int iPixelFormat = 0;
struct stw_framebuffer *fb;
fb = stw_framebuffer_from_hdc(hdc);
- if(!fb)
- return 0;
+ if(fb) {
+ iPixelFormat = fb->iPixelFormat;
+ stw_framebuffer_release(fb);
+ }
- return fb->iPixelFormat;
+ return iPixelFormat;
}
@@ -406,10 +447,10 @@ stw_swap_buffers(
if (fb == NULL)
return FALSE;
- if (!(fb->pfi->pfd.dwFlags & PFD_DOUBLEBUFFER))
+ if (!(fb->pfi->pfd.dwFlags & PFD_DOUBLEBUFFER)) {
+ stw_framebuffer_release(fb);
return TRUE;
-
- pipe_mutex_lock( fb->mutex );
+ }
/* If we're swapping the buffer associated with the current context
* we have to flush any pending rendering commands first.
@@ -420,7 +461,7 @@ stw_swap_buffers(
if(!st_get_framebuffer_surface( fb->stfb, ST_SURFACE_BACK_LEFT, &surface )) {
/* FIXME: this shouldn't happen, but does on glean */
- pipe_mutex_unlock( fb->mutex );
+ stw_framebuffer_release(fb);
return FALSE;
}
@@ -434,8 +475,7 @@ stw_swap_buffers(
stw_dev->stw_winsys->flush_frontbuffer( screen, surface, hdc );
stw_framebuffer_update(fb);
-
- pipe_mutex_unlock( fb->mutex );
+ stw_framebuffer_release(fb);
return TRUE;
}