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