blob: 40b8286a13f2b6d361980d8696774284c924255d [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"
Eric Anholt16b68b12010-06-30 11:05:43 -070047#include "talloc.h"
Brian34ae99d2006-12-18 08:28:54 -070048
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);
Eric Anholt16b68b12010-06-30 11:05:43 -0700256 shader = talloc_zero(NULL, struct gl_shader);
Brianf2923612006-12-20 09:56:44 -0700257 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);
Brian Paul3d500f02008-07-24 14:56:54 -0600271 _mesa_reference_program(ctx, &sh->Program, NULL);
Eric Anholt16b68b12010-06-30 11:05:43 -0700272 talloc_free(sh);
Brianf2923612006-12-20 09:56:44 -0700273}
274
275
276/**
Brian3c008a02007-04-12 15:22:32 -0600277 * Set ptr to point to sh.
278 * If ptr is pointing to another shader, decrement its refcount (and delete
279 * if refcount hits zero).
280 * Then set ptr to point to sh, incrementing its refcount.
281 */
282/* XXX this could be static */
283void
284_mesa_reference_shader(GLcontext *ctx, struct gl_shader **ptr,
285 struct gl_shader *sh)
286{
287 assert(ptr);
288 if (*ptr == sh) {
289 /* no-op */
290 return;
291 }
292 if (*ptr) {
293 /* Unreference the old shader */
294 GLboolean deleteFlag = GL_FALSE;
295 struct gl_shader *old = *ptr;
296
297 ASSERT(old->RefCount > 0);
298 old->RefCount--;
Brian99193e42007-04-12 15:45:02 -0600299 /*printf("SHADER DECR %p (%d) to %d\n",
300 (void*) old, old->Name, old->RefCount);*/
Brian3c008a02007-04-12 15:22:32 -0600301 deleteFlag = (old->RefCount == 0);
302
303 if (deleteFlag) {
304 _mesa_HashRemove(ctx->Shared->ShaderObjects, old->Name);
305 _mesa_free_shader(ctx, old);
306 }
307
308 *ptr = NULL;
309 }
310 assert(!*ptr);
311
312 if (sh) {
313 /* reference new */
314 sh->RefCount++;
Brian99193e42007-04-12 15:45:02 -0600315 /*printf("SHADER INCR %p (%d) to %d\n",
316 (void*) sh, sh->Name, sh->RefCount);*/
Brian3c008a02007-04-12 15:22:32 -0600317 *ptr = sh;
318 }
319}
320
321
322/**
Brianf2923612006-12-20 09:56:44 -0700323 * Lookup a GLSL shader object.
324 */
325struct gl_shader *
326_mesa_lookup_shader(GLcontext *ctx, GLuint name)
327{
328 if (name) {
329 struct gl_shader *sh = (struct gl_shader *)
330 _mesa_HashLookup(ctx->Shared->ShaderObjects, name);
331 /* Note that both gl_shader and gl_shader_program objects are kept
332 * in the same hash table. Check the object's type to be sure it's
333 * what we're expecting.
334 */
Brianf3e8c322007-04-18 14:53:23 -0600335 if (sh && sh->Type == GL_SHADER_PROGRAM_MESA) {
Brianf2923612006-12-20 09:56:44 -0700336 return NULL;
337 }
338 return sh;
339 }
340 return NULL;
341}
342
343
Brianfa4d0362007-02-26 18:33:50 -0700344/**
Brian Paul530df582008-07-03 16:21:11 -0600345 * As above, but record an error if shader is not found.
346 */
347static struct gl_shader *
348_mesa_lookup_shader_err(GLcontext *ctx, GLuint name, const char *caller)
349{
350 if (!name) {
351 _mesa_error(ctx, GL_INVALID_VALUE, caller);
352 return NULL;
353 }
354 else {
355 struct gl_shader *sh = (struct gl_shader *)
356 _mesa_HashLookup(ctx->Shared->ShaderObjects, name);
357 if (!sh) {
358 _mesa_error(ctx, GL_INVALID_VALUE, caller);
359 return NULL;
360 }
361 if (sh->Type == GL_SHADER_PROGRAM_MESA) {
362 _mesa_error(ctx, GL_INVALID_OPERATION, caller);
363 return NULL;
364 }
365 return sh;
366 }
367}
368
369
Brian Paule01a03d2009-02-06 10:21:36 -0700370/**
371 * Return mask of GLSL_x flags by examining the MESA_GLSL env var.
372 */
373static GLbitfield
374get_shader_flags(void)
375{
376 GLbitfield flags = 0x0;
377 const char *env = _mesa_getenv("MESA_GLSL");
378
379 if (env) {
Kenneth Graunke0aecdb62010-02-18 23:50:51 -0800380 if (strstr(env, "dump"))
Brian Paule01a03d2009-02-06 10:21:36 -0700381 flags |= GLSL_DUMP;
Kenneth Graunke0aecdb62010-02-18 23:50:51 -0800382 if (strstr(env, "log"))
Brian Paule01a03d2009-02-06 10:21:36 -0700383 flags |= GLSL_LOG;
Kenneth Graunke0aecdb62010-02-18 23:50:51 -0800384 if (strstr(env, "nopvert"))
Brian Paulcb0de062009-09-29 10:22:32 -0600385 flags |= GLSL_NOP_VERT;
Kenneth Graunke0aecdb62010-02-18 23:50:51 -0800386 if (strstr(env, "nopfrag"))
Brian Paulcb0de062009-09-29 10:22:32 -0600387 flags |= GLSL_NOP_FRAG;
Kenneth Graunke0aecdb62010-02-18 23:50:51 -0800388 if (strstr(env, "nopt"))
Brian Paule01a03d2009-02-06 10:21:36 -0700389 flags |= GLSL_NO_OPT;
Kenneth Graunke0aecdb62010-02-18 23:50:51 -0800390 else if (strstr(env, "opt"))
Brian Paule01a03d2009-02-06 10:21:36 -0700391 flags |= GLSL_OPT;
Kenneth Graunke0aecdb62010-02-18 23:50:51 -0800392 if (strstr(env, "uniform"))
Brian Paule01a03d2009-02-06 10:21:36 -0700393 flags |= GLSL_UNIFORMS;
Kenneth Graunke0aecdb62010-02-18 23:50:51 -0800394 if (strstr(env, "useprog"))
Brian Paul2ee7fd82009-10-15 15:25:52 -0600395 flags |= GLSL_USE_PROG;
Brian Paule01a03d2009-02-06 10:21:36 -0700396 }
397
398 return flags;
399}
400
Brian Paul530df582008-07-03 16:21:11 -0600401
402/**
Brian Paule5c69642010-03-30 19:54:02 -0600403 * Find the length of the longest transform feedback varying name
404 * which was specified with glTransformFeedbackVaryings().
405 */
406static GLint
407longest_feedback_varying_name(const struct gl_shader_program *shProg)
408{
409 GLuint i;
410 GLint max = 0;
411 for (i = 0; i < shProg->TransformFeedback.NumVarying; i++) {
412 GLint len = strlen(shProg->TransformFeedback.VaryingNames[i]);
413 if (len > max)
414 max = len;
415 }
416 return max;
417}
418
419
420
421/**
Brianfa4d0362007-02-26 18:33:50 -0700422 * Initialize context's shader state.
423 */
Brianf2923612006-12-20 09:56:44 -0700424void
425_mesa_init_shader_state(GLcontext * ctx)
426{
Brianfa4d0362007-02-26 18:33:50 -0700427 /* Device drivers may override these to control what kind of instructions
428 * are generated by the GLSL compiler.
429 */
430 ctx->Shader.EmitHighLevelInstructions = GL_TRUE;
Brian Paul4031ea12009-06-17 11:57:39 -0600431 ctx->Shader.EmitContReturn = GL_TRUE;
Brian Paulc5c38352009-02-16 11:50:05 -0700432 ctx->Shader.EmitCondCodes = GL_FALSE;
Brianfa4d0362007-02-26 18:33:50 -0700433 ctx->Shader.EmitComments = GL_FALSE;
Brian Paule01a03d2009-02-06 10:21:36 -0700434 ctx->Shader.Flags = get_shader_flags();
Brian Paul65fc2ca2009-03-19 10:25:24 -0600435
436 /* Default pragma settings */
437 ctx->Shader.DefaultPragmas.IgnoreOptimize = GL_FALSE;
438 ctx->Shader.DefaultPragmas.IgnoreDebug = GL_FALSE;
439 ctx->Shader.DefaultPragmas.Optimize = GL_TRUE;
440 ctx->Shader.DefaultPragmas.Debug = GL_FALSE;
Brianf2923612006-12-20 09:56:44 -0700441}
442
443
Brian5b01c5e2006-12-19 18:02:03 -0700444/**
Brian935f93f2007-03-24 16:20:02 -0600445 * Free the per-context shader-related state.
446 */
447void
448_mesa_free_shader_state(GLcontext *ctx)
449{
Brian3c008a02007-04-12 15:22:32 -0600450 _mesa_reference_shader_program(ctx, &ctx->Shader.CurrentProgram, NULL);
Brian935f93f2007-03-24 16:20:02 -0600451}
452
453
454/**
Brian5b01c5e2006-12-19 18:02:03 -0700455 * Copy string from <src> to <dst>, up to maxLength characters, returning
456 * length of <dst> in <length>.
457 * \param src the strings source
458 * \param maxLength max chars to copy
459 * \param length returns number of chars copied
460 * \param dst the string destination
461 */
Brian Paule5c69642010-03-30 19:54:02 -0600462void
463_mesa_copy_string(GLchar *dst, GLsizei maxLength,
464 GLsizei *length, const GLchar *src)
Brian5b01c5e2006-12-19 18:02:03 -0700465{
466 GLsizei len;
467 for (len = 0; len < maxLength - 1 && src && src[len]; len++)
468 dst[len] = src[len];
469 if (maxLength > 0)
470 dst[len] = 0;
471 if (length)
472 *length = len;
473}
474
475
Brian Paul7acb7c12008-07-03 13:49:48 -0600476static GLboolean
477_mesa_is_program(GLcontext *ctx, GLuint name)
478{
479 struct gl_shader_program *shProg = _mesa_lookup_shader_program(ctx, name);
480 return shProg ? GL_TRUE : GL_FALSE;
481}
482
483
484static GLboolean
485_mesa_is_shader(GLcontext *ctx, GLuint name)
486{
487 struct gl_shader *shader = _mesa_lookup_shader(ctx, name);
488 return shader ? GL_TRUE : GL_FALSE;
489}
490
491
Brian5b01c5e2006-12-19 18:02:03 -0700492/**
493 * Called via ctx->Driver.AttachShader()
494 */
Brian Paulfd59f192008-05-18 16:04:55 -0600495static void
Brian5b01c5e2006-12-19 18:02:03 -0700496_mesa_attach_shader(GLcontext *ctx, GLuint program, GLuint shader)
497{
Brian Paul530df582008-07-03 16:21:11 -0600498 struct gl_shader_program *shProg;
499 struct gl_shader *sh;
500 GLuint i, n;
Brian5b01c5e2006-12-19 18:02:03 -0700501
Brian Paul530df582008-07-03 16:21:11 -0600502 shProg = _mesa_lookup_shader_program_err(ctx, program, "glAttachShader");
503 if (!shProg)
Brian5b01c5e2006-12-19 18:02:03 -0700504 return;
Brian5b01c5e2006-12-19 18:02:03 -0700505
Brian Paul530df582008-07-03 16:21:11 -0600506 sh = _mesa_lookup_shader_err(ctx, shader, "glAttachShader");
Brian Paul7acb7c12008-07-03 13:49:48 -0600507 if (!sh) {
Brian Paul7acb7c12008-07-03 13:49:48 -0600508 return;
509 }
510
Brian237b9852007-08-07 21:48:31 +0100511 n = shProg->NumShaders;
Brian5b01c5e2006-12-19 18:02:03 -0700512 for (i = 0; i < n; i++) {
Brian65a18442006-12-19 18:46:56 -0700513 if (shProg->Shaders[i] == sh) {
Ian Romanickd806d452008-09-29 12:18:06 -0700514 /* The shader is already attched to this program. The
515 * GL_ARB_shader_objects spec says:
516 *
517 * "The error INVALID_OPERATION is generated by AttachObjectARB
518 * if <obj> is already attached to <containerObj>."
519 */
520 _mesa_error(ctx, GL_INVALID_OPERATION, "glAttachShader");
Brian5b01c5e2006-12-19 18:02:03 -0700521 return;
Brian34ae99d2006-12-18 08:28:54 -0700522 }
523 }
Brian5b01c5e2006-12-19 18:02:03 -0700524
525 /* grow list */
Brian65a18442006-12-19 18:46:56 -0700526 shProg->Shaders = (struct gl_shader **)
527 _mesa_realloc(shProg->Shaders,
528 n * sizeof(struct gl_shader *),
529 (n + 1) * sizeof(struct gl_shader *));
530 if (!shProg->Shaders) {
Brian5b01c5e2006-12-19 18:02:03 -0700531 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glAttachShader");
532 return;
533 }
534
535 /* append */
Brian3c008a02007-04-12 15:22:32 -0600536 shProg->Shaders[n] = NULL; /* since realloc() didn't zero the new space */
537 _mesa_reference_shader(ctx, &shProg->Shaders[n], sh);
Brian65a18442006-12-19 18:46:56 -0700538 shProg->NumShaders++;
Brian5b01c5e2006-12-19 18:02:03 -0700539}
540
541
Brian Paulfd59f192008-05-18 16:04:55 -0600542static GLint
Brian Paul896c0cc2008-05-16 15:47:55 -0600543_mesa_get_attrib_location(GLcontext *ctx, GLuint program,
544 const GLchar *name)
545{
546 struct gl_shader_program *shProg
Brian Paul530df582008-07-03 16:21:11 -0600547 = _mesa_lookup_shader_program_err(ctx, program, "glGetAttribLocation");
Brian Paul896c0cc2008-05-16 15:47:55 -0600548
549 if (!shProg) {
Brian Paul896c0cc2008-05-16 15:47:55 -0600550 return -1;
551 }
552
553 if (!shProg->LinkStatus) {
554 _mesa_error(ctx, GL_INVALID_OPERATION,
555 "glGetAttribLocation(program not linked)");
556 return -1;
557 }
558
559 if (!name)
560 return -1;
561
Brian Paul27341a92008-09-16 16:28:36 -0600562 if (shProg->VertexProgram) {
563 const struct gl_program_parameter_list *attribs =
564 shProg->VertexProgram->Base.Attributes;
565 if (attribs) {
566 GLint i = _mesa_lookup_parameter_index(attribs, -1, name);
567 if (i >= 0) {
568 return attribs->Parameters[i].StateIndexes[0];
569 }
Brian Paul896c0cc2008-05-16 15:47:55 -0600570 }
571 }
572 return -1;
573}
574
575
Brian Paulfd59f192008-05-18 16:04:55 -0600576static void
Brian5b01c5e2006-12-19 18:02:03 -0700577_mesa_bind_attrib_location(GLcontext *ctx, GLuint program, GLuint index,
578 const GLchar *name)
579{
Brian Paul530df582008-07-03 16:21:11 -0600580 struct gl_shader_program *shProg;
Brianb7978af2007-01-09 19:17:17 -0700581 const GLint size = -1; /* unknown size */
Brian Paul6bc87492008-07-25 08:34:54 -0600582 GLint i, oldIndex;
Brian Paul6f1abb92008-07-29 17:27:22 -0600583 GLenum datatype = GL_FLOAT_VEC4;
Brian5b01c5e2006-12-19 18:02:03 -0700584
Brian Paul530df582008-07-03 16:21:11 -0600585 shProg = _mesa_lookup_shader_program_err(ctx, program,
586 "glBindAttribLocation");
Brian65a18442006-12-19 18:46:56 -0700587 if (!shProg) {
Brian5b01c5e2006-12-19 18:02:03 -0700588 return;
589 }
590
Brian9e4bae92006-12-20 09:27:42 -0700591 if (!name)
592 return;
593
594 if (strncmp(name, "gl_", 3) == 0) {
595 _mesa_error(ctx, GL_INVALID_OPERATION,
596 "glBindAttribLocation(illegal name)");
597 return;
598 }
599
Brian Paul7acb7c12008-07-03 13:49:48 -0600600 if (index >= ctx->Const.VertexProgram.MaxAttribs) {
601 _mesa_error(ctx, GL_INVALID_VALUE, "glBindAttribLocation(index)");
602 return;
603 }
604
Brian Paul6bc87492008-07-25 08:34:54 -0600605 if (shProg->LinkStatus) {
606 /* get current index/location for the attribute */
607 oldIndex = _mesa_get_attrib_location(ctx, program, name);
608 }
609 else {
610 oldIndex = -1;
611 }
612
Brian3209c3e2007-01-09 17:49:24 -0700613 /* this will replace the current value if it's already in the list */
Brian Paulffbc66b2008-07-21 13:58:50 -0600614 i = _mesa_add_attribute(shProg->Attributes, name, size, datatype, index);
Brian3209c3e2007-01-09 17:49:24 -0700615 if (i < 0) {
616 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBindAttribLocation");
Brian Paul6f1abb92008-07-29 17:27:22 -0600617 return;
Brian3209c3e2007-01-09 17:49:24 -0700618 }
619
Brian Paul27341a92008-09-16 16:28:36 -0600620 /*
621 * Note that this attribute binding won't go into effect until
622 * glLinkProgram is called again.
623 */
Brian34ae99d2006-12-18 08:28:54 -0700624}
625
626
Brian Paulfd59f192008-05-18 16:04:55 -0600627static GLuint
Brian5b01c5e2006-12-19 18:02:03 -0700628_mesa_create_shader(GLcontext *ctx, GLenum type)
629{
Brian65a18442006-12-19 18:46:56 -0700630 struct gl_shader *sh;
Brian5b01c5e2006-12-19 18:02:03 -0700631 GLuint name;
632
633 name = _mesa_HashFindFreeKeyBlock(ctx->Shared->ShaderObjects, 1);
634
635 switch (type) {
Brian65a18442006-12-19 18:46:56 -0700636 case GL_FRAGMENT_SHADER:
637 case GL_VERTEX_SHADER:
638 sh = _mesa_new_shader(ctx, name, type);
Brian5b01c5e2006-12-19 18:02:03 -0700639 break;
640 default:
641 _mesa_error(ctx, GL_INVALID_ENUM, "CreateShader(type)");
642 return 0;
643 }
644
Brian65a18442006-12-19 18:46:56 -0700645 _mesa_HashInsert(ctx->Shared->ShaderObjects, name, sh);
Brian5b01c5e2006-12-19 18:02:03 -0700646
647 return name;
648}
649
650
Brian Paulfd59f192008-05-18 16:04:55 -0600651static GLuint
Brian5b01c5e2006-12-19 18:02:03 -0700652_mesa_create_program(GLcontext *ctx)
653{
654 GLuint name;
Brian65a18442006-12-19 18:46:56 -0700655 struct gl_shader_program *shProg;
Brian5b01c5e2006-12-19 18:02:03 -0700656
Xiang, Haihaoaef47c42008-03-31 16:27:47 +0800657 name = _mesa_HashFindFreeKeyBlock(ctx->Shared->ShaderObjects, 1);
Brian65a18442006-12-19 18:46:56 -0700658 shProg = _mesa_new_shader_program(ctx, name);
Brian5b01c5e2006-12-19 18:02:03 -0700659
Xiang, Haihaoaef47c42008-03-31 16:27:47 +0800660 _mesa_HashInsert(ctx->Shared->ShaderObjects, name, shProg);
Brian5b01c5e2006-12-19 18:02:03 -0700661
Brian3c008a02007-04-12 15:22:32 -0600662 assert(shProg->RefCount == 1);
663
Brian5b01c5e2006-12-19 18:02:03 -0700664 return name;
665}
666
667
Brian3c008a02007-04-12 15:22:32 -0600668/**
669 * Named w/ "2" to indicate OpenGL 2.x vs GL_ARB_fragment_programs's
670 * DeleteProgramARB.
671 */
Brian Paulfd59f192008-05-18 16:04:55 -0600672static void
Brian5b01c5e2006-12-19 18:02:03 -0700673_mesa_delete_program2(GLcontext *ctx, GLuint name)
674{
Brian3c008a02007-04-12 15:22:32 -0600675 /*
676 * NOTE: deleting shaders/programs works a bit differently than
677 * texture objects (and buffer objects, etc). Shader/program
678 * handles/IDs exist in the hash table until the object is really
679 * deleted (refcount==0). With texture objects, the handle/ID is
680 * removed from the hash table in glDeleteTextures() while the tex
681 * object itself might linger until its refcount goes to zero.
682 */
Brian65a18442006-12-19 18:46:56 -0700683 struct gl_shader_program *shProg;
Brian5b01c5e2006-12-19 18:02:03 -0700684
Brian Paul530df582008-07-03 16:21:11 -0600685 shProg = _mesa_lookup_shader_program_err(ctx, name, "glDeleteProgram");
686 if (!shProg)
Brian5b01c5e2006-12-19 18:02:03 -0700687 return;
Brian5b01c5e2006-12-19 18:02:03 -0700688
Brian9e4bae92006-12-20 09:27:42 -0700689 shProg->DeletePending = GL_TRUE;
690
Brian3c008a02007-04-12 15:22:32 -0600691 /* effectively, decr shProg's refcount */
692 _mesa_reference_shader_program(ctx, &shProg, NULL);
Brian5b01c5e2006-12-19 18:02:03 -0700693}
694
695
Brian Paulfd59f192008-05-18 16:04:55 -0600696static void
Brian5b01c5e2006-12-19 18:02:03 -0700697_mesa_delete_shader(GLcontext *ctx, GLuint shader)
698{
Brian Paul530df582008-07-03 16:21:11 -0600699 struct gl_shader *sh;
700
701 sh = _mesa_lookup_shader_err(ctx, shader, "glDeleteShader");
702 if (!sh)
Brian9e4bae92006-12-20 09:27:42 -0700703 return;
Brian5b01c5e2006-12-19 18:02:03 -0700704
Brian9e4bae92006-12-20 09:27:42 -0700705 sh->DeletePending = GL_TRUE;
Brian3c008a02007-04-12 15:22:32 -0600706
707 /* effectively, decr sh's refcount */
708 _mesa_reference_shader(ctx, &sh, NULL);
Brian5b01c5e2006-12-19 18:02:03 -0700709}
710
711
Brian Paulfd59f192008-05-18 16:04:55 -0600712static void
Brian5b01c5e2006-12-19 18:02:03 -0700713_mesa_detach_shader(GLcontext *ctx, GLuint program, GLuint shader)
714{
Brian Paul530df582008-07-03 16:21:11 -0600715 struct gl_shader_program *shProg;
Brian237b9852007-08-07 21:48:31 +0100716 GLuint n;
Brian5b01c5e2006-12-19 18:02:03 -0700717 GLuint i, j;
718
Brian Paul530df582008-07-03 16:21:11 -0600719 shProg = _mesa_lookup_shader_program_err(ctx, program, "glDetachShader");
720 if (!shProg)
Brian5b01c5e2006-12-19 18:02:03 -0700721 return;
Brian5b01c5e2006-12-19 18:02:03 -0700722
Brian237b9852007-08-07 21:48:31 +0100723 n = shProg->NumShaders;
724
Brian5b01c5e2006-12-19 18:02:03 -0700725 for (i = 0; i < n; i++) {
Brian65a18442006-12-19 18:46:56 -0700726 if (shProg->Shaders[i]->Name == shader) {
Brian5b01c5e2006-12-19 18:02:03 -0700727 /* found it */
Brian3c008a02007-04-12 15:22:32 -0600728 struct gl_shader **newList;
Brian9e4bae92006-12-20 09:27:42 -0700729
Brian Paul530df582008-07-03 16:21:11 -0600730 /* release */
Brian3c008a02007-04-12 15:22:32 -0600731 _mesa_reference_shader(ctx, &shProg->Shaders[i], NULL);
Brian9e4bae92006-12-20 09:27:42 -0700732
Brian5b01c5e2006-12-19 18:02:03 -0700733 /* alloc new, smaller array */
Brian65a18442006-12-19 18:46:56 -0700734 newList = (struct gl_shader **)
Kristian Høgsberg32f2fd12010-02-19 11:58:49 -0500735 malloc((n - 1) * sizeof(struct gl_shader *));
Brian5b01c5e2006-12-19 18:02:03 -0700736 if (!newList) {
737 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glDetachShader");
738 return;
739 }
740 for (j = 0; j < i; j++) {
Brian65a18442006-12-19 18:46:56 -0700741 newList[j] = shProg->Shaders[j];
Brian5b01c5e2006-12-19 18:02:03 -0700742 }
743 while (++i < n)
Brian65a18442006-12-19 18:46:56 -0700744 newList[j++] = shProg->Shaders[i];
Kristian Høgsberg32f2fd12010-02-19 11:58:49 -0500745 free(shProg->Shaders);
Brian5b01c5e2006-12-19 18:02:03 -0700746
Brian65a18442006-12-19 18:46:56 -0700747 shProg->Shaders = newList;
Brianbac15c82007-04-18 14:55:18 -0600748 shProg->NumShaders = n - 1;
Brianaaa57412007-04-18 15:22:43 -0600749
750#ifdef DEBUG
751 /* sanity check */
752 {
753 for (j = 0; j < shProg->NumShaders; j++) {
754 assert(shProg->Shaders[j]->Type == GL_VERTEX_SHADER ||
755 shProg->Shaders[j]->Type == GL_FRAGMENT_SHADER);
756 assert(shProg->Shaders[j]->RefCount > 0);
757 }
758 }
759#endif
760
Brian5b01c5e2006-12-19 18:02:03 -0700761 return;
762 }
763 }
764
765 /* not found */
Brian Paul530df582008-07-03 16:21:11 -0600766 {
767 GLenum err;
768 if (_mesa_is_shader(ctx, shader))
769 err = GL_INVALID_OPERATION;
770 else if (_mesa_is_program(ctx, shader))
771 err = GL_INVALID_OPERATION;
772 else
773 err = GL_INVALID_VALUE;
774 _mesa_error(ctx, err, "glDetachProgram(shader)");
775 return;
776 }
Brian5b01c5e2006-12-19 18:02:03 -0700777}
778
779
Brian Paul1a148662010-04-01 22:15:16 -0600780/**
781 * Return the size of the given GLSL datatype, in floats (components).
782 */
783GLint
784_mesa_sizeof_glsl_type(GLenum type)
Brian Paulffbc66b2008-07-21 13:58:50 -0600785{
786 switch (type) {
787 case GL_FLOAT:
788 case GL_INT:
789 case GL_BOOL:
Brian Paul8c51e002008-08-11 15:09:47 -0600790 case GL_SAMPLER_1D:
791 case GL_SAMPLER_2D:
792 case GL_SAMPLER_3D:
793 case GL_SAMPLER_CUBE:
794 case GL_SAMPLER_1D_SHADOW:
795 case GL_SAMPLER_2D_SHADOW:
796 case GL_SAMPLER_2D_RECT_ARB:
797 case GL_SAMPLER_2D_RECT_SHADOW_ARB:
Brian Paulac498f22010-02-25 19:05:11 -0700798 case GL_SAMPLER_1D_ARRAY_EXT:
799 case GL_SAMPLER_2D_ARRAY_EXT:
Brian Paul8c51e002008-08-11 15:09:47 -0600800 case GL_SAMPLER_1D_ARRAY_SHADOW_EXT:
801 case GL_SAMPLER_2D_ARRAY_SHADOW_EXT:
802 case GL_SAMPLER_CUBE_SHADOW_EXT:
Brian Paulffbc66b2008-07-21 13:58:50 -0600803 return 1;
804 case GL_FLOAT_VEC2:
805 case GL_INT_VEC2:
Brian Paul91f841a2010-05-25 18:39:47 -0600806 case GL_UNSIGNED_INT_VEC2:
Brian Paulffbc66b2008-07-21 13:58:50 -0600807 case GL_BOOL_VEC2:
808 return 2;
809 case GL_FLOAT_VEC3:
810 case GL_INT_VEC3:
Brian Paul91f841a2010-05-25 18:39:47 -0600811 case GL_UNSIGNED_INT_VEC3:
Brian Paulffbc66b2008-07-21 13:58:50 -0600812 case GL_BOOL_VEC3:
813 return 3;
814 case GL_FLOAT_VEC4:
815 case GL_INT_VEC4:
Brian Paul91f841a2010-05-25 18:39:47 -0600816 case GL_UNSIGNED_INT_VEC4:
Brian Paulffbc66b2008-07-21 13:58:50 -0600817 case GL_BOOL_VEC4:
818 return 4;
819 case GL_FLOAT_MAT2:
820 case GL_FLOAT_MAT2x3:
821 case GL_FLOAT_MAT2x4:
822 return 8; /* two float[4] vectors */
823 case GL_FLOAT_MAT3:
824 case GL_FLOAT_MAT3x2:
825 case GL_FLOAT_MAT3x4:
826 return 12; /* three float[4] vectors */
827 case GL_FLOAT_MAT4:
828 case GL_FLOAT_MAT4x2:
829 case GL_FLOAT_MAT4x3:
830 return 16; /* four float[4] vectors */
831 default:
Brian Paul1a148662010-04-01 22:15:16 -0600832 _mesa_problem(NULL, "Invalid type in _mesa_sizeof_glsl_type()");
Brian Paulffbc66b2008-07-21 13:58:50 -0600833 return 1;
834 }
835}
836
837
Brian Paulfd59f192008-05-18 16:04:55 -0600838static void
Brian5b01c5e2006-12-19 18:02:03 -0700839_mesa_get_active_attrib(GLcontext *ctx, GLuint program, GLuint index,
840 GLsizei maxLength, GLsizei *length, GLint *size,
841 GLenum *type, GLchar *nameOut)
842{
Brian Paul27341a92008-09-16 16:28:36 -0600843 const struct gl_program_parameter_list *attribs = NULL;
Brian Paul530df582008-07-03 16:21:11 -0600844 struct gl_shader_program *shProg;
Brian5b01c5e2006-12-19 18:02:03 -0700845
Brian Paul530df582008-07-03 16:21:11 -0600846 shProg = _mesa_lookup_shader_program_err(ctx, program, "glGetActiveAttrib");
847 if (!shProg)
Brian5b01c5e2006-12-19 18:02:03 -0700848 return;
Brian5b01c5e2006-12-19 18:02:03 -0700849
Brian Paul27341a92008-09-16 16:28:36 -0600850 if (shProg->VertexProgram)
851 attribs = shProg->VertexProgram->Base.Attributes;
852
853 if (!attribs || index >= attribs->NumParameters) {
Brianaaa57412007-04-18 15:22:43 -0600854 _mesa_error(ctx, GL_INVALID_VALUE, "glGetActiveAttrib(index)");
Brian5b01c5e2006-12-19 18:02:03 -0700855 return;
856 }
857
Brian Paule5c69642010-03-30 19:54:02 -0600858 _mesa_copy_string(nameOut, maxLength, length,
859 attribs->Parameters[index].Name);
Brian Paul27341a92008-09-16 16:28:36 -0600860
Brian5b01c5e2006-12-19 18:02:03 -0700861 if (size)
Brian Paul27341a92008-09-16 16:28:36 -0600862 *size = attribs->Parameters[index].Size
Brian Paul1a148662010-04-01 22:15:16 -0600863 / _mesa_sizeof_glsl_type(attribs->Parameters[index].DataType);
Brian Paul27341a92008-09-16 16:28:36 -0600864
Brian Paulade50832008-05-14 16:09:46 -0600865 if (type)
Brian Paul27341a92008-09-16 16:28:36 -0600866 *type = attribs->Parameters[index].DataType;
Brian5b01c5e2006-12-19 18:02:03 -0700867}
868
869
Brian5b01c5e2006-12-19 18:02:03 -0700870/**
871 * Called via ctx->Driver.GetAttachedShaders().
872 */
Brian Paulfd59f192008-05-18 16:04:55 -0600873static void
Brian5b01c5e2006-12-19 18:02:03 -0700874_mesa_get_attached_shaders(GLcontext *ctx, GLuint program, GLsizei maxCount,
875 GLsizei *count, GLuint *obj)
876{
Brian Paul530df582008-07-03 16:21:11 -0600877 struct gl_shader_program *shProg =
878 _mesa_lookup_shader_program_err(ctx, program, "glGetAttachedShaders");
Brian65a18442006-12-19 18:46:56 -0700879 if (shProg) {
Brian Paul530df582008-07-03 16:21:11 -0600880 GLuint i;
881 for (i = 0; i < (GLuint) maxCount && i < shProg->NumShaders; i++) {
Brian65a18442006-12-19 18:46:56 -0700882 obj[i] = shProg->Shaders[i]->Name;
Brian5b01c5e2006-12-19 18:02:03 -0700883 }
884 if (count)
885 *count = i;
886 }
Brian5b01c5e2006-12-19 18:02:03 -0700887}
888
889
Brian Pauleb88c022010-05-26 22:40:38 -0600890/** glGetHandleARB() - return ID/name of currently bound shader program */
Brian Paulfd59f192008-05-18 16:04:55 -0600891static GLuint
Brian5b01c5e2006-12-19 18:02:03 -0700892_mesa_get_handle(GLcontext *ctx, GLenum pname)
Brian34ae99d2006-12-18 08:28:54 -0700893{
Ian Romanick905d8e02008-09-29 12:27:00 -0700894 if (pname == GL_PROGRAM_OBJECT_ARB) {
Brian Pauleb88c022010-05-26 22:40:38 -0600895 if (ctx->Shader.CurrentProgram)
896 return ctx->Shader.CurrentProgram->Name;
897 else
898 return 0;
Brian34ae99d2006-12-18 08:28:54 -0700899 }
Brian Pauleb88c022010-05-26 22:40:38 -0600900 else {
901 _mesa_error(ctx, GL_INVALID_ENUM, "glGetHandleARB");
902 return 0;
903 }
Brian34ae99d2006-12-18 08:28:54 -0700904}
905
906
Brian Pauleb88c022010-05-26 22:40:38 -0600907/**
908 * glGetProgramiv() - get shader program state.
909 * Note that this is for GLSL shader programs, not ARB vertex/fragment
910 * programs (see glGetProgramivARB).
911 */
Brian Paulfd59f192008-05-18 16:04:55 -0600912static void
Brian5b01c5e2006-12-19 18:02:03 -0700913_mesa_get_programiv(GLcontext *ctx, GLuint program,
914 GLenum pname, GLint *params)
Brian34ae99d2006-12-18 08:28:54 -0700915{
Brian Paul27341a92008-09-16 16:28:36 -0600916 const struct gl_program_parameter_list *attribs;
Brian65a18442006-12-19 18:46:56 -0700917 struct gl_shader_program *shProg
918 = _mesa_lookup_shader_program(ctx, program);
Brian34ae99d2006-12-18 08:28:54 -0700919
Brian65a18442006-12-19 18:46:56 -0700920 if (!shProg) {
Brian5b01c5e2006-12-19 18:02:03 -0700921 _mesa_error(ctx, GL_INVALID_VALUE, "glGetProgramiv(program)");
Brian34ae99d2006-12-18 08:28:54 -0700922 return;
923 }
924
Brian Paul27341a92008-09-16 16:28:36 -0600925 if (shProg->VertexProgram)
926 attribs = shProg->VertexProgram->Base.Attributes;
927 else
928 attribs = NULL;
929
Brian5b01c5e2006-12-19 18:02:03 -0700930 switch (pname) {
931 case GL_DELETE_STATUS:
Brian65a18442006-12-19 18:46:56 -0700932 *params = shProg->DeletePending;
Brian5b01c5e2006-12-19 18:02:03 -0700933 break;
934 case GL_LINK_STATUS:
Brian65a18442006-12-19 18:46:56 -0700935 *params = shProg->LinkStatus;
Brian34ae99d2006-12-18 08:28:54 -0700936 break;
Brian5b01c5e2006-12-19 18:02:03 -0700937 case GL_VALIDATE_STATUS:
Brian65a18442006-12-19 18:46:56 -0700938 *params = shProg->Validated;
Brian5b01c5e2006-12-19 18:02:03 -0700939 break;
940 case GL_INFO_LOG_LENGTH:
Jan Dvorak5a0f02a2007-07-13 16:36:00 -0600941 *params = shProg->InfoLog ? strlen(shProg->InfoLog) + 1 : 0;
Brian5b01c5e2006-12-19 18:02:03 -0700942 break;
943 case GL_ATTACHED_SHADERS:
Brian65a18442006-12-19 18:46:56 -0700944 *params = shProg->NumShaders;
Brian5b01c5e2006-12-19 18:02:03 -0700945 break;
946 case GL_ACTIVE_ATTRIBUTES:
Brian Paul27341a92008-09-16 16:28:36 -0600947 *params = attribs ? attribs->NumParameters : 0;
Brian5b01c5e2006-12-19 18:02:03 -0700948 break;
949 case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH:
Brian Paul27341a92008-09-16 16:28:36 -0600950 *params = _mesa_longest_parameter_name(attribs, PROGRAM_INPUT) + 1;
Brian5b01c5e2006-12-19 18:02:03 -0700951 break;
952 case GL_ACTIVE_UNIFORMS:
Brian Paulade50832008-05-14 16:09:46 -0600953 *params = shProg->Uniforms ? shProg->Uniforms->NumUniforms : 0;
Brian5b01c5e2006-12-19 18:02:03 -0700954 break;
955 case GL_ACTIVE_UNIFORM_MAX_LENGTH:
Brian Paulade50832008-05-14 16:09:46 -0600956 *params = _mesa_longest_uniform_name(shProg->Uniforms);
Brian274ac7a2007-04-18 16:05:53 -0600957 if (*params > 0)
958 (*params)++; /* add one for terminating zero */
Brian34ae99d2006-12-18 08:28:54 -0700959 break;
Brian Paulbda6ad22008-08-06 12:45:14 -0600960 case GL_PROGRAM_BINARY_LENGTH_OES:
961 *params = 0;
962 break;
Brian Paule5c69642010-03-30 19:54:02 -0600963#if FEATURE_EXT_transform_feedback
964 case GL_TRANSFORM_FEEDBACK_VARYINGS:
965 *params = shProg->TransformFeedback.NumVarying;
966 break;
967 case GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH:
968 *params = longest_feedback_varying_name(shProg) + 1;
969 break;
970 case GL_TRANSFORM_FEEDBACK_BUFFER_MODE:
971 *params = shProg->TransformFeedback.BufferMode;
972 break;
973#endif
Brian34ae99d2006-12-18 08:28:54 -0700974 default:
Brian5b01c5e2006-12-19 18:02:03 -0700975 _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramiv(pname)");
976 return;
Brian34ae99d2006-12-18 08:28:54 -0700977 }
Brian5b01c5e2006-12-19 18:02:03 -0700978}
Brian34ae99d2006-12-18 08:28:54 -0700979
Brian34ae99d2006-12-18 08:28:54 -0700980
Brian Pauleb88c022010-05-26 22:40:38 -0600981/** glGetShaderiv() - get GLSL shader state */
Brian Paulfd59f192008-05-18 16:04:55 -0600982static void
Brian5b01c5e2006-12-19 18:02:03 -0700983_mesa_get_shaderiv(GLcontext *ctx, GLuint name, GLenum pname, GLint *params)
984{
Brian Paul530df582008-07-03 16:21:11 -0600985 struct gl_shader *shader = _mesa_lookup_shader_err(ctx, name, "glGetShaderiv");
Brian5b01c5e2006-12-19 18:02:03 -0700986
987 if (!shader) {
Brian5b01c5e2006-12-19 18:02:03 -0700988 return;
989 }
Brian65a18442006-12-19 18:46:56 -0700990
Brian5b01c5e2006-12-19 18:02:03 -0700991 switch (pname) {
992 case GL_SHADER_TYPE:
993 *params = shader->Type;
994 break;
995 case GL_DELETE_STATUS:
996 *params = shader->DeletePending;
997 break;
998 case GL_COMPILE_STATUS:
999 *params = shader->CompileStatus;
1000 break;
1001 case GL_INFO_LOG_LENGTH:
Jan Dvorak5a0f02a2007-07-13 16:36:00 -06001002 *params = shader->InfoLog ? strlen(shader->InfoLog) + 1 : 0;
Brian5b01c5e2006-12-19 18:02:03 -07001003 break;
1004 case GL_SHADER_SOURCE_LENGTH:
Jan Dvorak5a0f02a2007-07-13 16:36:00 -06001005 *params = shader->Source ? strlen((char *) shader->Source) + 1 : 0;
Brian5b01c5e2006-12-19 18:02:03 -07001006 break;
1007 default:
1008 _mesa_error(ctx, GL_INVALID_ENUM, "glGetShaderiv(pname)");
1009 return;
1010 }
1011}
1012
1013
Brian Paulfd59f192008-05-18 16:04:55 -06001014static void
Brian5b01c5e2006-12-19 18:02:03 -07001015_mesa_get_program_info_log(GLcontext *ctx, GLuint program, GLsizei bufSize,
1016 GLsizei *length, GLchar *infoLog)
1017{
Brian65a18442006-12-19 18:46:56 -07001018 struct gl_shader_program *shProg
1019 = _mesa_lookup_shader_program(ctx, program);
1020 if (!shProg) {
Brian5b01c5e2006-12-19 18:02:03 -07001021 _mesa_error(ctx, GL_INVALID_VALUE, "glGetProgramInfoLog(program)");
1022 return;
1023 }
Brian Paule5c69642010-03-30 19:54:02 -06001024 _mesa_copy_string(infoLog, bufSize, length, shProg->InfoLog);
Brian5b01c5e2006-12-19 18:02:03 -07001025}
1026
1027
Brian Paulfd59f192008-05-18 16:04:55 -06001028static void
Brian5b01c5e2006-12-19 18:02:03 -07001029_mesa_get_shader_info_log(GLcontext *ctx, GLuint shader, GLsizei bufSize,
1030 GLsizei *length, GLchar *infoLog)
1031{
Brian65a18442006-12-19 18:46:56 -07001032 struct gl_shader *sh = _mesa_lookup_shader(ctx, shader);
1033 if (!sh) {
Brian5b01c5e2006-12-19 18:02:03 -07001034 _mesa_error(ctx, GL_INVALID_VALUE, "glGetShaderInfoLog(shader)");
1035 return;
1036 }
Brian Paule5c69642010-03-30 19:54:02 -06001037 _mesa_copy_string(infoLog, bufSize, length, sh->InfoLog);
Brian5b01c5e2006-12-19 18:02:03 -07001038}
1039
1040
1041/**
1042 * Called via ctx->Driver.GetShaderSource().
1043 */
Brian Paulfd59f192008-05-18 16:04:55 -06001044static void
Brian5b01c5e2006-12-19 18:02:03 -07001045_mesa_get_shader_source(GLcontext *ctx, GLuint shader, GLsizei maxLength,
1046 GLsizei *length, GLchar *sourceOut)
1047{
Brian Paul530df582008-07-03 16:21:11 -06001048 struct gl_shader *sh;
1049 sh = _mesa_lookup_shader_err(ctx, shader, "glGetShaderSource");
Brian65a18442006-12-19 18:46:56 -07001050 if (!sh) {
Brian5b01c5e2006-12-19 18:02:03 -07001051 return;
1052 }
Brian Paule5c69642010-03-30 19:54:02 -06001053 _mesa_copy_string(sourceOut, maxLength, length, sh->Source);
Brian5b01c5e2006-12-19 18:02:03 -07001054}
1055
1056
Brian5b01c5e2006-12-19 18:02:03 -07001057/**
1058 * Called via ctx->Driver.ShaderSource()
1059 */
Brian Paulfd59f192008-05-18 16:04:55 -06001060static void
Brian5b01c5e2006-12-19 18:02:03 -07001061_mesa_shader_source(GLcontext *ctx, GLuint shader, const GLchar *source)
Brian34ae99d2006-12-18 08:28:54 -07001062{
Brian Paul530df582008-07-03 16:21:11 -06001063 struct gl_shader *sh;
1064
1065 sh = _mesa_lookup_shader_err(ctx, shader, "glShaderSource");
1066 if (!sh)
Brian34ae99d2006-12-18 08:28:54 -07001067 return;
Brian34ae99d2006-12-18 08:28:54 -07001068
Brian34ae99d2006-12-18 08:28:54 -07001069 /* free old shader source string and install new one */
Brian65a18442006-12-19 18:46:56 -07001070 if (sh->Source) {
Kristian Høgsberg32f2fd12010-02-19 11:58:49 -05001071 free((void *) sh->Source);
Brian34ae99d2006-12-18 08:28:54 -07001072 }
Brian65a18442006-12-19 18:46:56 -07001073 sh->Source = source;
Brian9e4bae92006-12-20 09:27:42 -07001074 sh->CompileStatus = GL_FALSE;
Brian Paulf7783ba2009-08-04 15:35:48 -06001075#ifdef DEBUG
1076 sh->SourceChecksum = _mesa_str_checksum(sh->Source);
1077#endif
Brian34ae99d2006-12-18 08:28:54 -07001078}
1079
1080
Brian5b01c5e2006-12-19 18:02:03 -07001081/**
1082 * Called via ctx->Driver.CompileShader()
1083 */
Brian Paulfd59f192008-05-18 16:04:55 -06001084static void
Brian5b01c5e2006-12-19 18:02:03 -07001085_mesa_compile_shader(GLcontext *ctx, GLuint shaderObj)
Brian34ae99d2006-12-18 08:28:54 -07001086{
Brian Paul530df582008-07-03 16:21:11 -06001087 struct gl_shader *sh;
Brian34ae99d2006-12-18 08:28:54 -07001088
Brian Paul530df582008-07-03 16:21:11 -06001089 sh = _mesa_lookup_shader_err(ctx, shaderObj, "glCompileShader");
1090 if (!sh)
Brian34ae99d2006-12-18 08:28:54 -07001091 return;
Brian34ae99d2006-12-18 08:28:54 -07001092
Brian Paul65fc2ca2009-03-19 10:25:24 -06001093 /* set default pragma state for shader */
1094 sh->Pragmas = ctx->Shader.DefaultPragmas;
1095
Brian Paulcb136e02009-01-22 10:34:15 -07001096 /* this call will set the sh->CompileStatus field to indicate if
1097 * compilation was successful.
1098 */
Eric Anholt0a1b54d2010-06-21 11:29:15 -07001099 _mesa_glsl_compile_shader(ctx, sh);
Brian34ae99d2006-12-18 08:28:54 -07001100}
1101
1102
Brian5b01c5e2006-12-19 18:02:03 -07001103/**
1104 * Called via ctx->Driver.LinkProgram()
1105 */
Brian Paulfd59f192008-05-18 16:04:55 -06001106static void
Brian5b01c5e2006-12-19 18:02:03 -07001107_mesa_link_program(GLcontext *ctx, GLuint program)
Brian34ae99d2006-12-18 08:28:54 -07001108{
Brian65a18442006-12-19 18:46:56 -07001109 struct gl_shader_program *shProg;
Brian Paulfef6e362010-05-10 21:11:21 -06001110 struct gl_transform_feedback_object *obj =
1111 ctx->TransformFeedback.CurrentObject;
Brian34ae99d2006-12-18 08:28:54 -07001112
Brian Paul530df582008-07-03 16:21:11 -06001113 shProg = _mesa_lookup_shader_program_err(ctx, program, "glLinkProgram");
1114 if (!shProg)
Brian34ae99d2006-12-18 08:28:54 -07001115 return;
Brian34ae99d2006-12-18 08:28:54 -07001116
Brian Paulfef6e362010-05-10 21:11:21 -06001117 if (obj->Active && shProg == ctx->Shader.CurrentProgram) {
Brian Paul1a148662010-04-01 22:15:16 -06001118 _mesa_error(ctx, GL_INVALID_OPERATION,
1119 "glLinkProgram(transform feedback active");
1120 return;
1121 }
1122
Briandf43fb62008-05-06 23:08:51 -06001123 FLUSH_VERTICES(ctx, _NEW_PROGRAM);
1124
Eric Anholt0a1b54d2010-06-21 11:29:15 -07001125 _mesa_glsl_link_shader(ctx, shProg);
Brian Paulac3c8e32009-09-14 17:32:03 -06001126
1127 /* debug code */
1128 if (0) {
1129 GLuint i;
1130
Kristian Høgsberg298be2b2010-02-19 12:32:24 -05001131 printf("Link %u shaders in program %u: %s\n",
Brian Paulac3c8e32009-09-14 17:32:03 -06001132 shProg->NumShaders, shProg->Name,
1133 shProg->LinkStatus ? "Success" : "Failed");
1134
1135 for (i = 0; i < shProg->NumShaders; i++) {
Kristian Høgsberg298be2b2010-02-19 12:32:24 -05001136 printf(" shader %u, type 0x%x\n",
Brian Paulac3c8e32009-09-14 17:32:03 -06001137 shProg->Shaders[i]->Name,
1138 shProg->Shaders[i]->Type);
1139 }
1140 }
Brian34ae99d2006-12-18 08:28:54 -07001141}
1142
1143
1144/**
Brian Paul346250b2009-10-23 16:31:48 -06001145 * Print basic shader info (for debug).
1146 */
1147static void
1148print_shader_info(const struct gl_shader_program *shProg)
1149{
1150 GLuint i;
1151
Kristian Høgsberg298be2b2010-02-19 12:32:24 -05001152 printf("Mesa: glUseProgram(%u)\n", shProg->Name);
Brian Paul346250b2009-10-23 16:31:48 -06001153 for (i = 0; i < shProg->NumShaders; i++) {
1154 const char *s;
1155 switch (shProg->Shaders[i]->Type) {
1156 case GL_VERTEX_SHADER:
1157 s = "vertex";
1158 break;
1159 case GL_FRAGMENT_SHADER:
1160 s = "fragment";
1161 break;
1162 case GL_GEOMETRY_SHADER:
1163 s = "geometry";
1164 break;
1165 default:
1166 s = "";
1167 }
Kristian Høgsberg298be2b2010-02-19 12:32:24 -05001168 printf(" %s shader %u, checksum %u\n", s,
1169 shProg->Shaders[i]->Name,
1170 shProg->Shaders[i]->SourceChecksum);
Brian Paul346250b2009-10-23 16:31:48 -06001171 }
1172 if (shProg->VertexProgram)
Kristian Høgsberg298be2b2010-02-19 12:32:24 -05001173 printf(" vert prog %u\n", shProg->VertexProgram->Base.Id);
Brian Paul346250b2009-10-23 16:31:48 -06001174 if (shProg->FragmentProgram)
Kristian Høgsberg298be2b2010-02-19 12:32:24 -05001175 printf(" frag prog %u\n", shProg->FragmentProgram->Base.Id);
Brian Paul346250b2009-10-23 16:31:48 -06001176}
1177
1178
1179/**
Brian5b01c5e2006-12-19 18:02:03 -07001180 * Called via ctx->Driver.UseProgram()
Brian34ae99d2006-12-18 08:28:54 -07001181 */
Brian5b01c5e2006-12-19 18:02:03 -07001182void
1183_mesa_use_program(GLcontext *ctx, GLuint program)
Brian34ae99d2006-12-18 08:28:54 -07001184{
Brian3c008a02007-04-12 15:22:32 -06001185 struct gl_shader_program *shProg;
Brian Paulfef6e362010-05-10 21:11:21 -06001186 struct gl_transform_feedback_object *obj =
1187 ctx->TransformFeedback.CurrentObject;
Brian3c008a02007-04-12 15:22:32 -06001188
Brian Paulfef6e362010-05-10 21:11:21 -06001189 if (obj->Active) {
Brian Paul1a148662010-04-01 22:15:16 -06001190 _mesa_error(ctx, GL_INVALID_OPERATION,
1191 "glUseProgram(transform feedback active)");
1192 return;
1193 }
1194
Brian00d63aa2007-02-03 11:35:02 -07001195 if (ctx->Shader.CurrentProgram &&
1196 ctx->Shader.CurrentProgram->Name == program) {
1197 /* no-op */
1198 return;
1199 }
1200
Brian5b01c5e2006-12-19 18:02:03 -07001201 if (program) {
Brian Paul530df582008-07-03 16:21:11 -06001202 shProg = _mesa_lookup_shader_program_err(ctx, program, "glUseProgram");
Brian65a18442006-12-19 18:46:56 -07001203 if (!shProg) {
Brian Paul530df582008-07-03 16:21:11 -06001204 return;
1205 }
1206 if (!shProg->LinkStatus) {
Brian Paul621c9992009-02-18 13:28:12 -07001207 _mesa_error(ctx, GL_INVALID_OPERATION,
1208 "glUseProgram(program %u not linked)", program);
Brian5b01c5e2006-12-19 18:02:03 -07001209 return;
1210 }
Brian Paul4eda17d2009-03-13 09:11:42 -06001211
1212 /* debug code */
Brian Paul2ee7fd82009-10-15 15:25:52 -06001213 if (ctx->Shader.Flags & GLSL_USE_PROG) {
Brian Paul346250b2009-10-23 16:31:48 -06001214 print_shader_info(shProg);
Brian Paul4eda17d2009-03-13 09:11:42 -06001215 }
Brian5b01c5e2006-12-19 18:02:03 -07001216 }
1217 else {
Brian3c008a02007-04-12 15:22:32 -06001218 shProg = NULL;
1219 }
1220
Brian Paulb44304e2009-10-27 20:09:33 -06001221 if (ctx->Shader.CurrentProgram != shProg) {
1222 FLUSH_VERTICES(ctx, _NEW_PROGRAM | _NEW_PROGRAM_CONSTANTS);
1223 _mesa_reference_shader_program(ctx, &ctx->Shader.CurrentProgram, shProg);
1224 }
Brian5b01c5e2006-12-19 18:02:03 -07001225}
Brian34ae99d2006-12-18 08:28:54 -07001226
Brian5b01c5e2006-12-19 18:02:03 -07001227
Brian Paulade50832008-05-14 16:09:46 -06001228
1229/**
Brian Paul517401a2008-11-06 15:04:11 -07001230 * Update the vertex/fragment program's TexturesUsed array.
1231 *
1232 * This needs to be called after glUniform(set sampler var) is called.
1233 * A call to glUniform(samplerVar, value) causes a sampler to point to a
1234 * particular texture unit. We know the sampler's texture target
1235 * (1D/2D/3D/etc) from compile time but the sampler's texture unit is
1236 * set by glUniform() calls.
1237 *
1238 * So, scan the program->SamplerUnits[] and program->SamplerTargets[]
1239 * information to update the prog->TexturesUsed[] values.
1240 * Each value of TexturesUsed[unit] is one of zero, TEXTURE_1D_INDEX,
1241 * TEXTURE_2D_INDEX, TEXTURE_3D_INDEX, etc.
1242 * We'll use that info for state validation before rendering.
Brian Paulade50832008-05-14 16:09:46 -06001243 */
Brian Paul517401a2008-11-06 15:04:11 -07001244void
1245_mesa_update_shader_textures_used(struct gl_program *prog)
Brian Paulade50832008-05-14 16:09:46 -06001246{
1247 GLuint s;
1248
1249 memset(prog->TexturesUsed, 0, sizeof(prog->TexturesUsed));
1250
1251 for (s = 0; s < MAX_SAMPLERS; s++) {
1252 if (prog->SamplersUsed & (1 << s)) {
Brian Paulf05344f2009-08-26 10:58:06 -06001253 GLuint unit = prog->SamplerUnits[s];
1254 GLuint tgt = prog->SamplerTargets[s];
1255 assert(unit < MAX_TEXTURE_IMAGE_UNITS);
1256 assert(tgt < NUM_TEXTURE_TARGETS);
1257 prog->TexturesUsed[unit] |= (1 << tgt);
Brian Paulade50832008-05-14 16:09:46 -06001258 }
1259 }
1260}
1261
1262
1263/**
Brian Paulc90fca32009-08-25 17:42:47 -06001264 * Validate a program's samplers.
1265 * Specifically, check that there aren't two samplers of different types
1266 * pointing to the same texture unit.
1267 * \return GL_TRUE if valid, GL_FALSE if invalid
1268 */
1269static GLboolean
1270validate_samplers(GLcontext *ctx, const struct gl_program *prog, char *errMsg)
Brian34ae99d2006-12-18 08:28:54 -07001271{
Brian Paulc90fca32009-08-25 17:42:47 -06001272 static const char *targetName[] = {
1273 "TEXTURE_2D_ARRAY",
1274 "TEXTURE_1D_ARRAY",
1275 "TEXTURE_CUBE",
1276 "TEXTURE_3D",
1277 "TEXTURE_RECT",
1278 "TEXTURE_2D",
1279 "TEXTURE_1D",
1280 };
1281 GLint targetUsed[MAX_TEXTURE_IMAGE_UNITS];
1282 GLbitfield samplersUsed = prog->SamplersUsed;
1283 GLuint i;
Brian Paulbc985b52008-07-21 14:16:07 -06001284
Brian Paulc90fca32009-08-25 17:42:47 -06001285 assert(Elements(targetName) == NUM_TEXTURE_TARGETS);
1286
1287 if (samplersUsed == 0x0)
1288 return GL_TRUE;
1289
1290 for (i = 0; i < Elements(targetUsed); i++)
1291 targetUsed[i] = -1;
1292
1293 /* walk over bits which are set in 'samplers' */
1294 while (samplersUsed) {
1295 GLuint unit;
1296 gl_texture_index target;
1297 GLint sampler = _mesa_ffs(samplersUsed) - 1;
1298 assert(sampler >= 0);
1299 assert(sampler < MAX_TEXTURE_IMAGE_UNITS);
1300 unit = prog->SamplerUnits[sampler];
1301 target = prog->SamplerTargets[sampler];
1302 if (targetUsed[unit] != -1 && targetUsed[unit] != target) {
Brian Paul78a0c352010-02-19 12:56:49 -07001303 _mesa_snprintf(errMsg, 100,
Kristian Høgsberg298be2b2010-02-19 12:32:24 -05001304 "Texture unit %d is accessed both as %s and %s",
1305 unit, targetName[targetUsed[unit]], targetName[target]);
Brian Paulc90fca32009-08-25 17:42:47 -06001306 return GL_FALSE;
1307 }
1308 targetUsed[unit] = target;
1309 samplersUsed ^= (1 << sampler);
Brian34ae99d2006-12-18 08:28:54 -07001310 }
1311
Brian Paulc90fca32009-08-25 17:42:47 -06001312 return GL_TRUE;
1313}
1314
1315
1316/**
1317 * Do validation of the given shader program.
1318 * \param errMsg returns error message if validation fails.
1319 * \return GL_TRUE if valid, GL_FALSE if invalid (and set errMsg)
1320 */
1321GLboolean
1322_mesa_validate_shader_program(GLcontext *ctx,
1323 const struct gl_shader_program *shProg,
1324 char *errMsg)
1325{
1326 const struct gl_vertex_program *vp = shProg->VertexProgram;
1327 const struct gl_fragment_program *fp = shProg->FragmentProgram;
1328
Brian Paulbc985b52008-07-21 14:16:07 -06001329 if (!shProg->LinkStatus) {
Brian Paulc90fca32009-08-25 17:42:47 -06001330 return GL_FALSE;
Brian Paulbc985b52008-07-21 14:16:07 -06001331 }
1332
1333 /* From the GL spec, a program is invalid if any of these are true:
1334
Brian5b01c5e2006-12-19 18:02:03 -07001335 any two active samplers in the current program object are of
1336 different types, but refer to the same texture image unit,
1337
1338 any active sampler in the current program object refers to a texture
1339 image unit where fixed-function fragment processing accesses a
1340 texture target that does not match the sampler type, or
1341
1342 the sum of the number of active samplers in the program and the
1343 number of texture image units enabled for fixed-function fragment
1344 processing exceeds the combined limit on the total number of texture
1345 image units allowed.
1346 */
Brian Paulbc985b52008-07-21 14:16:07 -06001347
Brian Paulc90fca32009-08-25 17:42:47 -06001348
1349 /*
1350 * Check: any two active samplers in the current program object are of
1351 * different types, but refer to the same texture image unit,
1352 */
1353 if (vp && !validate_samplers(ctx, &vp->Base, errMsg)) {
1354 return GL_FALSE;
1355 }
1356 if (fp && !validate_samplers(ctx, &fp->Base, errMsg)) {
1357 return GL_FALSE;
1358 }
1359
1360 return GL_TRUE;
1361}
1362
1363
1364/**
1365 * Called via glValidateProgram()
1366 */
1367static void
1368_mesa_validate_program(GLcontext *ctx, GLuint program)
1369{
1370 struct gl_shader_program *shProg;
1371 char errMsg[100];
1372
1373 shProg = _mesa_lookup_shader_program_err(ctx, program, "glValidateProgram");
1374 if (!shProg) {
1375 return;
1376 }
1377
1378 shProg->Validated = _mesa_validate_shader_program(ctx, shProg, errMsg);
1379 if (!shProg->Validated) {
1380 /* update info log */
1381 if (shProg->InfoLog) {
Kristian Høgsberg32f2fd12010-02-19 11:58:49 -05001382 free(shProg->InfoLog);
Brian Paulc90fca32009-08-25 17:42:47 -06001383 }
1384 shProg->InfoLog = _mesa_strdup(errMsg);
1385 }
Brian34ae99d2006-12-18 08:28:54 -07001386}
Brian Paulfd59f192008-05-18 16:04:55 -06001387
1388
1389/**
1390 * Plug in Mesa's GLSL functions into the device driver function table.
1391 */
1392void
1393_mesa_init_glsl_driver_functions(struct dd_function_table *driver)
1394{
1395 driver->AttachShader = _mesa_attach_shader;
1396 driver->BindAttribLocation = _mesa_bind_attrib_location;
1397 driver->CompileShader = _mesa_compile_shader;
1398 driver->CreateProgram = _mesa_create_program;
1399 driver->CreateShader = _mesa_create_shader;
1400 driver->DeleteProgram2 = _mesa_delete_program2;
1401 driver->DeleteShader = _mesa_delete_shader;
1402 driver->DetachShader = _mesa_detach_shader;
1403 driver->GetActiveAttrib = _mesa_get_active_attrib;
Brian Paulfd59f192008-05-18 16:04:55 -06001404 driver->GetAttachedShaders = _mesa_get_attached_shaders;
1405 driver->GetAttribLocation = _mesa_get_attrib_location;
1406 driver->GetHandle = _mesa_get_handle;
1407 driver->GetProgramiv = _mesa_get_programiv;
1408 driver->GetProgramInfoLog = _mesa_get_program_info_log;
1409 driver->GetShaderiv = _mesa_get_shaderiv;
1410 driver->GetShaderInfoLog = _mesa_get_shader_info_log;
1411 driver->GetShaderSource = _mesa_get_shader_source;
Brian Paulfd59f192008-05-18 16:04:55 -06001412 driver->IsProgram = _mesa_is_program;
1413 driver->IsShader = _mesa_is_shader;
1414 driver->LinkProgram = _mesa_link_program;
1415 driver->ShaderSource = _mesa_shader_source;
Brian Paulfd59f192008-05-18 16:04:55 -06001416 driver->UseProgram = _mesa_use_program;
1417 driver->ValidateProgram = _mesa_validate_program;
Brian Paul69861ae2010-05-26 22:24:58 -06001418
1419 _mesa_init_uniform_functions(driver);
Brian Paulfd59f192008-05-18 16:04:55 -06001420}