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