gallium: unify transfer functions
[mesa.git] / src / gallium / drivers / r300 / r300_transfer.c
index 9140bb191cfe6443f1c98cc03e54da7685c2cf44..fbae2df52b9be8017971858b6fa027e5743d24f4 100644 (file)
@@ -76,18 +76,21 @@ static void r300_copy_into_tiled_texture(struct pipe_context *ctx,
     r300_flush(ctx, 0, NULL);
 }
 
-struct pipe_transfer*
-r300_texture_get_transfer(struct pipe_context *ctx,
+void *
+r300_texture_transfer_map(struct pipe_context *ctx,
                           struct pipe_resource *texture,
                           unsigned level,
                           unsigned usage,
-                          const struct pipe_box *box)
+                          const struct pipe_box *box,
+                          struct pipe_transfer **transfer)
 {
     struct r300_context *r300 = r300_context(ctx);
     struct r300_resource *tex = r300_resource(texture);
     struct r300_transfer *trans;
     struct pipe_resource base;
     boolean referenced_cs, referenced_hw;
+    enum pipe_format format = tex->b.b.format;
+    char *map;
 
     referenced_cs =
         r300->rws->cs_is_buffer_referenced(r300->cs, tex->cs_buf, RADEON_USAGE_READWRITE);
@@ -101,7 +104,7 @@ r300_texture_get_transfer(struct pipe_context *ctx,
     trans = CALLOC_STRUCT(r300_transfer);
     if (trans) {
         /* Initialize the transfer object. */
-        pipe_resource_reference(&trans->transfer.resource, texture);
+        trans->transfer.resource = texture;
         trans->transfer.level = level;
         trans->transfer.usage = usage;
         trans->transfer.box = *box;
@@ -161,15 +164,8 @@ r300_texture_get_transfer(struct pipe_context *ctx,
                                                 &base));
 
                 if (!trans->linear_texture) {
-                    /* For linear textures, it's safe to fallback to
-                     * an unpipelined transfer. */
-                    if (!tex->tex.microtile && !tex->tex.macrotile[level]) {
-                        goto unpipelined;
-                    }
-
-                    /* Otherwise, go to hell. */
                     fprintf(stderr,
-                        "r300: Failed to create a transfer object, praise.\n");
+                            "r300: Failed to create a transfer object.\n");
                     FREE(trans);
                     return NULL;
                 }
@@ -190,64 +186,43 @@ r300_texture_get_transfer(struct pipe_context *ctx,
                 /* Always referenced in the blit. */
                 r300_flush(ctx, 0, NULL);
             }
-            return &trans->transfer;
-        }
-
-    unpipelined:
-        /* Unpipelined transfer. */
-        trans->transfer.stride = tex->tex.stride_in_bytes[level];
-        trans->offset = r300_texture_get_offset(tex, level, box->z);
-
-        if (referenced_cs &&
-            !(usage & PIPE_TRANSFER_UNSYNCHRONIZED))
-            r300_flush(ctx, 0, NULL);
-        return &trans->transfer;
-    }
-    return NULL;
-}
+        } else {
+            /* Unpipelined transfer. */
+            trans->transfer.stride = tex->tex.stride_in_bytes[level];
+            trans->offset = r300_texture_get_offset(tex, level, box->z);
 
-void r300_texture_transfer_destroy(struct pipe_context *ctx,
-                                  struct pipe_transfer *trans)
-{
-    struct r300_transfer *r300transfer = r300_transfer(trans);
-
-    if (r300transfer->linear_texture) {
-        if (trans->usage & PIPE_TRANSFER_WRITE) {
-            r300_copy_into_tiled_texture(ctx, r300transfer);
+            if (referenced_cs &&
+                !(usage & PIPE_TRANSFER_UNSYNCHRONIZED)) {
+                r300_flush(ctx, 0, NULL);
+            }
         }
-
-        pipe_resource_reference(
-            (struct pipe_resource**)&r300transfer->linear_texture, NULL);
     }
-    pipe_resource_reference(&trans->resource, NULL);
-    FREE(trans);
-}
 
-void* r300_texture_transfer_map(struct pipe_context *ctx,
-                               struct pipe_transfer *transfer)
-{
-    struct r300_context *r300 = r300_context(ctx);
-    struct r300_transfer *r300transfer = r300_transfer(transfer);
-    struct r300_resource *tex = r300_resource(transfer->resource);
-    char *map;
-    enum pipe_format format = tex->b.b.format;
-
-    if (r300transfer->linear_texture) {
+    if (trans->linear_texture) {
         /* The detiled texture is of the same size as the region being mapped
          * (no offset needed). */
-        return r300->rws->buffer_map(r300transfer->linear_texture->cs_buf,
-                                    r300->cs, transfer->usage);
+        map = r300->rws->buffer_map(trans->linear_texture->cs_buf,
+                                    r300->cs, usage);
+        if (!map) {
+            pipe_resource_reference(
+                (struct pipe_resource**)&trans->linear_texture, NULL);
+            FREE(trans);
+            return NULL;
+        }
+       *transfer = &trans->transfer;
+        return map;
     } else {
         /* Tiling is disabled. */
-        map = r300->rws->buffer_map(tex->cs_buf, r300->cs, transfer->usage);
-
+        map = r300->rws->buffer_map(tex->cs_buf, r300->cs, usage);
         if (!map) {
+            FREE(trans);
             return NULL;
         }
 
-        return map + r300_transfer(transfer)->offset +
-            transfer->box.y / util_format_get_blockheight(format) * transfer->stride +
-            transfer->box.x / util_format_get_blockwidth(format) * util_format_get_blocksize(format);
+       *transfer = &trans->transfer;
+        return map + trans->offset +
+            box->y / util_format_get_blockheight(format) * trans->transfer.stride +
+            box->x / util_format_get_blockwidth(format) * util_format_get_blocksize(format);
     }
 }
 
@@ -255,12 +230,20 @@ void r300_texture_transfer_unmap(struct pipe_context *ctx,
                                 struct pipe_transfer *transfer)
 {
     struct radeon_winsys *rws = r300_context(ctx)->rws;
-    struct r300_transfer *r300transfer = r300_transfer(transfer);
+    struct r300_transfer *trans = r300_transfer(transfer);
     struct r300_resource *tex = r300_resource(transfer->resource);
 
-    if (r300transfer->linear_texture) {
-        rws->buffer_unmap(r300transfer->linear_texture->cs_buf);
+    if (trans->linear_texture) {
+        rws->buffer_unmap(trans->linear_texture->cs_buf);
+
+        if (transfer->usage & PIPE_TRANSFER_WRITE) {
+            r300_copy_into_tiled_texture(ctx, trans);
+        }
+
+        pipe_resource_reference(
+            (struct pipe_resource**)&trans->linear_texture, NULL);
     } else {
         rws->buffer_unmap(tex->cs_buf);
     }
+    FREE(transfer);
 }