*/
static unsigned
compute_texture_format_swizzle(GLenum baseFormat, GLenum depthMode,
- enum pipe_format actualFormat)
+ enum pipe_format actualFormat,
+ unsigned glsl_version)
{
switch (baseFormat) {
case GL_RGBA:
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);
+ /* 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);
static unsigned
-get_texture_format_swizzle(const struct st_texture_object *stObj)
+get_texture_format_swizzle(const struct st_texture_object *stObj,
+ unsigned glsl_version)
{
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);
+ stObj->pt->format,
+ glsl_version);
}
else {
tex_swizzle = SWIZZLE_XYZW;
*/
static boolean
check_sampler_swizzle(const struct st_texture_object *stObj,
- struct pipe_sampler_view *sv)
+ struct pipe_sampler_view *sv, unsigned glsl_version)
{
- unsigned swizzle = get_texture_format_swizzle(stObj);
+ unsigned swizzle = get_texture_format_swizzle(stObj, glsl_version);
return ((sv->swizzle_r != GET_SWZ(swizzle, 0)) ||
(sv->swizzle_g != GET_SWZ(swizzle, 1)) ||
static struct pipe_sampler_view *
st_create_texture_sampler_view_from_stobj(struct pipe_context *pipe,
struct st_texture_object *stObj,
- const struct gl_sampler_object *samp,
- enum pipe_format format)
+ enum pipe_format format,
+ unsigned glsl_version)
{
struct pipe_sampler_view templ;
- unsigned swizzle = get_texture_format_swizzle(stObj);
+ unsigned swizzle = get_texture_format_swizzle(stObj, glsl_version);
u_sampler_view_default_template(&templ,
stObj->pt,
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;
+ f = (base / (desc->block.bits / 8)) * desc->block.width;
+ n = (size / (desc->block.bits / 8)) * desc->block.width;
if (!n)
return NULL;
templ.u.buf.first_element = f;
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,
- enum pipe_format format)
+ enum pipe_format format,
+ unsigned glsl_version)
{
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 (stObj->base.StencilSampling &&
- util_format_is_depth_and_stencil(format))
- format = util_format_stencil_only(format);
+ 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) ||
+ if (check_sampler_swizzle(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 ||
}
if (!*sv) {
- *sv = st_create_texture_sampler_view_from_stobj(st->pipe, stObj, samp, format);
+ *sv = st_create_texture_sampler_view_from_stobj(st->pipe, stObj,
+ format, glsl_version);
} else if ((*sv)->context != st->pipe) {
/* Recreate view in correct context, use existing view as template */
static GLboolean
update_single_texture(struct st_context *st,
struct pipe_sampler_view **sampler_view,
- GLuint texUnit)
+ GLuint texUnit, unsigned glsl_version)
{
struct gl_context *ctx = st->ctx;
const struct gl_sampler_object *samp;
}
}
- *sampler_view = st_get_texture_sampler_view_from_stobj(st, stObj, samp,
- view_format);
+ *sampler_view =
+ st_get_texture_sampler_view_from_stobj(st, stObj, view_format,
+ glsl_version);
return GL_TRUE;
}
static void
update_textures(struct st_context *st,
- unsigned shader_stage,
+ gl_shader_stage mesa_shader,
const struct gl_program *prog,
unsigned max_units,
struct pipe_sampler_view **sampler_views,
const GLuint old_max = *num_textures;
GLbitfield samplers_used = prog->SamplersUsed;
GLuint unit;
+ struct gl_shader_program *shader =
+ st->ctx->_Shader->CurrentProgram[mesa_shader];
+ unsigned glsl_version = shader ? shader->Version : 0;
+ unsigned shader_stage = st_shader_stage_to_ptarget(mesa_shader);
if (samplers_used == 0x0 && old_max == 0)
return;
const GLuint texUnit = prog->SamplerUnits[unit];
GLboolean retval;
- retval = update_single_texture(st, &sampler_view, texUnit);
+ retval = update_single_texture(st, &sampler_view, texUnit,
+ glsl_version);
if (retval == GL_FALSE)
continue;
if (ctx->Const.Program[MESA_SHADER_VERTEX].MaxTextureImageUnits > 0) {
update_textures(st,
- PIPE_SHADER_VERTEX,
+ MESA_SHADER_VERTEX,
&ctx->VertexProgram._Current->Base,
ctx->Const.Program[MESA_SHADER_VERTEX].MaxTextureImageUnits,
st->state.sampler_views[PIPE_SHADER_VERTEX],
const struct gl_context *ctx = st->ctx;
update_textures(st,
- PIPE_SHADER_FRAGMENT,
+ MESA_SHADER_FRAGMENT,
&ctx->FragmentProgram._Current->Base,
ctx->Const.Program[MESA_SHADER_FRAGMENT].MaxTextureImageUnits,
st->state.sampler_views[PIPE_SHADER_FRAGMENT],
if (ctx->GeometryProgram._Current) {
update_textures(st,
- PIPE_SHADER_GEOMETRY,
+ MESA_SHADER_GEOMETRY,
&ctx->GeometryProgram._Current->Base,
ctx->Const.Program[MESA_SHADER_GEOMETRY].MaxTextureImageUnits,
st->state.sampler_views[PIPE_SHADER_GEOMETRY],
}
+static void
+update_tessctrl_textures(struct st_context *st)
+{
+ const struct gl_context *ctx = st->ctx;
+
+ if (ctx->TessCtrlProgram._Current) {
+ update_textures(st,
+ MESA_SHADER_TESS_CTRL,
+ &ctx->TessCtrlProgram._Current->Base,
+ ctx->Const.Program[MESA_SHADER_TESS_CTRL].MaxTextureImageUnits,
+ st->state.sampler_views[PIPE_SHADER_TESS_CTRL],
+ &st->state.num_sampler_views[PIPE_SHADER_TESS_CTRL]);
+ }
+}
+
+
+static void
+update_tesseval_textures(struct st_context *st)
+{
+ const struct gl_context *ctx = st->ctx;
+
+ if (ctx->TessEvalProgram._Current) {
+ update_textures(st,
+ MESA_SHADER_TESS_EVAL,
+ &ctx->TessEvalProgram._Current->Base,
+ ctx->Const.Program[MESA_SHADER_TESS_EVAL].MaxTextureImageUnits,
+ st->state.sampler_views[PIPE_SHADER_TESS_EVAL],
+ &st->state.num_sampler_views[PIPE_SHADER_TESS_EVAL]);
+ }
+}
+
+
const struct st_tracked_state st_update_fragment_texture = {
"st_update_texture", /* name */
{ /* dirty */
_NEW_TEXTURE, /* mesa */
- ST_NEW_FRAGMENT_PROGRAM, /* st */
+ ST_NEW_FRAGMENT_PROGRAM | ST_NEW_SAMPLER_VIEWS, /* st */
},
update_fragment_textures /* update */
};
"st_update_vertex_texture", /* name */
{ /* dirty */
_NEW_TEXTURE, /* mesa */
- ST_NEW_VERTEX_PROGRAM, /* st */
+ ST_NEW_VERTEX_PROGRAM | ST_NEW_SAMPLER_VIEWS, /* st */
},
update_vertex_textures /* update */
};
"st_update_geometry_texture", /* name */
{ /* dirty */
_NEW_TEXTURE, /* mesa */
- ST_NEW_GEOMETRY_PROGRAM, /* st */
+ ST_NEW_GEOMETRY_PROGRAM | ST_NEW_SAMPLER_VIEWS, /* st */
},
update_geometry_textures /* update */
};
-
-static void
-finalize_textures(struct st_context *st)
-{
- struct gl_context *ctx = st->ctx;
- struct gl_fragment_program *fprog = ctx->FragmentProgram._Current;
- const GLboolean prev_missing_textures = st->missing_textures;
- GLuint su;
-
- st->missing_textures = GL_FALSE;
-
- for (su = 0; su < ctx->Const.MaxTextureCoordUnits; su++) {
- if (fprog->Base.SamplersUsed & (1 << su)) {
- const GLuint texUnit = fprog->Base.SamplerUnits[su];
- struct gl_texture_object *texObj
- = ctx->Texture.Unit[texUnit]._Current;
-
- if (texObj) {
- GLboolean retval;
-
- retval = st_finalize_texture(ctx, st->pipe, texObj);
- if (!retval) {
- /* out of mem */
- st->missing_textures = GL_TRUE;
- continue;
- }
- }
- }
- }
-
- if (prev_missing_textures != st->missing_textures)
- st->dirty.st |= ST_NEW_FRAGMENT_PROGRAM;
-}
+const struct st_tracked_state st_update_tessctrl_texture = {
+ "st_update_tessctrl_texture", /* name */
+ { /* dirty */
+ _NEW_TEXTURE, /* mesa */
+ ST_NEW_TESSCTRL_PROGRAM | ST_NEW_SAMPLER_VIEWS, /* st */
+ },
+ update_tessctrl_textures /* update */
+};
-const struct st_tracked_state st_finalize_textures = {
- "st_finalize_textures", /* name */
- { /* dirty */
- _NEW_TEXTURE, /* mesa */
- 0, /* st */
+const struct st_tracked_state st_update_tesseval_texture = {
+ "st_update_tesseval_texture", /* name */
+ { /* dirty */
+ _NEW_TEXTURE, /* mesa */
+ ST_NEW_TESSEVAL_PROGRAM | ST_NEW_SAMPLER_VIEWS, /* st */
},
- finalize_textures /* update */
+ update_tesseval_textures /* update */
};