-static unsigned
-swizzle_swizzle(unsigned swizzle1, unsigned swizzle2)
-{
- unsigned i, swz[4];
-
- 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)
-{
- 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:
- return SWIZZLE_XYZW;
- case GL_DEPTH_STENCIL:
- /* fall-through */
- 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:
- 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_texture_object *stObj)
-{
- GLenum baseFormat = _mesa_texture_base_format(&stObj->base);
- unsigned tex_swizzle;
-
- if (baseFormat != GL_NONE) {
- tex_swizzle = compute_texture_format_swizzle(baseFormat,
- stObj->base.DepthMode,
- stObj->pt->format);
- }
- 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_texture_object *stObj,
- struct pipe_sampler_view *sv)
-{
- unsigned swizzle = get_texture_format_swizzle(stObj);
-
- 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(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(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;
-}
-
-static struct pipe_sampler_view *
-st_create_texture_sampler_view_from_stobj(struct pipe_context *pipe,
- struct st_texture_object *stObj,
- enum pipe_format format)
-{
- struct pipe_sampler_view templ;
- unsigned swizzle = get_texture_format_swizzle(stObj);
-
- u_sampler_view_default_template(&templ,
- stObj->pt,
- format);
-
- if (stObj->pt->target == PIPE_BUFFER) {
- unsigned base, size;
- unsigned f, n;
- const struct util_format_description *desc
- = util_format_description(templ.format);
-
- base = stObj->base.BufferOffset;
- if (base >= stObj->pt->width0)
- return NULL;
- size = MIN2(stObj->pt->width0 - base, (unsigned)stObj->base.BufferSize);
-
- f = ((base * 8) / desc->block.bits) * desc->block.width;
- n = ((size * 8) / desc->block.bits) * desc->block.width;
- if (!n)
- return NULL;
- templ.u.buf.first_element = f;
- templ.u.buf.last_element = f + (n - 1);
- } 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);
- }
-
- if (swizzle != SWIZZLE_NOOP) {
- 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 pipe->create_sampler_view(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,
- enum pipe_format format)
-{
- struct pipe_sampler_view **sv;
- const struct st_texture_image *firstImage;
- if (!stObj || !stObj->pt) {
- return NULL;
- }
-
- sv = st_texture_get_sampler_view(st, stObj);
-
- if (util_format_is_depth_and_stencil(format)) {
- if (stObj->base.StencilSampling)
- format = util_format_stencil_only(format);
- else {
- firstImage = st_texture_image_const(_mesa_base_tex_image(&stObj->base));
- if (firstImage->base._BaseFormat == GL_STENCIL_INDEX)
- format = util_format_stencil_only(format);
- }
- }
-
- /* if sampler view has changed dereference it */
- if (*sv) {
- if (check_sampler_swizzle(stObj, *sv) ||
- (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);
- }
- }
-
- if (!*sv) {
- *sv = st_create_texture_sampler_view_from_stobj(st->pipe, stObj, 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
-update_single_texture(struct st_context *st,
- struct pipe_sampler_view **sampler_view,
- GLuint texUnit)