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