gallium/util: Break recursion in pipe_resource_reference
[mesa.git] / src / gallium / auxiliary / util / u_inlines.h
index bb99a02ce49a2ce81d192a8167e10aceb840e97c..4fc683a57451ab6b5792c880a2a3f51fe6607db1 100644 (file)
@@ -136,8 +136,16 @@ pipe_resource_reference(struct pipe_resource **ptr, struct pipe_resource *tex)
    struct pipe_resource *old_tex = *ptr;
 
    if (pipe_reference_described(&(*ptr)->reference, &tex->reference, 
-                                (debug_reference_descriptor)debug_describe_resource))
-      old_tex->screen->resource_destroy(old_tex->screen, old_tex);
+                                (debug_reference_descriptor)debug_describe_resource)) {
+      /* Avoid recursion, which would prevent inlining this function */
+      do {
+         struct pipe_resource *next = old_tex->next;
+
+         old_tex->screen->resource_destroy(old_tex->screen, old_tex);
+         old_tex = next;
+      } while (pipe_reference_described(&old_tex->reference, NULL,
+                                        (debug_reference_descriptor)debug_describe_resource));
+   }
    *ptr = tex;
 }
 
@@ -173,17 +181,6 @@ pipe_sampler_view_release(struct pipe_context *ctx,
    *ptr = NULL;
 }
 
-static inline void
-pipe_image_view_reference(struct pipe_image_view **ptr, struct pipe_image_view *view)
-{
-   struct pipe_image_view *old_view = *ptr;
-
-   if (pipe_reference_described(&(*ptr)->reference, &view->reference,
-                                (debug_reference_descriptor)debug_describe_image_view))
-      old_view->context->image_view_destroy(old_view->context, old_view);
-   *ptr = view;
-}
-
 static inline void
 pipe_so_target_reference(struct pipe_stream_output_target **ptr,
                          struct pipe_stream_output_target *target)
@@ -196,6 +193,25 @@ pipe_so_target_reference(struct pipe_stream_output_target **ptr,
    *ptr = target;
 }
 
+static inline void
+pipe_vertex_buffer_unreference(struct pipe_vertex_buffer *dst)
+{
+   if (dst->is_user_buffer)
+      dst->buffer.user = NULL;
+   else
+      pipe_resource_reference(&dst->buffer.resource, NULL);
+}
+
+static inline void
+pipe_vertex_buffer_reference(struct pipe_vertex_buffer *dst,
+                             const struct pipe_vertex_buffer *src)
+{
+   pipe_vertex_buffer_unreference(dst);
+   if (!src->is_user_buffer)
+      pipe_resource_reference(&dst->buffer.resource, src->buffer.resource);
+   memcpy(dst, src, sizeof(*src));
+}
+
 static inline void
 pipe_surface_reset(struct pipe_context *ctx, struct pipe_surface* ps,
                    struct pipe_resource *pt, unsigned level, unsigned layer)
@@ -241,12 +257,12 @@ pipe_surface_equal(struct pipe_surface *s1, struct pipe_surface *s2)
 /**
  * Create a new resource.
  * \param bind  bitmask of PIPE_BIND_x flags
- * \param usage  bitmask of PIPE_USAGE_x flags
+ * \param usage  a PIPE_USAGE_x value
  */
 static inline struct pipe_resource *
 pipe_buffer_create( struct pipe_screen *screen,
                    unsigned bind,
-                   unsigned usage,
+                   enum pipe_resource_usage usage,
                    unsigned size )
 {
    struct pipe_resource buffer;
@@ -289,7 +305,7 @@ pipe_buffer_map_range(struct pipe_context *pipe,
    u_box_1d(offset, length, &box);
 
    map = pipe->transfer_map(pipe, buffer, 0, access, &box, transfer);
-   if (map == NULL) {
+   if (!map) {
       return NULL;
    }
 
@@ -350,25 +366,8 @@ pipe_buffer_write(struct pipe_context *pipe,
                   unsigned size,
                   const void *data)
 {
-   struct pipe_box box;
-   unsigned access = PIPE_TRANSFER_WRITE;
-
-   if (offset == 0 && size == buf->width0) {
-      access |= PIPE_TRANSFER_DISCARD_WHOLE_RESOURCE;
-   } else {
-      access |= PIPE_TRANSFER_DISCARD_RANGE;
-   }
-
-   u_box_1d(offset, size, &box);
-
-   pipe->transfer_inline_write( pipe,
-                                buf,
-                                0,
-                                access,
-                                &box,
-                                data,
-                                size,
-                                0);
+   /* Don't set any other usage bits. Drivers should derive them. */
+   pipe->buffer_subdata(pipe, buf, PIPE_TRANSFER_WRITE, offset, size, data);
 }
 
 /**
@@ -383,18 +382,10 @@ pipe_buffer_write_nooverlap(struct pipe_context *pipe,
                             unsigned offset, unsigned size,
                             const void *data)
 {
-   struct pipe_box box;
-
-   u_box_1d(offset, size, &box);
-
-   pipe->transfer_inline_write(pipe,
-                               buf,
-                               0,
-                               (PIPE_TRANSFER_WRITE |
-                                PIPE_TRANSFER_UNSYNCHRONIZED),
-                               &box,
-                               data,
-                               0, 0);
+   pipe->buffer_subdata(pipe, buf,
+                        (PIPE_TRANSFER_WRITE |
+                         PIPE_TRANSFER_UNSYNCHRONIZED),
+                        offset, size, data);
 }
 
 
@@ -406,7 +397,7 @@ pipe_buffer_write_nooverlap(struct pipe_context *pipe,
 static inline struct pipe_resource *
 pipe_buffer_create_with_data(struct pipe_context *pipe,
                              unsigned bind,
-                             unsigned usage,
+                             enum pipe_resource_usage usage,
                              unsigned size,
                              const void *ptr)
 {
@@ -492,7 +483,8 @@ pipe_transfer_unmap( struct pipe_context *context,
 }
 
 static inline void
-pipe_set_constant_buffer(struct pipe_context *pipe, uint shader, uint index,
+pipe_set_constant_buffer(struct pipe_context *pipe,
+                         enum pipe_shader_type shader, uint index,
                          struct pipe_resource *buf)
 {
    if (buf) {
@@ -633,6 +625,23 @@ util_copy_constant_buffer(struct pipe_constant_buffer *dst,
    }
 }
 
+static inline void
+util_copy_image_view(struct pipe_image_view *dst,
+                     const struct pipe_image_view *src)
+{
+   if (src) {
+      pipe_resource_reference(&dst->resource, src->resource);
+      dst->format = src->format;
+      dst->access = src->access;
+      dst->u = src->u;
+   } else {
+      pipe_resource_reference(&dst->resource, NULL);
+      dst->format = PIPE_FORMAT_NONE;
+      dst->access = 0;
+      memset(&dst->u, 0, sizeof(dst->u));
+   }
+}
+
 static inline unsigned
 util_max_layer(const struct pipe_resource *r, unsigned level)
 {
@@ -651,6 +660,18 @@ util_max_layer(const struct pipe_resource *r, unsigned level)
    }
 }
 
+static inline bool
+util_texrange_covers_whole_level(const struct pipe_resource *tex,
+                                 unsigned level, unsigned x, unsigned y,
+                                 unsigned z, unsigned width,
+                                 unsigned height, unsigned depth)
+{
+   return x == 0 && y == 0 && z == 0 &&
+          width == u_minify(tex->width0, level) &&
+          height == u_minify(tex->height0, level) &&
+          depth == util_max_layer(tex, level) + 1;
+}
+
 #ifdef __cplusplus
 }
 #endif