gallium: add PIPE_SHADER_CAP_GLSL_16BIT_TEMPS for LowerPrecisionTemporaries
[mesa.git] / src / gallium / drivers / svga / svga_resource_buffer.h
index 83b3d342aec2d42e1ba4b711b90bb9adfdc35e9b..09648d2ec0976dd258c83eaad4c891a68cd2125c 100644 (file)
@@ -58,45 +58,71 @@ struct svga_buffer_range
 
 struct svga_3d_update_gb_image;
 
+/**
+ * This structure describes the bind flags and cache key associated
+ * with the host surface.
+ */
+struct svga_buffer_surface
+{
+   struct list_head list;
+   unsigned bind_flags;
+   struct svga_host_surface_cache_key key;
+   struct svga_winsys_surface *handle;
+};
+
 /**
  * SVGA pipe buffer.
  */
-struct svga_buffer 
+struct svga_buffer
 {
    struct u_resource b;
 
+   /** This is a superset of b.b.bind */
+   unsigned bind_flags;
+
    /**
     * Regular (non DMA'able) memory.
-    * 
+    *
     * Used for user buffers or for buffers which we know before hand that can
     * never be used by the virtual hardware directly, such as constant buffers.
     */
    void *swbuf;
-   
-   /** 
+
+   /**
     * Whether swbuf was created by the user or not.
     */
    boolean user;
-   
+
+   /**
+    * Whether swbuf is used for this buffer.
+    */
+   boolean use_swbuf;
+
    /**
     * Creation key for the host surface handle.
-    * 
-    * This structure describes all the host surface characteristics so that it 
+    *
+    * This structure describes all the host surface characteristics so that it
     * can be looked up in cache, since creating a host surface is often a slow
     * operation.
     */
    struct svga_host_surface_cache_key key;
-   
+
    /**
     * Host surface handle.
-    * 
-    * This is a platform independent abstraction for host SID. We create when 
+    *
+    * This is a platform independent abstraction for host SID. We create when
     * trying to bind.
     *
     * Only set for non-user buffers.
     */
    struct svga_winsys_surface *handle;
 
+   /**
+    * List of surfaces created for this buffer resource to support
+    * incompatible bind flags.
+    */
+   struct list_head surfaces;
+
    /**
     * Information about ongoing and past map operations.
     */
@@ -187,17 +213,28 @@ struct svga_buffer
    struct list_head head;
 
    unsigned size;  /**< Approximate size in bytes */
+
+   boolean dirty;  /**< Need to do a readback before mapping? */
+
+   /** In some cases we try to keep the results of the translate_indices()
+    * function from svga_draw_elements.c
+    */
+   struct {
+      enum pipe_prim_type orig_prim, new_prim;
+      struct pipe_resource *buffer;
+      unsigned index_size;
+      unsigned offset;  /**< first index */
+      unsigned count;   /**< num indices */
+   } translated_indices;
 };
 
 
-static INLINE struct svga_buffer *
-svga_buffer(struct pipe_resource *buffer)
+static inline struct svga_buffer *
+svga_buffer(struct pipe_resource *resource)
 {
-   if (buffer) {
-      assert(((struct svga_buffer *)buffer)->b.vtbl == &svga_buffer_vtbl);
-      return (struct svga_buffer *)buffer;
-   }
-   return NULL;
+   struct svga_buffer *buf = (struct svga_buffer *) resource;
+   assert(buf == NULL || buf->b.vtbl == &svga_buffer_vtbl);
+   return buf;
 }
 
 
@@ -205,8 +242,8 @@ 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 
-svga_buffer_is_user_buffer( struct pipe_resource *buffer )
+static inline boolean
+svga_buffer_is_user_buffer(struct pipe_resource *buffer)
 {
    if (buffer) {
       return svga_buffer(buffer)->user;
@@ -219,7 +256,7 @@ svga_buffer_is_user_buffer( struct pipe_resource *buffer )
  * Returns a pointer to a struct svga_winsys_screen given a
  * struct svga_buffer.
  */
-static INLINE struct svga_winsys_screen *
+static inline struct svga_winsys_screen *
 svga_buffer_winsys_screen(struct svga_buffer *sbuf)
 {
    return svga_screen(sbuf->b.b.screen)->sws;
@@ -230,7 +267,7 @@ svga_buffer_winsys_screen(struct svga_buffer *sbuf)
  * Returns whether a buffer has hardware storage that is
  * visible to the GPU.
  */
-static INLINE boolean
+static inline boolean
 svga_buffer_has_hw_storage(struct svga_buffer *sbuf)
 {
    if (svga_buffer_winsys_screen(sbuf)->have_gb_objects)
@@ -241,15 +278,38 @@ svga_buffer_has_hw_storage(struct svga_buffer *sbuf)
 
 /**
  * Map the hardware storage of a buffer.
+ * \param flags  bitmask of PIPE_TRANSFER_* flags
  */
-static INLINE void *
+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_buffers_mapped++;
+
    if (sws->have_gb_objects) {
-      return svga->swc->surface_map(svga->swc, sbuf->handle, flags, retry);
+      struct svga_winsys_context *swc = svga->swc;
+      boolean rebind;
+      void *map;
+
+      if (swc->force_coherent) {
+         flags |= PIPE_TRANSFER_PERSISTENT | PIPE_TRANSFER_COHERENT;
+      }
+      map = swc->surface_map(swc, sbuf->handle, flags, retry, &rebind);
+      if (map && rebind) {
+         enum pipe_error ret;
+
+         ret = SVGA3D_BindGBSurface(swc, sbuf->handle);
+         if (ret != PIPE_OK) {
+            svga_context_flush(svga, NULL);
+            ret = SVGA3D_BindGBSurface(swc, sbuf->handle);
+            assert(ret == PIPE_OK);
+         }
+         svga_context_flush(svga, NULL);
+      }
+      return map;
    } else {
       *retry = FALSE;
       return sws->buffer_map(sws, sbuf->hwbuf, flags);
@@ -259,7 +319,7 @@ svga_buffer_hw_storage_map(struct svga_context *svga,
 /**
  * Unmap the hardware storage of a buffer.
  */
-static INLINE void
+static inline void
 svga_buffer_hw_storage_unmap(struct svga_context *svga,
                              struct svga_buffer *sbuf)
 {
@@ -268,16 +328,10 @@ svga_buffer_hw_storage_unmap(struct svga_context *svga,
    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);
-         }
+         SVGA_RETRY(svga, SVGA3D_BindGBSurface(swc, sbuf->handle));
       }
    } else
       sws->buffer_unmap(sws, sbuf->hwbuf);
@@ -288,11 +342,11 @@ struct pipe_resource *
 svga_user_buffer_create(struct pipe_screen *screen,
                         void *ptr,
                         unsigned bytes,
-                       unsigned usage);
+                        unsigned usage);
 
 struct pipe_resource *
 svga_buffer_create(struct pipe_screen *screen,
-                  const struct pipe_resource *template);
+                   const struct pipe_resource *template);
 
 
 
@@ -307,14 +361,15 @@ svga_buffer_create(struct pipe_screen *screen,
  */
 struct svga_winsys_surface *
 svga_buffer_handle(struct svga_context *svga,
-                   struct pipe_resource *buf);
+                   struct pipe_resource *buf,
+                   unsigned tobind_flags);
 
 void
 svga_context_flush_buffers(struct svga_context *svga);
 
 struct svga_winsys_buffer *
 svga_winsys_buffer_create(struct svga_context *svga,
-                          unsigned alignment, 
+                          unsigned alignment,
                           unsigned usage,
                           unsigned size);