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