wgl: Protect the framebuffer with a lock.
[mesa.git] / src / gallium / state_trackers / wgl / shared / stw_context.c
index e89438557de78b81e5d3556736a702e56b2dc5e1..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 "wgl/stw_wgl_arbmultisample.h"
+#include "stw_public.h"
 #include "stw_context.h"
-//#include "stw_wgl.h"
-
-static struct wgl_context *ctx_head = NULL;
-
-static HDC current_hdc = NULL;
-static HGLRC current_hrc = NULL;
+#include "stw_tls.h"
 
 BOOL
-stw_wgl_copy_context(
-   HGLRC hglrcSrc,
-   HGLRC hglrcDst,
+stw_copy_context(
+   UINT_PTR hglrcSrc,
+   UINT_PTR hglrcDst,
    UINT mask )
 {
-   (void) hglrcSrc;
-   (void) hglrcDst;
-   (void) mask;
+   struct stw_context *src;
+   struct stw_context *dst;
+   BOOL ret = FALSE;
+
+   pipe_mutex_lock( stw_dev->mutex );
+   
+   src = stw_lookup_context_locked( hglrcSrc );
+   dst = stw_lookup_context_locked( hglrcDst );
+
+   if (src && dst) { 
+      /* FIXME */
+      (void) src;
+      (void) dst;
+      (void) mask;
+   }
 
-   return FALSE;
+   pipe_mutex_unlock( stw_dev->mutex );
+   
+   return ret;
 }
 
-HGLRC
-stw_wgl_create_context(
+UINT_PTR
+stw_create_layer_context(
    HDC hdc,
    int iLayerPlane )
 {
    uint pfi;
-   const struct pixelformat_info *pf;
-   struct wgl_context *ctx;
-   GLvisual *visual;
-   struct pipe_context *pipe;
-
+   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;
+
+   if(!stw_dev)
+      return 0;
+   
    if (iLayerPlane != 0)
-      return NULL;
+      return 0;
 
-   pfi = wglGetPixelFormat( hdc );
+   pfi = stw_pixelformat_get( hdc );
    if (pfi == 0)
-      return NULL;
+      return 0;
 
-   pf = pixelformat_get_info( pfi - 1 );
+   pf = stw_pixelformat_get_info( pfi - 1 );
 
-   ctx = CALLOC_STRUCT( wgl_context );
+   ctx = CALLOC_STRUCT( stw_context );
    if (ctx == NULL)
-      return NULL;
+      return 0;
 
    ctx->hdc = hdc;
    ctx->color_bits = GetDeviceCaps( ctx->hdc, BITSPIXEL );
@@ -89,95 +109,151 @@ stw_wgl_create_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) ? wgl_query_samples() : 0 );
-   if (visual == NULL) {
-      FREE( ctx );
-      return NULL;
-   }
+      (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;
+
+   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
 
-   pipe = stw_dev->stw_winsys->create_context( stw_dev->screen );
-   if (!pipe) {
-      _mesa_destroy_visual( visual );
-      FREE( ctx );
-      return NULL;
-   }
-   
    assert(!pipe->priv);
    pipe->priv = hdc;
 
    ctx->st = st_create_context( pipe, visual, NULL );
-   if (ctx->st == NULL) {
-      pipe->destroy( pipe );
-      _mesa_destroy_visual( visual );
-      FREE( ctx );
-      return NULL;
-   }
+   if (ctx->st == NULL) 
+      goto fail;
+
    ctx->st->ctx->DriverCtx = ctx;
+   ctx->pfi = pf;
 
-   ctx->next = ctx_head;
-   ctx_head = ctx;
+   pipe_mutex_lock( stw_dev->mutex );
+   hglrc = handle_table_add(stw_dev->ctx_table, ctx);
+   pipe_mutex_unlock( stw_dev->mutex );
 
-   return (HGLRC) ctx;
-}
+   /* Success?
+    */
+   if (hglrc != 0)
+      return hglrc;
 
+fail:
+   if (visual)
+      _mesa_destroy_visual( visual );
+   
+   if (pipe)
+      pipe->destroy( pipe );
+      
+   FREE( ctx );
+   return 0;
+}
 
 BOOL
-stw_wgl_delete_context(
-   HGLRC hglrc )
+stw_delete_context(
+   UINT_PTR hglrc )
 {
-   struct wgl_context **link = &ctx_head;
-   struct wgl_context *ctx = ctx_head;
+   struct stw_context *ctx ;
+   BOOL ret = FALSE;
+   
+   if (!stw_dev)
+      return FALSE;
 
-   while (ctx != NULL) {
-      if (ctx == (struct wgl_context *) hglrc) {
-         GLcontext *glctx = ctx->st->ctx;
-         GET_CURRENT_CONTEXT( glcurctx );
-         struct stw_framebuffer *fb;
+   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 );
 
-         /* Unbind current if deleting current context.
-          */
-         if (glcurctx == glctx)
-            st_make_current( NULL, NULL, NULL );
+   if (ctx) {
+      GLcontext *glctx = ctx->st->ctx;
+      GET_CURRENT_CONTEXT( glcurctx );
+      struct stw_framebuffer *fb;
 
-         fb = framebuffer_from_hdc( ctx->hdc );
-         if (fb)
-            framebuffer_destroy( fb );
+      /* Unbind current if deleting current context.
+       */
+      if (glcurctx == glctx)
+         st_make_current( NULL, NULL, NULL );
 
-         if (WindowFromDC( ctx->hdc ) != NULL)
-            ReleaseDC( WindowFromDC( ctx->hdc ), ctx->hdc );
+      fb = stw_framebuffer_from_hdc( ctx->hdc );
+      if (fb)
+         stw_framebuffer_destroy( fb );
 
-         st_destroy_context( ctx->st );
+      if (WindowFromDC( ctx->hdc ) != NULL)
+         ReleaseDC( WindowFromDC( ctx->hdc ), ctx->hdc );
 
-         *link = ctx->next;
-         FREE( ctx );
-         return TRUE;
-      }
+      st_destroy_context(ctx->st);
+      FREE(ctx);
 
-      link = &ctx->next;
-      ctx = ctx->next;
+      ret = TRUE;
    }
 
-   return FALSE;
+   return ret;
+}
+
+BOOL
+stw_release_context(
+   UINT_PTR hglrc )
+{
+   struct stw_context *ctx;
+
+   if (!stw_dev)
+      return FALSE;
+
+   pipe_mutex_lock( stw_dev->mutex );
+   ctx = stw_lookup_context_locked( hglrc );
+   pipe_mutex_unlock( stw_dev->mutex );
+
+   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 );
+
+      if (glcurctx != glctx)
+         return FALSE;
+   }
+
+   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;
@@ -192,76 +268,80 @@ get_window_size( HDC hdc, GLuint *width, GLuint *height )
    }
 }
 
-HGLRC
-stw_wgl_get_current_context( void )
+UINT_PTR
+stw_get_current_context( void )
 {
-   return current_hrc;
+   return stw_tls_get_data()->currentGLRC;
 }
 
 HDC
-stw_wgl_get_current_dc( void )
+stw_get_current_dc( void )
 {
-    return current_hdc;
+    return stw_tls_get_data()->currentDC;
 }
 
 BOOL
-stw_wgl_make_current(
+stw_make_current(
    HDC hdc,
-   HGLRC hglrc )
+   UINT_PTR hglrc )
 {
-   struct wgl_context *ctx = ctx_head;
+   struct stw_context *ctx;
    GET_CURRENT_CONTEXT( glcurctx );
    struct stw_framebuffer *fb;
    GLuint width = 0;
    GLuint height = 0;
+   struct stw_context *curctx;
+
+   if (!stw_dev)
+      return FALSE;
 
-   current_hdc = hdc;
-   current_hrc = hglrc;
+   pipe_mutex_lock( stw_dev->mutex ); 
+   ctx = stw_lookup_context_locked( hglrc );
+   pipe_mutex_unlock( stw_dev->mutex );
 
-   if (hdc == NULL || hglrc == NULL) {
-      st_make_current( NULL, NULL, NULL );
-      return TRUE;
+   stw_tls_get_data()->currentDC = hdc;
+   stw_tls_get_data()->currentGLRC = hglrc;
+
+   if (glcurctx != NULL) {
+      curctx = (struct stw_context *) glcurctx->DriverCtx;
+
+      if (curctx != ctx)
+        st_flush(glcurctx->st, PIPE_FLUSH_RENDER_CACHE, NULL);
    }
 
-   while (ctx != NULL) {
-      if (ctx == (struct wgl_context *) hglrc)
-         break;
-      ctx = ctx->next;
+   if (hdc == NULL || hglrc == 0) {
+      st_make_current( NULL, NULL, NULL );
+      return TRUE;
    }
-   if (ctx == NULL)
-      return FALSE;
 
    /* Return if already current.
     */
    if (glcurctx != NULL) {
-      struct wgl_context *curctx = (struct wgl_context *) glcurctx->DriverCtx;
-
       if (curctx != NULL && curctx == ctx && ctx->hdc == hdc)
          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;
    }
@@ -272,74 +352,3 @@ stw_wgl_make_current(
 
    return TRUE;
 }
-
-struct wgl_context *
-wgl_context_from_hdc(
-   HDC hdc )
-{
-   struct wgl_context *ctx = ctx_head;
-
-   while (ctx != NULL) {
-      if (ctx->hdc == hdc)
-         return ctx;
-      ctx = ctx->next;
-   }
-   return NULL;
-}
-
-
-
-int
-stw_pixelformat_describe(
-   HDC hdc,
-   int iPixelFormat,
-   UINT nBytes,
-   LPPIXELFORMATDESCRIPTOR ppfd )
-{
-   uint count;
-   uint index;
-   const struct pixelformat_info *pf;
-
-   (void) hdc;
-
-   count = pixelformat_get_extended_count();
-   index = (uint) iPixelFormat - 1;
-
-   if (ppfd == NULL)
-      return count;
-   if (index >= count || nBytes != sizeof( PIXELFORMATDESCRIPTOR ))
-      return 0;
-
-   pf = pixelformat_get_info( index );
-
-   ppfd->nSize = sizeof( PIXELFORMATDESCRIPTOR );
-   ppfd->nVersion = 1;
-   ppfd->dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL;
-   if (pf->flags & PF_FLAG_DOUBLEBUFFER)
-      ppfd->dwFlags |= PFD_DOUBLEBUFFER | PFD_SWAP_COPY;
-   ppfd->iPixelType = PFD_TYPE_RGBA;
-   ppfd->cColorBits = pf->color.redbits + pf->color.greenbits + pf->color.bluebits;
-   ppfd->cRedBits = pf->color.redbits;
-   ppfd->cRedShift = pf->color.redshift;
-   ppfd->cGreenBits = pf->color.greenbits;
-   ppfd->cGreenShift = pf->color.greenshift;
-   ppfd->cBlueBits = pf->color.bluebits;
-   ppfd->cBlueShift = pf->color.blueshift;
-   ppfd->cAlphaBits = pf->alpha.alphabits;
-   ppfd->cAlphaShift = pf->alpha.alphashift;
-   ppfd->cAccumBits = 0;
-   ppfd->cAccumRedBits = 0;
-   ppfd->cAccumGreenBits = 0;
-   ppfd->cAccumBlueBits = 0;
-   ppfd->cAccumAlphaBits = 0;
-   ppfd->cDepthBits = pf->depth.depthbits;
-   ppfd->cStencilBits = pf->depth.stencilbits;
-   ppfd->cAuxBuffers = 0;
-   ppfd->iLayerType = 0;
-   ppfd->bReserved = 0;
-   ppfd->dwLayerMask = 0;
-   ppfd->dwVisibleMask = 0;
-   ppfd->dwDamageMask = 0;
-
-   return count;
-}