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