FYI, the series breaks this test: piglit/bin/glsl-resource-not-bound Buffer -auto -fbo glsl-resource-not-bound: state_tracker/st_sampler_view.c:456: st_get_texture_sampler_view_from_stobj: Assertion `stObj->pt' failed. Aborted
Removing the assertion fixes it. Note that empty TBO slots are NULL. Marek On Sun, Oct 2, 2016 at 2:29 PM, Marek Olšák <mar...@gmail.com> wrote: > You also need this: > > diff --git a/src/mesa/state_tracker/st_vdpau.c > b/src/mesa/state_tracker/st_vdpau.c > index 4f599dd..cafbd3d 100644 > --- a/src/mesa/state_tracker/st_vdpau.c > +++ b/src/mesa/state_tracker/st_vdpau.c > @@ -44,6 +44,7 @@ > #include "st_vdpau.h" > #include "st_context.h" > #include "st_texture.h" > +#include "st_sampler_view.h" > #include "st_format.h" > #include "st_cb_flush.h" > > With that fixed, the series is: > > Reviewed-by: Marek Olšák <marek.ol...@amd.com> > > Marek > > > > On Sat, Oct 1, 2016 at 12:53 AM, Brian Paul <bri...@vmware.com> wrote: >> Previously, the sampler view code was scattered across several different >> files. >> >> Note, the previous REALLOC(), FREE() for st_texture_object::sampler_views >> are replaced by realloc(), free() to avoid conflicting macros in Mesa vs. >> Gallium. >> --- >> src/mesa/Makefile.sources | 2 + >> src/mesa/state_tracker/st_atom_pixeltransfer.c | 1 + >> src/mesa/state_tracker/st_atom_texture.c | 358 +----------------- >> src/mesa/state_tracker/st_cb_bitmap.c | 1 + >> src/mesa/state_tracker/st_cb_drawpixels.c | 1 + >> src/mesa/state_tracker/st_cb_eglimage.c | 2 + >> src/mesa/state_tracker/st_cb_texture.c | 1 + >> src/mesa/state_tracker/st_context.c | 1 + >> src/mesa/state_tracker/st_sampler_view.c | 487 >> +++++++++++++++++++++++++ >> src/mesa/state_tracker/st_sampler_view.h | 83 +++++ >> src/mesa/state_tracker/st_texture.c | 93 ----- >> src/mesa/state_tracker/st_texture.h | 34 -- >> 12 files changed, 580 insertions(+), 484 deletions(-) >> create mode 100644 src/mesa/state_tracker/st_sampler_view.c >> create mode 100644 src/mesa/state_tracker/st_sampler_view.h >> >> diff --git a/src/mesa/Makefile.sources b/src/mesa/Makefile.sources >> index fbe5861..410a61a 100644 >> --- a/src/mesa/Makefile.sources >> +++ b/src/mesa/Makefile.sources >> @@ -510,6 +510,8 @@ STATETRACKER_FILES = \ >> state_tracker/st_pbo.h \ >> state_tracker/st_program.c \ >> state_tracker/st_program.h \ >> + state_tracker/st_sampler_view.c \ >> + state_tracker/st_sampler_view.h \ >> state_tracker/st_scissor.c \ >> state_tracker/st_scissor.h \ >> state_tracker/st_texture.c \ >> diff --git a/src/mesa/state_tracker/st_atom_pixeltransfer.c >> b/src/mesa/state_tracker/st_atom_pixeltransfer.c >> index 26d8ade..a2951a1 100644 >> --- a/src/mesa/state_tracker/st_atom_pixeltransfer.c >> +++ b/src/mesa/state_tracker/st_atom_pixeltransfer.c >> @@ -30,6 +30,7 @@ >> */ >> >> #include "st_context.h" >> +#include "st_sampler_view.h" >> #include "st_texture.h" >> >> #include "util/u_inlines.h" >> diff --git a/src/mesa/state_tracker/st_atom_texture.c >> b/src/mesa/state_tracker/st_atom_texture.c >> index e5574bd..c8ae62c 100644 >> --- a/src/mesa/state_tracker/st_atom_texture.c >> +++ b/src/mesa/state_tracker/st_atom_texture.c >> @@ -42,6 +42,7 @@ >> >> #include "st_context.h" >> #include "st_atom.h" >> +#include "st_sampler_view.h" >> #include "st_texture.h" >> #include "st_format.h" >> #include "st_cb_texture.h" >> @@ -51,363 +52,6 @@ >> #include "cso_cache/cso_context.h" >> >> >> -/** >> - * Return swizzle1(swizzle2) >> - */ >> -static unsigned >> -swizzle_swizzle(unsigned swizzle1, unsigned swizzle2) >> -{ >> - unsigned i, swz[4]; >> - >> - if (swizzle1 == SWIZZLE_XYZW) { >> - /* identity swizzle, no change to swizzle2 */ >> - return swizzle2; >> - } >> - >> - for (i = 0; i < 4; i++) { >> - unsigned s = GET_SWZ(swizzle1, i); >> - switch (s) { >> - case SWIZZLE_X: >> - case SWIZZLE_Y: >> - case SWIZZLE_Z: >> - case SWIZZLE_W: >> - swz[i] = GET_SWZ(swizzle2, s); >> - break; >> - case SWIZZLE_ZERO: >> - swz[i] = SWIZZLE_ZERO; >> - break; >> - case SWIZZLE_ONE: >> - swz[i] = SWIZZLE_ONE; >> - break; >> - default: >> - assert(!"Bad swizzle term"); >> - swz[i] = SWIZZLE_X; >> - } >> - } >> - >> - return MAKE_SWIZZLE4(swz[0], swz[1], swz[2], swz[3]); >> -} >> - >> - >> -/** >> - * Given a user-specified texture base format, the actual gallium texture >> - * format and the current GL_DEPTH_MODE, return a texture swizzle. >> - * >> - * Consider the case where the user requests a GL_RGB internal texture >> - * format the driver actually uses an RGBA format. The A component should >> - * be ignored and sampling from the texture should always return (r,g,b,1). >> - * But if we rendered to the texture we might have written A values != 1. >> - * By sampling the texture with a ".xyz1" swizzle we'll get the expected >> A=1. >> - * This function computes the texture swizzle needed to get the expected >> - * values. >> - * >> - * In the case of depth textures, the GL_DEPTH_MODE state determines the >> - * texture swizzle. >> - * >> - * This result must be composed with the user-specified swizzle to get >> - * the final swizzle. >> - */ >> -static unsigned >> -compute_texture_format_swizzle(GLenum baseFormat, GLenum depthMode, >> - enum pipe_format actualFormat, >> - unsigned glsl_version) >> -{ >> - switch (baseFormat) { >> - case GL_RGBA: >> - return SWIZZLE_XYZW; >> - case GL_RGB: >> - if (util_format_has_alpha(actualFormat)) >> - return MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_Y, SWIZZLE_Z, SWIZZLE_ONE); >> - else >> - return SWIZZLE_XYZW; >> - case GL_RG: >> - if (util_format_get_nr_components(actualFormat) > 2) >> - return MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_Y, SWIZZLE_ZERO, >> SWIZZLE_ONE); >> - else >> - return SWIZZLE_XYZW; >> - case GL_RED: >> - if (util_format_get_nr_components(actualFormat) > 1) >> - return MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_ZERO, >> - SWIZZLE_ZERO, SWIZZLE_ONE); >> - else >> - return SWIZZLE_XYZW; >> - case GL_ALPHA: >> - if (util_format_get_nr_components(actualFormat) > 1) >> - return MAKE_SWIZZLE4(SWIZZLE_ZERO, SWIZZLE_ZERO, >> - SWIZZLE_ZERO, SWIZZLE_W); >> - else >> - return SWIZZLE_XYZW; >> - case GL_LUMINANCE: >> - if (util_format_get_nr_components(actualFormat) > 1) >> - return MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_X, SWIZZLE_X, SWIZZLE_ONE); >> - else >> - return SWIZZLE_XYZW; >> - case GL_LUMINANCE_ALPHA: >> - if (util_format_get_nr_components(actualFormat) > 2) >> - return MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_X, SWIZZLE_X, SWIZZLE_W); >> - else >> - return SWIZZLE_XYZW; >> - case GL_INTENSITY: >> - if (util_format_get_nr_components(actualFormat) > 1) >> - return SWIZZLE_XXXX; >> - else >> - return SWIZZLE_XYZW; >> - case GL_STENCIL_INDEX: >> - case GL_DEPTH_STENCIL: >> - case GL_DEPTH_COMPONENT: >> - /* Now examine the depth mode */ >> - switch (depthMode) { >> - case GL_LUMINANCE: >> - return MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_X, SWIZZLE_X, SWIZZLE_ONE); >> - case GL_INTENSITY: >> - return MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_X, SWIZZLE_X, SWIZZLE_X); >> - case GL_ALPHA: >> - /* The texture(sampler*Shadow) functions from GLSL 1.30 ignore >> - * the depth mode and return float, while older shadow* functions >> - * and ARB_fp instructions return vec4 according to the depth mode. >> - * >> - * The problem with the GLSL 1.30 functions is that GL_ALPHA forces >> - * them to return 0, breaking them completely. >> - * >> - * A proper fix would increase code complexity and that's not worth >> - * it for a rarely used feature such as the GL_ALPHA depth mode >> - * in GL3. Therefore, change GL_ALPHA to GL_INTENSITY for all >> - * shaders that use GLSL 1.30 or later. >> - * >> - * BTW, it's required that sampler views are updated when >> - * shaders change (check_sampler_swizzle takes care of that). >> - */ >> - if (glsl_version && glsl_version >= 130) >> - return SWIZZLE_XXXX; >> - else >> - return MAKE_SWIZZLE4(SWIZZLE_ZERO, SWIZZLE_ZERO, >> - SWIZZLE_ZERO, SWIZZLE_X); >> - case GL_RED: >> - return MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_ZERO, >> - SWIZZLE_ZERO, SWIZZLE_ONE); >> - default: >> - assert(!"Unexpected depthMode"); >> - return SWIZZLE_XYZW; >> - } >> - default: >> - assert(!"Unexpected baseFormat"); >> - return SWIZZLE_XYZW; >> - } >> -} >> - >> - >> -static unsigned >> -get_texture_format_swizzle(const struct st_context *st, >> - const struct st_texture_object *stObj, >> - unsigned glsl_version) >> -{ >> - GLenum baseFormat = _mesa_texture_base_format(&stObj->base); >> - unsigned tex_swizzle; >> - >> - if (baseFormat != GL_NONE) { >> - GLenum depth_mode = stObj->base.DepthMode; >> - /* In ES 3.0, DEPTH_TEXTURE_MODE is expected to be GL_RED for textures >> - * with depth component data specified with a sized internal format. >> - */ >> - if (_mesa_is_gles3(st->ctx) && >> - util_format_is_depth_or_stencil(stObj->pt->format)) { >> - const struct gl_texture_image *firstImage = >> - _mesa_base_tex_image(&stObj->base); >> - if (firstImage->InternalFormat != GL_DEPTH_COMPONENT && >> - firstImage->InternalFormat != GL_DEPTH_STENCIL && >> - firstImage->InternalFormat != GL_STENCIL_INDEX) >> - depth_mode = GL_RED; >> - } >> - tex_swizzle = compute_texture_format_swizzle(baseFormat, >> - depth_mode, >> - stObj->pt->format, >> - glsl_version); >> - } >> - else { >> - tex_swizzle = SWIZZLE_XYZW; >> - } >> - >> - /* Combine the texture format swizzle with user's swizzle */ >> - return swizzle_swizzle(stObj->base._Swizzle, tex_swizzle); >> -} >> - >> - >> -/** >> - * Return TRUE if the texture's sampler view swizzle is not equal to >> - * the texture's swizzle. >> - * >> - * \param stObj the st texture object, >> - */ >> -static boolean >> -check_sampler_swizzle(const struct st_context *st, >> - const struct st_texture_object *stObj, >> - const struct pipe_sampler_view *sv, unsigned >> glsl_version) >> -{ >> - unsigned swizzle = get_texture_format_swizzle(st, stObj, glsl_version); >> - >> - return ((sv->swizzle_r != GET_SWZ(swizzle, 0)) || >> - (sv->swizzle_g != GET_SWZ(swizzle, 1)) || >> - (sv->swizzle_b != GET_SWZ(swizzle, 2)) || >> - (sv->swizzle_a != GET_SWZ(swizzle, 3))); >> -} >> - >> - >> -static unsigned >> -last_level(const struct st_texture_object *stObj) >> -{ >> - unsigned ret = MIN2(stObj->base.MinLevel + stObj->base._MaxLevel, >> - stObj->pt->last_level); >> - if (stObj->base.Immutable) >> - ret = MIN2(ret, stObj->base.MinLevel + stObj->base.NumLevels - 1); >> - return ret; >> -} >> - >> -static unsigned >> -last_layer(const struct st_texture_object *stObj) >> -{ >> - if (stObj->base.Immutable && stObj->pt->array_size > 1) >> - return MIN2(stObj->base.MinLayer + stObj->base.NumLayers - 1, >> - stObj->pt->array_size - 1); >> - return stObj->pt->array_size - 1; >> -} >> - >> - >> -/** >> - * Determine the format for the texture sampler view. >> - */ >> -static enum pipe_format >> -get_sampler_view_format(struct st_context *st, >> - const struct st_texture_object *stObj, >> - const struct gl_sampler_object *samp) >> -{ >> - enum pipe_format format; >> - >> - if (stObj->base.Target == GL_TEXTURE_BUFFER) { >> - format = >> - st_mesa_format_to_pipe_format(st, stObj->base._BufferObjectFormat); >> - } >> - else { >> - format = >> - stObj->surface_based ? stObj->surface_format : stObj->pt->format; >> - >> - if (util_format_is_depth_and_stencil(format)) { >> - if (stObj->base.StencilSampling) { >> - format = util_format_stencil_only(format); >> - } >> - else { >> - GLenum baseFormat = _mesa_texture_base_format(&stObj->base); >> - if (baseFormat == GL_STENCIL_INDEX) { >> - format = util_format_stencil_only(format); >> - } >> - } >> - } >> - else { >> - /* If sRGB decoding is off, use the linear format */ >> - if (samp->sRGBDecode == GL_SKIP_DECODE_EXT) { >> - format = util_format_linear(format); >> - } >> - >> - /* Use R8_UNORM for video formats */ >> - switch (format) { >> - case PIPE_FORMAT_NV12: >> - case PIPE_FORMAT_IYUV: >> - format = PIPE_FORMAT_R8_UNORM; >> - break; >> - default: >> - break; >> - } >> - } >> - } >> - >> - return format; >> -} >> - >> - >> -static struct pipe_sampler_view * >> -st_create_texture_sampler_view_from_stobj(struct st_context *st, >> - struct st_texture_object *stObj, >> - enum pipe_format format, >> - unsigned glsl_version) >> -{ >> - struct pipe_sampler_view templ; >> - unsigned swizzle = get_texture_format_swizzle(st, stObj, glsl_version); >> - >> - u_sampler_view_default_template(&templ, >> - stObj->pt, >> - format); >> - >> - if (stObj->pt->target == PIPE_BUFFER) { >> - unsigned base, size; >> - >> - base = stObj->base.BufferOffset; >> - if (base >= stObj->pt->width0) >> - return NULL; >> - size = MIN2(stObj->pt->width0 - base, >> (unsigned)stObj->base.BufferSize); >> - if (!size) >> - return NULL; >> - >> - templ.u.buf.offset = base; >> - templ.u.buf.size = size; >> - } else { >> - templ.u.tex.first_level = stObj->base.MinLevel + >> stObj->base.BaseLevel; >> - templ.u.tex.last_level = last_level(stObj); >> - assert(templ.u.tex.first_level <= templ.u.tex.last_level); >> - templ.u.tex.first_layer = stObj->base.MinLayer; >> - templ.u.tex.last_layer = last_layer(stObj); >> - assert(templ.u.tex.first_layer <= templ.u.tex.last_layer); >> - templ.target = gl_target_to_pipe(stObj->base.Target); >> - } >> - >> - templ.swizzle_r = GET_SWZ(swizzle, 0); >> - templ.swizzle_g = GET_SWZ(swizzle, 1); >> - templ.swizzle_b = GET_SWZ(swizzle, 2); >> - templ.swizzle_a = GET_SWZ(swizzle, 3); >> - >> - return st->pipe->create_sampler_view(st->pipe, stObj->pt, &templ); >> -} >> - >> - >> -static struct pipe_sampler_view * >> -st_get_texture_sampler_view_from_stobj(struct st_context *st, >> - struct st_texture_object *stObj, >> - const struct gl_sampler_object *samp, >> - unsigned glsl_version) >> -{ >> - struct pipe_sampler_view **sv; >> - >> - if (!stObj || !stObj->pt) { >> - return NULL; >> - } >> - >> - sv = st_texture_get_sampler_view(st, stObj); >> - >> - if (*sv) { >> - /* 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); >> - 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); >> - >> - *sv = st_create_texture_sampler_view_from_stobj(st, stObj, >> - format, glsl_version); >> - >> - } >> - >> - return *sv; >> -} >> - >> - >> static GLboolean >> update_single_texture(struct st_context *st, >> struct pipe_sampler_view **sampler_view, >> diff --git a/src/mesa/state_tracker/st_cb_bitmap.c >> b/src/mesa/state_tracker/st_cb_bitmap.c >> index a7d269b..1e4becd 100644 >> --- a/src/mesa/state_tracker/st_cb_bitmap.c >> +++ b/src/mesa/state_tracker/st_cb_bitmap.c >> @@ -45,6 +45,7 @@ >> #include "st_draw.h" >> #include "st_program.h" >> #include "st_cb_bitmap.h" >> +#include "st_sampler_view.h" >> #include "st_texture.h" >> >> #include "pipe/p_context.h" >> diff --git a/src/mesa/state_tracker/st_cb_drawpixels.c >> b/src/mesa/state_tracker/st_cb_drawpixels.c >> index b5f4227..7f92e02 100644 >> --- a/src/mesa/state_tracker/st_cb_drawpixels.c >> +++ b/src/mesa/state_tracker/st_cb_drawpixels.c >> @@ -60,6 +60,7 @@ >> #include "st_draw.h" >> #include "st_format.h" >> #include "st_program.h" >> +#include "st_sampler_view.h" >> #include "st_scissor.h" >> #include "st_texture.h" >> >> diff --git a/src/mesa/state_tracker/st_cb_eglimage.c >> b/src/mesa/state_tracker/st_cb_eglimage.c >> index 7bea565..c425154 100644 >> --- a/src/mesa/state_tracker/st_cb_eglimage.c >> +++ b/src/mesa/state_tracker/st_cb_eglimage.c >> @@ -35,6 +35,8 @@ >> #include "st_texture.h" >> #include "st_format.h" >> #include "st_manager.h" >> +#include "st_sampler_view.h" >> + >> >> /** >> * Return the base format just like _mesa_base_fbo_format does. >> diff --git a/src/mesa/state_tracker/st_cb_texture.c >> b/src/mesa/state_tracker/st_cb_texture.c >> index daef5a4..177201d 100644 >> --- a/src/mesa/state_tracker/st_cb_texture.c >> +++ b/src/mesa/state_tracker/st_cb_texture.c >> @@ -58,6 +58,7 @@ >> #include "state_tracker/st_texture.h" >> #include "state_tracker/st_gen_mipmap.h" >> #include "state_tracker/st_atom.h" >> +#include "state_tracker/st_sampler_view.h" >> >> #include "pipe/p_context.h" >> #include "pipe/p_defines.h" >> diff --git a/src/mesa/state_tracker/st_context.c >> b/src/mesa/state_tracker/st_context.c >> index b9dc0c6..174503f 100644 >> --- a/src/mesa/state_tracker/st_context.c >> +++ b/src/mesa/state_tracker/st_context.c >> @@ -70,6 +70,7 @@ >> #include "st_gen_mipmap.h" >> #include "st_pbo.h" >> #include "st_program.h" >> +#include "st_sampler_view.h" >> #include "st_vdpau.h" >> #include "st_texture.h" >> #include "pipe/p_context.h" >> diff --git a/src/mesa/state_tracker/st_sampler_view.c >> b/src/mesa/state_tracker/st_sampler_view.c >> new file mode 100644 >> index 0000000..0b07f2a >> --- /dev/null >> +++ b/src/mesa/state_tracker/st_sampler_view.c >> @@ -0,0 +1,487 @@ >> +/* >> + * Copyright 2016 VMware, Inc. >> + * All Rights Reserved. >> + * >> + * Permission is hereby granted, free of charge, to any person obtaining a >> + * copy of this software and associated documentation files (the >> + * "Software"), to deal in the Software without restriction, including >> + * without limitation the rights to use, copy, modify, merge, publish, >> + * distribute, sub license, and/or sell copies of the Software, and to >> + * permit persons to whom the Software is furnished to do so, subject to >> + * the following conditions: >> + * >> + * The above copyright notice and this permission notice (including the >> + * next paragraph) shall be included in all copies or substantial portions >> + * of the Software. >> + * >> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS >> + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF >> + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. >> + * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR >> + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, >> + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE >> + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. >> + */ >> + >> +#include "pipe/p_context.h" >> +#include "util/u_format.h" >> +#include "util/u_inlines.h" >> + >> +#include "main/context.h" >> +#include "main/macros.h" >> +#include "main/mtypes.h" >> +#include "main/teximage.h" >> +#include "main/texobj.h" >> +#include "program/prog_instruction.h" >> + >> +#include "st_context.h" >> +#include "st_sampler_view.h" >> +#include "st_texture.h" >> +#include "st_format.h" >> +#include "st_cb_texture.h" >> + >> + >> +/** >> + * 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 **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) { >> + /* check if the context matches */ >> + if ((*sv)->context == st->pipe) { >> + return 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 */ >> + unsigned new_size = (stObj->num_sampler_views + 1) * >> + sizeof(struct pipe_sampler_view *); >> + stObj->sampler_views = realloc(stObj->sampler_views, new_size); >> + free = &stObj->sampler_views[stObj->num_sampler_views++]; >> + *free = NULL; >> + } >> + >> + assert(*free == NULL); >> + >> + return free; >> +} >> + >> + >> +/** >> + * For the given texture object, release any sampler views which belong >> + * to the calling context. >> + */ >> +void >> +st_texture_release_sampler_view(struct st_context *st, >> + struct st_texture_object *stObj) >> +{ >> + 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; >> + } >> + } >> +} >> + >> + >> +/** >> + * Release all sampler views attached to the given texture object, >> regardless >> + * of the context. >> + */ >> +void >> +st_texture_release_all_sampler_views(struct st_context *st, >> + struct st_texture_object *stObj) >> +{ >> + GLuint i; >> + >> + /* XXX This should use sampler_views[i]->pipe, not st->pipe */ >> + for (i = 0; i < stObj->num_sampler_views; ++i) >> + pipe_sampler_view_release(st->pipe, &stObj->sampler_views[i]); >> +} >> + >> + >> +void >> +st_texture_free_sampler_views(struct st_texture_object *stObj) >> +{ >> + free(stObj->sampler_views); >> + stObj->sampler_views = NULL; >> + stObj->num_sampler_views = 0; >> +} >> + >> + >> +/** >> + * Return swizzle1(swizzle2) >> + */ >> +static unsigned >> +swizzle_swizzle(unsigned swizzle1, unsigned swizzle2) >> +{ >> + unsigned i, swz[4]; >> + >> + if (swizzle1 == SWIZZLE_XYZW) { >> + /* identity swizzle, no change to swizzle2 */ >> + return swizzle2; >> + } >> + >> + for (i = 0; i < 4; i++) { >> + unsigned s = GET_SWZ(swizzle1, i); >> + switch (s) { >> + case SWIZZLE_X: >> + case SWIZZLE_Y: >> + case SWIZZLE_Z: >> + case SWIZZLE_W: >> + swz[i] = GET_SWZ(swizzle2, s); >> + break; >> + case SWIZZLE_ZERO: >> + swz[i] = SWIZZLE_ZERO; >> + break; >> + case SWIZZLE_ONE: >> + swz[i] = SWIZZLE_ONE; >> + break; >> + default: >> + assert(!"Bad swizzle term"); >> + swz[i] = SWIZZLE_X; >> + } >> + } >> + >> + return MAKE_SWIZZLE4(swz[0], swz[1], swz[2], swz[3]); >> +} >> + >> + >> +/** >> + * Given a user-specified texture base format, the actual gallium texture >> + * format and the current GL_DEPTH_MODE, return a texture swizzle. >> + * >> + * Consider the case where the user requests a GL_RGB internal texture >> + * format the driver actually uses an RGBA format. The A component should >> + * be ignored and sampling from the texture should always return (r,g,b,1). >> + * But if we rendered to the texture we might have written A values != 1. >> + * By sampling the texture with a ".xyz1" swizzle we'll get the expected >> A=1. >> + * This function computes the texture swizzle needed to get the expected >> + * values. >> + * >> + * In the case of depth textures, the GL_DEPTH_MODE state determines the >> + * texture swizzle. >> + * >> + * This result must be composed with the user-specified swizzle to get >> + * the final swizzle. >> + */ >> +static unsigned >> +compute_texture_format_swizzle(GLenum baseFormat, GLenum depthMode, >> + enum pipe_format actualFormat, >> + unsigned glsl_version) >> +{ >> + switch (baseFormat) { >> + case GL_RGBA: >> + return SWIZZLE_XYZW; >> + case GL_RGB: >> + if (util_format_has_alpha(actualFormat)) >> + return MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_Y, SWIZZLE_Z, SWIZZLE_ONE); >> + else >> + return SWIZZLE_XYZW; >> + case GL_RG: >> + if (util_format_get_nr_components(actualFormat) > 2) >> + return MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_Y, SWIZZLE_ZERO, >> SWIZZLE_ONE); >> + else >> + return SWIZZLE_XYZW; >> + case GL_RED: >> + if (util_format_get_nr_components(actualFormat) > 1) >> + return MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_ZERO, >> + SWIZZLE_ZERO, SWIZZLE_ONE); >> + else >> + return SWIZZLE_XYZW; >> + case GL_ALPHA: >> + if (util_format_get_nr_components(actualFormat) > 1) >> + return MAKE_SWIZZLE4(SWIZZLE_ZERO, SWIZZLE_ZERO, >> + SWIZZLE_ZERO, SWIZZLE_W); >> + else >> + return SWIZZLE_XYZW; >> + case GL_LUMINANCE: >> + if (util_format_get_nr_components(actualFormat) > 1) >> + return MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_X, SWIZZLE_X, SWIZZLE_ONE); >> + else >> + return SWIZZLE_XYZW; >> + case GL_LUMINANCE_ALPHA: >> + if (util_format_get_nr_components(actualFormat) > 2) >> + return MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_X, SWIZZLE_X, SWIZZLE_W); >> + else >> + return SWIZZLE_XYZW; >> + case GL_INTENSITY: >> + if (util_format_get_nr_components(actualFormat) > 1) >> + return SWIZZLE_XXXX; >> + else >> + return SWIZZLE_XYZW; >> + case GL_STENCIL_INDEX: >> + case GL_DEPTH_STENCIL: >> + case GL_DEPTH_COMPONENT: >> + /* Now examine the depth mode */ >> + switch (depthMode) { >> + case GL_LUMINANCE: >> + return MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_X, SWIZZLE_X, SWIZZLE_ONE); >> + case GL_INTENSITY: >> + return MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_X, SWIZZLE_X, SWIZZLE_X); >> + case GL_ALPHA: >> + /* The texture(sampler*Shadow) functions from GLSL 1.30 ignore >> + * the depth mode and return float, while older shadow* functions >> + * and ARB_fp instructions return vec4 according to the depth mode. >> + * >> + * The problem with the GLSL 1.30 functions is that GL_ALPHA forces >> + * them to return 0, breaking them completely. >> + * >> + * A proper fix would increase code complexity and that's not worth >> + * it for a rarely used feature such as the GL_ALPHA depth mode >> + * in GL3. Therefore, change GL_ALPHA to GL_INTENSITY for all >> + * shaders that use GLSL 1.30 or later. >> + * >> + * BTW, it's required that sampler views are updated when >> + * shaders change (check_sampler_swizzle takes care of that). >> + */ >> + if (glsl_version && glsl_version >= 130) >> + return SWIZZLE_XXXX; >> + else >> + return MAKE_SWIZZLE4(SWIZZLE_ZERO, SWIZZLE_ZERO, >> + SWIZZLE_ZERO, SWIZZLE_X); >> + case GL_RED: >> + return MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_ZERO, >> + SWIZZLE_ZERO, SWIZZLE_ONE); >> + default: >> + assert(!"Unexpected depthMode"); >> + return SWIZZLE_XYZW; >> + } >> + default: >> + assert(!"Unexpected baseFormat"); >> + return SWIZZLE_XYZW; >> + } >> +} >> + >> + >> +static unsigned >> +get_texture_format_swizzle(const struct st_context *st, >> + const struct st_texture_object *stObj, >> + unsigned glsl_version) >> +{ >> + GLenum baseFormat = _mesa_texture_base_format(&stObj->base); >> + unsigned tex_swizzle; >> + >> + if (baseFormat != GL_NONE) { >> + GLenum depth_mode = stObj->base.DepthMode; >> + /* In ES 3.0, DEPTH_TEXTURE_MODE is expected to be GL_RED for textures >> + * with depth component data specified with a sized internal format. >> + */ >> + if (_mesa_is_gles3(st->ctx) && >> + util_format_is_depth_or_stencil(stObj->pt->format)) { >> + const struct gl_texture_image *firstImage = >> + _mesa_base_tex_image(&stObj->base); >> + if (firstImage->InternalFormat != GL_DEPTH_COMPONENT && >> + firstImage->InternalFormat != GL_DEPTH_STENCIL && >> + firstImage->InternalFormat != GL_STENCIL_INDEX) >> + depth_mode = GL_RED; >> + } >> + tex_swizzle = compute_texture_format_swizzle(baseFormat, >> + depth_mode, >> + stObj->pt->format, >> + glsl_version); >> + } >> + else { >> + tex_swizzle = SWIZZLE_XYZW; >> + } >> + >> + /* Combine the texture format swizzle with user's swizzle */ >> + return swizzle_swizzle(stObj->base._Swizzle, tex_swizzle); >> +} >> + >> + >> +/** >> + * Return TRUE if the texture's sampler view swizzle is not equal to >> + * the texture's swizzle. >> + * >> + * \param stObj the st texture object, >> + */ >> +static boolean >> +check_sampler_swizzle(const struct st_context *st, >> + const struct st_texture_object *stObj, >> + const struct pipe_sampler_view *sv, unsigned >> glsl_version) >> +{ >> + unsigned swizzle = get_texture_format_swizzle(st, stObj, glsl_version); >> + >> + return ((sv->swizzle_r != GET_SWZ(swizzle, 0)) || >> + (sv->swizzle_g != GET_SWZ(swizzle, 1)) || >> + (sv->swizzle_b != GET_SWZ(swizzle, 2)) || >> + (sv->swizzle_a != GET_SWZ(swizzle, 3))); >> +} >> + >> + >> +static unsigned >> +last_level(const struct st_texture_object *stObj) >> +{ >> + unsigned ret = MIN2(stObj->base.MinLevel + stObj->base._MaxLevel, >> + stObj->pt->last_level); >> + if (stObj->base.Immutable) >> + ret = MIN2(ret, stObj->base.MinLevel + stObj->base.NumLevels - 1); >> + return ret; >> +} >> + >> + >> +static unsigned >> +last_layer(const struct st_texture_object *stObj) >> +{ >> + if (stObj->base.Immutable && stObj->pt->array_size > 1) >> + return MIN2(stObj->base.MinLayer + stObj->base.NumLayers - 1, >> + stObj->pt->array_size - 1); >> + return stObj->pt->array_size - 1; >> +} >> + >> + >> +/** >> + * Determine the format for the texture sampler view. >> + */ >> +static enum pipe_format >> +get_sampler_view_format(struct st_context *st, >> + const struct st_texture_object *stObj, >> + const struct gl_sampler_object *samp) >> +{ >> + enum pipe_format format; >> + >> + if (stObj->base.Target == GL_TEXTURE_BUFFER) { >> + format = >> + st_mesa_format_to_pipe_format(st, stObj->base._BufferObjectFormat); >> + } >> + else { >> + format = >> + stObj->surface_based ? stObj->surface_format : stObj->pt->format; >> + >> + if (util_format_is_depth_and_stencil(format)) { >> + if (stObj->base.StencilSampling) { >> + format = util_format_stencil_only(format); >> + } >> + else { >> + GLenum baseFormat = _mesa_texture_base_format(&stObj->base); >> + if (baseFormat == GL_STENCIL_INDEX) { >> + format = util_format_stencil_only(format); >> + } >> + } >> + } >> + else { >> + /* If sRGB decoding is off, use the linear format */ >> + if (samp->sRGBDecode == GL_SKIP_DECODE_EXT) { >> + format = util_format_linear(format); >> + } >> + >> + /* Use R8_UNORM for video formats */ >> + switch (format) { >> + case PIPE_FORMAT_NV12: >> + case PIPE_FORMAT_IYUV: >> + format = PIPE_FORMAT_R8_UNORM; >> + break; >> + default: >> + break; >> + } >> + } >> + } >> + >> + return format; >> +} >> + >> + >> +static struct pipe_sampler_view * >> +st_create_texture_sampler_view_from_stobj(struct st_context *st, >> + struct st_texture_object *stObj, >> + enum pipe_format format, >> + unsigned glsl_version) >> +{ >> + struct pipe_sampler_view templ; >> + unsigned swizzle = get_texture_format_swizzle(st, stObj, glsl_version); >> + >> + u_sampler_view_default_template(&templ, stObj->pt, format); >> + >> + if (stObj->pt->target == PIPE_BUFFER) { >> + unsigned base, size; >> + >> + base = stObj->base.BufferOffset; >> + if (base >= stObj->pt->width0) >> + return NULL; >> + size = MIN2(stObj->pt->width0 - base, >> (unsigned)stObj->base.BufferSize); >> + if (!size) >> + return NULL; >> + >> + templ.u.buf.offset = base; >> + templ.u.buf.size = size; >> + } else { >> + templ.u.tex.first_level = stObj->base.MinLevel + >> stObj->base.BaseLevel; >> + templ.u.tex.last_level = last_level(stObj); >> + assert(templ.u.tex.first_level <= templ.u.tex.last_level); >> + templ.u.tex.first_layer = stObj->base.MinLayer; >> + templ.u.tex.last_layer = last_layer(stObj); >> + assert(templ.u.tex.first_layer <= templ.u.tex.last_layer); >> + templ.target = gl_target_to_pipe(stObj->base.Target); >> + } >> + >> + templ.swizzle_r = GET_SWZ(swizzle, 0); >> + templ.swizzle_g = GET_SWZ(swizzle, 1); >> + templ.swizzle_b = GET_SWZ(swizzle, 2); >> + templ.swizzle_a = GET_SWZ(swizzle, 3); >> + >> + return st->pipe->create_sampler_view(st->pipe, stObj->pt, &templ); >> +} >> + >> + >> +struct pipe_sampler_view * >> +st_get_texture_sampler_view_from_stobj(struct st_context *st, >> + struct st_texture_object *stObj, >> + const struct gl_sampler_object *samp, >> + unsigned glsl_version) >> +{ >> + struct pipe_sampler_view **sv; >> + >> + assert(stObj->pt); >> + if (!stObj || !stObj->pt) { >> + return NULL; >> + } >> + >> + sv = st_texture_get_sampler_view(st, stObj); >> + >> + if (*sv) { >> + /* Debug check: make sure that the sampler view's parameters are >> + * what they're supposed to be. >> + */ >> + MAYBE_UNUSED 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); >> + 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); >> + >> + *sv = st_create_texture_sampler_view_from_stobj(st, stObj, >> + format, glsl_version); >> + >> + } >> + >> + return *sv; >> +} >> diff --git a/src/mesa/state_tracker/st_sampler_view.h >> b/src/mesa/state_tracker/st_sampler_view.h >> new file mode 100644 >> index 0000000..d4c38bc >> --- /dev/null >> +++ b/src/mesa/state_tracker/st_sampler_view.h >> @@ -0,0 +1,83 @@ >> +/* >> + * Copyright 2016 VMware, Inc. >> + * All Rights Reserved. >> + * >> + * Permission is hereby granted, free of charge, to any person obtaining a >> + * copy of this software and associated documentation files (the >> + * "Software"), to deal in the Software without restriction, including >> + * without limitation the rights to use, copy, modify, merge, publish, >> + * distribute, sub license, and/or sell copies of the Software, and to >> + * permit persons to whom the Software is furnished to do so, subject to >> + * the following conditions: >> + * >> + * The above copyright notice and this permission notice (including the >> + * next paragraph) shall be included in all copies or substantial portions >> + * of the Software. >> + * >> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS >> + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF >> + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. >> + * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR >> + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, >> + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE >> + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. >> + */ >> + >> + >> +#ifndef ST_SAMPLER_VIEW_H >> +#define ST_SAMPLER_VIEW_H >> + >> +#include "pipe/p_compiler.h" >> +#include "pipe/p_context.h" >> +#include "pipe/p_state.h" >> +#include "util/u_sampler.h" >> + >> +struct st_texture_object; >> + >> + >> +static inline struct pipe_sampler_view * >> +st_create_texture_sampler_view_format(struct pipe_context *pipe, >> + struct pipe_resource *texture, >> + enum pipe_format format) >> +{ >> + struct pipe_sampler_view templ; >> + >> + u_sampler_view_default_template(&templ, texture, format); >> + >> + return pipe->create_sampler_view(pipe, texture, &templ); >> +} >> + >> + >> +static inline struct pipe_sampler_view * >> +st_create_texture_sampler_view(struct pipe_context *pipe, >> + struct pipe_resource *texture) >> +{ >> + return st_create_texture_sampler_view_format(pipe, texture, >> + texture->format); >> +} >> + >> + >> +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_context *st, >> + struct st_texture_object *stObj); >> + >> +void >> +st_texture_free_sampler_views(struct st_texture_object *stObj); >> + >> + >> +struct pipe_sampler_view * >> +st_get_texture_sampler_view_from_stobj(struct st_context *st, >> + struct st_texture_object *stObj, >> + const struct gl_sampler_object *samp, >> + unsigned glsl_version); >> + >> + >> +#endif /* ST_SAMPLER_VIEW_H */ >> diff --git a/src/mesa/state_tracker/st_texture.c >> b/src/mesa/state_tracker/st_texture.c >> index 32e5b84..a2c36ac 100644 >> --- a/src/mesa/state_tracker/st_texture.c >> +++ b/src/mesa/state_tracker/st_texture.c >> @@ -418,96 +418,3 @@ st_create_color_map_texture(struct gl_context *ctx) >> texSize, texSize, 1, 1, 0, >> PIPE_BIND_SAMPLER_VIEW); >> 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 **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) { >> - /* check if the context matches */ >> - if ((*sv)->context == st->pipe) { >> - return 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; >> - } >> - >> - assert(*free == NULL); >> - >> - return free; >> -} >> - >> - >> -/** >> - * For the given texture object, release any sampler views which belong >> - * to the calling context. >> - */ >> -void >> -st_texture_release_sampler_view(struct st_context *st, >> - struct st_texture_object *stObj) >> -{ >> - 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; >> - } >> - } >> -} >> - >> - >> -/** >> - * Release all sampler views attached to the given texture object, >> regardless >> - * of the context. >> - */ >> -void >> -st_texture_release_all_sampler_views(struct st_context *st, >> - struct st_texture_object *stObj) >> -{ >> - GLuint i; >> - >> - /* XXX This should use sampler_views[i]->pipe, not st->pipe */ >> - for (i = 0; i < stObj->num_sampler_views; ++i) >> - pipe_sampler_view_release(st->pipe, &stObj->sampler_views[i]); >> -} >> - >> - >> -void >> -st_texture_free_sampler_views(struct st_texture_object *stObj) >> -{ >> - /* NOTE: >> - * We use FREE() here to match REALLOC() above. Both come from >> - * u_memory.h, not imports.h. If we mis-match MALLOC/FREE from >> - * those two headers we can trash the heap. >> - */ >> - FREE(stObj->sampler_views); >> - stObj->sampler_views = NULL; >> - stObj->num_sampler_views = 0; >> -} >> diff --git a/src/mesa/state_tracker/st_texture.h >> b/src/mesa/state_tracker/st_texture.h >> index 9c9a05b..730843a 100644 >> --- a/src/mesa/state_tracker/st_texture.h >> +++ b/src/mesa/state_tracker/st_texture.h >> @@ -155,26 +155,6 @@ st_get_stobj_resource(struct st_texture_object *stObj) >> } >> >> >> -static inline struct pipe_sampler_view * >> -st_create_texture_sampler_view_format(struct pipe_context *pipe, >> - struct pipe_resource *texture, >> - enum pipe_format format) >> -{ >> - struct pipe_sampler_view templ; >> - >> - u_sampler_view_default_template(&templ, texture, format); >> - >> - return pipe->create_sampler_view(pipe, texture, &templ); >> -} >> - >> -static inline struct pipe_sampler_view * >> -st_create_texture_sampler_view(struct pipe_context *pipe, >> - struct pipe_resource *texture) >> -{ >> - return st_create_texture_sampler_view_format(pipe, texture, >> - texture->format); >> -} >> - >> static inline struct st_texture_object * >> st_get_texture_object(struct gl_context *ctx, >> const struct gl_program *prog, >> @@ -261,20 +241,6 @@ 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_context *st, >> - struct st_texture_object *stObj); >> - >> -void >> -st_texture_free_sampler_views(struct st_texture_object *stObj); >> >> bool >> st_etc_fallback(struct st_context *st, struct gl_texture_image *texImage); >> -- >> 1.9.1 >> >> _______________________________________________ >> mesa-dev mailing list >> mesa-dev@lists.freedesktop.org >> https://lists.freedesktop.org/mailman/listinfo/mesa-dev _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/mesa-dev