1bf215546Sopenharmony_ci/*
2bf215546Sopenharmony_ci * Mesa 3-D graphics library
3bf215546Sopenharmony_ci *
4bf215546Sopenharmony_ci * Copyright (C) 2015 Intel Corporation.  All Rights Reserved.
5bf215546Sopenharmony_ci *
6bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a
7bf215546Sopenharmony_ci * copy of this software and associated documentation files (the "Software"),
8bf215546Sopenharmony_ci * to deal in the Software without restriction, including without limitation
9bf215546Sopenharmony_ci * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10bf215546Sopenharmony_ci * and/or sell copies of the Software, and to permit persons to whom the
11bf215546Sopenharmony_ci * Software is furnished to do so, subject to the following conditions:
12bf215546Sopenharmony_ci *
13bf215546Sopenharmony_ci * The above copyright notice and this permission notice shall be included
14bf215546Sopenharmony_ci * in all copies or substantial portions of the Software.
15bf215546Sopenharmony_ci *
16bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
17bf215546Sopenharmony_ci * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18bf215546Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
19bf215546Sopenharmony_ci * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
20bf215546Sopenharmony_ci * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21bf215546Sopenharmony_ci * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22bf215546Sopenharmony_ci * OTHER DEALINGS IN THE SOFTWARE.
23bf215546Sopenharmony_ci *
24bf215546Sopenharmony_ci */
25bf215546Sopenharmony_ci
26bf215546Sopenharmony_ci#include "main/enums.h"
27bf215546Sopenharmony_ci#include "main/macros.h"
28bf215546Sopenharmony_ci#include "main/mtypes.h"
29bf215546Sopenharmony_ci#include "main/shaderapi.h"
30bf215546Sopenharmony_ci#include "main/shaderobj.h"
31bf215546Sopenharmony_ci#include "main/context.h"
32bf215546Sopenharmony_ci#include "compiler/glsl/ir_uniform.h"
33bf215546Sopenharmony_ci#include "api_exec_decl.h"
34bf215546Sopenharmony_ci
35bf215546Sopenharmony_cistatic bool
36bf215546Sopenharmony_cisupported_interface_enum(struct gl_context *ctx, GLenum iface)
37bf215546Sopenharmony_ci{
38bf215546Sopenharmony_ci   switch (iface) {
39bf215546Sopenharmony_ci   case GL_UNIFORM:
40bf215546Sopenharmony_ci   case GL_UNIFORM_BLOCK:
41bf215546Sopenharmony_ci   case GL_PROGRAM_INPUT:
42bf215546Sopenharmony_ci   case GL_PROGRAM_OUTPUT:
43bf215546Sopenharmony_ci   case GL_TRANSFORM_FEEDBACK_BUFFER:
44bf215546Sopenharmony_ci   case GL_TRANSFORM_FEEDBACK_VARYING:
45bf215546Sopenharmony_ci   case GL_ATOMIC_COUNTER_BUFFER:
46bf215546Sopenharmony_ci   case GL_BUFFER_VARIABLE:
47bf215546Sopenharmony_ci   case GL_SHADER_STORAGE_BLOCK:
48bf215546Sopenharmony_ci      return true;
49bf215546Sopenharmony_ci   case GL_VERTEX_SUBROUTINE:
50bf215546Sopenharmony_ci   case GL_FRAGMENT_SUBROUTINE:
51bf215546Sopenharmony_ci   case GL_VERTEX_SUBROUTINE_UNIFORM:
52bf215546Sopenharmony_ci   case GL_FRAGMENT_SUBROUTINE_UNIFORM:
53bf215546Sopenharmony_ci      return _mesa_has_ARB_shader_subroutine(ctx);
54bf215546Sopenharmony_ci   case GL_GEOMETRY_SUBROUTINE:
55bf215546Sopenharmony_ci   case GL_GEOMETRY_SUBROUTINE_UNIFORM:
56bf215546Sopenharmony_ci      return _mesa_has_geometry_shaders(ctx) && _mesa_has_ARB_shader_subroutine(ctx);
57bf215546Sopenharmony_ci   case GL_COMPUTE_SUBROUTINE:
58bf215546Sopenharmony_ci   case GL_COMPUTE_SUBROUTINE_UNIFORM:
59bf215546Sopenharmony_ci      return _mesa_has_compute_shaders(ctx) && _mesa_has_ARB_shader_subroutine(ctx);
60bf215546Sopenharmony_ci   case GL_TESS_CONTROL_SUBROUTINE:
61bf215546Sopenharmony_ci   case GL_TESS_EVALUATION_SUBROUTINE:
62bf215546Sopenharmony_ci   case GL_TESS_CONTROL_SUBROUTINE_UNIFORM:
63bf215546Sopenharmony_ci   case GL_TESS_EVALUATION_SUBROUTINE_UNIFORM:
64bf215546Sopenharmony_ci      return _mesa_has_tessellation(ctx) && _mesa_has_ARB_shader_subroutine(ctx);
65bf215546Sopenharmony_ci   default:
66bf215546Sopenharmony_ci      return false;
67bf215546Sopenharmony_ci   }
68bf215546Sopenharmony_ci}
69bf215546Sopenharmony_ci
70bf215546Sopenharmony_cistatic struct gl_shader_program *
71bf215546Sopenharmony_cilookup_linked_program(GLuint program, const char *caller)
72bf215546Sopenharmony_ci{
73bf215546Sopenharmony_ci   GET_CURRENT_CONTEXT(ctx);
74bf215546Sopenharmony_ci   struct gl_shader_program *prog =
75bf215546Sopenharmony_ci      _mesa_lookup_shader_program_err(ctx, program, caller);
76bf215546Sopenharmony_ci
77bf215546Sopenharmony_ci   if (!prog)
78bf215546Sopenharmony_ci      return NULL;
79bf215546Sopenharmony_ci
80bf215546Sopenharmony_ci   if (prog->data->LinkStatus == LINKING_FAILURE) {
81bf215546Sopenharmony_ci      _mesa_error(ctx, GL_INVALID_OPERATION, "%s(program not linked)",
82bf215546Sopenharmony_ci                  caller);
83bf215546Sopenharmony_ci      return NULL;
84bf215546Sopenharmony_ci   }
85bf215546Sopenharmony_ci   return prog;
86bf215546Sopenharmony_ci}
87bf215546Sopenharmony_ci
88bf215546Sopenharmony_civoid GLAPIENTRY
89bf215546Sopenharmony_ci_mesa_GetProgramInterfaceiv(GLuint program, GLenum programInterface,
90bf215546Sopenharmony_ci                            GLenum pname, GLint *params)
91bf215546Sopenharmony_ci{
92bf215546Sopenharmony_ci   GET_CURRENT_CONTEXT(ctx);
93bf215546Sopenharmony_ci
94bf215546Sopenharmony_ci   if (MESA_VERBOSE & VERBOSE_API) {
95bf215546Sopenharmony_ci      _mesa_debug(ctx, "glGetProgramInterfaceiv(%u, %s, %s, %p)\n",
96bf215546Sopenharmony_ci                  program, _mesa_enum_to_string(programInterface),
97bf215546Sopenharmony_ci                  _mesa_enum_to_string(pname), params);
98bf215546Sopenharmony_ci   }
99bf215546Sopenharmony_ci
100bf215546Sopenharmony_ci   struct gl_shader_program *shProg =
101bf215546Sopenharmony_ci      _mesa_lookup_shader_program_err(ctx, program,
102bf215546Sopenharmony_ci                                      "glGetProgramInterfaceiv");
103bf215546Sopenharmony_ci   if (!shProg)
104bf215546Sopenharmony_ci      return;
105bf215546Sopenharmony_ci
106bf215546Sopenharmony_ci   if (!params) {
107bf215546Sopenharmony_ci      _mesa_error(ctx, GL_INVALID_OPERATION,
108bf215546Sopenharmony_ci                  "glGetProgramInterfaceiv(params NULL)");
109bf215546Sopenharmony_ci      return;
110bf215546Sopenharmony_ci   }
111bf215546Sopenharmony_ci
112bf215546Sopenharmony_ci   /* Validate interface. */
113bf215546Sopenharmony_ci   if (!supported_interface_enum(ctx, programInterface)) {
114bf215546Sopenharmony_ci      _mesa_error(ctx, GL_INVALID_OPERATION, "glGetProgramInterfaceiv(%s)",
115bf215546Sopenharmony_ci                  _mesa_enum_to_string(programInterface));
116bf215546Sopenharmony_ci      return;
117bf215546Sopenharmony_ci   }
118bf215546Sopenharmony_ci
119bf215546Sopenharmony_ci   _mesa_get_program_interfaceiv(shProg, programInterface, pname, params);
120bf215546Sopenharmony_ci}
121bf215546Sopenharmony_ci
122bf215546Sopenharmony_cistatic bool
123bf215546Sopenharmony_ciis_xfb_marker(const char *str)
124bf215546Sopenharmony_ci{
125bf215546Sopenharmony_ci   static const char *markers[] = {
126bf215546Sopenharmony_ci      "gl_NextBuffer",
127bf215546Sopenharmony_ci      "gl_SkipComponents1",
128bf215546Sopenharmony_ci      "gl_SkipComponents2",
129bf215546Sopenharmony_ci      "gl_SkipComponents3",
130bf215546Sopenharmony_ci      "gl_SkipComponents4",
131bf215546Sopenharmony_ci      NULL
132bf215546Sopenharmony_ci   };
133bf215546Sopenharmony_ci   const char **m = markers;
134bf215546Sopenharmony_ci
135bf215546Sopenharmony_ci   if (strncmp(str, "gl_", 3) != 0)
136bf215546Sopenharmony_ci      return false;
137bf215546Sopenharmony_ci
138bf215546Sopenharmony_ci   for (; *m; m++)
139bf215546Sopenharmony_ci      if (strcmp(*m, str) == 0)
140bf215546Sopenharmony_ci         return true;
141bf215546Sopenharmony_ci
142bf215546Sopenharmony_ci   return false;
143bf215546Sopenharmony_ci}
144bf215546Sopenharmony_ci
145bf215546Sopenharmony_ciGLuint GLAPIENTRY
146bf215546Sopenharmony_ci_mesa_GetProgramResourceIndex(GLuint program, GLenum programInterface,
147bf215546Sopenharmony_ci                              const GLchar *name)
148bf215546Sopenharmony_ci{
149bf215546Sopenharmony_ci   GET_CURRENT_CONTEXT(ctx);
150bf215546Sopenharmony_ci
151bf215546Sopenharmony_ci   if (MESA_VERBOSE & VERBOSE_API) {
152bf215546Sopenharmony_ci      _mesa_debug(ctx, "glGetProgramResourceIndex(%u, %s, %s)\n",
153bf215546Sopenharmony_ci                  program, _mesa_enum_to_string(programInterface), name);
154bf215546Sopenharmony_ci   }
155bf215546Sopenharmony_ci
156bf215546Sopenharmony_ci   unsigned array_index = 0;
157bf215546Sopenharmony_ci   struct gl_program_resource *res;
158bf215546Sopenharmony_ci   struct gl_shader_program *shProg =
159bf215546Sopenharmony_ci      _mesa_lookup_shader_program_err(ctx, program,
160bf215546Sopenharmony_ci                                      "glGetProgramResourceIndex");
161bf215546Sopenharmony_ci   if (!shProg || !name)
162bf215546Sopenharmony_ci      return GL_INVALID_INDEX;
163bf215546Sopenharmony_ci
164bf215546Sopenharmony_ci   if (!supported_interface_enum(ctx, programInterface)) {
165bf215546Sopenharmony_ci      _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramResourceIndex(%s)",
166bf215546Sopenharmony_ci                  _mesa_enum_to_string(programInterface));
167bf215546Sopenharmony_ci      return GL_INVALID_INDEX;
168bf215546Sopenharmony_ci   }
169bf215546Sopenharmony_ci   /*
170bf215546Sopenharmony_ci    * For the interface TRANSFORM_FEEDBACK_VARYING, the value INVALID_INDEX
171bf215546Sopenharmony_ci    * should be returned when querying the index assigned to the special names
172bf215546Sopenharmony_ci    * "gl_NextBuffer", "gl_SkipComponents1", "gl_SkipComponents2",
173bf215546Sopenharmony_ci    * "gl_SkipComponents3", and "gl_SkipComponents4".
174bf215546Sopenharmony_ci    */
175bf215546Sopenharmony_ci   if (programInterface == GL_TRANSFORM_FEEDBACK_VARYING &&
176bf215546Sopenharmony_ci       is_xfb_marker(name))
177bf215546Sopenharmony_ci      return GL_INVALID_INDEX;
178bf215546Sopenharmony_ci
179bf215546Sopenharmony_ci   switch (programInterface) {
180bf215546Sopenharmony_ci   case GL_TESS_CONTROL_SUBROUTINE:
181bf215546Sopenharmony_ci   case GL_TESS_CONTROL_SUBROUTINE_UNIFORM:
182bf215546Sopenharmony_ci   case GL_TESS_EVALUATION_SUBROUTINE:
183bf215546Sopenharmony_ci   case GL_TESS_EVALUATION_SUBROUTINE_UNIFORM:
184bf215546Sopenharmony_ci   case GL_COMPUTE_SUBROUTINE:
185bf215546Sopenharmony_ci   case GL_COMPUTE_SUBROUTINE_UNIFORM:
186bf215546Sopenharmony_ci   case GL_GEOMETRY_SUBROUTINE:
187bf215546Sopenharmony_ci   case GL_GEOMETRY_SUBROUTINE_UNIFORM:
188bf215546Sopenharmony_ci   case GL_VERTEX_SUBROUTINE:
189bf215546Sopenharmony_ci   case GL_FRAGMENT_SUBROUTINE:
190bf215546Sopenharmony_ci   case GL_VERTEX_SUBROUTINE_UNIFORM:
191bf215546Sopenharmony_ci   case GL_FRAGMENT_SUBROUTINE_UNIFORM:
192bf215546Sopenharmony_ci   case GL_PROGRAM_INPUT:
193bf215546Sopenharmony_ci   case GL_PROGRAM_OUTPUT:
194bf215546Sopenharmony_ci   case GL_UNIFORM:
195bf215546Sopenharmony_ci   case GL_BUFFER_VARIABLE:
196bf215546Sopenharmony_ci   case GL_TRANSFORM_FEEDBACK_VARYING:
197bf215546Sopenharmony_ci   case GL_UNIFORM_BLOCK:
198bf215546Sopenharmony_ci   case GL_SHADER_STORAGE_BLOCK:
199bf215546Sopenharmony_ci      res = _mesa_program_resource_find_name(shProg, programInterface, name,
200bf215546Sopenharmony_ci                                             &array_index);
201bf215546Sopenharmony_ci      if (!res || array_index > 0)
202bf215546Sopenharmony_ci         return GL_INVALID_INDEX;
203bf215546Sopenharmony_ci
204bf215546Sopenharmony_ci      return _mesa_program_resource_index(shProg, res);
205bf215546Sopenharmony_ci   case GL_ATOMIC_COUNTER_BUFFER:
206bf215546Sopenharmony_ci   case GL_TRANSFORM_FEEDBACK_BUFFER:
207bf215546Sopenharmony_ci   default:
208bf215546Sopenharmony_ci      _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramResourceIndex(%s)",
209bf215546Sopenharmony_ci                  _mesa_enum_to_string(programInterface));
210bf215546Sopenharmony_ci   }
211bf215546Sopenharmony_ci
212bf215546Sopenharmony_ci   return GL_INVALID_INDEX;
213bf215546Sopenharmony_ci}
214bf215546Sopenharmony_ci
215bf215546Sopenharmony_civoid GLAPIENTRY
216bf215546Sopenharmony_ci_mesa_GetProgramResourceName(GLuint program, GLenum programInterface,
217bf215546Sopenharmony_ci                             GLuint index, GLsizei bufSize, GLsizei *length,
218bf215546Sopenharmony_ci                             GLchar *name)
219bf215546Sopenharmony_ci{
220bf215546Sopenharmony_ci   GET_CURRENT_CONTEXT(ctx);
221bf215546Sopenharmony_ci
222bf215546Sopenharmony_ci   if (MESA_VERBOSE & VERBOSE_API) {
223bf215546Sopenharmony_ci      _mesa_debug(ctx, "glGetProgramResourceName(%u, %s, %u, %d, %p, %p)\n",
224bf215546Sopenharmony_ci                  program, _mesa_enum_to_string(programInterface), index,
225bf215546Sopenharmony_ci                  bufSize, length, name);
226bf215546Sopenharmony_ci   }
227bf215546Sopenharmony_ci
228bf215546Sopenharmony_ci   struct gl_shader_program *shProg =
229bf215546Sopenharmony_ci      _mesa_lookup_shader_program_err(ctx, program,
230bf215546Sopenharmony_ci                                      "glGetProgramResourceName");
231bf215546Sopenharmony_ci
232bf215546Sopenharmony_ci   if (!shProg || !name)
233bf215546Sopenharmony_ci      return;
234bf215546Sopenharmony_ci
235bf215546Sopenharmony_ci   if (programInterface == GL_ATOMIC_COUNTER_BUFFER ||
236bf215546Sopenharmony_ci       programInterface == GL_TRANSFORM_FEEDBACK_BUFFER ||
237bf215546Sopenharmony_ci       !supported_interface_enum(ctx, programInterface)) {
238bf215546Sopenharmony_ci      _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramResourceName(%s)",
239bf215546Sopenharmony_ci                  _mesa_enum_to_string(programInterface));
240bf215546Sopenharmony_ci      return;
241bf215546Sopenharmony_ci   }
242bf215546Sopenharmony_ci
243bf215546Sopenharmony_ci   _mesa_get_program_resource_name(shProg, programInterface, index, bufSize,
244bf215546Sopenharmony_ci                                   length, name, false,
245bf215546Sopenharmony_ci                                   "glGetProgramResourceName");
246bf215546Sopenharmony_ci}
247bf215546Sopenharmony_ci
248bf215546Sopenharmony_civoid GLAPIENTRY
249bf215546Sopenharmony_ci_mesa_GetProgramResourceiv(GLuint program, GLenum programInterface,
250bf215546Sopenharmony_ci                           GLuint index, GLsizei propCount,
251bf215546Sopenharmony_ci                           const GLenum *props, GLsizei bufSize,
252bf215546Sopenharmony_ci                           GLsizei *length, GLint *params)
253bf215546Sopenharmony_ci{
254bf215546Sopenharmony_ci   GET_CURRENT_CONTEXT(ctx);
255bf215546Sopenharmony_ci
256bf215546Sopenharmony_ci   if (MESA_VERBOSE & VERBOSE_API) {
257bf215546Sopenharmony_ci      _mesa_debug(ctx, "glGetProgramResourceiv(%u, %s, %u, %d, %p, %d, %p, %p)\n",
258bf215546Sopenharmony_ci                  program, _mesa_enum_to_string(programInterface), index,
259bf215546Sopenharmony_ci                  propCount, props, bufSize, length, params);
260bf215546Sopenharmony_ci   }
261bf215546Sopenharmony_ci
262bf215546Sopenharmony_ci   struct gl_shader_program *shProg =
263bf215546Sopenharmony_ci      _mesa_lookup_shader_program_err(ctx, program, "glGetProgramResourceiv");
264bf215546Sopenharmony_ci
265bf215546Sopenharmony_ci   if (!shProg || !params)
266bf215546Sopenharmony_ci      return;
267bf215546Sopenharmony_ci
268bf215546Sopenharmony_ci   /* The error INVALID_VALUE is generated if <propCount> is zero.
269bf215546Sopenharmony_ci    * Note that we check < 0 here because it makes sense to bail early.
270bf215546Sopenharmony_ci    */
271bf215546Sopenharmony_ci   if (propCount <= 0) {
272bf215546Sopenharmony_ci      _mesa_error(ctx, GL_INVALID_VALUE,
273bf215546Sopenharmony_ci                  "glGetProgramResourceiv(propCount <= 0)");
274bf215546Sopenharmony_ci      return;
275bf215546Sopenharmony_ci   }
276bf215546Sopenharmony_ci
277bf215546Sopenharmony_ci   _mesa_get_program_resourceiv(shProg, programInterface, index,
278bf215546Sopenharmony_ci                                propCount, props, bufSize, length, params);
279bf215546Sopenharmony_ci}
280bf215546Sopenharmony_ci
281bf215546Sopenharmony_ciGLint GLAPIENTRY
282bf215546Sopenharmony_ci_mesa_GetProgramResourceLocation(GLuint program, GLenum programInterface,
283bf215546Sopenharmony_ci                                 const GLchar *name)
284bf215546Sopenharmony_ci{
285bf215546Sopenharmony_ci   GET_CURRENT_CONTEXT(ctx);
286bf215546Sopenharmony_ci
287bf215546Sopenharmony_ci   if (MESA_VERBOSE & VERBOSE_API) {
288bf215546Sopenharmony_ci      _mesa_debug(ctx, "glGetProgramResourceLocation(%u, %s, %s)\n",
289bf215546Sopenharmony_ci                  program, _mesa_enum_to_string(programInterface), name);
290bf215546Sopenharmony_ci   }
291bf215546Sopenharmony_ci
292bf215546Sopenharmony_ci   struct gl_shader_program *shProg =
293bf215546Sopenharmony_ci      lookup_linked_program(program, "glGetProgramResourceLocation");
294bf215546Sopenharmony_ci
295bf215546Sopenharmony_ci   if (!shProg || !name)
296bf215546Sopenharmony_ci      return -1;
297bf215546Sopenharmony_ci
298bf215546Sopenharmony_ci   /* Validate programInterface. */
299bf215546Sopenharmony_ci   switch (programInterface) {
300bf215546Sopenharmony_ci   case GL_UNIFORM:
301bf215546Sopenharmony_ci   case GL_PROGRAM_INPUT:
302bf215546Sopenharmony_ci   case GL_PROGRAM_OUTPUT:
303bf215546Sopenharmony_ci      break;
304bf215546Sopenharmony_ci
305bf215546Sopenharmony_ci   case GL_VERTEX_SUBROUTINE_UNIFORM:
306bf215546Sopenharmony_ci   case GL_FRAGMENT_SUBROUTINE_UNIFORM:
307bf215546Sopenharmony_ci      if (!_mesa_has_ARB_shader_subroutine(ctx))
308bf215546Sopenharmony_ci         goto fail;
309bf215546Sopenharmony_ci      break;
310bf215546Sopenharmony_ci   case GL_GEOMETRY_SUBROUTINE_UNIFORM:
311bf215546Sopenharmony_ci      if (!_mesa_has_geometry_shaders(ctx) || !_mesa_has_ARB_shader_subroutine(ctx))
312bf215546Sopenharmony_ci         goto fail;
313bf215546Sopenharmony_ci      break;
314bf215546Sopenharmony_ci   case GL_COMPUTE_SUBROUTINE_UNIFORM:
315bf215546Sopenharmony_ci      if (!_mesa_has_compute_shaders(ctx) || !_mesa_has_ARB_shader_subroutine(ctx))
316bf215546Sopenharmony_ci         goto fail;
317bf215546Sopenharmony_ci      break;
318bf215546Sopenharmony_ci   case GL_TESS_CONTROL_SUBROUTINE_UNIFORM:
319bf215546Sopenharmony_ci   case GL_TESS_EVALUATION_SUBROUTINE_UNIFORM:
320bf215546Sopenharmony_ci      if (!_mesa_has_tessellation(ctx) || !_mesa_has_ARB_shader_subroutine(ctx))
321bf215546Sopenharmony_ci         goto fail;
322bf215546Sopenharmony_ci      break;
323bf215546Sopenharmony_ci   default:
324bf215546Sopenharmony_ci         goto fail;
325bf215546Sopenharmony_ci   }
326bf215546Sopenharmony_ci
327bf215546Sopenharmony_ci   return _mesa_program_resource_location(shProg, programInterface, name);
328bf215546Sopenharmony_cifail:
329bf215546Sopenharmony_ci   _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramResourceLocation(%s %s)",
330bf215546Sopenharmony_ci               _mesa_enum_to_string(programInterface), name);
331bf215546Sopenharmony_ci   return -1;
332bf215546Sopenharmony_ci}
333bf215546Sopenharmony_ci
334bf215546Sopenharmony_ci/**
335bf215546Sopenharmony_ci * Returns output index for dual source blending.
336bf215546Sopenharmony_ci */
337bf215546Sopenharmony_ciGLint GLAPIENTRY
338bf215546Sopenharmony_ci_mesa_GetProgramResourceLocationIndex(GLuint program, GLenum programInterface,
339bf215546Sopenharmony_ci                                      const GLchar *name)
340bf215546Sopenharmony_ci{
341bf215546Sopenharmony_ci   GET_CURRENT_CONTEXT(ctx);
342bf215546Sopenharmony_ci
343bf215546Sopenharmony_ci   if (MESA_VERBOSE & VERBOSE_API) {
344bf215546Sopenharmony_ci      _mesa_debug(ctx, "glGetProgramResourceLocationIndex(%u, %s, %s)\n",
345bf215546Sopenharmony_ci                  program, _mesa_enum_to_string(programInterface), name);
346bf215546Sopenharmony_ci   }
347bf215546Sopenharmony_ci
348bf215546Sopenharmony_ci   struct gl_shader_program *shProg =
349bf215546Sopenharmony_ci      lookup_linked_program(program, "glGetProgramResourceLocationIndex");
350bf215546Sopenharmony_ci
351bf215546Sopenharmony_ci   if (!shProg || !name)
352bf215546Sopenharmony_ci      return -1;
353bf215546Sopenharmony_ci
354bf215546Sopenharmony_ci   /* From the GL_ARB_program_interface_query spec:
355bf215546Sopenharmony_ci    *
356bf215546Sopenharmony_ci    * "For GetProgramResourceLocationIndex, <programInterface> must be
357bf215546Sopenharmony_ci    * PROGRAM_OUTPUT."
358bf215546Sopenharmony_ci    */
359bf215546Sopenharmony_ci   if (programInterface != GL_PROGRAM_OUTPUT) {
360bf215546Sopenharmony_ci      _mesa_error(ctx, GL_INVALID_ENUM,
361bf215546Sopenharmony_ci                  "glGetProgramResourceLocationIndex(%s)",
362bf215546Sopenharmony_ci                  _mesa_enum_to_string(programInterface));
363bf215546Sopenharmony_ci      return -1;
364bf215546Sopenharmony_ci   }
365bf215546Sopenharmony_ci
366bf215546Sopenharmony_ci   return _mesa_program_resource_location_index(shProg, GL_PROGRAM_OUTPUT,
367bf215546Sopenharmony_ci                                                name);
368bf215546Sopenharmony_ci}
369