Merge remote-tracking 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 GLsizei bufSize, GLfloat *params)
416 {
417 struct gl_program *prog;
418 GLint paramPos, offset;
419
420 split_location_offset(&location, &offset);
421
422 lookup_uniform_parameter(ctx, program, location, &prog, &paramPos);
423
424 if (prog) {
425 const struct gl_program_parameter *p =
426 &prog->Parameters->Parameters[paramPos];
427 GLint rows, cols, i, j, k;
428 GLsizei numBytes;
429
430 get_uniform_rows_cols(p, &rows, &cols);
431
432 numBytes = rows * cols * sizeof *params;
433 if (bufSize < numBytes) {
434 _mesa_error( ctx, GL_INVALID_OPERATION,
435 "glGetnUniformfvARB(out of bounds: bufSize is %d,"
436 " but %d bytes are required)", bufSize, numBytes );
437 return;
438 }
439
440 k = 0;
441 for (i = 0; i < rows; i++) {
442 const int base = paramPos + offset + i;
443
444 for (j = 0; j < cols; j++ ) {
445 params[k++] = prog->Parameters->ParameterValues[base][j];
446 }
447 }
448 }
449 }
450
451
452 /**
453 * Called via glGetUniformiv().
454 * \sa _mesa_get_uniformfv, only difference is a cast.
455 */
456 static void
457 _mesa_get_uniformiv(struct gl_context *ctx, GLuint program, GLint location,
458 GLsizei bufSize, GLint *params)
459 {
460 struct gl_program *prog;
461 GLint paramPos, offset;
462
463 split_location_offset(&location, &offset);
464
465 lookup_uniform_parameter(ctx, program, location, &prog, &paramPos);
466
467 if (prog) {
468 const struct gl_program_parameter *p =
469 &prog->Parameters->Parameters[paramPos];
470 GLint rows, cols, i, j, k;
471 GLsizei numBytes;
472
473 get_uniform_rows_cols(p, &rows, &cols);
474
475 numBytes = rows * cols * sizeof *params;
476 if (bufSize < numBytes) {
477 _mesa_error( ctx, GL_INVALID_OPERATION,
478 "glGetnUniformivARB(out of bounds: bufSize is %d,"
479 " but %d bytes are required)", bufSize, numBytes );
480 return;
481 }
482
483 k = 0;
484 for (i = 0; i < rows; i++) {
485 const int base = paramPos + offset + i;
486
487 for (j = 0; j < cols; j++ ) {
488 params[k++] = (GLint) prog->Parameters->ParameterValues[base][j];
489 }
490 }
491 }
492 }
493
494
495 /**
496 * Called via glGetUniformuiv().
497 * New in GL_EXT_gpu_shader4, OpenGL 3.0
498 * \sa _mesa_get_uniformfv, only difference is a cast.
499 */
500 static void
501 _mesa_get_uniformuiv(struct gl_context *ctx, GLuint program, GLint location,
502 GLsizei bufSize, GLuint *params)
503 {
504 struct gl_program *prog;
505 GLint paramPos, offset;
506
507 split_location_offset(&location, &offset);
508
509 lookup_uniform_parameter(ctx, program, location, &prog, &paramPos);
510
511 if (prog) {
512 const struct gl_program_parameter *p =
513 &prog->Parameters->Parameters[paramPos];
514 GLint rows, cols, i, j, k;
515 GLsizei numBytes;
516
517 get_uniform_rows_cols(p, &rows, &cols);
518
519 numBytes = rows * cols * sizeof *params;
520 if (bufSize < numBytes) {
521 _mesa_error( ctx, GL_INVALID_OPERATION,
522 "glGetnUniformuivARB(out of bounds: bufSize is %d,"
523 " but %d bytes are required)", bufSize, numBytes );
524 return;
525 }
526
527 k = 0;
528 for (i = 0; i < rows; i++) {
529 const int base = paramPos + offset + i;
530
531 for (j = 0; j < cols; j++ ) {
532 params[k++] = (GLuint) prog->Parameters->ParameterValues[base][j];
533 }
534 }
535 }
536 }
537
538
539 /**
540 * Called via glGetUniformdv().
541 * New in GL_ARB_gpu_shader_fp64, OpenGL 4.0
542 */
543 static void
544 _mesa_get_uniformdv(struct gl_context *ctx, GLuint program, GLint location,
545 GLsizei bufSize, GLdouble *params)
546 {
547 _mesa_error(ctx, GL_INVALID_OPERATION, "glGetUniformdvARB"
548 "(GL_ARB_gpu_shader_fp64 not implemented)");
549 }
550
551
552 /**
553 * Called via glGetUniformLocation().
554 *
555 * The return value will encode two values, the uniform location and an
556 * offset (used for arrays, structs).
557 */
558 GLint
559 _mesa_get_uniform_location(struct gl_context *ctx, struct gl_shader_program *shProg,
560 const GLchar *name)
561 {
562 GLint offset = 0, location = -1;
563
564 if (shProg->LinkStatus == GL_FALSE) {
565 _mesa_error(ctx, GL_INVALID_OPERATION, "glGetUniformfv(program)");
566 return -1;
567 }
568
569 /* XXX we should return -1 if the uniform was declared, but not
570 * actually used.
571 */
572
573 /* XXX we need to be able to parse uniform names for structs and arrays
574 * such as:
575 * mymatrix[1]
576 * mystruct.field1
577 */
578
579 {
580 /* handle 1-dimension arrays here... */
581 char *c = strchr(name, '[');
582 if (c) {
583 /* truncate name at [ */
584 const GLint len = c - name;
585 GLchar *newName = malloc(len + 1);
586 if (!newName)
587 return -1; /* out of mem */
588 memcpy(newName, name, len);
589 newName[len] = 0;
590
591 location = _mesa_lookup_uniform(shProg->Uniforms, newName);
592 if (location >= 0) {
593 const GLint element = atoi(c + 1);
594 if (element > 0) {
595 /* get type of the uniform array element */
596 struct gl_program_parameter *p;
597 p = get_uniform_parameter(shProg, location);
598 if (p) {
599 GLint rows, cols;
600 get_matrix_dims(p->DataType, &rows, &cols);
601 if (rows < 1)
602 rows = 1;
603 offset = element * rows;
604 }
605 }
606 }
607
608 free(newName);
609 }
610 }
611
612 if (location < 0) {
613 location = _mesa_lookup_uniform(shProg->Uniforms, name);
614 }
615
616 if (location >= 0) {
617 merge_location_offset(&location, offset);
618 }
619
620 return location;
621 }
622
623
624
625 /**
626 * Update the vertex/fragment program's TexturesUsed array.
627 *
628 * This needs to be called after glUniform(set sampler var) is called.
629 * A call to glUniform(samplerVar, value) causes a sampler to point to a
630 * particular texture unit. We know the sampler's texture target
631 * (1D/2D/3D/etc) from compile time but the sampler's texture unit is
632 * set by glUniform() calls.
633 *
634 * So, scan the program->SamplerUnits[] and program->SamplerTargets[]
635 * information to update the prog->TexturesUsed[] values.
636 * Each value of TexturesUsed[unit] is one of zero, TEXTURE_1D_INDEX,
637 * TEXTURE_2D_INDEX, TEXTURE_3D_INDEX, etc.
638 * We'll use that info for state validation before rendering.
639 */
640 void
641 _mesa_update_shader_textures_used(struct gl_program *prog)
642 {
643 GLuint s;
644
645 memset(prog->TexturesUsed, 0, sizeof(prog->TexturesUsed));
646
647 for (s = 0; s < MAX_SAMPLERS; s++) {
648 if (prog->SamplersUsed & (1 << s)) {
649 GLuint unit = prog->SamplerUnits[s];
650 GLuint tgt = prog->SamplerTargets[s];
651 assert(unit < MAX_TEXTURE_IMAGE_UNITS);
652 assert(tgt < NUM_TEXTURE_TARGETS);
653 prog->TexturesUsed[unit] |= (1 << tgt);
654 }
655 }
656 }
657
658
659 /**
660 * Check if the type given by userType is allowed to set a uniform of the
661 * target type. Generally, equivalence is required, but setting Boolean
662 * uniforms can be done with glUniformiv or glUniformfv.
663 */
664 static GLboolean
665 compatible_types(GLenum userType, GLenum targetType)
666 {
667 if (userType == targetType)
668 return GL_TRUE;
669
670 if (targetType == GL_BOOL && (userType == GL_FLOAT ||
671 userType == GL_UNSIGNED_INT ||
672 userType == GL_INT))
673 return GL_TRUE;
674
675 if (targetType == GL_BOOL_VEC2 && (userType == GL_FLOAT_VEC2 ||
676 userType == GL_UNSIGNED_INT_VEC2 ||
677 userType == GL_INT_VEC2))
678 return GL_TRUE;
679
680 if (targetType == GL_BOOL_VEC3 && (userType == GL_FLOAT_VEC3 ||
681 userType == GL_UNSIGNED_INT_VEC3 ||
682 userType == GL_INT_VEC3))
683 return GL_TRUE;
684
685 if (targetType == GL_BOOL_VEC4 && (userType == GL_FLOAT_VEC4 ||
686 userType == GL_UNSIGNED_INT_VEC4 ||
687 userType == GL_INT_VEC4))
688 return GL_TRUE;
689
690 if (is_sampler_type(targetType) && userType == GL_INT)
691 return GL_TRUE;
692
693 return GL_FALSE;
694 }
695
696
697 /**
698 * Set the value of a program's uniform variable.
699 * \param program the program whose uniform to update
700 * \param index the index of the program parameter for the uniform
701 * \param offset additional parameter slot offset (for arrays)
702 * \param type the incoming datatype of 'values'
703 * \param count the number of uniforms to set
704 * \param elems number of elements per uniform (1, 2, 3 or 4)
705 * \param values the new values, of datatype 'type'
706 */
707 static void
708 set_program_uniform(struct gl_context *ctx, struct gl_program *program,
709 GLint index, GLint offset,
710 GLenum type, GLsizei count, GLint elems,
711 const void *values)
712 {
713 const struct gl_program_parameter *param =
714 &program->Parameters->Parameters[index];
715
716 assert(offset >= 0);
717 assert(elems >= 1);
718 assert(elems <= 4);
719
720 if (!compatible_types(type, param->DataType)) {
721 _mesa_error(ctx, GL_INVALID_OPERATION, "glUniform(type mismatch)");
722 return;
723 }
724
725 if (index + offset > (GLint) program->Parameters->Size) {
726 /* out of bounds! */
727 return;
728 }
729
730 if (param->Type == PROGRAM_SAMPLER) {
731 /* This controls which texture unit which is used by a sampler */
732 GLboolean changed = GL_FALSE;
733 GLint i;
734
735 /* this should have been caught by the compatible_types() check */
736 ASSERT(type == GL_INT);
737
738 /* loop over number of samplers to change */
739 for (i = 0; i < count; i++) {
740 GLuint sampler =
741 (GLuint) program->Parameters->ParameterValues[index + offset + i][0];
742 GLuint texUnit = ((GLuint *) values)[i];
743
744 /* check that the sampler (tex unit index) is legal */
745 if (texUnit >= ctx->Const.MaxTextureImageUnits) {
746 _mesa_error(ctx, GL_INVALID_VALUE,
747 "glUniform1(invalid sampler/tex unit index for '%s')",
748 param->Name);
749 return;
750 }
751
752 /* This maps a sampler to a texture unit: */
753 if (sampler < MAX_SAMPLERS) {
754 #if 0
755 printf("Set program %p sampler %d '%s' to unit %u\n",
756 program, sampler, param->Name, texUnit);
757 #endif
758 if (program->SamplerUnits[sampler] != texUnit) {
759 program->SamplerUnits[sampler] = texUnit;
760 changed = GL_TRUE;
761 }
762 }
763 }
764
765 if (changed) {
766 /* When a sampler's value changes it usually requires rewriting
767 * a GPU program's TEX instructions since there may not be a
768 * sampler->texture lookup table. We signal this with the
769 * ProgramStringNotify() callback.
770 */
771 FLUSH_VERTICES(ctx, _NEW_TEXTURE | _NEW_PROGRAM);
772 _mesa_update_shader_textures_used(program);
773 /* Do we need to care about the return value here?
774 * This should not be the first time the driver was notified of
775 * this program.
776 */
777 (void) ctx->Driver.ProgramStringNotify(ctx, program->Target, program);
778 }
779 }
780 else {
781 /* ordinary uniform variable */
782 const GLboolean isUniformBool = is_boolean_type(param->DataType);
783 const GLenum basicType = base_uniform_type(type);
784 const GLint slots = (param->Size + 3) / 4;
785 const GLint typeSize = _mesa_sizeof_glsl_type(param->DataType);
786 GLsizei k, i;
787
788 if ((GLint) param->Size > typeSize) {
789 /* an array */
790 /* we'll ignore extra data below */
791 }
792 else {
793 /* non-array: count must be at most one; count == 0 is handled by the loop below */
794 if (count > 1) {
795 _mesa_error(ctx, GL_INVALID_OPERATION,
796 "glUniform(uniform '%s' is not an array)",
797 param->Name);
798 return;
799 }
800 }
801
802 /* loop over number of array elements */
803 for (k = 0; k < count; k++) {
804 GLfloat *uniformVal;
805
806 if (offset + k >= slots) {
807 /* Extra array data is ignored */
808 break;
809 }
810
811 /* uniformVal (the destination) is always float[4] */
812 uniformVal = program->Parameters->ParameterValues[index + offset + k];
813
814 if (basicType == GL_INT) {
815 /* convert user's ints to floats */
816 const GLint *iValues = ((const GLint *) values) + k * elems;
817 for (i = 0; i < elems; i++) {
818 uniformVal[i] = (GLfloat) iValues[i];
819 }
820 }
821 else if (basicType == GL_UNSIGNED_INT) {
822 /* convert user's uints to floats */
823 const GLuint *iValues = ((const GLuint *) values) + k * elems;
824 for (i = 0; i < elems; i++) {
825 uniformVal[i] = (GLfloat) iValues[i];
826 }
827 }
828 else {
829 const GLfloat *fValues = ((const GLfloat *) values) + k * elems;
830 assert(basicType == GL_FLOAT);
831 for (i = 0; i < elems; i++) {
832 uniformVal[i] = fValues[i];
833 }
834 }
835
836 /* if the uniform is bool-valued, convert to 1.0 or 0.0 */
837 if (isUniformBool) {
838 for (i = 0; i < elems; i++) {
839 uniformVal[i] = uniformVal[i] ? 1.0f : 0.0f;
840 }
841 }
842 }
843 }
844 }
845
846
847 /**
848 * Called via glUniform*() functions.
849 */
850 void
851 _mesa_uniform(struct gl_context *ctx, struct gl_shader_program *shProg,
852 GLint location, GLsizei count,
853 const GLvoid *values, GLenum type)
854 {
855 struct gl_uniform *uniform;
856 GLint elems, offset;
857
858 if (!shProg || !shProg->LinkStatus) {
859 _mesa_error(ctx, GL_INVALID_OPERATION, "glUniform(program not linked)");
860 return;
861 }
862
863 if (location == -1)
864 return; /* The standard specifies this as a no-op */
865
866 if (location < -1) {
867 _mesa_error(ctx, GL_INVALID_OPERATION, "glUniform(location=%d)",
868 location);
869 return;
870 }
871
872 split_location_offset(&location, &offset);
873
874 if (location < 0 || location >= (GLint) shProg->Uniforms->NumUniforms) {
875 _mesa_error(ctx, GL_INVALID_VALUE, "glUniform(location=%d)", location);
876 return;
877 }
878
879 if (count < 0) {
880 _mesa_error(ctx, GL_INVALID_VALUE, "glUniform(count < 0)");
881 return;
882 }
883
884 elems = _mesa_sizeof_glsl_type(type);
885
886 FLUSH_VERTICES(ctx, _NEW_PROGRAM_CONSTANTS);
887
888 uniform = &shProg->Uniforms->Uniforms[location];
889
890 if (ctx->Shader.Flags & GLSL_UNIFORMS) {
891 const GLenum basicType = base_uniform_type(type);
892 GLint i;
893 printf("Mesa: set program %u uniform %s (loc %d) to: ",
894 shProg->Name, uniform->Name, location);
895 if (basicType == GL_INT) {
896 const GLint *v = (const GLint *) values;
897 for (i = 0; i < count * elems; i++) {
898 printf("%d ", v[i]);
899 }
900 }
901 else if (basicType == GL_UNSIGNED_INT) {
902 const GLuint *v = (const GLuint *) values;
903 for (i = 0; i < count * elems; i++) {
904 printf("%u ", v[i]);
905 }
906 }
907 else {
908 const GLfloat *v = (const GLfloat *) values;
909 assert(basicType == GL_FLOAT);
910 for (i = 0; i < count * elems; i++) {
911 printf("%g ", v[i]);
912 }
913 }
914 printf("\n");
915 }
916
917 /* A uniform var may be used by both a vertex shader and a fragment
918 * shader. We may need to update one or both shader's uniform here:
919 */
920 if (shProg->VertexProgram) {
921 /* convert uniform location to program parameter index */
922 GLint index = uniform->VertPos;
923 if (index >= 0) {
924 set_program_uniform(ctx, &shProg->VertexProgram->Base,
925 index, offset, type, count, elems, values);
926 }
927 }
928
929 if (shProg->FragmentProgram) {
930 /* convert uniform location to program parameter index */
931 GLint index = uniform->FragPos;
932 if (index >= 0) {
933 set_program_uniform(ctx, &shProg->FragmentProgram->Base,
934 index, offset, type, count, elems, values);
935 }
936 }
937
938 if (shProg->GeometryProgram) {
939 /* convert uniform location to program parameter index */
940 GLint index = uniform->GeomPos;
941 if (index >= 0) {
942 set_program_uniform(ctx, &shProg->GeometryProgram->Base,
943 index, offset, type, count, elems, values);
944 }
945 }
946
947 uniform->Initialized = GL_TRUE;
948 }
949
950
951 /**
952 * Set a matrix-valued program parameter.
953 */
954 static void
955 set_program_uniform_matrix(struct gl_context *ctx, struct gl_program *program,
956 GLuint index, GLuint offset,
957 GLuint count, GLuint rows, GLuint cols,
958 GLboolean transpose, const GLfloat *values)
959 {
960 GLuint mat, row, col;
961 GLuint src = 0;
962 const struct gl_program_parameter * param = &program->Parameters->Parameters[index];
963 const GLuint slots = (param->Size + 3) / 4;
964 const GLint typeSize = _mesa_sizeof_glsl_type(param->DataType);
965 GLint nr, nc;
966
967 /* check that the number of rows, columns is correct */
968 get_matrix_dims(param->DataType, &nr, &nc);
969 if (rows != nr || cols != nc) {
970 _mesa_error(ctx, GL_INVALID_OPERATION,
971 "glUniformMatrix(matrix size mismatch)");
972 return;
973 }
974
975 if ((GLint) param->Size <= typeSize) {
976 /* non-array: count must be at most one; count == 0 is handled by the loop below */
977 if (count > 1) {
978 _mesa_error(ctx, GL_INVALID_OPERATION,
979 "glUniformMatrix(uniform is not an array)");
980 return;
981 }
982 }
983
984 /*
985 * Note: the _columns_ of a matrix are stored in program registers, not
986 * the rows. So, the loops below look a little funny.
987 * XXX could optimize this a bit...
988 */
989
990 /* loop over matrices */
991 for (mat = 0; mat < count; mat++) {
992
993 /* each matrix: */
994 for (col = 0; col < cols; col++) {
995 GLfloat *v;
996 if (offset >= slots) {
997 /* Ignore writes beyond the end of (the used part of) an array */
998 return;
999 }
1000 v = program->Parameters->ParameterValues[index + offset];
1001 for (row = 0; row < rows; row++) {
1002 if (transpose) {
1003 v[row] = values[src + row * cols + col];
1004 }
1005 else {
1006 v[row] = values[src + col * rows + row];
1007 }
1008 }
1009
1010 offset++;
1011 }
1012
1013 src += rows * cols; /* next matrix */
1014 }
1015 }
1016
1017
1018 /**
1019 * Called by glUniformMatrix*() functions.
1020 * Note: cols=2, rows=4 ==> array[2] of vec4
1021 */
1022 void
1023 _mesa_uniform_matrix(struct gl_context *ctx, struct gl_shader_program *shProg,
1024 GLint cols, GLint rows,
1025 GLint location, GLsizei count,
1026 GLboolean transpose, const GLfloat *values)
1027 {
1028 struct gl_uniform *uniform;
1029 GLint offset;
1030
1031 if (!shProg || !shProg->LinkStatus) {
1032 _mesa_error(ctx, GL_INVALID_OPERATION,
1033 "glUniformMatrix(program not linked)");
1034 return;
1035 }
1036
1037 if (location == -1)
1038 return; /* The standard specifies this as a no-op */
1039
1040 if (location < -1) {
1041 _mesa_error(ctx, GL_INVALID_OPERATION, "glUniformMatrix(location)");
1042 return;
1043 }
1044
1045 split_location_offset(&location, &offset);
1046
1047 if (location < 0 || location >= (GLint) shProg->Uniforms->NumUniforms) {
1048 _mesa_error(ctx, GL_INVALID_VALUE, "glUniformMatrix(location)");
1049 return;
1050 }
1051 if (values == NULL) {
1052 _mesa_error(ctx, GL_INVALID_VALUE, "glUniformMatrix");
1053 return;
1054 }
1055
1056 FLUSH_VERTICES(ctx, _NEW_PROGRAM_CONSTANTS);
1057
1058 uniform = &shProg->Uniforms->Uniforms[location];
1059
1060 if (shProg->VertexProgram) {
1061 /* convert uniform location to program parameter index */
1062 GLint index = uniform->VertPos;
1063 if (index >= 0) {
1064 set_program_uniform_matrix(ctx, &shProg->VertexProgram->Base,
1065 index, offset,
1066 count, rows, cols, transpose, values);
1067 }
1068 }
1069
1070 if (shProg->FragmentProgram) {
1071 /* convert uniform location to program parameter index */
1072 GLint index = uniform->FragPos;
1073 if (index >= 0) {
1074 set_program_uniform_matrix(ctx, &shProg->FragmentProgram->Base,
1075 index, offset,
1076 count, rows, cols, transpose, values);
1077 }
1078 }
1079
1080 if (shProg->GeometryProgram) {
1081 /* convert uniform location to program parameter index */
1082 GLint index = uniform->GeomPos;
1083 if (index >= 0) {
1084 set_program_uniform_matrix(ctx, &shProg->GeometryProgram->Base,
1085 index, offset,
1086 count, rows, cols, transpose, values);
1087 }
1088 }
1089
1090 uniform->Initialized = GL_TRUE;
1091 }
1092
1093
1094 void GLAPIENTRY
1095 _mesa_Uniform1fARB(GLint location, GLfloat v0)
1096 {
1097 GET_CURRENT_CONTEXT(ctx);
1098 _mesa_uniform(ctx, ctx->Shader.ActiveProgram, location, 1, &v0, GL_FLOAT);
1099 }
1100
1101 void GLAPIENTRY
1102 _mesa_Uniform2fARB(GLint location, GLfloat v0, GLfloat v1)
1103 {
1104 GET_CURRENT_CONTEXT(ctx);
1105 GLfloat v[2];
1106 v[0] = v0;
1107 v[1] = v1;
1108 _mesa_uniform(ctx, ctx->Shader.ActiveProgram, location, 1, v, GL_FLOAT_VEC2);
1109 }
1110
1111 void GLAPIENTRY
1112 _mesa_Uniform3fARB(GLint location, GLfloat v0, GLfloat v1, GLfloat v2)
1113 {
1114 GET_CURRENT_CONTEXT(ctx);
1115 GLfloat v[3];
1116 v[0] = v0;
1117 v[1] = v1;
1118 v[2] = v2;
1119 _mesa_uniform(ctx, ctx->Shader.ActiveProgram, location, 1, v, GL_FLOAT_VEC3);
1120 }
1121
1122 void GLAPIENTRY
1123 _mesa_Uniform4fARB(GLint location, GLfloat v0, GLfloat v1, GLfloat v2,
1124 GLfloat v3)
1125 {
1126 GET_CURRENT_CONTEXT(ctx);
1127 GLfloat v[4];
1128 v[0] = v0;
1129 v[1] = v1;
1130 v[2] = v2;
1131 v[3] = v3;
1132 _mesa_uniform(ctx, ctx->Shader.ActiveProgram, location, 1, v, GL_FLOAT_VEC4);
1133 }
1134
1135 void GLAPIENTRY
1136 _mesa_Uniform1iARB(GLint location, GLint v0)
1137 {
1138 GET_CURRENT_CONTEXT(ctx);
1139 _mesa_uniform(ctx, ctx->Shader.ActiveProgram, location, 1, &v0, GL_INT);
1140 }
1141
1142 void GLAPIENTRY
1143 _mesa_Uniform2iARB(GLint location, GLint v0, GLint v1)
1144 {
1145 GET_CURRENT_CONTEXT(ctx);
1146 GLint v[2];
1147 v[0] = v0;
1148 v[1] = v1;
1149 _mesa_uniform(ctx, ctx->Shader.ActiveProgram, location, 1, v, GL_INT_VEC2);
1150 }
1151
1152 void GLAPIENTRY
1153 _mesa_Uniform3iARB(GLint location, GLint v0, GLint v1, GLint v2)
1154 {
1155 GET_CURRENT_CONTEXT(ctx);
1156 GLint v[3];
1157 v[0] = v0;
1158 v[1] = v1;
1159 v[2] = v2;
1160 _mesa_uniform(ctx, ctx->Shader.ActiveProgram, location, 1, v, GL_INT_VEC3);
1161 }
1162
1163 void GLAPIENTRY
1164 _mesa_Uniform4iARB(GLint location, GLint v0, GLint v1, GLint v2, GLint v3)
1165 {
1166 GET_CURRENT_CONTEXT(ctx);
1167 GLint v[4];
1168 v[0] = v0;
1169 v[1] = v1;
1170 v[2] = v2;
1171 v[3] = v3;
1172 _mesa_uniform(ctx, ctx->Shader.ActiveProgram, location, 1, v, GL_INT_VEC4);
1173 }
1174
1175 void GLAPIENTRY
1176 _mesa_Uniform1fvARB(GLint location, GLsizei count, const GLfloat * value)
1177 {
1178 GET_CURRENT_CONTEXT(ctx);
1179 _mesa_uniform(ctx, ctx->Shader.ActiveProgram, location, count, value, GL_FLOAT);
1180 }
1181
1182 void GLAPIENTRY
1183 _mesa_Uniform2fvARB(GLint location, GLsizei count, const GLfloat * value)
1184 {
1185 GET_CURRENT_CONTEXT(ctx);
1186 _mesa_uniform(ctx, ctx->Shader.ActiveProgram, location, count, value, GL_FLOAT_VEC2);
1187 }
1188
1189 void GLAPIENTRY
1190 _mesa_Uniform3fvARB(GLint location, GLsizei count, const GLfloat * value)
1191 {
1192 GET_CURRENT_CONTEXT(ctx);
1193 _mesa_uniform(ctx, ctx->Shader.ActiveProgram, location, count, value, GL_FLOAT_VEC3);
1194 }
1195
1196 void GLAPIENTRY
1197 _mesa_Uniform4fvARB(GLint location, GLsizei count, const GLfloat * value)
1198 {
1199 GET_CURRENT_CONTEXT(ctx);
1200 _mesa_uniform(ctx, ctx->Shader.ActiveProgram, location, count, value, GL_FLOAT_VEC4);
1201 }
1202
1203 void GLAPIENTRY
1204 _mesa_Uniform1ivARB(GLint location, GLsizei count, const GLint * value)
1205 {
1206 GET_CURRENT_CONTEXT(ctx);
1207 _mesa_uniform(ctx, ctx->Shader.ActiveProgram, location, count, value, GL_INT);
1208 }
1209
1210 void GLAPIENTRY
1211 _mesa_Uniform2ivARB(GLint location, GLsizei count, const GLint * value)
1212 {
1213 GET_CURRENT_CONTEXT(ctx);
1214 _mesa_uniform(ctx, ctx->Shader.ActiveProgram, location, count, value, GL_INT_VEC2);
1215 }
1216
1217 void GLAPIENTRY
1218 _mesa_Uniform3ivARB(GLint location, GLsizei count, const GLint * value)
1219 {
1220 GET_CURRENT_CONTEXT(ctx);
1221 _mesa_uniform(ctx, ctx->Shader.ActiveProgram, location, count, value, GL_INT_VEC3);
1222 }
1223
1224 void GLAPIENTRY
1225 _mesa_Uniform4ivARB(GLint location, GLsizei count, const GLint * value)
1226 {
1227 GET_CURRENT_CONTEXT(ctx);
1228 _mesa_uniform(ctx, ctx->Shader.ActiveProgram, location, count, value, GL_INT_VEC4);
1229 }
1230
1231
1232 /** OpenGL 3.0 GLuint-valued functions **/
1233 void GLAPIENTRY
1234 _mesa_Uniform1ui(GLint location, GLuint v0)
1235 {
1236 GET_CURRENT_CONTEXT(ctx);
1237 _mesa_uniform(ctx, ctx->Shader.ActiveProgram, location, 1, &v0, GL_UNSIGNED_INT);
1238 }
1239
1240 void GLAPIENTRY
1241 _mesa_Uniform2ui(GLint location, GLuint v0, GLuint v1)
1242 {
1243 GET_CURRENT_CONTEXT(ctx);
1244 GLuint v[2];
1245 v[0] = v0;
1246 v[1] = v1;
1247 _mesa_uniform(ctx, ctx->Shader.ActiveProgram, location, 1, v, GL_UNSIGNED_INT_VEC2);
1248 }
1249
1250 void GLAPIENTRY
1251 _mesa_Uniform3ui(GLint location, GLuint v0, GLuint v1, GLuint v2)
1252 {
1253 GET_CURRENT_CONTEXT(ctx);
1254 GLuint v[3];
1255 v[0] = v0;
1256 v[1] = v1;
1257 v[2] = v2;
1258 _mesa_uniform(ctx, ctx->Shader.ActiveProgram, location, 1, v, GL_UNSIGNED_INT_VEC3);
1259 }
1260
1261 void GLAPIENTRY
1262 _mesa_Uniform4ui(GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3)
1263 {
1264 GET_CURRENT_CONTEXT(ctx);
1265 GLuint v[4];
1266 v[0] = v0;
1267 v[1] = v1;
1268 v[2] = v2;
1269 v[3] = v3;
1270 _mesa_uniform(ctx, ctx->Shader.ActiveProgram, location, 1, v, GL_UNSIGNED_INT_VEC4);
1271 }
1272
1273 void GLAPIENTRY
1274 _mesa_Uniform1uiv(GLint location, GLsizei count, const GLuint *value)
1275 {
1276 GET_CURRENT_CONTEXT(ctx);
1277 _mesa_uniform(ctx, ctx->Shader.ActiveProgram, location, count, value, GL_UNSIGNED_INT);
1278 }
1279
1280 void GLAPIENTRY
1281 _mesa_Uniform2uiv(GLint location, GLsizei count, const GLuint *value)
1282 {
1283 GET_CURRENT_CONTEXT(ctx);
1284 _mesa_uniform(ctx, ctx->Shader.ActiveProgram, location, count, value, GL_UNSIGNED_INT_VEC2);
1285 }
1286
1287 void GLAPIENTRY
1288 _mesa_Uniform3uiv(GLint location, GLsizei count, const GLuint *value)
1289 {
1290 GET_CURRENT_CONTEXT(ctx);
1291 _mesa_uniform(ctx, ctx->Shader.ActiveProgram, location, count, value, GL_UNSIGNED_INT_VEC3);
1292 }
1293
1294 void GLAPIENTRY
1295 _mesa_Uniform4uiv(GLint location, GLsizei count, const GLuint *value)
1296 {
1297 GET_CURRENT_CONTEXT(ctx);
1298 _mesa_uniform(ctx, ctx->Shader.ActiveProgram, location, count, value, GL_UNSIGNED_INT_VEC4);
1299 }
1300
1301
1302
1303 void GLAPIENTRY
1304 _mesa_UniformMatrix2fvARB(GLint location, GLsizei count, GLboolean transpose,
1305 const GLfloat * value)
1306 {
1307 GET_CURRENT_CONTEXT(ctx);
1308 _mesa_uniform_matrix(ctx, ctx->Shader.ActiveProgram,
1309 2, 2, location, count, transpose, value);
1310 }
1311
1312 void GLAPIENTRY
1313 _mesa_UniformMatrix3fvARB(GLint location, GLsizei count, GLboolean transpose,
1314 const GLfloat * value)
1315 {
1316 GET_CURRENT_CONTEXT(ctx);
1317 _mesa_uniform_matrix(ctx, ctx->Shader.ActiveProgram,
1318 3, 3, location, count, transpose, value);
1319 }
1320
1321 void GLAPIENTRY
1322 _mesa_UniformMatrix4fvARB(GLint location, GLsizei count, GLboolean transpose,
1323 const GLfloat * value)
1324 {
1325 GET_CURRENT_CONTEXT(ctx);
1326 _mesa_uniform_matrix(ctx, ctx->Shader.ActiveProgram,
1327 4, 4, location, count, transpose, value);
1328 }
1329
1330
1331 /**
1332 * Non-square UniformMatrix are OpenGL 2.1
1333 */
1334 void GLAPIENTRY
1335 _mesa_UniformMatrix2x3fv(GLint location, GLsizei count, GLboolean transpose,
1336 const GLfloat *value)
1337 {
1338 GET_CURRENT_CONTEXT(ctx);
1339 _mesa_uniform_matrix(ctx, ctx->Shader.ActiveProgram,
1340 2, 3, location, count, transpose, value);
1341 }
1342
1343 void GLAPIENTRY
1344 _mesa_UniformMatrix3x2fv(GLint location, GLsizei count, GLboolean transpose,
1345 const GLfloat *value)
1346 {
1347 GET_CURRENT_CONTEXT(ctx);
1348 _mesa_uniform_matrix(ctx, ctx->Shader.ActiveProgram,
1349 3, 2, location, count, transpose, value);
1350 }
1351
1352 void GLAPIENTRY
1353 _mesa_UniformMatrix2x4fv(GLint location, GLsizei count, GLboolean transpose,
1354 const GLfloat *value)
1355 {
1356 GET_CURRENT_CONTEXT(ctx);
1357 _mesa_uniform_matrix(ctx, ctx->Shader.ActiveProgram,
1358 2, 4, location, count, transpose, value);
1359 }
1360
1361 void GLAPIENTRY
1362 _mesa_UniformMatrix4x2fv(GLint location, GLsizei count, GLboolean transpose,
1363 const GLfloat *value)
1364 {
1365 GET_CURRENT_CONTEXT(ctx);
1366 _mesa_uniform_matrix(ctx, ctx->Shader.ActiveProgram,
1367 4, 2, location, count, transpose, value);
1368 }
1369
1370 void GLAPIENTRY
1371 _mesa_UniformMatrix3x4fv(GLint location, GLsizei count, GLboolean transpose,
1372 const GLfloat *value)
1373 {
1374 GET_CURRENT_CONTEXT(ctx);
1375 _mesa_uniform_matrix(ctx, ctx->Shader.ActiveProgram,
1376 3, 4, location, count, transpose, value);
1377 }
1378
1379 void GLAPIENTRY
1380 _mesa_UniformMatrix4x3fv(GLint location, GLsizei count, GLboolean transpose,
1381 const GLfloat *value)
1382 {
1383 GET_CURRENT_CONTEXT(ctx);
1384 _mesa_uniform_matrix(ctx, ctx->Shader.ActiveProgram,
1385 4, 3, location, count, transpose, value);
1386 }
1387
1388
1389 void GLAPIENTRY
1390 _mesa_GetnUniformfvARB(GLhandleARB program, GLint location,
1391 GLsizei bufSize, GLfloat *params)
1392 {
1393 GET_CURRENT_CONTEXT(ctx);
1394 _mesa_get_uniformfv(ctx, program, location, bufSize, params);
1395 }
1396
1397 void GLAPIENTRY
1398 _mesa_GetUniformfvARB(GLhandleARB program, GLint location, GLfloat *params)
1399 {
1400 _mesa_GetnUniformfvARB(program, location, INT_MAX, params);
1401 }
1402
1403
1404 void GLAPIENTRY
1405 _mesa_GetnUniformivARB(GLhandleARB program, GLint location,
1406 GLsizei bufSize, GLint *params)
1407 {
1408 GET_CURRENT_CONTEXT(ctx);
1409 _mesa_get_uniformiv(ctx, program, location, bufSize, params);
1410 }
1411
1412 void GLAPIENTRY
1413 _mesa_GetUniformivARB(GLhandleARB program, GLint location, GLint *params)
1414 {
1415 _mesa_GetnUniformivARB(program, location, INT_MAX, params);
1416 }
1417
1418
1419 /* GL3 */
1420 void GLAPIENTRY
1421 _mesa_GetnUniformuivARB(GLhandleARB program, GLint location,
1422 GLsizei bufSize, GLuint *params)
1423 {
1424 GET_CURRENT_CONTEXT(ctx);
1425 _mesa_get_uniformuiv(ctx, program, location, bufSize, params);
1426 }
1427
1428 void GLAPIENTRY
1429 _mesa_GetUniformuiv(GLhandleARB program, GLint location, GLuint *params)
1430 {
1431 _mesa_GetnUniformuivARB(program, location, INT_MAX, params);
1432 }
1433
1434
1435 /* GL4 */
1436 void GLAPIENTRY
1437 _mesa_GetnUniformdvARB(GLhandleARB program, GLint location,
1438 GLsizei bufSize, GLdouble *params)
1439 {
1440 GET_CURRENT_CONTEXT(ctx);
1441 _mesa_get_uniformdv(ctx, program, location, bufSize, params);
1442 }
1443
1444 void GLAPIENTRY
1445 _mesa_GetUniformdv(GLhandleARB program, GLint location, GLdouble *params)
1446 {
1447 _mesa_GetnUniformdvARB(program, location, INT_MAX, params);
1448 }
1449
1450
1451 GLint GLAPIENTRY
1452 _mesa_GetUniformLocationARB(GLhandleARB programObj, const GLcharARB *name)
1453 {
1454 struct gl_shader_program *shProg;
1455
1456 GET_CURRENT_CONTEXT(ctx);
1457
1458 shProg = _mesa_lookup_shader_program_err(ctx, programObj,
1459 "glGetUniformLocation");
1460 if (!shProg)
1461 return -1;
1462
1463 return _mesa_get_uniform_location(ctx, shProg, name);
1464 }
1465
1466
1467 void GLAPIENTRY
1468 _mesa_GetActiveUniformARB(GLhandleARB program, GLuint index,
1469 GLsizei maxLength, GLsizei * length, GLint * size,
1470 GLenum * type, GLcharARB * name)
1471 {
1472 GET_CURRENT_CONTEXT(ctx);
1473 _mesa_get_active_uniform(ctx, program, index, maxLength, length, size,
1474 type, name);
1475 }
1476
1477
1478 /**
1479 * Plug in shader uniform-related functions into API dispatch table.
1480 */
1481 void
1482 _mesa_init_shader_uniform_dispatch(struct _glapi_table *exec)
1483 {
1484 #if FEATURE_GL
1485 SET_Uniform1fARB(exec, _mesa_Uniform1fARB);
1486 SET_Uniform2fARB(exec, _mesa_Uniform2fARB);
1487 SET_Uniform3fARB(exec, _mesa_Uniform3fARB);
1488 SET_Uniform4fARB(exec, _mesa_Uniform4fARB);
1489 SET_Uniform1iARB(exec, _mesa_Uniform1iARB);
1490 SET_Uniform2iARB(exec, _mesa_Uniform2iARB);
1491 SET_Uniform3iARB(exec, _mesa_Uniform3iARB);
1492 SET_Uniform4iARB(exec, _mesa_Uniform4iARB);
1493 SET_Uniform1fvARB(exec, _mesa_Uniform1fvARB);
1494 SET_Uniform2fvARB(exec, _mesa_Uniform2fvARB);
1495 SET_Uniform3fvARB(exec, _mesa_Uniform3fvARB);
1496 SET_Uniform4fvARB(exec, _mesa_Uniform4fvARB);
1497 SET_Uniform1ivARB(exec, _mesa_Uniform1ivARB);
1498 SET_Uniform2ivARB(exec, _mesa_Uniform2ivARB);
1499 SET_Uniform3ivARB(exec, _mesa_Uniform3ivARB);
1500 SET_Uniform4ivARB(exec, _mesa_Uniform4ivARB);
1501 SET_UniformMatrix2fvARB(exec, _mesa_UniformMatrix2fvARB);
1502 SET_UniformMatrix3fvARB(exec, _mesa_UniformMatrix3fvARB);
1503 SET_UniformMatrix4fvARB(exec, _mesa_UniformMatrix4fvARB);
1504
1505 SET_GetActiveUniformARB(exec, _mesa_GetActiveUniformARB);
1506 SET_GetUniformLocationARB(exec, _mesa_GetUniformLocationARB);
1507 SET_GetUniformfvARB(exec, _mesa_GetUniformfvARB);
1508 SET_GetUniformivARB(exec, _mesa_GetUniformivARB);
1509
1510 /* OpenGL 2.1 */
1511 SET_UniformMatrix2x3fv(exec, _mesa_UniformMatrix2x3fv);
1512 SET_UniformMatrix3x2fv(exec, _mesa_UniformMatrix3x2fv);
1513 SET_UniformMatrix2x4fv(exec, _mesa_UniformMatrix2x4fv);
1514 SET_UniformMatrix4x2fv(exec, _mesa_UniformMatrix4x2fv);
1515 SET_UniformMatrix3x4fv(exec, _mesa_UniformMatrix3x4fv);
1516 SET_UniformMatrix4x3fv(exec, _mesa_UniformMatrix4x3fv);
1517
1518 /* OpenGL 3.0 */
1519 /* XXX finish dispatch */
1520 SET_Uniform1uiEXT(exec, _mesa_Uniform1ui);
1521 SET_Uniform2uiEXT(exec, _mesa_Uniform2ui);
1522 SET_Uniform3uiEXT(exec, _mesa_Uniform3ui);
1523 SET_Uniform4uiEXT(exec, _mesa_Uniform4ui);
1524 SET_Uniform1uivEXT(exec, _mesa_Uniform1uiv);
1525 SET_Uniform2uivEXT(exec, _mesa_Uniform2uiv);
1526 SET_Uniform3uivEXT(exec, _mesa_Uniform3uiv);
1527 SET_Uniform4uivEXT(exec, _mesa_Uniform4uiv);
1528 SET_GetUniformuivEXT(exec, _mesa_GetUniformuiv);
1529
1530 /* GL_ARB_robustness */
1531 SET_GetnUniformfvARB(exec, _mesa_GetnUniformfvARB);
1532 SET_GetnUniformivARB(exec, _mesa_GetnUniformivARB);
1533 SET_GetnUniformuivARB(exec, _mesa_GetnUniformuivARB);
1534 SET_GetnUniformdvARB(exec, _mesa_GetnUniformdvARB); /* GL 4.0 */
1535
1536 #endif /* FEATURE_GL */
1537 }