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