2 * Mesa 3-D graphics library
4 * Copyright (C) 2004-2008 Brian Paul All Rights Reserved.
5 * Copyright (C) 2009-2010 VMware, Inc. All Rights Reserved.
7 * Permission is hereby granted, free of charge, to any person obtaining a
8 * copy of this software and associated documentation files (the "Software"),
9 * to deal in the Software without restriction, including without limitation
10 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11 * and/or sell copies of the Software, and to permit persons to whom the
12 * Software is furnished to do so, subject to the following conditions:
14 * The above copyright notice and this permission notice shall be included
15 * in all copies or substantial portions of the Software.
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
21 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
32 #include "main/glheader.h"
33 #include "main/context.h"
34 #include "main/dispatch.h"
35 #include "main/hash.h"
36 #include "main/shaderobj.h"
37 #include "shader/program.h"
38 #include "shader/prog_parameter.h"
39 #include "shader/prog_uniform.h"
42 /**********************************************************************/
43 /*** Shader object functions ***/
44 /**********************************************************************/
48 * Set ptr to point to sh.
49 * If ptr is pointing to another shader, decrement its refcount (and delete
50 * if refcount hits zero).
51 * Then set ptr to point to sh, incrementing its refcount.
54 _mesa_reference_shader(GLcontext
*ctx
, struct gl_shader
**ptr
,
63 /* Unreference the old shader */
64 GLboolean deleteFlag
= GL_FALSE
;
65 struct gl_shader
*old
= *ptr
;
67 ASSERT(old
->RefCount
> 0);
69 /*printf("SHADER DECR %p (%d) to %d\n",
70 (void*) old, old->Name, old->RefCount);*/
71 deleteFlag
= (old
->RefCount
== 0);
74 _mesa_HashRemove(ctx
->Shared
->ShaderObjects
, old
->Name
);
75 ctx
->Driver
.DeleteShader(ctx
, old
);
85 /*printf("SHADER INCR %p (%d) to %d\n",
86 (void*) sh, sh->Name, sh->RefCount);*/
93 * Allocate a new gl_shader object, initialize it.
94 * Called via ctx->Driver.NewShader()
96 static struct gl_shader
*
97 _mesa_new_shader(GLcontext
*ctx
, GLuint name
, GLenum type
)
99 struct gl_shader
*shader
;
100 assert(type
== GL_FRAGMENT_SHADER
|| type
== GL_VERTEX_SHADER
);
101 shader
= CALLOC_STRUCT(gl_shader
);
105 shader
->RefCount
= 1;
112 * Delete a shader object.
113 * Called via ctx->Driver.DeleteShader().
116 __mesa_delete_shader(GLcontext
*ctx
, struct gl_shader
*sh
)
119 free((void *) sh
->Source
);
122 _mesa_reference_program(ctx
, &sh
->Program
, NULL
);
128 * Lookup a GLSL shader object.
131 _mesa_lookup_shader(GLcontext
*ctx
, GLuint name
)
134 struct gl_shader
*sh
= (struct gl_shader
*)
135 _mesa_HashLookup(ctx
->Shared
->ShaderObjects
, name
);
136 /* Note that both gl_shader and gl_shader_program objects are kept
137 * in the same hash table. Check the object's type to be sure it's
138 * what we're expecting.
140 if (sh
&& sh
->Type
== GL_SHADER_PROGRAM_MESA
) {
150 * As above, but record an error if shader is not found.
153 _mesa_lookup_shader_err(GLcontext
*ctx
, GLuint name
, const char *caller
)
156 _mesa_error(ctx
, GL_INVALID_VALUE
, caller
);
160 struct gl_shader
*sh
= (struct gl_shader
*)
161 _mesa_HashLookup(ctx
->Shared
->ShaderObjects
, name
);
163 _mesa_error(ctx
, GL_INVALID_VALUE
, caller
);
166 if (sh
->Type
== GL_SHADER_PROGRAM_MESA
) {
167 _mesa_error(ctx
, GL_INVALID_OPERATION
, caller
);
176 /**********************************************************************/
177 /*** Shader Program object functions ***/
178 /**********************************************************************/
182 * Set ptr to point to shProg.
183 * If ptr is pointing to another object, decrement its refcount (and delete
184 * if refcount hits zero).
185 * Then set ptr to point to shProg, incrementing its refcount.
188 _mesa_reference_shader_program(GLcontext
*ctx
,
189 struct gl_shader_program
**ptr
,
190 struct gl_shader_program
*shProg
)
193 if (*ptr
== shProg
) {
198 /* Unreference the old shader program */
199 GLboolean deleteFlag
= GL_FALSE
;
200 struct gl_shader_program
*old
= *ptr
;
202 ASSERT(old
->RefCount
> 0);
205 printf("ShaderProgram %p ID=%u RefCount-- to %d\n",
206 (void *) old
, old
->Name
, old
->RefCount
);
208 deleteFlag
= (old
->RefCount
== 0);
211 _mesa_HashRemove(ctx
->Shared
->ShaderObjects
, old
->Name
);
212 ctx
->Driver
.DeleteShaderProgram(ctx
, old
);
222 printf("ShaderProgram %p ID=%u RefCount++ to %d\n",
223 (void *) shProg
, shProg
->Name
, shProg
->RefCount
);
231 * Allocate a new gl_shader_program object, initialize it.
232 * Called via ctx->Driver.NewShaderProgram()
234 static struct gl_shader_program
*
235 _mesa_new_shader_program(GLcontext
*ctx
, GLuint name
)
237 struct gl_shader_program
*shProg
;
238 shProg
= CALLOC_STRUCT(gl_shader_program
);
240 shProg
->Type
= GL_SHADER_PROGRAM_MESA
;
242 shProg
->RefCount
= 1;
243 shProg
->Attributes
= _mesa_new_parameter_list();
250 * Clear (free) the shader program state that gets produced by linking.
253 _mesa_clear_shader_program_data(GLcontext
*ctx
,
254 struct gl_shader_program
*shProg
)
256 _mesa_reference_vertprog(ctx
, &shProg
->VertexProgram
, NULL
);
257 _mesa_reference_fragprog(ctx
, &shProg
->FragmentProgram
, NULL
);
259 if (shProg
->Uniforms
) {
260 _mesa_free_uniform_list(shProg
->Uniforms
);
261 shProg
->Uniforms
= NULL
;
264 if (shProg
->Varying
) {
265 _mesa_free_parameter_list(shProg
->Varying
);
266 shProg
->Varying
= NULL
;
272 * Free all the data that hangs off a shader program object, but not the
276 _mesa_free_shader_program_data(GLcontext
*ctx
,
277 struct gl_shader_program
*shProg
)
281 assert(shProg
->Type
== GL_SHADER_PROGRAM_MESA
);
283 _mesa_clear_shader_program_data(ctx
, shProg
);
285 if (shProg
->Attributes
) {
286 _mesa_free_parameter_list(shProg
->Attributes
);
287 shProg
->Attributes
= NULL
;
291 for (i
= 0; i
< shProg
->NumShaders
; i
++) {
292 _mesa_reference_shader(ctx
, &shProg
->Shaders
[i
], NULL
);
294 shProg
->NumShaders
= 0;
296 if (shProg
->Shaders
) {
297 free(shProg
->Shaders
);
298 shProg
->Shaders
= NULL
;
301 if (shProg
->InfoLog
) {
302 free(shProg
->InfoLog
);
303 shProg
->InfoLog
= NULL
;
306 /* Transform feedback varying vars */
307 for (i
= 0; i
< shProg
->TransformFeedback
.NumVarying
; i
++) {
308 free(shProg
->TransformFeedback
.VaryingNames
[i
]);
310 free(shProg
->TransformFeedback
.VaryingNames
);
311 shProg
->TransformFeedback
.VaryingNames
= NULL
;
312 shProg
->TransformFeedback
.NumVarying
= 0;
317 * Free/delete a shader program object.
318 * Called via ctx->Driver.DeleteShaderProgram().
321 __mesa_delete_shader_program(GLcontext
*ctx
, struct gl_shader_program
*shProg
)
323 _mesa_free_shader_program_data(ctx
, shProg
);
330 * Lookup a GLSL program object.
332 struct gl_shader_program
*
333 _mesa_lookup_shader_program(GLcontext
*ctx
, GLuint name
)
335 struct gl_shader_program
*shProg
;
337 shProg
= (struct gl_shader_program
*)
338 _mesa_HashLookup(ctx
->Shared
->ShaderObjects
, name
);
339 /* Note that both gl_shader and gl_shader_program objects are kept
340 * in the same hash table. Check the object's type to be sure it's
341 * what we're expecting.
343 if (shProg
&& shProg
->Type
!= GL_SHADER_PROGRAM_MESA
) {
353 * As above, but record an error if program is not found.
355 struct gl_shader_program
*
356 _mesa_lookup_shader_program_err(GLcontext
*ctx
, GLuint name
,
360 _mesa_error(ctx
, GL_INVALID_VALUE
, caller
);
364 struct gl_shader_program
*shProg
= (struct gl_shader_program
*)
365 _mesa_HashLookup(ctx
->Shared
->ShaderObjects
, name
);
367 _mesa_error(ctx
, GL_INVALID_VALUE
, caller
);
370 if (shProg
->Type
!= GL_SHADER_PROGRAM_MESA
) {
371 _mesa_error(ctx
, GL_INVALID_OPERATION
, caller
);
380 _mesa_init_shader_object_functions(struct dd_function_table
*driver
)
382 driver
->NewShader
= _mesa_new_shader
;
383 driver
->DeleteShader
= __mesa_delete_shader
;
384 driver
->NewShaderProgram
= _mesa_new_shader_program
;
385 driver
->DeleteShaderProgram
= __mesa_delete_shader_program
;