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