#include "main/glheader.h"
#include "main/context.h"
#include "main/hash.h"
-#include "main/macros.h"
#include "shader/program.h"
#include "shader/prog_parameter.h"
-#include "shader/prog_print.h"
#include "shader/prog_statevars.h"
#include "shader/prog_uniform.h"
#include "shader/shader_api.h"
flags |= GLSL_DUMP;
if (_mesa_strstr(env, "log"))
flags |= GLSL_LOG;
+ if (_mesa_strstr(env, "nopvert"))
+ flags |= GLSL_NOP_VERT;
+ if (_mesa_strstr(env, "nopfrag"))
+ flags |= GLSL_NOP_FRAG;
if (_mesa_strstr(env, "nopt"))
flags |= GLSL_NO_OPT;
else if (_mesa_strstr(env, "opt"))
flags |= GLSL_OPT;
if (_mesa_strstr(env, "uniform"))
flags |= GLSL_UNIFORMS;
+ if (_mesa_strstr(env, "useprog"))
+ flags |= GLSL_USE_PROG;
}
return flags;
if (size) {
GLint typeSize = sizeof_glsl_type(param->DataType);
- if (param->Size > typeSize) {
+ if ((GLint) param->Size > typeSize) {
/* This is an array.
* Array elements are placed on vector[4] boundaries so they're
* a multiple of four floats. We round typeSize up to next multiple
FLUSH_VERTICES(ctx, _NEW_PROGRAM);
_slang_link(ctx, program, shProg);
+
+ /* debug code */
+ if (0) {
+ GLuint i;
+
+ _mesa_printf("Link %u shaders in program %u: %s\n",
+ shProg->NumShaders, shProg->Name,
+ shProg->LinkStatus ? "Success" : "Failed");
+
+ for (i = 0; i < shProg->NumShaders; i++) {
+ _mesa_printf(" shader %u, type 0x%x\n",
+ shProg->Shaders[i]->Name,
+ shProg->Shaders[i]->Type);
+ }
+ }
+}
+
+
+/**
+ * Print basic shader info (for debug).
+ */
+static void
+print_shader_info(const struct gl_shader_program *shProg)
+{
+ GLuint i;
+
+ _mesa_printf("Mesa: glUseProgram(%u)\n", shProg->Name);
+ for (i = 0; i < shProg->NumShaders; i++) {
+ const char *s;
+ switch (shProg->Shaders[i]->Type) {
+ case GL_VERTEX_SHADER:
+ s = "vertex";
+ break;
+ case GL_FRAGMENT_SHADER:
+ s = "fragment";
+ break;
+ case GL_GEOMETRY_SHADER:
+ s = "geometry";
+ break;
+ default:
+ s = "";
+ }
+ _mesa_printf(" %s shader %u, checksum %u\n", s,
+ shProg->Shaders[i]->Name,
+ shProg->Shaders[i]->SourceChecksum);
+ }
+ if (shProg->VertexProgram)
+ _mesa_printf(" vert prog %u\n", shProg->VertexProgram->Base.Id);
+ if (shProg->FragmentProgram)
+ _mesa_printf(" frag prog %u\n", shProg->FragmentProgram->Base.Id);
}
return;
}
- FLUSH_VERTICES(ctx, _NEW_PROGRAM | _NEW_PROGRAM_CONSTANTS);
-
if (program) {
shProg = _mesa_lookup_shader_program_err(ctx, program, "glUseProgram");
if (!shProg) {
}
/* debug code */
- if (0) {
- GLuint i;
- _mesa_printf("Use Shader %u\n", shProg->Name);
- for (i = 0; i < shProg->NumShaders; i++) {
- _mesa_printf(" shader %u, type 0x%x, checksum %u\n",
- shProg->Shaders[i]->Name,
- 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);
+ if (ctx->Shader.Flags & GLSL_USE_PROG) {
+ print_shader_info(shProg);
}
}
else {
shProg = NULL;
}
- _mesa_reference_shader_program(ctx, &ctx->Shader.CurrentProgram, shProg);
+ if (ctx->Shader.CurrentProgram != shProg) {
+ FLUSH_VERTICES(ctx, _NEW_PROGRAM | _NEW_PROGRAM_CONSTANTS);
+ _mesa_reference_shader_program(ctx, &ctx->Shader.CurrentProgram, shProg);
+ }
}
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);
}
}
}
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);
if (param->Type == PROGRAM_SAMPLER) {
/* This controls which texture unit which is used by a sampler */
+ 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];
_mesa_printf("Set program %p sampler %d '%s' to unit %u\n",
program, sampler, param->Name, texUnit);
#endif
- program->SamplerUnits[sampler] = texUnit;
+ if (program->SamplerUnits[sampler] != texUnit) {
+ program->SamplerUnits[sampler] = texUnit;
+ changed = GL_TRUE;
+ }
}
}
- _mesa_update_shader_textures_used(program);
-
- FLUSH_VERTICES(ctx, _NEW_TEXTURE);
+ if (changed) {
+ /* When a sampler's value changes it usually requires rewriting
+ * a GPU program's TEX instructions since there may not be a
+ * sampler->texture lookup table. We signal this with the
+ * ProgramStringNotify() callback.
+ */
+ FLUSH_VERTICES(ctx, _NEW_TEXTURE | _NEW_PROGRAM);
+ _mesa_update_shader_textures_used(program);
+ ctx->Driver.ProgramStringNotify(ctx, program->Target, 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) {
+ if ((GLint) param->Size > typeSize) {
/* an array */
/* we'll ignore extra data below */
}
else {
- /* non-array: count must be one */
- if (count != 1) {
+ /* non-array: count must be at most one; count == 0 is handled by the loop below */
+ if (count > 1) {
_mesa_error(ctx, GL_INVALID_OPERATION,
"glUniform(uniform is not an array)");
return;
GLboolean transpose, const GLfloat *values)
{
GLuint mat, row, col;
- GLuint dst = index + offset, src = 0;
+ GLuint src = 0;
+ const struct gl_program_parameter * param = &program->Parameters->Parameters[index];
+ const GLuint slots = (param->Size + 3) / 4;
+ const GLint typeSize = sizeof_glsl_type(param->DataType);
GLint nr, nc;
/* check that the number of rows, columns is correct */
- get_matrix_dims(program->Parameters->Parameters[index].DataType, &nr, &nc);
+ get_matrix_dims(param->DataType, &nr, &nc);
if (rows != nr || cols != nc) {
_mesa_error(ctx, GL_INVALID_OPERATION,
"glUniformMatrix(matrix size mismatch)");
return;
}
- if (index + offset > program->Parameters->Size) {
- /* out of bounds! */
- return;
+ if ((GLint) param->Size <= typeSize) {
+ /* non-array: count must be at most one; count == 0 is handled by the loop below */
+ if (count > 1) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glUniformMatrix(uniform is not an array)");
+ return;
+ }
}
/*
/* each matrix: */
for (col = 0; col < cols; col++) {
- GLfloat *v = program->Parameters->ParameterValues[dst];
+ GLfloat *v;
+ if (offset >= slots) {
+ /* Ignore writes beyond the end of (the used part of) an array */
+ return;
+ }
+ v = program->Parameters->ParameterValues[index + offset];
for (row = 0; row < rows; row++) {
if (transpose) {
v[row] = values[src + row * cols + col];
v[row] = values[src + col * rows + row];
}
}
- dst++;
+
+ offset++;
}
src += rows * cols; /* next matrix */