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 ¶ms); 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