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