2 * Copyright © 2011 Intel Corporation
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:
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
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.
25 * \file shader_query.cpp
26 * C-to-C++ bridge functions to query GLSL shader data
28 * \author Ian Romanick <ian.d.romanick@intel.com>
31 #include "main/core.h"
32 #include "glsl_symbol_table.h"
34 #include "shaderobj.h"
35 #include "program/hash_table.h"
36 #include "../glsl/program.h"
39 #include "shaderapi.h"
43 _mesa_BindAttribLocation(GLhandleARB program
, GLuint index
,
44 const GLcharARB
*name
)
46 GET_CURRENT_CONTEXT(ctx
);
48 struct gl_shader_program
*const shProg
=
49 _mesa_lookup_shader_program_err(ctx
, program
, "glBindAttribLocation");
56 if (strncmp(name
, "gl_", 3) == 0) {
57 _mesa_error(ctx
, GL_INVALID_OPERATION
,
58 "glBindAttribLocation(illegal name)");
62 if (index
>= ctx
->Const
.Program
[MESA_SHADER_VERTEX
].MaxAttribs
) {
63 _mesa_error(ctx
, GL_INVALID_VALUE
, "glBindAttribLocation(index)");
67 /* Replace the current value if it's already in the list. Add
68 * VERT_ATTRIB_GENERIC0 because that's how the linker differentiates
69 * between built-in attributes and user-defined attributes.
71 shProg
->AttributeBindings
->put(index
+ VERT_ATTRIB_GENERIC0
, name
);
74 * Note that this attribute binding won't go into effect until
75 * glLinkProgram is called again.
80 is_active_attrib(const ir_variable
*var
)
85 switch (var
->data
.mode
) {
86 case ir_var_shader_in
:
87 return var
->data
.location
!= -1;
89 case ir_var_system_value
:
90 /* From GL 4.3 core spec, section 11.1.1 (Vertex Attributes):
91 * "For GetActiveAttrib, all active vertex shader input variables
92 * are enumerated, including the special built-in inputs gl_VertexID
95 return !strcmp(var
->name
, "gl_VertexID") ||
96 !strcmp(var
->name
, "gl_InstanceID");
104 _mesa_GetActiveAttrib(GLhandleARB program
, GLuint desired_index
,
105 GLsizei maxLength
, GLsizei
* length
, GLint
* size
,
106 GLenum
* type
, GLcharARB
* name
)
108 GET_CURRENT_CONTEXT(ctx
);
109 struct gl_shader_program
*shProg
;
111 shProg
= _mesa_lookup_shader_program_err(ctx
, program
, "glGetActiveAttrib");
115 if (!shProg
->LinkStatus
) {
116 _mesa_error(ctx
, GL_INVALID_VALUE
,
117 "glGetActiveAttrib(program not linked)");
121 if (shProg
->_LinkedShaders
[MESA_SHADER_VERTEX
] == NULL
) {
122 _mesa_error(ctx
, GL_INVALID_VALUE
, "glGetActiveAttrib(no vertex shader)");
126 exec_list
*const ir
= shProg
->_LinkedShaders
[MESA_SHADER_VERTEX
]->ir
;
127 unsigned current_index
= 0;
129 foreach_list(node
, ir
) {
130 const ir_variable
*const var
= ((ir_instruction
*) node
)->as_variable();
132 if (!is_active_attrib(var
))
135 if (current_index
== desired_index
) {
136 _mesa_copy_string(name
, maxLength
, length
, var
->name
);
139 *size
= (var
->type
->is_array()) ? var
->type
->length
: 1;
142 *type
= var
->type
->gl_type
;
150 /* If the loop did not return early, the caller must have asked for
151 * an index that did not exit. Set an error.
153 _mesa_error(ctx
, GL_INVALID_VALUE
, "glGetActiveAttrib(index)");
156 /* Locations associated with shader variables (array or non-array) can be
157 * queried using its base name or using the base name appended with the
158 * valid array index. For example, in case of below vertex shader, valid
159 * queries can be made to know the location of "xyz", "array", "array[0]",
160 * "array[1]", "array[2]" and "array[3]". In this example index reurned
161 * will be 0, 0, 0, 1, 2, 3 respectively.
164 * layout(location=0) in vec4 xyz;
165 * layout(location=1) in vec4[4] array;
169 * This requirement came up with the addition of ARB_program_interface_query
170 * to OpenGL 4.3 specification. See page 101 (page 122 of the PDF) for details.
172 * This utility function is used by:
173 * _mesa_GetAttribLocation
174 * _mesa_GetFragDataLocation
175 * _mesa_GetFragDataIndex
178 * if the 'name' string matches var->name.
179 * Returns 'matched index':
180 * if the 'name' string matches var->name appended with valid array index.
183 get_matching_index(const ir_variable
*const var
, const char *name
) {
185 const char *const paren
= strchr(name
, '[');
186 const unsigned len
= (paren
!= NULL
) ? paren
- name
: strlen(name
);
189 if (!var
->type
->is_array())
193 idx
= (unsigned) strtol(paren
+ 1, &endptr
, 10);
194 const unsigned idx_len
= endptr
!= (paren
+ 1) ? endptr
- paren
- 1 : 0;
196 /* Validate the sub string representing index in 'name' string */
197 if ((idx
> 0 && paren
[1] == '0') /* leading zeroes */
198 || (idx
== 0 && idx_len
> 1) /* all zeroes */
199 || paren
[1] == ' ' /* whitespace */
200 || endptr
[0] != ']' /* closing brace */
201 || endptr
[1] != '\0' /* null char */
202 || idx_len
== 0 /* missing index */
203 || idx
>= var
->type
->length
) /* exceeding array bound */
207 if (strncmp(var
->name
, name
, len
) == 0 && var
->name
[len
] == '\0')
214 _mesa_GetAttribLocation(GLhandleARB program
, const GLcharARB
* name
)
216 GET_CURRENT_CONTEXT(ctx
);
217 struct gl_shader_program
*const shProg
=
218 _mesa_lookup_shader_program_err(ctx
, program
, "glGetAttribLocation");
224 if (!shProg
->LinkStatus
) {
225 _mesa_error(ctx
, GL_INVALID_OPERATION
,
226 "glGetAttribLocation(program not linked)");
233 /* Not having a vertex shader is not an error.
235 if (shProg
->_LinkedShaders
[MESA_SHADER_VERTEX
] == NULL
)
238 exec_list
*ir
= shProg
->_LinkedShaders
[MESA_SHADER_VERTEX
]->ir
;
239 foreach_list(node
, ir
) {
240 const ir_variable
*const var
= ((ir_instruction
*) node
)->as_variable();
242 /* The extra check against VERT_ATTRIB_GENERIC0 is because
243 * glGetAttribLocation cannot be used on "conventional" attributes.
245 * From page 95 of the OpenGL 3.0 spec:
247 * "If name is not an active attribute, if name is a conventional
248 * attribute, or if an error occurs, -1 will be returned."
251 || var
->data
.mode
!= ir_var_shader_in
252 || var
->data
.location
== -1
253 || var
->data
.location
< VERT_ATTRIB_GENERIC0
)
256 int index
= get_matching_index(var
, (const char *) name
);
259 return var
->data
.location
+ index
- VERT_ATTRIB_GENERIC0
;
267 _mesa_count_active_attribs(struct gl_shader_program
*shProg
)
269 if (!shProg
->LinkStatus
270 || shProg
->_LinkedShaders
[MESA_SHADER_VERTEX
] == NULL
) {
274 exec_list
*const ir
= shProg
->_LinkedShaders
[MESA_SHADER_VERTEX
]->ir
;
277 foreach_list(node
, ir
) {
278 const ir_variable
*const var
= ((ir_instruction
*) node
)->as_variable();
280 if (!is_active_attrib(var
))
291 _mesa_longest_attribute_name_length(struct gl_shader_program
*shProg
)
293 if (!shProg
->LinkStatus
294 || shProg
->_LinkedShaders
[MESA_SHADER_VERTEX
] == NULL
) {
298 exec_list
*const ir
= shProg
->_LinkedShaders
[MESA_SHADER_VERTEX
]->ir
;
301 foreach_list(node
, ir
) {
302 const ir_variable
*const var
= ((ir_instruction
*) node
)->as_variable();
305 || var
->data
.mode
!= ir_var_shader_in
306 || var
->data
.location
== -1)
309 const size_t len
= strlen(var
->name
);
318 _mesa_BindFragDataLocation(GLuint program
, GLuint colorNumber
,
321 _mesa_BindFragDataLocationIndexed(program
, colorNumber
, 0, name
);
325 _mesa_BindFragDataLocationIndexed(GLuint program
, GLuint colorNumber
,
326 GLuint index
, const GLchar
*name
)
328 GET_CURRENT_CONTEXT(ctx
);
330 struct gl_shader_program
*const shProg
=
331 _mesa_lookup_shader_program_err(ctx
, program
, "glBindFragDataLocationIndexed");
338 if (strncmp(name
, "gl_", 3) == 0) {
339 _mesa_error(ctx
, GL_INVALID_OPERATION
, "glBindFragDataLocationIndexed(illegal name)");
344 _mesa_error(ctx
, GL_INVALID_VALUE
, "glBindFragDataLocationIndexed(index)");
348 if (index
== 0 && colorNumber
>= ctx
->Const
.MaxDrawBuffers
) {
349 _mesa_error(ctx
, GL_INVALID_VALUE
, "glBindFragDataLocationIndexed(colorNumber)");
353 if (index
== 1 && colorNumber
>= ctx
->Const
.MaxDualSourceDrawBuffers
) {
354 _mesa_error(ctx
, GL_INVALID_VALUE
, "glBindFragDataLocationIndexed(colorNumber)");
358 /* Replace the current value if it's already in the list. Add
359 * FRAG_RESULT_DATA0 because that's how the linker differentiates
360 * between built-in attributes and user-defined attributes.
362 shProg
->FragDataBindings
->put(colorNumber
+ FRAG_RESULT_DATA0
, name
);
363 shProg
->FragDataIndexBindings
->put(index
, name
);
365 * Note that this binding won't go into effect until
366 * glLinkProgram is called again.
372 _mesa_GetFragDataIndex(GLuint program
, const GLchar
*name
)
374 GET_CURRENT_CONTEXT(ctx
);
375 struct gl_shader_program
*const shProg
=
376 _mesa_lookup_shader_program_err(ctx
, program
, "glGetFragDataIndex");
382 if (!shProg
->LinkStatus
) {
383 _mesa_error(ctx
, GL_INVALID_OPERATION
,
384 "glGetFragDataIndex(program not linked)");
391 if (strncmp(name
, "gl_", 3) == 0) {
392 _mesa_error(ctx
, GL_INVALID_OPERATION
,
393 "glGetFragDataIndex(illegal name)");
397 /* Not having a fragment shader is not an error.
399 if (shProg
->_LinkedShaders
[MESA_SHADER_FRAGMENT
] == NULL
)
402 exec_list
*ir
= shProg
->_LinkedShaders
[MESA_SHADER_FRAGMENT
]->ir
;
403 foreach_list(node
, ir
) {
404 const ir_variable
*const var
= ((ir_instruction
*) node
)->as_variable();
406 /* The extra check against FRAG_RESULT_DATA0 is because
407 * glGetFragDataLocation cannot be used on "conventional" attributes.
409 * From page 95 of the OpenGL 3.0 spec:
411 * "If name is not an active attribute, if name is a conventional
412 * attribute, or if an error occurs, -1 will be returned."
415 || var
->data
.mode
!= ir_var_shader_out
416 || var
->data
.location
== -1
417 || var
->data
.location
< FRAG_RESULT_DATA0
)
420 if (get_matching_index(var
, (const char *) name
) >= 0)
421 return var
->data
.index
;
428 _mesa_GetFragDataLocation(GLuint program
, const GLchar
*name
)
430 GET_CURRENT_CONTEXT(ctx
);
431 struct gl_shader_program
*const shProg
=
432 _mesa_lookup_shader_program_err(ctx
, program
, "glGetFragDataLocation");
438 if (!shProg
->LinkStatus
) {
439 _mesa_error(ctx
, GL_INVALID_OPERATION
,
440 "glGetFragDataLocation(program not linked)");
447 if (strncmp(name
, "gl_", 3) == 0) {
448 _mesa_error(ctx
, GL_INVALID_OPERATION
,
449 "glGetFragDataLocation(illegal name)");
453 /* Not having a fragment shader is not an error.
455 if (shProg
->_LinkedShaders
[MESA_SHADER_FRAGMENT
] == NULL
)
458 exec_list
*ir
= shProg
->_LinkedShaders
[MESA_SHADER_FRAGMENT
]->ir
;
459 foreach_list(node
, ir
) {
460 const ir_variable
*const var
= ((ir_instruction
*) node
)->as_variable();
462 /* The extra check against FRAG_RESULT_DATA0 is because
463 * glGetFragDataLocation cannot be used on "conventional" attributes.
465 * From page 95 of the OpenGL 3.0 spec:
467 * "If name is not an active attribute, if name is a conventional
468 * attribute, or if an error occurs, -1 will be returned."
471 || var
->data
.mode
!= ir_var_shader_out
472 || var
->data
.location
== -1
473 || var
->data
.location
< FRAG_RESULT_DATA0
)
476 int index
= get_matching_index(var
, (const char *) name
);
479 return var
->data
.location
+ index
- FRAG_RESULT_DATA0
;