2 * Mesa 3-D graphics library
4 * Copyright (C) 2015 Intel Corporation. All Rights Reserved.
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the "Software"),
8 * to deal in the Software without restriction, including without limitation
9 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 * and/or sell copies of the Software, and to permit persons to whom the
11 * Software is furnished to do so, subject to the following conditions:
13 * The above copyright notice and this permission notice shall be included
14 * in all copies or substantial portions of the Software.
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
17 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
20 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22 * OTHER DEALINGS IN THE SOFTWARE.
26 #include "main/enums.h"
27 #include "main/macros.h"
28 #include "main/mtypes.h"
29 #include "main/shaderapi.h"
30 #include "main/shaderobj.h"
31 #include "main/context.h"
32 #include "program_resource.h"
33 #include "ir_uniform.h"
35 supported_interface_enum(struct gl_context
*ctx
, GLenum iface
)
39 case GL_UNIFORM_BLOCK
:
40 case GL_PROGRAM_INPUT
:
41 case GL_PROGRAM_OUTPUT
:
42 case GL_TRANSFORM_FEEDBACK_VARYING
:
43 case GL_ATOMIC_COUNTER_BUFFER
:
45 case GL_VERTEX_SUBROUTINE
:
46 case GL_FRAGMENT_SUBROUTINE
:
47 case GL_VERTEX_SUBROUTINE_UNIFORM
:
48 case GL_FRAGMENT_SUBROUTINE_UNIFORM
:
49 return _mesa_has_shader_subroutine(ctx
);
50 case GL_GEOMETRY_SUBROUTINE
:
51 case GL_GEOMETRY_SUBROUTINE_UNIFORM
:
52 return _mesa_has_geometry_shaders(ctx
) && _mesa_has_shader_subroutine(ctx
);
53 case GL_COMPUTE_SUBROUTINE
:
54 case GL_COMPUTE_SUBROUTINE_UNIFORM
:
55 return _mesa_has_compute_shaders(ctx
) && _mesa_has_shader_subroutine(ctx
);
56 case GL_TESS_CONTROL_SUBROUTINE
:
57 case GL_TESS_EVALUATION_SUBROUTINE
:
58 case GL_TESS_CONTROL_SUBROUTINE_UNIFORM
:
59 case GL_TESS_EVALUATION_SUBROUTINE_UNIFORM
:
60 return _mesa_has_tessellation(ctx
) && _mesa_has_shader_subroutine(ctx
);
61 case GL_BUFFER_VARIABLE
:
62 case GL_SHADER_STORAGE_BLOCK
:
69 _mesa_GetProgramInterfaceiv(GLuint program
, GLenum programInterface
,
70 GLenum pname
, GLint
*params
)
72 GET_CURRENT_CONTEXT(ctx
);
74 struct gl_shader_program
*shProg
=
75 _mesa_lookup_shader_program_err(ctx
, program
,
76 "glGetProgramInterfaceiv");
81 _mesa_error(ctx
, GL_INVALID_OPERATION
,
82 "glGetProgramInterfaceiv(params NULL)");
86 /* Validate interface. */
87 if (!supported_interface_enum(ctx
, programInterface
)) {
88 _mesa_error(ctx
, GL_INVALID_OPERATION
, "glGetProgramInterfaceiv(%s)",
89 _mesa_enum_to_string(programInterface
));
93 /* Validate pname against interface. */
95 case GL_ACTIVE_RESOURCES
:
96 for (i
= 0, *params
= 0; i
< shProg
->NumProgramResourceList
; i
++)
97 if (shProg
->ProgramResourceList
[i
].Type
== programInterface
)
100 case GL_MAX_NAME_LENGTH
:
101 if (programInterface
== GL_ATOMIC_COUNTER_BUFFER
) {
102 _mesa_error(ctx
, GL_INVALID_OPERATION
,
103 "glGetProgramInterfaceiv(%s pname %s)",
104 _mesa_enum_to_string(programInterface
),
105 _mesa_enum_to_string(pname
));
108 /* Name length consists of base name, 3 additional chars '[0]' if
109 * resource is an array and finally 1 char for string terminator.
111 for (i
= 0, *params
= 0; i
< shProg
->NumProgramResourceList
; i
++) {
112 if (shProg
->ProgramResourceList
[i
].Type
!= programInterface
)
115 _mesa_program_resource_name(&shProg
->ProgramResourceList
[i
]);
116 unsigned array_size
=
117 _mesa_program_resource_array_size(&shProg
->ProgramResourceList
[i
]);
118 *params
= MAX2(*params
, strlen(name
) + (array_size
? 3 : 0) + 1);
121 case GL_MAX_NUM_ACTIVE_VARIABLES
:
122 switch (programInterface
) {
123 case GL_UNIFORM_BLOCK
:
124 for (i
= 0, *params
= 0; i
< shProg
->NumProgramResourceList
; i
++) {
125 if (shProg
->ProgramResourceList
[i
].Type
== programInterface
) {
126 struct gl_uniform_block
*block
=
127 (struct gl_uniform_block
*)
128 shProg
->ProgramResourceList
[i
].Data
;
129 *params
= MAX2(*params
, block
->NumUniforms
);
133 case GL_ATOMIC_COUNTER_BUFFER
:
134 for (i
= 0, *params
= 0; i
< shProg
->NumProgramResourceList
; i
++) {
135 if (shProg
->ProgramResourceList
[i
].Type
== programInterface
) {
136 struct gl_active_atomic_buffer
*buffer
=
137 (struct gl_active_atomic_buffer
*)
138 shProg
->ProgramResourceList
[i
].Data
;
139 *params
= MAX2(*params
, buffer
->NumUniforms
);
144 _mesa_error(ctx
, GL_INVALID_OPERATION
,
145 "glGetProgramInterfaceiv(%s pname %s)",
146 _mesa_enum_to_string(programInterface
),
147 _mesa_enum_to_string(pname
));
150 case GL_MAX_NUM_COMPATIBLE_SUBROUTINES
:
151 switch (programInterface
) {
152 case GL_VERTEX_SUBROUTINE_UNIFORM
:
153 case GL_FRAGMENT_SUBROUTINE_UNIFORM
:
154 case GL_GEOMETRY_SUBROUTINE_UNIFORM
:
155 case GL_COMPUTE_SUBROUTINE_UNIFORM
:
156 case GL_TESS_CONTROL_SUBROUTINE_UNIFORM
:
157 case GL_TESS_EVALUATION_SUBROUTINE_UNIFORM
: {
158 for (i
= 0, *params
= 0; i
< shProg
->NumProgramResourceList
; i
++) {
159 if (shProg
->ProgramResourceList
[i
].Type
== programInterface
) {
160 struct gl_uniform_storage
*uni
=
161 (struct gl_uniform_storage
*)
162 shProg
->ProgramResourceList
[i
].Data
;
163 *params
= MAX2(*params
, uni
->num_compatible_subroutines
);
170 _mesa_error(ctx
, GL_INVALID_OPERATION
,
171 "glGetProgramInterfaceiv(%s pname %s)",
172 _mesa_enum_to_string(programInterface
),
173 _mesa_enum_to_string(pname
));
177 _mesa_error(ctx
, GL_INVALID_OPERATION
,
178 "glGetProgramInterfaceiv(pname %s)",
179 _mesa_enum_to_string(pname
));
184 is_xfb_marker(const char *str
)
186 static const char *markers
[] = {
188 "gl_SkipComponents1",
189 "gl_SkipComponents2",
190 "gl_SkipComponents3",
191 "gl_SkipComponents4",
194 const char **m
= markers
;
196 if (strncmp(str
, "gl_", 3) != 0)
200 if (strcmp(*m
, str
) == 0)
207 * Checks if given name index is legal for GetProgramResourceIndex,
208 * check is written to be compatible with GL_ARB_array_of_arrays.
211 valid_program_resource_index_name(const GLchar
*name
)
213 const char *array
= strstr(name
, "[");
214 const char *close
= strrchr(name
, ']');
216 /* Not array, no need for the check. */
220 /* Last array index has to be zero. */
221 if (!close
|| *--close
!= '0')
228 _mesa_GetProgramResourceIndex(GLuint program
, GLenum programInterface
,
231 GET_CURRENT_CONTEXT(ctx
);
232 unsigned array_index
= 0;
233 struct gl_program_resource
*res
;
234 struct gl_shader_program
*shProg
=
235 _mesa_lookup_shader_program_err(ctx
, program
,
236 "glGetProgramResourceIndex");
237 if (!shProg
|| !name
)
238 return GL_INVALID_INDEX
;
240 if (!supported_interface_enum(ctx
, programInterface
)) {
241 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetProgramResourceIndex(%s)",
242 _mesa_enum_to_string(programInterface
));
243 return GL_INVALID_INDEX
;
246 * For the interface TRANSFORM_FEEDBACK_VARYING, the value INVALID_INDEX
247 * should be returned when querying the index assigned to the special names
248 * "gl_NextBuffer", "gl_SkipComponents1", "gl_SkipComponents2",
249 * "gl_SkipComponents3", and "gl_SkipComponents4".
251 if (programInterface
== GL_TRANSFORM_FEEDBACK_VARYING
&&
253 return GL_INVALID_INDEX
;
255 switch (programInterface
) {
256 case GL_TESS_CONTROL_SUBROUTINE
:
257 case GL_TESS_CONTROL_SUBROUTINE_UNIFORM
:
258 case GL_TESS_EVALUATION_SUBROUTINE
:
259 case GL_TESS_EVALUATION_SUBROUTINE_UNIFORM
:
260 case GL_COMPUTE_SUBROUTINE
:
261 case GL_COMPUTE_SUBROUTINE_UNIFORM
:
262 case GL_GEOMETRY_SUBROUTINE
:
263 case GL_GEOMETRY_SUBROUTINE_UNIFORM
:
264 case GL_VERTEX_SUBROUTINE
:
265 case GL_FRAGMENT_SUBROUTINE
:
266 case GL_VERTEX_SUBROUTINE_UNIFORM
:
267 case GL_FRAGMENT_SUBROUTINE_UNIFORM
:
268 case GL_PROGRAM_INPUT
:
269 case GL_PROGRAM_OUTPUT
:
271 case GL_TRANSFORM_FEEDBACK_VARYING
:
272 case GL_UNIFORM_BLOCK
:
273 res
= _mesa_program_resource_find_name(shProg
, programInterface
, name
,
275 if (!res
|| array_index
> 0)
276 return GL_INVALID_INDEX
;
278 return _mesa_program_resource_index(shProg
, res
);
279 case GL_ATOMIC_COUNTER_BUFFER
:
281 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetProgramResourceIndex(%s)",
282 _mesa_enum_to_string(programInterface
));
285 return GL_INVALID_INDEX
;
289 _mesa_GetProgramResourceName(GLuint program
, GLenum programInterface
,
290 GLuint index
, GLsizei bufSize
, GLsizei
*length
,
293 GET_CURRENT_CONTEXT(ctx
);
294 struct gl_shader_program
*shProg
=
295 _mesa_lookup_shader_program_err(ctx
, program
,
296 "glGetProgramResourceName");
298 /* Set user friendly return values in case of errors. */
304 if (!shProg
|| !name
)
307 if (programInterface
== GL_ATOMIC_COUNTER_BUFFER
||
308 !supported_interface_enum(ctx
, programInterface
)) {
309 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetProgramResourceName(%s)",
310 _mesa_enum_to_string(programInterface
));
314 _mesa_get_program_resource_name(shProg
, programInterface
, index
, bufSize
,
315 length
, name
, "glGetProgramResourceName");
319 _mesa_GetProgramResourceiv(GLuint program
, GLenum programInterface
,
320 GLuint index
, GLsizei propCount
,
321 const GLenum
*props
, GLsizei bufSize
,
322 GLsizei
*length
, GLint
*params
)
324 GET_CURRENT_CONTEXT(ctx
);
325 struct gl_shader_program
*shProg
=
326 _mesa_lookup_shader_program_err(ctx
, program
, "glGetProgramResourceiv");
328 if (!shProg
|| !params
)
331 /* The error INVALID_VALUE is generated if <propCount> is zero.
332 * Note that we check < 0 here because it makes sense to bail early.
334 if (propCount
<= 0) {
335 _mesa_error(ctx
, GL_INVALID_VALUE
,
336 "glGetProgramResourceiv(propCount <= 0)");
340 /* No need to write any properties, user requested none. */
344 _mesa_get_program_resourceiv(shProg
, programInterface
, index
,
345 propCount
, props
, bufSize
, length
, params
);
349 * Function verifies syntax of given name for GetProgramResourceLocation
350 * and GetProgramResourceLocationIndex for the following cases:
352 * "array element portion of a string passed to GetProgramResourceLocation
353 * or GetProgramResourceLocationIndex must not have, a "+" sign, extra
354 * leading zeroes, or whitespace".
356 * Check is written to be compatible with GL_ARB_array_of_arrays.
359 invalid_array_element_syntax(const GLchar
*name
)
361 char *first
= strchr(name
, '[');
362 char *last
= strrchr(name
, '[');
367 /* No '+' or ' ' allowed anywhere. */
368 if (strchr(first
, '+') || strchr(first
, ' '))
371 /* Check that last array index is 0. */
372 if (last
[1] == '0' && last
[2] != ']')
378 static struct gl_shader_program
*
379 lookup_linked_program(GLuint program
, const char *caller
)
381 GET_CURRENT_CONTEXT(ctx
);
382 struct gl_shader_program
*prog
=
383 _mesa_lookup_shader_program_err(ctx
, program
, caller
);
388 if (prog
->LinkStatus
== GL_FALSE
) {
389 _mesa_error(ctx
, GL_INVALID_OPERATION
, "%s(program not linked)",
397 _mesa_GetProgramResourceLocation(GLuint program
, GLenum programInterface
,
400 GET_CURRENT_CONTEXT(ctx
);
401 struct gl_shader_program
*shProg
=
402 lookup_linked_program(program
, "glGetProgramResourceLocation");
404 if (!shProg
|| !name
)
407 /* Validate programInterface. */
408 switch (programInterface
) {
410 case GL_PROGRAM_INPUT
:
411 case GL_PROGRAM_OUTPUT
:
414 case GL_VERTEX_SUBROUTINE_UNIFORM
:
415 case GL_FRAGMENT_SUBROUTINE_UNIFORM
:
416 if (!_mesa_has_shader_subroutine(ctx
))
419 case GL_GEOMETRY_SUBROUTINE_UNIFORM
:
420 if (!_mesa_has_geometry_shaders(ctx
) || !_mesa_has_shader_subroutine(ctx
))
423 case GL_COMPUTE_SUBROUTINE_UNIFORM
:
424 if (!_mesa_has_compute_shaders(ctx
) || !_mesa_has_shader_subroutine(ctx
))
427 case GL_TESS_CONTROL_SUBROUTINE_UNIFORM
:
428 case GL_TESS_EVALUATION_SUBROUTINE_UNIFORM
:
429 if (!_mesa_has_tessellation(ctx
) || !_mesa_has_shader_subroutine(ctx
))
436 return _mesa_program_resource_location(shProg
, programInterface
, name
);
438 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetProgramResourceLocation(%s %s)",
439 _mesa_enum_to_string(programInterface
), name
);
444 * Returns output index for dual source blending.
447 _mesa_GetProgramResourceLocationIndex(GLuint program
, GLenum programInterface
,
450 GET_CURRENT_CONTEXT(ctx
);
451 struct gl_shader_program
*shProg
=
452 lookup_linked_program(program
, "glGetProgramResourceLocationIndex");
454 if (!shProg
|| !name
)
457 /* From the GL_ARB_program_interface_query spec:
459 * "For GetProgramResourceLocationIndex, <programInterface> must be
462 if (programInterface
!= GL_PROGRAM_OUTPUT
) {
463 _mesa_error(ctx
, GL_INVALID_ENUM
,
464 "glGetProgramResourceLocationIndex(%s)",
465 _mesa_enum_to_string(programInterface
));
469 return _mesa_program_resource_location_index(shProg
, GL_PROGRAM_OUTPUT
,