wgl: mutex-protect the shared stw_icd struct
authorKeith Whitwell <keith@tungstengraphics.com>
Tue, 10 Feb 2009 18:11:44 +0000 (18:11 +0000)
committerKeith Whitwell <keith@tungstengraphics.com>
Tue, 10 Feb 2009 18:11:44 +0000 (18:11 +0000)
src/gallium/state_trackers/wgl/icd/stw_icd.c

index e160004aea4d52c8b8bddd2da308e6aade8af436..2cefc5c812c10d9a4d725c2c70f235f43e604a1e 100644 (file)
@@ -31,6 +31,7 @@
 #include "GL/gl.h"
 
 #include "pipe/p_debug.h"
+#include "pipe/p_thread.h"
 
 #include "shared/stw_public.h"
 #include "icd/stw_icd.h"
 
 struct stw_icd
 {
+   pipe_mutex mutex;
+
+   GLCLTPROCTABLE cpt;
+   boolean cpt_initialized;
+
    struct {
       struct stw_context *ctx;
    } ctx_array[DRV_CONTEXT_MAX];
@@ -60,6 +66,8 @@ stw_icd_init( void )
    stw_icd = &stw_icd_storage;
    memset(stw_icd, 0, sizeof *stw_icd);
 
+   pipe_mutex_init( stw_icd->mutex );
+
    return TRUE;
 }
 
@@ -70,24 +78,30 @@ stw_icd_cleanup(void)
 
    if(!stw_icd)
       return;
+   
+   pipe_mutex_lock( stw_icd->mutex );
+   {
+      /* Ensure all contexts are destroyed */
+      for (i = 0; i < DRV_CONTEXT_MAX; i++)
+         if (stw_icd->ctx_array[i].ctx) 
+            stw_delete_context( stw_icd->ctx_array[i].ctx );
+   }
+   pipe_mutex_unlock( stw_icd->mutex );
 
-   /* Ensure all contexts are destroyed */
-   for (i = 0; i < DRV_CONTEXT_MAX; i++)
-      if (stw_icd->ctx_array[i].ctx) 
-         stw_delete_context( stw_icd->ctx_array[i].ctx );
-
+   pipe_mutex_init( stw_icd->mutex );
    stw_icd = NULL;
 }
 
 
 static struct stw_context *
-lookup_context( DHGLRC dhglrc )
+lookup_context( struct stw_icd *icd, 
+                DHGLRC dhglrc )
 {
    if (dhglrc == 0 || 
        dhglrc >= DRV_CONTEXT_MAX)
       return NULL;
 
-   return stw_icd->ctx_array[dhglrc - 1].ctx;
+   return icd->ctx_array[dhglrc - 1].ctx;
 }
 
 BOOL APIENTRY
@@ -96,14 +110,22 @@ DrvCopyContext(
    DHGLRC dhrcDest,
    UINT fuMask )
 {
-   struct stw_context *src = lookup_context( dhrcSource );
-   struct stw_context *dst = lookup_context( dhrcDest );
+   BOOL ret = FALSE;
+
+   pipe_mutex_lock( stw_icd->mutex );
+   {
+      struct stw_context *src = lookup_context( stw_icd, dhrcSource );
+      struct stw_context *dst = lookup_context( stw_icd, dhrcDest );
    
-   if (src == NULL ||
-       dst == NULL)
-      return FALSE;
+      if (src == NULL || dst == NULL) 
+         goto done;
 
-   return stw_copy_context( src, dst, fuMask );
+      ret = stw_copy_context( src, dst, fuMask );
+   }
+done:
+   pipe_mutex_unlock( stw_icd->mutex );
+
+   return ret;
 }
 
 DHGLRC APIENTRY
@@ -111,23 +133,34 @@ DrvCreateLayerContext(
    HDC hdc,
    INT iLayerPlane )
 {
-   DWORD i;
+   DHGLRC handle = 0;;
+
+   pipe_mutex_lock( stw_icd->mutex );
+   {
+      int i;
+
+      for (i = 0; i < DRV_CONTEXT_MAX; i++) {
+         if (stw_icd->ctx_array[i].ctx == NULL)
+            break;
+      }
    
-   for (i = 0; i < DRV_CONTEXT_MAX; i++) {
-      if (stw_icd->ctx_array[i].ctx == NULL)
-         goto found_slot;
+      /* No slot available, fail:
+       */
+      if (i == DRV_CONTEXT_MAX)
+         goto done;
+
+      stw_icd->ctx_array[i].ctx = stw_create_context( hdc, iLayerPlane );
+      if (stw_icd->ctx_array[i].ctx == NULL) 
+         goto done;
+      
+      /* success:
+       */
+      handle = (DHGLRC) i + 1;
    }
-   
-   /* No slot available, fail:
-    */
-   return 0;
-
-found_slot:
-   stw_icd->ctx_array[i].ctx = stw_create_context( hdc, iLayerPlane );
-   if (stw_icd->ctx_array[i].ctx == NULL)
-      return 0;
+done:
+   pipe_mutex_unlock( stw_icd->mutex );
 
-   return (DHGLRC) i + 1;
+   return handle;
 }
 
 DHGLRC APIENTRY
@@ -141,20 +174,27 @@ BOOL APIENTRY
 DrvDeleteContext(
    DHGLRC dhglrc )
 {
-   struct stw_context *ctx;
+   BOOL ret = FALSE;
 
-   ctx = lookup_context( dhglrc );
-   if (ctx == NULL) 
-      goto fail;
+   pipe_mutex_lock( stw_icd->mutex );
+   {
+      struct stw_context *ctx;
 
-   if (stw_delete_context( ctx ) == FALSE)
-      goto fail;
+      ctx = lookup_context( stw_icd, dhglrc );
+      if (ctx == NULL) 
+         goto done;
+      
+      if (stw_delete_context( ctx ) == FALSE)
+         goto done;
+      
+      stw_icd->ctx_array[dhglrc - 1].ctx = NULL;
+      ret = TRUE;
 
-   stw_icd->ctx_array[dhglrc - 1].ctx = NULL;
-   return TRUE;
+   }
+done:
+   pipe_mutex_unlock( stw_icd->mutex );
    
-fail:
-   return FALSE;
+   return ret;
 }
 
 BOOL APIENTRY
@@ -228,23 +268,29 @@ BOOL APIENTRY
 DrvReleaseContext(
    DHGLRC dhglrc )
 {
-   struct stw_context *ctx;
+   BOOL ret = FALSE;
 
-   /* XXX: The expectation is that ctx is the same context which is
-    * current for this thread.  We should check that and return False
-    * if not the case.
-    */
-   ctx = lookup_context( dhglrc );
-   if (ctx == NULL) 
-      goto fail;
+   pipe_mutex_lock( stw_icd->mutex );
+   {
+      struct stw_context *ctx;
 
-   if (stw_make_current( NULL, NULL ) == FALSE)
-      goto fail;
+      /* XXX: The expectation is that ctx is the same context which is
+       * current for this thread.  We should check that and return False
+       * if not the case.
+       */
+      ctx = lookup_context( stw_icd, dhglrc );
+      if (ctx == NULL) 
+         goto done;
 
-   return TRUE;
+      if (stw_make_current( NULL, NULL ) == FALSE)
+         goto done;
 
-fail:
-   return FALSE;
+      ret = TRUE;
+   }
+done:
+   pipe_mutex_unlock( stw_icd->mutex );
+
+   return ret;
 }
 
 void APIENTRY
@@ -257,31 +303,15 @@ DrvSetCallbackProcs(
    return;
 }
 
-#define GPA_GL( NAME ) disp->NAME = gl##NAME
 
-static GLCLTPROCTABLE cpt;
+static void init_proc_table( GLCLTPROCTABLE *cpt )
+{ 
+   GLDISPATCHTABLE *disp = &cpt->glDispatchTable;
 
-PGLCLTPROCTABLE APIENTRY
-DrvSetContext(
-   HDC hdc,
-   DHGLRC dhglrc,
-   PFN_SETPROCTABLE pfnSetProcTable )
-{
-   struct stw_context *ctx;
-   GLDISPATCHTABLE *disp = &cpt.glDispatchTable;
-
-   debug_printf( "%s( 0x%p, %u, 0x%p )\n", __FUNCTION__, hdc, dhglrc, pfnSetProcTable );
-
-   ctx = lookup_context( dhglrc );
-   if (ctx == NULL)
-      return NULL;
-
-   if (!stw_make_current( hdc, ctx ))
-      return NULL;
-
-   memset( &cpt, 0, sizeof( cpt ) );
-   cpt.cEntries = OPENGL_VERSION_110_ENTRIES;
+   memset( cpt, 0, sizeof *cpt );
+   cpt->cEntries = OPENGL_VERSION_110_ENTRIES;
 
+#define GPA_GL( NAME ) disp->NAME = gl##NAME
    GPA_GL( NewList );
    GPA_GL( EndList );
    GPA_GL( CallList );
@@ -618,8 +648,43 @@ DrvSetContext(
    GPA_GL( TexSubImage2D );
    GPA_GL( PopClientAttrib );
    GPA_GL( PushClientAttrib );
+}
+
+PGLCLTPROCTABLE APIENTRY
+DrvSetContext(
+   HDC hdc,
+   DHGLRC dhglrc,
+   PFN_SETPROCTABLE pfnSetProcTable )
+{
+   PGLCLTPROCTABLE result = NULL;
+
+   pipe_mutex_lock( stw_icd->mutex ); 
+   {
+      struct stw_context *ctx;
+
+      debug_printf( "%s( 0x%p, %u, 0x%p )\n", 
+                    __FUNCTION__, hdc, dhglrc, pfnSetProcTable );
+
+      /* Although WGL allows different dispatch entrypoints per 
+       */
+      if (!stw_icd->cpt_initialized) {
+         init_proc_table( &stw_icd->cpt );
+         stw_icd->cpt_initialized = TRUE;
+      }
+
+      ctx = lookup_context( stw_icd, dhglrc );
+      if (ctx == NULL)
+         goto done;
+
+      if (!stw_make_current( hdc, ctx ))
+         goto done;
+
+      result = &stw_icd->cpt;
+   }
+done:
+   pipe_mutex_unlock( stw_icd->mutex );
 
-   return &cpt;
+   return result;
 }
 
 int APIENTRY