gallium/svga: handle query_rendered caps
[mesa.git] / src / gallium / drivers / svga / svga_resource_buffer.c
index ff53b82785518c57dfba6f2556fedf6e57cfcc71..d2c7762e7ff9f852d7750ec041b15aa12101317d 100644 (file)
@@ -31,6 +31,7 @@
 #include "os/os_thread.h"
 #include "util/u_math.h"
 #include "util/u_memory.h"
+#include "util/u_resource.h"
 
 #include "svga_context.h"
 #include "svga_screen.h"
@@ -62,17 +63,19 @@ svga_buffer_needs_hw_storage(unsigned usage)
  * the end result is exactly the same as if one DMA was used for every mapped
  * range.
  */
-static struct pipe_transfer *
-svga_buffer_get_transfer(struct pipe_context *pipe,
+static void *
+svga_buffer_transfer_map(struct pipe_context *pipe,
                          struct pipe_resource *resource,
                          unsigned level,
                          unsigned usage,
-                         const struct pipe_box *box)
+                         const struct pipe_box *box,
+                         struct pipe_transfer **ptransfer)
 {
    struct svga_context *svga = svga_context(pipe);
    struct svga_screen *ss = svga_screen(pipe->screen);
    struct svga_buffer *sbuf = svga_buffer(resource);
    struct pipe_transfer *transfer;
+   uint8_t *map;
 
    transfer = CALLOC_STRUCT(pipe_transfer);
    if (transfer == NULL) {
@@ -100,9 +103,13 @@ svga_buffer_get_transfer(struct pipe_context *pipe,
             /*
              * Instead of flushing the context command buffer, simply discard
              * the current hwbuf, and start a new one.
+             * With GB objects, the map operation takes care of this
+             * if passed the PIPE_TRANSFER_DISCARD_WHOLE_RESOURCE flag,
+             * and the old backing store is busy.
              */
 
-            svga_buffer_destroy_hw_storage(ss, sbuf);
+            if (!svga_have_gb_objects(svga))
+               svga_buffer_destroy_hw_storage(ss, sbuf);
          }
 
          sbuf->map.num_ranges = 0;
@@ -129,7 +136,7 @@ svga_buffer_get_transfer(struct pipe_context *pipe,
          if (sbuf->dma.pending) {
             svga_buffer_upload_flush(svga, sbuf);
 
-            if (sbuf->hwbuf) {
+            if (svga_buffer_has_hw_storage(sbuf)) {
                /*
                 * We have a pending DMA upload from a hardware buffer, therefore
                 * we need to ensure that the host finishes processing that DMA
@@ -165,7 +172,7 @@ svga_buffer_get_transfer(struct pipe_context *pipe,
       }
    }
 
-   if (!sbuf->swbuf && !sbuf->hwbuf) {
+   if (!sbuf->swbuf && !svga_buffer_has_hw_storage(sbuf)) {
       if (svga_buffer_create_hw_storage(ss, sbuf) != PIPE_OK) {
          /*
           * We can't create a hardware buffer big enough, so create a malloc
@@ -186,30 +193,23 @@ svga_buffer_get_transfer(struct pipe_context *pipe,
       }
    }
 
-   return transfer;
-}
-
-
-/**
- * Map a range of a buffer.
- */
-static void *
-svga_buffer_transfer_map( struct pipe_context *pipe,
-                          struct pipe_transfer *transfer )
-{
-   struct svga_buffer *sbuf = svga_buffer(transfer->resource);
-
-   uint8_t *map;
-
    if (sbuf->swbuf) {
       /* User/malloc buffer */
       map = sbuf->swbuf;
    }
-   else if (sbuf->hwbuf) {
-      struct svga_screen *ss = svga_screen(pipe->screen);
-      struct svga_winsys_screen *sws = ss->sws;
+   else if (svga_buffer_has_hw_storage(sbuf)) {
+      boolean retry;
 
-      map = sws->buffer_map(sws, sbuf->hwbuf, transfer->usage);
+      map = svga_buffer_hw_storage_map(svga, sbuf, transfer->usage, &retry);
+      if (map == NULL && retry) {
+         /*
+          * At this point, svga_buffer_get_transfer() has already
+          * hit the DISCARD_WHOLE_RESOURCE path and flushed HWTNL
+          * for this buffer.
+          */
+         svga_context_flush(svga, NULL);
+         map = svga_buffer_hw_storage_map(svga, sbuf, transfer->usage, &retry);
+      }
    }
    else {
       map = NULL;
@@ -218,6 +218,9 @@ svga_buffer_transfer_map( struct pipe_context *pipe,
    if (map) {
       ++sbuf->map.count;
       map += transfer->box.x;
+      *ptransfer = transfer;
+   } else {
+      FREE(transfer);
    }
    
    return map;
@@ -249,7 +252,7 @@ svga_buffer_transfer_unmap( struct pipe_context *pipe,
                             struct pipe_transfer *transfer )
 {
    struct svga_screen *ss = svga_screen(pipe->screen);
-   struct svga_winsys_screen *sws = ss->sws;
+   struct svga_context *svga = svga_context(pipe);
    struct svga_buffer *sbuf = svga_buffer(transfer->resource);
    
    pipe_mutex_lock(ss->swc_mutex);
@@ -259,8 +262,8 @@ svga_buffer_transfer_unmap( struct pipe_context *pipe,
       --sbuf->map.count;
    }
 
-   if (sbuf->hwbuf) {
-      sws->buffer_unmap(sws, sbuf->hwbuf);
+   if (svga_buffer_has_hw_storage(sbuf)) {
+      svga_buffer_hw_storage_unmap(svga, sbuf);
    }
 
    if (transfer->usage & PIPE_TRANSFER_WRITE) {
@@ -280,16 +283,6 @@ svga_buffer_transfer_unmap( struct pipe_context *pipe,
    }
 
    pipe_mutex_unlock(ss->swc_mutex);
-}
-
-
-/**
- * Destroy transfer
- */
-static void
-svga_buffer_transfer_destroy(struct pipe_context *pipe,
-                             struct pipe_transfer *transfer)
-{
    FREE(transfer);
 }
 
@@ -317,6 +310,8 @@ svga_buffer_destroy( struct pipe_screen *screen,
    if(sbuf->swbuf && !sbuf->user)
       align_free(sbuf->swbuf);
    
+   ss->total_resource_bytes -= sbuf->size;
+
    FREE(sbuf);
 }
 
@@ -325,8 +320,6 @@ struct u_resource_vtbl svga_buffer_vtbl =
 {
    u_default_resource_get_handle,      /* get_handle */
    svga_buffer_destroy,                     /* resource_destroy */
-   svga_buffer_get_transfer,        /* get_transfer */
-   svga_buffer_transfer_destroy,     /* transfer_destroy */
    svga_buffer_transfer_map,        /* transfer_map */
    svga_buffer_transfer_flush_region,  /* transfer_flush_region */
    svga_buffer_transfer_unmap,      /* transfer_unmap */
@@ -364,6 +357,9 @@ svga_buffer_create(struct pipe_screen *screen,
    debug_reference(&sbuf->b.b.reference,
                    (debug_reference_descriptor)debug_describe_resource, 0);
 
+   sbuf->size = util_resource_size(template);
+   ss->total_resource_bytes += sbuf->size;
+
    return &sbuf->b.b; 
 
 error2:
@@ -394,7 +390,6 @@ svga_user_buffer_create(struct pipe_screen *screen,
    sbuf->b.b.height0 = 1;
    sbuf->b.b.depth0 = 1;
    sbuf->b.b.array_size = 1;
-   sbuf->b.b.user_ptr = ptr;
 
    sbuf->swbuf = ptr;
    sbuf->user = TRUE;