wgl: Protect the framebuffer with a lock.
authorJosé Fonseca <jfonseca@vmware.com>
Fri, 10 Apr 2009 18:48:59 +0000 (19:48 +0100)
committerJosé Fonseca <jfonseca@vmware.com>
Fri, 10 Apr 2009 18:50:35 +0000 (19:50 +0100)
Unfortunately this doesn't catch all the cases, as the mesa state tracker
can still use the framebuffer without giving the wgl state tracker
the chance to lock it.

src/gallium/state_trackers/wgl/shared/stw_context.c
src/gallium/state_trackers/wgl/shared/stw_framebuffer.c
src/gallium/state_trackers/wgl/shared/stw_framebuffer.h

index 1e3bf103176f4605ce27cfeac2f46a71102ca5ff..f3c7af93f503aa99e97c33da1e99f04277b5828a 100644 (file)
@@ -337,8 +337,11 @@ stw_make_current(
    }
 
    if (ctx && fb) {
+      pipe_mutex_lock( fb->mutex );
       st_make_current( ctx->st, fb->stfb, fb->stfb );
-      stw_framebuffer_resize( fb, width, height );
+      st_resize_framebuffer( fb->stfb, width, height );
+      pipe_mutex_unlock( fb->mutex );
+
       ctx->hdc = hdc;
       ctx->st->pipe->priv = hdc;
    }
index e70e20390e1742521a5fcbdad43be4ba2959f426..4348b8f326217ddcd09e91bf3e5a2bc5f78e5f84 100644 (file)
 #include "stw_tls.h"
 
 
-void
-stw_framebuffer_resize(
-   struct stw_framebuffer *fb,
-   GLuint width,
-   GLuint height )
-{
-   st_resize_framebuffer( fb->stfb, width, height );
-}
-
 /**
  * @sa http://msdn.microsoft.com/en-us/library/ms644975(VS.85).aspx
  * @sa http://msdn.microsoft.com/en-us/library/ms644960(VS.85).aspx
@@ -86,7 +77,16 @@ stw_call_window_proc(
       if(fb) {
          unsigned width = LOWORD( pParams->lParam );
          unsigned height = HIWORD( pParams->lParam );
-         stw_framebuffer_resize( fb, width, height );
+         
+         /* FIXME: The mesa statetracker makes the assumptions that only
+          * one context is using the framebuffer, and that that context is the 
+          * current one. However neither holds true, as WGL allows more than
+          * one context to be bound to the same drawable, and this function can 
+          * be called from any thread.
+          */
+         pipe_mutex_lock( fb->mutex );
+         st_resize_framebuffer( fb->stfb, width, height );
+         pipe_mutex_unlock( fb->mutex );
       }
    }
 
@@ -125,6 +125,11 @@ stw_framebuffer_create(
    if (fb == NULL)
       return NULL;
 
+   fb->hDC = hdc;
+   fb->hWnd = WindowFromDC( hdc );
+
+   pipe_mutex_init( fb->mutex );
+
    fb->stfb = st_create_framebuffer(
       visual,
       colorFormat,
@@ -133,9 +138,10 @@ stw_framebuffer_create(
       width,
       height,
       (void *) fb );
-
-   fb->hDC = hdc;
-   fb->hWnd = WindowFromDC( hdc );
+   if(!fb->stfb) {
+      FREE(fb);
+      return NULL;
+   }
 
    pipe_mutex_lock( stw_dev->mutex );
    fb->next = stw_dev->fb_head;
@@ -165,6 +171,8 @@ stw_framebuffer_destroy(
 
    st_unreference_framebuffer(fb->stfb);
    
+   pipe_mutex_destroy( fb->mutex );
+   
    FREE( fb );
 }
 
@@ -199,6 +207,8 @@ stw_swap_buffers(
    if (fb == NULL)
       return FALSE;
 
+   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.
     */
@@ -206,9 +216,11 @@ stw_swap_buffers(
 
    screen = stw_dev->screen;
    
-   if(!st_get_framebuffer_surface( fb->stfb, ST_SURFACE_BACK_LEFT, &surface ))
+   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 );
       return FALSE;
+   }
 
 #ifdef DEBUG
    if(stw_dev->trace_running) {
@@ -219,6 +231,8 @@ stw_swap_buffers(
 
    stw_dev->stw_winsys->flush_frontbuffer( screen, surface, hdc );
    
+   pipe_mutex_unlock( fb->mutex );
+   
    return TRUE;
 }
 
index 607b7f0ef2a3e9039dfdc2e74d1dce1ab5652b6c..f5b48db048cfaa7229d481b2b112caa43f9887aa 100644 (file)
 #ifndef STW_FRAMEBUFFER_H
 #define STW_FRAMEBUFFER_H
 
+#include <windows.h>
+
 #include "main/mtypes.h"
 
+#include "pipe/p_thread.h"
+
 struct stw_pixelformat_info;
 
 /**
@@ -37,9 +41,13 @@ struct stw_pixelformat_info;
  */
 struct stw_framebuffer
 {
-   struct st_framebuffer *stfb;
    HDC hDC;
    HWND hWnd;
+
+   pipe_mutex mutex;
+   struct st_framebuffer *stfb;
+   
+   /** This is protected by stw_device::mutex, not the mutex above */
    struct stw_framebuffer *next;
 };
 
@@ -55,12 +63,6 @@ void
 stw_framebuffer_destroy(
    struct stw_framebuffer *fb );
 
-void
-stw_framebuffer_resize(
-   struct stw_framebuffer *fb,
-   GLuint width,
-   GLuint height );
-
 struct stw_framebuffer *
 stw_framebuffer_from_hdc(
    HDC hdc );