-#include "program/prog_parameter.h"
-#include "program/prog_statevars.h"
-#include "program/prog_uniform.h"
-#include "program/prog_instruction.h"
-
-
-static GLenum
-base_uniform_type(GLenum type)
-{
- switch (type) {
-#if 0 /* not needed, for now */
- case GL_BOOL:
- case GL_BOOL_VEC2:
- case GL_BOOL_VEC3:
- case GL_BOOL_VEC4:
- return GL_BOOL;
-#endif
- case GL_FLOAT:
- case GL_FLOAT_VEC2:
- case GL_FLOAT_VEC3:
- case GL_FLOAT_VEC4:
- return GL_FLOAT;
- case GL_UNSIGNED_INT:
- case GL_UNSIGNED_INT_VEC2:
- case GL_UNSIGNED_INT_VEC3:
- case GL_UNSIGNED_INT_VEC4:
- return GL_UNSIGNED_INT;
- case GL_INT:
- case GL_INT_VEC2:
- case GL_INT_VEC3:
- case GL_INT_VEC4:
- return GL_INT;
- default:
- _mesa_problem(NULL, "Invalid type in base_uniform_type()");
- return GL_FLOAT;
- }
-}
-
-static struct gl_builtin_uniform_element gl_DepthRange_elements[] = {
- {"near", {STATE_DEPTH_RANGE, 0, 0}, SWIZZLE_XXXX},
- {"far", {STATE_DEPTH_RANGE, 0, 0}, SWIZZLE_YYYY},
- {"diff", {STATE_DEPTH_RANGE, 0, 0}, SWIZZLE_ZZZZ},
-};
-
-static struct gl_builtin_uniform_element gl_ClipPlane_elements[] = {
- {NULL, {STATE_CLIPPLANE, 0, 0}, SWIZZLE_XYZW}
-};
-
-static struct gl_builtin_uniform_element gl_Point_elements[] = {
- {"size", {STATE_POINT_SIZE}, SWIZZLE_XXXX},
- {"sizeMin", {STATE_POINT_SIZE}, SWIZZLE_YYYY},
- {"sizeMax", {STATE_POINT_SIZE}, SWIZZLE_ZZZZ},
- {"fadeThresholdSize", {STATE_POINT_SIZE}, SWIZZLE_WWWW},
- {"distanceConstantAttenuation", {STATE_POINT_ATTENUATION}, SWIZZLE_XXXX},
- {"distanceLinearAttenuation", {STATE_POINT_ATTENUATION}, SWIZZLE_YYYY},
- {"distanceQuadraticAttenuation", {STATE_POINT_ATTENUATION}, SWIZZLE_ZZZZ},
-};
-
-static struct gl_builtin_uniform_element gl_FrontMaterial_elements[] = {
- {"emission", {STATE_MATERIAL, 0, STATE_EMISSION}, SWIZZLE_XYZW},
- {"ambient", {STATE_MATERIAL, 0, STATE_AMBIENT}, SWIZZLE_XYZW},
- {"diffuse", {STATE_MATERIAL, 0, STATE_DIFFUSE}, SWIZZLE_XYZW},
- {"specular", {STATE_MATERIAL, 0, STATE_SPECULAR}, SWIZZLE_XYZW},
- {"shininess", {STATE_MATERIAL, 0, STATE_SHININESS}, SWIZZLE_XXXX},
-};
-
-static struct gl_builtin_uniform_element gl_BackMaterial_elements[] = {
- {"emission", {STATE_MATERIAL, 1, STATE_EMISSION}, SWIZZLE_XYZW},
- {"ambient", {STATE_MATERIAL, 1, STATE_AMBIENT}, SWIZZLE_XYZW},
- {"diffuse", {STATE_MATERIAL, 1, STATE_DIFFUSE}, SWIZZLE_XYZW},
- {"specular", {STATE_MATERIAL, 1, STATE_SPECULAR}, SWIZZLE_XYZW},
- {"shininess", {STATE_MATERIAL, 1, STATE_SHININESS}, SWIZZLE_XXXX},
-};
-
-static struct gl_builtin_uniform_element gl_LightSource_elements[] = {
- {"ambient", {STATE_LIGHT, 0, STATE_AMBIENT}, SWIZZLE_XYZW},
- {"diffuse", {STATE_LIGHT, 0, STATE_DIFFUSE}, SWIZZLE_XYZW},
- {"specular", {STATE_LIGHT, 0, STATE_SPECULAR}, SWIZZLE_XYZW},
- {"position", {STATE_LIGHT, 0, STATE_POSITION}, SWIZZLE_XYZW},
- {"halfVector", {STATE_LIGHT, 0, STATE_HALF_VECTOR}, SWIZZLE_XYZW},
- {"spotDirection", {STATE_LIGHT, 0, STATE_SPOT_DIRECTION},
- MAKE_SWIZZLE4(SWIZZLE_X,
- SWIZZLE_Y,
- SWIZZLE_Z,
- SWIZZLE_Z)},
- {"spotCosCutoff", {STATE_LIGHT, 0, STATE_SPOT_DIRECTION}, SWIZZLE_WWWW},
- {"spotCutoff", {STATE_LIGHT, 0, STATE_SPOT_CUTOFF}, SWIZZLE_XXXX},
- {"spotExponent", {STATE_LIGHT, 0, STATE_ATTENUATION}, SWIZZLE_WWWW},
- {"constantAttenuation", {STATE_LIGHT, 0, STATE_ATTENUATION}, SWIZZLE_XXXX},
- {"linearAttenuation", {STATE_LIGHT, 0, STATE_ATTENUATION}, SWIZZLE_YYYY},
- {"quadraticAttenuation", {STATE_LIGHT, 0, STATE_ATTENUATION}, SWIZZLE_ZZZZ},
-};
-
-static struct gl_builtin_uniform_element gl_LightModel_elements[] = {
- {"ambient", {STATE_LIGHTMODEL_AMBIENT, 0}, SWIZZLE_XYZW},
-};
-
-static struct gl_builtin_uniform_element gl_FrontLightModelProduct_elements[] = {
- {"sceneColor", {STATE_LIGHTMODEL_SCENECOLOR, 0}, SWIZZLE_XYZW},
-};
-
-static struct gl_builtin_uniform_element gl_BackLightModelProduct_elements[] = {
- {"sceneColor", {STATE_LIGHTMODEL_SCENECOLOR, 1}, SWIZZLE_XYZW},
-};
-
-static struct gl_builtin_uniform_element gl_FrontLightProduct_elements[] = {
- {"ambient", {STATE_LIGHTPROD, 0, 0, STATE_AMBIENT}, SWIZZLE_XYZW},
- {"diffuse", {STATE_LIGHTPROD, 0, 0, STATE_DIFFUSE}, SWIZZLE_XYZW},
- {"specular", {STATE_LIGHTPROD, 0, 0, STATE_SPECULAR}, SWIZZLE_XYZW},
-};
-
-static struct gl_builtin_uniform_element gl_BackLightProduct_elements[] = {
- {"ambient", {STATE_LIGHTPROD, 0, 1, STATE_AMBIENT}, SWIZZLE_XYZW},
- {"diffuse", {STATE_LIGHTPROD, 0, 1, STATE_DIFFUSE}, SWIZZLE_XYZW},
- {"specular", {STATE_LIGHTPROD, 0, 1, STATE_SPECULAR}, SWIZZLE_XYZW},
-};
-
-static struct gl_builtin_uniform_element gl_TextureEnvColor_elements[] = {
- {NULL, {STATE_TEXENV_COLOR, 0}, SWIZZLE_XYZW},
-};
-
-static struct gl_builtin_uniform_element gl_EyePlaneS_elements[] = {
- {NULL, {STATE_TEXGEN, 0, STATE_TEXGEN_EYE_S}, SWIZZLE_XYZW},
-};
-
-static struct gl_builtin_uniform_element gl_EyePlaneT_elements[] = {
- {NULL, {STATE_TEXGEN, 0, STATE_TEXGEN_EYE_T}, SWIZZLE_XYZW},
-};
-
-static struct gl_builtin_uniform_element gl_EyePlaneR_elements[] = {
- {NULL, {STATE_TEXGEN, 0, STATE_TEXGEN_EYE_R}, SWIZZLE_XYZW},
-};
-
-static struct gl_builtin_uniform_element gl_EyePlaneQ_elements[] = {
- {NULL, {STATE_TEXGEN, 0, STATE_TEXGEN_EYE_Q}, SWIZZLE_XYZW},
-};
-
-static struct gl_builtin_uniform_element gl_ObjectPlaneS_elements[] = {
- {NULL, {STATE_TEXGEN, 0, STATE_TEXGEN_OBJECT_S}, SWIZZLE_XYZW},
-};
-
-static struct gl_builtin_uniform_element gl_ObjectPlaneT_elements[] = {
- {NULL, {STATE_TEXGEN, 0, STATE_TEXGEN_OBJECT_T}, SWIZZLE_XYZW},
-};
-
-static struct gl_builtin_uniform_element gl_ObjectPlaneR_elements[] = {
- {NULL, {STATE_TEXGEN, 0, STATE_TEXGEN_OBJECT_R}, SWIZZLE_XYZW},
-};
-
-static struct gl_builtin_uniform_element gl_ObjectPlaneQ_elements[] = {
- {NULL, {STATE_TEXGEN, 0, STATE_TEXGEN_OBJECT_Q}, SWIZZLE_XYZW},
-};
-
-static struct gl_builtin_uniform_element gl_Fog_elements[] = {
- {"color", {STATE_FOG_COLOR}, SWIZZLE_XYZW},
- {"density", {STATE_FOG_PARAMS}, SWIZZLE_XXXX},
- {"start", {STATE_FOG_PARAMS}, SWIZZLE_YYYY},
- {"end", {STATE_FOG_PARAMS}, SWIZZLE_ZZZZ},
- {"scale", {STATE_FOG_PARAMS}, SWIZZLE_WWWW},
-};
-
-static struct gl_builtin_uniform_element gl_NormalScale_elements[] = {
- {NULL, {STATE_NORMAL_SCALE}, SWIZZLE_XXXX},
-};
-
-#define MATRIX(name, statevar, modifier) \
- static struct gl_builtin_uniform_element name ## _elements[] = { \
- { NULL, { statevar, 0, 0, 0, modifier}, SWIZZLE_XYZW }, \
- { NULL, { statevar, 0, 1, 1, modifier}, SWIZZLE_XYZW }, \
- { NULL, { statevar, 0, 2, 2, modifier}, SWIZZLE_XYZW }, \
- { NULL, { statevar, 0, 3, 3, modifier}, SWIZZLE_XYZW }, \
- }
-
-MATRIX(gl_ModelViewMatrix,
- STATE_MODELVIEW_MATRIX, STATE_MATRIX_TRANSPOSE);
-MATRIX(gl_ModelViewMatrixInverse,
- STATE_MODELVIEW_MATRIX, STATE_MATRIX_INVTRANS);
-MATRIX(gl_ModelViewMatrixTranspose,
- STATE_MODELVIEW_MATRIX, 0);
-MATRIX(gl_ModelViewMatrixInverseTranspose,
- STATE_MODELVIEW_MATRIX, STATE_MATRIX_INVERSE);
-
-MATRIX(gl_ProjectionMatrix,
- STATE_PROJECTION_MATRIX, STATE_MATRIX_TRANSPOSE);
-MATRIX(gl_ProjectionMatrixInverse,
- STATE_PROJECTION_MATRIX, STATE_MATRIX_INVTRANS);
-MATRIX(gl_ProjectionMatrixTranspose,
- STATE_PROJECTION_MATRIX, 0);
-MATRIX(gl_ProjectionMatrixInverseTranspose,
- STATE_PROJECTION_MATRIX, STATE_MATRIX_INVERSE);
-
-MATRIX(gl_ModelViewProjectionMatrix,
- STATE_MVP_MATRIX, STATE_MATRIX_TRANSPOSE);
-MATRIX(gl_ModelViewProjectionMatrixInverse,
- STATE_MVP_MATRIX, STATE_MATRIX_INVTRANS);
-MATRIX(gl_ModelViewProjectionMatrixTranspose,
- STATE_MVP_MATRIX, 0);
-MATRIX(gl_ModelViewProjectionMatrixInverseTranspose,
- STATE_MVP_MATRIX, STATE_MATRIX_INVERSE);
-
-MATRIX(gl_TextureMatrix,
- STATE_TEXTURE_MATRIX, STATE_MATRIX_TRANSPOSE);
-MATRIX(gl_TextureMatrixInverse,
- STATE_TEXTURE_MATRIX, STATE_MATRIX_INVTRANS);
-MATRIX(gl_TextureMatrixTranspose,
- STATE_TEXTURE_MATRIX, 0);
-MATRIX(gl_TextureMatrixInverseTranspose,
- STATE_TEXTURE_MATRIX, STATE_MATRIX_INVERSE);
-
-static struct gl_builtin_uniform_element gl_NormalMatrix_elements[] = {
- { NULL, { STATE_MODELVIEW_MATRIX, 0, 0, 0, STATE_MATRIX_INVERSE},
- SWIZZLE_XYZW },
- { NULL, { STATE_MODELVIEW_MATRIX, 0, 1, 1, STATE_MATRIX_INVERSE},
- SWIZZLE_XYZW },
- { NULL, { STATE_MODELVIEW_MATRIX, 0, 2, 2, STATE_MATRIX_INVERSE},
- SWIZZLE_XYZW },
-};
-
-#undef MATRIX
-
-#define STATEVAR(name) {#name, name ## _elements, Elements(name ## _elements)}
-
-const struct gl_builtin_uniform_desc _mesa_builtin_uniform_desc[] = {
- STATEVAR(gl_DepthRange),
- STATEVAR(gl_ClipPlane),
- STATEVAR(gl_Point),
- STATEVAR(gl_FrontMaterial),
- STATEVAR(gl_BackMaterial),
- STATEVAR(gl_LightSource),
- STATEVAR(gl_LightModel),
- STATEVAR(gl_FrontLightModelProduct),
- STATEVAR(gl_BackLightModelProduct),
- STATEVAR(gl_FrontLightProduct),
- STATEVAR(gl_BackLightProduct),
- STATEVAR(gl_TextureEnvColor),
- STATEVAR(gl_EyePlaneS),
- STATEVAR(gl_EyePlaneT),
- STATEVAR(gl_EyePlaneR),
- STATEVAR(gl_EyePlaneQ),
- STATEVAR(gl_ObjectPlaneS),
- STATEVAR(gl_ObjectPlaneT),
- STATEVAR(gl_ObjectPlaneR),
- STATEVAR(gl_ObjectPlaneQ),
- STATEVAR(gl_Fog),
-
- STATEVAR(gl_ModelViewMatrix),
- STATEVAR(gl_ModelViewMatrixInverse),
- STATEVAR(gl_ModelViewMatrixTranspose),
- STATEVAR(gl_ModelViewMatrixInverseTranspose),
-
- STATEVAR(gl_ProjectionMatrix),
- STATEVAR(gl_ProjectionMatrixInverse),
- STATEVAR(gl_ProjectionMatrixTranspose),
- STATEVAR(gl_ProjectionMatrixInverseTranspose),
-
- STATEVAR(gl_ModelViewProjectionMatrix),
- STATEVAR(gl_ModelViewProjectionMatrixInverse),
- STATEVAR(gl_ModelViewProjectionMatrixTranspose),
- STATEVAR(gl_ModelViewProjectionMatrixInverseTranspose),
-
- STATEVAR(gl_TextureMatrix),
- STATEVAR(gl_TextureMatrixInverse),
- STATEVAR(gl_TextureMatrixTranspose),
- STATEVAR(gl_TextureMatrixInverseTranspose),
-
- STATEVAR(gl_NormalMatrix),
- STATEVAR(gl_NormalScale),
-
- {NULL, NULL, 0}
-};
-
-static GLboolean
-is_boolean_type(GLenum type)
-{
- switch (type) {
- case GL_BOOL:
- case GL_BOOL_VEC2:
- case GL_BOOL_VEC3:
- case GL_BOOL_VEC4:
- return GL_TRUE;
- default:
- return GL_FALSE;
- }
-}
-
-
-static GLboolean
-is_sampler_type(GLenum type)
-{
- switch (type) {
- case GL_SAMPLER_1D:
- case GL_SAMPLER_2D:
- case GL_SAMPLER_3D:
- case GL_SAMPLER_CUBE:
- case GL_SAMPLER_1D_SHADOW:
- case GL_SAMPLER_2D_SHADOW:
- case GL_SAMPLER_2D_RECT_ARB:
- case GL_SAMPLER_2D_RECT_SHADOW_ARB:
- case GL_SAMPLER_1D_ARRAY_EXT:
- case GL_SAMPLER_2D_ARRAY_EXT:
- case GL_SAMPLER_1D_ARRAY_SHADOW_EXT:
- case GL_SAMPLER_2D_ARRAY_SHADOW_EXT:
- return GL_TRUE;
- default:
- return GL_FALSE;
- }
-}
-
-
-static struct gl_program_parameter *
-get_uniform_parameter(const struct gl_shader_program *shProg, GLuint index)
-{
- const struct gl_program *prog = NULL;
- GLint progPos;
-
- progPos = shProg->Uniforms->Uniforms[index].VertPos;
- if (progPos >= 0) {
- prog = &shProg->VertexProgram->Base;
- }
- else {
- progPos = shProg->Uniforms->Uniforms[index].FragPos;
- if (progPos >= 0) {
- prog = &shProg->FragmentProgram->Base;
- } else {
- progPos = shProg->Uniforms->Uniforms[index].GeomPos;
- if (progPos >= 0) {
- prog = &shProg->GeometryProgram->Base;
- }
- }
- }
-
- if (!prog || progPos < 0)
- return NULL; /* should never happen */
-
- return &prog->Parameters->Parameters[progPos];
-}
-
-
-/**
- * Called by glGetActiveUniform().
- */
-static void
-_mesa_get_active_uniform(struct gl_context *ctx, GLuint program, GLuint index,
- GLsizei maxLength, GLsizei *length, GLint *size,
- GLenum *type, GLchar *nameOut)
-{
- const struct gl_shader_program *shProg;
- const struct gl_program *prog = NULL;
- const struct gl_program_parameter *param;
- GLint progPos;
-
- shProg = _mesa_lookup_shader_program_err(ctx, program, "glGetActiveUniform");
- if (!shProg)
- return;
-
- if (!shProg->Uniforms || index >= shProg->Uniforms->NumUniforms) {
- _mesa_error(ctx, GL_INVALID_VALUE, "glGetActiveUniform(index)");
- return;
- }
-
- progPos = shProg->Uniforms->Uniforms[index].VertPos;
- if (progPos >= 0) {
- prog = &shProg->VertexProgram->Base;
- }
- else {
- progPos = shProg->Uniforms->Uniforms[index].FragPos;
- if (progPos >= 0) {
- prog = &shProg->FragmentProgram->Base;
- } else {
- progPos = shProg->Uniforms->Uniforms[index].GeomPos;
- if (progPos >= 0) {
- prog = &shProg->GeometryProgram->Base;
- }
- }
- }
-
- if (!prog || progPos < 0)
- return; /* should never happen */
-
- ASSERT(progPos < prog->Parameters->NumParameters);
- param = &prog->Parameters->Parameters[progPos];
-
- if (nameOut) {
- _mesa_copy_string(nameOut, maxLength, length, param->Name);
- }
-
- if (size) {
- GLint typeSize = _mesa_sizeof_glsl_type(param->DataType);
- 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
- * 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;
- }
-}
-
-
-
-static void
-get_matrix_dims(GLenum type, GLint *rows, GLint *cols)
-{
- switch (type) {
- case GL_FLOAT_MAT2:
- *rows = *cols = 2;
- break;
- case GL_FLOAT_MAT2x3:
- *rows = 3;
- *cols = 2;
- break;
- case GL_FLOAT_MAT2x4:
- *rows = 4;
- *cols = 2;
- break;
- case GL_FLOAT_MAT3:
- *rows = 3;
- *cols = 3;
- break;
- case GL_FLOAT_MAT3x2:
- *rows = 2;
- *cols = 3;
- break;
- case GL_FLOAT_MAT3x4:
- *rows = 4;
- *cols = 3;
- break;
- case GL_FLOAT_MAT4:
- *rows = 4;
- *cols = 4;
- break;
- case GL_FLOAT_MAT4x2:
- *rows = 2;
- *cols = 4;
- break;
- case GL_FLOAT_MAT4x3:
- *rows = 3;
- *cols = 4;
- break;
- default:
- *rows = *cols = 0;
- }
-}
-
-
-/**
- * Determine the number of rows and columns occupied by a uniform
- * 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,
- GLint *rows, GLint *cols)
-{
- get_matrix_dims(p->DataType, rows, cols);
- if (*rows == 0 && *cols == 0) {
- /* not a matrix type, probably a float or vector */
- if (p->Size <= 4) {
- *rows = 1;
- *cols = p->Size;
- }
- else {
- *rows = (p->Size + 3) / 4;
- if (p->Size % 4 == 0)
- *cols = 4;
- else
- *cols = p->Size % 4;
- }
- }
-}
-
-
-/**
- * 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 void
-lookup_uniform_parameter(struct gl_context *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");
- 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;
- }
- else {
- progPos = shProg->Uniforms->Uniforms[location].FragPos;
- if (progPos >= 0) {
- prog = &shProg->FragmentProgram->Base;
- } else {
- progPos = shProg->Uniforms->Uniforms[location].GeomPos;
- if (progPos >= 0) {
- prog = &shProg->GeometryProgram->Base;
- }
- }
- }
- }
- }
-
- *progOut = prog;
- *paramPosOut = progPos;
-}
-
-
-/**
- * GLGL uniform arrays and structs require special handling.
- *
- * The GL_ARB_shader_objects spec says that if you use
- * glGetUniformLocation to get the location of an array, you CANNOT
- * access other elements of the array by adding an offset to the
- * returned location. For example, you must call
- * glGetUniformLocation("foo[16]") if you want to set the 16th element
- * of the array with glUniform().
- *
- * HOWEVER, some other OpenGL drivers allow accessing array elements
- * by adding an offset to the returned array location. And some apps
- * seem to depend on that behaviour.
- *
- * Mesa's gl_uniform_list doesn't directly support this since each
- * entry in the list describes one uniform variable, not one uniform
- * element. We could insert dummy entries in the list for each array
- * element after [0] but that causes complications elsewhere.
- *
- * We solve this problem by encoding two values in the location that's
- * returned by glGetUniformLocation():
- * a) index into gl_uniform_list::Uniforms[] for the uniform
- * b) an array/field offset (0 for simple types)
- *
- * These two values are encoded in the high and low halves of a GLint.
- * By putting the uniform number in the high part and the offset in the
- * low part, we can support the unofficial ability to index into arrays
- * by adding offsets to the location value.
- */
-static void
-merge_location_offset(GLint *location, GLint offset)
-{
- *location = (*location << 16) | offset;
-}
-
-
-/**
- * Separate the uniform location and parameter offset. See above.
- */
-static void
-split_location_offset(GLint *location, GLint *offset)
-{
- *offset = *location & 0xffff;
- *location = *location >> 16;
-}
-
-
-
-/**
- * Called via glGetUniformfv().
- */
-static void
-_mesa_get_uniformfv(struct gl_context *ctx, GLuint program, GLint location,
- GLfloat *params)
-{
- struct gl_program *prog;
- GLint paramPos;
- GLint offset;
-
- split_location_offset(&location, &offset);
-
- 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 glGetUniformiv().
- * \sa _mesa_get_uniformfv, only difference is a cast.
- */
-static void
-_mesa_get_uniformiv(struct gl_context *ctx, GLuint program, GLint location,
- GLint *params)
-{
- struct gl_program *prog;
- GLint paramPos;
- GLint offset;
-
- split_location_offset(&location, &offset);
-
- 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];
- }
- }
- }
-}
-
-
-/**
- * Called via glGetUniformuiv().
- * New in GL_EXT_gpu_shader4, OpenGL 3.0
- * \sa _mesa_get_uniformfv, only difference is a cast.
- */
-static void
-_mesa_get_uniformuiv(struct gl_context *ctx, GLuint program, GLint location,
- GLuint *params)
-{
- struct gl_program *prog;
- GLint paramPos;
- GLint offset;
-
- split_location_offset(&location, &offset);
-
- 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++] = (GLuint) prog->Parameters->ParameterValues[paramPos+i][j];
- }
- }
- }
-}
-
-
-/**
- * Called via glGetUniformLocation().
- *
- * The return value will encode two values, the uniform location and an
- * offset (used for arrays, structs).
- */
-GLint
-_mesa_get_uniform_location(struct gl_context *ctx, struct gl_shader_program *shProg,
- const GLchar *name)
-{
- GLint offset = 0, location = -1;
-
- if (shProg->LinkStatus == GL_FALSE) {
- _mesa_error(ctx, GL_INVALID_OPERATION, "glGetUniformfv(program)");
- return -1;
- }
-
- /* XXX we should return -1 if the uniform was declared, but not
- * actually used.
- */
-
- /* XXX we need to be able to parse uniform names for structs and arrays
- * such as:
- * mymatrix[1]
- * mystruct.field1
- */
-
- {
- /* handle 1-dimension arrays here... */
- char *c = strchr(name, '[');
- if (c) {
- /* truncate name at [ */
- const GLint len = c - name;
- GLchar *newName = malloc(len + 1);
- if (!newName)
- return -1; /* out of mem */
- memcpy(newName, name, len);
- newName[len] = 0;
-
- location = _mesa_lookup_uniform(shProg->Uniforms, newName);
- if (location >= 0) {
- const GLint element = atoi(c + 1);
- if (element > 0) {
- /* get type of the uniform array element */
- struct gl_program_parameter *p;
- p = get_uniform_parameter(shProg, location);
- if (p) {
- GLint rows, cols;
- get_matrix_dims(p->DataType, &rows, &cols);
- if (rows < 1)
- rows = 1;
- offset = element * rows;
- }
- }
- }
-
- free(newName);
- }
- }
-
- if (location < 0) {
- location = _mesa_lookup_uniform(shProg->Uniforms, name);
- }
-
- if (location >= 0) {
- merge_location_offset(&location, offset);
- }
-
- return location;
-}
-
-