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