xref: /aosp_15_r20/external/mesa3d/src/mesa/main/shaderobj.c (revision 6104692788411f58d303aa86923a9ff6ecaded22)
1*61046927SAndroid Build Coastguard Worker /*
2*61046927SAndroid Build Coastguard Worker  * Mesa 3-D graphics library
3*61046927SAndroid Build Coastguard Worker  *
4*61046927SAndroid Build Coastguard Worker  * Copyright (C) 2004-2008  Brian Paul   All Rights Reserved.
5*61046927SAndroid Build Coastguard Worker  * Copyright (C) 2009-2010  VMware, Inc.  All Rights Reserved.
6*61046927SAndroid Build Coastguard Worker  *
7*61046927SAndroid Build Coastguard Worker  * Permission is hereby granted, free of charge, to any person obtaining a
8*61046927SAndroid Build Coastguard Worker  * copy of this software and associated documentation files (the "Software"),
9*61046927SAndroid Build Coastguard Worker  * to deal in the Software without restriction, including without limitation
10*61046927SAndroid Build Coastguard Worker  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11*61046927SAndroid Build Coastguard Worker  * and/or sell copies of the Software, and to permit persons to whom the
12*61046927SAndroid Build Coastguard Worker  * Software is furnished to do so, subject to the following conditions:
13*61046927SAndroid Build Coastguard Worker  *
14*61046927SAndroid Build Coastguard Worker  * The above copyright notice and this permission notice shall be included
15*61046927SAndroid Build Coastguard Worker  * in all copies or substantial portions of the Software.
16*61046927SAndroid Build Coastguard Worker  *
17*61046927SAndroid Build Coastguard Worker  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18*61046927SAndroid Build Coastguard Worker  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19*61046927SAndroid Build Coastguard Worker  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
20*61046927SAndroid Build Coastguard Worker  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
21*61046927SAndroid Build Coastguard Worker  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
22*61046927SAndroid Build Coastguard Worker  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
23*61046927SAndroid Build Coastguard Worker  * OTHER DEALINGS IN THE SOFTWARE.
24*61046927SAndroid Build Coastguard Worker  */
25*61046927SAndroid Build Coastguard Worker 
26*61046927SAndroid Build Coastguard Worker /**
27*61046927SAndroid Build Coastguard Worker  * \file shaderobj.c
28*61046927SAndroid Build Coastguard Worker  * \author Brian Paul
29*61046927SAndroid Build Coastguard Worker  *
30*61046927SAndroid Build Coastguard Worker  */
31*61046927SAndroid Build Coastguard Worker 
32*61046927SAndroid Build Coastguard Worker 
33*61046927SAndroid Build Coastguard Worker #include "compiler/glsl/string_to_uint_map.h"
34*61046927SAndroid Build Coastguard Worker #include "util/glheader.h"
35*61046927SAndroid Build Coastguard Worker #include "main/context.h"
36*61046927SAndroid Build Coastguard Worker #include "main/glspirv.h"
37*61046927SAndroid Build Coastguard Worker #include "main/hash.h"
38*61046927SAndroid Build Coastguard Worker #include "main/mtypes.h"
39*61046927SAndroid Build Coastguard Worker #include "main/shaderapi.h"
40*61046927SAndroid Build Coastguard Worker #include "main/shaderobj.h"
41*61046927SAndroid Build Coastguard Worker #include "main/uniforms.h"
42*61046927SAndroid Build Coastguard Worker #include "program/program.h"
43*61046927SAndroid Build Coastguard Worker #include "program/prog_parameter.h"
44*61046927SAndroid Build Coastguard Worker #include "util/ralloc.h"
45*61046927SAndroid Build Coastguard Worker #include "util/u_atomic.h"
46*61046927SAndroid Build Coastguard Worker 
47*61046927SAndroid Build Coastguard Worker /**********************************************************************/
48*61046927SAndroid Build Coastguard Worker /*** Shader object functions                                        ***/
49*61046927SAndroid Build Coastguard Worker /**********************************************************************/
50*61046927SAndroid Build Coastguard Worker 
51*61046927SAndroid Build Coastguard Worker 
52*61046927SAndroid Build Coastguard Worker /**
53*61046927SAndroid Build Coastguard Worker  * Set ptr to point to sh.
54*61046927SAndroid Build Coastguard Worker  * If ptr is pointing to another shader, decrement its refcount (and delete
55*61046927SAndroid Build Coastguard Worker  * if refcount hits zero).
56*61046927SAndroid Build Coastguard Worker  * Then set ptr to point to sh, incrementing its refcount.
57*61046927SAndroid Build Coastguard Worker  */
58*61046927SAndroid Build Coastguard Worker static void
_reference_shader(struct gl_context * ctx,struct gl_shader ** ptr,struct gl_shader * sh,bool skip_locking)59*61046927SAndroid Build Coastguard Worker _reference_shader(struct gl_context *ctx, struct gl_shader **ptr,
60*61046927SAndroid Build Coastguard Worker                        struct gl_shader *sh, bool skip_locking)
61*61046927SAndroid Build Coastguard Worker {
62*61046927SAndroid Build Coastguard Worker    assert(ptr);
63*61046927SAndroid Build Coastguard Worker    if (*ptr == sh) {
64*61046927SAndroid Build Coastguard Worker       /* no-op */
65*61046927SAndroid Build Coastguard Worker       return;
66*61046927SAndroid Build Coastguard Worker    }
67*61046927SAndroid Build Coastguard Worker    if (*ptr) {
68*61046927SAndroid Build Coastguard Worker       /* Unreference the old shader */
69*61046927SAndroid Build Coastguard Worker       struct gl_shader *old = *ptr;
70*61046927SAndroid Build Coastguard Worker 
71*61046927SAndroid Build Coastguard Worker       assert(old->RefCount > 0);
72*61046927SAndroid Build Coastguard Worker 
73*61046927SAndroid Build Coastguard Worker       if (p_atomic_dec_zero(&old->RefCount)) {
74*61046927SAndroid Build Coastguard Worker          if (old->Name != 0) {
75*61046927SAndroid Build Coastguard Worker             if (skip_locking)
76*61046927SAndroid Build Coastguard Worker                _mesa_HashRemoveLocked(&ctx->Shared->ShaderObjects, old->Name);
77*61046927SAndroid Build Coastguard Worker             else
78*61046927SAndroid Build Coastguard Worker                _mesa_HashRemove(&ctx->Shared->ShaderObjects, old->Name);
79*61046927SAndroid Build Coastguard Worker          }
80*61046927SAndroid Build Coastguard Worker          _mesa_delete_shader(ctx, old);
81*61046927SAndroid Build Coastguard Worker       }
82*61046927SAndroid Build Coastguard Worker 
83*61046927SAndroid Build Coastguard Worker       *ptr = NULL;
84*61046927SAndroid Build Coastguard Worker    }
85*61046927SAndroid Build Coastguard Worker    assert(!*ptr);
86*61046927SAndroid Build Coastguard Worker 
87*61046927SAndroid Build Coastguard Worker    if (sh) {
88*61046927SAndroid Build Coastguard Worker       /* reference new */
89*61046927SAndroid Build Coastguard Worker       p_atomic_inc(&sh->RefCount);
90*61046927SAndroid Build Coastguard Worker       *ptr = sh;
91*61046927SAndroid Build Coastguard Worker    }
92*61046927SAndroid Build Coastguard Worker }
93*61046927SAndroid Build Coastguard Worker 
94*61046927SAndroid Build Coastguard Worker void
_mesa_reference_shader(struct gl_context * ctx,struct gl_shader ** ptr,struct gl_shader * sh)95*61046927SAndroid Build Coastguard Worker _mesa_reference_shader(struct gl_context *ctx, struct gl_shader **ptr,
96*61046927SAndroid Build Coastguard Worker                        struct gl_shader *sh)
97*61046927SAndroid Build Coastguard Worker {
98*61046927SAndroid Build Coastguard Worker    _reference_shader(ctx, ptr, sh, false);
99*61046927SAndroid Build Coastguard Worker }
100*61046927SAndroid Build Coastguard Worker 
101*61046927SAndroid Build Coastguard Worker static void
_mesa_init_shader(struct gl_shader * shader)102*61046927SAndroid Build Coastguard Worker _mesa_init_shader(struct gl_shader *shader)
103*61046927SAndroid Build Coastguard Worker {
104*61046927SAndroid Build Coastguard Worker    shader->RefCount = 1;
105*61046927SAndroid Build Coastguard Worker    shader->info.Geom.VerticesOut = -1;
106*61046927SAndroid Build Coastguard Worker    shader->info.Geom.InputType = MESA_PRIM_TRIANGLES;
107*61046927SAndroid Build Coastguard Worker    shader->info.Geom.OutputType = MESA_PRIM_TRIANGLE_STRIP;
108*61046927SAndroid Build Coastguard Worker }
109*61046927SAndroid Build Coastguard Worker 
110*61046927SAndroid Build Coastguard Worker /**
111*61046927SAndroid Build Coastguard Worker  * Allocate a new gl_shader object, initialize it.
112*61046927SAndroid Build Coastguard Worker  */
113*61046927SAndroid Build Coastguard Worker struct gl_shader *
_mesa_new_shader(GLuint name,gl_shader_stage stage)114*61046927SAndroid Build Coastguard Worker _mesa_new_shader(GLuint name, gl_shader_stage stage)
115*61046927SAndroid Build Coastguard Worker {
116*61046927SAndroid Build Coastguard Worker    struct gl_shader *shader;
117*61046927SAndroid Build Coastguard Worker    shader = rzalloc(NULL, struct gl_shader);
118*61046927SAndroid Build Coastguard Worker    if (shader) {
119*61046927SAndroid Build Coastguard Worker       shader->Stage = stage;
120*61046927SAndroid Build Coastguard Worker       shader->Name = name;
121*61046927SAndroid Build Coastguard Worker       _mesa_init_shader(shader);
122*61046927SAndroid Build Coastguard Worker    }
123*61046927SAndroid Build Coastguard Worker    return shader;
124*61046927SAndroid Build Coastguard Worker }
125*61046927SAndroid Build Coastguard Worker 
126*61046927SAndroid Build Coastguard Worker 
127*61046927SAndroid Build Coastguard Worker /**
128*61046927SAndroid Build Coastguard Worker  * Delete a shader object.
129*61046927SAndroid Build Coastguard Worker  */
130*61046927SAndroid Build Coastguard Worker void
_mesa_delete_shader(struct gl_context * ctx,struct gl_shader * sh)131*61046927SAndroid Build Coastguard Worker _mesa_delete_shader(struct gl_context *ctx, struct gl_shader *sh)
132*61046927SAndroid Build Coastguard Worker {
133*61046927SAndroid Build Coastguard Worker    _mesa_shader_spirv_data_reference(&sh->spirv_data, NULL);
134*61046927SAndroid Build Coastguard Worker    free((void *)sh->Source);
135*61046927SAndroid Build Coastguard Worker    free((void *)sh->FallbackSource);
136*61046927SAndroid Build Coastguard Worker    free(sh->Label);
137*61046927SAndroid Build Coastguard Worker    ralloc_free(sh);
138*61046927SAndroid Build Coastguard Worker }
139*61046927SAndroid Build Coastguard Worker 
140*61046927SAndroid Build Coastguard Worker 
141*61046927SAndroid Build Coastguard Worker /**
142*61046927SAndroid Build Coastguard Worker  * Delete a shader object.
143*61046927SAndroid Build Coastguard Worker  */
144*61046927SAndroid Build Coastguard Worker void
_mesa_delete_linked_shader(struct gl_context * ctx,struct gl_linked_shader * sh)145*61046927SAndroid Build Coastguard Worker _mesa_delete_linked_shader(struct gl_context *ctx,
146*61046927SAndroid Build Coastguard Worker                            struct gl_linked_shader *sh)
147*61046927SAndroid Build Coastguard Worker {
148*61046927SAndroid Build Coastguard Worker    _mesa_shader_spirv_data_reference(&sh->spirv_data, NULL);
149*61046927SAndroid Build Coastguard Worker    _mesa_reference_program(ctx, &sh->Program, NULL);
150*61046927SAndroid Build Coastguard Worker    ralloc_free(sh);
151*61046927SAndroid Build Coastguard Worker }
152*61046927SAndroid Build Coastguard Worker 
153*61046927SAndroid Build Coastguard Worker 
154*61046927SAndroid Build Coastguard Worker /**
155*61046927SAndroid Build Coastguard Worker  * Lookup a GLSL shader object.
156*61046927SAndroid Build Coastguard Worker  */
157*61046927SAndroid Build Coastguard Worker struct gl_shader *
_mesa_lookup_shader(struct gl_context * ctx,GLuint name)158*61046927SAndroid Build Coastguard Worker _mesa_lookup_shader(struct gl_context *ctx, GLuint name)
159*61046927SAndroid Build Coastguard Worker {
160*61046927SAndroid Build Coastguard Worker    if (name) {
161*61046927SAndroid Build Coastguard Worker       struct gl_shader *sh = (struct gl_shader *)
162*61046927SAndroid Build Coastguard Worker          _mesa_HashLookup(&ctx->Shared->ShaderObjects, name);
163*61046927SAndroid Build Coastguard Worker       /* Note that both gl_shader and gl_shader_program objects are kept
164*61046927SAndroid Build Coastguard Worker        * in the same hash table.  Check the object's type to be sure it's
165*61046927SAndroid Build Coastguard Worker        * what we're expecting.
166*61046927SAndroid Build Coastguard Worker        */
167*61046927SAndroid Build Coastguard Worker       if (sh && sh->Type == GL_SHADER_PROGRAM_MESA) {
168*61046927SAndroid Build Coastguard Worker          return NULL;
169*61046927SAndroid Build Coastguard Worker       }
170*61046927SAndroid Build Coastguard Worker       return sh;
171*61046927SAndroid Build Coastguard Worker    }
172*61046927SAndroid Build Coastguard Worker    return NULL;
173*61046927SAndroid Build Coastguard Worker }
174*61046927SAndroid Build Coastguard Worker 
175*61046927SAndroid Build Coastguard Worker 
176*61046927SAndroid Build Coastguard Worker /**
177*61046927SAndroid Build Coastguard Worker  * As above, but record an error if shader is not found.
178*61046927SAndroid Build Coastguard Worker  */
179*61046927SAndroid Build Coastguard Worker struct gl_shader *
_mesa_lookup_shader_err(struct gl_context * ctx,GLuint name,const char * caller)180*61046927SAndroid Build Coastguard Worker _mesa_lookup_shader_err(struct gl_context *ctx, GLuint name, const char *caller)
181*61046927SAndroid Build Coastguard Worker {
182*61046927SAndroid Build Coastguard Worker    if (!name) {
183*61046927SAndroid Build Coastguard Worker       _mesa_error(ctx, GL_INVALID_VALUE, "%s", caller);
184*61046927SAndroid Build Coastguard Worker       return NULL;
185*61046927SAndroid Build Coastguard Worker    }
186*61046927SAndroid Build Coastguard Worker    else {
187*61046927SAndroid Build Coastguard Worker       struct gl_shader *sh = (struct gl_shader *)
188*61046927SAndroid Build Coastguard Worker          _mesa_HashLookup(&ctx->Shared->ShaderObjects, name);
189*61046927SAndroid Build Coastguard Worker       if (!sh) {
190*61046927SAndroid Build Coastguard Worker          _mesa_error(ctx, GL_INVALID_VALUE, "%s", caller);
191*61046927SAndroid Build Coastguard Worker          return NULL;
192*61046927SAndroid Build Coastguard Worker       }
193*61046927SAndroid Build Coastguard Worker       if (sh->Type == GL_SHADER_PROGRAM_MESA) {
194*61046927SAndroid Build Coastguard Worker          _mesa_error(ctx, GL_INVALID_OPERATION, "%s", caller);
195*61046927SAndroid Build Coastguard Worker          return NULL;
196*61046927SAndroid Build Coastguard Worker       }
197*61046927SAndroid Build Coastguard Worker       return sh;
198*61046927SAndroid Build Coastguard Worker    }
199*61046927SAndroid Build Coastguard Worker }
200*61046927SAndroid Build Coastguard Worker 
201*61046927SAndroid Build Coastguard Worker 
202*61046927SAndroid Build Coastguard Worker 
203*61046927SAndroid Build Coastguard Worker /**********************************************************************/
204*61046927SAndroid Build Coastguard Worker /*** Shader Program object functions                                ***/
205*61046927SAndroid Build Coastguard Worker /**********************************************************************/
206*61046927SAndroid Build Coastguard Worker 
207*61046927SAndroid Build Coastguard Worker void
_mesa_reference_shader_program_data(struct gl_shader_program_data ** ptr,struct gl_shader_program_data * data)208*61046927SAndroid Build Coastguard Worker _mesa_reference_shader_program_data(struct gl_shader_program_data **ptr,
209*61046927SAndroid Build Coastguard Worker                                     struct gl_shader_program_data *data)
210*61046927SAndroid Build Coastguard Worker {
211*61046927SAndroid Build Coastguard Worker    if (*ptr == data)
212*61046927SAndroid Build Coastguard Worker       return;
213*61046927SAndroid Build Coastguard Worker 
214*61046927SAndroid Build Coastguard Worker    if (*ptr) {
215*61046927SAndroid Build Coastguard Worker       struct gl_shader_program_data *oldData = *ptr;
216*61046927SAndroid Build Coastguard Worker 
217*61046927SAndroid Build Coastguard Worker       assert(oldData->RefCount > 0);
218*61046927SAndroid Build Coastguard Worker 
219*61046927SAndroid Build Coastguard Worker       if (p_atomic_dec_zero(&oldData->RefCount)) {
220*61046927SAndroid Build Coastguard Worker          assert(oldData->NumUniformStorage == 0 ||
221*61046927SAndroid Build Coastguard Worker                 oldData->UniformStorage);
222*61046927SAndroid Build Coastguard Worker 
223*61046927SAndroid Build Coastguard Worker          for (unsigned i = 0; i < oldData->NumUniformStorage; ++i)
224*61046927SAndroid Build Coastguard Worker             _mesa_uniform_detach_all_driver_storage(&oldData->UniformStorage[i]);
225*61046927SAndroid Build Coastguard Worker 
226*61046927SAndroid Build Coastguard Worker          ralloc_free(oldData);
227*61046927SAndroid Build Coastguard Worker       }
228*61046927SAndroid Build Coastguard Worker 
229*61046927SAndroid Build Coastguard Worker       *ptr = NULL;
230*61046927SAndroid Build Coastguard Worker    }
231*61046927SAndroid Build Coastguard Worker 
232*61046927SAndroid Build Coastguard Worker    if (data)
233*61046927SAndroid Build Coastguard Worker       p_atomic_inc(&data->RefCount);
234*61046927SAndroid Build Coastguard Worker 
235*61046927SAndroid Build Coastguard Worker    *ptr = data;
236*61046927SAndroid Build Coastguard Worker }
237*61046927SAndroid Build Coastguard Worker 
238*61046927SAndroid Build Coastguard Worker /**
239*61046927SAndroid Build Coastguard Worker  * Set ptr to point to shProg.
240*61046927SAndroid Build Coastguard Worker  * If ptr is pointing to another object, decrement its refcount (and delete
241*61046927SAndroid Build Coastguard Worker  * if refcount hits zero).
242*61046927SAndroid Build Coastguard Worker  * Then set ptr to point to shProg, incrementing its refcount.
243*61046927SAndroid Build Coastguard Worker  */
244*61046927SAndroid Build Coastguard Worker void
_mesa_reference_shader_program_(struct gl_context * ctx,struct gl_shader_program ** ptr,struct gl_shader_program * shProg)245*61046927SAndroid Build Coastguard Worker _mesa_reference_shader_program_(struct gl_context *ctx,
246*61046927SAndroid Build Coastguard Worker                                 struct gl_shader_program **ptr,
247*61046927SAndroid Build Coastguard Worker                                 struct gl_shader_program *shProg)
248*61046927SAndroid Build Coastguard Worker {
249*61046927SAndroid Build Coastguard Worker    assert(ptr);
250*61046927SAndroid Build Coastguard Worker    if (*ptr == shProg) {
251*61046927SAndroid Build Coastguard Worker       /* no-op */
252*61046927SAndroid Build Coastguard Worker       return;
253*61046927SAndroid Build Coastguard Worker    }
254*61046927SAndroid Build Coastguard Worker    if (*ptr) {
255*61046927SAndroid Build Coastguard Worker       /* Unreference the old shader program */
256*61046927SAndroid Build Coastguard Worker       struct gl_shader_program *old = *ptr;
257*61046927SAndroid Build Coastguard Worker 
258*61046927SAndroid Build Coastguard Worker       assert(old->RefCount > 0);
259*61046927SAndroid Build Coastguard Worker 
260*61046927SAndroid Build Coastguard Worker       if (p_atomic_dec_zero(&old->RefCount)) {
261*61046927SAndroid Build Coastguard Worker          _mesa_HashLockMutex(&ctx->Shared->ShaderObjects);
262*61046927SAndroid Build Coastguard Worker          if (old->Name != 0)
263*61046927SAndroid Build Coastguard Worker 	         _mesa_HashRemoveLocked(&ctx->Shared->ShaderObjects, old->Name);
264*61046927SAndroid Build Coastguard Worker          _mesa_delete_shader_program(ctx, old);
265*61046927SAndroid Build Coastguard Worker          _mesa_HashUnlockMutex(&ctx->Shared->ShaderObjects);
266*61046927SAndroid Build Coastguard Worker       }
267*61046927SAndroid Build Coastguard Worker 
268*61046927SAndroid Build Coastguard Worker       *ptr = NULL;
269*61046927SAndroid Build Coastguard Worker    }
270*61046927SAndroid Build Coastguard Worker    assert(!*ptr);
271*61046927SAndroid Build Coastguard Worker 
272*61046927SAndroid Build Coastguard Worker    if (shProg) {
273*61046927SAndroid Build Coastguard Worker       p_atomic_inc(&shProg->RefCount);
274*61046927SAndroid Build Coastguard Worker       *ptr = shProg;
275*61046927SAndroid Build Coastguard Worker    }
276*61046927SAndroid Build Coastguard Worker }
277*61046927SAndroid Build Coastguard Worker 
278*61046927SAndroid Build Coastguard Worker struct gl_shader_program_data *
_mesa_create_shader_program_data()279*61046927SAndroid Build Coastguard Worker _mesa_create_shader_program_data()
280*61046927SAndroid Build Coastguard Worker {
281*61046927SAndroid Build Coastguard Worker    struct gl_shader_program_data *data;
282*61046927SAndroid Build Coastguard Worker    data = rzalloc(NULL, struct gl_shader_program_data);
283*61046927SAndroid Build Coastguard Worker    if (data) {
284*61046927SAndroid Build Coastguard Worker       data->RefCount = 1;
285*61046927SAndroid Build Coastguard Worker       data->InfoLog = ralloc_strdup(data, "");
286*61046927SAndroid Build Coastguard Worker    }
287*61046927SAndroid Build Coastguard Worker 
288*61046927SAndroid Build Coastguard Worker    return data;
289*61046927SAndroid Build Coastguard Worker }
290*61046927SAndroid Build Coastguard Worker 
291*61046927SAndroid Build Coastguard Worker static void
init_shader_program(struct gl_shader_program * prog)292*61046927SAndroid Build Coastguard Worker init_shader_program(struct gl_shader_program *prog)
293*61046927SAndroid Build Coastguard Worker {
294*61046927SAndroid Build Coastguard Worker    prog->Type = GL_SHADER_PROGRAM_MESA;
295*61046927SAndroid Build Coastguard Worker    prog->RefCount = 1;
296*61046927SAndroid Build Coastguard Worker 
297*61046927SAndroid Build Coastguard Worker    prog->AttributeBindings = string_to_uint_map_ctor();
298*61046927SAndroid Build Coastguard Worker    prog->FragDataBindings = string_to_uint_map_ctor();
299*61046927SAndroid Build Coastguard Worker    prog->FragDataIndexBindings = string_to_uint_map_ctor();
300*61046927SAndroid Build Coastguard Worker 
301*61046927SAndroid Build Coastguard Worker    prog->TransformFeedback.BufferMode = GL_INTERLEAVED_ATTRIBS;
302*61046927SAndroid Build Coastguard Worker 
303*61046927SAndroid Build Coastguard Worker    exec_list_make_empty(&prog->EmptyUniformLocations);
304*61046927SAndroid Build Coastguard Worker }
305*61046927SAndroid Build Coastguard Worker 
306*61046927SAndroid Build Coastguard Worker /**
307*61046927SAndroid Build Coastguard Worker  * Allocate a new gl_shader_program object, initialize it.
308*61046927SAndroid Build Coastguard Worker  */
309*61046927SAndroid Build Coastguard Worker struct gl_shader_program *
_mesa_new_shader_program(GLuint name)310*61046927SAndroid Build Coastguard Worker _mesa_new_shader_program(GLuint name)
311*61046927SAndroid Build Coastguard Worker {
312*61046927SAndroid Build Coastguard Worker    struct gl_shader_program *shProg;
313*61046927SAndroid Build Coastguard Worker    shProg = rzalloc(NULL, struct gl_shader_program);
314*61046927SAndroid Build Coastguard Worker    if (shProg) {
315*61046927SAndroid Build Coastguard Worker       shProg->Name = name;
316*61046927SAndroid Build Coastguard Worker       shProg->data = _mesa_create_shader_program_data();
317*61046927SAndroid Build Coastguard Worker       if (!shProg->data) {
318*61046927SAndroid Build Coastguard Worker          ralloc_free(shProg);
319*61046927SAndroid Build Coastguard Worker          return NULL;
320*61046927SAndroid Build Coastguard Worker       }
321*61046927SAndroid Build Coastguard Worker       init_shader_program(shProg);
322*61046927SAndroid Build Coastguard Worker    }
323*61046927SAndroid Build Coastguard Worker    return shProg;
324*61046927SAndroid Build Coastguard Worker }
325*61046927SAndroid Build Coastguard Worker 
326*61046927SAndroid Build Coastguard Worker 
327*61046927SAndroid Build Coastguard Worker /**
328*61046927SAndroid Build Coastguard Worker  * Clear (free) the shader program state that gets produced by linking.
329*61046927SAndroid Build Coastguard Worker  */
330*61046927SAndroid Build Coastguard Worker void
_mesa_clear_shader_program_data(struct gl_context * ctx,struct gl_shader_program * shProg)331*61046927SAndroid Build Coastguard Worker _mesa_clear_shader_program_data(struct gl_context *ctx,
332*61046927SAndroid Build Coastguard Worker                                 struct gl_shader_program *shProg)
333*61046927SAndroid Build Coastguard Worker {
334*61046927SAndroid Build Coastguard Worker    for (gl_shader_stage sh = 0; sh < MESA_SHADER_STAGES; sh++) {
335*61046927SAndroid Build Coastguard Worker       if (shProg->_LinkedShaders[sh] != NULL) {
336*61046927SAndroid Build Coastguard Worker          _mesa_delete_linked_shader(ctx, shProg->_LinkedShaders[sh]);
337*61046927SAndroid Build Coastguard Worker          shProg->_LinkedShaders[sh] = NULL;
338*61046927SAndroid Build Coastguard Worker       }
339*61046927SAndroid Build Coastguard Worker    }
340*61046927SAndroid Build Coastguard Worker 
341*61046927SAndroid Build Coastguard Worker    if (shProg->UniformRemapTable) {
342*61046927SAndroid Build Coastguard Worker       ralloc_free(shProg->UniformRemapTable);
343*61046927SAndroid Build Coastguard Worker       shProg->NumUniformRemapTable = 0;
344*61046927SAndroid Build Coastguard Worker       shProg->UniformRemapTable = NULL;
345*61046927SAndroid Build Coastguard Worker    }
346*61046927SAndroid Build Coastguard Worker 
347*61046927SAndroid Build Coastguard Worker    if (shProg->data)
348*61046927SAndroid Build Coastguard Worker       _mesa_program_resource_hash_destroy(shProg);
349*61046927SAndroid Build Coastguard Worker 
350*61046927SAndroid Build Coastguard Worker    _mesa_reference_shader_program_data(&shProg->data, NULL);
351*61046927SAndroid Build Coastguard Worker }
352*61046927SAndroid Build Coastguard Worker 
353*61046927SAndroid Build Coastguard Worker 
354*61046927SAndroid Build Coastguard Worker /**
355*61046927SAndroid Build Coastguard Worker  * Free all the data that hangs off a shader program object, but not the
356*61046927SAndroid Build Coastguard Worker  * object itself.
357*61046927SAndroid Build Coastguard Worker  * Must be called with shared->ShaderObjects locked.
358*61046927SAndroid Build Coastguard Worker  */
359*61046927SAndroid Build Coastguard Worker void
_mesa_free_shader_program_data(struct gl_context * ctx,struct gl_shader_program * shProg)360*61046927SAndroid Build Coastguard Worker _mesa_free_shader_program_data(struct gl_context *ctx,
361*61046927SAndroid Build Coastguard Worker                                struct gl_shader_program *shProg)
362*61046927SAndroid Build Coastguard Worker {
363*61046927SAndroid Build Coastguard Worker    GLuint i;
364*61046927SAndroid Build Coastguard Worker 
365*61046927SAndroid Build Coastguard Worker    assert(shProg->Type == GL_SHADER_PROGRAM_MESA);
366*61046927SAndroid Build Coastguard Worker 
367*61046927SAndroid Build Coastguard Worker    _mesa_clear_shader_program_data(ctx, shProg);
368*61046927SAndroid Build Coastguard Worker 
369*61046927SAndroid Build Coastguard Worker    if (shProg->AttributeBindings) {
370*61046927SAndroid Build Coastguard Worker       string_to_uint_map_dtor(shProg->AttributeBindings);
371*61046927SAndroid Build Coastguard Worker       shProg->AttributeBindings = NULL;
372*61046927SAndroid Build Coastguard Worker    }
373*61046927SAndroid Build Coastguard Worker 
374*61046927SAndroid Build Coastguard Worker    if (shProg->FragDataBindings) {
375*61046927SAndroid Build Coastguard Worker       string_to_uint_map_dtor(shProg->FragDataBindings);
376*61046927SAndroid Build Coastguard Worker       shProg->FragDataBindings = NULL;
377*61046927SAndroid Build Coastguard Worker    }
378*61046927SAndroid Build Coastguard Worker 
379*61046927SAndroid Build Coastguard Worker    if (shProg->FragDataIndexBindings) {
380*61046927SAndroid Build Coastguard Worker       string_to_uint_map_dtor(shProg->FragDataIndexBindings);
381*61046927SAndroid Build Coastguard Worker       shProg->FragDataIndexBindings = NULL;
382*61046927SAndroid Build Coastguard Worker    }
383*61046927SAndroid Build Coastguard Worker 
384*61046927SAndroid Build Coastguard Worker    /* detach shaders */
385*61046927SAndroid Build Coastguard Worker    for (i = 0; i < shProg->NumShaders; i++) {
386*61046927SAndroid Build Coastguard Worker       _reference_shader(ctx, &shProg->Shaders[i], NULL, true);
387*61046927SAndroid Build Coastguard Worker    }
388*61046927SAndroid Build Coastguard Worker    shProg->NumShaders = 0;
389*61046927SAndroid Build Coastguard Worker 
390*61046927SAndroid Build Coastguard Worker    free(shProg->Shaders);
391*61046927SAndroid Build Coastguard Worker    shProg->Shaders = NULL;
392*61046927SAndroid Build Coastguard Worker 
393*61046927SAndroid Build Coastguard Worker    /* Transform feedback varying vars */
394*61046927SAndroid Build Coastguard Worker    for (i = 0; i < shProg->TransformFeedback.NumVarying; i++) {
395*61046927SAndroid Build Coastguard Worker       free(shProg->TransformFeedback.VaryingNames[i]);
396*61046927SAndroid Build Coastguard Worker    }
397*61046927SAndroid Build Coastguard Worker    free(shProg->TransformFeedback.VaryingNames);
398*61046927SAndroid Build Coastguard Worker    shProg->TransformFeedback.VaryingNames = NULL;
399*61046927SAndroid Build Coastguard Worker    shProg->TransformFeedback.NumVarying = 0;
400*61046927SAndroid Build Coastguard Worker 
401*61046927SAndroid Build Coastguard Worker    free(shProg->Label);
402*61046927SAndroid Build Coastguard Worker    shProg->Label = NULL;
403*61046927SAndroid Build Coastguard Worker }
404*61046927SAndroid Build Coastguard Worker 
405*61046927SAndroid Build Coastguard Worker 
406*61046927SAndroid Build Coastguard Worker /**
407*61046927SAndroid Build Coastguard Worker  * Free/delete a shader program object.
408*61046927SAndroid Build Coastguard Worker  */
409*61046927SAndroid Build Coastguard Worker void
_mesa_delete_shader_program(struct gl_context * ctx,struct gl_shader_program * shProg)410*61046927SAndroid Build Coastguard Worker _mesa_delete_shader_program(struct gl_context *ctx,
411*61046927SAndroid Build Coastguard Worker                             struct gl_shader_program *shProg)
412*61046927SAndroid Build Coastguard Worker {
413*61046927SAndroid Build Coastguard Worker    _mesa_free_shader_program_data(ctx, shProg);
414*61046927SAndroid Build Coastguard Worker    ralloc_free(shProg);
415*61046927SAndroid Build Coastguard Worker }
416*61046927SAndroid Build Coastguard Worker 
417*61046927SAndroid Build Coastguard Worker 
418*61046927SAndroid Build Coastguard Worker /**
419*61046927SAndroid Build Coastguard Worker  * Lookup a GLSL program object.
420*61046927SAndroid Build Coastguard Worker  */
421*61046927SAndroid Build Coastguard Worker struct gl_shader_program *
_mesa_lookup_shader_program(struct gl_context * ctx,GLuint name)422*61046927SAndroid Build Coastguard Worker _mesa_lookup_shader_program(struct gl_context *ctx, GLuint name)
423*61046927SAndroid Build Coastguard Worker {
424*61046927SAndroid Build Coastguard Worker    struct gl_shader_program *shProg;
425*61046927SAndroid Build Coastguard Worker    if (name) {
426*61046927SAndroid Build Coastguard Worker       shProg = (struct gl_shader_program *)
427*61046927SAndroid Build Coastguard Worker          _mesa_HashLookup(&ctx->Shared->ShaderObjects, name);
428*61046927SAndroid Build Coastguard Worker       /* Note that both gl_shader and gl_shader_program objects are kept
429*61046927SAndroid Build Coastguard Worker        * in the same hash table.  Check the object's type to be sure it's
430*61046927SAndroid Build Coastguard Worker        * what we're expecting.
431*61046927SAndroid Build Coastguard Worker        */
432*61046927SAndroid Build Coastguard Worker       if (shProg && shProg->Type != GL_SHADER_PROGRAM_MESA) {
433*61046927SAndroid Build Coastguard Worker          return NULL;
434*61046927SAndroid Build Coastguard Worker       }
435*61046927SAndroid Build Coastguard Worker       return shProg;
436*61046927SAndroid Build Coastguard Worker    }
437*61046927SAndroid Build Coastguard Worker    return NULL;
438*61046927SAndroid Build Coastguard Worker }
439*61046927SAndroid Build Coastguard Worker 
440*61046927SAndroid Build Coastguard Worker 
441*61046927SAndroid Build Coastguard Worker /**
442*61046927SAndroid Build Coastguard Worker  * As above, but record an error if program is not found.
443*61046927SAndroid Build Coastguard Worker  */
444*61046927SAndroid Build Coastguard Worker struct gl_shader_program *
_mesa_lookup_shader_program_err_glthread(struct gl_context * ctx,GLuint name,bool glthread,const char * caller)445*61046927SAndroid Build Coastguard Worker _mesa_lookup_shader_program_err_glthread(struct gl_context *ctx, GLuint name,
446*61046927SAndroid Build Coastguard Worker                                          bool glthread, const char *caller)
447*61046927SAndroid Build Coastguard Worker {
448*61046927SAndroid Build Coastguard Worker    if (!name) {
449*61046927SAndroid Build Coastguard Worker       _mesa_error_glthread_safe(ctx, GL_INVALID_VALUE, glthread, "%s", caller);
450*61046927SAndroid Build Coastguard Worker       return NULL;
451*61046927SAndroid Build Coastguard Worker    }
452*61046927SAndroid Build Coastguard Worker    else {
453*61046927SAndroid Build Coastguard Worker       struct gl_shader_program *shProg = (struct gl_shader_program *)
454*61046927SAndroid Build Coastguard Worker          _mesa_HashLookup(&ctx->Shared->ShaderObjects, name);
455*61046927SAndroid Build Coastguard Worker       if (!shProg) {
456*61046927SAndroid Build Coastguard Worker          _mesa_error_glthread_safe(ctx, GL_INVALID_VALUE, glthread,
457*61046927SAndroid Build Coastguard Worker                                    "%s", caller);
458*61046927SAndroid Build Coastguard Worker          return NULL;
459*61046927SAndroid Build Coastguard Worker       }
460*61046927SAndroid Build Coastguard Worker       if (shProg->Type != GL_SHADER_PROGRAM_MESA) {
461*61046927SAndroid Build Coastguard Worker          _mesa_error_glthread_safe(ctx, GL_INVALID_OPERATION, glthread,
462*61046927SAndroid Build Coastguard Worker                                    "%s", caller);
463*61046927SAndroid Build Coastguard Worker          return NULL;
464*61046927SAndroid Build Coastguard Worker       }
465*61046927SAndroid Build Coastguard Worker       return shProg;
466*61046927SAndroid Build Coastguard Worker    }
467*61046927SAndroid Build Coastguard Worker }
468*61046927SAndroid Build Coastguard Worker 
469*61046927SAndroid Build Coastguard Worker 
470*61046927SAndroid Build Coastguard Worker struct gl_shader_program *
_mesa_lookup_shader_program_err(struct gl_context * ctx,GLuint name,const char * caller)471*61046927SAndroid Build Coastguard Worker _mesa_lookup_shader_program_err(struct gl_context *ctx, GLuint name,
472*61046927SAndroid Build Coastguard Worker                                 const char *caller)
473*61046927SAndroid Build Coastguard Worker {
474*61046927SAndroid Build Coastguard Worker    return _mesa_lookup_shader_program_err_glthread(ctx, name, false, caller);
475*61046927SAndroid Build Coastguard Worker }
476