1bf215546Sopenharmony_ci/*
2bf215546Sopenharmony_ci * Mesa 3-D graphics library
3bf215546Sopenharmony_ci *
4bf215546Sopenharmony_ci * Copyright (C) 2004-2008  Brian Paul   All Rights Reserved.
5bf215546Sopenharmony_ci * Copyright (C) 2009-2010  VMware, Inc.  All Rights Reserved.
6bf215546Sopenharmony_ci *
7bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a
8bf215546Sopenharmony_ci * copy of this software and associated documentation files (the "Software"),
9bf215546Sopenharmony_ci * to deal in the Software without restriction, including without limitation
10bf215546Sopenharmony_ci * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11bf215546Sopenharmony_ci * and/or sell copies of the Software, and to permit persons to whom the
12bf215546Sopenharmony_ci * Software is furnished to do so, subject to the following conditions:
13bf215546Sopenharmony_ci *
14bf215546Sopenharmony_ci * The above copyright notice and this permission notice shall be included
15bf215546Sopenharmony_ci * in all copies or substantial portions of the Software.
16bf215546Sopenharmony_ci *
17bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18bf215546Sopenharmony_ci * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19bf215546Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
20bf215546Sopenharmony_ci * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
21bf215546Sopenharmony_ci * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
22bf215546Sopenharmony_ci * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
23bf215546Sopenharmony_ci * OTHER DEALINGS IN THE SOFTWARE.
24bf215546Sopenharmony_ci */
25bf215546Sopenharmony_ci
26bf215546Sopenharmony_ci/**
27bf215546Sopenharmony_ci * \file shaderapi.c
28bf215546Sopenharmony_ci * \author Brian Paul
29bf215546Sopenharmony_ci *
30bf215546Sopenharmony_ci * Implementation of GLSL-related API functions.
31bf215546Sopenharmony_ci * The glUniform* functions are in uniforms.c
32bf215546Sopenharmony_ci */
33bf215546Sopenharmony_ci
34bf215546Sopenharmony_ci
35bf215546Sopenharmony_ci#include <errno.h>
36bf215546Sopenharmony_ci#include <stdbool.h>
37bf215546Sopenharmony_ci#include <c99_alloca.h>
38bf215546Sopenharmony_ci
39bf215546Sopenharmony_ci#include "main/glheader.h"
40bf215546Sopenharmony_ci#include "main/context.h"
41bf215546Sopenharmony_ci#include "draw_validate.h"
42bf215546Sopenharmony_ci#include "main/enums.h"
43bf215546Sopenharmony_ci#include "main/glspirv.h"
44bf215546Sopenharmony_ci#include "main/hash.h"
45bf215546Sopenharmony_ci#include "main/mtypes.h"
46bf215546Sopenharmony_ci#include "main/pipelineobj.h"
47bf215546Sopenharmony_ci#include "main/program_binary.h"
48bf215546Sopenharmony_ci#include "main/shaderapi.h"
49bf215546Sopenharmony_ci#include "main/shaderobj.h"
50bf215546Sopenharmony_ci#include "main/state.h"
51bf215546Sopenharmony_ci#include "main/transformfeedback.h"
52bf215546Sopenharmony_ci#include "main/uniforms.h"
53bf215546Sopenharmony_ci#include "compiler/glsl/builtin_functions.h"
54bf215546Sopenharmony_ci#include "compiler/glsl/glsl_parser_extras.h"
55bf215546Sopenharmony_ci#include "compiler/glsl/ir.h"
56bf215546Sopenharmony_ci#include "compiler/glsl/ir_uniform.h"
57bf215546Sopenharmony_ci#include "compiler/glsl/program.h"
58bf215546Sopenharmony_ci#include "program/program.h"
59bf215546Sopenharmony_ci#include "program/prog_print.h"
60bf215546Sopenharmony_ci#include "program/prog_parameter.h"
61bf215546Sopenharmony_ci#include "util/ralloc.h"
62bf215546Sopenharmony_ci#include "util/hash_table.h"
63bf215546Sopenharmony_ci#include "util/crc32.h"
64bf215546Sopenharmony_ci#include "util/os_file.h"
65bf215546Sopenharmony_ci#include "util/list.h"
66bf215546Sopenharmony_ci#include "util/u_process.h"
67bf215546Sopenharmony_ci#include "util/u_string.h"
68bf215546Sopenharmony_ci#include "api_exec_decl.h"
69bf215546Sopenharmony_ci
70bf215546Sopenharmony_ci#include "state_tracker/st_context.h"
71bf215546Sopenharmony_ci#include "state_tracker/st_program.h"
72bf215546Sopenharmony_ci
73bf215546Sopenharmony_ci#ifdef ENABLE_SHADER_CACHE
74bf215546Sopenharmony_ci#if CUSTOM_SHADER_REPLACEMENT
75bf215546Sopenharmony_ci#include "shader_replacement.h"
76bf215546Sopenharmony_ci/* shader_replacement.h must declare a variable like this:
77bf215546Sopenharmony_ci
78bf215546Sopenharmony_ci   struct _shader_replacement {
79bf215546Sopenharmony_ci      // process name. If null, only sha1 is used to match
80bf215546Sopenharmony_ci      const char *app;
81bf215546Sopenharmony_ci      // original glsl shader sha1
82bf215546Sopenharmony_ci      const char *sha1;
83bf215546Sopenharmony_ci      // shader stage
84bf215546Sopenharmony_ci      gl_shader_stage stage;
85bf215546Sopenharmony_ci      ... any other information ...
86bf215546Sopenharmony_ci   };
87bf215546Sopenharmony_ci   struct _shader_replacement shader_replacements[...];
88bf215546Sopenharmony_ci
89bf215546Sopenharmony_ci   And a method to load a given replacement and return the new
90bf215546Sopenharmony_ci   glsl source:
91bf215546Sopenharmony_ci
92bf215546Sopenharmony_ci   char* load_shader_replacement(struct _shader_replacement *repl);
93bf215546Sopenharmony_ci
94bf215546Sopenharmony_ci   And a method to replace the shader without sha1 matching:
95bf215546Sopenharmony_ci
96bf215546Sopenharmony_ci   char *try_direct_replace(const char *app, const char *source)
97bf215546Sopenharmony_ci
98bf215546Sopenharmony_ci   shader_replacement.h can be generated at build time, or copied
99bf215546Sopenharmony_ci   from an external folder, or any other method.
100bf215546Sopenharmony_ci*/
101bf215546Sopenharmony_ci#else
102bf215546Sopenharmony_cistruct _shader_replacement {
103bf215546Sopenharmony_ci   const char *app;
104bf215546Sopenharmony_ci   const char *sha1;
105bf215546Sopenharmony_ci   gl_shader_stage stage;
106bf215546Sopenharmony_ci};
107bf215546Sopenharmony_cistruct _shader_replacement shader_replacements[0];
108bf215546Sopenharmony_ci
109bf215546Sopenharmony_cistatic char *try_direct_replace(const char *app, const char *source)
110bf215546Sopenharmony_ci{
111bf215546Sopenharmony_ci   return NULL;
112bf215546Sopenharmony_ci}
113bf215546Sopenharmony_ci
114bf215546Sopenharmony_cistatic char* load_shader_replacement(struct _shader_replacement *repl)
115bf215546Sopenharmony_ci{
116bf215546Sopenharmony_ci   return NULL;
117bf215546Sopenharmony_ci}
118bf215546Sopenharmony_ci#endif
119bf215546Sopenharmony_ci#endif
120bf215546Sopenharmony_ci
121bf215546Sopenharmony_ci/**
122bf215546Sopenharmony_ci * Return mask of GLSL_x flags by examining the MESA_GLSL env var.
123bf215546Sopenharmony_ci */
124bf215546Sopenharmony_ciGLbitfield
125bf215546Sopenharmony_ci_mesa_get_shader_flags(void)
126bf215546Sopenharmony_ci{
127bf215546Sopenharmony_ci   GLbitfield flags = 0x0;
128bf215546Sopenharmony_ci   const char *env = getenv("MESA_GLSL");
129bf215546Sopenharmony_ci
130bf215546Sopenharmony_ci   if (env) {
131bf215546Sopenharmony_ci      if (strstr(env, "dump_on_error"))
132bf215546Sopenharmony_ci         flags |= GLSL_DUMP_ON_ERROR;
133bf215546Sopenharmony_ci#ifndef CUSTOM_SHADER_REPLACEMENT
134bf215546Sopenharmony_ci      else if (strstr(env, "dump"))
135bf215546Sopenharmony_ci         flags |= GLSL_DUMP;
136bf215546Sopenharmony_ci      if (strstr(env, "log"))
137bf215546Sopenharmony_ci         flags |= GLSL_LOG;
138bf215546Sopenharmony_ci#endif
139bf215546Sopenharmony_ci      if (strstr(env, "cache_fb"))
140bf215546Sopenharmony_ci         flags |= GLSL_CACHE_FALLBACK;
141bf215546Sopenharmony_ci      if (strstr(env, "cache_info"))
142bf215546Sopenharmony_ci         flags |= GLSL_CACHE_INFO;
143bf215546Sopenharmony_ci      if (strstr(env, "nopvert"))
144bf215546Sopenharmony_ci         flags |= GLSL_NOP_VERT;
145bf215546Sopenharmony_ci      if (strstr(env, "nopfrag"))
146bf215546Sopenharmony_ci         flags |= GLSL_NOP_FRAG;
147bf215546Sopenharmony_ci      if (strstr(env, "uniform"))
148bf215546Sopenharmony_ci         flags |= GLSL_UNIFORMS;
149bf215546Sopenharmony_ci      if (strstr(env, "useprog"))
150bf215546Sopenharmony_ci         flags |= GLSL_USE_PROG;
151bf215546Sopenharmony_ci      if (strstr(env, "errors"))
152bf215546Sopenharmony_ci         flags |= GLSL_REPORT_ERRORS;
153bf215546Sopenharmony_ci   }
154bf215546Sopenharmony_ci
155bf215546Sopenharmony_ci   return flags;
156bf215546Sopenharmony_ci}
157bf215546Sopenharmony_ci
158bf215546Sopenharmony_ci#define ANDROID_SHADER_CAPTURE 0
159bf215546Sopenharmony_ci
160bf215546Sopenharmony_ci#if ANDROID_SHADER_CAPTURE
161bf215546Sopenharmony_ci#include "util/u_process.h"
162bf215546Sopenharmony_ci#include <sys/stat.h>
163bf215546Sopenharmony_ci#include <sys/types.h>
164bf215546Sopenharmony_ci#endif
165bf215546Sopenharmony_ci
166bf215546Sopenharmony_ci/**
167bf215546Sopenharmony_ci * Memoized version of getenv("MESA_SHADER_CAPTURE_PATH").
168bf215546Sopenharmony_ci */
169bf215546Sopenharmony_ciconst char *
170bf215546Sopenharmony_ci_mesa_get_shader_capture_path(void)
171bf215546Sopenharmony_ci{
172bf215546Sopenharmony_ci   static bool read_env_var = false;
173bf215546Sopenharmony_ci   static const char *path = NULL;
174bf215546Sopenharmony_ci
175bf215546Sopenharmony_ci   if (!read_env_var) {
176bf215546Sopenharmony_ci      path = getenv("MESA_SHADER_CAPTURE_PATH");
177bf215546Sopenharmony_ci      read_env_var = true;
178bf215546Sopenharmony_ci
179bf215546Sopenharmony_ci#if ANDROID_SHADER_CAPTURE
180bf215546Sopenharmony_ci      if (!path) {
181bf215546Sopenharmony_ci         char *p;
182bf215546Sopenharmony_ci         asprintf(&p, "/data/shaders/%s", util_get_process_name());
183bf215546Sopenharmony_ci         mkdir(p, 0755);
184bf215546Sopenharmony_ci         path = p;
185bf215546Sopenharmony_ci      }
186bf215546Sopenharmony_ci#endif
187bf215546Sopenharmony_ci   }
188bf215546Sopenharmony_ci
189bf215546Sopenharmony_ci   return path;
190bf215546Sopenharmony_ci}
191bf215546Sopenharmony_ci
192bf215546Sopenharmony_ci/**
193bf215546Sopenharmony_ci * Initialize context's shader state.
194bf215546Sopenharmony_ci */
195bf215546Sopenharmony_civoid
196bf215546Sopenharmony_ci_mesa_init_shader_state(struct gl_context *ctx)
197bf215546Sopenharmony_ci{
198bf215546Sopenharmony_ci   /* Device drivers may override these to control what kind of instructions
199bf215546Sopenharmony_ci    * are generated by the GLSL compiler.
200bf215546Sopenharmony_ci    */
201bf215546Sopenharmony_ci   struct gl_shader_compiler_options options;
202bf215546Sopenharmony_ci   gl_shader_stage sh;
203bf215546Sopenharmony_ci   int i;
204bf215546Sopenharmony_ci
205bf215546Sopenharmony_ci   memset(&options, 0, sizeof(options));
206bf215546Sopenharmony_ci   options.MaxIfDepth = UINT_MAX;
207bf215546Sopenharmony_ci
208bf215546Sopenharmony_ci   for (sh = 0; sh < MESA_SHADER_STAGES; ++sh)
209bf215546Sopenharmony_ci      memcpy(&ctx->Const.ShaderCompilerOptions[sh], &options, sizeof(options));
210bf215546Sopenharmony_ci
211bf215546Sopenharmony_ci   ctx->Shader.Flags = _mesa_get_shader_flags();
212bf215546Sopenharmony_ci
213bf215546Sopenharmony_ci   if (ctx->Shader.Flags != 0)
214bf215546Sopenharmony_ci      ctx->Const.GenerateTemporaryNames = true;
215bf215546Sopenharmony_ci
216bf215546Sopenharmony_ci   /* Extended for ARB_separate_shader_objects */
217bf215546Sopenharmony_ci   ctx->Shader.RefCount = 1;
218bf215546Sopenharmony_ci   ctx->TessCtrlProgram.patch_vertices = 3;
219bf215546Sopenharmony_ci   for (i = 0; i < 4; ++i)
220bf215546Sopenharmony_ci      ctx->TessCtrlProgram.patch_default_outer_level[i] = 1.0;
221bf215546Sopenharmony_ci   for (i = 0; i < 2; ++i)
222bf215546Sopenharmony_ci      ctx->TessCtrlProgram.patch_default_inner_level[i] = 1.0;
223bf215546Sopenharmony_ci}
224bf215546Sopenharmony_ci
225bf215546Sopenharmony_ci
226bf215546Sopenharmony_ci/**
227bf215546Sopenharmony_ci * Free the per-context shader-related state.
228bf215546Sopenharmony_ci */
229bf215546Sopenharmony_civoid
230bf215546Sopenharmony_ci_mesa_free_shader_state(struct gl_context *ctx)
231bf215546Sopenharmony_ci{
232bf215546Sopenharmony_ci   for (int i = 0; i < MESA_SHADER_STAGES; i++) {
233bf215546Sopenharmony_ci      _mesa_reference_program(ctx, &ctx->Shader.CurrentProgram[i], NULL);
234bf215546Sopenharmony_ci      _mesa_reference_shader_program(ctx,
235bf215546Sopenharmony_ci                                     &ctx->Shader.ReferencedPrograms[i],
236bf215546Sopenharmony_ci                                     NULL);
237bf215546Sopenharmony_ci      free(ctx->SubroutineIndex[i].IndexPtr);
238bf215546Sopenharmony_ci      ctx->SubroutineIndex[i].IndexPtr = NULL;
239bf215546Sopenharmony_ci   }
240bf215546Sopenharmony_ci   _mesa_reference_shader_program(ctx, &ctx->Shader.ActiveProgram, NULL);
241bf215546Sopenharmony_ci
242bf215546Sopenharmony_ci   /* Extended for ARB_separate_shader_objects */
243bf215546Sopenharmony_ci   _mesa_reference_pipeline_object(ctx, &ctx->_Shader, NULL);
244bf215546Sopenharmony_ci
245bf215546Sopenharmony_ci   assert(ctx->Shader.RefCount == 1);
246bf215546Sopenharmony_ci}
247bf215546Sopenharmony_ci
248bf215546Sopenharmony_ci
249bf215546Sopenharmony_ci/**
250bf215546Sopenharmony_ci * Copy string from <src> to <dst>, up to maxLength characters, returning
251bf215546Sopenharmony_ci * length of <dst> in <length>.
252bf215546Sopenharmony_ci * \param src  the strings source
253bf215546Sopenharmony_ci * \param maxLength  max chars to copy
254bf215546Sopenharmony_ci * \param length  returns number of chars copied
255bf215546Sopenharmony_ci * \param dst  the string destination
256bf215546Sopenharmony_ci */
257bf215546Sopenharmony_civoid
258bf215546Sopenharmony_ci_mesa_copy_string(GLchar *dst, GLsizei maxLength,
259bf215546Sopenharmony_ci                  GLsizei *length, const GLchar *src)
260bf215546Sopenharmony_ci{
261bf215546Sopenharmony_ci   GLsizei len;
262bf215546Sopenharmony_ci   for (len = 0; len < maxLength - 1 && src && src[len]; len++)
263bf215546Sopenharmony_ci      dst[len] = src[len];
264bf215546Sopenharmony_ci   if (maxLength > 0)
265bf215546Sopenharmony_ci      dst[len] = 0;
266bf215546Sopenharmony_ci   if (length)
267bf215546Sopenharmony_ci      *length = len;
268bf215546Sopenharmony_ci}
269bf215546Sopenharmony_ci
270bf215546Sopenharmony_ci
271bf215546Sopenharmony_ci
272bf215546Sopenharmony_ci/**
273bf215546Sopenharmony_ci * Confirm that the a shader type is valid and supported by the implementation
274bf215546Sopenharmony_ci *
275bf215546Sopenharmony_ci * \param ctx   Current GL context
276bf215546Sopenharmony_ci * \param type  Shader target
277bf215546Sopenharmony_ci *
278bf215546Sopenharmony_ci */
279bf215546Sopenharmony_cibool
280bf215546Sopenharmony_ci_mesa_validate_shader_target(const struct gl_context *ctx, GLenum type)
281bf215546Sopenharmony_ci{
282bf215546Sopenharmony_ci   /* Note: when building built-in GLSL functions, this function may be
283bf215546Sopenharmony_ci    * invoked with ctx == NULL.  In that case, we can only validate that it's
284bf215546Sopenharmony_ci    * a shader target we recognize, not that it's supported in the current
285bf215546Sopenharmony_ci    * context.  But that's fine--we don't need any further validation than
286bf215546Sopenharmony_ci    * that when building built-in GLSL functions.
287bf215546Sopenharmony_ci    */
288bf215546Sopenharmony_ci
289bf215546Sopenharmony_ci   switch (type) {
290bf215546Sopenharmony_ci   case GL_FRAGMENT_SHADER:
291bf215546Sopenharmony_ci      return ctx == NULL || ctx->Extensions.ARB_fragment_shader;
292bf215546Sopenharmony_ci   case GL_VERTEX_SHADER:
293bf215546Sopenharmony_ci      return ctx == NULL || ctx->Extensions.ARB_vertex_shader;
294bf215546Sopenharmony_ci   case GL_GEOMETRY_SHADER_ARB:
295bf215546Sopenharmony_ci      return ctx == NULL || _mesa_has_geometry_shaders(ctx);
296bf215546Sopenharmony_ci   case GL_TESS_CONTROL_SHADER:
297bf215546Sopenharmony_ci   case GL_TESS_EVALUATION_SHADER:
298bf215546Sopenharmony_ci      return ctx == NULL || _mesa_has_tessellation(ctx);
299bf215546Sopenharmony_ci   case GL_COMPUTE_SHADER:
300bf215546Sopenharmony_ci      return ctx == NULL || _mesa_has_compute_shaders(ctx);
301bf215546Sopenharmony_ci   default:
302bf215546Sopenharmony_ci      return false;
303bf215546Sopenharmony_ci   }
304bf215546Sopenharmony_ci}
305bf215546Sopenharmony_ci
306bf215546Sopenharmony_ci
307bf215546Sopenharmony_cistatic GLboolean
308bf215546Sopenharmony_ciis_program(struct gl_context *ctx, GLuint name)
309bf215546Sopenharmony_ci{
310bf215546Sopenharmony_ci   struct gl_shader_program *shProg = _mesa_lookup_shader_program(ctx, name);
311bf215546Sopenharmony_ci   return shProg ? GL_TRUE : GL_FALSE;
312bf215546Sopenharmony_ci}
313bf215546Sopenharmony_ci
314bf215546Sopenharmony_ci
315bf215546Sopenharmony_cistatic GLboolean
316bf215546Sopenharmony_ciis_shader(struct gl_context *ctx, GLuint name)
317bf215546Sopenharmony_ci{
318bf215546Sopenharmony_ci   struct gl_shader *shader = _mesa_lookup_shader(ctx, name);
319bf215546Sopenharmony_ci   return shader ? GL_TRUE : GL_FALSE;
320bf215546Sopenharmony_ci}
321bf215546Sopenharmony_ci
322bf215546Sopenharmony_ci
323bf215546Sopenharmony_ci/**
324bf215546Sopenharmony_ci * Attach shader to a shader program.
325bf215546Sopenharmony_ci */
326bf215546Sopenharmony_cistatic void
327bf215546Sopenharmony_ciattach_shader(struct gl_context *ctx, struct gl_shader_program *shProg,
328bf215546Sopenharmony_ci              struct gl_shader *sh)
329bf215546Sopenharmony_ci{
330bf215546Sopenharmony_ci   GLuint n = shProg->NumShaders;
331bf215546Sopenharmony_ci
332bf215546Sopenharmony_ci   shProg->Shaders = realloc(shProg->Shaders,
333bf215546Sopenharmony_ci                             (n + 1) * sizeof(struct gl_shader *));
334bf215546Sopenharmony_ci   if (!shProg->Shaders) {
335bf215546Sopenharmony_ci      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glAttachShader");
336bf215546Sopenharmony_ci      return;
337bf215546Sopenharmony_ci   }
338bf215546Sopenharmony_ci
339bf215546Sopenharmony_ci   /* append */
340bf215546Sopenharmony_ci   shProg->Shaders[n] = NULL; /* since realloc() didn't zero the new space */
341bf215546Sopenharmony_ci   _mesa_reference_shader(ctx, &shProg->Shaders[n], sh);
342bf215546Sopenharmony_ci   shProg->NumShaders++;
343bf215546Sopenharmony_ci}
344bf215546Sopenharmony_ci
345bf215546Sopenharmony_cistatic void
346bf215546Sopenharmony_ciattach_shader_err(struct gl_context *ctx, GLuint program, GLuint shader,
347bf215546Sopenharmony_ci                  const char *caller)
348bf215546Sopenharmony_ci{
349bf215546Sopenharmony_ci   struct gl_shader_program *shProg;
350bf215546Sopenharmony_ci   struct gl_shader *sh;
351bf215546Sopenharmony_ci   GLuint i, n;
352bf215546Sopenharmony_ci
353bf215546Sopenharmony_ci   const bool same_type_disallowed = _mesa_is_gles(ctx);
354bf215546Sopenharmony_ci
355bf215546Sopenharmony_ci   shProg = _mesa_lookup_shader_program_err(ctx, program, caller);
356bf215546Sopenharmony_ci   if (!shProg)
357bf215546Sopenharmony_ci      return;
358bf215546Sopenharmony_ci
359bf215546Sopenharmony_ci   sh = _mesa_lookup_shader_err(ctx, shader, caller);
360bf215546Sopenharmony_ci   if (!sh) {
361bf215546Sopenharmony_ci      return;
362bf215546Sopenharmony_ci   }
363bf215546Sopenharmony_ci
364bf215546Sopenharmony_ci   n = shProg->NumShaders;
365bf215546Sopenharmony_ci   for (i = 0; i < n; i++) {
366bf215546Sopenharmony_ci      if (shProg->Shaders[i] == sh) {
367bf215546Sopenharmony_ci         /* The shader is already attched to this program.  The
368bf215546Sopenharmony_ci          * GL_ARB_shader_objects spec says:
369bf215546Sopenharmony_ci          *
370bf215546Sopenharmony_ci          *     "The error INVALID_OPERATION is generated by AttachObjectARB
371bf215546Sopenharmony_ci          *     if <obj> is already attached to <containerObj>."
372bf215546Sopenharmony_ci          */
373bf215546Sopenharmony_ci         _mesa_error(ctx, GL_INVALID_OPERATION, "%s", caller);
374bf215546Sopenharmony_ci         return;
375bf215546Sopenharmony_ci      } else if (same_type_disallowed &&
376bf215546Sopenharmony_ci                 shProg->Shaders[i]->Stage == sh->Stage) {
377bf215546Sopenharmony_ci        /* Shader with the same type is already attached to this program,
378bf215546Sopenharmony_ci         * OpenGL ES 2.0 and 3.0 specs say:
379bf215546Sopenharmony_ci         *
380bf215546Sopenharmony_ci         *      "Multiple shader objects of the same type may not be attached
381bf215546Sopenharmony_ci         *      to a single program object. [...] The error INVALID_OPERATION
382bf215546Sopenharmony_ci         *      is generated if [...] another shader object of the same type
383bf215546Sopenharmony_ci         *      as shader is already attached to program."
384bf215546Sopenharmony_ci         */
385bf215546Sopenharmony_ci         _mesa_error(ctx, GL_INVALID_OPERATION, "%s", caller);
386bf215546Sopenharmony_ci         return;
387bf215546Sopenharmony_ci      }
388bf215546Sopenharmony_ci   }
389bf215546Sopenharmony_ci
390bf215546Sopenharmony_ci   attach_shader(ctx, shProg, sh);
391bf215546Sopenharmony_ci}
392bf215546Sopenharmony_ci
393bf215546Sopenharmony_cistatic void
394bf215546Sopenharmony_ciattach_shader_no_error(struct gl_context *ctx, GLuint program, GLuint shader)
395bf215546Sopenharmony_ci{
396bf215546Sopenharmony_ci   struct gl_shader_program *shProg;
397bf215546Sopenharmony_ci   struct gl_shader *sh;
398bf215546Sopenharmony_ci
399bf215546Sopenharmony_ci   shProg = _mesa_lookup_shader_program(ctx, program);
400bf215546Sopenharmony_ci   sh = _mesa_lookup_shader(ctx, shader);
401bf215546Sopenharmony_ci
402bf215546Sopenharmony_ci   attach_shader(ctx, shProg, sh);
403bf215546Sopenharmony_ci}
404bf215546Sopenharmony_ci
405bf215546Sopenharmony_cistatic GLuint
406bf215546Sopenharmony_cicreate_shader(struct gl_context *ctx, GLenum type)
407bf215546Sopenharmony_ci{
408bf215546Sopenharmony_ci   struct gl_shader *sh;
409bf215546Sopenharmony_ci   GLuint name;
410bf215546Sopenharmony_ci
411bf215546Sopenharmony_ci   _mesa_HashLockMutex(ctx->Shared->ShaderObjects);
412bf215546Sopenharmony_ci   name = _mesa_HashFindFreeKeyBlock(ctx->Shared->ShaderObjects, 1);
413bf215546Sopenharmony_ci   sh = _mesa_new_shader(name, _mesa_shader_enum_to_shader_stage(type));
414bf215546Sopenharmony_ci   sh->Type = type;
415bf215546Sopenharmony_ci   _mesa_HashInsertLocked(ctx->Shared->ShaderObjects, name, sh, true);
416bf215546Sopenharmony_ci   _mesa_HashUnlockMutex(ctx->Shared->ShaderObjects);
417bf215546Sopenharmony_ci
418bf215546Sopenharmony_ci   return name;
419bf215546Sopenharmony_ci}
420bf215546Sopenharmony_ci
421bf215546Sopenharmony_ci
422bf215546Sopenharmony_cistatic GLuint
423bf215546Sopenharmony_cicreate_shader_err(struct gl_context *ctx, GLenum type, const char *caller)
424bf215546Sopenharmony_ci{
425bf215546Sopenharmony_ci   if (!_mesa_validate_shader_target(ctx, type)) {
426bf215546Sopenharmony_ci      _mesa_error(ctx, GL_INVALID_ENUM, "%s(%s)",
427bf215546Sopenharmony_ci                  caller, _mesa_enum_to_string(type));
428bf215546Sopenharmony_ci      return 0;
429bf215546Sopenharmony_ci   }
430bf215546Sopenharmony_ci
431bf215546Sopenharmony_ci   return create_shader(ctx, type);
432bf215546Sopenharmony_ci}
433bf215546Sopenharmony_ci
434bf215546Sopenharmony_ci
435bf215546Sopenharmony_cistatic GLuint
436bf215546Sopenharmony_cicreate_shader_program(struct gl_context *ctx)
437bf215546Sopenharmony_ci{
438bf215546Sopenharmony_ci   GLuint name;
439bf215546Sopenharmony_ci   struct gl_shader_program *shProg;
440bf215546Sopenharmony_ci
441bf215546Sopenharmony_ci   _mesa_HashLockMutex(ctx->Shared->ShaderObjects);
442bf215546Sopenharmony_ci
443bf215546Sopenharmony_ci   name = _mesa_HashFindFreeKeyBlock(ctx->Shared->ShaderObjects, 1);
444bf215546Sopenharmony_ci
445bf215546Sopenharmony_ci   shProg = _mesa_new_shader_program(name);
446bf215546Sopenharmony_ci
447bf215546Sopenharmony_ci   _mesa_HashInsertLocked(ctx->Shared->ShaderObjects, name, shProg, true);
448bf215546Sopenharmony_ci
449bf215546Sopenharmony_ci   assert(shProg->RefCount == 1);
450bf215546Sopenharmony_ci
451bf215546Sopenharmony_ci   _mesa_HashUnlockMutex(ctx->Shared->ShaderObjects);
452bf215546Sopenharmony_ci
453bf215546Sopenharmony_ci   return name;
454bf215546Sopenharmony_ci}
455bf215546Sopenharmony_ci
456bf215546Sopenharmony_ci
457bf215546Sopenharmony_ci/**
458bf215546Sopenharmony_ci * Delete a shader program.  Actually, just decrement the program's
459bf215546Sopenharmony_ci * reference count and mark it as DeletePending.
460bf215546Sopenharmony_ci * Used to implement glDeleteProgram() and glDeleteObjectARB().
461bf215546Sopenharmony_ci */
462bf215546Sopenharmony_cistatic void
463bf215546Sopenharmony_cidelete_shader_program(struct gl_context *ctx, GLuint name)
464bf215546Sopenharmony_ci{
465bf215546Sopenharmony_ci   /*
466bf215546Sopenharmony_ci    * NOTE: deleting shaders/programs works a bit differently than
467bf215546Sopenharmony_ci    * texture objects (and buffer objects, etc).  Shader/program
468bf215546Sopenharmony_ci    * handles/IDs exist in the hash table until the object is really
469bf215546Sopenharmony_ci    * deleted (refcount==0).  With texture objects, the handle/ID is
470bf215546Sopenharmony_ci    * removed from the hash table in glDeleteTextures() while the tex
471bf215546Sopenharmony_ci    * object itself might linger until its refcount goes to zero.
472bf215546Sopenharmony_ci    */
473bf215546Sopenharmony_ci   struct gl_shader_program *shProg;
474bf215546Sopenharmony_ci
475bf215546Sopenharmony_ci   shProg = _mesa_lookup_shader_program_err(ctx, name, "glDeleteProgram");
476bf215546Sopenharmony_ci   if (!shProg)
477bf215546Sopenharmony_ci      return;
478bf215546Sopenharmony_ci
479bf215546Sopenharmony_ci   if (!shProg->DeletePending) {
480bf215546Sopenharmony_ci      shProg->DeletePending = GL_TRUE;
481bf215546Sopenharmony_ci
482bf215546Sopenharmony_ci      /* effectively, decr shProg's refcount */
483bf215546Sopenharmony_ci      _mesa_reference_shader_program(ctx, &shProg, NULL);
484bf215546Sopenharmony_ci   }
485bf215546Sopenharmony_ci}
486bf215546Sopenharmony_ci
487bf215546Sopenharmony_ci
488bf215546Sopenharmony_cistatic void
489bf215546Sopenharmony_cidelete_shader(struct gl_context *ctx, GLuint shader)
490bf215546Sopenharmony_ci{
491bf215546Sopenharmony_ci   struct gl_shader *sh;
492bf215546Sopenharmony_ci
493bf215546Sopenharmony_ci   sh = _mesa_lookup_shader_err(ctx, shader, "glDeleteShader");
494bf215546Sopenharmony_ci   if (!sh)
495bf215546Sopenharmony_ci      return;
496bf215546Sopenharmony_ci
497bf215546Sopenharmony_ci   if (!sh->DeletePending) {
498bf215546Sopenharmony_ci      sh->DeletePending = GL_TRUE;
499bf215546Sopenharmony_ci
500bf215546Sopenharmony_ci      /* effectively, decr sh's refcount */
501bf215546Sopenharmony_ci      _mesa_reference_shader(ctx, &sh, NULL);
502bf215546Sopenharmony_ci   }
503bf215546Sopenharmony_ci}
504bf215546Sopenharmony_ci
505bf215546Sopenharmony_ci
506bf215546Sopenharmony_cistatic ALWAYS_INLINE void
507bf215546Sopenharmony_cidetach_shader(struct gl_context *ctx, GLuint program, GLuint shader,
508bf215546Sopenharmony_ci              bool no_error)
509bf215546Sopenharmony_ci{
510bf215546Sopenharmony_ci   struct gl_shader_program *shProg;
511bf215546Sopenharmony_ci   GLuint n;
512bf215546Sopenharmony_ci   GLuint i, j;
513bf215546Sopenharmony_ci
514bf215546Sopenharmony_ci   if (!no_error) {
515bf215546Sopenharmony_ci      shProg = _mesa_lookup_shader_program_err(ctx, program, "glDetachShader");
516bf215546Sopenharmony_ci      if (!shProg)
517bf215546Sopenharmony_ci         return;
518bf215546Sopenharmony_ci   } else {
519bf215546Sopenharmony_ci      shProg = _mesa_lookup_shader_program(ctx, program);
520bf215546Sopenharmony_ci   }
521bf215546Sopenharmony_ci
522bf215546Sopenharmony_ci   n = shProg->NumShaders;
523bf215546Sopenharmony_ci
524bf215546Sopenharmony_ci   for (i = 0; i < n; i++) {
525bf215546Sopenharmony_ci      if (shProg->Shaders[i]->Name == shader) {
526bf215546Sopenharmony_ci         /* found it */
527bf215546Sopenharmony_ci         struct gl_shader **newList;
528bf215546Sopenharmony_ci
529bf215546Sopenharmony_ci         /* release */
530bf215546Sopenharmony_ci         _mesa_reference_shader(ctx, &shProg->Shaders[i], NULL);
531bf215546Sopenharmony_ci
532bf215546Sopenharmony_ci         /* alloc new, smaller array */
533bf215546Sopenharmony_ci         newList = malloc((n - 1) * sizeof(struct gl_shader *));
534bf215546Sopenharmony_ci         if (!newList) {
535bf215546Sopenharmony_ci            _mesa_error(ctx, GL_OUT_OF_MEMORY, "glDetachShader");
536bf215546Sopenharmony_ci            return;
537bf215546Sopenharmony_ci         }
538bf215546Sopenharmony_ci         /* Copy old list entries to new list, skipping removed entry at [i] */
539bf215546Sopenharmony_ci         for (j = 0; j < i; j++) {
540bf215546Sopenharmony_ci            newList[j] = shProg->Shaders[j];
541bf215546Sopenharmony_ci         }
542bf215546Sopenharmony_ci         while (++i < n) {
543bf215546Sopenharmony_ci            newList[j++] = shProg->Shaders[i];
544bf215546Sopenharmony_ci         }
545bf215546Sopenharmony_ci
546bf215546Sopenharmony_ci         /* Free old list and install new one */
547bf215546Sopenharmony_ci         free(shProg->Shaders);
548bf215546Sopenharmony_ci         shProg->Shaders = newList;
549bf215546Sopenharmony_ci         shProg->NumShaders = n - 1;
550bf215546Sopenharmony_ci
551bf215546Sopenharmony_ci#ifndef NDEBUG
552bf215546Sopenharmony_ci         /* sanity check - make sure the new list's entries are sensible */
553bf215546Sopenharmony_ci         for (j = 0; j < shProg->NumShaders; j++) {
554bf215546Sopenharmony_ci            assert(shProg->Shaders[j]->Stage == MESA_SHADER_VERTEX ||
555bf215546Sopenharmony_ci                   shProg->Shaders[j]->Stage == MESA_SHADER_TESS_CTRL ||
556bf215546Sopenharmony_ci                   shProg->Shaders[j]->Stage == MESA_SHADER_TESS_EVAL ||
557bf215546Sopenharmony_ci                   shProg->Shaders[j]->Stage == MESA_SHADER_GEOMETRY ||
558bf215546Sopenharmony_ci                   shProg->Shaders[j]->Stage == MESA_SHADER_FRAGMENT);
559bf215546Sopenharmony_ci            assert(shProg->Shaders[j]->RefCount > 0);
560bf215546Sopenharmony_ci         }
561bf215546Sopenharmony_ci#endif
562bf215546Sopenharmony_ci
563bf215546Sopenharmony_ci         return;
564bf215546Sopenharmony_ci      }
565bf215546Sopenharmony_ci   }
566bf215546Sopenharmony_ci
567bf215546Sopenharmony_ci   /* not found */
568bf215546Sopenharmony_ci   if (!no_error) {
569bf215546Sopenharmony_ci      GLenum err;
570bf215546Sopenharmony_ci      if (is_shader(ctx, shader) || is_program(ctx, shader))
571bf215546Sopenharmony_ci         err = GL_INVALID_OPERATION;
572bf215546Sopenharmony_ci      else
573bf215546Sopenharmony_ci         err = GL_INVALID_VALUE;
574bf215546Sopenharmony_ci      _mesa_error(ctx, err, "glDetachShader(shader)");
575bf215546Sopenharmony_ci      return;
576bf215546Sopenharmony_ci   }
577bf215546Sopenharmony_ci}
578bf215546Sopenharmony_ci
579bf215546Sopenharmony_ci
580bf215546Sopenharmony_cistatic void
581bf215546Sopenharmony_cidetach_shader_error(struct gl_context *ctx, GLuint program, GLuint shader)
582bf215546Sopenharmony_ci{
583bf215546Sopenharmony_ci   detach_shader(ctx, program, shader, false);
584bf215546Sopenharmony_ci}
585bf215546Sopenharmony_ci
586bf215546Sopenharmony_ci
587bf215546Sopenharmony_cistatic void
588bf215546Sopenharmony_cidetach_shader_no_error(struct gl_context *ctx, GLuint program, GLuint shader)
589bf215546Sopenharmony_ci{
590bf215546Sopenharmony_ci   detach_shader(ctx, program, shader, true);
591bf215546Sopenharmony_ci}
592bf215546Sopenharmony_ci
593bf215546Sopenharmony_ci
594bf215546Sopenharmony_ci/**
595bf215546Sopenharmony_ci * Return list of shaders attached to shader program.
596bf215546Sopenharmony_ci * \param objOut  returns GLuint ids
597bf215546Sopenharmony_ci * \param handleOut  returns GLhandleARB handles
598bf215546Sopenharmony_ci */
599bf215546Sopenharmony_cistatic void
600bf215546Sopenharmony_ciget_attached_shaders(struct gl_context *ctx, GLuint program, GLsizei maxCount,
601bf215546Sopenharmony_ci                     GLsizei *countOut, GLuint *objOut, GLhandleARB *handleOut)
602bf215546Sopenharmony_ci{
603bf215546Sopenharmony_ci   struct gl_shader_program *shProg;
604bf215546Sopenharmony_ci
605bf215546Sopenharmony_ci   if (maxCount < 0) {
606bf215546Sopenharmony_ci      _mesa_error(ctx, GL_INVALID_VALUE, "glGetAttachedShaders(maxCount < 0)");
607bf215546Sopenharmony_ci      return;
608bf215546Sopenharmony_ci   }
609bf215546Sopenharmony_ci
610bf215546Sopenharmony_ci   shProg =
611bf215546Sopenharmony_ci      _mesa_lookup_shader_program_err(ctx, program, "glGetAttachedShaders");
612bf215546Sopenharmony_ci
613bf215546Sopenharmony_ci   if (shProg) {
614bf215546Sopenharmony_ci      GLuint i;
615bf215546Sopenharmony_ci      for (i = 0; i < (GLuint) maxCount && i < shProg->NumShaders; i++) {
616bf215546Sopenharmony_ci         if (objOut) {
617bf215546Sopenharmony_ci            objOut[i] = shProg->Shaders[i]->Name;
618bf215546Sopenharmony_ci         }
619bf215546Sopenharmony_ci
620bf215546Sopenharmony_ci         if (handleOut) {
621bf215546Sopenharmony_ci            handleOut[i] = (GLhandleARB) shProg->Shaders[i]->Name;
622bf215546Sopenharmony_ci         }
623bf215546Sopenharmony_ci      }
624bf215546Sopenharmony_ci      if (countOut) {
625bf215546Sopenharmony_ci         *countOut = i;
626bf215546Sopenharmony_ci      }
627bf215546Sopenharmony_ci   }
628bf215546Sopenharmony_ci}
629bf215546Sopenharmony_ci
630bf215546Sopenharmony_ci/**
631bf215546Sopenharmony_ci * glGetHandleARB() - return ID/name of currently bound shader program.
632bf215546Sopenharmony_ci */
633bf215546Sopenharmony_cistatic GLuint
634bf215546Sopenharmony_ciget_handle(struct gl_context *ctx, GLenum pname)
635bf215546Sopenharmony_ci{
636bf215546Sopenharmony_ci   if (pname == GL_PROGRAM_OBJECT_ARB) {
637bf215546Sopenharmony_ci      if (ctx->_Shader->ActiveProgram)
638bf215546Sopenharmony_ci         return ctx->_Shader->ActiveProgram->Name;
639bf215546Sopenharmony_ci      else
640bf215546Sopenharmony_ci         return 0;
641bf215546Sopenharmony_ci   }
642bf215546Sopenharmony_ci   else {
643bf215546Sopenharmony_ci      _mesa_error(ctx, GL_INVALID_ENUM, "glGetHandleARB");
644bf215546Sopenharmony_ci      return 0;
645bf215546Sopenharmony_ci   }
646bf215546Sopenharmony_ci}
647bf215546Sopenharmony_ci
648bf215546Sopenharmony_ci
649bf215546Sopenharmony_ci/**
650bf215546Sopenharmony_ci * Check if a geometry shader query is valid at this time.  If not, report an
651bf215546Sopenharmony_ci * error and return false.
652bf215546Sopenharmony_ci *
653bf215546Sopenharmony_ci * From GL 3.2 section 6.1.16 (Shader and Program Queries):
654bf215546Sopenharmony_ci *
655bf215546Sopenharmony_ci *     "If GEOMETRY_VERTICES_OUT, GEOMETRY_INPUT_TYPE, or GEOMETRY_OUTPUT_TYPE
656bf215546Sopenharmony_ci *     are queried for a program which has not been linked successfully, or
657bf215546Sopenharmony_ci *     which does not contain objects to form a geometry shader, then an
658bf215546Sopenharmony_ci *     INVALID_OPERATION error is generated."
659bf215546Sopenharmony_ci */
660bf215546Sopenharmony_cistatic bool
661bf215546Sopenharmony_cicheck_gs_query(struct gl_context *ctx, const struct gl_shader_program *shProg)
662bf215546Sopenharmony_ci{
663bf215546Sopenharmony_ci   if (shProg->data->LinkStatus &&
664bf215546Sopenharmony_ci       shProg->_LinkedShaders[MESA_SHADER_GEOMETRY] != NULL) {
665bf215546Sopenharmony_ci      return true;
666bf215546Sopenharmony_ci   }
667bf215546Sopenharmony_ci
668bf215546Sopenharmony_ci   _mesa_error(ctx, GL_INVALID_OPERATION,
669bf215546Sopenharmony_ci               "glGetProgramv(linked geometry shader required)");
670bf215546Sopenharmony_ci   return false;
671bf215546Sopenharmony_ci}
672bf215546Sopenharmony_ci
673bf215546Sopenharmony_ci
674bf215546Sopenharmony_ci/**
675bf215546Sopenharmony_ci * Check if a tessellation control shader query is valid at this time.
676bf215546Sopenharmony_ci * If not, report an error and return false.
677bf215546Sopenharmony_ci *
678bf215546Sopenharmony_ci * From GL 4.0 section 6.1.12 (Shader and Program Queries):
679bf215546Sopenharmony_ci *
680bf215546Sopenharmony_ci *     "If TESS_CONTROL_OUTPUT_VERTICES is queried for a program which has
681bf215546Sopenharmony_ci *     not been linked successfully, or which does not contain objects to
682bf215546Sopenharmony_ci *     form a tessellation control shader, then an INVALID_OPERATION error is
683bf215546Sopenharmony_ci *     generated."
684bf215546Sopenharmony_ci */
685bf215546Sopenharmony_cistatic bool
686bf215546Sopenharmony_cicheck_tcs_query(struct gl_context *ctx, const struct gl_shader_program *shProg)
687bf215546Sopenharmony_ci{
688bf215546Sopenharmony_ci   if (shProg->data->LinkStatus &&
689bf215546Sopenharmony_ci       shProg->_LinkedShaders[MESA_SHADER_TESS_CTRL] != NULL) {
690bf215546Sopenharmony_ci      return true;
691bf215546Sopenharmony_ci   }
692bf215546Sopenharmony_ci
693bf215546Sopenharmony_ci   _mesa_error(ctx, GL_INVALID_OPERATION,
694bf215546Sopenharmony_ci               "glGetProgramv(linked tessellation control shader required)");
695bf215546Sopenharmony_ci   return false;
696bf215546Sopenharmony_ci}
697bf215546Sopenharmony_ci
698bf215546Sopenharmony_ci
699bf215546Sopenharmony_ci/**
700bf215546Sopenharmony_ci * Check if a tessellation evaluation shader query is valid at this time.
701bf215546Sopenharmony_ci * If not, report an error and return false.
702bf215546Sopenharmony_ci *
703bf215546Sopenharmony_ci * From GL 4.0 section 6.1.12 (Shader and Program Queries):
704bf215546Sopenharmony_ci *
705bf215546Sopenharmony_ci *     "If any of the pname values in this paragraph are queried for a program
706bf215546Sopenharmony_ci *     which has not been linked successfully, or which does not contain
707bf215546Sopenharmony_ci *     objects to form a tessellation evaluation shader, then an
708bf215546Sopenharmony_ci *     INVALID_OPERATION error is generated."
709bf215546Sopenharmony_ci *
710bf215546Sopenharmony_ci */
711bf215546Sopenharmony_cistatic bool
712bf215546Sopenharmony_cicheck_tes_query(struct gl_context *ctx, const struct gl_shader_program *shProg)
713bf215546Sopenharmony_ci{
714bf215546Sopenharmony_ci   if (shProg->data->LinkStatus &&
715bf215546Sopenharmony_ci       shProg->_LinkedShaders[MESA_SHADER_TESS_EVAL] != NULL) {
716bf215546Sopenharmony_ci      return true;
717bf215546Sopenharmony_ci   }
718bf215546Sopenharmony_ci
719bf215546Sopenharmony_ci   _mesa_error(ctx, GL_INVALID_OPERATION, "glGetProgramv(linked tessellation "
720bf215546Sopenharmony_ci               "evaluation shader required)");
721bf215546Sopenharmony_ci   return false;
722bf215546Sopenharmony_ci}
723bf215546Sopenharmony_ci
724bf215546Sopenharmony_cistatic bool
725bf215546Sopenharmony_ciget_shader_program_completion_status(struct gl_context *ctx,
726bf215546Sopenharmony_ci                                     struct gl_shader_program *shprog)
727bf215546Sopenharmony_ci{
728bf215546Sopenharmony_ci   struct pipe_screen *screen = ctx->screen;
729bf215546Sopenharmony_ci
730bf215546Sopenharmony_ci   if (!screen->is_parallel_shader_compilation_finished)
731bf215546Sopenharmony_ci      return true;
732bf215546Sopenharmony_ci
733bf215546Sopenharmony_ci   for (unsigned i = 0; i < MESA_SHADER_STAGES; i++) {
734bf215546Sopenharmony_ci      struct gl_linked_shader *linked = shprog->_LinkedShaders[i];
735bf215546Sopenharmony_ci      void *sh = NULL;
736bf215546Sopenharmony_ci
737bf215546Sopenharmony_ci      if (!linked || !linked->Program)
738bf215546Sopenharmony_ci         continue;
739bf215546Sopenharmony_ci
740bf215546Sopenharmony_ci      if (linked->Program->variants)
741bf215546Sopenharmony_ci         sh = linked->Program->variants->driver_shader;
742bf215546Sopenharmony_ci
743bf215546Sopenharmony_ci      unsigned type = pipe_shader_type_from_mesa(i);
744bf215546Sopenharmony_ci
745bf215546Sopenharmony_ci      if (sh &&
746bf215546Sopenharmony_ci          !screen->is_parallel_shader_compilation_finished(screen, sh, type))
747bf215546Sopenharmony_ci         return false;
748bf215546Sopenharmony_ci   }
749bf215546Sopenharmony_ci   return true;
750bf215546Sopenharmony_ci}
751bf215546Sopenharmony_ci
752bf215546Sopenharmony_ci/**
753bf215546Sopenharmony_ci * glGetProgramiv() - get shader program state.
754bf215546Sopenharmony_ci * Note that this is for GLSL shader programs, not ARB vertex/fragment
755bf215546Sopenharmony_ci * programs (see glGetProgramivARB).
756bf215546Sopenharmony_ci */
757bf215546Sopenharmony_cistatic void
758bf215546Sopenharmony_ciget_programiv(struct gl_context *ctx, GLuint program, GLenum pname,
759bf215546Sopenharmony_ci              GLint *params)
760bf215546Sopenharmony_ci{
761bf215546Sopenharmony_ci   struct gl_shader_program *shProg
762bf215546Sopenharmony_ci      = _mesa_lookup_shader_program_err(ctx, program, "glGetProgramiv(program)");
763bf215546Sopenharmony_ci
764bf215546Sopenharmony_ci   /* Is transform feedback available in this context?
765bf215546Sopenharmony_ci    */
766bf215546Sopenharmony_ci   const bool has_xfb =
767bf215546Sopenharmony_ci      (ctx->API == API_OPENGL_COMPAT && ctx->Extensions.EXT_transform_feedback)
768bf215546Sopenharmony_ci      || ctx->API == API_OPENGL_CORE
769bf215546Sopenharmony_ci      || _mesa_is_gles3(ctx);
770bf215546Sopenharmony_ci
771bf215546Sopenharmony_ci   /* True if geometry shaders (of the form that was adopted into GLSL 1.50
772bf215546Sopenharmony_ci    * and GL 3.2) are available in this context
773bf215546Sopenharmony_ci    */
774bf215546Sopenharmony_ci   const bool has_gs = _mesa_has_geometry_shaders(ctx);
775bf215546Sopenharmony_ci   const bool has_tess = _mesa_has_tessellation(ctx);
776bf215546Sopenharmony_ci
777bf215546Sopenharmony_ci   /* Are uniform buffer objects available in this context?
778bf215546Sopenharmony_ci    */
779bf215546Sopenharmony_ci   const bool has_ubo =
780bf215546Sopenharmony_ci      (ctx->API == API_OPENGL_COMPAT &&
781bf215546Sopenharmony_ci       ctx->Extensions.ARB_uniform_buffer_object)
782bf215546Sopenharmony_ci      || ctx->API == API_OPENGL_CORE
783bf215546Sopenharmony_ci      || _mesa_is_gles3(ctx);
784bf215546Sopenharmony_ci
785bf215546Sopenharmony_ci   if (!shProg) {
786bf215546Sopenharmony_ci      return;
787bf215546Sopenharmony_ci   }
788bf215546Sopenharmony_ci
789bf215546Sopenharmony_ci   switch (pname) {
790bf215546Sopenharmony_ci   case GL_DELETE_STATUS:
791bf215546Sopenharmony_ci      *params = shProg->DeletePending;
792bf215546Sopenharmony_ci      return;
793bf215546Sopenharmony_ci   case GL_COMPLETION_STATUS_ARB:
794bf215546Sopenharmony_ci      *params = get_shader_program_completion_status(ctx, shProg);
795bf215546Sopenharmony_ci      return;
796bf215546Sopenharmony_ci   case GL_LINK_STATUS:
797bf215546Sopenharmony_ci      *params = shProg->data->LinkStatus ? GL_TRUE : GL_FALSE;
798bf215546Sopenharmony_ci      return;
799bf215546Sopenharmony_ci   case GL_VALIDATE_STATUS:
800bf215546Sopenharmony_ci      *params = shProg->data->Validated;
801bf215546Sopenharmony_ci      return;
802bf215546Sopenharmony_ci   case GL_INFO_LOG_LENGTH:
803bf215546Sopenharmony_ci      *params = (shProg->data->InfoLog && shProg->data->InfoLog[0] != '\0') ?
804bf215546Sopenharmony_ci         strlen(shProg->data->InfoLog) + 1 : 0;
805bf215546Sopenharmony_ci      return;
806bf215546Sopenharmony_ci   case GL_ATTACHED_SHADERS:
807bf215546Sopenharmony_ci      *params = shProg->NumShaders;
808bf215546Sopenharmony_ci      return;
809bf215546Sopenharmony_ci   case GL_ACTIVE_ATTRIBUTES:
810bf215546Sopenharmony_ci      *params = _mesa_count_active_attribs(shProg);
811bf215546Sopenharmony_ci      return;
812bf215546Sopenharmony_ci   case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH:
813bf215546Sopenharmony_ci      *params = _mesa_longest_attribute_name_length(shProg);
814bf215546Sopenharmony_ci      return;
815bf215546Sopenharmony_ci   case GL_ACTIVE_UNIFORMS: {
816bf215546Sopenharmony_ci      _mesa_get_program_interfaceiv(shProg, GL_UNIFORM, GL_ACTIVE_RESOURCES,
817bf215546Sopenharmony_ci                                    params);
818bf215546Sopenharmony_ci      return;
819bf215546Sopenharmony_ci   }
820bf215546Sopenharmony_ci   case GL_ACTIVE_UNIFORM_MAX_LENGTH: {
821bf215546Sopenharmony_ci      _mesa_get_program_interfaceiv(shProg, GL_UNIFORM, GL_MAX_NAME_LENGTH,
822bf215546Sopenharmony_ci                                    params);
823bf215546Sopenharmony_ci      return;
824bf215546Sopenharmony_ci   }
825bf215546Sopenharmony_ci   case GL_TRANSFORM_FEEDBACK_VARYINGS:
826bf215546Sopenharmony_ci      if (!has_xfb)
827bf215546Sopenharmony_ci         break;
828bf215546Sopenharmony_ci
829bf215546Sopenharmony_ci      /* Check first if there are transform feedback varyings specified in the
830bf215546Sopenharmony_ci       * shader (ARB_enhanced_layouts). If there isn't any, return the number of
831bf215546Sopenharmony_ci       * varyings specified using the API.
832bf215546Sopenharmony_ci       */
833bf215546Sopenharmony_ci      if (shProg->last_vert_prog &&
834bf215546Sopenharmony_ci          shProg->last_vert_prog->sh.LinkedTransformFeedback->NumVarying > 0)
835bf215546Sopenharmony_ci         *params =
836bf215546Sopenharmony_ci            shProg->last_vert_prog->sh.LinkedTransformFeedback->NumVarying;
837bf215546Sopenharmony_ci      else
838bf215546Sopenharmony_ci         *params = shProg->TransformFeedback.NumVarying;
839bf215546Sopenharmony_ci      return;
840bf215546Sopenharmony_ci   case GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH: {
841bf215546Sopenharmony_ci      if (!has_xfb)
842bf215546Sopenharmony_ci         break;
843bf215546Sopenharmony_ci
844bf215546Sopenharmony_ci      _mesa_get_program_interfaceiv(shProg, GL_TRANSFORM_FEEDBACK_VARYING,
845bf215546Sopenharmony_ci                                    GL_MAX_NAME_LENGTH, params);
846bf215546Sopenharmony_ci      return;
847bf215546Sopenharmony_ci   }
848bf215546Sopenharmony_ci   case GL_TRANSFORM_FEEDBACK_BUFFER_MODE:
849bf215546Sopenharmony_ci      if (!has_xfb)
850bf215546Sopenharmony_ci         break;
851bf215546Sopenharmony_ci      *params = shProg->TransformFeedback.BufferMode;
852bf215546Sopenharmony_ci      return;
853bf215546Sopenharmony_ci   case GL_GEOMETRY_VERTICES_OUT:
854bf215546Sopenharmony_ci      if (!has_gs)
855bf215546Sopenharmony_ci         break;
856bf215546Sopenharmony_ci      if (check_gs_query(ctx, shProg)) {
857bf215546Sopenharmony_ci         *params = shProg->_LinkedShaders[MESA_SHADER_GEOMETRY]->
858bf215546Sopenharmony_ci            Program->info.gs.vertices_out;
859bf215546Sopenharmony_ci      }
860bf215546Sopenharmony_ci      return;
861bf215546Sopenharmony_ci   case GL_GEOMETRY_SHADER_INVOCATIONS:
862bf215546Sopenharmony_ci      if (!has_gs ||
863bf215546Sopenharmony_ci          (_mesa_is_desktop_gl(ctx) && !ctx->Extensions.ARB_gpu_shader5)) {
864bf215546Sopenharmony_ci         break;
865bf215546Sopenharmony_ci      }
866bf215546Sopenharmony_ci      if (check_gs_query(ctx, shProg)) {
867bf215546Sopenharmony_ci         *params = shProg->_LinkedShaders[MESA_SHADER_GEOMETRY]->
868bf215546Sopenharmony_ci            Program->info.gs.invocations;
869bf215546Sopenharmony_ci      }
870bf215546Sopenharmony_ci      return;
871bf215546Sopenharmony_ci   case GL_GEOMETRY_INPUT_TYPE:
872bf215546Sopenharmony_ci      if (!has_gs)
873bf215546Sopenharmony_ci         break;
874bf215546Sopenharmony_ci      if (check_gs_query(ctx, shProg)) {
875bf215546Sopenharmony_ci         *params = shProg->_LinkedShaders[MESA_SHADER_GEOMETRY]->
876bf215546Sopenharmony_ci            Program->info.gs.input_primitive;
877bf215546Sopenharmony_ci      }
878bf215546Sopenharmony_ci      return;
879bf215546Sopenharmony_ci   case GL_GEOMETRY_OUTPUT_TYPE:
880bf215546Sopenharmony_ci      if (!has_gs)
881bf215546Sopenharmony_ci         break;
882bf215546Sopenharmony_ci      if (check_gs_query(ctx, shProg)) {
883bf215546Sopenharmony_ci         *params = shProg->_LinkedShaders[MESA_SHADER_GEOMETRY]->
884bf215546Sopenharmony_ci            Program->info.gs.output_primitive;
885bf215546Sopenharmony_ci      }
886bf215546Sopenharmony_ci      return;
887bf215546Sopenharmony_ci   case GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH: {
888bf215546Sopenharmony_ci      if (!has_ubo)
889bf215546Sopenharmony_ci         break;
890bf215546Sopenharmony_ci
891bf215546Sopenharmony_ci      _mesa_get_program_interfaceiv(shProg, GL_UNIFORM_BLOCK,
892bf215546Sopenharmony_ci                                    GL_MAX_NAME_LENGTH, params);
893bf215546Sopenharmony_ci      return;
894bf215546Sopenharmony_ci   }
895bf215546Sopenharmony_ci   case GL_ACTIVE_UNIFORM_BLOCKS:
896bf215546Sopenharmony_ci      if (!has_ubo)
897bf215546Sopenharmony_ci         break;
898bf215546Sopenharmony_ci
899bf215546Sopenharmony_ci      *params = shProg->data->NumUniformBlocks;
900bf215546Sopenharmony_ci      return;
901bf215546Sopenharmony_ci   case GL_PROGRAM_BINARY_RETRIEVABLE_HINT:
902bf215546Sopenharmony_ci      /* This enum isn't part of the OES extension for OpenGL ES 2.0.  It is
903bf215546Sopenharmony_ci       * only available with desktop OpenGL 3.0+ with the
904bf215546Sopenharmony_ci       * GL_ARB_get_program_binary extension or OpenGL ES 3.0.
905bf215546Sopenharmony_ci       *
906bf215546Sopenharmony_ci       * On desktop, we ignore the 3.0+ requirement because it is silly.
907bf215546Sopenharmony_ci       */
908bf215546Sopenharmony_ci      if (!_mesa_is_desktop_gl(ctx) && !_mesa_is_gles3(ctx))
909bf215546Sopenharmony_ci         break;
910bf215546Sopenharmony_ci
911bf215546Sopenharmony_ci      *params = shProg->BinaryRetrievableHint;
912bf215546Sopenharmony_ci      return;
913bf215546Sopenharmony_ci   case GL_PROGRAM_BINARY_LENGTH:
914bf215546Sopenharmony_ci      if (ctx->Const.NumProgramBinaryFormats == 0 || !shProg->data->LinkStatus) {
915bf215546Sopenharmony_ci         *params = 0;
916bf215546Sopenharmony_ci      } else {
917bf215546Sopenharmony_ci         _mesa_get_program_binary_length(ctx, shProg, params);
918bf215546Sopenharmony_ci      }
919bf215546Sopenharmony_ci      return;
920bf215546Sopenharmony_ci   case GL_ACTIVE_ATOMIC_COUNTER_BUFFERS:
921bf215546Sopenharmony_ci      if (!ctx->Extensions.ARB_shader_atomic_counters && !_mesa_is_gles31(ctx))
922bf215546Sopenharmony_ci         break;
923bf215546Sopenharmony_ci
924bf215546Sopenharmony_ci      *params = shProg->data->NumAtomicBuffers;
925bf215546Sopenharmony_ci      return;
926bf215546Sopenharmony_ci   case GL_COMPUTE_WORK_GROUP_SIZE: {
927bf215546Sopenharmony_ci      int i;
928bf215546Sopenharmony_ci      if (!_mesa_has_compute_shaders(ctx))
929bf215546Sopenharmony_ci         break;
930bf215546Sopenharmony_ci      if (!shProg->data->LinkStatus) {
931bf215546Sopenharmony_ci         _mesa_error(ctx, GL_INVALID_OPERATION, "glGetProgramiv(program not "
932bf215546Sopenharmony_ci                     "linked)");
933bf215546Sopenharmony_ci         return;
934bf215546Sopenharmony_ci      }
935bf215546Sopenharmony_ci      if (shProg->_LinkedShaders[MESA_SHADER_COMPUTE] == NULL) {
936bf215546Sopenharmony_ci         _mesa_error(ctx, GL_INVALID_OPERATION, "glGetProgramiv(no compute "
937bf215546Sopenharmony_ci                     "shaders)");
938bf215546Sopenharmony_ci         return;
939bf215546Sopenharmony_ci      }
940bf215546Sopenharmony_ci      for (i = 0; i < 3; i++)
941bf215546Sopenharmony_ci         params[i] = shProg->_LinkedShaders[MESA_SHADER_COMPUTE]->
942bf215546Sopenharmony_ci            Program->info.workgroup_size[i];
943bf215546Sopenharmony_ci      return;
944bf215546Sopenharmony_ci   }
945bf215546Sopenharmony_ci   case GL_PROGRAM_SEPARABLE:
946bf215546Sopenharmony_ci      /* If the program has not been linked, return initial value 0. */
947bf215546Sopenharmony_ci      *params = (shProg->data->LinkStatus == LINKING_FAILURE) ? 0 : shProg->SeparateShader;
948bf215546Sopenharmony_ci      return;
949bf215546Sopenharmony_ci
950bf215546Sopenharmony_ci   /* ARB_tessellation_shader */
951bf215546Sopenharmony_ci   case GL_TESS_CONTROL_OUTPUT_VERTICES:
952bf215546Sopenharmony_ci      if (!has_tess)
953bf215546Sopenharmony_ci         break;
954bf215546Sopenharmony_ci      if (check_tcs_query(ctx, shProg)) {
955bf215546Sopenharmony_ci         *params = shProg->_LinkedShaders[MESA_SHADER_TESS_CTRL]->
956bf215546Sopenharmony_ci            Program->info.tess.tcs_vertices_out;
957bf215546Sopenharmony_ci      }
958bf215546Sopenharmony_ci      return;
959bf215546Sopenharmony_ci   case GL_TESS_GEN_MODE:
960bf215546Sopenharmony_ci      if (!has_tess)
961bf215546Sopenharmony_ci         break;
962bf215546Sopenharmony_ci      if (check_tes_query(ctx, shProg)) {
963bf215546Sopenharmony_ci         const struct gl_linked_shader *tes =
964bf215546Sopenharmony_ci            shProg->_LinkedShaders[MESA_SHADER_TESS_EVAL];
965bf215546Sopenharmony_ci         switch (tes->Program->info.tess._primitive_mode) {
966bf215546Sopenharmony_ci         case TESS_PRIMITIVE_TRIANGLES:
967bf215546Sopenharmony_ci            *params = GL_TRIANGLES;
968bf215546Sopenharmony_ci            break;
969bf215546Sopenharmony_ci         case TESS_PRIMITIVE_QUADS:
970bf215546Sopenharmony_ci            *params = GL_QUADS;
971bf215546Sopenharmony_ci            break;
972bf215546Sopenharmony_ci         case TESS_PRIMITIVE_ISOLINES:
973bf215546Sopenharmony_ci            *params = GL_ISOLINES;
974bf215546Sopenharmony_ci            break;
975bf215546Sopenharmony_ci         case TESS_PRIMITIVE_UNSPECIFIED:
976bf215546Sopenharmony_ci            *params = 0;
977bf215546Sopenharmony_ci            break;
978bf215546Sopenharmony_ci         }
979bf215546Sopenharmony_ci      }
980bf215546Sopenharmony_ci      return;
981bf215546Sopenharmony_ci   case GL_TESS_GEN_SPACING:
982bf215546Sopenharmony_ci      if (!has_tess)
983bf215546Sopenharmony_ci         break;
984bf215546Sopenharmony_ci      if (check_tes_query(ctx, shProg)) {
985bf215546Sopenharmony_ci         const struct gl_linked_shader *tes =
986bf215546Sopenharmony_ci            shProg->_LinkedShaders[MESA_SHADER_TESS_EVAL];
987bf215546Sopenharmony_ci         switch (tes->Program->info.tess.spacing) {
988bf215546Sopenharmony_ci         case TESS_SPACING_EQUAL:
989bf215546Sopenharmony_ci            *params = GL_EQUAL;
990bf215546Sopenharmony_ci            break;
991bf215546Sopenharmony_ci         case TESS_SPACING_FRACTIONAL_ODD:
992bf215546Sopenharmony_ci            *params = GL_FRACTIONAL_ODD;
993bf215546Sopenharmony_ci            break;
994bf215546Sopenharmony_ci         case TESS_SPACING_FRACTIONAL_EVEN:
995bf215546Sopenharmony_ci            *params = GL_FRACTIONAL_EVEN;
996bf215546Sopenharmony_ci            break;
997bf215546Sopenharmony_ci         case TESS_SPACING_UNSPECIFIED:
998bf215546Sopenharmony_ci            *params = 0;
999bf215546Sopenharmony_ci            break;
1000bf215546Sopenharmony_ci         }
1001bf215546Sopenharmony_ci      }
1002bf215546Sopenharmony_ci      return;
1003bf215546Sopenharmony_ci   case GL_TESS_GEN_VERTEX_ORDER:
1004bf215546Sopenharmony_ci      if (!has_tess)
1005bf215546Sopenharmony_ci         break;
1006bf215546Sopenharmony_ci      if (check_tes_query(ctx, shProg)) {
1007bf215546Sopenharmony_ci         *params = shProg->_LinkedShaders[MESA_SHADER_TESS_EVAL]->
1008bf215546Sopenharmony_ci            Program->info.tess.ccw ? GL_CCW : GL_CW;
1009bf215546Sopenharmony_ci         }
1010bf215546Sopenharmony_ci      return;
1011bf215546Sopenharmony_ci   case GL_TESS_GEN_POINT_MODE:
1012bf215546Sopenharmony_ci      if (!has_tess)
1013bf215546Sopenharmony_ci         break;
1014bf215546Sopenharmony_ci      if (check_tes_query(ctx, shProg)) {
1015bf215546Sopenharmony_ci         *params = shProg->_LinkedShaders[MESA_SHADER_TESS_EVAL]->
1016bf215546Sopenharmony_ci            Program->info.tess.point_mode ? GL_TRUE : GL_FALSE;
1017bf215546Sopenharmony_ci      }
1018bf215546Sopenharmony_ci      return;
1019bf215546Sopenharmony_ci   default:
1020bf215546Sopenharmony_ci      break;
1021bf215546Sopenharmony_ci   }
1022bf215546Sopenharmony_ci
1023bf215546Sopenharmony_ci   _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramiv(pname=%s)",
1024bf215546Sopenharmony_ci               _mesa_enum_to_string(pname));
1025bf215546Sopenharmony_ci}
1026bf215546Sopenharmony_ci
1027bf215546Sopenharmony_ci
1028bf215546Sopenharmony_ci/**
1029bf215546Sopenharmony_ci * glGetShaderiv() - get GLSL shader state
1030bf215546Sopenharmony_ci */
1031bf215546Sopenharmony_cistatic void
1032bf215546Sopenharmony_ciget_shaderiv(struct gl_context *ctx, GLuint name, GLenum pname, GLint *params)
1033bf215546Sopenharmony_ci{
1034bf215546Sopenharmony_ci   struct gl_shader *shader =
1035bf215546Sopenharmony_ci      _mesa_lookup_shader_err(ctx, name, "glGetShaderiv");
1036bf215546Sopenharmony_ci
1037bf215546Sopenharmony_ci   if (!shader) {
1038bf215546Sopenharmony_ci      return;
1039bf215546Sopenharmony_ci   }
1040bf215546Sopenharmony_ci
1041bf215546Sopenharmony_ci   switch (pname) {
1042bf215546Sopenharmony_ci   case GL_SHADER_TYPE:
1043bf215546Sopenharmony_ci      *params = shader->Type;
1044bf215546Sopenharmony_ci      break;
1045bf215546Sopenharmony_ci   case GL_DELETE_STATUS:
1046bf215546Sopenharmony_ci      *params = shader->DeletePending;
1047bf215546Sopenharmony_ci      break;
1048bf215546Sopenharmony_ci   case GL_COMPLETION_STATUS_ARB:
1049bf215546Sopenharmony_ci      /* _mesa_glsl_compile_shader is not offloaded to other threads. */
1050bf215546Sopenharmony_ci      *params = GL_TRUE;
1051bf215546Sopenharmony_ci      return;
1052bf215546Sopenharmony_ci   case GL_COMPILE_STATUS:
1053bf215546Sopenharmony_ci      *params = shader->CompileStatus ? GL_TRUE : GL_FALSE;
1054bf215546Sopenharmony_ci      break;
1055bf215546Sopenharmony_ci   case GL_INFO_LOG_LENGTH:
1056bf215546Sopenharmony_ci      *params = (shader->InfoLog && shader->InfoLog[0] != '\0') ?
1057bf215546Sopenharmony_ci         strlen(shader->InfoLog) + 1 : 0;
1058bf215546Sopenharmony_ci      break;
1059bf215546Sopenharmony_ci   case GL_SHADER_SOURCE_LENGTH:
1060bf215546Sopenharmony_ci      *params = shader->Source ? strlen((char *) shader->Source) + 1 : 0;
1061bf215546Sopenharmony_ci      break;
1062bf215546Sopenharmony_ci   case GL_SPIR_V_BINARY_ARB:
1063bf215546Sopenharmony_ci      *params = (shader->spirv_data != NULL);
1064bf215546Sopenharmony_ci      break;
1065bf215546Sopenharmony_ci   default:
1066bf215546Sopenharmony_ci      _mesa_error(ctx, GL_INVALID_ENUM, "glGetShaderiv(pname)");
1067bf215546Sopenharmony_ci      return;
1068bf215546Sopenharmony_ci   }
1069bf215546Sopenharmony_ci}
1070bf215546Sopenharmony_ci
1071bf215546Sopenharmony_ci
1072bf215546Sopenharmony_cistatic void
1073bf215546Sopenharmony_ciget_program_info_log(struct gl_context *ctx, GLuint program, GLsizei bufSize,
1074bf215546Sopenharmony_ci                     GLsizei *length, GLchar *infoLog)
1075bf215546Sopenharmony_ci{
1076bf215546Sopenharmony_ci   struct gl_shader_program *shProg;
1077bf215546Sopenharmony_ci
1078bf215546Sopenharmony_ci   /* Section 2.5 GL Errors (page 18) of the OpenGL ES 3.0.4 spec and
1079bf215546Sopenharmony_ci    * section 2.3.1 (Errors) of the OpenGL 4.5 spec say:
1080bf215546Sopenharmony_ci    *
1081bf215546Sopenharmony_ci    *     "If a negative number is provided where an argument of type sizei or
1082bf215546Sopenharmony_ci    *     sizeiptr is specified, an INVALID_VALUE error is generated."
1083bf215546Sopenharmony_ci    */
1084bf215546Sopenharmony_ci   if (bufSize < 0) {
1085bf215546Sopenharmony_ci      _mesa_error(ctx, GL_INVALID_VALUE, "glGetProgramInfoLog(bufSize < 0)");
1086bf215546Sopenharmony_ci      return;
1087bf215546Sopenharmony_ci   }
1088bf215546Sopenharmony_ci
1089bf215546Sopenharmony_ci   shProg = _mesa_lookup_shader_program_err(ctx, program,
1090bf215546Sopenharmony_ci                                            "glGetProgramInfoLog(program)");
1091bf215546Sopenharmony_ci   if (!shProg) {
1092bf215546Sopenharmony_ci      return;
1093bf215546Sopenharmony_ci   }
1094bf215546Sopenharmony_ci
1095bf215546Sopenharmony_ci   _mesa_copy_string(infoLog, bufSize, length, shProg->data->InfoLog);
1096bf215546Sopenharmony_ci}
1097bf215546Sopenharmony_ci
1098bf215546Sopenharmony_ci
1099bf215546Sopenharmony_cistatic void
1100bf215546Sopenharmony_ciget_shader_info_log(struct gl_context *ctx, GLuint shader, GLsizei bufSize,
1101bf215546Sopenharmony_ci                    GLsizei *length, GLchar *infoLog)
1102bf215546Sopenharmony_ci{
1103bf215546Sopenharmony_ci   struct gl_shader *sh;
1104bf215546Sopenharmony_ci
1105bf215546Sopenharmony_ci   /* Section 2.5 GL Errors (page 18) of the OpenGL ES 3.0.4 spec and
1106bf215546Sopenharmony_ci    * section 2.3.1 (Errors) of the OpenGL 4.5 spec say:
1107bf215546Sopenharmony_ci    *
1108bf215546Sopenharmony_ci    *     "If a negative number is provided where an argument of type sizei or
1109bf215546Sopenharmony_ci    *     sizeiptr is specified, an INVALID_VALUE error is generated."
1110bf215546Sopenharmony_ci    */
1111bf215546Sopenharmony_ci   if (bufSize < 0) {
1112bf215546Sopenharmony_ci      _mesa_error(ctx, GL_INVALID_VALUE, "glGetShaderInfoLog(bufSize < 0)");
1113bf215546Sopenharmony_ci      return;
1114bf215546Sopenharmony_ci   }
1115bf215546Sopenharmony_ci
1116bf215546Sopenharmony_ci   sh = _mesa_lookup_shader_err(ctx, shader, "glGetShaderInfoLog(shader)");
1117bf215546Sopenharmony_ci   if (!sh) {
1118bf215546Sopenharmony_ci      return;
1119bf215546Sopenharmony_ci   }
1120bf215546Sopenharmony_ci
1121bf215546Sopenharmony_ci   _mesa_copy_string(infoLog, bufSize, length, sh->InfoLog);
1122bf215546Sopenharmony_ci}
1123bf215546Sopenharmony_ci
1124bf215546Sopenharmony_ci
1125bf215546Sopenharmony_ci/**
1126bf215546Sopenharmony_ci * Return shader source code.
1127bf215546Sopenharmony_ci */
1128bf215546Sopenharmony_cistatic void
1129bf215546Sopenharmony_ciget_shader_source(struct gl_context *ctx, GLuint shader, GLsizei maxLength,
1130bf215546Sopenharmony_ci                  GLsizei *length, GLchar *sourceOut)
1131bf215546Sopenharmony_ci{
1132bf215546Sopenharmony_ci   struct gl_shader *sh;
1133bf215546Sopenharmony_ci
1134bf215546Sopenharmony_ci   if (maxLength < 0) {
1135bf215546Sopenharmony_ci      _mesa_error(ctx, GL_INVALID_VALUE, "glGetShaderSource(bufSize < 0)");
1136bf215546Sopenharmony_ci      return;
1137bf215546Sopenharmony_ci   }
1138bf215546Sopenharmony_ci
1139bf215546Sopenharmony_ci   sh = _mesa_lookup_shader_err(ctx, shader, "glGetShaderSource");
1140bf215546Sopenharmony_ci   if (!sh) {
1141bf215546Sopenharmony_ci      return;
1142bf215546Sopenharmony_ci   }
1143bf215546Sopenharmony_ci   _mesa_copy_string(sourceOut, maxLength, length, sh->Source);
1144bf215546Sopenharmony_ci}
1145bf215546Sopenharmony_ci
1146bf215546Sopenharmony_ci
1147bf215546Sopenharmony_ci/**
1148bf215546Sopenharmony_ci * Set/replace shader source code.  A helper function used by
1149bf215546Sopenharmony_ci * glShaderSource[ARB].
1150bf215546Sopenharmony_ci */
1151bf215546Sopenharmony_cistatic void
1152bf215546Sopenharmony_ciset_shader_source(struct gl_shader *sh, const GLchar *source,
1153bf215546Sopenharmony_ci                  const uint8_t original_sha1[SHA1_DIGEST_LENGTH])
1154bf215546Sopenharmony_ci{
1155bf215546Sopenharmony_ci   assert(sh);
1156bf215546Sopenharmony_ci
1157bf215546Sopenharmony_ci   /* The GL_ARB_gl_spirv spec adds the following to the end of the description
1158bf215546Sopenharmony_ci    * of ShaderSource:
1159bf215546Sopenharmony_ci    *
1160bf215546Sopenharmony_ci    *   "If <shader> was previously associated with a SPIR-V module (via the
1161bf215546Sopenharmony_ci    *    ShaderBinary command), that association is broken. Upon successful
1162bf215546Sopenharmony_ci    *    completion of this command the SPIR_V_BINARY_ARB state of <shader>
1163bf215546Sopenharmony_ci    *    is set to FALSE."
1164bf215546Sopenharmony_ci    */
1165bf215546Sopenharmony_ci   _mesa_shader_spirv_data_reference(&sh->spirv_data, NULL);
1166bf215546Sopenharmony_ci
1167bf215546Sopenharmony_ci   if (sh->CompileStatus == COMPILE_SKIPPED && !sh->FallbackSource) {
1168bf215546Sopenharmony_ci      /* If shader was previously compiled back-up the source in case of cache
1169bf215546Sopenharmony_ci       * fallback.
1170bf215546Sopenharmony_ci       */
1171bf215546Sopenharmony_ci      sh->FallbackSource = sh->Source;
1172bf215546Sopenharmony_ci      memcpy(sh->fallback_source_sha1, sh->source_sha1, SHA1_DIGEST_LENGTH);
1173bf215546Sopenharmony_ci      sh->Source = source;
1174bf215546Sopenharmony_ci   } else {
1175bf215546Sopenharmony_ci      /* free old shader source string and install new one */
1176bf215546Sopenharmony_ci      free((void *)sh->Source);
1177bf215546Sopenharmony_ci      sh->Source = source;
1178bf215546Sopenharmony_ci   }
1179bf215546Sopenharmony_ci
1180bf215546Sopenharmony_ci   memcpy(sh->source_sha1, original_sha1, SHA1_DIGEST_LENGTH);
1181bf215546Sopenharmony_ci}
1182bf215546Sopenharmony_ci
1183bf215546Sopenharmony_cistatic void
1184bf215546Sopenharmony_ciensure_builtin_types(struct gl_context *ctx)
1185bf215546Sopenharmony_ci{
1186bf215546Sopenharmony_ci   if (!ctx->shader_builtin_ref) {
1187bf215546Sopenharmony_ci      _mesa_glsl_builtin_functions_init_or_ref();
1188bf215546Sopenharmony_ci      ctx->shader_builtin_ref = true;
1189bf215546Sopenharmony_ci   }
1190bf215546Sopenharmony_ci}
1191bf215546Sopenharmony_ci
1192bf215546Sopenharmony_ci/**
1193bf215546Sopenharmony_ci * Compile a shader.
1194bf215546Sopenharmony_ci */
1195bf215546Sopenharmony_civoid
1196bf215546Sopenharmony_ci_mesa_compile_shader(struct gl_context *ctx, struct gl_shader *sh)
1197bf215546Sopenharmony_ci{
1198bf215546Sopenharmony_ci   if (!sh)
1199bf215546Sopenharmony_ci      return;
1200bf215546Sopenharmony_ci
1201bf215546Sopenharmony_ci   /* The GL_ARB_gl_spirv spec says:
1202bf215546Sopenharmony_ci    *
1203bf215546Sopenharmony_ci    *    "Add a new error for the CompileShader command:
1204bf215546Sopenharmony_ci    *
1205bf215546Sopenharmony_ci    *      An INVALID_OPERATION error is generated if the SPIR_V_BINARY_ARB
1206bf215546Sopenharmony_ci    *      state of <shader> is TRUE."
1207bf215546Sopenharmony_ci    */
1208bf215546Sopenharmony_ci   if (sh->spirv_data) {
1209bf215546Sopenharmony_ci      _mesa_error(ctx, GL_INVALID_OPERATION, "glCompileShader(SPIR-V)");
1210bf215546Sopenharmony_ci      return;
1211bf215546Sopenharmony_ci   }
1212bf215546Sopenharmony_ci
1213bf215546Sopenharmony_ci   if (!sh->Source) {
1214bf215546Sopenharmony_ci      /* If the user called glCompileShader without first calling
1215bf215546Sopenharmony_ci       * glShaderSource, we should fail to compile, but not raise a GL_ERROR.
1216bf215546Sopenharmony_ci       */
1217bf215546Sopenharmony_ci      sh->CompileStatus = COMPILE_FAILURE;
1218bf215546Sopenharmony_ci   } else {
1219bf215546Sopenharmony_ci      if (ctx->_Shader->Flags & GLSL_DUMP) {
1220bf215546Sopenharmony_ci         _mesa_log("GLSL source for %s shader %d:\n",
1221bf215546Sopenharmony_ci                 _mesa_shader_stage_to_string(sh->Stage), sh->Name);
1222bf215546Sopenharmony_ci         _mesa_log_direct(sh->Source);
1223bf215546Sopenharmony_ci      }
1224bf215546Sopenharmony_ci
1225bf215546Sopenharmony_ci      ensure_builtin_types(ctx);
1226bf215546Sopenharmony_ci
1227bf215546Sopenharmony_ci      /* this call will set the shader->CompileStatus field to indicate if
1228bf215546Sopenharmony_ci       * compilation was successful.
1229bf215546Sopenharmony_ci       */
1230bf215546Sopenharmony_ci      _mesa_glsl_compile_shader(ctx, sh, false, false, false);
1231bf215546Sopenharmony_ci
1232bf215546Sopenharmony_ci      if (ctx->_Shader->Flags & GLSL_LOG) {
1233bf215546Sopenharmony_ci         _mesa_write_shader_to_file(sh);
1234bf215546Sopenharmony_ci      }
1235bf215546Sopenharmony_ci
1236bf215546Sopenharmony_ci      if (ctx->_Shader->Flags & GLSL_DUMP) {
1237bf215546Sopenharmony_ci         if (sh->CompileStatus) {
1238bf215546Sopenharmony_ci            if (sh->ir) {
1239bf215546Sopenharmony_ci               _mesa_log("GLSL IR for shader %d:\n", sh->Name);
1240bf215546Sopenharmony_ci               _mesa_print_ir(_mesa_get_log_file(), sh->ir, NULL);
1241bf215546Sopenharmony_ci            } else {
1242bf215546Sopenharmony_ci               _mesa_log("No GLSL IR for shader %d (shader may be from "
1243bf215546Sopenharmony_ci                         "cache)\n", sh->Name);
1244bf215546Sopenharmony_ci            }
1245bf215546Sopenharmony_ci            _mesa_log("\n\n");
1246bf215546Sopenharmony_ci         } else {
1247bf215546Sopenharmony_ci            _mesa_log("GLSL shader %d failed to compile.\n", sh->Name);
1248bf215546Sopenharmony_ci         }
1249bf215546Sopenharmony_ci         if (sh->InfoLog && sh->InfoLog[0] != 0) {
1250bf215546Sopenharmony_ci            _mesa_log("GLSL shader %d info log:\n", sh->Name);
1251bf215546Sopenharmony_ci            _mesa_log("%s\n", sh->InfoLog);
1252bf215546Sopenharmony_ci         }
1253bf215546Sopenharmony_ci      }
1254bf215546Sopenharmony_ci   }
1255bf215546Sopenharmony_ci
1256bf215546Sopenharmony_ci   if (!sh->CompileStatus) {
1257bf215546Sopenharmony_ci      if (ctx->_Shader->Flags & GLSL_DUMP_ON_ERROR) {
1258bf215546Sopenharmony_ci         _mesa_log("GLSL source for %s shader %d:\n",
1259bf215546Sopenharmony_ci                 _mesa_shader_stage_to_string(sh->Stage), sh->Name);
1260bf215546Sopenharmony_ci         _mesa_log("%s\n", sh->Source);
1261bf215546Sopenharmony_ci         _mesa_log("Info Log:\n%s\n", sh->InfoLog);
1262bf215546Sopenharmony_ci      }
1263bf215546Sopenharmony_ci
1264bf215546Sopenharmony_ci      if (ctx->_Shader->Flags & GLSL_REPORT_ERRORS) {
1265bf215546Sopenharmony_ci         _mesa_debug(ctx, "Error compiling shader %u:\n%s\n",
1266bf215546Sopenharmony_ci                     sh->Name, sh->InfoLog);
1267bf215546Sopenharmony_ci      }
1268bf215546Sopenharmony_ci   }
1269bf215546Sopenharmony_ci}
1270bf215546Sopenharmony_ci
1271bf215546Sopenharmony_ci
1272bf215546Sopenharmony_cistruct update_programs_in_pipeline_params
1273bf215546Sopenharmony_ci{
1274bf215546Sopenharmony_ci   struct gl_context *ctx;
1275bf215546Sopenharmony_ci   struct gl_shader_program *shProg;
1276bf215546Sopenharmony_ci};
1277bf215546Sopenharmony_ci
1278bf215546Sopenharmony_cistatic void
1279bf215546Sopenharmony_ciupdate_programs_in_pipeline(void *data, void *userData)
1280bf215546Sopenharmony_ci{
1281bf215546Sopenharmony_ci   struct update_programs_in_pipeline_params *params =
1282bf215546Sopenharmony_ci      (struct update_programs_in_pipeline_params *) userData;
1283bf215546Sopenharmony_ci   struct gl_pipeline_object *obj = (struct gl_pipeline_object *) data;
1284bf215546Sopenharmony_ci
1285bf215546Sopenharmony_ci   for (unsigned stage = 0; stage < MESA_SHADER_STAGES; stage++) {
1286bf215546Sopenharmony_ci      if (obj->CurrentProgram[stage] &&
1287bf215546Sopenharmony_ci          obj->CurrentProgram[stage]->Id == params->shProg->Name) {
1288bf215546Sopenharmony_ci         struct gl_program *prog = params->shProg->_LinkedShaders[stage]->Program;
1289bf215546Sopenharmony_ci         _mesa_use_program(params->ctx, stage, params->shProg, prog, obj);
1290bf215546Sopenharmony_ci      }
1291bf215546Sopenharmony_ci   }
1292bf215546Sopenharmony_ci}
1293bf215546Sopenharmony_ci
1294bf215546Sopenharmony_ci
1295bf215546Sopenharmony_ci/**
1296bf215546Sopenharmony_ci * Link a program's shaders.
1297bf215546Sopenharmony_ci */
1298bf215546Sopenharmony_cistatic ALWAYS_INLINE void
1299bf215546Sopenharmony_cilink_program(struct gl_context *ctx, struct gl_shader_program *shProg,
1300bf215546Sopenharmony_ci             bool no_error)
1301bf215546Sopenharmony_ci{
1302bf215546Sopenharmony_ci   if (!shProg)
1303bf215546Sopenharmony_ci      return;
1304bf215546Sopenharmony_ci
1305bf215546Sopenharmony_ci   if (!no_error) {
1306bf215546Sopenharmony_ci      /* From the ARB_transform_feedback2 specification:
1307bf215546Sopenharmony_ci       * "The error INVALID_OPERATION is generated by LinkProgram if <program>
1308bf215546Sopenharmony_ci       * is the name of a program being used by one or more transform feedback
1309bf215546Sopenharmony_ci       * objects, even if the objects are not currently bound or are paused."
1310bf215546Sopenharmony_ci       */
1311bf215546Sopenharmony_ci      if (_mesa_transform_feedback_is_using_program(ctx, shProg)) {
1312bf215546Sopenharmony_ci         _mesa_error(ctx, GL_INVALID_OPERATION,
1313bf215546Sopenharmony_ci                     "glLinkProgram(transform feedback is using the program)");
1314bf215546Sopenharmony_ci         return;
1315bf215546Sopenharmony_ci      }
1316bf215546Sopenharmony_ci   }
1317bf215546Sopenharmony_ci
1318bf215546Sopenharmony_ci   unsigned programs_in_use = 0;
1319bf215546Sopenharmony_ci   if (ctx->_Shader)
1320bf215546Sopenharmony_ci      for (unsigned stage = 0; stage < MESA_SHADER_STAGES; stage++) {
1321bf215546Sopenharmony_ci         if (ctx->_Shader->CurrentProgram[stage] &&
1322bf215546Sopenharmony_ci             ctx->_Shader->CurrentProgram[stage]->Id == shProg->Name) {
1323bf215546Sopenharmony_ci            programs_in_use |= 1 << stage;
1324bf215546Sopenharmony_ci         }
1325bf215546Sopenharmony_ci      }
1326bf215546Sopenharmony_ci
1327bf215546Sopenharmony_ci   ensure_builtin_types(ctx);
1328bf215546Sopenharmony_ci
1329bf215546Sopenharmony_ci   FLUSH_VERTICES(ctx, 0, 0);
1330bf215546Sopenharmony_ci   _mesa_glsl_link_shader(ctx, shProg);
1331bf215546Sopenharmony_ci
1332bf215546Sopenharmony_ci   /* From section 7.3 (Program Objects) of the OpenGL 4.5 spec:
1333bf215546Sopenharmony_ci    *
1334bf215546Sopenharmony_ci    *    "If LinkProgram or ProgramBinary successfully re-links a program
1335bf215546Sopenharmony_ci    *     object that is active for any shader stage, then the newly generated
1336bf215546Sopenharmony_ci    *     executable code will be installed as part of the current rendering
1337bf215546Sopenharmony_ci    *     state for all shader stages where the program is active.
1338bf215546Sopenharmony_ci    *     Additionally, the newly generated executable code is made part of
1339bf215546Sopenharmony_ci    *     the state of any program pipeline for all stages where the program
1340bf215546Sopenharmony_ci    *     is attached."
1341bf215546Sopenharmony_ci    */
1342bf215546Sopenharmony_ci   if (shProg->data->LinkStatus) {
1343bf215546Sopenharmony_ci      while (programs_in_use) {
1344bf215546Sopenharmony_ci         const int stage = u_bit_scan(&programs_in_use);
1345bf215546Sopenharmony_ci
1346bf215546Sopenharmony_ci         struct gl_program *prog = NULL;
1347bf215546Sopenharmony_ci         if (shProg->_LinkedShaders[stage])
1348bf215546Sopenharmony_ci            prog = shProg->_LinkedShaders[stage]->Program;
1349bf215546Sopenharmony_ci
1350bf215546Sopenharmony_ci         _mesa_use_program(ctx, stage, shProg, prog, ctx->_Shader);
1351bf215546Sopenharmony_ci      }
1352bf215546Sopenharmony_ci
1353bf215546Sopenharmony_ci      if (ctx->Pipeline.Objects) {
1354bf215546Sopenharmony_ci         struct update_programs_in_pipeline_params params = {
1355bf215546Sopenharmony_ci            .ctx = ctx,
1356bf215546Sopenharmony_ci            .shProg = shProg
1357bf215546Sopenharmony_ci         };
1358bf215546Sopenharmony_ci         _mesa_HashWalk(ctx->Pipeline.Objects, update_programs_in_pipeline,
1359bf215546Sopenharmony_ci                        &params);
1360bf215546Sopenharmony_ci      }
1361bf215546Sopenharmony_ci   }
1362bf215546Sopenharmony_ci
1363bf215546Sopenharmony_ci#ifndef CUSTOM_SHADER_REPLACEMENT
1364bf215546Sopenharmony_ci   /* Capture .shader_test files. */
1365bf215546Sopenharmony_ci   const char *capture_path = _mesa_get_shader_capture_path();
1366bf215546Sopenharmony_ci   if (shProg->Name != 0 && shProg->Name != ~0 && capture_path != NULL) {
1367bf215546Sopenharmony_ci      /* Find an unused filename. */
1368bf215546Sopenharmony_ci      FILE *file = NULL;
1369bf215546Sopenharmony_ci      char *filename = NULL;
1370bf215546Sopenharmony_ci      for (unsigned i = 0;; i++) {
1371bf215546Sopenharmony_ci         if (i) {
1372bf215546Sopenharmony_ci            filename = ralloc_asprintf(NULL, "%s/%u-%u.shader_test",
1373bf215546Sopenharmony_ci                                       capture_path, shProg->Name, i);
1374bf215546Sopenharmony_ci         } else {
1375bf215546Sopenharmony_ci            filename = ralloc_asprintf(NULL, "%s/%u.shader_test",
1376bf215546Sopenharmony_ci                                       capture_path, shProg->Name);
1377bf215546Sopenharmony_ci         }
1378bf215546Sopenharmony_ci         file = os_file_create_unique(filename, 0644);
1379bf215546Sopenharmony_ci         if (file)
1380bf215546Sopenharmony_ci            break;
1381bf215546Sopenharmony_ci         /* If we are failing for another reason than "this filename already
1382bf215546Sopenharmony_ci          * exists", we are likely to fail again with another filename, so
1383bf215546Sopenharmony_ci          * let's just give up */
1384bf215546Sopenharmony_ci         if (errno != EEXIST)
1385bf215546Sopenharmony_ci            break;
1386bf215546Sopenharmony_ci         ralloc_free(filename);
1387bf215546Sopenharmony_ci      }
1388bf215546Sopenharmony_ci      if (file) {
1389bf215546Sopenharmony_ci         fprintf(file, "[require]\nGLSL%s >= %u.%02u\n",
1390bf215546Sopenharmony_ci                 shProg->IsES ? " ES" : "",
1391bf215546Sopenharmony_ci                 shProg->data->Version / 100, shProg->data->Version % 100);
1392bf215546Sopenharmony_ci         if (shProg->SeparateShader)
1393bf215546Sopenharmony_ci            fprintf(file, "GL_ARB_separate_shader_objects\nSSO ENABLED\n");
1394bf215546Sopenharmony_ci         fprintf(file, "\n");
1395bf215546Sopenharmony_ci
1396bf215546Sopenharmony_ci         for (unsigned i = 0; i < shProg->NumShaders; i++) {
1397bf215546Sopenharmony_ci            fprintf(file, "[%s shader]\n%s\n",
1398bf215546Sopenharmony_ci                    _mesa_shader_stage_to_string(shProg->Shaders[i]->Stage),
1399bf215546Sopenharmony_ci                    shProg->Shaders[i]->Source);
1400bf215546Sopenharmony_ci         }
1401bf215546Sopenharmony_ci         fclose(file);
1402bf215546Sopenharmony_ci      } else {
1403bf215546Sopenharmony_ci         _mesa_warning(ctx, "Failed to open %s", filename);
1404bf215546Sopenharmony_ci      }
1405bf215546Sopenharmony_ci
1406bf215546Sopenharmony_ci      ralloc_free(filename);
1407bf215546Sopenharmony_ci   }
1408bf215546Sopenharmony_ci#endif
1409bf215546Sopenharmony_ci
1410bf215546Sopenharmony_ci   if (shProg->data->LinkStatus == LINKING_FAILURE &&
1411bf215546Sopenharmony_ci       (ctx->_Shader->Flags & GLSL_REPORT_ERRORS)) {
1412bf215546Sopenharmony_ci      _mesa_debug(ctx, "Error linking program %u:\n%s\n",
1413bf215546Sopenharmony_ci                  shProg->Name, shProg->data->InfoLog);
1414bf215546Sopenharmony_ci   }
1415bf215546Sopenharmony_ci
1416bf215546Sopenharmony_ci   _mesa_update_vertex_processing_mode(ctx);
1417bf215546Sopenharmony_ci   _mesa_update_valid_to_render_state(ctx);
1418bf215546Sopenharmony_ci
1419bf215546Sopenharmony_ci   shProg->BinaryRetrievableHint = shProg->BinaryRetrievableHintPending;
1420bf215546Sopenharmony_ci
1421bf215546Sopenharmony_ci   /* debug code */
1422bf215546Sopenharmony_ci   if (0) {
1423bf215546Sopenharmony_ci      GLuint i;
1424bf215546Sopenharmony_ci
1425bf215546Sopenharmony_ci      printf("Link %u shaders in program %u: %s\n",
1426bf215546Sopenharmony_ci                   shProg->NumShaders, shProg->Name,
1427bf215546Sopenharmony_ci                   shProg->data->LinkStatus ? "Success" : "Failed");
1428bf215546Sopenharmony_ci
1429bf215546Sopenharmony_ci      for (i = 0; i < shProg->NumShaders; i++) {
1430bf215546Sopenharmony_ci         printf(" shader %u, stage %u\n",
1431bf215546Sopenharmony_ci                      shProg->Shaders[i]->Name,
1432bf215546Sopenharmony_ci                      shProg->Shaders[i]->Stage);
1433bf215546Sopenharmony_ci      }
1434bf215546Sopenharmony_ci   }
1435bf215546Sopenharmony_ci}
1436bf215546Sopenharmony_ci
1437bf215546Sopenharmony_ci
1438bf215546Sopenharmony_cistatic void
1439bf215546Sopenharmony_cilink_program_error(struct gl_context *ctx, struct gl_shader_program *shProg)
1440bf215546Sopenharmony_ci{
1441bf215546Sopenharmony_ci   link_program(ctx, shProg, false);
1442bf215546Sopenharmony_ci}
1443bf215546Sopenharmony_ci
1444bf215546Sopenharmony_ci
1445bf215546Sopenharmony_cistatic void
1446bf215546Sopenharmony_cilink_program_no_error(struct gl_context *ctx, struct gl_shader_program *shProg)
1447bf215546Sopenharmony_ci{
1448bf215546Sopenharmony_ci   link_program(ctx, shProg, true);
1449bf215546Sopenharmony_ci}
1450bf215546Sopenharmony_ci
1451bf215546Sopenharmony_ci
1452bf215546Sopenharmony_civoid
1453bf215546Sopenharmony_ci_mesa_link_program(struct gl_context *ctx, struct gl_shader_program *shProg)
1454bf215546Sopenharmony_ci{
1455bf215546Sopenharmony_ci   link_program_error(ctx, shProg);
1456bf215546Sopenharmony_ci}
1457bf215546Sopenharmony_ci
1458bf215546Sopenharmony_ci
1459bf215546Sopenharmony_ci/**
1460bf215546Sopenharmony_ci * Print basic shader info (for debug).
1461bf215546Sopenharmony_ci */
1462bf215546Sopenharmony_cistatic void
1463bf215546Sopenharmony_ciprint_shader_info(const struct gl_shader_program *shProg)
1464bf215546Sopenharmony_ci{
1465bf215546Sopenharmony_ci   GLuint i;
1466bf215546Sopenharmony_ci
1467bf215546Sopenharmony_ci   printf("Mesa: glUseProgram(%u)\n", shProg->Name);
1468bf215546Sopenharmony_ci   for (i = 0; i < shProg->NumShaders; i++) {
1469bf215546Sopenharmony_ci      printf("  %s shader %u\n",
1470bf215546Sopenharmony_ci             _mesa_shader_stage_to_string(shProg->Shaders[i]->Stage),
1471bf215546Sopenharmony_ci             shProg->Shaders[i]->Name);
1472bf215546Sopenharmony_ci   }
1473bf215546Sopenharmony_ci   if (shProg->_LinkedShaders[MESA_SHADER_VERTEX])
1474bf215546Sopenharmony_ci      printf("  vert prog %u\n",
1475bf215546Sopenharmony_ci	     shProg->_LinkedShaders[MESA_SHADER_VERTEX]->Program->Id);
1476bf215546Sopenharmony_ci   if (shProg->_LinkedShaders[MESA_SHADER_FRAGMENT])
1477bf215546Sopenharmony_ci      printf("  frag prog %u\n",
1478bf215546Sopenharmony_ci	     shProg->_LinkedShaders[MESA_SHADER_FRAGMENT]->Program->Id);
1479bf215546Sopenharmony_ci   if (shProg->_LinkedShaders[MESA_SHADER_GEOMETRY])
1480bf215546Sopenharmony_ci      printf("  geom prog %u\n",
1481bf215546Sopenharmony_ci	     shProg->_LinkedShaders[MESA_SHADER_GEOMETRY]->Program->Id);
1482bf215546Sopenharmony_ci   if (shProg->_LinkedShaders[MESA_SHADER_TESS_CTRL])
1483bf215546Sopenharmony_ci      printf("  tesc prog %u\n",
1484bf215546Sopenharmony_ci	     shProg->_LinkedShaders[MESA_SHADER_TESS_CTRL]->Program->Id);
1485bf215546Sopenharmony_ci   if (shProg->_LinkedShaders[MESA_SHADER_TESS_EVAL])
1486bf215546Sopenharmony_ci      printf("  tese prog %u\n",
1487bf215546Sopenharmony_ci	     shProg->_LinkedShaders[MESA_SHADER_TESS_EVAL]->Program->Id);
1488bf215546Sopenharmony_ci}
1489bf215546Sopenharmony_ci
1490bf215546Sopenharmony_ci
1491bf215546Sopenharmony_ci/**
1492bf215546Sopenharmony_ci * Use the named shader program for subsequent glUniform calls
1493bf215546Sopenharmony_ci */
1494bf215546Sopenharmony_civoid
1495bf215546Sopenharmony_ci_mesa_active_program(struct gl_context *ctx, struct gl_shader_program *shProg,
1496bf215546Sopenharmony_ci		     const char *caller)
1497bf215546Sopenharmony_ci{
1498bf215546Sopenharmony_ci   if ((shProg != NULL) && !shProg->data->LinkStatus) {
1499bf215546Sopenharmony_ci      _mesa_error(ctx, GL_INVALID_OPERATION,
1500bf215546Sopenharmony_ci		  "%s(program %u not linked)", caller, shProg->Name);
1501bf215546Sopenharmony_ci      return;
1502bf215546Sopenharmony_ci   }
1503bf215546Sopenharmony_ci
1504bf215546Sopenharmony_ci   if (ctx->Shader.ActiveProgram != shProg) {
1505bf215546Sopenharmony_ci      _mesa_reference_shader_program(ctx, &ctx->Shader.ActiveProgram, shProg);
1506bf215546Sopenharmony_ci      _mesa_update_valid_to_render_state(ctx);
1507bf215546Sopenharmony_ci   }
1508bf215546Sopenharmony_ci}
1509bf215546Sopenharmony_ci
1510bf215546Sopenharmony_ci
1511bf215546Sopenharmony_ci/**
1512bf215546Sopenharmony_ci * Use the named shader program for subsequent rendering.
1513bf215546Sopenharmony_ci */
1514bf215546Sopenharmony_civoid
1515bf215546Sopenharmony_ci_mesa_use_shader_program(struct gl_context *ctx,
1516bf215546Sopenharmony_ci                         struct gl_shader_program *shProg)
1517bf215546Sopenharmony_ci{
1518bf215546Sopenharmony_ci   for (int i = 0; i < MESA_SHADER_STAGES; i++) {
1519bf215546Sopenharmony_ci      struct gl_program *new_prog = NULL;
1520bf215546Sopenharmony_ci      if (shProg && shProg->_LinkedShaders[i])
1521bf215546Sopenharmony_ci         new_prog = shProg->_LinkedShaders[i]->Program;
1522bf215546Sopenharmony_ci      _mesa_use_program(ctx, i, shProg, new_prog, &ctx->Shader);
1523bf215546Sopenharmony_ci   }
1524bf215546Sopenharmony_ci   _mesa_active_program(ctx, shProg, "glUseProgram");
1525bf215546Sopenharmony_ci}
1526bf215546Sopenharmony_ci
1527bf215546Sopenharmony_ci
1528bf215546Sopenharmony_ci/**
1529bf215546Sopenharmony_ci * Do validation of the given shader program.
1530bf215546Sopenharmony_ci * \param errMsg  returns error message if validation fails.
1531bf215546Sopenharmony_ci * \return GL_TRUE if valid, GL_FALSE if invalid (and set errMsg)
1532bf215546Sopenharmony_ci */
1533bf215546Sopenharmony_cistatic GLboolean
1534bf215546Sopenharmony_civalidate_shader_program(const struct gl_shader_program *shProg,
1535bf215546Sopenharmony_ci                        char *errMsg)
1536bf215546Sopenharmony_ci{
1537bf215546Sopenharmony_ci   if (!shProg->data->LinkStatus) {
1538bf215546Sopenharmony_ci      return GL_FALSE;
1539bf215546Sopenharmony_ci   }
1540bf215546Sopenharmony_ci
1541bf215546Sopenharmony_ci   /* From the GL spec, a program is invalid if any of these are true:
1542bf215546Sopenharmony_ci
1543bf215546Sopenharmony_ci     any two active samplers in the current program object are of
1544bf215546Sopenharmony_ci     different types, but refer to the same texture image unit,
1545bf215546Sopenharmony_ci
1546bf215546Sopenharmony_ci     any active sampler in the current program object refers to a texture
1547bf215546Sopenharmony_ci     image unit where fixed-function fragment processing accesses a
1548bf215546Sopenharmony_ci     texture target that does not match the sampler type, or
1549bf215546Sopenharmony_ci
1550bf215546Sopenharmony_ci     the sum of the number of active samplers in the program and the
1551bf215546Sopenharmony_ci     number of texture image units enabled for fixed-function fragment
1552bf215546Sopenharmony_ci     processing exceeds the combined limit on the total number of texture
1553bf215546Sopenharmony_ci     image units allowed.
1554bf215546Sopenharmony_ci   */
1555bf215546Sopenharmony_ci
1556bf215546Sopenharmony_ci   /*
1557bf215546Sopenharmony_ci    * Check: any two active samplers in the current program object are of
1558bf215546Sopenharmony_ci    * different types, but refer to the same texture image unit,
1559bf215546Sopenharmony_ci    */
1560bf215546Sopenharmony_ci   if (!_mesa_sampler_uniforms_are_valid(shProg, errMsg, 100))
1561bf215546Sopenharmony_ci      return GL_FALSE;
1562bf215546Sopenharmony_ci
1563bf215546Sopenharmony_ci   return GL_TRUE;
1564bf215546Sopenharmony_ci}
1565bf215546Sopenharmony_ci
1566bf215546Sopenharmony_ci
1567bf215546Sopenharmony_ci/**
1568bf215546Sopenharmony_ci * Called via glValidateProgram()
1569bf215546Sopenharmony_ci */
1570bf215546Sopenharmony_cistatic void
1571bf215546Sopenharmony_civalidate_program(struct gl_context *ctx, GLuint program)
1572bf215546Sopenharmony_ci{
1573bf215546Sopenharmony_ci   struct gl_shader_program *shProg;
1574bf215546Sopenharmony_ci   char errMsg[100] = "";
1575bf215546Sopenharmony_ci
1576bf215546Sopenharmony_ci   shProg = _mesa_lookup_shader_program_err(ctx, program, "glValidateProgram");
1577bf215546Sopenharmony_ci   if (!shProg) {
1578bf215546Sopenharmony_ci      return;
1579bf215546Sopenharmony_ci   }
1580bf215546Sopenharmony_ci
1581bf215546Sopenharmony_ci   shProg->data->Validated = validate_shader_program(shProg, errMsg);
1582bf215546Sopenharmony_ci   if (!shProg->data->Validated) {
1583bf215546Sopenharmony_ci      /* update info log */
1584bf215546Sopenharmony_ci      if (shProg->data->InfoLog) {
1585bf215546Sopenharmony_ci         ralloc_free(shProg->data->InfoLog);
1586bf215546Sopenharmony_ci      }
1587bf215546Sopenharmony_ci      shProg->data->InfoLog = ralloc_strdup(shProg->data, errMsg);
1588bf215546Sopenharmony_ci   }
1589bf215546Sopenharmony_ci}
1590bf215546Sopenharmony_ci
1591bf215546Sopenharmony_ci
1592bf215546Sopenharmony_civoid GLAPIENTRY
1593bf215546Sopenharmony_ci_mesa_AttachObjectARB_no_error(GLhandleARB program, GLhandleARB shader)
1594bf215546Sopenharmony_ci{
1595bf215546Sopenharmony_ci   GET_CURRENT_CONTEXT(ctx);
1596bf215546Sopenharmony_ci   attach_shader_no_error(ctx, program, shader);
1597bf215546Sopenharmony_ci}
1598bf215546Sopenharmony_ci
1599bf215546Sopenharmony_ci
1600bf215546Sopenharmony_civoid GLAPIENTRY
1601bf215546Sopenharmony_ci_mesa_AttachObjectARB(GLhandleARB program, GLhandleARB shader)
1602bf215546Sopenharmony_ci{
1603bf215546Sopenharmony_ci   GET_CURRENT_CONTEXT(ctx);
1604bf215546Sopenharmony_ci   attach_shader_err(ctx, program, shader, "glAttachObjectARB");
1605bf215546Sopenharmony_ci}
1606bf215546Sopenharmony_ci
1607bf215546Sopenharmony_ci
1608bf215546Sopenharmony_civoid GLAPIENTRY
1609bf215546Sopenharmony_ci_mesa_AttachShader_no_error(GLuint program, GLuint shader)
1610bf215546Sopenharmony_ci{
1611bf215546Sopenharmony_ci   GET_CURRENT_CONTEXT(ctx);
1612bf215546Sopenharmony_ci   attach_shader_no_error(ctx, program, shader);
1613bf215546Sopenharmony_ci}
1614bf215546Sopenharmony_ci
1615bf215546Sopenharmony_ci
1616bf215546Sopenharmony_civoid GLAPIENTRY
1617bf215546Sopenharmony_ci_mesa_AttachShader(GLuint program, GLuint shader)
1618bf215546Sopenharmony_ci{
1619bf215546Sopenharmony_ci   GET_CURRENT_CONTEXT(ctx);
1620bf215546Sopenharmony_ci   attach_shader_err(ctx, program, shader, "glAttachShader");
1621bf215546Sopenharmony_ci}
1622bf215546Sopenharmony_ci
1623bf215546Sopenharmony_ci
1624bf215546Sopenharmony_civoid GLAPIENTRY
1625bf215546Sopenharmony_ci_mesa_CompileShader(GLuint shaderObj)
1626bf215546Sopenharmony_ci{
1627bf215546Sopenharmony_ci   GET_CURRENT_CONTEXT(ctx);
1628bf215546Sopenharmony_ci   if (MESA_VERBOSE & VERBOSE_API)
1629bf215546Sopenharmony_ci      _mesa_debug(ctx, "glCompileShader %u\n", shaderObj);
1630bf215546Sopenharmony_ci   _mesa_compile_shader(ctx, _mesa_lookup_shader_err(ctx, shaderObj,
1631bf215546Sopenharmony_ci                                                     "glCompileShader"));
1632bf215546Sopenharmony_ci}
1633bf215546Sopenharmony_ci
1634bf215546Sopenharmony_ci
1635bf215546Sopenharmony_ciGLuint GLAPIENTRY
1636bf215546Sopenharmony_ci_mesa_CreateShader_no_error(GLenum type)
1637bf215546Sopenharmony_ci{
1638bf215546Sopenharmony_ci   GET_CURRENT_CONTEXT(ctx);
1639bf215546Sopenharmony_ci   return create_shader(ctx, type);
1640bf215546Sopenharmony_ci}
1641bf215546Sopenharmony_ci
1642bf215546Sopenharmony_ci
1643bf215546Sopenharmony_ciGLuint GLAPIENTRY
1644bf215546Sopenharmony_ci_mesa_CreateShader(GLenum type)
1645bf215546Sopenharmony_ci{
1646bf215546Sopenharmony_ci   GET_CURRENT_CONTEXT(ctx);
1647bf215546Sopenharmony_ci
1648bf215546Sopenharmony_ci   if (MESA_VERBOSE & VERBOSE_API)
1649bf215546Sopenharmony_ci      _mesa_debug(ctx, "glCreateShader %s\n", _mesa_enum_to_string(type));
1650bf215546Sopenharmony_ci
1651bf215546Sopenharmony_ci   return create_shader_err(ctx, type, "glCreateShader");
1652bf215546Sopenharmony_ci}
1653bf215546Sopenharmony_ci
1654bf215546Sopenharmony_ci
1655bf215546Sopenharmony_ciGLhandleARB GLAPIENTRY
1656bf215546Sopenharmony_ci_mesa_CreateShaderObjectARB_no_error(GLenum type)
1657bf215546Sopenharmony_ci{
1658bf215546Sopenharmony_ci   GET_CURRENT_CONTEXT(ctx);
1659bf215546Sopenharmony_ci   return create_shader(ctx, type);
1660bf215546Sopenharmony_ci}
1661bf215546Sopenharmony_ci
1662bf215546Sopenharmony_ci
1663bf215546Sopenharmony_ciGLhandleARB GLAPIENTRY
1664bf215546Sopenharmony_ci_mesa_CreateShaderObjectARB(GLenum type)
1665bf215546Sopenharmony_ci{
1666bf215546Sopenharmony_ci   GET_CURRENT_CONTEXT(ctx);
1667bf215546Sopenharmony_ci   return create_shader_err(ctx, type, "glCreateShaderObjectARB");
1668bf215546Sopenharmony_ci}
1669bf215546Sopenharmony_ci
1670bf215546Sopenharmony_ci
1671bf215546Sopenharmony_ciGLuint GLAPIENTRY
1672bf215546Sopenharmony_ci_mesa_CreateProgram(void)
1673bf215546Sopenharmony_ci{
1674bf215546Sopenharmony_ci   GET_CURRENT_CONTEXT(ctx);
1675bf215546Sopenharmony_ci   if (MESA_VERBOSE & VERBOSE_API)
1676bf215546Sopenharmony_ci      _mesa_debug(ctx, "glCreateProgram\n");
1677bf215546Sopenharmony_ci   return create_shader_program(ctx);
1678bf215546Sopenharmony_ci}
1679bf215546Sopenharmony_ci
1680bf215546Sopenharmony_ci
1681bf215546Sopenharmony_ciGLhandleARB GLAPIENTRY
1682bf215546Sopenharmony_ci_mesa_CreateProgramObjectARB(void)
1683bf215546Sopenharmony_ci{
1684bf215546Sopenharmony_ci   GET_CURRENT_CONTEXT(ctx);
1685bf215546Sopenharmony_ci   return create_shader_program(ctx);
1686bf215546Sopenharmony_ci}
1687bf215546Sopenharmony_ci
1688bf215546Sopenharmony_ci
1689bf215546Sopenharmony_civoid GLAPIENTRY
1690bf215546Sopenharmony_ci_mesa_DeleteObjectARB(GLhandleARB obj)
1691bf215546Sopenharmony_ci{
1692bf215546Sopenharmony_ci   if (MESA_VERBOSE & VERBOSE_API) {
1693bf215546Sopenharmony_ci      GET_CURRENT_CONTEXT(ctx);
1694bf215546Sopenharmony_ci      _mesa_debug(ctx, "glDeleteObjectARB(%lu)\n", (unsigned long)obj);
1695bf215546Sopenharmony_ci   }
1696bf215546Sopenharmony_ci
1697bf215546Sopenharmony_ci   if (obj) {
1698bf215546Sopenharmony_ci      GET_CURRENT_CONTEXT(ctx);
1699bf215546Sopenharmony_ci      FLUSH_VERTICES(ctx, 0, 0);
1700bf215546Sopenharmony_ci      if (is_program(ctx, obj)) {
1701bf215546Sopenharmony_ci         delete_shader_program(ctx, obj);
1702bf215546Sopenharmony_ci      }
1703bf215546Sopenharmony_ci      else if (is_shader(ctx, obj)) {
1704bf215546Sopenharmony_ci         delete_shader(ctx, obj);
1705bf215546Sopenharmony_ci      }
1706bf215546Sopenharmony_ci      else {
1707bf215546Sopenharmony_ci         _mesa_error(ctx, GL_INVALID_VALUE, "glDeleteObjectARB");
1708bf215546Sopenharmony_ci      }
1709bf215546Sopenharmony_ci   }
1710bf215546Sopenharmony_ci}
1711bf215546Sopenharmony_ci
1712bf215546Sopenharmony_ci
1713bf215546Sopenharmony_civoid GLAPIENTRY
1714bf215546Sopenharmony_ci_mesa_DeleteProgram(GLuint name)
1715bf215546Sopenharmony_ci{
1716bf215546Sopenharmony_ci   if (name) {
1717bf215546Sopenharmony_ci      GET_CURRENT_CONTEXT(ctx);
1718bf215546Sopenharmony_ci      FLUSH_VERTICES(ctx, 0, 0);
1719bf215546Sopenharmony_ci      delete_shader_program(ctx, name);
1720bf215546Sopenharmony_ci   }
1721bf215546Sopenharmony_ci}
1722bf215546Sopenharmony_ci
1723bf215546Sopenharmony_ci
1724bf215546Sopenharmony_civoid GLAPIENTRY
1725bf215546Sopenharmony_ci_mesa_DeleteShader(GLuint name)
1726bf215546Sopenharmony_ci{
1727bf215546Sopenharmony_ci   if (name) {
1728bf215546Sopenharmony_ci      GET_CURRENT_CONTEXT(ctx);
1729bf215546Sopenharmony_ci      FLUSH_VERTICES(ctx, 0, 0);
1730bf215546Sopenharmony_ci      delete_shader(ctx, name);
1731bf215546Sopenharmony_ci   }
1732bf215546Sopenharmony_ci}
1733bf215546Sopenharmony_ci
1734bf215546Sopenharmony_ci
1735bf215546Sopenharmony_civoid GLAPIENTRY
1736bf215546Sopenharmony_ci_mesa_DetachObjectARB_no_error(GLhandleARB program, GLhandleARB shader)
1737bf215546Sopenharmony_ci{
1738bf215546Sopenharmony_ci   GET_CURRENT_CONTEXT(ctx);
1739bf215546Sopenharmony_ci   detach_shader_no_error(ctx, program, shader);
1740bf215546Sopenharmony_ci}
1741bf215546Sopenharmony_ci
1742bf215546Sopenharmony_ci
1743bf215546Sopenharmony_civoid GLAPIENTRY
1744bf215546Sopenharmony_ci_mesa_DetachObjectARB(GLhandleARB program, GLhandleARB shader)
1745bf215546Sopenharmony_ci{
1746bf215546Sopenharmony_ci   GET_CURRENT_CONTEXT(ctx);
1747bf215546Sopenharmony_ci   detach_shader_error(ctx, program, shader);
1748bf215546Sopenharmony_ci}
1749bf215546Sopenharmony_ci
1750bf215546Sopenharmony_ci
1751bf215546Sopenharmony_civoid GLAPIENTRY
1752bf215546Sopenharmony_ci_mesa_DetachShader_no_error(GLuint program, GLuint shader)
1753bf215546Sopenharmony_ci{
1754bf215546Sopenharmony_ci   GET_CURRENT_CONTEXT(ctx);
1755bf215546Sopenharmony_ci   detach_shader_no_error(ctx, program, shader);
1756bf215546Sopenharmony_ci}
1757bf215546Sopenharmony_ci
1758bf215546Sopenharmony_ci
1759bf215546Sopenharmony_civoid GLAPIENTRY
1760bf215546Sopenharmony_ci_mesa_DetachShader(GLuint program, GLuint shader)
1761bf215546Sopenharmony_ci{
1762bf215546Sopenharmony_ci   GET_CURRENT_CONTEXT(ctx);
1763bf215546Sopenharmony_ci   detach_shader_error(ctx, program, shader);
1764bf215546Sopenharmony_ci}
1765bf215546Sopenharmony_ci
1766bf215546Sopenharmony_ci
1767bf215546Sopenharmony_civoid GLAPIENTRY
1768bf215546Sopenharmony_ci_mesa_GetAttachedObjectsARB(GLhandleARB container, GLsizei maxCount,
1769bf215546Sopenharmony_ci                            GLsizei * count, GLhandleARB * obj)
1770bf215546Sopenharmony_ci{
1771bf215546Sopenharmony_ci   GET_CURRENT_CONTEXT(ctx);
1772bf215546Sopenharmony_ci   get_attached_shaders(ctx, (GLuint)container, maxCount, count, NULL, obj);
1773bf215546Sopenharmony_ci}
1774bf215546Sopenharmony_ci
1775bf215546Sopenharmony_ci
1776bf215546Sopenharmony_civoid GLAPIENTRY
1777bf215546Sopenharmony_ci_mesa_GetAttachedShaders(GLuint program, GLsizei maxCount,
1778bf215546Sopenharmony_ci                         GLsizei *count, GLuint *obj)
1779bf215546Sopenharmony_ci{
1780bf215546Sopenharmony_ci   GET_CURRENT_CONTEXT(ctx);
1781bf215546Sopenharmony_ci   get_attached_shaders(ctx, program, maxCount, count, obj, NULL);
1782bf215546Sopenharmony_ci}
1783bf215546Sopenharmony_ci
1784bf215546Sopenharmony_ci
1785bf215546Sopenharmony_civoid GLAPIENTRY
1786bf215546Sopenharmony_ci_mesa_GetInfoLogARB(GLhandleARB object, GLsizei maxLength, GLsizei * length,
1787bf215546Sopenharmony_ci                    GLcharARB * infoLog)
1788bf215546Sopenharmony_ci{
1789bf215546Sopenharmony_ci   GET_CURRENT_CONTEXT(ctx);
1790bf215546Sopenharmony_ci   if (is_program(ctx, object)) {
1791bf215546Sopenharmony_ci      get_program_info_log(ctx, object, maxLength, length, infoLog);
1792bf215546Sopenharmony_ci   }
1793bf215546Sopenharmony_ci   else if (is_shader(ctx, object)) {
1794bf215546Sopenharmony_ci      get_shader_info_log(ctx, object, maxLength, length, infoLog);
1795bf215546Sopenharmony_ci   }
1796bf215546Sopenharmony_ci   else {
1797bf215546Sopenharmony_ci      _mesa_error(ctx, GL_INVALID_OPERATION, "glGetInfoLogARB");
1798bf215546Sopenharmony_ci   }
1799bf215546Sopenharmony_ci}
1800bf215546Sopenharmony_ci
1801bf215546Sopenharmony_ci
1802bf215546Sopenharmony_civoid GLAPIENTRY
1803bf215546Sopenharmony_ci_mesa_GetObjectParameterivARB(GLhandleARB object, GLenum pname, GLint *params)
1804bf215546Sopenharmony_ci{
1805bf215546Sopenharmony_ci   GET_CURRENT_CONTEXT(ctx);
1806bf215546Sopenharmony_ci   /* Implement in terms of GetProgramiv, GetShaderiv */
1807bf215546Sopenharmony_ci   if (is_program(ctx, object)) {
1808bf215546Sopenharmony_ci      if (pname == GL_OBJECT_TYPE_ARB) {
1809bf215546Sopenharmony_ci	 *params = GL_PROGRAM_OBJECT_ARB;
1810bf215546Sopenharmony_ci      }
1811bf215546Sopenharmony_ci      else {
1812bf215546Sopenharmony_ci	 get_programiv(ctx, object, pname, params);
1813bf215546Sopenharmony_ci      }
1814bf215546Sopenharmony_ci   }
1815bf215546Sopenharmony_ci   else if (is_shader(ctx, object)) {
1816bf215546Sopenharmony_ci      if (pname == GL_OBJECT_TYPE_ARB) {
1817bf215546Sopenharmony_ci	 *params = GL_SHADER_OBJECT_ARB;
1818bf215546Sopenharmony_ci      }
1819bf215546Sopenharmony_ci      else {
1820bf215546Sopenharmony_ci	 get_shaderiv(ctx, object, pname, params);
1821bf215546Sopenharmony_ci      }
1822bf215546Sopenharmony_ci   }
1823bf215546Sopenharmony_ci   else {
1824bf215546Sopenharmony_ci      _mesa_error(ctx, GL_INVALID_VALUE, "glGetObjectParameterivARB");
1825bf215546Sopenharmony_ci   }
1826bf215546Sopenharmony_ci}
1827bf215546Sopenharmony_ci
1828bf215546Sopenharmony_ci
1829bf215546Sopenharmony_civoid GLAPIENTRY
1830bf215546Sopenharmony_ci_mesa_GetObjectParameterfvARB(GLhandleARB object, GLenum pname,
1831bf215546Sopenharmony_ci                              GLfloat *params)
1832bf215546Sopenharmony_ci{
1833bf215546Sopenharmony_ci   GLint iparams[1] = {0};  /* XXX is one element enough? */
1834bf215546Sopenharmony_ci   _mesa_GetObjectParameterivARB(object, pname, iparams);
1835bf215546Sopenharmony_ci   params[0] = (GLfloat) iparams[0];
1836bf215546Sopenharmony_ci}
1837bf215546Sopenharmony_ci
1838bf215546Sopenharmony_ci
1839bf215546Sopenharmony_civoid GLAPIENTRY
1840bf215546Sopenharmony_ci_mesa_GetProgramiv(GLuint program, GLenum pname, GLint *params)
1841bf215546Sopenharmony_ci{
1842bf215546Sopenharmony_ci   GET_CURRENT_CONTEXT(ctx);
1843bf215546Sopenharmony_ci   get_programiv(ctx, program, pname, params);
1844bf215546Sopenharmony_ci}
1845bf215546Sopenharmony_ci
1846bf215546Sopenharmony_ci
1847bf215546Sopenharmony_civoid GLAPIENTRY
1848bf215546Sopenharmony_ci_mesa_GetShaderiv(GLuint shader, GLenum pname, GLint *params)
1849bf215546Sopenharmony_ci{
1850bf215546Sopenharmony_ci   GET_CURRENT_CONTEXT(ctx);
1851bf215546Sopenharmony_ci   get_shaderiv(ctx, shader, pname, params);
1852bf215546Sopenharmony_ci}
1853bf215546Sopenharmony_ci
1854bf215546Sopenharmony_ci
1855bf215546Sopenharmony_civoid GLAPIENTRY
1856bf215546Sopenharmony_ci_mesa_GetProgramInfoLog(GLuint program, GLsizei bufSize,
1857bf215546Sopenharmony_ci                        GLsizei *length, GLchar *infoLog)
1858bf215546Sopenharmony_ci{
1859bf215546Sopenharmony_ci   GET_CURRENT_CONTEXT(ctx);
1860bf215546Sopenharmony_ci   get_program_info_log(ctx, program, bufSize, length, infoLog);
1861bf215546Sopenharmony_ci}
1862bf215546Sopenharmony_ci
1863bf215546Sopenharmony_ci
1864bf215546Sopenharmony_civoid GLAPIENTRY
1865bf215546Sopenharmony_ci_mesa_GetShaderInfoLog(GLuint shader, GLsizei bufSize,
1866bf215546Sopenharmony_ci                       GLsizei *length, GLchar *infoLog)
1867bf215546Sopenharmony_ci{
1868bf215546Sopenharmony_ci   GET_CURRENT_CONTEXT(ctx);
1869bf215546Sopenharmony_ci   get_shader_info_log(ctx, shader, bufSize, length, infoLog);
1870bf215546Sopenharmony_ci}
1871bf215546Sopenharmony_ci
1872bf215546Sopenharmony_ci
1873bf215546Sopenharmony_civoid GLAPIENTRY
1874bf215546Sopenharmony_ci_mesa_GetShaderSource(GLuint shader, GLsizei maxLength,
1875bf215546Sopenharmony_ci                      GLsizei *length, GLchar *sourceOut)
1876bf215546Sopenharmony_ci{
1877bf215546Sopenharmony_ci   GET_CURRENT_CONTEXT(ctx);
1878bf215546Sopenharmony_ci   get_shader_source(ctx, shader, maxLength, length, sourceOut);
1879bf215546Sopenharmony_ci}
1880bf215546Sopenharmony_ci
1881bf215546Sopenharmony_ci
1882bf215546Sopenharmony_ciGLhandleARB GLAPIENTRY
1883bf215546Sopenharmony_ci_mesa_GetHandleARB(GLenum pname)
1884bf215546Sopenharmony_ci{
1885bf215546Sopenharmony_ci   GET_CURRENT_CONTEXT(ctx);
1886bf215546Sopenharmony_ci   return get_handle(ctx, pname);
1887bf215546Sopenharmony_ci}
1888bf215546Sopenharmony_ci
1889bf215546Sopenharmony_ci
1890bf215546Sopenharmony_ciGLboolean GLAPIENTRY
1891bf215546Sopenharmony_ci_mesa_IsProgram(GLuint name)
1892bf215546Sopenharmony_ci{
1893bf215546Sopenharmony_ci   GET_CURRENT_CONTEXT(ctx);
1894bf215546Sopenharmony_ci   return is_program(ctx, name);
1895bf215546Sopenharmony_ci}
1896bf215546Sopenharmony_ci
1897bf215546Sopenharmony_ci
1898bf215546Sopenharmony_ciGLboolean GLAPIENTRY
1899bf215546Sopenharmony_ci_mesa_IsShader(GLuint name)
1900bf215546Sopenharmony_ci{
1901bf215546Sopenharmony_ci   GET_CURRENT_CONTEXT(ctx);
1902bf215546Sopenharmony_ci   return is_shader(ctx, name);
1903bf215546Sopenharmony_ci}
1904bf215546Sopenharmony_ci
1905bf215546Sopenharmony_ci
1906bf215546Sopenharmony_civoid GLAPIENTRY
1907bf215546Sopenharmony_ci_mesa_LinkProgram_no_error(GLuint programObj)
1908bf215546Sopenharmony_ci{
1909bf215546Sopenharmony_ci   GET_CURRENT_CONTEXT(ctx);
1910bf215546Sopenharmony_ci
1911bf215546Sopenharmony_ci   struct gl_shader_program *shProg =
1912bf215546Sopenharmony_ci      _mesa_lookup_shader_program(ctx, programObj);
1913bf215546Sopenharmony_ci   link_program_no_error(ctx, shProg);
1914bf215546Sopenharmony_ci}
1915bf215546Sopenharmony_ci
1916bf215546Sopenharmony_ci
1917bf215546Sopenharmony_civoid GLAPIENTRY
1918bf215546Sopenharmony_ci_mesa_LinkProgram(GLuint programObj)
1919bf215546Sopenharmony_ci{
1920bf215546Sopenharmony_ci   GET_CURRENT_CONTEXT(ctx);
1921bf215546Sopenharmony_ci
1922bf215546Sopenharmony_ci   if (MESA_VERBOSE & VERBOSE_API)
1923bf215546Sopenharmony_ci      _mesa_debug(ctx, "glLinkProgram %u\n", programObj);
1924bf215546Sopenharmony_ci
1925bf215546Sopenharmony_ci   struct gl_shader_program *shProg =
1926bf215546Sopenharmony_ci      _mesa_lookup_shader_program_err(ctx, programObj, "glLinkProgram");
1927bf215546Sopenharmony_ci   link_program_error(ctx, shProg);
1928bf215546Sopenharmony_ci}
1929bf215546Sopenharmony_ci
1930bf215546Sopenharmony_ci#ifdef ENABLE_SHADER_CACHE
1931bf215546Sopenharmony_ci
1932bf215546Sopenharmony_ci/**
1933bf215546Sopenharmony_ci * Construct a full path for shader replacement functionality using
1934bf215546Sopenharmony_ci * following format:
1935bf215546Sopenharmony_ci *
1936bf215546Sopenharmony_ci * <path>/<stage prefix>_<CHECKSUM>.glsl
1937bf215546Sopenharmony_ci * <path>/<stage prefix>_<CHECKSUM>.arb
1938bf215546Sopenharmony_ci */
1939bf215546Sopenharmony_cistatic char *
1940bf215546Sopenharmony_ciconstruct_name(const gl_shader_stage stage, const char *sha,
1941bf215546Sopenharmony_ci               const char *source, const char *path)
1942bf215546Sopenharmony_ci{
1943bf215546Sopenharmony_ci   static const char *types[] = {
1944bf215546Sopenharmony_ci      "VS", "TC", "TE", "GS", "FS", "CS",
1945bf215546Sopenharmony_ci   };
1946bf215546Sopenharmony_ci
1947bf215546Sopenharmony_ci   const char *format = strncmp(source, "!!ARB", 5) ? "glsl" : "arb";
1948bf215546Sopenharmony_ci
1949bf215546Sopenharmony_ci   return ralloc_asprintf(NULL, "%s/%s_%s.%s", path, types[stage], sha, format);
1950bf215546Sopenharmony_ci}
1951bf215546Sopenharmony_ci
1952bf215546Sopenharmony_ci/**
1953bf215546Sopenharmony_ci * Write given shader source to a file in MESA_SHADER_DUMP_PATH.
1954bf215546Sopenharmony_ci */
1955bf215546Sopenharmony_civoid
1956bf215546Sopenharmony_ci_mesa_dump_shader_source(const gl_shader_stage stage, const char *source,
1957bf215546Sopenharmony_ci                         const uint8_t sha1[SHA1_DIGEST_LENGTH])
1958bf215546Sopenharmony_ci{
1959bf215546Sopenharmony_ci#ifndef CUSTOM_SHADER_REPLACEMENT
1960bf215546Sopenharmony_ci   static bool path_exists = true;
1961bf215546Sopenharmony_ci   char *dump_path;
1962bf215546Sopenharmony_ci   FILE *f;
1963bf215546Sopenharmony_ci   char sha[64];
1964bf215546Sopenharmony_ci
1965bf215546Sopenharmony_ci   if (!path_exists)
1966bf215546Sopenharmony_ci      return;
1967bf215546Sopenharmony_ci
1968bf215546Sopenharmony_ci   dump_path = getenv("MESA_SHADER_DUMP_PATH");
1969bf215546Sopenharmony_ci   if (!dump_path) {
1970bf215546Sopenharmony_ci      path_exists = false;
1971bf215546Sopenharmony_ci      return;
1972bf215546Sopenharmony_ci   }
1973bf215546Sopenharmony_ci
1974bf215546Sopenharmony_ci   _mesa_sha1_format(sha, sha1);
1975bf215546Sopenharmony_ci   char *name = construct_name(stage, sha, source, dump_path);
1976bf215546Sopenharmony_ci
1977bf215546Sopenharmony_ci   f = fopen(name, "w");
1978bf215546Sopenharmony_ci   if (f) {
1979bf215546Sopenharmony_ci      fputs(source, f);
1980bf215546Sopenharmony_ci      fclose(f);
1981bf215546Sopenharmony_ci   } else {
1982bf215546Sopenharmony_ci      GET_CURRENT_CONTEXT(ctx);
1983bf215546Sopenharmony_ci      _mesa_warning(ctx, "could not open %s for dumping shader (%s)", name,
1984bf215546Sopenharmony_ci                    strerror(errno));
1985bf215546Sopenharmony_ci   }
1986bf215546Sopenharmony_ci   ralloc_free(name);
1987bf215546Sopenharmony_ci#endif
1988bf215546Sopenharmony_ci}
1989bf215546Sopenharmony_ci
1990bf215546Sopenharmony_ci/**
1991bf215546Sopenharmony_ci * Read shader source code from a file.
1992bf215546Sopenharmony_ci * Useful for debugging to override an app's shader.
1993bf215546Sopenharmony_ci */
1994bf215546Sopenharmony_ciGLcharARB *
1995bf215546Sopenharmony_ci_mesa_read_shader_source(const gl_shader_stage stage, const char *source,
1996bf215546Sopenharmony_ci                         const uint8_t sha1[SHA1_DIGEST_LENGTH])
1997bf215546Sopenharmony_ci{
1998bf215546Sopenharmony_ci   char *read_path;
1999bf215546Sopenharmony_ci   static bool path_exists = true;
2000bf215546Sopenharmony_ci   int len, shader_size = 0;
2001bf215546Sopenharmony_ci   GLcharARB *buffer;
2002bf215546Sopenharmony_ci   FILE *f;
2003bf215546Sopenharmony_ci   char sha[64];
2004bf215546Sopenharmony_ci
2005bf215546Sopenharmony_ci   _mesa_sha1_format(sha, sha1);
2006bf215546Sopenharmony_ci
2007bf215546Sopenharmony_ci   if (!debug_get_bool_option("MESA_NO_SHADER_REPLACEMENT", false)) {
2008bf215546Sopenharmony_ci      const char *process_name = util_get_process_name();
2009bf215546Sopenharmony_ci
2010bf215546Sopenharmony_ci      char *new_source = try_direct_replace(process_name, source);
2011bf215546Sopenharmony_ci      if (new_source)
2012bf215546Sopenharmony_ci         return new_source;
2013bf215546Sopenharmony_ci
2014bf215546Sopenharmony_ci      for (size_t i = 0; i < ARRAY_SIZE(shader_replacements); i++) {
2015bf215546Sopenharmony_ci         if (stage != shader_replacements[i].stage)
2016bf215546Sopenharmony_ci            continue;
2017bf215546Sopenharmony_ci
2018bf215546Sopenharmony_ci         if (shader_replacements[i].app &&
2019bf215546Sopenharmony_ci             strcmp(process_name, shader_replacements[i].app) != 0)
2020bf215546Sopenharmony_ci            continue;
2021bf215546Sopenharmony_ci
2022bf215546Sopenharmony_ci         if (memcmp(sha, shader_replacements[i].sha1, 40) != 0)
2023bf215546Sopenharmony_ci            continue;
2024bf215546Sopenharmony_ci
2025bf215546Sopenharmony_ci         return load_shader_replacement(&shader_replacements[i]);
2026bf215546Sopenharmony_ci      }
2027bf215546Sopenharmony_ci   }
2028bf215546Sopenharmony_ci
2029bf215546Sopenharmony_ci   if (!path_exists)
2030bf215546Sopenharmony_ci      return NULL;
2031bf215546Sopenharmony_ci
2032bf215546Sopenharmony_ci   read_path = getenv("MESA_SHADER_READ_PATH");
2033bf215546Sopenharmony_ci   if (!read_path) {
2034bf215546Sopenharmony_ci      path_exists = false;
2035bf215546Sopenharmony_ci      return NULL;
2036bf215546Sopenharmony_ci   }
2037bf215546Sopenharmony_ci
2038bf215546Sopenharmony_ci   char *name = construct_name(stage, sha, source, read_path);
2039bf215546Sopenharmony_ci   f = fopen(name, "r");
2040bf215546Sopenharmony_ci   ralloc_free(name);
2041bf215546Sopenharmony_ci   if (!f)
2042bf215546Sopenharmony_ci      return NULL;
2043bf215546Sopenharmony_ci
2044bf215546Sopenharmony_ci   /* allocate enough room for the entire shader */
2045bf215546Sopenharmony_ci   fseek(f, 0, SEEK_END);
2046bf215546Sopenharmony_ci   shader_size = ftell(f);
2047bf215546Sopenharmony_ci   rewind(f);
2048bf215546Sopenharmony_ci   assert(shader_size);
2049bf215546Sopenharmony_ci
2050bf215546Sopenharmony_ci   /* add one for terminating zero */
2051bf215546Sopenharmony_ci   shader_size++;
2052bf215546Sopenharmony_ci
2053bf215546Sopenharmony_ci   buffer = malloc(shader_size);
2054bf215546Sopenharmony_ci   assert(buffer);
2055bf215546Sopenharmony_ci
2056bf215546Sopenharmony_ci   len = fread(buffer, 1, shader_size, f);
2057bf215546Sopenharmony_ci   buffer[len] = 0;
2058bf215546Sopenharmony_ci
2059bf215546Sopenharmony_ci   fclose(f);
2060bf215546Sopenharmony_ci
2061bf215546Sopenharmony_ci   return buffer;
2062bf215546Sopenharmony_ci}
2063bf215546Sopenharmony_ci
2064bf215546Sopenharmony_ci#endif /* ENABLE_SHADER_CACHE */
2065bf215546Sopenharmony_ci
2066bf215546Sopenharmony_ci/**
2067bf215546Sopenharmony_ci * Called via glShaderSource() and glShaderSourceARB() API functions.
2068bf215546Sopenharmony_ci * Basically, concatenate the source code strings into one long string
2069bf215546Sopenharmony_ci * and pass it to _mesa_shader_source().
2070bf215546Sopenharmony_ci */
2071bf215546Sopenharmony_cistatic ALWAYS_INLINE void
2072bf215546Sopenharmony_cishader_source(struct gl_context *ctx, GLuint shaderObj, GLsizei count,
2073bf215546Sopenharmony_ci              const GLchar *const *string, const GLint *length, bool no_error)
2074bf215546Sopenharmony_ci{
2075bf215546Sopenharmony_ci   GLint *offsets;
2076bf215546Sopenharmony_ci   GLsizei i, totalLength;
2077bf215546Sopenharmony_ci   GLcharARB *source;
2078bf215546Sopenharmony_ci   struct gl_shader *sh;
2079bf215546Sopenharmony_ci
2080bf215546Sopenharmony_ci   if (!no_error) {
2081bf215546Sopenharmony_ci      sh = _mesa_lookup_shader_err(ctx, shaderObj, "glShaderSourceARB");
2082bf215546Sopenharmony_ci      if (!sh)
2083bf215546Sopenharmony_ci         return;
2084bf215546Sopenharmony_ci
2085bf215546Sopenharmony_ci      if (string == NULL || count < 0) {
2086bf215546Sopenharmony_ci         _mesa_error(ctx, GL_INVALID_VALUE, "glShaderSourceARB");
2087bf215546Sopenharmony_ci         return;
2088bf215546Sopenharmony_ci      }
2089bf215546Sopenharmony_ci   } else {
2090bf215546Sopenharmony_ci      sh = _mesa_lookup_shader(ctx, shaderObj);
2091bf215546Sopenharmony_ci   }
2092bf215546Sopenharmony_ci
2093bf215546Sopenharmony_ci   /* Return silently the spec doesn't define this as an error */
2094bf215546Sopenharmony_ci   if (count == 0)
2095bf215546Sopenharmony_ci      return;
2096bf215546Sopenharmony_ci
2097bf215546Sopenharmony_ci   /*
2098bf215546Sopenharmony_ci    * This array holds offsets of where the appropriate string ends, thus the
2099bf215546Sopenharmony_ci    * last element will be set to the total length of the source code.
2100bf215546Sopenharmony_ci    */
2101bf215546Sopenharmony_ci   offsets = calloc(count, sizeof(GLint));
2102bf215546Sopenharmony_ci   if (offsets == NULL) {
2103bf215546Sopenharmony_ci      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glShaderSourceARB");
2104bf215546Sopenharmony_ci      return;
2105bf215546Sopenharmony_ci   }
2106bf215546Sopenharmony_ci
2107bf215546Sopenharmony_ci   for (i = 0; i < count; i++) {
2108bf215546Sopenharmony_ci      if (!no_error && string[i] == NULL) {
2109bf215546Sopenharmony_ci         free((GLvoid *) offsets);
2110bf215546Sopenharmony_ci         _mesa_error(ctx, GL_INVALID_OPERATION,
2111bf215546Sopenharmony_ci                     "glShaderSourceARB(null string)");
2112bf215546Sopenharmony_ci         return;
2113bf215546Sopenharmony_ci      }
2114bf215546Sopenharmony_ci      if (length == NULL || length[i] < 0)
2115bf215546Sopenharmony_ci         offsets[i] = strlen(string[i]);
2116bf215546Sopenharmony_ci      else
2117bf215546Sopenharmony_ci         offsets[i] = length[i];
2118bf215546Sopenharmony_ci      /* accumulate string lengths */
2119bf215546Sopenharmony_ci      if (i > 0)
2120bf215546Sopenharmony_ci         offsets[i] += offsets[i - 1];
2121bf215546Sopenharmony_ci   }
2122bf215546Sopenharmony_ci
2123bf215546Sopenharmony_ci   /* Total length of source string is sum off all strings plus two.
2124bf215546Sopenharmony_ci    * One extra byte for terminating zero, another extra byte to silence
2125bf215546Sopenharmony_ci    * valgrind warnings in the parser/grammer code.
2126bf215546Sopenharmony_ci    */
2127bf215546Sopenharmony_ci   totalLength = offsets[count - 1] + 2;
2128bf215546Sopenharmony_ci   source = malloc(totalLength * sizeof(GLcharARB));
2129bf215546Sopenharmony_ci   if (source == NULL) {
2130bf215546Sopenharmony_ci      free((GLvoid *) offsets);
2131bf215546Sopenharmony_ci      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glShaderSourceARB");
2132bf215546Sopenharmony_ci      return;
2133bf215546Sopenharmony_ci   }
2134bf215546Sopenharmony_ci
2135bf215546Sopenharmony_ci   for (i = 0; i < count; i++) {
2136bf215546Sopenharmony_ci      GLint start = (i > 0) ? offsets[i - 1] : 0;
2137bf215546Sopenharmony_ci      memcpy(source + start, string[i],
2138bf215546Sopenharmony_ci             (offsets[i] - start) * sizeof(GLcharARB));
2139bf215546Sopenharmony_ci   }
2140bf215546Sopenharmony_ci   source[totalLength - 1] = '\0';
2141bf215546Sopenharmony_ci   source[totalLength - 2] = '\0';
2142bf215546Sopenharmony_ci
2143bf215546Sopenharmony_ci   /* Compute the original source sha1 before shader replacement. */
2144bf215546Sopenharmony_ci   uint8_t original_sha1[SHA1_DIGEST_LENGTH];
2145bf215546Sopenharmony_ci   _mesa_sha1_compute(source, strlen(source), original_sha1);
2146bf215546Sopenharmony_ci
2147bf215546Sopenharmony_ci#ifdef ENABLE_SHADER_CACHE
2148bf215546Sopenharmony_ci   GLcharARB *replacement;
2149bf215546Sopenharmony_ci
2150bf215546Sopenharmony_ci   /* Dump original shader source to MESA_SHADER_DUMP_PATH and replace
2151bf215546Sopenharmony_ci    * if corresponding entry found from MESA_SHADER_READ_PATH.
2152bf215546Sopenharmony_ci    */
2153bf215546Sopenharmony_ci   _mesa_dump_shader_source(sh->Stage, source, original_sha1);
2154bf215546Sopenharmony_ci
2155bf215546Sopenharmony_ci   replacement = _mesa_read_shader_source(sh->Stage, source, original_sha1);
2156bf215546Sopenharmony_ci   if (replacement) {
2157bf215546Sopenharmony_ci      free(source);
2158bf215546Sopenharmony_ci      source = replacement;
2159bf215546Sopenharmony_ci   }
2160bf215546Sopenharmony_ci#endif /* ENABLE_SHADER_CACHE */
2161bf215546Sopenharmony_ci
2162bf215546Sopenharmony_ci   set_shader_source(sh, source, original_sha1);
2163bf215546Sopenharmony_ci
2164bf215546Sopenharmony_ci   free(offsets);
2165bf215546Sopenharmony_ci}
2166bf215546Sopenharmony_ci
2167bf215546Sopenharmony_ci
2168bf215546Sopenharmony_civoid GLAPIENTRY
2169bf215546Sopenharmony_ci_mesa_ShaderSource_no_error(GLuint shaderObj, GLsizei count,
2170bf215546Sopenharmony_ci                            const GLchar *const *string, const GLint *length)
2171bf215546Sopenharmony_ci{
2172bf215546Sopenharmony_ci   GET_CURRENT_CONTEXT(ctx);
2173bf215546Sopenharmony_ci   shader_source(ctx, shaderObj, count, string, length, true);
2174bf215546Sopenharmony_ci}
2175bf215546Sopenharmony_ci
2176bf215546Sopenharmony_ci
2177bf215546Sopenharmony_civoid GLAPIENTRY
2178bf215546Sopenharmony_ci_mesa_ShaderSource(GLuint shaderObj, GLsizei count,
2179bf215546Sopenharmony_ci                   const GLchar *const *string, const GLint *length)
2180bf215546Sopenharmony_ci{
2181bf215546Sopenharmony_ci   GET_CURRENT_CONTEXT(ctx);
2182bf215546Sopenharmony_ci   shader_source(ctx, shaderObj, count, string, length, false);
2183bf215546Sopenharmony_ci}
2184bf215546Sopenharmony_ci
2185bf215546Sopenharmony_ci
2186bf215546Sopenharmony_cistatic ALWAYS_INLINE void
2187bf215546Sopenharmony_ciuse_program(GLuint program, bool no_error)
2188bf215546Sopenharmony_ci{
2189bf215546Sopenharmony_ci   GET_CURRENT_CONTEXT(ctx);
2190bf215546Sopenharmony_ci   struct gl_shader_program *shProg = NULL;
2191bf215546Sopenharmony_ci
2192bf215546Sopenharmony_ci   if (MESA_VERBOSE & VERBOSE_API)
2193bf215546Sopenharmony_ci      _mesa_debug(ctx, "glUseProgram %u\n", program);
2194bf215546Sopenharmony_ci
2195bf215546Sopenharmony_ci   if (no_error) {
2196bf215546Sopenharmony_ci      if (program) {
2197bf215546Sopenharmony_ci         shProg = _mesa_lookup_shader_program(ctx, program);
2198bf215546Sopenharmony_ci      }
2199bf215546Sopenharmony_ci   } else {
2200bf215546Sopenharmony_ci      if (_mesa_is_xfb_active_and_unpaused(ctx)) {
2201bf215546Sopenharmony_ci         _mesa_error(ctx, GL_INVALID_OPERATION,
2202bf215546Sopenharmony_ci                     "glUseProgram(transform feedback active)");
2203bf215546Sopenharmony_ci         return;
2204bf215546Sopenharmony_ci      }
2205bf215546Sopenharmony_ci
2206bf215546Sopenharmony_ci      if (program) {
2207bf215546Sopenharmony_ci         shProg =
2208bf215546Sopenharmony_ci            _mesa_lookup_shader_program_err(ctx, program, "glUseProgram");
2209bf215546Sopenharmony_ci         if (!shProg)
2210bf215546Sopenharmony_ci            return;
2211bf215546Sopenharmony_ci
2212bf215546Sopenharmony_ci         if (!shProg->data->LinkStatus) {
2213bf215546Sopenharmony_ci            _mesa_error(ctx, GL_INVALID_OPERATION,
2214bf215546Sopenharmony_ci                        "glUseProgram(program %u not linked)", program);
2215bf215546Sopenharmony_ci            return;
2216bf215546Sopenharmony_ci         }
2217bf215546Sopenharmony_ci
2218bf215546Sopenharmony_ci         /* debug code */
2219bf215546Sopenharmony_ci         if (ctx->_Shader->Flags & GLSL_USE_PROG) {
2220bf215546Sopenharmony_ci            print_shader_info(shProg);
2221bf215546Sopenharmony_ci         }
2222bf215546Sopenharmony_ci      }
2223bf215546Sopenharmony_ci   }
2224bf215546Sopenharmony_ci
2225bf215546Sopenharmony_ci   /* The ARB_separate_shader_object spec says:
2226bf215546Sopenharmony_ci    *
2227bf215546Sopenharmony_ci    *     "The executable code for an individual shader stage is taken from
2228bf215546Sopenharmony_ci    *     the current program for that stage.  If there is a current program
2229bf215546Sopenharmony_ci    *     object established by UseProgram, that program is considered current
2230bf215546Sopenharmony_ci    *     for all stages.  Otherwise, if there is a bound program pipeline
2231bf215546Sopenharmony_ci    *     object (section 2.14.PPO), the program bound to the appropriate
2232bf215546Sopenharmony_ci    *     stage of the pipeline object is considered current."
2233bf215546Sopenharmony_ci    */
2234bf215546Sopenharmony_ci   if (shProg) {
2235bf215546Sopenharmony_ci      /* Attach shader state to the binding point */
2236bf215546Sopenharmony_ci      _mesa_reference_pipeline_object(ctx, &ctx->_Shader, &ctx->Shader);
2237bf215546Sopenharmony_ci      /* Update the program */
2238bf215546Sopenharmony_ci      _mesa_use_shader_program(ctx, shProg);
2239bf215546Sopenharmony_ci   } else {
2240bf215546Sopenharmony_ci      /* Must be done first: detach the progam */
2241bf215546Sopenharmony_ci      _mesa_use_shader_program(ctx, shProg);
2242bf215546Sopenharmony_ci      /* Unattach shader_state binding point */
2243bf215546Sopenharmony_ci      _mesa_reference_pipeline_object(ctx, &ctx->_Shader,
2244bf215546Sopenharmony_ci                                      ctx->Pipeline.Default);
2245bf215546Sopenharmony_ci      /* If a pipeline was bound, rebind it */
2246bf215546Sopenharmony_ci      if (ctx->Pipeline.Current) {
2247bf215546Sopenharmony_ci         if (no_error)
2248bf215546Sopenharmony_ci            _mesa_BindProgramPipeline_no_error(ctx->Pipeline.Current->Name);
2249bf215546Sopenharmony_ci         else
2250bf215546Sopenharmony_ci            _mesa_BindProgramPipeline(ctx->Pipeline.Current->Name);
2251bf215546Sopenharmony_ci      }
2252bf215546Sopenharmony_ci   }
2253bf215546Sopenharmony_ci
2254bf215546Sopenharmony_ci   _mesa_update_vertex_processing_mode(ctx);
2255bf215546Sopenharmony_ci}
2256bf215546Sopenharmony_ci
2257bf215546Sopenharmony_ci
2258bf215546Sopenharmony_civoid GLAPIENTRY
2259bf215546Sopenharmony_ci_mesa_UseProgram_no_error(GLuint program)
2260bf215546Sopenharmony_ci{
2261bf215546Sopenharmony_ci   use_program(program, true);
2262bf215546Sopenharmony_ci}
2263bf215546Sopenharmony_ci
2264bf215546Sopenharmony_ci
2265bf215546Sopenharmony_civoid GLAPIENTRY
2266bf215546Sopenharmony_ci_mesa_UseProgram(GLuint program)
2267bf215546Sopenharmony_ci{
2268bf215546Sopenharmony_ci   use_program(program, false);
2269bf215546Sopenharmony_ci}
2270bf215546Sopenharmony_ci
2271bf215546Sopenharmony_ci
2272bf215546Sopenharmony_civoid GLAPIENTRY
2273bf215546Sopenharmony_ci_mesa_ValidateProgram(GLuint program)
2274bf215546Sopenharmony_ci{
2275bf215546Sopenharmony_ci   GET_CURRENT_CONTEXT(ctx);
2276bf215546Sopenharmony_ci   validate_program(ctx, program);
2277bf215546Sopenharmony_ci}
2278bf215546Sopenharmony_ci
2279bf215546Sopenharmony_ci
2280bf215546Sopenharmony_ci/**
2281bf215546Sopenharmony_ci * For OpenGL ES 2.0, GL_ARB_ES2_compatibility
2282bf215546Sopenharmony_ci */
2283bf215546Sopenharmony_civoid GLAPIENTRY
2284bf215546Sopenharmony_ci_mesa_GetShaderPrecisionFormat(GLenum shadertype, GLenum precisiontype,
2285bf215546Sopenharmony_ci                               GLint* range, GLint* precision)
2286bf215546Sopenharmony_ci{
2287bf215546Sopenharmony_ci   const struct gl_program_constants *limits;
2288bf215546Sopenharmony_ci   const struct gl_precision *p;
2289bf215546Sopenharmony_ci   GET_CURRENT_CONTEXT(ctx);
2290bf215546Sopenharmony_ci
2291bf215546Sopenharmony_ci   switch (shadertype) {
2292bf215546Sopenharmony_ci   case GL_VERTEX_SHADER:
2293bf215546Sopenharmony_ci      limits = &ctx->Const.Program[MESA_SHADER_VERTEX];
2294bf215546Sopenharmony_ci      break;
2295bf215546Sopenharmony_ci   case GL_FRAGMENT_SHADER:
2296bf215546Sopenharmony_ci      limits = &ctx->Const.Program[MESA_SHADER_FRAGMENT];
2297bf215546Sopenharmony_ci      break;
2298bf215546Sopenharmony_ci   default:
2299bf215546Sopenharmony_ci      _mesa_error(ctx, GL_INVALID_ENUM,
2300bf215546Sopenharmony_ci                  "glGetShaderPrecisionFormat(shadertype)");
2301bf215546Sopenharmony_ci      return;
2302bf215546Sopenharmony_ci   }
2303bf215546Sopenharmony_ci
2304bf215546Sopenharmony_ci   switch (precisiontype) {
2305bf215546Sopenharmony_ci   case GL_LOW_FLOAT:
2306bf215546Sopenharmony_ci      p = &limits->LowFloat;
2307bf215546Sopenharmony_ci      break;
2308bf215546Sopenharmony_ci   case GL_MEDIUM_FLOAT:
2309bf215546Sopenharmony_ci      p = &limits->MediumFloat;
2310bf215546Sopenharmony_ci      break;
2311bf215546Sopenharmony_ci   case GL_HIGH_FLOAT:
2312bf215546Sopenharmony_ci      p = &limits->HighFloat;
2313bf215546Sopenharmony_ci      break;
2314bf215546Sopenharmony_ci   case GL_LOW_INT:
2315bf215546Sopenharmony_ci      p = &limits->LowInt;
2316bf215546Sopenharmony_ci      break;
2317bf215546Sopenharmony_ci   case GL_MEDIUM_INT:
2318bf215546Sopenharmony_ci      p = &limits->MediumInt;
2319bf215546Sopenharmony_ci      break;
2320bf215546Sopenharmony_ci   case GL_HIGH_INT:
2321bf215546Sopenharmony_ci      p = &limits->HighInt;
2322bf215546Sopenharmony_ci      break;
2323bf215546Sopenharmony_ci   default:
2324bf215546Sopenharmony_ci      _mesa_error(ctx, GL_INVALID_ENUM,
2325bf215546Sopenharmony_ci                  "glGetShaderPrecisionFormat(precisiontype)");
2326bf215546Sopenharmony_ci      return;
2327bf215546Sopenharmony_ci   }
2328bf215546Sopenharmony_ci
2329bf215546Sopenharmony_ci   range[0] = p->RangeMin;
2330bf215546Sopenharmony_ci   range[1] = p->RangeMax;
2331bf215546Sopenharmony_ci   precision[0] = p->Precision;
2332bf215546Sopenharmony_ci}
2333bf215546Sopenharmony_ci
2334bf215546Sopenharmony_ci
2335bf215546Sopenharmony_ci/**
2336bf215546Sopenharmony_ci * For OpenGL ES 2.0, GL_ARB_ES2_compatibility
2337bf215546Sopenharmony_ci */
2338bf215546Sopenharmony_civoid GLAPIENTRY
2339bf215546Sopenharmony_ci_mesa_ReleaseShaderCompiler(void)
2340bf215546Sopenharmony_ci{
2341bf215546Sopenharmony_ci   GET_CURRENT_CONTEXT(ctx);
2342bf215546Sopenharmony_ci
2343bf215546Sopenharmony_ci   if (ctx->shader_builtin_ref) {
2344bf215546Sopenharmony_ci      _mesa_glsl_builtin_functions_decref();
2345bf215546Sopenharmony_ci      ctx->shader_builtin_ref = false;
2346bf215546Sopenharmony_ci   }
2347bf215546Sopenharmony_ci}
2348bf215546Sopenharmony_ci
2349bf215546Sopenharmony_ci
2350bf215546Sopenharmony_ci/**
2351bf215546Sopenharmony_ci * For OpenGL ES 2.0, GL_ARB_ES2_compatibility
2352bf215546Sopenharmony_ci */
2353bf215546Sopenharmony_civoid GLAPIENTRY
2354bf215546Sopenharmony_ci_mesa_ShaderBinary(GLint n, const GLuint* shaders, GLenum binaryformat,
2355bf215546Sopenharmony_ci                   const void* binary, GLint length)
2356bf215546Sopenharmony_ci{
2357bf215546Sopenharmony_ci   GET_CURRENT_CONTEXT(ctx);
2358bf215546Sopenharmony_ci   struct gl_shader **sh;
2359bf215546Sopenharmony_ci
2360bf215546Sopenharmony_ci   /* Page 68, section 7.2 'Shader Binaries" of the of the OpenGL ES 3.1, and
2361bf215546Sopenharmony_ci    * page 88 of the OpenGL 4.5 specs state:
2362bf215546Sopenharmony_ci    *
2363bf215546Sopenharmony_ci    *     "An INVALID_VALUE error is generated if count or length is negative.
2364bf215546Sopenharmony_ci    *      An INVALID_ENUM error is generated if binaryformat is not a supported
2365bf215546Sopenharmony_ci    *      format returned in SHADER_BINARY_FORMATS."
2366bf215546Sopenharmony_ci    */
2367bf215546Sopenharmony_ci   if (n < 0 || length < 0) {
2368bf215546Sopenharmony_ci      _mesa_error(ctx, GL_INVALID_VALUE, "glShaderBinary(count or length < 0)");
2369bf215546Sopenharmony_ci      return;
2370bf215546Sopenharmony_ci   }
2371bf215546Sopenharmony_ci
2372bf215546Sopenharmony_ci   /* Get all shader objects at once so we can make the operation
2373bf215546Sopenharmony_ci    * all-or-nothing.
2374bf215546Sopenharmony_ci    */
2375bf215546Sopenharmony_ci   if (n > SIZE_MAX / sizeof(*sh)) {
2376bf215546Sopenharmony_ci      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glShaderBinary(count)");
2377bf215546Sopenharmony_ci      return;
2378bf215546Sopenharmony_ci   }
2379bf215546Sopenharmony_ci
2380bf215546Sopenharmony_ci   sh = alloca(sizeof(*sh) * (size_t)n);
2381bf215546Sopenharmony_ci   if (!sh) {
2382bf215546Sopenharmony_ci      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glShaderBinary");
2383bf215546Sopenharmony_ci      return;
2384bf215546Sopenharmony_ci   }
2385bf215546Sopenharmony_ci
2386bf215546Sopenharmony_ci   for (int i = 0; i < n; ++i) {
2387bf215546Sopenharmony_ci      sh[i] = _mesa_lookup_shader_err(ctx, shaders[i], "glShaderBinary");
2388bf215546Sopenharmony_ci      if (!sh[i])
2389bf215546Sopenharmony_ci         return;
2390bf215546Sopenharmony_ci   }
2391bf215546Sopenharmony_ci
2392bf215546Sopenharmony_ci   if (binaryformat == GL_SHADER_BINARY_FORMAT_SPIR_V_ARB) {
2393bf215546Sopenharmony_ci      if (!ctx->Extensions.ARB_gl_spirv) {
2394bf215546Sopenharmony_ci         _mesa_error(ctx, GL_INVALID_OPERATION, "glShaderBinary(SPIR-V)");
2395bf215546Sopenharmony_ci      } else if (n > 0) {
2396bf215546Sopenharmony_ci         _mesa_spirv_shader_binary(ctx, (unsigned) n, sh, binary,
2397bf215546Sopenharmony_ci                                   (size_t) length);
2398bf215546Sopenharmony_ci      }
2399bf215546Sopenharmony_ci
2400bf215546Sopenharmony_ci      return;
2401bf215546Sopenharmony_ci   }
2402bf215546Sopenharmony_ci
2403bf215546Sopenharmony_ci   _mesa_error(ctx, GL_INVALID_ENUM, "glShaderBinary(format)");
2404bf215546Sopenharmony_ci}
2405bf215546Sopenharmony_ci
2406bf215546Sopenharmony_ci
2407bf215546Sopenharmony_civoid GLAPIENTRY
2408bf215546Sopenharmony_ci_mesa_GetProgramBinary(GLuint program, GLsizei bufSize, GLsizei *length,
2409bf215546Sopenharmony_ci                       GLenum *binaryFormat, GLvoid *binary)
2410bf215546Sopenharmony_ci{
2411bf215546Sopenharmony_ci   struct gl_shader_program *shProg;
2412bf215546Sopenharmony_ci   GLsizei length_dummy;
2413bf215546Sopenharmony_ci   GET_CURRENT_CONTEXT(ctx);
2414bf215546Sopenharmony_ci
2415bf215546Sopenharmony_ci   if (bufSize < 0){
2416bf215546Sopenharmony_ci      _mesa_error(ctx, GL_INVALID_VALUE, "glGetProgramBinary(bufSize < 0)");
2417bf215546Sopenharmony_ci      return;
2418bf215546Sopenharmony_ci   }
2419bf215546Sopenharmony_ci
2420bf215546Sopenharmony_ci   shProg = _mesa_lookup_shader_program_err(ctx, program, "glGetProgramBinary");
2421bf215546Sopenharmony_ci   if (!shProg)
2422bf215546Sopenharmony_ci      return;
2423bf215546Sopenharmony_ci
2424bf215546Sopenharmony_ci   /* The ARB_get_program_binary spec says:
2425bf215546Sopenharmony_ci    *
2426bf215546Sopenharmony_ci    *     "If <length> is NULL, then no length is returned."
2427bf215546Sopenharmony_ci    *
2428bf215546Sopenharmony_ci    * Ensure that length always points to valid storage to avoid multiple NULL
2429bf215546Sopenharmony_ci    * pointer checks below.
2430bf215546Sopenharmony_ci    */
2431bf215546Sopenharmony_ci   if (length == NULL)
2432bf215546Sopenharmony_ci      length = &length_dummy;
2433bf215546Sopenharmony_ci
2434bf215546Sopenharmony_ci
2435bf215546Sopenharmony_ci   /* The ARB_get_program_binary spec says:
2436bf215546Sopenharmony_ci    *
2437bf215546Sopenharmony_ci    *     "When a program object's LINK_STATUS is FALSE, its program binary
2438bf215546Sopenharmony_ci    *     length is zero, and a call to GetProgramBinary will generate an
2439bf215546Sopenharmony_ci    *     INVALID_OPERATION error.
2440bf215546Sopenharmony_ci    */
2441bf215546Sopenharmony_ci   if (!shProg->data->LinkStatus) {
2442bf215546Sopenharmony_ci      _mesa_error(ctx, GL_INVALID_OPERATION,
2443bf215546Sopenharmony_ci                  "glGetProgramBinary(program %u not linked)",
2444bf215546Sopenharmony_ci                  shProg->Name);
2445bf215546Sopenharmony_ci      *length = 0;
2446bf215546Sopenharmony_ci      return;
2447bf215546Sopenharmony_ci   }
2448bf215546Sopenharmony_ci
2449bf215546Sopenharmony_ci   if (ctx->Const.NumProgramBinaryFormats == 0) {
2450bf215546Sopenharmony_ci      *length = 0;
2451bf215546Sopenharmony_ci      _mesa_error(ctx, GL_INVALID_OPERATION,
2452bf215546Sopenharmony_ci                  "glGetProgramBinary(driver supports zero binary formats)");
2453bf215546Sopenharmony_ci   } else {
2454bf215546Sopenharmony_ci      _mesa_get_program_binary(ctx, shProg, bufSize, length, binaryFormat,
2455bf215546Sopenharmony_ci                               binary);
2456bf215546Sopenharmony_ci      assert(*length == 0 || *binaryFormat == GL_PROGRAM_BINARY_FORMAT_MESA);
2457bf215546Sopenharmony_ci   }
2458bf215546Sopenharmony_ci}
2459bf215546Sopenharmony_ci
2460bf215546Sopenharmony_civoid GLAPIENTRY
2461bf215546Sopenharmony_ci_mesa_ProgramBinary(GLuint program, GLenum binaryFormat,
2462bf215546Sopenharmony_ci                    const GLvoid *binary, GLsizei length)
2463bf215546Sopenharmony_ci{
2464bf215546Sopenharmony_ci   struct gl_shader_program *shProg;
2465bf215546Sopenharmony_ci   GET_CURRENT_CONTEXT(ctx);
2466bf215546Sopenharmony_ci
2467bf215546Sopenharmony_ci   shProg = _mesa_lookup_shader_program_err(ctx, program, "glProgramBinary");
2468bf215546Sopenharmony_ci   if (!shProg)
2469bf215546Sopenharmony_ci      return;
2470bf215546Sopenharmony_ci
2471bf215546Sopenharmony_ci   _mesa_clear_shader_program_data(ctx, shProg);
2472bf215546Sopenharmony_ci   shProg->data = _mesa_create_shader_program_data();
2473bf215546Sopenharmony_ci
2474bf215546Sopenharmony_ci   /* Section 2.3.1 (Errors) of the OpenGL 4.5 spec says:
2475bf215546Sopenharmony_ci    *
2476bf215546Sopenharmony_ci    *     "If a negative number is provided where an argument of type sizei or
2477bf215546Sopenharmony_ci    *     sizeiptr is specified, an INVALID_VALUE error is generated."
2478bf215546Sopenharmony_ci    */
2479bf215546Sopenharmony_ci   if (length < 0) {
2480bf215546Sopenharmony_ci      _mesa_error(ctx, GL_INVALID_VALUE, "glProgramBinary(length < 0)");
2481bf215546Sopenharmony_ci      return;
2482bf215546Sopenharmony_ci   }
2483bf215546Sopenharmony_ci
2484bf215546Sopenharmony_ci   if (ctx->Const.NumProgramBinaryFormats == 0 ||
2485bf215546Sopenharmony_ci       binaryFormat != GL_PROGRAM_BINARY_FORMAT_MESA) {
2486bf215546Sopenharmony_ci      /* The ARB_get_program_binary spec says:
2487bf215546Sopenharmony_ci       *
2488bf215546Sopenharmony_ci       *     "<binaryFormat> and <binary> must be those returned by a previous
2489bf215546Sopenharmony_ci       *     call to GetProgramBinary, and <length> must be the length of the
2490bf215546Sopenharmony_ci       *     program binary as returned by GetProgramBinary or GetProgramiv with
2491bf215546Sopenharmony_ci       *     <pname> PROGRAM_BINARY_LENGTH. Loading the program binary will fail,
2492bf215546Sopenharmony_ci       *     setting the LINK_STATUS of <program> to FALSE, if these conditions
2493bf215546Sopenharmony_ci       *     are not met."
2494bf215546Sopenharmony_ci       *
2495bf215546Sopenharmony_ci       * Since any value of binaryFormat passed "is not one of those specified as
2496bf215546Sopenharmony_ci       * allowable for [this] command, an INVALID_ENUM error is generated."
2497bf215546Sopenharmony_ci       */
2498bf215546Sopenharmony_ci      shProg->data->LinkStatus = LINKING_FAILURE;
2499bf215546Sopenharmony_ci      _mesa_error(ctx, GL_INVALID_ENUM, "glProgramBinary");
2500bf215546Sopenharmony_ci   } else {
2501bf215546Sopenharmony_ci      _mesa_program_binary(ctx, shProg, binaryFormat, binary, length);
2502bf215546Sopenharmony_ci   }
2503bf215546Sopenharmony_ci}
2504bf215546Sopenharmony_ci
2505bf215546Sopenharmony_ci
2506bf215546Sopenharmony_cistatic ALWAYS_INLINE void
2507bf215546Sopenharmony_ciprogram_parameteri(struct gl_context *ctx, struct gl_shader_program *shProg,
2508bf215546Sopenharmony_ci                   GLuint pname, GLint value, bool no_error)
2509bf215546Sopenharmony_ci{
2510bf215546Sopenharmony_ci   switch (pname) {
2511bf215546Sopenharmony_ci   case GL_PROGRAM_BINARY_RETRIEVABLE_HINT:
2512bf215546Sopenharmony_ci      /* This enum isn't part of the OES extension for OpenGL ES 2.0, but it
2513bf215546Sopenharmony_ci       * is part of OpenGL ES 3.0.  For the ES2 case, this function shouldn't
2514bf215546Sopenharmony_ci       * even be in the dispatch table, so we shouldn't need to expclicitly
2515bf215546Sopenharmony_ci       * check here.
2516bf215546Sopenharmony_ci       *
2517bf215546Sopenharmony_ci       * On desktop, we ignore the 3.0+ requirement because it is silly.
2518bf215546Sopenharmony_ci       */
2519bf215546Sopenharmony_ci
2520bf215546Sopenharmony_ci      /* The ARB_get_program_binary extension spec says:
2521bf215546Sopenharmony_ci       *
2522bf215546Sopenharmony_ci       *     "An INVALID_VALUE error is generated if the <value> argument to
2523bf215546Sopenharmony_ci       *     ProgramParameteri is not TRUE or FALSE."
2524bf215546Sopenharmony_ci       */
2525bf215546Sopenharmony_ci      if (!no_error && value != GL_TRUE && value != GL_FALSE) {
2526bf215546Sopenharmony_ci         goto invalid_value;
2527bf215546Sopenharmony_ci      }
2528bf215546Sopenharmony_ci
2529bf215546Sopenharmony_ci      /* No need to notify the driver.  Any changes will actually take effect
2530bf215546Sopenharmony_ci       * the next time the shader is linked.
2531bf215546Sopenharmony_ci       *
2532bf215546Sopenharmony_ci       * The ARB_get_program_binary extension spec says:
2533bf215546Sopenharmony_ci       *
2534bf215546Sopenharmony_ci       *     "To indicate that a program binary is likely to be retrieved,
2535bf215546Sopenharmony_ci       *     ProgramParameteri should be called with <pname>
2536bf215546Sopenharmony_ci       *     PROGRAM_BINARY_RETRIEVABLE_HINT and <value> TRUE. This setting
2537bf215546Sopenharmony_ci       *     will not be in effect until the next time LinkProgram or
2538bf215546Sopenharmony_ci       *     ProgramBinary has been called successfully."
2539bf215546Sopenharmony_ci       *
2540bf215546Sopenharmony_ci       * The resolution of issue 9 in the extension spec also says:
2541bf215546Sopenharmony_ci       *
2542bf215546Sopenharmony_ci       *     "The application may use the PROGRAM_BINARY_RETRIEVABLE_HINT hint
2543bf215546Sopenharmony_ci       *     to indicate to the GL implementation that this program will
2544bf215546Sopenharmony_ci       *     likely be saved with GetProgramBinary at some point. This will
2545bf215546Sopenharmony_ci       *     give the GL implementation the opportunity to track any state
2546bf215546Sopenharmony_ci       *     changes made to the program before being saved such that when it
2547bf215546Sopenharmony_ci       *     is loaded again a recompile can be avoided."
2548bf215546Sopenharmony_ci       */
2549bf215546Sopenharmony_ci      shProg->BinaryRetrievableHintPending = value;
2550bf215546Sopenharmony_ci      return;
2551bf215546Sopenharmony_ci
2552bf215546Sopenharmony_ci   case GL_PROGRAM_SEPARABLE:
2553bf215546Sopenharmony_ci      /* Spec imply that the behavior is the same as ARB_get_program_binary
2554bf215546Sopenharmony_ci       * Chapter 7.3 Program Objects
2555bf215546Sopenharmony_ci       */
2556bf215546Sopenharmony_ci      if (!no_error && value != GL_TRUE && value != GL_FALSE) {
2557bf215546Sopenharmony_ci         goto invalid_value;
2558bf215546Sopenharmony_ci      }
2559bf215546Sopenharmony_ci      shProg->SeparateShader = value;
2560bf215546Sopenharmony_ci      return;
2561bf215546Sopenharmony_ci
2562bf215546Sopenharmony_ci   default:
2563bf215546Sopenharmony_ci      if (!no_error) {
2564bf215546Sopenharmony_ci         _mesa_error(ctx, GL_INVALID_ENUM, "glProgramParameteri(pname=%s)",
2565bf215546Sopenharmony_ci                     _mesa_enum_to_string(pname));
2566bf215546Sopenharmony_ci      }
2567bf215546Sopenharmony_ci      return;
2568bf215546Sopenharmony_ci   }
2569bf215546Sopenharmony_ci
2570bf215546Sopenharmony_ciinvalid_value:
2571bf215546Sopenharmony_ci   _mesa_error(ctx, GL_INVALID_VALUE,
2572bf215546Sopenharmony_ci               "glProgramParameteri(pname=%s, value=%d): "
2573bf215546Sopenharmony_ci               "value must be 0 or 1.",
2574bf215546Sopenharmony_ci               _mesa_enum_to_string(pname),
2575bf215546Sopenharmony_ci               value);
2576bf215546Sopenharmony_ci}
2577bf215546Sopenharmony_ci
2578bf215546Sopenharmony_ci
2579bf215546Sopenharmony_civoid GLAPIENTRY
2580bf215546Sopenharmony_ci_mesa_ProgramParameteri_no_error(GLuint program, GLenum pname, GLint value)
2581bf215546Sopenharmony_ci{
2582bf215546Sopenharmony_ci   GET_CURRENT_CONTEXT(ctx);
2583bf215546Sopenharmony_ci
2584bf215546Sopenharmony_ci   struct gl_shader_program *shProg = _mesa_lookup_shader_program(ctx, program);
2585bf215546Sopenharmony_ci   program_parameteri(ctx, shProg, pname, value, true);
2586bf215546Sopenharmony_ci}
2587bf215546Sopenharmony_ci
2588bf215546Sopenharmony_ci
2589bf215546Sopenharmony_civoid GLAPIENTRY
2590bf215546Sopenharmony_ci_mesa_ProgramParameteri(GLuint program, GLenum pname, GLint value)
2591bf215546Sopenharmony_ci{
2592bf215546Sopenharmony_ci   struct gl_shader_program *shProg;
2593bf215546Sopenharmony_ci   GET_CURRENT_CONTEXT(ctx);
2594bf215546Sopenharmony_ci
2595bf215546Sopenharmony_ci   shProg = _mesa_lookup_shader_program_err(ctx, program,
2596bf215546Sopenharmony_ci                                            "glProgramParameteri");
2597bf215546Sopenharmony_ci   if (!shProg)
2598bf215546Sopenharmony_ci      return;
2599bf215546Sopenharmony_ci
2600bf215546Sopenharmony_ci   program_parameteri(ctx, shProg, pname, value, false);
2601bf215546Sopenharmony_ci}
2602bf215546Sopenharmony_ci
2603bf215546Sopenharmony_ci
2604bf215546Sopenharmony_civoid
2605bf215546Sopenharmony_ci_mesa_use_program(struct gl_context *ctx, gl_shader_stage stage,
2606bf215546Sopenharmony_ci                  struct gl_shader_program *shProg, struct gl_program *prog,
2607bf215546Sopenharmony_ci                  struct gl_pipeline_object *shTarget)
2608bf215546Sopenharmony_ci{
2609bf215546Sopenharmony_ci   struct gl_program **target;
2610bf215546Sopenharmony_ci
2611bf215546Sopenharmony_ci   target = &shTarget->CurrentProgram[stage];
2612bf215546Sopenharmony_ci   if (prog) {
2613bf215546Sopenharmony_ci      _mesa_program_init_subroutine_defaults(ctx, prog);
2614bf215546Sopenharmony_ci   }
2615bf215546Sopenharmony_ci
2616bf215546Sopenharmony_ci   if (*target != prog) {
2617bf215546Sopenharmony_ci      /* Program is current, flush it */
2618bf215546Sopenharmony_ci      if (shTarget == ctx->_Shader) {
2619bf215546Sopenharmony_ci         FLUSH_VERTICES(ctx, _NEW_PROGRAM | _NEW_PROGRAM_CONSTANTS, 0);
2620bf215546Sopenharmony_ci      }
2621bf215546Sopenharmony_ci
2622bf215546Sopenharmony_ci      _mesa_reference_shader_program(ctx,
2623bf215546Sopenharmony_ci                                     &shTarget->ReferencedPrograms[stage],
2624bf215546Sopenharmony_ci                                     shProg);
2625bf215546Sopenharmony_ci      _mesa_reference_program(ctx, target, prog);
2626bf215546Sopenharmony_ci      _mesa_update_allow_draw_out_of_order(ctx);
2627bf215546Sopenharmony_ci      _mesa_update_valid_to_render_state(ctx);
2628bf215546Sopenharmony_ci      if (stage == MESA_SHADER_VERTEX)
2629bf215546Sopenharmony_ci         _mesa_update_vertex_processing_mode(ctx);
2630bf215546Sopenharmony_ci      return;
2631bf215546Sopenharmony_ci   }
2632bf215546Sopenharmony_ci
2633bf215546Sopenharmony_ci}
2634bf215546Sopenharmony_ci
2635bf215546Sopenharmony_ci
2636bf215546Sopenharmony_ci/**
2637bf215546Sopenharmony_ci * Copy program-specific data generated by linking from the gl_shader_program
2638bf215546Sopenharmony_ci * object to the gl_program object referred to by the gl_linked_shader.
2639bf215546Sopenharmony_ci *
2640bf215546Sopenharmony_ci * This function expects _mesa_reference_program() to have been previously
2641bf215546Sopenharmony_ci * called setting the gl_linked_shaders program reference.
2642bf215546Sopenharmony_ci */
2643bf215546Sopenharmony_civoid
2644bf215546Sopenharmony_ci_mesa_copy_linked_program_data(const struct gl_shader_program *src,
2645bf215546Sopenharmony_ci                               struct gl_linked_shader *dst_sh)
2646bf215546Sopenharmony_ci{
2647bf215546Sopenharmony_ci   assert(dst_sh->Program);
2648bf215546Sopenharmony_ci
2649bf215546Sopenharmony_ci   struct gl_program *dst = dst_sh->Program;
2650bf215546Sopenharmony_ci
2651bf215546Sopenharmony_ci   dst->info.separate_shader = src->SeparateShader;
2652bf215546Sopenharmony_ci
2653bf215546Sopenharmony_ci   switch (dst_sh->Stage) {
2654bf215546Sopenharmony_ci   case MESA_SHADER_GEOMETRY: {
2655bf215546Sopenharmony_ci      dst->info.gs.vertices_in = src->Geom.VerticesIn;
2656bf215546Sopenharmony_ci      dst->info.gs.uses_end_primitive = src->Geom.UsesEndPrimitive;
2657bf215546Sopenharmony_ci      dst->info.gs.active_stream_mask = src->Geom.ActiveStreamMask;
2658bf215546Sopenharmony_ci      break;
2659bf215546Sopenharmony_ci   }
2660bf215546Sopenharmony_ci   case MESA_SHADER_FRAGMENT: {
2661bf215546Sopenharmony_ci      dst->info.fs.depth_layout = src->FragDepthLayout;
2662bf215546Sopenharmony_ci      break;
2663bf215546Sopenharmony_ci   }
2664bf215546Sopenharmony_ci   default:
2665bf215546Sopenharmony_ci      break;
2666bf215546Sopenharmony_ci   }
2667bf215546Sopenharmony_ci}
2668bf215546Sopenharmony_ci
2669bf215546Sopenharmony_ci/**
2670bf215546Sopenharmony_ci * ARB_separate_shader_objects: Compile & Link Program
2671bf215546Sopenharmony_ci */
2672bf215546Sopenharmony_ciGLuint GLAPIENTRY
2673bf215546Sopenharmony_ci_mesa_CreateShaderProgramv(GLenum type, GLsizei count,
2674bf215546Sopenharmony_ci                           const GLchar* const *strings)
2675bf215546Sopenharmony_ci{
2676bf215546Sopenharmony_ci   GET_CURRENT_CONTEXT(ctx);
2677bf215546Sopenharmony_ci
2678bf215546Sopenharmony_ci   const GLuint shader = create_shader_err(ctx, type, "glCreateShaderProgramv");
2679bf215546Sopenharmony_ci   GLuint program = 0;
2680bf215546Sopenharmony_ci
2681bf215546Sopenharmony_ci   /*
2682bf215546Sopenharmony_ci    * According to OpenGL 4.5 and OpenGL ES 3.1 standards, section 7.3:
2683bf215546Sopenharmony_ci    * GL_INVALID_VALUE should be generated if count < 0
2684bf215546Sopenharmony_ci    */
2685bf215546Sopenharmony_ci   if (count < 0) {
2686bf215546Sopenharmony_ci      _mesa_error(ctx, GL_INVALID_VALUE, "glCreateShaderProgram (count < 0)");
2687bf215546Sopenharmony_ci      return program;
2688bf215546Sopenharmony_ci   }
2689bf215546Sopenharmony_ci
2690bf215546Sopenharmony_ci   if (shader) {
2691bf215546Sopenharmony_ci      struct gl_shader *sh = _mesa_lookup_shader(ctx, shader);
2692bf215546Sopenharmony_ci
2693bf215546Sopenharmony_ci      _mesa_ShaderSource(shader, count, strings, NULL);
2694bf215546Sopenharmony_ci      _mesa_compile_shader(ctx, sh);
2695bf215546Sopenharmony_ci
2696bf215546Sopenharmony_ci      program = create_shader_program(ctx);
2697bf215546Sopenharmony_ci      if (program) {
2698bf215546Sopenharmony_ci	 struct gl_shader_program *shProg;
2699bf215546Sopenharmony_ci	 GLint compiled = GL_FALSE;
2700bf215546Sopenharmony_ci
2701bf215546Sopenharmony_ci	 shProg = _mesa_lookup_shader_program(ctx, program);
2702bf215546Sopenharmony_ci
2703bf215546Sopenharmony_ci	 shProg->SeparateShader = GL_TRUE;
2704bf215546Sopenharmony_ci
2705bf215546Sopenharmony_ci	 get_shaderiv(ctx, shader, GL_COMPILE_STATUS, &compiled);
2706bf215546Sopenharmony_ci	 if (compiled) {
2707bf215546Sopenharmony_ci	    attach_shader_err(ctx, program, shader, "glCreateShaderProgramv");
2708bf215546Sopenharmony_ci	    _mesa_link_program(ctx, shProg);
2709bf215546Sopenharmony_ci	    detach_shader_error(ctx, program, shader);
2710bf215546Sopenharmony_ci
2711bf215546Sopenharmony_ci#if 0
2712bf215546Sopenharmony_ci	    /* Possibly... */
2713bf215546Sopenharmony_ci	    if (active-user-defined-varyings-in-linked-program) {
2714bf215546Sopenharmony_ci	       append-error-to-info-log;
2715bf215546Sopenharmony_ci               shProg->data->LinkStatus = LINKING_FAILURE;
2716bf215546Sopenharmony_ci	    }
2717bf215546Sopenharmony_ci#endif
2718bf215546Sopenharmony_ci	 }
2719bf215546Sopenharmony_ci         if (sh->InfoLog)
2720bf215546Sopenharmony_ci            ralloc_strcat(&shProg->data->InfoLog, sh->InfoLog);
2721bf215546Sopenharmony_ci      }
2722bf215546Sopenharmony_ci
2723bf215546Sopenharmony_ci      delete_shader(ctx, shader);
2724bf215546Sopenharmony_ci   }
2725bf215546Sopenharmony_ci
2726bf215546Sopenharmony_ci   return program;
2727bf215546Sopenharmony_ci}
2728bf215546Sopenharmony_ci
2729bf215546Sopenharmony_ci
2730bf215546Sopenharmony_cistatic void
2731bf215546Sopenharmony_ciset_patch_vertices(struct gl_context *ctx, GLint value)
2732bf215546Sopenharmony_ci{
2733bf215546Sopenharmony_ci   if (ctx->TessCtrlProgram.patch_vertices != value) {
2734bf215546Sopenharmony_ci      FLUSH_VERTICES(ctx, 0, GL_CURRENT_BIT);
2735bf215546Sopenharmony_ci      ctx->NewDriverState |= ST_NEW_TESS_STATE;
2736bf215546Sopenharmony_ci      ctx->TessCtrlProgram.patch_vertices = value;
2737bf215546Sopenharmony_ci   }
2738bf215546Sopenharmony_ci}
2739bf215546Sopenharmony_ci
2740bf215546Sopenharmony_ci/**
2741bf215546Sopenharmony_ci * For GL_ARB_tessellation_shader
2742bf215546Sopenharmony_ci */
2743bf215546Sopenharmony_civoid GLAPIENTRY
2744bf215546Sopenharmony_ci_mesa_PatchParameteri_no_error(GLenum pname, GLint value)
2745bf215546Sopenharmony_ci{
2746bf215546Sopenharmony_ci   GET_CURRENT_CONTEXT(ctx);
2747bf215546Sopenharmony_ci
2748bf215546Sopenharmony_ci   set_patch_vertices(ctx, value);
2749bf215546Sopenharmony_ci}
2750bf215546Sopenharmony_ci
2751bf215546Sopenharmony_ci
2752bf215546Sopenharmony_ciextern void GLAPIENTRY
2753bf215546Sopenharmony_ci_mesa_PatchParameteri(GLenum pname, GLint value)
2754bf215546Sopenharmony_ci{
2755bf215546Sopenharmony_ci   GET_CURRENT_CONTEXT(ctx);
2756bf215546Sopenharmony_ci
2757bf215546Sopenharmony_ci   if (!_mesa_has_tessellation(ctx)) {
2758bf215546Sopenharmony_ci      _mesa_error(ctx, GL_INVALID_OPERATION, "glPatchParameteri");
2759bf215546Sopenharmony_ci      return;
2760bf215546Sopenharmony_ci   }
2761bf215546Sopenharmony_ci
2762bf215546Sopenharmony_ci   if (pname != GL_PATCH_VERTICES) {
2763bf215546Sopenharmony_ci      _mesa_error(ctx, GL_INVALID_ENUM, "glPatchParameteri");
2764bf215546Sopenharmony_ci      return;
2765bf215546Sopenharmony_ci   }
2766bf215546Sopenharmony_ci
2767bf215546Sopenharmony_ci   if (value <= 0 || value > ctx->Const.MaxPatchVertices) {
2768bf215546Sopenharmony_ci      _mesa_error(ctx, GL_INVALID_VALUE, "glPatchParameteri");
2769bf215546Sopenharmony_ci      return;
2770bf215546Sopenharmony_ci   }
2771bf215546Sopenharmony_ci
2772bf215546Sopenharmony_ci   set_patch_vertices(ctx, value);
2773bf215546Sopenharmony_ci}
2774bf215546Sopenharmony_ci
2775bf215546Sopenharmony_ci
2776bf215546Sopenharmony_ciextern void GLAPIENTRY
2777bf215546Sopenharmony_ci_mesa_PatchParameterfv(GLenum pname, const GLfloat *values)
2778bf215546Sopenharmony_ci{
2779bf215546Sopenharmony_ci   GET_CURRENT_CONTEXT(ctx);
2780bf215546Sopenharmony_ci
2781bf215546Sopenharmony_ci   if (!_mesa_has_tessellation(ctx)) {
2782bf215546Sopenharmony_ci      _mesa_error(ctx, GL_INVALID_OPERATION, "glPatchParameterfv");
2783bf215546Sopenharmony_ci      return;
2784bf215546Sopenharmony_ci   }
2785bf215546Sopenharmony_ci
2786bf215546Sopenharmony_ci   switch(pname) {
2787bf215546Sopenharmony_ci   case GL_PATCH_DEFAULT_OUTER_LEVEL:
2788bf215546Sopenharmony_ci      FLUSH_VERTICES(ctx, 0, 0);
2789bf215546Sopenharmony_ci      memcpy(ctx->TessCtrlProgram.patch_default_outer_level, values,
2790bf215546Sopenharmony_ci             4 * sizeof(GLfloat));
2791bf215546Sopenharmony_ci      ctx->NewDriverState |= ST_NEW_TESS_STATE;
2792bf215546Sopenharmony_ci      return;
2793bf215546Sopenharmony_ci   case GL_PATCH_DEFAULT_INNER_LEVEL:
2794bf215546Sopenharmony_ci      FLUSH_VERTICES(ctx, 0, 0);
2795bf215546Sopenharmony_ci      memcpy(ctx->TessCtrlProgram.patch_default_inner_level, values,
2796bf215546Sopenharmony_ci             2 * sizeof(GLfloat));
2797bf215546Sopenharmony_ci      ctx->NewDriverState |= ST_NEW_TESS_STATE;
2798bf215546Sopenharmony_ci      return;
2799bf215546Sopenharmony_ci   default:
2800bf215546Sopenharmony_ci      _mesa_error(ctx, GL_INVALID_ENUM, "glPatchParameterfv");
2801bf215546Sopenharmony_ci      return;
2802bf215546Sopenharmony_ci   }
2803bf215546Sopenharmony_ci}
2804bf215546Sopenharmony_ci
2805bf215546Sopenharmony_ci/**
2806bf215546Sopenharmony_ci * ARB_shader_subroutine
2807bf215546Sopenharmony_ci */
2808bf215546Sopenharmony_ciGLint GLAPIENTRY
2809bf215546Sopenharmony_ci_mesa_GetSubroutineUniformLocation(GLuint program, GLenum shadertype,
2810bf215546Sopenharmony_ci                                   const GLchar *name)
2811bf215546Sopenharmony_ci{
2812bf215546Sopenharmony_ci   GET_CURRENT_CONTEXT(ctx);
2813bf215546Sopenharmony_ci   const char *api_name = "glGetSubroutineUniformLocation";
2814bf215546Sopenharmony_ci   struct gl_shader_program *shProg;
2815bf215546Sopenharmony_ci   GLenum resource_type;
2816bf215546Sopenharmony_ci   gl_shader_stage stage;
2817bf215546Sopenharmony_ci
2818bf215546Sopenharmony_ci   if (!_mesa_validate_shader_target(ctx, shadertype)) {
2819bf215546Sopenharmony_ci      _mesa_error(ctx, GL_INVALID_OPERATION, "%s", api_name);
2820bf215546Sopenharmony_ci      return -1;
2821bf215546Sopenharmony_ci   }
2822bf215546Sopenharmony_ci
2823bf215546Sopenharmony_ci   shProg = _mesa_lookup_shader_program_err(ctx, program, api_name);
2824bf215546Sopenharmony_ci   if (!shProg)
2825bf215546Sopenharmony_ci      return -1;
2826bf215546Sopenharmony_ci
2827bf215546Sopenharmony_ci   stage = _mesa_shader_enum_to_shader_stage(shadertype);
2828bf215546Sopenharmony_ci   if (!shProg->_LinkedShaders[stage]) {
2829bf215546Sopenharmony_ci      _mesa_error(ctx, GL_INVALID_OPERATION, "%s", api_name);
2830bf215546Sopenharmony_ci      return -1;
2831bf215546Sopenharmony_ci   }
2832bf215546Sopenharmony_ci
2833bf215546Sopenharmony_ci   resource_type = _mesa_shader_stage_to_subroutine_uniform(stage);
2834bf215546Sopenharmony_ci   return _mesa_program_resource_location(shProg, resource_type, name);
2835bf215546Sopenharmony_ci}
2836bf215546Sopenharmony_ci
2837bf215546Sopenharmony_ciGLuint GLAPIENTRY
2838bf215546Sopenharmony_ci_mesa_GetSubroutineIndex(GLuint program, GLenum shadertype,
2839bf215546Sopenharmony_ci                         const GLchar *name)
2840bf215546Sopenharmony_ci{
2841bf215546Sopenharmony_ci   GET_CURRENT_CONTEXT(ctx);
2842bf215546Sopenharmony_ci   const char *api_name = "glGetSubroutineIndex";
2843bf215546Sopenharmony_ci   struct gl_shader_program *shProg;
2844bf215546Sopenharmony_ci   struct gl_program_resource *res;
2845bf215546Sopenharmony_ci   GLenum resource_type;
2846bf215546Sopenharmony_ci   gl_shader_stage stage;
2847bf215546Sopenharmony_ci
2848bf215546Sopenharmony_ci   if (!_mesa_validate_shader_target(ctx, shadertype)) {
2849bf215546Sopenharmony_ci      _mesa_error(ctx, GL_INVALID_OPERATION, "%s", api_name);
2850bf215546Sopenharmony_ci      return -1;
2851bf215546Sopenharmony_ci   }
2852bf215546Sopenharmony_ci
2853bf215546Sopenharmony_ci   shProg = _mesa_lookup_shader_program_err(ctx, program, api_name);
2854bf215546Sopenharmony_ci   if (!shProg)
2855bf215546Sopenharmony_ci      return -1;
2856bf215546Sopenharmony_ci
2857bf215546Sopenharmony_ci   stage = _mesa_shader_enum_to_shader_stage(shadertype);
2858bf215546Sopenharmony_ci   if (!shProg->_LinkedShaders[stage]) {
2859bf215546Sopenharmony_ci      _mesa_error(ctx, GL_INVALID_OPERATION, "%s", api_name);
2860bf215546Sopenharmony_ci      return -1;
2861bf215546Sopenharmony_ci   }
2862bf215546Sopenharmony_ci
2863bf215546Sopenharmony_ci   resource_type = _mesa_shader_stage_to_subroutine(stage);
2864bf215546Sopenharmony_ci   res = _mesa_program_resource_find_name(shProg, resource_type, name, NULL);
2865bf215546Sopenharmony_ci   if (!res) {
2866bf215546Sopenharmony_ci     return -1;
2867bf215546Sopenharmony_ci   }
2868bf215546Sopenharmony_ci
2869bf215546Sopenharmony_ci   return _mesa_program_resource_index(shProg, res);
2870bf215546Sopenharmony_ci}
2871bf215546Sopenharmony_ci
2872bf215546Sopenharmony_ci
2873bf215546Sopenharmony_ciGLvoid GLAPIENTRY
2874bf215546Sopenharmony_ci_mesa_GetActiveSubroutineUniformiv(GLuint program, GLenum shadertype,
2875bf215546Sopenharmony_ci                                   GLuint index, GLenum pname, GLint *values)
2876bf215546Sopenharmony_ci{
2877bf215546Sopenharmony_ci   GET_CURRENT_CONTEXT(ctx);
2878bf215546Sopenharmony_ci   const char *api_name = "glGetActiveSubroutineUniformiv";
2879bf215546Sopenharmony_ci   struct gl_shader_program *shProg;
2880bf215546Sopenharmony_ci   struct gl_linked_shader *sh;
2881bf215546Sopenharmony_ci   gl_shader_stage stage;
2882bf215546Sopenharmony_ci   struct gl_program_resource *res;
2883bf215546Sopenharmony_ci   const struct gl_uniform_storage *uni;
2884bf215546Sopenharmony_ci   GLenum resource_type;
2885bf215546Sopenharmony_ci   int count, i, j;
2886bf215546Sopenharmony_ci
2887bf215546Sopenharmony_ci   if (!_mesa_validate_shader_target(ctx, shadertype)) {
2888bf215546Sopenharmony_ci      _mesa_error(ctx, GL_INVALID_OPERATION, "%s", api_name);
2889bf215546Sopenharmony_ci      return;
2890bf215546Sopenharmony_ci   }
2891bf215546Sopenharmony_ci
2892bf215546Sopenharmony_ci   shProg = _mesa_lookup_shader_program_err(ctx, program, api_name);
2893bf215546Sopenharmony_ci   if (!shProg)
2894bf215546Sopenharmony_ci      return;
2895bf215546Sopenharmony_ci
2896bf215546Sopenharmony_ci   stage = _mesa_shader_enum_to_shader_stage(shadertype);
2897bf215546Sopenharmony_ci   resource_type = _mesa_shader_stage_to_subroutine_uniform(stage);
2898bf215546Sopenharmony_ci
2899bf215546Sopenharmony_ci   sh = shProg->_LinkedShaders[stage];
2900bf215546Sopenharmony_ci   if (!sh) {
2901bf215546Sopenharmony_ci      _mesa_error(ctx, GL_INVALID_OPERATION, "%s", api_name);
2902bf215546Sopenharmony_ci      return;
2903bf215546Sopenharmony_ci   }
2904bf215546Sopenharmony_ci
2905bf215546Sopenharmony_ci   struct gl_program *p = shProg->_LinkedShaders[stage]->Program;
2906bf215546Sopenharmony_ci   if (index >= p->sh.NumSubroutineUniforms) {
2907bf215546Sopenharmony_ci      _mesa_error(ctx, GL_INVALID_VALUE, "%s: invalid index greater than GL_ACTIVE_SUBROUTINE_UNIFORMS", api_name);
2908bf215546Sopenharmony_ci      return;
2909bf215546Sopenharmony_ci   }
2910bf215546Sopenharmony_ci
2911bf215546Sopenharmony_ci   switch (pname) {
2912bf215546Sopenharmony_ci   case GL_NUM_COMPATIBLE_SUBROUTINES: {
2913bf215546Sopenharmony_ci      res = _mesa_program_resource_find_index(shProg, resource_type, index);
2914bf215546Sopenharmony_ci      if (res) {
2915bf215546Sopenharmony_ci         uni = res->Data;
2916bf215546Sopenharmony_ci         values[0] = uni->num_compatible_subroutines;
2917bf215546Sopenharmony_ci      }
2918bf215546Sopenharmony_ci      break;
2919bf215546Sopenharmony_ci   }
2920bf215546Sopenharmony_ci   case GL_COMPATIBLE_SUBROUTINES: {
2921bf215546Sopenharmony_ci      res = _mesa_program_resource_find_index(shProg, resource_type, index);
2922bf215546Sopenharmony_ci      if (res) {
2923bf215546Sopenharmony_ci         uni = res->Data;
2924bf215546Sopenharmony_ci         count = 0;
2925bf215546Sopenharmony_ci         for (i = 0; i < p->sh.NumSubroutineFunctions; i++) {
2926bf215546Sopenharmony_ci            struct gl_subroutine_function *fn = &p->sh.SubroutineFunctions[i];
2927bf215546Sopenharmony_ci            for (j = 0; j < fn->num_compat_types; j++) {
2928bf215546Sopenharmony_ci               if (fn->types[j] == uni->type) {
2929bf215546Sopenharmony_ci                  values[count++] = i;
2930bf215546Sopenharmony_ci                  break;
2931bf215546Sopenharmony_ci               }
2932bf215546Sopenharmony_ci            }
2933bf215546Sopenharmony_ci         }
2934bf215546Sopenharmony_ci      }
2935bf215546Sopenharmony_ci      break;
2936bf215546Sopenharmony_ci   }
2937bf215546Sopenharmony_ci   case GL_UNIFORM_SIZE:
2938bf215546Sopenharmony_ci      res = _mesa_program_resource_find_index(shProg, resource_type, index);
2939bf215546Sopenharmony_ci      if (res) {
2940bf215546Sopenharmony_ci         uni = res->Data;
2941bf215546Sopenharmony_ci         values[0] = uni->array_elements ? uni->array_elements : 1;
2942bf215546Sopenharmony_ci      }
2943bf215546Sopenharmony_ci      break;
2944bf215546Sopenharmony_ci   case GL_UNIFORM_NAME_LENGTH:
2945bf215546Sopenharmony_ci      res = _mesa_program_resource_find_index(shProg, resource_type, index);
2946bf215546Sopenharmony_ci      if (res) {
2947bf215546Sopenharmony_ci         values[0] = _mesa_program_resource_name_length(res) + 1
2948bf215546Sopenharmony_ci            + ((_mesa_program_resource_array_size(res) != 0) ? 3 : 0);
2949bf215546Sopenharmony_ci      }
2950bf215546Sopenharmony_ci      break;
2951bf215546Sopenharmony_ci   default:
2952bf215546Sopenharmony_ci      _mesa_error(ctx, GL_INVALID_OPERATION, "%s", api_name);
2953bf215546Sopenharmony_ci      return;
2954bf215546Sopenharmony_ci   }
2955bf215546Sopenharmony_ci}
2956bf215546Sopenharmony_ci
2957bf215546Sopenharmony_ci
2958bf215546Sopenharmony_ciGLvoid GLAPIENTRY
2959bf215546Sopenharmony_ci_mesa_GetActiveSubroutineUniformName(GLuint program, GLenum shadertype,
2960bf215546Sopenharmony_ci                                     GLuint index, GLsizei bufsize,
2961bf215546Sopenharmony_ci                                     GLsizei *length, GLchar *name)
2962bf215546Sopenharmony_ci{
2963bf215546Sopenharmony_ci   GET_CURRENT_CONTEXT(ctx);
2964bf215546Sopenharmony_ci   const char *api_name = "glGetActiveSubroutineUniformName";
2965bf215546Sopenharmony_ci   struct gl_shader_program *shProg;
2966bf215546Sopenharmony_ci   GLenum resource_type;
2967bf215546Sopenharmony_ci   gl_shader_stage stage;
2968bf215546Sopenharmony_ci
2969bf215546Sopenharmony_ci   if (!_mesa_validate_shader_target(ctx, shadertype)) {
2970bf215546Sopenharmony_ci      _mesa_error(ctx, GL_INVALID_OPERATION, "%s", api_name);
2971bf215546Sopenharmony_ci      return;
2972bf215546Sopenharmony_ci   }
2973bf215546Sopenharmony_ci
2974bf215546Sopenharmony_ci   shProg = _mesa_lookup_shader_program_err(ctx, program, api_name);
2975bf215546Sopenharmony_ci   if (!shProg)
2976bf215546Sopenharmony_ci      return;
2977bf215546Sopenharmony_ci
2978bf215546Sopenharmony_ci   stage = _mesa_shader_enum_to_shader_stage(shadertype);
2979bf215546Sopenharmony_ci   if (!shProg->_LinkedShaders[stage]) {
2980bf215546Sopenharmony_ci      _mesa_error(ctx, GL_INVALID_OPERATION, "%s", api_name);
2981bf215546Sopenharmony_ci      return;
2982bf215546Sopenharmony_ci   }
2983bf215546Sopenharmony_ci
2984bf215546Sopenharmony_ci   resource_type = _mesa_shader_stage_to_subroutine_uniform(stage);
2985bf215546Sopenharmony_ci   /* get program resource name */
2986bf215546Sopenharmony_ci   _mesa_get_program_resource_name(shProg, resource_type,
2987bf215546Sopenharmony_ci                                   index, bufsize,
2988bf215546Sopenharmony_ci                                   length, name, false, api_name);
2989bf215546Sopenharmony_ci}
2990bf215546Sopenharmony_ci
2991bf215546Sopenharmony_ci
2992bf215546Sopenharmony_ciGLvoid GLAPIENTRY
2993bf215546Sopenharmony_ci_mesa_GetActiveSubroutineName(GLuint program, GLenum shadertype,
2994bf215546Sopenharmony_ci                              GLuint index, GLsizei bufsize,
2995bf215546Sopenharmony_ci                              GLsizei *length, GLchar *name)
2996bf215546Sopenharmony_ci{
2997bf215546Sopenharmony_ci   GET_CURRENT_CONTEXT(ctx);
2998bf215546Sopenharmony_ci   const char *api_name = "glGetActiveSubroutineName";
2999bf215546Sopenharmony_ci   struct gl_shader_program *shProg;
3000bf215546Sopenharmony_ci   GLenum resource_type;
3001bf215546Sopenharmony_ci   gl_shader_stage stage;
3002bf215546Sopenharmony_ci
3003bf215546Sopenharmony_ci   if (!_mesa_validate_shader_target(ctx, shadertype)) {
3004bf215546Sopenharmony_ci      _mesa_error(ctx, GL_INVALID_OPERATION, "%s", api_name);
3005bf215546Sopenharmony_ci      return;
3006bf215546Sopenharmony_ci   }
3007bf215546Sopenharmony_ci
3008bf215546Sopenharmony_ci   shProg = _mesa_lookup_shader_program_err(ctx, program, api_name);
3009bf215546Sopenharmony_ci   if (!shProg)
3010bf215546Sopenharmony_ci      return;
3011bf215546Sopenharmony_ci
3012bf215546Sopenharmony_ci   stage = _mesa_shader_enum_to_shader_stage(shadertype);
3013bf215546Sopenharmony_ci   if (!shProg->_LinkedShaders[stage]) {
3014bf215546Sopenharmony_ci      _mesa_error(ctx, GL_INVALID_OPERATION, "%s", api_name);
3015bf215546Sopenharmony_ci      return;
3016bf215546Sopenharmony_ci   }
3017bf215546Sopenharmony_ci   resource_type = _mesa_shader_stage_to_subroutine(stage);
3018bf215546Sopenharmony_ci   _mesa_get_program_resource_name(shProg, resource_type,
3019bf215546Sopenharmony_ci                                   index, bufsize,
3020bf215546Sopenharmony_ci                                   length, name, false, api_name);
3021bf215546Sopenharmony_ci}
3022bf215546Sopenharmony_ci
3023bf215546Sopenharmony_ciGLvoid GLAPIENTRY
3024bf215546Sopenharmony_ci_mesa_UniformSubroutinesuiv(GLenum shadertype, GLsizei count,
3025bf215546Sopenharmony_ci                            const GLuint *indices)
3026bf215546Sopenharmony_ci{
3027bf215546Sopenharmony_ci   GET_CURRENT_CONTEXT(ctx);
3028bf215546Sopenharmony_ci   const char *api_name = "glUniformSubroutinesuiv";
3029bf215546Sopenharmony_ci   gl_shader_stage stage;
3030bf215546Sopenharmony_ci   int i;
3031bf215546Sopenharmony_ci
3032bf215546Sopenharmony_ci   if (!_mesa_validate_shader_target(ctx, shadertype)) {
3033bf215546Sopenharmony_ci      _mesa_error(ctx, GL_INVALID_OPERATION, "%s", api_name);
3034bf215546Sopenharmony_ci      return;
3035bf215546Sopenharmony_ci   }
3036bf215546Sopenharmony_ci
3037bf215546Sopenharmony_ci   stage = _mesa_shader_enum_to_shader_stage(shadertype);
3038bf215546Sopenharmony_ci   struct gl_program *p = ctx->_Shader->CurrentProgram[stage];
3039bf215546Sopenharmony_ci   if (!p) {
3040bf215546Sopenharmony_ci      _mesa_error(ctx, GL_INVALID_OPERATION, "%s", api_name);
3041bf215546Sopenharmony_ci      return;
3042bf215546Sopenharmony_ci   }
3043bf215546Sopenharmony_ci
3044bf215546Sopenharmony_ci   if (count != p->sh.NumSubroutineUniformRemapTable) {
3045bf215546Sopenharmony_ci      _mesa_error(ctx, GL_INVALID_VALUE, "%s", api_name);
3046bf215546Sopenharmony_ci      return;
3047bf215546Sopenharmony_ci   }
3048bf215546Sopenharmony_ci
3049bf215546Sopenharmony_ci   i = 0;
3050bf215546Sopenharmony_ci   bool flushed = false;
3051bf215546Sopenharmony_ci   do {
3052bf215546Sopenharmony_ci      struct gl_uniform_storage *uni = p->sh.SubroutineUniformRemapTable[i];
3053bf215546Sopenharmony_ci      if (uni == NULL) {
3054bf215546Sopenharmony_ci         i++;
3055bf215546Sopenharmony_ci         continue;
3056bf215546Sopenharmony_ci      }
3057bf215546Sopenharmony_ci
3058bf215546Sopenharmony_ci      if (!flushed) {
3059bf215546Sopenharmony_ci         _mesa_flush_vertices_for_uniforms(ctx, uni);
3060bf215546Sopenharmony_ci         flushed = true;
3061bf215546Sopenharmony_ci      }
3062bf215546Sopenharmony_ci
3063bf215546Sopenharmony_ci      int uni_count = uni->array_elements ? uni->array_elements : 1;
3064bf215546Sopenharmony_ci      int j, k, f;
3065bf215546Sopenharmony_ci
3066bf215546Sopenharmony_ci      for (j = i; j < i + uni_count; j++) {
3067bf215546Sopenharmony_ci         struct gl_subroutine_function *subfn = NULL;
3068bf215546Sopenharmony_ci         if (indices[j] > p->sh.MaxSubroutineFunctionIndex) {
3069bf215546Sopenharmony_ci            _mesa_error(ctx, GL_INVALID_VALUE, "%s", api_name);
3070bf215546Sopenharmony_ci            return;
3071bf215546Sopenharmony_ci         }
3072bf215546Sopenharmony_ci
3073bf215546Sopenharmony_ci         for (f = 0; f < p->sh.NumSubroutineFunctions; f++) {
3074bf215546Sopenharmony_ci            if (p->sh.SubroutineFunctions[f].index == indices[j])
3075bf215546Sopenharmony_ci               subfn = &p->sh.SubroutineFunctions[f];
3076bf215546Sopenharmony_ci         }
3077bf215546Sopenharmony_ci
3078bf215546Sopenharmony_ci         if (!subfn) {
3079bf215546Sopenharmony_ci            continue;
3080bf215546Sopenharmony_ci         }
3081bf215546Sopenharmony_ci
3082bf215546Sopenharmony_ci         for (k = 0; k < subfn->num_compat_types; k++) {
3083bf215546Sopenharmony_ci            if (subfn->types[k] == uni->type)
3084bf215546Sopenharmony_ci               break;
3085bf215546Sopenharmony_ci         }
3086bf215546Sopenharmony_ci         if (k == subfn->num_compat_types) {
3087bf215546Sopenharmony_ci            _mesa_error(ctx, GL_INVALID_OPERATION, "%s", api_name);
3088bf215546Sopenharmony_ci            return;
3089bf215546Sopenharmony_ci         }
3090bf215546Sopenharmony_ci
3091bf215546Sopenharmony_ci         ctx->SubroutineIndex[p->info.stage].IndexPtr[j] = indices[j];
3092bf215546Sopenharmony_ci      }
3093bf215546Sopenharmony_ci      i += uni_count;
3094bf215546Sopenharmony_ci   } while(i < count);
3095bf215546Sopenharmony_ci}
3096bf215546Sopenharmony_ci
3097bf215546Sopenharmony_ci
3098bf215546Sopenharmony_ciGLvoid GLAPIENTRY
3099bf215546Sopenharmony_ci_mesa_GetUniformSubroutineuiv(GLenum shadertype, GLint location,
3100bf215546Sopenharmony_ci                              GLuint *params)
3101bf215546Sopenharmony_ci{
3102bf215546Sopenharmony_ci   GET_CURRENT_CONTEXT(ctx);
3103bf215546Sopenharmony_ci   const char *api_name = "glGetUniformSubroutineuiv";
3104bf215546Sopenharmony_ci   gl_shader_stage stage;
3105bf215546Sopenharmony_ci
3106bf215546Sopenharmony_ci   if (!_mesa_validate_shader_target(ctx, shadertype)) {
3107bf215546Sopenharmony_ci      _mesa_error(ctx, GL_INVALID_OPERATION, "%s", api_name);
3108bf215546Sopenharmony_ci      return;
3109bf215546Sopenharmony_ci   }
3110bf215546Sopenharmony_ci
3111bf215546Sopenharmony_ci   stage = _mesa_shader_enum_to_shader_stage(shadertype);
3112bf215546Sopenharmony_ci   struct gl_program *p = ctx->_Shader->CurrentProgram[stage];
3113bf215546Sopenharmony_ci   if (!p) {
3114bf215546Sopenharmony_ci      _mesa_error(ctx, GL_INVALID_OPERATION, "%s", api_name);
3115bf215546Sopenharmony_ci      return;
3116bf215546Sopenharmony_ci   }
3117bf215546Sopenharmony_ci
3118bf215546Sopenharmony_ci   if (location >= p->sh.NumSubroutineUniformRemapTable) {
3119bf215546Sopenharmony_ci      _mesa_error(ctx, GL_INVALID_VALUE, "%s", api_name);
3120bf215546Sopenharmony_ci      return;
3121bf215546Sopenharmony_ci   }
3122bf215546Sopenharmony_ci
3123bf215546Sopenharmony_ci   *params = ctx->SubroutineIndex[p->info.stage].IndexPtr[location];
3124bf215546Sopenharmony_ci}
3125bf215546Sopenharmony_ci
3126bf215546Sopenharmony_ci
3127bf215546Sopenharmony_ciGLvoid GLAPIENTRY
3128bf215546Sopenharmony_ci_mesa_GetProgramStageiv(GLuint program, GLenum shadertype,
3129bf215546Sopenharmony_ci                        GLenum pname, GLint *values)
3130bf215546Sopenharmony_ci{
3131bf215546Sopenharmony_ci   GET_CURRENT_CONTEXT(ctx);
3132bf215546Sopenharmony_ci   const char *api_name = "glGetProgramStageiv";
3133bf215546Sopenharmony_ci   struct gl_shader_program *shProg;
3134bf215546Sopenharmony_ci   struct gl_linked_shader *sh;
3135bf215546Sopenharmony_ci   gl_shader_stage stage;
3136bf215546Sopenharmony_ci
3137bf215546Sopenharmony_ci   if (!_mesa_validate_shader_target(ctx, shadertype)) {
3138bf215546Sopenharmony_ci      _mesa_error(ctx, GL_INVALID_OPERATION, "%s", api_name);
3139bf215546Sopenharmony_ci      return;
3140bf215546Sopenharmony_ci   }
3141bf215546Sopenharmony_ci
3142bf215546Sopenharmony_ci   shProg = _mesa_lookup_shader_program_err(ctx, program, api_name);
3143bf215546Sopenharmony_ci   if (!shProg)
3144bf215546Sopenharmony_ci      return;
3145bf215546Sopenharmony_ci
3146bf215546Sopenharmony_ci   stage = _mesa_shader_enum_to_shader_stage(shadertype);
3147bf215546Sopenharmony_ci   sh = shProg->_LinkedShaders[stage];
3148bf215546Sopenharmony_ci
3149bf215546Sopenharmony_ci   /* ARB_shader_subroutine doesn't ask the program to be linked, or list any
3150bf215546Sopenharmony_ci    * INVALID_OPERATION in the case of not be linked.
3151bf215546Sopenharmony_ci    *
3152bf215546Sopenharmony_ci    * And for some pnames, like GL_ACTIVE_SUBROUTINE_UNIFORMS, you can ask the
3153bf215546Sopenharmony_ci    * same info using other specs (ARB_program_interface_query), without the
3154bf215546Sopenharmony_ci    * need of the program to be linked, being the value for that case 0.
3155bf215546Sopenharmony_ci    *
3156bf215546Sopenharmony_ci    * But at the same time, some other methods require the program to be
3157bf215546Sopenharmony_ci    * linked for pname related to locations, so it would be inconsistent to
3158bf215546Sopenharmony_ci    * not do the same here. So we are:
3159bf215546Sopenharmony_ci    *   * Return GL_INVALID_OPERATION if not linked only for locations.
3160bf215546Sopenharmony_ci    *   * Setting a default value of 0, to be returned if not linked.
3161bf215546Sopenharmony_ci    */
3162bf215546Sopenharmony_ci   if (!sh) {
3163bf215546Sopenharmony_ci      values[0] = 0;
3164bf215546Sopenharmony_ci      if (pname == GL_ACTIVE_SUBROUTINE_UNIFORM_LOCATIONS) {
3165bf215546Sopenharmony_ci         _mesa_error(ctx, GL_INVALID_OPERATION, "%s", api_name);
3166bf215546Sopenharmony_ci      }
3167bf215546Sopenharmony_ci      return;
3168bf215546Sopenharmony_ci   }
3169bf215546Sopenharmony_ci
3170bf215546Sopenharmony_ci   struct gl_program *p = sh->Program;
3171bf215546Sopenharmony_ci   switch (pname) {
3172bf215546Sopenharmony_ci   case GL_ACTIVE_SUBROUTINES:
3173bf215546Sopenharmony_ci      values[0] = p->sh.NumSubroutineFunctions;
3174bf215546Sopenharmony_ci      break;
3175bf215546Sopenharmony_ci   case GL_ACTIVE_SUBROUTINE_UNIFORM_LOCATIONS:
3176bf215546Sopenharmony_ci      values[0] = p->sh.NumSubroutineUniformRemapTable;
3177bf215546Sopenharmony_ci      break;
3178bf215546Sopenharmony_ci   case GL_ACTIVE_SUBROUTINE_UNIFORMS:
3179bf215546Sopenharmony_ci      values[0] = p->sh.NumSubroutineUniforms;
3180bf215546Sopenharmony_ci      break;
3181bf215546Sopenharmony_ci   case GL_ACTIVE_SUBROUTINE_MAX_LENGTH:
3182bf215546Sopenharmony_ci   {
3183bf215546Sopenharmony_ci      unsigned i;
3184bf215546Sopenharmony_ci      GLint max_len = 0;
3185bf215546Sopenharmony_ci      GLenum resource_type;
3186bf215546Sopenharmony_ci      struct gl_program_resource *res;
3187bf215546Sopenharmony_ci
3188bf215546Sopenharmony_ci      resource_type = _mesa_shader_stage_to_subroutine(stage);
3189bf215546Sopenharmony_ci      for (i = 0; i < p->sh.NumSubroutineFunctions; i++) {
3190bf215546Sopenharmony_ci         res = _mesa_program_resource_find_index(shProg, resource_type, i);
3191bf215546Sopenharmony_ci         if (res) {
3192bf215546Sopenharmony_ci            const GLint len = _mesa_program_resource_name_length(res) + 1;
3193bf215546Sopenharmony_ci            if (len > max_len)
3194bf215546Sopenharmony_ci               max_len = len;
3195bf215546Sopenharmony_ci         }
3196bf215546Sopenharmony_ci      }
3197bf215546Sopenharmony_ci      values[0] = max_len;
3198bf215546Sopenharmony_ci      break;
3199bf215546Sopenharmony_ci   }
3200bf215546Sopenharmony_ci   case GL_ACTIVE_SUBROUTINE_UNIFORM_MAX_LENGTH:
3201bf215546Sopenharmony_ci   {
3202bf215546Sopenharmony_ci      unsigned i;
3203bf215546Sopenharmony_ci      GLint max_len = 0;
3204bf215546Sopenharmony_ci      GLenum resource_type;
3205bf215546Sopenharmony_ci      struct gl_program_resource *res;
3206bf215546Sopenharmony_ci
3207bf215546Sopenharmony_ci      resource_type = _mesa_shader_stage_to_subroutine_uniform(stage);
3208bf215546Sopenharmony_ci      for (i = 0; i < p->sh.NumSubroutineUniformRemapTable; i++) {
3209bf215546Sopenharmony_ci         res = _mesa_program_resource_find_index(shProg, resource_type, i);
3210bf215546Sopenharmony_ci         if (res) {
3211bf215546Sopenharmony_ci            const GLint len = _mesa_program_resource_name_length(res) + 1
3212bf215546Sopenharmony_ci               + ((_mesa_program_resource_array_size(res) != 0) ? 3 : 0);
3213bf215546Sopenharmony_ci
3214bf215546Sopenharmony_ci            if (len > max_len)
3215bf215546Sopenharmony_ci               max_len = len;
3216bf215546Sopenharmony_ci         }
3217bf215546Sopenharmony_ci      }
3218bf215546Sopenharmony_ci      values[0] = max_len;
3219bf215546Sopenharmony_ci      break;
3220bf215546Sopenharmony_ci   }
3221bf215546Sopenharmony_ci   default:
3222bf215546Sopenharmony_ci      _mesa_error(ctx, GL_INVALID_ENUM, "%s", api_name);
3223bf215546Sopenharmony_ci      values[0] = -1;
3224bf215546Sopenharmony_ci      break;
3225bf215546Sopenharmony_ci   }
3226bf215546Sopenharmony_ci}
3227bf215546Sopenharmony_ci
3228bf215546Sopenharmony_ci/* This is simple list entry that will be used to hold a list of string
3229bf215546Sopenharmony_ci * tokens of a parsed shader include path.
3230bf215546Sopenharmony_ci */
3231bf215546Sopenharmony_cistruct sh_incl_path_entry
3232bf215546Sopenharmony_ci{
3233bf215546Sopenharmony_ci   struct list_head list;
3234bf215546Sopenharmony_ci
3235bf215546Sopenharmony_ci   char *path;
3236bf215546Sopenharmony_ci};
3237bf215546Sopenharmony_ci
3238bf215546Sopenharmony_ci/* Nodes of the shader include tree */
3239bf215546Sopenharmony_cistruct sh_incl_path_ht_entry
3240bf215546Sopenharmony_ci{
3241bf215546Sopenharmony_ci   struct hash_table *path;
3242bf215546Sopenharmony_ci   char *shader_source;
3243bf215546Sopenharmony_ci};
3244bf215546Sopenharmony_ci
3245bf215546Sopenharmony_cistruct shader_includes {
3246bf215546Sopenharmony_ci   /* Array to hold include paths given to glCompileShaderIncludeARB() */
3247bf215546Sopenharmony_ci   struct sh_incl_path_entry **include_paths;
3248bf215546Sopenharmony_ci   size_t num_include_paths;
3249bf215546Sopenharmony_ci   size_t relative_path_cursor;
3250bf215546Sopenharmony_ci
3251bf215546Sopenharmony_ci   /* Root hash table holding the shader include tree */
3252bf215546Sopenharmony_ci   struct hash_table *shader_include_tree;
3253bf215546Sopenharmony_ci};
3254bf215546Sopenharmony_ci
3255bf215546Sopenharmony_civoid
3256bf215546Sopenharmony_ci_mesa_init_shader_includes(struct gl_shared_state *shared)
3257bf215546Sopenharmony_ci{
3258bf215546Sopenharmony_ci   shared->ShaderIncludes = calloc(1, sizeof(struct shader_includes));
3259bf215546Sopenharmony_ci   shared->ShaderIncludes->shader_include_tree =
3260bf215546Sopenharmony_ci      _mesa_hash_table_create(NULL, _mesa_hash_string,
3261bf215546Sopenharmony_ci                              _mesa_key_string_equal);
3262bf215546Sopenharmony_ci}
3263bf215546Sopenharmony_ci
3264bf215546Sopenharmony_cisize_t
3265bf215546Sopenharmony_ci_mesa_get_shader_include_cursor(struct gl_shared_state *shared)
3266bf215546Sopenharmony_ci{
3267bf215546Sopenharmony_ci   return shared->ShaderIncludes->relative_path_cursor;
3268bf215546Sopenharmony_ci}
3269bf215546Sopenharmony_ci
3270bf215546Sopenharmony_civoid
3271bf215546Sopenharmony_ci_mesa_set_shader_include_cursor(struct gl_shared_state *shared, size_t cursor)
3272bf215546Sopenharmony_ci{
3273bf215546Sopenharmony_ci   shared->ShaderIncludes->relative_path_cursor = cursor;
3274bf215546Sopenharmony_ci}
3275bf215546Sopenharmony_ci
3276bf215546Sopenharmony_cistatic void
3277bf215546Sopenharmony_cidestroy_shader_include(struct hash_entry *entry)
3278bf215546Sopenharmony_ci{
3279bf215546Sopenharmony_ci   struct sh_incl_path_ht_entry *sh_incl_ht_entry =
3280bf215546Sopenharmony_ci      (struct sh_incl_path_ht_entry *) entry->data;
3281bf215546Sopenharmony_ci
3282bf215546Sopenharmony_ci   _mesa_hash_table_destroy(sh_incl_ht_entry->path, destroy_shader_include);
3283bf215546Sopenharmony_ci   free(sh_incl_ht_entry->shader_source);
3284bf215546Sopenharmony_ci   free(sh_incl_ht_entry);
3285bf215546Sopenharmony_ci}
3286bf215546Sopenharmony_ci
3287bf215546Sopenharmony_civoid
3288bf215546Sopenharmony_ci_mesa_destroy_shader_includes(struct gl_shared_state *shared)
3289bf215546Sopenharmony_ci{
3290bf215546Sopenharmony_ci   _mesa_hash_table_destroy(shared->ShaderIncludes->shader_include_tree,
3291bf215546Sopenharmony_ci                            destroy_shader_include);
3292bf215546Sopenharmony_ci   free(shared->ShaderIncludes);
3293bf215546Sopenharmony_ci}
3294bf215546Sopenharmony_ci
3295bf215546Sopenharmony_cistatic bool
3296bf215546Sopenharmony_civalid_path_format(const char *str, bool relative_path)
3297bf215546Sopenharmony_ci{
3298bf215546Sopenharmony_ci   int i = 0;
3299bf215546Sopenharmony_ci
3300bf215546Sopenharmony_ci   if (!str[i] || (!relative_path && str[i] != '/'))
3301bf215546Sopenharmony_ci      return false;
3302bf215546Sopenharmony_ci
3303bf215546Sopenharmony_ci   i++;
3304bf215546Sopenharmony_ci
3305bf215546Sopenharmony_ci   while (str[i]) {
3306bf215546Sopenharmony_ci      const char c = str[i++];
3307bf215546Sopenharmony_ci      if (('A' <= c && c <= 'Z') ||
3308bf215546Sopenharmony_ci          ('a' <= c && c <= 'z') ||
3309bf215546Sopenharmony_ci          ('0' <= c && c <= '9'))
3310bf215546Sopenharmony_ci         continue;
3311bf215546Sopenharmony_ci
3312bf215546Sopenharmony_ci      if (c == '/') {
3313bf215546Sopenharmony_ci         if (str[i - 2] == '/')
3314bf215546Sopenharmony_ci            return false;
3315bf215546Sopenharmony_ci
3316bf215546Sopenharmony_ci         continue;
3317bf215546Sopenharmony_ci      }
3318bf215546Sopenharmony_ci
3319bf215546Sopenharmony_ci      if (strchr("^. _+*%[](){}|&~=!:;,?-", c) == NULL)
3320bf215546Sopenharmony_ci         return false;
3321bf215546Sopenharmony_ci  }
3322bf215546Sopenharmony_ci
3323bf215546Sopenharmony_ci  if (str[i - 1] == '/')
3324bf215546Sopenharmony_ci     return false;
3325bf215546Sopenharmony_ci
3326bf215546Sopenharmony_ci  return true;
3327bf215546Sopenharmony_ci}
3328bf215546Sopenharmony_ci
3329bf215546Sopenharmony_ci
3330bf215546Sopenharmony_cistatic bool
3331bf215546Sopenharmony_civalidate_and_tokenise_sh_incl(struct gl_context *ctx,
3332bf215546Sopenharmony_ci                              void *mem_ctx,
3333bf215546Sopenharmony_ci                              struct sh_incl_path_entry **path_list,
3334bf215546Sopenharmony_ci                              char *full_path, bool error_check)
3335bf215546Sopenharmony_ci{
3336bf215546Sopenharmony_ci   bool relative_path = ctx->Shared->ShaderIncludes->num_include_paths;
3337bf215546Sopenharmony_ci
3338bf215546Sopenharmony_ci   if (!valid_path_format(full_path, relative_path)) {
3339bf215546Sopenharmony_ci      if (error_check) {
3340bf215546Sopenharmony_ci         _mesa_error(ctx, GL_INVALID_VALUE,
3341bf215546Sopenharmony_ci                     "glNamedStringARB(invalid name %s)", full_path);
3342bf215546Sopenharmony_ci      }
3343bf215546Sopenharmony_ci      return false;
3344bf215546Sopenharmony_ci   }
3345bf215546Sopenharmony_ci
3346bf215546Sopenharmony_ci   char *save_ptr = NULL;
3347bf215546Sopenharmony_ci   char *path_str = strtok_r(full_path, "/", &save_ptr);
3348bf215546Sopenharmony_ci
3349bf215546Sopenharmony_ci   *path_list = rzalloc(mem_ctx, struct sh_incl_path_entry);
3350bf215546Sopenharmony_ci   struct sh_incl_path_entry * list = *path_list;
3351bf215546Sopenharmony_ci   list_inithead(&list->list);
3352bf215546Sopenharmony_ci
3353bf215546Sopenharmony_ci   while (path_str != NULL) {
3354bf215546Sopenharmony_ci      if (strlen(path_str) == 0) {
3355bf215546Sopenharmony_ci         if (error_check) {
3356bf215546Sopenharmony_ci            _mesa_error(ctx, GL_INVALID_VALUE,
3357bf215546Sopenharmony_ci                        "glNamedStringARB(invalid name %s)", full_path);
3358bf215546Sopenharmony_ci         }
3359bf215546Sopenharmony_ci
3360bf215546Sopenharmony_ci         return false;
3361bf215546Sopenharmony_ci      }
3362bf215546Sopenharmony_ci
3363bf215546Sopenharmony_ci      if (strcmp(path_str, ".") == 0) {
3364bf215546Sopenharmony_ci         /* Do nothing */
3365bf215546Sopenharmony_ci      } else if (strcmp(path_str, "..") == 0) {
3366bf215546Sopenharmony_ci         list_del(list->list.prev);
3367bf215546Sopenharmony_ci      } else {
3368bf215546Sopenharmony_ci         struct sh_incl_path_entry *path =
3369bf215546Sopenharmony_ci            rzalloc(mem_ctx, struct sh_incl_path_entry);
3370bf215546Sopenharmony_ci
3371bf215546Sopenharmony_ci         path->path = strdup(path_str);
3372bf215546Sopenharmony_ci         list_addtail(&path->list, &list->list);
3373bf215546Sopenharmony_ci      }
3374bf215546Sopenharmony_ci
3375bf215546Sopenharmony_ci      path_str = strtok_r(NULL, "/", &save_ptr);
3376bf215546Sopenharmony_ci   }
3377bf215546Sopenharmony_ci
3378bf215546Sopenharmony_ci   return true;
3379bf215546Sopenharmony_ci}
3380bf215546Sopenharmony_ci
3381bf215546Sopenharmony_cistatic struct sh_incl_path_ht_entry *
3382bf215546Sopenharmony_cilookup_shader_include(struct gl_context *ctx, char *path,
3383bf215546Sopenharmony_ci                      bool error_check)
3384bf215546Sopenharmony_ci{
3385bf215546Sopenharmony_ci   void *mem_ctx = ralloc_context(NULL);
3386bf215546Sopenharmony_ci   struct sh_incl_path_entry *path_list;
3387bf215546Sopenharmony_ci
3388bf215546Sopenharmony_ci   if (!validate_and_tokenise_sh_incl(ctx, mem_ctx, &path_list, path,
3389bf215546Sopenharmony_ci                                      error_check)) {
3390bf215546Sopenharmony_ci      ralloc_free(mem_ctx);
3391bf215546Sopenharmony_ci      return NULL;
3392bf215546Sopenharmony_ci   }
3393bf215546Sopenharmony_ci
3394bf215546Sopenharmony_ci   struct sh_incl_path_ht_entry *sh_incl_ht_entry = NULL;
3395bf215546Sopenharmony_ci   struct hash_table *path_ht =
3396bf215546Sopenharmony_ci      ctx->Shared->ShaderIncludes->shader_include_tree;
3397bf215546Sopenharmony_ci
3398bf215546Sopenharmony_ci   size_t count = ctx->Shared->ShaderIncludes->num_include_paths;
3399bf215546Sopenharmony_ci   bool relative_path = path[0] != '/';
3400bf215546Sopenharmony_ci
3401bf215546Sopenharmony_ci   size_t i = ctx->Shared->ShaderIncludes->relative_path_cursor;
3402bf215546Sopenharmony_ci   bool use_cursor = ctx->Shared->ShaderIncludes->relative_path_cursor;
3403bf215546Sopenharmony_ci
3404bf215546Sopenharmony_ci   do {
3405bf215546Sopenharmony_ci      struct sh_incl_path_entry *entry;
3406bf215546Sopenharmony_ci
3407bf215546Sopenharmony_ci      if (relative_path) {
3408bf215546Sopenharmony_cinext_relative_path:
3409bf215546Sopenharmony_ci         {
3410bf215546Sopenharmony_ci            struct sh_incl_path_entry *rel_path_list =
3411bf215546Sopenharmony_ci               ctx->Shared->ShaderIncludes->include_paths[i];
3412bf215546Sopenharmony_ci            LIST_FOR_EACH_ENTRY(entry, &rel_path_list->list, list) {
3413bf215546Sopenharmony_ci               struct hash_entry *ht_entry =
3414bf215546Sopenharmony_ci                  _mesa_hash_table_search(path_ht, entry->path);
3415bf215546Sopenharmony_ci
3416bf215546Sopenharmony_ci               if (!ht_entry) {
3417bf215546Sopenharmony_ci                  /* Reset search path and skip to the next include path */
3418bf215546Sopenharmony_ci                  path_ht = ctx->Shared->ShaderIncludes->shader_include_tree;
3419bf215546Sopenharmony_ci                  sh_incl_ht_entry = NULL;
3420bf215546Sopenharmony_ci                  if (use_cursor) {
3421bf215546Sopenharmony_ci                     i = 0;
3422bf215546Sopenharmony_ci                     use_cursor = false;
3423bf215546Sopenharmony_ci
3424bf215546Sopenharmony_ci                     goto next_relative_path;
3425bf215546Sopenharmony_ci                  }
3426bf215546Sopenharmony_ci                  i++;
3427bf215546Sopenharmony_ci                  if (i < count)
3428bf215546Sopenharmony_ci                     goto next_relative_path;
3429bf215546Sopenharmony_ci                  else
3430bf215546Sopenharmony_ci                     break;
3431bf215546Sopenharmony_ci               } else {
3432bf215546Sopenharmony_ci                  sh_incl_ht_entry =
3433bf215546Sopenharmony_ci                    (struct sh_incl_path_ht_entry *) ht_entry->data;
3434bf215546Sopenharmony_ci               }
3435bf215546Sopenharmony_ci
3436bf215546Sopenharmony_ci               path_ht = sh_incl_ht_entry->path;
3437bf215546Sopenharmony_ci            }
3438bf215546Sopenharmony_ci         }
3439bf215546Sopenharmony_ci      }
3440bf215546Sopenharmony_ci
3441bf215546Sopenharmony_ci      LIST_FOR_EACH_ENTRY(entry, &path_list->list, list) {
3442bf215546Sopenharmony_ci         struct hash_entry *ht_entry =
3443bf215546Sopenharmony_ci            _mesa_hash_table_search(path_ht, entry->path);
3444bf215546Sopenharmony_ci
3445bf215546Sopenharmony_ci         if (!ht_entry) {
3446bf215546Sopenharmony_ci            /* Reset search path and skip to the next include path */
3447bf215546Sopenharmony_ci            path_ht = ctx->Shared->ShaderIncludes->shader_include_tree;
3448bf215546Sopenharmony_ci            sh_incl_ht_entry = NULL;
3449bf215546Sopenharmony_ci            if (use_cursor) {
3450bf215546Sopenharmony_ci               i = 0;
3451bf215546Sopenharmony_ci               use_cursor = false;
3452bf215546Sopenharmony_ci
3453bf215546Sopenharmony_ci               break;
3454bf215546Sopenharmony_ci            }
3455bf215546Sopenharmony_ci            i++;
3456bf215546Sopenharmony_ci            break;
3457bf215546Sopenharmony_ci         } else {
3458bf215546Sopenharmony_ci
3459bf215546Sopenharmony_ci            sh_incl_ht_entry =
3460bf215546Sopenharmony_ci               (struct sh_incl_path_ht_entry *) ht_entry->data;
3461bf215546Sopenharmony_ci         }
3462bf215546Sopenharmony_ci
3463bf215546Sopenharmony_ci         path_ht = sh_incl_ht_entry->path;
3464bf215546Sopenharmony_ci      }
3465bf215546Sopenharmony_ci
3466bf215546Sopenharmony_ci      if (i < count &&
3467bf215546Sopenharmony_ci          (sh_incl_ht_entry == NULL || !sh_incl_ht_entry->shader_source))
3468bf215546Sopenharmony_ci         continue;
3469bf215546Sopenharmony_ci
3470bf215546Sopenharmony_ci      /* If we get here then we have found a matching path or exahusted our
3471bf215546Sopenharmony_ci       * relative search paths.
3472bf215546Sopenharmony_ci       */
3473bf215546Sopenharmony_ci      ctx->Shared->ShaderIncludes->relative_path_cursor = i;
3474bf215546Sopenharmony_ci      break;
3475bf215546Sopenharmony_ci   } while (i < count);
3476bf215546Sopenharmony_ci
3477bf215546Sopenharmony_ci   ralloc_free(mem_ctx);
3478bf215546Sopenharmony_ci
3479bf215546Sopenharmony_ci   return sh_incl_ht_entry;
3480bf215546Sopenharmony_ci}
3481bf215546Sopenharmony_ci
3482bf215546Sopenharmony_ciconst char *
3483bf215546Sopenharmony_ci_mesa_lookup_shader_include(struct gl_context *ctx, char *path,
3484bf215546Sopenharmony_ci                            bool error_check)
3485bf215546Sopenharmony_ci{
3486bf215546Sopenharmony_ci   struct sh_incl_path_ht_entry *shader_include =
3487bf215546Sopenharmony_ci      lookup_shader_include(ctx, path, error_check);
3488bf215546Sopenharmony_ci
3489bf215546Sopenharmony_ci   return shader_include ? shader_include->shader_source : NULL;
3490bf215546Sopenharmony_ci}
3491bf215546Sopenharmony_ci
3492bf215546Sopenharmony_cistatic char *
3493bf215546Sopenharmony_cicopy_string(struct gl_context *ctx, const char *str, int str_len,
3494bf215546Sopenharmony_ci            const char *caller)
3495bf215546Sopenharmony_ci{
3496bf215546Sopenharmony_ci   if (!str) {
3497bf215546Sopenharmony_ci      _mesa_error(ctx, GL_INVALID_VALUE, "%s(NULL string)", caller);
3498bf215546Sopenharmony_ci      return NULL;
3499bf215546Sopenharmony_ci   }
3500bf215546Sopenharmony_ci
3501bf215546Sopenharmony_ci   char *cp;
3502bf215546Sopenharmony_ci   if (str_len == -1)
3503bf215546Sopenharmony_ci      cp = strdup(str);
3504bf215546Sopenharmony_ci   else {
3505bf215546Sopenharmony_ci      cp = calloc(sizeof(char), str_len + 1);
3506bf215546Sopenharmony_ci      memcpy(cp, str, str_len);
3507bf215546Sopenharmony_ci   }
3508bf215546Sopenharmony_ci
3509bf215546Sopenharmony_ci   return cp;
3510bf215546Sopenharmony_ci}
3511bf215546Sopenharmony_ci
3512bf215546Sopenharmony_ciGLvoid GLAPIENTRY
3513bf215546Sopenharmony_ci_mesa_NamedStringARB(GLenum type, GLint namelen, const GLchar *name,
3514bf215546Sopenharmony_ci                     GLint stringlen, const GLchar *string)
3515bf215546Sopenharmony_ci{
3516bf215546Sopenharmony_ci   GET_CURRENT_CONTEXT(ctx);
3517bf215546Sopenharmony_ci   const char *caller = "glNamedStringARB";
3518bf215546Sopenharmony_ci
3519bf215546Sopenharmony_ci   if (type != GL_SHADER_INCLUDE_ARB) {
3520bf215546Sopenharmony_ci      _mesa_error(ctx, GL_INVALID_VALUE, "%s(invalid type)", caller);
3521bf215546Sopenharmony_ci      return;
3522bf215546Sopenharmony_ci   }
3523bf215546Sopenharmony_ci
3524bf215546Sopenharmony_ci   char *name_cp = copy_string(ctx, name, namelen, caller);
3525bf215546Sopenharmony_ci   char *string_cp = copy_string(ctx, string, stringlen, caller);
3526bf215546Sopenharmony_ci   if (!name_cp || !string_cp) {
3527bf215546Sopenharmony_ci      free(string_cp);
3528bf215546Sopenharmony_ci      free(name_cp);
3529bf215546Sopenharmony_ci      return;
3530bf215546Sopenharmony_ci   }
3531bf215546Sopenharmony_ci
3532bf215546Sopenharmony_ci   void *mem_ctx = ralloc_context(NULL);
3533bf215546Sopenharmony_ci   struct sh_incl_path_entry *path_list;
3534bf215546Sopenharmony_ci
3535bf215546Sopenharmony_ci   if (!validate_and_tokenise_sh_incl(ctx, mem_ctx, &path_list, name_cp,
3536bf215546Sopenharmony_ci                                      true)) {
3537bf215546Sopenharmony_ci      free(string_cp);
3538bf215546Sopenharmony_ci      free(name_cp);
3539bf215546Sopenharmony_ci      ralloc_free(mem_ctx);
3540bf215546Sopenharmony_ci      return;
3541bf215546Sopenharmony_ci   }
3542bf215546Sopenharmony_ci
3543bf215546Sopenharmony_ci   simple_mtx_lock(&ctx->Shared->ShaderIncludeMutex);
3544bf215546Sopenharmony_ci
3545bf215546Sopenharmony_ci   struct hash_table *path_ht =
3546bf215546Sopenharmony_ci      ctx->Shared->ShaderIncludes->shader_include_tree;
3547bf215546Sopenharmony_ci
3548bf215546Sopenharmony_ci   struct sh_incl_path_entry *entry;
3549bf215546Sopenharmony_ci   LIST_FOR_EACH_ENTRY(entry, &path_list->list, list) {
3550bf215546Sopenharmony_ci      struct hash_entry *ht_entry =
3551bf215546Sopenharmony_ci         _mesa_hash_table_search(path_ht, entry->path);
3552bf215546Sopenharmony_ci
3553bf215546Sopenharmony_ci      struct sh_incl_path_ht_entry *sh_incl_ht_entry;
3554bf215546Sopenharmony_ci      if (!ht_entry) {
3555bf215546Sopenharmony_ci         sh_incl_ht_entry = calloc(1, sizeof(struct sh_incl_path_ht_entry));
3556bf215546Sopenharmony_ci         sh_incl_ht_entry->path =
3557bf215546Sopenharmony_ci            _mesa_hash_table_create(NULL, _mesa_hash_string,
3558bf215546Sopenharmony_ci                                    _mesa_key_string_equal);
3559bf215546Sopenharmony_ci         _mesa_hash_table_insert(path_ht, entry->path, sh_incl_ht_entry);
3560bf215546Sopenharmony_ci      } else {
3561bf215546Sopenharmony_ci         sh_incl_ht_entry = (struct sh_incl_path_ht_entry *) ht_entry->data;
3562bf215546Sopenharmony_ci      }
3563bf215546Sopenharmony_ci
3564bf215546Sopenharmony_ci      path_ht = sh_incl_ht_entry->path;
3565bf215546Sopenharmony_ci
3566bf215546Sopenharmony_ci      if (list_last_entry(&path_list->list, struct sh_incl_path_entry, list) == entry) {
3567bf215546Sopenharmony_ci         free(sh_incl_ht_entry->shader_source);
3568bf215546Sopenharmony_ci         sh_incl_ht_entry->shader_source = string_cp;
3569bf215546Sopenharmony_ci      }
3570bf215546Sopenharmony_ci   }
3571bf215546Sopenharmony_ci
3572bf215546Sopenharmony_ci   simple_mtx_unlock(&ctx->Shared->ShaderIncludeMutex);
3573bf215546Sopenharmony_ci
3574bf215546Sopenharmony_ci   free(name_cp);
3575bf215546Sopenharmony_ci   ralloc_free(mem_ctx);
3576bf215546Sopenharmony_ci}
3577bf215546Sopenharmony_ci
3578bf215546Sopenharmony_ciGLvoid GLAPIENTRY
3579bf215546Sopenharmony_ci_mesa_DeleteNamedStringARB(GLint namelen, const GLchar *name)
3580bf215546Sopenharmony_ci{
3581bf215546Sopenharmony_ci   GET_CURRENT_CONTEXT(ctx);
3582bf215546Sopenharmony_ci   const char *caller = "glDeleteNamedStringARB";
3583bf215546Sopenharmony_ci
3584bf215546Sopenharmony_ci   char *name_cp = copy_string(ctx, name, namelen, caller);
3585bf215546Sopenharmony_ci   if (!name_cp)
3586bf215546Sopenharmony_ci      return;
3587bf215546Sopenharmony_ci
3588bf215546Sopenharmony_ci   struct sh_incl_path_ht_entry *shader_include =
3589bf215546Sopenharmony_ci      lookup_shader_include(ctx, name_cp, true);
3590bf215546Sopenharmony_ci
3591bf215546Sopenharmony_ci   if (!shader_include) {
3592bf215546Sopenharmony_ci      _mesa_error(ctx, GL_INVALID_OPERATION,
3593bf215546Sopenharmony_ci                  "%s(no string associated with path %s)", caller, name_cp);
3594bf215546Sopenharmony_ci      free(name_cp);
3595bf215546Sopenharmony_ci      return;
3596bf215546Sopenharmony_ci   }
3597bf215546Sopenharmony_ci
3598bf215546Sopenharmony_ci   simple_mtx_lock(&ctx->Shared->ShaderIncludeMutex);
3599bf215546Sopenharmony_ci
3600bf215546Sopenharmony_ci   free(shader_include->shader_source);
3601bf215546Sopenharmony_ci   shader_include->shader_source = NULL;
3602bf215546Sopenharmony_ci
3603bf215546Sopenharmony_ci   simple_mtx_unlock(&ctx->Shared->ShaderIncludeMutex);
3604bf215546Sopenharmony_ci
3605bf215546Sopenharmony_ci   free(name_cp);
3606bf215546Sopenharmony_ci}
3607bf215546Sopenharmony_ci
3608bf215546Sopenharmony_ciGLvoid GLAPIENTRY
3609bf215546Sopenharmony_ci_mesa_CompileShaderIncludeARB(GLuint shader, GLsizei count,
3610bf215546Sopenharmony_ci                              const GLchar* const *path, const GLint *length)
3611bf215546Sopenharmony_ci{
3612bf215546Sopenharmony_ci   GET_CURRENT_CONTEXT(ctx);
3613bf215546Sopenharmony_ci   const char *caller = "glCompileShaderIncludeARB";
3614bf215546Sopenharmony_ci
3615bf215546Sopenharmony_ci   if (count > 0 && path == NULL) {
3616bf215546Sopenharmony_ci      _mesa_error(ctx, GL_INVALID_VALUE, "%s(count > 0 && path == NULL)",
3617bf215546Sopenharmony_ci                  caller);
3618bf215546Sopenharmony_ci      return;
3619bf215546Sopenharmony_ci   }
3620bf215546Sopenharmony_ci
3621bf215546Sopenharmony_ci   void *mem_ctx = ralloc_context(NULL);
3622bf215546Sopenharmony_ci
3623bf215546Sopenharmony_ci   simple_mtx_lock(&ctx->Shared->ShaderIncludeMutex);
3624bf215546Sopenharmony_ci
3625bf215546Sopenharmony_ci   ctx->Shared->ShaderIncludes->include_paths =
3626bf215546Sopenharmony_ci      ralloc_array_size(mem_ctx, sizeof(struct sh_incl_path_entry *), count);
3627bf215546Sopenharmony_ci
3628bf215546Sopenharmony_ci   for (size_t i = 0; i < count; i++) {
3629bf215546Sopenharmony_ci      char *path_cp = copy_string(ctx, path[i], length ? length[i] : -1,
3630bf215546Sopenharmony_ci                                  caller);
3631bf215546Sopenharmony_ci      if (!path_cp) {
3632bf215546Sopenharmony_ci         goto exit;
3633bf215546Sopenharmony_ci      }
3634bf215546Sopenharmony_ci
3635bf215546Sopenharmony_ci      struct sh_incl_path_entry *path_list;
3636bf215546Sopenharmony_ci
3637bf215546Sopenharmony_ci      if (!validate_and_tokenise_sh_incl(ctx, mem_ctx, &path_list, path_cp,
3638bf215546Sopenharmony_ci                                         true)) {
3639bf215546Sopenharmony_ci         free(path_cp);
3640bf215546Sopenharmony_ci         goto exit;
3641bf215546Sopenharmony_ci      }
3642bf215546Sopenharmony_ci
3643bf215546Sopenharmony_ci      ctx->Shared->ShaderIncludes->include_paths[i] = path_list;
3644bf215546Sopenharmony_ci
3645bf215546Sopenharmony_ci      free(path_cp);
3646bf215546Sopenharmony_ci   }
3647bf215546Sopenharmony_ci
3648bf215546Sopenharmony_ci   /* We must set this *after* all calls to validate_and_tokenise_sh_incl()
3649bf215546Sopenharmony_ci    * are done as we use this to decide if we need to check the start of the
3650bf215546Sopenharmony_ci    * path for a '/'
3651bf215546Sopenharmony_ci    */
3652bf215546Sopenharmony_ci   ctx->Shared->ShaderIncludes->num_include_paths = count;
3653bf215546Sopenharmony_ci
3654bf215546Sopenharmony_ci   struct gl_shader *sh = _mesa_lookup_shader(ctx, shader);
3655bf215546Sopenharmony_ci   if (!sh) {
3656bf215546Sopenharmony_ci      _mesa_error(ctx, GL_INVALID_OPERATION, "%s(shader)", caller);
3657bf215546Sopenharmony_ci      goto exit;
3658bf215546Sopenharmony_ci   }
3659bf215546Sopenharmony_ci
3660bf215546Sopenharmony_ci   _mesa_compile_shader(ctx, sh);
3661bf215546Sopenharmony_ci
3662bf215546Sopenharmony_ciexit:
3663bf215546Sopenharmony_ci   ctx->Shared->ShaderIncludes->num_include_paths = 0;
3664bf215546Sopenharmony_ci   ctx->Shared->ShaderIncludes->relative_path_cursor = 0;
3665bf215546Sopenharmony_ci   ctx->Shared->ShaderIncludes->include_paths = NULL;
3666bf215546Sopenharmony_ci
3667bf215546Sopenharmony_ci   simple_mtx_unlock(&ctx->Shared->ShaderIncludeMutex);
3668bf215546Sopenharmony_ci
3669bf215546Sopenharmony_ci   ralloc_free(mem_ctx);
3670bf215546Sopenharmony_ci}
3671bf215546Sopenharmony_ci
3672bf215546Sopenharmony_ciGLboolean GLAPIENTRY
3673bf215546Sopenharmony_ci_mesa_IsNamedStringARB(GLint namelen, const GLchar *name)
3674bf215546Sopenharmony_ci{
3675bf215546Sopenharmony_ci   GET_CURRENT_CONTEXT(ctx);
3676bf215546Sopenharmony_ci
3677bf215546Sopenharmony_ci   if (!name)
3678bf215546Sopenharmony_ci      return false;
3679bf215546Sopenharmony_ci
3680bf215546Sopenharmony_ci   char *name_cp = copy_string(ctx, name, namelen, "");
3681bf215546Sopenharmony_ci
3682bf215546Sopenharmony_ci   const char *source = _mesa_lookup_shader_include(ctx, name_cp, false);
3683bf215546Sopenharmony_ci   free(name_cp);
3684bf215546Sopenharmony_ci
3685bf215546Sopenharmony_ci   if (!source)
3686bf215546Sopenharmony_ci      return false;
3687bf215546Sopenharmony_ci
3688bf215546Sopenharmony_ci   return true;
3689bf215546Sopenharmony_ci}
3690bf215546Sopenharmony_ci
3691bf215546Sopenharmony_ciGLvoid GLAPIENTRY
3692bf215546Sopenharmony_ci_mesa_GetNamedStringARB(GLint namelen, const GLchar *name, GLsizei bufSize,
3693bf215546Sopenharmony_ci                        GLint *stringlen, GLchar *string)
3694bf215546Sopenharmony_ci{
3695bf215546Sopenharmony_ci   GET_CURRENT_CONTEXT(ctx);
3696bf215546Sopenharmony_ci   const char *caller = "glGetNamedStringARB";
3697bf215546Sopenharmony_ci
3698bf215546Sopenharmony_ci   char *name_cp = copy_string(ctx, name, namelen, caller);
3699bf215546Sopenharmony_ci   if (!name_cp)
3700bf215546Sopenharmony_ci      return;
3701bf215546Sopenharmony_ci
3702bf215546Sopenharmony_ci   const char *source = _mesa_lookup_shader_include(ctx, name_cp, true);
3703bf215546Sopenharmony_ci   if (!source) {
3704bf215546Sopenharmony_ci      _mesa_error(ctx, GL_INVALID_OPERATION,
3705bf215546Sopenharmony_ci                  "%s(no string associated with path %s)", caller, name_cp);
3706bf215546Sopenharmony_ci      free(name_cp);
3707bf215546Sopenharmony_ci      return;
3708bf215546Sopenharmony_ci   }
3709bf215546Sopenharmony_ci
3710bf215546Sopenharmony_ci   size_t size = MIN2(strlen(source), bufSize - 1);
3711bf215546Sopenharmony_ci   memcpy(string, source, size);
3712bf215546Sopenharmony_ci   string[size] = '\0';
3713bf215546Sopenharmony_ci
3714bf215546Sopenharmony_ci   *stringlen = size;
3715bf215546Sopenharmony_ci
3716bf215546Sopenharmony_ci   free(name_cp);
3717bf215546Sopenharmony_ci}
3718bf215546Sopenharmony_ci
3719bf215546Sopenharmony_ciGLvoid GLAPIENTRY
3720bf215546Sopenharmony_ci_mesa_GetNamedStringivARB(GLint namelen, const GLchar *name,
3721bf215546Sopenharmony_ci                          GLenum pname, GLint *params)
3722bf215546Sopenharmony_ci{
3723bf215546Sopenharmony_ci   GET_CURRENT_CONTEXT(ctx);
3724bf215546Sopenharmony_ci   const char *caller = "glGetNamedStringivARB";
3725bf215546Sopenharmony_ci
3726bf215546Sopenharmony_ci   char *name_cp = copy_string(ctx, name, namelen, caller);
3727bf215546Sopenharmony_ci   if (!name_cp)
3728bf215546Sopenharmony_ci      return;
3729bf215546Sopenharmony_ci
3730bf215546Sopenharmony_ci   const char *source = _mesa_lookup_shader_include(ctx, name_cp, true);
3731bf215546Sopenharmony_ci   if (!source) {
3732bf215546Sopenharmony_ci      _mesa_error(ctx, GL_INVALID_OPERATION,
3733bf215546Sopenharmony_ci                  "%s(no string associated with path %s)", caller, name_cp);
3734bf215546Sopenharmony_ci      free(name_cp);
3735bf215546Sopenharmony_ci      return;
3736bf215546Sopenharmony_ci   }
3737bf215546Sopenharmony_ci
3738bf215546Sopenharmony_ci   switch (pname) {
3739bf215546Sopenharmony_ci   case GL_NAMED_STRING_LENGTH_ARB:
3740bf215546Sopenharmony_ci      *params = strlen(source) + 1;
3741bf215546Sopenharmony_ci      break;
3742bf215546Sopenharmony_ci   case GL_NAMED_STRING_TYPE_ARB:
3743bf215546Sopenharmony_ci      *params = GL_SHADER_INCLUDE_ARB;
3744bf215546Sopenharmony_ci      break;
3745bf215546Sopenharmony_ci   default:
3746bf215546Sopenharmony_ci      _mesa_error(ctx, GL_INVALID_ENUM, "%s(pname)", caller);
3747bf215546Sopenharmony_ci      break;
3748bf215546Sopenharmony_ci   }
3749bf215546Sopenharmony_ci
3750bf215546Sopenharmony_ci   free(name_cp);
3751bf215546Sopenharmony_ci}
3752bf215546Sopenharmony_ci
3753bf215546Sopenharmony_cistatic int
3754bf215546Sopenharmony_cifind_compat_subroutine(struct gl_program *p, const struct glsl_type *type)
3755bf215546Sopenharmony_ci{
3756bf215546Sopenharmony_ci   int i, j;
3757bf215546Sopenharmony_ci
3758bf215546Sopenharmony_ci   for (i = 0; i < p->sh.NumSubroutineFunctions; i++) {
3759bf215546Sopenharmony_ci      struct gl_subroutine_function *fn = &p->sh.SubroutineFunctions[i];
3760bf215546Sopenharmony_ci      for (j = 0; j < fn->num_compat_types; j++) {
3761bf215546Sopenharmony_ci         if (fn->types[j] == type)
3762bf215546Sopenharmony_ci            return i;
3763bf215546Sopenharmony_ci      }
3764bf215546Sopenharmony_ci   }
3765bf215546Sopenharmony_ci   return 0;
3766bf215546Sopenharmony_ci}
3767bf215546Sopenharmony_ci
3768bf215546Sopenharmony_cistatic void
3769bf215546Sopenharmony_ci_mesa_shader_write_subroutine_index(struct gl_context *ctx,
3770bf215546Sopenharmony_ci                                    struct gl_program *p)
3771bf215546Sopenharmony_ci{
3772bf215546Sopenharmony_ci   int i, j;
3773bf215546Sopenharmony_ci
3774bf215546Sopenharmony_ci   if (p->sh.NumSubroutineUniformRemapTable == 0)
3775bf215546Sopenharmony_ci      return;
3776bf215546Sopenharmony_ci
3777bf215546Sopenharmony_ci   i = 0;
3778bf215546Sopenharmony_ci   do {
3779bf215546Sopenharmony_ci      struct gl_uniform_storage *uni = p->sh.SubroutineUniformRemapTable[i];
3780bf215546Sopenharmony_ci      int uni_count;
3781bf215546Sopenharmony_ci      int val;
3782bf215546Sopenharmony_ci
3783bf215546Sopenharmony_ci      if (!uni) {
3784bf215546Sopenharmony_ci         i++;
3785bf215546Sopenharmony_ci         continue;
3786bf215546Sopenharmony_ci      }
3787bf215546Sopenharmony_ci
3788bf215546Sopenharmony_ci      uni_count = uni->array_elements ? uni->array_elements : 1;
3789bf215546Sopenharmony_ci      for (j = 0; j < uni_count; j++) {
3790bf215546Sopenharmony_ci         val = ctx->SubroutineIndex[p->info.stage].IndexPtr[i + j];
3791bf215546Sopenharmony_ci         memcpy(&uni->storage[j], &val, sizeof(int));
3792bf215546Sopenharmony_ci      }
3793bf215546Sopenharmony_ci
3794bf215546Sopenharmony_ci      _mesa_propagate_uniforms_to_driver_storage(uni, 0, uni_count);
3795bf215546Sopenharmony_ci      i += uni_count;
3796bf215546Sopenharmony_ci   } while(i < p->sh.NumSubroutineUniformRemapTable);
3797bf215546Sopenharmony_ci}
3798bf215546Sopenharmony_ci
3799bf215546Sopenharmony_civoid
3800bf215546Sopenharmony_ci_mesa_shader_write_subroutine_indices(struct gl_context *ctx,
3801bf215546Sopenharmony_ci                                      gl_shader_stage stage)
3802bf215546Sopenharmony_ci{
3803bf215546Sopenharmony_ci   if (ctx->_Shader->CurrentProgram[stage])
3804bf215546Sopenharmony_ci      _mesa_shader_write_subroutine_index(ctx,
3805bf215546Sopenharmony_ci                                          ctx->_Shader->CurrentProgram[stage]);
3806bf215546Sopenharmony_ci}
3807bf215546Sopenharmony_ci
3808bf215546Sopenharmony_civoid
3809bf215546Sopenharmony_ci_mesa_program_init_subroutine_defaults(struct gl_context *ctx,
3810bf215546Sopenharmony_ci                                       struct gl_program *p)
3811bf215546Sopenharmony_ci{
3812bf215546Sopenharmony_ci   assert(p);
3813bf215546Sopenharmony_ci
3814bf215546Sopenharmony_ci   struct gl_subroutine_index_binding *binding = &ctx->SubroutineIndex[p->info.stage];
3815bf215546Sopenharmony_ci   if (binding->NumIndex != p->sh.NumSubroutineUniformRemapTable) {
3816bf215546Sopenharmony_ci      binding->IndexPtr = realloc(binding->IndexPtr,
3817bf215546Sopenharmony_ci                                  p->sh.NumSubroutineUniformRemapTable * (sizeof(GLuint)));
3818bf215546Sopenharmony_ci      binding->NumIndex = p->sh.NumSubroutineUniformRemapTable;
3819bf215546Sopenharmony_ci   }
3820bf215546Sopenharmony_ci
3821bf215546Sopenharmony_ci   for (int i = 0; i < p->sh.NumSubroutineUniformRemapTable; i++) {
3822bf215546Sopenharmony_ci      struct gl_uniform_storage *uni = p->sh.SubroutineUniformRemapTable[i];
3823bf215546Sopenharmony_ci
3824bf215546Sopenharmony_ci      if (!uni)
3825bf215546Sopenharmony_ci         continue;
3826bf215546Sopenharmony_ci
3827bf215546Sopenharmony_ci      binding->IndexPtr[i] = find_compat_subroutine(p, uni->type);
3828bf215546Sopenharmony_ci   }
3829bf215546Sopenharmony_ci}
3830