Home | History | Annotate | Download | only in main
      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 }
    873