blob: a584f6072c44571ad903b9a101bf2dc95df34a07 [file] [log] [blame]
Brian34ae99d2006-12-18 08:28:54 -07001/*
2 * Mesa 3-D graphics library
Brian Paulc90fca32009-08-25 17:42:47 -06003 * Version: 7.6
Brian34ae99d2006-12-18 08:28:54 -07004 *
Brian Paul8c51e002008-08-11 15:09:47 -06005 * Copyright (C) 2004-2008 Brian Paul All Rights Reserved.
Brian Paulc4ffbf02009-02-18 17:46:00 -07006 * Copyright (C) 2009 VMware, Inc. All Rights Reserved.
Brian34ae99d2006-12-18 08:28:54 -07007 *
8 * Permission is hereby granted, free of charge, to any person obtaining a
9 * copy of this software and associated documentation files (the "Software"),
10 * to deal in the Software without restriction, including without limitation
11 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
12 * and/or sell copies of the Software, and to permit persons to whom the
13 * Software is furnished to do so, subject to the following conditions:
14 *
15 * The above copyright notice and this permission notice shall be included
16 * in all copies or substantial portions of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
21 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
22 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
23 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24 */
25
26/**
27 * \file shader_api.c
Brian5b01c5e2006-12-19 18:02:03 -070028 * Implementation of GLSL-related API functions
Brian34ae99d2006-12-18 08:28:54 -070029 * \author Brian Paul
30 */
31
32/**
33 * XXX things to do:
34 * 1. Check that the right error code is generated for all _mesa_error() calls.
Brian5b01c5e2006-12-19 18:02:03 -070035 * 2. Insert FLUSH_VERTICES calls in various places
Brian34ae99d2006-12-18 08:28:54 -070036 */
37
38
Brian Paulbbd28712008-09-18 12:26:54 -060039#include "main/glheader.h"
40#include "main/context.h"
41#include "main/hash.h"
Brian Paulbbd28712008-09-18 12:26:54 -060042#include "shader/program.h"
43#include "shader/prog_parameter.h"
Brian Paulbbd28712008-09-18 12:26:54 -060044#include "shader/prog_uniform.h"
Brianc223c6b2007-07-04 13:15:20 -060045#include "shader/shader_api.h"
Brian Paul69861ae2010-05-26 22:24:58 -060046#include "shader/uniforms.h"
Brian34ae99d2006-12-18 08:28:54 -070047
48
Brianf2923612006-12-20 09:56:44 -070049/**
50 * Allocate a new gl_shader_program object, initialize it.
51 */
Brian Paulfd59f192008-05-18 16:04:55 -060052static struct gl_shader_program *
Brianf2923612006-12-20 09:56:44 -070053_mesa_new_shader_program(GLcontext *ctx, GLuint name)
54{
55 struct gl_shader_program *shProg;
56 shProg = CALLOC_STRUCT(gl_shader_program);
57 if (shProg) {
Brianf3e8c322007-04-18 14:53:23 -060058 shProg->Type = GL_SHADER_PROGRAM_MESA;
Brianf2923612006-12-20 09:56:44 -070059 shProg->Name = name;
60 shProg->RefCount = 1;
Brian3209c3e2007-01-09 17:49:24 -070061 shProg->Attributes = _mesa_new_parameter_list();
Brianf2923612006-12-20 09:56:44 -070062 }
63 return shProg;
64}
65
66
Brianb9fbedd2007-03-26 09:23:44 -060067/**
Brian3c008a02007-04-12 15:22:32 -060068 * Clear (free) the shader program state that gets produced by linking.
Brianb9fbedd2007-03-26 09:23:44 -060069 */
Brianf2923612006-12-20 09:56:44 -070070void
Brian3c008a02007-04-12 15:22:32 -060071_mesa_clear_shader_program_data(GLcontext *ctx,
72 struct gl_shader_program *shProg)
Brianf2923612006-12-20 09:56:44 -070073{
Brian Paul8bdf5b62008-05-16 09:56:59 -060074 _mesa_reference_vertprog(ctx, &shProg->VertexProgram, NULL);
75 _mesa_reference_fragprog(ctx, &shProg->FragmentProgram, NULL);
Brianf2923612006-12-20 09:56:44 -070076
Brianf2923612006-12-20 09:56:44 -070077 if (shProg->Uniforms) {
Brian Paulade50832008-05-14 16:09:46 -060078 _mesa_free_uniform_list(shProg->Uniforms);
Brianf2923612006-12-20 09:56:44 -070079 shProg->Uniforms = NULL;
80 }
81
82 if (shProg->Varying) {
83 _mesa_free_parameter_list(shProg->Varying);
84 shProg->Varying = NULL;
85 }
86}
87
88
Brianb9fbedd2007-03-26 09:23:44 -060089/**
Brian3c008a02007-04-12 15:22:32 -060090 * Free all the data that hangs off a shader program object, but not the
91 * object itself.
92 */
93void
94_mesa_free_shader_program_data(GLcontext *ctx,
95 struct gl_shader_program *shProg)
96{
97 GLuint i;
98
Brianf3e8c322007-04-18 14:53:23 -060099 assert(shProg->Type == GL_SHADER_PROGRAM_MESA);
Brian3c008a02007-04-12 15:22:32 -0600100
101 _mesa_clear_shader_program_data(ctx, shProg);
102
Brian4b7c6fc2007-04-19 15:23:34 -0600103 if (shProg->Attributes) {
104 _mesa_free_parameter_list(shProg->Attributes);
105 shProg->Attributes = NULL;
106 }
107
Brian3c008a02007-04-12 15:22:32 -0600108 /* detach shaders */
109 for (i = 0; i < shProg->NumShaders; i++) {
110 _mesa_reference_shader(ctx, &shProg->Shaders[i], NULL);
111 }
Xiang, Haihao63d8a842008-03-31 17:02:47 +0800112 shProg->NumShaders = 0;
113
Brian3c008a02007-04-12 15:22:32 -0600114 if (shProg->Shaders) {
Kristian Høgsberg32f2fd12010-02-19 11:58:49 -0500115 free(shProg->Shaders);
Brian3c008a02007-04-12 15:22:32 -0600116 shProg->Shaders = NULL;
117 }
Alan Hourihaneeec20c32008-04-22 20:29:42 +0100118
119 if (shProg->InfoLog) {
Kristian Høgsberg32f2fd12010-02-19 11:58:49 -0500120 free(shProg->InfoLog);
Alan Hourihaneeec20c32008-04-22 20:29:42 +0100121 shProg->InfoLog = NULL;
122 }
Brian Paule5c69642010-03-30 19:54:02 -0600123
124 /* Transform feedback varying vars */
125 for (i = 0; i < shProg->TransformFeedback.NumVarying; i++) {
126 free(shProg->TransformFeedback.VaryingNames[i]);
127 }
128 free(shProg->TransformFeedback.VaryingNames);
129 shProg->TransformFeedback.VaryingNames = NULL;
130 shProg->TransformFeedback.NumVarying = 0;
Brian3c008a02007-04-12 15:22:32 -0600131}
132
133
134/**
Brianb9fbedd2007-03-26 09:23:44 -0600135 * Free/delete a shader program object.
136 */
Brianf2923612006-12-20 09:56:44 -0700137void
138_mesa_free_shader_program(GLcontext *ctx, struct gl_shader_program *shProg)
139{
140 _mesa_free_shader_program_data(ctx, shProg);
Alan Hourihaneeec20c32008-04-22 20:29:42 +0100141
Kristian Høgsberg32f2fd12010-02-19 11:58:49 -0500142 free(shProg);
Brianf2923612006-12-20 09:56:44 -0700143}
144
145
146/**
Brian3c008a02007-04-12 15:22:32 -0600147 * Set ptr to point to shProg.
148 * If ptr is pointing to another object, decrement its refcount (and delete
149 * if refcount hits zero).
150 * Then set ptr to point to shProg, incrementing its refcount.
151 */
152/* XXX this could be static */
153void
154_mesa_reference_shader_program(GLcontext *ctx,
155 struct gl_shader_program **ptr,
156 struct gl_shader_program *shProg)
157{
158 assert(ptr);
159 if (*ptr == shProg) {
160 /* no-op */
161 return;
162 }
163 if (*ptr) {
164 /* Unreference the old shader program */
165 GLboolean deleteFlag = GL_FALSE;
166 struct gl_shader_program *old = *ptr;
167
168 ASSERT(old->RefCount > 0);
169 old->RefCount--;
Brian Paul8bdf5b62008-05-16 09:56:59 -0600170#if 0
171 printf("ShaderProgram %p ID=%u RefCount-- to %d\n",
172 (void *) old, old->Name, old->RefCount);
173#endif
Brian3c008a02007-04-12 15:22:32 -0600174 deleteFlag = (old->RefCount == 0);
175
176 if (deleteFlag) {
Xiang, Haihaoaef47c42008-03-31 16:27:47 +0800177 _mesa_HashRemove(ctx->Shared->ShaderObjects, old->Name);
Brian3c008a02007-04-12 15:22:32 -0600178 _mesa_free_shader_program(ctx, old);
179 }
180
181 *ptr = NULL;
182 }
183 assert(!*ptr);
184
185 if (shProg) {
186 shProg->RefCount++;
Brian Paul8bdf5b62008-05-16 09:56:59 -0600187#if 0
188 printf("ShaderProgram %p ID=%u RefCount++ to %d\n",
189 (void *) shProg, shProg->Name, shProg->RefCount);
190#endif
Brian3c008a02007-04-12 15:22:32 -0600191 *ptr = shProg;
192 }
193}
194
195
196/**
Brianf2923612006-12-20 09:56:44 -0700197 * Lookup a GLSL program object.
198 */
199struct gl_shader_program *
200_mesa_lookup_shader_program(GLcontext *ctx, GLuint name)
201{
202 struct gl_shader_program *shProg;
203 if (name) {
204 shProg = (struct gl_shader_program *)
Xiang, Haihaoaef47c42008-03-31 16:27:47 +0800205 _mesa_HashLookup(ctx->Shared->ShaderObjects, name);
Brianf2923612006-12-20 09:56:44 -0700206 /* Note that both gl_shader and gl_shader_program objects are kept
207 * in the same hash table. Check the object's type to be sure it's
208 * what we're expecting.
209 */
Brianf3e8c322007-04-18 14:53:23 -0600210 if (shProg && shProg->Type != GL_SHADER_PROGRAM_MESA) {
Brianf2923612006-12-20 09:56:44 -0700211 return NULL;
212 }
213 return shProg;
214 }
215 return NULL;
216}
217
218
219/**
Brian Paul530df582008-07-03 16:21:11 -0600220 * As above, but record an error if program is not found.
221 */
Brian Paul69861ae2010-05-26 22:24:58 -0600222struct gl_shader_program *
Brian Paul530df582008-07-03 16:21:11 -0600223_mesa_lookup_shader_program_err(GLcontext *ctx, GLuint name,
224 const char *caller)
225{
226 if (!name) {
227 _mesa_error(ctx, GL_INVALID_VALUE, caller);
228 return NULL;
229 }
230 else {
231 struct gl_shader_program *shProg = (struct gl_shader_program *)
232 _mesa_HashLookup(ctx->Shared->ShaderObjects, name);
233 if (!shProg) {
234 _mesa_error(ctx, GL_INVALID_VALUE, caller);
235 return NULL;
236 }
237 if (shProg->Type != GL_SHADER_PROGRAM_MESA) {
238 _mesa_error(ctx, GL_INVALID_OPERATION, caller);
239 return NULL;
240 }
241 return shProg;
242 }
243}
244
245
246
247
248/**
Brianf2923612006-12-20 09:56:44 -0700249 * Allocate a new gl_shader object, initialize it.
250 */
251struct gl_shader *
252_mesa_new_shader(GLcontext *ctx, GLuint name, GLenum type)
253{
254 struct gl_shader *shader;
255 assert(type == GL_FRAGMENT_SHADER || type == GL_VERTEX_SHADER);
256 shader = CALLOC_STRUCT(gl_shader);
257 if (shader) {
258 shader->Type = type;
259 shader->Name = name;
260 shader->RefCount = 1;
261 }
262 return shader;
263}
264
265
266void
267_mesa_free_shader(GLcontext *ctx, struct gl_shader *sh)
268{
Brianf2923612006-12-20 09:56:44 -0700269 if (sh->Source)
Kristian Høgsberg32f2fd12010-02-19 11:58:49 -0500270 free((void *) sh->Source);
Brianf2923612006-12-20 09:56:44 -0700271 if (sh->InfoLog)
Kristian Høgsberg32f2fd12010-02-19 11:58:49 -0500272 free(sh->InfoLog);
Brian Paul3d500f02008-07-24 14:56:54 -0600273 _mesa_reference_program(ctx, &sh->Program, NULL);
Kristian Høgsberg32f2fd12010-02-19 11:58:49 -0500274 free(sh);
Brianf2923612006-12-20 09:56:44 -0700275}
276
277
278/**
Brian3c008a02007-04-12 15:22:32 -0600279 * Set ptr to point to sh.
280 * If ptr is pointing to another shader, decrement its refcount (and delete
281 * if refcount hits zero).
282 * Then set ptr to point to sh, incrementing its refcount.
283 */
284/* XXX this could be static */
285void
286_mesa_reference_shader(GLcontext *ctx, struct gl_shader **ptr,
287 struct gl_shader *sh)
288{
289 assert(ptr);
290 if (*ptr == sh) {
291 /* no-op */
292 return;
293 }
294 if (*ptr) {
295 /* Unreference the old shader */
296 GLboolean deleteFlag = GL_FALSE;
297 struct gl_shader *old = *ptr;
298
299 ASSERT(old->RefCount > 0);
300 old->RefCount--;
Brian99193e42007-04-12 15:45:02 -0600301 /*printf("SHADER DECR %p (%d) to %d\n",
302 (void*) old, old->Name, old->RefCount);*/
Brian3c008a02007-04-12 15:22:32 -0600303 deleteFlag = (old->RefCount == 0);
304
305 if (deleteFlag) {
306 _mesa_HashRemove(ctx->Shared->ShaderObjects, old->Name);
307 _mesa_free_shader(ctx, old);
308 }
309
310 *ptr = NULL;
311 }
312 assert(!*ptr);
313
314 if (sh) {
315 /* reference new */
316 sh->RefCount++;
Brian99193e42007-04-12 15:45:02 -0600317 /*printf("SHADER INCR %p (%d) to %d\n",
318 (void*) sh, sh->Name, sh->RefCount);*/
Brian3c008a02007-04-12 15:22:32 -0600319 *ptr = sh;
320 }
321}
322
323
324/**
Brianf2923612006-12-20 09:56:44 -0700325 * Lookup a GLSL shader object.
326 */
327struct gl_shader *
328_mesa_lookup_shader(GLcontext *ctx, GLuint name)
329{
330 if (name) {
331 struct gl_shader *sh = (struct gl_shader *)
332 _mesa_HashLookup(ctx->Shared->ShaderObjects, name);
333 /* Note that both gl_shader and gl_shader_program objects are kept
334 * in the same hash table. Check the object's type to be sure it's
335 * what we're expecting.
336 */
Brianf3e8c322007-04-18 14:53:23 -0600337 if (sh && sh->Type == GL_SHADER_PROGRAM_MESA) {
Brianf2923612006-12-20 09:56:44 -0700338 return NULL;
339 }
340 return sh;
341 }
342 return NULL;
343}
344
345
Brianfa4d0362007-02-26 18:33:50 -0700346/**
Brian Paul530df582008-07-03 16:21:11 -0600347 * As above, but record an error if shader is not found.
348 */
349static struct gl_shader *
350_mesa_lookup_shader_err(GLcontext *ctx, GLuint name, const char *caller)
351{
352 if (!name) {
353 _mesa_error(ctx, GL_INVALID_VALUE, caller);
354 return NULL;
355 }
356 else {
357 struct gl_shader *sh = (struct gl_shader *)
358 _mesa_HashLookup(ctx->Shared->ShaderObjects, name);
359 if (!sh) {
360 _mesa_error(ctx, GL_INVALID_VALUE, caller);
361 return NULL;
362 }
363 if (sh->Type == GL_SHADER_PROGRAM_MESA) {
364 _mesa_error(ctx, GL_INVALID_OPERATION, caller);
365 return NULL;
366 }
367 return sh;
368 }
369}
370
371
Brian Paule01a03d2009-02-06 10:21:36 -0700372/**
373 * Return mask of GLSL_x flags by examining the MESA_GLSL env var.
374 */
375static GLbitfield
376get_shader_flags(void)
377{
378 GLbitfield flags = 0x0;
379 const char *env = _mesa_getenv("MESA_GLSL");
380
381 if (env) {
Kenneth Graunke0aecdb62010-02-18 23:50:51 -0800382 if (strstr(env, "dump"))
Brian Paule01a03d2009-02-06 10:21:36 -0700383 flags |= GLSL_DUMP;
Kenneth Graunke0aecdb62010-02-18 23:50:51 -0800384 if (strstr(env, "log"))
Brian Paule01a03d2009-02-06 10:21:36 -0700385 flags |= GLSL_LOG;
Kenneth Graunke0aecdb62010-02-18 23:50:51 -0800386 if (strstr(env, "nopvert"))
Brian Paulcb0de062009-09-29 10:22:32 -0600387 flags |= GLSL_NOP_VERT;
Kenneth Graunke0aecdb62010-02-18 23:50:51 -0800388 if (strstr(env, "nopfrag"))
Brian Paulcb0de062009-09-29 10:22:32 -0600389 flags |= GLSL_NOP_FRAG;
Kenneth Graunke0aecdb62010-02-18 23:50:51 -0800390 if (strstr(env, "nopt"))
Brian Paule01a03d2009-02-06 10:21:36 -0700391 flags |= GLSL_NO_OPT;
Kenneth Graunke0aecdb62010-02-18 23:50:51 -0800392 else if (strstr(env, "opt"))
Brian Paule01a03d2009-02-06 10:21:36 -0700393 flags |= GLSL_OPT;
Kenneth Graunke0aecdb62010-02-18 23:50:51 -0800394 if (strstr(env, "uniform"))
Brian Paule01a03d2009-02-06 10:21:36 -0700395 flags |= GLSL_UNIFORMS;
Kenneth Graunke0aecdb62010-02-18 23:50:51 -0800396 if (strstr(env, "useprog"))
Brian Paul2ee7fd82009-10-15 15:25:52 -0600397 flags |= GLSL_USE_PROG;
Brian Paule01a03d2009-02-06 10:21:36 -0700398 }
399
400 return flags;
401}
402
Brian Paul530df582008-07-03 16:21:11 -0600403
404/**
Brian Paule5c69642010-03-30 19:54:02 -0600405 * Find the length of the longest transform feedback varying name
406 * which was specified with glTransformFeedbackVaryings().
407 */
408static GLint
409longest_feedback_varying_name(const struct gl_shader_program *shProg)
410{
411 GLuint i;
412 GLint max = 0;
413 for (i = 0; i < shProg->TransformFeedback.NumVarying; i++) {
414 GLint len = strlen(shProg->TransformFeedback.VaryingNames[i]);
415 if (len > max)
416 max = len;
417 }
418 return max;
419}
420
421
422
423/**
Brianfa4d0362007-02-26 18:33:50 -0700424 * Initialize context's shader state.
425 */
Brianf2923612006-12-20 09:56:44 -0700426void
427_mesa_init_shader_state(GLcontext * ctx)
428{
Brianfa4d0362007-02-26 18:33:50 -0700429 /* Device drivers may override these to control what kind of instructions
430 * are generated by the GLSL compiler.
431 */
432 ctx->Shader.EmitHighLevelInstructions = GL_TRUE;
Brian Paul4031ea12009-06-17 11:57:39 -0600433 ctx->Shader.EmitContReturn = GL_TRUE;
Brian Paulc5c38352009-02-16 11:50:05 -0700434 ctx->Shader.EmitCondCodes = GL_FALSE;
Brianfa4d0362007-02-26 18:33:50 -0700435 ctx->Shader.EmitComments = GL_FALSE;
Brian Paule01a03d2009-02-06 10:21:36 -0700436 ctx->Shader.Flags = get_shader_flags();
Brian Paul65fc2ca2009-03-19 10:25:24 -0600437
438 /* Default pragma settings */
439 ctx->Shader.DefaultPragmas.IgnoreOptimize = GL_FALSE;
440 ctx->Shader.DefaultPragmas.IgnoreDebug = GL_FALSE;
441 ctx->Shader.DefaultPragmas.Optimize = GL_TRUE;
442 ctx->Shader.DefaultPragmas.Debug = GL_FALSE;
Brianf2923612006-12-20 09:56:44 -0700443}
444
445
Brian5b01c5e2006-12-19 18:02:03 -0700446/**
Brian935f93f2007-03-24 16:20:02 -0600447 * Free the per-context shader-related state.
448 */
449void
450_mesa_free_shader_state(GLcontext *ctx)
451{
Brian3c008a02007-04-12 15:22:32 -0600452 _mesa_reference_shader_program(ctx, &ctx->Shader.CurrentProgram, NULL);
Brian935f93f2007-03-24 16:20:02 -0600453}
454
455
456/**
Brian5b01c5e2006-12-19 18:02:03 -0700457 * Copy string from <src> to <dst>, up to maxLength characters, returning
458 * length of <dst> in <length>.
459 * \param src the strings source
460 * \param maxLength max chars to copy
461 * \param length returns number of chars copied
462 * \param dst the string destination
463 */
Brian Paule5c69642010-03-30 19:54:02 -0600464void
465_mesa_copy_string(GLchar *dst, GLsizei maxLength,
466 GLsizei *length, const GLchar *src)
Brian5b01c5e2006-12-19 18:02:03 -0700467{
468 GLsizei len;
469 for (len = 0; len < maxLength - 1 && src && src[len]; len++)
470 dst[len] = src[len];
471 if (maxLength > 0)
472 dst[len] = 0;
473 if (length)
474 *length = len;
475}
476
477
Brian Paul7acb7c12008-07-03 13:49:48 -0600478static GLboolean
479_mesa_is_program(GLcontext *ctx, GLuint name)
480{
481 struct gl_shader_program *shProg = _mesa_lookup_shader_program(ctx, name);
482 return shProg ? GL_TRUE : GL_FALSE;
483}
484
485
486static GLboolean
487_mesa_is_shader(GLcontext *ctx, GLuint name)
488{
489 struct gl_shader *shader = _mesa_lookup_shader(ctx, name);
490 return shader ? GL_TRUE : GL_FALSE;
491}
492
493
Brian5b01c5e2006-12-19 18:02:03 -0700494/**
495 * Called via ctx->Driver.AttachShader()
496 */
Brian Paulfd59f192008-05-18 16:04:55 -0600497static void
Brian5b01c5e2006-12-19 18:02:03 -0700498_mesa_attach_shader(GLcontext *ctx, GLuint program, GLuint shader)
499{
Brian Paul530df582008-07-03 16:21:11 -0600500 struct gl_shader_program *shProg;
501 struct gl_shader *sh;
502 GLuint i, n;
Brian5b01c5e2006-12-19 18:02:03 -0700503
Brian Paul530df582008-07-03 16:21:11 -0600504 shProg = _mesa_lookup_shader_program_err(ctx, program, "glAttachShader");
505 if (!shProg)
Brian5b01c5e2006-12-19 18:02:03 -0700506 return;
Brian5b01c5e2006-12-19 18:02:03 -0700507
Brian Paul530df582008-07-03 16:21:11 -0600508 sh = _mesa_lookup_shader_err(ctx, shader, "glAttachShader");
Brian Paul7acb7c12008-07-03 13:49:48 -0600509 if (!sh) {
Brian Paul7acb7c12008-07-03 13:49:48 -0600510 return;
511 }
512
Brian237b9852007-08-07 21:48:31 +0100513 n = shProg->NumShaders;
Brian5b01c5e2006-12-19 18:02:03 -0700514 for (i = 0; i < n; i++) {
Brian65a18442006-12-19 18:46:56 -0700515 if (shProg->Shaders[i] == sh) {
Ian Romanickd806d452008-09-29 12:18:06 -0700516 /* The shader is already attched to this program. The
517 * GL_ARB_shader_objects spec says:
518 *
519 * "The error INVALID_OPERATION is generated by AttachObjectARB
520 * if <obj> is already attached to <containerObj>."
521 */
522 _mesa_error(ctx, GL_INVALID_OPERATION, "glAttachShader");
Brian5b01c5e2006-12-19 18:02:03 -0700523 return;
Brian34ae99d2006-12-18 08:28:54 -0700524 }
525 }
Brian5b01c5e2006-12-19 18:02:03 -0700526
527 /* grow list */
Brian65a18442006-12-19 18:46:56 -0700528 shProg->Shaders = (struct gl_shader **)
529 _mesa_realloc(shProg->Shaders,
530 n * sizeof(struct gl_shader *),
531 (n + 1) * sizeof(struct gl_shader *));
532 if (!shProg->Shaders) {
Brian5b01c5e2006-12-19 18:02:03 -0700533 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glAttachShader");
534 return;
535 }
536
537 /* append */
Brian3c008a02007-04-12 15:22:32 -0600538 shProg->Shaders[n] = NULL; /* since realloc() didn't zero the new space */
539 _mesa_reference_shader(ctx, &shProg->Shaders[n], sh);
Brian65a18442006-12-19 18:46:56 -0700540 shProg->NumShaders++;
Brian5b01c5e2006-12-19 18:02:03 -0700541}
542
543
Brian Paulfd59f192008-05-18 16:04:55 -0600544static GLint
Brian Paul896c0cc2008-05-16 15:47:55 -0600545_mesa_get_attrib_location(GLcontext *ctx, GLuint program,
546 const GLchar *name)
547{
548 struct gl_shader_program *shProg
Brian Paul530df582008-07-03 16:21:11 -0600549 = _mesa_lookup_shader_program_err(ctx, program, "glGetAttribLocation");
Brian Paul896c0cc2008-05-16 15:47:55 -0600550
551 if (!shProg) {
Brian Paul896c0cc2008-05-16 15:47:55 -0600552 return -1;
553 }
554
555 if (!shProg->LinkStatus) {
556 _mesa_error(ctx, GL_INVALID_OPERATION,
557 "glGetAttribLocation(program not linked)");
558 return -1;
559 }
560
561 if (!name)
562 return -1;
563
Brian Paul27341a92008-09-16 16:28:36 -0600564 if (shProg->VertexProgram) {
565 const struct gl_program_parameter_list *attribs =
566 shProg->VertexProgram->Base.Attributes;
567 if (attribs) {
568 GLint i = _mesa_lookup_parameter_index(attribs, -1, name);
569 if (i >= 0) {
570 return attribs->Parameters[i].StateIndexes[0];
571 }
Brian Paul896c0cc2008-05-16 15:47:55 -0600572 }
573 }
574 return -1;
575}
576
577
Brian Paulfd59f192008-05-18 16:04:55 -0600578static void
Brian5b01c5e2006-12-19 18:02:03 -0700579_mesa_bind_attrib_location(GLcontext *ctx, GLuint program, GLuint index,
580 const GLchar *name)
581{
Brian Paul530df582008-07-03 16:21:11 -0600582 struct gl_shader_program *shProg;
Brianb7978af2007-01-09 19:17:17 -0700583 const GLint size = -1; /* unknown size */
Brian Paul6bc87492008-07-25 08:34:54 -0600584 GLint i, oldIndex;
Brian Paul6f1abb92008-07-29 17:27:22 -0600585 GLenum datatype = GL_FLOAT_VEC4;
Brian5b01c5e2006-12-19 18:02:03 -0700586
Brian Paul530df582008-07-03 16:21:11 -0600587 shProg = _mesa_lookup_shader_program_err(ctx, program,
588 "glBindAttribLocation");
Brian65a18442006-12-19 18:46:56 -0700589 if (!shProg) {
Brian5b01c5e2006-12-19 18:02:03 -0700590 return;
591 }
592
Brian9e4bae92006-12-20 09:27:42 -0700593 if (!name)
594 return;
595
596 if (strncmp(name, "gl_", 3) == 0) {
597 _mesa_error(ctx, GL_INVALID_OPERATION,
598 "glBindAttribLocation(illegal name)");
599 return;
600 }
601
Brian Paul7acb7c12008-07-03 13:49:48 -0600602 if (index >= ctx->Const.VertexProgram.MaxAttribs) {
603 _mesa_error(ctx, GL_INVALID_VALUE, "glBindAttribLocation(index)");
604 return;
605 }
606
Brian Paul6bc87492008-07-25 08:34:54 -0600607 if (shProg->LinkStatus) {
608 /* get current index/location for the attribute */
609 oldIndex = _mesa_get_attrib_location(ctx, program, name);
610 }
611 else {
612 oldIndex = -1;
613 }
614
Brian3209c3e2007-01-09 17:49:24 -0700615 /* this will replace the current value if it's already in the list */
Brian Paulffbc66b2008-07-21 13:58:50 -0600616 i = _mesa_add_attribute(shProg->Attributes, name, size, datatype, index);
Brian3209c3e2007-01-09 17:49:24 -0700617 if (i < 0) {
618 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBindAttribLocation");
Brian Paul6f1abb92008-07-29 17:27:22 -0600619 return;
Brian3209c3e2007-01-09 17:49:24 -0700620 }
621
Brian Paul27341a92008-09-16 16:28:36 -0600622 /*
623 * Note that this attribute binding won't go into effect until
624 * glLinkProgram is called again.
625 */
Brian34ae99d2006-12-18 08:28:54 -0700626}
627
628
Brian Paulfd59f192008-05-18 16:04:55 -0600629static GLuint
Brian5b01c5e2006-12-19 18:02:03 -0700630_mesa_create_shader(GLcontext *ctx, GLenum type)
631{
Brian65a18442006-12-19 18:46:56 -0700632 struct gl_shader *sh;
Brian5b01c5e2006-12-19 18:02:03 -0700633 GLuint name;
634
635 name = _mesa_HashFindFreeKeyBlock(ctx->Shared->ShaderObjects, 1);
636
637 switch (type) {
Brian65a18442006-12-19 18:46:56 -0700638 case GL_FRAGMENT_SHADER:
639 case GL_VERTEX_SHADER:
640 sh = _mesa_new_shader(ctx, name, type);
Brian5b01c5e2006-12-19 18:02:03 -0700641 break;
642 default:
643 _mesa_error(ctx, GL_INVALID_ENUM, "CreateShader(type)");
644 return 0;
645 }
646
Brian65a18442006-12-19 18:46:56 -0700647 _mesa_HashInsert(ctx->Shared->ShaderObjects, name, sh);
Brian5b01c5e2006-12-19 18:02:03 -0700648
649 return name;
650}
651
652
Brian Paulfd59f192008-05-18 16:04:55 -0600653static GLuint
Brian5b01c5e2006-12-19 18:02:03 -0700654_mesa_create_program(GLcontext *ctx)
655{
656 GLuint name;
Brian65a18442006-12-19 18:46:56 -0700657 struct gl_shader_program *shProg;
Brian5b01c5e2006-12-19 18:02:03 -0700658
Xiang, Haihaoaef47c42008-03-31 16:27:47 +0800659 name = _mesa_HashFindFreeKeyBlock(ctx->Shared->ShaderObjects, 1);
Brian65a18442006-12-19 18:46:56 -0700660 shProg = _mesa_new_shader_program(ctx, name);
Brian5b01c5e2006-12-19 18:02:03 -0700661
Xiang, Haihaoaef47c42008-03-31 16:27:47 +0800662 _mesa_HashInsert(ctx->Shared->ShaderObjects, name, shProg);
Brian5b01c5e2006-12-19 18:02:03 -0700663
Brian3c008a02007-04-12 15:22:32 -0600664 assert(shProg->RefCount == 1);
665
Brian5b01c5e2006-12-19 18:02:03 -0700666 return name;
667}
668
669
Brian3c008a02007-04-12 15:22:32 -0600670/**
671 * Named w/ "2" to indicate OpenGL 2.x vs GL_ARB_fragment_programs's
672 * DeleteProgramARB.
673 */
Brian Paulfd59f192008-05-18 16:04:55 -0600674static void
Brian5b01c5e2006-12-19 18:02:03 -0700675_mesa_delete_program2(GLcontext *ctx, GLuint name)
676{
Brian3c008a02007-04-12 15:22:32 -0600677 /*
678 * NOTE: deleting shaders/programs works a bit differently than
679 * texture objects (and buffer objects, etc). Shader/program
680 * handles/IDs exist in the hash table until the object is really
681 * deleted (refcount==0). With texture objects, the handle/ID is
682 * removed from the hash table in glDeleteTextures() while the tex
683 * object itself might linger until its refcount goes to zero.
684 */
Brian65a18442006-12-19 18:46:56 -0700685 struct gl_shader_program *shProg;
Brian5b01c5e2006-12-19 18:02:03 -0700686
Brian Paul530df582008-07-03 16:21:11 -0600687 shProg = _mesa_lookup_shader_program_err(ctx, name, "glDeleteProgram");
688 if (!shProg)
Brian5b01c5e2006-12-19 18:02:03 -0700689 return;
Brian5b01c5e2006-12-19 18:02:03 -0700690
Brian9e4bae92006-12-20 09:27:42 -0700691 shProg->DeletePending = GL_TRUE;
692
Brian3c008a02007-04-12 15:22:32 -0600693 /* effectively, decr shProg's refcount */
694 _mesa_reference_shader_program(ctx, &shProg, NULL);
Brian5b01c5e2006-12-19 18:02:03 -0700695}
696
697
Brian Paulfd59f192008-05-18 16:04:55 -0600698static void
Brian5b01c5e2006-12-19 18:02:03 -0700699_mesa_delete_shader(GLcontext *ctx, GLuint shader)
700{
Brian Paul530df582008-07-03 16:21:11 -0600701 struct gl_shader *sh;
702
703 sh = _mesa_lookup_shader_err(ctx, shader, "glDeleteShader");
704 if (!sh)
Brian9e4bae92006-12-20 09:27:42 -0700705 return;
Brian5b01c5e2006-12-19 18:02:03 -0700706
Brian9e4bae92006-12-20 09:27:42 -0700707 sh->DeletePending = GL_TRUE;
Brian3c008a02007-04-12 15:22:32 -0600708
709 /* effectively, decr sh's refcount */
710 _mesa_reference_shader(ctx, &sh, NULL);
Brian5b01c5e2006-12-19 18:02:03 -0700711}
712
713
Brian Paulfd59f192008-05-18 16:04:55 -0600714static void
Brian5b01c5e2006-12-19 18:02:03 -0700715_mesa_detach_shader(GLcontext *ctx, GLuint program, GLuint shader)
716{
Brian Paul530df582008-07-03 16:21:11 -0600717 struct gl_shader_program *shProg;
Brian237b9852007-08-07 21:48:31 +0100718 GLuint n;
Brian5b01c5e2006-12-19 18:02:03 -0700719 GLuint i, j;
720
Brian Paul530df582008-07-03 16:21:11 -0600721 shProg = _mesa_lookup_shader_program_err(ctx, program, "glDetachShader");
722 if (!shProg)
Brian5b01c5e2006-12-19 18:02:03 -0700723 return;
Brian5b01c5e2006-12-19 18:02:03 -0700724
Brian237b9852007-08-07 21:48:31 +0100725 n = shProg->NumShaders;
726
Brian5b01c5e2006-12-19 18:02:03 -0700727 for (i = 0; i < n; i++) {
Brian65a18442006-12-19 18:46:56 -0700728 if (shProg->Shaders[i]->Name == shader) {
Brian5b01c5e2006-12-19 18:02:03 -0700729 /* found it */
Brian3c008a02007-04-12 15:22:32 -0600730 struct gl_shader **newList;
Brian9e4bae92006-12-20 09:27:42 -0700731
Brian Paul530df582008-07-03 16:21:11 -0600732 /* release */
Brian3c008a02007-04-12 15:22:32 -0600733 _mesa_reference_shader(ctx, &shProg->Shaders[i], NULL);
Brian9e4bae92006-12-20 09:27:42 -0700734
Brian5b01c5e2006-12-19 18:02:03 -0700735 /* alloc new, smaller array */
Brian65a18442006-12-19 18:46:56 -0700736 newList = (struct gl_shader **)
Kristian Høgsberg32f2fd12010-02-19 11:58:49 -0500737 malloc((n - 1) * sizeof(struct gl_shader *));
Brian5b01c5e2006-12-19 18:02:03 -0700738 if (!newList) {
739 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glDetachShader");
740 return;
741 }
742 for (j = 0; j < i; j++) {
Brian65a18442006-12-19 18:46:56 -0700743 newList[j] = shProg->Shaders[j];
Brian5b01c5e2006-12-19 18:02:03 -0700744 }
745 while (++i < n)
Brian65a18442006-12-19 18:46:56 -0700746 newList[j++] = shProg->Shaders[i];
Kristian Høgsberg32f2fd12010-02-19 11:58:49 -0500747 free(shProg->Shaders);
Brian5b01c5e2006-12-19 18:02:03 -0700748
Brian65a18442006-12-19 18:46:56 -0700749 shProg->Shaders = newList;
Brianbac15c82007-04-18 14:55:18 -0600750 shProg->NumShaders = n - 1;
Brianaaa57412007-04-18 15:22:43 -0600751
752#ifdef DEBUG
753 /* sanity check */
754 {
755 for (j = 0; j < shProg->NumShaders; j++) {
756 assert(shProg->Shaders[j]->Type == GL_VERTEX_SHADER ||
757 shProg->Shaders[j]->Type == GL_FRAGMENT_SHADER);
758 assert(shProg->Shaders[j]->RefCount > 0);
759 }
760 }
761#endif
762
Brian5b01c5e2006-12-19 18:02:03 -0700763 return;
764 }
765 }
766
767 /* not found */
Brian Paul530df582008-07-03 16:21:11 -0600768 {
769 GLenum err;
770 if (_mesa_is_shader(ctx, shader))
771 err = GL_INVALID_OPERATION;
772 else if (_mesa_is_program(ctx, shader))
773 err = GL_INVALID_OPERATION;
774 else
775 err = GL_INVALID_VALUE;
776 _mesa_error(ctx, err, "glDetachProgram(shader)");
777 return;
778 }
Brian5b01c5e2006-12-19 18:02:03 -0700779}
780
781
Brian Paul1a148662010-04-01 22:15:16 -0600782/**
783 * Return the size of the given GLSL datatype, in floats (components).
784 */
785GLint
786_mesa_sizeof_glsl_type(GLenum type)
Brian Paulffbc66b2008-07-21 13:58:50 -0600787{
788 switch (type) {
789 case GL_FLOAT:
790 case GL_INT:
791 case GL_BOOL:
Brian Paul8c51e002008-08-11 15:09:47 -0600792 case GL_SAMPLER_1D:
793 case GL_SAMPLER_2D:
794 case GL_SAMPLER_3D:
795 case GL_SAMPLER_CUBE:
796 case GL_SAMPLER_1D_SHADOW:
797 case GL_SAMPLER_2D_SHADOW:
798 case GL_SAMPLER_2D_RECT_ARB:
799 case GL_SAMPLER_2D_RECT_SHADOW_ARB:
Brian Paulac498f22010-02-25 19:05:11 -0700800 case GL_SAMPLER_1D_ARRAY_EXT:
801 case GL_SAMPLER_2D_ARRAY_EXT:
Brian Paul8c51e002008-08-11 15:09:47 -0600802 case GL_SAMPLER_1D_ARRAY_SHADOW_EXT:
803 case GL_SAMPLER_2D_ARRAY_SHADOW_EXT:
804 case GL_SAMPLER_CUBE_SHADOW_EXT:
Brian Paulffbc66b2008-07-21 13:58:50 -0600805 return 1;
806 case GL_FLOAT_VEC2:
807 case GL_INT_VEC2:
Brian Paul91f841a2010-05-25 18:39:47 -0600808 case GL_UNSIGNED_INT_VEC2:
Brian Paulffbc66b2008-07-21 13:58:50 -0600809 case GL_BOOL_VEC2:
810 return 2;
811 case GL_FLOAT_VEC3:
812 case GL_INT_VEC3:
Brian Paul91f841a2010-05-25 18:39:47 -0600813 case GL_UNSIGNED_INT_VEC3:
Brian Paulffbc66b2008-07-21 13:58:50 -0600814 case GL_BOOL_VEC3:
815 return 3;
816 case GL_FLOAT_VEC4:
817 case GL_INT_VEC4:
Brian Paul91f841a2010-05-25 18:39:47 -0600818 case GL_UNSIGNED_INT_VEC4:
Brian Paulffbc66b2008-07-21 13:58:50 -0600819 case GL_BOOL_VEC4:
820 return 4;
821 case GL_FLOAT_MAT2:
822 case GL_FLOAT_MAT2x3:
823 case GL_FLOAT_MAT2x4:
824 return 8; /* two float[4] vectors */
825 case GL_FLOAT_MAT3:
826 case GL_FLOAT_MAT3x2:
827 case GL_FLOAT_MAT3x4:
828 return 12; /* three float[4] vectors */
829 case GL_FLOAT_MAT4:
830 case GL_FLOAT_MAT4x2:
831 case GL_FLOAT_MAT4x3:
832 return 16; /* four float[4] vectors */
833 default:
Brian Paul1a148662010-04-01 22:15:16 -0600834 _mesa_problem(NULL, "Invalid type in _mesa_sizeof_glsl_type()");
Brian Paulffbc66b2008-07-21 13:58:50 -0600835 return 1;
836 }
837}
838
839
Brian Paulfd59f192008-05-18 16:04:55 -0600840static void
Brian5b01c5e2006-12-19 18:02:03 -0700841_mesa_get_active_attrib(GLcontext *ctx, GLuint program, GLuint index,
842 GLsizei maxLength, GLsizei *length, GLint *size,
843 GLenum *type, GLchar *nameOut)
844{
Brian Paul27341a92008-09-16 16:28:36 -0600845 const struct gl_program_parameter_list *attribs = NULL;
Brian Paul530df582008-07-03 16:21:11 -0600846 struct gl_shader_program *shProg;
Brian5b01c5e2006-12-19 18:02:03 -0700847
Brian Paul530df582008-07-03 16:21:11 -0600848 shProg = _mesa_lookup_shader_program_err(ctx, program, "glGetActiveAttrib");
849 if (!shProg)
Brian5b01c5e2006-12-19 18:02:03 -0700850 return;
Brian5b01c5e2006-12-19 18:02:03 -0700851
Brian Paul27341a92008-09-16 16:28:36 -0600852 if (shProg->VertexProgram)
853 attribs = shProg->VertexProgram->Base.Attributes;
854
855 if (!attribs || index >= attribs->NumParameters) {
Brianaaa57412007-04-18 15:22:43 -0600856 _mesa_error(ctx, GL_INVALID_VALUE, "glGetActiveAttrib(index)");
Brian5b01c5e2006-12-19 18:02:03 -0700857 return;
858 }
859
Brian Paule5c69642010-03-30 19:54:02 -0600860 _mesa_copy_string(nameOut, maxLength, length,
861 attribs->Parameters[index].Name);
Brian Paul27341a92008-09-16 16:28:36 -0600862
Brian5b01c5e2006-12-19 18:02:03 -0700863 if (size)
Brian Paul27341a92008-09-16 16:28:36 -0600864 *size = attribs->Parameters[index].Size
Brian Paul1a148662010-04-01 22:15:16 -0600865 / _mesa_sizeof_glsl_type(attribs->Parameters[index].DataType);
Brian Paul27341a92008-09-16 16:28:36 -0600866
Brian Paulade50832008-05-14 16:09:46 -0600867 if (type)
Brian Paul27341a92008-09-16 16:28:36 -0600868 *type = attribs->Parameters[index].DataType;
Brian5b01c5e2006-12-19 18:02:03 -0700869}
870
871
Brian5b01c5e2006-12-19 18:02:03 -0700872/**
873 * Called via ctx->Driver.GetAttachedShaders().
874 */
Brian Paulfd59f192008-05-18 16:04:55 -0600875static void
Brian5b01c5e2006-12-19 18:02:03 -0700876_mesa_get_attached_shaders(GLcontext *ctx, GLuint program, GLsizei maxCount,
877 GLsizei *count, GLuint *obj)
878{
Brian Paul530df582008-07-03 16:21:11 -0600879 struct gl_shader_program *shProg =
880 _mesa_lookup_shader_program_err(ctx, program, "glGetAttachedShaders");
Brian65a18442006-12-19 18:46:56 -0700881 if (shProg) {
Brian Paul530df582008-07-03 16:21:11 -0600882 GLuint i;
883 for (i = 0; i < (GLuint) maxCount && i < shProg->NumShaders; i++) {
Brian65a18442006-12-19 18:46:56 -0700884 obj[i] = shProg->Shaders[i]->Name;
Brian5b01c5e2006-12-19 18:02:03 -0700885 }
886 if (count)
887 *count = i;
888 }
Brian5b01c5e2006-12-19 18:02:03 -0700889}
890
891
Brian Pauleb88c022010-05-26 22:40:38 -0600892/** glGetHandleARB() - return ID/name of currently bound shader program */
Brian Paulfd59f192008-05-18 16:04:55 -0600893static GLuint
Brian5b01c5e2006-12-19 18:02:03 -0700894_mesa_get_handle(GLcontext *ctx, GLenum pname)
Brian34ae99d2006-12-18 08:28:54 -0700895{
Ian Romanick905d8e02008-09-29 12:27:00 -0700896 if (pname == GL_PROGRAM_OBJECT_ARB) {
Brian Pauleb88c022010-05-26 22:40:38 -0600897 if (ctx->Shader.CurrentProgram)
898 return ctx->Shader.CurrentProgram->Name;
899 else
900 return 0;
Brian34ae99d2006-12-18 08:28:54 -0700901 }
Brian Pauleb88c022010-05-26 22:40:38 -0600902 else {
903 _mesa_error(ctx, GL_INVALID_ENUM, "glGetHandleARB");
904 return 0;
905 }
Brian34ae99d2006-12-18 08:28:54 -0700906}
907
908
Brian Pauleb88c022010-05-26 22:40:38 -0600909/**
910 * glGetProgramiv() - get shader program state.
911 * Note that this is for GLSL shader programs, not ARB vertex/fragment
912 * programs (see glGetProgramivARB).
913 */
Brian Paulfd59f192008-05-18 16:04:55 -0600914static void
Brian5b01c5e2006-12-19 18:02:03 -0700915_mesa_get_programiv(GLcontext *ctx, GLuint program,
916 GLenum pname, GLint *params)
Brian34ae99d2006-12-18 08:28:54 -0700917{
Brian Paul27341a92008-09-16 16:28:36 -0600918 const struct gl_program_parameter_list *attribs;
Brian65a18442006-12-19 18:46:56 -0700919 struct gl_shader_program *shProg
920 = _mesa_lookup_shader_program(ctx, program);
Brian34ae99d2006-12-18 08:28:54 -0700921
Brian65a18442006-12-19 18:46:56 -0700922 if (!shProg) {
Brian5b01c5e2006-12-19 18:02:03 -0700923 _mesa_error(ctx, GL_INVALID_VALUE, "glGetProgramiv(program)");
Brian34ae99d2006-12-18 08:28:54 -0700924 return;
925 }
926
Brian Paul27341a92008-09-16 16:28:36 -0600927 if (shProg->VertexProgram)
928 attribs = shProg->VertexProgram->Base.Attributes;
929 else
930 attribs = NULL;
931
Brian5b01c5e2006-12-19 18:02:03 -0700932 switch (pname) {
933 case GL_DELETE_STATUS:
Brian65a18442006-12-19 18:46:56 -0700934 *params = shProg->DeletePending;
Brian5b01c5e2006-12-19 18:02:03 -0700935 break;
936 case GL_LINK_STATUS:
Brian65a18442006-12-19 18:46:56 -0700937 *params = shProg->LinkStatus;
Brian34ae99d2006-12-18 08:28:54 -0700938 break;
Brian5b01c5e2006-12-19 18:02:03 -0700939 case GL_VALIDATE_STATUS:
Brian65a18442006-12-19 18:46:56 -0700940 *params = shProg->Validated;
Brian5b01c5e2006-12-19 18:02:03 -0700941 break;
942 case GL_INFO_LOG_LENGTH:
Jan Dvorak5a0f02a2007-07-13 16:36:00 -0600943 *params = shProg->InfoLog ? strlen(shProg->InfoLog) + 1 : 0;
Brian5b01c5e2006-12-19 18:02:03 -0700944 break;
945 case GL_ATTACHED_SHADERS:
Brian65a18442006-12-19 18:46:56 -0700946 *params = shProg->NumShaders;
Brian5b01c5e2006-12-19 18:02:03 -0700947 break;
948 case GL_ACTIVE_ATTRIBUTES:
Brian Paul27341a92008-09-16 16:28:36 -0600949 *params = attribs ? attribs->NumParameters : 0;
Brian5b01c5e2006-12-19 18:02:03 -0700950 break;
951 case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH:
Brian Paul27341a92008-09-16 16:28:36 -0600952 *params = _mesa_longest_parameter_name(attribs, PROGRAM_INPUT) + 1;
Brian5b01c5e2006-12-19 18:02:03 -0700953 break;
954 case GL_ACTIVE_UNIFORMS:
Brian Paulade50832008-05-14 16:09:46 -0600955 *params = shProg->Uniforms ? shProg->Uniforms->NumUniforms : 0;
Brian5b01c5e2006-12-19 18:02:03 -0700956 break;
957 case GL_ACTIVE_UNIFORM_MAX_LENGTH:
Brian Paulade50832008-05-14 16:09:46 -0600958 *params = _mesa_longest_uniform_name(shProg->Uniforms);
Brian274ac7a2007-04-18 16:05:53 -0600959 if (*params > 0)
960 (*params)++; /* add one for terminating zero */
Brian34ae99d2006-12-18 08:28:54 -0700961 break;
Brian Paulbda6ad22008-08-06 12:45:14 -0600962 case GL_PROGRAM_BINARY_LENGTH_OES:
963 *params = 0;
964 break;
Brian Paule5c69642010-03-30 19:54:02 -0600965#if FEATURE_EXT_transform_feedback
966 case GL_TRANSFORM_FEEDBACK_VARYINGS:
967 *params = shProg->TransformFeedback.NumVarying;
968 break;
969 case GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH:
970 *params = longest_feedback_varying_name(shProg) + 1;
971 break;
972 case GL_TRANSFORM_FEEDBACK_BUFFER_MODE:
973 *params = shProg->TransformFeedback.BufferMode;
974 break;
975#endif
Brian34ae99d2006-12-18 08:28:54 -0700976 default:
Brian5b01c5e2006-12-19 18:02:03 -0700977 _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramiv(pname)");
978 return;
Brian34ae99d2006-12-18 08:28:54 -0700979 }
Brian5b01c5e2006-12-19 18:02:03 -0700980}
Brian34ae99d2006-12-18 08:28:54 -0700981
Brian34ae99d2006-12-18 08:28:54 -0700982
Brian Pauleb88c022010-05-26 22:40:38 -0600983/** glGetShaderiv() - get GLSL shader state */
Brian Paulfd59f192008-05-18 16:04:55 -0600984static void
Brian5b01c5e2006-12-19 18:02:03 -0700985_mesa_get_shaderiv(GLcontext *ctx, GLuint name, GLenum pname, GLint *params)
986{
Brian Paul530df582008-07-03 16:21:11 -0600987 struct gl_shader *shader = _mesa_lookup_shader_err(ctx, name, "glGetShaderiv");
Brian5b01c5e2006-12-19 18:02:03 -0700988
989 if (!shader) {
Brian5b01c5e2006-12-19 18:02:03 -0700990 return;
991 }
Brian65a18442006-12-19 18:46:56 -0700992
Brian5b01c5e2006-12-19 18:02:03 -0700993 switch (pname) {
994 case GL_SHADER_TYPE:
995 *params = shader->Type;
996 break;
997 case GL_DELETE_STATUS:
998 *params = shader->DeletePending;
999 break;
1000 case GL_COMPILE_STATUS:
1001 *params = shader->CompileStatus;
1002 break;
1003 case GL_INFO_LOG_LENGTH:
Jan Dvorak5a0f02a2007-07-13 16:36:00 -06001004 *params = shader->InfoLog ? strlen(shader->InfoLog) + 1 : 0;
Brian5b01c5e2006-12-19 18:02:03 -07001005 break;
1006 case GL_SHADER_SOURCE_LENGTH:
Jan Dvorak5a0f02a2007-07-13 16:36:00 -06001007 *params = shader->Source ? strlen((char *) shader->Source) + 1 : 0;
Brian5b01c5e2006-12-19 18:02:03 -07001008 break;
1009 default:
1010 _mesa_error(ctx, GL_INVALID_ENUM, "glGetShaderiv(pname)");
1011 return;
1012 }
1013}
1014
1015
Brian Paulfd59f192008-05-18 16:04:55 -06001016static void
Brian5b01c5e2006-12-19 18:02:03 -07001017_mesa_get_program_info_log(GLcontext *ctx, GLuint program, GLsizei bufSize,
1018 GLsizei *length, GLchar *infoLog)
1019{
Brian65a18442006-12-19 18:46:56 -07001020 struct gl_shader_program *shProg
1021 = _mesa_lookup_shader_program(ctx, program);
1022 if (!shProg) {
Brian5b01c5e2006-12-19 18:02:03 -07001023 _mesa_error(ctx, GL_INVALID_VALUE, "glGetProgramInfoLog(program)");
1024 return;
1025 }
Brian Paule5c69642010-03-30 19:54:02 -06001026 _mesa_copy_string(infoLog, bufSize, length, shProg->InfoLog);
Brian5b01c5e2006-12-19 18:02:03 -07001027}
1028
1029
Brian Paulfd59f192008-05-18 16:04:55 -06001030static void
Brian5b01c5e2006-12-19 18:02:03 -07001031_mesa_get_shader_info_log(GLcontext *ctx, GLuint shader, GLsizei bufSize,
1032 GLsizei *length, GLchar *infoLog)
1033{
Brian65a18442006-12-19 18:46:56 -07001034 struct gl_shader *sh = _mesa_lookup_shader(ctx, shader);
1035 if (!sh) {
Brian5b01c5e2006-12-19 18:02:03 -07001036 _mesa_error(ctx, GL_INVALID_VALUE, "glGetShaderInfoLog(shader)");
1037 return;
1038 }
Brian Paule5c69642010-03-30 19:54:02 -06001039 _mesa_copy_string(infoLog, bufSize, length, sh->InfoLog);
Brian5b01c5e2006-12-19 18:02:03 -07001040}
1041
1042
1043/**
1044 * Called via ctx->Driver.GetShaderSource().
1045 */
Brian Paulfd59f192008-05-18 16:04:55 -06001046static void
Brian5b01c5e2006-12-19 18:02:03 -07001047_mesa_get_shader_source(GLcontext *ctx, GLuint shader, GLsizei maxLength,
1048 GLsizei *length, GLchar *sourceOut)
1049{
Brian Paul530df582008-07-03 16:21:11 -06001050 struct gl_shader *sh;
1051 sh = _mesa_lookup_shader_err(ctx, shader, "glGetShaderSource");
Brian65a18442006-12-19 18:46:56 -07001052 if (!sh) {
Brian5b01c5e2006-12-19 18:02:03 -07001053 return;
1054 }
Brian Paule5c69642010-03-30 19:54:02 -06001055 _mesa_copy_string(sourceOut, maxLength, length, sh->Source);
Brian5b01c5e2006-12-19 18:02:03 -07001056}
1057
1058
Brian5b01c5e2006-12-19 18:02:03 -07001059/**
1060 * Called via ctx->Driver.ShaderSource()
1061 */
Brian Paulfd59f192008-05-18 16:04:55 -06001062static void
Brian5b01c5e2006-12-19 18:02:03 -07001063_mesa_shader_source(GLcontext *ctx, GLuint shader, const GLchar *source)
Brian34ae99d2006-12-18 08:28:54 -07001064{
Brian Paul530df582008-07-03 16:21:11 -06001065 struct gl_shader *sh;
1066
1067 sh = _mesa_lookup_shader_err(ctx, shader, "glShaderSource");
1068 if (!sh)
Brian34ae99d2006-12-18 08:28:54 -07001069 return;
Brian34ae99d2006-12-18 08:28:54 -07001070
Brian34ae99d2006-12-18 08:28:54 -07001071 /* free old shader source string and install new one */
Brian65a18442006-12-19 18:46:56 -07001072 if (sh->Source) {
Kristian Høgsberg32f2fd12010-02-19 11:58:49 -05001073 free((void *) sh->Source);
Brian34ae99d2006-12-18 08:28:54 -07001074 }
Brian65a18442006-12-19 18:46:56 -07001075 sh->Source = source;
Brian9e4bae92006-12-20 09:27:42 -07001076 sh->CompileStatus = GL_FALSE;
Brian Paulf7783ba2009-08-04 15:35:48 -06001077#ifdef DEBUG
1078 sh->SourceChecksum = _mesa_str_checksum(sh->Source);
1079#endif
Brian34ae99d2006-12-18 08:28:54 -07001080}
1081
1082
Brian5b01c5e2006-12-19 18:02:03 -07001083/**
1084 * Called via ctx->Driver.CompileShader()
1085 */
Brian Paulfd59f192008-05-18 16:04:55 -06001086static void
Brian5b01c5e2006-12-19 18:02:03 -07001087_mesa_compile_shader(GLcontext *ctx, GLuint shaderObj)
Brian34ae99d2006-12-18 08:28:54 -07001088{
Brian Paul530df582008-07-03 16:21:11 -06001089 struct gl_shader *sh;
Brian34ae99d2006-12-18 08:28:54 -07001090
Brian Paul530df582008-07-03 16:21:11 -06001091 sh = _mesa_lookup_shader_err(ctx, shaderObj, "glCompileShader");
1092 if (!sh)
Brian34ae99d2006-12-18 08:28:54 -07001093 return;
Brian34ae99d2006-12-18 08:28:54 -07001094
Brian Paul65fc2ca2009-03-19 10:25:24 -06001095 /* set default pragma state for shader */
1096 sh->Pragmas = ctx->Shader.DefaultPragmas;
1097
Brian Paulcb136e02009-01-22 10:34:15 -07001098 /* this call will set the sh->CompileStatus field to indicate if
1099 * compilation was successful.
1100 */
Eric Anholt0a1b54d2010-06-21 11:29:15 -07001101 _mesa_glsl_compile_shader(ctx, sh);
Brian34ae99d2006-12-18 08:28:54 -07001102}
1103
1104
Brian5b01c5e2006-12-19 18:02:03 -07001105/**
1106 * Called via ctx->Driver.LinkProgram()
1107 */
Brian Paulfd59f192008-05-18 16:04:55 -06001108static void
Brian5b01c5e2006-12-19 18:02:03 -07001109_mesa_link_program(GLcontext *ctx, GLuint program)
Brian34ae99d2006-12-18 08:28:54 -07001110{
Brian65a18442006-12-19 18:46:56 -07001111 struct gl_shader_program *shProg;
Brian Paulfef6e362010-05-10 21:11:21 -06001112 struct gl_transform_feedback_object *obj =
1113 ctx->TransformFeedback.CurrentObject;
Brian34ae99d2006-12-18 08:28:54 -07001114
Brian Paul530df582008-07-03 16:21:11 -06001115 shProg = _mesa_lookup_shader_program_err(ctx, program, "glLinkProgram");
1116 if (!shProg)
Brian34ae99d2006-12-18 08:28:54 -07001117 return;
Brian34ae99d2006-12-18 08:28:54 -07001118
Brian Paulfef6e362010-05-10 21:11:21 -06001119 if (obj->Active && shProg == ctx->Shader.CurrentProgram) {
Brian Paul1a148662010-04-01 22:15:16 -06001120 _mesa_error(ctx, GL_INVALID_OPERATION,
1121 "glLinkProgram(transform feedback active");
1122 return;
1123 }
1124
Briandf43fb62008-05-06 23:08:51 -06001125 FLUSH_VERTICES(ctx, _NEW_PROGRAM);
1126
Eric Anholt0a1b54d2010-06-21 11:29:15 -07001127 _mesa_glsl_link_shader(ctx, shProg);
Brian Paulac3c8e32009-09-14 17:32:03 -06001128
1129 /* debug code */
1130 if (0) {
1131 GLuint i;
1132
Kristian Høgsberg298be2b2010-02-19 12:32:24 -05001133 printf("Link %u shaders in program %u: %s\n",
Brian Paulac3c8e32009-09-14 17:32:03 -06001134 shProg->NumShaders, shProg->Name,
1135 shProg->LinkStatus ? "Success" : "Failed");
1136
1137 for (i = 0; i < shProg->NumShaders; i++) {
Kristian Høgsberg298be2b2010-02-19 12:32:24 -05001138 printf(" shader %u, type 0x%x\n",
Brian Paulac3c8e32009-09-14 17:32:03 -06001139 shProg->Shaders[i]->Name,
1140 shProg->Shaders[i]->Type);
1141 }
1142 }
Brian34ae99d2006-12-18 08:28:54 -07001143}
1144
1145
1146/**
Brian Paul346250b2009-10-23 16:31:48 -06001147 * Print basic shader info (for debug).
1148 */
1149static void
1150print_shader_info(const struct gl_shader_program *shProg)
1151{
1152 GLuint i;
1153
Kristian Høgsberg298be2b2010-02-19 12:32:24 -05001154 printf("Mesa: glUseProgram(%u)\n", shProg->Name);
Brian Paul346250b2009-10-23 16:31:48 -06001155 for (i = 0; i < shProg->NumShaders; i++) {
1156 const char *s;
1157 switch (shProg->Shaders[i]->Type) {
1158 case GL_VERTEX_SHADER:
1159 s = "vertex";
1160 break;
1161 case GL_FRAGMENT_SHADER:
1162 s = "fragment";
1163 break;
1164 case GL_GEOMETRY_SHADER:
1165 s = "geometry";
1166 break;
1167 default:
1168 s = "";
1169 }
Kristian Høgsberg298be2b2010-02-19 12:32:24 -05001170 printf(" %s shader %u, checksum %u\n", s,
1171 shProg->Shaders[i]->Name,
1172 shProg->Shaders[i]->SourceChecksum);
Brian Paul346250b2009-10-23 16:31:48 -06001173 }
1174 if (shProg->VertexProgram)
Kristian Høgsberg298be2b2010-02-19 12:32:24 -05001175 printf(" vert prog %u\n", shProg->VertexProgram->Base.Id);
Brian Paul346250b2009-10-23 16:31:48 -06001176 if (shProg->FragmentProgram)
Kristian Høgsberg298be2b2010-02-19 12:32:24 -05001177 printf(" frag prog %u\n", shProg->FragmentProgram->Base.Id);
Brian Paul346250b2009-10-23 16:31:48 -06001178}
1179
1180
1181/**
Brian5b01c5e2006-12-19 18:02:03 -07001182 * Called via ctx->Driver.UseProgram()
Brian34ae99d2006-12-18 08:28:54 -07001183 */
Brian5b01c5e2006-12-19 18:02:03 -07001184void
1185_mesa_use_program(GLcontext *ctx, GLuint program)
Brian34ae99d2006-12-18 08:28:54 -07001186{
Brian3c008a02007-04-12 15:22:32 -06001187 struct gl_shader_program *shProg;
Brian Paulfef6e362010-05-10 21:11:21 -06001188 struct gl_transform_feedback_object *obj =
1189 ctx->TransformFeedback.CurrentObject;
Brian3c008a02007-04-12 15:22:32 -06001190
Brian Paulfef6e362010-05-10 21:11:21 -06001191 if (obj->Active) {
Brian Paul1a148662010-04-01 22:15:16 -06001192 _mesa_error(ctx, GL_INVALID_OPERATION,
1193 "glUseProgram(transform feedback active)");
1194 return;
1195 }
1196
Brian00d63aa2007-02-03 11:35:02 -07001197 if (ctx->Shader.CurrentProgram &&
1198 ctx->Shader.CurrentProgram->Name == program) {
1199 /* no-op */
1200 return;
1201 }
1202
Brian5b01c5e2006-12-19 18:02:03 -07001203 if (program) {
Brian Paul530df582008-07-03 16:21:11 -06001204 shProg = _mesa_lookup_shader_program_err(ctx, program, "glUseProgram");
Brian65a18442006-12-19 18:46:56 -07001205 if (!shProg) {
Brian Paul530df582008-07-03 16:21:11 -06001206 return;
1207 }
1208 if (!shProg->LinkStatus) {
Brian Paul621c9992009-02-18 13:28:12 -07001209 _mesa_error(ctx, GL_INVALID_OPERATION,
1210 "glUseProgram(program %u not linked)", program);
Brian5b01c5e2006-12-19 18:02:03 -07001211 return;
1212 }
Brian Paul4eda17d2009-03-13 09:11:42 -06001213
1214 /* debug code */
Brian Paul2ee7fd82009-10-15 15:25:52 -06001215 if (ctx->Shader.Flags & GLSL_USE_PROG) {
Brian Paul346250b2009-10-23 16:31:48 -06001216 print_shader_info(shProg);
Brian Paul4eda17d2009-03-13 09:11:42 -06001217 }
Brian5b01c5e2006-12-19 18:02:03 -07001218 }
1219 else {
Brian3c008a02007-04-12 15:22:32 -06001220 shProg = NULL;
1221 }
1222
Brian Paulb44304e2009-10-27 20:09:33 -06001223 if (ctx->Shader.CurrentProgram != shProg) {
1224 FLUSH_VERTICES(ctx, _NEW_PROGRAM | _NEW_PROGRAM_CONSTANTS);
1225 _mesa_reference_shader_program(ctx, &ctx->Shader.CurrentProgram, shProg);
1226 }
Brian5b01c5e2006-12-19 18:02:03 -07001227}
Brian34ae99d2006-12-18 08:28:54 -07001228
Brian5b01c5e2006-12-19 18:02:03 -07001229
Brian Paulade50832008-05-14 16:09:46 -06001230
1231/**
Brian Paul517401a2008-11-06 15:04:11 -07001232 * Update the vertex/fragment program's TexturesUsed array.
1233 *
1234 * This needs to be called after glUniform(set sampler var) is called.
1235 * A call to glUniform(samplerVar, value) causes a sampler to point to a
1236 * particular texture unit. We know the sampler's texture target
1237 * (1D/2D/3D/etc) from compile time but the sampler's texture unit is
1238 * set by glUniform() calls.
1239 *
1240 * So, scan the program->SamplerUnits[] and program->SamplerTargets[]
1241 * information to update the prog->TexturesUsed[] values.
1242 * Each value of TexturesUsed[unit] is one of zero, TEXTURE_1D_INDEX,
1243 * TEXTURE_2D_INDEX, TEXTURE_3D_INDEX, etc.
1244 * We'll use that info for state validation before rendering.
Brian Paulade50832008-05-14 16:09:46 -06001245 */
Brian Paul517401a2008-11-06 15:04:11 -07001246void
1247_mesa_update_shader_textures_used(struct gl_program *prog)
Brian Paulade50832008-05-14 16:09:46 -06001248{
1249 GLuint s;
1250
1251 memset(prog->TexturesUsed, 0, sizeof(prog->TexturesUsed));
1252
1253 for (s = 0; s < MAX_SAMPLERS; s++) {
1254 if (prog->SamplersUsed & (1 << s)) {
Brian Paulf05344f2009-08-26 10:58:06 -06001255 GLuint unit = prog->SamplerUnits[s];
1256 GLuint tgt = prog->SamplerTargets[s];
1257 assert(unit < MAX_TEXTURE_IMAGE_UNITS);
1258 assert(tgt < NUM_TEXTURE_TARGETS);
1259 prog->TexturesUsed[unit] |= (1 << tgt);
Brian Paulade50832008-05-14 16:09:46 -06001260 }
1261 }
1262}
1263
1264
1265/**
Brian Paulc90fca32009-08-25 17:42:47 -06001266 * Validate a program's samplers.
1267 * Specifically, check that there aren't two samplers of different types
1268 * pointing to the same texture unit.
1269 * \return GL_TRUE if valid, GL_FALSE if invalid
1270 */
1271static GLboolean
1272validate_samplers(GLcontext *ctx, const struct gl_program *prog, char *errMsg)
Brian34ae99d2006-12-18 08:28:54 -07001273{
Brian Paulc90fca32009-08-25 17:42:47 -06001274 static const char *targetName[] = {
1275 "TEXTURE_2D_ARRAY",
1276 "TEXTURE_1D_ARRAY",
1277 "TEXTURE_CUBE",
1278 "TEXTURE_3D",
1279 "TEXTURE_RECT",
1280 "TEXTURE_2D",
1281 "TEXTURE_1D",
1282 };
1283 GLint targetUsed[MAX_TEXTURE_IMAGE_UNITS];
1284 GLbitfield samplersUsed = prog->SamplersUsed;
1285 GLuint i;
Brian Paulbc985b52008-07-21 14:16:07 -06001286
Brian Paulc90fca32009-08-25 17:42:47 -06001287 assert(Elements(targetName) == NUM_TEXTURE_TARGETS);
1288
1289 if (samplersUsed == 0x0)
1290 return GL_TRUE;
1291
1292 for (i = 0; i < Elements(targetUsed); i++)
1293 targetUsed[i] = -1;
1294
1295 /* walk over bits which are set in 'samplers' */
1296 while (samplersUsed) {
1297 GLuint unit;
1298 gl_texture_index target;
1299 GLint sampler = _mesa_ffs(samplersUsed) - 1;
1300 assert(sampler >= 0);
1301 assert(sampler < MAX_TEXTURE_IMAGE_UNITS);
1302 unit = prog->SamplerUnits[sampler];
1303 target = prog->SamplerTargets[sampler];
1304 if (targetUsed[unit] != -1 && targetUsed[unit] != target) {
Brian Paul78a0c352010-02-19 12:56:49 -07001305 _mesa_snprintf(errMsg, 100,
Kristian Høgsberg298be2b2010-02-19 12:32:24 -05001306 "Texture unit %d is accessed both as %s and %s",
1307 unit, targetName[targetUsed[unit]], targetName[target]);
Brian Paulc90fca32009-08-25 17:42:47 -06001308 return GL_FALSE;
1309 }
1310 targetUsed[unit] = target;
1311 samplersUsed ^= (1 << sampler);
Brian34ae99d2006-12-18 08:28:54 -07001312 }
1313
Brian Paulc90fca32009-08-25 17:42:47 -06001314 return GL_TRUE;
1315}
1316
1317
1318/**
1319 * Do validation of the given shader program.
1320 * \param errMsg returns error message if validation fails.
1321 * \return GL_TRUE if valid, GL_FALSE if invalid (and set errMsg)
1322 */
1323GLboolean
1324_mesa_validate_shader_program(GLcontext *ctx,
1325 const struct gl_shader_program *shProg,
1326 char *errMsg)
1327{
1328 const struct gl_vertex_program *vp = shProg->VertexProgram;
1329 const struct gl_fragment_program *fp = shProg->FragmentProgram;
1330
Brian Paulbc985b52008-07-21 14:16:07 -06001331 if (!shProg->LinkStatus) {
Brian Paulc90fca32009-08-25 17:42:47 -06001332 return GL_FALSE;
Brian Paulbc985b52008-07-21 14:16:07 -06001333 }
1334
1335 /* From the GL spec, a program is invalid if any of these are true:
1336
Brian5b01c5e2006-12-19 18:02:03 -07001337 any two active samplers in the current program object are of
1338 different types, but refer to the same texture image unit,
1339
1340 any active sampler in the current program object refers to a texture
1341 image unit where fixed-function fragment processing accesses a
1342 texture target that does not match the sampler type, or
1343
1344 the sum of the number of active samplers in the program and the
1345 number of texture image units enabled for fixed-function fragment
1346 processing exceeds the combined limit on the total number of texture
1347 image units allowed.
1348 */
Brian Paulbc985b52008-07-21 14:16:07 -06001349
Brian Paulc90fca32009-08-25 17:42:47 -06001350
1351 /*
1352 * Check: any two active samplers in the current program object are of
1353 * different types, but refer to the same texture image unit,
1354 */
1355 if (vp && !validate_samplers(ctx, &vp->Base, errMsg)) {
1356 return GL_FALSE;
1357 }
1358 if (fp && !validate_samplers(ctx, &fp->Base, errMsg)) {
1359 return GL_FALSE;
1360 }
1361
1362 return GL_TRUE;
1363}
1364
1365
1366/**
1367 * Called via glValidateProgram()
1368 */
1369static void
1370_mesa_validate_program(GLcontext *ctx, GLuint program)
1371{
1372 struct gl_shader_program *shProg;
1373 char errMsg[100];
1374
1375 shProg = _mesa_lookup_shader_program_err(ctx, program, "glValidateProgram");
1376 if (!shProg) {
1377 return;
1378 }
1379
1380 shProg->Validated = _mesa_validate_shader_program(ctx, shProg, errMsg);
1381 if (!shProg->Validated) {
1382 /* update info log */
1383 if (shProg->InfoLog) {
Kristian Høgsberg32f2fd12010-02-19 11:58:49 -05001384 free(shProg->InfoLog);
Brian Paulc90fca32009-08-25 17:42:47 -06001385 }
1386 shProg->InfoLog = _mesa_strdup(errMsg);
1387 }
Brian34ae99d2006-12-18 08:28:54 -07001388}
Brian Paulfd59f192008-05-18 16:04:55 -06001389
1390
1391/**
1392 * Plug in Mesa's GLSL functions into the device driver function table.
1393 */
1394void
1395_mesa_init_glsl_driver_functions(struct dd_function_table *driver)
1396{
1397 driver->AttachShader = _mesa_attach_shader;
1398 driver->BindAttribLocation = _mesa_bind_attrib_location;
1399 driver->CompileShader = _mesa_compile_shader;
1400 driver->CreateProgram = _mesa_create_program;
1401 driver->CreateShader = _mesa_create_shader;
1402 driver->DeleteProgram2 = _mesa_delete_program2;
1403 driver->DeleteShader = _mesa_delete_shader;
1404 driver->DetachShader = _mesa_detach_shader;
1405 driver->GetActiveAttrib = _mesa_get_active_attrib;
Brian Paulfd59f192008-05-18 16:04:55 -06001406 driver->GetAttachedShaders = _mesa_get_attached_shaders;
1407 driver->GetAttribLocation = _mesa_get_attrib_location;
1408 driver->GetHandle = _mesa_get_handle;
1409 driver->GetProgramiv = _mesa_get_programiv;
1410 driver->GetProgramInfoLog = _mesa_get_program_info_log;
1411 driver->GetShaderiv = _mesa_get_shaderiv;
1412 driver->GetShaderInfoLog = _mesa_get_shader_info_log;
1413 driver->GetShaderSource = _mesa_get_shader_source;
Brian Paulfd59f192008-05-18 16:04:55 -06001414 driver->IsProgram = _mesa_is_program;
1415 driver->IsShader = _mesa_is_shader;
1416 driver->LinkProgram = _mesa_link_program;
1417 driver->ShaderSource = _mesa_shader_source;
Brian Paulfd59f192008-05-18 16:04:55 -06001418 driver->UseProgram = _mesa_use_program;
1419 driver->ValidateProgram = _mesa_validate_program;
Brian Paul69861ae2010-05-26 22:24:58 -06001420
1421 _mesa_init_uniform_functions(driver);
Brian Paulfd59f192008-05-18 16:04:55 -06001422}