mesa: Don't set uniform dispatch pointers for many things in ES2 or core
[profile/ivi/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 #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  */
63 void
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  */
95 void
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  */
122 void
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
130 void 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
137 void 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
147 void 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
158 void 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
171 void 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
178 void 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
188 void 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
199 void 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
211 void 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
218 void 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
225 void 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
232 void 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
239 void 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
246 void 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
253 void 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
260 void 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 **/
269 void 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
276 void 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
286 void 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
297 void 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
309 void 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
316 void 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
323 void 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
330 void 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
339 void 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
348 void 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
357 void 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  */
370 void 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
379 void 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
388 void 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
397 void 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
406 void 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
415 void 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
425 void 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
433 void GLAPIENTRY
434 _mesa_GetUniformfvARB(GLhandleARB program, GLint location, GLfloat *params)
435 {
436    _mesa_GetnUniformfvARB(program, location, INT_MAX, params);
437 }
438
439
440 void 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
448 void GLAPIENTRY
449 _mesa_GetUniformivARB(GLhandleARB program, GLint location, GLint *params)
450 {
451    _mesa_GetnUniformivARB(program, location, INT_MAX, params);
452 }
453
454
455 /* GL3 */
456 void 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
464 void GLAPIENTRY
465 _mesa_GetUniformuiv(GLhandleARB program, GLint location, GLuint *params)
466 {
467    _mesa_GetnUniformuivARB(program, location, INT_MAX, params);
468 }
469
470
471 /* GL4 */
472 void 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
490 void GLAPIENTRY
491 _mesa_GetUniformdv(GLhandleARB program, GLint location, GLdouble *params)
492 {
493    _mesa_GetnUniformdvARB(program, location, INT_MAX, params);
494 }
495
496
497 GLint 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
538 static 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
564 static 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
597 static 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
647 static 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
723 static 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
765 static 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  */
806 void
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 }