wgl: Protect the framebuffer with a lock.
[mesa.git] / src / gallium / state_trackers / wgl / shared / stw_context.c
index d77daac39cd63833eee8e10bc55633f80238caed..f3c7af93f503aa99e97c33da1e99f04277b5828a 100644 (file)
 #include "pipe/p_context.h"
 #include "state_tracker/st_context.h"
 #include "state_tracker/st_public.h"
+
+#ifdef DEBUG
+#include "trace/tr_screen.h"
+#include "trace/tr_context.h"
+#endif
+
 #include "shared/stw_device.h"
 #include "shared/stw_winsys.h"
 #include "shared/stw_framebuffer.h"
 #include "shared/stw_pixelformat.h"
 #include "stw_public.h"
 #include "stw_context.h"
-
-static HDC current_hdc = NULL;
-static UINT_PTR current_hglrc = 0;
+#include "stw_tls.h"
 
 BOOL
 stw_copy_context(
@@ -55,8 +59,8 @@ stw_copy_context(
 
    pipe_mutex_lock( stw_dev->mutex );
    
-   src = stw_lookup_context( hglrcSrc );
-   dst = stw_lookup_context( hglrcDst );
+   src = stw_lookup_context_locked( hglrcSrc );
+   dst = stw_lookup_context_locked( hglrcDst );
 
    if (src && dst) { 
       /* FIXME */
@@ -76,9 +80,10 @@ stw_create_layer_context(
    int iLayerPlane )
 {
    uint pfi;
-   const struct pixelformat_info *pf = NULL;
+   const struct stw_pixelformat_info *pf = NULL;
    struct stw_context *ctx = NULL;
    GLvisual *visual = NULL;
+   struct pipe_screen *screen = NULL;
    struct pipe_context *pipe = NULL;
    UINT_PTR hglrc = 0;
 
@@ -92,7 +97,7 @@ stw_create_layer_context(
    if (pfi == 0)
       return 0;
 
-   pf = pixelformat_get_info( pfi - 1 );
+   pf = stw_pixelformat_get_info( pfi - 1 );
 
    ctx = CALLOC_STRUCT( stw_context );
    if (ctx == NULL)
@@ -104,28 +109,42 @@ stw_create_layer_context(
    /* Create visual based on flags
     */
    visual = _mesa_create_visual(
-      GL_TRUE,
-      (pf->flags & PF_FLAG_DOUBLEBUFFER) ? GL_TRUE : GL_FALSE,
-      GL_FALSE,
-      pf->color.redbits,
-      pf->color.greenbits,
-      pf->color.bluebits,
-      pf->alpha.alphabits,
-      0,
-      pf->depth.depthbits,
-      pf->depth.stencilbits,
-      0,
-      0,
-      0,
-      0,
-      (pf->flags & PF_FLAG_MULTISAMPLED) ? stw_query_samples() : 0 );
+      (pf->pfd.iPixelType == PFD_TYPE_RGBA) ? GL_TRUE : GL_FALSE,
+      (pf->pfd.dwFlags & PFD_DOUBLEBUFFER) ? GL_TRUE : GL_FALSE,
+      (pf->pfd.dwFlags & PFD_STEREO) ? GL_TRUE : GL_FALSE,
+      pf->pfd.cRedBits,
+      pf->pfd.cGreenBits,
+      pf->pfd.cBlueBits,
+      pf->pfd.cAlphaBits,
+      (pf->pfd.iPixelType == PFD_TYPE_COLORINDEX) ? pf->pfd.cColorBits : 0,
+      pf->pfd.cDepthBits,
+      pf->pfd.cStencilBits,
+      pf->pfd.cAccumRedBits,
+      pf->pfd.cAccumGreenBits,
+      pf->pfd.cAccumBlueBits,
+      pf->pfd.cAccumAlphaBits,
+      pf->numSamples );
    if (visual == NULL) 
       goto fail;
 
-   pipe = stw_dev->stw_winsys->create_context( stw_dev->screen );
+   screen = stw_dev->screen;
+
+#ifdef DEBUG
+   /* Unwrap screen */
+   if(stw_dev->trace_running)
+      screen = trace_screen(screen)->screen;
+#endif
+
+   pipe = stw_dev->stw_winsys->create_context( screen );
    if (pipe == NULL) 
       goto fail;
 
+#ifdef DEBUG
+   /* Wrap context */
+   if(stw_dev->trace_running)
+      pipe = trace_context_create(stw_dev->screen, pipe);
+#endif
+
    assert(!pipe->priv);
    pipe->priv = hdc;
 
@@ -134,21 +153,10 @@ stw_create_layer_context(
       goto fail;
 
    ctx->st->ctx->DriverCtx = ctx;
+   ctx->pfi = pf;
 
    pipe_mutex_lock( stw_dev->mutex );
-   {
-      UINT_PTR i;
-
-      for (i = 0; i < STW_CONTEXT_MAX; i++) {
-         if (stw_dev->ctx_array[i].ctx == NULL) {
-            /* success:
-             */
-            stw_dev->ctx_array[i].ctx = ctx;
-            hglrc = i + 1;
-            break;
-         }
-      }
-   }
+   hglrc = handle_table_add(stw_dev->ctx_table, ctx);
    pipe_mutex_unlock( stw_dev->mutex );
 
    /* Success?
@@ -178,8 +186,10 @@ stw_delete_context(
       return FALSE;
 
    pipe_mutex_lock( stw_dev->mutex );
+   ctx = stw_lookup_context_locked(hglrc);
+   handle_table_remove(stw_dev->ctx_table, hglrc);
+   pipe_mutex_unlock( stw_dev->mutex );
 
-   ctx = stw_lookup_context(hglrc);
    if (ctx) {
       GLcontext *glctx = ctx->st->ctx;
       GET_CURRENT_CONTEXT( glcurctx );
@@ -190,24 +200,19 @@ stw_delete_context(
       if (glcurctx == glctx)
          st_make_current( NULL, NULL, NULL );
 
-      fb = framebuffer_from_hdc( ctx->hdc );
+      fb = stw_framebuffer_from_hdc( ctx->hdc );
       if (fb)
-         framebuffer_destroy( fb );
+         stw_framebuffer_destroy( fb );
 
       if (WindowFromDC( ctx->hdc ) != NULL)
          ReleaseDC( WindowFromDC( ctx->hdc ), ctx->hdc );
 
-      st_destroy_context( ctx->st );
+      st_destroy_context(ctx->st);
+      FREE(ctx);
 
-      FREE( ctx );
-      
-      stw_dev->ctx_array[hglrc - 1].ctx = NULL;
-      
       ret = TRUE;
    }
 
-   pipe_mutex_unlock( stw_dev->mutex );
-   
    return ret;
 }
 
@@ -215,38 +220,40 @@ BOOL
 stw_release_context(
    UINT_PTR hglrc )
 {
-   BOOL ret = FALSE;
+   struct stw_context *ctx;
 
    if (!stw_dev)
-      return ret;
+      return FALSE;
 
    pipe_mutex_lock( stw_dev->mutex );
-   {
-      struct stw_context *ctx;
-
-      /* 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 = stw_lookup_context( hglrc );
-      if (ctx == NULL) 
-         goto done;
+   ctx = stw_lookup_context_locked( hglrc );
+   pipe_mutex_unlock( stw_dev->mutex );
 
-      if (stw_make_current( NULL, 0 ) == FALSE)
-         goto done;
+   if (!ctx)
+      return FALSE;
+   
+   /* 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.
+    */
+   {
+      GLcontext *glctx = ctx->st->ctx;
+      GET_CURRENT_CONTEXT( glcurctx );
 
-      ret = TRUE;
+      if (glcurctx != glctx)
+         return FALSE;
    }
-done:
-   pipe_mutex_unlock( stw_dev->mutex );
 
-   return ret;
+   if (stw_make_current( NULL, 0 ) == FALSE)
+      return FALSE;
+
+   return TRUE;
 }
 
 /* Find the width and height of the window named by hdc.
  */
 static void
-get_window_size( HDC hdc, GLuint *width, GLuint *height )
+stw_get_window_size( HDC hdc, GLuint *width, GLuint *height )
 {
    if (WindowFromDC( hdc )) {
       RECT rect;
@@ -264,13 +271,13 @@ get_window_size( HDC hdc, GLuint *width, GLuint *height )
 UINT_PTR
 stw_get_current_context( void )
 {
-   return current_hglrc;
+   return stw_tls_get_data()->currentGLRC;
 }
 
 HDC
 stw_get_current_dc( void )
 {
-    return current_hdc;
+    return stw_tls_get_data()->currentDC;
 }
 
 BOOL
@@ -289,14 +296,11 @@ stw_make_current(
       return FALSE;
 
    pipe_mutex_lock( stw_dev->mutex ); 
-   ctx = stw_lookup_context( hglrc );
+   ctx = stw_lookup_context_locked( hglrc );
    pipe_mutex_unlock( stw_dev->mutex );
-   
-   if (ctx == NULL)
-      return FALSE;
 
-   current_hdc = hdc;
-   current_hglrc = hglrc;
+   stw_tls_get_data()->currentDC = hdc;
+   stw_tls_get_data()->currentGLRC = hglrc;
 
    if (glcurctx != NULL) {
       curctx = (struct stw_context *) glcurctx->DriverCtx;
@@ -317,28 +321,27 @@ stw_make_current(
          return TRUE;
    }
 
-   fb = framebuffer_from_hdc( hdc );
+   fb = stw_framebuffer_from_hdc( hdc );
 
    if (hdc != NULL)
-      get_window_size( hdc, &width, &height );
+      stw_get_window_size( hdc, &width, &height );
 
-   /* Lazy creation of framebuffers.
+   /* Lazy creation of stw_framebuffers.
     */
    if (fb == NULL && ctx != NULL && hdc != NULL) {
       GLvisual *visual = &ctx->st->ctx->Visual;
 
-      fb = framebuffer_create( hdc, visual, width, height );
+      fb = stw_framebuffer_create( hdc, visual, ctx->pfi, width, height );
       if (fb == NULL)
          return FALSE;
-
-      fb->dib_hDC = CreateCompatibleDC( hdc );
-      fb->hbmDIB = NULL;
-      fb->pbPixels = NULL;
    }
 
    if (ctx && fb) {
+      pipe_mutex_lock( fb->mutex );
       st_make_current( ctx->st, fb->stfb, fb->stfb );
-      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;
    }