st/mesa: add destroy_drawable interface
[mesa.git] / src / gallium / state_trackers / wgl / stw_st.c
index f4ea61ed2c653a47ce4ca9dd74210fde4cfe0e4a..85a8b1743eaa603336f8227e8c76eb390593e3a5 100644 (file)
@@ -1,6 +1,5 @@
 /*
  * Mesa 3-D graphics library
- * Version:  7.9
  *
  * Copyright (C) 2010 LunarG Inc.
  *
  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
- * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
  *
  * Authors:
  *    Chia-I Wu <olv@lunarg.com>
@@ -27,7 +27,8 @@
 
 #include "util/u_memory.h"
 #include "util/u_inlines.h"
-#include "state_tracker/st_manager.h" /* for st_manager_create_api */
+#include "util/u_atomic.h"
+#include "state_tracker/st_gl_api.h" /* for st_gl_api_create */
 
 #include "stw_st.h"
 #include "stw_device.h"
@@ -43,16 +44,31 @@ struct stw_st_framebuffer {
    struct pipe_resource *textures[ST_ATTACHMENT_COUNT];
    unsigned texture_width, texture_height;
    unsigned texture_mask;
-
-   struct pipe_surface *front_surface, *back_surface;
 };
 
-static INLINE struct stw_st_framebuffer *
-stw_st_framebuffer(struct st_framebuffer_iface *stfb)
+static uint32_t stwfb_ID = 0;
+
+/**
+ * Is the given mutex held by the calling thread?
+ */
+bool
+stw_own_mutex(const CRITICAL_SECTION *cs)
 {
-   return (struct stw_st_framebuffer *) stfb;
+   // We can't compare OwningThread with our thread handle/id (see
+   // http://stackoverflow.com/a/12675635 ) but we can compare with the
+   // OwningThread member of a critical section we know we own.
+   CRITICAL_SECTION dummy;
+   InitializeCriticalSection(&dummy);
+   EnterCriticalSection(&dummy);
+   if (0)
+      _debug_printf("%p %p\n", cs->OwningThread, dummy.OwningThread);
+   bool ret = cs->OwningThread == dummy.OwningThread;
+   LeaveCriticalSection(&dummy);
+   DeleteCriticalSection(&dummy);
+   return ret;
 }
 
+
 /**
  * Remove outdated textures and create the requested ones.
  */
@@ -65,10 +81,6 @@ stw_st_framebuffer_validate_locked(struct st_framebuffer_iface *stfb,
    struct pipe_resource templ;
    unsigned i;
 
-   /* remove outdated surface */
-   pipe_surface_reference(&stwfb->front_surface, NULL);
-   pipe_surface_reference(&stwfb->back_surface, NULL);
-
    /* remove outdated textures */
    if (stwfb->texture_width != width || stwfb->texture_height != height) {
       for (i = 0; i < ST_ATTACHMENT_COUNT; i++)
@@ -80,7 +92,9 @@ stw_st_framebuffer_validate_locked(struct st_framebuffer_iface *stfb,
    templ.width0 = width;
    templ.height0 = height;
    templ.depth0 = 1;
+   templ.array_size = 1;
    templ.last_level = 0;
+   templ.nr_samples = stwfb->stvis.samples;
 
    for (i = 0; i < ST_ATTACHMENT_COUNT; i++) {
       enum pipe_format format;
@@ -99,6 +113,7 @@ stw_st_framebuffer_validate_locked(struct st_framebuffer_iface *stfb,
       case ST_ATTACHMENT_BACK_LEFT:
          format = stwfb->stvis.color_format;
          bind = PIPE_BIND_DISPLAY_TARGET |
+                PIPE_BIND_SAMPLER_VIEW |
                 PIPE_BIND_RENDER_TARGET;
          break;
       case ST_ATTACHMENT_DEPTH_STENCIL:
@@ -125,7 +140,8 @@ stw_st_framebuffer_validate_locked(struct st_framebuffer_iface *stfb,
 }
 
 static boolean 
-stw_st_framebuffer_validate(struct st_framebuffer_iface *stfb,
+stw_st_framebuffer_validate(struct st_context_iface *stctx,
+                            struct st_framebuffer_iface *stfb,
                             const enum st_attachment_type *statts,
                             unsigned count,
                             struct pipe_resource **out)
@@ -137,7 +153,7 @@ stw_st_framebuffer_validate(struct st_framebuffer_iface *stfb,
    for (i = 0; i < count; i++)
       statt_mask |= 1 << statts[i];
 
-   pipe_mutex_lock(stwfb->fb->mutex);
+   stw_framebuffer_lock(stwfb->fb);
 
    if (stwfb->fb->must_resize || (statt_mask & ~stwfb->texture_mask)) {
       stw_st_framebuffer_validate_locked(&stwfb->base,
@@ -150,78 +166,58 @@ stw_st_framebuffer_validate(struct st_framebuffer_iface *stfb,
       pipe_resource_reference(&out[i], stwfb->textures[statts[i]]);
    }
 
-   stw_framebuffer_release(stwfb->fb);
+   stw_framebuffer_unlock(stwfb->fb);
 
    return TRUE;
 }
 
-static struct pipe_surface *
-get_present_surface_locked(struct st_framebuffer_iface *stfb,
-                           enum st_attachment_type statt)
-{
-   struct stw_st_framebuffer *stwfb = stw_st_framebuffer(stfb);
-   struct pipe_resource *ptex;
-   struct pipe_surface *psurf, **cache;
-   
-   ptex = stwfb->textures[statt];
-   if (!ptex)
-      return NULL;
-
-   psurf = NULL;
-
-   switch (statt) {
-   case ST_ATTACHMENT_FRONT_LEFT:
-      cache = &stwfb->front_surface;
-      break;
-   case ST_ATTACHMENT_BACK_LEFT:
-      cache = &stwfb->back_surface;
-      break;
-   default:
-      cache = &psurf;
-      break;
-   }
-
-   if (!*cache) {
-      *cache = stw_dev->screen->get_tex_surface(stw_dev->screen,
-            ptex, 0, 0, 0,
-            PIPE_BIND_DISPLAY_TARGET |
-            PIPE_BIND_RENDER_TARGET);
-   }
-
-   if (psurf != *cache)
-      pipe_surface_reference(&psurf, *cache);
-
-   return psurf;
-}
-
 /**
  * Present an attachment of the framebuffer.
  */
 static boolean
-stw_st_framebuffer_present_locked(struct st_framebuffer_iface *stfb,
+stw_st_framebuffer_present_locked(HDC hdc,
+                                  struct st_framebuffer_iface *stfb,
                                   enum st_attachment_type statt)
 {
    struct stw_st_framebuffer *stwfb = stw_st_framebuffer(stfb);
-   struct pipe_surface *psurf;
-   
-   psurf = get_present_surface_locked(&stwfb->base, statt);
-   if (psurf) {
-      stw_framebuffer_present_locked(stwfb->fb->hDC, stwfb->fb, psurf);
-      pipe_surface_reference(&psurf, NULL);
+   struct pipe_resource *resource;
+
+   assert(stw_own_mutex(&stwfb->fb->mutex));
+
+   resource = stwfb->textures[statt];
+   if (resource) {
+      stw_framebuffer_present_locked(hdc, stwfb->fb, resource);
+   }
+   else {
+      stw_framebuffer_unlock(stwfb->fb);
    }
 
+   assert(!stw_own_mutex(&stwfb->fb->mutex));
+
    return TRUE;
 }
 
 static boolean
-stw_st_framebuffer_flush_front(struct st_framebuffer_iface *stfb,
+stw_st_framebuffer_flush_front(struct st_context_iface *stctx,
+                               struct st_framebuffer_iface *stfb,
                                enum st_attachment_type statt)
 {
    struct stw_st_framebuffer *stwfb = stw_st_framebuffer(stfb);
+   boolean ret;
+   HDC hDC;
+
+   stw_framebuffer_lock(stwfb->fb);
+
+   /* We must not cache HDCs anywhere, as they can be invalidated by the
+    * application, or screen resolution changes. */
 
-   pipe_mutex_lock(stwfb->fb->mutex);
+   hDC = GetDC(stwfb->fb->hWnd);
 
-   return stw_st_framebuffer_present_locked(&stwfb->base, statt);
+   ret = stw_st_framebuffer_present_locked(hDC, &stwfb->base, statt);
+
+   ReleaseDC(stwfb->fb->hWnd, hDC);
+
+   return ret;
 }
 
 /**
@@ -238,8 +234,10 @@ stw_st_create_framebuffer(struct stw_framebuffer *fb)
 
    stwfb->fb = fb;
    stwfb->stvis = fb->pfi->stvis;
+   stwfb->base.ID = p_atomic_inc_return(&stwfb_ID);
 
    stwfb->base.visual = &stwfb->stvis;
+   p_atomic_set(&stwfb->base.stamp, 1);
    stwfb->base.flush_front = stw_st_framebuffer_flush_front;
    stwfb->base.validate = stw_st_framebuffer_validate;
 
@@ -255,12 +253,14 @@ stw_st_destroy_framebuffer_locked(struct st_framebuffer_iface *stfb)
    struct stw_st_framebuffer *stwfb = stw_st_framebuffer(stfb);
    int i;
 
-   pipe_surface_reference(&stwfb->front_surface, NULL);
-   pipe_surface_reference(&stwfb->back_surface, NULL);
-
    for (i = 0; i < ST_ATTACHMENT_COUNT; i++)
       pipe_resource_reference(&stwfb->textures[i], NULL);
 
+   /* Notify the st manager that the framebuffer interface is no
+    * longer valid.
+    */
+   stw_dev->stapi->destroy_drawable(stw_dev->stapi, &stwfb->base);
+
    FREE(stwfb);
 }
 
@@ -268,12 +268,11 @@ stw_st_destroy_framebuffer_locked(struct st_framebuffer_iface *stfb)
  * Swap the buffers of the given framebuffer.
  */
 boolean
-stw_st_swap_framebuffer_locked(struct st_framebuffer_iface *stfb)
+stw_st_swap_framebuffer_locked(HDC hdc, struct st_framebuffer_iface *stfb)
 {
    struct stw_st_framebuffer *stwfb = stw_st_framebuffer(stfb);
    unsigned front = ST_ATTACHMENT_FRONT_LEFT, back = ST_ATTACHMENT_BACK_LEFT;
    struct pipe_resource *ptex;
-   struct pipe_surface *psurf;
    unsigned mask;
 
    /* swap the textures */
@@ -281,11 +280,6 @@ stw_st_swap_framebuffer_locked(struct st_framebuffer_iface *stfb)
    stwfb->textures[front] = stwfb->textures[back];
    stwfb->textures[back] = ptex;
 
-   /* swap the surfaces */
-   psurf = stwfb->front_surface;
-   stwfb->front_surface = stwfb->back_surface;
-   stwfb->back_surface = psurf;
-
    /* convert to mask */
    front = 1 << front;
    back = 1 << back;
@@ -299,14 +293,27 @@ stw_st_swap_framebuffer_locked(struct st_framebuffer_iface *stfb)
    stwfb->texture_mask = mask;
 
    front = ST_ATTACHMENT_FRONT_LEFT;
-   return stw_st_framebuffer_present_locked(&stwfb->base, front);
+   return stw_st_framebuffer_present_locked(hdc, &stwfb->base, front);
 }
 
+
+/**
+ * Return the pipe_resource that correspond to given buffer.
+ */
+struct pipe_resource *
+stw_get_framebuffer_resource(struct st_framebuffer_iface *stfb,
+                             enum st_attachment_type att)
+{
+   struct stw_st_framebuffer *stwfb = stw_st_framebuffer(stfb);
+   return stwfb->textures[att];
+}
+
+
 /**
  * Create an st_api of the state tracker.
  */
 struct st_api *
 stw_st_create_api(void)
 {
-   return st_manager_create_api();
+   return st_gl_api_create();
 }