svga: only count hardware buffer mappings for HUD
[mesa.git] / src / gallium / drivers / svga / svga_resource_buffer.h
index 55e7321184faf4972891c35dfe2f861b98818c2c..0591f8960b9d720f227b436cdd206873f646c695 100644 (file)
 #include "pipe/p_state.h"
 #include "util/u_transfer.h"
 
-#include "util/u_double_list.h"
-
 #include "svga_screen_cache.h"
+#include "svga_screen.h"
+#include "svga_cmd.h"
+#include "svga_context.h"
 
 
 /**
@@ -42,7 +43,6 @@
 #define SVGA_BUFFER_MAX_RANGES 32
 
 
-struct svga_screen;
 struct svga_context;
 struct svga_winsys_buffer;
 struct svga_winsys_surface;
@@ -56,6 +56,7 @@ struct svga_buffer_range
    unsigned end;
 };
 
+struct svga_3d_update_gb_image;
 
 /**
  * SVGA pipe buffer.
@@ -64,6 +65,9 @@ struct svga_buffer
 {
    struct u_resource b;
 
+   /** This is a superset of b.b.bind */
+   unsigned bind_flags;
+
    /**
     * Regular (non DMA'able) memory.
     * 
@@ -90,7 +94,9 @@ struct svga_buffer
     * Host surface handle.
     * 
     * This is a platform independent abstraction for host SID. We create when 
-    * trying to bind
+    * trying to bind.
+    *
+    * Only set for non-user buffers.
     */
    struct svga_winsys_surface *handle;
 
@@ -100,23 +106,9 @@ struct svga_buffer
    struct {
       /**
        * Number of concurrent mappings.
-       *
-       * XXX: It is impossible to guarantee concurrent maps work in all
-       * circumstances -- pipe_buffers really need transfer objects too.
        */
       unsigned count;
 
-      /**
-       * Whether this buffer is currently mapped for writing.
-       */
-      boolean writing;
-
-      /**
-       * Whether the application will tell us explicity which ranges it touched
-       * or not.
-       */
-      boolean flush_explicit;
-
       /**
        * Dirty ranges.
        *
@@ -141,6 +133,12 @@ struct svga_buffer
        * is the relative offset within that buffer.
        */
       unsigned offset;
+
+      /**
+       * Range of user buffer that is uploaded in @buffer at @offset.
+       */
+      unsigned start;
+      unsigned end;
    } uploaded;
 
    /**
@@ -149,6 +147,8 @@ struct svga_buffer
     * A piece of GMR memory, with the same size of the buffer. It is created
     * when mapping the buffer, and will be used to upload vertex data to the
     * host.
+    *
+    * Only set for non-user buffers.
     */
    struct svga_winsys_buffer *hwbuf;
 
@@ -171,6 +171,12 @@ struct svga_buffer
        */
       SVGA3dCopyBox *boxes;
 
+      /**
+       * Pointer to the sequence of update commands
+       * *inside* the command buffer.
+       */
+      struct svga_3d_update_gb_image *updates;
+
       /**
        * Context that has the pending DMA to this buffer.
        */
@@ -182,10 +188,14 @@ struct svga_buffer
     * a context. It is only valid if the dma.pending is set above.
     */
    struct list_head head;
+
+   unsigned size;  /**< Approximate size in bytes */
+
+   boolean dirty;  /**< Need to do a readback before mapping? */
 };
 
 
-static INLINE struct svga_buffer *
+static inline struct svga_buffer *
 svga_buffer(struct pipe_resource *buffer)
 {
    if (buffer) {
@@ -200,14 +210,87 @@ svga_buffer(struct pipe_resource *buffer)
  * Returns TRUE for user buffers.  We may
  * decide to use an alternate upload path for these buffers.
  */
-static INLINE boolean 
+static inline boolean 
 svga_buffer_is_user_buffer( struct pipe_resource *buffer )
 {
-   return svga_buffer(buffer)->user;
+   if (buffer) {
+      return svga_buffer(buffer)->user;
+   } else {
+      return FALSE;
+   }
 }
 
+/**
+ * Returns a pointer to a struct svga_winsys_screen given a
+ * struct svga_buffer.
+ */
+static inline struct svga_winsys_screen *
+svga_buffer_winsys_screen(struct svga_buffer *sbuf)
+{
+   return svga_screen(sbuf->b.b.screen)->sws;
+}
 
 
+/**
+ * Returns whether a buffer has hardware storage that is
+ * visible to the GPU.
+ */
+static inline boolean
+svga_buffer_has_hw_storage(struct svga_buffer *sbuf)
+{
+   if (svga_buffer_winsys_screen(sbuf)->have_gb_objects)
+      return (sbuf->handle ? TRUE : FALSE);
+   else
+      return (sbuf->hwbuf ? TRUE : FALSE);
+}
+
+/**
+ * Map the hardware storage of a buffer.
+ */
+static inline void *
+svga_buffer_hw_storage_map(struct svga_context *svga,
+                           struct svga_buffer *sbuf,
+                           unsigned flags, boolean *retry)
+{
+   struct svga_winsys_screen *sws = svga_buffer_winsys_screen(sbuf);
+
+   svga->hud.num_resources_mapped++;
+
+   if (sws->have_gb_objects) {
+      return svga->swc->surface_map(svga->swc, sbuf->handle, flags, retry);
+   } else {
+      *retry = FALSE;
+      return sws->buffer_map(sws, sbuf->hwbuf, flags);
+   }
+}
+
+/**
+ * Unmap the hardware storage of a buffer.
+ */
+static inline void
+svga_buffer_hw_storage_unmap(struct svga_context *svga,
+                             struct svga_buffer *sbuf)
+{
+   struct svga_winsys_screen *sws = svga_buffer_winsys_screen(sbuf);
+
+   if (sws->have_gb_objects) {
+      struct svga_winsys_context *swc = svga->swc;
+      boolean rebind;
+      swc->surface_unmap(swc, sbuf->handle, &rebind);
+      if (rebind) {
+         enum pipe_error ret;
+         ret = SVGA3D_BindGBSurface(swc, sbuf->handle);
+         if (ret != PIPE_OK) {
+            /* flush and retry */
+            svga_context_flush(svga, NULL);
+            ret = SVGA3D_BindGBSurface(swc, sbuf->handle);
+            assert(ret == PIPE_OK);
+         }
+      }
+   } else
+      sws->buffer_unmap(sws, sbuf->hwbuf);
+}
+
 
 struct pipe_resource *
 svga_user_buffer_create(struct pipe_screen *screen,
@@ -238,7 +321,7 @@ void
 svga_context_flush_buffers(struct svga_context *svga);
 
 struct svga_winsys_buffer *
-svga_winsys_buffer_create(struct svga_screen *ss,
+svga_winsys_buffer_create(struct svga_context *svga,
                           unsigned alignment, 
                           unsigned usage,
                           unsigned size);