diff options
Diffstat (limited to 'src/mesa/shader/shader_api.c')
-rw-r--r-- | src/mesa/shader/shader_api.c | 297 |
1 files changed, 216 insertions, 81 deletions
diff --git a/src/mesa/shader/shader_api.c b/src/mesa/shader/shader_api.c index b3d66c5babd..013e912e5d6 100644 --- a/src/mesa/shader/shader_api.c +++ b/src/mesa/shader/shader_api.c @@ -370,6 +370,31 @@ _mesa_lookup_shader_err(GLcontext *ctx, GLuint name, const char *caller) } +/** + * Return mask of GLSL_x flags by examining the MESA_GLSL env var. + */ +static GLbitfield +get_shader_flags(void) +{ + GLbitfield flags = 0x0; + const char *env = _mesa_getenv("MESA_GLSL"); + + if (env) { + if (_mesa_strstr(env, "dump")) + flags |= GLSL_DUMP; + if (_mesa_strstr(env, "log")) + flags |= GLSL_LOG; + 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; + } + + return flags; +} + /** * Initialize context's shader state. @@ -381,8 +406,9 @@ _mesa_init_shader_state(GLcontext * ctx) * are generated by the GLSL compiler. */ ctx->Shader.EmitHighLevelInstructions = GL_TRUE; - ctx->Shader.EmitCondCodes = GL_TRUE; /* XXX probably want GL_FALSE... */ + ctx->Shader.EmitCondCodes = GL_FALSE;/*GL_TRUE;*/ /* XXX probably want GL_FALSE... */ ctx->Shader.EmitComments = GL_FALSE; + ctx->Shader.Flags = get_shader_flags(); } @@ -866,6 +892,7 @@ _mesa_get_active_uniform(GLcontext *ctx, GLuint program, GLuint index, { const struct gl_shader_program *shProg; const struct gl_program *prog; + const struct gl_program_parameter *param; GLint progPos; shProg = _mesa_lookup_shader_program_err(ctx, program, "glGetActiveUniform"); @@ -891,14 +918,30 @@ _mesa_get_active_uniform(GLcontext *ctx, GLuint program, GLuint index, if (!prog || progPos < 0) return; /* should never happen */ - if (nameOut) - copy_string(nameOut, maxLength, length, - prog->Parameters->Parameters[progPos].Name); - if (size) - *size = prog->Parameters->Parameters[progPos].Size - / sizeof_glsl_type(prog->Parameters->Parameters[progPos].DataType); - if (type) - *type = prog->Parameters->Parameters[progPos].DataType; + ASSERT(progPos < prog->Parameters->NumParameters); + param = &prog->Parameters->Parameters[progPos]; + + if (nameOut) { + copy_string(nameOut, maxLength, length, param->Name); + } + + if (size) { + GLint typeSize = sizeof_glsl_type(param->DataType); + if (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 + * of four to get the right size below. + */ + typeSize = (typeSize + 3) & ~3; + } + /* Note that the returned size is in units of the <type>, not bytes */ + *size = param->Size / typeSize; + } + + if (type) { + *type = param->DataType; + } } @@ -1117,7 +1160,8 @@ get_matrix_dims(GLenum type, GLint *rows, GLint *cols) /** * Determine the number of rows and columns occupied by a uniform - * according to its datatype. + * according to its datatype. For non-matrix types (such as GL_FLOAT_VEC4), + * the number of rows = 1 and cols = number of elements in the vector. */ static void get_uniform_rows_cols(const struct gl_program_parameter *p, @@ -1126,33 +1170,45 @@ get_uniform_rows_cols(const struct gl_program_parameter *p, get_matrix_dims(p->DataType, rows, cols); if (*rows == 0 && *cols == 0) { /* not a matrix type, probably a float or vector */ - *rows = p->Size / 4 + 1; - if (p->Size % 4 == 0) - *cols = 4; - else - *cols = p->Size % 4; + if (p->Size <= 4) { + *rows = 1; + *cols = p->Size; + } + else { + *rows = p->Size / 4 + 1; + if (p->Size % 4 == 0) + *cols = 4; + else + *cols = p->Size % 4; + } } } -#define MAX_UNIFORM_ELEMENTS 16 - /** - * Helper for GetUniformfv(), GetUniformiv() - * Returns number of elements written to 'params' output. + * Helper for get_uniform[fi]v() functions. + * Given a shader program name and uniform location, return a pointer + * to the shader program and return the program parameter position. */ -static GLuint -get_uniformfv(GLcontext *ctx, GLuint program, GLint location, - GLfloat *params) +static void +lookup_uniform_parameter(GLcontext *ctx, GLuint program, GLint location, + struct gl_program **progOut, GLint *paramPosOut) { struct gl_shader_program *shProg = _mesa_lookup_shader_program_err(ctx, program, "glGetUniform[if]v"); - if (shProg) { - if (shProg->Uniforms && - location >= 0 && location < (GLint) shProg->Uniforms->NumUniforms) { - GLint progPos; - const struct gl_program *prog = NULL; + struct gl_program *prog = NULL; + GLint progPos = -1; + /* if shProg is NULL, we'll have already recorded an error */ + + if (shProg) { + if (!shProg->Uniforms || + location < 0 || + location >= (GLint) shProg->Uniforms->NumUniforms) { + _mesa_error(ctx, GL_INVALID_OPERATION, "glGetUniformfv(location)"); + } + else { + /* OK, find the gl_program and program parameter location */ progPos = shProg->Uniforms->Uniforms[location].VertPos; if (progPos >= 0) { prog = &shProg->VertexProgram->Base; @@ -1163,33 +1219,11 @@ get_uniformfv(GLcontext *ctx, GLuint program, GLint location, prog = &shProg->FragmentProgram->Base; } } - - ASSERT(prog); - if (prog) { - const struct gl_program_parameter *p = - &prog->Parameters->Parameters[progPos]; - GLint rows, cols, i, j, k; - - /* See uniformiv() below */ - assert(p->Size <= MAX_UNIFORM_ELEMENTS); - - get_uniform_rows_cols(p, &rows, &cols); - - k = 0; - for (i = 0; i < rows; i++) { - for (j = 0; j < cols; j++ ) { - params[k++] = prog->Parameters->ParameterValues[progPos+i][j]; - } - } - - return p->Size; - } - } - else { - _mesa_error(ctx, GL_INVALID_OPERATION, "glGetUniformfv(location)"); } } - return 0; + + *progOut = prog; + *paramPosOut = progPos; } @@ -1200,23 +1234,54 @@ static void _mesa_get_uniformfv(GLcontext *ctx, GLuint program, GLint location, GLfloat *params) { - (void) get_uniformfv(ctx, program, location, params); + struct gl_program *prog; + GLint paramPos; + + lookup_uniform_parameter(ctx, program, location, &prog, ¶mPos); + + if (prog) { + const struct gl_program_parameter *p = + &prog->Parameters->Parameters[paramPos]; + GLint rows, cols, i, j, k; + + get_uniform_rows_cols(p, &rows, &cols); + + k = 0; + for (i = 0; i < rows; i++) { + for (j = 0; j < cols; j++ ) { + params[k++] = prog->Parameters->ParameterValues[paramPos+i][j]; + } + } + } } /** * Called via ctx->Driver.GetUniformiv(). + * \sa _mesa_get_uniformfv, only difference is a cast. */ static void _mesa_get_uniformiv(GLcontext *ctx, GLuint program, GLint location, GLint *params) { - GLfloat fparams[MAX_UNIFORM_ELEMENTS]; - GLuint n = get_uniformfv(ctx, program, location, fparams); - GLuint i; - assert(n <= MAX_UNIFORM_ELEMENTS); - for (i = 0; i < n; i++) { - params[i] = (GLint) fparams[i]; + struct gl_program *prog; + GLint paramPos; + + lookup_uniform_parameter(ctx, program, location, &prog, ¶mPos); + + if (prog) { + const struct gl_program_parameter *p = + &prog->Parameters->Parameters[paramPos]; + GLint rows, cols, i, j, k; + + get_uniform_rows_cols(p, &rows, &cols); + + k = 0; + for (i = 0; i < rows; i++) { + for (j = 0; j < cols; j++ ) { + params[k++] = (GLint) prog->Parameters->ParameterValues[paramPos+i][j]; + } + } } } @@ -1357,7 +1422,10 @@ _mesa_compile_shader(GLcontext *ctx, GLuint shaderObj) if (!sh) return; - sh->CompileStatus = _slang_compile(ctx, sh); + /* this call will set the sh->CompileStatus field to indicate if + * compilation was successful. + */ + (void) _slang_compile(ctx, sh); } @@ -1527,7 +1595,7 @@ set_program_uniform(GLcontext *ctx, struct gl_program *program, return; } - if (index + offset > program->Parameters->Size) { + if (index + offset > (GLint) program->Parameters->Size) { /* out of bounds! */ return; } @@ -1535,27 +1603,36 @@ set_program_uniform(GLcontext *ctx, struct gl_program *program, if (param->Type == PROGRAM_SAMPLER) { /* This controls which texture unit which is used by a sampler */ GLuint texUnit, sampler; + GLint i; /* data type for setting samplers must be int */ - if (type != GL_INT || count != 1) { + if (type != GL_INT) { _mesa_error(ctx, GL_INVALID_OPERATION, "glUniform(only glUniform1i can be used " "to set sampler uniforms)"); return; } - sampler = (GLuint) program->Parameters->ParameterValues[index][0]; - texUnit = ((GLuint *) values)[0]; + /* XXX arrays of samplers haven't been tested much, but it's not a + * common thing... + */ + for (i = 0; i < count; i++) { + sampler = (GLuint) program->Parameters->ParameterValues[index + i][0]; + texUnit = ((GLuint *) values)[i]; + + /* check that the sampler (tex unit index) is legal */ + if (texUnit >= ctx->Const.MaxTextureImageUnits) { + _mesa_error(ctx, GL_INVALID_VALUE, + "glUniform1(invalid sampler/tex unit index)"); + return; + } - /* check that the sampler (tex unit index) is legal */ - if (texUnit >= ctx->Const.MaxTextureImageUnits) { - _mesa_error(ctx, GL_INVALID_VALUE, - "glUniform1(invalid sampler/tex unit index)"); - return; + /* This maps a sampler to a texture unit: */ + if (sampler < MAX_SAMPLERS) { + program->SamplerUnits[sampler] = texUnit; + } } - /* This maps a sampler to a texture unit: */ - program->SamplerUnits[sampler] = texUnit; _mesa_update_shader_textures_used(program); FLUSH_VERTICES(ctx, _NEW_TEXTURE); @@ -1563,19 +1640,31 @@ set_program_uniform(GLcontext *ctx, struct gl_program *program, else { /* ordinary uniform variable */ GLsizei k, i; - GLint slots = (param->Size + 3) / 4; + const GLint slots = (param->Size + 3) / 4; + const GLint typeSize = sizeof_glsl_type(param->DataType); - if (count * elems > (GLint) param->Size) { - _mesa_error(ctx, GL_INVALID_OPERATION, "glUniform(count too large)"); - return; + if (param->Size > typeSize) { + /* an array */ + /* we'll ignore extra data below */ + } + else { + /* non-array: count must be one */ + if (count != 1) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glUniform(uniform is not an array)"); + return; + } } - - if (count > slots) - count = slots; for (k = 0; k < count; k++) { - GLfloat *uniformVal = - program->Parameters->ParameterValues[index + offset + k]; + GLfloat *uniformVal; + + if (offset + k > slots) { + /* Extra array data is ignored */ + break; + } + + uniformVal = program->Parameters->ParameterValues[index + offset + k]; if (is_integer_type(type)) { const GLint *iValues = ((const GLint *) values) + k * elems; for (i = 0; i < elems; i++) { @@ -1592,7 +1681,7 @@ set_program_uniform(GLcontext *ctx, struct gl_program *program, /* if the uniform is bool-valued, convert to 1.0 or 0.0 */ if (is_boolean_type(param->DataType)) { for (i = 0; i < elems; i++) { - uniformVal[i] = uniformVal[i] ? 1.0 : 0.0; + uniformVal[i] = uniformVal[i] ? 1.0f : 0.0f; } } } @@ -1610,6 +1699,7 @@ _mesa_uniform(GLcontext *ctx, GLint location, GLsizei count, struct gl_shader_program *shProg = ctx->Shader.CurrentProgram; struct gl_uniform *uniform; GLint elems, offset; + GLenum basicType; if (!shProg || !shProg->LinkStatus) { _mesa_error(ctx, GL_INVALID_OPERATION, "glUniform(program not linked)"); @@ -1619,6 +1709,11 @@ _mesa_uniform(GLcontext *ctx, GLint location, GLsizei count, if (location == -1) return; /* The standard specifies this as a no-op */ + if (location < -1) { + _mesa_error(ctx, GL_INVALID_OPERATION, "glUniform(location)"); + return; + } + split_location_offset(&location, &offset); if (location < 0 || location >= (GLint) shProg->Uniforms->NumUniforms) { @@ -1633,19 +1728,35 @@ _mesa_uniform(GLcontext *ctx, GLint location, GLsizei count, switch (type) { case GL_FLOAT: + basicType = GL_FLOAT; + elems = 1; + break; case GL_INT: + basicType = GL_INT; elems = 1; break; case GL_FLOAT_VEC2: + basicType = GL_FLOAT; + elems = 2; + break; case GL_INT_VEC2: + basicType = GL_INT; elems = 2; break; case GL_FLOAT_VEC3: + basicType = GL_FLOAT; + elems = 3; + break; case GL_INT_VEC3: + basicType = GL_INT; elems = 3; break; case GL_FLOAT_VEC4: + basicType = GL_FLOAT; + elems = 4; + break; case GL_INT_VEC4: + basicType = GL_INT; elems = 4; break; default: @@ -1657,6 +1768,25 @@ _mesa_uniform(GLcontext *ctx, GLint location, GLsizei count, uniform = &shProg->Uniforms->Uniforms[location]; + if (ctx->Shader.Flags & GLSL_UNIFORMS) { + GLint i; + _mesa_printf("Mesa: set program %u uniform %s (loc %d) to: ", + shProg->Name, uniform->Name, location); + if (basicType == GL_INT) { + const GLint *v = (const GLint *) values; + for (i = 0; i < count * elems; i++) { + _mesa_printf("%d ", v[i]); + } + } + else { + const GLfloat *v = (const GLfloat *) values; + for (i = 0; i < count * elems; i++) { + _mesa_printf("%g ", v[i]); + } + } + _mesa_printf("\n"); + } + /* A uniform var may be used by both a vertex shader and a fragment * shader. We may need to update one or both shader's uniform here: */ @@ -1758,6 +1888,11 @@ _mesa_uniform_matrix(GLcontext *ctx, GLint cols, GLint rows, if (location == -1) return; /* The standard specifies this as a no-op */ + if (location < -1) { + _mesa_error(ctx, GL_INVALID_OPERATION, "glUniformMatrix(location)"); + return; + } + split_location_offset(&location, &offset); if (location < 0 || location >= (GLint) shProg->Uniforms->NumUniforms) { |