r600g: Use the actual Evergreen functions to query format support on Evergreen.
[mesa.git] / src / gallium / auxiliary / util / u_upload_mgr.c
index 80c9b635f0e4dd3caf2cff558b3af8ef6a4752fe..e50db6d67feb4615feef2f644c82feef6d5860e5 100644 (file)
 struct u_upload_mgr {
    struct pipe_context *pipe;
 
-   unsigned default_size;
-   unsigned alignment;
-   unsigned bind;
-
-   /* The active buffer:
-    */
-   struct pipe_resource *buffer;
-   struct pipe_transfer *transfer;
-   uint8_t *map;
-   unsigned size;
-   unsigned offset;
+   unsigned default_size;  /* Minimum size of the upload buffer, in bytes. */
+   unsigned alignment;     /* Alignment of each sub-allocation. */
+   unsigned bind;          /* Bitmask of PIPE_BIND_* flags. */
+
+   struct pipe_resource *buffer;   /* Upload buffer. */
+   struct pipe_transfer *transfer; /* Transfer object for the upload buffer. */
+   uint8_t *map;    /* Pointer to the mapped upload buffer. */
+   unsigned size;   /* Actual size of the upload buffer. */
+   unsigned offset; /* Aligned offset to the upload buffer, pointing
+                     * at the first unused byte. */
 };
 
 
@@ -73,6 +72,22 @@ struct u_upload_mgr *u_upload_create( struct pipe_context *pipe,
    return upload;
 }
 
+void u_upload_unmap( struct u_upload_mgr *upload )
+{
+   if (upload->transfer) {
+      struct pipe_box *box = &upload->transfer->box;
+      if (upload->offset > box->x) {
+
+         pipe_buffer_flush_mapped_range(upload->pipe, upload->transfer,
+                                        box->x, upload->offset - box->x);
+      }
+      pipe_transfer_unmap(upload->pipe, upload->transfer);
+      pipe_transfer_destroy(upload->pipe, upload->transfer);
+      upload->transfer = NULL;
+      upload->map = NULL;
+   }
+}
+
 /* Release old buffer.
  * 
  * This must usually be called prior to firing the command stream
@@ -84,10 +99,8 @@ struct u_upload_mgr *u_upload_create( struct pipe_context *pipe,
  */
 void u_upload_flush( struct u_upload_mgr *upload )
 {
-   if (upload->transfer) {
-      pipe_transfer_unmap(upload->pipe, upload->transfer);
-      upload->transfer = NULL;
-   }
+   /* Unmap and unreference the upload buffer. */
+   u_upload_unmap(upload);
    pipe_resource_reference( &upload->buffer, NULL );
    upload->size = 0;
 }
@@ -106,7 +119,7 @@ u_upload_alloc_buffer( struct u_upload_mgr *upload,
 {
    unsigned size;
 
-   /* Release old buffer, if present:
+   /* Release the old buffer, if present:
     */
    u_upload_flush( upload );
 
@@ -116,12 +129,17 @@ u_upload_alloc_buffer( struct u_upload_mgr *upload,
 
    upload->buffer = pipe_buffer_create( upload->pipe->screen,
                                         upload->bind,
+                                        PIPE_USAGE_STREAM,
                                         size );
    if (upload->buffer == NULL) 
       goto fail;
 
-   upload->map = pipe_buffer_map(upload->pipe, upload->buffer,
-                                 PIPE_TRANSFER_WRITE, &upload->transfer);
+   /* Map the new buffer. */
+   upload->map = pipe_buffer_map_range(upload->pipe, upload->buffer,
+                                       0, size,
+                                       PIPE_TRANSFER_WRITE |
+                                       PIPE_TRANSFER_FLUSH_EXPLICIT,
+                                       &upload->transfer);
    
    upload->size = size;
 
@@ -147,6 +165,8 @@ enum pipe_error u_upload_alloc( struct u_upload_mgr *upload,
    unsigned alloc_offset = align(min_out_offset, upload->alignment);
    unsigned offset;
 
+   /* Make sure we have enough space in the upload buffer
+    * for the sub-allocation. */
    if (MAX2(upload->offset, alloc_offset) + alloc_size > upload->size) {
       enum pipe_error ret = u_upload_alloc_buffer(upload,
                                                   alloc_offset + alloc_size);
@@ -160,16 +180,24 @@ enum pipe_error u_upload_alloc( struct u_upload_mgr *upload,
 
    offset = MAX2(upload->offset, alloc_offset);
 
+   if (!upload->map) {
+      upload->map = pipe_buffer_map_range(upload->pipe, upload->buffer,
+                                         offset, upload->size - offset,
+                                         PIPE_TRANSFER_WRITE |
+                                         PIPE_TRANSFER_FLUSH_EXPLICIT |
+                                         PIPE_TRANSFER_UNSYNCHRONIZED,
+                                         &upload->transfer);
+   }
+
    assert(offset < upload->buffer->width0);
    assert(offset + size <= upload->buffer->width0);
    assert(size);
 
+   /* Emit the return values: */
    *ptr = upload->map + offset;
-
-   /* Emit the return values:
-    */
    pipe_resource_reference( outbuf, upload->buffer );
    *out_offset = offset;
+
    upload->offset = offset + alloc_size;
    return PIPE_OK;
 }
@@ -212,10 +240,11 @@ enum pipe_error u_upload_buffer( struct u_upload_mgr *upload,
    struct pipe_transfer *transfer = NULL;
    const char *map = NULL;
 
-   map = (const char *)pipe_buffer_map(upload->pipe,
-                                      inbuf,
-                                      PIPE_TRANSFER_READ,
-                                      &transfer);
+   map = (const char *)pipe_buffer_map_range(upload->pipe,
+                                             inbuf,
+                                             offset, size,
+                                             PIPE_TRANSFER_READ,
+                                             &transfer);
 
    if (map == NULL) {
       ret = PIPE_ERROR_OUT_OF_MEMORY;
@@ -228,7 +257,7 @@ enum pipe_error u_upload_buffer( struct u_upload_mgr *upload,
    ret = u_upload_data( upload,
                         min_out_offset,
                         size,
-                        map + offset,
+                        map,
                         out_offset,
                         outbuf, flushed );