1b8e80941Smrg/*
2b8e80941Smrg * Mesa 3-D graphics library
3b8e80941Smrg *
4b8e80941Smrg * Copyright (C) 2015 Intel Corporation.  All Rights Reserved.
5b8e80941Smrg *
6b8e80941Smrg * Permission is hereby granted, free of charge, to any person obtaining a
7b8e80941Smrg * copy of this software and associated documentation files (the "Software"),
8b8e80941Smrg * to deal in the Software without restriction, including without limitation
9b8e80941Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10b8e80941Smrg * and/or sell copies of the Software, and to permit persons to whom the
11b8e80941Smrg * Software is furnished to do so, subject to the following conditions:
12b8e80941Smrg *
13b8e80941Smrg * The above copyright notice and this permission notice shall be included
14b8e80941Smrg * in all copies or substantial portions of the Software.
15b8e80941Smrg *
16b8e80941Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
17b8e80941Smrg * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18b8e80941Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
19b8e80941Smrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
20b8e80941Smrg * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21b8e80941Smrg * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22b8e80941Smrg * OTHER DEALINGS IN THE SOFTWARE.
23b8e80941Smrg *
24b8e80941Smrg */
25b8e80941Smrg
26b8e80941Smrg#include "main/enums.h"
27b8e80941Smrg#include "main/macros.h"
28b8e80941Smrg#include "main/mtypes.h"
29b8e80941Smrg#include "main/shaderapi.h"
30b8e80941Smrg#include "main/shaderobj.h"
31b8e80941Smrg#include "main/context.h"
32b8e80941Smrg#include "program_resource.h"
33b8e80941Smrg#include "compiler/glsl/ir_uniform.h"
34b8e80941Smrg
35b8e80941Smrgstatic bool
36b8e80941Smrgsupported_interface_enum(struct gl_context *ctx, GLenum iface)
37b8e80941Smrg{
38b8e80941Smrg   switch (iface) {
39b8e80941Smrg   case GL_UNIFORM:
40b8e80941Smrg   case GL_UNIFORM_BLOCK:
41b8e80941Smrg   case GL_PROGRAM_INPUT:
42b8e80941Smrg   case GL_PROGRAM_OUTPUT:
43b8e80941Smrg   case GL_TRANSFORM_FEEDBACK_BUFFER:
44b8e80941Smrg   case GL_TRANSFORM_FEEDBACK_VARYING:
45b8e80941Smrg   case GL_ATOMIC_COUNTER_BUFFER:
46b8e80941Smrg   case GL_BUFFER_VARIABLE:
47b8e80941Smrg   case GL_SHADER_STORAGE_BLOCK:
48b8e80941Smrg      return true;
49b8e80941Smrg   case GL_VERTEX_SUBROUTINE:
50b8e80941Smrg   case GL_FRAGMENT_SUBROUTINE:
51b8e80941Smrg   case GL_VERTEX_SUBROUTINE_UNIFORM:
52b8e80941Smrg   case GL_FRAGMENT_SUBROUTINE_UNIFORM:
53b8e80941Smrg      return _mesa_has_ARB_shader_subroutine(ctx);
54b8e80941Smrg   case GL_GEOMETRY_SUBROUTINE:
55b8e80941Smrg   case GL_GEOMETRY_SUBROUTINE_UNIFORM:
56b8e80941Smrg      return _mesa_has_geometry_shaders(ctx) && _mesa_has_ARB_shader_subroutine(ctx);
57b8e80941Smrg   case GL_COMPUTE_SUBROUTINE:
58b8e80941Smrg   case GL_COMPUTE_SUBROUTINE_UNIFORM:
59b8e80941Smrg      return _mesa_has_compute_shaders(ctx) && _mesa_has_ARB_shader_subroutine(ctx);
60b8e80941Smrg   case GL_TESS_CONTROL_SUBROUTINE:
61b8e80941Smrg   case GL_TESS_EVALUATION_SUBROUTINE:
62b8e80941Smrg   case GL_TESS_CONTROL_SUBROUTINE_UNIFORM:
63b8e80941Smrg   case GL_TESS_EVALUATION_SUBROUTINE_UNIFORM:
64b8e80941Smrg      return _mesa_has_tessellation(ctx) && _mesa_has_ARB_shader_subroutine(ctx);
65b8e80941Smrg   default:
66b8e80941Smrg      return false;
67b8e80941Smrg   }
68b8e80941Smrg}
69b8e80941Smrg
70b8e80941Smrgstatic struct gl_shader_program *
71b8e80941Smrglookup_linked_program(GLuint program, const char *caller)
72b8e80941Smrg{
73b8e80941Smrg   GET_CURRENT_CONTEXT(ctx);
74b8e80941Smrg   struct gl_shader_program *prog =
75b8e80941Smrg      _mesa_lookup_shader_program_err(ctx, program, caller);
76b8e80941Smrg
77b8e80941Smrg   if (!prog)
78b8e80941Smrg      return NULL;
79b8e80941Smrg
80b8e80941Smrg   if (prog->data->LinkStatus == LINKING_FAILURE) {
81b8e80941Smrg      _mesa_error(ctx, GL_INVALID_OPERATION, "%s(program not linked)",
82b8e80941Smrg                  caller);
83b8e80941Smrg      return NULL;
84b8e80941Smrg   }
85b8e80941Smrg   return prog;
86b8e80941Smrg}
87b8e80941Smrg
88b8e80941Smrgvoid GLAPIENTRY
89b8e80941Smrg_mesa_GetProgramInterfaceiv(GLuint program, GLenum programInterface,
90b8e80941Smrg                            GLenum pname, GLint *params)
91b8e80941Smrg{
92b8e80941Smrg   GET_CURRENT_CONTEXT(ctx);
93b8e80941Smrg
94b8e80941Smrg   if (MESA_VERBOSE & VERBOSE_API) {
95b8e80941Smrg      _mesa_debug(ctx, "glGetProgramInterfaceiv(%u, %s, %s, %p)\n",
96b8e80941Smrg                  program, _mesa_enum_to_string(programInterface),
97b8e80941Smrg                  _mesa_enum_to_string(pname), params);
98b8e80941Smrg   }
99b8e80941Smrg
100b8e80941Smrg   unsigned i;
101b8e80941Smrg   struct gl_shader_program *shProg =
102b8e80941Smrg      _mesa_lookup_shader_program_err(ctx, program,
103b8e80941Smrg                                      "glGetProgramInterfaceiv");
104b8e80941Smrg   if (!shProg)
105b8e80941Smrg      return;
106b8e80941Smrg
107b8e80941Smrg   if (!params) {
108b8e80941Smrg      _mesa_error(ctx, GL_INVALID_OPERATION,
109b8e80941Smrg                  "glGetProgramInterfaceiv(params NULL)");
110b8e80941Smrg      return;
111b8e80941Smrg   }
112b8e80941Smrg
113b8e80941Smrg   /* Validate interface. */
114b8e80941Smrg   if (!supported_interface_enum(ctx, programInterface)) {
115b8e80941Smrg      _mesa_error(ctx, GL_INVALID_OPERATION, "glGetProgramInterfaceiv(%s)",
116b8e80941Smrg                  _mesa_enum_to_string(programInterface));
117b8e80941Smrg      return;
118b8e80941Smrg   }
119b8e80941Smrg
120b8e80941Smrg   /* Validate pname against interface. */
121b8e80941Smrg   switch(pname) {
122b8e80941Smrg   case GL_ACTIVE_RESOURCES:
123b8e80941Smrg      for (i = 0, *params = 0; i < shProg->data->NumProgramResourceList; i++)
124b8e80941Smrg         if (shProg->data->ProgramResourceList[i].Type == programInterface)
125b8e80941Smrg            (*params)++;
126b8e80941Smrg      break;
127b8e80941Smrg   case GL_MAX_NAME_LENGTH:
128b8e80941Smrg      if (programInterface == GL_ATOMIC_COUNTER_BUFFER ||
129b8e80941Smrg          programInterface == GL_TRANSFORM_FEEDBACK_BUFFER) {
130b8e80941Smrg         _mesa_error(ctx, GL_INVALID_OPERATION,
131b8e80941Smrg                     "glGetProgramInterfaceiv(%s pname %s)",
132b8e80941Smrg                     _mesa_enum_to_string(programInterface),
133b8e80941Smrg                     _mesa_enum_to_string(pname));
134b8e80941Smrg         return;
135b8e80941Smrg      }
136b8e80941Smrg      /* Name length consists of base name, 3 additional chars '[0]' if
137b8e80941Smrg       * resource is an array and finally 1 char for string terminator.
138b8e80941Smrg       */
139b8e80941Smrg      for (i = 0, *params = 0; i < shProg->data->NumProgramResourceList; i++) {
140b8e80941Smrg         if (shProg->data->ProgramResourceList[i].Type != programInterface)
141b8e80941Smrg            continue;
142b8e80941Smrg         unsigned len =
143b8e80941Smrg            _mesa_program_resource_name_len(&shProg->data->ProgramResourceList[i]);
144b8e80941Smrg         *params = MAX2(*params, len + 1);
145b8e80941Smrg      }
146b8e80941Smrg      break;
147b8e80941Smrg   case GL_MAX_NUM_ACTIVE_VARIABLES:
148b8e80941Smrg      switch (programInterface) {
149b8e80941Smrg      case GL_UNIFORM_BLOCK:
150b8e80941Smrg         for (i = 0, *params = 0; i < shProg->data->NumProgramResourceList; i++) {
151b8e80941Smrg            if (shProg->data->ProgramResourceList[i].Type == programInterface) {
152b8e80941Smrg               struct gl_uniform_block *block =
153b8e80941Smrg                  (struct gl_uniform_block *)
154b8e80941Smrg                  shProg->data->ProgramResourceList[i].Data;
155b8e80941Smrg               *params = MAX2(*params, block->NumUniforms);
156b8e80941Smrg            }
157b8e80941Smrg         }
158b8e80941Smrg         break;
159b8e80941Smrg      case GL_SHADER_STORAGE_BLOCK:
160b8e80941Smrg         for (i = 0, *params = 0; i < shProg->data->NumProgramResourceList; i++) {
161b8e80941Smrg            if (shProg->data->ProgramResourceList[i].Type == programInterface) {
162b8e80941Smrg               struct gl_uniform_block *block =
163b8e80941Smrg                  (struct gl_uniform_block *)
164b8e80941Smrg                  shProg->data->ProgramResourceList[i].Data;
165b8e80941Smrg               GLint block_params = 0;
166b8e80941Smrg               for (unsigned j = 0; j < block->NumUniforms; j++) {
167b8e80941Smrg                  const char *iname = block->Uniforms[j].IndexName;
168b8e80941Smrg                  struct gl_program_resource *uni =
169b8e80941Smrg                     _mesa_program_resource_find_name(shProg, GL_BUFFER_VARIABLE,
170b8e80941Smrg                                                      iname, NULL);
171b8e80941Smrg                  if (!uni)
172b8e80941Smrg                     continue;
173b8e80941Smrg                  block_params++;
174b8e80941Smrg               }
175b8e80941Smrg               *params = MAX2(*params, block_params);
176b8e80941Smrg            }
177b8e80941Smrg         }
178b8e80941Smrg         break;
179b8e80941Smrg      case GL_ATOMIC_COUNTER_BUFFER:
180b8e80941Smrg         for (i = 0, *params = 0; i < shProg->data->NumProgramResourceList; i++) {
181b8e80941Smrg            if (shProg->data->ProgramResourceList[i].Type == programInterface) {
182b8e80941Smrg               struct gl_active_atomic_buffer *buffer =
183b8e80941Smrg                  (struct gl_active_atomic_buffer *)
184b8e80941Smrg                  shProg->data->ProgramResourceList[i].Data;
185b8e80941Smrg               *params = MAX2(*params, buffer->NumUniforms);
186b8e80941Smrg            }
187b8e80941Smrg         }
188b8e80941Smrg         break;
189b8e80941Smrg      case GL_TRANSFORM_FEEDBACK_BUFFER:
190b8e80941Smrg         for (i = 0, *params = 0; i < shProg->data->NumProgramResourceList; i++) {
191b8e80941Smrg            if (shProg->data->ProgramResourceList[i].Type == programInterface) {
192b8e80941Smrg               struct gl_transform_feedback_buffer *buffer =
193b8e80941Smrg                  (struct gl_transform_feedback_buffer *)
194b8e80941Smrg                  shProg->data->ProgramResourceList[i].Data;
195b8e80941Smrg               *params = MAX2(*params, buffer->NumVaryings);
196b8e80941Smrg            }
197b8e80941Smrg         }
198b8e80941Smrg         break;
199b8e80941Smrg      default:
200b8e80941Smrg        _mesa_error(ctx, GL_INVALID_OPERATION,
201b8e80941Smrg                    "glGetProgramInterfaceiv(%s pname %s)",
202b8e80941Smrg                    _mesa_enum_to_string(programInterface),
203b8e80941Smrg                    _mesa_enum_to_string(pname));
204b8e80941Smrg      }
205b8e80941Smrg      break;
206b8e80941Smrg   case GL_MAX_NUM_COMPATIBLE_SUBROUTINES:
207b8e80941Smrg      switch (programInterface) {
208b8e80941Smrg      case GL_VERTEX_SUBROUTINE_UNIFORM:
209b8e80941Smrg      case GL_FRAGMENT_SUBROUTINE_UNIFORM:
210b8e80941Smrg      case GL_GEOMETRY_SUBROUTINE_UNIFORM:
211b8e80941Smrg      case GL_COMPUTE_SUBROUTINE_UNIFORM:
212b8e80941Smrg      case GL_TESS_CONTROL_SUBROUTINE_UNIFORM:
213b8e80941Smrg      case GL_TESS_EVALUATION_SUBROUTINE_UNIFORM: {
214b8e80941Smrg         for (i = 0, *params = 0; i < shProg->data->NumProgramResourceList; i++) {
215b8e80941Smrg            if (shProg->data->ProgramResourceList[i].Type == programInterface) {
216b8e80941Smrg               struct gl_uniform_storage *uni =
217b8e80941Smrg                  (struct gl_uniform_storage *)
218b8e80941Smrg                  shProg->data->ProgramResourceList[i].Data;
219b8e80941Smrg               *params = MAX2(*params, uni->num_compatible_subroutines);
220b8e80941Smrg            }
221b8e80941Smrg         }
222b8e80941Smrg         break;
223b8e80941Smrg      }
224b8e80941Smrg
225b8e80941Smrg      default:
226b8e80941Smrg         _mesa_error(ctx, GL_INVALID_OPERATION,
227b8e80941Smrg                     "glGetProgramInterfaceiv(%s pname %s)",
228b8e80941Smrg                     _mesa_enum_to_string(programInterface),
229b8e80941Smrg                     _mesa_enum_to_string(pname));
230b8e80941Smrg      }
231b8e80941Smrg      break;
232b8e80941Smrg   default:
233b8e80941Smrg      _mesa_error(ctx, GL_INVALID_OPERATION,
234b8e80941Smrg                  "glGetProgramInterfaceiv(pname %s)",
235b8e80941Smrg                  _mesa_enum_to_string(pname));
236b8e80941Smrg   }
237b8e80941Smrg}
238b8e80941Smrg
239b8e80941Smrgstatic bool
240b8e80941Smrgis_xfb_marker(const char *str)
241b8e80941Smrg{
242b8e80941Smrg   static const char *markers[] = {
243b8e80941Smrg      "gl_NextBuffer",
244b8e80941Smrg      "gl_SkipComponents1",
245b8e80941Smrg      "gl_SkipComponents2",
246b8e80941Smrg      "gl_SkipComponents3",
247b8e80941Smrg      "gl_SkipComponents4",
248b8e80941Smrg      NULL
249b8e80941Smrg   };
250b8e80941Smrg   const char **m = markers;
251b8e80941Smrg
252b8e80941Smrg   if (strncmp(str, "gl_", 3) != 0)
253b8e80941Smrg      return false;
254b8e80941Smrg
255b8e80941Smrg   for (; *m; m++)
256b8e80941Smrg      if (strcmp(*m, str) == 0)
257b8e80941Smrg         return true;
258b8e80941Smrg
259b8e80941Smrg   return false;
260b8e80941Smrg}
261b8e80941Smrg
262b8e80941SmrgGLuint GLAPIENTRY
263b8e80941Smrg_mesa_GetProgramResourceIndex(GLuint program, GLenum programInterface,
264b8e80941Smrg                              const GLchar *name)
265b8e80941Smrg{
266b8e80941Smrg   GET_CURRENT_CONTEXT(ctx);
267b8e80941Smrg
268b8e80941Smrg   if (MESA_VERBOSE & VERBOSE_API) {
269b8e80941Smrg      _mesa_debug(ctx, "glGetProgramResourceIndex(%u, %s, %s)\n",
270b8e80941Smrg                  program, _mesa_enum_to_string(programInterface), name);
271b8e80941Smrg   }
272b8e80941Smrg
273b8e80941Smrg   unsigned array_index = 0;
274b8e80941Smrg   struct gl_program_resource *res;
275b8e80941Smrg   struct gl_shader_program *shProg =
276b8e80941Smrg      _mesa_lookup_shader_program_err(ctx, program,
277b8e80941Smrg                                      "glGetProgramResourceIndex");
278b8e80941Smrg   if (!shProg || !name)
279b8e80941Smrg      return GL_INVALID_INDEX;
280b8e80941Smrg
281b8e80941Smrg   if (!supported_interface_enum(ctx, programInterface)) {
282b8e80941Smrg      _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramResourceIndex(%s)",
283b8e80941Smrg                  _mesa_enum_to_string(programInterface));
284b8e80941Smrg      return GL_INVALID_INDEX;
285b8e80941Smrg   }
286b8e80941Smrg   /*
287b8e80941Smrg    * For the interface TRANSFORM_FEEDBACK_VARYING, the value INVALID_INDEX
288b8e80941Smrg    * should be returned when querying the index assigned to the special names
289b8e80941Smrg    * "gl_NextBuffer", "gl_SkipComponents1", "gl_SkipComponents2",
290b8e80941Smrg    * "gl_SkipComponents3", and "gl_SkipComponents4".
291b8e80941Smrg    */
292b8e80941Smrg   if (programInterface == GL_TRANSFORM_FEEDBACK_VARYING &&
293b8e80941Smrg       is_xfb_marker(name))
294b8e80941Smrg      return GL_INVALID_INDEX;
295b8e80941Smrg
296b8e80941Smrg   switch (programInterface) {
297b8e80941Smrg   case GL_TESS_CONTROL_SUBROUTINE:
298b8e80941Smrg   case GL_TESS_CONTROL_SUBROUTINE_UNIFORM:
299b8e80941Smrg   case GL_TESS_EVALUATION_SUBROUTINE:
300b8e80941Smrg   case GL_TESS_EVALUATION_SUBROUTINE_UNIFORM:
301b8e80941Smrg   case GL_COMPUTE_SUBROUTINE:
302b8e80941Smrg   case GL_COMPUTE_SUBROUTINE_UNIFORM:
303b8e80941Smrg   case GL_GEOMETRY_SUBROUTINE:
304b8e80941Smrg   case GL_GEOMETRY_SUBROUTINE_UNIFORM:
305b8e80941Smrg   case GL_VERTEX_SUBROUTINE:
306b8e80941Smrg   case GL_FRAGMENT_SUBROUTINE:
307b8e80941Smrg   case GL_VERTEX_SUBROUTINE_UNIFORM:
308b8e80941Smrg   case GL_FRAGMENT_SUBROUTINE_UNIFORM:
309b8e80941Smrg   case GL_PROGRAM_INPUT:
310b8e80941Smrg   case GL_PROGRAM_OUTPUT:
311b8e80941Smrg   case GL_UNIFORM:
312b8e80941Smrg   case GL_BUFFER_VARIABLE:
313b8e80941Smrg   case GL_TRANSFORM_FEEDBACK_VARYING:
314b8e80941Smrg   case GL_UNIFORM_BLOCK:
315b8e80941Smrg   case GL_SHADER_STORAGE_BLOCK:
316b8e80941Smrg      res = _mesa_program_resource_find_name(shProg, programInterface, name,
317b8e80941Smrg                                             &array_index);
318b8e80941Smrg      if (!res || array_index > 0)
319b8e80941Smrg         return GL_INVALID_INDEX;
320b8e80941Smrg
321b8e80941Smrg      return _mesa_program_resource_index(shProg, res);
322b8e80941Smrg   case GL_ATOMIC_COUNTER_BUFFER:
323b8e80941Smrg   case GL_TRANSFORM_FEEDBACK_BUFFER:
324b8e80941Smrg   default:
325b8e80941Smrg      _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramResourceIndex(%s)",
326b8e80941Smrg                  _mesa_enum_to_string(programInterface));
327b8e80941Smrg   }
328b8e80941Smrg
329b8e80941Smrg   return GL_INVALID_INDEX;
330b8e80941Smrg}
331b8e80941Smrg
332b8e80941Smrgvoid GLAPIENTRY
333b8e80941Smrg_mesa_GetProgramResourceName(GLuint program, GLenum programInterface,
334b8e80941Smrg                             GLuint index, GLsizei bufSize, GLsizei *length,
335b8e80941Smrg                             GLchar *name)
336b8e80941Smrg{
337b8e80941Smrg   GET_CURRENT_CONTEXT(ctx);
338b8e80941Smrg
339b8e80941Smrg   if (MESA_VERBOSE & VERBOSE_API) {
340b8e80941Smrg      _mesa_debug(ctx, "glGetProgramResourceName(%u, %s, %u, %d, %p, %p)\n",
341b8e80941Smrg                  program, _mesa_enum_to_string(programInterface), index,
342b8e80941Smrg                  bufSize, length, name);
343b8e80941Smrg   }
344b8e80941Smrg
345b8e80941Smrg   struct gl_shader_program *shProg =
346b8e80941Smrg      _mesa_lookup_shader_program_err(ctx, program,
347b8e80941Smrg                                      "glGetProgramResourceName");
348b8e80941Smrg
349b8e80941Smrg   if (!shProg || !name)
350b8e80941Smrg      return;
351b8e80941Smrg
352b8e80941Smrg   if (programInterface == GL_ATOMIC_COUNTER_BUFFER ||
353b8e80941Smrg       programInterface == GL_TRANSFORM_FEEDBACK_BUFFER ||
354b8e80941Smrg       !supported_interface_enum(ctx, programInterface)) {
355b8e80941Smrg      _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramResourceName(%s)",
356b8e80941Smrg                  _mesa_enum_to_string(programInterface));
357b8e80941Smrg      return;
358b8e80941Smrg   }
359b8e80941Smrg
360b8e80941Smrg   _mesa_get_program_resource_name(shProg, programInterface, index, bufSize,
361b8e80941Smrg                                   length, name, "glGetProgramResourceName");
362b8e80941Smrg}
363b8e80941Smrg
364b8e80941Smrgvoid GLAPIENTRY
365b8e80941Smrg_mesa_GetProgramResourceiv(GLuint program, GLenum programInterface,
366b8e80941Smrg                           GLuint index, GLsizei propCount,
367b8e80941Smrg                           const GLenum *props, GLsizei bufSize,
368b8e80941Smrg                           GLsizei *length, GLint *params)
369b8e80941Smrg{
370b8e80941Smrg   GET_CURRENT_CONTEXT(ctx);
371b8e80941Smrg
372b8e80941Smrg   if (MESA_VERBOSE & VERBOSE_API) {
373b8e80941Smrg      _mesa_debug(ctx, "glGetProgramResourceiv(%u, %s, %u, %d, %p, %d, %p, %p)\n",
374b8e80941Smrg                  program, _mesa_enum_to_string(programInterface), index,
375b8e80941Smrg                  propCount, props, bufSize, length, params);
376b8e80941Smrg   }
377b8e80941Smrg
378b8e80941Smrg   struct gl_shader_program *shProg =
379b8e80941Smrg      _mesa_lookup_shader_program_err(ctx, program, "glGetProgramResourceiv");
380b8e80941Smrg
381b8e80941Smrg   if (!shProg || !params)
382b8e80941Smrg      return;
383b8e80941Smrg
384b8e80941Smrg   /* The error INVALID_VALUE is generated if <propCount> is zero.
385b8e80941Smrg    * Note that we check < 0 here because it makes sense to bail early.
386b8e80941Smrg    */
387b8e80941Smrg   if (propCount <= 0) {
388b8e80941Smrg      _mesa_error(ctx, GL_INVALID_VALUE,
389b8e80941Smrg                  "glGetProgramResourceiv(propCount <= 0)");
390b8e80941Smrg      return;
391b8e80941Smrg   }
392b8e80941Smrg
393b8e80941Smrg   _mesa_get_program_resourceiv(shProg, programInterface, index,
394b8e80941Smrg                                propCount, props, bufSize, length, params);
395b8e80941Smrg}
396b8e80941Smrg
397b8e80941SmrgGLint GLAPIENTRY
398b8e80941Smrg_mesa_GetProgramResourceLocation(GLuint program, GLenum programInterface,
399b8e80941Smrg                                 const GLchar *name)
400b8e80941Smrg{
401b8e80941Smrg   GET_CURRENT_CONTEXT(ctx);
402b8e80941Smrg
403b8e80941Smrg   if (MESA_VERBOSE & VERBOSE_API) {
404b8e80941Smrg      _mesa_debug(ctx, "glGetProgramResourceLocation(%u, %s, %s)\n",
405b8e80941Smrg                  program, _mesa_enum_to_string(programInterface), name);
406b8e80941Smrg   }
407b8e80941Smrg
408b8e80941Smrg   struct gl_shader_program *shProg =
409b8e80941Smrg      lookup_linked_program(program, "glGetProgramResourceLocation");
410b8e80941Smrg
411b8e80941Smrg   if (!shProg || !name)
412b8e80941Smrg      return -1;
413b8e80941Smrg
414b8e80941Smrg   /* Validate programInterface. */
415b8e80941Smrg   switch (programInterface) {
416b8e80941Smrg   case GL_UNIFORM:
417b8e80941Smrg   case GL_PROGRAM_INPUT:
418b8e80941Smrg   case GL_PROGRAM_OUTPUT:
419b8e80941Smrg      break;
420b8e80941Smrg
421b8e80941Smrg   case GL_VERTEX_SUBROUTINE_UNIFORM:
422b8e80941Smrg   case GL_FRAGMENT_SUBROUTINE_UNIFORM:
423b8e80941Smrg      if (!_mesa_has_ARB_shader_subroutine(ctx))
424b8e80941Smrg         goto fail;
425b8e80941Smrg      break;
426b8e80941Smrg   case GL_GEOMETRY_SUBROUTINE_UNIFORM:
427b8e80941Smrg      if (!_mesa_has_geometry_shaders(ctx) || !_mesa_has_ARB_shader_subroutine(ctx))
428b8e80941Smrg         goto fail;
429b8e80941Smrg      break;
430b8e80941Smrg   case GL_COMPUTE_SUBROUTINE_UNIFORM:
431b8e80941Smrg      if (!_mesa_has_compute_shaders(ctx) || !_mesa_has_ARB_shader_subroutine(ctx))
432b8e80941Smrg         goto fail;
433b8e80941Smrg      break;
434b8e80941Smrg   case GL_TESS_CONTROL_SUBROUTINE_UNIFORM:
435b8e80941Smrg   case GL_TESS_EVALUATION_SUBROUTINE_UNIFORM:
436b8e80941Smrg      if (!_mesa_has_tessellation(ctx) || !_mesa_has_ARB_shader_subroutine(ctx))
437b8e80941Smrg         goto fail;
438b8e80941Smrg      break;
439b8e80941Smrg   default:
440b8e80941Smrg         goto fail;
441b8e80941Smrg   }
442b8e80941Smrg
443b8e80941Smrg   return _mesa_program_resource_location(shProg, programInterface, name);
444b8e80941Smrgfail:
445b8e80941Smrg   _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramResourceLocation(%s %s)",
446b8e80941Smrg               _mesa_enum_to_string(programInterface), name);
447b8e80941Smrg   return -1;
448b8e80941Smrg}
449b8e80941Smrg
450b8e80941Smrg/**
451b8e80941Smrg * Returns output index for dual source blending.
452b8e80941Smrg */
453b8e80941SmrgGLint GLAPIENTRY
454b8e80941Smrg_mesa_GetProgramResourceLocationIndex(GLuint program, GLenum programInterface,
455b8e80941Smrg                                      const GLchar *name)
456b8e80941Smrg{
457b8e80941Smrg   GET_CURRENT_CONTEXT(ctx);
458b8e80941Smrg
459b8e80941Smrg   if (MESA_VERBOSE & VERBOSE_API) {
460b8e80941Smrg      _mesa_debug(ctx, "glGetProgramResourceLocationIndex(%u, %s, %s)\n",
461b8e80941Smrg                  program, _mesa_enum_to_string(programInterface), name);
462b8e80941Smrg   }
463b8e80941Smrg
464b8e80941Smrg   struct gl_shader_program *shProg =
465b8e80941Smrg      lookup_linked_program(program, "glGetProgramResourceLocationIndex");
466b8e80941Smrg
467b8e80941Smrg   if (!shProg || !name)
468b8e80941Smrg      return -1;
469b8e80941Smrg
470b8e80941Smrg   /* From the GL_ARB_program_interface_query spec:
471b8e80941Smrg    *
472b8e80941Smrg    * "For GetProgramResourceLocationIndex, <programInterface> must be
473b8e80941Smrg    * PROGRAM_OUTPUT."
474b8e80941Smrg    */
475b8e80941Smrg   if (programInterface != GL_PROGRAM_OUTPUT) {
476b8e80941Smrg      _mesa_error(ctx, GL_INVALID_ENUM,
477b8e80941Smrg                  "glGetProgramResourceLocationIndex(%s)",
478b8e80941Smrg                  _mesa_enum_to_string(programInterface));
479b8e80941Smrg      return -1;
480b8e80941Smrg   }
481b8e80941Smrg
482b8e80941Smrg   return _mesa_program_resource_location_index(shProg, GL_PROGRAM_OUTPUT,
483b8e80941Smrg                                                name);
484b8e80941Smrg}
485