configure.ac: Use AX_GCC_BUILTIN to check availability of __builtin_bswap32 v2
[mesa.git] / src / gallium / auxiliary / util / u_transfer.c
index e2828cfd99e8ef54330f777dadc199b9335b9884..7804f2a82ea55b30a663835f6e382313255e6005 100644 (file)
@@ -1,5 +1,5 @@
 #include "pipe/p_context.h"
-#include "util/u_rect.h"
+#include "util/u_surface.h"
 #include "util/u_inlines.h"
 #include "util/u_transfer.h"
 #include "util/u_memory.h"
@@ -18,41 +18,52 @@ void u_default_transfer_inline_write( struct pipe_context *pipe,
 {
    struct pipe_transfer *transfer = NULL;
    uint8_t *map = NULL;
-   const uint8_t *src_data = data;
-   unsigned i;
-
-   transfer = pipe->get_transfer(pipe,
-                                 resource,
-                                 level,
-                                 usage,
-                                 box );
-   if (transfer == NULL)
-      goto out;
-
-   map = pipe_transfer_map(pipe, transfer);
-   if (map == NULL)
-      goto out;
-
-   for (i = 0; i < box->depth; i++) {
-      util_copy_rect(map,
-                     resource->format,
-                     transfer->stride, /* bytes */
-                     0, 0,
-                     box->width,
-                     box->height,
-                     src_data,
-                     stride,       /* bytes */
-                     0, 0);
-      map += transfer->layer_stride;
-      src_data += layer_stride;
+
+   assert(!(usage & PIPE_TRANSFER_READ));
+
+   /* the write flag is implicit by the nature of transfer_inline_write */
+   usage |= PIPE_TRANSFER_WRITE;
+
+   /* transfer_inline_write implicitly discards the rewritten buffer range */
+   /* XXX this looks very broken for non-buffer resources having more than one dim. */
+   if (box->x == 0 && box->width == resource->width0) {
+      usage |= PIPE_TRANSFER_DISCARD_WHOLE_RESOURCE;
+   } else {
+      usage |= PIPE_TRANSFER_DISCARD_RANGE;
    }
 
-out:
-   if (map)
-      pipe_transfer_unmap(pipe, transfer);
+   map = pipe->transfer_map(pipe,
+                            resource,
+                            level,
+                            usage,
+                            box, &transfer);
+   if (map == NULL)
+      return;
+
+   if (resource->target == PIPE_BUFFER) {
+      assert(box->height == 1);
+      assert(box->depth == 1);
+
+      memcpy(map, data, box->width);
+   }
+   else {
+      const uint8_t *src_data = data;
+
+      util_copy_box(map,
+                   resource->format,
+                   transfer->stride, /* bytes */
+                   transfer->layer_stride, /* bytes */
+                    0, 0, 0,
+                   box->width,
+                   box->height,
+                   box->depth,
+                   src_data,
+                   stride,       /* bytes */
+                   layer_stride, /* bytes */
+                   0, 0, 0);
+   }
 
-   if (transfer)
-      pipe_transfer_destroy(pipe, transfer);
+   pipe_transfer_unmap(pipe, transfer);
 }
 
 
@@ -73,42 +84,80 @@ void u_default_transfer_flush_region( struct pipe_context *pipe,
     */
 }
 
-unsigned u_default_is_resource_referenced( struct pipe_context *pipe,
-                                           struct pipe_resource *resource,
-                                           unsigned level, int layer)
+void u_default_transfer_unmap( struct pipe_context *pipe,
+                               struct pipe_transfer *transfer )
+{
+}
+
+
+static INLINE struct u_resource *
+u_resource( struct pipe_resource *res )
 {
-   return 0;
+   return (struct u_resource *)res;
 }
 
-struct pipe_transfer * u_default_get_transfer(struct pipe_context *context,
-                                              struct pipe_resource *resource,
-                                              unsigned level,
-                                              unsigned usage,
-                                              const struct pipe_box *box)
+boolean u_resource_get_handle_vtbl(struct pipe_screen *screen,
+                                   struct pipe_resource *resource,
+                                   struct winsys_handle *handle)
 {
-   struct pipe_transfer *transfer = CALLOC_STRUCT(pipe_transfer);
-   if (transfer == NULL)
-      return NULL;
+   struct u_resource *ur = u_resource(resource);
+   return ur->vtbl->resource_get_handle(screen, resource, handle);
+}
 
-   transfer->resource = resource;
-   transfer->level = level;
-   transfer->usage = usage;
-   transfer->box = *box;
+void u_resource_destroy_vtbl(struct pipe_screen *screen,
+                             struct pipe_resource *resource)
+{
+   struct u_resource *ur = u_resource(resource);
+   ur->vtbl->resource_destroy(screen, resource);
+}
 
-   /* Note strides are zero, this is ok for buffers, but not for
-    * textures 2d & higher at least. 
-    */
-   return transfer;
+void *u_transfer_map_vtbl(struct pipe_context *context,
+                          struct pipe_resource *resource,
+                          unsigned level,
+                          unsigned usage,
+                          const struct pipe_box *box,
+                          struct pipe_transfer **transfer)
+{
+   struct u_resource *ur = u_resource(resource);
+   return ur->vtbl->transfer_map(context, resource, level, usage, box,
+                                 transfer);
 }
 
-void u_default_transfer_unmap( struct pipe_context *pipe,
-                               struct pipe_transfer *transfer )
+void u_transfer_flush_region_vtbl( struct pipe_context *pipe,
+                                   struct pipe_transfer *transfer,
+                                   const struct pipe_box *box)
+{
+   struct u_resource *ur = u_resource(transfer->resource);
+   ur->vtbl->transfer_flush_region(pipe, transfer, box);
+}
+
+void u_transfer_unmap_vtbl( struct pipe_context *pipe,
+                            struct pipe_transfer *transfer )
 {
+   struct u_resource *ur = u_resource(transfer->resource);
+   ur->vtbl->transfer_unmap(pipe, transfer);
 }
 
-void u_default_transfer_destroy(struct pipe_context *pipe,
-                                struct pipe_transfer *transfer)
+void u_transfer_inline_write_vtbl( struct pipe_context *pipe,
+                                   struct pipe_resource *resource,
+                                   unsigned level,
+                                   unsigned usage,
+                                   const struct pipe_box *box,
+                                   const void *data,
+                                   unsigned stride,
+                                   unsigned layer_stride)
 {
-   FREE(transfer);
+   struct u_resource *ur = u_resource(resource);
+   ur->vtbl->transfer_inline_write(pipe,
+                                   resource,
+                                   level,
+                                   usage,
+                                   box,
+                                   data,
+                                   stride,
+                                   layer_stride);
 }
 
+
+
+