OSDN Git Service

c609abeed4551f9565e7319f11223e462df23859
[android-x86/external-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 "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    unsigned i;
74    struct gl_shader_program *shProg =
75       _mesa_lookup_shader_program_err(ctx, program,
76                                       "glGetProgramInterfaceiv");
77    if (!shProg)
78       return;
79
80    if (!params) {
81       _mesa_error(ctx, GL_INVALID_OPERATION,
82                   "glGetProgramInterfaceiv(params NULL)");
83       return;
84    }
85
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));
90       return;
91    }
92
93    /* Validate pname against interface. */
94    switch(pname) {
95    case GL_ACTIVE_RESOURCES:
96       for (i = 0, *params = 0; i < shProg->NumProgramResourceList; i++)
97          if (shProg->ProgramResourceList[i].Type == programInterface)
98             (*params)++;
99       break;
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));
106          return;
107       }
108       /* Name length consists of base name, 3 additional chars '[0]' if
109        * resource is an array and finally 1 char for string terminator.
110        */
111       for (i = 0, *params = 0; i < shProg->NumProgramResourceList; i++) {
112          if (shProg->ProgramResourceList[i].Type != programInterface)
113             continue;
114          const char *name =
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);
119       }
120       break;
121    case GL_MAX_NUM_ACTIVE_VARIABLES:
122       switch (programInterface) {
123       case GL_UNIFORM_BLOCK:
124       case GL_SHADER_STORAGE_BLOCK:
125          for (i = 0, *params = 0; i < shProg->NumProgramResourceList; i++) {
126             if (shProg->ProgramResourceList[i].Type == programInterface) {
127                struct gl_uniform_block *block =
128                   (struct gl_uniform_block *)
129                   shProg->ProgramResourceList[i].Data;
130                *params = MAX2(*params, block->NumUniforms);
131             }
132          }
133          break;
134       case GL_ATOMIC_COUNTER_BUFFER:
135          for (i = 0, *params = 0; i < shProg->NumProgramResourceList; i++) {
136             if (shProg->ProgramResourceList[i].Type == programInterface) {
137                struct gl_active_atomic_buffer *buffer =
138                   (struct gl_active_atomic_buffer *)
139                   shProg->ProgramResourceList[i].Data;
140                *params = MAX2(*params, buffer->NumUniforms);
141             }
142          }
143          break;
144       default:
145         _mesa_error(ctx, GL_INVALID_OPERATION,
146                     "glGetProgramInterfaceiv(%s pname %s)",
147                     _mesa_enum_to_string(programInterface),
148                     _mesa_enum_to_string(pname));
149       };
150       break;
151    case GL_MAX_NUM_COMPATIBLE_SUBROUTINES:
152       switch (programInterface) {
153       case GL_VERTEX_SUBROUTINE_UNIFORM:
154       case GL_FRAGMENT_SUBROUTINE_UNIFORM:
155       case GL_GEOMETRY_SUBROUTINE_UNIFORM:
156       case GL_COMPUTE_SUBROUTINE_UNIFORM:
157       case GL_TESS_CONTROL_SUBROUTINE_UNIFORM:
158       case GL_TESS_EVALUATION_SUBROUTINE_UNIFORM: {
159          for (i = 0, *params = 0; i < shProg->NumProgramResourceList; i++) {
160             if (shProg->ProgramResourceList[i].Type == programInterface) {
161                struct gl_uniform_storage *uni =
162                   (struct gl_uniform_storage *)
163                   shProg->ProgramResourceList[i].Data;
164                *params = MAX2(*params, uni->num_compatible_subroutines);
165             }
166          }
167          break;
168       }
169
170       default:
171          _mesa_error(ctx, GL_INVALID_OPERATION,
172                      "glGetProgramInterfaceiv(%s pname %s)",
173                      _mesa_enum_to_string(programInterface),
174                      _mesa_enum_to_string(pname));
175       }
176       break;
177    default:
178       _mesa_error(ctx, GL_INVALID_OPERATION,
179                   "glGetProgramInterfaceiv(pname %s)",
180                   _mesa_enum_to_string(pname));
181    }
182 }
183
184 static bool
185 is_xfb_marker(const char *str)
186 {
187    static const char *markers[] = {
188       "gl_NextBuffer",
189       "gl_SkipComponents1",
190       "gl_SkipComponents2",
191       "gl_SkipComponents3",
192       "gl_SkipComponents4",
193       NULL
194    };
195    const char **m = markers;
196
197    if (strncmp(str, "gl_", 3) != 0)
198       return false;
199
200    for (; *m; m++)
201       if (strcmp(*m, str) == 0)
202          return true;
203
204    return false;
205 }
206
207 GLuint GLAPIENTRY
208 _mesa_GetProgramResourceIndex(GLuint program, GLenum programInterface,
209                               const GLchar *name)
210 {
211    GET_CURRENT_CONTEXT(ctx);
212    unsigned array_index = 0;
213    struct gl_program_resource *res;
214    struct gl_shader_program *shProg =
215       _mesa_lookup_shader_program_err(ctx, program,
216                                       "glGetProgramResourceIndex");
217    if (!shProg || !name)
218       return GL_INVALID_INDEX;
219
220    if (!supported_interface_enum(ctx, programInterface)) {
221       _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramResourceIndex(%s)",
222                   _mesa_enum_to_string(programInterface));
223       return GL_INVALID_INDEX;
224    }
225    /*
226     * For the interface TRANSFORM_FEEDBACK_VARYING, the value INVALID_INDEX
227     * should be returned when querying the index assigned to the special names
228     * "gl_NextBuffer", "gl_SkipComponents1", "gl_SkipComponents2",
229     * "gl_SkipComponents3", and "gl_SkipComponents4".
230     */
231    if (programInterface == GL_TRANSFORM_FEEDBACK_VARYING &&
232        is_xfb_marker(name))
233       return GL_INVALID_INDEX;
234
235    switch (programInterface) {
236    case GL_TESS_CONTROL_SUBROUTINE:
237    case GL_TESS_CONTROL_SUBROUTINE_UNIFORM:
238    case GL_TESS_EVALUATION_SUBROUTINE:
239    case GL_TESS_EVALUATION_SUBROUTINE_UNIFORM:
240    case GL_COMPUTE_SUBROUTINE:
241    case GL_COMPUTE_SUBROUTINE_UNIFORM:
242    case GL_GEOMETRY_SUBROUTINE:
243    case GL_GEOMETRY_SUBROUTINE_UNIFORM:
244    case GL_VERTEX_SUBROUTINE:
245    case GL_FRAGMENT_SUBROUTINE:
246    case GL_VERTEX_SUBROUTINE_UNIFORM:
247    case GL_FRAGMENT_SUBROUTINE_UNIFORM:
248    case GL_PROGRAM_INPUT:
249    case GL_PROGRAM_OUTPUT:
250    case GL_UNIFORM:
251    case GL_BUFFER_VARIABLE:
252    case GL_TRANSFORM_FEEDBACK_VARYING:
253    case GL_UNIFORM_BLOCK:
254    case GL_SHADER_STORAGE_BLOCK:
255       res = _mesa_program_resource_find_name(shProg, programInterface, name,
256                                              &array_index);
257       if (!res || array_index > 0)
258          return GL_INVALID_INDEX;
259
260       return _mesa_program_resource_index(shProg, res);
261    case GL_ATOMIC_COUNTER_BUFFER:
262    default:
263       _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramResourceIndex(%s)",
264                   _mesa_enum_to_string(programInterface));
265    }
266
267    return GL_INVALID_INDEX;
268 }
269
270 void GLAPIENTRY
271 _mesa_GetProgramResourceName(GLuint program, GLenum programInterface,
272                              GLuint index, GLsizei bufSize, GLsizei *length,
273                              GLchar *name)
274 {
275    GET_CURRENT_CONTEXT(ctx);
276    struct gl_shader_program *shProg =
277       _mesa_lookup_shader_program_err(ctx, program,
278                                       "glGetProgramResourceName");
279
280    if (!shProg || !name)
281       return;
282
283    if (programInterface == GL_ATOMIC_COUNTER_BUFFER ||
284        !supported_interface_enum(ctx, programInterface)) {
285       _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramResourceName(%s)",
286                   _mesa_enum_to_string(programInterface));
287       return;
288    }
289
290    _mesa_get_program_resource_name(shProg, programInterface, index, bufSize,
291                                    length, name, "glGetProgramResourceName");
292 }
293
294 void GLAPIENTRY
295 _mesa_GetProgramResourceiv(GLuint program, GLenum programInterface,
296                            GLuint index, GLsizei propCount,
297                            const GLenum *props, GLsizei bufSize,
298                            GLsizei *length, GLint *params)
299 {
300    GET_CURRENT_CONTEXT(ctx);
301    struct gl_shader_program *shProg =
302       _mesa_lookup_shader_program_err(ctx, program, "glGetProgramResourceiv");
303
304    if (!shProg || !params)
305       return;
306
307    /* The error INVALID_VALUE is generated if <propCount> is zero.
308     * Note that we check < 0 here because it makes sense to bail early.
309     */
310    if (propCount <= 0) {
311       _mesa_error(ctx, GL_INVALID_VALUE,
312                   "glGetProgramResourceiv(propCount <= 0)");
313       return;
314    }
315
316    /* No need to write any properties, user requested none. */
317    if (bufSize == 0)
318       return;
319
320    _mesa_get_program_resourceiv(shProg, programInterface, index,
321                                 propCount, props, bufSize, length, params);
322 }
323
324 static struct gl_shader_program *
325 lookup_linked_program(GLuint program, const char *caller)
326 {
327    GET_CURRENT_CONTEXT(ctx);
328    struct gl_shader_program *prog =
329       _mesa_lookup_shader_program_err(ctx, program, caller);
330
331    if (!prog)
332       return NULL;
333
334    if (prog->LinkStatus == GL_FALSE) {
335       _mesa_error(ctx, GL_INVALID_OPERATION, "%s(program not linked)",
336                   caller);
337       return NULL;
338    }
339    return prog;
340 }
341
342 GLint GLAPIENTRY
343 _mesa_GetProgramResourceLocation(GLuint program, GLenum programInterface,
344                                  const GLchar *name)
345 {
346    GET_CURRENT_CONTEXT(ctx);
347    struct gl_shader_program *shProg =
348       lookup_linked_program(program, "glGetProgramResourceLocation");
349
350    if (!shProg || !name)
351       return -1;
352
353    /* Validate programInterface. */
354    switch (programInterface) {
355    case GL_UNIFORM:
356    case GL_PROGRAM_INPUT:
357    case GL_PROGRAM_OUTPUT:
358       break;
359
360    case GL_VERTEX_SUBROUTINE_UNIFORM:
361    case GL_FRAGMENT_SUBROUTINE_UNIFORM:
362       if (!_mesa_has_shader_subroutine(ctx))
363          goto fail;
364       break;
365    case GL_GEOMETRY_SUBROUTINE_UNIFORM:
366       if (!_mesa_has_geometry_shaders(ctx) || !_mesa_has_shader_subroutine(ctx))
367          goto fail;
368       break;
369    case GL_COMPUTE_SUBROUTINE_UNIFORM:
370       if (!_mesa_has_compute_shaders(ctx) || !_mesa_has_shader_subroutine(ctx))
371          goto fail;
372       break;
373    case GL_TESS_CONTROL_SUBROUTINE_UNIFORM:
374    case GL_TESS_EVALUATION_SUBROUTINE_UNIFORM:
375       if (!_mesa_has_tessellation(ctx) || !_mesa_has_shader_subroutine(ctx))
376          goto fail;
377       break;
378    default:
379          goto fail;
380    }
381
382    return _mesa_program_resource_location(shProg, programInterface, name);
383 fail:
384    _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramResourceLocation(%s %s)",
385                _mesa_enum_to_string(programInterface), name);
386    return -1;
387 }
388
389 /**
390  * Returns output index for dual source blending.
391  */
392 GLint GLAPIENTRY
393 _mesa_GetProgramResourceLocationIndex(GLuint program, GLenum programInterface,
394                                       const GLchar *name)
395 {
396    GET_CURRENT_CONTEXT(ctx);
397    struct gl_shader_program *shProg =
398       lookup_linked_program(program, "glGetProgramResourceLocationIndex");
399
400    if (!shProg || !name)
401       return -1;
402
403    /* From the GL_ARB_program_interface_query spec:
404     *
405     * "For GetProgramResourceLocationIndex, <programInterface> must be
406     * PROGRAM_OUTPUT."
407     */
408    if (programInterface != GL_PROGRAM_OUTPUT) {
409       _mesa_error(ctx, GL_INVALID_ENUM,
410                   "glGetProgramResourceLocationIndex(%s)",
411                   _mesa_enum_to_string(programInterface));
412       return -1;
413    }
414
415    return _mesa_program_resource_location_index(shProg, GL_PROGRAM_OUTPUT,
416                                                 name);
417 }