Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | RSS feed

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