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