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#include "main/glheader.h"
39#include "main/context.h"
40#include "main/dispatch.h"
41#include "main/shaderapi.h"
42#include "main/shaderobj.h"
43#include "main/uniforms.h"
44#include "main/enums.h"
45#include "ir_uniform.h"
46#include "glsl_types.h"
47
48/**
49 * Update the vertex/fragment program's TexturesUsed array.
50 *
51 * This needs to be called after glUniform(set sampler var) is called.
52 * A call to glUniform(samplerVar, value) causes a sampler to point to a
53 * particular texture unit.  We know the sampler's texture target
54 * (1D/2D/3D/etc) from compile time but the sampler's texture unit is
55 * set by glUniform() calls.
56 *
57 * So, scan the program->SamplerUnits[] and program->SamplerTargets[]
58 * information to update the prog->TexturesUsed[] values.
59 * Each value of TexturesUsed[unit] is one of zero, TEXTURE_1D_INDEX,
60 * TEXTURE_2D_INDEX, TEXTURE_3D_INDEX, etc.
61 * We'll use that info for state validation before rendering.
62 */
63void
64_mesa_update_shader_textures_used(struct gl_shader_program *shProg,
65				  struct gl_program *prog)
66{
67   GLuint s;
68
69   memcpy(prog->SamplerUnits, shProg->SamplerUnits, sizeof(prog->SamplerUnits));
70   memset(prog->TexturesUsed, 0, sizeof(prog->TexturesUsed));
71
72   for (s = 0; s < MAX_SAMPLERS; s++) {
73      if (prog->SamplersUsed & (1 << s)) {
74         GLuint unit = shProg->SamplerUnits[s];
75         GLuint tgt = shProg->SamplerTargets[s];
76         assert(unit < Elements(prog->TexturesUsed));
77         assert(tgt < NUM_TEXTURE_TARGETS);
78         prog->TexturesUsed[unit] |= (1 << tgt);
79      }
80   }
81}
82
83/**
84 * Connect a piece of driver storage with a part of a uniform
85 *
86 * \param uni            The uniform with which the storage will be associated
87 * \param element_stride Byte-stride between array elements.
88 *                       \sa gl_uniform_driver_storage::element_stride.
89 * \param vector_stride  Byte-stride between vectors (in a matrix).
90 *                       \sa gl_uniform_driver_storage::vector_stride.
91 * \param format         Conversion from native format to driver format
92 *                       required by the driver.
93 * \param data           Location to dump the data.
94 */
95void
96_mesa_uniform_attach_driver_storage(struct gl_uniform_storage *uni,
97				    unsigned element_stride,
98				    unsigned vector_stride,
99				    enum gl_uniform_driver_format format,
100				    void *data)
101{
102   uni->driver_storage = (struct gl_uniform_driver_storage*)
103      realloc(uni->driver_storage,
104	      sizeof(struct gl_uniform_driver_storage)
105	      * (uni->num_driver_storage + 1));
106
107   uni->driver_storage[uni->num_driver_storage].element_stride = element_stride;
108   uni->driver_storage[uni->num_driver_storage].vector_stride = vector_stride;
109   uni->driver_storage[uni->num_driver_storage].format = (uint8_t) format;
110   uni->driver_storage[uni->num_driver_storage].data = data;
111
112   uni->num_driver_storage++;
113}
114
115/**
116 * Sever all connections with all pieces of driver storage for all uniforms
117 *
118 * \warning
119 * This function does \b not release any of the \c data pointers
120 * previously passed in to \c _mesa_uniform_attach_driver_stoarge.
121 */
122void
123_mesa_uniform_detach_all_driver_storage(struct gl_uniform_storage *uni)
124{
125   free(uni->driver_storage);
126   uni->driver_storage = NULL;
127   uni->num_driver_storage = 0;
128}
129
130void GLAPIENTRY
131_mesa_Uniform1fARB(GLint location, GLfloat v0)
132{
133   GET_CURRENT_CONTEXT(ctx);
134   _mesa_uniform(ctx, ctx->Shader.ActiveProgram, location, 1, &v0, GL_FLOAT);
135}
136
137void GLAPIENTRY
138_mesa_Uniform2fARB(GLint location, GLfloat v0, GLfloat v1)
139{
140   GET_CURRENT_CONTEXT(ctx);
141   GLfloat v[2];
142   v[0] = v0;
143   v[1] = v1;
144   _mesa_uniform(ctx, ctx->Shader.ActiveProgram, location, 1, v, GL_FLOAT_VEC2);
145}
146
147void GLAPIENTRY
148_mesa_Uniform3fARB(GLint location, GLfloat v0, GLfloat v1, GLfloat v2)
149{
150   GET_CURRENT_CONTEXT(ctx);
151   GLfloat v[3];
152   v[0] = v0;
153   v[1] = v1;
154   v[2] = v2;
155   _mesa_uniform(ctx, ctx->Shader.ActiveProgram, location, 1, v, GL_FLOAT_VEC3);
156}
157
158void GLAPIENTRY
159_mesa_Uniform4fARB(GLint location, GLfloat v0, GLfloat v1, GLfloat v2,
160                   GLfloat v3)
161{
162   GET_CURRENT_CONTEXT(ctx);
163   GLfloat v[4];
164   v[0] = v0;
165   v[1] = v1;
166   v[2] = v2;
167   v[3] = v3;
168   _mesa_uniform(ctx, ctx->Shader.ActiveProgram, location, 1, v, GL_FLOAT_VEC4);
169}
170
171void GLAPIENTRY
172_mesa_Uniform1iARB(GLint location, GLint v0)
173{
174   GET_CURRENT_CONTEXT(ctx);
175   _mesa_uniform(ctx, ctx->Shader.ActiveProgram, location, 1, &v0, GL_INT);
176}
177
178void GLAPIENTRY
179_mesa_Uniform2iARB(GLint location, GLint v0, GLint v1)
180{
181   GET_CURRENT_CONTEXT(ctx);
182   GLint v[2];
183   v[0] = v0;
184   v[1] = v1;
185   _mesa_uniform(ctx, ctx->Shader.ActiveProgram, location, 1, v, GL_INT_VEC2);
186}
187
188void GLAPIENTRY
189_mesa_Uniform3iARB(GLint location, GLint v0, GLint v1, GLint v2)
190{
191   GET_CURRENT_CONTEXT(ctx);
192   GLint v[3];
193   v[0] = v0;
194   v[1] = v1;
195   v[2] = v2;
196   _mesa_uniform(ctx, ctx->Shader.ActiveProgram, location, 1, v, GL_INT_VEC3);
197}
198
199void GLAPIENTRY
200_mesa_Uniform4iARB(GLint location, GLint v0, GLint v1, GLint v2, GLint v3)
201{
202   GET_CURRENT_CONTEXT(ctx);
203   GLint v[4];
204   v[0] = v0;
205   v[1] = v1;
206   v[2] = v2;
207   v[3] = v3;
208   _mesa_uniform(ctx, ctx->Shader.ActiveProgram, location, 1, v, GL_INT_VEC4);
209}
210
211void GLAPIENTRY
212_mesa_Uniform1fvARB(GLint location, GLsizei count, const GLfloat * value)
213{
214   GET_CURRENT_CONTEXT(ctx);
215   _mesa_uniform(ctx, ctx->Shader.ActiveProgram, location, count, value, GL_FLOAT);
216}
217
218void GLAPIENTRY
219_mesa_Uniform2fvARB(GLint location, GLsizei count, const GLfloat * value)
220{
221   GET_CURRENT_CONTEXT(ctx);
222   _mesa_uniform(ctx, ctx->Shader.ActiveProgram, location, count, value, GL_FLOAT_VEC2);
223}
224
225void GLAPIENTRY
226_mesa_Uniform3fvARB(GLint location, GLsizei count, const GLfloat * value)
227{
228   GET_CURRENT_CONTEXT(ctx);
229   _mesa_uniform(ctx, ctx->Shader.ActiveProgram, location, count, value, GL_FLOAT_VEC3);
230}
231
232void GLAPIENTRY
233_mesa_Uniform4fvARB(GLint location, GLsizei count, const GLfloat * value)
234{
235   GET_CURRENT_CONTEXT(ctx);
236   _mesa_uniform(ctx, ctx->Shader.ActiveProgram, location, count, value, GL_FLOAT_VEC4);
237}
238
239void GLAPIENTRY
240_mesa_Uniform1ivARB(GLint location, GLsizei count, const GLint * value)
241{
242   GET_CURRENT_CONTEXT(ctx);
243   _mesa_uniform(ctx, ctx->Shader.ActiveProgram, location, count, value, GL_INT);
244}
245
246void GLAPIENTRY
247_mesa_Uniform2ivARB(GLint location, GLsizei count, const GLint * value)
248{
249   GET_CURRENT_CONTEXT(ctx);
250   _mesa_uniform(ctx, ctx->Shader.ActiveProgram, location, count, value, GL_INT_VEC2);
251}
252
253void GLAPIENTRY
254_mesa_Uniform3ivARB(GLint location, GLsizei count, const GLint * value)
255{
256   GET_CURRENT_CONTEXT(ctx);
257   _mesa_uniform(ctx, ctx->Shader.ActiveProgram, location, count, value, GL_INT_VEC3);
258}
259
260void GLAPIENTRY
261_mesa_Uniform4ivARB(GLint location, GLsizei count, const GLint * value)
262{
263   GET_CURRENT_CONTEXT(ctx);
264   _mesa_uniform(ctx, ctx->Shader.ActiveProgram, location, count, value, GL_INT_VEC4);
265}
266
267
268/** OpenGL 3.0 GLuint-valued functions **/
269void GLAPIENTRY
270_mesa_Uniform1ui(GLint location, GLuint v0)
271{
272   GET_CURRENT_CONTEXT(ctx);
273   _mesa_uniform(ctx, ctx->Shader.ActiveProgram, location, 1, &v0, GL_UNSIGNED_INT);
274}
275
276void GLAPIENTRY
277_mesa_Uniform2ui(GLint location, GLuint v0, GLuint v1)
278{
279   GET_CURRENT_CONTEXT(ctx);
280   GLuint v[2];
281   v[0] = v0;
282   v[1] = v1;
283   _mesa_uniform(ctx, ctx->Shader.ActiveProgram, location, 1, v, GL_UNSIGNED_INT_VEC2);
284}
285
286void GLAPIENTRY
287_mesa_Uniform3ui(GLint location, GLuint v0, GLuint v1, GLuint v2)
288{
289   GET_CURRENT_CONTEXT(ctx);
290   GLuint v[3];
291   v[0] = v0;
292   v[1] = v1;
293   v[2] = v2;
294   _mesa_uniform(ctx, ctx->Shader.ActiveProgram, location, 1, v, GL_UNSIGNED_INT_VEC3);
295}
296
297void GLAPIENTRY
298_mesa_Uniform4ui(GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3)
299{
300   GET_CURRENT_CONTEXT(ctx);
301   GLuint v[4];
302   v[0] = v0;
303   v[1] = v1;
304   v[2] = v2;
305   v[3] = v3;
306   _mesa_uniform(ctx, ctx->Shader.ActiveProgram, location, 1, v, GL_UNSIGNED_INT_VEC4);
307}
308
309void GLAPIENTRY
310_mesa_Uniform1uiv(GLint location, GLsizei count, const GLuint *value)
311{
312   GET_CURRENT_CONTEXT(ctx);
313   _mesa_uniform(ctx, ctx->Shader.ActiveProgram, location, count, value, GL_UNSIGNED_INT);
314}
315
316void GLAPIENTRY
317_mesa_Uniform2uiv(GLint location, GLsizei count, const GLuint *value)
318{
319   GET_CURRENT_CONTEXT(ctx);
320   _mesa_uniform(ctx, ctx->Shader.ActiveProgram, location, count, value, GL_UNSIGNED_INT_VEC2);
321}
322
323void GLAPIENTRY
324_mesa_Uniform3uiv(GLint location, GLsizei count, const GLuint *value)
325{
326   GET_CURRENT_CONTEXT(ctx);
327   _mesa_uniform(ctx, ctx->Shader.ActiveProgram, location, count, value, GL_UNSIGNED_INT_VEC3);
328}
329
330void GLAPIENTRY
331_mesa_Uniform4uiv(GLint location, GLsizei count, const GLuint *value)
332{
333   GET_CURRENT_CONTEXT(ctx);
334   _mesa_uniform(ctx, ctx->Shader.ActiveProgram, location, count, value, GL_UNSIGNED_INT_VEC4);
335}
336
337
338
339void GLAPIENTRY
340_mesa_UniformMatrix2fvARB(GLint location, GLsizei count, GLboolean transpose,
341                          const GLfloat * value)
342{
343   GET_CURRENT_CONTEXT(ctx);
344   _mesa_uniform_matrix(ctx, ctx->Shader.ActiveProgram,
345			2, 2, location, count, transpose, value);
346}
347
348void GLAPIENTRY
349_mesa_UniformMatrix3fvARB(GLint location, GLsizei count, GLboolean transpose,
350                          const GLfloat * value)
351{
352   GET_CURRENT_CONTEXT(ctx);
353   _mesa_uniform_matrix(ctx, ctx->Shader.ActiveProgram,
354			3, 3, location, count, transpose, value);
355}
356
357void GLAPIENTRY
358_mesa_UniformMatrix4fvARB(GLint location, GLsizei count, GLboolean transpose,
359                          const GLfloat * value)
360{
361   GET_CURRENT_CONTEXT(ctx);
362   _mesa_uniform_matrix(ctx, ctx->Shader.ActiveProgram,
363			4, 4, location, count, transpose, value);
364}
365
366
367/**
368 * Non-square UniformMatrix are OpenGL 2.1
369 */
370void GLAPIENTRY
371_mesa_UniformMatrix2x3fv(GLint location, GLsizei count, GLboolean transpose,
372                         const GLfloat *value)
373{
374   GET_CURRENT_CONTEXT(ctx);
375   _mesa_uniform_matrix(ctx, ctx->Shader.ActiveProgram,
376			2, 3, location, count, transpose, value);
377}
378
379void GLAPIENTRY
380_mesa_UniformMatrix3x2fv(GLint location, GLsizei count, GLboolean transpose,
381                         const GLfloat *value)
382{
383   GET_CURRENT_CONTEXT(ctx);
384   _mesa_uniform_matrix(ctx, ctx->Shader.ActiveProgram,
385			3, 2, location, count, transpose, value);
386}
387
388void GLAPIENTRY
389_mesa_UniformMatrix2x4fv(GLint location, GLsizei count, GLboolean transpose,
390                         const GLfloat *value)
391{
392   GET_CURRENT_CONTEXT(ctx);
393   _mesa_uniform_matrix(ctx, ctx->Shader.ActiveProgram,
394			2, 4, location, count, transpose, value);
395}
396
397void GLAPIENTRY
398_mesa_UniformMatrix4x2fv(GLint location, GLsizei count, GLboolean transpose,
399                         const GLfloat *value)
400{
401   GET_CURRENT_CONTEXT(ctx);
402   _mesa_uniform_matrix(ctx, ctx->Shader.ActiveProgram,
403			4, 2, location, count, transpose, value);
404}
405
406void GLAPIENTRY
407_mesa_UniformMatrix3x4fv(GLint location, GLsizei count, GLboolean transpose,
408                         const GLfloat *value)
409{
410   GET_CURRENT_CONTEXT(ctx);
411   _mesa_uniform_matrix(ctx, ctx->Shader.ActiveProgram,
412			3, 4, location, count, transpose, value);
413}
414
415void GLAPIENTRY
416_mesa_UniformMatrix4x3fv(GLint location, GLsizei count, GLboolean transpose,
417                         const GLfloat *value)
418{
419   GET_CURRENT_CONTEXT(ctx);
420   _mesa_uniform_matrix(ctx, ctx->Shader.ActiveProgram,
421			4, 3, location, count, transpose, value);
422}
423
424
425void GLAPIENTRY
426_mesa_GetnUniformfvARB(GLhandleARB program, GLint location,
427                       GLsizei bufSize, GLfloat *params)
428{
429   GET_CURRENT_CONTEXT(ctx);
430   _mesa_get_uniform(ctx, program, location, bufSize, GLSL_TYPE_FLOAT, params);
431}
432
433void GLAPIENTRY
434_mesa_GetUniformfvARB(GLhandleARB program, GLint location, GLfloat *params)
435{
436   _mesa_GetnUniformfvARB(program, location, INT_MAX, params);
437}
438
439
440void GLAPIENTRY
441_mesa_GetnUniformivARB(GLhandleARB program, GLint location,
442                       GLsizei bufSize, GLint *params)
443{
444   GET_CURRENT_CONTEXT(ctx);
445   _mesa_get_uniform(ctx, program, location, bufSize, GLSL_TYPE_INT, params);
446}
447
448void GLAPIENTRY
449_mesa_GetUniformivARB(GLhandleARB program, GLint location, GLint *params)
450{
451   _mesa_GetnUniformivARB(program, location, INT_MAX, params);
452}
453
454
455/* GL3 */
456void GLAPIENTRY
457_mesa_GetnUniformuivARB(GLhandleARB program, GLint location,
458                        GLsizei bufSize, GLuint *params)
459{
460   GET_CURRENT_CONTEXT(ctx);
461   _mesa_get_uniform(ctx, program, location, bufSize, GLSL_TYPE_UINT, params);
462}
463
464void GLAPIENTRY
465_mesa_GetUniformuiv(GLhandleARB program, GLint location, GLuint *params)
466{
467   _mesa_GetnUniformuivARB(program, location, INT_MAX, params);
468}
469
470
471/* GL4 */
472void GLAPIENTRY
473_mesa_GetnUniformdvARB(GLhandleARB program, GLint location,
474                        GLsizei bufSize, GLdouble *params)
475{
476   GET_CURRENT_CONTEXT(ctx);
477
478   (void) program;
479   (void) location;
480   (void) bufSize;
481   (void) params;
482
483   /*
484   _mesa_get_uniform(ctx, program, location, bufSize, GLSL_TYPE_DOUBLE, params);
485   */
486   _mesa_error(ctx, GL_INVALID_OPERATION, "glGetUniformdvARB"
487               "(GL_ARB_gpu_shader_fp64 not implemented)");
488}
489
490void GLAPIENTRY
491_mesa_GetUniformdv(GLhandleARB program, GLint location, GLdouble *params)
492{
493   _mesa_GetnUniformdvARB(program, location, INT_MAX, params);
494}
495
496
497GLint GLAPIENTRY
498_mesa_GetUniformLocationARB(GLhandleARB programObj, const GLcharARB *name)
499{
500   struct gl_shader_program *shProg;
501   GLuint index, offset;
502
503   GET_CURRENT_CONTEXT(ctx);
504
505   shProg = _mesa_lookup_shader_program_err(ctx, programObj,
506					    "glGetUniformLocation");
507   if (!shProg)
508      return -1;
509
510   /* Page 80 (page 94 of the PDF) of the OpenGL 2.1 spec says:
511    *
512    *     "If program has not been successfully linked, the error
513    *     INVALID_OPERATION is generated."
514    */
515   if (shProg->LinkStatus == GL_FALSE) {
516      _mesa_error(ctx, GL_INVALID_OPERATION,
517		  "glGetUniformLocation(program not linked)");
518      return -1;
519   }
520
521   index = _mesa_get_uniform_location(ctx, shProg, name, &offset);
522   if (index == GL_INVALID_INDEX)
523      return -1;
524
525   /* From the GL_ARB_uniform_buffer_object spec:
526    *
527    *     "The value -1 will be returned if <name> does not correspond to an
528    *      active uniform variable name in <program>, if <name> is associated
529    *      with a named uniform block, or if <name> starts with the reserved
530    *      prefix "gl_"."
531    */
532   if (shProg->UniformStorage[index].block_index != -1)
533      return -1;
534
535   return _mesa_uniform_merge_location_offset(index, offset);
536}
537
538static GLuint GLAPIENTRY
539_mesa_GetUniformBlockIndex(GLuint program,
540			   const GLchar *uniformBlockName)
541{
542   GET_CURRENT_CONTEXT(ctx);
543   GLuint i;
544   struct gl_shader_program *shProg;
545
546   if (!ctx->Extensions.ARB_uniform_buffer_object) {
547      _mesa_error(ctx, GL_INVALID_OPERATION, "glGetUniformBlockIndex");
548      return GL_INVALID_INDEX;
549   }
550
551   shProg = _mesa_lookup_shader_program_err(ctx, program,
552					    "glGetUniformBlockIndex");
553   if (!shProg)
554      return GL_INVALID_INDEX;
555
556   for (i = 0; i < shProg->NumUniformBlocks; i++) {
557      if (!strcmp(shProg->UniformBlocks[i].Name, uniformBlockName))
558	 return i;
559   }
560
561   return GL_INVALID_INDEX;
562}
563
564static void GLAPIENTRY
565_mesa_GetUniformIndices(GLuint program,
566			GLsizei uniformCount,
567			const GLchar * const *uniformNames,
568			GLuint *uniformIndices)
569{
570   GET_CURRENT_CONTEXT(ctx);
571   GLsizei i;
572   struct gl_shader_program *shProg;
573
574   if (!ctx->Extensions.ARB_uniform_buffer_object) {
575      _mesa_error(ctx, GL_INVALID_OPERATION, "glGetUniformIndices");
576      return;
577   }
578
579   shProg = _mesa_lookup_shader_program_err(ctx, program,
580					    "glGetUniformIndices");
581   if (!shProg)
582      return;
583
584   if (uniformCount < 0) {
585      _mesa_error(ctx, GL_INVALID_VALUE,
586		  "glGetUniformIndices(uniformCount < 0)");
587      return;
588   }
589
590   for (i = 0; i < uniformCount; i++) {
591      unsigned offset;
592      uniformIndices[i] = _mesa_get_uniform_location(ctx, shProg,
593						     uniformNames[i], &offset);
594   }
595}
596
597static void GLAPIENTRY
598_mesa_UniformBlockBinding(GLuint program,
599			  GLuint uniformBlockIndex,
600			  GLuint uniformBlockBinding)
601{
602   GET_CURRENT_CONTEXT(ctx);
603   struct gl_shader_program *shProg;
604
605   if (!ctx->Extensions.ARB_uniform_buffer_object) {
606      _mesa_error(ctx, GL_INVALID_OPERATION, "glUniformBlockBinding");
607      return;
608   }
609
610   shProg = _mesa_lookup_shader_program_err(ctx, program,
611					    "glUniformBlockBinding");
612   if (!shProg)
613      return;
614
615   if (uniformBlockIndex >= shProg->NumUniformBlocks) {
616      _mesa_error(ctx, GL_INVALID_VALUE,
617		  "glUniformBlockBinding(block index %d >= %d)",
618		  uniformBlockIndex, shProg->NumUniformBlocks);
619      return;
620   }
621
622   if (uniformBlockBinding >= ctx->Const.MaxUniformBufferBindings) {
623      _mesa_error(ctx, GL_INVALID_VALUE,
624		  "glUniformBlockBinding(block binding %d >= %d)",
625		  uniformBlockBinding, ctx->Const.MaxUniformBufferBindings);
626      return;
627   }
628
629   if (shProg->UniformBlocks[uniformBlockIndex].Binding !=
630       uniformBlockBinding) {
631      int i;
632
633      FLUSH_VERTICES(ctx, _NEW_BUFFER_OBJECT);
634      shProg->UniformBlocks[uniformBlockIndex].Binding = uniformBlockBinding;
635
636      for (i = 0; i < MESA_SHADER_TYPES; i++) {
637	 int stage_index = shProg->UniformBlockStageIndex[i][uniformBlockIndex];
638
639	 if (stage_index != -1) {
640	    struct gl_shader *sh = shProg->_LinkedShaders[i];
641	    sh->UniformBlocks[stage_index].Binding = uniformBlockBinding;
642	 }
643      }
644   }
645}
646
647static void GLAPIENTRY
648_mesa_GetActiveUniformBlockiv(GLuint program,
649			      GLuint uniformBlockIndex,
650			      GLenum pname,
651			      GLint *params)
652{
653   GET_CURRENT_CONTEXT(ctx);
654   struct gl_shader_program *shProg;
655   struct gl_uniform_block *block;
656   unsigned i;
657
658   if (!ctx->Extensions.ARB_uniform_buffer_object) {
659      _mesa_error(ctx, GL_INVALID_OPERATION, "glGetActiveUniformBlockiv");
660      return;
661   }
662
663   shProg = _mesa_lookup_shader_program_err(ctx, program,
664					    "glGetActiveUniformBlockiv");
665   if (!shProg)
666      return;
667
668   if (uniformBlockIndex >= shProg->NumUniformBlocks) {
669      _mesa_error(ctx, GL_INVALID_VALUE,
670		  "glGetActiveUniformBlockiv(block index %d >= %d)",
671		  uniformBlockIndex, shProg->NumUniformBlocks);
672      return;
673   }
674
675   block = &shProg->UniformBlocks[uniformBlockIndex];
676
677   switch (pname) {
678   case GL_UNIFORM_BLOCK_BINDING:
679      params[0] = block->Binding;
680      return;
681
682   case GL_UNIFORM_BLOCK_DATA_SIZE:
683      params[0] = block->UniformBufferSize;
684      return;
685
686   case GL_UNIFORM_BLOCK_NAME_LENGTH:
687      params[0] = strlen(block->Name) + 1;
688      return;
689
690   case GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS:
691      params[0] = block->NumUniforms;
692      return;
693
694   case GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES:
695      for (i = 0; i < block->NumUniforms; i++) {
696	 unsigned offset;
697	 params[i] = _mesa_get_uniform_location(ctx, shProg,
698						block->Uniforms[i].Name,
699						&offset);
700      }
701      return;
702
703   case GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER:
704      params[0] = shProg->UniformBlockStageIndex[MESA_SHADER_VERTEX][uniformBlockIndex] != -1;
705      return;
706
707   case GL_UNIFORM_BLOCK_REFERENCED_BY_GEOMETRY_SHADER:
708      params[0] = shProg->UniformBlockStageIndex[MESA_SHADER_GEOMETRY][uniformBlockIndex] != -1;
709      return;
710
711   case GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER:
712      params[0] = shProg->UniformBlockStageIndex[MESA_SHADER_FRAGMENT][uniformBlockIndex] != -1;
713      return;
714
715   default:
716      _mesa_error(ctx, GL_INVALID_ENUM,
717		  "glGetActiveUniformBlockiv(pname 0x%x (%s))",
718		  pname, _mesa_lookup_enum_by_nr(pname));
719      return;
720   }
721}
722
723static void GLAPIENTRY
724_mesa_GetActiveUniformBlockName(GLuint program,
725				GLuint uniformBlockIndex,
726				GLsizei bufSize,
727				GLsizei *length,
728				GLchar *uniformBlockName)
729{
730   GET_CURRENT_CONTEXT(ctx);
731   struct gl_shader_program *shProg;
732   struct gl_uniform_block *block;
733
734   if (!ctx->Extensions.ARB_uniform_buffer_object) {
735      _mesa_error(ctx, GL_INVALID_OPERATION, "glGetActiveUniformBlockiv");
736      return;
737   }
738
739   if (bufSize < 0) {
740      _mesa_error(ctx, GL_INVALID_VALUE,
741		  "glGetActiveUniformBlockName(bufSize %d < 0)",
742		  bufSize);
743      return;
744   }
745
746   shProg = _mesa_lookup_shader_program_err(ctx, program,
747					    "glGetActiveUniformBlockiv");
748   if (!shProg)
749      return;
750
751   if (uniformBlockIndex >= shProg->NumUniformBlocks) {
752      _mesa_error(ctx, GL_INVALID_VALUE,
753		  "glGetActiveUniformBlockiv(block index %d >= %d)",
754		  uniformBlockIndex, shProg->NumUniformBlocks);
755      return;
756   }
757
758   block = &shProg->UniformBlocks[uniformBlockIndex];
759
760   if (uniformBlockName) {
761      _mesa_copy_string(uniformBlockName, bufSize, length, block->Name);
762   }
763}
764
765static void GLAPIENTRY
766_mesa_GetActiveUniformName(GLuint program, GLuint uniformIndex,
767			   GLsizei bufSize, GLsizei *length,
768			   GLchar *uniformName)
769{
770   GET_CURRENT_CONTEXT(ctx);
771   struct gl_shader_program *shProg;
772
773   if (!ctx->Extensions.ARB_uniform_buffer_object) {
774      _mesa_error(ctx, GL_INVALID_OPERATION, "glGetActiveUniformBlockiv");
775      return;
776   }
777
778   if (bufSize < 0) {
779      _mesa_error(ctx, GL_INVALID_VALUE,
780		  "glGetActiveUniformName(bufSize %d < 0)",
781		  bufSize);
782      return;
783   }
784
785   ASSERT_OUTSIDE_BEGIN_END(ctx);
786
787   shProg = _mesa_lookup_shader_program_err(ctx, program, "glGetActiveUniformName");
788
789   if (!shProg)
790      return;
791
792   if (uniformIndex >= shProg->NumUserUniformStorage) {
793      _mesa_error(ctx, GL_INVALID_VALUE, "glGetActiveUniform(index)");
794      return;
795   }
796
797   if (uniformName) {
798      _mesa_copy_string(uniformName, bufSize, length,
799			shProg->UniformStorage[uniformIndex].name);
800   }
801}
802
803/**
804 * Plug in shader uniform-related functions into API dispatch table.
805 */
806void
807_mesa_init_shader_uniform_dispatch(const struct gl_context *ctx,
808                                   struct _glapi_table *exec)
809{
810#if FEATURE_GL
811   SET_Uniform1fARB(exec, _mesa_Uniform1fARB);
812   SET_Uniform2fARB(exec, _mesa_Uniform2fARB);
813   SET_Uniform3fARB(exec, _mesa_Uniform3fARB);
814   SET_Uniform4fARB(exec, _mesa_Uniform4fARB);
815   SET_Uniform1iARB(exec, _mesa_Uniform1iARB);
816   SET_Uniform2iARB(exec, _mesa_Uniform2iARB);
817   SET_Uniform3iARB(exec, _mesa_Uniform3iARB);
818   SET_Uniform4iARB(exec, _mesa_Uniform4iARB);
819   SET_Uniform1fvARB(exec, _mesa_Uniform1fvARB);
820   SET_Uniform2fvARB(exec, _mesa_Uniform2fvARB);
821   SET_Uniform3fvARB(exec, _mesa_Uniform3fvARB);
822   SET_Uniform4fvARB(exec, _mesa_Uniform4fvARB);
823   SET_Uniform1ivARB(exec, _mesa_Uniform1ivARB);
824   SET_Uniform2ivARB(exec, _mesa_Uniform2ivARB);
825   SET_Uniform3ivARB(exec, _mesa_Uniform3ivARB);
826   SET_Uniform4ivARB(exec, _mesa_Uniform4ivARB);
827   SET_UniformMatrix2fvARB(exec, _mesa_UniformMatrix2fvARB);
828   SET_UniformMatrix3fvARB(exec, _mesa_UniformMatrix3fvARB);
829   SET_UniformMatrix4fvARB(exec, _mesa_UniformMatrix4fvARB);
830
831   SET_GetActiveUniformARB(exec, _mesa_GetActiveUniformARB);
832   SET_GetUniformLocationARB(exec, _mesa_GetUniformLocationARB);
833   SET_GetUniformfvARB(exec, _mesa_GetUniformfvARB);
834   SET_GetUniformivARB(exec, _mesa_GetUniformivARB);
835
836   /* OpenGL 2.1 */
837   if (ctx->API != API_OPENGLES2 || _mesa_is_gles3(ctx)) {
838      SET_UniformMatrix2x3fv(exec, _mesa_UniformMatrix2x3fv);
839      SET_UniformMatrix3x2fv(exec, _mesa_UniformMatrix3x2fv);
840      SET_UniformMatrix2x4fv(exec, _mesa_UniformMatrix2x4fv);
841      SET_UniformMatrix4x2fv(exec, _mesa_UniformMatrix4x2fv);
842      SET_UniformMatrix3x4fv(exec, _mesa_UniformMatrix3x4fv);
843      SET_UniformMatrix4x3fv(exec, _mesa_UniformMatrix4x3fv);
844
845      /* OpenGL 3.0 */
846      SET_Uniform1uiEXT(exec, _mesa_Uniform1ui);
847      SET_Uniform2uiEXT(exec, _mesa_Uniform2ui);
848      SET_Uniform3uiEXT(exec, _mesa_Uniform3ui);
849      SET_Uniform4uiEXT(exec, _mesa_Uniform4ui);
850      SET_Uniform1uivEXT(exec, _mesa_Uniform1uiv);
851      SET_Uniform2uivEXT(exec, _mesa_Uniform2uiv);
852      SET_Uniform3uivEXT(exec, _mesa_Uniform3uiv);
853      SET_Uniform4uivEXT(exec, _mesa_Uniform4uiv);
854      SET_GetUniformuivEXT(exec, _mesa_GetUniformuiv);
855
856      /* GL_ARB_robustness */
857      SET_GetnUniformfvARB(exec, _mesa_GetnUniformfvARB);
858      SET_GetnUniformivARB(exec, _mesa_GetnUniformivARB);
859      SET_GetnUniformuivARB(exec, _mesa_GetnUniformuivARB);
860      SET_GetnUniformdvARB(exec, _mesa_GetnUniformdvARB); /* GL 4.0 */
861
862      /* GL_ARB_uniform_buffer_object / GL 3.1 */
863      SET_GetUniformBlockIndex(exec, _mesa_GetUniformBlockIndex);
864      SET_GetUniformIndices(exec, _mesa_GetUniformIndices);
865      SET_GetActiveUniformsiv(exec, _mesa_GetActiveUniformsiv);
866      SET_GetActiveUniformBlockiv(exec, _mesa_GetActiveUniformBlockiv);
867      SET_GetActiveUniformBlockName(exec, _mesa_GetActiveUniformBlockName);
868      SET_GetActiveUniformName(exec, _mesa_GetActiveUniformName);
869      SET_UniformBlockBinding(exec, _mesa_UniformBlockBinding);
870   }
871#endif /* FEATURE_GL */
872}
873