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/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 glGetUniformuiv().
686 * New in GL_EXT_gpu_shader4, OpenGL 3.0
687 * \sa _mesa_get_uniformfv, only difference is a cast.
688 */
689 static void
690 _mesa_get_uniformuiv(struct gl_context *ctx, GLuint program, GLint location,
691 GLuint *params)
692 {
693 struct gl_program *prog;
694 GLint paramPos;
695 GLint offset;
696
697 split_location_offset(&location, &offset);
698
699 lookup_uniform_parameter(ctx, program, location, &prog, &paramPos);
700
701 if (prog) {
702 const struct gl_program_parameter *p =
703 &prog->Parameters->Parameters[paramPos];
704 GLint rows, cols, i, j, k;
705
706 get_uniform_rows_cols(p, &rows, &cols);
707
708 k = 0;
709 for (i = 0; i < rows; i++) {
710 for (j = 0; j < cols; j++ ) {
711 params[k++] = (GLuint) prog->Parameters->ParameterValues[paramPos+i][j];
712 }
713 }
714 }
715 }
716
717
718 /**
719 * Called via glGetUniformLocation().
720 *
721 * The return value will encode two values, the uniform location and an
722 * offset (used for arrays, structs).
723 */
724 GLint
725 _mesa_get_uniform_location(struct gl_context *ctx, struct gl_shader_program *shProg,
726 const GLchar *name)
727 {
728 GLint offset = 0, location = -1;
729
730 if (shProg->LinkStatus == GL_FALSE) {
731 _mesa_error(ctx, GL_INVALID_OPERATION, "glGetUniformfv(program)");
732 return -1;
733 }
734
735 /* XXX we should return -1 if the uniform was declared, but not
736 * actually used.
737 */
738
739 /* XXX we need to be able to parse uniform names for structs and arrays
740 * such as:
741 * mymatrix[1]
742 * mystruct.field1
743 */
744
745 {
746 /* handle 1-dimension arrays here... */
747 char *c = strchr(name, '[');
748 if (c) {
749 /* truncate name at [ */
750 const GLint len = c - name;
751 GLchar *newName = malloc(len + 1);
752 if (!newName)
753 return -1; /* out of mem */
754 memcpy(newName, name, len);
755 newName[len] = 0;
756
757 location = _mesa_lookup_uniform(shProg->Uniforms, newName);
758 if (location >= 0) {
759 const GLint element = atoi(c + 1);
760 if (element > 0) {
761 /* get type of the uniform array element */
762 struct gl_program_parameter *p;
763 p = get_uniform_parameter(shProg, location);
764 if (p) {
765 GLint rows, cols;
766 get_matrix_dims(p->DataType, &rows, &cols);
767 if (rows < 1)
768 rows = 1;
769 offset = element * rows;
770 }
771 }
772 }
773
774 free(newName);
775 }
776 }
777
778 if (location < 0) {
779 location = _mesa_lookup_uniform(shProg->Uniforms, name);
780 }
781
782 if (location >= 0) {
783 merge_location_offset(&location, offset);
784 }
785
786 return location;
787 }
788
789
790
791 /**
792 * Update the vertex/fragment program's TexturesUsed array.
793 *
794 * This needs to be called after glUniform(set sampler var) is called.
795 * A call to glUniform(samplerVar, value) causes a sampler to point to a
796 * particular texture unit. We know the sampler's texture target
797 * (1D/2D/3D/etc) from compile time but the sampler's texture unit is
798 * set by glUniform() calls.
799 *
800 * So, scan the program->SamplerUnits[] and program->SamplerTargets[]
801 * information to update the prog->TexturesUsed[] values.
802 * Each value of TexturesUsed[unit] is one of zero, TEXTURE_1D_INDEX,
803 * TEXTURE_2D_INDEX, TEXTURE_3D_INDEX, etc.
804 * We'll use that info for state validation before rendering.
805 */
806 void
807 _mesa_update_shader_textures_used(struct gl_program *prog)
808 {
809 GLuint s;
810
811 memset(prog->TexturesUsed, 0, sizeof(prog->TexturesUsed));
812
813 for (s = 0; s < MAX_SAMPLERS; s++) {
814 if (prog->SamplersUsed & (1 << s)) {
815 GLuint unit = prog->SamplerUnits[s];
816 GLuint tgt = prog->SamplerTargets[s];
817 assert(unit < MAX_TEXTURE_IMAGE_UNITS);
818 assert(tgt < NUM_TEXTURE_TARGETS);
819 prog->TexturesUsed[unit] |= (1 << tgt);
820 }
821 }
822 }
823
824
825 /**
826 * Check if the type given by userType is allowed to set a uniform of the
827 * target type. Generally, equivalence is required, but setting Boolean
828 * uniforms can be done with glUniformiv or glUniformfv.
829 */
830 static GLboolean
831 compatible_types(GLenum userType, GLenum targetType)
832 {
833 if (userType == targetType)
834 return GL_TRUE;
835
836 if (targetType == GL_BOOL && (userType == GL_FLOAT ||
837 userType == GL_UNSIGNED_INT ||
838 userType == GL_INT))
839 return GL_TRUE;
840
841 if (targetType == GL_BOOL_VEC2 && (userType == GL_FLOAT_VEC2 ||
842 userType == GL_UNSIGNED_INT_VEC2 ||
843 userType == GL_INT_VEC2))
844 return GL_TRUE;
845
846 if (targetType == GL_BOOL_VEC3 && (userType == GL_FLOAT_VEC3 ||
847 userType == GL_UNSIGNED_INT_VEC3 ||
848 userType == GL_INT_VEC3))
849 return GL_TRUE;
850
851 if (targetType == GL_BOOL_VEC4 && (userType == GL_FLOAT_VEC4 ||
852 userType == GL_UNSIGNED_INT_VEC4 ||
853 userType == GL_INT_VEC4))
854 return GL_TRUE;
855
856 if (is_sampler_type(targetType) && userType == GL_INT)
857 return GL_TRUE;
858
859 return GL_FALSE;
860 }
861
862
863 /**
864 * Set the value of a program's uniform variable.
865 * \param program the program whose uniform to update
866 * \param index the index of the program parameter for the uniform
867 * \param offset additional parameter slot offset (for arrays)
868 * \param type the incoming datatype of 'values'
869 * \param count the number of uniforms to set
870 * \param elems number of elements per uniform (1, 2, 3 or 4)
871 * \param values the new values, of datatype 'type'
872 */
873 static void
874 set_program_uniform(struct gl_context *ctx, struct gl_program *program,
875 GLint index, GLint offset,
876 GLenum type, GLsizei count, GLint elems,
877 const void *values)
878 {
879 const struct gl_program_parameter *param =
880 &program->Parameters->Parameters[index];
881
882 assert(offset >= 0);
883 assert(elems >= 1);
884 assert(elems <= 4);
885
886 if (!compatible_types(type, param->DataType)) {
887 _mesa_error(ctx, GL_INVALID_OPERATION, "glUniform(type mismatch)");
888 return;
889 }
890
891 if (index + offset > (GLint) program->Parameters->Size) {
892 /* out of bounds! */
893 return;
894 }
895
896 if (param->Type == PROGRAM_SAMPLER) {
897 /* This controls which texture unit which is used by a sampler */
898 GLboolean changed = GL_FALSE;
899 GLint i;
900
901 /* this should have been caught by the compatible_types() check */
902 ASSERT(type == GL_INT);
903
904 /* loop over number of samplers to change */
905 for (i = 0; i < count; i++) {
906 GLuint sampler =
907 (GLuint) program->Parameters->ParameterValues[index + offset + i][0];
908 GLuint texUnit = ((GLuint *) values)[i];
909
910 /* check that the sampler (tex unit index) is legal */
911 if (texUnit >= ctx->Const.MaxTextureImageUnits) {
912 _mesa_error(ctx, GL_INVALID_VALUE,
913 "glUniform1(invalid sampler/tex unit index for '%s')",
914 param->Name);
915 return;
916 }
917
918 /* This maps a sampler to a texture unit: */
919 if (sampler < MAX_SAMPLERS) {
920 #if 0
921 printf("Set program %p sampler %d '%s' to unit %u\n",
922 program, sampler, param->Name, texUnit);
923 #endif
924 if (program->SamplerUnits[sampler] != texUnit) {
925 program->SamplerUnits[sampler] = texUnit;
926 changed = GL_TRUE;
927 }
928 }
929 }
930
931 if (changed) {
932 /* When a sampler's value changes it usually requires rewriting
933 * a GPU program's TEX instructions since there may not be a
934 * sampler->texture lookup table. We signal this with the
935 * ProgramStringNotify() callback.
936 */
937 FLUSH_VERTICES(ctx, _NEW_TEXTURE | _NEW_PROGRAM);
938 _mesa_update_shader_textures_used(program);
939 /* Do we need to care about the return value here?
940 * This should not be the first time the driver was notified of
941 * this program.
942 */
943 (void) ctx->Driver.ProgramStringNotify(ctx, program->Target, program);
944 }
945 }
946 else {
947 /* ordinary uniform variable */
948 const GLboolean isUniformBool = is_boolean_type(param->DataType);
949 const GLenum basicType = base_uniform_type(type);
950 const GLint slots = (param->Size + 3) / 4;
951 const GLint typeSize = _mesa_sizeof_glsl_type(param->DataType);
952 GLsizei k, i;
953
954 if ((GLint) param->Size > typeSize) {
955 /* an array */
956 /* we'll ignore extra data below */
957 }
958 else {
959 /* non-array: count must be at most one; count == 0 is handled by the loop below */
960 if (count > 1) {
961 _mesa_error(ctx, GL_INVALID_OPERATION,
962 "glUniform(uniform '%s' is not an array)",
963 param->Name);
964 return;
965 }
966 }
967
968 /* loop over number of array elements */
969 for (k = 0; k < count; k++) {
970 GLfloat *uniformVal;
971
972 if (offset + k >= slots) {
973 /* Extra array data is ignored */
974 break;
975 }
976
977 /* uniformVal (the destination) is always float[4] */
978 uniformVal = program->Parameters->ParameterValues[index + offset + k];
979
980 if (basicType == GL_INT) {
981 /* convert user's ints to floats */
982 const GLint *iValues = ((const GLint *) values) + k * elems;
983 for (i = 0; i < elems; i++) {
984 uniformVal[i] = (GLfloat) iValues[i];
985 }
986 }
987 else if (basicType == GL_UNSIGNED_INT) {
988 /* convert user's uints to floats */
989 const GLuint *iValues = ((const GLuint *) values) + k * elems;
990 for (i = 0; i < elems; i++) {
991 uniformVal[i] = (GLfloat) iValues[i];
992 }
993 }
994 else {
995 const GLfloat *fValues = ((const GLfloat *) values) + k * elems;
996 assert(basicType == GL_FLOAT);
997 for (i = 0; i < elems; i++) {
998 uniformVal[i] = fValues[i];
999 }
1000 }
1001
1002 /* if the uniform is bool-valued, convert to 1.0 or 0.0 */
1003 if (isUniformBool) {
1004 for (i = 0; i < elems; i++) {
1005 uniformVal[i] = uniformVal[i] ? 1.0f : 0.0f;
1006 }
1007 }
1008 }
1009 }
1010 }
1011
1012
1013 /**
1014 * Called via glUniform*() functions.
1015 */
1016 void
1017 _mesa_uniform(struct gl_context *ctx, struct gl_shader_program *shProg,
1018 GLint location, GLsizei count,
1019 const GLvoid *values, GLenum type)
1020 {
1021 struct gl_uniform *uniform;
1022 GLint elems, offset;
1023
1024 if (!shProg || !shProg->LinkStatus) {
1025 _mesa_error(ctx, GL_INVALID_OPERATION, "glUniform(program not linked)");
1026 return;
1027 }
1028
1029 if (location == -1)
1030 return; /* The standard specifies this as a no-op */
1031
1032 if (location < -1) {
1033 _mesa_error(ctx, GL_INVALID_OPERATION, "glUniform(location=%d)",
1034 location);
1035 return;
1036 }
1037
1038 split_location_offset(&location, &offset);
1039
1040 if (location < 0 || location >= (GLint) shProg->Uniforms->NumUniforms) {
1041 _mesa_error(ctx, GL_INVALID_VALUE, "glUniform(location=%d)", location);
1042 return;
1043 }
1044
1045 if (count < 0) {
1046 _mesa_error(ctx, GL_INVALID_VALUE, "glUniform(count < 0)");
1047 return;
1048 }
1049
1050 elems = _mesa_sizeof_glsl_type(type);
1051
1052 FLUSH_VERTICES(ctx, _NEW_PROGRAM_CONSTANTS);
1053
1054 uniform = &shProg->Uniforms->Uniforms[location];
1055
1056 if (ctx->Shader.Flags & GLSL_UNIFORMS) {
1057 const GLenum basicType = base_uniform_type(type);
1058 GLint i;
1059 printf("Mesa: set program %u uniform %s (loc %d) to: ",
1060 shProg->Name, uniform->Name, location);
1061 if (basicType == GL_INT) {
1062 const GLint *v = (const GLint *) values;
1063 for (i = 0; i < count * elems; i++) {
1064 printf("%d ", v[i]);
1065 }
1066 }
1067 else if (basicType == GL_UNSIGNED_INT) {
1068 const GLuint *v = (const GLuint *) values;
1069 for (i = 0; i < count * elems; i++) {
1070 printf("%u ", v[i]);
1071 }
1072 }
1073 else {
1074 const GLfloat *v = (const GLfloat *) values;
1075 assert(basicType == GL_FLOAT);
1076 for (i = 0; i < count * elems; i++) {
1077 printf("%g ", v[i]);
1078 }
1079 }
1080 printf("\n");
1081 }
1082
1083 /* A uniform var may be used by both a vertex shader and a fragment
1084 * shader. We may need to update one or both shader's uniform here:
1085 */
1086 if (shProg->VertexProgram) {
1087 /* convert uniform location to program parameter index */
1088 GLint index = uniform->VertPos;
1089 if (index >= 0) {
1090 set_program_uniform(ctx, &shProg->VertexProgram->Base,
1091 index, offset, type, count, elems, values);
1092 }
1093 }
1094
1095 if (shProg->FragmentProgram) {
1096 /* convert uniform location to program parameter index */
1097 GLint index = uniform->FragPos;
1098 if (index >= 0) {
1099 set_program_uniform(ctx, &shProg->FragmentProgram->Base,
1100 index, offset, type, count, elems, values);
1101 }
1102 }
1103
1104 if (shProg->GeometryProgram) {
1105 /* convert uniform location to program parameter index */
1106 GLint index = uniform->GeomPos;
1107 if (index >= 0) {
1108 set_program_uniform(ctx, &shProg->GeometryProgram->Base,
1109 index, offset, type, count, elems, values);
1110 }
1111 }
1112
1113 uniform->Initialized = GL_TRUE;
1114 }
1115
1116
1117 /**
1118 * Set a matrix-valued program parameter.
1119 */
1120 static void
1121 set_program_uniform_matrix(struct gl_context *ctx, struct gl_program *program,
1122 GLuint index, GLuint offset,
1123 GLuint count, GLuint rows, GLuint cols,
1124 GLboolean transpose, const GLfloat *values)
1125 {
1126 GLuint mat, row, col;
1127 GLuint src = 0;
1128 const struct gl_program_parameter * param = &program->Parameters->Parameters[index];
1129 const GLuint slots = (param->Size + 3) / 4;
1130 const GLint typeSize = _mesa_sizeof_glsl_type(param->DataType);
1131 GLint nr, nc;
1132
1133 /* check that the number of rows, columns is correct */
1134 get_matrix_dims(param->DataType, &nr, &nc);
1135 if (rows != nr || cols != nc) {
1136 _mesa_error(ctx, GL_INVALID_OPERATION,
1137 "glUniformMatrix(matrix size mismatch)");
1138 return;
1139 }
1140
1141 if ((GLint) param->Size <= typeSize) {
1142 /* non-array: count must be at most one; count == 0 is handled by the loop below */
1143 if (count > 1) {
1144 _mesa_error(ctx, GL_INVALID_OPERATION,
1145 "glUniformMatrix(uniform is not an array)");
1146 return;
1147 }
1148 }
1149
1150 /*
1151 * Note: the _columns_ of a matrix are stored in program registers, not
1152 * the rows. So, the loops below look a little funny.
1153 * XXX could optimize this a bit...
1154 */
1155
1156 /* loop over matrices */
1157 for (mat = 0; mat < count; mat++) {
1158
1159 /* each matrix: */
1160 for (col = 0; col < cols; col++) {
1161 GLfloat *v;
1162 if (offset >= slots) {
1163 /* Ignore writes beyond the end of (the used part of) an array */
1164 return;
1165 }
1166 v = program->Parameters->ParameterValues[index + offset];
1167 for (row = 0; row < rows; row++) {
1168 if (transpose) {
1169 v[row] = values[src + row * cols + col];
1170 }
1171 else {
1172 v[row] = values[src + col * rows + row];
1173 }
1174 }
1175
1176 offset++;
1177 }
1178
1179 src += rows * cols; /* next matrix */
1180 }
1181 }
1182
1183
1184 /**
1185 * Called by glUniformMatrix*() functions.
1186 * Note: cols=2, rows=4 ==> array[2] of vec4
1187 */
1188 void
1189 _mesa_uniform_matrix(struct gl_context *ctx, struct gl_shader_program *shProg,
1190 GLint cols, GLint rows,
1191 GLint location, GLsizei count,
1192 GLboolean transpose, const GLfloat *values)
1193 {
1194 struct gl_uniform *uniform;
1195 GLint offset;
1196
1197 if (!shProg || !shProg->LinkStatus) {
1198 _mesa_error(ctx, GL_INVALID_OPERATION,
1199 "glUniformMatrix(program not linked)");
1200 return;
1201 }
1202
1203 if (location == -1)
1204 return; /* The standard specifies this as a no-op */
1205
1206 if (location < -1) {
1207 _mesa_error(ctx, GL_INVALID_OPERATION, "glUniformMatrix(location)");
1208 return;
1209 }
1210
1211 split_location_offset(&location, &offset);
1212
1213 if (location < 0 || location >= (GLint) shProg->Uniforms->NumUniforms) {
1214 _mesa_error(ctx, GL_INVALID_VALUE, "glUniformMatrix(location)");
1215 return;
1216 }
1217 if (values == NULL) {
1218 _mesa_error(ctx, GL_INVALID_VALUE, "glUniformMatrix");
1219 return;
1220 }
1221
1222 FLUSH_VERTICES(ctx, _NEW_PROGRAM_CONSTANTS);
1223
1224 uniform = &shProg->Uniforms->Uniforms[location];
1225
1226 if (shProg->VertexProgram) {
1227 /* convert uniform location to program parameter index */
1228 GLint index = uniform->VertPos;
1229 if (index >= 0) {
1230 set_program_uniform_matrix(ctx, &shProg->VertexProgram->Base,
1231 index, offset,
1232 count, rows, cols, transpose, values);
1233 }
1234 }
1235
1236 if (shProg->FragmentProgram) {
1237 /* convert uniform location to program parameter index */
1238 GLint index = uniform->FragPos;
1239 if (index >= 0) {
1240 set_program_uniform_matrix(ctx, &shProg->FragmentProgram->Base,
1241 index, offset,
1242 count, rows, cols, transpose, values);
1243 }
1244 }
1245
1246 if (shProg->GeometryProgram) {
1247 /* convert uniform location to program parameter index */
1248 GLint index = uniform->GeomPos;
1249 if (index >= 0) {
1250 set_program_uniform_matrix(ctx, &shProg->GeometryProgram->Base,
1251 index, offset,
1252 count, rows, cols, transpose, values);
1253 }
1254 }
1255
1256 uniform->Initialized = GL_TRUE;
1257 }
1258
1259
1260 void GLAPIENTRY
1261 _mesa_Uniform1fARB(GLint location, GLfloat v0)
1262 {
1263 GET_CURRENT_CONTEXT(ctx);
1264 _mesa_uniform(ctx, ctx->Shader.ActiveProgram, location, 1, &v0, GL_FLOAT);
1265 }
1266
1267 void GLAPIENTRY
1268 _mesa_Uniform2fARB(GLint location, GLfloat v0, GLfloat v1)
1269 {
1270 GET_CURRENT_CONTEXT(ctx);
1271 GLfloat v[2];
1272 v[0] = v0;
1273 v[1] = v1;
1274 _mesa_uniform(ctx, ctx->Shader.ActiveProgram, location, 1, v, GL_FLOAT_VEC2);
1275 }
1276
1277 void GLAPIENTRY
1278 _mesa_Uniform3fARB(GLint location, GLfloat v0, GLfloat v1, GLfloat v2)
1279 {
1280 GET_CURRENT_CONTEXT(ctx);
1281 GLfloat v[3];
1282 v[0] = v0;
1283 v[1] = v1;
1284 v[2] = v2;
1285 _mesa_uniform(ctx, ctx->Shader.ActiveProgram, location, 1, v, GL_FLOAT_VEC3);
1286 }
1287
1288 void GLAPIENTRY
1289 _mesa_Uniform4fARB(GLint location, GLfloat v0, GLfloat v1, GLfloat v2,
1290 GLfloat v3)
1291 {
1292 GET_CURRENT_CONTEXT(ctx);
1293 GLfloat v[4];
1294 v[0] = v0;
1295 v[1] = v1;
1296 v[2] = v2;
1297 v[3] = v3;
1298 _mesa_uniform(ctx, ctx->Shader.ActiveProgram, location, 1, v, GL_FLOAT_VEC4);
1299 }
1300
1301 void GLAPIENTRY
1302 _mesa_Uniform1iARB(GLint location, GLint v0)
1303 {
1304 GET_CURRENT_CONTEXT(ctx);
1305 _mesa_uniform(ctx, ctx->Shader.ActiveProgram, location, 1, &v0, GL_INT);
1306 }
1307
1308 void GLAPIENTRY
1309 _mesa_Uniform2iARB(GLint location, GLint v0, GLint v1)
1310 {
1311 GET_CURRENT_CONTEXT(ctx);
1312 GLint v[2];
1313 v[0] = v0;
1314 v[1] = v1;
1315 _mesa_uniform(ctx, ctx->Shader.ActiveProgram, location, 1, v, GL_INT_VEC2);
1316 }
1317
1318 void GLAPIENTRY
1319 _mesa_Uniform3iARB(GLint location, GLint v0, GLint v1, GLint v2)
1320 {
1321 GET_CURRENT_CONTEXT(ctx);
1322 GLint v[3];
1323 v[0] = v0;
1324 v[1] = v1;
1325 v[2] = v2;
1326 _mesa_uniform(ctx, ctx->Shader.ActiveProgram, location, 1, v, GL_INT_VEC3);
1327 }
1328
1329 void GLAPIENTRY
1330 _mesa_Uniform4iARB(GLint location, GLint v0, GLint v1, GLint v2, GLint v3)
1331 {
1332 GET_CURRENT_CONTEXT(ctx);
1333 GLint v[4];
1334 v[0] = v0;
1335 v[1] = v1;
1336 v[2] = v2;
1337 v[3] = v3;
1338 _mesa_uniform(ctx, ctx->Shader.ActiveProgram, location, 1, v, GL_INT_VEC4);
1339 }
1340
1341 void GLAPIENTRY
1342 _mesa_Uniform1fvARB(GLint location, GLsizei count, const GLfloat * value)
1343 {
1344 GET_CURRENT_CONTEXT(ctx);
1345 _mesa_uniform(ctx, ctx->Shader.ActiveProgram, location, count, value, GL_FLOAT);
1346 }
1347
1348 void GLAPIENTRY
1349 _mesa_Uniform2fvARB(GLint location, GLsizei count, const GLfloat * value)
1350 {
1351 GET_CURRENT_CONTEXT(ctx);
1352 _mesa_uniform(ctx, ctx->Shader.ActiveProgram, location, count, value, GL_FLOAT_VEC2);
1353 }
1354
1355 void GLAPIENTRY
1356 _mesa_Uniform3fvARB(GLint location, GLsizei count, const GLfloat * value)
1357 {
1358 GET_CURRENT_CONTEXT(ctx);
1359 _mesa_uniform(ctx, ctx->Shader.ActiveProgram, location, count, value, GL_FLOAT_VEC3);
1360 }
1361
1362 void GLAPIENTRY
1363 _mesa_Uniform4fvARB(GLint location, GLsizei count, const GLfloat * value)
1364 {
1365 GET_CURRENT_CONTEXT(ctx);
1366 _mesa_uniform(ctx, ctx->Shader.ActiveProgram, location, count, value, GL_FLOAT_VEC4);
1367 }
1368
1369 void GLAPIENTRY
1370 _mesa_Uniform1ivARB(GLint location, GLsizei count, const GLint * value)
1371 {
1372 GET_CURRENT_CONTEXT(ctx);
1373 _mesa_uniform(ctx, ctx->Shader.ActiveProgram, location, count, value, GL_INT);
1374 }
1375
1376 void GLAPIENTRY
1377 _mesa_Uniform2ivARB(GLint location, GLsizei count, const GLint * value)
1378 {
1379 GET_CURRENT_CONTEXT(ctx);
1380 _mesa_uniform(ctx, ctx->Shader.ActiveProgram, location, count, value, GL_INT_VEC2);
1381 }
1382
1383 void GLAPIENTRY
1384 _mesa_Uniform3ivARB(GLint location, GLsizei count, const GLint * value)
1385 {
1386 GET_CURRENT_CONTEXT(ctx);
1387 _mesa_uniform(ctx, ctx->Shader.ActiveProgram, location, count, value, GL_INT_VEC3);
1388 }
1389
1390 void GLAPIENTRY
1391 _mesa_Uniform4ivARB(GLint location, GLsizei count, const GLint * value)
1392 {
1393 GET_CURRENT_CONTEXT(ctx);
1394 _mesa_uniform(ctx, ctx->Shader.ActiveProgram, location, count, value, GL_INT_VEC4);
1395 }
1396
1397
1398 /** OpenGL 3.0 GLuint-valued functions **/
1399 void GLAPIENTRY
1400 _mesa_Uniform1ui(GLint location, GLuint v0)
1401 {
1402 GET_CURRENT_CONTEXT(ctx);
1403 _mesa_uniform(ctx, ctx->Shader.ActiveProgram, location, 1, &v0, GL_UNSIGNED_INT);
1404 }
1405
1406 void GLAPIENTRY
1407 _mesa_Uniform2ui(GLint location, GLuint v0, GLuint v1)
1408 {
1409 GET_CURRENT_CONTEXT(ctx);
1410 GLuint v[2];
1411 v[0] = v0;
1412 v[1] = v1;
1413 _mesa_uniform(ctx, ctx->Shader.ActiveProgram, location, 1, v, GL_UNSIGNED_INT_VEC2);
1414 }
1415
1416 void GLAPIENTRY
1417 _mesa_Uniform3ui(GLint location, GLuint v0, GLuint v1, GLuint v2)
1418 {
1419 GET_CURRENT_CONTEXT(ctx);
1420 GLuint v[3];
1421 v[0] = v0;
1422 v[1] = v1;
1423 v[2] = v2;
1424 _mesa_uniform(ctx, ctx->Shader.ActiveProgram, location, 1, v, GL_UNSIGNED_INT_VEC3);
1425 }
1426
1427 void GLAPIENTRY
1428 _mesa_Uniform4ui(GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3)
1429 {
1430 GET_CURRENT_CONTEXT(ctx);
1431 GLuint v[4];
1432 v[0] = v0;
1433 v[1] = v1;
1434 v[2] = v2;
1435 v[3] = v3;
1436 _mesa_uniform(ctx, ctx->Shader.ActiveProgram, location, 1, v, GL_UNSIGNED_INT_VEC4);
1437 }
1438
1439 void GLAPIENTRY
1440 _mesa_Uniform1uiv(GLint location, GLsizei count, const GLuint *value)
1441 {
1442 GET_CURRENT_CONTEXT(ctx);
1443 _mesa_uniform(ctx, ctx->Shader.ActiveProgram, location, count, value, GL_UNSIGNED_INT);
1444 }
1445
1446 void GLAPIENTRY
1447 _mesa_Uniform2uiv(GLint location, GLsizei count, const GLuint *value)
1448 {
1449 GET_CURRENT_CONTEXT(ctx);
1450 _mesa_uniform(ctx, ctx->Shader.ActiveProgram, location, count, value, GL_UNSIGNED_INT_VEC2);
1451 }
1452
1453 void GLAPIENTRY
1454 _mesa_Uniform3uiv(GLint location, GLsizei count, const GLuint *value)
1455 {
1456 GET_CURRENT_CONTEXT(ctx);
1457 _mesa_uniform(ctx, ctx->Shader.ActiveProgram, location, count, value, GL_UNSIGNED_INT_VEC3);
1458 }
1459
1460 void GLAPIENTRY
1461 _mesa_Uniform4uiv(GLint location, GLsizei count, const GLuint *value)
1462 {
1463 GET_CURRENT_CONTEXT(ctx);
1464 _mesa_uniform(ctx, ctx->Shader.ActiveProgram, location, count, value, GL_UNSIGNED_INT_VEC4);
1465 }
1466
1467
1468
1469 void GLAPIENTRY
1470 _mesa_UniformMatrix2fvARB(GLint location, GLsizei count, GLboolean transpose,
1471 const GLfloat * value)
1472 {
1473 GET_CURRENT_CONTEXT(ctx);
1474 _mesa_uniform_matrix(ctx, ctx->Shader.ActiveProgram,
1475 2, 2, location, count, transpose, value);
1476 }
1477
1478 void GLAPIENTRY
1479 _mesa_UniformMatrix3fvARB(GLint location, GLsizei count, GLboolean transpose,
1480 const GLfloat * value)
1481 {
1482 GET_CURRENT_CONTEXT(ctx);
1483 _mesa_uniform_matrix(ctx, ctx->Shader.ActiveProgram,
1484 3, 3, location, count, transpose, value);
1485 }
1486
1487 void GLAPIENTRY
1488 _mesa_UniformMatrix4fvARB(GLint location, GLsizei count, GLboolean transpose,
1489 const GLfloat * value)
1490 {
1491 GET_CURRENT_CONTEXT(ctx);
1492 _mesa_uniform_matrix(ctx, ctx->Shader.ActiveProgram,
1493 4, 4, location, count, transpose, value);
1494 }
1495
1496
1497 /**
1498 * Non-square UniformMatrix are OpenGL 2.1
1499 */
1500 void GLAPIENTRY
1501 _mesa_UniformMatrix2x3fv(GLint location, GLsizei count, GLboolean transpose,
1502 const GLfloat *value)
1503 {
1504 GET_CURRENT_CONTEXT(ctx);
1505 _mesa_uniform_matrix(ctx, ctx->Shader.ActiveProgram,
1506 2, 3, location, count, transpose, value);
1507 }
1508
1509 void GLAPIENTRY
1510 _mesa_UniformMatrix3x2fv(GLint location, GLsizei count, GLboolean transpose,
1511 const GLfloat *value)
1512 {
1513 GET_CURRENT_CONTEXT(ctx);
1514 _mesa_uniform_matrix(ctx, ctx->Shader.ActiveProgram,
1515 3, 2, location, count, transpose, value);
1516 }
1517
1518 void GLAPIENTRY
1519 _mesa_UniformMatrix2x4fv(GLint location, GLsizei count, GLboolean transpose,
1520 const GLfloat *value)
1521 {
1522 GET_CURRENT_CONTEXT(ctx);
1523 _mesa_uniform_matrix(ctx, ctx->Shader.ActiveProgram,
1524 2, 4, location, count, transpose, value);
1525 }
1526
1527 void GLAPIENTRY
1528 _mesa_UniformMatrix4x2fv(GLint location, GLsizei count, GLboolean transpose,
1529 const GLfloat *value)
1530 {
1531 GET_CURRENT_CONTEXT(ctx);
1532 _mesa_uniform_matrix(ctx, ctx->Shader.ActiveProgram,
1533 4, 2, location, count, transpose, value);
1534 }
1535
1536 void GLAPIENTRY
1537 _mesa_UniformMatrix3x4fv(GLint location, GLsizei count, GLboolean transpose,
1538 const GLfloat *value)
1539 {
1540 GET_CURRENT_CONTEXT(ctx);
1541 _mesa_uniform_matrix(ctx, ctx->Shader.ActiveProgram,
1542 3, 4, location, count, transpose, value);
1543 }
1544
1545 void GLAPIENTRY
1546 _mesa_UniformMatrix4x3fv(GLint location, GLsizei count, GLboolean transpose,
1547 const GLfloat *value)
1548 {
1549 GET_CURRENT_CONTEXT(ctx);
1550 _mesa_uniform_matrix(ctx, ctx->Shader.ActiveProgram,
1551 4, 3, location, count, transpose, value);
1552 }
1553
1554
1555 void GLAPIENTRY
1556 _mesa_GetUniformfvARB(GLhandleARB program, GLint location, GLfloat *params)
1557 {
1558 GET_CURRENT_CONTEXT(ctx);
1559 _mesa_get_uniformfv(ctx, program, location, params);
1560 }
1561
1562
1563 void GLAPIENTRY
1564 _mesa_GetUniformivARB(GLhandleARB program, GLint location, GLint *params)
1565 {
1566 GET_CURRENT_CONTEXT(ctx);
1567 _mesa_get_uniformiv(ctx, program, location, params);
1568 }
1569
1570
1571 /* GL3 */
1572 void GLAPIENTRY
1573 _mesa_GetUniformuiv(GLhandleARB program, GLint location, GLuint *params)
1574 {
1575 GET_CURRENT_CONTEXT(ctx);
1576 _mesa_get_uniformuiv(ctx, program, location, params);
1577 }
1578
1579
1580
1581 GLint GLAPIENTRY
1582 _mesa_GetUniformLocationARB(GLhandleARB programObj, const GLcharARB *name)
1583 {
1584 struct gl_shader_program *shProg;
1585
1586 GET_CURRENT_CONTEXT(ctx);
1587
1588 shProg = _mesa_lookup_shader_program_err(ctx, programObj,
1589 "glGetUniformLocation");
1590 if (!shProg)
1591 return -1;
1592
1593 return _mesa_get_uniform_location(ctx, shProg, name);
1594 }
1595
1596
1597 void GLAPIENTRY
1598 _mesa_GetActiveUniformARB(GLhandleARB program, GLuint index,
1599 GLsizei maxLength, GLsizei * length, GLint * size,
1600 GLenum * type, GLcharARB * name)
1601 {
1602 GET_CURRENT_CONTEXT(ctx);
1603 _mesa_get_active_uniform(ctx, program, index, maxLength, length, size,
1604 type, name);
1605 }
1606
1607
1608 /**
1609 * Plug in shader uniform-related functions into API dispatch table.
1610 */
1611 void
1612 _mesa_init_shader_uniform_dispatch(struct _glapi_table *exec)
1613 {
1614 #if FEATURE_GL
1615 SET_Uniform1fARB(exec, _mesa_Uniform1fARB);
1616 SET_Uniform2fARB(exec, _mesa_Uniform2fARB);
1617 SET_Uniform3fARB(exec, _mesa_Uniform3fARB);
1618 SET_Uniform4fARB(exec, _mesa_Uniform4fARB);
1619 SET_Uniform1iARB(exec, _mesa_Uniform1iARB);
1620 SET_Uniform2iARB(exec, _mesa_Uniform2iARB);
1621 SET_Uniform3iARB(exec, _mesa_Uniform3iARB);
1622 SET_Uniform4iARB(exec, _mesa_Uniform4iARB);
1623 SET_Uniform1fvARB(exec, _mesa_Uniform1fvARB);
1624 SET_Uniform2fvARB(exec, _mesa_Uniform2fvARB);
1625 SET_Uniform3fvARB(exec, _mesa_Uniform3fvARB);
1626 SET_Uniform4fvARB(exec, _mesa_Uniform4fvARB);
1627 SET_Uniform1ivARB(exec, _mesa_Uniform1ivARB);
1628 SET_Uniform2ivARB(exec, _mesa_Uniform2ivARB);
1629 SET_Uniform3ivARB(exec, _mesa_Uniform3ivARB);
1630 SET_Uniform4ivARB(exec, _mesa_Uniform4ivARB);
1631 SET_UniformMatrix2fvARB(exec, _mesa_UniformMatrix2fvARB);
1632 SET_UniformMatrix3fvARB(exec, _mesa_UniformMatrix3fvARB);
1633 SET_UniformMatrix4fvARB(exec, _mesa_UniformMatrix4fvARB);
1634
1635 SET_GetActiveUniformARB(exec, _mesa_GetActiveUniformARB);
1636 SET_GetUniformLocationARB(exec, _mesa_GetUniformLocationARB);
1637 SET_GetUniformfvARB(exec, _mesa_GetUniformfvARB);
1638 SET_GetUniformivARB(exec, _mesa_GetUniformivARB);
1639
1640 /* OpenGL 2.1 */
1641 SET_UniformMatrix2x3fv(exec, _mesa_UniformMatrix2x3fv);
1642 SET_UniformMatrix3x2fv(exec, _mesa_UniformMatrix3x2fv);
1643 SET_UniformMatrix2x4fv(exec, _mesa_UniformMatrix2x4fv);
1644 SET_UniformMatrix4x2fv(exec, _mesa_UniformMatrix4x2fv);
1645 SET_UniformMatrix3x4fv(exec, _mesa_UniformMatrix3x4fv);
1646 SET_UniformMatrix4x3fv(exec, _mesa_UniformMatrix4x3fv);
1647
1648 /* OpenGL 3.0 */
1649 /* XXX finish dispatch */
1650 SET_Uniform1uiEXT(exec, _mesa_Uniform1ui);
1651 SET_Uniform2uiEXT(exec, _mesa_Uniform2ui);
1652 SET_Uniform3uiEXT(exec, _mesa_Uniform3ui);
1653 SET_Uniform4uiEXT(exec, _mesa_Uniform4ui);
1654 SET_Uniform1uivEXT(exec, _mesa_Uniform1uiv);
1655 SET_Uniform2uivEXT(exec, _mesa_Uniform2uiv);
1656 SET_Uniform3uivEXT(exec, _mesa_Uniform3uiv);
1657 SET_Uniform4uivEXT(exec, _mesa_Uniform4uiv);
1658 SET_GetUniformuivEXT(exec, _mesa_GetUniformuiv);
1659
1660
1661 #endif /* FEATURE_GL */
1662 }