r600g: reduce flushes for queries
[mesa.git] / src / gallium / state_trackers / wgl / stw_context.c
index 86c0a28e8da75122cfa59aa62d279872e8f02ce6..c2839fe815ff8aaa22854a097fb1e753fb3f3149 100644 (file)
@@ -31,6 +31,7 @@
 #include "pipe/p_context.h"
 #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"
@@ -264,75 +265,82 @@ 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)
-         curctx->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);
       }
-
-      stw_framebuffer_reference(&curctx->current_framebuffer, NULL);
    }
 
-   if (hdc == NULL || dhglrc == 0) {
-      return stw_dev->stapi->make_current(stw_dev->stapi, 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) {
-      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) 
+   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;
-   }
-   
-   if(fb->iPixelFormat != ctx->iPixelFormat)
-      goto fail;
+      }
 
-   /* Bind the new framebuffer */
-   ctx->hdc = hdc;
+      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 (!stw_dev->stapi->make_current(stw_dev->stapi, ctx->st, fb->stfb, fb->stfb))
-      goto fail;
+      if (fb->iPixelFormat != ctx->iPixelFormat) {
+         SetLastError(ERROR_INVALID_PIXEL_FORMAT);
+         goto fail;
+      }
 
-   stw_framebuffer_reference(&ctx->current_framebuffer, fb);
+      /* Bind the new framebuffer */
+      ctx->hdc = hdc;
 
-success:
-   assert(fb);
-   if(fb) {
-      stw_framebuffer_release(fb);
+      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);
    }
    
-   return TRUE;
-
 fail:
-   if(fb)
+
+   if (fb) {
       stw_framebuffer_release(fb);
-   stw_dev->stapi->make_current(stw_dev->stapi, 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;
 }
 
 /**
@@ -344,11 +352,7 @@ 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,
-            PIPE_FLUSH_RENDER_CACHE | 
-            PIPE_FLUSH_SWAPBUFFERS |
-            PIPE_FLUSH_FRAME,
-            NULL);
+      ctx->st->flush(ctx->st, ST_FLUSH_FRONT, NULL);
    }
 }
 
@@ -358,10 +362,7 @@ stw_flush_current_locked( struct stw_framebuffer *fb )
 void
 stw_notify_current_locked( struct stw_framebuffer *fb )
 {
-   struct stw_context *ctx = stw_current_context();
-
-   if (ctx && ctx->current_framebuffer == fb)
-      ctx->st->notify_invalid_framebuffer(ctx->st, fb->stfb);
+   p_atomic_inc(&fb->stfb->stamp);
 }
 
 /**