b5f1d082c3e8b9c39eff248e3b248cb494ee09c4
[mesa.git] / src / mesa / main / shader_query.cpp
1 /*
2 * Copyright © 2011 Intel Corporation
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
13 * Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21 * DEALINGS IN THE SOFTWARE.
22 */
23
24 /**
25 * \file shader_query.cpp
26 * C-to-C++ bridge functions to query GLSL shader data
27 *
28 * \author Ian Romanick <ian.d.romanick@intel.com>
29 */
30
31 #include "main/core.h"
32 #include "glsl_symbol_table.h"
33 #include "ir.h"
34 #include "shaderobj.h"
35 #include "program/hash_table.h"
36 #include "../glsl/program.h"
37 #include "uniforms.h"
38 #include "main/enums.h"
39
40 extern "C" {
41 #include "shaderapi.h"
42 }
43
44 static GLint
45 program_resource_location(struct gl_shader_program *shProg,
46 struct gl_program_resource *res, const char *name);
47
48 /**
49 * Declare convenience functions to return resource data in a given type.
50 * Warning! this is not type safe so be *very* careful when using these.
51 */
52 #define DECL_RESOURCE_FUNC(name, type) \
53 const type * RESOURCE_ ## name (gl_program_resource *res) { \
54 assert(res->Data); \
55 return (type *) res->Data; \
56 }
57
58 DECL_RESOURCE_FUNC(VAR, ir_variable);
59 DECL_RESOURCE_FUNC(UBO, gl_uniform_block);
60 DECL_RESOURCE_FUNC(UNI, gl_uniform_storage);
61 DECL_RESOURCE_FUNC(ATC, gl_active_atomic_buffer);
62 DECL_RESOURCE_FUNC(XFB, gl_transform_feedback_varying_info);
63
64 void GLAPIENTRY
65 _mesa_BindAttribLocation(GLhandleARB program, GLuint index,
66 const GLcharARB *name)
67 {
68 GET_CURRENT_CONTEXT(ctx);
69
70 struct gl_shader_program *const shProg =
71 _mesa_lookup_shader_program_err(ctx, program, "glBindAttribLocation");
72 if (!shProg)
73 return;
74
75 if (!name)
76 return;
77
78 if (strncmp(name, "gl_", 3) == 0) {
79 _mesa_error(ctx, GL_INVALID_OPERATION,
80 "glBindAttribLocation(illegal name)");
81 return;
82 }
83
84 if (index >= ctx->Const.Program[MESA_SHADER_VERTEX].MaxAttribs) {
85 _mesa_error(ctx, GL_INVALID_VALUE, "glBindAttribLocation(index)");
86 return;
87 }
88
89 /* Replace the current value if it's already in the list. Add
90 * VERT_ATTRIB_GENERIC0 because that's how the linker differentiates
91 * between built-in attributes and user-defined attributes.
92 */
93 shProg->AttributeBindings->put(index + VERT_ATTRIB_GENERIC0, name);
94
95 /*
96 * Note that this attribute binding won't go into effect until
97 * glLinkProgram is called again.
98 */
99 }
100
101 static bool
102 is_active_attrib(const ir_variable *var)
103 {
104 if (!var)
105 return false;
106
107 switch (var->data.mode) {
108 case ir_var_shader_in:
109 return var->data.location != -1;
110
111 case ir_var_system_value:
112 /* From GL 4.3 core spec, section 11.1.1 (Vertex Attributes):
113 * "For GetActiveAttrib, all active vertex shader input variables
114 * are enumerated, including the special built-in inputs gl_VertexID
115 * and gl_InstanceID."
116 */
117 return var->data.location == SYSTEM_VALUE_VERTEX_ID ||
118 var->data.location == SYSTEM_VALUE_VERTEX_ID_ZERO_BASE ||
119 var->data.location == SYSTEM_VALUE_INSTANCE_ID;
120
121 default:
122 return false;
123 }
124 }
125
126 void GLAPIENTRY
127 _mesa_GetActiveAttrib(GLhandleARB program, GLuint desired_index,
128 GLsizei maxLength, GLsizei * length, GLint * size,
129 GLenum * type, GLcharARB * name)
130 {
131 GET_CURRENT_CONTEXT(ctx);
132 struct gl_shader_program *shProg;
133
134 if (maxLength < 0) {
135 _mesa_error(ctx, GL_INVALID_VALUE, "glGetActiveAttrib(maxLength < 0)");
136 return;
137 }
138
139 shProg = _mesa_lookup_shader_program_err(ctx, program, "glGetActiveAttrib");
140 if (!shProg)
141 return;
142
143 if (!shProg->LinkStatus) {
144 _mesa_error(ctx, GL_INVALID_VALUE,
145 "glGetActiveAttrib(program not linked)");
146 return;
147 }
148
149 if (shProg->_LinkedShaders[MESA_SHADER_VERTEX] == NULL) {
150 _mesa_error(ctx, GL_INVALID_VALUE, "glGetActiveAttrib(no vertex shader)");
151 return;
152 }
153
154 struct gl_program_resource *res =
155 _mesa_program_resource_find_index(shProg, GL_PROGRAM_INPUT,
156 desired_index);
157
158 /* User asked for index that does not exist. */
159 if (!res) {
160 _mesa_error(ctx, GL_INVALID_VALUE, "glGetActiveAttrib(index)");
161 return;
162 }
163
164 const ir_variable *const var = RESOURCE_VAR(res);
165
166 if (!is_active_attrib(var))
167 return;
168
169 const char *var_name = var->name;
170
171 /* Since gl_VertexID may be lowered to gl_VertexIDMESA, we need to
172 * consider gl_VertexIDMESA as gl_VertexID for purposes of checking
173 * active attributes.
174 */
175 if (var->data.mode == ir_var_system_value &&
176 var->data.location == SYSTEM_VALUE_VERTEX_ID_ZERO_BASE) {
177 var_name = "gl_VertexID";
178 }
179
180 _mesa_copy_string(name, maxLength, length, var_name);
181
182 if (size)
183 _mesa_program_resource_prop(shProg, res, desired_index, GL_ARRAY_SIZE,
184 size, "glGetActiveAttrib");
185
186 if (type)
187 _mesa_program_resource_prop(shProg, res, desired_index, GL_TYPE,
188 (GLint *) type, "glGetActiveAttrib");
189 }
190
191 /* Locations associated with shader variables (array or non-array) can be
192 * queried using its base name or using the base name appended with the
193 * valid array index. For example, in case of below vertex shader, valid
194 * queries can be made to know the location of "xyz", "array", "array[0]",
195 * "array[1]", "array[2]" and "array[3]". In this example index reurned
196 * will be 0, 0, 0, 1, 2, 3 respectively.
197 *
198 * [Vertex Shader]
199 * layout(location=0) in vec4 xyz;
200 * layout(location=1) in vec4[4] array;
201 * void main()
202 * { }
203 *
204 * This requirement came up with the addition of ARB_program_interface_query
205 * to OpenGL 4.3 specification. See page 101 (page 122 of the PDF) for details.
206 *
207 * This utility function is used by:
208 * _mesa_GetAttribLocation
209 * _mesa_GetFragDataLocation
210 * _mesa_GetFragDataIndex
211 *
212 * Returns 0:
213 * if the 'name' string matches var->name.
214 * Returns 'matched index':
215 * if the 'name' string matches var->name appended with valid array index.
216 */
217 int static inline
218 get_matching_index(const ir_variable *const var, const char *name) {
219 unsigned idx = 0;
220 const char *const paren = strchr(name, '[');
221 const unsigned len = (paren != NULL) ? paren - name : strlen(name);
222
223 if (paren != NULL) {
224 if (!var->type->is_array())
225 return -1;
226
227 char *endptr;
228 idx = (unsigned) strtol(paren + 1, &endptr, 10);
229 const unsigned idx_len = endptr != (paren + 1) ? endptr - paren - 1 : 0;
230
231 /* Validate the sub string representing index in 'name' string */
232 if ((idx > 0 && paren[1] == '0') /* leading zeroes */
233 || (idx == 0 && idx_len > 1) /* all zeroes */
234 || paren[1] == ' ' /* whitespace */
235 || endptr[0] != ']' /* closing brace */
236 || endptr[1] != '\0' /* null char */
237 || idx_len == 0 /* missing index */
238 || idx >= var->type->length) /* exceeding array bound */
239 return -1;
240 }
241
242 if (strncmp(var->name, name, len) == 0 && var->name[len] == '\0')
243 return idx;
244
245 return -1;
246 }
247
248 GLint GLAPIENTRY
249 _mesa_GetAttribLocation(GLhandleARB program, const GLcharARB * name)
250 {
251 GET_CURRENT_CONTEXT(ctx);
252 struct gl_shader_program *const shProg =
253 _mesa_lookup_shader_program_err(ctx, program, "glGetAttribLocation");
254
255 if (!shProg) {
256 return -1;
257 }
258
259 if (!shProg->LinkStatus) {
260 _mesa_error(ctx, GL_INVALID_OPERATION,
261 "glGetAttribLocation(program not linked)");
262 return -1;
263 }
264
265 if (!name)
266 return -1;
267
268 /* Not having a vertex shader is not an error.
269 */
270 if (shProg->_LinkedShaders[MESA_SHADER_VERTEX] == NULL)
271 return -1;
272
273 struct gl_program_resource *res =
274 _mesa_program_resource_find_name(shProg, GL_PROGRAM_INPUT, name);
275
276 if (!res)
277 return -1;
278
279 GLint loc = program_resource_location(shProg, res, name);
280
281 /* The extra check against against 0 is made because of builtin-attribute
282 * locations that have offset applied. Function program_resource_location
283 * can return built-in attribute locations < 0 and glGetAttribLocation
284 * cannot be used on "conventional" attributes.
285 *
286 * From page 95 of the OpenGL 3.0 spec:
287 *
288 * "If name is not an active attribute, if name is a conventional
289 * attribute, or if an error occurs, -1 will be returned."
290 */
291 return (loc >= 0) ? loc : -1;
292 }
293
294
295 unsigned
296 _mesa_count_active_attribs(struct gl_shader_program *shProg)
297 {
298 if (!shProg->LinkStatus
299 || shProg->_LinkedShaders[MESA_SHADER_VERTEX] == NULL) {
300 return 0;
301 }
302
303 exec_list *const ir = shProg->_LinkedShaders[MESA_SHADER_VERTEX]->ir;
304 unsigned i = 0;
305
306 foreach_in_list(ir_instruction, node, ir) {
307 const ir_variable *const var = node->as_variable();
308
309 if (!is_active_attrib(var))
310 continue;
311
312 i++;
313 }
314
315 return i;
316 }
317
318
319 size_t
320 _mesa_longest_attribute_name_length(struct gl_shader_program *shProg)
321 {
322 if (!shProg->LinkStatus
323 || shProg->_LinkedShaders[MESA_SHADER_VERTEX] == NULL) {
324 return 0;
325 }
326
327 exec_list *const ir = shProg->_LinkedShaders[MESA_SHADER_VERTEX]->ir;
328 size_t longest = 0;
329
330 foreach_in_list(ir_instruction, node, ir) {
331 const ir_variable *const var = node->as_variable();
332
333 if (var == NULL
334 || var->data.mode != ir_var_shader_in
335 || var->data.location == -1)
336 continue;
337
338 const size_t len = strlen(var->name);
339 if (len >= longest)
340 longest = len + 1;
341 }
342
343 return longest;
344 }
345
346 void GLAPIENTRY
347 _mesa_BindFragDataLocation(GLuint program, GLuint colorNumber,
348 const GLchar *name)
349 {
350 _mesa_BindFragDataLocationIndexed(program, colorNumber, 0, name);
351 }
352
353 void GLAPIENTRY
354 _mesa_BindFragDataLocationIndexed(GLuint program, GLuint colorNumber,
355 GLuint index, const GLchar *name)
356 {
357 GET_CURRENT_CONTEXT(ctx);
358
359 struct gl_shader_program *const shProg =
360 _mesa_lookup_shader_program_err(ctx, program, "glBindFragDataLocationIndexed");
361 if (!shProg)
362 return;
363
364 if (!name)
365 return;
366
367 if (strncmp(name, "gl_", 3) == 0) {
368 _mesa_error(ctx, GL_INVALID_OPERATION, "glBindFragDataLocationIndexed(illegal name)");
369 return;
370 }
371
372 if (index > 1) {
373 _mesa_error(ctx, GL_INVALID_VALUE, "glBindFragDataLocationIndexed(index)");
374 return;
375 }
376
377 if (index == 0 && colorNumber >= ctx->Const.MaxDrawBuffers) {
378 _mesa_error(ctx, GL_INVALID_VALUE, "glBindFragDataLocationIndexed(colorNumber)");
379 return;
380 }
381
382 if (index == 1 && colorNumber >= ctx->Const.MaxDualSourceDrawBuffers) {
383 _mesa_error(ctx, GL_INVALID_VALUE, "glBindFragDataLocationIndexed(colorNumber)");
384 return;
385 }
386
387 /* Replace the current value if it's already in the list. Add
388 * FRAG_RESULT_DATA0 because that's how the linker differentiates
389 * between built-in attributes and user-defined attributes.
390 */
391 shProg->FragDataBindings->put(colorNumber + FRAG_RESULT_DATA0, name);
392 shProg->FragDataIndexBindings->put(index, name);
393 /*
394 * Note that this binding won't go into effect until
395 * glLinkProgram is called again.
396 */
397
398 }
399
400 GLint GLAPIENTRY
401 _mesa_GetFragDataIndex(GLuint program, const GLchar *name)
402 {
403 GET_CURRENT_CONTEXT(ctx);
404 struct gl_shader_program *const shProg =
405 _mesa_lookup_shader_program_err(ctx, program, "glGetFragDataIndex");
406
407 if (!shProg) {
408 return -1;
409 }
410
411 if (!shProg->LinkStatus) {
412 _mesa_error(ctx, GL_INVALID_OPERATION,
413 "glGetFragDataIndex(program not linked)");
414 return -1;
415 }
416
417 if (!name)
418 return -1;
419
420 if (strncmp(name, "gl_", 3) == 0) {
421 _mesa_error(ctx, GL_INVALID_OPERATION,
422 "glGetFragDataIndex(illegal name)");
423 return -1;
424 }
425
426 /* Not having a fragment shader is not an error.
427 */
428 if (shProg->_LinkedShaders[MESA_SHADER_FRAGMENT] == NULL)
429 return -1;
430
431 return _mesa_program_resource_location_index(shProg, GL_PROGRAM_OUTPUT,
432 name);
433 }
434
435 GLint GLAPIENTRY
436 _mesa_GetFragDataLocation(GLuint program, const GLchar *name)
437 {
438 GET_CURRENT_CONTEXT(ctx);
439 struct gl_shader_program *const shProg =
440 _mesa_lookup_shader_program_err(ctx, program, "glGetFragDataLocation");
441
442 if (!shProg) {
443 return -1;
444 }
445
446 if (!shProg->LinkStatus) {
447 _mesa_error(ctx, GL_INVALID_OPERATION,
448 "glGetFragDataLocation(program not linked)");
449 return -1;
450 }
451
452 if (!name)
453 return -1;
454
455 if (strncmp(name, "gl_", 3) == 0) {
456 _mesa_error(ctx, GL_INVALID_OPERATION,
457 "glGetFragDataLocation(illegal name)");
458 return -1;
459 }
460
461 /* Not having a fragment shader is not an error.
462 */
463 if (shProg->_LinkedShaders[MESA_SHADER_FRAGMENT] == NULL)
464 return -1;
465
466 struct gl_program_resource *res =
467 _mesa_program_resource_find_name(shProg, GL_PROGRAM_OUTPUT, name);
468
469 if (!res)
470 return -1;
471
472 GLint loc = program_resource_location(shProg, res, name);
473
474 /* The extra check against against 0 is made because of builtin-attribute
475 * locations that have offset applied. Function program_resource_location
476 * can return built-in attribute locations < 0 and glGetFragDataLocation
477 * cannot be used on "conventional" attributes.
478 *
479 * From page 95 of the OpenGL 3.0 spec:
480 *
481 * "If name is not an active attribute, if name is a conventional
482 * attribute, or if an error occurs, -1 will be returned."
483 */
484 return (loc >= 0) ? loc : -1;
485 }
486
487 const char*
488 _mesa_program_resource_name(struct gl_program_resource *res)
489 {
490 switch (res->Type) {
491 case GL_UNIFORM_BLOCK:
492 return RESOURCE_UBO(res)->Name;
493 case GL_TRANSFORM_FEEDBACK_VARYING:
494 return RESOURCE_XFB(res)->Name;
495 case GL_PROGRAM_INPUT:
496 case GL_PROGRAM_OUTPUT:
497 return RESOURCE_VAR(res)->name;
498 case GL_UNIFORM:
499 return RESOURCE_UNI(res)->name;
500 default:
501 assert(!"support for resource type not implemented");
502 }
503 return NULL;
504 }
505
506
507 unsigned
508 _mesa_program_resource_array_size(struct gl_program_resource *res)
509 {
510 switch (res->Type) {
511 case GL_TRANSFORM_FEEDBACK_VARYING:
512 return RESOURCE_XFB(res)->Size > 1 ?
513 RESOURCE_XFB(res)->Size : 0;
514 case GL_PROGRAM_INPUT:
515 case GL_PROGRAM_OUTPUT:
516 return RESOURCE_VAR(res)->data.max_array_access;
517 case GL_UNIFORM:
518 return RESOURCE_UNI(res)->array_elements;
519 case GL_ATOMIC_COUNTER_BUFFER:
520 case GL_UNIFORM_BLOCK:
521 return 0;
522 default:
523 assert(!"support for resource type not implemented");
524 }
525 return 0;
526 }
527
528 static int
529 array_index_of_resource(struct gl_program_resource *res,
530 const char *name)
531 {
532 assert(res->Data);
533
534 switch (res->Type) {
535 case GL_PROGRAM_INPUT:
536 case GL_PROGRAM_OUTPUT:
537 return get_matching_index(RESOURCE_VAR(res), name);
538 default:
539 assert(!"support for resource type not implemented");
540 }
541 }
542
543 /* Find a program resource with specific name in given interface.
544 */
545 struct gl_program_resource *
546 _mesa_program_resource_find_name(struct gl_shader_program *shProg,
547 GLenum programInterface, const char *name)
548 {
549 struct gl_program_resource *res = shProg->ProgramResourceList;
550 for (unsigned i = 0; i < shProg->NumProgramResourceList; i++, res++) {
551 if (res->Type != programInterface)
552 continue;
553
554 /* Resource basename. */
555 const char *rname = _mesa_program_resource_name(res);
556 unsigned baselen = strlen(rname);
557
558 switch (programInterface) {
559 case GL_TRANSFORM_FEEDBACK_VARYING:
560 case GL_UNIFORM_BLOCK:
561 case GL_UNIFORM:
562 if (strncmp(rname, name, baselen) == 0) {
563 /* Basename match, check if array or struct. */
564 if (name[baselen] == '\0' ||
565 name[baselen] == '[' ||
566 name[baselen] == '.') {
567 return res;
568 }
569 }
570 break;
571 case GL_PROGRAM_INPUT:
572 case GL_PROGRAM_OUTPUT:
573 if (array_index_of_resource(res, name) >= 0)
574 return res;
575 break;
576 default:
577 assert(!"not implemented for given interface");
578 }
579 }
580 return NULL;
581 }
582
583 static GLuint
584 calc_resource_index(struct gl_shader_program *shProg,
585 struct gl_program_resource *res)
586 {
587 unsigned i;
588 GLuint index = 0;
589 for (i = 0; i < shProg->NumProgramResourceList; i++) {
590 if (&shProg->ProgramResourceList[i] == res)
591 return index;
592 if (shProg->ProgramResourceList[i].Type == res->Type)
593 index++;
594 }
595 return GL_INVALID_INDEX;
596 }
597
598 /**
599 * Calculate index for the given resource.
600 */
601 GLuint
602 _mesa_program_resource_index(struct gl_shader_program *shProg,
603 struct gl_program_resource *res)
604 {
605 if (!res)
606 return GL_INVALID_INDEX;
607
608 switch (res->Type) {
609 case GL_UNIFORM_BLOCK:
610 return RESOURCE_UBO(res)- shProg->UniformBlocks;
611 case GL_ATOMIC_COUNTER_BUFFER:
612 return RESOURCE_ATC(res) - shProg->AtomicBuffers;
613 case GL_TRANSFORM_FEEDBACK_VARYING:
614 default:
615 return calc_resource_index(shProg, res);
616 }
617 }
618
619 /* Find a program resource with specific index in given interface.
620 */
621 struct gl_program_resource *
622 _mesa_program_resource_find_index(struct gl_shader_program *shProg,
623 GLenum programInterface, GLuint index)
624 {
625 struct gl_program_resource *res = shProg->ProgramResourceList;
626 int idx = -1;
627
628 for (unsigned i = 0; i < shProg->NumProgramResourceList; i++, res++) {
629 if (res->Type != programInterface)
630 continue;
631
632 switch (res->Type) {
633 case GL_UNIFORM_BLOCK:
634 case GL_ATOMIC_COUNTER_BUFFER:
635 if (_mesa_program_resource_index(shProg, res) == index)
636 return res;
637
638 case GL_TRANSFORM_FEEDBACK_VARYING:
639 case GL_PROGRAM_INPUT:
640 case GL_PROGRAM_OUTPUT:
641 case GL_UNIFORM:
642 if (++idx == (int) index)
643 return res;
644 break;
645 default:
646 assert(!"not implemented for given interface");
647 }
648 }
649 return NULL;
650 }
651
652 /* Get full name of a program resource.
653 */
654 bool
655 _mesa_get_program_resource_name(struct gl_shader_program *shProg,
656 GLenum programInterface, GLuint index,
657 GLsizei bufSize, GLsizei *length,
658 GLchar *name, const char *caller)
659 {
660 GET_CURRENT_CONTEXT(ctx);
661
662 /* Find resource with given interface and index. */
663 struct gl_program_resource *res =
664 _mesa_program_resource_find_index(shProg, programInterface, index);
665
666 /* The error INVALID_VALUE is generated if <index> is greater than
667 * or equal to the number of entries in the active resource list for
668 * <programInterface>.
669 */
670 if (!res) {
671 _mesa_error(ctx, GL_INVALID_VALUE, "%s(index %u)", caller, index);
672 return false;
673 }
674
675 if (bufSize < 0) {
676 _mesa_error(ctx, GL_INVALID_VALUE, "%s(bufSize %d)", caller, bufSize);
677 return false;
678 }
679
680 GLsizei localLength;
681
682 if (length == NULL)
683 length = &localLength;
684
685 _mesa_copy_string(name, bufSize, length, _mesa_program_resource_name(res));
686
687 /* Page 61 (page 73 of the PDF) in section 2.11 of the OpenGL ES 3.0
688 * spec says:
689 *
690 * "If the active uniform is an array, the uniform name returned in
691 * name will always be the name of the uniform array appended with
692 * "[0]"."
693 *
694 * The same text also appears in the OpenGL 4.2 spec. It does not,
695 * however, appear in any previous spec. Previous specifications are
696 * ambiguous in this regard. However, either name can later be passed
697 * to glGetUniformLocation (and related APIs), so there shouldn't be any
698 * harm in always appending "[0]" to uniform array names.
699 *
700 * Geometry shader stage has different naming convention where the 'normal'
701 * condition is an array, therefore for variables referenced in geometry
702 * stage we do not add '[0]'.
703 *
704 * Note, that TCS outputs and TES inputs should not have index appended
705 * either.
706 */
707 bool add_index = !(((programInterface == GL_PROGRAM_INPUT) &&
708 res->StageReferences & (1 << MESA_SHADER_GEOMETRY)));
709
710 if (add_index && _mesa_program_resource_array_size(res)) {
711 int i;
712
713 /* The comparison is strange because *length does *NOT* include the
714 * terminating NUL, but maxLength does.
715 */
716 for (i = 0; i < 3 && (*length + i + 1) < bufSize; i++)
717 name[*length + i] = "[0]"[i];
718
719 name[*length + i] = '\0';
720 *length += i;
721 }
722 return true;
723 }
724
725 static GLint
726 program_resource_location(struct gl_shader_program *shProg,
727 struct gl_program_resource *res, const char *name)
728 {
729 unsigned index, offset;
730 int array_index = -1;
731
732 if (res->Type == GL_PROGRAM_INPUT || res->Type == GL_PROGRAM_OUTPUT) {
733 array_index = array_index_of_resource(res, name);
734 if (array_index < 0)
735 return -1;
736 }
737
738 /* VERT_ATTRIB_GENERIC0 and FRAG_RESULT_DATA0 are decremented as these
739 * offsets are used internally to differentiate between built-in attributes
740 * and user-defined attributes.
741 */
742 switch (res->Type) {
743 case GL_PROGRAM_INPUT:
744 return RESOURCE_VAR(res)->data.location + array_index - VERT_ATTRIB_GENERIC0;
745 case GL_PROGRAM_OUTPUT:
746 return RESOURCE_VAR(res)->data.location + array_index - FRAG_RESULT_DATA0;
747 case GL_UNIFORM:
748 index = _mesa_get_uniform_location(shProg, name, &offset);
749
750 if (index == GL_INVALID_INDEX)
751 return -1;
752
753 /* From the GL_ARB_uniform_buffer_object spec:
754 *
755 * "The value -1 will be returned if <name> does not correspond to an
756 * active uniform variable name in <program>, if <name> is associated
757 * with a named uniform block, or if <name> starts with the reserved
758 * prefix "gl_"."
759 */
760 if (RESOURCE_UNI(res)->block_index != -1 ||
761 RESOURCE_UNI(res)->atomic_buffer_index != -1)
762 return -1;
763
764 /* location in remap table + array element offset */
765 return RESOURCE_UNI(res)->remap_location + offset;
766
767 default:
768 return -1;
769 }
770 }
771
772 /**
773 * Function implements following location queries:
774 * glGetAttribLocation
775 * glGetFragDataLocation
776 * glGetUniformLocation
777 */
778 GLint
779 _mesa_program_resource_location(struct gl_shader_program *shProg,
780 GLenum programInterface, const char *name)
781 {
782 struct gl_program_resource *res =
783 _mesa_program_resource_find_name(shProg, programInterface, name);
784
785 /* Resource not found. */
786 if (!res)
787 return -1;
788
789 return program_resource_location(shProg, res, name);
790 }
791
792 /**
793 * Function implements following index queries:
794 * glGetFragDataIndex
795 */
796 GLint
797 _mesa_program_resource_location_index(struct gl_shader_program *shProg,
798 GLenum programInterface, const char *name)
799 {
800 struct gl_program_resource *res =
801 _mesa_program_resource_find_name(shProg, programInterface, name);
802
803 /* Non-existent variable or resource is not referenced by fragment stage. */
804 if (!res || !(res->StageReferences & (1 << MESA_SHADER_FRAGMENT)))
805 return -1;
806
807 return RESOURCE_VAR(res)->data.index;
808 }
809
810 static uint8_t
811 stage_from_enum(GLenum ref)
812 {
813 switch (ref) {
814 case GL_REFERENCED_BY_VERTEX_SHADER:
815 return MESA_SHADER_VERTEX;
816 case GL_REFERENCED_BY_GEOMETRY_SHADER:
817 return MESA_SHADER_GEOMETRY;
818 case GL_REFERENCED_BY_FRAGMENT_SHADER:
819 return MESA_SHADER_FRAGMENT;
820 default:
821 assert(!"shader stage not supported");
822 return MESA_SHADER_STAGES;
823 }
824 }
825
826 /**
827 * Check if resource is referenced by given 'referenced by' stage enum.
828 * ATC and UBO resources hold stage references of their own.
829 */
830 static bool
831 is_resource_referenced(struct gl_shader_program *shProg,
832 struct gl_program_resource *res,
833 GLuint index, uint8_t stage)
834 {
835 if (res->Type == GL_ATOMIC_COUNTER_BUFFER)
836 return RESOURCE_ATC(res)->StageReferences[stage];
837
838 if (res->Type == GL_UNIFORM_BLOCK)
839 return shProg->UniformBlockStageIndex[stage][index] != -1;
840
841 return res->StageReferences & (1 << stage);
842 }
843
844 static unsigned
845 get_buffer_property(struct gl_shader_program *shProg,
846 struct gl_program_resource *res, const GLenum prop,
847 GLint *val, const char *caller)
848 {
849 GET_CURRENT_CONTEXT(ctx);
850 if (res->Type != GL_UNIFORM_BLOCK &&
851 res->Type != GL_ATOMIC_COUNTER_BUFFER)
852 goto invalid_operation;
853
854 if (res->Type == GL_UNIFORM_BLOCK) {
855 switch (prop) {
856 case GL_BUFFER_BINDING:
857 *val = RESOURCE_UBO(res)->Binding;
858 return 1;
859 case GL_BUFFER_DATA_SIZE:
860 *val = RESOURCE_UBO(res)->UniformBufferSize;
861 return 1;
862 case GL_NUM_ACTIVE_VARIABLES:
863 *val = RESOURCE_UBO(res)->NumUniforms;
864 return 1;
865 case GL_ACTIVE_VARIABLES:
866 for (unsigned i = 0; i < RESOURCE_UBO(res)->NumUniforms; i++) {
867 const char *iname = RESOURCE_UBO(res)->Uniforms[i].IndexName;
868 struct gl_program_resource *uni =
869 _mesa_program_resource_find_name(shProg, GL_UNIFORM, iname);
870 *val++ =
871 _mesa_program_resource_index(shProg, uni);
872 }
873 return RESOURCE_UBO(res)->NumUniforms;
874 }
875 } else if (res->Type == GL_ATOMIC_COUNTER_BUFFER) {
876 switch (prop) {
877 case GL_BUFFER_BINDING:
878 *val = RESOURCE_ATC(res)->Binding;
879 return 1;
880 case GL_BUFFER_DATA_SIZE:
881 *val = RESOURCE_ATC(res)->MinimumSize;
882 return 1;
883 case GL_NUM_ACTIVE_VARIABLES:
884 *val = RESOURCE_ATC(res)->NumUniforms;
885 return 1;
886 case GL_ACTIVE_VARIABLES:
887 for (unsigned i = 0; i < RESOURCE_ATC(res)->NumUniforms; i++)
888 *val++ = RESOURCE_ATC(res)->Uniforms[i];
889 return RESOURCE_ATC(res)->NumUniforms;
890 }
891 }
892 assert(!"support for property type not implemented");
893
894 invalid_operation:
895 _mesa_error(ctx, GL_INVALID_OPERATION, "%s(%s prop %s)", caller,
896 _mesa_lookup_enum_by_nr(res->Type),
897 _mesa_lookup_enum_by_nr(prop));
898
899 return 0;
900 }
901
902 unsigned
903 _mesa_program_resource_prop(struct gl_shader_program *shProg,
904 struct gl_program_resource *res, GLuint index,
905 const GLenum prop, GLint *val, const char *caller)
906 {
907 GET_CURRENT_CONTEXT(ctx);
908
909 #define VALIDATE_TYPE(type)\
910 if (res->Type != type)\
911 goto invalid_operation;
912
913 switch(prop) {
914 case GL_NAME_LENGTH:
915 if (res->Type == GL_ATOMIC_COUNTER_BUFFER)
916 goto invalid_operation;
917 /* Base name +3 if array '[0]' + terminator. */
918 *val = strlen(_mesa_program_resource_name(res)) +
919 (_mesa_program_resource_array_size(res) > 0 ? 3 : 0) + 1;
920 return 1;
921 case GL_TYPE:
922 switch (res->Type) {
923 case GL_UNIFORM:
924 *val = RESOURCE_UNI(res)->type->gl_type;
925 return 1;
926 case GL_PROGRAM_INPUT:
927 case GL_PROGRAM_OUTPUT:
928 *val = RESOURCE_VAR(res)->type->gl_type;
929 return 1;
930 case GL_TRANSFORM_FEEDBACK_VARYING:
931 *val = RESOURCE_XFB(res)->Type;
932 return 1;
933 default:
934 goto invalid_operation;
935 }
936 case GL_ARRAY_SIZE:
937 switch (res->Type) {
938 case GL_UNIFORM:
939 *val = MAX2(RESOURCE_UNI(res)->array_elements, 1);
940 return 1;
941 case GL_PROGRAM_INPUT:
942 case GL_PROGRAM_OUTPUT:
943 *val = MAX2(RESOURCE_VAR(res)->type->length, 1);
944 return 1;
945 case GL_TRANSFORM_FEEDBACK_VARYING:
946 *val = MAX2(RESOURCE_XFB(res)->Size, 1);
947 return 1;
948 default:
949 goto invalid_operation;
950 }
951 case GL_OFFSET:
952 VALIDATE_TYPE(GL_UNIFORM);
953 *val = RESOURCE_UNI(res)->offset;
954 return 1;
955 case GL_BLOCK_INDEX:
956 VALIDATE_TYPE(GL_UNIFORM);
957 *val = RESOURCE_UNI(res)->block_index;
958 return 1;
959 case GL_ARRAY_STRIDE:
960 VALIDATE_TYPE(GL_UNIFORM);
961 *val = RESOURCE_UNI(res)->array_stride;
962 return 1;
963 case GL_MATRIX_STRIDE:
964 VALIDATE_TYPE(GL_UNIFORM);
965 *val = RESOURCE_UNI(res)->matrix_stride;
966 return 1;
967 case GL_IS_ROW_MAJOR:
968 VALIDATE_TYPE(GL_UNIFORM);
969 *val = RESOURCE_UNI(res)->row_major;
970 return 1;
971 case GL_ATOMIC_COUNTER_BUFFER_INDEX:
972 VALIDATE_TYPE(GL_UNIFORM);
973 *val = RESOURCE_UNI(res)->atomic_buffer_index;
974 return 1;
975 case GL_BUFFER_BINDING:
976 case GL_BUFFER_DATA_SIZE:
977 case GL_NUM_ACTIVE_VARIABLES:
978 case GL_ACTIVE_VARIABLES:
979 return get_buffer_property(shProg, res, prop, val, caller);
980 case GL_REFERENCED_BY_VERTEX_SHADER:
981 case GL_REFERENCED_BY_GEOMETRY_SHADER:
982 case GL_REFERENCED_BY_FRAGMENT_SHADER:
983 switch (res->Type) {
984 case GL_UNIFORM:
985 case GL_PROGRAM_INPUT:
986 case GL_PROGRAM_OUTPUT:
987 case GL_UNIFORM_BLOCK:
988 case GL_ATOMIC_COUNTER_BUFFER:
989 *val = is_resource_referenced(shProg, res, index,
990 stage_from_enum(prop));
991 return 1;
992 default:
993 goto invalid_operation;
994 }
995 case GL_LOCATION:
996 switch (res->Type) {
997 case GL_UNIFORM:
998 case GL_PROGRAM_INPUT:
999 case GL_PROGRAM_OUTPUT:
1000 *val = program_resource_location(shProg, res,
1001 _mesa_program_resource_name(res));
1002 return 1;
1003 default:
1004 goto invalid_operation;
1005 }
1006 case GL_LOCATION_INDEX:
1007 if (res->Type != GL_PROGRAM_OUTPUT)
1008 goto invalid_operation;
1009 *val = RESOURCE_VAR(res)->data.index;
1010 return 1;
1011
1012 /* GL_ARB_tessellation_shader */
1013 case GL_IS_PER_PATCH:
1014 case GL_REFERENCED_BY_TESS_CONTROL_SHADER:
1015 case GL_REFERENCED_BY_TESS_EVALUATION_SHADER:
1016 /* GL_ARB_compute_shader */
1017 case GL_REFERENCED_BY_COMPUTE_SHADER:
1018 default:
1019 _mesa_error(ctx, GL_INVALID_ENUM, "%s(%s prop %s)", caller,
1020 _mesa_lookup_enum_by_nr(res->Type),
1021 _mesa_lookup_enum_by_nr(prop));
1022 return 0;
1023 }
1024
1025 #undef VALIDATE_TYPE
1026
1027 invalid_operation:
1028 _mesa_error(ctx, GL_INVALID_OPERATION, "%s(%s prop %s)", caller,
1029 _mesa_lookup_enum_by_nr(res->Type),
1030 _mesa_lookup_enum_by_nr(prop));
1031 return 0;
1032 }
1033
1034 extern void
1035 _mesa_get_program_resourceiv(struct gl_shader_program *shProg,
1036 GLenum programInterface, GLuint index, GLsizei propCount,
1037 const GLenum *props, GLsizei bufSize,
1038 GLsizei *length, GLint *params)
1039 {
1040 GET_CURRENT_CONTEXT(ctx);
1041 GLint *val = (GLint *) params;
1042 const GLenum *prop = props;
1043 GLsizei amount = 0;
1044
1045 struct gl_program_resource *res =
1046 _mesa_program_resource_find_index(shProg, programInterface, index);
1047
1048 /* No such resource found or bufSize negative. */
1049 if (!res || bufSize < 0) {
1050 _mesa_error(ctx, GL_INVALID_VALUE,
1051 "glGetProgramResourceiv(%s index %d bufSize %d)",
1052 _mesa_lookup_enum_by_nr(programInterface), index, bufSize);
1053 return;
1054 }
1055
1056 /* Write propCount values until error occurs or bufSize reached. */
1057 for (int i = 0; i < propCount && i < bufSize; i++, val++, prop++) {
1058 int props_written =
1059 _mesa_program_resource_prop(shProg, res, index, *prop, val,
1060 "glGetProgramResourceiv");
1061
1062 /* Error happened. */
1063 if (props_written == 0)
1064 return;
1065
1066 amount += props_written;
1067 }
1068
1069 /* If <length> is not NULL, the actual number of integer values
1070 * written to <params> will be written to <length>.
1071 */
1072 if (length)
1073 *length = amount;
1074 }