13464ebd5Sriastradh/*
23464ebd5Sriastradh * Mesa 3-D graphics library
33464ebd5Sriastradh *
43464ebd5Sriastradh * Copyright (C) 2004-2008  Brian Paul   All Rights Reserved.
53464ebd5Sriastradh * Copyright (C) 2009-2010  VMware, Inc.  All Rights Reserved.
63464ebd5Sriastradh *
73464ebd5Sriastradh * Permission is hereby granted, free of charge, to any person obtaining a
83464ebd5Sriastradh * copy of this software and associated documentation files (the "Software"),
93464ebd5Sriastradh * to deal in the Software without restriction, including without limitation
103464ebd5Sriastradh * the rights to use, copy, modify, merge, publish, distribute, sublicense,
113464ebd5Sriastradh * and/or sell copies of the Software, and to permit persons to whom the
123464ebd5Sriastradh * Software is furnished to do so, subject to the following conditions:
133464ebd5Sriastradh *
143464ebd5Sriastradh * The above copyright notice and this permission notice shall be included
153464ebd5Sriastradh * in all copies or substantial portions of the Software.
163464ebd5Sriastradh *
173464ebd5Sriastradh * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
183464ebd5Sriastradh * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
193464ebd5Sriastradh * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
20af69d88dSmrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
21af69d88dSmrg * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
22af69d88dSmrg * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
23af69d88dSmrg * OTHER DEALINGS IN THE SOFTWARE.
243464ebd5Sriastradh */
253464ebd5Sriastradh
263464ebd5Sriastradh/**
273464ebd5Sriastradh * \file shaderapi.c
283464ebd5Sriastradh * \author Brian Paul
293464ebd5Sriastradh *
303464ebd5Sriastradh * Implementation of GLSL-related API functions.
313464ebd5Sriastradh * The glUniform* functions are in uniforms.c
323464ebd5Sriastradh */
333464ebd5Sriastradh
343464ebd5Sriastradh
357ec681f3Smrg#include <errno.h>
3601e04c3fSmrg#include <stdbool.h>
3701e04c3fSmrg#include <c99_alloca.h>
387ec681f3Smrg
393464ebd5Sriastradh#include "main/glheader.h"
403464ebd5Sriastradh#include "main/context.h"
417ec681f3Smrg#include "draw_validate.h"
423464ebd5Sriastradh#include "main/enums.h"
4301e04c3fSmrg#include "main/glspirv.h"
443464ebd5Sriastradh#include "main/hash.h"
453464ebd5Sriastradh#include "main/mtypes.h"
46af69d88dSmrg#include "main/pipelineobj.h"
4701e04c3fSmrg#include "main/program_binary.h"
483464ebd5Sriastradh#include "main/shaderapi.h"
493464ebd5Sriastradh#include "main/shaderobj.h"
5001e04c3fSmrg#include "main/state.h"
51af69d88dSmrg#include "main/transformfeedback.h"
52af69d88dSmrg#include "main/uniforms.h"
537ec681f3Smrg#include "compiler/glsl/builtin_functions.h"
5401e04c3fSmrg#include "compiler/glsl/glsl_parser_extras.h"
5501e04c3fSmrg#include "compiler/glsl/ir.h"
5601e04c3fSmrg#include "compiler/glsl/ir_uniform.h"
5701e04c3fSmrg#include "compiler/glsl/program.h"
583464ebd5Sriastradh#include "program/program.h"
59af69d88dSmrg#include "program/prog_print.h"
603464ebd5Sriastradh#include "program/prog_parameter.h"
61af69d88dSmrg#include "util/ralloc.h"
62af69d88dSmrg#include "util/hash_table.h"
6301e04c3fSmrg#include "util/mesa-sha1.h"
6401e04c3fSmrg#include "util/crc32.h"
657ec681f3Smrg#include "util/os_file.h"
667ec681f3Smrg#include "util/simple_list.h"
677ec681f3Smrg#include "util/u_process.h"
687ec681f3Smrg#include "util/u_string.h"
697ec681f3Smrg
707ec681f3Smrg#ifdef ENABLE_SHADER_CACHE
717ec681f3Smrg#if CUSTOM_SHADER_REPLACEMENT
727ec681f3Smrg#include "shader_replacement.h"
737ec681f3Smrg/* shader_replacement.h must declare a variable like this:
747ec681f3Smrg
757ec681f3Smrg   struct _shader_replacement {
767ec681f3Smrg      // process name. If null, only sha1 is used to match
777ec681f3Smrg      const char *app;
787ec681f3Smrg      // original glsl shader sha1
797ec681f3Smrg      const char *sha1;
807ec681f3Smrg      // shader stage
817ec681f3Smrg      gl_shader_stage stage;
827ec681f3Smrg      ... any other information ...
837ec681f3Smrg   };
847ec681f3Smrg   struct _shader_replacement shader_replacements[...];
857ec681f3Smrg
867ec681f3Smrg   And a method to load a given replacement and return the new
877ec681f3Smrg   glsl source:
887ec681f3Smrg
897ec681f3Smrg   char* load_shader_replacement(struct _shader_replacement *repl);
907ec681f3Smrg
917ec681f3Smrg   shader_replacement.h can be generated at build time, or copied
927ec681f3Smrg   from an external folder, or any other method.
937ec681f3Smrg*/
947ec681f3Smrg#else
957ec681f3Smrgstruct _shader_replacement {
967ec681f3Smrg   const char *app;
977ec681f3Smrg   const char *sha1;
987ec681f3Smrg   gl_shader_stage stage;
997ec681f3Smrg};
1007ec681f3Smrgstruct _shader_replacement shader_replacements[0];
1017ec681f3Smrgstatic char* load_shader_replacement(struct _shader_replacement *repl)
1027ec681f3Smrg{
1037ec681f3Smrg   return NULL;
1047ec681f3Smrg}
1057ec681f3Smrg#endif
1067ec681f3Smrg#endif
1073464ebd5Sriastradh
1083464ebd5Sriastradh/**
1093464ebd5Sriastradh * Return mask of GLSL_x flags by examining the MESA_GLSL env var.
1103464ebd5Sriastradh */
111af69d88dSmrgGLbitfield
112af69d88dSmrg_mesa_get_shader_flags(void)
1133464ebd5Sriastradh{
1143464ebd5Sriastradh   GLbitfield flags = 0x0;
11501e04c3fSmrg   const char *env = getenv("MESA_GLSL");
1163464ebd5Sriastradh
1173464ebd5Sriastradh   if (env) {
118af69d88dSmrg      if (strstr(env, "dump_on_error"))
119af69d88dSmrg         flags |= GLSL_DUMP_ON_ERROR;
1207ec681f3Smrg#ifndef CUSTOM_SHADER_REPLACEMENT
121af69d88dSmrg      else if (strstr(env, "dump"))
1223464ebd5Sriastradh         flags |= GLSL_DUMP;
1233464ebd5Sriastradh      if (strstr(env, "log"))
1243464ebd5Sriastradh         flags |= GLSL_LOG;
1257ec681f3Smrg#endif
12601e04c3fSmrg      if (strstr(env, "cache_fb"))
12701e04c3fSmrg         flags |= GLSL_CACHE_FALLBACK;
12801e04c3fSmrg      if (strstr(env, "cache_info"))
12901e04c3fSmrg         flags |= GLSL_CACHE_INFO;
1303464ebd5Sriastradh      if (strstr(env, "nopvert"))
1313464ebd5Sriastradh         flags |= GLSL_NOP_VERT;
1323464ebd5Sriastradh      if (strstr(env, "nopfrag"))
1333464ebd5Sriastradh         flags |= GLSL_NOP_FRAG;
1343464ebd5Sriastradh      if (strstr(env, "uniform"))
1353464ebd5Sriastradh         flags |= GLSL_UNIFORMS;
1363464ebd5Sriastradh      if (strstr(env, "useprog"))
1373464ebd5Sriastradh         flags |= GLSL_USE_PROG;
138af69d88dSmrg      if (strstr(env, "errors"))
139af69d88dSmrg         flags |= GLSL_REPORT_ERRORS;
1403464ebd5Sriastradh   }
1413464ebd5Sriastradh
1423464ebd5Sriastradh   return flags;
1433464ebd5Sriastradh}
1443464ebd5Sriastradh
14501e04c3fSmrg/**
14601e04c3fSmrg * Memoized version of getenv("MESA_SHADER_CAPTURE_PATH").
14701e04c3fSmrg */
14801e04c3fSmrgconst char *
14901e04c3fSmrg_mesa_get_shader_capture_path(void)
15001e04c3fSmrg{
15101e04c3fSmrg   static bool read_env_var = false;
15201e04c3fSmrg   static const char *path = NULL;
15301e04c3fSmrg
15401e04c3fSmrg   if (!read_env_var) {
15501e04c3fSmrg      path = getenv("MESA_SHADER_CAPTURE_PATH");
15601e04c3fSmrg      read_env_var = true;
15701e04c3fSmrg   }
15801e04c3fSmrg
15901e04c3fSmrg   return path;
16001e04c3fSmrg}
1613464ebd5Sriastradh
1623464ebd5Sriastradh/**
1633464ebd5Sriastradh * Initialize context's shader state.
1643464ebd5Sriastradh */
1653464ebd5Sriastradhvoid
1663464ebd5Sriastradh_mesa_init_shader_state(struct gl_context *ctx)
1673464ebd5Sriastradh{
1683464ebd5Sriastradh   /* Device drivers may override these to control what kind of instructions
1693464ebd5Sriastradh    * are generated by the GLSL compiler.
1703464ebd5Sriastradh    */
1713464ebd5Sriastradh   struct gl_shader_compiler_options options;
172af69d88dSmrg   gl_shader_stage sh;
17301e04c3fSmrg   int i;
1743464ebd5Sriastradh
1753464ebd5Sriastradh   memset(&options, 0, sizeof(options));
1763464ebd5Sriastradh   options.MaxUnrollIterations = 32;
177af69d88dSmrg   options.MaxIfDepth = UINT_MAX;
1783464ebd5Sriastradh
179af69d88dSmrg   for (sh = 0; sh < MESA_SHADER_STAGES; ++sh)
180af69d88dSmrg      memcpy(&ctx->Const.ShaderCompilerOptions[sh], &options, sizeof(options));
1813464ebd5Sriastradh
182af69d88dSmrg   ctx->Shader.Flags = _mesa_get_shader_flags();
183af69d88dSmrg
18401e04c3fSmrg   if (ctx->Shader.Flags != 0)
18501e04c3fSmrg      ctx->Const.GenerateTemporaryNames = true;
18601e04c3fSmrg
187af69d88dSmrg   /* Extended for ARB_separate_shader_objects */
188af69d88dSmrg   ctx->Shader.RefCount = 1;
18901e04c3fSmrg   ctx->TessCtrlProgram.patch_vertices = 3;
19001e04c3fSmrg   for (i = 0; i < 4; ++i)
19101e04c3fSmrg      ctx->TessCtrlProgram.patch_default_outer_level[i] = 1.0;
19201e04c3fSmrg   for (i = 0; i < 2; ++i)
19301e04c3fSmrg      ctx->TessCtrlProgram.patch_default_inner_level[i] = 1.0;
1943464ebd5Sriastradh}
1953464ebd5Sriastradh
1963464ebd5Sriastradh
1973464ebd5Sriastradh/**
1983464ebd5Sriastradh * Free the per-context shader-related state.
1993464ebd5Sriastradh */
2003464ebd5Sriastradhvoid
2013464ebd5Sriastradh_mesa_free_shader_state(struct gl_context *ctx)
2023464ebd5Sriastradh{
20301e04c3fSmrg   for (int i = 0; i < MESA_SHADER_STAGES; i++) {
20401e04c3fSmrg      _mesa_reference_program(ctx, &ctx->Shader.CurrentProgram[i], NULL);
20501e04c3fSmrg      _mesa_reference_shader_program(ctx,
20601e04c3fSmrg                                     &ctx->Shader.ReferencedPrograms[i],
207af69d88dSmrg                                     NULL);
208b9abf16eSmaya      free(ctx->SubroutineIndex[i].IndexPtr);
209b9abf16eSmaya      ctx->SubroutineIndex[i].IndexPtr = NULL;
210af69d88dSmrg   }
2113464ebd5Sriastradh   _mesa_reference_shader_program(ctx, &ctx->Shader.ActiveProgram, NULL);
2123464ebd5Sriastradh
213af69d88dSmrg   /* Extended for ARB_separate_shader_objects */
214af69d88dSmrg   _mesa_reference_pipeline_object(ctx, &ctx->_Shader, NULL);
2153464ebd5Sriastradh
216af69d88dSmrg   assert(ctx->Shader.RefCount == 1);
2173464ebd5Sriastradh}
2183464ebd5Sriastradh
2193464ebd5Sriastradh
2203464ebd5Sriastradh/**
2213464ebd5Sriastradh * Copy string from <src> to <dst>, up to maxLength characters, returning
2223464ebd5Sriastradh * length of <dst> in <length>.
2233464ebd5Sriastradh * \param src  the strings source
2243464ebd5Sriastradh * \param maxLength  max chars to copy
2253464ebd5Sriastradh * \param length  returns number of chars copied
2263464ebd5Sriastradh * \param dst  the string destination
2273464ebd5Sriastradh */
2283464ebd5Sriastradhvoid
2293464ebd5Sriastradh_mesa_copy_string(GLchar *dst, GLsizei maxLength,
2303464ebd5Sriastradh                  GLsizei *length, const GLchar *src)
2313464ebd5Sriastradh{
2323464ebd5Sriastradh   GLsizei len;
2333464ebd5Sriastradh   for (len = 0; len < maxLength - 1 && src && src[len]; len++)
2343464ebd5Sriastradh      dst[len] = src[len];
2353464ebd5Sriastradh   if (maxLength > 0)
2363464ebd5Sriastradh      dst[len] = 0;
2373464ebd5Sriastradh   if (length)
2383464ebd5Sriastradh      *length = len;
2393464ebd5Sriastradh}
2403464ebd5Sriastradh
2413464ebd5Sriastradh
2423464ebd5Sriastradh
2433464ebd5Sriastradh/**
2443464ebd5Sriastradh * Confirm that the a shader type is valid and supported by the implementation
2453464ebd5Sriastradh *
2463464ebd5Sriastradh * \param ctx   Current GL context
2473464ebd5Sriastradh * \param type  Shader target
2483464ebd5Sriastradh *
2493464ebd5Sriastradh */
250af69d88dSmrgbool
251af69d88dSmrg_mesa_validate_shader_target(const struct gl_context *ctx, GLenum type)
252af69d88dSmrg{
253af69d88dSmrg   /* Note: when building built-in GLSL functions, this function may be
254af69d88dSmrg    * invoked with ctx == NULL.  In that case, we can only validate that it's
255af69d88dSmrg    * a shader target we recognize, not that it's supported in the current
256af69d88dSmrg    * context.  But that's fine--we don't need any further validation than
257af69d88dSmrg    * that when building built-in GLSL functions.
258af69d88dSmrg    */
259af69d88dSmrg
2603464ebd5Sriastradh   switch (type) {
2613464ebd5Sriastradh   case GL_FRAGMENT_SHADER:
262af69d88dSmrg      return ctx == NULL || ctx->Extensions.ARB_fragment_shader;
2633464ebd5Sriastradh   case GL_VERTEX_SHADER:
264af69d88dSmrg      return ctx == NULL || ctx->Extensions.ARB_vertex_shader;
2653464ebd5Sriastradh   case GL_GEOMETRY_SHADER_ARB:
266af69d88dSmrg      return ctx == NULL || _mesa_has_geometry_shaders(ctx);
26701e04c3fSmrg   case GL_TESS_CONTROL_SHADER:
26801e04c3fSmrg   case GL_TESS_EVALUATION_SHADER:
26901e04c3fSmrg      return ctx == NULL || _mesa_has_tessellation(ctx);
270af69d88dSmrg   case GL_COMPUTE_SHADER:
27101e04c3fSmrg      return ctx == NULL || _mesa_has_compute_shaders(ctx);
2723464ebd5Sriastradh   default:
2733464ebd5Sriastradh      return false;
2743464ebd5Sriastradh   }
2753464ebd5Sriastradh}
2763464ebd5Sriastradh
2773464ebd5Sriastradh
2783464ebd5Sriastradhstatic GLboolean
2793464ebd5Sriastradhis_program(struct gl_context *ctx, GLuint name)
2803464ebd5Sriastradh{
2813464ebd5Sriastradh   struct gl_shader_program *shProg = _mesa_lookup_shader_program(ctx, name);
2823464ebd5Sriastradh   return shProg ? GL_TRUE : GL_FALSE;
2833464ebd5Sriastradh}
2843464ebd5Sriastradh
2853464ebd5Sriastradh
2863464ebd5Sriastradhstatic GLboolean
2873464ebd5Sriastradhis_shader(struct gl_context *ctx, GLuint name)
2883464ebd5Sriastradh{
2893464ebd5Sriastradh   struct gl_shader *shader = _mesa_lookup_shader(ctx, name);
2903464ebd5Sriastradh   return shader ? GL_TRUE : GL_FALSE;
2913464ebd5Sriastradh}
2923464ebd5Sriastradh
2933464ebd5Sriastradh
2943464ebd5Sriastradh/**
2953464ebd5Sriastradh * Attach shader to a shader program.
2963464ebd5Sriastradh */
2973464ebd5Sriastradhstatic void
29801e04c3fSmrgattach_shader(struct gl_context *ctx, struct gl_shader_program *shProg,
29901e04c3fSmrg              struct gl_shader *sh)
30001e04c3fSmrg{
30101e04c3fSmrg   GLuint n = shProg->NumShaders;
30201e04c3fSmrg
30301e04c3fSmrg   shProg->Shaders = realloc(shProg->Shaders,
30401e04c3fSmrg                             (n + 1) * sizeof(struct gl_shader *));
30501e04c3fSmrg   if (!shProg->Shaders) {
30601e04c3fSmrg      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glAttachShader");
30701e04c3fSmrg      return;
30801e04c3fSmrg   }
30901e04c3fSmrg
31001e04c3fSmrg   /* append */
31101e04c3fSmrg   shProg->Shaders[n] = NULL; /* since realloc() didn't zero the new space */
31201e04c3fSmrg   _mesa_reference_shader(ctx, &shProg->Shaders[n], sh);
31301e04c3fSmrg   shProg->NumShaders++;
31401e04c3fSmrg}
31501e04c3fSmrg
31601e04c3fSmrgstatic void
31701e04c3fSmrgattach_shader_err(struct gl_context *ctx, GLuint program, GLuint shader,
31801e04c3fSmrg                  const char *caller)
3193464ebd5Sriastradh{
3203464ebd5Sriastradh   struct gl_shader_program *shProg;
3213464ebd5Sriastradh   struct gl_shader *sh;
3223464ebd5Sriastradh   GLuint i, n;
3233464ebd5Sriastradh
324af69d88dSmrg   const bool same_type_disallowed = _mesa_is_gles(ctx);
325af69d88dSmrg
32601e04c3fSmrg   shProg = _mesa_lookup_shader_program_err(ctx, program, caller);
3273464ebd5Sriastradh   if (!shProg)
3283464ebd5Sriastradh      return;
3293464ebd5Sriastradh
33001e04c3fSmrg   sh = _mesa_lookup_shader_err(ctx, shader, caller);
3313464ebd5Sriastradh   if (!sh) {
3323464ebd5Sriastradh      return;
3333464ebd5Sriastradh   }
3343464ebd5Sriastradh
3353464ebd5Sriastradh   n = shProg->NumShaders;
3363464ebd5Sriastradh   for (i = 0; i < n; i++) {
3373464ebd5Sriastradh      if (shProg->Shaders[i] == sh) {
3383464ebd5Sriastradh         /* The shader is already attched to this program.  The
3393464ebd5Sriastradh          * GL_ARB_shader_objects spec says:
3403464ebd5Sriastradh          *
3413464ebd5Sriastradh          *     "The error INVALID_OPERATION is generated by AttachObjectARB
3423464ebd5Sriastradh          *     if <obj> is already attached to <containerObj>."
3433464ebd5Sriastradh          */
34401e04c3fSmrg         _mesa_error(ctx, GL_INVALID_OPERATION, "%s", caller);
3453464ebd5Sriastradh         return;
346af69d88dSmrg      } else if (same_type_disallowed &&
34701e04c3fSmrg                 shProg->Shaders[i]->Stage == sh->Stage) {
348af69d88dSmrg        /* Shader with the same type is already attached to this program,
349af69d88dSmrg         * OpenGL ES 2.0 and 3.0 specs say:
350af69d88dSmrg         *
351af69d88dSmrg         *      "Multiple shader objects of the same type may not be attached
352af69d88dSmrg         *      to a single program object. [...] The error INVALID_OPERATION
353af69d88dSmrg         *      is generated if [...] another shader object of the same type
354af69d88dSmrg         *      as shader is already attached to program."
355af69d88dSmrg         */
35601e04c3fSmrg         _mesa_error(ctx, GL_INVALID_OPERATION, "%s", caller);
357af69d88dSmrg         return;
3583464ebd5Sriastradh      }
3593464ebd5Sriastradh   }
3603464ebd5Sriastradh
36101e04c3fSmrg   attach_shader(ctx, shProg, sh);
3623464ebd5Sriastradh}
3633464ebd5Sriastradh
36401e04c3fSmrgstatic void
36501e04c3fSmrgattach_shader_no_error(struct gl_context *ctx, GLuint program, GLuint shader)
36601e04c3fSmrg{
36701e04c3fSmrg   struct gl_shader_program *shProg;
36801e04c3fSmrg   struct gl_shader *sh;
36901e04c3fSmrg
37001e04c3fSmrg   shProg = _mesa_lookup_shader_program(ctx, program);
37101e04c3fSmrg   sh = _mesa_lookup_shader(ctx, shader);
37201e04c3fSmrg
37301e04c3fSmrg   attach_shader(ctx, shProg, sh);
37401e04c3fSmrg}
3753464ebd5Sriastradh
3763464ebd5Sriastradhstatic GLuint
3773464ebd5Sriastradhcreate_shader(struct gl_context *ctx, GLenum type)
3783464ebd5Sriastradh{
3793464ebd5Sriastradh   struct gl_shader *sh;
3803464ebd5Sriastradh   GLuint name;
3813464ebd5Sriastradh
38201e04c3fSmrg   _mesa_HashLockMutex(ctx->Shared->ShaderObjects);
38301e04c3fSmrg   name = _mesa_HashFindFreeKeyBlock(ctx->Shared->ShaderObjects, 1);
38401e04c3fSmrg   sh = _mesa_new_shader(name, _mesa_shader_enum_to_shader_stage(type));
38501e04c3fSmrg   sh->Type = type;
3867ec681f3Smrg   _mesa_HashInsertLocked(ctx->Shared->ShaderObjects, name, sh, true);
38701e04c3fSmrg   _mesa_HashUnlockMutex(ctx->Shared->ShaderObjects);
38801e04c3fSmrg
38901e04c3fSmrg   return name;
39001e04c3fSmrg}
39101e04c3fSmrg
39201e04c3fSmrg
39301e04c3fSmrgstatic GLuint
39401e04c3fSmrgcreate_shader_err(struct gl_context *ctx, GLenum type, const char *caller)
39501e04c3fSmrg{
396af69d88dSmrg   if (!_mesa_validate_shader_target(ctx, type)) {
39701e04c3fSmrg      _mesa_error(ctx, GL_INVALID_ENUM, "%s(%s)",
39801e04c3fSmrg                  caller, _mesa_enum_to_string(type));
3993464ebd5Sriastradh      return 0;
4003464ebd5Sriastradh   }
4013464ebd5Sriastradh
40201e04c3fSmrg   return create_shader(ctx, type);
4033464ebd5Sriastradh}
4043464ebd5Sriastradh
4053464ebd5Sriastradh
40601e04c3fSmrgstatic GLuint
4073464ebd5Sriastradhcreate_shader_program(struct gl_context *ctx)
4083464ebd5Sriastradh{
4093464ebd5Sriastradh   GLuint name;
4103464ebd5Sriastradh   struct gl_shader_program *shProg;
4113464ebd5Sriastradh
41201e04c3fSmrg   _mesa_HashLockMutex(ctx->Shared->ShaderObjects);
41301e04c3fSmrg
4143464ebd5Sriastradh   name = _mesa_HashFindFreeKeyBlock(ctx->Shared->ShaderObjects, 1);
4153464ebd5Sriastradh
41601e04c3fSmrg   shProg = _mesa_new_shader_program(name);
4173464ebd5Sriastradh
4187ec681f3Smrg   _mesa_HashInsertLocked(ctx->Shared->ShaderObjects, name, shProg, true);
4193464ebd5Sriastradh
4203464ebd5Sriastradh   assert(shProg->RefCount == 1);
4213464ebd5Sriastradh
42201e04c3fSmrg   _mesa_HashUnlockMutex(ctx->Shared->ShaderObjects);
42301e04c3fSmrg
4243464ebd5Sriastradh   return name;
4253464ebd5Sriastradh}
4263464ebd5Sriastradh
4273464ebd5Sriastradh
4283464ebd5Sriastradh/**
42901e04c3fSmrg * Delete a shader program.  Actually, just decrement the program's
43001e04c3fSmrg * reference count and mark it as DeletePending.
43101e04c3fSmrg * Used to implement glDeleteProgram() and glDeleteObjectARB().
4323464ebd5Sriastradh */
4333464ebd5Sriastradhstatic void
4343464ebd5Sriastradhdelete_shader_program(struct gl_context *ctx, GLuint name)
4353464ebd5Sriastradh{
4363464ebd5Sriastradh   /*
4373464ebd5Sriastradh    * NOTE: deleting shaders/programs works a bit differently than
4383464ebd5Sriastradh    * texture objects (and buffer objects, etc).  Shader/program
4393464ebd5Sriastradh    * handles/IDs exist in the hash table until the object is really
4403464ebd5Sriastradh    * deleted (refcount==0).  With texture objects, the handle/ID is
4413464ebd5Sriastradh    * removed from the hash table in glDeleteTextures() while the tex
4423464ebd5Sriastradh    * object itself might linger until its refcount goes to zero.
4433464ebd5Sriastradh    */
4443464ebd5Sriastradh   struct gl_shader_program *shProg;
4453464ebd5Sriastradh
4463464ebd5Sriastradh   shProg = _mesa_lookup_shader_program_err(ctx, name, "glDeleteProgram");
4473464ebd5Sriastradh   if (!shProg)
4483464ebd5Sriastradh      return;
4493464ebd5Sriastradh
450af69d88dSmrg   if (!shProg->DeletePending) {
451af69d88dSmrg      shProg->DeletePending = GL_TRUE;
4523464ebd5Sriastradh
453af69d88dSmrg      /* effectively, decr shProg's refcount */
454af69d88dSmrg      _mesa_reference_shader_program(ctx, &shProg, NULL);
455af69d88dSmrg   }
4563464ebd5Sriastradh}
4573464ebd5Sriastradh
4583464ebd5Sriastradh
4593464ebd5Sriastradhstatic void
4603464ebd5Sriastradhdelete_shader(struct gl_context *ctx, GLuint shader)
4613464ebd5Sriastradh{
4623464ebd5Sriastradh   struct gl_shader *sh;
4633464ebd5Sriastradh
4643464ebd5Sriastradh   sh = _mesa_lookup_shader_err(ctx, shader, "glDeleteShader");
4653464ebd5Sriastradh   if (!sh)
4663464ebd5Sriastradh      return;
4673464ebd5Sriastradh
468af69d88dSmrg   if (!sh->DeletePending) {
469af69d88dSmrg      sh->DeletePending = GL_TRUE;
4703464ebd5Sriastradh
471af69d88dSmrg      /* effectively, decr sh's refcount */
472af69d88dSmrg      _mesa_reference_shader(ctx, &sh, NULL);
473af69d88dSmrg   }
4743464ebd5Sriastradh}
4753464ebd5Sriastradh
4763464ebd5Sriastradh
47701e04c3fSmrgstatic ALWAYS_INLINE void
47801e04c3fSmrgdetach_shader(struct gl_context *ctx, GLuint program, GLuint shader,
47901e04c3fSmrg              bool no_error)
4803464ebd5Sriastradh{
4813464ebd5Sriastradh   struct gl_shader_program *shProg;
4823464ebd5Sriastradh   GLuint n;
4833464ebd5Sriastradh   GLuint i, j;
4843464ebd5Sriastradh
48501e04c3fSmrg   if (!no_error) {
48601e04c3fSmrg      shProg = _mesa_lookup_shader_program_err(ctx, program, "glDetachShader");
48701e04c3fSmrg      if (!shProg)
48801e04c3fSmrg         return;
48901e04c3fSmrg   } else {
49001e04c3fSmrg      shProg = _mesa_lookup_shader_program(ctx, program);
49101e04c3fSmrg   }
4923464ebd5Sriastradh
4933464ebd5Sriastradh   n = shProg->NumShaders;
4943464ebd5Sriastradh
4953464ebd5Sriastradh   for (i = 0; i < n; i++) {
4963464ebd5Sriastradh      if (shProg->Shaders[i]->Name == shader) {
4973464ebd5Sriastradh         /* found it */
4983464ebd5Sriastradh         struct gl_shader **newList;
4993464ebd5Sriastradh
5003464ebd5Sriastradh         /* release */
5013464ebd5Sriastradh         _mesa_reference_shader(ctx, &shProg->Shaders[i], NULL);
5023464ebd5Sriastradh
5033464ebd5Sriastradh         /* alloc new, smaller array */
504af69d88dSmrg         newList = malloc((n - 1) * sizeof(struct gl_shader *));
5053464ebd5Sriastradh         if (!newList) {
5063464ebd5Sriastradh            _mesa_error(ctx, GL_OUT_OF_MEMORY, "glDetachShader");
5073464ebd5Sriastradh            return;
5083464ebd5Sriastradh         }
509af69d88dSmrg         /* Copy old list entries to new list, skipping removed entry at [i] */
5103464ebd5Sriastradh         for (j = 0; j < i; j++) {
5113464ebd5Sriastradh            newList[j] = shProg->Shaders[j];
5123464ebd5Sriastradh         }
513af69d88dSmrg         while (++i < n) {
5143464ebd5Sriastradh            newList[j++] = shProg->Shaders[i];
515af69d88dSmrg         }
5163464ebd5Sriastradh
517af69d88dSmrg         /* Free old list and install new one */
518af69d88dSmrg         free(shProg->Shaders);
5193464ebd5Sriastradh         shProg->Shaders = newList;
5203464ebd5Sriastradh         shProg->NumShaders = n - 1;
5213464ebd5Sriastradh
5227ec681f3Smrg#ifndef NDEBUG
523af69d88dSmrg         /* sanity check - make sure the new list's entries are sensible */
524af69d88dSmrg         for (j = 0; j < shProg->NumShaders; j++) {
52501e04c3fSmrg            assert(shProg->Shaders[j]->Stage == MESA_SHADER_VERTEX ||
52601e04c3fSmrg                   shProg->Shaders[j]->Stage == MESA_SHADER_TESS_CTRL ||
52701e04c3fSmrg                   shProg->Shaders[j]->Stage == MESA_SHADER_TESS_EVAL ||
52801e04c3fSmrg                   shProg->Shaders[j]->Stage == MESA_SHADER_GEOMETRY ||
52901e04c3fSmrg                   shProg->Shaders[j]->Stage == MESA_SHADER_FRAGMENT);
530af69d88dSmrg            assert(shProg->Shaders[j]->RefCount > 0);
5313464ebd5Sriastradh         }
5323464ebd5Sriastradh#endif
5333464ebd5Sriastradh
5343464ebd5Sriastradh         return;
5353464ebd5Sriastradh      }
5363464ebd5Sriastradh   }
5373464ebd5Sriastradh
5383464ebd5Sriastradh   /* not found */
53901e04c3fSmrg   if (!no_error) {
5403464ebd5Sriastradh      GLenum err;
54101e04c3fSmrg      if (is_shader(ctx, shader) || is_program(ctx, shader))
5423464ebd5Sriastradh         err = GL_INVALID_OPERATION;
5433464ebd5Sriastradh      else
5443464ebd5Sriastradh         err = GL_INVALID_VALUE;
545af69d88dSmrg      _mesa_error(ctx, err, "glDetachShader(shader)");
5463464ebd5Sriastradh      return;
5473464ebd5Sriastradh   }
5483464ebd5Sriastradh}
5493464ebd5Sriastradh
5503464ebd5Sriastradh
55101e04c3fSmrgstatic void
55201e04c3fSmrgdetach_shader_error(struct gl_context *ctx, GLuint program, GLuint shader)
55301e04c3fSmrg{
55401e04c3fSmrg   detach_shader(ctx, program, shader, false);
55501e04c3fSmrg}
55601e04c3fSmrg
55701e04c3fSmrg
55801e04c3fSmrgstatic void
55901e04c3fSmrgdetach_shader_no_error(struct gl_context *ctx, GLuint program, GLuint shader)
56001e04c3fSmrg{
56101e04c3fSmrg   detach_shader(ctx, program, shader, true);
56201e04c3fSmrg}
56301e04c3fSmrg
56401e04c3fSmrg
5653464ebd5Sriastradh/**
5663464ebd5Sriastradh * Return list of shaders attached to shader program.
56701e04c3fSmrg * \param objOut  returns GLuint ids
56801e04c3fSmrg * \param handleOut  returns GLhandleARB handles
5693464ebd5Sriastradh */
5703464ebd5Sriastradhstatic void
5713464ebd5Sriastradhget_attached_shaders(struct gl_context *ctx, GLuint program, GLsizei maxCount,
57201e04c3fSmrg                     GLsizei *countOut, GLuint *objOut, GLhandleARB *handleOut)
5733464ebd5Sriastradh{
57401e04c3fSmrg   struct gl_shader_program *shProg;
57501e04c3fSmrg
57601e04c3fSmrg   if (maxCount < 0) {
57701e04c3fSmrg      _mesa_error(ctx, GL_INVALID_VALUE, "glGetAttachedShaders(maxCount < 0)");
57801e04c3fSmrg      return;
57901e04c3fSmrg   }
58001e04c3fSmrg
58101e04c3fSmrg   shProg =
5823464ebd5Sriastradh      _mesa_lookup_shader_program_err(ctx, program, "glGetAttachedShaders");
58301e04c3fSmrg
5843464ebd5Sriastradh   if (shProg) {
5853464ebd5Sriastradh      GLuint i;
5863464ebd5Sriastradh      for (i = 0; i < (GLuint) maxCount && i < shProg->NumShaders; i++) {
58701e04c3fSmrg         if (objOut) {
58801e04c3fSmrg            objOut[i] = shProg->Shaders[i]->Name;
58901e04c3fSmrg         }
59001e04c3fSmrg
59101e04c3fSmrg         if (handleOut) {
59201e04c3fSmrg            handleOut[i] = (GLhandleARB) shProg->Shaders[i]->Name;
59301e04c3fSmrg         }
59401e04c3fSmrg      }
59501e04c3fSmrg      if (countOut) {
59601e04c3fSmrg         *countOut = i;
5973464ebd5Sriastradh      }
5983464ebd5Sriastradh   }
5993464ebd5Sriastradh}
6003464ebd5Sriastradh
6013464ebd5Sriastradh/**
6023464ebd5Sriastradh * glGetHandleARB() - return ID/name of currently bound shader program.
6033464ebd5Sriastradh */
6043464ebd5Sriastradhstatic GLuint
6053464ebd5Sriastradhget_handle(struct gl_context *ctx, GLenum pname)
6063464ebd5Sriastradh{
6073464ebd5Sriastradh   if (pname == GL_PROGRAM_OBJECT_ARB) {
608af69d88dSmrg      if (ctx->_Shader->ActiveProgram)
609af69d88dSmrg         return ctx->_Shader->ActiveProgram->Name;
6103464ebd5Sriastradh      else
6113464ebd5Sriastradh         return 0;
6123464ebd5Sriastradh   }
6133464ebd5Sriastradh   else {
6143464ebd5Sriastradh      _mesa_error(ctx, GL_INVALID_ENUM, "glGetHandleARB");
6153464ebd5Sriastradh      return 0;
6163464ebd5Sriastradh   }
6173464ebd5Sriastradh}
6183464ebd5Sriastradh
6193464ebd5Sriastradh
620af69d88dSmrg/**
621af69d88dSmrg * Check if a geometry shader query is valid at this time.  If not, report an
622af69d88dSmrg * error and return false.
623af69d88dSmrg *
624af69d88dSmrg * From GL 3.2 section 6.1.16 (Shader and Program Queries):
625af69d88dSmrg *
626af69d88dSmrg *     "If GEOMETRY_VERTICES_OUT, GEOMETRY_INPUT_TYPE, or GEOMETRY_OUTPUT_TYPE
627af69d88dSmrg *     are queried for a program which has not been linked successfully, or
628af69d88dSmrg *     which does not contain objects to form a geometry shader, then an
629af69d88dSmrg *     INVALID_OPERATION error is generated."
630af69d88dSmrg */
631af69d88dSmrgstatic bool
632af69d88dSmrgcheck_gs_query(struct gl_context *ctx, const struct gl_shader_program *shProg)
633af69d88dSmrg{
63401e04c3fSmrg   if (shProg->data->LinkStatus &&
635af69d88dSmrg       shProg->_LinkedShaders[MESA_SHADER_GEOMETRY] != NULL) {
636af69d88dSmrg      return true;
637af69d88dSmrg   }
638af69d88dSmrg
639af69d88dSmrg   _mesa_error(ctx, GL_INVALID_OPERATION,
640af69d88dSmrg               "glGetProgramv(linked geometry shader required)");
641af69d88dSmrg   return false;
642af69d88dSmrg}
643af69d88dSmrg
644af69d88dSmrg
64501e04c3fSmrg/**
64601e04c3fSmrg * Check if a tessellation control shader query is valid at this time.
64701e04c3fSmrg * If not, report an error and return false.
64801e04c3fSmrg *
64901e04c3fSmrg * From GL 4.0 section 6.1.12 (Shader and Program Queries):
65001e04c3fSmrg *
65101e04c3fSmrg *     "If TESS_CONTROL_OUTPUT_VERTICES is queried for a program which has
65201e04c3fSmrg *     not been linked successfully, or which does not contain objects to
65301e04c3fSmrg *     form a tessellation control shader, then an INVALID_OPERATION error is
65401e04c3fSmrg *     generated."
65501e04c3fSmrg */
65601e04c3fSmrgstatic bool
65701e04c3fSmrgcheck_tcs_query(struct gl_context *ctx, const struct gl_shader_program *shProg)
65801e04c3fSmrg{
65901e04c3fSmrg   if (shProg->data->LinkStatus &&
66001e04c3fSmrg       shProg->_LinkedShaders[MESA_SHADER_TESS_CTRL] != NULL) {
66101e04c3fSmrg      return true;
66201e04c3fSmrg   }
66301e04c3fSmrg
66401e04c3fSmrg   _mesa_error(ctx, GL_INVALID_OPERATION,
66501e04c3fSmrg               "glGetProgramv(linked tessellation control shader required)");
66601e04c3fSmrg   return false;
66701e04c3fSmrg}
66801e04c3fSmrg
66901e04c3fSmrg
67001e04c3fSmrg/**
67101e04c3fSmrg * Check if a tessellation evaluation shader query is valid at this time.
67201e04c3fSmrg * If not, report an error and return false.
67301e04c3fSmrg *
67401e04c3fSmrg * From GL 4.0 section 6.1.12 (Shader and Program Queries):
67501e04c3fSmrg *
67601e04c3fSmrg *     "If any of the pname values in this paragraph are queried for a program
67701e04c3fSmrg *     which has not been linked successfully, or which does not contain
67801e04c3fSmrg *     objects to form a tessellation evaluation shader, then an
67901e04c3fSmrg *     INVALID_OPERATION error is generated."
68001e04c3fSmrg *
68101e04c3fSmrg */
68201e04c3fSmrgstatic bool
68301e04c3fSmrgcheck_tes_query(struct gl_context *ctx, const struct gl_shader_program *shProg)
68401e04c3fSmrg{
68501e04c3fSmrg   if (shProg->data->LinkStatus &&
68601e04c3fSmrg       shProg->_LinkedShaders[MESA_SHADER_TESS_EVAL] != NULL) {
68701e04c3fSmrg      return true;
68801e04c3fSmrg   }
68901e04c3fSmrg
69001e04c3fSmrg   _mesa_error(ctx, GL_INVALID_OPERATION, "glGetProgramv(linked tessellation "
69101e04c3fSmrg               "evaluation shader required)");
69201e04c3fSmrg   return false;
69301e04c3fSmrg}
69401e04c3fSmrg
6957ec681f3Smrg/**
6967ec681f3Smrg * Return the length of a string, or 0 if the pointer passed in is NULL
6977ec681f3Smrg */
6987ec681f3Smrgstatic size_t strlen_or_zero(const char *s)
6997ec681f3Smrg{
7007ec681f3Smrg   return s ? strlen(s) : 0;
7017ec681f3Smrg}
70201e04c3fSmrg
7033464ebd5Sriastradh/**
7043464ebd5Sriastradh * glGetProgramiv() - get shader program state.
7053464ebd5Sriastradh * Note that this is for GLSL shader programs, not ARB vertex/fragment
7063464ebd5Sriastradh * programs (see glGetProgramivARB).
7073464ebd5Sriastradh */
7083464ebd5Sriastradhstatic void
70901e04c3fSmrgget_programiv(struct gl_context *ctx, GLuint program, GLenum pname,
71001e04c3fSmrg              GLint *params)
7113464ebd5Sriastradh{
7123464ebd5Sriastradh   struct gl_shader_program *shProg
71301e04c3fSmrg      = _mesa_lookup_shader_program_err(ctx, program, "glGetProgramiv(program)");
7143464ebd5Sriastradh
715af69d88dSmrg   /* Is transform feedback available in this context?
716af69d88dSmrg    */
717af69d88dSmrg   const bool has_xfb =
718af69d88dSmrg      (ctx->API == API_OPENGL_COMPAT && ctx->Extensions.EXT_transform_feedback)
719af69d88dSmrg      || ctx->API == API_OPENGL_CORE
720af69d88dSmrg      || _mesa_is_gles3(ctx);
721af69d88dSmrg
722af69d88dSmrg   /* True if geometry shaders (of the form that was adopted into GLSL 1.50
723af69d88dSmrg    * and GL 3.2) are available in this context
724af69d88dSmrg    */
72501e04c3fSmrg   const bool has_gs = _mesa_has_geometry_shaders(ctx);
72601e04c3fSmrg   const bool has_tess = _mesa_has_tessellation(ctx);
727af69d88dSmrg
728af69d88dSmrg   /* Are uniform buffer objects available in this context?
729af69d88dSmrg    */
730af69d88dSmrg   const bool has_ubo =
73101e04c3fSmrg      (ctx->API == API_OPENGL_COMPAT &&
73201e04c3fSmrg       ctx->Extensions.ARB_uniform_buffer_object)
733af69d88dSmrg      || ctx->API == API_OPENGL_CORE
734af69d88dSmrg      || _mesa_is_gles3(ctx);
735af69d88dSmrg
7363464ebd5Sriastradh   if (!shProg) {
7373464ebd5Sriastradh      return;
7383464ebd5Sriastradh   }
7393464ebd5Sriastradh
7403464ebd5Sriastradh   switch (pname) {
7413464ebd5Sriastradh   case GL_DELETE_STATUS:
7423464ebd5Sriastradh      *params = shProg->DeletePending;
743af69d88dSmrg      return;
744b9abf16eSmaya   case GL_COMPLETION_STATUS_ARB:
745b9abf16eSmaya      if (ctx->Driver.GetShaderProgramCompletionStatus)
746b9abf16eSmaya         *params = ctx->Driver.GetShaderProgramCompletionStatus(ctx, shProg);
747b9abf16eSmaya      else
748b9abf16eSmaya         *params = GL_TRUE;
749b9abf16eSmaya      return;
7503464ebd5Sriastradh   case GL_LINK_STATUS:
75101e04c3fSmrg      *params = shProg->data->LinkStatus ? GL_TRUE : GL_FALSE;
752af69d88dSmrg      return;
7533464ebd5Sriastradh   case GL_VALIDATE_STATUS:
75401e04c3fSmrg      *params = shProg->data->Validated;
755af69d88dSmrg      return;
7563464ebd5Sriastradh   case GL_INFO_LOG_LENGTH:
75701e04c3fSmrg      *params = (shProg->data->InfoLog && shProg->data->InfoLog[0] != '\0') ?
75801e04c3fSmrg         strlen(shProg->data->InfoLog) + 1 : 0;
759af69d88dSmrg      return;
7603464ebd5Sriastradh   case GL_ATTACHED_SHADERS:
7613464ebd5Sriastradh      *params = shProg->NumShaders;
762af69d88dSmrg      return;
7633464ebd5Sriastradh   case GL_ACTIVE_ATTRIBUTES:
764af69d88dSmrg      *params = _mesa_count_active_attribs(shProg);
765af69d88dSmrg      return;
7663464ebd5Sriastradh   case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH:
767af69d88dSmrg      *params = _mesa_longest_attribute_name_length(shProg);
768af69d88dSmrg      return;
76901e04c3fSmrg   case GL_ACTIVE_UNIFORMS: {
7707ec681f3Smrg      _mesa_get_program_interfaceiv(shProg, GL_UNIFORM, GL_ACTIVE_RESOURCES,
7717ec681f3Smrg                                    params);
772af69d88dSmrg      return;
77301e04c3fSmrg   }
774af69d88dSmrg   case GL_ACTIVE_UNIFORM_MAX_LENGTH: {
775af69d88dSmrg      unsigned i;
776af69d88dSmrg      GLint max_len = 0;
77701e04c3fSmrg      const unsigned num_uniforms =
77801e04c3fSmrg         shProg->data->NumUniformStorage - shProg->data->NumHiddenUniforms;
77901e04c3fSmrg
78001e04c3fSmrg      for (i = 0; i < num_uniforms; i++) {
78101e04c3fSmrg         if (shProg->data->UniformStorage[i].is_shader_storage)
78201e04c3fSmrg            continue;
783af69d88dSmrg
7847ec681f3Smrg         /* From ARB_gl_spirv spec:
7857ec681f3Smrg          *
7867ec681f3Smrg          *   "If pname is ACTIVE_UNIFORM_MAX_LENGTH, the length of the
7877ec681f3Smrg          *    longest active uniform name, including a null terminator, is
7887ec681f3Smrg          *    returned. If no active uniforms exist, zero is returned. If no
7897ec681f3Smrg          *    name reflection information is available, one is returned."
7907ec681f3Smrg          *
7917ec681f3Smrg          * We are setting 0 here, as below it will add 1 for the NUL character.
7927ec681f3Smrg          */
7937ec681f3Smrg         const GLint base_len =
7947ec681f3Smrg            strlen_or_zero(shProg->data->UniformStorage[i].name);
7957ec681f3Smrg
796af69d88dSmrg	 /* Add one for the terminating NUL character for a non-array, and
797af69d88dSmrg	  * 4 for the "[0]" and the NUL for an array.
798af69d88dSmrg	  */
7997ec681f3Smrg         const GLint len = base_len + 1 +
8007ec681f3Smrg            ((shProg->data->UniformStorage[i].array_elements != 0) ? 3 : 0);
801af69d88dSmrg
802af69d88dSmrg	 if (len > max_len)
803af69d88dSmrg	    max_len = len;
804af69d88dSmrg      }
805af69d88dSmrg
806af69d88dSmrg      *params = max_len;
807af69d88dSmrg      return;
808af69d88dSmrg   }
8093464ebd5Sriastradh   case GL_TRANSFORM_FEEDBACK_VARYINGS:
810af69d88dSmrg      if (!has_xfb)
811af69d88dSmrg         break;
8127ec681f3Smrg
8137ec681f3Smrg      /* Check first if there are transform feedback varyings specified in the
8147ec681f3Smrg       * shader (ARB_enhanced_layouts). If there isn't any, return the number of
8157ec681f3Smrg       * varyings specified using the API.
8167ec681f3Smrg       */
8177ec681f3Smrg      if (shProg->last_vert_prog &&
8187ec681f3Smrg          shProg->last_vert_prog->sh.LinkedTransformFeedback->NumVarying > 0)
8197ec681f3Smrg         *params =
8207ec681f3Smrg            shProg->last_vert_prog->sh.LinkedTransformFeedback->NumVarying;
8217ec681f3Smrg      else
8227ec681f3Smrg         *params = shProg->TransformFeedback.NumVarying;
823af69d88dSmrg      return;
824af69d88dSmrg   case GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH: {
825af69d88dSmrg      unsigned i;
826af69d88dSmrg      GLint max_len = 0;
8277ec681f3Smrg      bool in_shader_varyings;
8287ec681f3Smrg      int num_varying;
8297ec681f3Smrg
830af69d88dSmrg      if (!has_xfb)
831af69d88dSmrg         break;
832af69d88dSmrg
8337ec681f3Smrg      /* Check first if there are transform feedback varyings specified in the
8347ec681f3Smrg       * shader (ARB_enhanced_layouts). If there isn't any, use the ones
8357ec681f3Smrg       * specified using the API.
8367ec681f3Smrg       */
8377ec681f3Smrg      in_shader_varyings = shProg->last_vert_prog &&
8387ec681f3Smrg         shProg->last_vert_prog->sh.LinkedTransformFeedback->NumVarying > 0;
8397ec681f3Smrg
8407ec681f3Smrg      num_varying = in_shader_varyings ?
8417ec681f3Smrg         shProg->last_vert_prog->sh.LinkedTransformFeedback->NumVarying :
8427ec681f3Smrg         shProg->TransformFeedback.NumVarying;
8437ec681f3Smrg
8447ec681f3Smrg      for (i = 0; i < num_varying; i++) {
8457ec681f3Smrg         const char *name = in_shader_varyings ?
8467ec681f3Smrg            shProg->last_vert_prog->sh.LinkedTransformFeedback->Varyings[i].Name
8477ec681f3Smrg            : shProg->TransformFeedback.VaryingNames[i];
8487ec681f3Smrg
8497ec681f3Smrg         /* Add one for the terminating NUL character. We have to use
8507ec681f3Smrg          * strlen_or_zero, as for shaders constructed from SPIR-V binaries,
8517ec681f3Smrg          * it is possible that no name reflection information is available.
852af69d88dSmrg          */
8537ec681f3Smrg         const GLint len = strlen_or_zero(name) + 1;
854af69d88dSmrg
855af69d88dSmrg         if (len > max_len)
856af69d88dSmrg            max_len = len;
857af69d88dSmrg      }
858af69d88dSmrg
859af69d88dSmrg      *params = max_len;
860af69d88dSmrg      return;
861af69d88dSmrg   }
8623464ebd5Sriastradh   case GL_TRANSFORM_FEEDBACK_BUFFER_MODE:
863af69d88dSmrg      if (!has_xfb)
864af69d88dSmrg         break;
8653464ebd5Sriastradh      *params = shProg->TransformFeedback.BufferMode;
8663464ebd5Sriastradh      return;
867af69d88dSmrg   case GL_GEOMETRY_VERTICES_OUT:
86801e04c3fSmrg      if (!has_gs)
869af69d88dSmrg         break;
87001e04c3fSmrg      if (check_gs_query(ctx, shProg)) {
87101e04c3fSmrg         *params = shProg->_LinkedShaders[MESA_SHADER_GEOMETRY]->
87201e04c3fSmrg            Program->info.gs.vertices_out;
87301e04c3fSmrg      }
874af69d88dSmrg      return;
875af69d88dSmrg   case GL_GEOMETRY_SHADER_INVOCATIONS:
8767ec681f3Smrg      if (!has_gs ||
8777ec681f3Smrg          (_mesa_is_desktop_gl(ctx) && !ctx->Extensions.ARB_gpu_shader5)) {
878af69d88dSmrg         break;
8797ec681f3Smrg      }
88001e04c3fSmrg      if (check_gs_query(ctx, shProg)) {
88101e04c3fSmrg         *params = shProg->_LinkedShaders[MESA_SHADER_GEOMETRY]->
88201e04c3fSmrg            Program->info.gs.invocations;
88301e04c3fSmrg      }
884af69d88dSmrg      return;
885af69d88dSmrg   case GL_GEOMETRY_INPUT_TYPE:
88601e04c3fSmrg      if (!has_gs)
887af69d88dSmrg         break;
88801e04c3fSmrg      if (check_gs_query(ctx, shProg)) {
88901e04c3fSmrg         *params = shProg->_LinkedShaders[MESA_SHADER_GEOMETRY]->
89001e04c3fSmrg            Program->info.gs.input_primitive;
89101e04c3fSmrg      }
892af69d88dSmrg      return;
893af69d88dSmrg   case GL_GEOMETRY_OUTPUT_TYPE:
89401e04c3fSmrg      if (!has_gs)
895af69d88dSmrg         break;
89601e04c3fSmrg      if (check_gs_query(ctx, shProg)) {
89701e04c3fSmrg         *params = shProg->_LinkedShaders[MESA_SHADER_GEOMETRY]->
89801e04c3fSmrg            Program->info.gs.output_primitive;
89901e04c3fSmrg      }
900af69d88dSmrg      return;
901af69d88dSmrg   case GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH: {
902af69d88dSmrg      unsigned i;
903af69d88dSmrg      GLint max_len = 0;
904af69d88dSmrg
905af69d88dSmrg      if (!has_ubo)
906af69d88dSmrg         break;
907af69d88dSmrg
90801e04c3fSmrg      for (i = 0; i < shProg->data->NumUniformBlocks; i++) {
9097ec681f3Smrg	 /* Add one for the terminating NUL character. Name can be NULL, in
9107ec681f3Smrg          * that case, from ARB_gl_spirv:
9117ec681f3Smrg          *   "If pname is ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH, the length of
9127ec681f3Smrg          *    the longest active uniform block name, including the null
9137ec681f3Smrg          *    terminator, is returned. If no active uniform blocks exist,
9147ec681f3Smrg          *    zero is returned. If no name reflection information is
9157ec681f3Smrg          *    available, one is returned."
916af69d88dSmrg	  */
9177ec681f3Smrg         const GLint len =
9187ec681f3Smrg            strlen_or_zero(shProg->data->UniformBlocks[i].Name) + 1;
919af69d88dSmrg
920af69d88dSmrg	 if (len > max_len)
921af69d88dSmrg	    max_len = len;
922af69d88dSmrg      }
923af69d88dSmrg
924af69d88dSmrg      *params = max_len;
925af69d88dSmrg      return;
926af69d88dSmrg   }
927af69d88dSmrg   case GL_ACTIVE_UNIFORM_BLOCKS:
928af69d88dSmrg      if (!has_ubo)
929af69d88dSmrg         break;
930af69d88dSmrg
93101e04c3fSmrg      *params = shProg->data->NumUniformBlocks;
932af69d88dSmrg      return;
933af69d88dSmrg   case GL_PROGRAM_BINARY_RETRIEVABLE_HINT:
934af69d88dSmrg      /* This enum isn't part of the OES extension for OpenGL ES 2.0.  It is
935af69d88dSmrg       * only available with desktop OpenGL 3.0+ with the
936af69d88dSmrg       * GL_ARB_get_program_binary extension or OpenGL ES 3.0.
937af69d88dSmrg       *
938af69d88dSmrg       * On desktop, we ignore the 3.0+ requirement because it is silly.
939af69d88dSmrg       */
940af69d88dSmrg      if (!_mesa_is_desktop_gl(ctx) && !_mesa_is_gles3(ctx))
941af69d88dSmrg         break;
942af69d88dSmrg
9437ec681f3Smrg      *params = shProg->BinaryRetrievableHint;
944af69d88dSmrg      return;
945af69d88dSmrg   case GL_PROGRAM_BINARY_LENGTH:
94601e04c3fSmrg      if (ctx->Const.NumProgramBinaryFormats == 0 || !shProg->data->LinkStatus) {
94701e04c3fSmrg         *params = 0;
94801e04c3fSmrg      } else {
94901e04c3fSmrg         _mesa_get_program_binary_length(ctx, shProg, params);
95001e04c3fSmrg      }
951af69d88dSmrg      return;
952af69d88dSmrg   case GL_ACTIVE_ATOMIC_COUNTER_BUFFERS:
9537ec681f3Smrg      if (!ctx->Extensions.ARB_shader_atomic_counters && !_mesa_is_gles31(ctx))
954af69d88dSmrg         break;
955af69d88dSmrg
95601e04c3fSmrg      *params = shProg->data->NumAtomicBuffers;
957af69d88dSmrg      return;
958af69d88dSmrg   case GL_COMPUTE_WORK_GROUP_SIZE: {
959af69d88dSmrg      int i;
96001e04c3fSmrg      if (!_mesa_has_compute_shaders(ctx))
961af69d88dSmrg         break;
96201e04c3fSmrg      if (!shProg->data->LinkStatus) {
963af69d88dSmrg         _mesa_error(ctx, GL_INVALID_OPERATION, "glGetProgramiv(program not "
964af69d88dSmrg                     "linked)");
965af69d88dSmrg         return;
966af69d88dSmrg      }
967af69d88dSmrg      if (shProg->_LinkedShaders[MESA_SHADER_COMPUTE] == NULL) {
968af69d88dSmrg         _mesa_error(ctx, GL_INVALID_OPERATION, "glGetProgramiv(no compute "
969af69d88dSmrg                     "shaders)");
970af69d88dSmrg         return;
971af69d88dSmrg      }
972af69d88dSmrg      for (i = 0; i < 3; i++)
97301e04c3fSmrg         params[i] = shProg->_LinkedShaders[MESA_SHADER_COMPUTE]->
9747ec681f3Smrg            Program->info.workgroup_size[i];
975af69d88dSmrg      return;
976af69d88dSmrg   }
977af69d88dSmrg   case GL_PROGRAM_SEPARABLE:
97801e04c3fSmrg      /* If the program has not been linked, return initial value 0. */
97901e04c3fSmrg      *params = (shProg->data->LinkStatus == LINKING_FAILURE) ? 0 : shProg->SeparateShader;
98001e04c3fSmrg      return;
98101e04c3fSmrg
98201e04c3fSmrg   /* ARB_tessellation_shader */
98301e04c3fSmrg   case GL_TESS_CONTROL_OUTPUT_VERTICES:
98401e04c3fSmrg      if (!has_tess)
98501e04c3fSmrg         break;
98601e04c3fSmrg      if (check_tcs_query(ctx, shProg)) {
98701e04c3fSmrg         *params = shProg->_LinkedShaders[MESA_SHADER_TESS_CTRL]->
98801e04c3fSmrg            Program->info.tess.tcs_vertices_out;
98901e04c3fSmrg      }
99001e04c3fSmrg      return;
99101e04c3fSmrg   case GL_TESS_GEN_MODE:
99201e04c3fSmrg      if (!has_tess)
99301e04c3fSmrg         break;
99401e04c3fSmrg      if (check_tes_query(ctx, shProg)) {
99501e04c3fSmrg         *params = shProg->_LinkedShaders[MESA_SHADER_TESS_EVAL]->
99601e04c3fSmrg            Program->info.tess.primitive_mode;
99701e04c3fSmrg      }
99801e04c3fSmrg      return;
99901e04c3fSmrg   case GL_TESS_GEN_SPACING:
100001e04c3fSmrg      if (!has_tess)
100101e04c3fSmrg         break;
100201e04c3fSmrg      if (check_tes_query(ctx, shProg)) {
100301e04c3fSmrg         const struct gl_linked_shader *tes =
100401e04c3fSmrg            shProg->_LinkedShaders[MESA_SHADER_TESS_EVAL];
100501e04c3fSmrg         switch (tes->Program->info.tess.spacing) {
100601e04c3fSmrg         case TESS_SPACING_EQUAL:
100701e04c3fSmrg            *params = GL_EQUAL;
100801e04c3fSmrg            break;
100901e04c3fSmrg         case TESS_SPACING_FRACTIONAL_ODD:
101001e04c3fSmrg            *params = GL_FRACTIONAL_ODD;
101101e04c3fSmrg            break;
101201e04c3fSmrg         case TESS_SPACING_FRACTIONAL_EVEN:
101301e04c3fSmrg            *params = GL_FRACTIONAL_EVEN;
101401e04c3fSmrg            break;
101501e04c3fSmrg         case TESS_SPACING_UNSPECIFIED:
101601e04c3fSmrg            *params = 0;
101701e04c3fSmrg            break;
101801e04c3fSmrg         }
101901e04c3fSmrg      }
102001e04c3fSmrg      return;
102101e04c3fSmrg   case GL_TESS_GEN_VERTEX_ORDER:
102201e04c3fSmrg      if (!has_tess)
102301e04c3fSmrg         break;
102401e04c3fSmrg      if (check_tes_query(ctx, shProg)) {
102501e04c3fSmrg         *params = shProg->_LinkedShaders[MESA_SHADER_TESS_EVAL]->
102601e04c3fSmrg            Program->info.tess.ccw ? GL_CCW : GL_CW;
102701e04c3fSmrg         }
102801e04c3fSmrg      return;
102901e04c3fSmrg   case GL_TESS_GEN_POINT_MODE:
103001e04c3fSmrg      if (!has_tess)
103101e04c3fSmrg         break;
103201e04c3fSmrg      if (check_tes_query(ctx, shProg)) {
103301e04c3fSmrg         *params = shProg->_LinkedShaders[MESA_SHADER_TESS_EVAL]->
103401e04c3fSmrg            Program->info.tess.point_mode ? GL_TRUE : GL_FALSE;
103501e04c3fSmrg      }
1036af69d88dSmrg      return;
1037af69d88dSmrg   default:
1038af69d88dSmrg      break;
10393464ebd5Sriastradh   }
1040af69d88dSmrg
1041af69d88dSmrg   _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramiv(pname=%s)",
104201e04c3fSmrg               _mesa_enum_to_string(pname));
10433464ebd5Sriastradh}
10443464ebd5Sriastradh
10453464ebd5Sriastradh
10463464ebd5Sriastradh/**
10473464ebd5Sriastradh * glGetShaderiv() - get GLSL shader state
10483464ebd5Sriastradh */
10493464ebd5Sriastradhstatic void
10503464ebd5Sriastradhget_shaderiv(struct gl_context *ctx, GLuint name, GLenum pname, GLint *params)
10513464ebd5Sriastradh{
10523464ebd5Sriastradh   struct gl_shader *shader =
10533464ebd5Sriastradh      _mesa_lookup_shader_err(ctx, name, "glGetShaderiv");
10543464ebd5Sriastradh
10553464ebd5Sriastradh   if (!shader) {
10563464ebd5Sriastradh      return;
10573464ebd5Sriastradh   }
10583464ebd5Sriastradh
10593464ebd5Sriastradh   switch (pname) {
10603464ebd5Sriastradh   case GL_SHADER_TYPE:
10613464ebd5Sriastradh      *params = shader->Type;
10623464ebd5Sriastradh      break;
10633464ebd5Sriastradh   case GL_DELETE_STATUS:
10643464ebd5Sriastradh      *params = shader->DeletePending;
10653464ebd5Sriastradh      break;
1066b9abf16eSmaya   case GL_COMPLETION_STATUS_ARB:
1067b9abf16eSmaya      /* _mesa_glsl_compile_shader is not offloaded to other threads. */
1068b9abf16eSmaya      *params = GL_TRUE;
1069b9abf16eSmaya      return;
10703464ebd5Sriastradh   case GL_COMPILE_STATUS:
107101e04c3fSmrg      *params = shader->CompileStatus ? GL_TRUE : GL_FALSE;
10723464ebd5Sriastradh      break;
10733464ebd5Sriastradh   case GL_INFO_LOG_LENGTH:
107401e04c3fSmrg      *params = (shader->InfoLog && shader->InfoLog[0] != '\0') ?
107501e04c3fSmrg         strlen(shader->InfoLog) + 1 : 0;
10763464ebd5Sriastradh      break;
10773464ebd5Sriastradh   case GL_SHADER_SOURCE_LENGTH:
10783464ebd5Sriastradh      *params = shader->Source ? strlen((char *) shader->Source) + 1 : 0;
10793464ebd5Sriastradh      break;
108001e04c3fSmrg   case GL_SPIR_V_BINARY_ARB:
108101e04c3fSmrg      *params = (shader->spirv_data != NULL);
108201e04c3fSmrg      break;
10833464ebd5Sriastradh   default:
10843464ebd5Sriastradh      _mesa_error(ctx, GL_INVALID_ENUM, "glGetShaderiv(pname)");
10853464ebd5Sriastradh      return;
10863464ebd5Sriastradh   }
10873464ebd5Sriastradh}
10883464ebd5Sriastradh
10893464ebd5Sriastradh
10903464ebd5Sriastradhstatic void
10913464ebd5Sriastradhget_program_info_log(struct gl_context *ctx, GLuint program, GLsizei bufSize,
10923464ebd5Sriastradh                     GLsizei *length, GLchar *infoLog)
10933464ebd5Sriastradh{
109401e04c3fSmrg   struct gl_shader_program *shProg;
109501e04c3fSmrg
109601e04c3fSmrg   /* Section 2.5 GL Errors (page 18) of the OpenGL ES 3.0.4 spec and
109701e04c3fSmrg    * section 2.3.1 (Errors) of the OpenGL 4.5 spec say:
109801e04c3fSmrg    *
109901e04c3fSmrg    *     "If a negative number is provided where an argument of type sizei or
110001e04c3fSmrg    *     sizeiptr is specified, an INVALID_VALUE error is generated."
110101e04c3fSmrg    */
110201e04c3fSmrg   if (bufSize < 0) {
110301e04c3fSmrg      _mesa_error(ctx, GL_INVALID_VALUE, "glGetProgramInfoLog(bufSize < 0)");
110401e04c3fSmrg      return;
110501e04c3fSmrg   }
110601e04c3fSmrg
110701e04c3fSmrg   shProg = _mesa_lookup_shader_program_err(ctx, program,
110801e04c3fSmrg                                            "glGetProgramInfoLog(program)");
11093464ebd5Sriastradh   if (!shProg) {
11103464ebd5Sriastradh      return;
11113464ebd5Sriastradh   }
111201e04c3fSmrg
111301e04c3fSmrg   _mesa_copy_string(infoLog, bufSize, length, shProg->data->InfoLog);
11143464ebd5Sriastradh}
11153464ebd5Sriastradh
11163464ebd5Sriastradh
11173464ebd5Sriastradhstatic void
11183464ebd5Sriastradhget_shader_info_log(struct gl_context *ctx, GLuint shader, GLsizei bufSize,
11193464ebd5Sriastradh                    GLsizei *length, GLchar *infoLog)
11203464ebd5Sriastradh{
112101e04c3fSmrg   struct gl_shader *sh;
112201e04c3fSmrg
112301e04c3fSmrg   /* Section 2.5 GL Errors (page 18) of the OpenGL ES 3.0.4 spec and
112401e04c3fSmrg    * section 2.3.1 (Errors) of the OpenGL 4.5 spec say:
112501e04c3fSmrg    *
112601e04c3fSmrg    *     "If a negative number is provided where an argument of type sizei or
112701e04c3fSmrg    *     sizeiptr is specified, an INVALID_VALUE error is generated."
112801e04c3fSmrg    */
112901e04c3fSmrg   if (bufSize < 0) {
113001e04c3fSmrg      _mesa_error(ctx, GL_INVALID_VALUE, "glGetShaderInfoLog(bufSize < 0)");
113101e04c3fSmrg      return;
113201e04c3fSmrg   }
113301e04c3fSmrg
113401e04c3fSmrg   sh = _mesa_lookup_shader_err(ctx, shader, "glGetShaderInfoLog(shader)");
11353464ebd5Sriastradh   if (!sh) {
11363464ebd5Sriastradh      return;
11373464ebd5Sriastradh   }
113801e04c3fSmrg
11393464ebd5Sriastradh   _mesa_copy_string(infoLog, bufSize, length, sh->InfoLog);
11403464ebd5Sriastradh}
11413464ebd5Sriastradh
11423464ebd5Sriastradh
11433464ebd5Sriastradh/**
11443464ebd5Sriastradh * Return shader source code.
11453464ebd5Sriastradh */
11463464ebd5Sriastradhstatic void
11473464ebd5Sriastradhget_shader_source(struct gl_context *ctx, GLuint shader, GLsizei maxLength,
11483464ebd5Sriastradh                  GLsizei *length, GLchar *sourceOut)
11493464ebd5Sriastradh{
11503464ebd5Sriastradh   struct gl_shader *sh;
115101e04c3fSmrg
115201e04c3fSmrg   if (maxLength < 0) {
115301e04c3fSmrg      _mesa_error(ctx, GL_INVALID_VALUE, "glGetShaderSource(bufSize < 0)");
115401e04c3fSmrg      return;
115501e04c3fSmrg   }
115601e04c3fSmrg
11573464ebd5Sriastradh   sh = _mesa_lookup_shader_err(ctx, shader, "glGetShaderSource");
11583464ebd5Sriastradh   if (!sh) {
11593464ebd5Sriastradh      return;
11603464ebd5Sriastradh   }
11613464ebd5Sriastradh   _mesa_copy_string(sourceOut, maxLength, length, sh->Source);
11623464ebd5Sriastradh}
11633464ebd5Sriastradh
11643464ebd5Sriastradh
11653464ebd5Sriastradh/**
1166af69d88dSmrg * Set/replace shader source code.  A helper function used by
1167af69d88dSmrg * glShaderSource[ARB].
11683464ebd5Sriastradh */
11693464ebd5Sriastradhstatic void
117001e04c3fSmrgset_shader_source(struct gl_shader *sh, const GLchar *source)
11713464ebd5Sriastradh{
117201e04c3fSmrg   assert(sh);
11733464ebd5Sriastradh
117401e04c3fSmrg   /* The GL_ARB_gl_spirv spec adds the following to the end of the description
117501e04c3fSmrg    * of ShaderSource:
117601e04c3fSmrg    *
117701e04c3fSmrg    *   "If <shader> was previously associated with a SPIR-V module (via the
117801e04c3fSmrg    *    ShaderBinary command), that association is broken. Upon successful
117901e04c3fSmrg    *    completion of this command the SPIR_V_BINARY_ARB state of <shader>
118001e04c3fSmrg    *    is set to FALSE."
118101e04c3fSmrg    */
118201e04c3fSmrg   _mesa_shader_spirv_data_reference(&sh->spirv_data, NULL);
118301e04c3fSmrg
118401e04c3fSmrg   if (sh->CompileStatus == COMPILE_SKIPPED && !sh->FallbackSource) {
118501e04c3fSmrg      /* If shader was previously compiled back-up the source in case of cache
118601e04c3fSmrg       * fallback.
118701e04c3fSmrg       */
118801e04c3fSmrg      sh->FallbackSource = sh->Source;
118901e04c3fSmrg      sh->Source = source;
119001e04c3fSmrg   } else {
119101e04c3fSmrg      /* free old shader source string and install new one */
119201e04c3fSmrg      free((void *)sh->Source);
119301e04c3fSmrg      sh->Source = source;
119401e04c3fSmrg   }
11953464ebd5Sriastradh
11963464ebd5Sriastradh#ifdef DEBUG
119701e04c3fSmrg   sh->SourceChecksum = util_hash_crc32(sh->Source, strlen(sh->Source));
11983464ebd5Sriastradh#endif
11993464ebd5Sriastradh}
12003464ebd5Sriastradh
12017ec681f3Smrgstatic void
12027ec681f3Smrgensure_builtin_types(struct gl_context *ctx)
12037ec681f3Smrg{
12047ec681f3Smrg   if (!ctx->shader_builtin_ref) {
12057ec681f3Smrg      _mesa_glsl_builtin_functions_init_or_ref();
12067ec681f3Smrg      ctx->shader_builtin_ref = true;
12077ec681f3Smrg   }
12087ec681f3Smrg}
12093464ebd5Sriastradh
12103464ebd5Sriastradh/**
12113464ebd5Sriastradh * Compile a shader.
12123464ebd5Sriastradh */
121301e04c3fSmrgvoid
121401e04c3fSmrg_mesa_compile_shader(struct gl_context *ctx, struct gl_shader *sh)
12153464ebd5Sriastradh{
12163464ebd5Sriastradh   if (!sh)
12173464ebd5Sriastradh      return;
12183464ebd5Sriastradh
121901e04c3fSmrg   /* The GL_ARB_gl_spirv spec says:
122001e04c3fSmrg    *
122101e04c3fSmrg    *    "Add a new error for the CompileShader command:
122201e04c3fSmrg    *
122301e04c3fSmrg    *      An INVALID_OPERATION error is generated if the SPIR_V_BINARY_ARB
122401e04c3fSmrg    *      state of <shader> is TRUE."
122501e04c3fSmrg    */
122601e04c3fSmrg   if (sh->spirv_data) {
122701e04c3fSmrg      _mesa_error(ctx, GL_INVALID_OPERATION, "glCompileShader(SPIR-V)");
122801e04c3fSmrg      return;
122901e04c3fSmrg   }
12303464ebd5Sriastradh
1231af69d88dSmrg   if (!sh->Source) {
1232af69d88dSmrg      /* If the user called glCompileShader without first calling
1233af69d88dSmrg       * glShaderSource, we should fail to compile, but not raise a GL_ERROR.
1234af69d88dSmrg       */
123501e04c3fSmrg      sh->CompileStatus = COMPILE_FAILURE;
1236af69d88dSmrg   } else {
1237af69d88dSmrg      if (ctx->_Shader->Flags & GLSL_DUMP) {
123801e04c3fSmrg         _mesa_log("GLSL source for %s shader %d:\n",
1239af69d88dSmrg                 _mesa_shader_stage_to_string(sh->Stage), sh->Name);
124001e04c3fSmrg         _mesa_log("%s\n", sh->Source);
1241af69d88dSmrg      }
1242af69d88dSmrg
12437ec681f3Smrg      ensure_builtin_types(ctx);
12447ec681f3Smrg
1245af69d88dSmrg      /* this call will set the shader->CompileStatus field to indicate if
1246af69d88dSmrg       * compilation was successful.
1247af69d88dSmrg       */
124801e04c3fSmrg      _mesa_glsl_compile_shader(ctx, sh, false, false, false);
1249af69d88dSmrg
1250af69d88dSmrg      if (ctx->_Shader->Flags & GLSL_LOG) {
1251af69d88dSmrg         _mesa_write_shader_to_file(sh);
1252af69d88dSmrg      }
1253af69d88dSmrg
1254af69d88dSmrg      if (ctx->_Shader->Flags & GLSL_DUMP) {
1255af69d88dSmrg         if (sh->CompileStatus) {
125601e04c3fSmrg            if (sh->ir) {
125701e04c3fSmrg               _mesa_log("GLSL IR for shader %d:\n", sh->Name);
125801e04c3fSmrg               _mesa_print_ir(_mesa_get_log_file(), sh->ir, NULL);
125901e04c3fSmrg            } else {
126001e04c3fSmrg               _mesa_log("No GLSL IR for shader %d (shader may be from "
126101e04c3fSmrg                         "cache)\n", sh->Name);
126201e04c3fSmrg            }
126301e04c3fSmrg            _mesa_log("\n\n");
1264af69d88dSmrg         } else {
126501e04c3fSmrg            _mesa_log("GLSL shader %d failed to compile.\n", sh->Name);
1266af69d88dSmrg         }
1267af69d88dSmrg         if (sh->InfoLog && sh->InfoLog[0] != 0) {
126801e04c3fSmrg            _mesa_log("GLSL shader %d info log:\n", sh->Name);
126901e04c3fSmrg            _mesa_log("%s\n", sh->InfoLog);
1270af69d88dSmrg         }
1271af69d88dSmrg      }
1272af69d88dSmrg   }
1273af69d88dSmrg
1274af69d88dSmrg   if (!sh->CompileStatus) {
1275af69d88dSmrg      if (ctx->_Shader->Flags & GLSL_DUMP_ON_ERROR) {
127601e04c3fSmrg         _mesa_log("GLSL source for %s shader %d:\n",
1277af69d88dSmrg                 _mesa_shader_stage_to_string(sh->Stage), sh->Name);
127801e04c3fSmrg         _mesa_log("%s\n", sh->Source);
127901e04c3fSmrg         _mesa_log("Info Log:\n%s\n", sh->InfoLog);
1280af69d88dSmrg      }
1281af69d88dSmrg
1282af69d88dSmrg      if (ctx->_Shader->Flags & GLSL_REPORT_ERRORS) {
1283af69d88dSmrg         _mesa_debug(ctx, "Error compiling shader %u:\n%s\n",
1284af69d88dSmrg                     sh->Name, sh->InfoLog);
1285af69d88dSmrg      }
1286af69d88dSmrg   }
12873464ebd5Sriastradh}
12883464ebd5Sriastradh
12893464ebd5Sriastradh
12907ec681f3Smrgstruct update_programs_in_pipeline_params
12917ec681f3Smrg{
12927ec681f3Smrg   struct gl_context *ctx;
12937ec681f3Smrg   struct gl_shader_program *shProg;
12947ec681f3Smrg};
12957ec681f3Smrg
12967ec681f3Smrgstatic void
12977ec681f3Smrgupdate_programs_in_pipeline(void *data, void *userData)
12987ec681f3Smrg{
12997ec681f3Smrg   struct update_programs_in_pipeline_params *params =
13007ec681f3Smrg      (struct update_programs_in_pipeline_params *) userData;
13017ec681f3Smrg   struct gl_pipeline_object *obj = (struct gl_pipeline_object *) data;
13027ec681f3Smrg
13037ec681f3Smrg   for (unsigned stage = 0; stage < MESA_SHADER_STAGES; stage++) {
13047ec681f3Smrg      if (obj->CurrentProgram[stage] &&
13057ec681f3Smrg          obj->CurrentProgram[stage]->Id == params->shProg->Name) {
13067ec681f3Smrg         struct gl_program *prog = params->shProg->_LinkedShaders[stage]->Program;
13077ec681f3Smrg         _mesa_use_program(params->ctx, stage, params->shProg, prog, obj);
13087ec681f3Smrg      }
13097ec681f3Smrg   }
13107ec681f3Smrg}
13117ec681f3Smrg
13127ec681f3Smrg
13133464ebd5Sriastradh/**
13143464ebd5Sriastradh * Link a program's shaders.
13153464ebd5Sriastradh */
131601e04c3fSmrgstatic ALWAYS_INLINE void
131701e04c3fSmrglink_program(struct gl_context *ctx, struct gl_shader_program *shProg,
131801e04c3fSmrg             bool no_error)
13193464ebd5Sriastradh{
13203464ebd5Sriastradh   if (!shProg)
13213464ebd5Sriastradh      return;
13223464ebd5Sriastradh
132301e04c3fSmrg   if (!no_error) {
132401e04c3fSmrg      /* From the ARB_transform_feedback2 specification:
132501e04c3fSmrg       * "The error INVALID_OPERATION is generated by LinkProgram if <program>
132601e04c3fSmrg       * is the name of a program being used by one or more transform feedback
132701e04c3fSmrg       * objects, even if the objects are not currently bound or are paused."
132801e04c3fSmrg       */
132901e04c3fSmrg      if (_mesa_transform_feedback_is_using_program(ctx, shProg)) {
133001e04c3fSmrg         _mesa_error(ctx, GL_INVALID_OPERATION,
133101e04c3fSmrg                     "glLinkProgram(transform feedback is using the program)");
133201e04c3fSmrg         return;
133301e04c3fSmrg      }
13343464ebd5Sriastradh   }
13353464ebd5Sriastradh
133601e04c3fSmrg   unsigned programs_in_use = 0;
133701e04c3fSmrg   if (ctx->_Shader)
133801e04c3fSmrg      for (unsigned stage = 0; stage < MESA_SHADER_STAGES; stage++) {
133901e04c3fSmrg         if (ctx->_Shader->CurrentProgram[stage] &&
134001e04c3fSmrg             ctx->_Shader->CurrentProgram[stage]->Id == shProg->Name) {
134101e04c3fSmrg            programs_in_use |= 1 << stage;
134201e04c3fSmrg         }
13437ec681f3Smrg      }
13447ec681f3Smrg
13457ec681f3Smrg   ensure_builtin_types(ctx);
13463464ebd5Sriastradh
13477ec681f3Smrg   FLUSH_VERTICES(ctx, 0, 0);
13483464ebd5Sriastradh   _mesa_glsl_link_shader(ctx, shProg);
13493464ebd5Sriastradh
135001e04c3fSmrg   /* From section 7.3 (Program Objects) of the OpenGL 4.5 spec:
135101e04c3fSmrg    *
135201e04c3fSmrg    *    "If LinkProgram or ProgramBinary successfully re-links a program
135301e04c3fSmrg    *     object that is active for any shader stage, then the newly generated
135401e04c3fSmrg    *     executable code will be installed as part of the current rendering
135501e04c3fSmrg    *     state for all shader stages where the program is active.
135601e04c3fSmrg    *     Additionally, the newly generated executable code is made part of
135701e04c3fSmrg    *     the state of any program pipeline for all stages where the program
135801e04c3fSmrg    *     is attached."
135901e04c3fSmrg    */
13607ec681f3Smrg   if (shProg->data->LinkStatus) {
136101e04c3fSmrg      while (programs_in_use) {
136201e04c3fSmrg         const int stage = u_bit_scan(&programs_in_use);
136301e04c3fSmrg
136401e04c3fSmrg         struct gl_program *prog = NULL;
136501e04c3fSmrg         if (shProg->_LinkedShaders[stage])
136601e04c3fSmrg            prog = shProg->_LinkedShaders[stage]->Program;
136701e04c3fSmrg
136801e04c3fSmrg         _mesa_use_program(ctx, stage, shProg, prog, ctx->_Shader);
136901e04c3fSmrg      }
13707ec681f3Smrg
13717ec681f3Smrg      if (ctx->Pipeline.Objects) {
13727ec681f3Smrg         struct update_programs_in_pipeline_params params = {
13737ec681f3Smrg            .ctx = ctx,
13747ec681f3Smrg            .shProg = shProg
13757ec681f3Smrg         };
13767ec681f3Smrg         _mesa_HashWalk(ctx->Pipeline.Objects, update_programs_in_pipeline,
13777ec681f3Smrg                        &params);
13787ec681f3Smrg      }
137901e04c3fSmrg   }
138001e04c3fSmrg
13817ec681f3Smrg#ifndef CUSTOM_SHADER_REPLACEMENT
138201e04c3fSmrg   /* Capture .shader_test files. */
138301e04c3fSmrg   const char *capture_path = _mesa_get_shader_capture_path();
138401e04c3fSmrg   if (shProg->Name != 0 && shProg->Name != ~0 && capture_path != NULL) {
1385b9abf16eSmaya      /* Find an unused filename. */
13867ec681f3Smrg      FILE *file = NULL;
1387b9abf16eSmaya      char *filename = NULL;
1388b9abf16eSmaya      for (unsigned i = 0;; i++) {
1389b9abf16eSmaya         if (i) {
1390b9abf16eSmaya            filename = ralloc_asprintf(NULL, "%s/%u-%u.shader_test",
1391b9abf16eSmaya                                       capture_path, shProg->Name, i);
1392b9abf16eSmaya         } else {
1393b9abf16eSmaya            filename = ralloc_asprintf(NULL, "%s/%u.shader_test",
139401e04c3fSmrg                                       capture_path, shProg->Name);
1395b9abf16eSmaya         }
13967ec681f3Smrg         file = os_file_create_unique(filename, 0644);
13977ec681f3Smrg         if (file)
13987ec681f3Smrg            break;
13997ec681f3Smrg         /* If we are failing for another reason than "this filename already
14007ec681f3Smrg          * exists", we are likely to fail again with another filename, so
14017ec681f3Smrg          * let's just give up */
14027ec681f3Smrg         if (errno != EEXIST)
1403b9abf16eSmaya            break;
1404b9abf16eSmaya         ralloc_free(filename);
1405b9abf16eSmaya      }
140601e04c3fSmrg      if (file) {
140701e04c3fSmrg         fprintf(file, "[require]\nGLSL%s >= %u.%02u\n",
140801e04c3fSmrg                 shProg->IsES ? " ES" : "",
140901e04c3fSmrg                 shProg->data->Version / 100, shProg->data->Version % 100);
141001e04c3fSmrg         if (shProg->SeparateShader)
141101e04c3fSmrg            fprintf(file, "GL_ARB_separate_shader_objects\nSSO ENABLED\n");
141201e04c3fSmrg         fprintf(file, "\n");
141301e04c3fSmrg
141401e04c3fSmrg         for (unsigned i = 0; i < shProg->NumShaders; i++) {
141501e04c3fSmrg            fprintf(file, "[%s shader]\n%s\n",
141601e04c3fSmrg                    _mesa_shader_stage_to_string(shProg->Shaders[i]->Stage),
141701e04c3fSmrg                    shProg->Shaders[i]->Source);
141801e04c3fSmrg         }
141901e04c3fSmrg         fclose(file);
142001e04c3fSmrg      } else {
142101e04c3fSmrg         _mesa_warning(ctx, "Failed to open %s", filename);
142201e04c3fSmrg      }
142301e04c3fSmrg
142401e04c3fSmrg      ralloc_free(filename);
142501e04c3fSmrg   }
14267ec681f3Smrg#endif
142701e04c3fSmrg
142801e04c3fSmrg   if (shProg->data->LinkStatus == LINKING_FAILURE &&
1429af69d88dSmrg       (ctx->_Shader->Flags & GLSL_REPORT_ERRORS)) {
1430af69d88dSmrg      _mesa_debug(ctx, "Error linking program %u:\n%s\n",
143101e04c3fSmrg                  shProg->Name, shProg->data->InfoLog);
1432af69d88dSmrg   }
1433af69d88dSmrg
143401e04c3fSmrg   _mesa_update_vertex_processing_mode(ctx);
14357ec681f3Smrg   _mesa_update_valid_to_render_state(ctx);
14367ec681f3Smrg
14377ec681f3Smrg   shProg->BinaryRetrievableHint = shProg->BinaryRetrievableHintPending;
143801e04c3fSmrg
14393464ebd5Sriastradh   /* debug code */
14403464ebd5Sriastradh   if (0) {
14413464ebd5Sriastradh      GLuint i;
14423464ebd5Sriastradh
14433464ebd5Sriastradh      printf("Link %u shaders in program %u: %s\n",
14443464ebd5Sriastradh                   shProg->NumShaders, shProg->Name,
144501e04c3fSmrg                   shProg->data->LinkStatus ? "Success" : "Failed");
14463464ebd5Sriastradh
14473464ebd5Sriastradh      for (i = 0; i < shProg->NumShaders; i++) {
144801e04c3fSmrg         printf(" shader %u, stage %u\n",
14493464ebd5Sriastradh                      shProg->Shaders[i]->Name,
145001e04c3fSmrg                      shProg->Shaders[i]->Stage);
14513464ebd5Sriastradh      }
14523464ebd5Sriastradh   }
14533464ebd5Sriastradh}
14543464ebd5Sriastradh
14553464ebd5Sriastradh
145601e04c3fSmrgstatic void
145701e04c3fSmrglink_program_error(struct gl_context *ctx, struct gl_shader_program *shProg)
145801e04c3fSmrg{
145901e04c3fSmrg   link_program(ctx, shProg, false);
146001e04c3fSmrg}
146101e04c3fSmrg
146201e04c3fSmrg
146301e04c3fSmrgstatic void
146401e04c3fSmrglink_program_no_error(struct gl_context *ctx, struct gl_shader_program *shProg)
146501e04c3fSmrg{
146601e04c3fSmrg   link_program(ctx, shProg, true);
146701e04c3fSmrg}
146801e04c3fSmrg
146901e04c3fSmrg
147001e04c3fSmrgvoid
147101e04c3fSmrg_mesa_link_program(struct gl_context *ctx, struct gl_shader_program *shProg)
147201e04c3fSmrg{
147301e04c3fSmrg   link_program_error(ctx, shProg);
147401e04c3fSmrg}
147501e04c3fSmrg
147601e04c3fSmrg
14773464ebd5Sriastradh/**
14783464ebd5Sriastradh * Print basic shader info (for debug).
14793464ebd5Sriastradh */
14803464ebd5Sriastradhstatic void
14813464ebd5Sriastradhprint_shader_info(const struct gl_shader_program *shProg)
14823464ebd5Sriastradh{
14833464ebd5Sriastradh   GLuint i;
14843464ebd5Sriastradh
14853464ebd5Sriastradh   printf("Mesa: glUseProgram(%u)\n", shProg->Name);
14863464ebd5Sriastradh   for (i = 0; i < shProg->NumShaders; i++) {
148701e04c3fSmrg#ifdef DEBUG
1488af69d88dSmrg      printf("  %s shader %u, checksum %u\n",
1489af69d88dSmrg             _mesa_shader_stage_to_string(shProg->Shaders[i]->Stage),
14903464ebd5Sriastradh	     shProg->Shaders[i]->Name,
14913464ebd5Sriastradh	     shProg->Shaders[i]->SourceChecksum);
149201e04c3fSmrg#else
149301e04c3fSmrg      printf("  %s shader %u\n",
149401e04c3fSmrg             _mesa_shader_stage_to_string(shProg->Shaders[i]->Stage),
149501e04c3fSmrg             shProg->Shaders[i]->Name);
149601e04c3fSmrg#endif
14973464ebd5Sriastradh   }
1498af69d88dSmrg   if (shProg->_LinkedShaders[MESA_SHADER_VERTEX])
1499af69d88dSmrg      printf("  vert prog %u\n",
1500af69d88dSmrg	     shProg->_LinkedShaders[MESA_SHADER_VERTEX]->Program->Id);
1501af69d88dSmrg   if (shProg->_LinkedShaders[MESA_SHADER_FRAGMENT])
1502af69d88dSmrg      printf("  frag prog %u\n",
1503af69d88dSmrg	     shProg->_LinkedShaders[MESA_SHADER_FRAGMENT]->Program->Id);
1504af69d88dSmrg   if (shProg->_LinkedShaders[MESA_SHADER_GEOMETRY])
1505af69d88dSmrg      printf("  geom prog %u\n",
1506af69d88dSmrg	     shProg->_LinkedShaders[MESA_SHADER_GEOMETRY]->Program->Id);
150701e04c3fSmrg   if (shProg->_LinkedShaders[MESA_SHADER_TESS_CTRL])
150801e04c3fSmrg      printf("  tesc prog %u\n",
150901e04c3fSmrg	     shProg->_LinkedShaders[MESA_SHADER_TESS_CTRL]->Program->Id);
151001e04c3fSmrg   if (shProg->_LinkedShaders[MESA_SHADER_TESS_EVAL])
151101e04c3fSmrg      printf("  tese prog %u\n",
151201e04c3fSmrg	     shProg->_LinkedShaders[MESA_SHADER_TESS_EVAL]->Program->Id);
15133464ebd5Sriastradh}
15143464ebd5Sriastradh
15153464ebd5Sriastradh
15163464ebd5Sriastradh/**
15173464ebd5Sriastradh * Use the named shader program for subsequent glUniform calls
15183464ebd5Sriastradh */
15193464ebd5Sriastradhvoid
15203464ebd5Sriastradh_mesa_active_program(struct gl_context *ctx, struct gl_shader_program *shProg,
15213464ebd5Sriastradh		     const char *caller)
15223464ebd5Sriastradh{
152301e04c3fSmrg   if ((shProg != NULL) && !shProg->data->LinkStatus) {
15243464ebd5Sriastradh      _mesa_error(ctx, GL_INVALID_OPERATION,
15253464ebd5Sriastradh		  "%s(program %u not linked)", caller, shProg->Name);
15263464ebd5Sriastradh      return;
15273464ebd5Sriastradh   }
15283464ebd5Sriastradh
15293464ebd5Sriastradh   if (ctx->Shader.ActiveProgram != shProg) {
15303464ebd5Sriastradh      _mesa_reference_shader_program(ctx, &ctx->Shader.ActiveProgram, shProg);
15317ec681f3Smrg      _mesa_update_valid_to_render_state(ctx);
15323464ebd5Sriastradh   }
15333464ebd5Sriastradh}
15343464ebd5Sriastradh
15353464ebd5Sriastradh
15363464ebd5Sriastradh/**
15373464ebd5Sriastradh * Use the named shader program for subsequent rendering.
15383464ebd5Sriastradh */
15393464ebd5Sriastradhvoid
154001e04c3fSmrg_mesa_use_shader_program(struct gl_context *ctx,
154101e04c3fSmrg                         struct gl_shader_program *shProg)
15423464ebd5Sriastradh{
154301e04c3fSmrg   for (int i = 0; i < MESA_SHADER_STAGES; i++) {
154401e04c3fSmrg      struct gl_program *new_prog = NULL;
154501e04c3fSmrg      if (shProg && shProg->_LinkedShaders[i])
154601e04c3fSmrg         new_prog = shProg->_LinkedShaders[i]->Program;
154701e04c3fSmrg      _mesa_use_program(ctx, i, shProg, new_prog, &ctx->Shader);
154801e04c3fSmrg   }
15493464ebd5Sriastradh   _mesa_active_program(ctx, shProg, "glUseProgram");
15503464ebd5Sriastradh}
15513464ebd5Sriastradh
15523464ebd5Sriastradh
15533464ebd5Sriastradh/**
15543464ebd5Sriastradh * Do validation of the given shader program.
15553464ebd5Sriastradh * \param errMsg  returns error message if validation fails.
15563464ebd5Sriastradh * \return GL_TRUE if valid, GL_FALSE if invalid (and set errMsg)
15573464ebd5Sriastradh */
15583464ebd5Sriastradhstatic GLboolean
15593464ebd5Sriastradhvalidate_shader_program(const struct gl_shader_program *shProg,
15603464ebd5Sriastradh                        char *errMsg)
15613464ebd5Sriastradh{
156201e04c3fSmrg   if (!shProg->data->LinkStatus) {
15633464ebd5Sriastradh      return GL_FALSE;
15643464ebd5Sriastradh   }
15653464ebd5Sriastradh
15663464ebd5Sriastradh   /* From the GL spec, a program is invalid if any of these are true:
15673464ebd5Sriastradh
15683464ebd5Sriastradh     any two active samplers in the current program object are of
15693464ebd5Sriastradh     different types, but refer to the same texture image unit,
15703464ebd5Sriastradh
15713464ebd5Sriastradh     any active sampler in the current program object refers to a texture
15723464ebd5Sriastradh     image unit where fixed-function fragment processing accesses a
157301e04c3fSmrg     texture target that does not match the sampler type, or
15743464ebd5Sriastradh
15753464ebd5Sriastradh     the sum of the number of active samplers in the program and the
15763464ebd5Sriastradh     number of texture image units enabled for fixed-function fragment
15773464ebd5Sriastradh     processing exceeds the combined limit on the total number of texture
15783464ebd5Sriastradh     image units allowed.
15793464ebd5Sriastradh   */
15803464ebd5Sriastradh
15813464ebd5Sriastradh   /*
15823464ebd5Sriastradh    * Check: any two active samplers in the current program object are of
15833464ebd5Sriastradh    * different types, but refer to the same texture image unit,
15843464ebd5Sriastradh    */
1585af69d88dSmrg   if (!_mesa_sampler_uniforms_are_valid(shProg, errMsg, 100))
15863464ebd5Sriastradh      return GL_FALSE;
15873464ebd5Sriastradh
15883464ebd5Sriastradh   return GL_TRUE;
15893464ebd5Sriastradh}
15903464ebd5Sriastradh
15913464ebd5Sriastradh
15923464ebd5Sriastradh/**
15933464ebd5Sriastradh * Called via glValidateProgram()
15943464ebd5Sriastradh */
15953464ebd5Sriastradhstatic void
15963464ebd5Sriastradhvalidate_program(struct gl_context *ctx, GLuint program)
15973464ebd5Sriastradh{
15983464ebd5Sriastradh   struct gl_shader_program *shProg;
15993464ebd5Sriastradh   char errMsg[100] = "";
16003464ebd5Sriastradh
16013464ebd5Sriastradh   shProg = _mesa_lookup_shader_program_err(ctx, program, "glValidateProgram");
16023464ebd5Sriastradh   if (!shProg) {
16033464ebd5Sriastradh      return;
16043464ebd5Sriastradh   }
16053464ebd5Sriastradh
160601e04c3fSmrg   shProg->data->Validated = validate_shader_program(shProg, errMsg);
160701e04c3fSmrg   if (!shProg->data->Validated) {
16083464ebd5Sriastradh      /* update info log */
160901e04c3fSmrg      if (shProg->data->InfoLog) {
161001e04c3fSmrg         ralloc_free(shProg->data->InfoLog);
16113464ebd5Sriastradh      }
161201e04c3fSmrg      shProg->data->InfoLog = ralloc_strdup(shProg->data, errMsg);
16133464ebd5Sriastradh   }
16143464ebd5Sriastradh}
16153464ebd5Sriastradh
16163464ebd5Sriastradh
16173464ebd5Sriastradhvoid GLAPIENTRY
161801e04c3fSmrg_mesa_AttachObjectARB_no_error(GLhandleARB program, GLhandleARB shader)
16193464ebd5Sriastradh{
16203464ebd5Sriastradh   GET_CURRENT_CONTEXT(ctx);
162101e04c3fSmrg   attach_shader_no_error(ctx, program, shader);
162201e04c3fSmrg}
162301e04c3fSmrg
162401e04c3fSmrg
162501e04c3fSmrgvoid GLAPIENTRY
162601e04c3fSmrg_mesa_AttachObjectARB(GLhandleARB program, GLhandleARB shader)
162701e04c3fSmrg{
162801e04c3fSmrg   GET_CURRENT_CONTEXT(ctx);
162901e04c3fSmrg   attach_shader_err(ctx, program, shader, "glAttachObjectARB");
163001e04c3fSmrg}
163101e04c3fSmrg
163201e04c3fSmrg
163301e04c3fSmrgvoid GLAPIENTRY
163401e04c3fSmrg_mesa_AttachShader_no_error(GLuint program, GLuint shader)
163501e04c3fSmrg{
163601e04c3fSmrg   GET_CURRENT_CONTEXT(ctx);
163701e04c3fSmrg   attach_shader_no_error(ctx, program, shader);
16383464ebd5Sriastradh}
16393464ebd5Sriastradh
16403464ebd5Sriastradh
16413464ebd5Sriastradhvoid GLAPIENTRY
16423464ebd5Sriastradh_mesa_AttachShader(GLuint program, GLuint shader)
16433464ebd5Sriastradh{
16443464ebd5Sriastradh   GET_CURRENT_CONTEXT(ctx);
164501e04c3fSmrg   attach_shader_err(ctx, program, shader, "glAttachShader");
16463464ebd5Sriastradh}
16473464ebd5Sriastradh
16483464ebd5Sriastradh
16493464ebd5Sriastradhvoid GLAPIENTRY
165001e04c3fSmrg_mesa_CompileShader(GLuint shaderObj)
16513464ebd5Sriastradh{
16523464ebd5Sriastradh   GET_CURRENT_CONTEXT(ctx);
16533464ebd5Sriastradh   if (MESA_VERBOSE & VERBOSE_API)
16543464ebd5Sriastradh      _mesa_debug(ctx, "glCompileShader %u\n", shaderObj);
165501e04c3fSmrg   _mesa_compile_shader(ctx, _mesa_lookup_shader_err(ctx, shaderObj,
165601e04c3fSmrg                                                     "glCompileShader"));
165701e04c3fSmrg}
165801e04c3fSmrg
165901e04c3fSmrg
166001e04c3fSmrgGLuint GLAPIENTRY
166101e04c3fSmrg_mesa_CreateShader_no_error(GLenum type)
166201e04c3fSmrg{
166301e04c3fSmrg   GET_CURRENT_CONTEXT(ctx);
166401e04c3fSmrg   return create_shader(ctx, type);
16653464ebd5Sriastradh}
16663464ebd5Sriastradh
16673464ebd5Sriastradh
16683464ebd5SriastradhGLuint GLAPIENTRY
16693464ebd5Sriastradh_mesa_CreateShader(GLenum type)
16703464ebd5Sriastradh{
16713464ebd5Sriastradh   GET_CURRENT_CONTEXT(ctx);
167201e04c3fSmrg
16733464ebd5Sriastradh   if (MESA_VERBOSE & VERBOSE_API)
167401e04c3fSmrg      _mesa_debug(ctx, "glCreateShader %s\n", _mesa_enum_to_string(type));
167501e04c3fSmrg
167601e04c3fSmrg   return create_shader_err(ctx, type, "glCreateShader");
167701e04c3fSmrg}
167801e04c3fSmrg
167901e04c3fSmrg
168001e04c3fSmrgGLhandleARB GLAPIENTRY
168101e04c3fSmrg_mesa_CreateShaderObjectARB_no_error(GLenum type)
168201e04c3fSmrg{
168301e04c3fSmrg   GET_CURRENT_CONTEXT(ctx);
16843464ebd5Sriastradh   return create_shader(ctx, type);
16853464ebd5Sriastradh}
16863464ebd5Sriastradh
16873464ebd5Sriastradh
16883464ebd5SriastradhGLhandleARB GLAPIENTRY
16893464ebd5Sriastradh_mesa_CreateShaderObjectARB(GLenum type)
16903464ebd5Sriastradh{
16913464ebd5Sriastradh   GET_CURRENT_CONTEXT(ctx);
169201e04c3fSmrg   return create_shader_err(ctx, type, "glCreateShaderObjectARB");
16933464ebd5Sriastradh}
16943464ebd5Sriastradh
16953464ebd5Sriastradh
16963464ebd5SriastradhGLuint GLAPIENTRY
16973464ebd5Sriastradh_mesa_CreateProgram(void)
16983464ebd5Sriastradh{
16993464ebd5Sriastradh   GET_CURRENT_CONTEXT(ctx);
17003464ebd5Sriastradh   if (MESA_VERBOSE & VERBOSE_API)
17013464ebd5Sriastradh      _mesa_debug(ctx, "glCreateProgram\n");
17023464ebd5Sriastradh   return create_shader_program(ctx);
17033464ebd5Sriastradh}
17043464ebd5Sriastradh
17053464ebd5Sriastradh
17063464ebd5SriastradhGLhandleARB GLAPIENTRY
17073464ebd5Sriastradh_mesa_CreateProgramObjectARB(void)
17083464ebd5Sriastradh{
17093464ebd5Sriastradh   GET_CURRENT_CONTEXT(ctx);
17103464ebd5Sriastradh   return create_shader_program(ctx);
17113464ebd5Sriastradh}
17123464ebd5Sriastradh
17133464ebd5Sriastradh
17143464ebd5Sriastradhvoid GLAPIENTRY
17153464ebd5Sriastradh_mesa_DeleteObjectARB(GLhandleARB obj)
17163464ebd5Sriastradh{
17173464ebd5Sriastradh   if (MESA_VERBOSE & VERBOSE_API) {
17183464ebd5Sriastradh      GET_CURRENT_CONTEXT(ctx);
171901e04c3fSmrg      _mesa_debug(ctx, "glDeleteObjectARB(%lu)\n", (unsigned long)obj);
17203464ebd5Sriastradh   }
17213464ebd5Sriastradh
17223464ebd5Sriastradh   if (obj) {
17233464ebd5Sriastradh      GET_CURRENT_CONTEXT(ctx);
17247ec681f3Smrg      FLUSH_VERTICES(ctx, 0, 0);
17253464ebd5Sriastradh      if (is_program(ctx, obj)) {
17263464ebd5Sriastradh         delete_shader_program(ctx, obj);
17273464ebd5Sriastradh      }
17283464ebd5Sriastradh      else if (is_shader(ctx, obj)) {
17293464ebd5Sriastradh         delete_shader(ctx, obj);
17303464ebd5Sriastradh      }
17313464ebd5Sriastradh      else {
17323464ebd5Sriastradh         /* error? */
17333464ebd5Sriastradh      }
17343464ebd5Sriastradh   }
17353464ebd5Sriastradh}
17363464ebd5Sriastradh
17373464ebd5Sriastradh
17383464ebd5Sriastradhvoid GLAPIENTRY
17393464ebd5Sriastradh_mesa_DeleteProgram(GLuint name)
17403464ebd5Sriastradh{
17413464ebd5Sriastradh   if (name) {
17423464ebd5Sriastradh      GET_CURRENT_CONTEXT(ctx);
17437ec681f3Smrg      FLUSH_VERTICES(ctx, 0, 0);
17443464ebd5Sriastradh      delete_shader_program(ctx, name);
17453464ebd5Sriastradh   }
17463464ebd5Sriastradh}
17473464ebd5Sriastradh
17483464ebd5Sriastradh
17493464ebd5Sriastradhvoid GLAPIENTRY
17503464ebd5Sriastradh_mesa_DeleteShader(GLuint name)
17513464ebd5Sriastradh{
17523464ebd5Sriastradh   if (name) {
17533464ebd5Sriastradh      GET_CURRENT_CONTEXT(ctx);
17547ec681f3Smrg      FLUSH_VERTICES(ctx, 0, 0);
17553464ebd5Sriastradh      delete_shader(ctx, name);
17563464ebd5Sriastradh   }
17573464ebd5Sriastradh}
17583464ebd5Sriastradh
17593464ebd5Sriastradh
176001e04c3fSmrgvoid GLAPIENTRY
176101e04c3fSmrg_mesa_DetachObjectARB_no_error(GLhandleARB program, GLhandleARB shader)
176201e04c3fSmrg{
176301e04c3fSmrg   GET_CURRENT_CONTEXT(ctx);
176401e04c3fSmrg   detach_shader_no_error(ctx, program, shader);
176501e04c3fSmrg}
176601e04c3fSmrg
176701e04c3fSmrg
17683464ebd5Sriastradhvoid GLAPIENTRY
17693464ebd5Sriastradh_mesa_DetachObjectARB(GLhandleARB program, GLhandleARB shader)
17703464ebd5Sriastradh{
17713464ebd5Sriastradh   GET_CURRENT_CONTEXT(ctx);
177201e04c3fSmrg   detach_shader_error(ctx, program, shader);
177301e04c3fSmrg}
177401e04c3fSmrg
177501e04c3fSmrg
177601e04c3fSmrgvoid GLAPIENTRY
177701e04c3fSmrg_mesa_DetachShader_no_error(GLuint program, GLuint shader)
177801e04c3fSmrg{
177901e04c3fSmrg   GET_CURRENT_CONTEXT(ctx);
178001e04c3fSmrg   detach_shader_no_error(ctx, program, shader);
17813464ebd5Sriastradh}
17823464ebd5Sriastradh
17833464ebd5Sriastradh
17843464ebd5Sriastradhvoid GLAPIENTRY
17853464ebd5Sriastradh_mesa_DetachShader(GLuint program, GLuint shader)
17863464ebd5Sriastradh{
17873464ebd5Sriastradh   GET_CURRENT_CONTEXT(ctx);
178801e04c3fSmrg   detach_shader_error(ctx, program, shader);
17893464ebd5Sriastradh}
17903464ebd5Sriastradh
17913464ebd5Sriastradh
17923464ebd5Sriastradhvoid GLAPIENTRY
17933464ebd5Sriastradh_mesa_GetAttachedObjectsARB(GLhandleARB container, GLsizei maxCount,
17943464ebd5Sriastradh                            GLsizei * count, GLhandleARB * obj)
17953464ebd5Sriastradh{
17963464ebd5Sriastradh   GET_CURRENT_CONTEXT(ctx);
179701e04c3fSmrg   get_attached_shaders(ctx, (GLuint)container, maxCount, count, NULL, obj);
17983464ebd5Sriastradh}
17993464ebd5Sriastradh
18003464ebd5Sriastradh
18013464ebd5Sriastradhvoid GLAPIENTRY
18023464ebd5Sriastradh_mesa_GetAttachedShaders(GLuint program, GLsizei maxCount,
18033464ebd5Sriastradh                         GLsizei *count, GLuint *obj)
18043464ebd5Sriastradh{
18053464ebd5Sriastradh   GET_CURRENT_CONTEXT(ctx);
180601e04c3fSmrg   get_attached_shaders(ctx, program, maxCount, count, obj, NULL);
18073464ebd5Sriastradh}
18083464ebd5Sriastradh
18093464ebd5Sriastradh
18103464ebd5Sriastradhvoid GLAPIENTRY
18113464ebd5Sriastradh_mesa_GetInfoLogARB(GLhandleARB object, GLsizei maxLength, GLsizei * length,
18123464ebd5Sriastradh                    GLcharARB * infoLog)
18133464ebd5Sriastradh{
18143464ebd5Sriastradh   GET_CURRENT_CONTEXT(ctx);
18153464ebd5Sriastradh   if (is_program(ctx, object)) {
18163464ebd5Sriastradh      get_program_info_log(ctx, object, maxLength, length, infoLog);
18173464ebd5Sriastradh   }
18183464ebd5Sriastradh   else if (is_shader(ctx, object)) {
18193464ebd5Sriastradh      get_shader_info_log(ctx, object, maxLength, length, infoLog);
18203464ebd5Sriastradh   }
18213464ebd5Sriastradh   else {
18223464ebd5Sriastradh      _mesa_error(ctx, GL_INVALID_OPERATION, "glGetInfoLogARB");
18233464ebd5Sriastradh   }
18243464ebd5Sriastradh}
18253464ebd5Sriastradh
18263464ebd5Sriastradh
18273464ebd5Sriastradhvoid GLAPIENTRY
18283464ebd5Sriastradh_mesa_GetObjectParameterivARB(GLhandleARB object, GLenum pname, GLint *params)
18293464ebd5Sriastradh{
18303464ebd5Sriastradh   GET_CURRENT_CONTEXT(ctx);
18313464ebd5Sriastradh   /* Implement in terms of GetProgramiv, GetShaderiv */
18323464ebd5Sriastradh   if (is_program(ctx, object)) {
18333464ebd5Sriastradh      if (pname == GL_OBJECT_TYPE_ARB) {
18343464ebd5Sriastradh	 *params = GL_PROGRAM_OBJECT_ARB;
18353464ebd5Sriastradh      }
18363464ebd5Sriastradh      else {
18373464ebd5Sriastradh	 get_programiv(ctx, object, pname, params);
18383464ebd5Sriastradh      }
18393464ebd5Sriastradh   }
18403464ebd5Sriastradh   else if (is_shader(ctx, object)) {
18413464ebd5Sriastradh      if (pname == GL_OBJECT_TYPE_ARB) {
18423464ebd5Sriastradh	 *params = GL_SHADER_OBJECT_ARB;
18433464ebd5Sriastradh      }
18443464ebd5Sriastradh      else {
18453464ebd5Sriastradh	 get_shaderiv(ctx, object, pname, params);
18463464ebd5Sriastradh      }
18473464ebd5Sriastradh   }
18483464ebd5Sriastradh   else {
18493464ebd5Sriastradh      _mesa_error(ctx, GL_INVALID_VALUE, "glGetObjectParameterivARB");
18503464ebd5Sriastradh   }
18513464ebd5Sriastradh}
18523464ebd5Sriastradh
18533464ebd5Sriastradh
18543464ebd5Sriastradhvoid GLAPIENTRY
18553464ebd5Sriastradh_mesa_GetObjectParameterfvARB(GLhandleARB object, GLenum pname,
18563464ebd5Sriastradh                              GLfloat *params)
18573464ebd5Sriastradh{
185801e04c3fSmrg   GLint iparams[1] = {0};  /* XXX is one element enough? */
18593464ebd5Sriastradh   _mesa_GetObjectParameterivARB(object, pname, iparams);
18603464ebd5Sriastradh   params[0] = (GLfloat) iparams[0];
18613464ebd5Sriastradh}
18623464ebd5Sriastradh
18633464ebd5Sriastradh
18643464ebd5Sriastradhvoid GLAPIENTRY
18653464ebd5Sriastradh_mesa_GetProgramiv(GLuint program, GLenum pname, GLint *params)
18663464ebd5Sriastradh{
18673464ebd5Sriastradh   GET_CURRENT_CONTEXT(ctx);
18683464ebd5Sriastradh   get_programiv(ctx, program, pname, params);
18693464ebd5Sriastradh}
18703464ebd5Sriastradh
18713464ebd5Sriastradh
18723464ebd5Sriastradhvoid GLAPIENTRY
18733464ebd5Sriastradh_mesa_GetShaderiv(GLuint shader, GLenum pname, GLint *params)
18743464ebd5Sriastradh{
18753464ebd5Sriastradh   GET_CURRENT_CONTEXT(ctx);
18763464ebd5Sriastradh   get_shaderiv(ctx, shader, pname, params);
18773464ebd5Sriastradh}
18783464ebd5Sriastradh
18793464ebd5Sriastradh
18803464ebd5Sriastradhvoid GLAPIENTRY
18813464ebd5Sriastradh_mesa_GetProgramInfoLog(GLuint program, GLsizei bufSize,
18823464ebd5Sriastradh                        GLsizei *length, GLchar *infoLog)
18833464ebd5Sriastradh{
18843464ebd5Sriastradh   GET_CURRENT_CONTEXT(ctx);
18853464ebd5Sriastradh   get_program_info_log(ctx, program, bufSize, length, infoLog);
18863464ebd5Sriastradh}
18873464ebd5Sriastradh
18883464ebd5Sriastradh
18893464ebd5Sriastradhvoid GLAPIENTRY
18903464ebd5Sriastradh_mesa_GetShaderInfoLog(GLuint shader, GLsizei bufSize,
18913464ebd5Sriastradh                       GLsizei *length, GLchar *infoLog)
18923464ebd5Sriastradh{
18933464ebd5Sriastradh   GET_CURRENT_CONTEXT(ctx);
18943464ebd5Sriastradh   get_shader_info_log(ctx, shader, bufSize, length, infoLog);
18953464ebd5Sriastradh}
18963464ebd5Sriastradh
18973464ebd5Sriastradh
18983464ebd5Sriastradhvoid GLAPIENTRY
189901e04c3fSmrg_mesa_GetShaderSource(GLuint shader, GLsizei maxLength,
190001e04c3fSmrg                      GLsizei *length, GLchar *sourceOut)
19013464ebd5Sriastradh{
19023464ebd5Sriastradh   GET_CURRENT_CONTEXT(ctx);
19033464ebd5Sriastradh   get_shader_source(ctx, shader, maxLength, length, sourceOut);
19043464ebd5Sriastradh}
19053464ebd5Sriastradh
19063464ebd5Sriastradh
19073464ebd5SriastradhGLhandleARB GLAPIENTRY
19083464ebd5Sriastradh_mesa_GetHandleARB(GLenum pname)
19093464ebd5Sriastradh{
19103464ebd5Sriastradh   GET_CURRENT_CONTEXT(ctx);
19113464ebd5Sriastradh   return get_handle(ctx, pname);
19123464ebd5Sriastradh}
19133464ebd5Sriastradh
19143464ebd5Sriastradh
19153464ebd5SriastradhGLboolean GLAPIENTRY
19163464ebd5Sriastradh_mesa_IsProgram(GLuint name)
19173464ebd5Sriastradh{
19183464ebd5Sriastradh   GET_CURRENT_CONTEXT(ctx);
19193464ebd5Sriastradh   return is_program(ctx, name);
19203464ebd5Sriastradh}
19213464ebd5Sriastradh
19223464ebd5Sriastradh
19233464ebd5SriastradhGLboolean GLAPIENTRY
19243464ebd5Sriastradh_mesa_IsShader(GLuint name)
19253464ebd5Sriastradh{
19263464ebd5Sriastradh   GET_CURRENT_CONTEXT(ctx);
19273464ebd5Sriastradh   return is_shader(ctx, name);
19283464ebd5Sriastradh}
19293464ebd5Sriastradh
19303464ebd5Sriastradh
19313464ebd5Sriastradhvoid GLAPIENTRY
193201e04c3fSmrg_mesa_LinkProgram_no_error(GLuint programObj)
193301e04c3fSmrg{
193401e04c3fSmrg   GET_CURRENT_CONTEXT(ctx);
193501e04c3fSmrg
193601e04c3fSmrg   struct gl_shader_program *shProg =
193701e04c3fSmrg      _mesa_lookup_shader_program(ctx, programObj);
193801e04c3fSmrg   link_program_no_error(ctx, shProg);
193901e04c3fSmrg}
194001e04c3fSmrg
194101e04c3fSmrg
194201e04c3fSmrgvoid GLAPIENTRY
194301e04c3fSmrg_mesa_LinkProgram(GLuint programObj)
19443464ebd5Sriastradh{
19453464ebd5Sriastradh   GET_CURRENT_CONTEXT(ctx);
194601e04c3fSmrg
194701e04c3fSmrg   if (MESA_VERBOSE & VERBOSE_API)
194801e04c3fSmrg      _mesa_debug(ctx, "glLinkProgram %u\n", programObj);
194901e04c3fSmrg
195001e04c3fSmrg   struct gl_shader_program *shProg =
195101e04c3fSmrg      _mesa_lookup_shader_program_err(ctx, programObj, "glLinkProgram");
195201e04c3fSmrg   link_program_error(ctx, shProg);
195301e04c3fSmrg}
195401e04c3fSmrg
195501e04c3fSmrg#ifdef ENABLE_SHADER_CACHE
195601e04c3fSmrg/**
195701e04c3fSmrg * Generate a SHA-1 hash value string for given source string.
195801e04c3fSmrg */
19597ec681f3Smrgstatic char *
196001e04c3fSmrggenerate_sha1(const char *source, char sha_str[64])
196101e04c3fSmrg{
196201e04c3fSmrg   unsigned char sha[20];
196301e04c3fSmrg   _mesa_sha1_compute(source, strlen(source), sha);
196401e04c3fSmrg   _mesa_sha1_format(sha_str, sha);
19657ec681f3Smrg   return sha_str;
196601e04c3fSmrg}
196701e04c3fSmrg
196801e04c3fSmrg/**
196901e04c3fSmrg * Construct a full path for shader replacement functionality using
197001e04c3fSmrg * following format:
197101e04c3fSmrg *
197201e04c3fSmrg * <path>/<stage prefix>_<CHECKSUM>.glsl
197301e04c3fSmrg * <path>/<stage prefix>_<CHECKSUM>.arb
197401e04c3fSmrg */
197501e04c3fSmrgstatic char *
19767ec681f3Smrgconstruct_name(const gl_shader_stage stage, const char *sha,
19777ec681f3Smrg               const char *source, const char *path)
197801e04c3fSmrg{
197901e04c3fSmrg   static const char *types[] = {
198001e04c3fSmrg      "VS", "TC", "TE", "GS", "FS", "CS",
198101e04c3fSmrg   };
198201e04c3fSmrg
198301e04c3fSmrg   const char *format = strncmp(source, "!!ARB", 5) ? "glsl" : "arb";
198401e04c3fSmrg
198501e04c3fSmrg   return ralloc_asprintf(NULL, "%s/%s_%s.%s", path, types[stage], sha, format);
19863464ebd5Sriastradh}
19873464ebd5Sriastradh
198801e04c3fSmrg/**
198901e04c3fSmrg * Write given shader source to a file in MESA_SHADER_DUMP_PATH.
199001e04c3fSmrg */
199101e04c3fSmrgvoid
199201e04c3fSmrg_mesa_dump_shader_source(const gl_shader_stage stage, const char *source)
199301e04c3fSmrg{
19947ec681f3Smrg#ifndef CUSTOM_SHADER_REPLACEMENT
199501e04c3fSmrg   static bool path_exists = true;
199601e04c3fSmrg   char *dump_path;
199701e04c3fSmrg   FILE *f;
19987ec681f3Smrg   char sha[64];
199901e04c3fSmrg
200001e04c3fSmrg   if (!path_exists)
200101e04c3fSmrg      return;
200201e04c3fSmrg
200301e04c3fSmrg   dump_path = getenv("MESA_SHADER_DUMP_PATH");
200401e04c3fSmrg   if (!dump_path) {
200501e04c3fSmrg      path_exists = false;
200601e04c3fSmrg      return;
200701e04c3fSmrg   }
20083464ebd5Sriastradh
20097ec681f3Smrg   char *name = construct_name(stage, generate_sha1(source, sha),
20107ec681f3Smrg                               source, dump_path);
201101e04c3fSmrg
201201e04c3fSmrg   f = fopen(name, "w");
201301e04c3fSmrg   if (f) {
201401e04c3fSmrg      fputs(source, f);
201501e04c3fSmrg      fclose(f);
201601e04c3fSmrg   } else {
201701e04c3fSmrg      GET_CURRENT_CONTEXT(ctx);
201801e04c3fSmrg      _mesa_warning(ctx, "could not open %s for dumping shader (%s)", name,
201901e04c3fSmrg                    strerror(errno));
202001e04c3fSmrg   }
202101e04c3fSmrg   ralloc_free(name);
20227ec681f3Smrg#endif
202301e04c3fSmrg}
20243464ebd5Sriastradh
20253464ebd5Sriastradh/**
20263464ebd5Sriastradh * Read shader source code from a file.
20273464ebd5Sriastradh * Useful for debugging to override an app's shader.
20283464ebd5Sriastradh */
202901e04c3fSmrgGLcharARB *
203001e04c3fSmrg_mesa_read_shader_source(const gl_shader_stage stage, const char *source)
20313464ebd5Sriastradh{
203201e04c3fSmrg   char *read_path;
203301e04c3fSmrg   static bool path_exists = true;
203401e04c3fSmrg   int len, shader_size = 0;
203501e04c3fSmrg   GLcharARB *buffer;
203601e04c3fSmrg   FILE *f;
20377ec681f3Smrg   char sha[64];
20387ec681f3Smrg
20397ec681f3Smrg   generate_sha1(source, sha);
20407ec681f3Smrg
20417ec681f3Smrg   if (!debug_get_bool_option("MESA_NO_SHADER_REPLACEMENT", false)) {
20427ec681f3Smrg      const char *process_name =
20437ec681f3Smrg         ARRAY_SIZE(shader_replacements) ? util_get_process_name() : NULL;
20447ec681f3Smrg      for (size_t i = 0; i < ARRAY_SIZE(shader_replacements); i++) {
20457ec681f3Smrg         if (stage != shader_replacements[i].stage)
20467ec681f3Smrg            continue;
20477ec681f3Smrg
20487ec681f3Smrg         if (shader_replacements[i].app &&
20497ec681f3Smrg             strcmp(process_name, shader_replacements[i].app) != 0)
20507ec681f3Smrg            continue;
20517ec681f3Smrg
20527ec681f3Smrg         if (memcmp(sha, shader_replacements[i].sha1, 40) != 0)
20537ec681f3Smrg            continue;
20547ec681f3Smrg
20557ec681f3Smrg         return load_shader_replacement(&shader_replacements[i]);
20567ec681f3Smrg      }
20577ec681f3Smrg   }
205801e04c3fSmrg
205901e04c3fSmrg   if (!path_exists)
206001e04c3fSmrg      return NULL;
20613464ebd5Sriastradh
206201e04c3fSmrg   read_path = getenv("MESA_SHADER_READ_PATH");
206301e04c3fSmrg   if (!read_path) {
206401e04c3fSmrg      path_exists = false;
20653464ebd5Sriastradh      return NULL;
20663464ebd5Sriastradh   }
20673464ebd5Sriastradh
20687ec681f3Smrg   char *name = construct_name(stage, sha, source, read_path);
206901e04c3fSmrg   f = fopen(name, "r");
207001e04c3fSmrg   ralloc_free(name);
207101e04c3fSmrg   if (!f)
207201e04c3fSmrg      return NULL;
207301e04c3fSmrg
2074af69d88dSmrg   /* allocate enough room for the entire shader */
2075af69d88dSmrg   fseek(f, 0, SEEK_END);
2076af69d88dSmrg   shader_size = ftell(f);
2077af69d88dSmrg   rewind(f);
2078af69d88dSmrg   assert(shader_size);
2079af69d88dSmrg
2080af69d88dSmrg   /* add one for terminating zero */
2081af69d88dSmrg   shader_size++;
2082af69d88dSmrg
2083af69d88dSmrg   buffer = malloc(shader_size);
2084af69d88dSmrg   assert(buffer);
2085af69d88dSmrg
2086af69d88dSmrg   len = fread(buffer, 1, shader_size, f);
20873464ebd5Sriastradh   buffer[len] = 0;
20883464ebd5Sriastradh
20893464ebd5Sriastradh   fclose(f);
20903464ebd5Sriastradh
209101e04c3fSmrg   return buffer;
20923464ebd5Sriastradh}
20933464ebd5Sriastradh
209401e04c3fSmrg#endif /* ENABLE_SHADER_CACHE */
20953464ebd5Sriastradh
20963464ebd5Sriastradh/**
20973464ebd5Sriastradh * Called via glShaderSource() and glShaderSourceARB() API functions.
20983464ebd5Sriastradh * Basically, concatenate the source code strings into one long string
20993464ebd5Sriastradh * and pass it to _mesa_shader_source().
21003464ebd5Sriastradh */
210101e04c3fSmrgstatic ALWAYS_INLINE void
210201e04c3fSmrgshader_source(struct gl_context *ctx, GLuint shaderObj, GLsizei count,
210301e04c3fSmrg              const GLchar *const *string, const GLint *length, bool no_error)
21043464ebd5Sriastradh{
21053464ebd5Sriastradh   GLint *offsets;
21063464ebd5Sriastradh   GLsizei i, totalLength;
21073464ebd5Sriastradh   GLcharARB *source;
210801e04c3fSmrg   struct gl_shader *sh;
21093464ebd5Sriastradh
211001e04c3fSmrg   if (!no_error) {
211101e04c3fSmrg      sh = _mesa_lookup_shader_err(ctx, shaderObj, "glShaderSourceARB");
211201e04c3fSmrg      if (!sh)
211301e04c3fSmrg         return;
211401e04c3fSmrg
21157ec681f3Smrg      if (string == NULL || count < 0) {
211601e04c3fSmrg         _mesa_error(ctx, GL_INVALID_VALUE, "glShaderSourceARB");
211701e04c3fSmrg         return;
211801e04c3fSmrg      }
211901e04c3fSmrg   } else {
212001e04c3fSmrg      sh = _mesa_lookup_shader(ctx, shaderObj);
21213464ebd5Sriastradh   }
21223464ebd5Sriastradh
21237ec681f3Smrg   /* Return silently the spec doesn't define this as an error */
21247ec681f3Smrg   if (count == 0)
21257ec681f3Smrg      return;
21267ec681f3Smrg
21273464ebd5Sriastradh   /*
21283464ebd5Sriastradh    * This array holds offsets of where the appropriate string ends, thus the
21293464ebd5Sriastradh    * last element will be set to the total length of the source code.
21303464ebd5Sriastradh    */
21317ec681f3Smrg   offsets = calloc(count, sizeof(GLint));
21323464ebd5Sriastradh   if (offsets == NULL) {
21333464ebd5Sriastradh      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glShaderSourceARB");
21343464ebd5Sriastradh      return;
21353464ebd5Sriastradh   }
21363464ebd5Sriastradh
21373464ebd5Sriastradh   for (i = 0; i < count; i++) {
213801e04c3fSmrg      if (!no_error && string[i] == NULL) {
21393464ebd5Sriastradh         free((GLvoid *) offsets);
21403464ebd5Sriastradh         _mesa_error(ctx, GL_INVALID_OPERATION,
21413464ebd5Sriastradh                     "glShaderSourceARB(null string)");
21423464ebd5Sriastradh         return;
21433464ebd5Sriastradh      }
21443464ebd5Sriastradh      if (length == NULL || length[i] < 0)
21453464ebd5Sriastradh         offsets[i] = strlen(string[i]);
21463464ebd5Sriastradh      else
21473464ebd5Sriastradh         offsets[i] = length[i];
21483464ebd5Sriastradh      /* accumulate string lengths */
21493464ebd5Sriastradh      if (i > 0)
21503464ebd5Sriastradh         offsets[i] += offsets[i - 1];
21513464ebd5Sriastradh   }
21523464ebd5Sriastradh
21533464ebd5Sriastradh   /* Total length of source string is sum off all strings plus two.
21543464ebd5Sriastradh    * One extra byte for terminating zero, another extra byte to silence
21553464ebd5Sriastradh    * valgrind warnings in the parser/grammer code.
21563464ebd5Sriastradh    */
21573464ebd5Sriastradh   totalLength = offsets[count - 1] + 2;
2158af69d88dSmrg   source = malloc(totalLength * sizeof(GLcharARB));
21593464ebd5Sriastradh   if (source == NULL) {
21603464ebd5Sriastradh      free((GLvoid *) offsets);
21613464ebd5Sriastradh      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glShaderSourceARB");
21623464ebd5Sriastradh      return;
21633464ebd5Sriastradh   }
21643464ebd5Sriastradh
21653464ebd5Sriastradh   for (i = 0; i < count; i++) {
21663464ebd5Sriastradh      GLint start = (i > 0) ? offsets[i - 1] : 0;
21673464ebd5Sriastradh      memcpy(source + start, string[i],
21683464ebd5Sriastradh             (offsets[i] - start) * sizeof(GLcharARB));
21693464ebd5Sriastradh   }
21703464ebd5Sriastradh   source[totalLength - 1] = '\0';
21713464ebd5Sriastradh   source[totalLength - 2] = '\0';
21723464ebd5Sriastradh
217301e04c3fSmrg#ifdef ENABLE_SHADER_CACHE
217401e04c3fSmrg   GLcharARB *replacement;
21753464ebd5Sriastradh
217601e04c3fSmrg   /* Dump original shader source to MESA_SHADER_DUMP_PATH and replace
217701e04c3fSmrg    * if corresponding entry found from MESA_SHADER_READ_PATH.
217801e04c3fSmrg    */
217901e04c3fSmrg   _mesa_dump_shader_source(sh->Stage, source);
21803464ebd5Sriastradh
218101e04c3fSmrg   replacement = _mesa_read_shader_source(sh->Stage, source);
218201e04c3fSmrg   if (replacement) {
218301e04c3fSmrg      free(source);
218401e04c3fSmrg      source = replacement;
21853464ebd5Sriastradh   }
218601e04c3fSmrg#endif /* ENABLE_SHADER_CACHE */
21873464ebd5Sriastradh
218801e04c3fSmrg   set_shader_source(sh, source);
21893464ebd5Sriastradh
21903464ebd5Sriastradh   free(offsets);
21913464ebd5Sriastradh}
21923464ebd5Sriastradh
21933464ebd5Sriastradh
21943464ebd5Sriastradhvoid GLAPIENTRY
219501e04c3fSmrg_mesa_ShaderSource_no_error(GLuint shaderObj, GLsizei count,
219601e04c3fSmrg                            const GLchar *const *string, const GLint *length)
21973464ebd5Sriastradh{
21983464ebd5Sriastradh   GET_CURRENT_CONTEXT(ctx);
219901e04c3fSmrg   shader_source(ctx, shaderObj, count, string, length, true);
220001e04c3fSmrg}
22013464ebd5Sriastradh
22023464ebd5Sriastradh
220301e04c3fSmrgvoid GLAPIENTRY
220401e04c3fSmrg_mesa_ShaderSource(GLuint shaderObj, GLsizei count,
220501e04c3fSmrg                   const GLchar *const *string, const GLint *length)
220601e04c3fSmrg{
220701e04c3fSmrg   GET_CURRENT_CONTEXT(ctx);
220801e04c3fSmrg   shader_source(ctx, shaderObj, count, string, length, false);
220901e04c3fSmrg}
221001e04c3fSmrg
221101e04c3fSmrg
221201e04c3fSmrgstatic ALWAYS_INLINE void
221301e04c3fSmrguse_program(GLuint program, bool no_error)
221401e04c3fSmrg{
221501e04c3fSmrg   GET_CURRENT_CONTEXT(ctx);
221601e04c3fSmrg   struct gl_shader_program *shProg = NULL;
221701e04c3fSmrg
221801e04c3fSmrg   if (MESA_VERBOSE & VERBOSE_API)
221901e04c3fSmrg      _mesa_debug(ctx, "glUseProgram %u\n", program);
222001e04c3fSmrg
222101e04c3fSmrg   if (no_error) {
222201e04c3fSmrg      if (program) {
222301e04c3fSmrg         shProg = _mesa_lookup_shader_program(ctx, program);
22243464ebd5Sriastradh      }
222501e04c3fSmrg   } else {
222601e04c3fSmrg      if (_mesa_is_xfb_active_and_unpaused(ctx)) {
22273464ebd5Sriastradh         _mesa_error(ctx, GL_INVALID_OPERATION,
222801e04c3fSmrg                     "glUseProgram(transform feedback active)");
22293464ebd5Sriastradh         return;
22303464ebd5Sriastradh      }
22313464ebd5Sriastradh
223201e04c3fSmrg      if (program) {
223301e04c3fSmrg         shProg =
223401e04c3fSmrg            _mesa_lookup_shader_program_err(ctx, program, "glUseProgram");
223501e04c3fSmrg         if (!shProg)
223601e04c3fSmrg            return;
223701e04c3fSmrg
223801e04c3fSmrg         if (!shProg->data->LinkStatus) {
223901e04c3fSmrg            _mesa_error(ctx, GL_INVALID_OPERATION,
224001e04c3fSmrg                        "glUseProgram(program %u not linked)", program);
224101e04c3fSmrg            return;
224201e04c3fSmrg         }
224301e04c3fSmrg
224401e04c3fSmrg         /* debug code */
224501e04c3fSmrg         if (ctx->_Shader->Flags & GLSL_USE_PROG) {
224601e04c3fSmrg            print_shader_info(shProg);
224701e04c3fSmrg         }
22483464ebd5Sriastradh      }
22493464ebd5Sriastradh   }
22503464ebd5Sriastradh
2251af69d88dSmrg   /* The ARB_separate_shader_object spec says:
2252af69d88dSmrg    *
2253af69d88dSmrg    *     "The executable code for an individual shader stage is taken from
2254af69d88dSmrg    *     the current program for that stage.  If there is a current program
2255af69d88dSmrg    *     object established by UseProgram, that program is considered current
2256af69d88dSmrg    *     for all stages.  Otherwise, if there is a bound program pipeline
2257af69d88dSmrg    *     object (section 2.14.PPO), the program bound to the appropriate
2258af69d88dSmrg    *     stage of the pipeline object is considered current."
2259af69d88dSmrg    */
226001e04c3fSmrg   if (shProg) {
2261af69d88dSmrg      /* Attach shader state to the binding point */
2262af69d88dSmrg      _mesa_reference_pipeline_object(ctx, &ctx->_Shader, &ctx->Shader);
2263af69d88dSmrg      /* Update the program */
226401e04c3fSmrg      _mesa_use_shader_program(ctx, shProg);
2265af69d88dSmrg   } else {
2266af69d88dSmrg      /* Must be done first: detach the progam */
226701e04c3fSmrg      _mesa_use_shader_program(ctx, shProg);
2268af69d88dSmrg      /* Unattach shader_state binding point */
226901e04c3fSmrg      _mesa_reference_pipeline_object(ctx, &ctx->_Shader,
227001e04c3fSmrg                                      ctx->Pipeline.Default);
2271af69d88dSmrg      /* If a pipeline was bound, rebind it */
2272af69d88dSmrg      if (ctx->Pipeline.Current) {
227301e04c3fSmrg         if (no_error)
227401e04c3fSmrg            _mesa_BindProgramPipeline_no_error(ctx->Pipeline.Current->Name);
227501e04c3fSmrg         else
227601e04c3fSmrg            _mesa_BindProgramPipeline(ctx->Pipeline.Current->Name);
2277af69d88dSmrg      }
2278af69d88dSmrg   }
227901e04c3fSmrg
228001e04c3fSmrg   _mesa_update_vertex_processing_mode(ctx);
228101e04c3fSmrg}
228201e04c3fSmrg
228301e04c3fSmrg
228401e04c3fSmrgvoid GLAPIENTRY
228501e04c3fSmrg_mesa_UseProgram_no_error(GLuint program)
228601e04c3fSmrg{
228701e04c3fSmrg   use_program(program, true);
22883464ebd5Sriastradh}
22893464ebd5Sriastradh
22903464ebd5Sriastradh
22913464ebd5Sriastradhvoid GLAPIENTRY
229201e04c3fSmrg_mesa_UseProgram(GLuint program)
229301e04c3fSmrg{
229401e04c3fSmrg   use_program(program, false);
229501e04c3fSmrg}
229601e04c3fSmrg
229701e04c3fSmrg
229801e04c3fSmrgvoid GLAPIENTRY
229901e04c3fSmrg_mesa_ValidateProgram(GLuint program)
23003464ebd5Sriastradh{
23013464ebd5Sriastradh   GET_CURRENT_CONTEXT(ctx);
23023464ebd5Sriastradh   validate_program(ctx, program);
23033464ebd5Sriastradh}
23043464ebd5Sriastradh
23053464ebd5Sriastradh
2306af69d88dSmrg/**
2307af69d88dSmrg * For OpenGL ES 2.0, GL_ARB_ES2_compatibility
2308af69d88dSmrg */
23093464ebd5Sriastradhvoid GLAPIENTRY
23103464ebd5Sriastradh_mesa_GetShaderPrecisionFormat(GLenum shadertype, GLenum precisiontype,
23113464ebd5Sriastradh                               GLint* range, GLint* precision)
23123464ebd5Sriastradh{
23133464ebd5Sriastradh   const struct gl_program_constants *limits;
23143464ebd5Sriastradh   const struct gl_precision *p;
23153464ebd5Sriastradh   GET_CURRENT_CONTEXT(ctx);
23163464ebd5Sriastradh
23173464ebd5Sriastradh   switch (shadertype) {
23183464ebd5Sriastradh   case GL_VERTEX_SHADER:
2319af69d88dSmrg      limits = &ctx->Const.Program[MESA_SHADER_VERTEX];
23203464ebd5Sriastradh      break;
23213464ebd5Sriastradh   case GL_FRAGMENT_SHADER:
2322af69d88dSmrg      limits = &ctx->Const.Program[MESA_SHADER_FRAGMENT];
23233464ebd5Sriastradh      break;
23243464ebd5Sriastradh   default:
23253464ebd5Sriastradh      _mesa_error(ctx, GL_INVALID_ENUM,
23263464ebd5Sriastradh                  "glGetShaderPrecisionFormat(shadertype)");
23273464ebd5Sriastradh      return;
23283464ebd5Sriastradh   }
23293464ebd5Sriastradh
23303464ebd5Sriastradh   switch (precisiontype) {
23313464ebd5Sriastradh   case GL_LOW_FLOAT:
23323464ebd5Sriastradh      p = &limits->LowFloat;
23333464ebd5Sriastradh      break;
23343464ebd5Sriastradh   case GL_MEDIUM_FLOAT:
23353464ebd5Sriastradh      p = &limits->MediumFloat;
23363464ebd5Sriastradh      break;
23373464ebd5Sriastradh   case GL_HIGH_FLOAT:
23383464ebd5Sriastradh      p = &limits->HighFloat;
23393464ebd5Sriastradh      break;
23403464ebd5Sriastradh   case GL_LOW_INT:
23413464ebd5Sriastradh      p = &limits->LowInt;
23423464ebd5Sriastradh      break;
23433464ebd5Sriastradh   case GL_MEDIUM_INT:
23443464ebd5Sriastradh      p = &limits->MediumInt;
23453464ebd5Sriastradh      break;
23463464ebd5Sriastradh   case GL_HIGH_INT:
23473464ebd5Sriastradh      p = &limits->HighInt;
23483464ebd5Sriastradh      break;
23493464ebd5Sriastradh   default:
23503464ebd5Sriastradh      _mesa_error(ctx, GL_INVALID_ENUM,
23513464ebd5Sriastradh                  "glGetShaderPrecisionFormat(precisiontype)");
23523464ebd5Sriastradh      return;
23533464ebd5Sriastradh   }
23543464ebd5Sriastradh
23553464ebd5Sriastradh   range[0] = p->RangeMin;
23563464ebd5Sriastradh   range[1] = p->RangeMax;
23573464ebd5Sriastradh   precision[0] = p->Precision;
23583464ebd5Sriastradh}
23593464ebd5Sriastradh
23603464ebd5Sriastradh
2361af69d88dSmrg/**
2362af69d88dSmrg * For OpenGL ES 2.0, GL_ARB_ES2_compatibility
2363af69d88dSmrg */
23643464ebd5Sriastradhvoid GLAPIENTRY
23653464ebd5Sriastradh_mesa_ReleaseShaderCompiler(void)
23663464ebd5Sriastradh{
23677ec681f3Smrg   GET_CURRENT_CONTEXT(ctx);
23687ec681f3Smrg
23697ec681f3Smrg   if (ctx->shader_builtin_ref) {
23707ec681f3Smrg      _mesa_glsl_builtin_functions_decref();
23717ec681f3Smrg      ctx->shader_builtin_ref = false;
23727ec681f3Smrg   }
23733464ebd5Sriastradh}
23743464ebd5Sriastradh
23753464ebd5Sriastradh
2376af69d88dSmrg/**
2377af69d88dSmrg * For OpenGL ES 2.0, GL_ARB_ES2_compatibility
2378af69d88dSmrg */
23793464ebd5Sriastradhvoid GLAPIENTRY
23803464ebd5Sriastradh_mesa_ShaderBinary(GLint n, const GLuint* shaders, GLenum binaryformat,
23813464ebd5Sriastradh                   const void* binary, GLint length)
23823464ebd5Sriastradh{
23833464ebd5Sriastradh   GET_CURRENT_CONTEXT(ctx);
238401e04c3fSmrg   struct gl_shader **sh;
238501e04c3fSmrg
238601e04c3fSmrg   /* Page 68, section 7.2 'Shader Binaries" of the of the OpenGL ES 3.1, and
238701e04c3fSmrg    * page 88 of the OpenGL 4.5 specs state:
238801e04c3fSmrg    *
238901e04c3fSmrg    *     "An INVALID_VALUE error is generated if count or length is negative.
239001e04c3fSmrg    *      An INVALID_ENUM error is generated if binaryformat is not a supported
239101e04c3fSmrg    *      format returned in SHADER_BINARY_FORMATS."
239201e04c3fSmrg    */
239301e04c3fSmrg   if (n < 0 || length < 0) {
239401e04c3fSmrg      _mesa_error(ctx, GL_INVALID_VALUE, "glShaderBinary(count or length < 0)");
239501e04c3fSmrg      return;
239601e04c3fSmrg   }
239701e04c3fSmrg
239801e04c3fSmrg   /* Get all shader objects at once so we can make the operation
239901e04c3fSmrg    * all-or-nothing.
240001e04c3fSmrg    */
240101e04c3fSmrg   if (n > SIZE_MAX / sizeof(*sh)) {
240201e04c3fSmrg      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glShaderBinary(count)");
240301e04c3fSmrg      return;
240401e04c3fSmrg   }
240501e04c3fSmrg
240601e04c3fSmrg   sh = alloca(sizeof(*sh) * (size_t)n);
240701e04c3fSmrg   if (!sh) {
240801e04c3fSmrg      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glShaderBinary");
240901e04c3fSmrg      return;
241001e04c3fSmrg   }
241101e04c3fSmrg
241201e04c3fSmrg   for (int i = 0; i < n; ++i) {
241301e04c3fSmrg      sh[i] = _mesa_lookup_shader_err(ctx, shaders[i], "glShaderBinary");
241401e04c3fSmrg      if (!sh[i])
241501e04c3fSmrg         return;
241601e04c3fSmrg   }
241701e04c3fSmrg
241801e04c3fSmrg   if (binaryformat == GL_SHADER_BINARY_FORMAT_SPIR_V_ARB) {
241901e04c3fSmrg      if (!ctx->Extensions.ARB_gl_spirv) {
242001e04c3fSmrg         _mesa_error(ctx, GL_INVALID_OPERATION, "glShaderBinary(SPIR-V)");
242101e04c3fSmrg      } else if (n > 0) {
242201e04c3fSmrg         _mesa_spirv_shader_binary(ctx, (unsigned) n, sh, binary,
242301e04c3fSmrg                                   (size_t) length);
242401e04c3fSmrg      }
242501e04c3fSmrg
242601e04c3fSmrg      return;
242701e04c3fSmrg   }
242801e04c3fSmrg
242901e04c3fSmrg   _mesa_error(ctx, GL_INVALID_ENUM, "glShaderBinary(format)");
24303464ebd5Sriastradh}
24313464ebd5Sriastradh
24323464ebd5Sriastradh
2433af69d88dSmrgvoid GLAPIENTRY
2434af69d88dSmrg_mesa_GetProgramBinary(GLuint program, GLsizei bufSize, GLsizei *length,
2435af69d88dSmrg                       GLenum *binaryFormat, GLvoid *binary)
2436af69d88dSmrg{
2437af69d88dSmrg   struct gl_shader_program *shProg;
243801e04c3fSmrg   GLsizei length_dummy;
2439af69d88dSmrg   GET_CURRENT_CONTEXT(ctx);
2440af69d88dSmrg
2441af69d88dSmrg   if (bufSize < 0){
2442af69d88dSmrg      _mesa_error(ctx, GL_INVALID_VALUE, "glGetProgramBinary(bufSize < 0)");
2443af69d88dSmrg      return;
2444af69d88dSmrg   }
2445af69d88dSmrg
244601e04c3fSmrg   shProg = _mesa_lookup_shader_program_err(ctx, program, "glGetProgramBinary");
244701e04c3fSmrg   if (!shProg)
244801e04c3fSmrg      return;
244901e04c3fSmrg
2450af69d88dSmrg   /* The ARB_get_program_binary spec says:
2451af69d88dSmrg    *
2452af69d88dSmrg    *     "If <length> is NULL, then no length is returned."
245301e04c3fSmrg    *
245401e04c3fSmrg    * Ensure that length always points to valid storage to avoid multiple NULL
245501e04c3fSmrg    * pointer checks below.
245601e04c3fSmrg    */
245701e04c3fSmrg   if (length == NULL)
245801e04c3fSmrg      length = &length_dummy;
245901e04c3fSmrg
246001e04c3fSmrg
246101e04c3fSmrg   /* The ARB_get_program_binary spec says:
246201e04c3fSmrg    *
246301e04c3fSmrg    *     "When a program object's LINK_STATUS is FALSE, its program binary
246401e04c3fSmrg    *     length is zero, and a call to GetProgramBinary will generate an
246501e04c3fSmrg    *     INVALID_OPERATION error.
2466af69d88dSmrg    */
246701e04c3fSmrg   if (!shProg->data->LinkStatus) {
246801e04c3fSmrg      _mesa_error(ctx, GL_INVALID_OPERATION,
246901e04c3fSmrg                  "glGetProgramBinary(program %u not linked)",
247001e04c3fSmrg                  shProg->Name);
2471af69d88dSmrg      *length = 0;
247201e04c3fSmrg      return;
247301e04c3fSmrg   }
2474af69d88dSmrg
247501e04c3fSmrg   if (ctx->Const.NumProgramBinaryFormats == 0) {
247601e04c3fSmrg      *length = 0;
247701e04c3fSmrg      _mesa_error(ctx, GL_INVALID_OPERATION,
247801e04c3fSmrg                  "glGetProgramBinary(driver supports zero binary formats)");
247901e04c3fSmrg   } else {
248001e04c3fSmrg      _mesa_get_program_binary(ctx, shProg, bufSize, length, binaryFormat,
248101e04c3fSmrg                               binary);
248201e04c3fSmrg      assert(*length == 0 || *binaryFormat == GL_PROGRAM_BINARY_FORMAT_MESA);
248301e04c3fSmrg   }
2484af69d88dSmrg}
24853464ebd5Sriastradh
24863464ebd5Sriastradhvoid GLAPIENTRY
2487af69d88dSmrg_mesa_ProgramBinary(GLuint program, GLenum binaryFormat,
2488af69d88dSmrg                    const GLvoid *binary, GLsizei length)
24893464ebd5Sriastradh{
24903464ebd5Sriastradh   struct gl_shader_program *shProg;
24913464ebd5Sriastradh   GET_CURRENT_CONTEXT(ctx);
24923464ebd5Sriastradh
2493af69d88dSmrg   shProg = _mesa_lookup_shader_program_err(ctx, program, "glProgramBinary");
2494af69d88dSmrg   if (!shProg)
2495af69d88dSmrg      return;
2496af69d88dSmrg
249701e04c3fSmrg   _mesa_clear_shader_program_data(ctx, shProg);
249801e04c3fSmrg   shProg->data = _mesa_create_shader_program_data();
2499af69d88dSmrg
250001e04c3fSmrg   /* Section 2.3.1 (Errors) of the OpenGL 4.5 spec says:
250101e04c3fSmrg    *
250201e04c3fSmrg    *     "If a negative number is provided where an argument of type sizei or
250301e04c3fSmrg    *     sizeiptr is specified, an INVALID_VALUE error is generated."
250401e04c3fSmrg    */
250501e04c3fSmrg   if (length < 0) {
250601e04c3fSmrg      _mesa_error(ctx, GL_INVALID_VALUE, "glProgramBinary(length < 0)");
250701e04c3fSmrg      return;
250801e04c3fSmrg   }
2509af69d88dSmrg
251001e04c3fSmrg   if (ctx->Const.NumProgramBinaryFormats == 0 ||
251101e04c3fSmrg       binaryFormat != GL_PROGRAM_BINARY_FORMAT_MESA) {
251201e04c3fSmrg      /* The ARB_get_program_binary spec says:
251301e04c3fSmrg       *
251401e04c3fSmrg       *     "<binaryFormat> and <binary> must be those returned by a previous
251501e04c3fSmrg       *     call to GetProgramBinary, and <length> must be the length of the
251601e04c3fSmrg       *     program binary as returned by GetProgramBinary or GetProgramiv with
251701e04c3fSmrg       *     <pname> PROGRAM_BINARY_LENGTH. Loading the program binary will fail,
251801e04c3fSmrg       *     setting the LINK_STATUS of <program> to FALSE, if these conditions
251901e04c3fSmrg       *     are not met."
252001e04c3fSmrg       *
252101e04c3fSmrg       * Since any value of binaryFormat passed "is not one of those specified as
252201e04c3fSmrg       * allowable for [this] command, an INVALID_ENUM error is generated."
252301e04c3fSmrg       */
252401e04c3fSmrg      shProg->data->LinkStatus = LINKING_FAILURE;
252501e04c3fSmrg      _mesa_error(ctx, GL_INVALID_ENUM, "glProgramBinary");
252601e04c3fSmrg   } else {
252701e04c3fSmrg      _mesa_program_binary(ctx, shProg, binaryFormat, binary, length);
252801e04c3fSmrg   }
252901e04c3fSmrg}
25303464ebd5Sriastradh
25313464ebd5Sriastradh
253201e04c3fSmrgstatic ALWAYS_INLINE void
253301e04c3fSmrgprogram_parameteri(struct gl_context *ctx, struct gl_shader_program *shProg,
253401e04c3fSmrg                   GLuint pname, GLint value, bool no_error)
253501e04c3fSmrg{
25363464ebd5Sriastradh   switch (pname) {
2537af69d88dSmrg   case GL_PROGRAM_BINARY_RETRIEVABLE_HINT:
2538af69d88dSmrg      /* This enum isn't part of the OES extension for OpenGL ES 2.0, but it
2539af69d88dSmrg       * is part of OpenGL ES 3.0.  For the ES2 case, this function shouldn't
2540af69d88dSmrg       * even be in the dispatch table, so we shouldn't need to expclicitly
2541af69d88dSmrg       * check here.
2542af69d88dSmrg       *
2543af69d88dSmrg       * On desktop, we ignore the 3.0+ requirement because it is silly.
2544af69d88dSmrg       */
2545af69d88dSmrg
2546af69d88dSmrg      /* The ARB_get_program_binary extension spec says:
2547af69d88dSmrg       *
2548af69d88dSmrg       *     "An INVALID_VALUE error is generated if the <value> argument to
2549af69d88dSmrg       *     ProgramParameteri is not TRUE or FALSE."
2550af69d88dSmrg       */
255101e04c3fSmrg      if (!no_error && value != GL_TRUE && value != GL_FALSE) {
255201e04c3fSmrg         goto invalid_value;
25533464ebd5Sriastradh      }
2554af69d88dSmrg
2555af69d88dSmrg      /* No need to notify the driver.  Any changes will actually take effect
2556af69d88dSmrg       * the next time the shader is linked.
2557af69d88dSmrg       *
2558af69d88dSmrg       * The ARB_get_program_binary extension spec says:
2559af69d88dSmrg       *
2560af69d88dSmrg       *     "To indicate that a program binary is likely to be retrieved,
2561af69d88dSmrg       *     ProgramParameteri should be called with <pname>
2562af69d88dSmrg       *     PROGRAM_BINARY_RETRIEVABLE_HINT and <value> TRUE. This setting
2563af69d88dSmrg       *     will not be in effect until the next time LinkProgram or
2564af69d88dSmrg       *     ProgramBinary has been called successfully."
2565af69d88dSmrg       *
25667ec681f3Smrg       * The resolution of issue 9 in the extension spec also says:
2567af69d88dSmrg       *
2568af69d88dSmrg       *     "The application may use the PROGRAM_BINARY_RETRIEVABLE_HINT hint
2569af69d88dSmrg       *     to indicate to the GL implementation that this program will
2570af69d88dSmrg       *     likely be saved with GetProgramBinary at some point. This will
2571af69d88dSmrg       *     give the GL implementation the opportunity to track any state
2572af69d88dSmrg       *     changes made to the program before being saved such that when it
2573af69d88dSmrg       *     is loaded again a recompile can be avoided."
2574af69d88dSmrg       */
25757ec681f3Smrg      shProg->BinaryRetrievableHintPending = value;
2576af69d88dSmrg      return;
2577af69d88dSmrg
2578af69d88dSmrg   case GL_PROGRAM_SEPARABLE:
2579af69d88dSmrg      /* Spec imply that the behavior is the same as ARB_get_program_binary
2580af69d88dSmrg       * Chapter 7.3 Program Objects
2581af69d88dSmrg       */
258201e04c3fSmrg      if (!no_error && value != GL_TRUE && value != GL_FALSE) {
258301e04c3fSmrg         goto invalid_value;
25843464ebd5Sriastradh      }
2585af69d88dSmrg      shProg->SeparateShader = value;
2586af69d88dSmrg      return;
2587af69d88dSmrg
25883464ebd5Sriastradh   default:
258901e04c3fSmrg      if (!no_error) {
259001e04c3fSmrg         _mesa_error(ctx, GL_INVALID_ENUM, "glProgramParameteri(pname=%s)",
259101e04c3fSmrg                     _mesa_enum_to_string(pname));
259201e04c3fSmrg      }
259301e04c3fSmrg      return;
25943464ebd5Sriastradh   }
25953464ebd5Sriastradh
259601e04c3fSmrginvalid_value:
259701e04c3fSmrg   _mesa_error(ctx, GL_INVALID_VALUE,
259801e04c3fSmrg               "glProgramParameteri(pname=%s, value=%d): "
259901e04c3fSmrg               "value must be 0 or 1.",
260001e04c3fSmrg               _mesa_enum_to_string(pname),
260101e04c3fSmrg               value);
2602af69d88dSmrg}
26033464ebd5Sriastradh
260401e04c3fSmrg
260501e04c3fSmrgvoid GLAPIENTRY
260601e04c3fSmrg_mesa_ProgramParameteri_no_error(GLuint program, GLenum pname, GLint value)
26073464ebd5Sriastradh{
260801e04c3fSmrg   GET_CURRENT_CONTEXT(ctx);
26093464ebd5Sriastradh
261001e04c3fSmrg   struct gl_shader_program *shProg = _mesa_lookup_shader_program(ctx, program);
261101e04c3fSmrg   program_parameteri(ctx, shProg, pname, value, true);
26123464ebd5Sriastradh}
26133464ebd5Sriastradh
26143464ebd5Sriastradh
261501e04c3fSmrgvoid GLAPIENTRY
261601e04c3fSmrg_mesa_ProgramParameteri(GLuint program, GLenum pname, GLint value)
26173464ebd5Sriastradh{
261801e04c3fSmrg   struct gl_shader_program *shProg;
261901e04c3fSmrg   GET_CURRENT_CONTEXT(ctx);
26203464ebd5Sriastradh
262101e04c3fSmrg   shProg = _mesa_lookup_shader_program_err(ctx, program,
262201e04c3fSmrg                                            "glProgramParameteri");
262301e04c3fSmrg   if (!shProg)
262401e04c3fSmrg      return;
2625af69d88dSmrg
262601e04c3fSmrg   program_parameteri(ctx, shProg, pname, value, false);
262701e04c3fSmrg}
26283464ebd5Sriastradh
26293464ebd5Sriastradh
263001e04c3fSmrgvoid
263101e04c3fSmrg_mesa_use_program(struct gl_context *ctx, gl_shader_stage stage,
263201e04c3fSmrg                  struct gl_shader_program *shProg, struct gl_program *prog,
263301e04c3fSmrg                  struct gl_pipeline_object *shTarget)
263401e04c3fSmrg{
263501e04c3fSmrg   struct gl_program **target;
26363464ebd5Sriastradh
263701e04c3fSmrg   target = &shTarget->CurrentProgram[stage];
263801e04c3fSmrg   if (prog) {
263901e04c3fSmrg      _mesa_program_init_subroutine_defaults(ctx, prog);
264001e04c3fSmrg   }
2641af69d88dSmrg
264201e04c3fSmrg   if (*target != prog) {
264301e04c3fSmrg      /* Program is current, flush it */
264401e04c3fSmrg      if (shTarget == ctx->_Shader) {
26457ec681f3Smrg         FLUSH_VERTICES(ctx, _NEW_PROGRAM | _NEW_PROGRAM_CONSTANTS, 0);
264601e04c3fSmrg      }
26473464ebd5Sriastradh
264801e04c3fSmrg      _mesa_reference_shader_program(ctx,
264901e04c3fSmrg                                     &shTarget->ReferencedPrograms[stage],
265001e04c3fSmrg                                     shProg);
265101e04c3fSmrg      _mesa_reference_program(ctx, target, prog);
26527ec681f3Smrg      _mesa_update_allow_draw_out_of_order(ctx);
26537ec681f3Smrg      _mesa_update_valid_to_render_state(ctx);
265401e04c3fSmrg      if (stage == MESA_SHADER_VERTEX)
265501e04c3fSmrg         _mesa_update_vertex_processing_mode(ctx);
265601e04c3fSmrg      return;
26573464ebd5Sriastradh   }
26583464ebd5Sriastradh
26593464ebd5Sriastradh}
26603464ebd5Sriastradh
2661af69d88dSmrg
26623464ebd5Sriastradh/**
2663af69d88dSmrg * Copy program-specific data generated by linking from the gl_shader_program
266401e04c3fSmrg * object to the gl_program object referred to by the gl_linked_shader.
266501e04c3fSmrg *
266601e04c3fSmrg * This function expects _mesa_reference_program() to have been previously
266701e04c3fSmrg * called setting the gl_linked_shaders program reference.
26683464ebd5Sriastradh */
26693464ebd5Sriastradhvoid
267001e04c3fSmrg_mesa_copy_linked_program_data(const struct gl_shader_program *src,
267101e04c3fSmrg                               struct gl_linked_shader *dst_sh)
2672af69d88dSmrg{
267301e04c3fSmrg   assert(dst_sh->Program);
267401e04c3fSmrg
267501e04c3fSmrg   struct gl_program *dst = dst_sh->Program;
267601e04c3fSmrg
267701e04c3fSmrg   dst->info.separate_shader = src->SeparateShader;
267801e04c3fSmrg
267901e04c3fSmrg   switch (dst_sh->Stage) {
2680af69d88dSmrg   case MESA_SHADER_GEOMETRY: {
268101e04c3fSmrg      dst->info.gs.vertices_in = src->Geom.VerticesIn;
268201e04c3fSmrg      dst->info.gs.uses_end_primitive = src->Geom.UsesEndPrimitive;
26837ec681f3Smrg      dst->info.gs.active_stream_mask = src->Geom.ActiveStreamMask;
2684af69d88dSmrg      break;
2685af69d88dSmrg   }
268601e04c3fSmrg   case MESA_SHADER_FRAGMENT: {
268701e04c3fSmrg      dst->info.fs.depth_layout = src->FragDepthLayout;
2688af69d88dSmrg      break;
2689af69d88dSmrg   }
269001e04c3fSmrg   case MESA_SHADER_COMPUTE: {
26917ec681f3Smrg      dst->info.shared_size = src->Comp.SharedSize;
2692af69d88dSmrg      break;
269301e04c3fSmrg   }
2694af69d88dSmrg   default:
2695af69d88dSmrg      break;
2696af69d88dSmrg   }
2697af69d88dSmrg}
26983464ebd5Sriastradh
2699af69d88dSmrg/**
2700af69d88dSmrg * ARB_separate_shader_objects: Compile & Link Program
2701af69d88dSmrg */
2702af69d88dSmrgGLuint GLAPIENTRY
2703af69d88dSmrg_mesa_CreateShaderProgramv(GLenum type, GLsizei count,
2704af69d88dSmrg                           const GLchar* const *strings)
2705af69d88dSmrg{
2706af69d88dSmrg   GET_CURRENT_CONTEXT(ctx);
27073464ebd5Sriastradh
270801e04c3fSmrg   const GLuint shader = create_shader_err(ctx, type, "glCreateShaderProgramv");
270901e04c3fSmrg   GLuint program = 0;
271001e04c3fSmrg
271101e04c3fSmrg   /*
271201e04c3fSmrg    * According to OpenGL 4.5 and OpenGL ES 3.1 standards, section 7.3:
271301e04c3fSmrg    * GL_INVALID_VALUE should be generated if count < 0
271401e04c3fSmrg    */
271501e04c3fSmrg   if (count < 0) {
271601e04c3fSmrg      _mesa_error(ctx, GL_INVALID_VALUE, "glCreateShaderProgram (count < 0)");
271701e04c3fSmrg      return program;
271801e04c3fSmrg   }
271901e04c3fSmrg
272001e04c3fSmrg   if (shader) {
272101e04c3fSmrg      struct gl_shader *sh = _mesa_lookup_shader(ctx, shader);
272201e04c3fSmrg
272301e04c3fSmrg      _mesa_ShaderSource(shader, count, strings, NULL);
272401e04c3fSmrg      _mesa_compile_shader(ctx, sh);
272501e04c3fSmrg
272601e04c3fSmrg      program = create_shader_program(ctx);
272701e04c3fSmrg      if (program) {
272801e04c3fSmrg	 struct gl_shader_program *shProg;
272901e04c3fSmrg	 GLint compiled = GL_FALSE;
273001e04c3fSmrg
273101e04c3fSmrg	 shProg = _mesa_lookup_shader_program(ctx, program);
273201e04c3fSmrg
273301e04c3fSmrg	 shProg->SeparateShader = GL_TRUE;
273401e04c3fSmrg
273501e04c3fSmrg	 get_shaderiv(ctx, shader, GL_COMPILE_STATUS, &compiled);
273601e04c3fSmrg	 if (compiled) {
273701e04c3fSmrg	    attach_shader_err(ctx, program, shader, "glCreateShaderProgramv");
273801e04c3fSmrg	    _mesa_link_program(ctx, shProg);
273901e04c3fSmrg	    detach_shader_error(ctx, program, shader);
274001e04c3fSmrg
274101e04c3fSmrg#if 0
274201e04c3fSmrg	    /* Possibly... */
274301e04c3fSmrg	    if (active-user-defined-varyings-in-linked-program) {
274401e04c3fSmrg	       append-error-to-info-log;
274501e04c3fSmrg               shProg->data->LinkStatus = LINKING_FAILURE;
274601e04c3fSmrg	    }
274701e04c3fSmrg#endif
274801e04c3fSmrg	 }
274901e04c3fSmrg         if (sh->InfoLog)
275001e04c3fSmrg            ralloc_strcat(&shProg->data->InfoLog, sh->InfoLog);
275101e04c3fSmrg      }
275201e04c3fSmrg
275301e04c3fSmrg      delete_shader(ctx, shader);
275401e04c3fSmrg   }
275501e04c3fSmrg
275601e04c3fSmrg   return program;
275701e04c3fSmrg}
275801e04c3fSmrg
275901e04c3fSmrg
27607ec681f3Smrgstatic void
27617ec681f3Smrgset_patch_vertices(struct gl_context *ctx, GLint value)
27627ec681f3Smrg{
27637ec681f3Smrg   if (ctx->TessCtrlProgram.patch_vertices != value) {
27647ec681f3Smrg      FLUSH_VERTICES(ctx, 0, GL_CURRENT_BIT);
27657ec681f3Smrg      ctx->NewDriverState |= ctx->DriverFlags.NewTessState;
27667ec681f3Smrg      ctx->TessCtrlProgram.patch_vertices = value;
27677ec681f3Smrg   }
27687ec681f3Smrg}
27697ec681f3Smrg
277001e04c3fSmrg/**
277101e04c3fSmrg * For GL_ARB_tessellation_shader
277201e04c3fSmrg */
277301e04c3fSmrgvoid GLAPIENTRY
277401e04c3fSmrg_mesa_PatchParameteri_no_error(GLenum pname, GLint value)
277501e04c3fSmrg{
277601e04c3fSmrg   GET_CURRENT_CONTEXT(ctx);
27777ec681f3Smrg
27787ec681f3Smrg   set_patch_vertices(ctx, value);
277901e04c3fSmrg}
278001e04c3fSmrg
278101e04c3fSmrg
278201e04c3fSmrgextern void GLAPIENTRY
278301e04c3fSmrg_mesa_PatchParameteri(GLenum pname, GLint value)
278401e04c3fSmrg{
278501e04c3fSmrg   GET_CURRENT_CONTEXT(ctx);
278601e04c3fSmrg
278701e04c3fSmrg   if (!_mesa_has_tessellation(ctx)) {
278801e04c3fSmrg      _mesa_error(ctx, GL_INVALID_OPERATION, "glPatchParameteri");
278901e04c3fSmrg      return;
279001e04c3fSmrg   }
279101e04c3fSmrg
279201e04c3fSmrg   if (pname != GL_PATCH_VERTICES) {
279301e04c3fSmrg      _mesa_error(ctx, GL_INVALID_ENUM, "glPatchParameteri");
279401e04c3fSmrg      return;
279501e04c3fSmrg   }
279601e04c3fSmrg
279701e04c3fSmrg   if (value <= 0 || value > ctx->Const.MaxPatchVertices) {
279801e04c3fSmrg      _mesa_error(ctx, GL_INVALID_VALUE, "glPatchParameteri");
279901e04c3fSmrg      return;
280001e04c3fSmrg   }
280101e04c3fSmrg
28027ec681f3Smrg   set_patch_vertices(ctx, value);
280301e04c3fSmrg}
280401e04c3fSmrg
280501e04c3fSmrg
280601e04c3fSmrgextern void GLAPIENTRY
280701e04c3fSmrg_mesa_PatchParameterfv(GLenum pname, const GLfloat *values)
280801e04c3fSmrg{
280901e04c3fSmrg   GET_CURRENT_CONTEXT(ctx);
281001e04c3fSmrg
281101e04c3fSmrg   if (!_mesa_has_tessellation(ctx)) {
281201e04c3fSmrg      _mesa_error(ctx, GL_INVALID_OPERATION, "glPatchParameterfv");
281301e04c3fSmrg      return;
281401e04c3fSmrg   }
281501e04c3fSmrg
281601e04c3fSmrg   switch(pname) {
281701e04c3fSmrg   case GL_PATCH_DEFAULT_OUTER_LEVEL:
28187ec681f3Smrg      FLUSH_VERTICES(ctx, 0, 0);
281901e04c3fSmrg      memcpy(ctx->TessCtrlProgram.patch_default_outer_level, values,
282001e04c3fSmrg             4 * sizeof(GLfloat));
28217ec681f3Smrg      ctx->NewDriverState |= ctx->DriverFlags.NewTessState;
282201e04c3fSmrg      return;
282301e04c3fSmrg   case GL_PATCH_DEFAULT_INNER_LEVEL:
28247ec681f3Smrg      FLUSH_VERTICES(ctx, 0, 0);
282501e04c3fSmrg      memcpy(ctx->TessCtrlProgram.patch_default_inner_level, values,
282601e04c3fSmrg             2 * sizeof(GLfloat));
28277ec681f3Smrg      ctx->NewDriverState |= ctx->DriverFlags.NewTessState;
282801e04c3fSmrg      return;
282901e04c3fSmrg   default:
283001e04c3fSmrg      _mesa_error(ctx, GL_INVALID_ENUM, "glPatchParameterfv");
283101e04c3fSmrg      return;
283201e04c3fSmrg   }
283301e04c3fSmrg}
283401e04c3fSmrg
283501e04c3fSmrg/**
283601e04c3fSmrg * ARB_shader_subroutine
283701e04c3fSmrg */
283801e04c3fSmrgGLint GLAPIENTRY
283901e04c3fSmrg_mesa_GetSubroutineUniformLocation(GLuint program, GLenum shadertype,
284001e04c3fSmrg                                   const GLchar *name)
284101e04c3fSmrg{
284201e04c3fSmrg   GET_CURRENT_CONTEXT(ctx);
284301e04c3fSmrg   const char *api_name = "glGetSubroutineUniformLocation";
284401e04c3fSmrg   struct gl_shader_program *shProg;
284501e04c3fSmrg   GLenum resource_type;
284601e04c3fSmrg   gl_shader_stage stage;
284701e04c3fSmrg
284801e04c3fSmrg   if (!_mesa_validate_shader_target(ctx, shadertype)) {
284901e04c3fSmrg      _mesa_error(ctx, GL_INVALID_OPERATION, "%s", api_name);
285001e04c3fSmrg      return -1;
285101e04c3fSmrg   }
285201e04c3fSmrg
285301e04c3fSmrg   shProg = _mesa_lookup_shader_program_err(ctx, program, api_name);
285401e04c3fSmrg   if (!shProg)
285501e04c3fSmrg      return -1;
285601e04c3fSmrg
285701e04c3fSmrg   stage = _mesa_shader_enum_to_shader_stage(shadertype);
285801e04c3fSmrg   if (!shProg->_LinkedShaders[stage]) {
285901e04c3fSmrg      _mesa_error(ctx, GL_INVALID_OPERATION, "%s", api_name);
286001e04c3fSmrg      return -1;
286101e04c3fSmrg   }
286201e04c3fSmrg
286301e04c3fSmrg   resource_type = _mesa_shader_stage_to_subroutine_uniform(stage);
286401e04c3fSmrg   return _mesa_program_resource_location(shProg, resource_type, name);
286501e04c3fSmrg}
286601e04c3fSmrg
286701e04c3fSmrgGLuint GLAPIENTRY
286801e04c3fSmrg_mesa_GetSubroutineIndex(GLuint program, GLenum shadertype,
286901e04c3fSmrg                         const GLchar *name)
287001e04c3fSmrg{
287101e04c3fSmrg   GET_CURRENT_CONTEXT(ctx);
287201e04c3fSmrg   const char *api_name = "glGetSubroutineIndex";
287301e04c3fSmrg   struct gl_shader_program *shProg;
287401e04c3fSmrg   struct gl_program_resource *res;
287501e04c3fSmrg   GLenum resource_type;
287601e04c3fSmrg   gl_shader_stage stage;
287701e04c3fSmrg
287801e04c3fSmrg   if (!_mesa_validate_shader_target(ctx, shadertype)) {
287901e04c3fSmrg      _mesa_error(ctx, GL_INVALID_OPERATION, "%s", api_name);
288001e04c3fSmrg      return -1;
288101e04c3fSmrg   }
288201e04c3fSmrg
288301e04c3fSmrg   shProg = _mesa_lookup_shader_program_err(ctx, program, api_name);
288401e04c3fSmrg   if (!shProg)
288501e04c3fSmrg      return -1;
288601e04c3fSmrg
288701e04c3fSmrg   stage = _mesa_shader_enum_to_shader_stage(shadertype);
288801e04c3fSmrg   if (!shProg->_LinkedShaders[stage]) {
288901e04c3fSmrg      _mesa_error(ctx, GL_INVALID_OPERATION, "%s", api_name);
289001e04c3fSmrg      return -1;
289101e04c3fSmrg   }
289201e04c3fSmrg
289301e04c3fSmrg   resource_type = _mesa_shader_stage_to_subroutine(stage);
289401e04c3fSmrg   res = _mesa_program_resource_find_name(shProg, resource_type, name, NULL);
289501e04c3fSmrg   if (!res) {
289601e04c3fSmrg     return -1;
289701e04c3fSmrg   }
289801e04c3fSmrg
289901e04c3fSmrg   return _mesa_program_resource_index(shProg, res);
290001e04c3fSmrg}
290101e04c3fSmrg
290201e04c3fSmrg
290301e04c3fSmrgGLvoid GLAPIENTRY
290401e04c3fSmrg_mesa_GetActiveSubroutineUniformiv(GLuint program, GLenum shadertype,
290501e04c3fSmrg                                   GLuint index, GLenum pname, GLint *values)
290601e04c3fSmrg{
290701e04c3fSmrg   GET_CURRENT_CONTEXT(ctx);
290801e04c3fSmrg   const char *api_name = "glGetActiveSubroutineUniformiv";
290901e04c3fSmrg   struct gl_shader_program *shProg;
291001e04c3fSmrg   struct gl_linked_shader *sh;
291101e04c3fSmrg   gl_shader_stage stage;
291201e04c3fSmrg   struct gl_program_resource *res;
291301e04c3fSmrg   const struct gl_uniform_storage *uni;
291401e04c3fSmrg   GLenum resource_type;
291501e04c3fSmrg   int count, i, j;
291601e04c3fSmrg
291701e04c3fSmrg   if (!_mesa_validate_shader_target(ctx, shadertype)) {
291801e04c3fSmrg      _mesa_error(ctx, GL_INVALID_OPERATION, "%s", api_name);
291901e04c3fSmrg      return;
292001e04c3fSmrg   }
292101e04c3fSmrg
292201e04c3fSmrg   shProg = _mesa_lookup_shader_program_err(ctx, program, api_name);
292301e04c3fSmrg   if (!shProg)
292401e04c3fSmrg      return;
292501e04c3fSmrg
292601e04c3fSmrg   stage = _mesa_shader_enum_to_shader_stage(shadertype);
292701e04c3fSmrg   resource_type = _mesa_shader_stage_to_subroutine_uniform(stage);
292801e04c3fSmrg
292901e04c3fSmrg   sh = shProg->_LinkedShaders[stage];
293001e04c3fSmrg   if (!sh) {
293101e04c3fSmrg      _mesa_error(ctx, GL_INVALID_OPERATION, "%s", api_name);
293201e04c3fSmrg      return;
293301e04c3fSmrg   }
293401e04c3fSmrg
293501e04c3fSmrg   struct gl_program *p = shProg->_LinkedShaders[stage]->Program;
293601e04c3fSmrg   if (index >= p->sh.NumSubroutineUniforms) {
293701e04c3fSmrg      _mesa_error(ctx, GL_INVALID_VALUE, "%s: invalid index greater than GL_ACTIVE_SUBROUTINE_UNIFORMS", api_name);
293801e04c3fSmrg      return;
293901e04c3fSmrg   }
294001e04c3fSmrg
294101e04c3fSmrg   switch (pname) {
294201e04c3fSmrg   case GL_NUM_COMPATIBLE_SUBROUTINES: {
294301e04c3fSmrg      res = _mesa_program_resource_find_index(shProg, resource_type, index);
294401e04c3fSmrg      if (res) {
294501e04c3fSmrg         uni = res->Data;
294601e04c3fSmrg         values[0] = uni->num_compatible_subroutines;
294701e04c3fSmrg      }
294801e04c3fSmrg      break;
294901e04c3fSmrg   }
295001e04c3fSmrg   case GL_COMPATIBLE_SUBROUTINES: {
295101e04c3fSmrg      res = _mesa_program_resource_find_index(shProg, resource_type, index);
295201e04c3fSmrg      if (res) {
295301e04c3fSmrg         uni = res->Data;
295401e04c3fSmrg         count = 0;
295501e04c3fSmrg         for (i = 0; i < p->sh.NumSubroutineFunctions; i++) {
295601e04c3fSmrg            struct gl_subroutine_function *fn = &p->sh.SubroutineFunctions[i];
295701e04c3fSmrg            for (j = 0; j < fn->num_compat_types; j++) {
295801e04c3fSmrg               if (fn->types[j] == uni->type) {
295901e04c3fSmrg                  values[count++] = i;
296001e04c3fSmrg                  break;
296101e04c3fSmrg               }
296201e04c3fSmrg            }
296301e04c3fSmrg         }
296401e04c3fSmrg      }
296501e04c3fSmrg      break;
296601e04c3fSmrg   }
296701e04c3fSmrg   case GL_UNIFORM_SIZE:
296801e04c3fSmrg      res = _mesa_program_resource_find_index(shProg, resource_type, index);
296901e04c3fSmrg      if (res) {
297001e04c3fSmrg         uni = res->Data;
297101e04c3fSmrg         values[0] = uni->array_elements ? uni->array_elements : 1;
297201e04c3fSmrg      }
297301e04c3fSmrg      break;
297401e04c3fSmrg   case GL_UNIFORM_NAME_LENGTH:
297501e04c3fSmrg      res = _mesa_program_resource_find_index(shProg, resource_type, index);
297601e04c3fSmrg      if (res) {
297701e04c3fSmrg         values[0] = strlen(_mesa_program_resource_name(res)) + 1
297801e04c3fSmrg            + ((_mesa_program_resource_array_size(res) != 0) ? 3 : 0);
297901e04c3fSmrg      }
298001e04c3fSmrg      break;
298101e04c3fSmrg   default:
298201e04c3fSmrg      _mesa_error(ctx, GL_INVALID_OPERATION, "%s", api_name);
298301e04c3fSmrg      return;
298401e04c3fSmrg   }
298501e04c3fSmrg}
298601e04c3fSmrg
298701e04c3fSmrg
298801e04c3fSmrgGLvoid GLAPIENTRY
298901e04c3fSmrg_mesa_GetActiveSubroutineUniformName(GLuint program, GLenum shadertype,
299001e04c3fSmrg                                     GLuint index, GLsizei bufsize,
299101e04c3fSmrg                                     GLsizei *length, GLchar *name)
299201e04c3fSmrg{
299301e04c3fSmrg   GET_CURRENT_CONTEXT(ctx);
299401e04c3fSmrg   const char *api_name = "glGetActiveSubroutineUniformName";
299501e04c3fSmrg   struct gl_shader_program *shProg;
299601e04c3fSmrg   GLenum resource_type;
299701e04c3fSmrg   gl_shader_stage stage;
299801e04c3fSmrg
299901e04c3fSmrg   if (!_mesa_validate_shader_target(ctx, shadertype)) {
300001e04c3fSmrg      _mesa_error(ctx, GL_INVALID_OPERATION, "%s", api_name);
300101e04c3fSmrg      return;
300201e04c3fSmrg   }
300301e04c3fSmrg
300401e04c3fSmrg   shProg = _mesa_lookup_shader_program_err(ctx, program, api_name);
300501e04c3fSmrg   if (!shProg)
300601e04c3fSmrg      return;
300701e04c3fSmrg
300801e04c3fSmrg   stage = _mesa_shader_enum_to_shader_stage(shadertype);
300901e04c3fSmrg   if (!shProg->_LinkedShaders[stage]) {
301001e04c3fSmrg      _mesa_error(ctx, GL_INVALID_OPERATION, "%s", api_name);
301101e04c3fSmrg      return;
301201e04c3fSmrg   }
301301e04c3fSmrg
301401e04c3fSmrg   resource_type = _mesa_shader_stage_to_subroutine_uniform(stage);
301501e04c3fSmrg   /* get program resource name */
301601e04c3fSmrg   _mesa_get_program_resource_name(shProg, resource_type,
301701e04c3fSmrg                                   index, bufsize,
30187ec681f3Smrg                                   length, name, false, api_name);
301901e04c3fSmrg}
302001e04c3fSmrg
302101e04c3fSmrg
302201e04c3fSmrgGLvoid GLAPIENTRY
302301e04c3fSmrg_mesa_GetActiveSubroutineName(GLuint program, GLenum shadertype,
302401e04c3fSmrg                              GLuint index, GLsizei bufsize,
302501e04c3fSmrg                              GLsizei *length, GLchar *name)
302601e04c3fSmrg{
302701e04c3fSmrg   GET_CURRENT_CONTEXT(ctx);
302801e04c3fSmrg   const char *api_name = "glGetActiveSubroutineName";
302901e04c3fSmrg   struct gl_shader_program *shProg;
303001e04c3fSmrg   GLenum resource_type;
303101e04c3fSmrg   gl_shader_stage stage;
303201e04c3fSmrg
303301e04c3fSmrg   if (!_mesa_validate_shader_target(ctx, shadertype)) {
303401e04c3fSmrg      _mesa_error(ctx, GL_INVALID_OPERATION, "%s", api_name);
303501e04c3fSmrg      return;
303601e04c3fSmrg   }
303701e04c3fSmrg
303801e04c3fSmrg   shProg = _mesa_lookup_shader_program_err(ctx, program, api_name);
303901e04c3fSmrg   if (!shProg)
304001e04c3fSmrg      return;
304101e04c3fSmrg
304201e04c3fSmrg   stage = _mesa_shader_enum_to_shader_stage(shadertype);
304301e04c3fSmrg   if (!shProg->_LinkedShaders[stage]) {
304401e04c3fSmrg      _mesa_error(ctx, GL_INVALID_OPERATION, "%s", api_name);
304501e04c3fSmrg      return;
304601e04c3fSmrg   }
304701e04c3fSmrg   resource_type = _mesa_shader_stage_to_subroutine(stage);
304801e04c3fSmrg   _mesa_get_program_resource_name(shProg, resource_type,
304901e04c3fSmrg                                   index, bufsize,
30507ec681f3Smrg                                   length, name, false, api_name);
305101e04c3fSmrg}
305201e04c3fSmrg
305301e04c3fSmrgGLvoid GLAPIENTRY
305401e04c3fSmrg_mesa_UniformSubroutinesuiv(GLenum shadertype, GLsizei count,
305501e04c3fSmrg                            const GLuint *indices)
305601e04c3fSmrg{
305701e04c3fSmrg   GET_CURRENT_CONTEXT(ctx);
305801e04c3fSmrg   const char *api_name = "glUniformSubroutinesuiv";
305901e04c3fSmrg   gl_shader_stage stage;
306001e04c3fSmrg   int i;
306101e04c3fSmrg
306201e04c3fSmrg   if (!_mesa_validate_shader_target(ctx, shadertype)) {
306301e04c3fSmrg      _mesa_error(ctx, GL_INVALID_OPERATION, "%s", api_name);
306401e04c3fSmrg      return;
306501e04c3fSmrg   }
306601e04c3fSmrg
306701e04c3fSmrg   stage = _mesa_shader_enum_to_shader_stage(shadertype);
306801e04c3fSmrg   struct gl_program *p = ctx->_Shader->CurrentProgram[stage];
306901e04c3fSmrg   if (!p) {
307001e04c3fSmrg      _mesa_error(ctx, GL_INVALID_OPERATION, "%s", api_name);
307101e04c3fSmrg      return;
307201e04c3fSmrg   }
307301e04c3fSmrg
307401e04c3fSmrg   if (count != p->sh.NumSubroutineUniformRemapTable) {
307501e04c3fSmrg      _mesa_error(ctx, GL_INVALID_VALUE, "%s", api_name);
307601e04c3fSmrg      return;
307701e04c3fSmrg   }
307801e04c3fSmrg
307901e04c3fSmrg   i = 0;
308001e04c3fSmrg   bool flushed = false;
308101e04c3fSmrg   do {
308201e04c3fSmrg      struct gl_uniform_storage *uni = p->sh.SubroutineUniformRemapTable[i];
308301e04c3fSmrg      if (uni == NULL) {
308401e04c3fSmrg         i++;
308501e04c3fSmrg         continue;
308601e04c3fSmrg      }
308701e04c3fSmrg
308801e04c3fSmrg      if (!flushed) {
308901e04c3fSmrg         _mesa_flush_vertices_for_uniforms(ctx, uni);
309001e04c3fSmrg         flushed = true;
309101e04c3fSmrg      }
309201e04c3fSmrg
309301e04c3fSmrg      int uni_count = uni->array_elements ? uni->array_elements : 1;
309401e04c3fSmrg      int j, k, f;
309501e04c3fSmrg
309601e04c3fSmrg      for (j = i; j < i + uni_count; j++) {
309701e04c3fSmrg         struct gl_subroutine_function *subfn = NULL;
309801e04c3fSmrg         if (indices[j] > p->sh.MaxSubroutineFunctionIndex) {
309901e04c3fSmrg            _mesa_error(ctx, GL_INVALID_VALUE, "%s", api_name);
310001e04c3fSmrg            return;
310101e04c3fSmrg         }
310201e04c3fSmrg
310301e04c3fSmrg         for (f = 0; f < p->sh.NumSubroutineFunctions; f++) {
310401e04c3fSmrg            if (p->sh.SubroutineFunctions[f].index == indices[j])
310501e04c3fSmrg               subfn = &p->sh.SubroutineFunctions[f];
310601e04c3fSmrg         }
310701e04c3fSmrg
310801e04c3fSmrg         if (!subfn) {
310901e04c3fSmrg            continue;
311001e04c3fSmrg         }
311101e04c3fSmrg
311201e04c3fSmrg         for (k = 0; k < subfn->num_compat_types; k++) {
311301e04c3fSmrg            if (subfn->types[k] == uni->type)
311401e04c3fSmrg               break;
311501e04c3fSmrg         }
311601e04c3fSmrg         if (k == subfn->num_compat_types) {
311701e04c3fSmrg            _mesa_error(ctx, GL_INVALID_OPERATION, "%s", api_name);
311801e04c3fSmrg            return;
311901e04c3fSmrg         }
312001e04c3fSmrg
312101e04c3fSmrg         ctx->SubroutineIndex[p->info.stage].IndexPtr[j] = indices[j];
312201e04c3fSmrg      }
312301e04c3fSmrg      i += uni_count;
312401e04c3fSmrg   } while(i < count);
312501e04c3fSmrg}
312601e04c3fSmrg
312701e04c3fSmrg
312801e04c3fSmrgGLvoid GLAPIENTRY
312901e04c3fSmrg_mesa_GetUniformSubroutineuiv(GLenum shadertype, GLint location,
313001e04c3fSmrg                              GLuint *params)
313101e04c3fSmrg{
313201e04c3fSmrg   GET_CURRENT_CONTEXT(ctx);
313301e04c3fSmrg   const char *api_name = "glGetUniformSubroutineuiv";
313401e04c3fSmrg   gl_shader_stage stage;
313501e04c3fSmrg
313601e04c3fSmrg   if (!_mesa_validate_shader_target(ctx, shadertype)) {
313701e04c3fSmrg      _mesa_error(ctx, GL_INVALID_OPERATION, "%s", api_name);
313801e04c3fSmrg      return;
313901e04c3fSmrg   }
314001e04c3fSmrg
314101e04c3fSmrg   stage = _mesa_shader_enum_to_shader_stage(shadertype);
314201e04c3fSmrg   struct gl_program *p = ctx->_Shader->CurrentProgram[stage];
314301e04c3fSmrg   if (!p) {
314401e04c3fSmrg      _mesa_error(ctx, GL_INVALID_OPERATION, "%s", api_name);
314501e04c3fSmrg      return;
314601e04c3fSmrg   }
314701e04c3fSmrg
314801e04c3fSmrg   if (location >= p->sh.NumSubroutineUniformRemapTable) {
314901e04c3fSmrg      _mesa_error(ctx, GL_INVALID_VALUE, "%s", api_name);
315001e04c3fSmrg      return;
315101e04c3fSmrg   }
315201e04c3fSmrg
315301e04c3fSmrg   *params = ctx->SubroutineIndex[p->info.stage].IndexPtr[location];
315401e04c3fSmrg}
315501e04c3fSmrg
315601e04c3fSmrg
315701e04c3fSmrgGLvoid GLAPIENTRY
315801e04c3fSmrg_mesa_GetProgramStageiv(GLuint program, GLenum shadertype,
315901e04c3fSmrg                        GLenum pname, GLint *values)
316001e04c3fSmrg{
316101e04c3fSmrg   GET_CURRENT_CONTEXT(ctx);
316201e04c3fSmrg   const char *api_name = "glGetProgramStageiv";
316301e04c3fSmrg   struct gl_shader_program *shProg;
316401e04c3fSmrg   struct gl_linked_shader *sh;
316501e04c3fSmrg   gl_shader_stage stage;
316601e04c3fSmrg
316701e04c3fSmrg   if (!_mesa_validate_shader_target(ctx, shadertype)) {
316801e04c3fSmrg      _mesa_error(ctx, GL_INVALID_OPERATION, "%s", api_name);
316901e04c3fSmrg      return;
317001e04c3fSmrg   }
317101e04c3fSmrg
317201e04c3fSmrg   shProg = _mesa_lookup_shader_program_err(ctx, program, api_name);
317301e04c3fSmrg   if (!shProg)
317401e04c3fSmrg      return;
317501e04c3fSmrg
317601e04c3fSmrg   stage = _mesa_shader_enum_to_shader_stage(shadertype);
317701e04c3fSmrg   sh = shProg->_LinkedShaders[stage];
317801e04c3fSmrg
317901e04c3fSmrg   /* ARB_shader_subroutine doesn't ask the program to be linked, or list any
318001e04c3fSmrg    * INVALID_OPERATION in the case of not be linked.
318101e04c3fSmrg    *
318201e04c3fSmrg    * And for some pnames, like GL_ACTIVE_SUBROUTINE_UNIFORMS, you can ask the
318301e04c3fSmrg    * same info using other specs (ARB_program_interface_query), without the
318401e04c3fSmrg    * need of the program to be linked, being the value for that case 0.
318501e04c3fSmrg    *
318601e04c3fSmrg    * But at the same time, some other methods require the program to be
318701e04c3fSmrg    * linked for pname related to locations, so it would be inconsistent to
318801e04c3fSmrg    * not do the same here. So we are:
318901e04c3fSmrg    *   * Return GL_INVALID_OPERATION if not linked only for locations.
319001e04c3fSmrg    *   * Setting a default value of 0, to be returned if not linked.
319101e04c3fSmrg    */
319201e04c3fSmrg   if (!sh) {
319301e04c3fSmrg      values[0] = 0;
319401e04c3fSmrg      if (pname == GL_ACTIVE_SUBROUTINE_UNIFORM_LOCATIONS) {
319501e04c3fSmrg         _mesa_error(ctx, GL_INVALID_OPERATION, "%s", api_name);
319601e04c3fSmrg      }
319701e04c3fSmrg      return;
319801e04c3fSmrg   }
319901e04c3fSmrg
320001e04c3fSmrg   struct gl_program *p = sh->Program;
320101e04c3fSmrg   switch (pname) {
320201e04c3fSmrg   case GL_ACTIVE_SUBROUTINES:
320301e04c3fSmrg      values[0] = p->sh.NumSubroutineFunctions;
320401e04c3fSmrg      break;
320501e04c3fSmrg   case GL_ACTIVE_SUBROUTINE_UNIFORM_LOCATIONS:
320601e04c3fSmrg      values[0] = p->sh.NumSubroutineUniformRemapTable;
320701e04c3fSmrg      break;
320801e04c3fSmrg   case GL_ACTIVE_SUBROUTINE_UNIFORMS:
320901e04c3fSmrg      values[0] = p->sh.NumSubroutineUniforms;
321001e04c3fSmrg      break;
321101e04c3fSmrg   case GL_ACTIVE_SUBROUTINE_MAX_LENGTH:
321201e04c3fSmrg   {
321301e04c3fSmrg      unsigned i;
321401e04c3fSmrg      GLint max_len = 0;
321501e04c3fSmrg      GLenum resource_type;
321601e04c3fSmrg      struct gl_program_resource *res;
321701e04c3fSmrg
321801e04c3fSmrg      resource_type = _mesa_shader_stage_to_subroutine(stage);
321901e04c3fSmrg      for (i = 0; i < p->sh.NumSubroutineFunctions; i++) {
322001e04c3fSmrg         res = _mesa_program_resource_find_index(shProg, resource_type, i);
322101e04c3fSmrg         if (res) {
322201e04c3fSmrg            const GLint len = strlen(_mesa_program_resource_name(res)) + 1;
322301e04c3fSmrg            if (len > max_len)
322401e04c3fSmrg               max_len = len;
322501e04c3fSmrg         }
322601e04c3fSmrg      }
322701e04c3fSmrg      values[0] = max_len;
322801e04c3fSmrg      break;
322901e04c3fSmrg   }
323001e04c3fSmrg   case GL_ACTIVE_SUBROUTINE_UNIFORM_MAX_LENGTH:
323101e04c3fSmrg   {
323201e04c3fSmrg      unsigned i;
323301e04c3fSmrg      GLint max_len = 0;
323401e04c3fSmrg      GLenum resource_type;
323501e04c3fSmrg      struct gl_program_resource *res;
323601e04c3fSmrg
323701e04c3fSmrg      resource_type = _mesa_shader_stage_to_subroutine_uniform(stage);
323801e04c3fSmrg      for (i = 0; i < p->sh.NumSubroutineUniformRemapTable; i++) {
323901e04c3fSmrg         res = _mesa_program_resource_find_index(shProg, resource_type, i);
324001e04c3fSmrg         if (res) {
324101e04c3fSmrg            const GLint len = strlen(_mesa_program_resource_name(res)) + 1
324201e04c3fSmrg               + ((_mesa_program_resource_array_size(res) != 0) ? 3 : 0);
324301e04c3fSmrg
324401e04c3fSmrg            if (len > max_len)
324501e04c3fSmrg               max_len = len;
324601e04c3fSmrg         }
324701e04c3fSmrg      }
324801e04c3fSmrg      values[0] = max_len;
324901e04c3fSmrg      break;
325001e04c3fSmrg   }
325101e04c3fSmrg   default:
325201e04c3fSmrg      _mesa_error(ctx, GL_INVALID_ENUM, "%s", api_name);
325301e04c3fSmrg      values[0] = -1;
325401e04c3fSmrg      break;
325501e04c3fSmrg   }
325601e04c3fSmrg}
325701e04c3fSmrg
32587ec681f3Smrg/* This is simple list entry that will be used to hold a list of string
32597ec681f3Smrg * tokens of a parsed shader include path.
32607ec681f3Smrg */
32617ec681f3Smrgstruct sh_incl_path_entry
32627ec681f3Smrg{
32637ec681f3Smrg   struct sh_incl_path_entry *next;
32647ec681f3Smrg   struct sh_incl_path_entry *prev;
32657ec681f3Smrg
32667ec681f3Smrg   char *path;
32677ec681f3Smrg};
32687ec681f3Smrg
32697ec681f3Smrg/* Nodes of the shader include tree */
32707ec681f3Smrgstruct sh_incl_path_ht_entry
32717ec681f3Smrg{
32727ec681f3Smrg   struct hash_table *path;
32737ec681f3Smrg   char *shader_source;
32747ec681f3Smrg};
32757ec681f3Smrg
32767ec681f3Smrgstruct shader_includes {
32777ec681f3Smrg   /* Array to hold include paths given to glCompileShaderIncludeARB() */
32787ec681f3Smrg   struct sh_incl_path_entry **include_paths;
32797ec681f3Smrg   size_t num_include_paths;
32807ec681f3Smrg   size_t relative_path_cursor;
32817ec681f3Smrg
32827ec681f3Smrg   /* Root hash table holding the shader include tree */
32837ec681f3Smrg   struct hash_table *shader_include_tree;
32847ec681f3Smrg};
32857ec681f3Smrg
32867ec681f3Smrgvoid
32877ec681f3Smrg_mesa_init_shader_includes(struct gl_shared_state *shared)
32887ec681f3Smrg{
32897ec681f3Smrg   shared->ShaderIncludes = calloc(1, sizeof(struct shader_includes));
32907ec681f3Smrg   shared->ShaderIncludes->shader_include_tree =
32917ec681f3Smrg      _mesa_hash_table_create(NULL, _mesa_hash_string,
32927ec681f3Smrg                              _mesa_key_string_equal);
32937ec681f3Smrg}
32947ec681f3Smrg
32957ec681f3Smrgsize_t
32967ec681f3Smrg_mesa_get_shader_include_cursor(struct gl_shared_state *shared)
32977ec681f3Smrg{
32987ec681f3Smrg   return shared->ShaderIncludes->relative_path_cursor;
32997ec681f3Smrg}
33007ec681f3Smrg
33017ec681f3Smrgvoid
33027ec681f3Smrg_mesa_set_shader_include_cursor(struct gl_shared_state *shared, size_t cursor)
33037ec681f3Smrg{
33047ec681f3Smrg   shared->ShaderIncludes->relative_path_cursor = cursor;
33057ec681f3Smrg}
33067ec681f3Smrg
33077ec681f3Smrgstatic void
33087ec681f3Smrgdestroy_shader_include(struct hash_entry *entry)
33097ec681f3Smrg{
33107ec681f3Smrg   struct sh_incl_path_ht_entry *sh_incl_ht_entry =
33117ec681f3Smrg      (struct sh_incl_path_ht_entry *) entry->data;
33127ec681f3Smrg
33137ec681f3Smrg   _mesa_hash_table_destroy(sh_incl_ht_entry->path, destroy_shader_include);
33147ec681f3Smrg   free(sh_incl_ht_entry->shader_source);
33157ec681f3Smrg   free(sh_incl_ht_entry);
33167ec681f3Smrg}
33177ec681f3Smrg
33187ec681f3Smrgvoid
33197ec681f3Smrg_mesa_destroy_shader_includes(struct gl_shared_state *shared)
33207ec681f3Smrg{
33217ec681f3Smrg   _mesa_hash_table_destroy(shared->ShaderIncludes->shader_include_tree,
33227ec681f3Smrg                            destroy_shader_include);
33237ec681f3Smrg   free(shared->ShaderIncludes);
33247ec681f3Smrg}
33257ec681f3Smrg
33267ec681f3Smrgstatic bool
33277ec681f3Smrgvalid_path_format(const char *str, bool relative_path)
33287ec681f3Smrg{
33297ec681f3Smrg   int i = 0;
33307ec681f3Smrg
33317ec681f3Smrg   if (!str[i] || (!relative_path && str[i] != '/'))
33327ec681f3Smrg      return false;
33337ec681f3Smrg
33347ec681f3Smrg   i++;
33357ec681f3Smrg
33367ec681f3Smrg   while (str[i]) {
33377ec681f3Smrg      const char c = str[i++];
33387ec681f3Smrg      if (('A' <= c && c <= 'Z') ||
33397ec681f3Smrg          ('a' <= c && c <= 'z') ||
33407ec681f3Smrg          ('0' <= c && c <= '9'))
33417ec681f3Smrg         continue;
33427ec681f3Smrg
33437ec681f3Smrg      if (c == '/') {
33447ec681f3Smrg         if (str[i - 2] == '/')
33457ec681f3Smrg            return false;
33467ec681f3Smrg
33477ec681f3Smrg         continue;
33487ec681f3Smrg      }
33497ec681f3Smrg
33507ec681f3Smrg      if (strchr("^. _+*%[](){}|&~=!:;,?-", c) == NULL)
33517ec681f3Smrg         return false;
33527ec681f3Smrg  }
33537ec681f3Smrg
33547ec681f3Smrg  if (str[i - 1] == '/')
33557ec681f3Smrg     return false;
33567ec681f3Smrg
33577ec681f3Smrg  return true;
33587ec681f3Smrg}
33597ec681f3Smrg
33607ec681f3Smrg
33617ec681f3Smrgstatic bool
33627ec681f3Smrgvalidate_and_tokenise_sh_incl(struct gl_context *ctx,
33637ec681f3Smrg                              void *mem_ctx,
33647ec681f3Smrg                              struct sh_incl_path_entry **path_list,
33657ec681f3Smrg                              char *full_path, bool error_check)
33667ec681f3Smrg{
33677ec681f3Smrg   bool relative_path = ctx->Shared->ShaderIncludes->num_include_paths;
33687ec681f3Smrg
33697ec681f3Smrg   if (!valid_path_format(full_path, relative_path)) {
33707ec681f3Smrg      if (error_check) {
33717ec681f3Smrg         _mesa_error(ctx, GL_INVALID_VALUE,
33727ec681f3Smrg                     "glNamedStringARB(invalid name %s)", full_path);
33737ec681f3Smrg      }
33747ec681f3Smrg      return false;
33757ec681f3Smrg   }
33767ec681f3Smrg
33777ec681f3Smrg   char *save_ptr = NULL;
33787ec681f3Smrg   char *path_str = strtok_r(full_path, "/", &save_ptr);
33797ec681f3Smrg
33807ec681f3Smrg   *path_list = rzalloc(mem_ctx, struct sh_incl_path_entry);
33817ec681f3Smrg
33827ec681f3Smrg   make_empty_list(*path_list);
33837ec681f3Smrg
33847ec681f3Smrg   while (path_str != NULL) {
33857ec681f3Smrg      if (strlen(path_str) == 0) {
33867ec681f3Smrg         if (error_check) {
33877ec681f3Smrg            _mesa_error(ctx, GL_INVALID_VALUE,
33887ec681f3Smrg                        "glNamedStringARB(invalid name %s)", full_path);
33897ec681f3Smrg         }
33907ec681f3Smrg
33917ec681f3Smrg         return false;
33927ec681f3Smrg      }
33937ec681f3Smrg
33947ec681f3Smrg      if (strcmp(path_str, ".") == 0) {
33957ec681f3Smrg         /* Do nothing */
33967ec681f3Smrg      } else if (strcmp(path_str, "..") == 0) {
33977ec681f3Smrg         struct sh_incl_path_entry *last = last_elem(*path_list);
33987ec681f3Smrg         remove_from_list(last);
33997ec681f3Smrg      } else {
34007ec681f3Smrg         struct sh_incl_path_entry *path =
34017ec681f3Smrg            rzalloc(mem_ctx, struct sh_incl_path_entry);
34027ec681f3Smrg
34037ec681f3Smrg         path->path = strdup(path_str);
34047ec681f3Smrg         insert_at_tail(*path_list, path);
34057ec681f3Smrg      }
34067ec681f3Smrg
34077ec681f3Smrg      path_str = strtok_r(NULL, "/", &save_ptr);
34087ec681f3Smrg   }
34097ec681f3Smrg
34107ec681f3Smrg   return true;
34117ec681f3Smrg}
34127ec681f3Smrg
34137ec681f3Smrgstatic struct sh_incl_path_ht_entry *
34147ec681f3Smrglookup_shader_include(struct gl_context *ctx, char *path,
34157ec681f3Smrg                      bool error_check)
34167ec681f3Smrg{
34177ec681f3Smrg   void *mem_ctx = ralloc_context(NULL);
34187ec681f3Smrg   struct sh_incl_path_entry *path_list;
34197ec681f3Smrg
34207ec681f3Smrg   if (!validate_and_tokenise_sh_incl(ctx, mem_ctx, &path_list, path,
34217ec681f3Smrg                                      error_check)) {
34227ec681f3Smrg      ralloc_free(mem_ctx);
34237ec681f3Smrg      return NULL;
34247ec681f3Smrg   }
34257ec681f3Smrg
34267ec681f3Smrg   struct sh_incl_path_ht_entry *sh_incl_ht_entry = NULL;
34277ec681f3Smrg   struct hash_table *path_ht =
34287ec681f3Smrg      ctx->Shared->ShaderIncludes->shader_include_tree;
34297ec681f3Smrg
34307ec681f3Smrg   size_t count = ctx->Shared->ShaderIncludes->num_include_paths;
34317ec681f3Smrg   bool relative_path = path[0] != '/';
34327ec681f3Smrg
34337ec681f3Smrg   size_t i = ctx->Shared->ShaderIncludes->relative_path_cursor;
34347ec681f3Smrg   bool use_cursor = ctx->Shared->ShaderIncludes->relative_path_cursor;
34357ec681f3Smrg
34367ec681f3Smrg   do {
34377ec681f3Smrg      struct sh_incl_path_entry *entry;
34387ec681f3Smrg
34397ec681f3Smrg      if (relative_path) {
34407ec681f3Smrgnext_relative_path:
34417ec681f3Smrg         {
34427ec681f3Smrg            struct sh_incl_path_entry *rel_path_list =
34437ec681f3Smrg               ctx->Shared->ShaderIncludes->include_paths[i];
34447ec681f3Smrg            foreach(entry, rel_path_list) {
34457ec681f3Smrg               struct hash_entry *ht_entry =
34467ec681f3Smrg                  _mesa_hash_table_search(path_ht, entry->path);
34477ec681f3Smrg
34487ec681f3Smrg               if (!ht_entry) {
34497ec681f3Smrg                  /* Reset search path and skip to the next include path */
34507ec681f3Smrg                  path_ht = ctx->Shared->ShaderIncludes->shader_include_tree;
34517ec681f3Smrg                  sh_incl_ht_entry = NULL;
34527ec681f3Smrg                  if (use_cursor) {
34537ec681f3Smrg                     i = 0;
34547ec681f3Smrg                     use_cursor = false;
34557ec681f3Smrg
34567ec681f3Smrg                     goto next_relative_path;
34577ec681f3Smrg                  }
34587ec681f3Smrg                  i++;
34597ec681f3Smrg                  if (i < count)
34607ec681f3Smrg                     goto next_relative_path;
34617ec681f3Smrg                  else
34627ec681f3Smrg                     break;
34637ec681f3Smrg               } else {
34647ec681f3Smrg                  sh_incl_ht_entry =
34657ec681f3Smrg                    (struct sh_incl_path_ht_entry *) ht_entry->data;
34667ec681f3Smrg               }
34677ec681f3Smrg
34687ec681f3Smrg               path_ht = sh_incl_ht_entry->path;
34697ec681f3Smrg            }
34707ec681f3Smrg         }
34717ec681f3Smrg      }
34727ec681f3Smrg
34737ec681f3Smrg      foreach(entry, path_list) {
34747ec681f3Smrg         struct hash_entry *ht_entry =
34757ec681f3Smrg            _mesa_hash_table_search(path_ht, entry->path);
34767ec681f3Smrg
34777ec681f3Smrg         if (!ht_entry) {
34787ec681f3Smrg            /* Reset search path and skip to the next include path */
34797ec681f3Smrg            path_ht = ctx->Shared->ShaderIncludes->shader_include_tree;
34807ec681f3Smrg            sh_incl_ht_entry = NULL;
34817ec681f3Smrg            if (use_cursor) {
34827ec681f3Smrg               i = 0;
34837ec681f3Smrg               use_cursor = false;
34847ec681f3Smrg
34857ec681f3Smrg               break;
34867ec681f3Smrg            }
34877ec681f3Smrg            i++;
34887ec681f3Smrg            break;
34897ec681f3Smrg         } else {
34907ec681f3Smrg
34917ec681f3Smrg            sh_incl_ht_entry =
34927ec681f3Smrg               (struct sh_incl_path_ht_entry *) ht_entry->data;
34937ec681f3Smrg         }
34947ec681f3Smrg
34957ec681f3Smrg         path_ht = sh_incl_ht_entry->path;
34967ec681f3Smrg      }
34977ec681f3Smrg
34987ec681f3Smrg      if (i < count &&
34997ec681f3Smrg          (sh_incl_ht_entry == NULL || !sh_incl_ht_entry->shader_source))
35007ec681f3Smrg         continue;
35017ec681f3Smrg
35027ec681f3Smrg      /* If we get here then we have found a matching path or exahusted our
35037ec681f3Smrg       * relative search paths.
35047ec681f3Smrg       */
35057ec681f3Smrg      ctx->Shared->ShaderIncludes->relative_path_cursor = i;
35067ec681f3Smrg      break;
35077ec681f3Smrg   } while (i < count);
35087ec681f3Smrg
35097ec681f3Smrg   ralloc_free(mem_ctx);
35107ec681f3Smrg
35117ec681f3Smrg   return sh_incl_ht_entry;
35127ec681f3Smrg}
35137ec681f3Smrg
35147ec681f3Smrgconst char *
35157ec681f3Smrg_mesa_lookup_shader_include(struct gl_context *ctx, char *path,
35167ec681f3Smrg                            bool error_check)
35177ec681f3Smrg{
35187ec681f3Smrg   struct sh_incl_path_ht_entry *shader_include =
35197ec681f3Smrg      lookup_shader_include(ctx, path, error_check);
35207ec681f3Smrg
35217ec681f3Smrg   return shader_include ? shader_include->shader_source : NULL;
35227ec681f3Smrg}
35237ec681f3Smrg
35247ec681f3Smrgstatic char *
35257ec681f3Smrgcopy_string(struct gl_context *ctx, const char *str, int str_len,
35267ec681f3Smrg            const char *caller)
35277ec681f3Smrg{
35287ec681f3Smrg   if (!str) {
35297ec681f3Smrg      _mesa_error(ctx, GL_INVALID_VALUE, "%s(NULL string)", caller);
35307ec681f3Smrg      return NULL;
35317ec681f3Smrg   }
35327ec681f3Smrg
35337ec681f3Smrg   char *cp;
35347ec681f3Smrg   if (str_len == -1)
35357ec681f3Smrg      cp = strdup(str);
35367ec681f3Smrg   else {
35377ec681f3Smrg      cp = calloc(sizeof(char), str_len + 1);
35387ec681f3Smrg      memcpy(cp, str, str_len);
35397ec681f3Smrg   }
35407ec681f3Smrg
35417ec681f3Smrg   return cp;
35427ec681f3Smrg}
35437ec681f3Smrg
35447ec681f3SmrgGLvoid GLAPIENTRY
35457ec681f3Smrg_mesa_NamedStringARB(GLenum type, GLint namelen, const GLchar *name,
35467ec681f3Smrg                     GLint stringlen, const GLchar *string)
35477ec681f3Smrg{
35487ec681f3Smrg   GET_CURRENT_CONTEXT(ctx);
35497ec681f3Smrg   const char *caller = "glNamedStringARB";
35507ec681f3Smrg
35517ec681f3Smrg   if (type != GL_SHADER_INCLUDE_ARB) {
35527ec681f3Smrg      _mesa_error(ctx, GL_INVALID_VALUE, "%s(invalid type)", caller);
35537ec681f3Smrg      return;
35547ec681f3Smrg   }
35557ec681f3Smrg
35567ec681f3Smrg   char *name_cp = copy_string(ctx, name, namelen, caller);
35577ec681f3Smrg   char *string_cp = copy_string(ctx, string, stringlen, caller);
35587ec681f3Smrg   if (!name_cp || !string_cp) {
35597ec681f3Smrg      free(string_cp);
35607ec681f3Smrg      free(name_cp);
35617ec681f3Smrg      return;
35627ec681f3Smrg   }
35637ec681f3Smrg
35647ec681f3Smrg   void *mem_ctx = ralloc_context(NULL);
35657ec681f3Smrg   struct sh_incl_path_entry *path_list;
35667ec681f3Smrg
35677ec681f3Smrg   if (!validate_and_tokenise_sh_incl(ctx, mem_ctx, &path_list, name_cp,
35687ec681f3Smrg                                      true)) {
35697ec681f3Smrg      free(string_cp);
35707ec681f3Smrg      free(name_cp);
35717ec681f3Smrg      ralloc_free(mem_ctx);
35727ec681f3Smrg      return;
35737ec681f3Smrg   }
35747ec681f3Smrg
35757ec681f3Smrg   simple_mtx_lock(&ctx->Shared->ShaderIncludeMutex);
35767ec681f3Smrg
35777ec681f3Smrg   struct hash_table *path_ht =
35787ec681f3Smrg      ctx->Shared->ShaderIncludes->shader_include_tree;
35797ec681f3Smrg
35807ec681f3Smrg   struct sh_incl_path_entry *entry;
35817ec681f3Smrg   foreach(entry, path_list) {
35827ec681f3Smrg      struct hash_entry *ht_entry =
35837ec681f3Smrg         _mesa_hash_table_search(path_ht, entry->path);
35847ec681f3Smrg
35857ec681f3Smrg      struct sh_incl_path_ht_entry *sh_incl_ht_entry;
35867ec681f3Smrg      if (!ht_entry) {
35877ec681f3Smrg         sh_incl_ht_entry = calloc(1, sizeof(struct sh_incl_path_ht_entry));
35887ec681f3Smrg         sh_incl_ht_entry->path =
35897ec681f3Smrg            _mesa_hash_table_create(NULL, _mesa_hash_string,
35907ec681f3Smrg                                    _mesa_key_string_equal);
35917ec681f3Smrg         _mesa_hash_table_insert(path_ht, entry->path, sh_incl_ht_entry);
35927ec681f3Smrg      } else {
35937ec681f3Smrg         sh_incl_ht_entry = (struct sh_incl_path_ht_entry *) ht_entry->data;
35947ec681f3Smrg      }
35957ec681f3Smrg
35967ec681f3Smrg      path_ht = sh_incl_ht_entry->path;
35977ec681f3Smrg
35987ec681f3Smrg      if (last_elem(path_list) == entry) {
35997ec681f3Smrg         free(sh_incl_ht_entry->shader_source);
36007ec681f3Smrg         sh_incl_ht_entry->shader_source = string_cp;
36017ec681f3Smrg      }
36027ec681f3Smrg   }
36037ec681f3Smrg
36047ec681f3Smrg   simple_mtx_unlock(&ctx->Shared->ShaderIncludeMutex);
36057ec681f3Smrg
36067ec681f3Smrg   free(name_cp);
36077ec681f3Smrg   ralloc_free(mem_ctx);
36087ec681f3Smrg}
36097ec681f3Smrg
36107ec681f3SmrgGLvoid GLAPIENTRY
36117ec681f3Smrg_mesa_DeleteNamedStringARB(GLint namelen, const GLchar *name)
36127ec681f3Smrg{
36137ec681f3Smrg   GET_CURRENT_CONTEXT(ctx);
36147ec681f3Smrg   const char *caller = "glDeleteNamedStringARB";
36157ec681f3Smrg
36167ec681f3Smrg   char *name_cp = copy_string(ctx, name, namelen, caller);
36177ec681f3Smrg   if (!name_cp)
36187ec681f3Smrg      return;
36197ec681f3Smrg
36207ec681f3Smrg   struct sh_incl_path_ht_entry *shader_include =
36217ec681f3Smrg      lookup_shader_include(ctx, name_cp, true);
36227ec681f3Smrg
36237ec681f3Smrg   if (!shader_include) {
36247ec681f3Smrg      _mesa_error(ctx, GL_INVALID_OPERATION,
36257ec681f3Smrg                  "%s(no string associated with path %s)", caller, name_cp);
36267ec681f3Smrg      free(name_cp);
36277ec681f3Smrg      return;
36287ec681f3Smrg   }
36297ec681f3Smrg
36307ec681f3Smrg   simple_mtx_lock(&ctx->Shared->ShaderIncludeMutex);
36317ec681f3Smrg
36327ec681f3Smrg   free(shader_include->shader_source);
36337ec681f3Smrg   shader_include->shader_source = NULL;
36347ec681f3Smrg
36357ec681f3Smrg   simple_mtx_unlock(&ctx->Shared->ShaderIncludeMutex);
36367ec681f3Smrg
36377ec681f3Smrg   free(name_cp);
36387ec681f3Smrg}
36397ec681f3Smrg
36407ec681f3SmrgGLvoid GLAPIENTRY
36417ec681f3Smrg_mesa_CompileShaderIncludeARB(GLuint shader, GLsizei count,
36427ec681f3Smrg                              const GLchar* const *path, const GLint *length)
36437ec681f3Smrg{
36447ec681f3Smrg   GET_CURRENT_CONTEXT(ctx);
36457ec681f3Smrg   const char *caller = "glCompileShaderIncludeARB";
36467ec681f3Smrg
36477ec681f3Smrg   if (count > 0 && path == NULL) {
36487ec681f3Smrg      _mesa_error(ctx, GL_INVALID_VALUE, "%s(count > 0 && path == NULL)",
36497ec681f3Smrg                  caller);
36507ec681f3Smrg      return;
36517ec681f3Smrg   }
36527ec681f3Smrg
36537ec681f3Smrg   void *mem_ctx = ralloc_context(NULL);
36547ec681f3Smrg
36557ec681f3Smrg   simple_mtx_lock(&ctx->Shared->ShaderIncludeMutex);
36567ec681f3Smrg
36577ec681f3Smrg   ctx->Shared->ShaderIncludes->include_paths =
36587ec681f3Smrg      ralloc_array_size(mem_ctx, sizeof(struct sh_incl_path_entry *), count);
36597ec681f3Smrg
36607ec681f3Smrg   for (size_t i = 0; i < count; i++) {
36617ec681f3Smrg      char *path_cp = copy_string(ctx, path[i], length ? length[i] : -1,
36627ec681f3Smrg                                  caller);
36637ec681f3Smrg      if (!path_cp) {
36647ec681f3Smrg         goto exit;
36657ec681f3Smrg      }
36667ec681f3Smrg
36677ec681f3Smrg      struct sh_incl_path_entry *path_list;
36687ec681f3Smrg
36697ec681f3Smrg      if (!validate_and_tokenise_sh_incl(ctx, mem_ctx, &path_list, path_cp,
36707ec681f3Smrg                                         true)) {
36717ec681f3Smrg         free(path_cp);
36727ec681f3Smrg         goto exit;
36737ec681f3Smrg      }
36747ec681f3Smrg
36757ec681f3Smrg      ctx->Shared->ShaderIncludes->include_paths[i] = path_list;
36767ec681f3Smrg
36777ec681f3Smrg      free(path_cp);
36787ec681f3Smrg   }
36797ec681f3Smrg
36807ec681f3Smrg   /* We must set this *after* all calls to validate_and_tokenise_sh_incl()
36817ec681f3Smrg    * are done as we use this to decide if we need to check the start of the
36827ec681f3Smrg    * path for a '/'
36837ec681f3Smrg    */
36847ec681f3Smrg   ctx->Shared->ShaderIncludes->num_include_paths = count;
36857ec681f3Smrg
36867ec681f3Smrg   struct gl_shader *sh = _mesa_lookup_shader(ctx, shader);
36877ec681f3Smrg   if (!sh) {
36887ec681f3Smrg      _mesa_error(ctx, GL_INVALID_OPERATION, "%s(shader)", caller);
36897ec681f3Smrg      goto exit;
36907ec681f3Smrg   }
36917ec681f3Smrg
36927ec681f3Smrg   _mesa_compile_shader(ctx, sh);
36937ec681f3Smrg
36947ec681f3Smrgexit:
36957ec681f3Smrg   ctx->Shared->ShaderIncludes->num_include_paths = 0;
36967ec681f3Smrg   ctx->Shared->ShaderIncludes->relative_path_cursor = 0;
36977ec681f3Smrg   ctx->Shared->ShaderIncludes->include_paths = NULL;
36987ec681f3Smrg
36997ec681f3Smrg   simple_mtx_unlock(&ctx->Shared->ShaderIncludeMutex);
37007ec681f3Smrg
37017ec681f3Smrg   ralloc_free(mem_ctx);
37027ec681f3Smrg}
37037ec681f3Smrg
37047ec681f3SmrgGLboolean GLAPIENTRY
37057ec681f3Smrg_mesa_IsNamedStringARB(GLint namelen, const GLchar *name)
37067ec681f3Smrg{
37077ec681f3Smrg   GET_CURRENT_CONTEXT(ctx);
37087ec681f3Smrg
37097ec681f3Smrg   if (!name)
37107ec681f3Smrg      return false;
37117ec681f3Smrg
37127ec681f3Smrg   char *name_cp = copy_string(ctx, name, namelen, "");
37137ec681f3Smrg
37147ec681f3Smrg   const char *source = _mesa_lookup_shader_include(ctx, name_cp, false);
37157ec681f3Smrg   free(name_cp);
37167ec681f3Smrg
37177ec681f3Smrg   if (!source)
37187ec681f3Smrg      return false;
37197ec681f3Smrg
37207ec681f3Smrg   return true;
37217ec681f3Smrg}
37227ec681f3Smrg
37237ec681f3SmrgGLvoid GLAPIENTRY
37247ec681f3Smrg_mesa_GetNamedStringARB(GLint namelen, const GLchar *name, GLsizei bufSize,
37257ec681f3Smrg                        GLint *stringlen, GLchar *string)
37267ec681f3Smrg{
37277ec681f3Smrg   GET_CURRENT_CONTEXT(ctx);
37287ec681f3Smrg   const char *caller = "glGetNamedStringARB";
37297ec681f3Smrg
37307ec681f3Smrg   char *name_cp = copy_string(ctx, name, namelen, caller);
37317ec681f3Smrg   if (!name_cp)
37327ec681f3Smrg      return;
37337ec681f3Smrg
37347ec681f3Smrg   const char *source = _mesa_lookup_shader_include(ctx, name_cp, true);
37357ec681f3Smrg   if (!source) {
37367ec681f3Smrg      _mesa_error(ctx, GL_INVALID_OPERATION,
37377ec681f3Smrg                  "%s(no string associated with path %s)", caller, name_cp);
37387ec681f3Smrg      free(name_cp);
37397ec681f3Smrg      return;
37407ec681f3Smrg   }
37417ec681f3Smrg
37427ec681f3Smrg   size_t size = MIN2(strlen(source), bufSize - 1);
37437ec681f3Smrg   memcpy(string, source, size);
37447ec681f3Smrg   string[size] = '\0';
37457ec681f3Smrg
37467ec681f3Smrg   *stringlen = size;
37477ec681f3Smrg
37487ec681f3Smrg   free(name_cp);
37497ec681f3Smrg}
37507ec681f3Smrg
37517ec681f3SmrgGLvoid GLAPIENTRY
37527ec681f3Smrg_mesa_GetNamedStringivARB(GLint namelen, const GLchar *name,
37537ec681f3Smrg                          GLenum pname, GLint *params)
37547ec681f3Smrg{
37557ec681f3Smrg   GET_CURRENT_CONTEXT(ctx);
37567ec681f3Smrg   const char *caller = "glGetNamedStringivARB";
37577ec681f3Smrg
37587ec681f3Smrg   char *name_cp = copy_string(ctx, name, namelen, caller);
37597ec681f3Smrg   if (!name_cp)
37607ec681f3Smrg      return;
37617ec681f3Smrg
37627ec681f3Smrg   const char *source = _mesa_lookup_shader_include(ctx, name_cp, true);
37637ec681f3Smrg   if (!source) {
37647ec681f3Smrg      _mesa_error(ctx, GL_INVALID_OPERATION,
37657ec681f3Smrg                  "%s(no string associated with path %s)", caller, name_cp);
37667ec681f3Smrg      free(name_cp);
37677ec681f3Smrg      return;
37687ec681f3Smrg   }
37697ec681f3Smrg
37707ec681f3Smrg   switch (pname) {
37717ec681f3Smrg   case GL_NAMED_STRING_LENGTH_ARB:
37727ec681f3Smrg      *params = strlen(source) + 1;
37737ec681f3Smrg      break;
37747ec681f3Smrg   case GL_NAMED_STRING_TYPE_ARB:
37757ec681f3Smrg      *params = GL_SHADER_INCLUDE_ARB;
37767ec681f3Smrg      break;
37777ec681f3Smrg   default:
37787ec681f3Smrg      _mesa_error(ctx, GL_INVALID_ENUM, "%s(pname)", caller);
37797ec681f3Smrg      break;
37807ec681f3Smrg   }
37817ec681f3Smrg
37827ec681f3Smrg   free(name_cp);
37837ec681f3Smrg}
37847ec681f3Smrg
378501e04c3fSmrgstatic int
378601e04c3fSmrgfind_compat_subroutine(struct gl_program *p, const struct glsl_type *type)
378701e04c3fSmrg{
378801e04c3fSmrg   int i, j;
378901e04c3fSmrg
379001e04c3fSmrg   for (i = 0; i < p->sh.NumSubroutineFunctions; i++) {
379101e04c3fSmrg      struct gl_subroutine_function *fn = &p->sh.SubroutineFunctions[i];
379201e04c3fSmrg      for (j = 0; j < fn->num_compat_types; j++) {
379301e04c3fSmrg         if (fn->types[j] == type)
379401e04c3fSmrg            return i;
379501e04c3fSmrg      }
379601e04c3fSmrg   }
379701e04c3fSmrg   return 0;
379801e04c3fSmrg}
379901e04c3fSmrg
380001e04c3fSmrgstatic void
380101e04c3fSmrg_mesa_shader_write_subroutine_index(struct gl_context *ctx,
380201e04c3fSmrg                                    struct gl_program *p)
380301e04c3fSmrg{
380401e04c3fSmrg   int i, j;
380501e04c3fSmrg
380601e04c3fSmrg   if (p->sh.NumSubroutineUniformRemapTable == 0)
380701e04c3fSmrg      return;
380801e04c3fSmrg
380901e04c3fSmrg   i = 0;
381001e04c3fSmrg   do {
381101e04c3fSmrg      struct gl_uniform_storage *uni = p->sh.SubroutineUniformRemapTable[i];
381201e04c3fSmrg      int uni_count;
381301e04c3fSmrg      int val;
381401e04c3fSmrg
381501e04c3fSmrg      if (!uni) {
381601e04c3fSmrg         i++;
381701e04c3fSmrg         continue;
381801e04c3fSmrg      }
381901e04c3fSmrg
382001e04c3fSmrg      uni_count = uni->array_elements ? uni->array_elements : 1;
382101e04c3fSmrg      for (j = 0; j < uni_count; j++) {
382201e04c3fSmrg         val = ctx->SubroutineIndex[p->info.stage].IndexPtr[i + j];
382301e04c3fSmrg         memcpy(&uni->storage[j], &val, sizeof(int));
382401e04c3fSmrg      }
382501e04c3fSmrg
382601e04c3fSmrg      _mesa_propagate_uniforms_to_driver_storage(uni, 0, uni_count);
382701e04c3fSmrg      i += uni_count;
382801e04c3fSmrg   } while(i < p->sh.NumSubroutineUniformRemapTable);
382901e04c3fSmrg}
383001e04c3fSmrg
383101e04c3fSmrgvoid
383201e04c3fSmrg_mesa_shader_write_subroutine_indices(struct gl_context *ctx,
383301e04c3fSmrg                                      gl_shader_stage stage)
383401e04c3fSmrg{
383501e04c3fSmrg   if (ctx->_Shader->CurrentProgram[stage])
383601e04c3fSmrg      _mesa_shader_write_subroutine_index(ctx,
383701e04c3fSmrg                                          ctx->_Shader->CurrentProgram[stage]);
383801e04c3fSmrg}
383901e04c3fSmrg
384001e04c3fSmrgvoid
384101e04c3fSmrg_mesa_program_init_subroutine_defaults(struct gl_context *ctx,
384201e04c3fSmrg                                       struct gl_program *p)
384301e04c3fSmrg{
384401e04c3fSmrg   assert(p);
384501e04c3fSmrg
384601e04c3fSmrg   struct gl_subroutine_index_binding *binding = &ctx->SubroutineIndex[p->info.stage];
384701e04c3fSmrg   if (binding->NumIndex != p->sh.NumSubroutineUniformRemapTable) {
384801e04c3fSmrg      binding->IndexPtr = realloc(binding->IndexPtr,
384901e04c3fSmrg                                  p->sh.NumSubroutineUniformRemapTable * (sizeof(GLuint)));
385001e04c3fSmrg      binding->NumIndex = p->sh.NumSubroutineUniformRemapTable;
385101e04c3fSmrg   }
385201e04c3fSmrg
385301e04c3fSmrg   for (int i = 0; i < p->sh.NumSubroutineUniformRemapTable; i++) {
385401e04c3fSmrg      struct gl_uniform_storage *uni = p->sh.SubroutineUniformRemapTable[i];
385501e04c3fSmrg
385601e04c3fSmrg      if (!uni)
385701e04c3fSmrg         continue;
385801e04c3fSmrg
385901e04c3fSmrg      binding->IndexPtr[i] = find_compat_subroutine(p, uni->type);
386001e04c3fSmrg   }
38613464ebd5Sriastradh}
3862