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
.VertexProgram
.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 _mesa_GetActiveAttrib(GLhandleARB program
, GLuint desired_index
,
81 GLsizei maxLength
, GLsizei
* length
, GLint
* size
,
82 GLenum
* type
, GLcharARB
* name
)
84 GET_CURRENT_CONTEXT(ctx
);
85 struct gl_shader_program
*shProg
;
87 shProg
= _mesa_lookup_shader_program_err(ctx
, program
, "glGetActiveAttrib");
91 if (!shProg
->LinkStatus
) {
92 _mesa_error(ctx
, GL_INVALID_VALUE
,
93 "glGetActiveAttrib(program not linked)");
97 if (shProg
->_LinkedShaders
[MESA_SHADER_VERTEX
] == NULL
) {
98 _mesa_error(ctx
, GL_INVALID_VALUE
, "glGetActiveAttrib(no vertex shader)");
102 exec_list
*const ir
= shProg
->_LinkedShaders
[MESA_SHADER_VERTEX
]->ir
;
103 unsigned current_index
= 0;
105 foreach_list(node
, ir
) {
106 const ir_variable
*const var
= ((ir_instruction
*) node
)->as_variable();
109 || var
->mode
!= ir_var_shader_in
110 || var
->location
== -1)
113 if (current_index
== desired_index
) {
114 _mesa_copy_string(name
, maxLength
, length
, var
->name
);
117 *size
= (var
->type
->is_array()) ? var
->type
->length
: 1;
120 *type
= var
->type
->gl_type
;
128 /* If the loop did not return early, the caller must have asked for
129 * an index that did not exit. Set an error.
131 _mesa_error(ctx
, GL_INVALID_VALUE
, "glGetActiveAttrib(index)");
135 _mesa_GetAttribLocation(GLhandleARB program
, const GLcharARB
* name
)
137 GET_CURRENT_CONTEXT(ctx
);
138 struct gl_shader_program
*const shProg
=
139 _mesa_lookup_shader_program_err(ctx
, program
, "glGetAttribLocation");
145 if (!shProg
->LinkStatus
) {
146 _mesa_error(ctx
, GL_INVALID_OPERATION
,
147 "glGetAttribLocation(program not linked)");
154 /* Not having a vertex shader is not an error.
156 if (shProg
->_LinkedShaders
[MESA_SHADER_VERTEX
] == NULL
)
159 exec_list
*ir
= shProg
->_LinkedShaders
[MESA_SHADER_VERTEX
]->ir
;
160 foreach_list(node
, ir
) {
161 const ir_variable
*const var
= ((ir_instruction
*) node
)->as_variable();
163 /* The extra check against VERT_ATTRIB_GENERIC0 is because
164 * glGetAttribLocation cannot be used on "conventional" attributes.
166 * From page 95 of the OpenGL 3.0 spec:
168 * "If name is not an active attribute, if name is a conventional
169 * attribute, or if an error occurs, -1 will be returned."
172 || var
->mode
!= ir_var_shader_in
173 || var
->location
== -1
174 || var
->location
< VERT_ATTRIB_GENERIC0
)
177 if (strcmp(var
->name
, name
) == 0)
178 return var
->location
- VERT_ATTRIB_GENERIC0
;
186 _mesa_count_active_attribs(struct gl_shader_program
*shProg
)
188 if (!shProg
->LinkStatus
189 || shProg
->_LinkedShaders
[MESA_SHADER_VERTEX
] == NULL
) {
193 exec_list
*const ir
= shProg
->_LinkedShaders
[MESA_SHADER_VERTEX
]->ir
;
196 foreach_list(node
, ir
) {
197 const ir_variable
*const var
= ((ir_instruction
*) node
)->as_variable();
200 || var
->mode
!= ir_var_shader_in
201 || var
->location
== -1)
212 _mesa_longest_attribute_name_length(struct gl_shader_program
*shProg
)
214 if (!shProg
->LinkStatus
215 || shProg
->_LinkedShaders
[MESA_SHADER_VERTEX
] == NULL
) {
219 exec_list
*const ir
= shProg
->_LinkedShaders
[MESA_SHADER_VERTEX
]->ir
;
222 foreach_list(node
, ir
) {
223 const ir_variable
*const var
= ((ir_instruction
*) node
)->as_variable();
226 || var
->mode
!= ir_var_shader_in
227 || var
->location
== -1)
230 const size_t len
= strlen(var
->name
);
239 _mesa_BindFragDataLocation(GLuint program
, GLuint colorNumber
,
242 _mesa_BindFragDataLocationIndexed(program
, colorNumber
, 0, name
);
246 _mesa_BindFragDataLocationIndexed(GLuint program
, GLuint colorNumber
,
247 GLuint index
, const GLchar
*name
)
249 GET_CURRENT_CONTEXT(ctx
);
251 struct gl_shader_program
*const shProg
=
252 _mesa_lookup_shader_program_err(ctx
, program
, "glBindFragDataLocationIndexed");
259 if (strncmp(name
, "gl_", 3) == 0) {
260 _mesa_error(ctx
, GL_INVALID_OPERATION
, "glBindFragDataLocationIndexed(illegal name)");
265 _mesa_error(ctx
, GL_INVALID_VALUE
, "glBindFragDataLocationIndexed(index)");
269 if (index
== 0 && colorNumber
>= ctx
->Const
.MaxDrawBuffers
) {
270 _mesa_error(ctx
, GL_INVALID_VALUE
, "glBindFragDataLocationIndexed(colorNumber)");
274 if (index
== 1 && colorNumber
>= ctx
->Const
.MaxDualSourceDrawBuffers
) {
275 _mesa_error(ctx
, GL_INVALID_VALUE
, "glBindFragDataLocationIndexed(colorNumber)");
279 /* Replace the current value if it's already in the list. Add
280 * FRAG_RESULT_DATA0 because that's how the linker differentiates
281 * between built-in attributes and user-defined attributes.
283 shProg
->FragDataBindings
->put(colorNumber
+ FRAG_RESULT_DATA0
, name
);
284 shProg
->FragDataIndexBindings
->put(index
, name
);
286 * Note that this binding won't go into effect until
287 * glLinkProgram is called again.
293 _mesa_GetFragDataIndex(GLuint program
, const GLchar
*name
)
295 GET_CURRENT_CONTEXT(ctx
);
296 struct gl_shader_program
*const shProg
=
297 _mesa_lookup_shader_program_err(ctx
, program
, "glGetFragDataIndex");
303 if (!shProg
->LinkStatus
) {
304 _mesa_error(ctx
, GL_INVALID_OPERATION
,
305 "glGetFragDataIndex(program not linked)");
312 if (strncmp(name
, "gl_", 3) == 0) {
313 _mesa_error(ctx
, GL_INVALID_OPERATION
,
314 "glGetFragDataIndex(illegal name)");
318 /* Not having a fragment shader is not an error.
320 if (shProg
->_LinkedShaders
[MESA_SHADER_FRAGMENT
] == NULL
)
323 exec_list
*ir
= shProg
->_LinkedShaders
[MESA_SHADER_FRAGMENT
]->ir
;
324 foreach_list(node
, ir
) {
325 const ir_variable
*const var
= ((ir_instruction
*) node
)->as_variable();
327 /* The extra check against FRAG_RESULT_DATA0 is because
328 * glGetFragDataLocation cannot be used on "conventional" attributes.
330 * From page 95 of the OpenGL 3.0 spec:
332 * "If name is not an active attribute, if name is a conventional
333 * attribute, or if an error occurs, -1 will be returned."
336 || var
->mode
!= ir_var_shader_out
337 || var
->location
== -1
338 || var
->location
< FRAG_RESULT_DATA0
)
341 if (strcmp(var
->name
, name
) == 0)
349 _mesa_GetFragDataLocation(GLuint program
, const GLchar
*name
)
351 GET_CURRENT_CONTEXT(ctx
);
352 struct gl_shader_program
*const shProg
=
353 _mesa_lookup_shader_program_err(ctx
, program
, "glGetFragDataLocation");
359 if (!shProg
->LinkStatus
) {
360 _mesa_error(ctx
, GL_INVALID_OPERATION
,
361 "glGetFragDataLocation(program not linked)");
368 if (strncmp(name
, "gl_", 3) == 0) {
369 _mesa_error(ctx
, GL_INVALID_OPERATION
,
370 "glGetFragDataLocation(illegal name)");
374 /* Not having a fragment shader is not an error.
376 if (shProg
->_LinkedShaders
[MESA_SHADER_FRAGMENT
] == NULL
)
379 exec_list
*ir
= shProg
->_LinkedShaders
[MESA_SHADER_FRAGMENT
]->ir
;
380 foreach_list(node
, ir
) {
381 const ir_variable
*const var
= ((ir_instruction
*) node
)->as_variable();
383 /* The extra check against FRAG_RESULT_DATA0 is because
384 * glGetFragDataLocation cannot be used on "conventional" attributes.
386 * From page 95 of the OpenGL 3.0 spec:
388 * "If name is not an active attribute, if name is a conventional
389 * attribute, or if an error occurs, -1 will be returned."
392 || var
->mode
!= ir_var_shader_out
393 || var
->location
== -1
394 || var
->location
< FRAG_RESULT_DATA0
)
397 if (strcmp(var
->name
, name
) == 0)
398 return var
->location
- FRAG_RESULT_DATA0
;