st-api: Rework how drawables are invalidated v3.
[mesa.git] / src / gallium / state_trackers / wgl / stw_context.c
index f2f0264844a73c26707904c487022ff298fdb9a5..c2839fe815ff8aaa22854a097fb1e753fb3f3149 100644 (file)
 
 #include <windows.h>
 
-#include "main/mtypes.h"
-#include "main/context.h"
 #include "pipe/p_compiler.h"
 #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 "pipe/p_state.h"
+#include "util/u_memory.h"
+#include "util/u_atomic.h"
+#include "state_tracker/st_api.h"
 
 #include "stw_icd.h"
 #include "stw_device.h"
 #include "stw_tls.h"
 
 
-static INLINE struct stw_context *
-stw_context(GLcontext *glctx)
-{
-   if(!glctx)
-      return NULL;
-   assert(glctx->DriverCtx);
-   return (struct stw_context *)glctx->DriverCtx;
-}
-
 static INLINE struct stw_context *
 stw_current_context(void)
 {
-   /* We must check if multiple threads are being used or GET_CURRENT_CONTEXT 
-    * might return the current context of the thread first seen. */
-   _glapi_check_multithread();
+   struct st_context_iface *st;
 
-   {
-      GET_CURRENT_CONTEXT( glctx );
-      return stw_context(glctx);
-   }
+   st = (stw_dev) ? stw_dev->stapi->get_current(stw_dev->stapi) : NULL;
+
+   return (struct stw_context *) ((st) ? st->st_manager_private : NULL);
 }
 
 BOOL APIENTRY
@@ -80,6 +63,9 @@ DrvCopyContext(
    struct stw_context *dst;
    BOOL ret = FALSE;
 
+   if (!stw_dev)
+      return FALSE;
+
    pipe_mutex_lock( stw_dev->ctx_mutex );
    
    src = stw_lookup_context_locked( dhrcSource );
@@ -107,35 +93,22 @@ DrvShareLists(
    struct stw_context *ctx2;
    BOOL ret = FALSE;
 
+   if (!stw_dev)
+      return FALSE;
+
    pipe_mutex_lock( stw_dev->ctx_mutex );
    
    ctx1 = stw_lookup_context_locked( dhglrc1 );
    ctx2 = stw_lookup_context_locked( dhglrc2 );
 
-   if (ctx1 && ctx2 &&
-       ctx1->iPixelFormat == ctx2->iPixelFormat) { 
-      ret = _mesa_share_state(ctx2->st->ctx, ctx1->st->ctx);
-   }
+   if (ctx1 && ctx2 && ctx2->st->share)
+      ret = ctx2->st->share(ctx2->st, ctx1->st);
 
    pipe_mutex_unlock( stw_dev->ctx_mutex );
    
    return ret;
 }
 
-static void
-stw_viewport(GLcontext * glctx, GLint x, GLint y,
-             GLsizei width, GLsizei height)
-{
-   struct stw_context *ctx = (struct stw_context *)glctx->DriverCtx;
-   struct stw_framebuffer *fb;
-   
-   fb = stw_framebuffer_from_hdc( ctx->hdc );
-   if(fb) {
-      stw_framebuffer_update(fb);
-      stw_framebuffer_release(fb);
-   }
-}
-
 DHGLRC APIENTRY
 DrvCreateContext(
    HDC hdc )
@@ -150,10 +123,8 @@ DrvCreateLayerContext(
 {
    int iPixelFormat;
    const struct stw_pixelformat_info *pfi;
-   GLvisual visual;
+   struct st_context_attribs attribs;
    struct stw_context *ctx = NULL;
-   struct pipe_screen *screen = NULL;
-   struct pipe_context *pipe = NULL;
    
    if(!stw_dev)
       return 0;
@@ -166,7 +137,6 @@ DrvCreateLayerContext(
       return 0;
    
    pfi = stw_pixelformat_get_info( iPixelFormat - 1 );
-   stw_pixelformat_visual(&visual, pfi);
    
    ctx = CALLOC_STRUCT( stw_context );
    if (ctx == NULL)
@@ -175,34 +145,16 @@ DrvCreateLayerContext(
    ctx->hdc = hdc;
    ctx->iPixelFormat = iPixelFormat;
 
-   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 no_pipe;
-
-#ifdef DEBUG
-   /* Wrap context */
-   if(stw_dev->trace_running)
-      pipe = trace_context_create(stw_dev->screen, pipe);
-#endif
+   memset(&attribs, 0, sizeof(attribs));
+   attribs.profile = ST_PROFILE_DEFAULT;
+   attribs.visual = pfi->stvis;
 
-   /* pass to stw_flush_frontbuffer as context_private */
-   assert(!pipe->priv);
-   pipe->priv = hdc;
-
-   ctx->st = st_create_context( pipe, &visual, NULL );
+   ctx->st = stw_dev->stapi->create_context(stw_dev->stapi,
+         stw_dev->smapi, &attribs, NULL);
    if (ctx->st == NULL) 
       goto no_st_ctx;
 
-   ctx->st->ctx->DriverCtx = ctx;
-   ctx->st->ctx->Driver.Viewport = stw_viewport;
+   ctx->st->st_manager_private = (void *) ctx;
 
    pipe_mutex_lock( stw_dev->ctx_mutex );
    ctx->dhglrc = handle_table_add(stw_dev->ctx_table, ctx);
@@ -213,11 +165,8 @@ DrvCreateLayerContext(
    return ctx->dhglrc;
 
 no_hglrc:
-   st_destroy_context(ctx->st);
-   goto no_pipe; /* st_context_destroy already destroys pipe */
+   ctx->st->destroy(ctx->st);
 no_st_ctx:
-   pipe->destroy( pipe );
-no_pipe:
    FREE(ctx);
 no_ctx:
    return 0;
@@ -243,9 +192,9 @@ DrvDeleteContext(
       
       /* Unbind current if deleting current context. */
       if (curctx == ctx)
-         st_make_current( NULL, NULL, NULL );
+         stw_dev->stapi->make_current(stw_dev->stapi, NULL, NULL, NULL);
 
-      st_destroy_context(ctx->st);
+      ctx->st->destroy(ctx->st);
       FREE(ctx);
 
       ret = TRUE;
@@ -316,76 +265,104 @@ stw_make_current(
    struct stw_context *curctx = NULL;
    struct stw_context *ctx = NULL;
    struct stw_framebuffer *fb = NULL;
+   BOOL ret = FALSE;
 
    if (!stw_dev)
-      goto fail;
+      return FALSE;
 
    curctx = stw_current_context();
    if (curctx != NULL) {
-      if (curctx->dhglrc != dhglrc)
-        st_flush(curctx->st, PIPE_FLUSH_RENDER_CACHE, NULL);
-      
-      /* Return if already current. */
-      if (curctx->dhglrc == dhglrc && curctx->hdc == hdc) {
-         ctx = curctx;
-         fb = stw_framebuffer_from_hdc( hdc );
-         goto success;
+      if (curctx->dhglrc == dhglrc) {
+         if (curctx->hdc == hdc) {
+            /* Return if already current. */
+            return TRUE;
+         }
+      } else {
+         curctx->st->flush(curctx->st, ST_FLUSH_FRONT, NULL);
       }
    }
 
-   if (hdc == NULL || dhglrc == 0) {
-      return st_make_current( NULL, NULL, NULL );
-   }
-
-   pipe_mutex_lock( stw_dev->ctx_mutex ); 
-   ctx = stw_lookup_context_locked( dhglrc );
-   pipe_mutex_unlock( stw_dev->ctx_mutex ); 
-   if(!ctx)
-      goto fail;
-
-   fb = stw_framebuffer_from_hdc( hdc );
-   if(!fb) { 
-      /* Applications should call SetPixelFormat before creating a context,
-       * but not all do, and the opengl32 runtime seems to use a default pixel
-       * format in some cases, so we must create a framebuffer for those here
-       */
-      int iPixelFormat = GetPixelFormat(hdc);
-      if(iPixelFormat)
-         fb = stw_framebuffer_create( hdc, iPixelFormat );
-      if(!fb) 
+   if (dhglrc) {
+      pipe_mutex_lock( stw_dev->ctx_mutex );
+      ctx = stw_lookup_context_locked( dhglrc );
+      pipe_mutex_unlock( stw_dev->ctx_mutex );
+      if (!ctx) {
          goto fail;
-   }
+      }
+
+      fb = stw_framebuffer_from_hdc( hdc );
+      if (fb) {
+         stw_framebuffer_update(fb);
+      }
+      else {
+         /* Applications should call SetPixelFormat before creating a context,
+          * but not all do, and the opengl32 runtime seems to use a default pixel
+          * format in some cases, so we must create a framebuffer for those here
+          */
+         int iPixelFormat = GetPixelFormat(hdc);
+         if (iPixelFormat)
+            fb = stw_framebuffer_create( hdc, iPixelFormat );
+         if (!fb)
+            goto fail;
+      }
    
-   if(fb->iPixelFormat != ctx->iPixelFormat)
-      goto fail;
+      if (fb->iPixelFormat != ctx->iPixelFormat) {
+         SetLastError(ERROR_INVALID_PIXEL_FORMAT);
+         goto fail;
+      }
 
-   /* Lazy allocation of the frame buffer */
-   if(!stw_framebuffer_allocate(fb))
-      goto fail;
+      /* Bind the new framebuffer */
+      ctx->hdc = hdc;
 
-   /* Bind the new framebuffer */
-   ctx->hdc = hdc;
-   
-   /* pass to stw_flush_frontbuffer as context_private */
-   ctx->st->pipe->priv = hdc;
+      ret = stw_dev->stapi->make_current(stw_dev->stapi, ctx->st, fb->stfb, fb->stfb);
+      stw_framebuffer_reference(&ctx->current_framebuffer, fb);
+   } else {
+      ret = stw_dev->stapi->make_current(stw_dev->stapi, NULL, NULL, NULL);
+   }
    
-   if(!st_make_current( ctx->st, fb->stfb, fb->stfb ))
-      goto fail;
+fail:
 
-success:
-   assert(fb);
-   if(fb) {
-      stw_framebuffer_update(fb);
+   if (fb) {
       stw_framebuffer_release(fb);
    }
-   
-   return TRUE;
 
-fail:
-   if(fb)
-      stw_framebuffer_release(fb);
-   st_make_current( NULL, NULL, NULL );
-   return FALSE;
+   /* On failure, make the thread's current rendering context not current
+    * before returning */
+   if (!ret) {
+      stw_dev->stapi->make_current(stw_dev->stapi, NULL, NULL, NULL);
+      ctx = NULL;
+   }
+
+   /* Unreference the previous framebuffer if any. It must be done after
+    * make_current, as it can be referenced inside.
+    */
+   if (curctx && curctx != ctx) {
+      stw_framebuffer_reference(&curctx->current_framebuffer, NULL);
+   }
+
+   return ret;
+}
+
+/**
+ * Flush the current context if it is bound to the framebuffer.
+ */
+void
+stw_flush_current_locked( struct stw_framebuffer *fb )
+{
+   struct stw_context *ctx = stw_current_context();
+
+   if (ctx && ctx->current_framebuffer == fb) {
+      ctx->st->flush(ctx->st, ST_FLUSH_FRONT, NULL);
+   }
+}
+
+/**
+ * Notify the current context that the framebuffer has become invalid.
+ */
+void
+stw_notify_current_locked( struct stw_framebuffer *fb )
+{
+   p_atomic_inc(&fb->stfb->stamp);
 }
 
 /**