summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/mesa/Makefile.sources2
-rw-r--r--src/mesa/state_tracker/st_atom_pixeltransfer.c1
-rw-r--r--src/mesa/state_tracker/st_atom_texture.c367
-rw-r--r--src/mesa/state_tracker/st_cb_bitmap.c1
-rw-r--r--src/mesa/state_tracker/st_cb_drawpixels.c1
-rw-r--r--src/mesa/state_tracker/st_cb_eglimage.c2
-rw-r--r--src/mesa/state_tracker/st_cb_texture.c1
-rw-r--r--src/mesa/state_tracker/st_context.c1
-rw-r--r--src/mesa/state_tracker/st_sampler_view.c495
-rw-r--r--src/mesa/state_tracker/st_sampler_view.h83
-rw-r--r--src/mesa/state_tracker/st_texture.c93
-rw-r--r--src/mesa/state_tracker/st_texture.h34
-rw-r--r--src/mesa/state_tracker/st_vdpau.c1
13 files changed, 589 insertions, 493 deletions
diff --git a/src/mesa/Makefile.sources b/src/mesa/Makefile.sources
index fbe58610582..410a61a749e 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 26d8adec3a2..a2951a1d6be 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 45f1f6b02f1..c8ae62c2a7b 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,372 +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);
- 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);
-
- *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 a7d269b82e6..1e4becd10bd 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 b5f4227f6dd..7f92e02dc5e 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 7bea5653e46..c425154ba91 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 392b2a4b512..b448e56738f 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 b9dc0c67da3..174503f80ff 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 00000000000..9fe0bfe87d3
--- /dev/null
+++ b/src/mesa/state_tracker/st_sampler_view.c
@@ -0,0 +1,495 @@
+/*
+ * 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;
+
+ 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);
+ 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);
+
+ *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 00000000000..d4c38bccdce
--- /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 32e5b84a5af..a2c36ace461 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 9c9a05b5605..730843ae321 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);
diff --git a/src/mesa/state_tracker/st_vdpau.c b/src/mesa/state_tracker/st_vdpau.c
index 4f599dd1ef0..79120579ff5 100644
--- a/src/mesa/state_tracker/st_vdpau.c
+++ b/src/mesa/state_tracker/st_vdpau.c
@@ -43,6 +43,7 @@
#include "st_vdpau.h"
#include "st_context.h"
+#include "st_sampler_view.h"
#include "st_texture.h"
#include "st_format.h"
#include "st_cb_flush.h"