mesa: Add support for ARB_shader_atomic_counters.
[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 #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 shProg->UniformStorage[index].atomic_buffer_index != -1)
540 return -1;
541
542 return _mesa_uniform_merge_location_offset(shProg, index, offset);
543 }
544
545 GLuint GLAPIENTRY
546 _mesa_GetUniformBlockIndex(GLuint program,
547 const GLchar *uniformBlockName)
548 {
549 GET_CURRENT_CONTEXT(ctx);
550 GLuint i;
551 struct gl_shader_program *shProg;
552
553 if (!ctx->Extensions.ARB_uniform_buffer_object) {
554 _mesa_error(ctx, GL_INVALID_OPERATION, "glGetUniformBlockIndex");
555 return GL_INVALID_INDEX;
556 }
557
558 shProg = _mesa_lookup_shader_program_err(ctx, program,
559 "glGetUniformBlockIndex");
560 if (!shProg)
561 return GL_INVALID_INDEX;
562
563 for (i = 0; i < shProg->NumUniformBlocks; i++) {
564 if (!strcmp(shProg->UniformBlocks[i].Name, uniformBlockName))
565 return i;
566 }
567
568 return GL_INVALID_INDEX;
569 }
570
571 void GLAPIENTRY
572 _mesa_GetUniformIndices(GLuint program,
573 GLsizei uniformCount,
574 const GLchar * const *uniformNames,
575 GLuint *uniformIndices)
576 {
577 GET_CURRENT_CONTEXT(ctx);
578 GLsizei i;
579 struct gl_shader_program *shProg;
580
581 if (!ctx->Extensions.ARB_uniform_buffer_object) {
582 _mesa_error(ctx, GL_INVALID_OPERATION, "glGetUniformIndices");
583 return;
584 }
585
586 shProg = _mesa_lookup_shader_program_err(ctx, program,
587 "glGetUniformIndices");
588 if (!shProg)
589 return;
590
591 if (uniformCount < 0) {
592 _mesa_error(ctx, GL_INVALID_VALUE,
593 "glGetUniformIndices(uniformCount < 0)");
594 return;
595 }
596
597 for (i = 0; i < uniformCount; i++) {
598 unsigned offset;
599 uniformIndices[i] = _mesa_get_uniform_location(ctx, shProg,
600 uniformNames[i], &offset);
601 }
602 }
603
604 void GLAPIENTRY
605 _mesa_UniformBlockBinding(GLuint program,
606 GLuint uniformBlockIndex,
607 GLuint uniformBlockBinding)
608 {
609 GET_CURRENT_CONTEXT(ctx);
610 struct gl_shader_program *shProg;
611
612 if (!ctx->Extensions.ARB_uniform_buffer_object) {
613 _mesa_error(ctx, GL_INVALID_OPERATION, "glUniformBlockBinding");
614 return;
615 }
616
617 shProg = _mesa_lookup_shader_program_err(ctx, program,
618 "glUniformBlockBinding");
619 if (!shProg)
620 return;
621
622 if (uniformBlockIndex >= shProg->NumUniformBlocks) {
623 _mesa_error(ctx, GL_INVALID_VALUE,
624 "glUniformBlockBinding(block index %u >= %u)",
625 uniformBlockIndex, shProg->NumUniformBlocks);
626 return;
627 }
628
629 if (uniformBlockBinding >= ctx->Const.MaxUniformBufferBindings) {
630 _mesa_error(ctx, GL_INVALID_VALUE,
631 "glUniformBlockBinding(block binding %u >= %u)",
632 uniformBlockBinding, ctx->Const.MaxUniformBufferBindings);
633 return;
634 }
635
636 if (shProg->UniformBlocks[uniformBlockIndex].Binding !=
637 uniformBlockBinding) {
638 int i;
639
640 FLUSH_VERTICES(ctx, 0);
641 ctx->NewDriverState |= ctx->DriverFlags.NewUniformBuffer;
642
643 shProg->UniformBlocks[uniformBlockIndex].Binding = uniformBlockBinding;
644
645 for (i = 0; i < MESA_SHADER_TYPES; i++) {
646 int stage_index = shProg->UniformBlockStageIndex[i][uniformBlockIndex];
647
648 if (stage_index != -1) {
649 struct gl_shader *sh = shProg->_LinkedShaders[i];
650 sh->UniformBlocks[stage_index].Binding = uniformBlockBinding;
651 }
652 }
653 }
654 }
655
656 void GLAPIENTRY
657 _mesa_GetActiveUniformBlockiv(GLuint program,
658 GLuint uniformBlockIndex,
659 GLenum pname,
660 GLint *params)
661 {
662 GET_CURRENT_CONTEXT(ctx);
663 struct gl_shader_program *shProg;
664 struct gl_uniform_block *block;
665 unsigned i;
666
667 if (!ctx->Extensions.ARB_uniform_buffer_object) {
668 _mesa_error(ctx, GL_INVALID_OPERATION, "glGetActiveUniformBlockiv");
669 return;
670 }
671
672 shProg = _mesa_lookup_shader_program_err(ctx, program,
673 "glGetActiveUniformBlockiv");
674 if (!shProg)
675 return;
676
677 if (uniformBlockIndex >= shProg->NumUniformBlocks) {
678 _mesa_error(ctx, GL_INVALID_VALUE,
679 "glGetActiveUniformBlockiv(block index %u >= %u)",
680 uniformBlockIndex, shProg->NumUniformBlocks);
681 return;
682 }
683
684 block = &shProg->UniformBlocks[uniformBlockIndex];
685
686 switch (pname) {
687 case GL_UNIFORM_BLOCK_BINDING:
688 params[0] = block->Binding;
689 return;
690
691 case GL_UNIFORM_BLOCK_DATA_SIZE:
692 params[0] = block->UniformBufferSize;
693 return;
694
695 case GL_UNIFORM_BLOCK_NAME_LENGTH:
696 params[0] = strlen(block->Name) + 1;
697 return;
698
699 case GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS:
700 params[0] = block->NumUniforms;
701 return;
702
703 case GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES:
704 for (i = 0; i < block->NumUniforms; i++) {
705 unsigned offset;
706 params[i] = _mesa_get_uniform_location(ctx, shProg,
707 block->Uniforms[i].IndexName,
708 &offset);
709 }
710 return;
711
712 case GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER:
713 params[0] = shProg->UniformBlockStageIndex[MESA_SHADER_VERTEX][uniformBlockIndex] != -1;
714 return;
715
716 case GL_UNIFORM_BLOCK_REFERENCED_BY_GEOMETRY_SHADER:
717 params[0] = shProg->UniformBlockStageIndex[MESA_SHADER_GEOMETRY][uniformBlockIndex] != -1;
718 return;
719
720 case GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER:
721 params[0] = shProg->UniformBlockStageIndex[MESA_SHADER_FRAGMENT][uniformBlockIndex] != -1;
722 return;
723
724 default:
725 _mesa_error(ctx, GL_INVALID_ENUM,
726 "glGetActiveUniformBlockiv(pname 0x%x (%s))",
727 pname, _mesa_lookup_enum_by_nr(pname));
728 return;
729 }
730 }
731
732 void GLAPIENTRY
733 _mesa_GetActiveUniformBlockName(GLuint program,
734 GLuint uniformBlockIndex,
735 GLsizei bufSize,
736 GLsizei *length,
737 GLchar *uniformBlockName)
738 {
739 GET_CURRENT_CONTEXT(ctx);
740 struct gl_shader_program *shProg;
741 struct gl_uniform_block *block;
742
743 if (!ctx->Extensions.ARB_uniform_buffer_object) {
744 _mesa_error(ctx, GL_INVALID_OPERATION, "glGetActiveUniformBlockiv");
745 return;
746 }
747
748 if (bufSize < 0) {
749 _mesa_error(ctx, GL_INVALID_VALUE,
750 "glGetActiveUniformBlockName(bufSize %d < 0)",
751 bufSize);
752 return;
753 }
754
755 shProg = _mesa_lookup_shader_program_err(ctx, program,
756 "glGetActiveUniformBlockiv");
757 if (!shProg)
758 return;
759
760 if (uniformBlockIndex >= shProg->NumUniformBlocks) {
761 _mesa_error(ctx, GL_INVALID_VALUE,
762 "glGetActiveUniformBlockiv(block index %u >= %u)",
763 uniformBlockIndex, shProg->NumUniformBlocks);
764 return;
765 }
766
767 block = &shProg->UniformBlocks[uniformBlockIndex];
768
769 if (uniformBlockName) {
770 _mesa_copy_string(uniformBlockName, bufSize, length, block->Name);
771 }
772 }
773
774 void GLAPIENTRY
775 _mesa_GetActiveUniformName(GLuint program, GLuint uniformIndex,
776 GLsizei bufSize, GLsizei *length,
777 GLchar *uniformName)
778 {
779 GET_CURRENT_CONTEXT(ctx);
780 struct gl_shader_program *shProg;
781
782 if (!ctx->Extensions.ARB_uniform_buffer_object) {
783 _mesa_error(ctx, GL_INVALID_OPERATION, "glGetActiveUniformBlockiv");
784 return;
785 }
786
787 if (bufSize < 0) {
788 _mesa_error(ctx, GL_INVALID_VALUE,
789 "glGetActiveUniformName(bufSize %d < 0)",
790 bufSize);
791 return;
792 }
793
794 shProg = _mesa_lookup_shader_program_err(ctx, program, "glGetActiveUniformName");
795
796 if (!shProg)
797 return;
798
799 if (uniformIndex >= shProg->NumUserUniformStorage) {
800 _mesa_error(ctx, GL_INVALID_VALUE, "glGetActiveUniform(index)");
801 return;
802 }
803
804 if (uniformName) {
805 _mesa_get_uniform_name(& shProg->UniformStorage[uniformIndex],
806 bufSize, length, uniformName);
807 }
808 }
809
810 void
811 _mesa_get_uniform_name(const struct gl_uniform_storage *uni,
812 GLsizei maxLength, GLsizei *length,
813 GLchar *nameOut)
814 {
815 GLsizei localLength;
816
817 if (length == NULL)
818 length = &localLength;
819
820 _mesa_copy_string(nameOut, maxLength, length, uni->name);
821
822 /* Page 61 (page 73 of the PDF) in section 2.11 of the OpenGL ES 3.0
823 * spec says:
824 *
825 * "If the active uniform is an array, the uniform name returned in
826 * name will always be the name of the uniform array appended with
827 * "[0]"."
828 *
829 * The same text also appears in the OpenGL 4.2 spec. It does not,
830 * however, appear in any previous spec. Previous specifications are
831 * ambiguous in this regard. However, either name can later be passed
832 * to glGetUniformLocation (and related APIs), so there shouldn't be any
833 * harm in always appending "[0]" to uniform array names.
834 */
835 if (uni->array_elements != 0) {
836 int i;
837
838 /* The comparison is strange because *length does *NOT* include the
839 * terminating NUL, but maxLength does.
840 */
841 for (i = 0; i < 3 && (*length + i + 1) < maxLength; i++)
842 nameOut[*length + i] = "[0]"[i];
843
844 nameOut[*length + i] = '\0';
845 *length += i;
846 }
847 }
848
849 void GLAPIENTRY
850 _mesa_GetActiveAtomicCounterBufferiv(GLuint program, GLuint bufferIndex,
851 GLenum pname, GLint *params)
852 {
853 GET_CURRENT_CONTEXT(ctx);
854 struct gl_shader_program *shProg;
855 struct gl_active_atomic_buffer *ab;
856 int i;
857
858 if (!ctx->Extensions.ARB_shader_atomic_counters) {
859 _mesa_error(ctx, GL_INVALID_OPERATION,
860 "glGetActiveAtomicCounterBufferiv");
861 return;
862 }
863
864 shProg = _mesa_lookup_shader_program_err(ctx, program,
865 "glGetActiveAtomicCounterBufferiv");
866 if (!shProg)
867 return;
868
869 if (bufferIndex >= shProg->NumAtomicBuffers) {
870 _mesa_error(ctx, GL_INVALID_VALUE,
871 "glGetActiveAtomicCounterBufferiv(bufferIndex)");
872 return;
873 }
874
875 ab = &shProg->AtomicBuffers[bufferIndex];
876
877 switch (pname) {
878 case GL_ATOMIC_COUNTER_BUFFER_BINDING:
879 params[0] = ab->Binding;
880 return;
881 case GL_ATOMIC_COUNTER_BUFFER_DATA_SIZE:
882 params[0] = ab->MinimumSize;
883 return;
884 case GL_ATOMIC_COUNTER_BUFFER_ACTIVE_ATOMIC_COUNTERS:
885 params[0] = ab->NumUniforms;
886 return;
887 case GL_ATOMIC_COUNTER_BUFFER_ACTIVE_ATOMIC_COUNTER_INDICES:
888 for (i = 0; i < ab->NumUniforms; ++i)
889 params[i] = ab->Uniforms[i];
890 return;
891 case GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_VERTEX_SHADER:
892 params[0] = ab->StageReferences[MESA_SHADER_VERTEX];
893 return;
894 case GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_GEOMETRY_SHADER:
895 params[0] = ab->StageReferences[MESA_SHADER_GEOMETRY];
896 return;
897 case GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_FRAGMENT_SHADER:
898 params[0] = ab->StageReferences[MESA_SHADER_FRAGMENT];
899 return;
900 case GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_TESS_CONTROL_SHADER:
901 params[0] = GL_FALSE;
902 return;
903 case GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_TESS_EVALUATION_SHADER:
904 params[0] = GL_FALSE;
905 return;
906 default:
907 _mesa_error(ctx, GL_INVALID_ENUM,
908 "glGetActiveAtomicCounterBufferiv(pname 0x%x (%s))",
909 pname, _mesa_lookup_enum_by_nr(pname));
910 return;
911 }
912 }