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>
This commit is contained in:
@@ -182,15 +182,27 @@ convert_sampler(struct st_context *st,
|
|||||||
msamp->BorderColor.ui[3]) {
|
msamp->BorderColor.ui[3]) {
|
||||||
const struct st_texture_object *stobj = st_texture_object_const(texobj);
|
const struct st_texture_object *stobj = st_texture_object_const(texobj);
|
||||||
const GLboolean is_integer = texobj->_IsIntegerFormat;
|
const GLboolean is_integer = texobj->_IsIntegerFormat;
|
||||||
|
const struct pipe_sampler_view *sv = NULL;
|
||||||
union pipe_color_union border_color;
|
union pipe_color_union border_color;
|
||||||
|
GLuint i;
|
||||||
|
|
||||||
if (st->apply_texture_swizzle_to_border_color && stobj->sampler_view) {
|
/* 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 && sv) {
|
||||||
const unsigned char swz[4] =
|
const unsigned char swz[4] =
|
||||||
{
|
{
|
||||||
stobj->sampler_view->swizzle_r,
|
sv->swizzle_r,
|
||||||
stobj->sampler_view->swizzle_g,
|
sv->swizzle_g,
|
||||||
stobj->sampler_view->swizzle_b,
|
sv->swizzle_b,
|
||||||
stobj->sampler_view->swizzle_a,
|
sv->swizzle_a,
|
||||||
};
|
};
|
||||||
|
|
||||||
st_translate_color(&msamp->BorderColor,
|
st_translate_color(&msamp->BorderColor,
|
||||||
|
|||||||
@@ -200,9 +200,9 @@ get_texture_format_swizzle(const struct st_texture_object *stObj)
|
|||||||
* \param stObj the st texture object,
|
* \param stObj the st texture object,
|
||||||
*/
|
*/
|
||||||
static boolean
|
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);
|
unsigned swizzle = get_texture_format_swizzle(stObj);
|
||||||
|
|
||||||
return ((sv->swizzle_r != GET_SWZ(swizzle, 0)) ||
|
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 *
|
static struct pipe_sampler_view *
|
||||||
st_get_texture_sampler_view_from_stobj(struct st_texture_object *stObj,
|
st_get_texture_sampler_view_from_stobj(struct st_context *st,
|
||||||
struct pipe_context *pipe,
|
struct st_texture_object *stObj,
|
||||||
const struct gl_sampler_object *samp,
|
const struct gl_sampler_object *samp,
|
||||||
enum pipe_format format)
|
enum pipe_format format)
|
||||||
{
|
{
|
||||||
|
struct pipe_sampler_view **sv;
|
||||||
|
|
||||||
if (!stObj || !stObj->pt) {
|
if (!stObj || !stObj->pt) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!stObj->sampler_view) {
|
sv = st_texture_get_sampler_view(st, stObj);
|
||||||
stObj->sampler_view =
|
|
||||||
st_create_texture_sampler_view_from_stobj(pipe, stObj, samp, format);
|
|
||||||
|
|
||||||
} else if (stObj->sampler_view->context != pipe) {
|
/* if sampler view has changed dereference it */
|
||||||
/* Recreate view in correct context, use existing view as template */
|
if (*sv) {
|
||||||
/* XXX: This isn't optimal, we should try to use more than one view.
|
if (check_sampler_swizzle(stObj, *sv) ||
|
||||||
Otherwise we create/destroy the view all the time
|
(format != (*sv)->format) ||
|
||||||
*/
|
stObj->base.BaseLevel != (*sv)->u.tex.first_level) {
|
||||||
struct pipe_sampler_view *sv =
|
pipe_sampler_view_reference(sv, NULL);
|
||||||
pipe->create_sampler_view(pipe, stObj->pt, stObj->sampler_view);
|
}
|
||||||
pipe_sampler_view_reference(&stObj->sampler_view, NULL);
|
|
||||||
stObj->sampler_view = sv;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return stObj->sampler_view;
|
if (!*sv) {
|
||||||
}
|
*sv = st_create_texture_sampler_view_from_stobj(st->pipe, stObj, samp, format);
|
||||||
|
|
||||||
|
} else if ((*sv)->context != st->pipe) {
|
||||||
|
/* Recreate view in correct context, use existing view as template */
|
||||||
|
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 *sv;
|
||||||
|
}
|
||||||
|
|
||||||
static GLboolean
|
static GLboolean
|
||||||
update_single_texture(struct st_context *st,
|
update_single_texture(struct st_context *st,
|
||||||
struct pipe_sampler_view **sampler_view,
|
struct pipe_sampler_view **sampler_view,
|
||||||
GLuint texUnit)
|
GLuint texUnit)
|
||||||
{
|
{
|
||||||
struct pipe_context *pipe = st->pipe;
|
|
||||||
struct gl_context *ctx = st->ctx;
|
struct gl_context *ctx = st->ctx;
|
||||||
const struct gl_sampler_object *samp;
|
const struct gl_sampler_object *samp;
|
||||||
struct gl_texture_object *texObj;
|
struct gl_texture_object *texObj;
|
||||||
@@ -330,17 +337,7 @@ update_single_texture(struct st_context *st,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* if sampler view has changed dereference it */
|
*sampler_view = st_get_texture_sampler_view_from_stobj(st, stObj, samp,
|
||||||
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,
|
|
||||||
view_format);
|
view_format);
|
||||||
return GL_TRUE;
|
return GL_TRUE;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -124,7 +124,7 @@ st_bind_surface(struct gl_context *ctx, GLenum target,
|
|||||||
|
|
||||||
/* FIXME create a non-default sampler view from the pipe_surface? */
|
/* FIXME create a non-default sampler view from the pipe_surface? */
|
||||||
pipe_resource_reference(&stObj->pt, ps->texture);
|
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);
|
pipe_resource_reference(&stImage->pt, stObj->pt);
|
||||||
|
|
||||||
stObj->width0 = ps->width;
|
stObj->width0 = ps->width;
|
||||||
|
|||||||
@@ -151,13 +151,11 @@ static void
|
|||||||
st_DeleteTextureObject(struct gl_context *ctx,
|
st_DeleteTextureObject(struct gl_context *ctx,
|
||||||
struct gl_texture_object *texObj)
|
struct gl_texture_object *texObj)
|
||||||
{
|
{
|
||||||
struct st_context *st = st_context(ctx);
|
|
||||||
struct st_texture_object *stObj = st_texture_object(texObj);
|
struct st_texture_object *stObj = st_texture_object(texObj);
|
||||||
if (stObj->pt)
|
|
||||||
pipe_resource_reference(&stObj->pt, NULL);
|
pipe_resource_reference(&stObj->pt, NULL);
|
||||||
if (stObj->sampler_view) {
|
st_texture_release_all_sampler_views(stObj);
|
||||||
pipe_sampler_view_release(st->pipe, &stObj->sampler_view);
|
FREE(stObj->sampler_views);
|
||||||
}
|
|
||||||
_mesa_delete_texture_object(ctx, texObj);
|
_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 */
|
/* The parent texture object does not have space for this image */
|
||||||
|
|
||||||
pipe_resource_reference(&stObj->pt, NULL);
|
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)) {
|
if (!guess_and_alloc_texture(st, stObj, stImage)) {
|
||||||
/* Probably out of memory.
|
/* Probably out of memory.
|
||||||
@@ -1487,13 +1485,13 @@ st_finalize_texture(struct gl_context *ctx,
|
|||||||
|
|
||||||
if (!st_obj) {
|
if (!st_obj) {
|
||||||
pipe_resource_reference(&stObj->pt, NULL);
|
pipe_resource_reference(&stObj->pt, NULL);
|
||||||
pipe_sampler_view_reference(&stObj->sampler_view, NULL);
|
st_texture_release_all_sampler_views(stObj);
|
||||||
return GL_TRUE;
|
return GL_TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (st_obj->buffer != stObj->pt) {
|
if (st_obj->buffer != stObj->pt) {
|
||||||
pipe_resource_reference(&stObj->pt, st_obj->buffer);
|
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->width0 = stObj->pt->width0 / _mesa_get_format_bytes(tObj->_BufferObjectFormat);
|
||||||
stObj->height0 = 1;
|
stObj->height0 = 1;
|
||||||
stObj->depth0 = 1;
|
stObj->depth0 = 1;
|
||||||
@@ -1514,7 +1512,7 @@ st_finalize_texture(struct gl_context *ctx,
|
|||||||
firstImage->pt != stObj->pt &&
|
firstImage->pt != stObj->pt &&
|
||||||
(!stObj->pt || firstImage->pt->last_level >= stObj->pt->last_level)) {
|
(!stObj->pt || firstImage->pt->last_level >= stObj->pt->last_level)) {
|
||||||
pipe_resource_reference(&stObj->pt, firstImage->pt);
|
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. */
|
/* 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.
|
* gallium texture now. We'll make a new one below.
|
||||||
*/
|
*/
|
||||||
pipe_resource_reference(&stObj->pt, NULL);
|
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;
|
st->dirty.st |= ST_NEW_FRAMEBUFFER;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -182,7 +182,7 @@ st_generate_mipmap(struct gl_context *ctx, GLenum target,
|
|||||||
|
|
||||||
/* release the old tex (will likely be freed too) */
|
/* release the old tex (will likely be freed too) */
|
||||||
pipe_resource_reference(&oldTex, NULL);
|
pipe_resource_reference(&oldTex, NULL);
|
||||||
pipe_sampler_view_reference(&stObj->sampler_view, NULL);
|
st_texture_release_all_sampler_views(stObj);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
/* Make sure that the base texture image data is present in the
|
/* Make sure that the base texture image data is present in the
|
||||||
|
|||||||
@@ -40,6 +40,7 @@
|
|||||||
#include "util/u_format.h"
|
#include "util/u_format.h"
|
||||||
#include "util/u_rect.h"
|
#include "util/u_rect.h"
|
||||||
#include "util/u_math.h"
|
#include "util/u_math.h"
|
||||||
|
#include "util/u_memory.h"
|
||||||
|
|
||||||
|
|
||||||
#define DBG if(0) printf
|
#define DBG if(0) printf
|
||||||
@@ -412,10 +413,73 @@ st_create_color_map_texture(struct gl_context *ctx)
|
|||||||
return pt;
|
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
|
void
|
||||||
st_texture_release_sampler_view(struct st_context *st,
|
st_texture_release_sampler_view(struct st_context *st,
|
||||||
struct st_texture_object *stObj)
|
struct st_texture_object *stObj)
|
||||||
{
|
{
|
||||||
if (stObj->sampler_view && stObj->sampler_view->context == st->pipe)
|
GLuint i;
|
||||||
pipe_sampler_view_reference(&stObj->sampler_view, NULL);
|
|
||||||
|
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);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -82,10 +82,13 @@ struct st_texture_object
|
|||||||
*/
|
*/
|
||||||
struct pipe_resource *pt;
|
struct pipe_resource *pt;
|
||||||
|
|
||||||
/* Default sampler view attached to this texture object. Created lazily
|
/* Number of views in sampler_views array */
|
||||||
* on first binding.
|
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
|
/* 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
|
* 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 *
|
extern struct pipe_resource *
|
||||||
st_create_color_map_texture(struct gl_context *ctx);
|
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
|
extern void
|
||||||
st_texture_release_sampler_view(struct st_context *st,
|
st_texture_release_sampler_view(struct st_context *st,
|
||||||
struct st_texture_object *stObj);
|
struct st_texture_object *stObj);
|
||||||
|
|
||||||
|
extern void
|
||||||
|
st_texture_release_all_sampler_views(struct st_texture_object *stObj);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -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 st_texture_image *stImage = st_texture_image(texImage);
|
||||||
|
|
||||||
struct pipe_resource *res;
|
struct pipe_resource *res;
|
||||||
struct pipe_sampler_view *sv, templ;
|
struct pipe_sampler_view templ, **sampler_view;
|
||||||
mesa_format texFormat;
|
mesa_format texFormat;
|
||||||
|
|
||||||
getProcAddr = ctx->vdpGetProcAddress;
|
getProcAddr = ctx->vdpGetProcAddress;
|
||||||
@@ -83,6 +83,7 @@ st_vdpau_map_surface(struct gl_context *ctx, GLenum target, GLenum access,
|
|||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
struct pipe_sampler_view *sv;
|
||||||
VdpVideoSurfaceGallium *f;
|
VdpVideoSurfaceGallium *f;
|
||||||
|
|
||||||
struct pipe_video_buffer *buffer;
|
struct pipe_video_buffer *buffer;
|
||||||
@@ -138,7 +139,7 @@ st_vdpau_map_surface(struct gl_context *ctx, GLenum target, GLenum access,
|
|||||||
texFormat);
|
texFormat);
|
||||||
|
|
||||||
pipe_resource_reference(&stObj->pt, res);
|
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);
|
pipe_resource_reference(&stImage->pt, res);
|
||||||
|
|
||||||
u_sampler_view_default_template(&templ, res, res->format);
|
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_g = GET_SWZ(stObj->base._Swizzle, 1);
|
||||||
templ.swizzle_b = GET_SWZ(stObj->base._Swizzle, 2);
|
templ.swizzle_b = GET_SWZ(stObj->base._Swizzle, 2);
|
||||||
templ.swizzle_a = GET_SWZ(stObj->base._Swizzle, 3);
|
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->width0 = res->width0;
|
||||||
stObj->height0 = res->height0;
|
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);
|
struct st_texture_image *stImage = st_texture_image(texImage);
|
||||||
|
|
||||||
pipe_resource_reference(&stObj->pt, NULL);
|
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);
|
pipe_resource_reference(&stImage->pt, NULL);
|
||||||
|
|
||||||
_mesa_dirty_texobj(ctx, texObj);
|
_mesa_dirty_texobj(ctx, texObj);
|
||||||
|
|||||||
Reference in New Issue
Block a user