Mesa (nvfx-next-6): auxiliary: add util_surfaces to track a resource' s pipe_surface structs

Luca Barbieri lb at kemper.freedesktop.org
Sun Apr 18 14:25:32 UTC 2010


Module: Mesa
Branch: nvfx-next-6
Commit: ac4b8db62d056fa5b85661f67ba5e1d1d29e3fcf
URL:    http://cgit.freedesktop.org/mesa/mesa/commit/?id=ac4b8db62d056fa5b85661f67ba5e1d1d29e3fcf

Author: Luca Barbieri <luca at luca-barbieri.com>
Date:   Sun Apr 18 14:54:16 2010 +0200

auxiliary: add util_surfaces to track a resource's pipe_surface structs

---

 src/gallium/auxiliary/Makefile          |    1 +
 src/gallium/auxiliary/util/u_surfaces.c |  112 +++++++++++++++++++++++++++++++
 src/gallium/auxiliary/util/u_surfaces.h |   54 +++++++++++++++
 3 files changed, 167 insertions(+), 0 deletions(-)

diff --git a/src/gallium/auxiliary/Makefile b/src/gallium/auxiliary/Makefile
index c672f32..38ce14d 100644
--- a/src/gallium/auxiliary/Makefile
+++ b/src/gallium/auxiliary/Makefile
@@ -129,6 +129,7 @@ C_SOURCES = \
 	util/u_simple_shaders.c \
 	util/u_snprintf.c \
 	util/u_surface.c \
+	util/u_surfaces.c \
 	util/u_texture.c \
 	util/u_tile.c \
 	util/u_transfer.c \
diff --git a/src/gallium/auxiliary/util/u_surfaces.c b/src/gallium/auxiliary/util/u_surfaces.c
new file mode 100644
index 0000000..3a0539c
--- /dev/null
+++ b/src/gallium/auxiliary/util/u_surfaces.c
@@ -0,0 +1,112 @@
+#include "u_surfaces.h"
+#include "util/u_hash_table.h"
+#include "util/u_inlines.h"
+#include "util/u_memory.h"
+
+/* TODO: ouch, util_hash_table should do these by default when passed a null function pointer
+ * this indirect function call is quite bad
+ */
+static unsigned
+hash(void *key)
+{
+   return (unsigned)key;
+}
+
+static int
+compare(void *key1, void *key2)
+{
+   return (unsigned)key1 - (unsigned)key2;
+}
+
+struct pipe_surface *
+util_surfaces_do_get(struct util_surfaces *us, unsigned surface_struct_size, struct pipe_screen *pscreen, struct pipe_resource *pt, unsigned face, unsigned level, unsigned zslice, unsigned flags)
+{
+   struct pipe_surface *ps;
+   void *key;
+
+   if(pt->target == PIPE_TEXTURE_3D || pt->target == PIPE_TEXTURE_CUBE)
+   {	/* or 2D array */
+      if(!us->u.table)
+	 us->u.table = util_hash_table_create(hash, compare);
+      key = (void *)(((zslice + face) << 8) | level);
+      /* TODO: ouch, should have a get-reference function...
+       * also, shouldn't allocate a two-pointer structure for each item... */
+      ps = util_hash_table_get(us->u.table, key);
+   }
+   else
+   {
+      if(!us->u.array)
+	 us->u.array = CALLOC(pt->last_level + 1, sizeof(struct pipe_surface *));
+      ps = us->u.array[level];
+   }
+
+   if(ps)
+   {
+      p_atomic_inc(&ps->reference.count);
+      return ps;
+   }
+
+   ps = (struct pipe_surface *)CALLOC(1, surface_struct_size);
+   if(!ps)
+      return NULL;
+
+   pipe_reference_init(&ps->reference, 1);
+   pipe_surface_init(ps, pt, face, level, zslice, flags);
+   ps->offset = ~0;
+
+   if(pt->target == PIPE_TEXTURE_3D || pt->target == PIPE_TEXTURE_CUBE)
+      util_hash_table_set(us->u.table, key, ps);
+   else
+      us->u.array[level] = ps;
+
+   return ps;
+}
+
+void
+util_surfaces_do_detach(struct util_surfaces *us, struct pipe_surface *ps)
+{
+   struct pipe_resource *pt = ps->texture;
+   if(pt->target == PIPE_TEXTURE_3D || pt->target == PIPE_TEXTURE_CUBE)
+   {	/* or 2D array */
+      unsigned key = ((ps->zslice + ps->face) << 8) | ps->level;
+      util_hash_table_remove(us->u.table, key);
+   }
+   else
+      us->u.array[ps->level] = 0;
+}
+
+static enum pipe_error
+util_surfaces_destroy_callback(void *key, void *value, void *data)
+{
+   void (*destroy_surface) (struct pipe_surface * ps) = data;
+   destroy_surface((struct pipe_surface *)value);
+   return PIPE_OK;
+}
+
+void
+util_surfaces_destroy(struct util_surfaces *us, struct pipe_resource *pt, void (*destroy_surface) (struct pipe_surface *))
+{
+   if(pt->target == PIPE_TEXTURE_3D || pt->target == PIPE_TEXTURE_CUBE)
+   {	/* or 2D array */
+      if(us->u.table)
+      {
+	 util_hash_table_foreach(us->u.table, util_surfaces_destroy_callback, destroy_surface);
+	 util_hash_table_destroy(us->u.table);
+	 us->u.table = NULL;
+      }
+   }
+   else
+   {
+      if(us->u.array)
+      {
+	 for(unsigned i = 0; i < pt->last_level; ++i)
+	 {
+	    struct pipe_surface *ps = us->u.array[i];
+	    if(ps)
+	       destroy_surface(ps);
+	 }
+	 free(us->u.array);
+	 us->u.array = NULL;
+      }
+   }
+}
diff --git a/src/gallium/auxiliary/util/u_surfaces.h b/src/gallium/auxiliary/util/u_surfaces.h
new file mode 100644
index 0000000..6de5e7c
--- /dev/null
+++ b/src/gallium/auxiliary/util/u_surfaces.h
@@ -0,0 +1,54 @@
+#ifndef U_SURFACES_H_
+#define U_SURFACES_H_
+
+#include "pipe/p_compiler.h"
+#include "pipe/p_state.h"
+#include "util/u_atomic.h"
+
+struct util_hash_table;
+
+struct util_surfaces
+{
+   union
+   {
+      struct util_hash_table *table;
+      struct pipe_surface **array;
+   } u;
+};
+
+struct pipe_surface *util_surfaces_do_get(struct util_surfaces *us, unsigned surface_struct_size, struct pipe_screen *pscreen, struct pipe_resource *pt, unsigned face, unsigned level, unsigned zslice, unsigned flags);
+
+/* fast inline path for the very common case */
+static INLINE struct pipe_surface *
+util_surfaces_get(struct util_surfaces *us, unsigned surface_struct_size, struct pipe_screen *pscreen, struct pipe_resource *pt, unsigned face, unsigned level, unsigned zslice, unsigned flags)
+{
+   if(likely(pt->target == PIPE_TEXTURE_2D && us->u.array))
+   {
+      struct pipe_surface *ps = us->u.array[level];
+      if(ps)
+      {
+	 p_atomic_inc(&ps->reference.count);
+	 return ps;
+      }
+   }
+
+   return util_surfaces_do_get(us, surface_struct_size, pscreen, pt, face, level, zslice, flags);
+}
+
+void util_surfaces_do_detach(struct util_surfaces *us, struct pipe_surface *ps);
+
+static INLINE void
+util_surfaces_detach(struct util_surfaces *us, struct pipe_surface *ps)
+{
+   if(likely(ps->texture->target == PIPE_TEXTURE_2D))
+   {
+      us->u.array[ps->level] = 0;
+      return;
+   }
+
+   return util_surfaces_do_detach(us, ps);
+}
+
+void util_surfaces_destroy(struct util_surfaces *us, struct pipe_resource *pt, void (*destroy_surface) (struct pipe_surface *));
+
+#endif




More information about the mesa-commit mailing list