static struct pipe_sampler_view *
st_get_texture_sampler_view_from_stobj(struct st_context *st,
struct st_texture_object *stObj,
- enum pipe_format format,
+ const struct gl_sampler_object *samp,
unsigned glsl_version)
{
struct pipe_sampler_view **sv;
sv = st_texture_get_sampler_view(st, stObj);
- /* if sampler view has changed dereference it */
if (*sv) {
- if (check_sampler_swizzle(st, stObj, *sv, glsl_version) ||
- (format != (*sv)->format) ||
- gl_target_to_pipe(stObj->base.Target) != (*sv)->target ||
- stObj->base.MinLevel + stObj->base.BaseLevel != (*sv)->u.tex.first_level ||
- last_level(stObj) != (*sv)->u.tex.last_level ||
- stObj->base.MinLayer != (*sv)->u.tex.first_layer ||
- last_layer(stObj) != (*sv)->u.tex.last_layer) {
- pipe_sampler_view_reference(sv, NULL);
+ /* Debug check: make sure that the sampler view's parameters are
+ * what they're supposed to be.
+ */
+ struct pipe_sampler_view *view = *sv;
+ assert(!check_sampler_swizzle(st, stObj, view, glsl_version));
+ assert(get_sampler_view_format(st, stObj, samp) == view->format);
+ assert(gl_target_to_pipe(stObj->base.Target) == view->target);
+ if (stObj->base.Target == GL_TEXTURE_BUFFER) {
+ unsigned base = stObj->base.BufferOffset;
+ unsigned size = MIN2(stObj->pt->width0 - base,
+ (unsigned) stObj->base.BufferSize);
+ assert(view->u.buf.offset == base);
+ assert(view->u.buf.size == size);
+ }
+ else {
+ assert(stObj->base.MinLevel + stObj->base.BaseLevel ==
+ view->u.tex.first_level);
+ assert(last_level(stObj) == view->u.tex.last_level);
+ assert(stObj->base.MinLayer == view->u.tex.first_layer);
+ assert(last_layer(stObj) == view->u.tex.last_layer);
}
}
+ else {
+ /* create new sampler view */
+ enum pipe_format format = get_sampler_view_format(st, stObj, samp);
- if (!*sv) {
*sv = st_create_texture_sampler_view_from_stobj(st, stObj,
format, glsl_version);
- } 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
update_single_texture(struct st_context *st,
struct pipe_sampler_view **sampler_view,
const struct gl_sampler_object *samp;
struct gl_texture_object *texObj;
struct st_texture_object *stObj;
- enum pipe_format view_format;
GLboolean retval;
samp = _mesa_get_samplerobj(ctx, texUnit);
return GL_FALSE;
}
- view_format = get_sampler_view_format(st, stObj, samp);
+ /* Check a few pieces of state outside the texture object to see if we
+ * need to force revalidation.
+ */
+ if (stObj->prev_glsl_version != glsl_version ||
+ stObj->prev_sRGBDecode != samp->sRGBDecode) {
+
+ st_texture_release_all_sampler_views(st, stObj);
+
+ stObj->prev_glsl_version = glsl_version;
+ stObj->prev_sRGBDecode = samp->sRGBDecode;
+ }
*sampler_view =
- st_get_texture_sampler_view_from_stobj(st, stObj, view_format,
- glsl_version);
+ st_get_texture_sampler_view_from_stobj(st, stObj, samp, glsl_version);
return GL_TRUE;
}
st_FreeTextureImageBuffer(struct gl_context *ctx,
struct gl_texture_image *texImage)
{
+ struct st_context *st = st_context(ctx);
+ struct st_texture_object *stObj = st_texture_object(texImage->TexObject);
struct st_texture_image *stImage = st_texture_image(texImage);
DBG("%s\n", __func__);
free(stImage->etc_data);
stImage->etc_data = NULL;
}
+
+ /* if the texture image is being deallocated, the structure of the
+ * texture is changing so we'll likely need a new sampler view.
+ */
+ st_texture_release_all_sampler_views(st, stObj);
}
bool
struct gl_texture_object *texObj,
struct gl_texture_object *origTexObj)
{
+ struct st_context *st = st_context(ctx);
struct st_texture_object *orig = st_texture_object(origTexObj);
struct st_texture_object *tex = st_texture_object(texObj);
struct gl_texture_image *image = texObj->Image[0][0];
tex->lastLevel = numLevels - 1;
+ /* free texture sampler views. They need to be recreated when we
+ * change the texture view parameters.
+ */
+ st_texture_release_all_sampler_views(st, tex);
+
return GL_TRUE;
}
pipe->clear_texture(pipe, pt, level, &box, clearValue ? clearValue : zeros);
}
+
+/**
+ * Called via the glTexParam*() function, but only when some texture object
+ * state has actually changed.
+ */
+static void
+st_TexParameter(struct gl_context *ctx,
+ struct gl_texture_object *texObj,
+ GLenum pname, const GLfloat *params)
+{
+ struct st_context *st = st_context(ctx);
+ struct st_texture_object *stObj = st_texture_object(texObj);
+
+ switch (pname) {
+ case GL_TEXTURE_BASE_LEVEL:
+ case GL_TEXTURE_MAX_LEVEL:
+ case GL_DEPTH_TEXTURE_MODE:
+ case GL_DEPTH_STENCIL_TEXTURE_MODE:
+ case GL_TEXTURE_SRGB_DECODE_EXT:
+ case GL_TEXTURE_SWIZZLE_R:
+ case GL_TEXTURE_SWIZZLE_G:
+ case GL_TEXTURE_SWIZZLE_B:
+ case GL_TEXTURE_SWIZZLE_A:
+ case GL_TEXTURE_SWIZZLE_RGBA:
+ case GL_TEXTURE_BUFFER_SIZE:
+ case GL_TEXTURE_BUFFER_OFFSET:
+ /* changing any of these texture parameters means we must create
+ * new sampler views.
+ */
+ st_texture_release_all_sampler_views(st, stObj);
+ break;
+ default:
+ ; /* nothing */
+ }
+}
+
+
void
st_init_texture_functions(struct dd_function_table *functions)
{
functions->AllocTextureStorage = st_AllocTextureStorage;
functions->TextureView = st_TextureView;
functions->ClearTexSubImage = st_ClearTexSubImage;
+
+ functions->TexParameter = st_TexParameter;
}
st_texture_get_sampler_view(struct st_context *st,
struct st_texture_object *stObj)
{
- struct pipe_sampler_view *used = NULL, **free = NULL;
+ struct pipe_sampler_view **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)
+ /* check if the context matches */
+ 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;
*free = NULL;
}
- /* Add just any sampler view to be used as a template */
- if (used)
- pipe_sampler_view_reference(free, used);
+ assert(*free == NULL);
return free;
}
* those two headers we can trash the heap.
*/
FREE(stObj->sampler_views);
+ stObj->sampler_views = NULL;
+ stObj->num_sampler_views = 0;
}
* views and surfaces instead of pt->format.
*/
enum pipe_format surface_format;
+
+ /** The glsl version of the shader seen during the previous validation */
+ unsigned prev_glsl_version;
+ /** The value of the sampler's sRGBDecode state at the previous validation */
+ GLenum prev_sRGBDecode;
};