mesa/teximage: Make _mesa_format_no_online_compression public
[mesa.git] / src / mesa / main / program_resource.c
1 /*
2 * Mesa 3-D graphics library
3 *
4 * Copyright (C) 2015 Intel Corporation. All Rights Reserved.
5 *
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:
12 *
13 * The above copyright notice and this permission notice shall be included
14 * in all copies or substantial portions of the Software.
15 *
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.
23 *
24 */
25
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 "compiler/glsl/ir_uniform.h"
34 static bool
35 supported_interface_enum(struct gl_context *ctx, GLenum iface)
36 {
37 switch (iface) {
38 case GL_UNIFORM:
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:
44 case GL_BUFFER_VARIABLE:
45 case GL_SHADER_STORAGE_BLOCK:
46 return true;
47 case GL_VERTEX_SUBROUTINE:
48 case GL_FRAGMENT_SUBROUTINE:
49 case GL_VERTEX_SUBROUTINE_UNIFORM:
50 case GL_FRAGMENT_SUBROUTINE_UNIFORM:
51 return _mesa_has_shader_subroutine(ctx);
52 case GL_GEOMETRY_SUBROUTINE:
53 case GL_GEOMETRY_SUBROUTINE_UNIFORM:
54 return _mesa_has_geometry_shaders(ctx) && _mesa_has_shader_subroutine(ctx);
55 case GL_COMPUTE_SUBROUTINE:
56 case GL_COMPUTE_SUBROUTINE_UNIFORM:
57 return _mesa_has_compute_shaders(ctx) && _mesa_has_shader_subroutine(ctx);
58 case GL_TESS_CONTROL_SUBROUTINE:
59 case GL_TESS_EVALUATION_SUBROUTINE:
60 case GL_TESS_CONTROL_SUBROUTINE_UNIFORM:
61 case GL_TESS_EVALUATION_SUBROUTINE_UNIFORM:
62 return _mesa_has_tessellation(ctx) && _mesa_has_shader_subroutine(ctx);
63 default:
64 return false;
65 }
66 }
67
68 void GLAPIENTRY
69 _mesa_GetProgramInterfaceiv(GLuint program, GLenum programInterface,
70 GLenum pname, GLint *params)
71 {
72 GET_CURRENT_CONTEXT(ctx);
73
74 if (MESA_VERBOSE & VERBOSE_API) {
75 _mesa_debug(ctx, "glGetProgramInterfaceiv(%u, %s, %s, %p)\n",
76 program, _mesa_enum_to_string(programInterface),
77 _mesa_enum_to_string(pname), params);
78 }
79
80 unsigned i;
81 struct gl_shader_program *shProg =
82 _mesa_lookup_shader_program_err(ctx, program,
83 "glGetProgramInterfaceiv");
84 if (!shProg)
85 return;
86
87 if (!params) {
88 _mesa_error(ctx, GL_INVALID_OPERATION,
89 "glGetProgramInterfaceiv(params NULL)");
90 return;
91 }
92
93 /* Validate interface. */
94 if (!supported_interface_enum(ctx, programInterface)) {
95 _mesa_error(ctx, GL_INVALID_OPERATION, "glGetProgramInterfaceiv(%s)",
96 _mesa_enum_to_string(programInterface));
97 return;
98 }
99
100 /* Validate pname against interface. */
101 switch(pname) {
102 case GL_ACTIVE_RESOURCES:
103 for (i = 0, *params = 0; i < shProg->NumProgramResourceList; i++)
104 if (shProg->ProgramResourceList[i].Type == programInterface)
105 (*params)++;
106 break;
107 case GL_MAX_NAME_LENGTH:
108 if (programInterface == GL_ATOMIC_COUNTER_BUFFER) {
109 _mesa_error(ctx, GL_INVALID_OPERATION,
110 "glGetProgramInterfaceiv(%s pname %s)",
111 _mesa_enum_to_string(programInterface),
112 _mesa_enum_to_string(pname));
113 return;
114 }
115 /* Name length consists of base name, 3 additional chars '[0]' if
116 * resource is an array and finally 1 char for string terminator.
117 */
118 for (i = 0, *params = 0; i < shProg->NumProgramResourceList; i++) {
119 if (shProg->ProgramResourceList[i].Type != programInterface)
120 continue;
121 unsigned len =
122 _mesa_program_resource_name_len(&shProg->ProgramResourceList[i]);
123 *params = MAX2(*params, len + 1);
124 }
125 break;
126 case GL_MAX_NUM_ACTIVE_VARIABLES:
127 switch (programInterface) {
128 case GL_UNIFORM_BLOCK:
129 for (i = 0, *params = 0; i < shProg->NumProgramResourceList; i++) {
130 if (shProg->ProgramResourceList[i].Type == programInterface) {
131 struct gl_uniform_block *block =
132 (struct gl_uniform_block *)
133 shProg->ProgramResourceList[i].Data;
134 *params = MAX2(*params, block->NumUniforms);
135 }
136 }
137 break;
138 case GL_SHADER_STORAGE_BLOCK:
139 for (i = 0, *params = 0; i < shProg->NumProgramResourceList; i++) {
140 if (shProg->ProgramResourceList[i].Type == programInterface) {
141 struct gl_uniform_block *block =
142 (struct gl_uniform_block *)
143 shProg->ProgramResourceList[i].Data;
144 GLint block_params = 0;
145 for (unsigned j = 0; j < block->NumUniforms; j++) {
146 const char *iname = block->Uniforms[j].IndexName;
147 struct gl_program_resource *uni =
148 _mesa_program_resource_find_name(shProg, GL_BUFFER_VARIABLE,
149 iname, NULL);
150 if (!uni)
151 continue;
152 block_params++;
153 }
154 *params = MAX2(*params, block_params);
155 }
156 }
157 break;
158 case GL_ATOMIC_COUNTER_BUFFER:
159 for (i = 0, *params = 0; i < shProg->NumProgramResourceList; i++) {
160 if (shProg->ProgramResourceList[i].Type == programInterface) {
161 struct gl_active_atomic_buffer *buffer =
162 (struct gl_active_atomic_buffer *)
163 shProg->ProgramResourceList[i].Data;
164 *params = MAX2(*params, buffer->NumUniforms);
165 }
166 }
167 break;
168 default:
169 _mesa_error(ctx, GL_INVALID_OPERATION,
170 "glGetProgramInterfaceiv(%s pname %s)",
171 _mesa_enum_to_string(programInterface),
172 _mesa_enum_to_string(pname));
173 };
174 break;
175 case GL_MAX_NUM_COMPATIBLE_SUBROUTINES:
176 switch (programInterface) {
177 case GL_VERTEX_SUBROUTINE_UNIFORM:
178 case GL_FRAGMENT_SUBROUTINE_UNIFORM:
179 case GL_GEOMETRY_SUBROUTINE_UNIFORM:
180 case GL_COMPUTE_SUBROUTINE_UNIFORM:
181 case GL_TESS_CONTROL_SUBROUTINE_UNIFORM:
182 case GL_TESS_EVALUATION_SUBROUTINE_UNIFORM: {
183 for (i = 0, *params = 0; i < shProg->NumProgramResourceList; i++) {
184 if (shProg->ProgramResourceList[i].Type == programInterface) {
185 struct gl_uniform_storage *uni =
186 (struct gl_uniform_storage *)
187 shProg->ProgramResourceList[i].Data;
188 *params = MAX2(*params, uni->num_compatible_subroutines);
189 }
190 }
191 break;
192 }
193
194 default:
195 _mesa_error(ctx, GL_INVALID_OPERATION,
196 "glGetProgramInterfaceiv(%s pname %s)",
197 _mesa_enum_to_string(programInterface),
198 _mesa_enum_to_string(pname));
199 }
200 break;
201 default:
202 _mesa_error(ctx, GL_INVALID_OPERATION,
203 "glGetProgramInterfaceiv(pname %s)",
204 _mesa_enum_to_string(pname));
205 }
206 }
207
208 static bool
209 is_xfb_marker(const char *str)
210 {
211 static const char *markers[] = {
212 "gl_NextBuffer",
213 "gl_SkipComponents1",
214 "gl_SkipComponents2",
215 "gl_SkipComponents3",
216 "gl_SkipComponents4",
217 NULL
218 };
219 const char **m = markers;
220
221 if (strncmp(str, "gl_", 3) != 0)
222 return false;
223
224 for (; *m; m++)
225 if (strcmp(*m, str) == 0)
226 return true;
227
228 return false;
229 }
230
231 GLuint GLAPIENTRY
232 _mesa_GetProgramResourceIndex(GLuint program, GLenum programInterface,
233 const GLchar *name)
234 {
235 GET_CURRENT_CONTEXT(ctx);
236
237 if (MESA_VERBOSE & VERBOSE_API) {
238 _mesa_debug(ctx, "glGetProgramResourceIndex(%u, %s, %s)\n",
239 program, _mesa_enum_to_string(programInterface), name);
240 }
241
242 unsigned array_index = 0;
243 struct gl_program_resource *res;
244 struct gl_shader_program *shProg =
245 _mesa_lookup_shader_program_err(ctx, program,
246 "glGetProgramResourceIndex");
247 if (!shProg || !name)
248 return GL_INVALID_INDEX;
249
250 if (!supported_interface_enum(ctx, programInterface)) {
251 _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramResourceIndex(%s)",
252 _mesa_enum_to_string(programInterface));
253 return GL_INVALID_INDEX;
254 }
255 /*
256 * For the interface TRANSFORM_FEEDBACK_VARYING, the value INVALID_INDEX
257 * should be returned when querying the index assigned to the special names
258 * "gl_NextBuffer", "gl_SkipComponents1", "gl_SkipComponents2",
259 * "gl_SkipComponents3", and "gl_SkipComponents4".
260 */
261 if (programInterface == GL_TRANSFORM_FEEDBACK_VARYING &&
262 is_xfb_marker(name))
263 return GL_INVALID_INDEX;
264
265 switch (programInterface) {
266 case GL_TESS_CONTROL_SUBROUTINE:
267 case GL_TESS_CONTROL_SUBROUTINE_UNIFORM:
268 case GL_TESS_EVALUATION_SUBROUTINE:
269 case GL_TESS_EVALUATION_SUBROUTINE_UNIFORM:
270 case GL_COMPUTE_SUBROUTINE:
271 case GL_COMPUTE_SUBROUTINE_UNIFORM:
272 case GL_GEOMETRY_SUBROUTINE:
273 case GL_GEOMETRY_SUBROUTINE_UNIFORM:
274 case GL_VERTEX_SUBROUTINE:
275 case GL_FRAGMENT_SUBROUTINE:
276 case GL_VERTEX_SUBROUTINE_UNIFORM:
277 case GL_FRAGMENT_SUBROUTINE_UNIFORM:
278 case GL_PROGRAM_INPUT:
279 case GL_PROGRAM_OUTPUT:
280 case GL_UNIFORM:
281 case GL_BUFFER_VARIABLE:
282 case GL_TRANSFORM_FEEDBACK_VARYING:
283 case GL_UNIFORM_BLOCK:
284 case GL_SHADER_STORAGE_BLOCK:
285 res = _mesa_program_resource_find_name(shProg, programInterface, name,
286 &array_index);
287 if (!res || array_index > 0)
288 return GL_INVALID_INDEX;
289
290 return _mesa_program_resource_index(shProg, res);
291 case GL_ATOMIC_COUNTER_BUFFER:
292 default:
293 _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramResourceIndex(%s)",
294 _mesa_enum_to_string(programInterface));
295 }
296
297 return GL_INVALID_INDEX;
298 }
299
300 void GLAPIENTRY
301 _mesa_GetProgramResourceName(GLuint program, GLenum programInterface,
302 GLuint index, GLsizei bufSize, GLsizei *length,
303 GLchar *name)
304 {
305 GET_CURRENT_CONTEXT(ctx);
306
307 if (MESA_VERBOSE & VERBOSE_API) {
308 _mesa_debug(ctx, "glGetProgramResourceName(%u, %s, %u, %d, %p, %p)\n",
309 program, _mesa_enum_to_string(programInterface), index,
310 bufSize, length, name);
311 }
312
313 struct gl_shader_program *shProg =
314 _mesa_lookup_shader_program_err(ctx, program,
315 "glGetProgramResourceName");
316
317 if (!shProg || !name)
318 return;
319
320 if (programInterface == GL_ATOMIC_COUNTER_BUFFER ||
321 !supported_interface_enum(ctx, programInterface)) {
322 _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramResourceName(%s)",
323 _mesa_enum_to_string(programInterface));
324 return;
325 }
326
327 _mesa_get_program_resource_name(shProg, programInterface, index, bufSize,
328 length, name, "glGetProgramResourceName");
329 }
330
331 void GLAPIENTRY
332 _mesa_GetProgramResourceiv(GLuint program, GLenum programInterface,
333 GLuint index, GLsizei propCount,
334 const GLenum *props, GLsizei bufSize,
335 GLsizei *length, GLint *params)
336 {
337 GET_CURRENT_CONTEXT(ctx);
338
339 if (MESA_VERBOSE & VERBOSE_API) {
340 _mesa_debug(ctx, "glGetProgramResourceiv(%u, %s, %u, %d, %p, %d, %p, %p)\n",
341 program, _mesa_enum_to_string(programInterface), index,
342 propCount, props, bufSize, length, params);
343 }
344
345 struct gl_shader_program *shProg =
346 _mesa_lookup_shader_program_err(ctx, program, "glGetProgramResourceiv");
347
348 if (!shProg || !params)
349 return;
350
351 /* The error INVALID_VALUE is generated if <propCount> is zero.
352 * Note that we check < 0 here because it makes sense to bail early.
353 */
354 if (propCount <= 0) {
355 _mesa_error(ctx, GL_INVALID_VALUE,
356 "glGetProgramResourceiv(propCount <= 0)");
357 return;
358 }
359
360 _mesa_get_program_resourceiv(shProg, programInterface, index,
361 propCount, props, bufSize, length, params);
362 }
363
364 static struct gl_shader_program *
365 lookup_linked_program(GLuint program, const char *caller)
366 {
367 GET_CURRENT_CONTEXT(ctx);
368 struct gl_shader_program *prog =
369 _mesa_lookup_shader_program_err(ctx, program, caller);
370
371 if (!prog)
372 return NULL;
373
374 if (prog->LinkStatus == GL_FALSE) {
375 _mesa_error(ctx, GL_INVALID_OPERATION, "%s(program not linked)",
376 caller);
377 return NULL;
378 }
379 return prog;
380 }
381
382 GLint GLAPIENTRY
383 _mesa_GetProgramResourceLocation(GLuint program, GLenum programInterface,
384 const GLchar *name)
385 {
386 GET_CURRENT_CONTEXT(ctx);
387
388 if (MESA_VERBOSE & VERBOSE_API) {
389 _mesa_debug(ctx, "glGetProgramResourceLocation(%u, %s, %s)\n",
390 program, _mesa_enum_to_string(programInterface), name);
391 }
392
393 struct gl_shader_program *shProg =
394 lookup_linked_program(program, "glGetProgramResourceLocation");
395
396 if (!shProg || !name)
397 return -1;
398
399 /* Validate programInterface. */
400 switch (programInterface) {
401 case GL_UNIFORM:
402 case GL_PROGRAM_INPUT:
403 case GL_PROGRAM_OUTPUT:
404 break;
405
406 case GL_VERTEX_SUBROUTINE_UNIFORM:
407 case GL_FRAGMENT_SUBROUTINE_UNIFORM:
408 if (!_mesa_has_shader_subroutine(ctx))
409 goto fail;
410 break;
411 case GL_GEOMETRY_SUBROUTINE_UNIFORM:
412 if (!_mesa_has_geometry_shaders(ctx) || !_mesa_has_shader_subroutine(ctx))
413 goto fail;
414 break;
415 case GL_COMPUTE_SUBROUTINE_UNIFORM:
416 if (!_mesa_has_compute_shaders(ctx) || !_mesa_has_shader_subroutine(ctx))
417 goto fail;
418 break;
419 case GL_TESS_CONTROL_SUBROUTINE_UNIFORM:
420 case GL_TESS_EVALUATION_SUBROUTINE_UNIFORM:
421 if (!_mesa_has_tessellation(ctx) || !_mesa_has_shader_subroutine(ctx))
422 goto fail;
423 break;
424 default:
425 goto fail;
426 }
427
428 return _mesa_program_resource_location(shProg, programInterface, name);
429 fail:
430 _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramResourceLocation(%s %s)",
431 _mesa_enum_to_string(programInterface), name);
432 return -1;
433 }
434
435 /**
436 * Returns output index for dual source blending.
437 */
438 GLint GLAPIENTRY
439 _mesa_GetProgramResourceLocationIndex(GLuint program, GLenum programInterface,
440 const GLchar *name)
441 {
442 GET_CURRENT_CONTEXT(ctx);
443
444 if (MESA_VERBOSE & VERBOSE_API) {
445 _mesa_debug(ctx, "glGetProgramResourceLocationIndex(%u, %s, %s)\n",
446 program, _mesa_enum_to_string(programInterface), name);
447 }
448
449 struct gl_shader_program *shProg =
450 lookup_linked_program(program, "glGetProgramResourceLocationIndex");
451
452 if (!shProg || !name)
453 return -1;
454
455 /* From the GL_ARB_program_interface_query spec:
456 *
457 * "For GetProgramResourceLocationIndex, <programInterface> must be
458 * PROGRAM_OUTPUT."
459 */
460 if (programInterface != GL_PROGRAM_OUTPUT) {
461 _mesa_error(ctx, GL_INVALID_ENUM,
462 "glGetProgramResourceLocationIndex(%s)",
463 _mesa_enum_to_string(programInterface));
464 return -1;
465 }
466
467 return _mesa_program_resource_location_index(shProg, GL_PROGRAM_OUTPUT,
468 name);
469 }