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