mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-02-01 04:40:22 +01:00
Fix several bugs relating to uniforms and attributes in GLSL API
- fix sizes for GL_FLOAT_MAT2x3 and GL_FLOAT_MAT4x3 in sizeof_glsl_type - fix size returns in _mesa_get_active_attrib - fix out-of-bounds array access to vec_types in _mesa_get_active_attrib - fix queries of matrix uniforms in _mesa_get_uniformfv - fix _mesa_get_uniformfv to only return one base, even from an array - allow location == -1 in _mesa_uniform - validate types in _mesa_uniform - allow array overruns in _mesa_uniform
This commit is contained in:
parent
8349073561
commit
eeb03faadc
1 changed files with 73 additions and 11 deletions
|
|
@ -399,7 +399,7 @@ sizeof_glsl_type(GLenum type)
|
|||
case GL_FLOAT_MAT4:
|
||||
return 16;
|
||||
case GL_FLOAT_MAT2x3:
|
||||
return 6;
|
||||
return 8; /* 2 rows of 4, actually */
|
||||
case GL_FLOAT_MAT2x4:
|
||||
return 8;
|
||||
case GL_FLOAT_MAT3x2:
|
||||
|
|
@ -409,7 +409,7 @@ sizeof_glsl_type(GLenum type)
|
|||
case GL_FLOAT_MAT4x2:
|
||||
return 16; /* 4 rows of 4, actually */
|
||||
case GL_FLOAT_MAT4x3:
|
||||
return 12;
|
||||
return 16; /* 4 rows of 4, actually */
|
||||
default:
|
||||
return 0; /* error */
|
||||
}
|
||||
|
|
@ -680,9 +680,9 @@ _mesa_get_active_attrib(GLcontext *ctx, GLuint program, GLuint index,
|
|||
shProg->Attributes->Parameters[index].Name);
|
||||
sz = shProg->Attributes->Parameters[index].Size;
|
||||
if (size)
|
||||
*size = sz;
|
||||
if (type)
|
||||
*type = vec_types[sz]; /* XXX this is a temporary hack */
|
||||
*size = 1; /* attributes may not be arrays */
|
||||
if (type && sz > 0 && sz <= 4) /* XXX this is a temporary hack */
|
||||
*type = vec_types[sz - 1];
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -954,9 +954,40 @@ _mesa_get_uniformfv(GLcontext *ctx, GLuint program, GLint location,
|
|||
if (shProg) {
|
||||
GLint i;
|
||||
if (location >= 0 && location < shProg->Uniforms->NumParameters) {
|
||||
for (i = 0; i < shProg->Uniforms->Parameters[location].Size; i++) {
|
||||
params[i] = shProg->Uniforms->ParameterValues[location][i];
|
||||
GLuint uSize;
|
||||
GLenum uType;
|
||||
GLint rows = 0;
|
||||
uType = shProg->Uniforms->Parameters[location].DataType;
|
||||
uSize = sizeof_glsl_type(uType);
|
||||
/* Matrix types need special handling, because they span several
|
||||
* parameters, and may also not be fully packed.
|
||||
*/
|
||||
switch (shProg->Uniforms->Parameters[location].DataType) {
|
||||
case GL_FLOAT_MAT2:
|
||||
case GL_FLOAT_MAT3x2:
|
||||
case GL_FLOAT_MAT4x2:
|
||||
rows = 2;
|
||||
break;
|
||||
case GL_FLOAT_MAT2x3:
|
||||
case GL_FLOAT_MAT3:
|
||||
case GL_FLOAT_MAT4x3:
|
||||
rows = 3;
|
||||
break;
|
||||
case GL_FLOAT_MAT2x4:
|
||||
case GL_FLOAT_MAT3x4:
|
||||
case GL_FLOAT_MAT4:
|
||||
rows = 4;
|
||||
}
|
||||
if (rows != 0) {
|
||||
GLint r, c;
|
||||
for (c = 0, i = 0; c * 4 < uSize; c++)
|
||||
for (r = 0; r < rows; r++, i++)
|
||||
params[i] = shProg->Uniforms->ParameterValues[location + c][r];
|
||||
}
|
||||
else
|
||||
for (i = 0; i < uSize; i++) {
|
||||
params[i] = shProg->Uniforms->ParameterValues[location][i];
|
||||
}
|
||||
}
|
||||
else {
|
||||
_mesa_error(ctx, GL_INVALID_VALUE, "glGetUniformfv(location)");
|
||||
|
|
@ -1110,12 +1141,17 @@ _mesa_uniform(GLcontext *ctx, GLint location, GLsizei count,
|
|||
{
|
||||
struct gl_shader_program *shProg = ctx->Shader.CurrentProgram;
|
||||
GLint elems, i, k;
|
||||
GLenum uType;
|
||||
GLsizei maxCount;
|
||||
|
||||
if (!shProg || !shProg->LinkStatus) {
|
||||
_mesa_error(ctx, GL_INVALID_OPERATION, "glUniform(program not linked)");
|
||||
return;
|
||||
}
|
||||
|
||||
if (location == -1)
|
||||
return; /* The standard specifies this as a no-op */
|
||||
|
||||
if (location < 0 || location >= (GLint) shProg->Uniforms->NumParameters) {
|
||||
_mesa_error(ctx, GL_INVALID_VALUE, "glUniform(location)");
|
||||
return;
|
||||
|
|
@ -1123,10 +1159,11 @@ _mesa_uniform(GLcontext *ctx, GLint location, GLsizei count,
|
|||
|
||||
FLUSH_VERTICES(ctx, _NEW_PROGRAM);
|
||||
|
||||
uType = shProg->Uniforms->Parameters[location].Type;
|
||||
/*
|
||||
* If we're setting a sampler, we must use glUniformi1()!
|
||||
*/
|
||||
if (shProg->Uniforms->Parameters[location].Type == PROGRAM_SAMPLER) {
|
||||
if (uType == PROGRAM_SAMPLER) {
|
||||
GLint unit;
|
||||
if (type != GL_INT || count != 1) {
|
||||
_mesa_error(ctx, GL_INVALID_OPERATION,
|
||||
|
|
@ -1170,11 +1207,36 @@ _mesa_uniform(GLcontext *ctx, GLint location, GLsizei count,
|
|||
return;
|
||||
}
|
||||
|
||||
if (count * elems > shProg->Uniforms->Parameters[location].Size) {
|
||||
_mesa_error(ctx, GL_INVALID_OPERATION, "glUniform(count too large)");
|
||||
return;
|
||||
/* OpenGL requires types to match exactly, except that one can convert
|
||||
* float or int array to boolean array.
|
||||
*/
|
||||
switch (uType)
|
||||
{
|
||||
case GL_BOOL:
|
||||
case GL_BOOL_VEC2:
|
||||
case GL_BOOL_VEC3:
|
||||
case GL_BOOL_VEC4:
|
||||
if (elems != sizeof_glsl_type(shProg->Uniforms->Parameters[location].DataType)) {
|
||||
_mesa_error(ctx, GL_INVALID_OPERATION, "glUniform(count mismatch)");
|
||||
}
|
||||
break;
|
||||
case PROGRAM_SAMPLER:
|
||||
break;
|
||||
default:
|
||||
if (uType != type) {
|
||||
_mesa_error(ctx, GL_INVALID_OPERATION, "glUniform(type mismatch)");
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
/* XXX if this is a base type, then count must equal 1. However, we
|
||||
* don't have enough information from the compiler to distinguish a
|
||||
* base type from a 1-element array of that type. The standard allows
|
||||
* count to overrun an array, in which case the overflow is ignored.
|
||||
*/
|
||||
maxCount = shProg->Uniforms->Parameters[location].Size / elems;
|
||||
if (count > maxCount) count = maxCount;
|
||||
|
||||
for (k = 0; k < count; k++) {
|
||||
GLfloat *uniformVal = shProg->Uniforms->ParameterValues[location + k];
|
||||
if (type == GL_INT ||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue