1848b8605Smrg/*
2848b8605Smrg * Mesa 3-D graphics library
3848b8605Smrg *
4848b8605Smrg * Copyright (C) 2004-2008  Brian Paul   All Rights Reserved.
5848b8605Smrg * Copyright (C) 2009-2010  VMware, Inc.  All Rights Reserved.
6848b8605Smrg *
7848b8605Smrg * Permission is hereby granted, free of charge, to any person obtaining a
8848b8605Smrg * copy of this software and associated documentation files (the "Software"),
9848b8605Smrg * to deal in the Software without restriction, including without limitation
10848b8605Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11848b8605Smrg * and/or sell copies of the Software, and to permit persons to whom the
12848b8605Smrg * Software is furnished to do so, subject to the following conditions:
13848b8605Smrg *
14848b8605Smrg * The above copyright notice and this permission notice shall be included
15848b8605Smrg * in all copies or substantial portions of the Software.
16848b8605Smrg *
17848b8605Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18848b8605Smrg * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19848b8605Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
20848b8605Smrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
21848b8605Smrg * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
22848b8605Smrg * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
23848b8605Smrg * OTHER DEALINGS IN THE SOFTWARE.
24848b8605Smrg */
25848b8605Smrg
26848b8605Smrg/**
27848b8605Smrg * \file shaderapi.c
28848b8605Smrg * \author Brian Paul
29848b8605Smrg *
30848b8605Smrg * Implementation of GLSL-related API functions.
31848b8605Smrg * The glUniform* functions are in uniforms.c
32848b8605Smrg *
33848b8605Smrg *
34848b8605Smrg * XXX things to do:
35848b8605Smrg * 1. Check that the right error code is generated for all _mesa_error() calls.
36848b8605Smrg * 2. Insert FLUSH_VERTICES calls in various places
37848b8605Smrg */
38848b8605Smrg
39848b8605Smrg
40b8e80941Smrg#include <stdbool.h>
41b8e80941Smrg#include <c99_alloca.h>
42848b8605Smrg#include "main/glheader.h"
43848b8605Smrg#include "main/context.h"
44848b8605Smrg#include "main/enums.h"
45b8e80941Smrg#include "main/glspirv.h"
46848b8605Smrg#include "main/hash.h"
47848b8605Smrg#include "main/mtypes.h"
48848b8605Smrg#include "main/pipelineobj.h"
49b8e80941Smrg#include "main/program_binary.h"
50848b8605Smrg#include "main/shaderapi.h"
51848b8605Smrg#include "main/shaderobj.h"
52b8e80941Smrg#include "main/state.h"
53848b8605Smrg#include "main/transformfeedback.h"
54848b8605Smrg#include "main/uniforms.h"
55b8e80941Smrg#include "compiler/glsl/glsl_parser_extras.h"
56b8e80941Smrg#include "compiler/glsl/ir.h"
57b8e80941Smrg#include "compiler/glsl/ir_uniform.h"
58b8e80941Smrg#include "compiler/glsl/program.h"
59848b8605Smrg#include "program/program.h"
60848b8605Smrg#include "program/prog_print.h"
61848b8605Smrg#include "program/prog_parameter.h"
62848b8605Smrg#include "util/ralloc.h"
63848b8605Smrg#include "util/hash_table.h"
64b8e80941Smrg#include "util/mesa-sha1.h"
65b8e80941Smrg#include "util/crc32.h"
66848b8605Smrg
67848b8605Smrg/**
68848b8605Smrg * Return mask of GLSL_x flags by examining the MESA_GLSL env var.
69848b8605Smrg */
70848b8605SmrgGLbitfield
71848b8605Smrg_mesa_get_shader_flags(void)
72848b8605Smrg{
73848b8605Smrg   GLbitfield flags = 0x0;
74b8e80941Smrg   const char *env = getenv("MESA_GLSL");
75848b8605Smrg
76848b8605Smrg   if (env) {
77848b8605Smrg      if (strstr(env, "dump_on_error"))
78848b8605Smrg         flags |= GLSL_DUMP_ON_ERROR;
79848b8605Smrg      else if (strstr(env, "dump"))
80848b8605Smrg         flags |= GLSL_DUMP;
81848b8605Smrg      if (strstr(env, "log"))
82848b8605Smrg         flags |= GLSL_LOG;
83b8e80941Smrg      if (strstr(env, "cache_fb"))
84b8e80941Smrg         flags |= GLSL_CACHE_FALLBACK;
85b8e80941Smrg      if (strstr(env, "cache_info"))
86b8e80941Smrg         flags |= GLSL_CACHE_INFO;
87848b8605Smrg      if (strstr(env, "nopvert"))
88848b8605Smrg         flags |= GLSL_NOP_VERT;
89848b8605Smrg      if (strstr(env, "nopfrag"))
90848b8605Smrg         flags |= GLSL_NOP_FRAG;
91848b8605Smrg      if (strstr(env, "uniform"))
92848b8605Smrg         flags |= GLSL_UNIFORMS;
93848b8605Smrg      if (strstr(env, "useprog"))
94848b8605Smrg         flags |= GLSL_USE_PROG;
95848b8605Smrg      if (strstr(env, "errors"))
96848b8605Smrg         flags |= GLSL_REPORT_ERRORS;
97848b8605Smrg   }
98848b8605Smrg
99848b8605Smrg   return flags;
100848b8605Smrg}
101848b8605Smrg
102b8e80941Smrg/**
103b8e80941Smrg * Memoized version of getenv("MESA_SHADER_CAPTURE_PATH").
104b8e80941Smrg */
105b8e80941Smrgconst char *
106b8e80941Smrg_mesa_get_shader_capture_path(void)
107b8e80941Smrg{
108b8e80941Smrg   static bool read_env_var = false;
109b8e80941Smrg   static const char *path = NULL;
110b8e80941Smrg
111b8e80941Smrg   if (!read_env_var) {
112b8e80941Smrg      path = getenv("MESA_SHADER_CAPTURE_PATH");
113b8e80941Smrg      read_env_var = true;
114b8e80941Smrg   }
115b8e80941Smrg
116b8e80941Smrg   return path;
117b8e80941Smrg}
118848b8605Smrg
119848b8605Smrg/**
120848b8605Smrg * Initialize context's shader state.
121848b8605Smrg */
122848b8605Smrgvoid
123848b8605Smrg_mesa_init_shader_state(struct gl_context *ctx)
124848b8605Smrg{
125848b8605Smrg   /* Device drivers may override these to control what kind of instructions
126848b8605Smrg    * are generated by the GLSL compiler.
127848b8605Smrg    */
128848b8605Smrg   struct gl_shader_compiler_options options;
129848b8605Smrg   gl_shader_stage sh;
130b8e80941Smrg   int i;
131848b8605Smrg
132848b8605Smrg   memset(&options, 0, sizeof(options));
133848b8605Smrg   options.MaxUnrollIterations = 32;
134848b8605Smrg   options.MaxIfDepth = UINT_MAX;
135848b8605Smrg
136848b8605Smrg   for (sh = 0; sh < MESA_SHADER_STAGES; ++sh)
137848b8605Smrg      memcpy(&ctx->Const.ShaderCompilerOptions[sh], &options, sizeof(options));
138848b8605Smrg
139848b8605Smrg   ctx->Shader.Flags = _mesa_get_shader_flags();
140848b8605Smrg
141b8e80941Smrg   if (ctx->Shader.Flags != 0)
142b8e80941Smrg      ctx->Const.GenerateTemporaryNames = true;
143b8e80941Smrg
144848b8605Smrg   /* Extended for ARB_separate_shader_objects */
145848b8605Smrg   ctx->Shader.RefCount = 1;
146b8e80941Smrg   ctx->TessCtrlProgram.patch_vertices = 3;
147b8e80941Smrg   for (i = 0; i < 4; ++i)
148b8e80941Smrg      ctx->TessCtrlProgram.patch_default_outer_level[i] = 1.0;
149b8e80941Smrg   for (i = 0; i < 2; ++i)
150b8e80941Smrg      ctx->TessCtrlProgram.patch_default_inner_level[i] = 1.0;
151848b8605Smrg}
152848b8605Smrg
153848b8605Smrg
154848b8605Smrg/**
155848b8605Smrg * Free the per-context shader-related state.
156848b8605Smrg */
157848b8605Smrgvoid
158848b8605Smrg_mesa_free_shader_state(struct gl_context *ctx)
159848b8605Smrg{
160b8e80941Smrg   for (int i = 0; i < MESA_SHADER_STAGES; i++) {
161b8e80941Smrg      _mesa_reference_program(ctx, &ctx->Shader.CurrentProgram[i], NULL);
162b8e80941Smrg      _mesa_reference_shader_program(ctx,
163b8e80941Smrg                                     &ctx->Shader.ReferencedPrograms[i],
164848b8605Smrg                                     NULL);
165b8e80941Smrg      free(ctx->SubroutineIndex[i].IndexPtr);
166b8e80941Smrg      ctx->SubroutineIndex[i].IndexPtr = NULL;
167848b8605Smrg   }
168848b8605Smrg   _mesa_reference_shader_program(ctx, &ctx->Shader.ActiveProgram, NULL);
169848b8605Smrg
170848b8605Smrg   /* Extended for ARB_separate_shader_objects */
171848b8605Smrg   _mesa_reference_pipeline_object(ctx, &ctx->_Shader, NULL);
172848b8605Smrg
173848b8605Smrg   assert(ctx->Shader.RefCount == 1);
174848b8605Smrg}
175848b8605Smrg
176848b8605Smrg
177848b8605Smrg/**
178848b8605Smrg * Copy string from <src> to <dst>, up to maxLength characters, returning
179848b8605Smrg * length of <dst> in <length>.
180848b8605Smrg * \param src  the strings source
181848b8605Smrg * \param maxLength  max chars to copy
182848b8605Smrg * \param length  returns number of chars copied
183848b8605Smrg * \param dst  the string destination
184848b8605Smrg */
185848b8605Smrgvoid
186848b8605Smrg_mesa_copy_string(GLchar *dst, GLsizei maxLength,
187848b8605Smrg                  GLsizei *length, const GLchar *src)
188848b8605Smrg{
189848b8605Smrg   GLsizei len;
190848b8605Smrg   for (len = 0; len < maxLength - 1 && src && src[len]; len++)
191848b8605Smrg      dst[len] = src[len];
192848b8605Smrg   if (maxLength > 0)
193848b8605Smrg      dst[len] = 0;
194848b8605Smrg   if (length)
195848b8605Smrg      *length = len;
196848b8605Smrg}
197848b8605Smrg
198848b8605Smrg
199848b8605Smrg
200848b8605Smrg/**
201848b8605Smrg * Confirm that the a shader type is valid and supported by the implementation
202848b8605Smrg *
203848b8605Smrg * \param ctx   Current GL context
204848b8605Smrg * \param type  Shader target
205848b8605Smrg *
206848b8605Smrg */
207848b8605Smrgbool
208848b8605Smrg_mesa_validate_shader_target(const struct gl_context *ctx, GLenum type)
209848b8605Smrg{
210848b8605Smrg   /* Note: when building built-in GLSL functions, this function may be
211848b8605Smrg    * invoked with ctx == NULL.  In that case, we can only validate that it's
212848b8605Smrg    * a shader target we recognize, not that it's supported in the current
213848b8605Smrg    * context.  But that's fine--we don't need any further validation than
214848b8605Smrg    * that when building built-in GLSL functions.
215848b8605Smrg    */
216848b8605Smrg
217848b8605Smrg   switch (type) {
218848b8605Smrg   case GL_FRAGMENT_SHADER:
219848b8605Smrg      return ctx == NULL || ctx->Extensions.ARB_fragment_shader;
220848b8605Smrg   case GL_VERTEX_SHADER:
221848b8605Smrg      return ctx == NULL || ctx->Extensions.ARB_vertex_shader;
222848b8605Smrg   case GL_GEOMETRY_SHADER_ARB:
223848b8605Smrg      return ctx == NULL || _mesa_has_geometry_shaders(ctx);
224b8e80941Smrg   case GL_TESS_CONTROL_SHADER:
225b8e80941Smrg   case GL_TESS_EVALUATION_SHADER:
226b8e80941Smrg      return ctx == NULL || _mesa_has_tessellation(ctx);
227848b8605Smrg   case GL_COMPUTE_SHADER:
228b8e80941Smrg      return ctx == NULL || _mesa_has_compute_shaders(ctx);
229848b8605Smrg   default:
230848b8605Smrg      return false;
231848b8605Smrg   }
232848b8605Smrg}
233848b8605Smrg
234848b8605Smrg
235848b8605Smrgstatic GLboolean
236848b8605Smrgis_program(struct gl_context *ctx, GLuint name)
237848b8605Smrg{
238848b8605Smrg   struct gl_shader_program *shProg = _mesa_lookup_shader_program(ctx, name);
239848b8605Smrg   return shProg ? GL_TRUE : GL_FALSE;
240848b8605Smrg}
241848b8605Smrg
242848b8605Smrg
243848b8605Smrgstatic GLboolean
244848b8605Smrgis_shader(struct gl_context *ctx, GLuint name)
245848b8605Smrg{
246848b8605Smrg   struct gl_shader *shader = _mesa_lookup_shader(ctx, name);
247848b8605Smrg   return shader ? GL_TRUE : GL_FALSE;
248848b8605Smrg}
249848b8605Smrg
250848b8605Smrg
251848b8605Smrg/**
252848b8605Smrg * Attach shader to a shader program.
253848b8605Smrg */
254848b8605Smrgstatic void
255b8e80941Smrgattach_shader(struct gl_context *ctx, struct gl_shader_program *shProg,
256b8e80941Smrg              struct gl_shader *sh)
257b8e80941Smrg{
258b8e80941Smrg   GLuint n = shProg->NumShaders;
259b8e80941Smrg
260b8e80941Smrg   shProg->Shaders = realloc(shProg->Shaders,
261b8e80941Smrg                             (n + 1) * sizeof(struct gl_shader *));
262b8e80941Smrg   if (!shProg->Shaders) {
263b8e80941Smrg      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glAttachShader");
264b8e80941Smrg      return;
265b8e80941Smrg   }
266b8e80941Smrg
267b8e80941Smrg   /* append */
268b8e80941Smrg   shProg->Shaders[n] = NULL; /* since realloc() didn't zero the new space */
269b8e80941Smrg   _mesa_reference_shader(ctx, &shProg->Shaders[n], sh);
270b8e80941Smrg   shProg->NumShaders++;
271b8e80941Smrg}
272b8e80941Smrg
273b8e80941Smrgstatic void
274b8e80941Smrgattach_shader_err(struct gl_context *ctx, GLuint program, GLuint shader,
275b8e80941Smrg                  const char *caller)
276848b8605Smrg{
277848b8605Smrg   struct gl_shader_program *shProg;
278848b8605Smrg   struct gl_shader *sh;
279848b8605Smrg   GLuint i, n;
280848b8605Smrg
281848b8605Smrg   const bool same_type_disallowed = _mesa_is_gles(ctx);
282848b8605Smrg
283b8e80941Smrg   shProg = _mesa_lookup_shader_program_err(ctx, program, caller);
284848b8605Smrg   if (!shProg)
285848b8605Smrg      return;
286848b8605Smrg
287b8e80941Smrg   sh = _mesa_lookup_shader_err(ctx, shader, caller);
288848b8605Smrg   if (!sh) {
289848b8605Smrg      return;
290848b8605Smrg   }
291848b8605Smrg
292848b8605Smrg   n = shProg->NumShaders;
293848b8605Smrg   for (i = 0; i < n; i++) {
294848b8605Smrg      if (shProg->Shaders[i] == sh) {
295848b8605Smrg         /* The shader is already attched to this program.  The
296848b8605Smrg          * GL_ARB_shader_objects spec says:
297848b8605Smrg          *
298848b8605Smrg          *     "The error INVALID_OPERATION is generated by AttachObjectARB
299848b8605Smrg          *     if <obj> is already attached to <containerObj>."
300848b8605Smrg          */
301b8e80941Smrg         _mesa_error(ctx, GL_INVALID_OPERATION, "%s", caller);
302848b8605Smrg         return;
303848b8605Smrg      } else if (same_type_disallowed &&
304b8e80941Smrg                 shProg->Shaders[i]->Stage == sh->Stage) {
305848b8605Smrg        /* Shader with the same type is already attached to this program,
306848b8605Smrg         * OpenGL ES 2.0 and 3.0 specs say:
307848b8605Smrg         *
308848b8605Smrg         *      "Multiple shader objects of the same type may not be attached
309848b8605Smrg         *      to a single program object. [...] The error INVALID_OPERATION
310848b8605Smrg         *      is generated if [...] another shader object of the same type
311848b8605Smrg         *      as shader is already attached to program."
312848b8605Smrg         */
313b8e80941Smrg         _mesa_error(ctx, GL_INVALID_OPERATION, "%s", caller);
314848b8605Smrg         return;
315848b8605Smrg      }
316848b8605Smrg   }
317848b8605Smrg
318b8e80941Smrg   attach_shader(ctx, shProg, sh);
319848b8605Smrg}
320848b8605Smrg
321b8e80941Smrgstatic void
322b8e80941Smrgattach_shader_no_error(struct gl_context *ctx, GLuint program, GLuint shader)
323b8e80941Smrg{
324b8e80941Smrg   struct gl_shader_program *shProg;
325b8e80941Smrg   struct gl_shader *sh;
326b8e80941Smrg
327b8e80941Smrg   shProg = _mesa_lookup_shader_program(ctx, program);
328b8e80941Smrg   sh = _mesa_lookup_shader(ctx, shader);
329b8e80941Smrg
330b8e80941Smrg   attach_shader(ctx, shProg, sh);
331b8e80941Smrg}
332848b8605Smrg
333848b8605Smrgstatic GLuint
334848b8605Smrgcreate_shader(struct gl_context *ctx, GLenum type)
335848b8605Smrg{
336848b8605Smrg   struct gl_shader *sh;
337848b8605Smrg   GLuint name;
338848b8605Smrg
339b8e80941Smrg   _mesa_HashLockMutex(ctx->Shared->ShaderObjects);
340b8e80941Smrg   name = _mesa_HashFindFreeKeyBlock(ctx->Shared->ShaderObjects, 1);
341b8e80941Smrg   sh = _mesa_new_shader(name, _mesa_shader_enum_to_shader_stage(type));
342b8e80941Smrg   sh->Type = type;
343b8e80941Smrg   _mesa_HashInsertLocked(ctx->Shared->ShaderObjects, name, sh);
344b8e80941Smrg   _mesa_HashUnlockMutex(ctx->Shared->ShaderObjects);
345b8e80941Smrg
346b8e80941Smrg   return name;
347b8e80941Smrg}
348b8e80941Smrg
349b8e80941Smrg
350b8e80941Smrgstatic GLuint
351b8e80941Smrgcreate_shader_err(struct gl_context *ctx, GLenum type, const char *caller)
352b8e80941Smrg{
353848b8605Smrg   if (!_mesa_validate_shader_target(ctx, type)) {
354b8e80941Smrg      _mesa_error(ctx, GL_INVALID_ENUM, "%s(%s)",
355b8e80941Smrg                  caller, _mesa_enum_to_string(type));
356848b8605Smrg      return 0;
357848b8605Smrg   }
358848b8605Smrg
359b8e80941Smrg   return create_shader(ctx, type);
360848b8605Smrg}
361848b8605Smrg
362848b8605Smrg
363b8e80941Smrgstatic GLuint
364848b8605Smrgcreate_shader_program(struct gl_context *ctx)
365848b8605Smrg{
366848b8605Smrg   GLuint name;
367848b8605Smrg   struct gl_shader_program *shProg;
368848b8605Smrg
369b8e80941Smrg   _mesa_HashLockMutex(ctx->Shared->ShaderObjects);
370b8e80941Smrg
371848b8605Smrg   name = _mesa_HashFindFreeKeyBlock(ctx->Shared->ShaderObjects, 1);
372848b8605Smrg
373b8e80941Smrg   shProg = _mesa_new_shader_program(name);
374848b8605Smrg
375b8e80941Smrg   _mesa_HashInsertLocked(ctx->Shared->ShaderObjects, name, shProg);
376848b8605Smrg
377848b8605Smrg   assert(shProg->RefCount == 1);
378848b8605Smrg
379b8e80941Smrg   _mesa_HashUnlockMutex(ctx->Shared->ShaderObjects);
380b8e80941Smrg
381848b8605Smrg   return name;
382848b8605Smrg}
383848b8605Smrg
384848b8605Smrg
385848b8605Smrg/**
386b8e80941Smrg * Delete a shader program.  Actually, just decrement the program's
387b8e80941Smrg * reference count and mark it as DeletePending.
388b8e80941Smrg * Used to implement glDeleteProgram() and glDeleteObjectARB().
389848b8605Smrg */
390848b8605Smrgstatic void
391848b8605Smrgdelete_shader_program(struct gl_context *ctx, GLuint name)
392848b8605Smrg{
393848b8605Smrg   /*
394848b8605Smrg    * NOTE: deleting shaders/programs works a bit differently than
395848b8605Smrg    * texture objects (and buffer objects, etc).  Shader/program
396848b8605Smrg    * handles/IDs exist in the hash table until the object is really
397848b8605Smrg    * deleted (refcount==0).  With texture objects, the handle/ID is
398848b8605Smrg    * removed from the hash table in glDeleteTextures() while the tex
399848b8605Smrg    * object itself might linger until its refcount goes to zero.
400848b8605Smrg    */
401848b8605Smrg   struct gl_shader_program *shProg;
402848b8605Smrg
403848b8605Smrg   shProg = _mesa_lookup_shader_program_err(ctx, name, "glDeleteProgram");
404848b8605Smrg   if (!shProg)
405848b8605Smrg      return;
406848b8605Smrg
407848b8605Smrg   if (!shProg->DeletePending) {
408848b8605Smrg      shProg->DeletePending = GL_TRUE;
409848b8605Smrg
410848b8605Smrg      /* effectively, decr shProg's refcount */
411848b8605Smrg      _mesa_reference_shader_program(ctx, &shProg, NULL);
412848b8605Smrg   }
413848b8605Smrg}
414848b8605Smrg
415848b8605Smrg
416848b8605Smrgstatic void
417848b8605Smrgdelete_shader(struct gl_context *ctx, GLuint shader)
418848b8605Smrg{
419848b8605Smrg   struct gl_shader *sh;
420848b8605Smrg
421848b8605Smrg   sh = _mesa_lookup_shader_err(ctx, shader, "glDeleteShader");
422848b8605Smrg   if (!sh)
423848b8605Smrg      return;
424848b8605Smrg
425848b8605Smrg   if (!sh->DeletePending) {
426848b8605Smrg      sh->DeletePending = GL_TRUE;
427848b8605Smrg
428848b8605Smrg      /* effectively, decr sh's refcount */
429848b8605Smrg      _mesa_reference_shader(ctx, &sh, NULL);
430848b8605Smrg   }
431848b8605Smrg}
432848b8605Smrg
433848b8605Smrg
434b8e80941Smrgstatic ALWAYS_INLINE void
435b8e80941Smrgdetach_shader(struct gl_context *ctx, GLuint program, GLuint shader,
436b8e80941Smrg              bool no_error)
437848b8605Smrg{
438848b8605Smrg   struct gl_shader_program *shProg;
439848b8605Smrg   GLuint n;
440848b8605Smrg   GLuint i, j;
441848b8605Smrg
442b8e80941Smrg   if (!no_error) {
443b8e80941Smrg      shProg = _mesa_lookup_shader_program_err(ctx, program, "glDetachShader");
444b8e80941Smrg      if (!shProg)
445b8e80941Smrg         return;
446b8e80941Smrg   } else {
447b8e80941Smrg      shProg = _mesa_lookup_shader_program(ctx, program);
448b8e80941Smrg   }
449848b8605Smrg
450848b8605Smrg   n = shProg->NumShaders;
451848b8605Smrg
452848b8605Smrg   for (i = 0; i < n; i++) {
453848b8605Smrg      if (shProg->Shaders[i]->Name == shader) {
454848b8605Smrg         /* found it */
455848b8605Smrg         struct gl_shader **newList;
456848b8605Smrg
457848b8605Smrg         /* release */
458848b8605Smrg         _mesa_reference_shader(ctx, &shProg->Shaders[i], NULL);
459848b8605Smrg
460848b8605Smrg         /* alloc new, smaller array */
461848b8605Smrg         newList = malloc((n - 1) * sizeof(struct gl_shader *));
462848b8605Smrg         if (!newList) {
463848b8605Smrg            _mesa_error(ctx, GL_OUT_OF_MEMORY, "glDetachShader");
464848b8605Smrg            return;
465848b8605Smrg         }
466848b8605Smrg         /* Copy old list entries to new list, skipping removed entry at [i] */
467848b8605Smrg         for (j = 0; j < i; j++) {
468848b8605Smrg            newList[j] = shProg->Shaders[j];
469848b8605Smrg         }
470848b8605Smrg         while (++i < n) {
471848b8605Smrg            newList[j++] = shProg->Shaders[i];
472848b8605Smrg         }
473848b8605Smrg
474848b8605Smrg         /* Free old list and install new one */
475848b8605Smrg         free(shProg->Shaders);
476848b8605Smrg         shProg->Shaders = newList;
477848b8605Smrg         shProg->NumShaders = n - 1;
478848b8605Smrg
479848b8605Smrg#ifdef DEBUG
480848b8605Smrg         /* sanity check - make sure the new list's entries are sensible */
481848b8605Smrg         for (j = 0; j < shProg->NumShaders; j++) {
482b8e80941Smrg            assert(shProg->Shaders[j]->Stage == MESA_SHADER_VERTEX ||
483b8e80941Smrg                   shProg->Shaders[j]->Stage == MESA_SHADER_TESS_CTRL ||
484b8e80941Smrg                   shProg->Shaders[j]->Stage == MESA_SHADER_TESS_EVAL ||
485b8e80941Smrg                   shProg->Shaders[j]->Stage == MESA_SHADER_GEOMETRY ||
486b8e80941Smrg                   shProg->Shaders[j]->Stage == MESA_SHADER_FRAGMENT);
487848b8605Smrg            assert(shProg->Shaders[j]->RefCount > 0);
488848b8605Smrg         }
489848b8605Smrg#endif
490848b8605Smrg
491848b8605Smrg         return;
492848b8605Smrg      }
493848b8605Smrg   }
494848b8605Smrg
495848b8605Smrg   /* not found */
496b8e80941Smrg   if (!no_error) {
497848b8605Smrg      GLenum err;
498b8e80941Smrg      if (is_shader(ctx, shader) || is_program(ctx, shader))
499848b8605Smrg         err = GL_INVALID_OPERATION;
500848b8605Smrg      else
501848b8605Smrg         err = GL_INVALID_VALUE;
502848b8605Smrg      _mesa_error(ctx, err, "glDetachShader(shader)");
503848b8605Smrg      return;
504848b8605Smrg   }
505848b8605Smrg}
506848b8605Smrg
507848b8605Smrg
508b8e80941Smrgstatic void
509b8e80941Smrgdetach_shader_error(struct gl_context *ctx, GLuint program, GLuint shader)
510b8e80941Smrg{
511b8e80941Smrg   detach_shader(ctx, program, shader, false);
512b8e80941Smrg}
513b8e80941Smrg
514b8e80941Smrg
515b8e80941Smrgstatic void
516b8e80941Smrgdetach_shader_no_error(struct gl_context *ctx, GLuint program, GLuint shader)
517b8e80941Smrg{
518b8e80941Smrg   detach_shader(ctx, program, shader, true);
519b8e80941Smrg}
520b8e80941Smrg
521b8e80941Smrg
522848b8605Smrg/**
523848b8605Smrg * Return list of shaders attached to shader program.
524b8e80941Smrg * \param objOut  returns GLuint ids
525b8e80941Smrg * \param handleOut  returns GLhandleARB handles
526848b8605Smrg */
527848b8605Smrgstatic void
528848b8605Smrgget_attached_shaders(struct gl_context *ctx, GLuint program, GLsizei maxCount,
529b8e80941Smrg                     GLsizei *countOut, GLuint *objOut, GLhandleARB *handleOut)
530848b8605Smrg{
531b8e80941Smrg   struct gl_shader_program *shProg;
532b8e80941Smrg
533b8e80941Smrg   if (maxCount < 0) {
534b8e80941Smrg      _mesa_error(ctx, GL_INVALID_VALUE, "glGetAttachedShaders(maxCount < 0)");
535b8e80941Smrg      return;
536b8e80941Smrg   }
537b8e80941Smrg
538b8e80941Smrg   shProg =
539848b8605Smrg      _mesa_lookup_shader_program_err(ctx, program, "glGetAttachedShaders");
540b8e80941Smrg
541848b8605Smrg   if (shProg) {
542848b8605Smrg      GLuint i;
543848b8605Smrg      for (i = 0; i < (GLuint) maxCount && i < shProg->NumShaders; i++) {
544b8e80941Smrg         if (objOut) {
545b8e80941Smrg            objOut[i] = shProg->Shaders[i]->Name;
546b8e80941Smrg         }
547b8e80941Smrg
548b8e80941Smrg         if (handleOut) {
549b8e80941Smrg            handleOut[i] = (GLhandleARB) shProg->Shaders[i]->Name;
550b8e80941Smrg         }
551b8e80941Smrg      }
552b8e80941Smrg      if (countOut) {
553b8e80941Smrg         *countOut = i;
554848b8605Smrg      }
555848b8605Smrg   }
556848b8605Smrg}
557848b8605Smrg
558848b8605Smrg/**
559848b8605Smrg * glGetHandleARB() - return ID/name of currently bound shader program.
560848b8605Smrg */
561848b8605Smrgstatic GLuint
562848b8605Smrgget_handle(struct gl_context *ctx, GLenum pname)
563848b8605Smrg{
564848b8605Smrg   if (pname == GL_PROGRAM_OBJECT_ARB) {
565848b8605Smrg      if (ctx->_Shader->ActiveProgram)
566848b8605Smrg         return ctx->_Shader->ActiveProgram->Name;
567848b8605Smrg      else
568848b8605Smrg         return 0;
569848b8605Smrg   }
570848b8605Smrg   else {
571848b8605Smrg      _mesa_error(ctx, GL_INVALID_ENUM, "glGetHandleARB");
572848b8605Smrg      return 0;
573848b8605Smrg   }
574848b8605Smrg}
575848b8605Smrg
576848b8605Smrg
577848b8605Smrg/**
578848b8605Smrg * Check if a geometry shader query is valid at this time.  If not, report an
579848b8605Smrg * error and return false.
580848b8605Smrg *
581848b8605Smrg * From GL 3.2 section 6.1.16 (Shader and Program Queries):
582848b8605Smrg *
583848b8605Smrg *     "If GEOMETRY_VERTICES_OUT, GEOMETRY_INPUT_TYPE, or GEOMETRY_OUTPUT_TYPE
584848b8605Smrg *     are queried for a program which has not been linked successfully, or
585848b8605Smrg *     which does not contain objects to form a geometry shader, then an
586848b8605Smrg *     INVALID_OPERATION error is generated."
587848b8605Smrg */
588848b8605Smrgstatic bool
589848b8605Smrgcheck_gs_query(struct gl_context *ctx, const struct gl_shader_program *shProg)
590848b8605Smrg{
591b8e80941Smrg   if (shProg->data->LinkStatus &&
592848b8605Smrg       shProg->_LinkedShaders[MESA_SHADER_GEOMETRY] != NULL) {
593848b8605Smrg      return true;
594848b8605Smrg   }
595848b8605Smrg
596848b8605Smrg   _mesa_error(ctx, GL_INVALID_OPERATION,
597848b8605Smrg               "glGetProgramv(linked geometry shader required)");
598848b8605Smrg   return false;
599848b8605Smrg}
600848b8605Smrg
601848b8605Smrg
602b8e80941Smrg/**
603b8e80941Smrg * Check if a tessellation control shader query is valid at this time.
604b8e80941Smrg * If not, report an error and return false.
605b8e80941Smrg *
606b8e80941Smrg * From GL 4.0 section 6.1.12 (Shader and Program Queries):
607b8e80941Smrg *
608b8e80941Smrg *     "If TESS_CONTROL_OUTPUT_VERTICES is queried for a program which has
609b8e80941Smrg *     not been linked successfully, or which does not contain objects to
610b8e80941Smrg *     form a tessellation control shader, then an INVALID_OPERATION error is
611b8e80941Smrg *     generated."
612b8e80941Smrg */
613b8e80941Smrgstatic bool
614b8e80941Smrgcheck_tcs_query(struct gl_context *ctx, const struct gl_shader_program *shProg)
615b8e80941Smrg{
616b8e80941Smrg   if (shProg->data->LinkStatus &&
617b8e80941Smrg       shProg->_LinkedShaders[MESA_SHADER_TESS_CTRL] != NULL) {
618b8e80941Smrg      return true;
619b8e80941Smrg   }
620b8e80941Smrg
621b8e80941Smrg   _mesa_error(ctx, GL_INVALID_OPERATION,
622b8e80941Smrg               "glGetProgramv(linked tessellation control shader required)");
623b8e80941Smrg   return false;
624b8e80941Smrg}
625b8e80941Smrg
626b8e80941Smrg
627b8e80941Smrg/**
628b8e80941Smrg * Check if a tessellation evaluation shader query is valid at this time.
629b8e80941Smrg * If not, report an error and return false.
630b8e80941Smrg *
631b8e80941Smrg * From GL 4.0 section 6.1.12 (Shader and Program Queries):
632b8e80941Smrg *
633b8e80941Smrg *     "If any of the pname values in this paragraph are queried for a program
634b8e80941Smrg *     which has not been linked successfully, or which does not contain
635b8e80941Smrg *     objects to form a tessellation evaluation shader, then an
636b8e80941Smrg *     INVALID_OPERATION error is generated."
637b8e80941Smrg *
638b8e80941Smrg */
639b8e80941Smrgstatic bool
640b8e80941Smrgcheck_tes_query(struct gl_context *ctx, const struct gl_shader_program *shProg)
641b8e80941Smrg{
642b8e80941Smrg   if (shProg->data->LinkStatus &&
643b8e80941Smrg       shProg->_LinkedShaders[MESA_SHADER_TESS_EVAL] != NULL) {
644b8e80941Smrg      return true;
645b8e80941Smrg   }
646b8e80941Smrg
647b8e80941Smrg   _mesa_error(ctx, GL_INVALID_OPERATION, "glGetProgramv(linked tessellation "
648b8e80941Smrg               "evaluation shader required)");
649b8e80941Smrg   return false;
650b8e80941Smrg}
651b8e80941Smrg
652b8e80941Smrg
653848b8605Smrg/**
654848b8605Smrg * glGetProgramiv() - get shader program state.
655848b8605Smrg * Note that this is for GLSL shader programs, not ARB vertex/fragment
656848b8605Smrg * programs (see glGetProgramivARB).
657848b8605Smrg */
658848b8605Smrgstatic void
659b8e80941Smrgget_programiv(struct gl_context *ctx, GLuint program, GLenum pname,
660b8e80941Smrg              GLint *params)
661848b8605Smrg{
662848b8605Smrg   struct gl_shader_program *shProg
663b8e80941Smrg      = _mesa_lookup_shader_program_err(ctx, program, "glGetProgramiv(program)");
664848b8605Smrg
665848b8605Smrg   /* Is transform feedback available in this context?
666848b8605Smrg    */
667848b8605Smrg   const bool has_xfb =
668848b8605Smrg      (ctx->API == API_OPENGL_COMPAT && ctx->Extensions.EXT_transform_feedback)
669848b8605Smrg      || ctx->API == API_OPENGL_CORE
670848b8605Smrg      || _mesa_is_gles3(ctx);
671848b8605Smrg
672848b8605Smrg   /* True if geometry shaders (of the form that was adopted into GLSL 1.50
673848b8605Smrg    * and GL 3.2) are available in this context
674848b8605Smrg    */
675b8e80941Smrg   const bool has_gs = _mesa_has_geometry_shaders(ctx);
676b8e80941Smrg   const bool has_tess = _mesa_has_tessellation(ctx);
677848b8605Smrg
678848b8605Smrg   /* Are uniform buffer objects available in this context?
679848b8605Smrg    */
680848b8605Smrg   const bool has_ubo =
681b8e80941Smrg      (ctx->API == API_OPENGL_COMPAT &&
682b8e80941Smrg       ctx->Extensions.ARB_uniform_buffer_object)
683848b8605Smrg      || ctx->API == API_OPENGL_CORE
684848b8605Smrg      || _mesa_is_gles3(ctx);
685848b8605Smrg
686848b8605Smrg   if (!shProg) {
687848b8605Smrg      return;
688848b8605Smrg   }
689848b8605Smrg
690848b8605Smrg   switch (pname) {
691848b8605Smrg   case GL_DELETE_STATUS:
692848b8605Smrg      *params = shProg->DeletePending;
693848b8605Smrg      return;
694b8e80941Smrg   case GL_COMPLETION_STATUS_ARB:
695b8e80941Smrg      if (ctx->Driver.GetShaderProgramCompletionStatus)
696b8e80941Smrg         *params = ctx->Driver.GetShaderProgramCompletionStatus(ctx, shProg);
697b8e80941Smrg      else
698b8e80941Smrg         *params = GL_TRUE;
699b8e80941Smrg      return;
700848b8605Smrg   case GL_LINK_STATUS:
701b8e80941Smrg      *params = shProg->data->LinkStatus ? GL_TRUE : GL_FALSE;
702848b8605Smrg      return;
703848b8605Smrg   case GL_VALIDATE_STATUS:
704b8e80941Smrg      *params = shProg->data->Validated;
705848b8605Smrg      return;
706848b8605Smrg   case GL_INFO_LOG_LENGTH:
707b8e80941Smrg      *params = (shProg->data->InfoLog && shProg->data->InfoLog[0] != '\0') ?
708b8e80941Smrg         strlen(shProg->data->InfoLog) + 1 : 0;
709848b8605Smrg      return;
710848b8605Smrg   case GL_ATTACHED_SHADERS:
711848b8605Smrg      *params = shProg->NumShaders;
712848b8605Smrg      return;
713848b8605Smrg   case GL_ACTIVE_ATTRIBUTES:
714848b8605Smrg      *params = _mesa_count_active_attribs(shProg);
715848b8605Smrg      return;
716848b8605Smrg   case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH:
717848b8605Smrg      *params = _mesa_longest_attribute_name_length(shProg);
718848b8605Smrg      return;
719b8e80941Smrg   case GL_ACTIVE_UNIFORMS: {
720b8e80941Smrg      unsigned i;
721b8e80941Smrg      const unsigned num_uniforms =
722b8e80941Smrg         shProg->data->NumUniformStorage - shProg->data->NumHiddenUniforms;
723b8e80941Smrg      for (*params = 0, i = 0; i < num_uniforms; i++) {
724b8e80941Smrg         if (!shProg->data->UniformStorage[i].is_shader_storage)
725b8e80941Smrg            (*params)++;
726b8e80941Smrg      }
727848b8605Smrg      return;
728b8e80941Smrg   }
729848b8605Smrg   case GL_ACTIVE_UNIFORM_MAX_LENGTH: {
730848b8605Smrg      unsigned i;
731848b8605Smrg      GLint max_len = 0;
732b8e80941Smrg      const unsigned num_uniforms =
733b8e80941Smrg         shProg->data->NumUniformStorage - shProg->data->NumHiddenUniforms;
734b8e80941Smrg
735b8e80941Smrg      for (i = 0; i < num_uniforms; i++) {
736b8e80941Smrg         if (shProg->data->UniformStorage[i].is_shader_storage)
737b8e80941Smrg            continue;
738848b8605Smrg
739848b8605Smrg	 /* Add one for the terminating NUL character for a non-array, and
740848b8605Smrg	  * 4 for the "[0]" and the NUL for an array.
741848b8605Smrg	  */
742b8e80941Smrg         const GLint len = strlen(shProg->data->UniformStorage[i].name) + 1 +
743b8e80941Smrg             ((shProg->data->UniformStorage[i].array_elements != 0) ? 3 : 0);
744848b8605Smrg
745848b8605Smrg	 if (len > max_len)
746848b8605Smrg	    max_len = len;
747848b8605Smrg      }
748848b8605Smrg
749848b8605Smrg      *params = max_len;
750848b8605Smrg      return;
751848b8605Smrg   }
752848b8605Smrg   case GL_TRANSFORM_FEEDBACK_VARYINGS:
753848b8605Smrg      if (!has_xfb)
754848b8605Smrg         break;
755848b8605Smrg      *params = shProg->TransformFeedback.NumVarying;
756848b8605Smrg      return;
757848b8605Smrg   case GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH: {
758848b8605Smrg      unsigned i;
759848b8605Smrg      GLint max_len = 0;
760848b8605Smrg      if (!has_xfb)
761848b8605Smrg         break;
762848b8605Smrg
763848b8605Smrg      for (i = 0; i < shProg->TransformFeedback.NumVarying; i++) {
764848b8605Smrg         /* Add one for the terminating NUL character.
765848b8605Smrg          */
766b8e80941Smrg         const GLint len =
767b8e80941Smrg            strlen(shProg->TransformFeedback.VaryingNames[i]) + 1;
768848b8605Smrg
769848b8605Smrg         if (len > max_len)
770848b8605Smrg            max_len = len;
771848b8605Smrg      }
772848b8605Smrg
773848b8605Smrg      *params = max_len;
774848b8605Smrg      return;
775848b8605Smrg   }
776848b8605Smrg   case GL_TRANSFORM_FEEDBACK_BUFFER_MODE:
777848b8605Smrg      if (!has_xfb)
778848b8605Smrg         break;
779848b8605Smrg      *params = shProg->TransformFeedback.BufferMode;
780848b8605Smrg      return;
781848b8605Smrg   case GL_GEOMETRY_VERTICES_OUT:
782b8e80941Smrg      if (!has_gs)
783848b8605Smrg         break;
784b8e80941Smrg      if (check_gs_query(ctx, shProg)) {
785b8e80941Smrg         *params = shProg->_LinkedShaders[MESA_SHADER_GEOMETRY]->
786b8e80941Smrg            Program->info.gs.vertices_out;
787b8e80941Smrg      }
788848b8605Smrg      return;
789848b8605Smrg   case GL_GEOMETRY_SHADER_INVOCATIONS:
790b8e80941Smrg      if (!has_gs || !ctx->Extensions.ARB_gpu_shader5)
791848b8605Smrg         break;
792b8e80941Smrg      if (check_gs_query(ctx, shProg)) {
793b8e80941Smrg         *params = shProg->_LinkedShaders[MESA_SHADER_GEOMETRY]->
794b8e80941Smrg            Program->info.gs.invocations;
795b8e80941Smrg      }
796848b8605Smrg      return;
797848b8605Smrg   case GL_GEOMETRY_INPUT_TYPE:
798b8e80941Smrg      if (!has_gs)
799848b8605Smrg         break;
800b8e80941Smrg      if (check_gs_query(ctx, shProg)) {
801b8e80941Smrg         *params = shProg->_LinkedShaders[MESA_SHADER_GEOMETRY]->
802b8e80941Smrg            Program->info.gs.input_primitive;
803b8e80941Smrg      }
804848b8605Smrg      return;
805848b8605Smrg   case GL_GEOMETRY_OUTPUT_TYPE:
806b8e80941Smrg      if (!has_gs)
807848b8605Smrg         break;
808b8e80941Smrg      if (check_gs_query(ctx, shProg)) {
809b8e80941Smrg         *params = shProg->_LinkedShaders[MESA_SHADER_GEOMETRY]->
810b8e80941Smrg            Program->info.gs.output_primitive;
811b8e80941Smrg      }
812848b8605Smrg      return;
813848b8605Smrg   case GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH: {
814848b8605Smrg      unsigned i;
815848b8605Smrg      GLint max_len = 0;
816848b8605Smrg
817848b8605Smrg      if (!has_ubo)
818848b8605Smrg         break;
819848b8605Smrg
820b8e80941Smrg      for (i = 0; i < shProg->data->NumUniformBlocks; i++) {
821848b8605Smrg	 /* Add one for the terminating NUL character.
822848b8605Smrg	  */
823b8e80941Smrg         const GLint len = strlen(shProg->data->UniformBlocks[i].Name) + 1;
824848b8605Smrg
825848b8605Smrg	 if (len > max_len)
826848b8605Smrg	    max_len = len;
827848b8605Smrg      }
828848b8605Smrg
829848b8605Smrg      *params = max_len;
830848b8605Smrg      return;
831848b8605Smrg   }
832848b8605Smrg   case GL_ACTIVE_UNIFORM_BLOCKS:
833848b8605Smrg      if (!has_ubo)
834848b8605Smrg         break;
835848b8605Smrg
836b8e80941Smrg      *params = shProg->data->NumUniformBlocks;
837848b8605Smrg      return;
838848b8605Smrg   case GL_PROGRAM_BINARY_RETRIEVABLE_HINT:
839848b8605Smrg      /* This enum isn't part of the OES extension for OpenGL ES 2.0.  It is
840848b8605Smrg       * only available with desktop OpenGL 3.0+ with the
841848b8605Smrg       * GL_ARB_get_program_binary extension or OpenGL ES 3.0.
842848b8605Smrg       *
843848b8605Smrg       * On desktop, we ignore the 3.0+ requirement because it is silly.
844848b8605Smrg       */
845848b8605Smrg      if (!_mesa_is_desktop_gl(ctx) && !_mesa_is_gles3(ctx))
846848b8605Smrg         break;
847848b8605Smrg
848848b8605Smrg      *params = shProg->BinaryRetreivableHint;
849848b8605Smrg      return;
850848b8605Smrg   case GL_PROGRAM_BINARY_LENGTH:
851b8e80941Smrg      if (ctx->Const.NumProgramBinaryFormats == 0 || !shProg->data->LinkStatus) {
852b8e80941Smrg         *params = 0;
853b8e80941Smrg      } else {
854b8e80941Smrg         _mesa_get_program_binary_length(ctx, shProg, params);
855b8e80941Smrg      }
856848b8605Smrg      return;
857848b8605Smrg   case GL_ACTIVE_ATOMIC_COUNTER_BUFFERS:
858848b8605Smrg      if (!ctx->Extensions.ARB_shader_atomic_counters)
859848b8605Smrg         break;
860848b8605Smrg
861b8e80941Smrg      *params = shProg->data->NumAtomicBuffers;
862848b8605Smrg      return;
863848b8605Smrg   case GL_COMPUTE_WORK_GROUP_SIZE: {
864848b8605Smrg      int i;
865b8e80941Smrg      if (!_mesa_has_compute_shaders(ctx))
866848b8605Smrg         break;
867b8e80941Smrg      if (!shProg->data->LinkStatus) {
868848b8605Smrg         _mesa_error(ctx, GL_INVALID_OPERATION, "glGetProgramiv(program not "
869848b8605Smrg                     "linked)");
870848b8605Smrg         return;
871848b8605Smrg      }
872848b8605Smrg      if (shProg->_LinkedShaders[MESA_SHADER_COMPUTE] == NULL) {
873848b8605Smrg         _mesa_error(ctx, GL_INVALID_OPERATION, "glGetProgramiv(no compute "
874848b8605Smrg                     "shaders)");
875848b8605Smrg         return;
876848b8605Smrg      }
877848b8605Smrg      for (i = 0; i < 3; i++)
878b8e80941Smrg         params[i] = shProg->_LinkedShaders[MESA_SHADER_COMPUTE]->
879b8e80941Smrg            Program->info.cs.local_size[i];
880848b8605Smrg      return;
881848b8605Smrg   }
882848b8605Smrg   case GL_PROGRAM_SEPARABLE:
883b8e80941Smrg      /* If the program has not been linked, return initial value 0. */
884b8e80941Smrg      *params = (shProg->data->LinkStatus == LINKING_FAILURE) ? 0 : shProg->SeparateShader;
885b8e80941Smrg      return;
886b8e80941Smrg
887b8e80941Smrg   /* ARB_tessellation_shader */
888b8e80941Smrg   case GL_TESS_CONTROL_OUTPUT_VERTICES:
889b8e80941Smrg      if (!has_tess)
890b8e80941Smrg         break;
891b8e80941Smrg      if (check_tcs_query(ctx, shProg)) {
892b8e80941Smrg         *params = shProg->_LinkedShaders[MESA_SHADER_TESS_CTRL]->
893b8e80941Smrg            Program->info.tess.tcs_vertices_out;
894b8e80941Smrg      }
895b8e80941Smrg      return;
896b8e80941Smrg   case GL_TESS_GEN_MODE:
897b8e80941Smrg      if (!has_tess)
898b8e80941Smrg         break;
899b8e80941Smrg      if (check_tes_query(ctx, shProg)) {
900b8e80941Smrg         *params = shProg->_LinkedShaders[MESA_SHADER_TESS_EVAL]->
901b8e80941Smrg            Program->info.tess.primitive_mode;
902b8e80941Smrg      }
903b8e80941Smrg      return;
904b8e80941Smrg   case GL_TESS_GEN_SPACING:
905b8e80941Smrg      if (!has_tess)
906b8e80941Smrg         break;
907b8e80941Smrg      if (check_tes_query(ctx, shProg)) {
908b8e80941Smrg         const struct gl_linked_shader *tes =
909b8e80941Smrg            shProg->_LinkedShaders[MESA_SHADER_TESS_EVAL];
910b8e80941Smrg         switch (tes->Program->info.tess.spacing) {
911b8e80941Smrg         case TESS_SPACING_EQUAL:
912b8e80941Smrg            *params = GL_EQUAL;
913b8e80941Smrg            break;
914b8e80941Smrg         case TESS_SPACING_FRACTIONAL_ODD:
915b8e80941Smrg            *params = GL_FRACTIONAL_ODD;
916b8e80941Smrg            break;
917b8e80941Smrg         case TESS_SPACING_FRACTIONAL_EVEN:
918b8e80941Smrg            *params = GL_FRACTIONAL_EVEN;
919b8e80941Smrg            break;
920b8e80941Smrg         case TESS_SPACING_UNSPECIFIED:
921b8e80941Smrg            *params = 0;
922b8e80941Smrg            break;
923b8e80941Smrg         }
924b8e80941Smrg      }
925b8e80941Smrg      return;
926b8e80941Smrg   case GL_TESS_GEN_VERTEX_ORDER:
927b8e80941Smrg      if (!has_tess)
928b8e80941Smrg         break;
929b8e80941Smrg      if (check_tes_query(ctx, shProg)) {
930b8e80941Smrg         *params = shProg->_LinkedShaders[MESA_SHADER_TESS_EVAL]->
931b8e80941Smrg            Program->info.tess.ccw ? GL_CCW : GL_CW;
932b8e80941Smrg         }
933b8e80941Smrg      return;
934b8e80941Smrg   case GL_TESS_GEN_POINT_MODE:
935b8e80941Smrg      if (!has_tess)
936b8e80941Smrg         break;
937b8e80941Smrg      if (check_tes_query(ctx, shProg)) {
938b8e80941Smrg         *params = shProg->_LinkedShaders[MESA_SHADER_TESS_EVAL]->
939b8e80941Smrg            Program->info.tess.point_mode ? GL_TRUE : GL_FALSE;
940b8e80941Smrg      }
941848b8605Smrg      return;
942848b8605Smrg   default:
943848b8605Smrg      break;
944848b8605Smrg   }
945848b8605Smrg
946848b8605Smrg   _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramiv(pname=%s)",
947b8e80941Smrg               _mesa_enum_to_string(pname));
948848b8605Smrg}
949848b8605Smrg
950848b8605Smrg
951848b8605Smrg/**
952848b8605Smrg * glGetShaderiv() - get GLSL shader state
953848b8605Smrg */
954848b8605Smrgstatic void
955848b8605Smrgget_shaderiv(struct gl_context *ctx, GLuint name, GLenum pname, GLint *params)
956848b8605Smrg{
957848b8605Smrg   struct gl_shader *shader =
958848b8605Smrg      _mesa_lookup_shader_err(ctx, name, "glGetShaderiv");
959848b8605Smrg
960848b8605Smrg   if (!shader) {
961848b8605Smrg      return;
962848b8605Smrg   }
963848b8605Smrg
964848b8605Smrg   switch (pname) {
965848b8605Smrg   case GL_SHADER_TYPE:
966848b8605Smrg      *params = shader->Type;
967848b8605Smrg      break;
968848b8605Smrg   case GL_DELETE_STATUS:
969848b8605Smrg      *params = shader->DeletePending;
970848b8605Smrg      break;
971b8e80941Smrg   case GL_COMPLETION_STATUS_ARB:
972b8e80941Smrg      /* _mesa_glsl_compile_shader is not offloaded to other threads. */
973b8e80941Smrg      *params = GL_TRUE;
974b8e80941Smrg      return;
975848b8605Smrg   case GL_COMPILE_STATUS:
976b8e80941Smrg      *params = shader->CompileStatus ? GL_TRUE : GL_FALSE;
977848b8605Smrg      break;
978848b8605Smrg   case GL_INFO_LOG_LENGTH:
979b8e80941Smrg      *params = (shader->InfoLog && shader->InfoLog[0] != '\0') ?
980b8e80941Smrg         strlen(shader->InfoLog) + 1 : 0;
981848b8605Smrg      break;
982848b8605Smrg   case GL_SHADER_SOURCE_LENGTH:
983848b8605Smrg      *params = shader->Source ? strlen((char *) shader->Source) + 1 : 0;
984848b8605Smrg      break;
985b8e80941Smrg   case GL_SPIR_V_BINARY_ARB:
986b8e80941Smrg      *params = (shader->spirv_data != NULL);
987b8e80941Smrg      break;
988848b8605Smrg   default:
989848b8605Smrg      _mesa_error(ctx, GL_INVALID_ENUM, "glGetShaderiv(pname)");
990848b8605Smrg      return;
991848b8605Smrg   }
992848b8605Smrg}
993848b8605Smrg
994848b8605Smrg
995848b8605Smrgstatic void
996848b8605Smrgget_program_info_log(struct gl_context *ctx, GLuint program, GLsizei bufSize,
997848b8605Smrg                     GLsizei *length, GLchar *infoLog)
998848b8605Smrg{
999b8e80941Smrg   struct gl_shader_program *shProg;
1000b8e80941Smrg
1001b8e80941Smrg   /* Section 2.5 GL Errors (page 18) of the OpenGL ES 3.0.4 spec and
1002b8e80941Smrg    * section 2.3.1 (Errors) of the OpenGL 4.5 spec say:
1003b8e80941Smrg    *
1004b8e80941Smrg    *     "If a negative number is provided where an argument of type sizei or
1005b8e80941Smrg    *     sizeiptr is specified, an INVALID_VALUE error is generated."
1006b8e80941Smrg    */
1007b8e80941Smrg   if (bufSize < 0) {
1008b8e80941Smrg      _mesa_error(ctx, GL_INVALID_VALUE, "glGetProgramInfoLog(bufSize < 0)");
1009b8e80941Smrg      return;
1010b8e80941Smrg   }
1011b8e80941Smrg
1012b8e80941Smrg   shProg = _mesa_lookup_shader_program_err(ctx, program,
1013b8e80941Smrg                                            "glGetProgramInfoLog(program)");
1014848b8605Smrg   if (!shProg) {
1015848b8605Smrg      return;
1016848b8605Smrg   }
1017b8e80941Smrg
1018b8e80941Smrg   _mesa_copy_string(infoLog, bufSize, length, shProg->data->InfoLog);
1019848b8605Smrg}
1020848b8605Smrg
1021848b8605Smrg
1022848b8605Smrgstatic void
1023848b8605Smrgget_shader_info_log(struct gl_context *ctx, GLuint shader, GLsizei bufSize,
1024848b8605Smrg                    GLsizei *length, GLchar *infoLog)
1025848b8605Smrg{
1026b8e80941Smrg   struct gl_shader *sh;
1027b8e80941Smrg
1028b8e80941Smrg   /* Section 2.5 GL Errors (page 18) of the OpenGL ES 3.0.4 spec and
1029b8e80941Smrg    * section 2.3.1 (Errors) of the OpenGL 4.5 spec say:
1030b8e80941Smrg    *
1031b8e80941Smrg    *     "If a negative number is provided where an argument of type sizei or
1032b8e80941Smrg    *     sizeiptr is specified, an INVALID_VALUE error is generated."
1033b8e80941Smrg    */
1034b8e80941Smrg   if (bufSize < 0) {
1035b8e80941Smrg      _mesa_error(ctx, GL_INVALID_VALUE, "glGetShaderInfoLog(bufSize < 0)");
1036b8e80941Smrg      return;
1037b8e80941Smrg   }
1038b8e80941Smrg
1039b8e80941Smrg   sh = _mesa_lookup_shader_err(ctx, shader, "glGetShaderInfoLog(shader)");
1040848b8605Smrg   if (!sh) {
1041848b8605Smrg      return;
1042848b8605Smrg   }
1043b8e80941Smrg
1044848b8605Smrg   _mesa_copy_string(infoLog, bufSize, length, sh->InfoLog);
1045848b8605Smrg}
1046848b8605Smrg
1047848b8605Smrg
1048848b8605Smrg/**
1049848b8605Smrg * Return shader source code.
1050848b8605Smrg */
1051848b8605Smrgstatic void
1052848b8605Smrgget_shader_source(struct gl_context *ctx, GLuint shader, GLsizei maxLength,
1053848b8605Smrg                  GLsizei *length, GLchar *sourceOut)
1054848b8605Smrg{
1055848b8605Smrg   struct gl_shader *sh;
1056b8e80941Smrg
1057b8e80941Smrg   if (maxLength < 0) {
1058b8e80941Smrg      _mesa_error(ctx, GL_INVALID_VALUE, "glGetShaderSource(bufSize < 0)");
1059b8e80941Smrg      return;
1060b8e80941Smrg   }
1061b8e80941Smrg
1062848b8605Smrg   sh = _mesa_lookup_shader_err(ctx, shader, "glGetShaderSource");
1063848b8605Smrg   if (!sh) {
1064848b8605Smrg      return;
1065848b8605Smrg   }
1066848b8605Smrg   _mesa_copy_string(sourceOut, maxLength, length, sh->Source);
1067848b8605Smrg}
1068848b8605Smrg
1069848b8605Smrg
1070848b8605Smrg/**
1071848b8605Smrg * Set/replace shader source code.  A helper function used by
1072848b8605Smrg * glShaderSource[ARB].
1073848b8605Smrg */
1074848b8605Smrgstatic void
1075b8e80941Smrgset_shader_source(struct gl_shader *sh, const GLchar *source)
1076848b8605Smrg{
1077b8e80941Smrg   assert(sh);
1078848b8605Smrg
1079b8e80941Smrg   /* The GL_ARB_gl_spirv spec adds the following to the end of the description
1080b8e80941Smrg    * of ShaderSource:
1081b8e80941Smrg    *
1082b8e80941Smrg    *   "If <shader> was previously associated with a SPIR-V module (via the
1083b8e80941Smrg    *    ShaderBinary command), that association is broken. Upon successful
1084b8e80941Smrg    *    completion of this command the SPIR_V_BINARY_ARB state of <shader>
1085b8e80941Smrg    *    is set to FALSE."
1086b8e80941Smrg    */
1087b8e80941Smrg   _mesa_shader_spirv_data_reference(&sh->spirv_data, NULL);
1088b8e80941Smrg
1089b8e80941Smrg   if (sh->CompileStatus == COMPILE_SKIPPED && !sh->FallbackSource) {
1090b8e80941Smrg      /* If shader was previously compiled back-up the source in case of cache
1091b8e80941Smrg       * fallback.
1092b8e80941Smrg       */
1093b8e80941Smrg      sh->FallbackSource = sh->Source;
1094b8e80941Smrg      sh->Source = source;
1095b8e80941Smrg   } else {
1096b8e80941Smrg      /* free old shader source string and install new one */
1097b8e80941Smrg      free((void *)sh->Source);
1098b8e80941Smrg      sh->Source = source;
1099b8e80941Smrg   }
1100848b8605Smrg
1101848b8605Smrg#ifdef DEBUG
1102b8e80941Smrg   sh->SourceChecksum = util_hash_crc32(sh->Source, strlen(sh->Source));
1103848b8605Smrg#endif
1104848b8605Smrg}
1105848b8605Smrg
1106848b8605Smrg
1107848b8605Smrg/**
1108848b8605Smrg * Compile a shader.
1109848b8605Smrg */
1110b8e80941Smrgvoid
1111b8e80941Smrg_mesa_compile_shader(struct gl_context *ctx, struct gl_shader *sh)
1112848b8605Smrg{
1113848b8605Smrg   if (!sh)
1114848b8605Smrg      return;
1115848b8605Smrg
1116b8e80941Smrg   /* The GL_ARB_gl_spirv spec says:
1117b8e80941Smrg    *
1118b8e80941Smrg    *    "Add a new error for the CompileShader command:
1119b8e80941Smrg    *
1120b8e80941Smrg    *      An INVALID_OPERATION error is generated if the SPIR_V_BINARY_ARB
1121b8e80941Smrg    *      state of <shader> is TRUE."
1122b8e80941Smrg    */
1123b8e80941Smrg   if (sh->spirv_data) {
1124b8e80941Smrg      _mesa_error(ctx, GL_INVALID_OPERATION, "glCompileShader(SPIR-V)");
1125b8e80941Smrg      return;
1126b8e80941Smrg   }
1127848b8605Smrg
1128848b8605Smrg   if (!sh->Source) {
1129848b8605Smrg      /* If the user called glCompileShader without first calling
1130848b8605Smrg       * glShaderSource, we should fail to compile, but not raise a GL_ERROR.
1131848b8605Smrg       */
1132b8e80941Smrg      sh->CompileStatus = COMPILE_FAILURE;
1133848b8605Smrg   } else {
1134848b8605Smrg      if (ctx->_Shader->Flags & GLSL_DUMP) {
1135b8e80941Smrg         _mesa_log("GLSL source for %s shader %d:\n",
1136848b8605Smrg                 _mesa_shader_stage_to_string(sh->Stage), sh->Name);
1137b8e80941Smrg         _mesa_log("%s\n", sh->Source);
1138848b8605Smrg      }
1139848b8605Smrg
1140848b8605Smrg      /* this call will set the shader->CompileStatus field to indicate if
1141848b8605Smrg       * compilation was successful.
1142848b8605Smrg       */
1143b8e80941Smrg      _mesa_glsl_compile_shader(ctx, sh, false, false, false);
1144848b8605Smrg
1145848b8605Smrg      if (ctx->_Shader->Flags & GLSL_LOG) {
1146848b8605Smrg         _mesa_write_shader_to_file(sh);
1147848b8605Smrg      }
1148848b8605Smrg
1149848b8605Smrg      if (ctx->_Shader->Flags & GLSL_DUMP) {
1150848b8605Smrg         if (sh->CompileStatus) {
1151b8e80941Smrg            if (sh->ir) {
1152b8e80941Smrg               _mesa_log("GLSL IR for shader %d:\n", sh->Name);
1153b8e80941Smrg               _mesa_print_ir(_mesa_get_log_file(), sh->ir, NULL);
1154b8e80941Smrg            } else {
1155b8e80941Smrg               _mesa_log("No GLSL IR for shader %d (shader may be from "
1156b8e80941Smrg                         "cache)\n", sh->Name);
1157b8e80941Smrg            }
1158b8e80941Smrg            _mesa_log("\n\n");
1159848b8605Smrg         } else {
1160b8e80941Smrg            _mesa_log("GLSL shader %d failed to compile.\n", sh->Name);
1161848b8605Smrg         }
1162848b8605Smrg         if (sh->InfoLog && sh->InfoLog[0] != 0) {
1163b8e80941Smrg            _mesa_log("GLSL shader %d info log:\n", sh->Name);
1164b8e80941Smrg            _mesa_log("%s\n", sh->InfoLog);
1165848b8605Smrg         }
1166848b8605Smrg      }
1167848b8605Smrg   }
1168848b8605Smrg
1169848b8605Smrg   if (!sh->CompileStatus) {
1170848b8605Smrg      if (ctx->_Shader->Flags & GLSL_DUMP_ON_ERROR) {
1171b8e80941Smrg         _mesa_log("GLSL source for %s shader %d:\n",
1172848b8605Smrg                 _mesa_shader_stage_to_string(sh->Stage), sh->Name);
1173b8e80941Smrg         _mesa_log("%s\n", sh->Source);
1174b8e80941Smrg         _mesa_log("Info Log:\n%s\n", sh->InfoLog);
1175848b8605Smrg      }
1176848b8605Smrg
1177848b8605Smrg      if (ctx->_Shader->Flags & GLSL_REPORT_ERRORS) {
1178848b8605Smrg         _mesa_debug(ctx, "Error compiling shader %u:\n%s\n",
1179848b8605Smrg                     sh->Name, sh->InfoLog);
1180848b8605Smrg      }
1181848b8605Smrg   }
1182848b8605Smrg}
1183848b8605Smrg
1184848b8605Smrg
1185848b8605Smrg/**
1186848b8605Smrg * Link a program's shaders.
1187848b8605Smrg */
1188b8e80941Smrgstatic ALWAYS_INLINE void
1189b8e80941Smrglink_program(struct gl_context *ctx, struct gl_shader_program *shProg,
1190b8e80941Smrg             bool no_error)
1191848b8605Smrg{
1192848b8605Smrg   if (!shProg)
1193848b8605Smrg      return;
1194848b8605Smrg
1195b8e80941Smrg   if (!no_error) {
1196b8e80941Smrg      /* From the ARB_transform_feedback2 specification:
1197b8e80941Smrg       * "The error INVALID_OPERATION is generated by LinkProgram if <program>
1198b8e80941Smrg       * is the name of a program being used by one or more transform feedback
1199b8e80941Smrg       * objects, even if the objects are not currently bound or are paused."
1200b8e80941Smrg       */
1201b8e80941Smrg      if (_mesa_transform_feedback_is_using_program(ctx, shProg)) {
1202b8e80941Smrg         _mesa_error(ctx, GL_INVALID_OPERATION,
1203b8e80941Smrg                     "glLinkProgram(transform feedback is using the program)");
1204b8e80941Smrg         return;
1205b8e80941Smrg      }
1206848b8605Smrg   }
1207848b8605Smrg
1208b8e80941Smrg   unsigned programs_in_use = 0;
1209b8e80941Smrg   if (ctx->_Shader)
1210b8e80941Smrg      for (unsigned stage = 0; stage < MESA_SHADER_STAGES; stage++) {
1211b8e80941Smrg         if (ctx->_Shader->CurrentProgram[stage] &&
1212b8e80941Smrg             ctx->_Shader->CurrentProgram[stage]->Id == shProg->Name) {
1213b8e80941Smrg            programs_in_use |= 1 << stage;
1214b8e80941Smrg         }
1215b8e80941Smrg   }
1216848b8605Smrg
1217b8e80941Smrg   FLUSH_VERTICES(ctx, 0);
1218848b8605Smrg   _mesa_glsl_link_shader(ctx, shProg);
1219848b8605Smrg
1220b8e80941Smrg   /* From section 7.3 (Program Objects) of the OpenGL 4.5 spec:
1221b8e80941Smrg    *
1222b8e80941Smrg    *    "If LinkProgram or ProgramBinary successfully re-links a program
1223b8e80941Smrg    *     object that is active for any shader stage, then the newly generated
1224b8e80941Smrg    *     executable code will be installed as part of the current rendering
1225b8e80941Smrg    *     state for all shader stages where the program is active.
1226b8e80941Smrg    *     Additionally, the newly generated executable code is made part of
1227b8e80941Smrg    *     the state of any program pipeline for all stages where the program
1228b8e80941Smrg    *     is attached."
1229b8e80941Smrg    */
1230b8e80941Smrg   if (shProg->data->LinkStatus && programs_in_use) {
1231b8e80941Smrg      while (programs_in_use) {
1232b8e80941Smrg         const int stage = u_bit_scan(&programs_in_use);
1233b8e80941Smrg
1234b8e80941Smrg         struct gl_program *prog = NULL;
1235b8e80941Smrg         if (shProg->_LinkedShaders[stage])
1236b8e80941Smrg            prog = shProg->_LinkedShaders[stage]->Program;
1237b8e80941Smrg
1238b8e80941Smrg         _mesa_use_program(ctx, stage, shProg, prog, ctx->_Shader);
1239b8e80941Smrg      }
1240b8e80941Smrg   }
1241b8e80941Smrg
1242b8e80941Smrg   /* Capture .shader_test files. */
1243b8e80941Smrg   const char *capture_path = _mesa_get_shader_capture_path();
1244b8e80941Smrg   if (shProg->Name != 0 && shProg->Name != ~0 && capture_path != NULL) {
1245b8e80941Smrg      /* Find an unused filename. */
1246b8e80941Smrg      char *filename = NULL;
1247b8e80941Smrg      for (unsigned i = 0;; i++) {
1248b8e80941Smrg         if (i) {
1249b8e80941Smrg            filename = ralloc_asprintf(NULL, "%s/%u-%u.shader_test",
1250b8e80941Smrg                                       capture_path, shProg->Name, i);
1251b8e80941Smrg         } else {
1252b8e80941Smrg            filename = ralloc_asprintf(NULL, "%s/%u.shader_test",
1253b8e80941Smrg                                       capture_path, shProg->Name);
1254b8e80941Smrg         }
1255b8e80941Smrg         FILE *file = fopen(filename, "r");
1256b8e80941Smrg         if (!file)
1257b8e80941Smrg            break;
1258b8e80941Smrg         fclose(file);
1259b8e80941Smrg         ralloc_free(filename);
1260b8e80941Smrg      }
1261b8e80941Smrg
1262b8e80941Smrg      FILE *file = fopen(filename, "w");
1263b8e80941Smrg      if (file) {
1264b8e80941Smrg         fprintf(file, "[require]\nGLSL%s >= %u.%02u\n",
1265b8e80941Smrg                 shProg->IsES ? " ES" : "",
1266b8e80941Smrg                 shProg->data->Version / 100, shProg->data->Version % 100);
1267b8e80941Smrg         if (shProg->SeparateShader)
1268b8e80941Smrg            fprintf(file, "GL_ARB_separate_shader_objects\nSSO ENABLED\n");
1269b8e80941Smrg         fprintf(file, "\n");
1270b8e80941Smrg
1271b8e80941Smrg         for (unsigned i = 0; i < shProg->NumShaders; i++) {
1272b8e80941Smrg            fprintf(file, "[%s shader]\n%s\n",
1273b8e80941Smrg                    _mesa_shader_stage_to_string(shProg->Shaders[i]->Stage),
1274b8e80941Smrg                    shProg->Shaders[i]->Source);
1275b8e80941Smrg         }
1276b8e80941Smrg         fclose(file);
1277b8e80941Smrg      } else {
1278b8e80941Smrg         _mesa_warning(ctx, "Failed to open %s", filename);
1279b8e80941Smrg      }
1280b8e80941Smrg
1281b8e80941Smrg      ralloc_free(filename);
1282b8e80941Smrg   }
1283b8e80941Smrg
1284b8e80941Smrg   if (shProg->data->LinkStatus == LINKING_FAILURE &&
1285848b8605Smrg       (ctx->_Shader->Flags & GLSL_REPORT_ERRORS)) {
1286848b8605Smrg      _mesa_debug(ctx, "Error linking program %u:\n%s\n",
1287b8e80941Smrg                  shProg->Name, shProg->data->InfoLog);
1288848b8605Smrg   }
1289848b8605Smrg
1290b8e80941Smrg   _mesa_update_vertex_processing_mode(ctx);
1291b8e80941Smrg
1292848b8605Smrg   /* debug code */
1293848b8605Smrg   if (0) {
1294848b8605Smrg      GLuint i;
1295848b8605Smrg
1296848b8605Smrg      printf("Link %u shaders in program %u: %s\n",
1297848b8605Smrg                   shProg->NumShaders, shProg->Name,
1298b8e80941Smrg                   shProg->data->LinkStatus ? "Success" : "Failed");
1299848b8605Smrg
1300848b8605Smrg      for (i = 0; i < shProg->NumShaders; i++) {
1301b8e80941Smrg         printf(" shader %u, stage %u\n",
1302848b8605Smrg                      shProg->Shaders[i]->Name,
1303b8e80941Smrg                      shProg->Shaders[i]->Stage);
1304848b8605Smrg      }
1305848b8605Smrg   }
1306848b8605Smrg}
1307848b8605Smrg
1308848b8605Smrg
1309b8e80941Smrgstatic void
1310b8e80941Smrglink_program_error(struct gl_context *ctx, struct gl_shader_program *shProg)
1311b8e80941Smrg{
1312b8e80941Smrg   link_program(ctx, shProg, false);
1313b8e80941Smrg}
1314b8e80941Smrg
1315b8e80941Smrg
1316b8e80941Smrgstatic void
1317b8e80941Smrglink_program_no_error(struct gl_context *ctx, struct gl_shader_program *shProg)
1318b8e80941Smrg{
1319b8e80941Smrg   link_program(ctx, shProg, true);
1320b8e80941Smrg}
1321b8e80941Smrg
1322b8e80941Smrg
1323b8e80941Smrgvoid
1324b8e80941Smrg_mesa_link_program(struct gl_context *ctx, struct gl_shader_program *shProg)
1325b8e80941Smrg{
1326b8e80941Smrg   link_program_error(ctx, shProg);
1327b8e80941Smrg}
1328b8e80941Smrg
1329b8e80941Smrg
1330848b8605Smrg/**
1331848b8605Smrg * Print basic shader info (for debug).
1332848b8605Smrg */
1333848b8605Smrgstatic void
1334848b8605Smrgprint_shader_info(const struct gl_shader_program *shProg)
1335848b8605Smrg{
1336848b8605Smrg   GLuint i;
1337848b8605Smrg
1338848b8605Smrg   printf("Mesa: glUseProgram(%u)\n", shProg->Name);
1339848b8605Smrg   for (i = 0; i < shProg->NumShaders; i++) {
1340b8e80941Smrg#ifdef DEBUG
1341848b8605Smrg      printf("  %s shader %u, checksum %u\n",
1342848b8605Smrg             _mesa_shader_stage_to_string(shProg->Shaders[i]->Stage),
1343848b8605Smrg	     shProg->Shaders[i]->Name,
1344848b8605Smrg	     shProg->Shaders[i]->SourceChecksum);
1345b8e80941Smrg#else
1346b8e80941Smrg      printf("  %s shader %u\n",
1347b8e80941Smrg             _mesa_shader_stage_to_string(shProg->Shaders[i]->Stage),
1348b8e80941Smrg             shProg->Shaders[i]->Name);
1349b8e80941Smrg#endif
1350848b8605Smrg   }
1351848b8605Smrg   if (shProg->_LinkedShaders[MESA_SHADER_VERTEX])
1352848b8605Smrg      printf("  vert prog %u\n",
1353848b8605Smrg	     shProg->_LinkedShaders[MESA_SHADER_VERTEX]->Program->Id);
1354848b8605Smrg   if (shProg->_LinkedShaders[MESA_SHADER_FRAGMENT])
1355848b8605Smrg      printf("  frag prog %u\n",
1356848b8605Smrg	     shProg->_LinkedShaders[MESA_SHADER_FRAGMENT]->Program->Id);
1357848b8605Smrg   if (shProg->_LinkedShaders[MESA_SHADER_GEOMETRY])
1358848b8605Smrg      printf("  geom prog %u\n",
1359848b8605Smrg	     shProg->_LinkedShaders[MESA_SHADER_GEOMETRY]->Program->Id);
1360b8e80941Smrg   if (shProg->_LinkedShaders[MESA_SHADER_TESS_CTRL])
1361b8e80941Smrg      printf("  tesc prog %u\n",
1362b8e80941Smrg	     shProg->_LinkedShaders[MESA_SHADER_TESS_CTRL]->Program->Id);
1363b8e80941Smrg   if (shProg->_LinkedShaders[MESA_SHADER_TESS_EVAL])
1364b8e80941Smrg      printf("  tese prog %u\n",
1365b8e80941Smrg	     shProg->_LinkedShaders[MESA_SHADER_TESS_EVAL]->Program->Id);
1366848b8605Smrg}
1367848b8605Smrg
1368848b8605Smrg
1369848b8605Smrg/**
1370848b8605Smrg * Use the named shader program for subsequent glUniform calls
1371848b8605Smrg */
1372848b8605Smrgvoid
1373848b8605Smrg_mesa_active_program(struct gl_context *ctx, struct gl_shader_program *shProg,
1374848b8605Smrg		     const char *caller)
1375848b8605Smrg{
1376b8e80941Smrg   if ((shProg != NULL) && !shProg->data->LinkStatus) {
1377848b8605Smrg      _mesa_error(ctx, GL_INVALID_OPERATION,
1378848b8605Smrg		  "%s(program %u not linked)", caller, shProg->Name);
1379848b8605Smrg      return;
1380848b8605Smrg   }
1381848b8605Smrg
1382848b8605Smrg   if (ctx->Shader.ActiveProgram != shProg) {
1383848b8605Smrg      _mesa_reference_shader_program(ctx, &ctx->Shader.ActiveProgram, shProg);
1384848b8605Smrg   }
1385848b8605Smrg}
1386848b8605Smrg
1387b8e80941Smrg
1388848b8605Smrg/**
1389b8e80941Smrg * Use the named shader program for subsequent rendering.
1390848b8605Smrg */
1391b8e80941Smrgvoid
1392b8e80941Smrg_mesa_use_shader_program(struct gl_context *ctx,
1393b8e80941Smrg                         struct gl_shader_program *shProg)
1394848b8605Smrg{
1395b8e80941Smrg   for (int i = 0; i < MESA_SHADER_STAGES; i++) {
1396b8e80941Smrg      struct gl_program *new_prog = NULL;
1397b8e80941Smrg      if (shProg && shProg->_LinkedShaders[i])
1398b8e80941Smrg         new_prog = shProg->_LinkedShaders[i]->Program;
1399b8e80941Smrg      _mesa_use_program(ctx, i, shProg, new_prog, &ctx->Shader);
1400b8e80941Smrg   }
1401b8e80941Smrg   _mesa_active_program(ctx, shProg, "glUseProgram");
1402b8e80941Smrg}
1403848b8605Smrg
1404848b8605Smrg
1405848b8605Smrg/**
1406848b8605Smrg * Do validation of the given shader program.
1407848b8605Smrg * \param errMsg  returns error message if validation fails.
1408848b8605Smrg * \return GL_TRUE if valid, GL_FALSE if invalid (and set errMsg)
1409848b8605Smrg */
1410848b8605Smrgstatic GLboolean
1411848b8605Smrgvalidate_shader_program(const struct gl_shader_program *shProg,
1412848b8605Smrg                        char *errMsg)
1413848b8605Smrg{
1414b8e80941Smrg   if (!shProg->data->LinkStatus) {
1415848b8605Smrg      return GL_FALSE;
1416848b8605Smrg   }
1417848b8605Smrg
1418848b8605Smrg   /* From the GL spec, a program is invalid if any of these are true:
1419848b8605Smrg
1420848b8605Smrg     any two active samplers in the current program object are of
1421848b8605Smrg     different types, but refer to the same texture image unit,
1422848b8605Smrg
1423848b8605Smrg     any active sampler in the current program object refers to a texture
1424848b8605Smrg     image unit where fixed-function fragment processing accesses a
1425b8e80941Smrg     texture target that does not match the sampler type, or
1426848b8605Smrg
1427848b8605Smrg     the sum of the number of active samplers in the program and the
1428848b8605Smrg     number of texture image units enabled for fixed-function fragment
1429848b8605Smrg     processing exceeds the combined limit on the total number of texture
1430848b8605Smrg     image units allowed.
1431848b8605Smrg   */
1432848b8605Smrg
1433848b8605Smrg   /*
1434848b8605Smrg    * Check: any two active samplers in the current program object are of
1435848b8605Smrg    * different types, but refer to the same texture image unit,
1436848b8605Smrg    */
1437848b8605Smrg   if (!_mesa_sampler_uniforms_are_valid(shProg, errMsg, 100))
1438848b8605Smrg      return GL_FALSE;
1439848b8605Smrg
1440848b8605Smrg   return GL_TRUE;
1441848b8605Smrg}
1442848b8605Smrg
1443848b8605Smrg
1444848b8605Smrg/**
1445848b8605Smrg * Called via glValidateProgram()
1446848b8605Smrg */
1447848b8605Smrgstatic void
1448848b8605Smrgvalidate_program(struct gl_context *ctx, GLuint program)
1449848b8605Smrg{
1450848b8605Smrg   struct gl_shader_program *shProg;
1451848b8605Smrg   char errMsg[100] = "";
1452848b8605Smrg
1453848b8605Smrg   shProg = _mesa_lookup_shader_program_err(ctx, program, "glValidateProgram");
1454848b8605Smrg   if (!shProg) {
1455848b8605Smrg      return;
1456848b8605Smrg   }
1457848b8605Smrg
1458b8e80941Smrg   shProg->data->Validated = validate_shader_program(shProg, errMsg);
1459b8e80941Smrg   if (!shProg->data->Validated) {
1460848b8605Smrg      /* update info log */
1461b8e80941Smrg      if (shProg->data->InfoLog) {
1462b8e80941Smrg         ralloc_free(shProg->data->InfoLog);
1463848b8605Smrg      }
1464b8e80941Smrg      shProg->data->InfoLog = ralloc_strdup(shProg->data, errMsg);
1465848b8605Smrg   }
1466848b8605Smrg}
1467848b8605Smrg
1468848b8605Smrg
1469b8e80941Smrgvoid GLAPIENTRY
1470b8e80941Smrg_mesa_AttachObjectARB_no_error(GLhandleARB program, GLhandleARB shader)
1471b8e80941Smrg{
1472b8e80941Smrg   GET_CURRENT_CONTEXT(ctx);
1473b8e80941Smrg   attach_shader_no_error(ctx, program, shader);
1474b8e80941Smrg}
1475b8e80941Smrg
1476848b8605Smrg
1477848b8605Smrgvoid GLAPIENTRY
1478848b8605Smrg_mesa_AttachObjectARB(GLhandleARB program, GLhandleARB shader)
1479848b8605Smrg{
1480848b8605Smrg   GET_CURRENT_CONTEXT(ctx);
1481b8e80941Smrg   attach_shader_err(ctx, program, shader, "glAttachObjectARB");
1482b8e80941Smrg}
1483b8e80941Smrg
1484b8e80941Smrg
1485b8e80941Smrgvoid GLAPIENTRY
1486b8e80941Smrg_mesa_AttachShader_no_error(GLuint program, GLuint shader)
1487b8e80941Smrg{
1488b8e80941Smrg   GET_CURRENT_CONTEXT(ctx);
1489b8e80941Smrg   attach_shader_no_error(ctx, program, shader);
1490848b8605Smrg}
1491848b8605Smrg
1492848b8605Smrg
1493848b8605Smrgvoid GLAPIENTRY
1494848b8605Smrg_mesa_AttachShader(GLuint program, GLuint shader)
1495848b8605Smrg{
1496848b8605Smrg   GET_CURRENT_CONTEXT(ctx);
1497b8e80941Smrg   attach_shader_err(ctx, program, shader, "glAttachShader");
1498848b8605Smrg}
1499848b8605Smrg
1500848b8605Smrg
1501848b8605Smrgvoid GLAPIENTRY
1502b8e80941Smrg_mesa_CompileShader(GLuint shaderObj)
1503848b8605Smrg{
1504848b8605Smrg   GET_CURRENT_CONTEXT(ctx);
1505848b8605Smrg   if (MESA_VERBOSE & VERBOSE_API)
1506848b8605Smrg      _mesa_debug(ctx, "glCompileShader %u\n", shaderObj);
1507b8e80941Smrg   _mesa_compile_shader(ctx, _mesa_lookup_shader_err(ctx, shaderObj,
1508b8e80941Smrg                                                     "glCompileShader"));
1509b8e80941Smrg}
1510b8e80941Smrg
1511b8e80941Smrg
1512b8e80941SmrgGLuint GLAPIENTRY
1513b8e80941Smrg_mesa_CreateShader_no_error(GLenum type)
1514b8e80941Smrg{
1515b8e80941Smrg   GET_CURRENT_CONTEXT(ctx);
1516b8e80941Smrg   return create_shader(ctx, type);
1517848b8605Smrg}
1518848b8605Smrg
1519848b8605Smrg
1520848b8605SmrgGLuint GLAPIENTRY
1521848b8605Smrg_mesa_CreateShader(GLenum type)
1522848b8605Smrg{
1523848b8605Smrg   GET_CURRENT_CONTEXT(ctx);
1524b8e80941Smrg
1525848b8605Smrg   if (MESA_VERBOSE & VERBOSE_API)
1526b8e80941Smrg      _mesa_debug(ctx, "glCreateShader %s\n", _mesa_enum_to_string(type));
1527b8e80941Smrg
1528b8e80941Smrg   return create_shader_err(ctx, type, "glCreateShader");
1529b8e80941Smrg}
1530b8e80941Smrg
1531b8e80941Smrg
1532b8e80941SmrgGLhandleARB GLAPIENTRY
1533b8e80941Smrg_mesa_CreateShaderObjectARB_no_error(GLenum type)
1534b8e80941Smrg{
1535b8e80941Smrg   GET_CURRENT_CONTEXT(ctx);
1536848b8605Smrg   return create_shader(ctx, type);
1537848b8605Smrg}
1538848b8605Smrg
1539848b8605Smrg
1540848b8605SmrgGLhandleARB GLAPIENTRY
1541848b8605Smrg_mesa_CreateShaderObjectARB(GLenum type)
1542848b8605Smrg{
1543848b8605Smrg   GET_CURRENT_CONTEXT(ctx);
1544b8e80941Smrg   return create_shader_err(ctx, type, "glCreateShaderObjectARB");
1545848b8605Smrg}
1546848b8605Smrg
1547848b8605Smrg
1548848b8605SmrgGLuint GLAPIENTRY
1549848b8605Smrg_mesa_CreateProgram(void)
1550848b8605Smrg{
1551848b8605Smrg   GET_CURRENT_CONTEXT(ctx);
1552848b8605Smrg   if (MESA_VERBOSE & VERBOSE_API)
1553848b8605Smrg      _mesa_debug(ctx, "glCreateProgram\n");
1554848b8605Smrg   return create_shader_program(ctx);
1555848b8605Smrg}
1556848b8605Smrg
1557848b8605Smrg
1558848b8605SmrgGLhandleARB GLAPIENTRY
1559848b8605Smrg_mesa_CreateProgramObjectARB(void)
1560848b8605Smrg{
1561848b8605Smrg   GET_CURRENT_CONTEXT(ctx);
1562848b8605Smrg   return create_shader_program(ctx);
1563848b8605Smrg}
1564848b8605Smrg
1565848b8605Smrg
1566848b8605Smrgvoid GLAPIENTRY
1567848b8605Smrg_mesa_DeleteObjectARB(GLhandleARB obj)
1568848b8605Smrg{
1569848b8605Smrg   if (MESA_VERBOSE & VERBOSE_API) {
1570848b8605Smrg      GET_CURRENT_CONTEXT(ctx);
1571b8e80941Smrg      _mesa_debug(ctx, "glDeleteObjectARB(%lu)\n", (unsigned long)obj);
1572848b8605Smrg   }
1573848b8605Smrg
1574848b8605Smrg   if (obj) {
1575848b8605Smrg      GET_CURRENT_CONTEXT(ctx);
1576848b8605Smrg      FLUSH_VERTICES(ctx, 0);
1577848b8605Smrg      if (is_program(ctx, obj)) {
1578848b8605Smrg         delete_shader_program(ctx, obj);
1579848b8605Smrg      }
1580848b8605Smrg      else if (is_shader(ctx, obj)) {
1581848b8605Smrg         delete_shader(ctx, obj);
1582848b8605Smrg      }
1583848b8605Smrg      else {
1584848b8605Smrg         /* error? */
1585848b8605Smrg      }
1586848b8605Smrg   }
1587848b8605Smrg}
1588848b8605Smrg
1589848b8605Smrg
1590848b8605Smrgvoid GLAPIENTRY
1591848b8605Smrg_mesa_DeleteProgram(GLuint name)
1592848b8605Smrg{
1593848b8605Smrg   if (name) {
1594848b8605Smrg      GET_CURRENT_CONTEXT(ctx);
1595848b8605Smrg      FLUSH_VERTICES(ctx, 0);
1596848b8605Smrg      delete_shader_program(ctx, name);
1597848b8605Smrg   }
1598848b8605Smrg}
1599848b8605Smrg
1600848b8605Smrg
1601848b8605Smrgvoid GLAPIENTRY
1602848b8605Smrg_mesa_DeleteShader(GLuint name)
1603848b8605Smrg{
1604848b8605Smrg   if (name) {
1605848b8605Smrg      GET_CURRENT_CONTEXT(ctx);
1606848b8605Smrg      FLUSH_VERTICES(ctx, 0);
1607848b8605Smrg      delete_shader(ctx, name);
1608848b8605Smrg   }
1609848b8605Smrg}
1610848b8605Smrg
1611848b8605Smrg
1612b8e80941Smrgvoid GLAPIENTRY
1613b8e80941Smrg_mesa_DetachObjectARB_no_error(GLhandleARB program, GLhandleARB shader)
1614b8e80941Smrg{
1615b8e80941Smrg   GET_CURRENT_CONTEXT(ctx);
1616b8e80941Smrg   detach_shader_no_error(ctx, program, shader);
1617b8e80941Smrg}
1618b8e80941Smrg
1619b8e80941Smrg
1620848b8605Smrgvoid GLAPIENTRY
1621848b8605Smrg_mesa_DetachObjectARB(GLhandleARB program, GLhandleARB shader)
1622848b8605Smrg{
1623848b8605Smrg   GET_CURRENT_CONTEXT(ctx);
1624b8e80941Smrg   detach_shader_error(ctx, program, shader);
1625b8e80941Smrg}
1626b8e80941Smrg
1627b8e80941Smrg
1628b8e80941Smrgvoid GLAPIENTRY
1629b8e80941Smrg_mesa_DetachShader_no_error(GLuint program, GLuint shader)
1630b8e80941Smrg{
1631b8e80941Smrg   GET_CURRENT_CONTEXT(ctx);
1632b8e80941Smrg   detach_shader_no_error(ctx, program, shader);
1633848b8605Smrg}
1634848b8605Smrg
1635848b8605Smrg
1636848b8605Smrgvoid GLAPIENTRY
1637848b8605Smrg_mesa_DetachShader(GLuint program, GLuint shader)
1638848b8605Smrg{
1639848b8605Smrg   GET_CURRENT_CONTEXT(ctx);
1640b8e80941Smrg   detach_shader_error(ctx, program, shader);
1641848b8605Smrg}
1642848b8605Smrg
1643848b8605Smrg
1644848b8605Smrgvoid GLAPIENTRY
1645848b8605Smrg_mesa_GetAttachedObjectsARB(GLhandleARB container, GLsizei maxCount,
1646848b8605Smrg                            GLsizei * count, GLhandleARB * obj)
1647848b8605Smrg{
1648848b8605Smrg   GET_CURRENT_CONTEXT(ctx);
1649b8e80941Smrg   get_attached_shaders(ctx, (GLuint)container, maxCount, count, NULL, obj);
1650848b8605Smrg}
1651848b8605Smrg
1652848b8605Smrg
1653848b8605Smrgvoid GLAPIENTRY
1654848b8605Smrg_mesa_GetAttachedShaders(GLuint program, GLsizei maxCount,
1655848b8605Smrg                         GLsizei *count, GLuint *obj)
1656848b8605Smrg{
1657848b8605Smrg   GET_CURRENT_CONTEXT(ctx);
1658b8e80941Smrg   get_attached_shaders(ctx, program, maxCount, count, obj, NULL);
1659848b8605Smrg}
1660848b8605Smrg
1661848b8605Smrg
1662848b8605Smrgvoid GLAPIENTRY
1663848b8605Smrg_mesa_GetInfoLogARB(GLhandleARB object, GLsizei maxLength, GLsizei * length,
1664848b8605Smrg                    GLcharARB * infoLog)
1665848b8605Smrg{
1666848b8605Smrg   GET_CURRENT_CONTEXT(ctx);
1667848b8605Smrg   if (is_program(ctx, object)) {
1668848b8605Smrg      get_program_info_log(ctx, object, maxLength, length, infoLog);
1669848b8605Smrg   }
1670848b8605Smrg   else if (is_shader(ctx, object)) {
1671848b8605Smrg      get_shader_info_log(ctx, object, maxLength, length, infoLog);
1672848b8605Smrg   }
1673848b8605Smrg   else {
1674848b8605Smrg      _mesa_error(ctx, GL_INVALID_OPERATION, "glGetInfoLogARB");
1675848b8605Smrg   }
1676848b8605Smrg}
1677848b8605Smrg
1678848b8605Smrg
1679848b8605Smrgvoid GLAPIENTRY
1680848b8605Smrg_mesa_GetObjectParameterivARB(GLhandleARB object, GLenum pname, GLint *params)
1681848b8605Smrg{
1682848b8605Smrg   GET_CURRENT_CONTEXT(ctx);
1683848b8605Smrg   /* Implement in terms of GetProgramiv, GetShaderiv */
1684848b8605Smrg   if (is_program(ctx, object)) {
1685848b8605Smrg      if (pname == GL_OBJECT_TYPE_ARB) {
1686848b8605Smrg	 *params = GL_PROGRAM_OBJECT_ARB;
1687848b8605Smrg      }
1688848b8605Smrg      else {
1689848b8605Smrg	 get_programiv(ctx, object, pname, params);
1690848b8605Smrg      }
1691848b8605Smrg   }
1692848b8605Smrg   else if (is_shader(ctx, object)) {
1693848b8605Smrg      if (pname == GL_OBJECT_TYPE_ARB) {
1694848b8605Smrg	 *params = GL_SHADER_OBJECT_ARB;
1695848b8605Smrg      }
1696848b8605Smrg      else {
1697848b8605Smrg	 get_shaderiv(ctx, object, pname, params);
1698848b8605Smrg      }
1699848b8605Smrg   }
1700848b8605Smrg   else {
1701848b8605Smrg      _mesa_error(ctx, GL_INVALID_VALUE, "glGetObjectParameterivARB");
1702848b8605Smrg   }
1703848b8605Smrg}
1704848b8605Smrg
1705848b8605Smrg
1706848b8605Smrgvoid GLAPIENTRY
1707848b8605Smrg_mesa_GetObjectParameterfvARB(GLhandleARB object, GLenum pname,
1708848b8605Smrg                              GLfloat *params)
1709848b8605Smrg{
1710b8e80941Smrg   GLint iparams[1] = {0};  /* XXX is one element enough? */
1711848b8605Smrg   _mesa_GetObjectParameterivARB(object, pname, iparams);
1712848b8605Smrg   params[0] = (GLfloat) iparams[0];
1713848b8605Smrg}
1714848b8605Smrg
1715848b8605Smrg
1716848b8605Smrgvoid GLAPIENTRY
1717848b8605Smrg_mesa_GetProgramiv(GLuint program, GLenum pname, GLint *params)
1718848b8605Smrg{
1719848b8605Smrg   GET_CURRENT_CONTEXT(ctx);
1720848b8605Smrg   get_programiv(ctx, program, pname, params);
1721848b8605Smrg}
1722848b8605Smrg
1723848b8605Smrg
1724848b8605Smrgvoid GLAPIENTRY
1725848b8605Smrg_mesa_GetShaderiv(GLuint shader, GLenum pname, GLint *params)
1726848b8605Smrg{
1727848b8605Smrg   GET_CURRENT_CONTEXT(ctx);
1728848b8605Smrg   get_shaderiv(ctx, shader, pname, params);
1729848b8605Smrg}
1730848b8605Smrg
1731848b8605Smrg
1732848b8605Smrgvoid GLAPIENTRY
1733848b8605Smrg_mesa_GetProgramInfoLog(GLuint program, GLsizei bufSize,
1734848b8605Smrg                        GLsizei *length, GLchar *infoLog)
1735848b8605Smrg{
1736848b8605Smrg   GET_CURRENT_CONTEXT(ctx);
1737848b8605Smrg   get_program_info_log(ctx, program, bufSize, length, infoLog);
1738848b8605Smrg}
1739848b8605Smrg
1740848b8605Smrg
1741848b8605Smrgvoid GLAPIENTRY
1742848b8605Smrg_mesa_GetShaderInfoLog(GLuint shader, GLsizei bufSize,
1743848b8605Smrg                       GLsizei *length, GLchar *infoLog)
1744848b8605Smrg{
1745848b8605Smrg   GET_CURRENT_CONTEXT(ctx);
1746848b8605Smrg   get_shader_info_log(ctx, shader, bufSize, length, infoLog);
1747848b8605Smrg}
1748848b8605Smrg
1749848b8605Smrg
1750848b8605Smrgvoid GLAPIENTRY
1751b8e80941Smrg_mesa_GetShaderSource(GLuint shader, GLsizei maxLength,
1752b8e80941Smrg                      GLsizei *length, GLchar *sourceOut)
1753848b8605Smrg{
1754848b8605Smrg   GET_CURRENT_CONTEXT(ctx);
1755848b8605Smrg   get_shader_source(ctx, shader, maxLength, length, sourceOut);
1756848b8605Smrg}
1757848b8605Smrg
1758848b8605Smrg
1759848b8605SmrgGLhandleARB GLAPIENTRY
1760848b8605Smrg_mesa_GetHandleARB(GLenum pname)
1761848b8605Smrg{
1762848b8605Smrg   GET_CURRENT_CONTEXT(ctx);
1763848b8605Smrg   return get_handle(ctx, pname);
1764848b8605Smrg}
1765848b8605Smrg
1766848b8605Smrg
1767848b8605SmrgGLboolean GLAPIENTRY
1768848b8605Smrg_mesa_IsProgram(GLuint name)
1769848b8605Smrg{
1770848b8605Smrg   GET_CURRENT_CONTEXT(ctx);
1771848b8605Smrg   return is_program(ctx, name);
1772848b8605Smrg}
1773848b8605Smrg
1774848b8605Smrg
1775848b8605SmrgGLboolean GLAPIENTRY
1776848b8605Smrg_mesa_IsShader(GLuint name)
1777848b8605Smrg{
1778848b8605Smrg   GET_CURRENT_CONTEXT(ctx);
1779848b8605Smrg   return is_shader(ctx, name);
1780848b8605Smrg}
1781848b8605Smrg
1782848b8605Smrg
1783848b8605Smrgvoid GLAPIENTRY
1784b8e80941Smrg_mesa_LinkProgram_no_error(GLuint programObj)
1785b8e80941Smrg{
1786b8e80941Smrg   GET_CURRENT_CONTEXT(ctx);
1787b8e80941Smrg
1788b8e80941Smrg   struct gl_shader_program *shProg =
1789b8e80941Smrg      _mesa_lookup_shader_program(ctx, programObj);
1790b8e80941Smrg   link_program_no_error(ctx, shProg);
1791b8e80941Smrg}
1792b8e80941Smrg
1793b8e80941Smrg
1794b8e80941Smrgvoid GLAPIENTRY
1795b8e80941Smrg_mesa_LinkProgram(GLuint programObj)
1796848b8605Smrg{
1797848b8605Smrg   GET_CURRENT_CONTEXT(ctx);
1798b8e80941Smrg
1799b8e80941Smrg   if (MESA_VERBOSE & VERBOSE_API)
1800b8e80941Smrg      _mesa_debug(ctx, "glLinkProgram %u\n", programObj);
1801b8e80941Smrg
1802b8e80941Smrg   struct gl_shader_program *shProg =
1803b8e80941Smrg      _mesa_lookup_shader_program_err(ctx, programObj, "glLinkProgram");
1804b8e80941Smrg   link_program_error(ctx, shProg);
1805b8e80941Smrg}
1806b8e80941Smrg
1807b8e80941Smrg#ifdef ENABLE_SHADER_CACHE
1808b8e80941Smrg/**
1809b8e80941Smrg * Generate a SHA-1 hash value string for given source string.
1810b8e80941Smrg */
1811b8e80941Smrgstatic void
1812b8e80941Smrggenerate_sha1(const char *source, char sha_str[64])
1813b8e80941Smrg{
1814b8e80941Smrg   unsigned char sha[20];
1815b8e80941Smrg   _mesa_sha1_compute(source, strlen(source), sha);
1816b8e80941Smrg   _mesa_sha1_format(sha_str, sha);
1817b8e80941Smrg}
1818b8e80941Smrg
1819b8e80941Smrg/**
1820b8e80941Smrg * Construct a full path for shader replacement functionality using
1821b8e80941Smrg * following format:
1822b8e80941Smrg *
1823b8e80941Smrg * <path>/<stage prefix>_<CHECKSUM>.glsl
1824b8e80941Smrg * <path>/<stage prefix>_<CHECKSUM>.arb
1825b8e80941Smrg */
1826b8e80941Smrgstatic char *
1827b8e80941Smrgconstruct_name(const gl_shader_stage stage, const char *source,
1828b8e80941Smrg               const char *path)
1829b8e80941Smrg{
1830b8e80941Smrg   char sha[64];
1831b8e80941Smrg   static const char *types[] = {
1832b8e80941Smrg      "VS", "TC", "TE", "GS", "FS", "CS",
1833b8e80941Smrg   };
1834b8e80941Smrg
1835b8e80941Smrg   const char *format = strncmp(source, "!!ARB", 5) ? "glsl" : "arb";
1836b8e80941Smrg
1837b8e80941Smrg   generate_sha1(source, sha);
1838b8e80941Smrg   return ralloc_asprintf(NULL, "%s/%s_%s.%s", path, types[stage], sha, format);
1839848b8605Smrg}
1840848b8605Smrg
1841b8e80941Smrg/**
1842b8e80941Smrg * Write given shader source to a file in MESA_SHADER_DUMP_PATH.
1843b8e80941Smrg */
1844b8e80941Smrgvoid
1845b8e80941Smrg_mesa_dump_shader_source(const gl_shader_stage stage, const char *source)
1846b8e80941Smrg{
1847b8e80941Smrg   static bool path_exists = true;
1848b8e80941Smrg   char *dump_path;
1849b8e80941Smrg   FILE *f;
1850b8e80941Smrg
1851b8e80941Smrg   if (!path_exists)
1852b8e80941Smrg      return;
1853b8e80941Smrg
1854b8e80941Smrg   dump_path = getenv("MESA_SHADER_DUMP_PATH");
1855b8e80941Smrg   if (!dump_path) {
1856b8e80941Smrg      path_exists = false;
1857b8e80941Smrg      return;
1858b8e80941Smrg   }
1859b8e80941Smrg
1860b8e80941Smrg   char *name = construct_name(stage, source, dump_path);
1861848b8605Smrg
1862b8e80941Smrg   f = fopen(name, "w");
1863b8e80941Smrg   if (f) {
1864b8e80941Smrg      fputs(source, f);
1865b8e80941Smrg      fclose(f);
1866b8e80941Smrg   } else {
1867b8e80941Smrg      GET_CURRENT_CONTEXT(ctx);
1868b8e80941Smrg      _mesa_warning(ctx, "could not open %s for dumping shader (%s)", name,
1869b8e80941Smrg                    strerror(errno));
1870b8e80941Smrg   }
1871b8e80941Smrg   ralloc_free(name);
1872b8e80941Smrg}
1873848b8605Smrg
1874848b8605Smrg/**
1875848b8605Smrg * Read shader source code from a file.
1876848b8605Smrg * Useful for debugging to override an app's shader.
1877848b8605Smrg */
1878b8e80941SmrgGLcharARB *
1879b8e80941Smrg_mesa_read_shader_source(const gl_shader_stage stage, const char *source)
1880848b8605Smrg{
1881b8e80941Smrg   char *read_path;
1882b8e80941Smrg   static bool path_exists = true;
1883b8e80941Smrg   int len, shader_size = 0;
1884b8e80941Smrg   GLcharARB *buffer;
1885b8e80941Smrg   FILE *f;
1886b8e80941Smrg
1887b8e80941Smrg   if (!path_exists)
1888b8e80941Smrg      return NULL;
1889848b8605Smrg
1890b8e80941Smrg   read_path = getenv("MESA_SHADER_READ_PATH");
1891b8e80941Smrg   if (!read_path) {
1892b8e80941Smrg      path_exists = false;
1893848b8605Smrg      return NULL;
1894848b8605Smrg   }
1895848b8605Smrg
1896b8e80941Smrg   char *name = construct_name(stage, source, read_path);
1897b8e80941Smrg   f = fopen(name, "r");
1898b8e80941Smrg   ralloc_free(name);
1899b8e80941Smrg   if (!f)
1900b8e80941Smrg      return NULL;
1901b8e80941Smrg
1902848b8605Smrg   /* allocate enough room for the entire shader */
1903848b8605Smrg   fseek(f, 0, SEEK_END);
1904848b8605Smrg   shader_size = ftell(f);
1905848b8605Smrg   rewind(f);
1906848b8605Smrg   assert(shader_size);
1907848b8605Smrg
1908848b8605Smrg   /* add one for terminating zero */
1909848b8605Smrg   shader_size++;
1910848b8605Smrg
1911848b8605Smrg   buffer = malloc(shader_size);
1912848b8605Smrg   assert(buffer);
1913848b8605Smrg
1914848b8605Smrg   len = fread(buffer, 1, shader_size, f);
1915848b8605Smrg   buffer[len] = 0;
1916848b8605Smrg
1917848b8605Smrg   fclose(f);
1918848b8605Smrg
1919b8e80941Smrg   return buffer;
1920848b8605Smrg}
1921848b8605Smrg
1922b8e80941Smrg#endif /* ENABLE_SHADER_CACHE */
1923848b8605Smrg
1924848b8605Smrg/**
1925848b8605Smrg * Called via glShaderSource() and glShaderSourceARB() API functions.
1926848b8605Smrg * Basically, concatenate the source code strings into one long string
1927848b8605Smrg * and pass it to _mesa_shader_source().
1928848b8605Smrg */
1929b8e80941Smrgstatic ALWAYS_INLINE void
1930b8e80941Smrgshader_source(struct gl_context *ctx, GLuint shaderObj, GLsizei count,
1931b8e80941Smrg              const GLchar *const *string, const GLint *length, bool no_error)
1932848b8605Smrg{
1933848b8605Smrg   GLint *offsets;
1934848b8605Smrg   GLsizei i, totalLength;
1935848b8605Smrg   GLcharARB *source;
1936b8e80941Smrg   struct gl_shader *sh;
1937848b8605Smrg
1938b8e80941Smrg   if (!no_error) {
1939b8e80941Smrg      sh = _mesa_lookup_shader_err(ctx, shaderObj, "glShaderSourceARB");
1940b8e80941Smrg      if (!sh)
1941b8e80941Smrg         return;
1942b8e80941Smrg
1943b8e80941Smrg      if (string == NULL) {
1944b8e80941Smrg         _mesa_error(ctx, GL_INVALID_VALUE, "glShaderSourceARB");
1945b8e80941Smrg         return;
1946b8e80941Smrg      }
1947b8e80941Smrg   } else {
1948b8e80941Smrg      sh = _mesa_lookup_shader(ctx, shaderObj);
1949848b8605Smrg   }
1950848b8605Smrg
1951848b8605Smrg   /*
1952848b8605Smrg    * This array holds offsets of where the appropriate string ends, thus the
1953848b8605Smrg    * last element will be set to the total length of the source code.
1954848b8605Smrg    */
1955848b8605Smrg   offsets = malloc(count * sizeof(GLint));
1956848b8605Smrg   if (offsets == NULL) {
1957848b8605Smrg      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glShaderSourceARB");
1958848b8605Smrg      return;
1959848b8605Smrg   }
1960848b8605Smrg
1961848b8605Smrg   for (i = 0; i < count; i++) {
1962b8e80941Smrg      if (!no_error && string[i] == NULL) {
1963848b8605Smrg         free((GLvoid *) offsets);
1964848b8605Smrg         _mesa_error(ctx, GL_INVALID_OPERATION,
1965848b8605Smrg                     "glShaderSourceARB(null string)");
1966848b8605Smrg         return;
1967848b8605Smrg      }
1968848b8605Smrg      if (length == NULL || length[i] < 0)
1969848b8605Smrg         offsets[i] = strlen(string[i]);
1970848b8605Smrg      else
1971848b8605Smrg         offsets[i] = length[i];
1972848b8605Smrg      /* accumulate string lengths */
1973848b8605Smrg      if (i > 0)
1974848b8605Smrg         offsets[i] += offsets[i - 1];
1975848b8605Smrg   }
1976848b8605Smrg
1977848b8605Smrg   /* Total length of source string is sum off all strings plus two.
1978848b8605Smrg    * One extra byte for terminating zero, another extra byte to silence
1979848b8605Smrg    * valgrind warnings in the parser/grammer code.
1980848b8605Smrg    */
1981848b8605Smrg   totalLength = offsets[count - 1] + 2;
1982848b8605Smrg   source = malloc(totalLength * sizeof(GLcharARB));
1983848b8605Smrg   if (source == NULL) {
1984848b8605Smrg      free((GLvoid *) offsets);
1985848b8605Smrg      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glShaderSourceARB");
1986848b8605Smrg      return;
1987848b8605Smrg   }
1988848b8605Smrg
1989848b8605Smrg   for (i = 0; i < count; i++) {
1990848b8605Smrg      GLint start = (i > 0) ? offsets[i - 1] : 0;
1991848b8605Smrg      memcpy(source + start, string[i],
1992848b8605Smrg             (offsets[i] - start) * sizeof(GLcharARB));
1993848b8605Smrg   }
1994848b8605Smrg   source[totalLength - 1] = '\0';
1995848b8605Smrg   source[totalLength - 2] = '\0';
1996848b8605Smrg
1997b8e80941Smrg#ifdef ENABLE_SHADER_CACHE
1998b8e80941Smrg   GLcharARB *replacement;
1999848b8605Smrg
2000b8e80941Smrg   /* Dump original shader source to MESA_SHADER_DUMP_PATH and replace
2001b8e80941Smrg    * if corresponding entry found from MESA_SHADER_READ_PATH.
2002b8e80941Smrg    */
2003b8e80941Smrg   _mesa_dump_shader_source(sh->Stage, source);
2004848b8605Smrg
2005b8e80941Smrg   replacement = _mesa_read_shader_source(sh->Stage, source);
2006b8e80941Smrg   if (replacement) {
2007b8e80941Smrg      free(source);
2008b8e80941Smrg      source = replacement;
2009848b8605Smrg   }
2010b8e80941Smrg#endif /* ENABLE_SHADER_CACHE */
2011848b8605Smrg
2012b8e80941Smrg   set_shader_source(sh, source);
2013848b8605Smrg
2014848b8605Smrg   free(offsets);
2015848b8605Smrg}
2016848b8605Smrg
2017848b8605Smrg
2018848b8605Smrgvoid GLAPIENTRY
2019b8e80941Smrg_mesa_ShaderSource_no_error(GLuint shaderObj, GLsizei count,
2020b8e80941Smrg                            const GLchar *const *string, const GLint *length)
2021848b8605Smrg{
2022848b8605Smrg   GET_CURRENT_CONTEXT(ctx);
2023b8e80941Smrg   shader_source(ctx, shaderObj, count, string, length, true);
2024b8e80941Smrg}
2025848b8605Smrg
2026848b8605Smrg
2027b8e80941Smrgvoid GLAPIENTRY
2028b8e80941Smrg_mesa_ShaderSource(GLuint shaderObj, GLsizei count,
2029b8e80941Smrg                   const GLchar *const *string, const GLint *length)
2030b8e80941Smrg{
2031b8e80941Smrg   GET_CURRENT_CONTEXT(ctx);
2032b8e80941Smrg   shader_source(ctx, shaderObj, count, string, length, false);
2033b8e80941Smrg}
2034b8e80941Smrg
2035b8e80941Smrg
2036b8e80941Smrgstatic ALWAYS_INLINE void
2037b8e80941Smrguse_program(GLuint program, bool no_error)
2038b8e80941Smrg{
2039b8e80941Smrg   GET_CURRENT_CONTEXT(ctx);
2040b8e80941Smrg   struct gl_shader_program *shProg = NULL;
2041b8e80941Smrg
2042b8e80941Smrg   if (MESA_VERBOSE & VERBOSE_API)
2043b8e80941Smrg      _mesa_debug(ctx, "glUseProgram %u\n", program);
2044b8e80941Smrg
2045b8e80941Smrg   if (no_error) {
2046b8e80941Smrg      if (program) {
2047b8e80941Smrg         shProg = _mesa_lookup_shader_program(ctx, program);
2048848b8605Smrg      }
2049b8e80941Smrg   } else {
2050b8e80941Smrg      if (_mesa_is_xfb_active_and_unpaused(ctx)) {
2051848b8605Smrg         _mesa_error(ctx, GL_INVALID_OPERATION,
2052b8e80941Smrg                     "glUseProgram(transform feedback active)");
2053848b8605Smrg         return;
2054848b8605Smrg      }
2055848b8605Smrg
2056b8e80941Smrg      if (program) {
2057b8e80941Smrg         shProg =
2058b8e80941Smrg            _mesa_lookup_shader_program_err(ctx, program, "glUseProgram");
2059b8e80941Smrg         if (!shProg)
2060b8e80941Smrg            return;
2061b8e80941Smrg
2062b8e80941Smrg         if (!shProg->data->LinkStatus) {
2063b8e80941Smrg            _mesa_error(ctx, GL_INVALID_OPERATION,
2064b8e80941Smrg                        "glUseProgram(program %u not linked)", program);
2065b8e80941Smrg            return;
2066b8e80941Smrg         }
2067b8e80941Smrg
2068b8e80941Smrg         /* debug code */
2069b8e80941Smrg         if (ctx->_Shader->Flags & GLSL_USE_PROG) {
2070b8e80941Smrg            print_shader_info(shProg);
2071b8e80941Smrg         }
2072848b8605Smrg      }
2073848b8605Smrg   }
2074848b8605Smrg
2075848b8605Smrg   /* The ARB_separate_shader_object spec says:
2076848b8605Smrg    *
2077848b8605Smrg    *     "The executable code for an individual shader stage is taken from
2078848b8605Smrg    *     the current program for that stage.  If there is a current program
2079848b8605Smrg    *     object established by UseProgram, that program is considered current
2080848b8605Smrg    *     for all stages.  Otherwise, if there is a bound program pipeline
2081848b8605Smrg    *     object (section 2.14.PPO), the program bound to the appropriate
2082848b8605Smrg    *     stage of the pipeline object is considered current."
2083848b8605Smrg    */
2084b8e80941Smrg   if (shProg) {
2085848b8605Smrg      /* Attach shader state to the binding point */
2086848b8605Smrg      _mesa_reference_pipeline_object(ctx, &ctx->_Shader, &ctx->Shader);
2087848b8605Smrg      /* Update the program */
2088b8e80941Smrg      _mesa_use_shader_program(ctx, shProg);
2089848b8605Smrg   } else {
2090848b8605Smrg      /* Must be done first: detach the progam */
2091b8e80941Smrg      _mesa_use_shader_program(ctx, shProg);
2092848b8605Smrg      /* Unattach shader_state binding point */
2093b8e80941Smrg      _mesa_reference_pipeline_object(ctx, &ctx->_Shader,
2094b8e80941Smrg                                      ctx->Pipeline.Default);
2095848b8605Smrg      /* If a pipeline was bound, rebind it */
2096848b8605Smrg      if (ctx->Pipeline.Current) {
2097b8e80941Smrg         if (no_error)
2098b8e80941Smrg            _mesa_BindProgramPipeline_no_error(ctx->Pipeline.Current->Name);
2099b8e80941Smrg         else
2100b8e80941Smrg            _mesa_BindProgramPipeline(ctx->Pipeline.Current->Name);
2101848b8605Smrg      }
2102848b8605Smrg   }
2103b8e80941Smrg
2104b8e80941Smrg   _mesa_update_vertex_processing_mode(ctx);
2105848b8605Smrg}
2106848b8605Smrg
2107848b8605Smrg
2108848b8605Smrgvoid GLAPIENTRY
2109b8e80941Smrg_mesa_UseProgram_no_error(GLuint program)
2110b8e80941Smrg{
2111b8e80941Smrg   use_program(program, true);
2112b8e80941Smrg}
2113b8e80941Smrg
2114b8e80941Smrg
2115b8e80941Smrgvoid GLAPIENTRY
2116b8e80941Smrg_mesa_UseProgram(GLuint program)
2117b8e80941Smrg{
2118b8e80941Smrg   use_program(program, false);
2119b8e80941Smrg}
2120b8e80941Smrg
2121b8e80941Smrg
2122b8e80941Smrgvoid GLAPIENTRY
2123b8e80941Smrg_mesa_ValidateProgram(GLuint program)
2124848b8605Smrg{
2125848b8605Smrg   GET_CURRENT_CONTEXT(ctx);
2126848b8605Smrg   validate_program(ctx, program);
2127848b8605Smrg}
2128848b8605Smrg
2129848b8605Smrg
2130848b8605Smrg/**
2131848b8605Smrg * For OpenGL ES 2.0, GL_ARB_ES2_compatibility
2132848b8605Smrg */
2133848b8605Smrgvoid GLAPIENTRY
2134848b8605Smrg_mesa_GetShaderPrecisionFormat(GLenum shadertype, GLenum precisiontype,
2135848b8605Smrg                               GLint* range, GLint* precision)
2136848b8605Smrg{
2137848b8605Smrg   const struct gl_program_constants *limits;
2138848b8605Smrg   const struct gl_precision *p;
2139848b8605Smrg   GET_CURRENT_CONTEXT(ctx);
2140848b8605Smrg
2141848b8605Smrg   switch (shadertype) {
2142848b8605Smrg   case GL_VERTEX_SHADER:
2143848b8605Smrg      limits = &ctx->Const.Program[MESA_SHADER_VERTEX];
2144848b8605Smrg      break;
2145848b8605Smrg   case GL_FRAGMENT_SHADER:
2146848b8605Smrg      limits = &ctx->Const.Program[MESA_SHADER_FRAGMENT];
2147848b8605Smrg      break;
2148848b8605Smrg   default:
2149848b8605Smrg      _mesa_error(ctx, GL_INVALID_ENUM,
2150848b8605Smrg                  "glGetShaderPrecisionFormat(shadertype)");
2151848b8605Smrg      return;
2152848b8605Smrg   }
2153848b8605Smrg
2154848b8605Smrg   switch (precisiontype) {
2155848b8605Smrg   case GL_LOW_FLOAT:
2156848b8605Smrg      p = &limits->LowFloat;
2157848b8605Smrg      break;
2158848b8605Smrg   case GL_MEDIUM_FLOAT:
2159848b8605Smrg      p = &limits->MediumFloat;
2160848b8605Smrg      break;
2161848b8605Smrg   case GL_HIGH_FLOAT:
2162848b8605Smrg      p = &limits->HighFloat;
2163848b8605Smrg      break;
2164848b8605Smrg   case GL_LOW_INT:
2165848b8605Smrg      p = &limits->LowInt;
2166848b8605Smrg      break;
2167848b8605Smrg   case GL_MEDIUM_INT:
2168848b8605Smrg      p = &limits->MediumInt;
2169848b8605Smrg      break;
2170848b8605Smrg   case GL_HIGH_INT:
2171848b8605Smrg      p = &limits->HighInt;
2172848b8605Smrg      break;
2173848b8605Smrg   default:
2174848b8605Smrg      _mesa_error(ctx, GL_INVALID_ENUM,
2175848b8605Smrg                  "glGetShaderPrecisionFormat(precisiontype)");
2176848b8605Smrg      return;
2177848b8605Smrg   }
2178848b8605Smrg
2179848b8605Smrg   range[0] = p->RangeMin;
2180848b8605Smrg   range[1] = p->RangeMax;
2181848b8605Smrg   precision[0] = p->Precision;
2182848b8605Smrg}
2183848b8605Smrg
2184848b8605Smrg
2185848b8605Smrg/**
2186848b8605Smrg * For OpenGL ES 2.0, GL_ARB_ES2_compatibility
2187848b8605Smrg */
2188848b8605Smrgvoid GLAPIENTRY
2189848b8605Smrg_mesa_ReleaseShaderCompiler(void)
2190848b8605Smrg{
2191848b8605Smrg   _mesa_destroy_shader_compiler_caches();
2192848b8605Smrg}
2193848b8605Smrg
2194848b8605Smrg
2195848b8605Smrg/**
2196848b8605Smrg * For OpenGL ES 2.0, GL_ARB_ES2_compatibility
2197848b8605Smrg */
2198848b8605Smrgvoid GLAPIENTRY
2199848b8605Smrg_mesa_ShaderBinary(GLint n, const GLuint* shaders, GLenum binaryformat,
2200848b8605Smrg                   const void* binary, GLint length)
2201848b8605Smrg{
2202848b8605Smrg   GET_CURRENT_CONTEXT(ctx);
2203b8e80941Smrg   struct gl_shader **sh;
2204b8e80941Smrg
2205b8e80941Smrg   /* Page 68, section 7.2 'Shader Binaries" of the of the OpenGL ES 3.1, and
2206b8e80941Smrg    * page 88 of the OpenGL 4.5 specs state:
2207b8e80941Smrg    *
2208b8e80941Smrg    *     "An INVALID_VALUE error is generated if count or length is negative.
2209b8e80941Smrg    *      An INVALID_ENUM error is generated if binaryformat is not a supported
2210b8e80941Smrg    *      format returned in SHADER_BINARY_FORMATS."
2211b8e80941Smrg    */
2212b8e80941Smrg   if (n < 0 || length < 0) {
2213b8e80941Smrg      _mesa_error(ctx, GL_INVALID_VALUE, "glShaderBinary(count or length < 0)");
2214b8e80941Smrg      return;
2215b8e80941Smrg   }
2216b8e80941Smrg
2217b8e80941Smrg   /* Get all shader objects at once so we can make the operation
2218b8e80941Smrg    * all-or-nothing.
2219b8e80941Smrg    */
2220b8e80941Smrg   if (n > SIZE_MAX / sizeof(*sh)) {
2221b8e80941Smrg      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glShaderBinary(count)");
2222b8e80941Smrg      return;
2223b8e80941Smrg   }
2224b8e80941Smrg
2225b8e80941Smrg   sh = alloca(sizeof(*sh) * (size_t)n);
2226b8e80941Smrg   if (!sh) {
2227b8e80941Smrg      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glShaderBinary");
2228b8e80941Smrg      return;
2229b8e80941Smrg   }
2230b8e80941Smrg
2231b8e80941Smrg   for (int i = 0; i < n; ++i) {
2232b8e80941Smrg      sh[i] = _mesa_lookup_shader_err(ctx, shaders[i], "glShaderBinary");
2233b8e80941Smrg      if (!sh[i])
2234b8e80941Smrg         return;
2235b8e80941Smrg   }
2236b8e80941Smrg
2237b8e80941Smrg   if (binaryformat == GL_SHADER_BINARY_FORMAT_SPIR_V_ARB) {
2238b8e80941Smrg      if (!ctx->Extensions.ARB_gl_spirv) {
2239b8e80941Smrg         _mesa_error(ctx, GL_INVALID_OPERATION, "glShaderBinary(SPIR-V)");
2240b8e80941Smrg      } else if (n > 0) {
2241b8e80941Smrg         _mesa_spirv_shader_binary(ctx, (unsigned) n, sh, binary,
2242b8e80941Smrg                                   (size_t) length);
2243b8e80941Smrg      }
2244b8e80941Smrg
2245b8e80941Smrg      return;
2246b8e80941Smrg   }
2247b8e80941Smrg
2248b8e80941Smrg   _mesa_error(ctx, GL_INVALID_ENUM, "glShaderBinary(format)");
2249848b8605Smrg}
2250848b8605Smrg
2251848b8605Smrg
2252848b8605Smrgvoid GLAPIENTRY
2253848b8605Smrg_mesa_GetProgramBinary(GLuint program, GLsizei bufSize, GLsizei *length,
2254848b8605Smrg                       GLenum *binaryFormat, GLvoid *binary)
2255848b8605Smrg{
2256848b8605Smrg   struct gl_shader_program *shProg;
2257b8e80941Smrg   GLsizei length_dummy;
2258848b8605Smrg   GET_CURRENT_CONTEXT(ctx);
2259848b8605Smrg
2260848b8605Smrg   if (bufSize < 0){
2261848b8605Smrg      _mesa_error(ctx, GL_INVALID_VALUE, "glGetProgramBinary(bufSize < 0)");
2262848b8605Smrg      return;
2263848b8605Smrg   }
2264848b8605Smrg
2265b8e80941Smrg   shProg = _mesa_lookup_shader_program_err(ctx, program, "glGetProgramBinary");
2266b8e80941Smrg   if (!shProg)
2267b8e80941Smrg      return;
2268b8e80941Smrg
2269848b8605Smrg   /* The ARB_get_program_binary spec says:
2270848b8605Smrg    *
2271848b8605Smrg    *     "If <length> is NULL, then no length is returned."
2272b8e80941Smrg    *
2273b8e80941Smrg    * Ensure that length always points to valid storage to avoid multiple NULL
2274b8e80941Smrg    * pointer checks below.
2275b8e80941Smrg    */
2276b8e80941Smrg   if (length == NULL)
2277b8e80941Smrg      length = &length_dummy;
2278b8e80941Smrg
2279b8e80941Smrg
2280b8e80941Smrg   /* The ARB_get_program_binary spec says:
2281b8e80941Smrg    *
2282b8e80941Smrg    *     "When a program object's LINK_STATUS is FALSE, its program binary
2283b8e80941Smrg    *     length is zero, and a call to GetProgramBinary will generate an
2284b8e80941Smrg    *     INVALID_OPERATION error.
2285848b8605Smrg    */
2286b8e80941Smrg   if (!shProg->data->LinkStatus) {
2287b8e80941Smrg      _mesa_error(ctx, GL_INVALID_OPERATION,
2288b8e80941Smrg                  "glGetProgramBinary(program %u not linked)",
2289b8e80941Smrg                  shProg->Name);
2290848b8605Smrg      *length = 0;
2291b8e80941Smrg      return;
2292b8e80941Smrg   }
2293848b8605Smrg
2294b8e80941Smrg   if (ctx->Const.NumProgramBinaryFormats == 0) {
2295b8e80941Smrg      *length = 0;
2296b8e80941Smrg      _mesa_error(ctx, GL_INVALID_OPERATION,
2297b8e80941Smrg                  "glGetProgramBinary(driver supports zero binary formats)");
2298b8e80941Smrg   } else {
2299b8e80941Smrg      _mesa_get_program_binary(ctx, shProg, bufSize, length, binaryFormat,
2300b8e80941Smrg                               binary);
2301b8e80941Smrg      assert(*length == 0 || *binaryFormat == GL_PROGRAM_BINARY_FORMAT_MESA);
2302b8e80941Smrg   }
2303848b8605Smrg}
2304848b8605Smrg
2305848b8605Smrgvoid GLAPIENTRY
2306848b8605Smrg_mesa_ProgramBinary(GLuint program, GLenum binaryFormat,
2307848b8605Smrg                    const GLvoid *binary, GLsizei length)
2308848b8605Smrg{
2309848b8605Smrg   struct gl_shader_program *shProg;
2310848b8605Smrg   GET_CURRENT_CONTEXT(ctx);
2311848b8605Smrg
2312848b8605Smrg   shProg = _mesa_lookup_shader_program_err(ctx, program, "glProgramBinary");
2313848b8605Smrg   if (!shProg)
2314848b8605Smrg      return;
2315848b8605Smrg
2316b8e80941Smrg   _mesa_clear_shader_program_data(ctx, shProg);
2317b8e80941Smrg   shProg->data = _mesa_create_shader_program_data();
2318848b8605Smrg
2319b8e80941Smrg   /* Section 2.3.1 (Errors) of the OpenGL 4.5 spec says:
2320b8e80941Smrg    *
2321b8e80941Smrg    *     "If a negative number is provided where an argument of type sizei or
2322b8e80941Smrg    *     sizeiptr is specified, an INVALID_VALUE error is generated."
2323b8e80941Smrg    */
2324b8e80941Smrg   if (length < 0) {
2325b8e80941Smrg      _mesa_error(ctx, GL_INVALID_VALUE, "glProgramBinary(length < 0)");
2326b8e80941Smrg      return;
2327b8e80941Smrg   }
2328848b8605Smrg
2329b8e80941Smrg   if (ctx->Const.NumProgramBinaryFormats == 0 ||
2330b8e80941Smrg       binaryFormat != GL_PROGRAM_BINARY_FORMAT_MESA) {
2331b8e80941Smrg      /* The ARB_get_program_binary spec says:
2332b8e80941Smrg       *
2333b8e80941Smrg       *     "<binaryFormat> and <binary> must be those returned by a previous
2334b8e80941Smrg       *     call to GetProgramBinary, and <length> must be the length of the
2335b8e80941Smrg       *     program binary as returned by GetProgramBinary or GetProgramiv with
2336b8e80941Smrg       *     <pname> PROGRAM_BINARY_LENGTH. Loading the program binary will fail,
2337b8e80941Smrg       *     setting the LINK_STATUS of <program> to FALSE, if these conditions
2338b8e80941Smrg       *     are not met."
2339b8e80941Smrg       *
2340b8e80941Smrg       * Since any value of binaryFormat passed "is not one of those specified as
2341b8e80941Smrg       * allowable for [this] command, an INVALID_ENUM error is generated."
2342b8e80941Smrg       */
2343b8e80941Smrg      shProg->data->LinkStatus = LINKING_FAILURE;
2344b8e80941Smrg      _mesa_error(ctx, GL_INVALID_ENUM, "glProgramBinary");
2345b8e80941Smrg   } else {
2346b8e80941Smrg      _mesa_program_binary(ctx, shProg, binaryFormat, binary, length);
2347b8e80941Smrg   }
2348b8e80941Smrg}
2349848b8605Smrg
2350848b8605Smrg
2351b8e80941Smrgstatic ALWAYS_INLINE void
2352b8e80941Smrgprogram_parameteri(struct gl_context *ctx, struct gl_shader_program *shProg,
2353b8e80941Smrg                   GLuint pname, GLint value, bool no_error)
2354b8e80941Smrg{
2355848b8605Smrg   switch (pname) {
2356848b8605Smrg   case GL_PROGRAM_BINARY_RETRIEVABLE_HINT:
2357848b8605Smrg      /* This enum isn't part of the OES extension for OpenGL ES 2.0, but it
2358848b8605Smrg       * is part of OpenGL ES 3.0.  For the ES2 case, this function shouldn't
2359848b8605Smrg       * even be in the dispatch table, so we shouldn't need to expclicitly
2360848b8605Smrg       * check here.
2361848b8605Smrg       *
2362848b8605Smrg       * On desktop, we ignore the 3.0+ requirement because it is silly.
2363848b8605Smrg       */
2364848b8605Smrg
2365848b8605Smrg      /* The ARB_get_program_binary extension spec says:
2366848b8605Smrg       *
2367848b8605Smrg       *     "An INVALID_VALUE error is generated if the <value> argument to
2368848b8605Smrg       *     ProgramParameteri is not TRUE or FALSE."
2369848b8605Smrg       */
2370b8e80941Smrg      if (!no_error && value != GL_TRUE && value != GL_FALSE) {
2371b8e80941Smrg         goto invalid_value;
2372848b8605Smrg      }
2373848b8605Smrg
2374848b8605Smrg      /* No need to notify the driver.  Any changes will actually take effect
2375848b8605Smrg       * the next time the shader is linked.
2376848b8605Smrg       *
2377848b8605Smrg       * The ARB_get_program_binary extension spec says:
2378848b8605Smrg       *
2379848b8605Smrg       *     "To indicate that a program binary is likely to be retrieved,
2380848b8605Smrg       *     ProgramParameteri should be called with <pname>
2381848b8605Smrg       *     PROGRAM_BINARY_RETRIEVABLE_HINT and <value> TRUE. This setting
2382848b8605Smrg       *     will not be in effect until the next time LinkProgram or
2383848b8605Smrg       *     ProgramBinary has been called successfully."
2384848b8605Smrg       *
2385848b8605Smrg       * The resloution of issue 9 in the extension spec also says:
2386848b8605Smrg       *
2387848b8605Smrg       *     "The application may use the PROGRAM_BINARY_RETRIEVABLE_HINT hint
2388848b8605Smrg       *     to indicate to the GL implementation that this program will
2389848b8605Smrg       *     likely be saved with GetProgramBinary at some point. This will
2390848b8605Smrg       *     give the GL implementation the opportunity to track any state
2391848b8605Smrg       *     changes made to the program before being saved such that when it
2392848b8605Smrg       *     is loaded again a recompile can be avoided."
2393848b8605Smrg       */
2394848b8605Smrg      shProg->BinaryRetreivableHint = value;
2395848b8605Smrg      return;
2396848b8605Smrg
2397848b8605Smrg   case GL_PROGRAM_SEPARABLE:
2398848b8605Smrg      /* Spec imply that the behavior is the same as ARB_get_program_binary
2399848b8605Smrg       * Chapter 7.3 Program Objects
2400848b8605Smrg       */
2401b8e80941Smrg      if (!no_error && value != GL_TRUE && value != GL_FALSE) {
2402b8e80941Smrg         goto invalid_value;
2403848b8605Smrg      }
2404848b8605Smrg      shProg->SeparateShader = value;
2405848b8605Smrg      return;
2406848b8605Smrg
2407848b8605Smrg   default:
2408b8e80941Smrg      if (!no_error) {
2409b8e80941Smrg         _mesa_error(ctx, GL_INVALID_ENUM, "glProgramParameteri(pname=%s)",
2410b8e80941Smrg                     _mesa_enum_to_string(pname));
2411b8e80941Smrg      }
2412b8e80941Smrg      return;
2413848b8605Smrg   }
2414848b8605Smrg
2415b8e80941Smrginvalid_value:
2416b8e80941Smrg   _mesa_error(ctx, GL_INVALID_VALUE,
2417b8e80941Smrg               "glProgramParameteri(pname=%s, value=%d): "
2418b8e80941Smrg               "value must be 0 or 1.",
2419b8e80941Smrg               _mesa_enum_to_string(pname),
2420b8e80941Smrg               value);
2421848b8605Smrg}
2422848b8605Smrg
2423b8e80941Smrg
2424b8e80941Smrgvoid GLAPIENTRY
2425b8e80941Smrg_mesa_ProgramParameteri_no_error(GLuint program, GLenum pname, GLint value)
2426848b8605Smrg{
2427b8e80941Smrg   GET_CURRENT_CONTEXT(ctx);
2428848b8605Smrg
2429b8e80941Smrg   struct gl_shader_program *shProg = _mesa_lookup_shader_program(ctx, program);
2430b8e80941Smrg   program_parameteri(ctx, shProg, pname, value, true);
2431848b8605Smrg}
2432848b8605Smrg
2433848b8605Smrg
2434b8e80941Smrgvoid GLAPIENTRY
2435b8e80941Smrg_mesa_ProgramParameteri(GLuint program, GLenum pname, GLint value)
2436848b8605Smrg{
2437b8e80941Smrg   struct gl_shader_program *shProg;
2438b8e80941Smrg   GET_CURRENT_CONTEXT(ctx);
2439848b8605Smrg
2440b8e80941Smrg   shProg = _mesa_lookup_shader_program_err(ctx, program,
2441b8e80941Smrg                                            "glProgramParameteri");
2442b8e80941Smrg   if (!shProg)
2443b8e80941Smrg      return;
2444848b8605Smrg
2445b8e80941Smrg   program_parameteri(ctx, shProg, pname, value, false);
2446b8e80941Smrg}
2447848b8605Smrg
2448848b8605Smrg
2449b8e80941Smrgvoid
2450b8e80941Smrg_mesa_use_program(struct gl_context *ctx, gl_shader_stage stage,
2451b8e80941Smrg                  struct gl_shader_program *shProg, struct gl_program *prog,
2452b8e80941Smrg                  struct gl_pipeline_object *shTarget)
2453b8e80941Smrg{
2454b8e80941Smrg   struct gl_program **target;
2455b8e80941Smrg
2456b8e80941Smrg   target = &shTarget->CurrentProgram[stage];
2457b8e80941Smrg   if (prog) {
2458b8e80941Smrg      _mesa_program_init_subroutine_defaults(ctx, prog);
2459b8e80941Smrg   }
2460b8e80941Smrg
2461b8e80941Smrg   if (*target != prog) {
2462b8e80941Smrg      /* Program is current, flush it */
2463b8e80941Smrg      if (shTarget == ctx->_Shader) {
2464b8e80941Smrg         FLUSH_VERTICES(ctx, _NEW_PROGRAM | _NEW_PROGRAM_CONSTANTS);
2465b8e80941Smrg      }
2466b8e80941Smrg
2467b8e80941Smrg      _mesa_reference_shader_program(ctx,
2468b8e80941Smrg                                     &shTarget->ReferencedPrograms[stage],
2469b8e80941Smrg                                     shProg);
2470b8e80941Smrg      _mesa_reference_program(ctx, target, prog);
2471b8e80941Smrg      if (stage == MESA_SHADER_VERTEX)
2472b8e80941Smrg         _mesa_update_vertex_processing_mode(ctx);
2473b8e80941Smrg      return;
2474b8e80941Smrg   }
2475b8e80941Smrg
2476b8e80941Smrg}
2477b8e80941Smrg
2478b8e80941Smrg
2479b8e80941Smrg/**
2480b8e80941Smrg * Copy program-specific data generated by linking from the gl_shader_program
2481b8e80941Smrg * object to the gl_program object referred to by the gl_linked_shader.
2482b8e80941Smrg *
2483b8e80941Smrg * This function expects _mesa_reference_program() to have been previously
2484b8e80941Smrg * called setting the gl_linked_shaders program reference.
2485b8e80941Smrg */
2486b8e80941Smrgvoid
2487b8e80941Smrg_mesa_copy_linked_program_data(const struct gl_shader_program *src,
2488b8e80941Smrg                               struct gl_linked_shader *dst_sh)
2489b8e80941Smrg{
2490b8e80941Smrg   assert(dst_sh->Program);
2491b8e80941Smrg
2492b8e80941Smrg   struct gl_program *dst = dst_sh->Program;
2493b8e80941Smrg
2494b8e80941Smrg   dst->info.separate_shader = src->SeparateShader;
2495b8e80941Smrg
2496b8e80941Smrg   switch (dst_sh->Stage) {
2497b8e80941Smrg   case MESA_SHADER_GEOMETRY: {
2498b8e80941Smrg      dst->info.gs.vertices_in = src->Geom.VerticesIn;
2499b8e80941Smrg      dst->info.gs.uses_end_primitive = src->Geom.UsesEndPrimitive;
2500b8e80941Smrg      dst->info.gs.uses_streams = src->Geom.UsesStreams;
2501b8e80941Smrg      break;
2502b8e80941Smrg   }
2503b8e80941Smrg   case MESA_SHADER_FRAGMENT: {
2504b8e80941Smrg      dst->info.fs.depth_layout = src->FragDepthLayout;
2505b8e80941Smrg      break;
2506b8e80941Smrg   }
2507b8e80941Smrg   case MESA_SHADER_COMPUTE: {
2508b8e80941Smrg      dst->info.cs.shared_size = src->Comp.SharedSize;
2509b8e80941Smrg      break;
2510b8e80941Smrg   }
2511b8e80941Smrg   default:
2512b8e80941Smrg      break;
2513b8e80941Smrg   }
2514b8e80941Smrg}
2515b8e80941Smrg
2516b8e80941Smrg/**
2517b8e80941Smrg * ARB_separate_shader_objects: Compile & Link Program
2518b8e80941Smrg */
2519b8e80941SmrgGLuint GLAPIENTRY
2520b8e80941Smrg_mesa_CreateShaderProgramv(GLenum type, GLsizei count,
2521b8e80941Smrg                           const GLchar* const *strings)
2522b8e80941Smrg{
2523b8e80941Smrg   GET_CURRENT_CONTEXT(ctx);
2524b8e80941Smrg
2525b8e80941Smrg   const GLuint shader = create_shader_err(ctx, type, "glCreateShaderProgramv");
2526b8e80941Smrg   GLuint program = 0;
2527b8e80941Smrg
2528b8e80941Smrg   /*
2529b8e80941Smrg    * According to OpenGL 4.5 and OpenGL ES 3.1 standards, section 7.3:
2530b8e80941Smrg    * GL_INVALID_VALUE should be generated if count < 0
2531b8e80941Smrg    */
2532b8e80941Smrg   if (count < 0) {
2533b8e80941Smrg      _mesa_error(ctx, GL_INVALID_VALUE, "glCreateShaderProgram (count < 0)");
2534b8e80941Smrg      return program;
2535b8e80941Smrg   }
2536b8e80941Smrg
2537b8e80941Smrg   if (shader) {
2538b8e80941Smrg      struct gl_shader *sh = _mesa_lookup_shader(ctx, shader);
2539b8e80941Smrg
2540b8e80941Smrg      _mesa_ShaderSource(shader, count, strings, NULL);
2541b8e80941Smrg      _mesa_compile_shader(ctx, sh);
2542b8e80941Smrg
2543b8e80941Smrg      program = create_shader_program(ctx);
2544b8e80941Smrg      if (program) {
2545b8e80941Smrg	 struct gl_shader_program *shProg;
2546b8e80941Smrg	 GLint compiled = GL_FALSE;
2547b8e80941Smrg
2548b8e80941Smrg	 shProg = _mesa_lookup_shader_program(ctx, program);
2549b8e80941Smrg
2550b8e80941Smrg	 shProg->SeparateShader = GL_TRUE;
2551848b8605Smrg
2552848b8605Smrg	 get_shaderiv(ctx, shader, GL_COMPILE_STATUS, &compiled);
2553848b8605Smrg	 if (compiled) {
2554b8e80941Smrg	    attach_shader_err(ctx, program, shader, "glCreateShaderProgramv");
2555b8e80941Smrg	    _mesa_link_program(ctx, shProg);
2556b8e80941Smrg	    detach_shader_error(ctx, program, shader);
2557848b8605Smrg
2558848b8605Smrg#if 0
2559848b8605Smrg	    /* Possibly... */
2560848b8605Smrg	    if (active-user-defined-varyings-in-linked-program) {
2561848b8605Smrg	       append-error-to-info-log;
2562b8e80941Smrg               shProg->data->LinkStatus = LINKING_FAILURE;
2563848b8605Smrg	    }
2564848b8605Smrg#endif
2565848b8605Smrg	 }
2566b8e80941Smrg         if (sh->InfoLog)
2567b8e80941Smrg            ralloc_strcat(&shProg->data->InfoLog, sh->InfoLog);
2568848b8605Smrg      }
2569848b8605Smrg
2570848b8605Smrg      delete_shader(ctx, shader);
2571848b8605Smrg   }
2572848b8605Smrg
2573848b8605Smrg   return program;
2574848b8605Smrg}
2575848b8605Smrg
2576848b8605Smrg
2577848b8605Smrg/**
2578b8e80941Smrg * For GL_ARB_tessellation_shader
2579848b8605Smrg */
2580b8e80941Smrgvoid GLAPIENTRY
2581b8e80941Smrg_mesa_PatchParameteri_no_error(GLenum pname, GLint value)
2582848b8605Smrg{
2583b8e80941Smrg   GET_CURRENT_CONTEXT(ctx);
2584b8e80941Smrg   ctx->TessCtrlProgram.patch_vertices = value;
2585b8e80941Smrg}
2586b8e80941Smrg
2587b8e80941Smrg
2588b8e80941Smrgextern void GLAPIENTRY
2589b8e80941Smrg_mesa_PatchParameteri(GLenum pname, GLint value)
2590b8e80941Smrg{
2591b8e80941Smrg   GET_CURRENT_CONTEXT(ctx);
2592b8e80941Smrg
2593b8e80941Smrg   if (!_mesa_has_tessellation(ctx)) {
2594b8e80941Smrg      _mesa_error(ctx, GL_INVALID_OPERATION, "glPatchParameteri");
2595b8e80941Smrg      return;
2596b8e80941Smrg   }
2597b8e80941Smrg
2598b8e80941Smrg   if (pname != GL_PATCH_VERTICES) {
2599b8e80941Smrg      _mesa_error(ctx, GL_INVALID_ENUM, "glPatchParameteri");
2600b8e80941Smrg      return;
2601b8e80941Smrg   }
2602b8e80941Smrg
2603b8e80941Smrg   if (value <= 0 || value > ctx->Const.MaxPatchVertices) {
2604b8e80941Smrg      _mesa_error(ctx, GL_INVALID_VALUE, "glPatchParameteri");
2605b8e80941Smrg      return;
2606b8e80941Smrg   }
2607b8e80941Smrg
2608b8e80941Smrg   ctx->TessCtrlProgram.patch_vertices = value;
2609b8e80941Smrg}
2610b8e80941Smrg
2611b8e80941Smrg
2612b8e80941Smrgextern void GLAPIENTRY
2613b8e80941Smrg_mesa_PatchParameterfv(GLenum pname, const GLfloat *values)
2614b8e80941Smrg{
2615b8e80941Smrg   GET_CURRENT_CONTEXT(ctx);
2616b8e80941Smrg
2617b8e80941Smrg   if (!_mesa_has_tessellation(ctx)) {
2618b8e80941Smrg      _mesa_error(ctx, GL_INVALID_OPERATION, "glPatchParameterfv");
2619b8e80941Smrg      return;
2620b8e80941Smrg   }
2621b8e80941Smrg
2622b8e80941Smrg   switch(pname) {
2623b8e80941Smrg   case GL_PATCH_DEFAULT_OUTER_LEVEL:
2624b8e80941Smrg      FLUSH_VERTICES(ctx, 0);
2625b8e80941Smrg      memcpy(ctx->TessCtrlProgram.patch_default_outer_level, values,
2626b8e80941Smrg             4 * sizeof(GLfloat));
2627b8e80941Smrg      ctx->NewDriverState |= ctx->DriverFlags.NewDefaultTessLevels;
2628b8e80941Smrg      return;
2629b8e80941Smrg   case GL_PATCH_DEFAULT_INNER_LEVEL:
2630b8e80941Smrg      FLUSH_VERTICES(ctx, 0);
2631b8e80941Smrg      memcpy(ctx->TessCtrlProgram.patch_default_inner_level, values,
2632b8e80941Smrg             2 * sizeof(GLfloat));
2633b8e80941Smrg      ctx->NewDriverState |= ctx->DriverFlags.NewDefaultTessLevels;
2634b8e80941Smrg      return;
2635b8e80941Smrg   default:
2636b8e80941Smrg      _mesa_error(ctx, GL_INVALID_ENUM, "glPatchParameterfv");
2637b8e80941Smrg      return;
2638b8e80941Smrg   }
2639b8e80941Smrg}
2640b8e80941Smrg
2641b8e80941Smrg/**
2642b8e80941Smrg * ARB_shader_subroutine
2643b8e80941Smrg */
2644b8e80941SmrgGLint GLAPIENTRY
2645b8e80941Smrg_mesa_GetSubroutineUniformLocation(GLuint program, GLenum shadertype,
2646b8e80941Smrg                                   const GLchar *name)
2647b8e80941Smrg{
2648b8e80941Smrg   GET_CURRENT_CONTEXT(ctx);
2649b8e80941Smrg   const char *api_name = "glGetSubroutineUniformLocation";
2650b8e80941Smrg   struct gl_shader_program *shProg;
2651b8e80941Smrg   GLenum resource_type;
2652b8e80941Smrg   gl_shader_stage stage;
2653b8e80941Smrg
2654b8e80941Smrg   if (!_mesa_validate_shader_target(ctx, shadertype)) {
2655b8e80941Smrg      _mesa_error(ctx, GL_INVALID_OPERATION, "%s", api_name);
2656b8e80941Smrg      return -1;
2657b8e80941Smrg   }
2658b8e80941Smrg
2659b8e80941Smrg   shProg = _mesa_lookup_shader_program_err(ctx, program, api_name);
2660b8e80941Smrg   if (!shProg)
2661b8e80941Smrg      return -1;
2662b8e80941Smrg
2663b8e80941Smrg   stage = _mesa_shader_enum_to_shader_stage(shadertype);
2664b8e80941Smrg   if (!shProg->_LinkedShaders[stage]) {
2665b8e80941Smrg      _mesa_error(ctx, GL_INVALID_OPERATION, "%s", api_name);
2666b8e80941Smrg      return -1;
2667b8e80941Smrg   }
2668b8e80941Smrg
2669b8e80941Smrg   resource_type = _mesa_shader_stage_to_subroutine_uniform(stage);
2670b8e80941Smrg   return _mesa_program_resource_location(shProg, resource_type, name);
2671b8e80941Smrg}
2672b8e80941Smrg
2673b8e80941SmrgGLuint GLAPIENTRY
2674b8e80941Smrg_mesa_GetSubroutineIndex(GLuint program, GLenum shadertype,
2675b8e80941Smrg                         const GLchar *name)
2676b8e80941Smrg{
2677b8e80941Smrg   GET_CURRENT_CONTEXT(ctx);
2678b8e80941Smrg   const char *api_name = "glGetSubroutineIndex";
2679b8e80941Smrg   struct gl_shader_program *shProg;
2680b8e80941Smrg   struct gl_program_resource *res;
2681b8e80941Smrg   GLenum resource_type;
2682b8e80941Smrg   gl_shader_stage stage;
2683b8e80941Smrg
2684b8e80941Smrg   if (!_mesa_validate_shader_target(ctx, shadertype)) {
2685b8e80941Smrg      _mesa_error(ctx, GL_INVALID_OPERATION, "%s", api_name);
2686b8e80941Smrg      return -1;
2687b8e80941Smrg   }
2688b8e80941Smrg
2689b8e80941Smrg   shProg = _mesa_lookup_shader_program_err(ctx, program, api_name);
2690b8e80941Smrg   if (!shProg)
2691b8e80941Smrg      return -1;
2692b8e80941Smrg
2693b8e80941Smrg   stage = _mesa_shader_enum_to_shader_stage(shadertype);
2694b8e80941Smrg   if (!shProg->_LinkedShaders[stage]) {
2695b8e80941Smrg      _mesa_error(ctx, GL_INVALID_OPERATION, "%s", api_name);
2696b8e80941Smrg      return -1;
2697b8e80941Smrg   }
2698b8e80941Smrg
2699b8e80941Smrg   resource_type = _mesa_shader_stage_to_subroutine(stage);
2700b8e80941Smrg   res = _mesa_program_resource_find_name(shProg, resource_type, name, NULL);
2701b8e80941Smrg   if (!res) {
2702b8e80941Smrg     return -1;
2703b8e80941Smrg   }
2704b8e80941Smrg
2705b8e80941Smrg   return _mesa_program_resource_index(shProg, res);
2706b8e80941Smrg}
2707b8e80941Smrg
2708b8e80941Smrg
2709b8e80941SmrgGLvoid GLAPIENTRY
2710b8e80941Smrg_mesa_GetActiveSubroutineUniformiv(GLuint program, GLenum shadertype,
2711b8e80941Smrg                                   GLuint index, GLenum pname, GLint *values)
2712b8e80941Smrg{
2713b8e80941Smrg   GET_CURRENT_CONTEXT(ctx);
2714b8e80941Smrg   const char *api_name = "glGetActiveSubroutineUniformiv";
2715b8e80941Smrg   struct gl_shader_program *shProg;
2716b8e80941Smrg   struct gl_linked_shader *sh;
2717b8e80941Smrg   gl_shader_stage stage;
2718b8e80941Smrg   struct gl_program_resource *res;
2719b8e80941Smrg   const struct gl_uniform_storage *uni;
2720b8e80941Smrg   GLenum resource_type;
2721b8e80941Smrg   int count, i, j;
2722b8e80941Smrg
2723b8e80941Smrg   if (!_mesa_validate_shader_target(ctx, shadertype)) {
2724b8e80941Smrg      _mesa_error(ctx, GL_INVALID_OPERATION, "%s", api_name);
2725b8e80941Smrg      return;
2726b8e80941Smrg   }
2727b8e80941Smrg
2728b8e80941Smrg   shProg = _mesa_lookup_shader_program_err(ctx, program, api_name);
2729b8e80941Smrg   if (!shProg)
2730b8e80941Smrg      return;
2731b8e80941Smrg
2732b8e80941Smrg   stage = _mesa_shader_enum_to_shader_stage(shadertype);
2733b8e80941Smrg   resource_type = _mesa_shader_stage_to_subroutine_uniform(stage);
2734b8e80941Smrg
2735b8e80941Smrg   sh = shProg->_LinkedShaders[stage];
2736b8e80941Smrg   if (!sh) {
2737b8e80941Smrg      _mesa_error(ctx, GL_INVALID_OPERATION, "%s", api_name);
2738b8e80941Smrg      return;
2739b8e80941Smrg   }
2740b8e80941Smrg
2741b8e80941Smrg   struct gl_program *p = shProg->_LinkedShaders[stage]->Program;
2742b8e80941Smrg   if (index >= p->sh.NumSubroutineUniforms) {
2743b8e80941Smrg      _mesa_error(ctx, GL_INVALID_VALUE, "%s: invalid index greater than GL_ACTIVE_SUBROUTINE_UNIFORMS", api_name);
2744b8e80941Smrg      return;
2745b8e80941Smrg   }
2746b8e80941Smrg
2747b8e80941Smrg   switch (pname) {
2748b8e80941Smrg   case GL_NUM_COMPATIBLE_SUBROUTINES: {
2749b8e80941Smrg      res = _mesa_program_resource_find_index(shProg, resource_type, index);
2750b8e80941Smrg      if (res) {
2751b8e80941Smrg         uni = res->Data;
2752b8e80941Smrg         values[0] = uni->num_compatible_subroutines;
2753b8e80941Smrg      }
2754848b8605Smrg      break;
2755848b8605Smrg   }
2756b8e80941Smrg   case GL_COMPATIBLE_SUBROUTINES: {
2757b8e80941Smrg      res = _mesa_program_resource_find_index(shProg, resource_type, index);
2758b8e80941Smrg      if (res) {
2759b8e80941Smrg         uni = res->Data;
2760b8e80941Smrg         count = 0;
2761b8e80941Smrg         for (i = 0; i < p->sh.NumSubroutineFunctions; i++) {
2762b8e80941Smrg            struct gl_subroutine_function *fn = &p->sh.SubroutineFunctions[i];
2763b8e80941Smrg            for (j = 0; j < fn->num_compat_types; j++) {
2764b8e80941Smrg               if (fn->types[j] == uni->type) {
2765b8e80941Smrg                  values[count++] = i;
2766b8e80941Smrg                  break;
2767b8e80941Smrg               }
2768b8e80941Smrg            }
2769b8e80941Smrg         }
2770b8e80941Smrg      }
2771848b8605Smrg      break;
2772848b8605Smrg   }
2773b8e80941Smrg   case GL_UNIFORM_SIZE:
2774b8e80941Smrg      res = _mesa_program_resource_find_index(shProg, resource_type, index);
2775b8e80941Smrg      if (res) {
2776b8e80941Smrg         uni = res->Data;
2777b8e80941Smrg         values[0] = uni->array_elements ? uni->array_elements : 1;
2778b8e80941Smrg      }
2779848b8605Smrg      break;
2780b8e80941Smrg   case GL_UNIFORM_NAME_LENGTH:
2781b8e80941Smrg      res = _mesa_program_resource_find_index(shProg, resource_type, index);
2782b8e80941Smrg      if (res) {
2783b8e80941Smrg         values[0] = strlen(_mesa_program_resource_name(res)) + 1
2784b8e80941Smrg            + ((_mesa_program_resource_array_size(res) != 0) ? 3 : 0);
2785b8e80941Smrg      }
2786b8e80941Smrg      break;
2787b8e80941Smrg   default:
2788b8e80941Smrg      _mesa_error(ctx, GL_INVALID_OPERATION, "%s", api_name);
2789b8e80941Smrg      return;
2790b8e80941Smrg   }
2791b8e80941Smrg}
2792b8e80941Smrg
2793b8e80941Smrg
2794b8e80941SmrgGLvoid GLAPIENTRY
2795b8e80941Smrg_mesa_GetActiveSubroutineUniformName(GLuint program, GLenum shadertype,
2796b8e80941Smrg                                     GLuint index, GLsizei bufsize,
2797b8e80941Smrg                                     GLsizei *length, GLchar *name)
2798b8e80941Smrg{
2799b8e80941Smrg   GET_CURRENT_CONTEXT(ctx);
2800b8e80941Smrg   const char *api_name = "glGetActiveSubroutineUniformName";
2801b8e80941Smrg   struct gl_shader_program *shProg;
2802b8e80941Smrg   GLenum resource_type;
2803b8e80941Smrg   gl_shader_stage stage;
2804b8e80941Smrg
2805b8e80941Smrg   if (!_mesa_validate_shader_target(ctx, shadertype)) {
2806b8e80941Smrg      _mesa_error(ctx, GL_INVALID_OPERATION, "%s", api_name);
2807b8e80941Smrg      return;
2808b8e80941Smrg   }
2809b8e80941Smrg
2810b8e80941Smrg   shProg = _mesa_lookup_shader_program_err(ctx, program, api_name);
2811b8e80941Smrg   if (!shProg)
2812b8e80941Smrg      return;
2813b8e80941Smrg
2814b8e80941Smrg   stage = _mesa_shader_enum_to_shader_stage(shadertype);
2815b8e80941Smrg   if (!shProg->_LinkedShaders[stage]) {
2816b8e80941Smrg      _mesa_error(ctx, GL_INVALID_OPERATION, "%s", api_name);
2817b8e80941Smrg      return;
2818b8e80941Smrg   }
2819b8e80941Smrg
2820b8e80941Smrg   resource_type = _mesa_shader_stage_to_subroutine_uniform(stage);
2821b8e80941Smrg   /* get program resource name */
2822b8e80941Smrg   _mesa_get_program_resource_name(shProg, resource_type,
2823b8e80941Smrg                                   index, bufsize,
2824b8e80941Smrg                                   length, name, api_name);
2825b8e80941Smrg}
2826b8e80941Smrg
2827b8e80941Smrg
2828b8e80941SmrgGLvoid GLAPIENTRY
2829b8e80941Smrg_mesa_GetActiveSubroutineName(GLuint program, GLenum shadertype,
2830b8e80941Smrg                              GLuint index, GLsizei bufsize,
2831b8e80941Smrg                              GLsizei *length, GLchar *name)
2832b8e80941Smrg{
2833b8e80941Smrg   GET_CURRENT_CONTEXT(ctx);
2834b8e80941Smrg   const char *api_name = "glGetActiveSubroutineName";
2835b8e80941Smrg   struct gl_shader_program *shProg;
2836b8e80941Smrg   GLenum resource_type;
2837b8e80941Smrg   gl_shader_stage stage;
2838b8e80941Smrg
2839b8e80941Smrg   if (!_mesa_validate_shader_target(ctx, shadertype)) {
2840b8e80941Smrg      _mesa_error(ctx, GL_INVALID_OPERATION, "%s", api_name);
2841b8e80941Smrg      return;
2842b8e80941Smrg   }
2843b8e80941Smrg
2844b8e80941Smrg   shProg = _mesa_lookup_shader_program_err(ctx, program, api_name);
2845b8e80941Smrg   if (!shProg)
2846b8e80941Smrg      return;
2847b8e80941Smrg
2848b8e80941Smrg   stage = _mesa_shader_enum_to_shader_stage(shadertype);
2849b8e80941Smrg   if (!shProg->_LinkedShaders[stage]) {
2850b8e80941Smrg      _mesa_error(ctx, GL_INVALID_OPERATION, "%s", api_name);
2851b8e80941Smrg      return;
2852b8e80941Smrg   }
2853b8e80941Smrg   resource_type = _mesa_shader_stage_to_subroutine(stage);
2854b8e80941Smrg   _mesa_get_program_resource_name(shProg, resource_type,
2855b8e80941Smrg                                   index, bufsize,
2856b8e80941Smrg                                   length, name, api_name);
2857b8e80941Smrg}
2858b8e80941Smrg
2859b8e80941SmrgGLvoid GLAPIENTRY
2860b8e80941Smrg_mesa_UniformSubroutinesuiv(GLenum shadertype, GLsizei count,
2861b8e80941Smrg                            const GLuint *indices)
2862b8e80941Smrg{
2863b8e80941Smrg   GET_CURRENT_CONTEXT(ctx);
2864b8e80941Smrg   const char *api_name = "glUniformSubroutinesuiv";
2865b8e80941Smrg   gl_shader_stage stage;
2866b8e80941Smrg   int i;
2867b8e80941Smrg
2868b8e80941Smrg   if (!_mesa_validate_shader_target(ctx, shadertype)) {
2869b8e80941Smrg      _mesa_error(ctx, GL_INVALID_OPERATION, "%s", api_name);
2870b8e80941Smrg      return;
2871b8e80941Smrg   }
2872b8e80941Smrg
2873b8e80941Smrg   stage = _mesa_shader_enum_to_shader_stage(shadertype);
2874b8e80941Smrg   struct gl_program *p = ctx->_Shader->CurrentProgram[stage];
2875b8e80941Smrg   if (!p) {
2876b8e80941Smrg      _mesa_error(ctx, GL_INVALID_OPERATION, "%s", api_name);
2877b8e80941Smrg      return;
2878b8e80941Smrg   }
2879b8e80941Smrg
2880b8e80941Smrg   if (count != p->sh.NumSubroutineUniformRemapTable) {
2881b8e80941Smrg      _mesa_error(ctx, GL_INVALID_VALUE, "%s", api_name);
2882b8e80941Smrg      return;
2883b8e80941Smrg   }
2884b8e80941Smrg
2885b8e80941Smrg   i = 0;
2886b8e80941Smrg   bool flushed = false;
2887b8e80941Smrg   do {
2888b8e80941Smrg      struct gl_uniform_storage *uni = p->sh.SubroutineUniformRemapTable[i];
2889b8e80941Smrg      if (uni == NULL) {
2890b8e80941Smrg         i++;
2891b8e80941Smrg         continue;
2892b8e80941Smrg      }
2893b8e80941Smrg
2894b8e80941Smrg      if (!flushed) {
2895b8e80941Smrg         _mesa_flush_vertices_for_uniforms(ctx, uni);
2896b8e80941Smrg         flushed = true;
2897b8e80941Smrg      }
2898b8e80941Smrg
2899b8e80941Smrg      int uni_count = uni->array_elements ? uni->array_elements : 1;
2900b8e80941Smrg      int j, k, f;
2901b8e80941Smrg
2902b8e80941Smrg      for (j = i; j < i + uni_count; j++) {
2903b8e80941Smrg         struct gl_subroutine_function *subfn = NULL;
2904b8e80941Smrg         if (indices[j] > p->sh.MaxSubroutineFunctionIndex) {
2905b8e80941Smrg            _mesa_error(ctx, GL_INVALID_VALUE, "%s", api_name);
2906b8e80941Smrg            return;
2907b8e80941Smrg         }
2908b8e80941Smrg
2909b8e80941Smrg         for (f = 0; f < p->sh.NumSubroutineFunctions; f++) {
2910b8e80941Smrg            if (p->sh.SubroutineFunctions[f].index == indices[j])
2911b8e80941Smrg               subfn = &p->sh.SubroutineFunctions[f];
2912b8e80941Smrg         }
2913b8e80941Smrg
2914b8e80941Smrg         if (!subfn) {
2915b8e80941Smrg            continue;
2916b8e80941Smrg         }
2917b8e80941Smrg
2918b8e80941Smrg         for (k = 0; k < subfn->num_compat_types; k++) {
2919b8e80941Smrg            if (subfn->types[k] == uni->type)
2920b8e80941Smrg               break;
2921b8e80941Smrg         }
2922b8e80941Smrg         if (k == subfn->num_compat_types) {
2923b8e80941Smrg            _mesa_error(ctx, GL_INVALID_OPERATION, "%s", api_name);
2924b8e80941Smrg            return;
2925b8e80941Smrg         }
2926b8e80941Smrg
2927b8e80941Smrg         ctx->SubroutineIndex[p->info.stage].IndexPtr[j] = indices[j];
2928b8e80941Smrg      }
2929b8e80941Smrg      i += uni_count;
2930b8e80941Smrg   } while(i < count);
2931b8e80941Smrg}
2932b8e80941Smrg
2933b8e80941Smrg
2934b8e80941SmrgGLvoid GLAPIENTRY
2935b8e80941Smrg_mesa_GetUniformSubroutineuiv(GLenum shadertype, GLint location,
2936b8e80941Smrg                              GLuint *params)
2937b8e80941Smrg{
2938b8e80941Smrg   GET_CURRENT_CONTEXT(ctx);
2939b8e80941Smrg   const char *api_name = "glGetUniformSubroutineuiv";
2940b8e80941Smrg   gl_shader_stage stage;
2941b8e80941Smrg
2942b8e80941Smrg   if (!_mesa_validate_shader_target(ctx, shadertype)) {
2943b8e80941Smrg      _mesa_error(ctx, GL_INVALID_OPERATION, "%s", api_name);
2944b8e80941Smrg      return;
2945b8e80941Smrg   }
2946b8e80941Smrg
2947b8e80941Smrg   stage = _mesa_shader_enum_to_shader_stage(shadertype);
2948b8e80941Smrg   struct gl_program *p = ctx->_Shader->CurrentProgram[stage];
2949b8e80941Smrg   if (!p) {
2950b8e80941Smrg      _mesa_error(ctx, GL_INVALID_OPERATION, "%s", api_name);
2951b8e80941Smrg      return;
2952b8e80941Smrg   }
2953b8e80941Smrg
2954b8e80941Smrg   if (location >= p->sh.NumSubroutineUniformRemapTable) {
2955b8e80941Smrg      _mesa_error(ctx, GL_INVALID_VALUE, "%s", api_name);
2956b8e80941Smrg      return;
2957b8e80941Smrg   }
2958b8e80941Smrg
2959b8e80941Smrg   *params = ctx->SubroutineIndex[p->info.stage].IndexPtr[location];
2960b8e80941Smrg}
2961b8e80941Smrg
2962b8e80941Smrg
2963b8e80941SmrgGLvoid GLAPIENTRY
2964b8e80941Smrg_mesa_GetProgramStageiv(GLuint program, GLenum shadertype,
2965b8e80941Smrg                        GLenum pname, GLint *values)
2966b8e80941Smrg{
2967b8e80941Smrg   GET_CURRENT_CONTEXT(ctx);
2968b8e80941Smrg   const char *api_name = "glGetProgramStageiv";
2969b8e80941Smrg   struct gl_shader_program *shProg;
2970b8e80941Smrg   struct gl_linked_shader *sh;
2971b8e80941Smrg   gl_shader_stage stage;
2972b8e80941Smrg
2973b8e80941Smrg   if (!_mesa_validate_shader_target(ctx, shadertype)) {
2974b8e80941Smrg      _mesa_error(ctx, GL_INVALID_OPERATION, "%s", api_name);
2975b8e80941Smrg      return;
2976b8e80941Smrg   }
2977b8e80941Smrg
2978b8e80941Smrg   shProg = _mesa_lookup_shader_program_err(ctx, program, api_name);
2979b8e80941Smrg   if (!shProg)
2980b8e80941Smrg      return;
2981b8e80941Smrg
2982b8e80941Smrg   stage = _mesa_shader_enum_to_shader_stage(shadertype);
2983b8e80941Smrg   sh = shProg->_LinkedShaders[stage];
2984b8e80941Smrg
2985b8e80941Smrg   /* ARB_shader_subroutine doesn't ask the program to be linked, or list any
2986b8e80941Smrg    * INVALID_OPERATION in the case of not be linked.
2987b8e80941Smrg    *
2988b8e80941Smrg    * And for some pnames, like GL_ACTIVE_SUBROUTINE_UNIFORMS, you can ask the
2989b8e80941Smrg    * same info using other specs (ARB_program_interface_query), without the
2990b8e80941Smrg    * need of the program to be linked, being the value for that case 0.
2991b8e80941Smrg    *
2992b8e80941Smrg    * But at the same time, some other methods require the program to be
2993b8e80941Smrg    * linked for pname related to locations, so it would be inconsistent to
2994b8e80941Smrg    * not do the same here. So we are:
2995b8e80941Smrg    *   * Return GL_INVALID_OPERATION if not linked only for locations.
2996b8e80941Smrg    *   * Setting a default value of 0, to be returned if not linked.
2997b8e80941Smrg    */
2998b8e80941Smrg   if (!sh) {
2999b8e80941Smrg      values[0] = 0;
3000b8e80941Smrg      if (pname == GL_ACTIVE_SUBROUTINE_UNIFORM_LOCATIONS) {
3001b8e80941Smrg         _mesa_error(ctx, GL_INVALID_OPERATION, "%s", api_name);
3002b8e80941Smrg      }
3003b8e80941Smrg      return;
3004848b8605Smrg   }
3005b8e80941Smrg
3006b8e80941Smrg   struct gl_program *p = sh->Program;
3007b8e80941Smrg   switch (pname) {
3008b8e80941Smrg   case GL_ACTIVE_SUBROUTINES:
3009b8e80941Smrg      values[0] = p->sh.NumSubroutineFunctions;
3010b8e80941Smrg      break;
3011b8e80941Smrg   case GL_ACTIVE_SUBROUTINE_UNIFORM_LOCATIONS:
3012b8e80941Smrg      values[0] = p->sh.NumSubroutineUniformRemapTable;
3013b8e80941Smrg      break;
3014b8e80941Smrg   case GL_ACTIVE_SUBROUTINE_UNIFORMS:
3015b8e80941Smrg      values[0] = p->sh.NumSubroutineUniforms;
3016848b8605Smrg      break;
3017b8e80941Smrg   case GL_ACTIVE_SUBROUTINE_MAX_LENGTH:
3018b8e80941Smrg   {
3019b8e80941Smrg      unsigned i;
3020b8e80941Smrg      GLint max_len = 0;
3021b8e80941Smrg      GLenum resource_type;
3022b8e80941Smrg      struct gl_program_resource *res;
3023b8e80941Smrg
3024b8e80941Smrg      resource_type = _mesa_shader_stage_to_subroutine(stage);
3025b8e80941Smrg      for (i = 0; i < p->sh.NumSubroutineFunctions; i++) {
3026b8e80941Smrg         res = _mesa_program_resource_find_index(shProg, resource_type, i);
3027b8e80941Smrg         if (res) {
3028b8e80941Smrg            const GLint len = strlen(_mesa_program_resource_name(res)) + 1;
3029b8e80941Smrg            if (len > max_len)
3030b8e80941Smrg               max_len = len;
3031b8e80941Smrg         }
3032b8e80941Smrg      }
3033b8e80941Smrg      values[0] = max_len;
3034b8e80941Smrg      break;
3035b8e80941Smrg   }
3036b8e80941Smrg   case GL_ACTIVE_SUBROUTINE_UNIFORM_MAX_LENGTH:
3037b8e80941Smrg   {
3038b8e80941Smrg      unsigned i;
3039b8e80941Smrg      GLint max_len = 0;
3040b8e80941Smrg      GLenum resource_type;
3041b8e80941Smrg      struct gl_program_resource *res;
3042b8e80941Smrg
3043b8e80941Smrg      resource_type = _mesa_shader_stage_to_subroutine_uniform(stage);
3044b8e80941Smrg      for (i = 0; i < p->sh.NumSubroutineUniformRemapTable; i++) {
3045b8e80941Smrg         res = _mesa_program_resource_find_index(shProg, resource_type, i);
3046b8e80941Smrg         if (res) {
3047b8e80941Smrg            const GLint len = strlen(_mesa_program_resource_name(res)) + 1
3048b8e80941Smrg               + ((_mesa_program_resource_array_size(res) != 0) ? 3 : 0);
3049b8e80941Smrg
3050b8e80941Smrg            if (len > max_len)
3051b8e80941Smrg               max_len = len;
3052b8e80941Smrg         }
3053b8e80941Smrg      }
3054b8e80941Smrg      values[0] = max_len;
3055b8e80941Smrg      break;
3056b8e80941Smrg   }
3057848b8605Smrg   default:
3058b8e80941Smrg      _mesa_error(ctx, GL_INVALID_ENUM, "%s", api_name);
3059b8e80941Smrg      values[0] = -1;
3060848b8605Smrg      break;
3061848b8605Smrg   }
3062848b8605Smrg}
3063848b8605Smrg
3064b8e80941Smrgstatic int
3065b8e80941Smrgfind_compat_subroutine(struct gl_program *p, const struct glsl_type *type)
3066848b8605Smrg{
3067b8e80941Smrg   int i, j;
3068b8e80941Smrg
3069b8e80941Smrg   for (i = 0; i < p->sh.NumSubroutineFunctions; i++) {
3070b8e80941Smrg      struct gl_subroutine_function *fn = &p->sh.SubroutineFunctions[i];
3071b8e80941Smrg      for (j = 0; j < fn->num_compat_types; j++) {
3072b8e80941Smrg         if (fn->types[j] == type)
3073b8e80941Smrg            return i;
3074b8e80941Smrg      }
3075b8e80941Smrg   }
3076b8e80941Smrg   return 0;
3077b8e80941Smrg}
3078b8e80941Smrg
3079b8e80941Smrgstatic void
3080b8e80941Smrg_mesa_shader_write_subroutine_index(struct gl_context *ctx,
3081b8e80941Smrg                                    struct gl_program *p)
3082b8e80941Smrg{
3083b8e80941Smrg   int i, j;
3084b8e80941Smrg
3085b8e80941Smrg   if (p->sh.NumSubroutineUniformRemapTable == 0)
3086b8e80941Smrg      return;
3087848b8605Smrg
3088b8e80941Smrg   i = 0;
3089b8e80941Smrg   do {
3090b8e80941Smrg      struct gl_uniform_storage *uni = p->sh.SubroutineUniformRemapTable[i];
3091b8e80941Smrg      int uni_count;
3092b8e80941Smrg      int val;
3093b8e80941Smrg
3094b8e80941Smrg      if (!uni) {
3095b8e80941Smrg         i++;
3096b8e80941Smrg         continue;
3097b8e80941Smrg      }
3098b8e80941Smrg
3099b8e80941Smrg      uni_count = uni->array_elements ? uni->array_elements : 1;
3100b8e80941Smrg      for (j = 0; j < uni_count; j++) {
3101b8e80941Smrg         val = ctx->SubroutineIndex[p->info.stage].IndexPtr[i + j];
3102b8e80941Smrg         memcpy(&uni->storage[j], &val, sizeof(int));
3103b8e80941Smrg      }
3104b8e80941Smrg
3105b8e80941Smrg      _mesa_propagate_uniforms_to_driver_storage(uni, 0, uni_count);
3106b8e80941Smrg      i += uni_count;
3107b8e80941Smrg   } while(i < p->sh.NumSubroutineUniformRemapTable);
3108b8e80941Smrg}
3109b8e80941Smrg
3110b8e80941Smrgvoid
3111b8e80941Smrg_mesa_shader_write_subroutine_indices(struct gl_context *ctx,
3112b8e80941Smrg                                      gl_shader_stage stage)
3113b8e80941Smrg{
3114b8e80941Smrg   if (ctx->_Shader->CurrentProgram[stage])
3115b8e80941Smrg      _mesa_shader_write_subroutine_index(ctx,
3116b8e80941Smrg                                          ctx->_Shader->CurrentProgram[stage]);
3117b8e80941Smrg}
3118b8e80941Smrg
3119b8e80941Smrgvoid
3120b8e80941Smrg_mesa_program_init_subroutine_defaults(struct gl_context *ctx,
3121b8e80941Smrg                                       struct gl_program *p)
3122b8e80941Smrg{
3123b8e80941Smrg   assert(p);
3124b8e80941Smrg
3125b8e80941Smrg   struct gl_subroutine_index_binding *binding = &ctx->SubroutineIndex[p->info.stage];
3126b8e80941Smrg   if (binding->NumIndex != p->sh.NumSubroutineUniformRemapTable) {
3127b8e80941Smrg      binding->IndexPtr = realloc(binding->IndexPtr,
3128b8e80941Smrg                                  p->sh.NumSubroutineUniformRemapTable * (sizeof(GLuint)));
3129b8e80941Smrg      binding->NumIndex = p->sh.NumSubroutineUniformRemapTable;
3130b8e80941Smrg   }
3131b8e80941Smrg
3132b8e80941Smrg   for (int i = 0; i < p->sh.NumSubroutineUniformRemapTable; i++) {
3133b8e80941Smrg      struct gl_uniform_storage *uni = p->sh.SubroutineUniformRemapTable[i];
3134b8e80941Smrg
3135b8e80941Smrg      if (!uni)
3136b8e80941Smrg         continue;
3137b8e80941Smrg
3138b8e80941Smrg      binding->IndexPtr[i] = find_compat_subroutine(p, uni->type);
3139b8e80941Smrg   }
3140848b8605Smrg}
3141