diff options
author | Luca Barbieri <[email protected]> | 2010-04-18 14:54:16 +0200 |
---|---|---|
committer | Luca Barbieri <[email protected]> | 2010-04-18 16:23:11 +0200 |
commit | ac4b8db62d056fa5b85661f67ba5e1d1d29e3fcf (patch) | |
tree | b3b6e60bd2f6d332a81809b3b801f242fdfbbda7 /src/gallium/auxiliary/util | |
parent | 24af25df2b0381d359f16abc815c95c0d500598b (diff) |
auxiliary: add util_surfaces to track a resource's pipe_surface structs
Diffstat (limited to 'src/gallium/auxiliary/util')
-rw-r--r-- | src/gallium/auxiliary/util/u_surfaces.c | 112 | ||||
-rw-r--r-- | src/gallium/auxiliary/util/u_surfaces.h | 54 |
2 files changed, 166 insertions, 0 deletions
diff --git a/src/gallium/auxiliary/util/u_surfaces.c b/src/gallium/auxiliary/util/u_surfaces.c new file mode 100644 index 00000000000..3a0539ceb47 --- /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 00000000000..6de5e7cc17e --- /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 |