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 shaderobj.c 28bf215546Sopenharmony_ci * \author Brian Paul 29bf215546Sopenharmony_ci * 30bf215546Sopenharmony_ci */ 31bf215546Sopenharmony_ci 32bf215546Sopenharmony_ci 33bf215546Sopenharmony_ci#include "compiler/glsl/string_to_uint_map.h" 34bf215546Sopenharmony_ci#include "main/glheader.h" 35bf215546Sopenharmony_ci#include "main/context.h" 36bf215546Sopenharmony_ci#include "main/glspirv.h" 37bf215546Sopenharmony_ci#include "main/hash.h" 38bf215546Sopenharmony_ci#include "main/mtypes.h" 39bf215546Sopenharmony_ci#include "main/shaderapi.h" 40bf215546Sopenharmony_ci#include "main/shaderobj.h" 41bf215546Sopenharmony_ci#include "main/uniforms.h" 42bf215546Sopenharmony_ci#include "program/program.h" 43bf215546Sopenharmony_ci#include "program/prog_parameter.h" 44bf215546Sopenharmony_ci#include "util/ralloc.h" 45bf215546Sopenharmony_ci#include "util/u_atomic.h" 46bf215546Sopenharmony_ci 47bf215546Sopenharmony_ci/**********************************************************************/ 48bf215546Sopenharmony_ci/*** Shader object functions ***/ 49bf215546Sopenharmony_ci/**********************************************************************/ 50bf215546Sopenharmony_ci 51bf215546Sopenharmony_ci 52bf215546Sopenharmony_ci/** 53bf215546Sopenharmony_ci * Set ptr to point to sh. 54bf215546Sopenharmony_ci * If ptr is pointing to another shader, decrement its refcount (and delete 55bf215546Sopenharmony_ci * if refcount hits zero). 56bf215546Sopenharmony_ci * Then set ptr to point to sh, incrementing its refcount. 57bf215546Sopenharmony_ci */ 58bf215546Sopenharmony_cistatic void 59bf215546Sopenharmony_ci_reference_shader(struct gl_context *ctx, struct gl_shader **ptr, 60bf215546Sopenharmony_ci struct gl_shader *sh, bool skip_locking) 61bf215546Sopenharmony_ci{ 62bf215546Sopenharmony_ci assert(ptr); 63bf215546Sopenharmony_ci if (*ptr == sh) { 64bf215546Sopenharmony_ci /* no-op */ 65bf215546Sopenharmony_ci return; 66bf215546Sopenharmony_ci } 67bf215546Sopenharmony_ci if (*ptr) { 68bf215546Sopenharmony_ci /* Unreference the old shader */ 69bf215546Sopenharmony_ci struct gl_shader *old = *ptr; 70bf215546Sopenharmony_ci 71bf215546Sopenharmony_ci assert(old->RefCount > 0); 72bf215546Sopenharmony_ci 73bf215546Sopenharmony_ci if (p_atomic_dec_zero(&old->RefCount)) { 74bf215546Sopenharmony_ci if (old->Name != 0) { 75bf215546Sopenharmony_ci if (skip_locking) 76bf215546Sopenharmony_ci _mesa_HashRemoveLocked(ctx->Shared->ShaderObjects, old->Name); 77bf215546Sopenharmony_ci else 78bf215546Sopenharmony_ci _mesa_HashRemove(ctx->Shared->ShaderObjects, old->Name); 79bf215546Sopenharmony_ci } 80bf215546Sopenharmony_ci _mesa_delete_shader(ctx, old); 81bf215546Sopenharmony_ci } 82bf215546Sopenharmony_ci 83bf215546Sopenharmony_ci *ptr = NULL; 84bf215546Sopenharmony_ci } 85bf215546Sopenharmony_ci assert(!*ptr); 86bf215546Sopenharmony_ci 87bf215546Sopenharmony_ci if (sh) { 88bf215546Sopenharmony_ci /* reference new */ 89bf215546Sopenharmony_ci p_atomic_inc(&sh->RefCount); 90bf215546Sopenharmony_ci *ptr = sh; 91bf215546Sopenharmony_ci } 92bf215546Sopenharmony_ci} 93bf215546Sopenharmony_ci 94bf215546Sopenharmony_civoid 95bf215546Sopenharmony_ci_mesa_reference_shader(struct gl_context *ctx, struct gl_shader **ptr, 96bf215546Sopenharmony_ci struct gl_shader *sh) 97bf215546Sopenharmony_ci{ 98bf215546Sopenharmony_ci _reference_shader(ctx, ptr, sh, false); 99bf215546Sopenharmony_ci} 100bf215546Sopenharmony_ci 101bf215546Sopenharmony_cistatic void 102bf215546Sopenharmony_ci_mesa_init_shader(struct gl_shader *shader) 103bf215546Sopenharmony_ci{ 104bf215546Sopenharmony_ci shader->RefCount = 1; 105bf215546Sopenharmony_ci shader->info.Geom.VerticesOut = -1; 106bf215546Sopenharmony_ci shader->info.Geom.InputType = SHADER_PRIM_TRIANGLES; 107bf215546Sopenharmony_ci shader->info.Geom.OutputType = SHADER_PRIM_TRIANGLE_STRIP; 108bf215546Sopenharmony_ci} 109bf215546Sopenharmony_ci 110bf215546Sopenharmony_ci/** 111bf215546Sopenharmony_ci * Allocate a new gl_shader object, initialize it. 112bf215546Sopenharmony_ci */ 113bf215546Sopenharmony_cistruct gl_shader * 114bf215546Sopenharmony_ci_mesa_new_shader(GLuint name, gl_shader_stage stage) 115bf215546Sopenharmony_ci{ 116bf215546Sopenharmony_ci struct gl_shader *shader; 117bf215546Sopenharmony_ci shader = rzalloc(NULL, struct gl_shader); 118bf215546Sopenharmony_ci if (shader) { 119bf215546Sopenharmony_ci shader->Stage = stage; 120bf215546Sopenharmony_ci shader->Name = name; 121bf215546Sopenharmony_ci _mesa_init_shader(shader); 122bf215546Sopenharmony_ci } 123bf215546Sopenharmony_ci return shader; 124bf215546Sopenharmony_ci} 125bf215546Sopenharmony_ci 126bf215546Sopenharmony_ci 127bf215546Sopenharmony_ci/** 128bf215546Sopenharmony_ci * Delete a shader object. 129bf215546Sopenharmony_ci */ 130bf215546Sopenharmony_civoid 131bf215546Sopenharmony_ci_mesa_delete_shader(struct gl_context *ctx, struct gl_shader *sh) 132bf215546Sopenharmony_ci{ 133bf215546Sopenharmony_ci _mesa_shader_spirv_data_reference(&sh->spirv_data, NULL); 134bf215546Sopenharmony_ci free((void *)sh->Source); 135bf215546Sopenharmony_ci free((void *)sh->FallbackSource); 136bf215546Sopenharmony_ci free(sh->Label); 137bf215546Sopenharmony_ci ralloc_free(sh); 138bf215546Sopenharmony_ci} 139bf215546Sopenharmony_ci 140bf215546Sopenharmony_ci 141bf215546Sopenharmony_ci/** 142bf215546Sopenharmony_ci * Delete a shader object. 143bf215546Sopenharmony_ci */ 144bf215546Sopenharmony_civoid 145bf215546Sopenharmony_ci_mesa_delete_linked_shader(struct gl_context *ctx, 146bf215546Sopenharmony_ci struct gl_linked_shader *sh) 147bf215546Sopenharmony_ci{ 148bf215546Sopenharmony_ci _mesa_shader_spirv_data_reference(&sh->spirv_data, NULL); 149bf215546Sopenharmony_ci _mesa_reference_program(ctx, &sh->Program, NULL); 150bf215546Sopenharmony_ci ralloc_free(sh); 151bf215546Sopenharmony_ci} 152bf215546Sopenharmony_ci 153bf215546Sopenharmony_ci 154bf215546Sopenharmony_ci/** 155bf215546Sopenharmony_ci * Lookup a GLSL shader object. 156bf215546Sopenharmony_ci */ 157bf215546Sopenharmony_cistruct gl_shader * 158bf215546Sopenharmony_ci_mesa_lookup_shader(struct gl_context *ctx, GLuint name) 159bf215546Sopenharmony_ci{ 160bf215546Sopenharmony_ci if (name) { 161bf215546Sopenharmony_ci struct gl_shader *sh = (struct gl_shader *) 162bf215546Sopenharmony_ci _mesa_HashLookup(ctx->Shared->ShaderObjects, name); 163bf215546Sopenharmony_ci /* Note that both gl_shader and gl_shader_program objects are kept 164bf215546Sopenharmony_ci * in the same hash table. Check the object's type to be sure it's 165bf215546Sopenharmony_ci * what we're expecting. 166bf215546Sopenharmony_ci */ 167bf215546Sopenharmony_ci if (sh && sh->Type == GL_SHADER_PROGRAM_MESA) { 168bf215546Sopenharmony_ci return NULL; 169bf215546Sopenharmony_ci } 170bf215546Sopenharmony_ci return sh; 171bf215546Sopenharmony_ci } 172bf215546Sopenharmony_ci return NULL; 173bf215546Sopenharmony_ci} 174bf215546Sopenharmony_ci 175bf215546Sopenharmony_ci 176bf215546Sopenharmony_ci/** 177bf215546Sopenharmony_ci * As above, but record an error if shader is not found. 178bf215546Sopenharmony_ci */ 179bf215546Sopenharmony_cistruct gl_shader * 180bf215546Sopenharmony_ci_mesa_lookup_shader_err(struct gl_context *ctx, GLuint name, const char *caller) 181bf215546Sopenharmony_ci{ 182bf215546Sopenharmony_ci if (!name) { 183bf215546Sopenharmony_ci _mesa_error(ctx, GL_INVALID_VALUE, "%s", caller); 184bf215546Sopenharmony_ci return NULL; 185bf215546Sopenharmony_ci } 186bf215546Sopenharmony_ci else { 187bf215546Sopenharmony_ci struct gl_shader *sh = (struct gl_shader *) 188bf215546Sopenharmony_ci _mesa_HashLookup(ctx->Shared->ShaderObjects, name); 189bf215546Sopenharmony_ci if (!sh) { 190bf215546Sopenharmony_ci _mesa_error(ctx, GL_INVALID_VALUE, "%s", caller); 191bf215546Sopenharmony_ci return NULL; 192bf215546Sopenharmony_ci } 193bf215546Sopenharmony_ci if (sh->Type == GL_SHADER_PROGRAM_MESA) { 194bf215546Sopenharmony_ci _mesa_error(ctx, GL_INVALID_OPERATION, "%s", caller); 195bf215546Sopenharmony_ci return NULL; 196bf215546Sopenharmony_ci } 197bf215546Sopenharmony_ci return sh; 198bf215546Sopenharmony_ci } 199bf215546Sopenharmony_ci} 200bf215546Sopenharmony_ci 201bf215546Sopenharmony_ci 202bf215546Sopenharmony_ci 203bf215546Sopenharmony_ci/**********************************************************************/ 204bf215546Sopenharmony_ci/*** Shader Program object functions ***/ 205bf215546Sopenharmony_ci/**********************************************************************/ 206bf215546Sopenharmony_ci 207bf215546Sopenharmony_civoid 208bf215546Sopenharmony_ci_mesa_reference_shader_program_data(struct gl_shader_program_data **ptr, 209bf215546Sopenharmony_ci struct gl_shader_program_data *data) 210bf215546Sopenharmony_ci{ 211bf215546Sopenharmony_ci if (*ptr == data) 212bf215546Sopenharmony_ci return; 213bf215546Sopenharmony_ci 214bf215546Sopenharmony_ci if (*ptr) { 215bf215546Sopenharmony_ci struct gl_shader_program_data *oldData = *ptr; 216bf215546Sopenharmony_ci 217bf215546Sopenharmony_ci assert(oldData->RefCount > 0); 218bf215546Sopenharmony_ci 219bf215546Sopenharmony_ci if (p_atomic_dec_zero(&oldData->RefCount)) { 220bf215546Sopenharmony_ci assert(oldData->NumUniformStorage == 0 || 221bf215546Sopenharmony_ci oldData->UniformStorage); 222bf215546Sopenharmony_ci 223bf215546Sopenharmony_ci for (unsigned i = 0; i < oldData->NumUniformStorage; ++i) 224bf215546Sopenharmony_ci _mesa_uniform_detach_all_driver_storage(&oldData->UniformStorage[i]); 225bf215546Sopenharmony_ci 226bf215546Sopenharmony_ci ralloc_free(oldData); 227bf215546Sopenharmony_ci } 228bf215546Sopenharmony_ci 229bf215546Sopenharmony_ci *ptr = NULL; 230bf215546Sopenharmony_ci } 231bf215546Sopenharmony_ci 232bf215546Sopenharmony_ci if (data) 233bf215546Sopenharmony_ci p_atomic_inc(&data->RefCount); 234bf215546Sopenharmony_ci 235bf215546Sopenharmony_ci *ptr = data; 236bf215546Sopenharmony_ci} 237bf215546Sopenharmony_ci 238bf215546Sopenharmony_ci/** 239bf215546Sopenharmony_ci * Set ptr to point to shProg. 240bf215546Sopenharmony_ci * If ptr is pointing to another object, decrement its refcount (and delete 241bf215546Sopenharmony_ci * if refcount hits zero). 242bf215546Sopenharmony_ci * Then set ptr to point to shProg, incrementing its refcount. 243bf215546Sopenharmony_ci */ 244bf215546Sopenharmony_civoid 245bf215546Sopenharmony_ci_mesa_reference_shader_program_(struct gl_context *ctx, 246bf215546Sopenharmony_ci struct gl_shader_program **ptr, 247bf215546Sopenharmony_ci struct gl_shader_program *shProg) 248bf215546Sopenharmony_ci{ 249bf215546Sopenharmony_ci assert(ptr); 250bf215546Sopenharmony_ci if (*ptr == shProg) { 251bf215546Sopenharmony_ci /* no-op */ 252bf215546Sopenharmony_ci return; 253bf215546Sopenharmony_ci } 254bf215546Sopenharmony_ci if (*ptr) { 255bf215546Sopenharmony_ci /* Unreference the old shader program */ 256bf215546Sopenharmony_ci struct gl_shader_program *old = *ptr; 257bf215546Sopenharmony_ci 258bf215546Sopenharmony_ci assert(old->RefCount > 0); 259bf215546Sopenharmony_ci 260bf215546Sopenharmony_ci if (p_atomic_dec_zero(&old->RefCount)) { 261bf215546Sopenharmony_ci _mesa_HashLockMutex(ctx->Shared->ShaderObjects); 262bf215546Sopenharmony_ci if (old->Name != 0) 263bf215546Sopenharmony_ci _mesa_HashRemoveLocked(ctx->Shared->ShaderObjects, old->Name); 264bf215546Sopenharmony_ci _mesa_delete_shader_program(ctx, old); 265bf215546Sopenharmony_ci _mesa_HashUnlockMutex(ctx->Shared->ShaderObjects); 266bf215546Sopenharmony_ci } 267bf215546Sopenharmony_ci 268bf215546Sopenharmony_ci *ptr = NULL; 269bf215546Sopenharmony_ci } 270bf215546Sopenharmony_ci assert(!*ptr); 271bf215546Sopenharmony_ci 272bf215546Sopenharmony_ci if (shProg) { 273bf215546Sopenharmony_ci p_atomic_inc(&shProg->RefCount); 274bf215546Sopenharmony_ci *ptr = shProg; 275bf215546Sopenharmony_ci } 276bf215546Sopenharmony_ci} 277bf215546Sopenharmony_ci 278bf215546Sopenharmony_cistruct gl_shader_program_data * 279bf215546Sopenharmony_ci_mesa_create_shader_program_data() 280bf215546Sopenharmony_ci{ 281bf215546Sopenharmony_ci struct gl_shader_program_data *data; 282bf215546Sopenharmony_ci data = rzalloc(NULL, struct gl_shader_program_data); 283bf215546Sopenharmony_ci if (data) { 284bf215546Sopenharmony_ci data->RefCount = 1; 285bf215546Sopenharmony_ci data->InfoLog = ralloc_strdup(data, ""); 286bf215546Sopenharmony_ci } 287bf215546Sopenharmony_ci 288bf215546Sopenharmony_ci return data; 289bf215546Sopenharmony_ci} 290bf215546Sopenharmony_ci 291bf215546Sopenharmony_cistatic void 292bf215546Sopenharmony_ciinit_shader_program(struct gl_shader_program *prog) 293bf215546Sopenharmony_ci{ 294bf215546Sopenharmony_ci prog->Type = GL_SHADER_PROGRAM_MESA; 295bf215546Sopenharmony_ci prog->RefCount = 1; 296bf215546Sopenharmony_ci 297bf215546Sopenharmony_ci prog->AttributeBindings = string_to_uint_map_ctor(); 298bf215546Sopenharmony_ci prog->FragDataBindings = string_to_uint_map_ctor(); 299bf215546Sopenharmony_ci prog->FragDataIndexBindings = string_to_uint_map_ctor(); 300bf215546Sopenharmony_ci 301bf215546Sopenharmony_ci prog->Geom.UsesEndPrimitive = false; 302bf215546Sopenharmony_ci prog->Geom.ActiveStreamMask = 0; 303bf215546Sopenharmony_ci 304bf215546Sopenharmony_ci prog->TransformFeedback.BufferMode = GL_INTERLEAVED_ATTRIBS; 305bf215546Sopenharmony_ci 306bf215546Sopenharmony_ci exec_list_make_empty(&prog->EmptyUniformLocations); 307bf215546Sopenharmony_ci} 308bf215546Sopenharmony_ci 309bf215546Sopenharmony_ci/** 310bf215546Sopenharmony_ci * Allocate a new gl_shader_program object, initialize it. 311bf215546Sopenharmony_ci */ 312bf215546Sopenharmony_cistruct gl_shader_program * 313bf215546Sopenharmony_ci_mesa_new_shader_program(GLuint name) 314bf215546Sopenharmony_ci{ 315bf215546Sopenharmony_ci struct gl_shader_program *shProg; 316bf215546Sopenharmony_ci shProg = rzalloc(NULL, struct gl_shader_program); 317bf215546Sopenharmony_ci if (shProg) { 318bf215546Sopenharmony_ci shProg->Name = name; 319bf215546Sopenharmony_ci shProg->data = _mesa_create_shader_program_data(); 320bf215546Sopenharmony_ci if (!shProg->data) { 321bf215546Sopenharmony_ci ralloc_free(shProg); 322bf215546Sopenharmony_ci return NULL; 323bf215546Sopenharmony_ci } 324bf215546Sopenharmony_ci init_shader_program(shProg); 325bf215546Sopenharmony_ci } 326bf215546Sopenharmony_ci return shProg; 327bf215546Sopenharmony_ci} 328bf215546Sopenharmony_ci 329bf215546Sopenharmony_ci 330bf215546Sopenharmony_ci/** 331bf215546Sopenharmony_ci * Clear (free) the shader program state that gets produced by linking. 332bf215546Sopenharmony_ci */ 333bf215546Sopenharmony_civoid 334bf215546Sopenharmony_ci_mesa_clear_shader_program_data(struct gl_context *ctx, 335bf215546Sopenharmony_ci struct gl_shader_program *shProg) 336bf215546Sopenharmony_ci{ 337bf215546Sopenharmony_ci for (gl_shader_stage sh = 0; sh < MESA_SHADER_STAGES; sh++) { 338bf215546Sopenharmony_ci if (shProg->_LinkedShaders[sh] != NULL) { 339bf215546Sopenharmony_ci _mesa_delete_linked_shader(ctx, shProg->_LinkedShaders[sh]); 340bf215546Sopenharmony_ci shProg->_LinkedShaders[sh] = NULL; 341bf215546Sopenharmony_ci } 342bf215546Sopenharmony_ci } 343bf215546Sopenharmony_ci 344bf215546Sopenharmony_ci if (shProg->UniformRemapTable) { 345bf215546Sopenharmony_ci ralloc_free(shProg->UniformRemapTable); 346bf215546Sopenharmony_ci shProg->NumUniformRemapTable = 0; 347bf215546Sopenharmony_ci shProg->UniformRemapTable = NULL; 348bf215546Sopenharmony_ci } 349bf215546Sopenharmony_ci 350bf215546Sopenharmony_ci if (shProg->UniformHash) { 351bf215546Sopenharmony_ci string_to_uint_map_dtor(shProg->UniformHash); 352bf215546Sopenharmony_ci shProg->UniformHash = NULL; 353bf215546Sopenharmony_ci } 354bf215546Sopenharmony_ci 355bf215546Sopenharmony_ci if (shProg->data) 356bf215546Sopenharmony_ci _mesa_program_resource_hash_destroy(shProg); 357bf215546Sopenharmony_ci 358bf215546Sopenharmony_ci _mesa_reference_shader_program_data(&shProg->data, NULL); 359bf215546Sopenharmony_ci} 360bf215546Sopenharmony_ci 361bf215546Sopenharmony_ci 362bf215546Sopenharmony_ci/** 363bf215546Sopenharmony_ci * Free all the data that hangs off a shader program object, but not the 364bf215546Sopenharmony_ci * object itself. 365bf215546Sopenharmony_ci * Must be called with shared->ShaderObjects locked. 366bf215546Sopenharmony_ci */ 367bf215546Sopenharmony_civoid 368bf215546Sopenharmony_ci_mesa_free_shader_program_data(struct gl_context *ctx, 369bf215546Sopenharmony_ci struct gl_shader_program *shProg) 370bf215546Sopenharmony_ci{ 371bf215546Sopenharmony_ci GLuint i; 372bf215546Sopenharmony_ci 373bf215546Sopenharmony_ci assert(shProg->Type == GL_SHADER_PROGRAM_MESA); 374bf215546Sopenharmony_ci 375bf215546Sopenharmony_ci _mesa_clear_shader_program_data(ctx, shProg); 376bf215546Sopenharmony_ci 377bf215546Sopenharmony_ci if (shProg->AttributeBindings) { 378bf215546Sopenharmony_ci string_to_uint_map_dtor(shProg->AttributeBindings); 379bf215546Sopenharmony_ci shProg->AttributeBindings = NULL; 380bf215546Sopenharmony_ci } 381bf215546Sopenharmony_ci 382bf215546Sopenharmony_ci if (shProg->FragDataBindings) { 383bf215546Sopenharmony_ci string_to_uint_map_dtor(shProg->FragDataBindings); 384bf215546Sopenharmony_ci shProg->FragDataBindings = NULL; 385bf215546Sopenharmony_ci } 386bf215546Sopenharmony_ci 387bf215546Sopenharmony_ci if (shProg->FragDataIndexBindings) { 388bf215546Sopenharmony_ci string_to_uint_map_dtor(shProg->FragDataIndexBindings); 389bf215546Sopenharmony_ci shProg->FragDataIndexBindings = NULL; 390bf215546Sopenharmony_ci } 391bf215546Sopenharmony_ci 392bf215546Sopenharmony_ci /* detach shaders */ 393bf215546Sopenharmony_ci for (i = 0; i < shProg->NumShaders; i++) { 394bf215546Sopenharmony_ci _reference_shader(ctx, &shProg->Shaders[i], NULL, true); 395bf215546Sopenharmony_ci } 396bf215546Sopenharmony_ci shProg->NumShaders = 0; 397bf215546Sopenharmony_ci 398bf215546Sopenharmony_ci free(shProg->Shaders); 399bf215546Sopenharmony_ci shProg->Shaders = NULL; 400bf215546Sopenharmony_ci 401bf215546Sopenharmony_ci /* Transform feedback varying vars */ 402bf215546Sopenharmony_ci for (i = 0; i < shProg->TransformFeedback.NumVarying; i++) { 403bf215546Sopenharmony_ci free(shProg->TransformFeedback.VaryingNames[i]); 404bf215546Sopenharmony_ci } 405bf215546Sopenharmony_ci free(shProg->TransformFeedback.VaryingNames); 406bf215546Sopenharmony_ci shProg->TransformFeedback.VaryingNames = NULL; 407bf215546Sopenharmony_ci shProg->TransformFeedback.NumVarying = 0; 408bf215546Sopenharmony_ci 409bf215546Sopenharmony_ci free(shProg->Label); 410bf215546Sopenharmony_ci shProg->Label = NULL; 411bf215546Sopenharmony_ci} 412bf215546Sopenharmony_ci 413bf215546Sopenharmony_ci 414bf215546Sopenharmony_ci/** 415bf215546Sopenharmony_ci * Free/delete a shader program object. 416bf215546Sopenharmony_ci */ 417bf215546Sopenharmony_civoid 418bf215546Sopenharmony_ci_mesa_delete_shader_program(struct gl_context *ctx, 419bf215546Sopenharmony_ci struct gl_shader_program *shProg) 420bf215546Sopenharmony_ci{ 421bf215546Sopenharmony_ci _mesa_free_shader_program_data(ctx, shProg); 422bf215546Sopenharmony_ci ralloc_free(shProg); 423bf215546Sopenharmony_ci} 424bf215546Sopenharmony_ci 425bf215546Sopenharmony_ci 426bf215546Sopenharmony_ci/** 427bf215546Sopenharmony_ci * Lookup a GLSL program object. 428bf215546Sopenharmony_ci */ 429bf215546Sopenharmony_cistruct gl_shader_program * 430bf215546Sopenharmony_ci_mesa_lookup_shader_program(struct gl_context *ctx, GLuint name) 431bf215546Sopenharmony_ci{ 432bf215546Sopenharmony_ci struct gl_shader_program *shProg; 433bf215546Sopenharmony_ci if (name) { 434bf215546Sopenharmony_ci shProg = (struct gl_shader_program *) 435bf215546Sopenharmony_ci _mesa_HashLookup(ctx->Shared->ShaderObjects, name); 436bf215546Sopenharmony_ci /* Note that both gl_shader and gl_shader_program objects are kept 437bf215546Sopenharmony_ci * in the same hash table. Check the object's type to be sure it's 438bf215546Sopenharmony_ci * what we're expecting. 439bf215546Sopenharmony_ci */ 440bf215546Sopenharmony_ci if (shProg && shProg->Type != GL_SHADER_PROGRAM_MESA) { 441bf215546Sopenharmony_ci return NULL; 442bf215546Sopenharmony_ci } 443bf215546Sopenharmony_ci return shProg; 444bf215546Sopenharmony_ci } 445bf215546Sopenharmony_ci return NULL; 446bf215546Sopenharmony_ci} 447bf215546Sopenharmony_ci 448bf215546Sopenharmony_ci 449bf215546Sopenharmony_ci/** 450bf215546Sopenharmony_ci * As above, but record an error if program is not found. 451bf215546Sopenharmony_ci */ 452bf215546Sopenharmony_cistruct gl_shader_program * 453bf215546Sopenharmony_ci_mesa_lookup_shader_program_err_glthread(struct gl_context *ctx, GLuint name, 454bf215546Sopenharmony_ci bool glthread, const char *caller) 455bf215546Sopenharmony_ci{ 456bf215546Sopenharmony_ci if (!name) { 457bf215546Sopenharmony_ci _mesa_error_glthread_safe(ctx, GL_INVALID_VALUE, glthread, "%s", caller); 458bf215546Sopenharmony_ci return NULL; 459bf215546Sopenharmony_ci } 460bf215546Sopenharmony_ci else { 461bf215546Sopenharmony_ci struct gl_shader_program *shProg = (struct gl_shader_program *) 462bf215546Sopenharmony_ci _mesa_HashLookup(ctx->Shared->ShaderObjects, name); 463bf215546Sopenharmony_ci if (!shProg) { 464bf215546Sopenharmony_ci _mesa_error_glthread_safe(ctx, GL_INVALID_VALUE, glthread, 465bf215546Sopenharmony_ci "%s", caller); 466bf215546Sopenharmony_ci return NULL; 467bf215546Sopenharmony_ci } 468bf215546Sopenharmony_ci if (shProg->Type != GL_SHADER_PROGRAM_MESA) { 469bf215546Sopenharmony_ci _mesa_error_glthread_safe(ctx, GL_INVALID_OPERATION, glthread, 470bf215546Sopenharmony_ci "%s", caller); 471bf215546Sopenharmony_ci return NULL; 472bf215546Sopenharmony_ci } 473bf215546Sopenharmony_ci return shProg; 474bf215546Sopenharmony_ci } 475bf215546Sopenharmony_ci} 476bf215546Sopenharmony_ci 477bf215546Sopenharmony_ci 478bf215546Sopenharmony_cistruct gl_shader_program * 479bf215546Sopenharmony_ci_mesa_lookup_shader_program_err(struct gl_context *ctx, GLuint name, 480bf215546Sopenharmony_ci const char *caller) 481bf215546Sopenharmony_ci{ 482bf215546Sopenharmony_ci return _mesa_lookup_shader_program_err_glthread(ctx, name, false, caller); 483bf215546Sopenharmony_ci} 484