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