1d74efafdf7d9183b15d8f210c7a94f144662a6f
[mesa.git] / src / mesa / main / uniforms.c
1 /*
2 * Mesa 3-D graphics library
3 *
4 * Copyright (C) 2004-2008 Brian Paul All Rights Reserved.
5 * Copyright (C) 2009-2010 VMware, Inc. All Rights Reserved.
6 * Copyright © 2010 Intel Corporation
7 *
8 * Permission is hereby granted, free of charge, to any person obtaining a
9 * copy of this software and associated documentation files (the "Software"),
10 * to deal in the Software without restriction, including without limitation
11 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
12 * and/or sell copies of the Software, and to permit persons to whom the
13 * Software is furnished to do so, subject to the following conditions:
14 *
15 * The above copyright notice and this permission notice shall be included
16 * in all copies or substantial portions of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
21 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
22 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
23 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24 */
25
26 /**
27 * \file uniforms.c
28 * Functions related to GLSL uniform variables.
29 * \author Brian Paul
30 */
31
32 /**
33 * XXX things to do:
34 * 1. Check that the right error code is generated for all _mesa_error() calls.
35 * 2. Insert FLUSH_VERTICES calls in various places
36 */
37
38
39 #include "main/glheader.h"
40 #include "main/context.h"
41 #include "main/dispatch.h"
42 #include "main/mfeatures.h"
43 #include "main/mtypes.h"
44 #include "main/shaderapi.h"
45 #include "main/shaderobj.h"
46 #include "main/uniforms.h"
47 #include "program/prog_parameter.h"
48 #include "program/prog_statevars.h"
49 #include "program/prog_uniform.h"
50 #include "program/prog_instruction.h"
51
52
53 static GLenum
54 base_uniform_type(GLenum type)
55 {
56 switch (type) {
57 #if 0 /* not needed, for now */
58 case GL_BOOL:
59 case GL_BOOL_VEC2:
60 case GL_BOOL_VEC3:
61 case GL_BOOL_VEC4:
62 return GL_BOOL;
63 #endif
64 case GL_FLOAT:
65 case GL_FLOAT_VEC2:
66 case GL_FLOAT_VEC3:
67 case GL_FLOAT_VEC4:
68 return GL_FLOAT;
69 case GL_UNSIGNED_INT:
70 case GL_UNSIGNED_INT_VEC2:
71 case GL_UNSIGNED_INT_VEC3:
72 case GL_UNSIGNED_INT_VEC4:
73 return GL_UNSIGNED_INT;
74 case GL_INT:
75 case GL_INT_VEC2:
76 case GL_INT_VEC3:
77 case GL_INT_VEC4:
78 return GL_INT;
79 default:
80 _mesa_problem(NULL, "Invalid type in base_uniform_type()");
81 return GL_FLOAT;
82 }
83 }
84
85 static struct gl_builtin_uniform_element gl_DepthRange_elements[] = {
86 {"near", {STATE_DEPTH_RANGE, 0, 0}, SWIZZLE_XXXX},
87 {"far", {STATE_DEPTH_RANGE, 0, 0}, SWIZZLE_YYYY},
88 {"diff", {STATE_DEPTH_RANGE, 0, 0}, SWIZZLE_ZZZZ},
89 };
90
91 static struct gl_builtin_uniform_element gl_ClipPlane_elements[] = {
92 {NULL, {STATE_CLIPPLANE, 0, 0}, SWIZZLE_XYZW}
93 };
94
95 static struct gl_builtin_uniform_element gl_Point_elements[] = {
96 {"size", {STATE_POINT_SIZE}, SWIZZLE_XXXX},
97 {"sizeMin", {STATE_POINT_SIZE}, SWIZZLE_YYYY},
98 {"sizeMax", {STATE_POINT_SIZE}, SWIZZLE_ZZZZ},
99 {"fadeThresholdSize", {STATE_POINT_SIZE}, SWIZZLE_WWWW},
100 {"distanceConstantAttenuation", {STATE_POINT_ATTENUATION}, SWIZZLE_XXXX},
101 {"distanceLinearAttenuation", {STATE_POINT_ATTENUATION}, SWIZZLE_YYYY},
102 {"distanceQuadraticAttenuation", {STATE_POINT_ATTENUATION}, SWIZZLE_ZZZZ},
103 };
104
105 static struct gl_builtin_uniform_element gl_FrontMaterial_elements[] = {
106 {"emission", {STATE_MATERIAL, 0, STATE_EMISSION}, SWIZZLE_XYZW},
107 {"ambient", {STATE_MATERIAL, 0, STATE_AMBIENT}, SWIZZLE_XYZW},
108 {"diffuse", {STATE_MATERIAL, 0, STATE_DIFFUSE}, SWIZZLE_XYZW},
109 {"specular", {STATE_MATERIAL, 0, STATE_SPECULAR}, SWIZZLE_XYZW},
110 {"shininess", {STATE_MATERIAL, 0, STATE_SHININESS}, SWIZZLE_XXXX},
111 };
112
113 static struct gl_builtin_uniform_element gl_BackMaterial_elements[] = {
114 {"emission", {STATE_MATERIAL, 1, STATE_EMISSION}, SWIZZLE_XYZW},
115 {"ambient", {STATE_MATERIAL, 1, STATE_AMBIENT}, SWIZZLE_XYZW},
116 {"diffuse", {STATE_MATERIAL, 1, STATE_DIFFUSE}, SWIZZLE_XYZW},
117 {"specular", {STATE_MATERIAL, 1, STATE_SPECULAR}, SWIZZLE_XYZW},
118 {"shininess", {STATE_MATERIAL, 1, STATE_SHININESS}, SWIZZLE_XXXX},
119 };
120
121 static struct gl_builtin_uniform_element gl_LightSource_elements[] = {
122 {"ambient", {STATE_LIGHT, 0, STATE_AMBIENT}, SWIZZLE_XYZW},
123 {"diffuse", {STATE_LIGHT, 0, STATE_DIFFUSE}, SWIZZLE_XYZW},
124 {"specular", {STATE_LIGHT, 0, STATE_SPECULAR}, SWIZZLE_XYZW},
125 {"position", {STATE_LIGHT, 0, STATE_POSITION}, SWIZZLE_XYZW},
126 {"halfVector", {STATE_LIGHT, 0, STATE_HALF_VECTOR}, SWIZZLE_XYZW},
127 {"spotDirection", {STATE_LIGHT, 0, STATE_SPOT_DIRECTION},
128 MAKE_SWIZZLE4(SWIZZLE_X,
129 SWIZZLE_Y,
130 SWIZZLE_Z,
131 SWIZZLE_Z)},
132 {"spotCosCutoff", {STATE_LIGHT, 0, STATE_SPOT_DIRECTION}, SWIZZLE_WWWW},
133 {"spotCutoff", {STATE_LIGHT, 0, STATE_SPOT_CUTOFF}, SWIZZLE_XXXX},
134 {"spotExponent", {STATE_LIGHT, 0, STATE_ATTENUATION}, SWIZZLE_WWWW},
135 {"constantAttenuation", {STATE_LIGHT, 0, STATE_ATTENUATION}, SWIZZLE_XXXX},
136 {"linearAttenuation", {STATE_LIGHT, 0, STATE_ATTENUATION}, SWIZZLE_YYYY},
137 {"quadraticAttenuation", {STATE_LIGHT, 0, STATE_ATTENUATION}, SWIZZLE_ZZZZ},
138 };
139
140 static struct gl_builtin_uniform_element gl_LightModel_elements[] = {
141 {"ambient", {STATE_LIGHTMODEL_AMBIENT, 0}, SWIZZLE_XYZW},
142 };
143
144 static struct gl_builtin_uniform_element gl_FrontLightModelProduct_elements[] = {
145 {"sceneColor", {STATE_LIGHTMODEL_SCENECOLOR, 0}, SWIZZLE_XYZW},
146 };
147
148 static struct gl_builtin_uniform_element gl_BackLightModelProduct_elements[] = {
149 {"sceneColor", {STATE_LIGHTMODEL_SCENECOLOR, 1}, SWIZZLE_XYZW},
150 };
151
152 static struct gl_builtin_uniform_element gl_FrontLightProduct_elements[] = {
153 {"ambient", {STATE_LIGHTPROD, 0, 0, STATE_AMBIENT}, SWIZZLE_XYZW},
154 {"diffuse", {STATE_LIGHTPROD, 0, 0, STATE_DIFFUSE}, SWIZZLE_XYZW},
155 {"specular", {STATE_LIGHTPROD, 0, 0, STATE_SPECULAR}, SWIZZLE_XYZW},
156 };
157
158 static struct gl_builtin_uniform_element gl_BackLightProduct_elements[] = {
159 {"ambient", {STATE_LIGHTPROD, 0, 1, STATE_AMBIENT}, SWIZZLE_XYZW},
160 {"diffuse", {STATE_LIGHTPROD, 0, 1, STATE_DIFFUSE}, SWIZZLE_XYZW},
161 {"specular", {STATE_LIGHTPROD, 0, 1, STATE_SPECULAR}, SWIZZLE_XYZW},
162 };
163
164 static struct gl_builtin_uniform_element gl_TextureEnvColor_elements[] = {
165 {NULL, {STATE_TEXENV_COLOR, 0}, SWIZZLE_XYZW},
166 };
167
168 static struct gl_builtin_uniform_element gl_EyePlaneS_elements[] = {
169 {NULL, {STATE_TEXGEN, 0, STATE_TEXGEN_EYE_S}, SWIZZLE_XYZW},
170 };
171
172 static struct gl_builtin_uniform_element gl_EyePlaneT_elements[] = {
173 {NULL, {STATE_TEXGEN, 0, STATE_TEXGEN_EYE_T}, SWIZZLE_XYZW},
174 };
175
176 static struct gl_builtin_uniform_element gl_EyePlaneR_elements[] = {
177 {NULL, {STATE_TEXGEN, 0, STATE_TEXGEN_EYE_R}, SWIZZLE_XYZW},
178 };
179
180 static struct gl_builtin_uniform_element gl_EyePlaneQ_elements[] = {
181 {NULL, {STATE_TEXGEN, 0, STATE_TEXGEN_EYE_Q}, SWIZZLE_XYZW},
182 };
183
184 static struct gl_builtin_uniform_element gl_ObjectPlaneS_elements[] = {
185 {NULL, {STATE_TEXGEN, 0, STATE_TEXGEN_OBJECT_S}, SWIZZLE_XYZW},
186 };
187
188 static struct gl_builtin_uniform_element gl_ObjectPlaneT_elements[] = {
189 {NULL, {STATE_TEXGEN, 0, STATE_TEXGEN_OBJECT_T}, SWIZZLE_XYZW},
190 };
191
192 static struct gl_builtin_uniform_element gl_ObjectPlaneR_elements[] = {
193 {NULL, {STATE_TEXGEN, 0, STATE_TEXGEN_OBJECT_R}, SWIZZLE_XYZW},
194 };
195
196 static struct gl_builtin_uniform_element gl_ObjectPlaneQ_elements[] = {
197 {NULL, {STATE_TEXGEN, 0, STATE_TEXGEN_OBJECT_Q}, SWIZZLE_XYZW},
198 };
199
200 static struct gl_builtin_uniform_element gl_Fog_elements[] = {
201 {"color", {STATE_FOG_COLOR}, SWIZZLE_XYZW},
202 {"density", {STATE_FOG_PARAMS}, SWIZZLE_XXXX},
203 {"start", {STATE_FOG_PARAMS}, SWIZZLE_YYYY},
204 {"end", {STATE_FOG_PARAMS}, SWIZZLE_ZZZZ},
205 {"scale", {STATE_FOG_PARAMS}, SWIZZLE_WWWW},
206 };
207
208 static struct gl_builtin_uniform_element gl_NormalScale_elements[] = {
209 {NULL, {STATE_NORMAL_SCALE}, SWIZZLE_XXXX},
210 };
211
212 static struct gl_builtin_uniform_element gl_MESABumpRotMatrix0_elements[] = {
213 {NULL, {STATE_INTERNAL, STATE_ROT_MATRIX_0}, SWIZZLE_XYZW},
214 };
215
216 static struct gl_builtin_uniform_element gl_MESABumpRotMatrix1_elements[] = {
217 {NULL, {STATE_INTERNAL, STATE_ROT_MATRIX_1}, SWIZZLE_XYZW},
218 };
219
220 static struct gl_builtin_uniform_element gl_MESAFogParamsOptimized_elements[] = {
221 {NULL, {STATE_INTERNAL, STATE_FOG_PARAMS_OPTIMIZED}, SWIZZLE_XYZW},
222 };
223
224 #define MATRIX(name, statevar, modifier) \
225 static struct gl_builtin_uniform_element name ## _elements[] = { \
226 { NULL, { statevar, 0, 0, 0, modifier}, SWIZZLE_XYZW }, \
227 { NULL, { statevar, 0, 1, 1, modifier}, SWIZZLE_XYZW }, \
228 { NULL, { statevar, 0, 2, 2, modifier}, SWIZZLE_XYZW }, \
229 { NULL, { statevar, 0, 3, 3, modifier}, SWIZZLE_XYZW }, \
230 }
231
232 MATRIX(gl_ModelViewMatrix,
233 STATE_MODELVIEW_MATRIX, STATE_MATRIX_TRANSPOSE);
234 MATRIX(gl_ModelViewMatrixInverse,
235 STATE_MODELVIEW_MATRIX, STATE_MATRIX_INVTRANS);
236 MATRIX(gl_ModelViewMatrixTranspose,
237 STATE_MODELVIEW_MATRIX, 0);
238 MATRIX(gl_ModelViewMatrixInverseTranspose,
239 STATE_MODELVIEW_MATRIX, STATE_MATRIX_INVERSE);
240
241 MATRIX(gl_ProjectionMatrix,
242 STATE_PROJECTION_MATRIX, STATE_MATRIX_TRANSPOSE);
243 MATRIX(gl_ProjectionMatrixInverse,
244 STATE_PROJECTION_MATRIX, STATE_MATRIX_INVTRANS);
245 MATRIX(gl_ProjectionMatrixTranspose,
246 STATE_PROJECTION_MATRIX, 0);
247 MATRIX(gl_ProjectionMatrixInverseTranspose,
248 STATE_PROJECTION_MATRIX, STATE_MATRIX_INVERSE);
249
250 MATRIX(gl_ModelViewProjectionMatrix,
251 STATE_MVP_MATRIX, STATE_MATRIX_TRANSPOSE);
252 MATRIX(gl_ModelViewProjectionMatrixInverse,
253 STATE_MVP_MATRIX, STATE_MATRIX_INVTRANS);
254 MATRIX(gl_ModelViewProjectionMatrixTranspose,
255 STATE_MVP_MATRIX, 0);
256 MATRIX(gl_ModelViewProjectionMatrixInverseTranspose,
257 STATE_MVP_MATRIX, STATE_MATRIX_INVERSE);
258
259 MATRIX(gl_TextureMatrix,
260 STATE_TEXTURE_MATRIX, STATE_MATRIX_TRANSPOSE);
261 MATRIX(gl_TextureMatrixInverse,
262 STATE_TEXTURE_MATRIX, STATE_MATRIX_INVTRANS);
263 MATRIX(gl_TextureMatrixTranspose,
264 STATE_TEXTURE_MATRIX, 0);
265 MATRIX(gl_TextureMatrixInverseTranspose,
266 STATE_TEXTURE_MATRIX, STATE_MATRIX_INVERSE);
267
268 static struct gl_builtin_uniform_element gl_NormalMatrix_elements[] = {
269 { NULL, { STATE_MODELVIEW_MATRIX, 0, 0, 0, STATE_MATRIX_INVERSE},
270 SWIZZLE_XYZW },
271 { NULL, { STATE_MODELVIEW_MATRIX, 0, 1, 1, STATE_MATRIX_INVERSE},
272 SWIZZLE_XYZW },
273 { NULL, { STATE_MODELVIEW_MATRIX, 0, 2, 2, STATE_MATRIX_INVERSE},
274 SWIZZLE_XYZW },
275 };
276
277 #undef MATRIX
278
279 #define STATEVAR(name) {#name, name ## _elements, Elements(name ## _elements)}
280
281 const struct gl_builtin_uniform_desc _mesa_builtin_uniform_desc[] = {
282 STATEVAR(gl_DepthRange),
283 STATEVAR(gl_ClipPlane),
284 STATEVAR(gl_Point),
285 STATEVAR(gl_FrontMaterial),
286 STATEVAR(gl_BackMaterial),
287 STATEVAR(gl_LightSource),
288 STATEVAR(gl_LightModel),
289 STATEVAR(gl_FrontLightModelProduct),
290 STATEVAR(gl_BackLightModelProduct),
291 STATEVAR(gl_FrontLightProduct),
292 STATEVAR(gl_BackLightProduct),
293 STATEVAR(gl_TextureEnvColor),
294 STATEVAR(gl_EyePlaneS),
295 STATEVAR(gl_EyePlaneT),
296 STATEVAR(gl_EyePlaneR),
297 STATEVAR(gl_EyePlaneQ),
298 STATEVAR(gl_ObjectPlaneS),
299 STATEVAR(gl_ObjectPlaneT),
300 STATEVAR(gl_ObjectPlaneR),
301 STATEVAR(gl_ObjectPlaneQ),
302 STATEVAR(gl_Fog),
303
304 STATEVAR(gl_ModelViewMatrix),
305 STATEVAR(gl_ModelViewMatrixInverse),
306 STATEVAR(gl_ModelViewMatrixTranspose),
307 STATEVAR(gl_ModelViewMatrixInverseTranspose),
308
309 STATEVAR(gl_ProjectionMatrix),
310 STATEVAR(gl_ProjectionMatrixInverse),
311 STATEVAR(gl_ProjectionMatrixTranspose),
312 STATEVAR(gl_ProjectionMatrixInverseTranspose),
313
314 STATEVAR(gl_ModelViewProjectionMatrix),
315 STATEVAR(gl_ModelViewProjectionMatrixInverse),
316 STATEVAR(gl_ModelViewProjectionMatrixTranspose),
317 STATEVAR(gl_ModelViewProjectionMatrixInverseTranspose),
318
319 STATEVAR(gl_TextureMatrix),
320 STATEVAR(gl_TextureMatrixInverse),
321 STATEVAR(gl_TextureMatrixTranspose),
322 STATEVAR(gl_TextureMatrixInverseTranspose),
323
324 STATEVAR(gl_NormalMatrix),
325 STATEVAR(gl_NormalScale),
326
327 STATEVAR(gl_MESABumpRotMatrix0),
328 STATEVAR(gl_MESABumpRotMatrix1),
329 STATEVAR(gl_MESAFogParamsOptimized),
330
331 {NULL, NULL, 0}
332 };
333
334 static GLboolean
335 is_boolean_type(GLenum type)
336 {
337 switch (type) {
338 case GL_BOOL:
339 case GL_BOOL_VEC2:
340 case GL_BOOL_VEC3:
341 case GL_BOOL_VEC4:
342 return GL_TRUE;
343 default:
344 return GL_FALSE;
345 }
346 }
347
348
349 static GLboolean
350 is_sampler_type(GLenum type)
351 {
352 switch (type) {
353 case GL_SAMPLER_1D:
354 case GL_SAMPLER_2D:
355 case GL_SAMPLER_3D:
356 case GL_SAMPLER_CUBE:
357 case GL_SAMPLER_1D_SHADOW:
358 case GL_SAMPLER_2D_SHADOW:
359 case GL_SAMPLER_2D_RECT_ARB:
360 case GL_SAMPLER_2D_RECT_SHADOW_ARB:
361 case GL_SAMPLER_1D_ARRAY_EXT:
362 case GL_SAMPLER_2D_ARRAY_EXT:
363 case GL_SAMPLER_1D_ARRAY_SHADOW_EXT:
364 case GL_SAMPLER_2D_ARRAY_SHADOW_EXT:
365 return GL_TRUE;
366 default:
367 return GL_FALSE;
368 }
369 }
370
371
372 static struct gl_program_parameter *
373 get_uniform_parameter(const struct gl_shader_program *shProg, GLuint index)
374 {
375 const struct gl_program *prog = NULL;
376 GLint progPos;
377
378 progPos = shProg->Uniforms->Uniforms[index].VertPos;
379 if (progPos >= 0) {
380 prog = &shProg->VertexProgram->Base;
381 }
382 else {
383 progPos = shProg->Uniforms->Uniforms[index].FragPos;
384 if (progPos >= 0) {
385 prog = &shProg->FragmentProgram->Base;
386 } else {
387 progPos = shProg->Uniforms->Uniforms[index].GeomPos;
388 if (progPos >= 0) {
389 prog = &shProg->GeometryProgram->Base;
390 }
391 }
392 }
393
394 if (!prog || progPos < 0)
395 return NULL; /* should never happen */
396
397 return &prog->Parameters->Parameters[progPos];
398 }
399
400
401 /**
402 * Called by glGetActiveUniform().
403 */
404 static void
405 _mesa_get_active_uniform(struct gl_context *ctx, GLuint program, GLuint index,
406 GLsizei maxLength, GLsizei *length, GLint *size,
407 GLenum *type, GLchar *nameOut)
408 {
409 const struct gl_shader_program *shProg;
410 const struct gl_program *prog = NULL;
411 const struct gl_program_parameter *param;
412 GLint progPos;
413
414 shProg = _mesa_lookup_shader_program_err(ctx, program, "glGetActiveUniform");
415 if (!shProg)
416 return;
417
418 if (!shProg->Uniforms || index >= shProg->Uniforms->NumUniforms) {
419 _mesa_error(ctx, GL_INVALID_VALUE, "glGetActiveUniform(index)");
420 return;
421 }
422
423 progPos = shProg->Uniforms->Uniforms[index].VertPos;
424 if (progPos >= 0) {
425 prog = &shProg->VertexProgram->Base;
426 }
427 else {
428 progPos = shProg->Uniforms->Uniforms[index].FragPos;
429 if (progPos >= 0) {
430 prog = &shProg->FragmentProgram->Base;
431 } else {
432 progPos = shProg->Uniforms->Uniforms[index].GeomPos;
433 if (progPos >= 0) {
434 prog = &shProg->GeometryProgram->Base;
435 }
436 }
437 }
438
439 if (!prog || progPos < 0)
440 return; /* should never happen */
441
442 ASSERT(progPos < prog->Parameters->NumParameters);
443 param = &prog->Parameters->Parameters[progPos];
444
445 if (nameOut) {
446 _mesa_copy_string(nameOut, maxLength, length, param->Name);
447 }
448
449 if (size) {
450 GLint typeSize = _mesa_sizeof_glsl_type(param->DataType);
451 if ((GLint) param->Size > typeSize) {
452 /* This is an array.
453 * Array elements are placed on vector[4] boundaries so they're
454 * a multiple of four floats. We round typeSize up to next multiple
455 * of four to get the right size below.
456 */
457 typeSize = (typeSize + 3) & ~3;
458 }
459 /* Note that the returned size is in units of the <type>, not bytes */
460 *size = param->Size / typeSize;
461 }
462
463 if (type) {
464 *type = param->DataType;
465 }
466 }
467
468
469 static unsigned
470 get_vector_elements(GLenum type)
471 {
472 switch (type) {
473 case GL_FLOAT:
474 case GL_INT:
475 case GL_BOOL:
476 case GL_UNSIGNED_INT:
477 default: /* Catch all the various sampler types. */
478 return 1;
479
480 case GL_FLOAT_VEC2:
481 case GL_INT_VEC2:
482 case GL_BOOL_VEC2:
483 case GL_UNSIGNED_INT_VEC2:
484 return 2;
485
486 case GL_FLOAT_VEC3:
487 case GL_INT_VEC3:
488 case GL_BOOL_VEC3:
489 case GL_UNSIGNED_INT_VEC3:
490 return 3;
491
492 case GL_FLOAT_VEC4:
493 case GL_INT_VEC4:
494 case GL_BOOL_VEC4:
495 case GL_UNSIGNED_INT_VEC4:
496 return 4;
497 }
498 }
499
500 static void
501 get_matrix_dims(GLenum type, GLint *rows, GLint *cols)
502 {
503 switch (type) {
504 case GL_FLOAT_MAT2:
505 *rows = *cols = 2;
506 break;
507 case GL_FLOAT_MAT2x3:
508 *rows = 3;
509 *cols = 2;
510 break;
511 case GL_FLOAT_MAT2x4:
512 *rows = 4;
513 *cols = 2;
514 break;
515 case GL_FLOAT_MAT3:
516 *rows = 3;
517 *cols = 3;
518 break;
519 case GL_FLOAT_MAT3x2:
520 *rows = 2;
521 *cols = 3;
522 break;
523 case GL_FLOAT_MAT3x4:
524 *rows = 4;
525 *cols = 3;
526 break;
527 case GL_FLOAT_MAT4:
528 *rows = 4;
529 *cols = 4;
530 break;
531 case GL_FLOAT_MAT4x2:
532 *rows = 2;
533 *cols = 4;
534 break;
535 case GL_FLOAT_MAT4x3:
536 *rows = 3;
537 *cols = 4;
538 break;
539 default:
540 *rows = *cols = 0;
541 }
542 }
543
544
545 /**
546 * Determine the number of rows and columns occupied by a uniform
547 * according to its datatype. For non-matrix types (such as GL_FLOAT_VEC4),
548 * the number of rows = 1 and cols = number of elements in the vector.
549 */
550 static void
551 get_uniform_rows_cols(const struct gl_program_parameter *p,
552 GLint *rows, GLint *cols)
553 {
554 get_matrix_dims(p->DataType, rows, cols);
555 if (*rows == 0 && *cols == 0) {
556 /* not a matrix type, probably a float or vector */
557 *rows = 1;
558 *cols = get_vector_elements(p->DataType);
559 }
560 }
561
562
563 /**
564 * Helper for get_uniform[fi]v() functions.
565 * Given a shader program name and uniform location, return a pointer
566 * to the shader program and return the program parameter position.
567 */
568 static void
569 lookup_uniform_parameter(struct gl_context *ctx, GLuint program, GLint location,
570 struct gl_program **progOut, GLint *paramPosOut)
571 {
572 struct gl_shader_program *shProg
573 = _mesa_lookup_shader_program_err(ctx, program, "glGetUniform[if]v");
574 struct gl_program *prog = NULL;
575 GLint progPos = -1;
576
577 /* if shProg is NULL, we'll have already recorded an error */
578
579 if (shProg) {
580 if (!shProg->Uniforms ||
581 location < 0 ||
582 location >= (GLint) shProg->Uniforms->NumUniforms) {
583 _mesa_error(ctx, GL_INVALID_OPERATION, "glGetUniformfv(location)");
584 }
585 else {
586 /* OK, find the gl_program and program parameter location */
587 progPos = shProg->Uniforms->Uniforms[location].VertPos;
588 if (progPos >= 0) {
589 prog = &shProg->VertexProgram->Base;
590 }
591 else {
592 progPos = shProg->Uniforms->Uniforms[location].FragPos;
593 if (progPos >= 0) {
594 prog = &shProg->FragmentProgram->Base;
595 } else {
596 progPos = shProg->Uniforms->Uniforms[location].GeomPos;
597 if (progPos >= 0) {
598 prog = &shProg->GeometryProgram->Base;
599 }
600 }
601 }
602 }
603 }
604
605 *progOut = prog;
606 *paramPosOut = progPos;
607 }
608
609
610 /**
611 * GLGL uniform arrays and structs require special handling.
612 *
613 * The GL_ARB_shader_objects spec says that if you use
614 * glGetUniformLocation to get the location of an array, you CANNOT
615 * access other elements of the array by adding an offset to the
616 * returned location. For example, you must call
617 * glGetUniformLocation("foo[16]") if you want to set the 16th element
618 * of the array with glUniform().
619 *
620 * HOWEVER, some other OpenGL drivers allow accessing array elements
621 * by adding an offset to the returned array location. And some apps
622 * seem to depend on that behaviour.
623 *
624 * Mesa's gl_uniform_list doesn't directly support this since each
625 * entry in the list describes one uniform variable, not one uniform
626 * element. We could insert dummy entries in the list for each array
627 * element after [0] but that causes complications elsewhere.
628 *
629 * We solve this problem by encoding two values in the location that's
630 * returned by glGetUniformLocation():
631 * a) index into gl_uniform_list::Uniforms[] for the uniform
632 * b) an array/field offset (0 for simple types)
633 *
634 * These two values are encoded in the high and low halves of a GLint.
635 * By putting the uniform number in the high part and the offset in the
636 * low part, we can support the unofficial ability to index into arrays
637 * by adding offsets to the location value.
638 */
639 static void
640 merge_location_offset(GLint *location, GLint offset)
641 {
642 *location = (*location << 16) | offset;
643 }
644
645
646 /**
647 * Separate the uniform location and parameter offset. See above.
648 */
649 static void
650 split_location_offset(GLint *location, GLint *offset)
651 {
652 *offset = *location & 0xffff;
653 *location = *location >> 16;
654 }
655
656
657
658 /**
659 * Called via glGetUniformfv().
660 */
661 static void
662 _mesa_get_uniformfv(struct gl_context *ctx, GLuint program, GLint location,
663 GLfloat *params)
664 {
665 struct gl_program *prog;
666 GLint paramPos;
667 GLint offset;
668
669 split_location_offset(&location, &offset);
670
671 lookup_uniform_parameter(ctx, program, location, &prog, &paramPos);
672
673 if (prog) {
674 const struct gl_program_parameter *p =
675 &prog->Parameters->Parameters[paramPos];
676 GLint rows, cols, i, j, k;
677
678 get_uniform_rows_cols(p, &rows, &cols);
679
680 k = 0;
681 for (i = 0; i < rows; i++) {
682 const int base = paramPos + offset + i;
683
684 for (j = 0; j < cols; j++ ) {
685 params[k++] = prog->Parameters->ParameterValues[base][j];
686 }
687 }
688 }
689 }
690
691
692 /**
693 * Called via glGetUniformiv().
694 * \sa _mesa_get_uniformfv, only difference is a cast.
695 */
696 static void
697 _mesa_get_uniformiv(struct gl_context *ctx, GLuint program, GLint location,
698 GLint *params)
699 {
700 struct gl_program *prog;
701 GLint paramPos;
702 GLint offset;
703
704 split_location_offset(&location, &offset);
705
706 lookup_uniform_parameter(ctx, program, location, &prog, &paramPos);
707
708 if (prog) {
709 const struct gl_program_parameter *p =
710 &prog->Parameters->Parameters[paramPos];
711 GLint rows, cols, i, j, k;
712
713 get_uniform_rows_cols(p, &rows, &cols);
714
715 k = 0;
716 for (i = 0; i < rows; i++) {
717 const int base = paramPos + offset + i;
718
719 for (j = 0; j < cols; j++ ) {
720 params[k++] = (GLint) prog->Parameters->ParameterValues[base][j];
721 }
722 }
723 }
724 }
725
726
727 /**
728 * Called via glGetUniformuiv().
729 * New in GL_EXT_gpu_shader4, OpenGL 3.0
730 * \sa _mesa_get_uniformfv, only difference is a cast.
731 */
732 static void
733 _mesa_get_uniformuiv(struct gl_context *ctx, GLuint program, GLint location,
734 GLuint *params)
735 {
736 struct gl_program *prog;
737 GLint paramPos;
738 GLint offset;
739
740 split_location_offset(&location, &offset);
741
742 lookup_uniform_parameter(ctx, program, location, &prog, &paramPos);
743
744 if (prog) {
745 const struct gl_program_parameter *p =
746 &prog->Parameters->Parameters[paramPos];
747 GLint rows, cols, i, j, k;
748
749 get_uniform_rows_cols(p, &rows, &cols);
750
751 k = 0;
752 for (i = 0; i < rows; i++) {
753 const int base = paramPos + offset + i;
754
755 for (j = 0; j < cols; j++ ) {
756 params[k++] = (GLuint) prog->Parameters->ParameterValues[base][j];
757 }
758 }
759 }
760 }
761
762
763 /**
764 * Called via glGetUniformLocation().
765 *
766 * The return value will encode two values, the uniform location and an
767 * offset (used for arrays, structs).
768 */
769 GLint
770 _mesa_get_uniform_location(struct gl_context *ctx, struct gl_shader_program *shProg,
771 const GLchar *name)
772 {
773 GLint offset = 0, location = -1;
774
775 if (shProg->LinkStatus == GL_FALSE) {
776 _mesa_error(ctx, GL_INVALID_OPERATION, "glGetUniformfv(program)");
777 return -1;
778 }
779
780 /* XXX we should return -1 if the uniform was declared, but not
781 * actually used.
782 */
783
784 /* XXX we need to be able to parse uniform names for structs and arrays
785 * such as:
786 * mymatrix[1]
787 * mystruct.field1
788 */
789
790 {
791 /* handle 1-dimension arrays here... */
792 char *c = strchr(name, '[');
793 if (c) {
794 /* truncate name at [ */
795 const GLint len = c - name;
796 GLchar *newName = malloc(len + 1);
797 if (!newName)
798 return -1; /* out of mem */
799 memcpy(newName, name, len);
800 newName[len] = 0;
801
802 location = _mesa_lookup_uniform(shProg->Uniforms, newName);
803 if (location >= 0) {
804 const GLint element = atoi(c + 1);
805 if (element > 0) {
806 /* get type of the uniform array element */
807 struct gl_program_parameter *p;
808 p = get_uniform_parameter(shProg, location);
809 if (p) {
810 GLint rows, cols;
811 get_matrix_dims(p->DataType, &rows, &cols);
812 if (rows < 1)
813 rows = 1;
814 offset = element * rows;
815 }
816 }
817 }
818
819 free(newName);
820 }
821 }
822
823 if (location < 0) {
824 location = _mesa_lookup_uniform(shProg->Uniforms, name);
825 }
826
827 if (location >= 0) {
828 merge_location_offset(&location, offset);
829 }
830
831 return location;
832 }
833
834
835
836 /**
837 * Update the vertex/fragment program's TexturesUsed array.
838 *
839 * This needs to be called after glUniform(set sampler var) is called.
840 * A call to glUniform(samplerVar, value) causes a sampler to point to a
841 * particular texture unit. We know the sampler's texture target
842 * (1D/2D/3D/etc) from compile time but the sampler's texture unit is
843 * set by glUniform() calls.
844 *
845 * So, scan the program->SamplerUnits[] and program->SamplerTargets[]
846 * information to update the prog->TexturesUsed[] values.
847 * Each value of TexturesUsed[unit] is one of zero, TEXTURE_1D_INDEX,
848 * TEXTURE_2D_INDEX, TEXTURE_3D_INDEX, etc.
849 * We'll use that info for state validation before rendering.
850 */
851 void
852 _mesa_update_shader_textures_used(struct gl_program *prog)
853 {
854 GLuint s;
855
856 memset(prog->TexturesUsed, 0, sizeof(prog->TexturesUsed));
857
858 for (s = 0; s < MAX_SAMPLERS; s++) {
859 if (prog->SamplersUsed & (1 << s)) {
860 GLuint unit = prog->SamplerUnits[s];
861 GLuint tgt = prog->SamplerTargets[s];
862 assert(unit < MAX_TEXTURE_IMAGE_UNITS);
863 assert(tgt < NUM_TEXTURE_TARGETS);
864 prog->TexturesUsed[unit] |= (1 << tgt);
865 }
866 }
867 }
868
869
870 /**
871 * Check if the type given by userType is allowed to set a uniform of the
872 * target type. Generally, equivalence is required, but setting Boolean
873 * uniforms can be done with glUniformiv or glUniformfv.
874 */
875 static GLboolean
876 compatible_types(GLenum userType, GLenum targetType)
877 {
878 if (userType == targetType)
879 return GL_TRUE;
880
881 if (targetType == GL_BOOL && (userType == GL_FLOAT ||
882 userType == GL_UNSIGNED_INT ||
883 userType == GL_INT))
884 return GL_TRUE;
885
886 if (targetType == GL_BOOL_VEC2 && (userType == GL_FLOAT_VEC2 ||
887 userType == GL_UNSIGNED_INT_VEC2 ||
888 userType == GL_INT_VEC2))
889 return GL_TRUE;
890
891 if (targetType == GL_BOOL_VEC3 && (userType == GL_FLOAT_VEC3 ||
892 userType == GL_UNSIGNED_INT_VEC3 ||
893 userType == GL_INT_VEC3))
894 return GL_TRUE;
895
896 if (targetType == GL_BOOL_VEC4 && (userType == GL_FLOAT_VEC4 ||
897 userType == GL_UNSIGNED_INT_VEC4 ||
898 userType == GL_INT_VEC4))
899 return GL_TRUE;
900
901 if (is_sampler_type(targetType) && userType == GL_INT)
902 return GL_TRUE;
903
904 return GL_FALSE;
905 }
906
907
908 /**
909 * Set the value of a program's uniform variable.
910 * \param program the program whose uniform to update
911 * \param index the index of the program parameter for the uniform
912 * \param offset additional parameter slot offset (for arrays)
913 * \param type the incoming datatype of 'values'
914 * \param count the number of uniforms to set
915 * \param elems number of elements per uniform (1, 2, 3 or 4)
916 * \param values the new values, of datatype 'type'
917 */
918 static void
919 set_program_uniform(struct gl_context *ctx, struct gl_program *program,
920 GLint index, GLint offset,
921 GLenum type, GLsizei count, GLint elems,
922 const void *values)
923 {
924 const struct gl_program_parameter *param =
925 &program->Parameters->Parameters[index];
926
927 assert(offset >= 0);
928 assert(elems >= 1);
929 assert(elems <= 4);
930
931 if (!compatible_types(type, param->DataType)) {
932 _mesa_error(ctx, GL_INVALID_OPERATION, "glUniform(type mismatch)");
933 return;
934 }
935
936 if (index + offset > (GLint) program->Parameters->Size) {
937 /* out of bounds! */
938 return;
939 }
940
941 if (param->Type == PROGRAM_SAMPLER) {
942 /* This controls which texture unit which is used by a sampler */
943 GLboolean changed = GL_FALSE;
944 GLint i;
945
946 /* this should have been caught by the compatible_types() check */
947 ASSERT(type == GL_INT);
948
949 /* loop over number of samplers to change */
950 for (i = 0; i < count; i++) {
951 GLuint sampler =
952 (GLuint) program->Parameters->ParameterValues[index + offset + i][0];
953 GLuint texUnit = ((GLuint *) values)[i];
954
955 /* check that the sampler (tex unit index) is legal */
956 if (texUnit >= ctx->Const.MaxTextureImageUnits) {
957 _mesa_error(ctx, GL_INVALID_VALUE,
958 "glUniform1(invalid sampler/tex unit index for '%s')",
959 param->Name);
960 return;
961 }
962
963 /* This maps a sampler to a texture unit: */
964 if (sampler < MAX_SAMPLERS) {
965 #if 0
966 printf("Set program %p sampler %d '%s' to unit %u\n",
967 program, sampler, param->Name, texUnit);
968 #endif
969 if (program->SamplerUnits[sampler] != texUnit) {
970 program->SamplerUnits[sampler] = texUnit;
971 changed = GL_TRUE;
972 }
973 }
974 }
975
976 if (changed) {
977 /* When a sampler's value changes it usually requires rewriting
978 * a GPU program's TEX instructions since there may not be a
979 * sampler->texture lookup table. We signal this with the
980 * ProgramStringNotify() callback.
981 */
982 FLUSH_VERTICES(ctx, _NEW_TEXTURE | _NEW_PROGRAM);
983 _mesa_update_shader_textures_used(program);
984 /* Do we need to care about the return value here?
985 * This should not be the first time the driver was notified of
986 * this program.
987 */
988 (void) ctx->Driver.ProgramStringNotify(ctx, program->Target, program);
989 }
990 }
991 else {
992 /* ordinary uniform variable */
993 const GLboolean isUniformBool = is_boolean_type(param->DataType);
994 const GLenum basicType = base_uniform_type(type);
995 const GLint slots = (param->Size + 3) / 4;
996 const GLint typeSize = _mesa_sizeof_glsl_type(param->DataType);
997 GLsizei k, i;
998
999 if ((GLint) param->Size > typeSize) {
1000 /* an array */
1001 /* we'll ignore extra data below */
1002 }
1003 else {
1004 /* non-array: count must be at most one; count == 0 is handled by the loop below */
1005 if (count > 1) {
1006 _mesa_error(ctx, GL_INVALID_OPERATION,
1007 "glUniform(uniform '%s' is not an array)",
1008 param->Name);
1009 return;
1010 }
1011 }
1012
1013 /* loop over number of array elements */
1014 for (k = 0; k < count; k++) {
1015 GLfloat *uniformVal;
1016
1017 if (offset + k >= slots) {
1018 /* Extra array data is ignored */
1019 break;
1020 }
1021
1022 /* uniformVal (the destination) is always float[4] */
1023 uniformVal = program->Parameters->ParameterValues[index + offset + k];
1024
1025 if (basicType == GL_INT) {
1026 /* convert user's ints to floats */
1027 const GLint *iValues = ((const GLint *) values) + k * elems;
1028 for (i = 0; i < elems; i++) {
1029 uniformVal[i] = (GLfloat) iValues[i];
1030 }
1031 }
1032 else if (basicType == GL_UNSIGNED_INT) {
1033 /* convert user's uints to floats */
1034 const GLuint *iValues = ((const GLuint *) values) + k * elems;
1035 for (i = 0; i < elems; i++) {
1036 uniformVal[i] = (GLfloat) iValues[i];
1037 }
1038 }
1039 else {
1040 const GLfloat *fValues = ((const GLfloat *) values) + k * elems;
1041 assert(basicType == GL_FLOAT);
1042 for (i = 0; i < elems; i++) {
1043 uniformVal[i] = fValues[i];
1044 }
1045 }
1046
1047 /* if the uniform is bool-valued, convert to 1.0 or 0.0 */
1048 if (isUniformBool) {
1049 for (i = 0; i < elems; i++) {
1050 uniformVal[i] = uniformVal[i] ? 1.0f : 0.0f;
1051 }
1052 }
1053 }
1054 }
1055 }
1056
1057
1058 /**
1059 * Called via glUniform*() functions.
1060 */
1061 void
1062 _mesa_uniform(struct gl_context *ctx, struct gl_shader_program *shProg,
1063 GLint location, GLsizei count,
1064 const GLvoid *values, GLenum type)
1065 {
1066 struct gl_uniform *uniform;
1067 GLint elems, offset;
1068
1069 if (!shProg || !shProg->LinkStatus) {
1070 _mesa_error(ctx, GL_INVALID_OPERATION, "glUniform(program not linked)");
1071 return;
1072 }
1073
1074 if (location == -1)
1075 return; /* The standard specifies this as a no-op */
1076
1077 if (location < -1) {
1078 _mesa_error(ctx, GL_INVALID_OPERATION, "glUniform(location=%d)",
1079 location);
1080 return;
1081 }
1082
1083 split_location_offset(&location, &offset);
1084
1085 if (location < 0 || location >= (GLint) shProg->Uniforms->NumUniforms) {
1086 _mesa_error(ctx, GL_INVALID_VALUE, "glUniform(location=%d)", location);
1087 return;
1088 }
1089
1090 if (count < 0) {
1091 _mesa_error(ctx, GL_INVALID_VALUE, "glUniform(count < 0)");
1092 return;
1093 }
1094
1095 elems = _mesa_sizeof_glsl_type(type);
1096
1097 FLUSH_VERTICES(ctx, _NEW_PROGRAM_CONSTANTS);
1098
1099 uniform = &shProg->Uniforms->Uniforms[location];
1100
1101 if (ctx->Shader.Flags & GLSL_UNIFORMS) {
1102 const GLenum basicType = base_uniform_type(type);
1103 GLint i;
1104 printf("Mesa: set program %u uniform %s (loc %d) to: ",
1105 shProg->Name, uniform->Name, location);
1106 if (basicType == GL_INT) {
1107 const GLint *v = (const GLint *) values;
1108 for (i = 0; i < count * elems; i++) {
1109 printf("%d ", v[i]);
1110 }
1111 }
1112 else if (basicType == GL_UNSIGNED_INT) {
1113 const GLuint *v = (const GLuint *) values;
1114 for (i = 0; i < count * elems; i++) {
1115 printf("%u ", v[i]);
1116 }
1117 }
1118 else {
1119 const GLfloat *v = (const GLfloat *) values;
1120 assert(basicType == GL_FLOAT);
1121 for (i = 0; i < count * elems; i++) {
1122 printf("%g ", v[i]);
1123 }
1124 }
1125 printf("\n");
1126 }
1127
1128 /* A uniform var may be used by both a vertex shader and a fragment
1129 * shader. We may need to update one or both shader's uniform here:
1130 */
1131 if (shProg->VertexProgram) {
1132 /* convert uniform location to program parameter index */
1133 GLint index = uniform->VertPos;
1134 if (index >= 0) {
1135 set_program_uniform(ctx, &shProg->VertexProgram->Base,
1136 index, offset, type, count, elems, values);
1137 }
1138 }
1139
1140 if (shProg->FragmentProgram) {
1141 /* convert uniform location to program parameter index */
1142 GLint index = uniform->FragPos;
1143 if (index >= 0) {
1144 set_program_uniform(ctx, &shProg->FragmentProgram->Base,
1145 index, offset, type, count, elems, values);
1146 }
1147 }
1148
1149 if (shProg->GeometryProgram) {
1150 /* convert uniform location to program parameter index */
1151 GLint index = uniform->GeomPos;
1152 if (index >= 0) {
1153 set_program_uniform(ctx, &shProg->GeometryProgram->Base,
1154 index, offset, type, count, elems, values);
1155 }
1156 }
1157
1158 uniform->Initialized = GL_TRUE;
1159 }
1160
1161
1162 /**
1163 * Set a matrix-valued program parameter.
1164 */
1165 static void
1166 set_program_uniform_matrix(struct gl_context *ctx, struct gl_program *program,
1167 GLuint index, GLuint offset,
1168 GLuint count, GLuint rows, GLuint cols,
1169 GLboolean transpose, const GLfloat *values)
1170 {
1171 GLuint mat, row, col;
1172 GLuint src = 0;
1173 const struct gl_program_parameter * param = &program->Parameters->Parameters[index];
1174 const GLuint slots = (param->Size + 3) / 4;
1175 const GLint typeSize = _mesa_sizeof_glsl_type(param->DataType);
1176 GLint nr, nc;
1177
1178 /* check that the number of rows, columns is correct */
1179 get_matrix_dims(param->DataType, &nr, &nc);
1180 if (rows != nr || cols != nc) {
1181 _mesa_error(ctx, GL_INVALID_OPERATION,
1182 "glUniformMatrix(matrix size mismatch)");
1183 return;
1184 }
1185
1186 if ((GLint) param->Size <= typeSize) {
1187 /* non-array: count must be at most one; count == 0 is handled by the loop below */
1188 if (count > 1) {
1189 _mesa_error(ctx, GL_INVALID_OPERATION,
1190 "glUniformMatrix(uniform is not an array)");
1191 return;
1192 }
1193 }
1194
1195 /*
1196 * Note: the _columns_ of a matrix are stored in program registers, not
1197 * the rows. So, the loops below look a little funny.
1198 * XXX could optimize this a bit...
1199 */
1200
1201 /* loop over matrices */
1202 for (mat = 0; mat < count; mat++) {
1203
1204 /* each matrix: */
1205 for (col = 0; col < cols; col++) {
1206 GLfloat *v;
1207 if (offset >= slots) {
1208 /* Ignore writes beyond the end of (the used part of) an array */
1209 return;
1210 }
1211 v = program->Parameters->ParameterValues[index + offset];
1212 for (row = 0; row < rows; row++) {
1213 if (transpose) {
1214 v[row] = values[src + row * cols + col];
1215 }
1216 else {
1217 v[row] = values[src + col * rows + row];
1218 }
1219 }
1220
1221 offset++;
1222 }
1223
1224 src += rows * cols; /* next matrix */
1225 }
1226 }
1227
1228
1229 /**
1230 * Called by glUniformMatrix*() functions.
1231 * Note: cols=2, rows=4 ==> array[2] of vec4
1232 */
1233 void
1234 _mesa_uniform_matrix(struct gl_context *ctx, struct gl_shader_program *shProg,
1235 GLint cols, GLint rows,
1236 GLint location, GLsizei count,
1237 GLboolean transpose, const GLfloat *values)
1238 {
1239 struct gl_uniform *uniform;
1240 GLint offset;
1241
1242 if (!shProg || !shProg->LinkStatus) {
1243 _mesa_error(ctx, GL_INVALID_OPERATION,
1244 "glUniformMatrix(program not linked)");
1245 return;
1246 }
1247
1248 if (location == -1)
1249 return; /* The standard specifies this as a no-op */
1250
1251 if (location < -1) {
1252 _mesa_error(ctx, GL_INVALID_OPERATION, "glUniformMatrix(location)");
1253 return;
1254 }
1255
1256 split_location_offset(&location, &offset);
1257
1258 if (location < 0 || location >= (GLint) shProg->Uniforms->NumUniforms) {
1259 _mesa_error(ctx, GL_INVALID_VALUE, "glUniformMatrix(location)");
1260 return;
1261 }
1262 if (values == NULL) {
1263 _mesa_error(ctx, GL_INVALID_VALUE, "glUniformMatrix");
1264 return;
1265 }
1266
1267 FLUSH_VERTICES(ctx, _NEW_PROGRAM_CONSTANTS);
1268
1269 uniform = &shProg->Uniforms->Uniforms[location];
1270
1271 if (shProg->VertexProgram) {
1272 /* convert uniform location to program parameter index */
1273 GLint index = uniform->VertPos;
1274 if (index >= 0) {
1275 set_program_uniform_matrix(ctx, &shProg->VertexProgram->Base,
1276 index, offset,
1277 count, rows, cols, transpose, values);
1278 }
1279 }
1280
1281 if (shProg->FragmentProgram) {
1282 /* convert uniform location to program parameter index */
1283 GLint index = uniform->FragPos;
1284 if (index >= 0) {
1285 set_program_uniform_matrix(ctx, &shProg->FragmentProgram->Base,
1286 index, offset,
1287 count, rows, cols, transpose, values);
1288 }
1289 }
1290
1291 if (shProg->GeometryProgram) {
1292 /* convert uniform location to program parameter index */
1293 GLint index = uniform->GeomPos;
1294 if (index >= 0) {
1295 set_program_uniform_matrix(ctx, &shProg->GeometryProgram->Base,
1296 index, offset,
1297 count, rows, cols, transpose, values);
1298 }
1299 }
1300
1301 uniform->Initialized = GL_TRUE;
1302 }
1303
1304
1305 void GLAPIENTRY
1306 _mesa_Uniform1fARB(GLint location, GLfloat v0)
1307 {
1308 GET_CURRENT_CONTEXT(ctx);
1309 _mesa_uniform(ctx, ctx->Shader.ActiveProgram, location, 1, &v0, GL_FLOAT);
1310 }
1311
1312 void GLAPIENTRY
1313 _mesa_Uniform2fARB(GLint location, GLfloat v0, GLfloat v1)
1314 {
1315 GET_CURRENT_CONTEXT(ctx);
1316 GLfloat v[2];
1317 v[0] = v0;
1318 v[1] = v1;
1319 _mesa_uniform(ctx, ctx->Shader.ActiveProgram, location, 1, v, GL_FLOAT_VEC2);
1320 }
1321
1322 void GLAPIENTRY
1323 _mesa_Uniform3fARB(GLint location, GLfloat v0, GLfloat v1, GLfloat v2)
1324 {
1325 GET_CURRENT_CONTEXT(ctx);
1326 GLfloat v[3];
1327 v[0] = v0;
1328 v[1] = v1;
1329 v[2] = v2;
1330 _mesa_uniform(ctx, ctx->Shader.ActiveProgram, location, 1, v, GL_FLOAT_VEC3);
1331 }
1332
1333 void GLAPIENTRY
1334 _mesa_Uniform4fARB(GLint location, GLfloat v0, GLfloat v1, GLfloat v2,
1335 GLfloat v3)
1336 {
1337 GET_CURRENT_CONTEXT(ctx);
1338 GLfloat v[4];
1339 v[0] = v0;
1340 v[1] = v1;
1341 v[2] = v2;
1342 v[3] = v3;
1343 _mesa_uniform(ctx, ctx->Shader.ActiveProgram, location, 1, v, GL_FLOAT_VEC4);
1344 }
1345
1346 void GLAPIENTRY
1347 _mesa_Uniform1iARB(GLint location, GLint v0)
1348 {
1349 GET_CURRENT_CONTEXT(ctx);
1350 _mesa_uniform(ctx, ctx->Shader.ActiveProgram, location, 1, &v0, GL_INT);
1351 }
1352
1353 void GLAPIENTRY
1354 _mesa_Uniform2iARB(GLint location, GLint v0, GLint v1)
1355 {
1356 GET_CURRENT_CONTEXT(ctx);
1357 GLint v[2];
1358 v[0] = v0;
1359 v[1] = v1;
1360 _mesa_uniform(ctx, ctx->Shader.ActiveProgram, location, 1, v, GL_INT_VEC2);
1361 }
1362
1363 void GLAPIENTRY
1364 _mesa_Uniform3iARB(GLint location, GLint v0, GLint v1, GLint v2)
1365 {
1366 GET_CURRENT_CONTEXT(ctx);
1367 GLint v[3];
1368 v[0] = v0;
1369 v[1] = v1;
1370 v[2] = v2;
1371 _mesa_uniform(ctx, ctx->Shader.ActiveProgram, location, 1, v, GL_INT_VEC3);
1372 }
1373
1374 void GLAPIENTRY
1375 _mesa_Uniform4iARB(GLint location, GLint v0, GLint v1, GLint v2, GLint v3)
1376 {
1377 GET_CURRENT_CONTEXT(ctx);
1378 GLint v[4];
1379 v[0] = v0;
1380 v[1] = v1;
1381 v[2] = v2;
1382 v[3] = v3;
1383 _mesa_uniform(ctx, ctx->Shader.ActiveProgram, location, 1, v, GL_INT_VEC4);
1384 }
1385
1386 void GLAPIENTRY
1387 _mesa_Uniform1fvARB(GLint location, GLsizei count, const GLfloat * value)
1388 {
1389 GET_CURRENT_CONTEXT(ctx);
1390 _mesa_uniform(ctx, ctx->Shader.ActiveProgram, location, count, value, GL_FLOAT);
1391 }
1392
1393 void GLAPIENTRY
1394 _mesa_Uniform2fvARB(GLint location, GLsizei count, const GLfloat * value)
1395 {
1396 GET_CURRENT_CONTEXT(ctx);
1397 _mesa_uniform(ctx, ctx->Shader.ActiveProgram, location, count, value, GL_FLOAT_VEC2);
1398 }
1399
1400 void GLAPIENTRY
1401 _mesa_Uniform3fvARB(GLint location, GLsizei count, const GLfloat * value)
1402 {
1403 GET_CURRENT_CONTEXT(ctx);
1404 _mesa_uniform(ctx, ctx->Shader.ActiveProgram, location, count, value, GL_FLOAT_VEC3);
1405 }
1406
1407 void GLAPIENTRY
1408 _mesa_Uniform4fvARB(GLint location, GLsizei count, const GLfloat * value)
1409 {
1410 GET_CURRENT_CONTEXT(ctx);
1411 _mesa_uniform(ctx, ctx->Shader.ActiveProgram, location, count, value, GL_FLOAT_VEC4);
1412 }
1413
1414 void GLAPIENTRY
1415 _mesa_Uniform1ivARB(GLint location, GLsizei count, const GLint * value)
1416 {
1417 GET_CURRENT_CONTEXT(ctx);
1418 _mesa_uniform(ctx, ctx->Shader.ActiveProgram, location, count, value, GL_INT);
1419 }
1420
1421 void GLAPIENTRY
1422 _mesa_Uniform2ivARB(GLint location, GLsizei count, const GLint * value)
1423 {
1424 GET_CURRENT_CONTEXT(ctx);
1425 _mesa_uniform(ctx, ctx->Shader.ActiveProgram, location, count, value, GL_INT_VEC2);
1426 }
1427
1428 void GLAPIENTRY
1429 _mesa_Uniform3ivARB(GLint location, GLsizei count, const GLint * value)
1430 {
1431 GET_CURRENT_CONTEXT(ctx);
1432 _mesa_uniform(ctx, ctx->Shader.ActiveProgram, location, count, value, GL_INT_VEC3);
1433 }
1434
1435 void GLAPIENTRY
1436 _mesa_Uniform4ivARB(GLint location, GLsizei count, const GLint * value)
1437 {
1438 GET_CURRENT_CONTEXT(ctx);
1439 _mesa_uniform(ctx, ctx->Shader.ActiveProgram, location, count, value, GL_INT_VEC4);
1440 }
1441
1442
1443 /** OpenGL 3.0 GLuint-valued functions **/
1444 void GLAPIENTRY
1445 _mesa_Uniform1ui(GLint location, GLuint v0)
1446 {
1447 GET_CURRENT_CONTEXT(ctx);
1448 _mesa_uniform(ctx, ctx->Shader.ActiveProgram, location, 1, &v0, GL_UNSIGNED_INT);
1449 }
1450
1451 void GLAPIENTRY
1452 _mesa_Uniform2ui(GLint location, GLuint v0, GLuint v1)
1453 {
1454 GET_CURRENT_CONTEXT(ctx);
1455 GLuint v[2];
1456 v[0] = v0;
1457 v[1] = v1;
1458 _mesa_uniform(ctx, ctx->Shader.ActiveProgram, location, 1, v, GL_UNSIGNED_INT_VEC2);
1459 }
1460
1461 void GLAPIENTRY
1462 _mesa_Uniform3ui(GLint location, GLuint v0, GLuint v1, GLuint v2)
1463 {
1464 GET_CURRENT_CONTEXT(ctx);
1465 GLuint v[3];
1466 v[0] = v0;
1467 v[1] = v1;
1468 v[2] = v2;
1469 _mesa_uniform(ctx, ctx->Shader.ActiveProgram, location, 1, v, GL_UNSIGNED_INT_VEC3);
1470 }
1471
1472 void GLAPIENTRY
1473 _mesa_Uniform4ui(GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3)
1474 {
1475 GET_CURRENT_CONTEXT(ctx);
1476 GLuint v[4];
1477 v[0] = v0;
1478 v[1] = v1;
1479 v[2] = v2;
1480 v[3] = v3;
1481 _mesa_uniform(ctx, ctx->Shader.ActiveProgram, location, 1, v, GL_UNSIGNED_INT_VEC4);
1482 }
1483
1484 void GLAPIENTRY
1485 _mesa_Uniform1uiv(GLint location, GLsizei count, const GLuint *value)
1486 {
1487 GET_CURRENT_CONTEXT(ctx);
1488 _mesa_uniform(ctx, ctx->Shader.ActiveProgram, location, count, value, GL_UNSIGNED_INT);
1489 }
1490
1491 void GLAPIENTRY
1492 _mesa_Uniform2uiv(GLint location, GLsizei count, const GLuint *value)
1493 {
1494 GET_CURRENT_CONTEXT(ctx);
1495 _mesa_uniform(ctx, ctx->Shader.ActiveProgram, location, count, value, GL_UNSIGNED_INT_VEC2);
1496 }
1497
1498 void GLAPIENTRY
1499 _mesa_Uniform3uiv(GLint location, GLsizei count, const GLuint *value)
1500 {
1501 GET_CURRENT_CONTEXT(ctx);
1502 _mesa_uniform(ctx, ctx->Shader.ActiveProgram, location, count, value, GL_UNSIGNED_INT_VEC3);
1503 }
1504
1505 void GLAPIENTRY
1506 _mesa_Uniform4uiv(GLint location, GLsizei count, const GLuint *value)
1507 {
1508 GET_CURRENT_CONTEXT(ctx);
1509 _mesa_uniform(ctx, ctx->Shader.ActiveProgram, location, count, value, GL_UNSIGNED_INT_VEC4);
1510 }
1511
1512
1513
1514 void GLAPIENTRY
1515 _mesa_UniformMatrix2fvARB(GLint location, GLsizei count, GLboolean transpose,
1516 const GLfloat * value)
1517 {
1518 GET_CURRENT_CONTEXT(ctx);
1519 _mesa_uniform_matrix(ctx, ctx->Shader.ActiveProgram,
1520 2, 2, location, count, transpose, value);
1521 }
1522
1523 void GLAPIENTRY
1524 _mesa_UniformMatrix3fvARB(GLint location, GLsizei count, GLboolean transpose,
1525 const GLfloat * value)
1526 {
1527 GET_CURRENT_CONTEXT(ctx);
1528 _mesa_uniform_matrix(ctx, ctx->Shader.ActiveProgram,
1529 3, 3, location, count, transpose, value);
1530 }
1531
1532 void GLAPIENTRY
1533 _mesa_UniformMatrix4fvARB(GLint location, GLsizei count, GLboolean transpose,
1534 const GLfloat * value)
1535 {
1536 GET_CURRENT_CONTEXT(ctx);
1537 _mesa_uniform_matrix(ctx, ctx->Shader.ActiveProgram,
1538 4, 4, location, count, transpose, value);
1539 }
1540
1541
1542 /**
1543 * Non-square UniformMatrix are OpenGL 2.1
1544 */
1545 void GLAPIENTRY
1546 _mesa_UniformMatrix2x3fv(GLint location, GLsizei count, GLboolean transpose,
1547 const GLfloat *value)
1548 {
1549 GET_CURRENT_CONTEXT(ctx);
1550 _mesa_uniform_matrix(ctx, ctx->Shader.ActiveProgram,
1551 2, 3, location, count, transpose, value);
1552 }
1553
1554 void GLAPIENTRY
1555 _mesa_UniformMatrix3x2fv(GLint location, GLsizei count, GLboolean transpose,
1556 const GLfloat *value)
1557 {
1558 GET_CURRENT_CONTEXT(ctx);
1559 _mesa_uniform_matrix(ctx, ctx->Shader.ActiveProgram,
1560 3, 2, location, count, transpose, value);
1561 }
1562
1563 void GLAPIENTRY
1564 _mesa_UniformMatrix2x4fv(GLint location, GLsizei count, GLboolean transpose,
1565 const GLfloat *value)
1566 {
1567 GET_CURRENT_CONTEXT(ctx);
1568 _mesa_uniform_matrix(ctx, ctx->Shader.ActiveProgram,
1569 2, 4, location, count, transpose, value);
1570 }
1571
1572 void GLAPIENTRY
1573 _mesa_UniformMatrix4x2fv(GLint location, GLsizei count, GLboolean transpose,
1574 const GLfloat *value)
1575 {
1576 GET_CURRENT_CONTEXT(ctx);
1577 _mesa_uniform_matrix(ctx, ctx->Shader.ActiveProgram,
1578 4, 2, location, count, transpose, value);
1579 }
1580
1581 void GLAPIENTRY
1582 _mesa_UniformMatrix3x4fv(GLint location, GLsizei count, GLboolean transpose,
1583 const GLfloat *value)
1584 {
1585 GET_CURRENT_CONTEXT(ctx);
1586 _mesa_uniform_matrix(ctx, ctx->Shader.ActiveProgram,
1587 3, 4, location, count, transpose, value);
1588 }
1589
1590 void GLAPIENTRY
1591 _mesa_UniformMatrix4x3fv(GLint location, GLsizei count, GLboolean transpose,
1592 const GLfloat *value)
1593 {
1594 GET_CURRENT_CONTEXT(ctx);
1595 _mesa_uniform_matrix(ctx, ctx->Shader.ActiveProgram,
1596 4, 3, location, count, transpose, value);
1597 }
1598
1599
1600 void GLAPIENTRY
1601 _mesa_GetUniformfvARB(GLhandleARB program, GLint location, GLfloat *params)
1602 {
1603 GET_CURRENT_CONTEXT(ctx);
1604 _mesa_get_uniformfv(ctx, program, location, params);
1605 }
1606
1607
1608 void GLAPIENTRY
1609 _mesa_GetUniformivARB(GLhandleARB program, GLint location, GLint *params)
1610 {
1611 GET_CURRENT_CONTEXT(ctx);
1612 _mesa_get_uniformiv(ctx, program, location, params);
1613 }
1614
1615
1616 /* GL3 */
1617 void GLAPIENTRY
1618 _mesa_GetUniformuiv(GLhandleARB program, GLint location, GLuint *params)
1619 {
1620 GET_CURRENT_CONTEXT(ctx);
1621 _mesa_get_uniformuiv(ctx, program, location, params);
1622 }
1623
1624
1625
1626 GLint GLAPIENTRY
1627 _mesa_GetUniformLocationARB(GLhandleARB programObj, const GLcharARB *name)
1628 {
1629 struct gl_shader_program *shProg;
1630
1631 GET_CURRENT_CONTEXT(ctx);
1632
1633 shProg = _mesa_lookup_shader_program_err(ctx, programObj,
1634 "glGetUniformLocation");
1635 if (!shProg)
1636 return -1;
1637
1638 return _mesa_get_uniform_location(ctx, shProg, name);
1639 }
1640
1641
1642 void GLAPIENTRY
1643 _mesa_GetActiveUniformARB(GLhandleARB program, GLuint index,
1644 GLsizei maxLength, GLsizei * length, GLint * size,
1645 GLenum * type, GLcharARB * name)
1646 {
1647 GET_CURRENT_CONTEXT(ctx);
1648 _mesa_get_active_uniform(ctx, program, index, maxLength, length, size,
1649 type, name);
1650 }
1651
1652
1653 /**
1654 * Plug in shader uniform-related functions into API dispatch table.
1655 */
1656 void
1657 _mesa_init_shader_uniform_dispatch(struct _glapi_table *exec)
1658 {
1659 #if FEATURE_GL
1660 SET_Uniform1fARB(exec, _mesa_Uniform1fARB);
1661 SET_Uniform2fARB(exec, _mesa_Uniform2fARB);
1662 SET_Uniform3fARB(exec, _mesa_Uniform3fARB);
1663 SET_Uniform4fARB(exec, _mesa_Uniform4fARB);
1664 SET_Uniform1iARB(exec, _mesa_Uniform1iARB);
1665 SET_Uniform2iARB(exec, _mesa_Uniform2iARB);
1666 SET_Uniform3iARB(exec, _mesa_Uniform3iARB);
1667 SET_Uniform4iARB(exec, _mesa_Uniform4iARB);
1668 SET_Uniform1fvARB(exec, _mesa_Uniform1fvARB);
1669 SET_Uniform2fvARB(exec, _mesa_Uniform2fvARB);
1670 SET_Uniform3fvARB(exec, _mesa_Uniform3fvARB);
1671 SET_Uniform4fvARB(exec, _mesa_Uniform4fvARB);
1672 SET_Uniform1ivARB(exec, _mesa_Uniform1ivARB);
1673 SET_Uniform2ivARB(exec, _mesa_Uniform2ivARB);
1674 SET_Uniform3ivARB(exec, _mesa_Uniform3ivARB);
1675 SET_Uniform4ivARB(exec, _mesa_Uniform4ivARB);
1676 SET_UniformMatrix2fvARB(exec, _mesa_UniformMatrix2fvARB);
1677 SET_UniformMatrix3fvARB(exec, _mesa_UniformMatrix3fvARB);
1678 SET_UniformMatrix4fvARB(exec, _mesa_UniformMatrix4fvARB);
1679
1680 SET_GetActiveUniformARB(exec, _mesa_GetActiveUniformARB);
1681 SET_GetUniformLocationARB(exec, _mesa_GetUniformLocationARB);
1682 SET_GetUniformfvARB(exec, _mesa_GetUniformfvARB);
1683 SET_GetUniformivARB(exec, _mesa_GetUniformivARB);
1684
1685 /* OpenGL 2.1 */
1686 SET_UniformMatrix2x3fv(exec, _mesa_UniformMatrix2x3fv);
1687 SET_UniformMatrix3x2fv(exec, _mesa_UniformMatrix3x2fv);
1688 SET_UniformMatrix2x4fv(exec, _mesa_UniformMatrix2x4fv);
1689 SET_UniformMatrix4x2fv(exec, _mesa_UniformMatrix4x2fv);
1690 SET_UniformMatrix3x4fv(exec, _mesa_UniformMatrix3x4fv);
1691 SET_UniformMatrix4x3fv(exec, _mesa_UniformMatrix4x3fv);
1692
1693 /* OpenGL 3.0 */
1694 /* XXX finish dispatch */
1695 SET_Uniform1uiEXT(exec, _mesa_Uniform1ui);
1696 SET_Uniform2uiEXT(exec, _mesa_Uniform2ui);
1697 SET_Uniform3uiEXT(exec, _mesa_Uniform3ui);
1698 SET_Uniform4uiEXT(exec, _mesa_Uniform4ui);
1699 SET_Uniform1uivEXT(exec, _mesa_Uniform1uiv);
1700 SET_Uniform2uivEXT(exec, _mesa_Uniform2uiv);
1701 SET_Uniform3uivEXT(exec, _mesa_Uniform3uiv);
1702 SET_Uniform4uivEXT(exec, _mesa_Uniform4uiv);
1703 SET_GetUniformuivEXT(exec, _mesa_GetUniformuiv);
1704
1705
1706 #endif /* FEATURE_GL */
1707 }