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