summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian König <christian.koenig@amd.com>2014-03-25 17:31:49 +0100
committerChristian König <christian.koenig@amd.com>2014-04-04 10:25:35 +0200
commit6c59be7776e4da17119a3fca21a0a568c5c11ea7 (patch)
tree0ed58e1aef79510c5ef3428f76fa7e65883c0536
parent61bedc3d6b08943f015f9d590c07a6af36c2a92c (diff)
st/mesa: improve sampler view handling
Keep a dynamically increasing array of all the views created for a texture instead of just the last one. v2: add comments, fix array size calculation, release only the first sampler view found Signed-off-by: Christian König <christian.koenig@amd.com> Reviewed-by: Brian Paul <brianp@vmware.com>
-rw-r--r--src/mesa/state_tracker/st_atom_sampler.c22
-rw-r--r--src/mesa/state_tracker/st_atom_texture.c55
-rw-r--r--src/mesa/state_tracker/st_cb_eglimage.c2
-rw-r--r--src/mesa/state_tracker/st_cb_texture.c20
-rw-r--r--src/mesa/state_tracker/st_gen_mipmap.c2
-rw-r--r--src/mesa/state_tracker/st_texture.c68
-rw-r--r--src/mesa/state_tracker/st_texture.h16
-rw-r--r--src/mesa/state_tracker/st_vdpau.c11
8 files changed, 140 insertions, 56 deletions
diff --git a/src/mesa/state_tracker/st_atom_sampler.c b/src/mesa/state_tracker/st_atom_sampler.c
index ec2bab20b54..3929251f83a 100644
--- a/src/mesa/state_tracker/st_atom_sampler.c
+++ b/src/mesa/state_tracker/st_atom_sampler.c
@@ -182,15 +182,27 @@ convert_sampler(struct st_context *st,
msamp->BorderColor.ui[3]) {
const struct st_texture_object *stobj = st_texture_object_const(texobj);
const GLboolean is_integer = texobj->_IsIntegerFormat;
+ const struct pipe_sampler_view *sv = NULL;
union pipe_color_union border_color;
+ GLuint i;
+
+ /* Just search for the first used view. We can do this because the
+ swizzle is per-texture, not per context. */
+ /* XXX: clean that up to not use the sampler view at all */
+ for (i = 0; i < stobj->num_sampler_views; ++i) {
+ if (stobj->sampler_views[i]) {
+ sv = stobj->sampler_views[i];
+ break;
+ }
+ }
- if (st->apply_texture_swizzle_to_border_color && stobj->sampler_view) {
+ if (st->apply_texture_swizzle_to_border_color && sv) {
const unsigned char swz[4] =
{
- stobj->sampler_view->swizzle_r,
- stobj->sampler_view->swizzle_g,
- stobj->sampler_view->swizzle_b,
- stobj->sampler_view->swizzle_a,
+ sv->swizzle_r,
+ sv->swizzle_g,
+ sv->swizzle_b,
+ sv->swizzle_a,
};
st_translate_color(&msamp->BorderColor,
diff --git a/src/mesa/state_tracker/st_atom_texture.c b/src/mesa/state_tracker/st_atom_texture.c
index c9bffce4f7e..afc6d9dab7e 100644
--- a/src/mesa/state_tracker/st_atom_texture.c
+++ b/src/mesa/state_tracker/st_atom_texture.c
@@ -200,9 +200,9 @@ get_texture_format_swizzle(const struct st_texture_object *stObj)
* \param stObj the st texture object,
*/
static boolean
-check_sampler_swizzle(const struct st_texture_object *stObj)
+check_sampler_swizzle(const struct st_texture_object *stObj,
+ struct pipe_sampler_view *sv)
{
- const struct pipe_sampler_view *sv = stObj->sampler_view;
unsigned swizzle = get_texture_format_swizzle(stObj);
return ((sv->swizzle_r != GET_SWZ(swizzle, 0)) ||
@@ -258,40 +258,47 @@ st_create_texture_sampler_view_from_stobj(struct pipe_context *pipe,
static struct pipe_sampler_view *
-st_get_texture_sampler_view_from_stobj(struct st_texture_object *stObj,
- struct pipe_context *pipe,
+st_get_texture_sampler_view_from_stobj(struct st_context *st,
+ struct st_texture_object *stObj,
const struct gl_sampler_object *samp,
enum pipe_format format)
{
+ struct pipe_sampler_view **sv;
+
if (!stObj || !stObj->pt) {
return NULL;
}
- if (!stObj->sampler_view) {
- stObj->sampler_view =
- st_create_texture_sampler_view_from_stobj(pipe, stObj, samp, format);
+ sv = st_texture_get_sampler_view(st, stObj);
+
+ /* if sampler view has changed dereference it */
+ if (*sv) {
+ if (check_sampler_swizzle(stObj, *sv) ||
+ (format != (*sv)->format) ||
+ stObj->base.BaseLevel != (*sv)->u.tex.first_level) {
+ pipe_sampler_view_reference(sv, NULL);
+ }
+ }
+
+ if (!*sv) {
+ *sv = st_create_texture_sampler_view_from_stobj(st->pipe, stObj, samp, format);
- } else if (stObj->sampler_view->context != pipe) {
+ } else if ((*sv)->context != st->pipe) {
/* Recreate view in correct context, use existing view as template */
- /* XXX: This isn't optimal, we should try to use more than one view.
- Otherwise we create/destroy the view all the time
- */
- struct pipe_sampler_view *sv =
- pipe->create_sampler_view(pipe, stObj->pt, stObj->sampler_view);
- pipe_sampler_view_reference(&stObj->sampler_view, NULL);
- stObj->sampler_view = sv;
+ struct pipe_sampler_view *new_sv =
+ st->pipe->create_sampler_view(st->pipe, stObj->pt, *sv);
+ pipe_sampler_view_reference(sv, NULL);
+ *sv = new_sv;
}
- return stObj->sampler_view;
+ return *sv;
}
-
static GLboolean
update_single_texture(struct st_context *st,
struct pipe_sampler_view **sampler_view,
GLuint texUnit)
{
- struct pipe_context *pipe = st->pipe;
struct gl_context *ctx = st->ctx;
const struct gl_sampler_object *samp;
struct gl_texture_object *texObj;
@@ -330,17 +337,7 @@ update_single_texture(struct st_context *st,
}
}
- /* if sampler view has changed dereference it */
- if (stObj->sampler_view) {
- if (check_sampler_swizzle(stObj) ||
- (view_format != stObj->sampler_view->format) ||
- stObj->base.BaseLevel != stObj->sampler_view->u.tex.first_level) {
- pipe_sampler_view_release(pipe, &stObj->sampler_view);
- }
- }
-
- *sampler_view = st_get_texture_sampler_view_from_stobj(stObj, pipe,
- samp,
+ *sampler_view = st_get_texture_sampler_view_from_stobj(st, stObj, samp,
view_format);
return GL_TRUE;
}
diff --git a/src/mesa/state_tracker/st_cb_eglimage.c b/src/mesa/state_tracker/st_cb_eglimage.c
index 561967d6c1c..34eb8095918 100644
--- a/src/mesa/state_tracker/st_cb_eglimage.c
+++ b/src/mesa/state_tracker/st_cb_eglimage.c
@@ -124,7 +124,7 @@ st_bind_surface(struct gl_context *ctx, GLenum target,
/* FIXME create a non-default sampler view from the pipe_surface? */
pipe_resource_reference(&stObj->pt, ps->texture);
- pipe_sampler_view_reference(&stObj->sampler_view, NULL);
+ st_texture_release_all_sampler_views(stObj);
pipe_resource_reference(&stImage->pt, stObj->pt);
stObj->width0 = ps->width;
diff --git a/src/mesa/state_tracker/st_cb_texture.c b/src/mesa/state_tracker/st_cb_texture.c
index f0bf3745bd5..353415bf2d5 100644
--- a/src/mesa/state_tracker/st_cb_texture.c
+++ b/src/mesa/state_tracker/st_cb_texture.c
@@ -151,13 +151,11 @@ static void
st_DeleteTextureObject(struct gl_context *ctx,
struct gl_texture_object *texObj)
{
- struct st_context *st = st_context(ctx);
struct st_texture_object *stObj = st_texture_object(texObj);
- if (stObj->pt)
- pipe_resource_reference(&stObj->pt, NULL);
- if (stObj->sampler_view) {
- pipe_sampler_view_release(st->pipe, &stObj->sampler_view);
- }
+
+ pipe_resource_reference(&stObj->pt, NULL);
+ st_texture_release_all_sampler_views(stObj);
+ FREE(stObj->sampler_views);
_mesa_delete_texture_object(ctx, texObj);
}
@@ -454,7 +452,7 @@ st_AllocTextureImageBuffer(struct gl_context *ctx,
/* The parent texture object does not have space for this image */
pipe_resource_reference(&stObj->pt, NULL);
- pipe_sampler_view_release(st->pipe, &stObj->sampler_view);
+ st_texture_release_all_sampler_views(stObj);
if (!guess_and_alloc_texture(st, stObj, stImage)) {
/* Probably out of memory.
@@ -1487,13 +1485,13 @@ st_finalize_texture(struct gl_context *ctx,
if (!st_obj) {
pipe_resource_reference(&stObj->pt, NULL);
- pipe_sampler_view_reference(&stObj->sampler_view, NULL);
+ st_texture_release_all_sampler_views(stObj);
return GL_TRUE;
}
if (st_obj->buffer != stObj->pt) {
pipe_resource_reference(&stObj->pt, st_obj->buffer);
- pipe_sampler_view_release(st->pipe, &stObj->sampler_view);
+ st_texture_release_all_sampler_views(stObj);
stObj->width0 = stObj->pt->width0 / _mesa_get_format_bytes(tObj->_BufferObjectFormat);
stObj->height0 = 1;
stObj->depth0 = 1;
@@ -1514,7 +1512,7 @@ st_finalize_texture(struct gl_context *ctx,
firstImage->pt != stObj->pt &&
(!stObj->pt || firstImage->pt->last_level >= stObj->pt->last_level)) {
pipe_resource_reference(&stObj->pt, firstImage->pt);
- pipe_sampler_view_release(st->pipe, &stObj->sampler_view);
+ st_texture_release_all_sampler_views(stObj);
}
/* If this texture comes from a window system, there is nothing else to do. */
@@ -1561,7 +1559,7 @@ st_finalize_texture(struct gl_context *ctx,
* gallium texture now. We'll make a new one below.
*/
pipe_resource_reference(&stObj->pt, NULL);
- pipe_sampler_view_release(st->pipe, &stObj->sampler_view);
+ st_texture_release_all_sampler_views(stObj);
st->dirty.st |= ST_NEW_FRAMEBUFFER;
}
}
diff --git a/src/mesa/state_tracker/st_gen_mipmap.c b/src/mesa/state_tracker/st_gen_mipmap.c
index b615575b5cc..f1864fcdebc 100644
--- a/src/mesa/state_tracker/st_gen_mipmap.c
+++ b/src/mesa/state_tracker/st_gen_mipmap.c
@@ -182,7 +182,7 @@ st_generate_mipmap(struct gl_context *ctx, GLenum target,
/* release the old tex (will likely be freed too) */
pipe_resource_reference(&oldTex, NULL);
- pipe_sampler_view_reference(&stObj->sampler_view, NULL);
+ st_texture_release_all_sampler_views(stObj);
}
else {
/* Make sure that the base texture image data is present in the
diff --git a/src/mesa/state_tracker/st_texture.c b/src/mesa/state_tracker/st_texture.c
index a3b345356e1..8d559dfcdfd 100644
--- a/src/mesa/state_tracker/st_texture.c
+++ b/src/mesa/state_tracker/st_texture.c
@@ -40,6 +40,7 @@
#include "util/u_format.h"
#include "util/u_rect.h"
#include "util/u_math.h"
+#include "util/u_memory.h"
#define DBG if(0) printf
@@ -412,10 +413,73 @@ st_create_color_map_texture(struct gl_context *ctx)
return pt;
}
+/**
+ * Try to find a matching sampler view for the given context.
+ * If none is found an empty slot is initialized with a
+ * template and returned instead.
+ */
+struct pipe_sampler_view **
+st_texture_get_sampler_view(struct st_context *st,
+ struct st_texture_object *stObj)
+{
+ struct pipe_sampler_view **used = NULL, **free = NULL;
+ GLuint i;
+
+ for (i = 0; i < stObj->num_sampler_views; ++i) {
+ struct pipe_sampler_view **sv = &stObj->sampler_views[i];
+ /* Is the array entry used ? */
+ if (*sv) {
+ /* Yes, check if it's the right one */
+ if ((*sv)->context == st->pipe)
+ return sv;
+
+ /* Wasn't the right one, but remember it as template */
+ used = sv;
+ } else {
+ /* Found a free slot, remember that */
+ free = sv;
+ }
+ }
+
+ /* Couldn't find a slot for our context, create a new one */
+
+ if (!free) {
+ /* Haven't even found a free one, resize the array */
+ GLuint old_size = stObj->num_sampler_views * sizeof(void *);
+ GLuint new_size = old_size + sizeof(void *);
+ stObj->sampler_views = REALLOC(stObj->sampler_views, old_size, new_size);
+ free = &stObj->sampler_views[stObj->num_sampler_views++];
+ *free = NULL;
+ }
+
+ /* Add just any sampler view to be used as a template */
+ if (used)
+ pipe_sampler_view_reference(free, *used);
+
+ return free;
+}
+
void
st_texture_release_sampler_view(struct st_context *st,
struct st_texture_object *stObj)
{
- if (stObj->sampler_view && stObj->sampler_view->context == st->pipe)
- pipe_sampler_view_reference(&stObj->sampler_view, NULL);
+ GLuint i;
+
+ for (i = 0; i < stObj->num_sampler_views; ++i) {
+ struct pipe_sampler_view **sv = &stObj->sampler_views[i];
+
+ if (*sv && (*sv)->context == st->pipe) {
+ pipe_sampler_view_reference(sv, NULL);
+ break;
+ }
+ }
+}
+
+void
+st_texture_release_all_sampler_views(struct st_texture_object *stObj)
+{
+ GLuint i;
+
+ for (i = 0; i < stObj->num_sampler_views; ++i)
+ pipe_sampler_view_reference(&stObj->sampler_views[i], NULL);
}
diff --git a/src/mesa/state_tracker/st_texture.h b/src/mesa/state_tracker/st_texture.h
index b4a27a00a9b..87de9f9f2f4 100644
--- a/src/mesa/state_tracker/st_texture.h
+++ b/src/mesa/state_tracker/st_texture.h
@@ -82,10 +82,13 @@ struct st_texture_object
*/
struct pipe_resource *pt;
- /* Default sampler view attached to this texture object. Created lazily
- * on first binding.
+ /* Number of views in sampler_views array */
+ GLuint num_sampler_views;
+
+ /* Array of sampler views (one per context) attached to this texture
+ * object. Created lazily on first binding in context.
*/
- struct pipe_sampler_view *sampler_view;
+ struct pipe_sampler_view **sampler_views;
/* True if this texture comes from the window system. Such a texture
* cannot be reallocated and the format can only be changed with a sampler
@@ -227,8 +230,15 @@ st_texture_image_copy(struct pipe_context *pipe,
extern struct pipe_resource *
st_create_color_map_texture(struct gl_context *ctx);
+extern struct pipe_sampler_view **
+st_texture_get_sampler_view(struct st_context *st,
+ struct st_texture_object *stObj);
+
extern void
st_texture_release_sampler_view(struct st_context *st,
struct st_texture_object *stObj);
+extern void
+st_texture_release_all_sampler_views(struct st_texture_object *stObj);
+
#endif
diff --git a/src/mesa/state_tracker/st_vdpau.c b/src/mesa/state_tracker/st_vdpau.c
index c5b4780ce5b..8c10cdaf38b 100644
--- a/src/mesa/state_tracker/st_vdpau.c
+++ b/src/mesa/state_tracker/st_vdpau.c
@@ -63,7 +63,7 @@ st_vdpau_map_surface(struct gl_context *ctx, GLenum target, GLenum access,
struct st_texture_image *stImage = st_texture_image(texImage);
struct pipe_resource *res;
- struct pipe_sampler_view *sv, templ;
+ struct pipe_sampler_view templ, **sampler_view;
mesa_format texFormat;
getProcAddr = ctx->vdpGetProcAddress;
@@ -83,6 +83,7 @@ st_vdpau_map_surface(struct gl_context *ctx, GLenum target, GLenum access,
}
} else {
+ struct pipe_sampler_view *sv;
VdpVideoSurfaceGallium *f;
struct pipe_video_buffer *buffer;
@@ -138,7 +139,7 @@ st_vdpau_map_surface(struct gl_context *ctx, GLenum target, GLenum access,
texFormat);
pipe_resource_reference(&stObj->pt, res);
- pipe_sampler_view_reference(&stObj->sampler_view, NULL);
+ st_texture_release_all_sampler_views(stObj);
pipe_resource_reference(&stImage->pt, res);
u_sampler_view_default_template(&templ, res, res->format);
@@ -148,7 +149,9 @@ st_vdpau_map_surface(struct gl_context *ctx, GLenum target, GLenum access,
templ.swizzle_g = GET_SWZ(stObj->base._Swizzle, 1);
templ.swizzle_b = GET_SWZ(stObj->base._Swizzle, 2);
templ.swizzle_a = GET_SWZ(stObj->base._Swizzle, 3);
- stObj->sampler_view = st->pipe->create_sampler_view(st->pipe, res, &templ);
+
+ sampler_view = st_texture_get_sampler_view(st, stObj);
+ *sampler_view = st->pipe->create_sampler_view(st->pipe, res, &templ);
stObj->width0 = res->width0;
stObj->height0 = res->height0;
@@ -169,7 +172,7 @@ st_vdpau_unmap_surface(struct gl_context *ctx, GLenum target, GLenum access,
struct st_texture_image *stImage = st_texture_image(texImage);
pipe_resource_reference(&stObj->pt, NULL);
- pipe_sampler_view_reference(&stObj->sampler_view, NULL);
+ st_texture_release_all_sampler_views(stObj);
pipe_resource_reference(&stImage->pt, NULL);
_mesa_dirty_texobj(ctx, texObj);