summaryrefslogtreecommitdiff
path: root/src/mesa/shader/shader_api.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/mesa/shader/shader_api.c')
-rw-r--r--src/mesa/shader/shader_api.c160
1 files changed, 127 insertions, 33 deletions
diff --git a/src/mesa/shader/shader_api.c b/src/mesa/shader/shader_api.c
index c36fc271a0..54a25dfaf0 100644
--- a/src/mesa/shader/shader_api.c
+++ b/src/mesa/shader/shader_api.c
@@ -1,6 +1,6 @@
/*
* Mesa 3-D graphics library
- * Version: 7.5
+ * Version: 7.6
*
* Copyright (C) 2004-2008 Brian Paul All Rights Reserved.
* Copyright (C) 2009 VMware, Inc. All Rights Reserved.
@@ -1431,6 +1431,9 @@ _mesa_shader_source(GLcontext *ctx, GLuint shader, const GLchar *source)
}
sh->Source = source;
sh->CompileStatus = GL_FALSE;
+#ifdef DEBUG
+ sh->SourceChecksum = _mesa_str_checksum(sh->Source);
+#endif
}
@@ -1488,7 +1491,7 @@ _mesa_use_program(GLcontext *ctx, GLuint program)
return;
}
- FLUSH_VERTICES(ctx, _NEW_PROGRAM);
+ FLUSH_VERTICES(ctx, _NEW_PROGRAM | _NEW_PROGRAM_CONSTANTS);
if (program) {
shProg = _mesa_lookup_shader_program_err(ctx, program, "glUseProgram");
@@ -1506,10 +1509,15 @@ _mesa_use_program(GLcontext *ctx, GLuint program)
GLuint i;
_mesa_printf("Use Shader %u\n", shProg->Name);
for (i = 0; i < shProg->NumShaders; i++) {
- _mesa_printf(" shader %u, type 0x%x\n",
+ _mesa_printf(" shader %u, type 0x%x, checksum %u\n",
shProg->Shaders[i]->Name,
- shProg->Shaders[i]->Type);
+ shProg->Shaders[i]->Type,
+ shProg->Shaders[i]->SourceChecksum);
}
+ if (shProg->VertexProgram)
+ printf(" vert prog %u\n", shProg->VertexProgram->Base.Id);
+ if (shProg->FragmentProgram)
+ printf(" frag prog %u\n", shProg->FragmentProgram->Base.Id);
}
}
else {
@@ -1545,10 +1553,11 @@ _mesa_update_shader_textures_used(struct gl_program *prog)
for (s = 0; s < MAX_SAMPLERS; s++) {
if (prog->SamplersUsed & (1 << s)) {
- GLuint u = prog->SamplerUnits[s];
- GLuint t = prog->SamplerTargets[s];
- assert(u < MAX_TEXTURE_IMAGE_UNITS);
- prog->TexturesUsed[u] |= (1 << t);
+ GLuint unit = prog->SamplerUnits[s];
+ GLuint tgt = prog->SamplerTargets[s];
+ assert(unit < MAX_TEXTURE_IMAGE_UNITS);
+ assert(tgt < NUM_TEXTURE_TARGETS);
+ prog->TexturesUsed[unit] |= (1 << tgt);
}
}
}
@@ -1603,10 +1612,8 @@ set_program_uniform(GLcontext *ctx, struct gl_program *program,
GLenum type, GLsizei count, GLint elems,
const void *values)
{
- struct gl_program_parameter *param =
+ const struct gl_program_parameter *param =
&program->Parameters->Parameters[index];
- const GLboolean isUniformBool = is_boolean_type(param->DataType);
- const GLboolean areIntValues = is_integer_type(type);
assert(offset >= 0);
assert(elems >= 1);
@@ -1627,17 +1634,10 @@ set_program_uniform(GLcontext *ctx, struct gl_program *program,
GLboolean changed = GL_FALSE;
GLint i;
- /* data type for setting samplers must be int */
- if (type != GL_INT) {
- _mesa_error(ctx, GL_INVALID_OPERATION,
- "glUniform(only glUniform1i can be used "
- "to set sampler uniforms)");
- return;
- }
+ /* this should have been caught by the compatible_types() check */
+ ASSERT(type == GL_INT);
- /* XXX arrays of samplers haven't been tested much, but it's not a
- * common thing...
- */
+ /* loop over number of samplers to change */
for (i = 0; i < count; i++) {
GLuint sampler =
(GLuint) program->Parameters->ParameterValues[index + offset + i][0];
@@ -1676,9 +1676,11 @@ set_program_uniform(GLcontext *ctx, struct gl_program *program,
}
else {
/* ordinary uniform variable */
- GLsizei k, i;
+ const GLboolean isUniformBool = is_boolean_type(param->DataType);
+ const GLboolean areIntValues = is_integer_type(type);
const GLint slots = (param->Size + 3) / 4;
const GLint typeSize = sizeof_glsl_type(param->DataType);
+ GLsizei k, i;
if (param->Size > typeSize) {
/* an array */
@@ -1805,7 +1807,7 @@ _mesa_uniform(GLcontext *ctx, GLint location, GLsizei count,
return;
}
- FLUSH_VERTICES(ctx, _NEW_PROGRAM | _NEW_PROGRAM_CONSTANTS);
+ FLUSH_VERTICES(ctx, _NEW_PROGRAM_CONSTANTS);
uniform = &shProg->Uniforms->Uniforms[location];
@@ -1945,7 +1947,7 @@ _mesa_uniform_matrix(GLcontext *ctx, GLint cols, GLint rows,
return;
}
- FLUSH_VERTICES(ctx, _NEW_PROGRAM | _NEW_PROGRAM_CONSTANTS);
+ FLUSH_VERTICES(ctx, _NEW_PROGRAM_CONSTANTS);
uniform = &shProg->Uniforms->Uniforms[location];
@@ -1973,19 +1975,74 @@ _mesa_uniform_matrix(GLcontext *ctx, GLint cols, GLint rows,
}
-static void
-_mesa_validate_program(GLcontext *ctx, GLuint program)
+/**
+ * Validate a program's samplers.
+ * Specifically, check that there aren't two samplers of different types
+ * pointing to the same texture unit.
+ * \return GL_TRUE if valid, GL_FALSE if invalid
+ */
+static GLboolean
+validate_samplers(GLcontext *ctx, const struct gl_program *prog, char *errMsg)
{
- struct gl_shader_program *shProg;
+ static const char *targetName[] = {
+ "TEXTURE_2D_ARRAY",
+ "TEXTURE_1D_ARRAY",
+ "TEXTURE_CUBE",
+ "TEXTURE_3D",
+ "TEXTURE_RECT",
+ "TEXTURE_2D",
+ "TEXTURE_1D",
+ };
+ GLint targetUsed[MAX_TEXTURE_IMAGE_UNITS];
+ GLbitfield samplersUsed = prog->SamplersUsed;
+ GLuint i;
- shProg = _mesa_lookup_shader_program_err(ctx, program, "glValidateProgram");
- if (!shProg) {
- return;
+ assert(Elements(targetName) == NUM_TEXTURE_TARGETS);
+
+ if (samplersUsed == 0x0)
+ return GL_TRUE;
+
+ for (i = 0; i < Elements(targetUsed); i++)
+ targetUsed[i] = -1;
+
+ /* walk over bits which are set in 'samplers' */
+ while (samplersUsed) {
+ GLuint unit;
+ gl_texture_index target;
+ GLint sampler = _mesa_ffs(samplersUsed) - 1;
+ assert(sampler >= 0);
+ assert(sampler < MAX_TEXTURE_IMAGE_UNITS);
+ unit = prog->SamplerUnits[sampler];
+ target = prog->SamplerTargets[sampler];
+ if (targetUsed[unit] != -1 && targetUsed[unit] != target) {
+ _mesa_snprintf(errMsg, 100,
+ "Texture unit %d is accessed both as %s and %s",
+ unit, targetName[targetUsed[unit]], targetName[target]);
+ return GL_FALSE;
+ }
+ targetUsed[unit] = target;
+ samplersUsed ^= (1 << sampler);
}
+ return GL_TRUE;
+}
+
+
+/**
+ * Do validation of the given shader program.
+ * \param errMsg returns error message if validation fails.
+ * \return GL_TRUE if valid, GL_FALSE if invalid (and set errMsg)
+ */
+GLboolean
+_mesa_validate_shader_program(GLcontext *ctx,
+ const struct gl_shader_program *shProg,
+ char *errMsg)
+{
+ const struct gl_vertex_program *vp = shProg->VertexProgram;
+ const struct gl_fragment_program *fp = shProg->FragmentProgram;
+
if (!shProg->LinkStatus) {
- shProg->Validated = GL_FALSE;
- return;
+ return GL_FALSE;
}
/* From the GL spec, a program is invalid if any of these are true:
@@ -2003,7 +2060,44 @@ _mesa_validate_program(GLcontext *ctx, GLuint program)
image units allowed.
*/
- shProg->Validated = GL_TRUE;
+
+ /*
+ * Check: any two active samplers in the current program object are of
+ * different types, but refer to the same texture image unit,
+ */
+ if (vp && !validate_samplers(ctx, &vp->Base, errMsg)) {
+ return GL_FALSE;
+ }
+ if (fp && !validate_samplers(ctx, &fp->Base, errMsg)) {
+ return GL_FALSE;
+ }
+
+ return GL_TRUE;
+}
+
+
+/**
+ * Called via glValidateProgram()
+ */
+static void
+_mesa_validate_program(GLcontext *ctx, GLuint program)
+{
+ struct gl_shader_program *shProg;
+ char errMsg[100];
+
+ shProg = _mesa_lookup_shader_program_err(ctx, program, "glValidateProgram");
+ if (!shProg) {
+ return;
+ }
+
+ shProg->Validated = _mesa_validate_shader_program(ctx, shProg, errMsg);
+ if (!shProg->Validated) {
+ /* update info log */
+ if (shProg->InfoLog) {
+ _mesa_free(shProg->InfoLog);
+ }
+ shProg->InfoLog = _mesa_strdup(errMsg);
+ }
}