blob: c414e89825fb365cfba0071d4e7b5ac1eaba47c8 [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"
Brianc223c6b2007-07-04 13:15:20 -060047#include "shader/slang/slang_compile.h"
48#include "shader/slang/slang_link.h"
Brian34ae99d2006-12-18 08:28:54 -070049
50
Brianf2923612006-12-20 09:56:44 -070051/**
52 * Allocate a new gl_shader_program object, initialize it.
53 */
Brian Paulfd59f192008-05-18 16:04:55 -060054static struct gl_shader_program *
Brianf2923612006-12-20 09:56:44 -070055_mesa_new_shader_program(GLcontext *ctx, GLuint name)
56{
57 struct gl_shader_program *shProg;
58 shProg = CALLOC_STRUCT(gl_shader_program);
59 if (shProg) {
Brianf3e8c322007-04-18 14:53:23 -060060 shProg->Type = GL_SHADER_PROGRAM_MESA;
Brianf2923612006-12-20 09:56:44 -070061 shProg->Name = name;
62 shProg->RefCount = 1;
Brian3209c3e2007-01-09 17:49:24 -070063 shProg->Attributes = _mesa_new_parameter_list();
Brianf2923612006-12-20 09:56:44 -070064 }
65 return shProg;
66}
67
68
Brianb9fbedd2007-03-26 09:23:44 -060069/**
Brian3c008a02007-04-12 15:22:32 -060070 * Clear (free) the shader program state that gets produced by linking.
Brianb9fbedd2007-03-26 09:23:44 -060071 */
Brianf2923612006-12-20 09:56:44 -070072void
Brian3c008a02007-04-12 15:22:32 -060073_mesa_clear_shader_program_data(GLcontext *ctx,
74 struct gl_shader_program *shProg)
Brianf2923612006-12-20 09:56:44 -070075{
Brian Paul8bdf5b62008-05-16 09:56:59 -060076 _mesa_reference_vertprog(ctx, &shProg->VertexProgram, NULL);
77 _mesa_reference_fragprog(ctx, &shProg->FragmentProgram, NULL);
Brianf2923612006-12-20 09:56:44 -070078
Brianf2923612006-12-20 09:56:44 -070079 if (shProg->Uniforms) {
Brian Paulade50832008-05-14 16:09:46 -060080 _mesa_free_uniform_list(shProg->Uniforms);
Brianf2923612006-12-20 09:56:44 -070081 shProg->Uniforms = NULL;
82 }
83
84 if (shProg->Varying) {
85 _mesa_free_parameter_list(shProg->Varying);
86 shProg->Varying = NULL;
87 }
88}
89
90
Brianb9fbedd2007-03-26 09:23:44 -060091/**
Brian3c008a02007-04-12 15:22:32 -060092 * Free all the data that hangs off a shader program object, but not the
93 * object itself.
94 */
95void
96_mesa_free_shader_program_data(GLcontext *ctx,
97 struct gl_shader_program *shProg)
98{
99 GLuint i;
100
Brianf3e8c322007-04-18 14:53:23 -0600101 assert(shProg->Type == GL_SHADER_PROGRAM_MESA);
Brian3c008a02007-04-12 15:22:32 -0600102
103 _mesa_clear_shader_program_data(ctx, shProg);
104
Brian4b7c6fc2007-04-19 15:23:34 -0600105 if (shProg->Attributes) {
106 _mesa_free_parameter_list(shProg->Attributes);
107 shProg->Attributes = NULL;
108 }
109
Brian3c008a02007-04-12 15:22:32 -0600110 /* detach shaders */
111 for (i = 0; i < shProg->NumShaders; i++) {
112 _mesa_reference_shader(ctx, &shProg->Shaders[i], NULL);
113 }
Xiang, Haihao63d8a842008-03-31 17:02:47 +0800114 shProg->NumShaders = 0;
115
Brian3c008a02007-04-12 15:22:32 -0600116 if (shProg->Shaders) {
Kristian Høgsberg32f2fd12010-02-19 11:58:49 -0500117 free(shProg->Shaders);
Brian3c008a02007-04-12 15:22:32 -0600118 shProg->Shaders = NULL;
119 }
Alan Hourihaneeec20c32008-04-22 20:29:42 +0100120
121 if (shProg->InfoLog) {
Kristian Høgsberg32f2fd12010-02-19 11:58:49 -0500122 free(shProg->InfoLog);
Alan Hourihaneeec20c32008-04-22 20:29:42 +0100123 shProg->InfoLog = NULL;
124 }
Brian Paule5c69642010-03-30 19:54:02 -0600125
126 /* Transform feedback varying vars */
127 for (i = 0; i < shProg->TransformFeedback.NumVarying; i++) {
128 free(shProg->TransformFeedback.VaryingNames[i]);
129 }
130 free(shProg->TransformFeedback.VaryingNames);
131 shProg->TransformFeedback.VaryingNames = NULL;
132 shProg->TransformFeedback.NumVarying = 0;
Brian3c008a02007-04-12 15:22:32 -0600133}
134
135
136/**
Brianb9fbedd2007-03-26 09:23:44 -0600137 * Free/delete a shader program object.
138 */
Brianf2923612006-12-20 09:56:44 -0700139void
140_mesa_free_shader_program(GLcontext *ctx, struct gl_shader_program *shProg)
141{
142 _mesa_free_shader_program_data(ctx, shProg);
Alan Hourihaneeec20c32008-04-22 20:29:42 +0100143
Kristian Høgsberg32f2fd12010-02-19 11:58:49 -0500144 free(shProg);
Brianf2923612006-12-20 09:56:44 -0700145}
146
147
148/**
Brian3c008a02007-04-12 15:22:32 -0600149 * Set ptr to point to shProg.
150 * If ptr is pointing to another object, decrement its refcount (and delete
151 * if refcount hits zero).
152 * Then set ptr to point to shProg, incrementing its refcount.
153 */
154/* XXX this could be static */
155void
156_mesa_reference_shader_program(GLcontext *ctx,
157 struct gl_shader_program **ptr,
158 struct gl_shader_program *shProg)
159{
160 assert(ptr);
161 if (*ptr == shProg) {
162 /* no-op */
163 return;
164 }
165 if (*ptr) {
166 /* Unreference the old shader program */
167 GLboolean deleteFlag = GL_FALSE;
168 struct gl_shader_program *old = *ptr;
169
170 ASSERT(old->RefCount > 0);
171 old->RefCount--;
Brian Paul8bdf5b62008-05-16 09:56:59 -0600172#if 0
173 printf("ShaderProgram %p ID=%u RefCount-- to %d\n",
174 (void *) old, old->Name, old->RefCount);
175#endif
Brian3c008a02007-04-12 15:22:32 -0600176 deleteFlag = (old->RefCount == 0);
177
178 if (deleteFlag) {
Xiang, Haihaoaef47c42008-03-31 16:27:47 +0800179 _mesa_HashRemove(ctx->Shared->ShaderObjects, old->Name);
Brian3c008a02007-04-12 15:22:32 -0600180 _mesa_free_shader_program(ctx, old);
181 }
182
183 *ptr = NULL;
184 }
185 assert(!*ptr);
186
187 if (shProg) {
188 shProg->RefCount++;
Brian Paul8bdf5b62008-05-16 09:56:59 -0600189#if 0
190 printf("ShaderProgram %p ID=%u RefCount++ to %d\n",
191 (void *) shProg, shProg->Name, shProg->RefCount);
192#endif
Brian3c008a02007-04-12 15:22:32 -0600193 *ptr = shProg;
194 }
195}
196
197
198/**
Brianf2923612006-12-20 09:56:44 -0700199 * Lookup a GLSL program object.
200 */
201struct gl_shader_program *
202_mesa_lookup_shader_program(GLcontext *ctx, GLuint name)
203{
204 struct gl_shader_program *shProg;
205 if (name) {
206 shProg = (struct gl_shader_program *)
Xiang, Haihaoaef47c42008-03-31 16:27:47 +0800207 _mesa_HashLookup(ctx->Shared->ShaderObjects, name);
Brianf2923612006-12-20 09:56:44 -0700208 /* Note that both gl_shader and gl_shader_program objects are kept
209 * in the same hash table. Check the object's type to be sure it's
210 * what we're expecting.
211 */
Brianf3e8c322007-04-18 14:53:23 -0600212 if (shProg && shProg->Type != GL_SHADER_PROGRAM_MESA) {
Brianf2923612006-12-20 09:56:44 -0700213 return NULL;
214 }
215 return shProg;
216 }
217 return NULL;
218}
219
220
221/**
Brian Paul530df582008-07-03 16:21:11 -0600222 * As above, but record an error if program is not found.
223 */
Brian Paul69861ae2010-05-26 22:24:58 -0600224struct gl_shader_program *
Brian Paul530df582008-07-03 16:21:11 -0600225_mesa_lookup_shader_program_err(GLcontext *ctx, GLuint name,
226 const char *caller)
227{
228 if (!name) {
229 _mesa_error(ctx, GL_INVALID_VALUE, caller);
230 return NULL;
231 }
232 else {
233 struct gl_shader_program *shProg = (struct gl_shader_program *)
234 _mesa_HashLookup(ctx->Shared->ShaderObjects, name);
235 if (!shProg) {
236 _mesa_error(ctx, GL_INVALID_VALUE, caller);
237 return NULL;
238 }
239 if (shProg->Type != GL_SHADER_PROGRAM_MESA) {
240 _mesa_error(ctx, GL_INVALID_OPERATION, caller);
241 return NULL;
242 }
243 return shProg;
244 }
245}
246
247
248
249
250/**
Brianf2923612006-12-20 09:56:44 -0700251 * Allocate a new gl_shader object, initialize it.
252 */
253struct gl_shader *
254_mesa_new_shader(GLcontext *ctx, GLuint name, GLenum type)
255{
256 struct gl_shader *shader;
257 assert(type == GL_FRAGMENT_SHADER || type == GL_VERTEX_SHADER);
258 shader = CALLOC_STRUCT(gl_shader);
259 if (shader) {
260 shader->Type = type;
261 shader->Name = name;
262 shader->RefCount = 1;
263 }
264 return shader;
265}
266
267
268void
269_mesa_free_shader(GLcontext *ctx, struct gl_shader *sh)
270{
Brianf2923612006-12-20 09:56:44 -0700271 if (sh->Source)
Kristian Høgsberg32f2fd12010-02-19 11:58:49 -0500272 free((void *) sh->Source);
Brianf2923612006-12-20 09:56:44 -0700273 if (sh->InfoLog)
Kristian Høgsberg32f2fd12010-02-19 11:58:49 -0500274 free(sh->InfoLog);
Brian Paul3d500f02008-07-24 14:56:54 -0600275 _mesa_reference_program(ctx, &sh->Program, NULL);
Kristian Høgsberg32f2fd12010-02-19 11:58:49 -0500276 free(sh);
Brianf2923612006-12-20 09:56:44 -0700277}
278
279
280/**
Brian3c008a02007-04-12 15:22:32 -0600281 * Set ptr to point to sh.
282 * If ptr is pointing to another shader, decrement its refcount (and delete
283 * if refcount hits zero).
284 * Then set ptr to point to sh, incrementing its refcount.
285 */
286/* XXX this could be static */
287void
288_mesa_reference_shader(GLcontext *ctx, struct gl_shader **ptr,
289 struct gl_shader *sh)
290{
291 assert(ptr);
292 if (*ptr == sh) {
293 /* no-op */
294 return;
295 }
296 if (*ptr) {
297 /* Unreference the old shader */
298 GLboolean deleteFlag = GL_FALSE;
299 struct gl_shader *old = *ptr;
300
301 ASSERT(old->RefCount > 0);
302 old->RefCount--;
Brian99193e42007-04-12 15:45:02 -0600303 /*printf("SHADER DECR %p (%d) to %d\n",
304 (void*) old, old->Name, old->RefCount);*/
Brian3c008a02007-04-12 15:22:32 -0600305 deleteFlag = (old->RefCount == 0);
306
307 if (deleteFlag) {
308 _mesa_HashRemove(ctx->Shared->ShaderObjects, old->Name);
309 _mesa_free_shader(ctx, old);
310 }
311
312 *ptr = NULL;
313 }
314 assert(!*ptr);
315
316 if (sh) {
317 /* reference new */
318 sh->RefCount++;
Brian99193e42007-04-12 15:45:02 -0600319 /*printf("SHADER INCR %p (%d) to %d\n",
320 (void*) sh, sh->Name, sh->RefCount);*/
Brian3c008a02007-04-12 15:22:32 -0600321 *ptr = sh;
322 }
323}
324
325
326/**
Brianf2923612006-12-20 09:56:44 -0700327 * Lookup a GLSL shader object.
328 */
329struct gl_shader *
330_mesa_lookup_shader(GLcontext *ctx, GLuint name)
331{
332 if (name) {
333 struct gl_shader *sh = (struct gl_shader *)
334 _mesa_HashLookup(ctx->Shared->ShaderObjects, name);
335 /* Note that both gl_shader and gl_shader_program objects are kept
336 * in the same hash table. Check the object's type to be sure it's
337 * what we're expecting.
338 */
Brianf3e8c322007-04-18 14:53:23 -0600339 if (sh && sh->Type == GL_SHADER_PROGRAM_MESA) {
Brianf2923612006-12-20 09:56:44 -0700340 return NULL;
341 }
342 return sh;
343 }
344 return NULL;
345}
346
347
Brianfa4d0362007-02-26 18:33:50 -0700348/**
Brian Paul530df582008-07-03 16:21:11 -0600349 * As above, but record an error if shader is not found.
350 */
351static struct gl_shader *
352_mesa_lookup_shader_err(GLcontext *ctx, GLuint name, const char *caller)
353{
354 if (!name) {
355 _mesa_error(ctx, GL_INVALID_VALUE, caller);
356 return NULL;
357 }
358 else {
359 struct gl_shader *sh = (struct gl_shader *)
360 _mesa_HashLookup(ctx->Shared->ShaderObjects, name);
361 if (!sh) {
362 _mesa_error(ctx, GL_INVALID_VALUE, caller);
363 return NULL;
364 }
365 if (sh->Type == GL_SHADER_PROGRAM_MESA) {
366 _mesa_error(ctx, GL_INVALID_OPERATION, caller);
367 return NULL;
368 }
369 return sh;
370 }
371}
372
373
Brian Paule01a03d2009-02-06 10:21:36 -0700374/**
375 * Return mask of GLSL_x flags by examining the MESA_GLSL env var.
376 */
377static GLbitfield
378get_shader_flags(void)
379{
380 GLbitfield flags = 0x0;
381 const char *env = _mesa_getenv("MESA_GLSL");
382
383 if (env) {
Kenneth Graunke0aecdb62010-02-18 23:50:51 -0800384 if (strstr(env, "dump"))
Brian Paule01a03d2009-02-06 10:21:36 -0700385 flags |= GLSL_DUMP;
Kenneth Graunke0aecdb62010-02-18 23:50:51 -0800386 if (strstr(env, "log"))
Brian Paule01a03d2009-02-06 10:21:36 -0700387 flags |= GLSL_LOG;
Kenneth Graunke0aecdb62010-02-18 23:50:51 -0800388 if (strstr(env, "nopvert"))
Brian Paulcb0de062009-09-29 10:22:32 -0600389 flags |= GLSL_NOP_VERT;
Kenneth Graunke0aecdb62010-02-18 23:50:51 -0800390 if (strstr(env, "nopfrag"))
Brian Paulcb0de062009-09-29 10:22:32 -0600391 flags |= GLSL_NOP_FRAG;
Kenneth Graunke0aecdb62010-02-18 23:50:51 -0800392 if (strstr(env, "nopt"))
Brian Paule01a03d2009-02-06 10:21:36 -0700393 flags |= GLSL_NO_OPT;
Kenneth Graunke0aecdb62010-02-18 23:50:51 -0800394 else if (strstr(env, "opt"))
Brian Paule01a03d2009-02-06 10:21:36 -0700395 flags |= GLSL_OPT;
Kenneth Graunke0aecdb62010-02-18 23:50:51 -0800396 if (strstr(env, "uniform"))
Brian Paule01a03d2009-02-06 10:21:36 -0700397 flags |= GLSL_UNIFORMS;
Kenneth Graunke0aecdb62010-02-18 23:50:51 -0800398 if (strstr(env, "useprog"))
Brian Paul2ee7fd82009-10-15 15:25:52 -0600399 flags |= GLSL_USE_PROG;
Brian Paule01a03d2009-02-06 10:21:36 -0700400 }
401
402 return flags;
403}
404
Brian Paul530df582008-07-03 16:21:11 -0600405
406/**
Brian Paule5c69642010-03-30 19:54:02 -0600407 * Find the length of the longest transform feedback varying name
408 * which was specified with glTransformFeedbackVaryings().
409 */
410static GLint
411longest_feedback_varying_name(const struct gl_shader_program *shProg)
412{
413 GLuint i;
414 GLint max = 0;
415 for (i = 0; i < shProg->TransformFeedback.NumVarying; i++) {
416 GLint len = strlen(shProg->TransformFeedback.VaryingNames[i]);
417 if (len > max)
418 max = len;
419 }
420 return max;
421}
422
423
424
425/**
Brianfa4d0362007-02-26 18:33:50 -0700426 * Initialize context's shader state.
427 */
Brianf2923612006-12-20 09:56:44 -0700428void
429_mesa_init_shader_state(GLcontext * ctx)
430{
Brianfa4d0362007-02-26 18:33:50 -0700431 /* Device drivers may override these to control what kind of instructions
432 * are generated by the GLSL compiler.
433 */
434 ctx->Shader.EmitHighLevelInstructions = GL_TRUE;
Brian Paul4031ea12009-06-17 11:57:39 -0600435 ctx->Shader.EmitContReturn = GL_TRUE;
Brian Paulc5c38352009-02-16 11:50:05 -0700436 ctx->Shader.EmitCondCodes = GL_FALSE;
Brianfa4d0362007-02-26 18:33:50 -0700437 ctx->Shader.EmitComments = GL_FALSE;
Brian Paule01a03d2009-02-06 10:21:36 -0700438 ctx->Shader.Flags = get_shader_flags();
Brian Paul65fc2ca2009-03-19 10:25:24 -0600439
440 /* Default pragma settings */
441 ctx->Shader.DefaultPragmas.IgnoreOptimize = GL_FALSE;
442 ctx->Shader.DefaultPragmas.IgnoreDebug = GL_FALSE;
443 ctx->Shader.DefaultPragmas.Optimize = GL_TRUE;
444 ctx->Shader.DefaultPragmas.Debug = GL_FALSE;
Brianf2923612006-12-20 09:56:44 -0700445}
446
447
Brian5b01c5e2006-12-19 18:02:03 -0700448/**
Brian935f93f2007-03-24 16:20:02 -0600449 * Free the per-context shader-related state.
450 */
451void
452_mesa_free_shader_state(GLcontext *ctx)
453{
Brian3c008a02007-04-12 15:22:32 -0600454 _mesa_reference_shader_program(ctx, &ctx->Shader.CurrentProgram, NULL);
Brian935f93f2007-03-24 16:20:02 -0600455}
456
457
458/**
Brian5b01c5e2006-12-19 18:02:03 -0700459 * Copy string from <src> to <dst>, up to maxLength characters, returning
460 * length of <dst> in <length>.
461 * \param src the strings source
462 * \param maxLength max chars to copy
463 * \param length returns number of chars copied
464 * \param dst the string destination
465 */
Brian Paule5c69642010-03-30 19:54:02 -0600466void
467_mesa_copy_string(GLchar *dst, GLsizei maxLength,
468 GLsizei *length, const GLchar *src)
Brian5b01c5e2006-12-19 18:02:03 -0700469{
470 GLsizei len;
471 for (len = 0; len < maxLength - 1 && src && src[len]; len++)
472 dst[len] = src[len];
473 if (maxLength > 0)
474 dst[len] = 0;
475 if (length)
476 *length = len;
477}
478
479
Brian Paul7acb7c12008-07-03 13:49:48 -0600480static GLboolean
481_mesa_is_program(GLcontext *ctx, GLuint name)
482{
483 struct gl_shader_program *shProg = _mesa_lookup_shader_program(ctx, name);
484 return shProg ? GL_TRUE : GL_FALSE;
485}
486
487
488static GLboolean
489_mesa_is_shader(GLcontext *ctx, GLuint name)
490{
491 struct gl_shader *shader = _mesa_lookup_shader(ctx, name);
492 return shader ? GL_TRUE : GL_FALSE;
493}
494
495
Brian5b01c5e2006-12-19 18:02:03 -0700496/**
497 * Called via ctx->Driver.AttachShader()
498 */
Brian Paulfd59f192008-05-18 16:04:55 -0600499static void
Brian5b01c5e2006-12-19 18:02:03 -0700500_mesa_attach_shader(GLcontext *ctx, GLuint program, GLuint shader)
501{
Brian Paul530df582008-07-03 16:21:11 -0600502 struct gl_shader_program *shProg;
503 struct gl_shader *sh;
504 GLuint i, n;
Brian5b01c5e2006-12-19 18:02:03 -0700505
Brian Paul530df582008-07-03 16:21:11 -0600506 shProg = _mesa_lookup_shader_program_err(ctx, program, "glAttachShader");
507 if (!shProg)
Brian5b01c5e2006-12-19 18:02:03 -0700508 return;
Brian5b01c5e2006-12-19 18:02:03 -0700509
Brian Paul530df582008-07-03 16:21:11 -0600510 sh = _mesa_lookup_shader_err(ctx, shader, "glAttachShader");
Brian Paul7acb7c12008-07-03 13:49:48 -0600511 if (!sh) {
Brian Paul7acb7c12008-07-03 13:49:48 -0600512 return;
513 }
514
Brian237b9852007-08-07 21:48:31 +0100515 n = shProg->NumShaders;
Brian5b01c5e2006-12-19 18:02:03 -0700516 for (i = 0; i < n; i++) {
Brian65a18442006-12-19 18:46:56 -0700517 if (shProg->Shaders[i] == sh) {
Ian Romanickd806d452008-09-29 12:18:06 -0700518 /* The shader is already attched to this program. The
519 * GL_ARB_shader_objects spec says:
520 *
521 * "The error INVALID_OPERATION is generated by AttachObjectARB
522 * if <obj> is already attached to <containerObj>."
523 */
524 _mesa_error(ctx, GL_INVALID_OPERATION, "glAttachShader");
Brian5b01c5e2006-12-19 18:02:03 -0700525 return;
Brian34ae99d2006-12-18 08:28:54 -0700526 }
527 }
Brian5b01c5e2006-12-19 18:02:03 -0700528
529 /* grow list */
Brian65a18442006-12-19 18:46:56 -0700530 shProg->Shaders = (struct gl_shader **)
531 _mesa_realloc(shProg->Shaders,
532 n * sizeof(struct gl_shader *),
533 (n + 1) * sizeof(struct gl_shader *));
534 if (!shProg->Shaders) {
Brian5b01c5e2006-12-19 18:02:03 -0700535 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glAttachShader");
536 return;
537 }
538
539 /* append */
Brian3c008a02007-04-12 15:22:32 -0600540 shProg->Shaders[n] = NULL; /* since realloc() didn't zero the new space */
541 _mesa_reference_shader(ctx, &shProg->Shaders[n], sh);
Brian65a18442006-12-19 18:46:56 -0700542 shProg->NumShaders++;
Brian5b01c5e2006-12-19 18:02:03 -0700543}
544
545
Brian Paulfd59f192008-05-18 16:04:55 -0600546static GLint
Brian Paul896c0cc2008-05-16 15:47:55 -0600547_mesa_get_attrib_location(GLcontext *ctx, GLuint program,
548 const GLchar *name)
549{
550 struct gl_shader_program *shProg
Brian Paul530df582008-07-03 16:21:11 -0600551 = _mesa_lookup_shader_program_err(ctx, program, "glGetAttribLocation");
Brian Paul896c0cc2008-05-16 15:47:55 -0600552
553 if (!shProg) {
Brian Paul896c0cc2008-05-16 15:47:55 -0600554 return -1;
555 }
556
557 if (!shProg->LinkStatus) {
558 _mesa_error(ctx, GL_INVALID_OPERATION,
559 "glGetAttribLocation(program not linked)");
560 return -1;
561 }
562
563 if (!name)
564 return -1;
565
Brian Paul27341a92008-09-16 16:28:36 -0600566 if (shProg->VertexProgram) {
567 const struct gl_program_parameter_list *attribs =
568 shProg->VertexProgram->Base.Attributes;
569 if (attribs) {
570 GLint i = _mesa_lookup_parameter_index(attribs, -1, name);
571 if (i >= 0) {
572 return attribs->Parameters[i].StateIndexes[0];
573 }
Brian Paul896c0cc2008-05-16 15:47:55 -0600574 }
575 }
576 return -1;
577}
578
579
Brian Paulfd59f192008-05-18 16:04:55 -0600580static void
Brian5b01c5e2006-12-19 18:02:03 -0700581_mesa_bind_attrib_location(GLcontext *ctx, GLuint program, GLuint index,
582 const GLchar *name)
583{
Brian Paul530df582008-07-03 16:21:11 -0600584 struct gl_shader_program *shProg;
Brianb7978af2007-01-09 19:17:17 -0700585 const GLint size = -1; /* unknown size */
Brian Paul6bc87492008-07-25 08:34:54 -0600586 GLint i, oldIndex;
Brian Paul6f1abb92008-07-29 17:27:22 -0600587 GLenum datatype = GL_FLOAT_VEC4;
Brian5b01c5e2006-12-19 18:02:03 -0700588
Brian Paul530df582008-07-03 16:21:11 -0600589 shProg = _mesa_lookup_shader_program_err(ctx, program,
590 "glBindAttribLocation");
Brian65a18442006-12-19 18:46:56 -0700591 if (!shProg) {
Brian5b01c5e2006-12-19 18:02:03 -0700592 return;
593 }
594
Brian9e4bae92006-12-20 09:27:42 -0700595 if (!name)
596 return;
597
598 if (strncmp(name, "gl_", 3) == 0) {
599 _mesa_error(ctx, GL_INVALID_OPERATION,
600 "glBindAttribLocation(illegal name)");
601 return;
602 }
603
Brian Paul7acb7c12008-07-03 13:49:48 -0600604 if (index >= ctx->Const.VertexProgram.MaxAttribs) {
605 _mesa_error(ctx, GL_INVALID_VALUE, "glBindAttribLocation(index)");
606 return;
607 }
608
Brian Paul6bc87492008-07-25 08:34:54 -0600609 if (shProg->LinkStatus) {
610 /* get current index/location for the attribute */
611 oldIndex = _mesa_get_attrib_location(ctx, program, name);
612 }
613 else {
614 oldIndex = -1;
615 }
616
Brian3209c3e2007-01-09 17:49:24 -0700617 /* this will replace the current value if it's already in the list */
Brian Paulffbc66b2008-07-21 13:58:50 -0600618 i = _mesa_add_attribute(shProg->Attributes, name, size, datatype, index);
Brian3209c3e2007-01-09 17:49:24 -0700619 if (i < 0) {
620 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBindAttribLocation");
Brian Paul6f1abb92008-07-29 17:27:22 -0600621 return;
Brian3209c3e2007-01-09 17:49:24 -0700622 }
623
Brian Paul27341a92008-09-16 16:28:36 -0600624 /*
625 * Note that this attribute binding won't go into effect until
626 * glLinkProgram is called again.
627 */
Brian34ae99d2006-12-18 08:28:54 -0700628}
629
630
Brian Paulfd59f192008-05-18 16:04:55 -0600631static GLuint
Brian5b01c5e2006-12-19 18:02:03 -0700632_mesa_create_shader(GLcontext *ctx, GLenum type)
633{
Brian65a18442006-12-19 18:46:56 -0700634 struct gl_shader *sh;
Brian5b01c5e2006-12-19 18:02:03 -0700635 GLuint name;
636
637 name = _mesa_HashFindFreeKeyBlock(ctx->Shared->ShaderObjects, 1);
638
639 switch (type) {
Brian65a18442006-12-19 18:46:56 -0700640 case GL_FRAGMENT_SHADER:
641 case GL_VERTEX_SHADER:
642 sh = _mesa_new_shader(ctx, name, type);
Brian5b01c5e2006-12-19 18:02:03 -0700643 break;
644 default:
645 _mesa_error(ctx, GL_INVALID_ENUM, "CreateShader(type)");
646 return 0;
647 }
648
Brian65a18442006-12-19 18:46:56 -0700649 _mesa_HashInsert(ctx->Shared->ShaderObjects, name, sh);
Brian5b01c5e2006-12-19 18:02:03 -0700650
651 return name;
652}
653
654
Brian Paulfd59f192008-05-18 16:04:55 -0600655static GLuint
Brian5b01c5e2006-12-19 18:02:03 -0700656_mesa_create_program(GLcontext *ctx)
657{
658 GLuint name;
Brian65a18442006-12-19 18:46:56 -0700659 struct gl_shader_program *shProg;
Brian5b01c5e2006-12-19 18:02:03 -0700660
Xiang, Haihaoaef47c42008-03-31 16:27:47 +0800661 name = _mesa_HashFindFreeKeyBlock(ctx->Shared->ShaderObjects, 1);
Brian65a18442006-12-19 18:46:56 -0700662 shProg = _mesa_new_shader_program(ctx, name);
Brian5b01c5e2006-12-19 18:02:03 -0700663
Xiang, Haihaoaef47c42008-03-31 16:27:47 +0800664 _mesa_HashInsert(ctx->Shared->ShaderObjects, name, shProg);
Brian5b01c5e2006-12-19 18:02:03 -0700665
Brian3c008a02007-04-12 15:22:32 -0600666 assert(shProg->RefCount == 1);
667
Brian5b01c5e2006-12-19 18:02:03 -0700668 return name;
669}
670
671
Brian3c008a02007-04-12 15:22:32 -0600672/**
673 * Named w/ "2" to indicate OpenGL 2.x vs GL_ARB_fragment_programs's
674 * DeleteProgramARB.
675 */
Brian Paulfd59f192008-05-18 16:04:55 -0600676static void
Brian5b01c5e2006-12-19 18:02:03 -0700677_mesa_delete_program2(GLcontext *ctx, GLuint name)
678{
Brian3c008a02007-04-12 15:22:32 -0600679 /*
680 * NOTE: deleting shaders/programs works a bit differently than
681 * texture objects (and buffer objects, etc). Shader/program
682 * handles/IDs exist in the hash table until the object is really
683 * deleted (refcount==0). With texture objects, the handle/ID is
684 * removed from the hash table in glDeleteTextures() while the tex
685 * object itself might linger until its refcount goes to zero.
686 */
Brian65a18442006-12-19 18:46:56 -0700687 struct gl_shader_program *shProg;
Brian5b01c5e2006-12-19 18:02:03 -0700688
Brian Paul530df582008-07-03 16:21:11 -0600689 shProg = _mesa_lookup_shader_program_err(ctx, name, "glDeleteProgram");
690 if (!shProg)
Brian5b01c5e2006-12-19 18:02:03 -0700691 return;
Brian5b01c5e2006-12-19 18:02:03 -0700692
Brian9e4bae92006-12-20 09:27:42 -0700693 shProg->DeletePending = GL_TRUE;
694
Brian3c008a02007-04-12 15:22:32 -0600695 /* effectively, decr shProg's refcount */
696 _mesa_reference_shader_program(ctx, &shProg, NULL);
Brian5b01c5e2006-12-19 18:02:03 -0700697}
698
699
Brian Paulfd59f192008-05-18 16:04:55 -0600700static void
Brian5b01c5e2006-12-19 18:02:03 -0700701_mesa_delete_shader(GLcontext *ctx, GLuint shader)
702{
Brian Paul530df582008-07-03 16:21:11 -0600703 struct gl_shader *sh;
704
705 sh = _mesa_lookup_shader_err(ctx, shader, "glDeleteShader");
706 if (!sh)
Brian9e4bae92006-12-20 09:27:42 -0700707 return;
Brian5b01c5e2006-12-19 18:02:03 -0700708
Brian9e4bae92006-12-20 09:27:42 -0700709 sh->DeletePending = GL_TRUE;
Brian3c008a02007-04-12 15:22:32 -0600710
711 /* effectively, decr sh's refcount */
712 _mesa_reference_shader(ctx, &sh, NULL);
Brian5b01c5e2006-12-19 18:02:03 -0700713}
714
715
Brian Paulfd59f192008-05-18 16:04:55 -0600716static void
Brian5b01c5e2006-12-19 18:02:03 -0700717_mesa_detach_shader(GLcontext *ctx, GLuint program, GLuint shader)
718{
Brian Paul530df582008-07-03 16:21:11 -0600719 struct gl_shader_program *shProg;
Brian237b9852007-08-07 21:48:31 +0100720 GLuint n;
Brian5b01c5e2006-12-19 18:02:03 -0700721 GLuint i, j;
722
Brian Paul530df582008-07-03 16:21:11 -0600723 shProg = _mesa_lookup_shader_program_err(ctx, program, "glDetachShader");
724 if (!shProg)
Brian5b01c5e2006-12-19 18:02:03 -0700725 return;
Brian5b01c5e2006-12-19 18:02:03 -0700726
Brian237b9852007-08-07 21:48:31 +0100727 n = shProg->NumShaders;
728
Brian5b01c5e2006-12-19 18:02:03 -0700729 for (i = 0; i < n; i++) {
Brian65a18442006-12-19 18:46:56 -0700730 if (shProg->Shaders[i]->Name == shader) {
Brian5b01c5e2006-12-19 18:02:03 -0700731 /* found it */
Brian3c008a02007-04-12 15:22:32 -0600732 struct gl_shader **newList;
Brian9e4bae92006-12-20 09:27:42 -0700733
Brian Paul530df582008-07-03 16:21:11 -0600734 /* release */
Brian3c008a02007-04-12 15:22:32 -0600735 _mesa_reference_shader(ctx, &shProg->Shaders[i], NULL);
Brian9e4bae92006-12-20 09:27:42 -0700736
Brian5b01c5e2006-12-19 18:02:03 -0700737 /* alloc new, smaller array */
Brian65a18442006-12-19 18:46:56 -0700738 newList = (struct gl_shader **)
Kristian Høgsberg32f2fd12010-02-19 11:58:49 -0500739 malloc((n - 1) * sizeof(struct gl_shader *));
Brian5b01c5e2006-12-19 18:02:03 -0700740 if (!newList) {
741 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glDetachShader");
742 return;
743 }
744 for (j = 0; j < i; j++) {
Brian65a18442006-12-19 18:46:56 -0700745 newList[j] = shProg->Shaders[j];
Brian5b01c5e2006-12-19 18:02:03 -0700746 }
747 while (++i < n)
Brian65a18442006-12-19 18:46:56 -0700748 newList[j++] = shProg->Shaders[i];
Kristian Høgsberg32f2fd12010-02-19 11:58:49 -0500749 free(shProg->Shaders);
Brian5b01c5e2006-12-19 18:02:03 -0700750
Brian65a18442006-12-19 18:46:56 -0700751 shProg->Shaders = newList;
Brianbac15c82007-04-18 14:55:18 -0600752 shProg->NumShaders = n - 1;
Brianaaa57412007-04-18 15:22:43 -0600753
754#ifdef DEBUG
755 /* sanity check */
756 {
757 for (j = 0; j < shProg->NumShaders; j++) {
758 assert(shProg->Shaders[j]->Type == GL_VERTEX_SHADER ||
759 shProg->Shaders[j]->Type == GL_FRAGMENT_SHADER);
760 assert(shProg->Shaders[j]->RefCount > 0);
761 }
762 }
763#endif
764
Brian5b01c5e2006-12-19 18:02:03 -0700765 return;
766 }
767 }
768
769 /* not found */
Brian Paul530df582008-07-03 16:21:11 -0600770 {
771 GLenum err;
772 if (_mesa_is_shader(ctx, shader))
773 err = GL_INVALID_OPERATION;
774 else if (_mesa_is_program(ctx, shader))
775 err = GL_INVALID_OPERATION;
776 else
777 err = GL_INVALID_VALUE;
778 _mesa_error(ctx, err, "glDetachProgram(shader)");
779 return;
780 }
Brian5b01c5e2006-12-19 18:02:03 -0700781}
782
783
Brian Paul1a148662010-04-01 22:15:16 -0600784/**
785 * Return the size of the given GLSL datatype, in floats (components).
786 */
787GLint
788_mesa_sizeof_glsl_type(GLenum type)
Brian Paulffbc66b2008-07-21 13:58:50 -0600789{
790 switch (type) {
791 case GL_FLOAT:
792 case GL_INT:
793 case GL_BOOL:
Brian Paul8c51e002008-08-11 15:09:47 -0600794 case GL_SAMPLER_1D:
795 case GL_SAMPLER_2D:
796 case GL_SAMPLER_3D:
797 case GL_SAMPLER_CUBE:
798 case GL_SAMPLER_1D_SHADOW:
799 case GL_SAMPLER_2D_SHADOW:
800 case GL_SAMPLER_2D_RECT_ARB:
801 case GL_SAMPLER_2D_RECT_SHADOW_ARB:
Brian Paulac498f22010-02-25 19:05:11 -0700802 case GL_SAMPLER_1D_ARRAY_EXT:
803 case GL_SAMPLER_2D_ARRAY_EXT:
Brian Paul8c51e002008-08-11 15:09:47 -0600804 case GL_SAMPLER_1D_ARRAY_SHADOW_EXT:
805 case GL_SAMPLER_2D_ARRAY_SHADOW_EXT:
806 case GL_SAMPLER_CUBE_SHADOW_EXT:
Brian Paulffbc66b2008-07-21 13:58:50 -0600807 return 1;
808 case GL_FLOAT_VEC2:
809 case GL_INT_VEC2:
Brian Paul91f841a2010-05-25 18:39:47 -0600810 case GL_UNSIGNED_INT_VEC2:
Brian Paulffbc66b2008-07-21 13:58:50 -0600811 case GL_BOOL_VEC2:
812 return 2;
813 case GL_FLOAT_VEC3:
814 case GL_INT_VEC3:
Brian Paul91f841a2010-05-25 18:39:47 -0600815 case GL_UNSIGNED_INT_VEC3:
Brian Paulffbc66b2008-07-21 13:58:50 -0600816 case GL_BOOL_VEC3:
817 return 3;
818 case GL_FLOAT_VEC4:
819 case GL_INT_VEC4:
Brian Paul91f841a2010-05-25 18:39:47 -0600820 case GL_UNSIGNED_INT_VEC4:
Brian Paulffbc66b2008-07-21 13:58:50 -0600821 case GL_BOOL_VEC4:
822 return 4;
823 case GL_FLOAT_MAT2:
824 case GL_FLOAT_MAT2x3:
825 case GL_FLOAT_MAT2x4:
826 return 8; /* two float[4] vectors */
827 case GL_FLOAT_MAT3:
828 case GL_FLOAT_MAT3x2:
829 case GL_FLOAT_MAT3x4:
830 return 12; /* three float[4] vectors */
831 case GL_FLOAT_MAT4:
832 case GL_FLOAT_MAT4x2:
833 case GL_FLOAT_MAT4x3:
834 return 16; /* four float[4] vectors */
835 default:
Brian Paul1a148662010-04-01 22:15:16 -0600836 _mesa_problem(NULL, "Invalid type in _mesa_sizeof_glsl_type()");
Brian Paulffbc66b2008-07-21 13:58:50 -0600837 return 1;
838 }
839}
840
841
Brian Paulfd59f192008-05-18 16:04:55 -0600842static void
Brian5b01c5e2006-12-19 18:02:03 -0700843_mesa_get_active_attrib(GLcontext *ctx, GLuint program, GLuint index,
844 GLsizei maxLength, GLsizei *length, GLint *size,
845 GLenum *type, GLchar *nameOut)
846{
Brian Paul27341a92008-09-16 16:28:36 -0600847 const struct gl_program_parameter_list *attribs = NULL;
Brian Paul530df582008-07-03 16:21:11 -0600848 struct gl_shader_program *shProg;
Brian5b01c5e2006-12-19 18:02:03 -0700849
Brian Paul530df582008-07-03 16:21:11 -0600850 shProg = _mesa_lookup_shader_program_err(ctx, program, "glGetActiveAttrib");
851 if (!shProg)
Brian5b01c5e2006-12-19 18:02:03 -0700852 return;
Brian5b01c5e2006-12-19 18:02:03 -0700853
Brian Paul27341a92008-09-16 16:28:36 -0600854 if (shProg->VertexProgram)
855 attribs = shProg->VertexProgram->Base.Attributes;
856
857 if (!attribs || index >= attribs->NumParameters) {
Brianaaa57412007-04-18 15:22:43 -0600858 _mesa_error(ctx, GL_INVALID_VALUE, "glGetActiveAttrib(index)");
Brian5b01c5e2006-12-19 18:02:03 -0700859 return;
860 }
861
Brian Paule5c69642010-03-30 19:54:02 -0600862 _mesa_copy_string(nameOut, maxLength, length,
863 attribs->Parameters[index].Name);
Brian Paul27341a92008-09-16 16:28:36 -0600864
Brian5b01c5e2006-12-19 18:02:03 -0700865 if (size)
Brian Paul27341a92008-09-16 16:28:36 -0600866 *size = attribs->Parameters[index].Size
Brian Paul1a148662010-04-01 22:15:16 -0600867 / _mesa_sizeof_glsl_type(attribs->Parameters[index].DataType);
Brian Paul27341a92008-09-16 16:28:36 -0600868
Brian Paulade50832008-05-14 16:09:46 -0600869 if (type)
Brian Paul27341a92008-09-16 16:28:36 -0600870 *type = attribs->Parameters[index].DataType;
Brian5b01c5e2006-12-19 18:02:03 -0700871}
872
873
Brian5b01c5e2006-12-19 18:02:03 -0700874/**
875 * Called via ctx->Driver.GetAttachedShaders().
876 */
Brian Paulfd59f192008-05-18 16:04:55 -0600877static void
Brian5b01c5e2006-12-19 18:02:03 -0700878_mesa_get_attached_shaders(GLcontext *ctx, GLuint program, GLsizei maxCount,
879 GLsizei *count, GLuint *obj)
880{
Brian Paul530df582008-07-03 16:21:11 -0600881 struct gl_shader_program *shProg =
882 _mesa_lookup_shader_program_err(ctx, program, "glGetAttachedShaders");
Brian65a18442006-12-19 18:46:56 -0700883 if (shProg) {
Brian Paul530df582008-07-03 16:21:11 -0600884 GLuint i;
885 for (i = 0; i < (GLuint) maxCount && i < shProg->NumShaders; i++) {
Brian65a18442006-12-19 18:46:56 -0700886 obj[i] = shProg->Shaders[i]->Name;
Brian5b01c5e2006-12-19 18:02:03 -0700887 }
888 if (count)
889 *count = i;
890 }
Brian5b01c5e2006-12-19 18:02:03 -0700891}
892
893
Brian Pauleb88c022010-05-26 22:40:38 -0600894/** glGetHandleARB() - return ID/name of currently bound shader program */
Brian Paulfd59f192008-05-18 16:04:55 -0600895static GLuint
Brian5b01c5e2006-12-19 18:02:03 -0700896_mesa_get_handle(GLcontext *ctx, GLenum pname)
Brian34ae99d2006-12-18 08:28:54 -0700897{
Ian Romanick905d8e02008-09-29 12:27:00 -0700898 if (pname == GL_PROGRAM_OBJECT_ARB) {
Brian Pauleb88c022010-05-26 22:40:38 -0600899 if (ctx->Shader.CurrentProgram)
900 return ctx->Shader.CurrentProgram->Name;
901 else
902 return 0;
Brian34ae99d2006-12-18 08:28:54 -0700903 }
Brian Pauleb88c022010-05-26 22:40:38 -0600904 else {
905 _mesa_error(ctx, GL_INVALID_ENUM, "glGetHandleARB");
906 return 0;
907 }
Brian34ae99d2006-12-18 08:28:54 -0700908}
909
910
Brian Pauleb88c022010-05-26 22:40:38 -0600911/**
912 * glGetProgramiv() - get shader program state.
913 * Note that this is for GLSL shader programs, not ARB vertex/fragment
914 * programs (see glGetProgramivARB).
915 */
Brian Paulfd59f192008-05-18 16:04:55 -0600916static void
Brian5b01c5e2006-12-19 18:02:03 -0700917_mesa_get_programiv(GLcontext *ctx, GLuint program,
918 GLenum pname, GLint *params)
Brian34ae99d2006-12-18 08:28:54 -0700919{
Brian Paul27341a92008-09-16 16:28:36 -0600920 const struct gl_program_parameter_list *attribs;
Brian65a18442006-12-19 18:46:56 -0700921 struct gl_shader_program *shProg
922 = _mesa_lookup_shader_program(ctx, program);
Brian34ae99d2006-12-18 08:28:54 -0700923
Brian65a18442006-12-19 18:46:56 -0700924 if (!shProg) {
Brian5b01c5e2006-12-19 18:02:03 -0700925 _mesa_error(ctx, GL_INVALID_VALUE, "glGetProgramiv(program)");
Brian34ae99d2006-12-18 08:28:54 -0700926 return;
927 }
928
Brian Paul27341a92008-09-16 16:28:36 -0600929 if (shProg->VertexProgram)
930 attribs = shProg->VertexProgram->Base.Attributes;
931 else
932 attribs = NULL;
933
Brian5b01c5e2006-12-19 18:02:03 -0700934 switch (pname) {
935 case GL_DELETE_STATUS:
Brian65a18442006-12-19 18:46:56 -0700936 *params = shProg->DeletePending;
Brian5b01c5e2006-12-19 18:02:03 -0700937 break;
938 case GL_LINK_STATUS:
Brian65a18442006-12-19 18:46:56 -0700939 *params = shProg->LinkStatus;
Brian34ae99d2006-12-18 08:28:54 -0700940 break;
Brian5b01c5e2006-12-19 18:02:03 -0700941 case GL_VALIDATE_STATUS:
Brian65a18442006-12-19 18:46:56 -0700942 *params = shProg->Validated;
Brian5b01c5e2006-12-19 18:02:03 -0700943 break;
944 case GL_INFO_LOG_LENGTH:
Jan Dvorak5a0f02a2007-07-13 16:36:00 -0600945 *params = shProg->InfoLog ? strlen(shProg->InfoLog) + 1 : 0;
Brian5b01c5e2006-12-19 18:02:03 -0700946 break;
947 case GL_ATTACHED_SHADERS:
Brian65a18442006-12-19 18:46:56 -0700948 *params = shProg->NumShaders;
Brian5b01c5e2006-12-19 18:02:03 -0700949 break;
950 case GL_ACTIVE_ATTRIBUTES:
Brian Paul27341a92008-09-16 16:28:36 -0600951 *params = attribs ? attribs->NumParameters : 0;
Brian5b01c5e2006-12-19 18:02:03 -0700952 break;
953 case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH:
Brian Paul27341a92008-09-16 16:28:36 -0600954 *params = _mesa_longest_parameter_name(attribs, PROGRAM_INPUT) + 1;
Brian5b01c5e2006-12-19 18:02:03 -0700955 break;
956 case GL_ACTIVE_UNIFORMS:
Brian Paulade50832008-05-14 16:09:46 -0600957 *params = shProg->Uniforms ? shProg->Uniforms->NumUniforms : 0;
Brian5b01c5e2006-12-19 18:02:03 -0700958 break;
959 case GL_ACTIVE_UNIFORM_MAX_LENGTH:
Brian Paulade50832008-05-14 16:09:46 -0600960 *params = _mesa_longest_uniform_name(shProg->Uniforms);
Brian274ac7a2007-04-18 16:05:53 -0600961 if (*params > 0)
962 (*params)++; /* add one for terminating zero */
Brian34ae99d2006-12-18 08:28:54 -0700963 break;
Brian Paulbda6ad22008-08-06 12:45:14 -0600964 case GL_PROGRAM_BINARY_LENGTH_OES:
965 *params = 0;
966 break;
Brian Paule5c69642010-03-30 19:54:02 -0600967#if FEATURE_EXT_transform_feedback
968 case GL_TRANSFORM_FEEDBACK_VARYINGS:
969 *params = shProg->TransformFeedback.NumVarying;
970 break;
971 case GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH:
972 *params = longest_feedback_varying_name(shProg) + 1;
973 break;
974 case GL_TRANSFORM_FEEDBACK_BUFFER_MODE:
975 *params = shProg->TransformFeedback.BufferMode;
976 break;
977#endif
Brian34ae99d2006-12-18 08:28:54 -0700978 default:
Brian5b01c5e2006-12-19 18:02:03 -0700979 _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramiv(pname)");
980 return;
Brian34ae99d2006-12-18 08:28:54 -0700981 }
Brian5b01c5e2006-12-19 18:02:03 -0700982}
Brian34ae99d2006-12-18 08:28:54 -0700983
Brian34ae99d2006-12-18 08:28:54 -0700984
Brian Pauleb88c022010-05-26 22:40:38 -0600985/** glGetShaderiv() - get GLSL shader state */
Brian Paulfd59f192008-05-18 16:04:55 -0600986static void
Brian5b01c5e2006-12-19 18:02:03 -0700987_mesa_get_shaderiv(GLcontext *ctx, GLuint name, GLenum pname, GLint *params)
988{
Brian Paul530df582008-07-03 16:21:11 -0600989 struct gl_shader *shader = _mesa_lookup_shader_err(ctx, name, "glGetShaderiv");
Brian5b01c5e2006-12-19 18:02:03 -0700990
991 if (!shader) {
Brian5b01c5e2006-12-19 18:02:03 -0700992 return;
993 }
Brian65a18442006-12-19 18:46:56 -0700994
Brian5b01c5e2006-12-19 18:02:03 -0700995 switch (pname) {
996 case GL_SHADER_TYPE:
997 *params = shader->Type;
998 break;
999 case GL_DELETE_STATUS:
1000 *params = shader->DeletePending;
1001 break;
1002 case GL_COMPILE_STATUS:
1003 *params = shader->CompileStatus;
1004 break;
1005 case GL_INFO_LOG_LENGTH:
Jan Dvorak5a0f02a2007-07-13 16:36:00 -06001006 *params = shader->InfoLog ? strlen(shader->InfoLog) + 1 : 0;
Brian5b01c5e2006-12-19 18:02:03 -07001007 break;
1008 case GL_SHADER_SOURCE_LENGTH:
Jan Dvorak5a0f02a2007-07-13 16:36:00 -06001009 *params = shader->Source ? strlen((char *) shader->Source) + 1 : 0;
Brian5b01c5e2006-12-19 18:02:03 -07001010 break;
1011 default:
1012 _mesa_error(ctx, GL_INVALID_ENUM, "glGetShaderiv(pname)");
1013 return;
1014 }
1015}
1016
1017
Brian Paulfd59f192008-05-18 16:04:55 -06001018static void
Brian5b01c5e2006-12-19 18:02:03 -07001019_mesa_get_program_info_log(GLcontext *ctx, GLuint program, GLsizei bufSize,
1020 GLsizei *length, GLchar *infoLog)
1021{
Brian65a18442006-12-19 18:46:56 -07001022 struct gl_shader_program *shProg
1023 = _mesa_lookup_shader_program(ctx, program);
1024 if (!shProg) {
Brian5b01c5e2006-12-19 18:02:03 -07001025 _mesa_error(ctx, GL_INVALID_VALUE, "glGetProgramInfoLog(program)");
1026 return;
1027 }
Brian Paule5c69642010-03-30 19:54:02 -06001028 _mesa_copy_string(infoLog, bufSize, length, shProg->InfoLog);
Brian5b01c5e2006-12-19 18:02:03 -07001029}
1030
1031
Brian Paulfd59f192008-05-18 16:04:55 -06001032static void
Brian5b01c5e2006-12-19 18:02:03 -07001033_mesa_get_shader_info_log(GLcontext *ctx, GLuint shader, GLsizei bufSize,
1034 GLsizei *length, GLchar *infoLog)
1035{
Brian65a18442006-12-19 18:46:56 -07001036 struct gl_shader *sh = _mesa_lookup_shader(ctx, shader);
1037 if (!sh) {
Brian5b01c5e2006-12-19 18:02:03 -07001038 _mesa_error(ctx, GL_INVALID_VALUE, "glGetShaderInfoLog(shader)");
1039 return;
1040 }
Brian Paule5c69642010-03-30 19:54:02 -06001041 _mesa_copy_string(infoLog, bufSize, length, sh->InfoLog);
Brian5b01c5e2006-12-19 18:02:03 -07001042}
1043
1044
1045/**
1046 * Called via ctx->Driver.GetShaderSource().
1047 */
Brian Paulfd59f192008-05-18 16:04:55 -06001048static void
Brian5b01c5e2006-12-19 18:02:03 -07001049_mesa_get_shader_source(GLcontext *ctx, GLuint shader, GLsizei maxLength,
1050 GLsizei *length, GLchar *sourceOut)
1051{
Brian Paul530df582008-07-03 16:21:11 -06001052 struct gl_shader *sh;
1053 sh = _mesa_lookup_shader_err(ctx, shader, "glGetShaderSource");
Brian65a18442006-12-19 18:46:56 -07001054 if (!sh) {
Brian5b01c5e2006-12-19 18:02:03 -07001055 return;
1056 }
Brian Paule5c69642010-03-30 19:54:02 -06001057 _mesa_copy_string(sourceOut, maxLength, length, sh->Source);
Brian5b01c5e2006-12-19 18:02:03 -07001058}
1059
1060
Brian5b01c5e2006-12-19 18:02:03 -07001061/**
1062 * Called via ctx->Driver.ShaderSource()
1063 */
Brian Paulfd59f192008-05-18 16:04:55 -06001064static void
Brian5b01c5e2006-12-19 18:02:03 -07001065_mesa_shader_source(GLcontext *ctx, GLuint shader, const GLchar *source)
Brian34ae99d2006-12-18 08:28:54 -07001066{
Brian Paul530df582008-07-03 16:21:11 -06001067 struct gl_shader *sh;
1068
1069 sh = _mesa_lookup_shader_err(ctx, shader, "glShaderSource");
1070 if (!sh)
Brian34ae99d2006-12-18 08:28:54 -07001071 return;
Brian34ae99d2006-12-18 08:28:54 -07001072
Brian34ae99d2006-12-18 08:28:54 -07001073 /* free old shader source string and install new one */
Brian65a18442006-12-19 18:46:56 -07001074 if (sh->Source) {
Kristian Høgsberg32f2fd12010-02-19 11:58:49 -05001075 free((void *) sh->Source);
Brian34ae99d2006-12-18 08:28:54 -07001076 }
Brian65a18442006-12-19 18:46:56 -07001077 sh->Source = source;
Brian9e4bae92006-12-20 09:27:42 -07001078 sh->CompileStatus = GL_FALSE;
Brian Paulf7783ba2009-08-04 15:35:48 -06001079#ifdef DEBUG
1080 sh->SourceChecksum = _mesa_str_checksum(sh->Source);
1081#endif
Brian34ae99d2006-12-18 08:28:54 -07001082}
1083
1084
Brian5b01c5e2006-12-19 18:02:03 -07001085/**
1086 * Called via ctx->Driver.CompileShader()
1087 */
Brian Paulfd59f192008-05-18 16:04:55 -06001088static void
Brian5b01c5e2006-12-19 18:02:03 -07001089_mesa_compile_shader(GLcontext *ctx, GLuint shaderObj)
Brian34ae99d2006-12-18 08:28:54 -07001090{
Brian Paul530df582008-07-03 16:21:11 -06001091 struct gl_shader *sh;
Brian34ae99d2006-12-18 08:28:54 -07001092
Brian Paul530df582008-07-03 16:21:11 -06001093 sh = _mesa_lookup_shader_err(ctx, shaderObj, "glCompileShader");
1094 if (!sh)
Brian34ae99d2006-12-18 08:28:54 -07001095 return;
Brian34ae99d2006-12-18 08:28:54 -07001096
Brian Paul65fc2ca2009-03-19 10:25:24 -06001097 /* set default pragma state for shader */
1098 sh->Pragmas = ctx->Shader.DefaultPragmas;
1099
Brian Paulcb136e02009-01-22 10:34:15 -07001100 /* this call will set the sh->CompileStatus field to indicate if
1101 * compilation was successful.
1102 */
1103 (void) _slang_compile(ctx, sh);
Brian34ae99d2006-12-18 08:28:54 -07001104}
1105
1106
Brian5b01c5e2006-12-19 18:02:03 -07001107/**
1108 * Called via ctx->Driver.LinkProgram()
1109 */
Brian Paulfd59f192008-05-18 16:04:55 -06001110static void
Brian5b01c5e2006-12-19 18:02:03 -07001111_mesa_link_program(GLcontext *ctx, GLuint program)
Brian34ae99d2006-12-18 08:28:54 -07001112{
Brian65a18442006-12-19 18:46:56 -07001113 struct gl_shader_program *shProg;
Brian Paulfef6e362010-05-10 21:11:21 -06001114 struct gl_transform_feedback_object *obj =
1115 ctx->TransformFeedback.CurrentObject;
Brian34ae99d2006-12-18 08:28:54 -07001116
Brian Paul530df582008-07-03 16:21:11 -06001117 shProg = _mesa_lookup_shader_program_err(ctx, program, "glLinkProgram");
1118 if (!shProg)
Brian34ae99d2006-12-18 08:28:54 -07001119 return;
Brian34ae99d2006-12-18 08:28:54 -07001120
Brian Paulfef6e362010-05-10 21:11:21 -06001121 if (obj->Active && shProg == ctx->Shader.CurrentProgram) {
Brian Paul1a148662010-04-01 22:15:16 -06001122 _mesa_error(ctx, GL_INVALID_OPERATION,
1123 "glLinkProgram(transform feedback active");
1124 return;
1125 }
1126
Briandf43fb62008-05-06 23:08:51 -06001127 FLUSH_VERTICES(ctx, _NEW_PROGRAM);
1128
Brianc1771912007-02-16 09:56:19 -07001129 _slang_link(ctx, program, shProg);
Brian Paulac3c8e32009-09-14 17:32:03 -06001130
1131 /* debug code */
1132 if (0) {
1133 GLuint i;
1134
Kristian Høgsberg298be2b2010-02-19 12:32:24 -05001135 printf("Link %u shaders in program %u: %s\n",
Brian Paulac3c8e32009-09-14 17:32:03 -06001136 shProg->NumShaders, shProg->Name,
1137 shProg->LinkStatus ? "Success" : "Failed");
1138
1139 for (i = 0; i < shProg->NumShaders; i++) {
Kristian Høgsberg298be2b2010-02-19 12:32:24 -05001140 printf(" shader %u, type 0x%x\n",
Brian Paulac3c8e32009-09-14 17:32:03 -06001141 shProg->Shaders[i]->Name,
1142 shProg->Shaders[i]->Type);
1143 }
1144 }
Brian34ae99d2006-12-18 08:28:54 -07001145}
1146
1147
1148/**
Brian Paul346250b2009-10-23 16:31:48 -06001149 * Print basic shader info (for debug).
1150 */
1151static void
1152print_shader_info(const struct gl_shader_program *shProg)
1153{
1154 GLuint i;
1155
Kristian Høgsberg298be2b2010-02-19 12:32:24 -05001156 printf("Mesa: glUseProgram(%u)\n", shProg->Name);
Brian Paul346250b2009-10-23 16:31:48 -06001157 for (i = 0; i < shProg->NumShaders; i++) {
1158 const char *s;
1159 switch (shProg->Shaders[i]->Type) {
1160 case GL_VERTEX_SHADER:
1161 s = "vertex";
1162 break;
1163 case GL_FRAGMENT_SHADER:
1164 s = "fragment";
1165 break;
1166 case GL_GEOMETRY_SHADER:
1167 s = "geometry";
1168 break;
1169 default:
1170 s = "";
1171 }
Kristian Høgsberg298be2b2010-02-19 12:32:24 -05001172 printf(" %s shader %u, checksum %u\n", s,
1173 shProg->Shaders[i]->Name,
1174 shProg->Shaders[i]->SourceChecksum);
Brian Paul346250b2009-10-23 16:31:48 -06001175 }
1176 if (shProg->VertexProgram)
Kristian Høgsberg298be2b2010-02-19 12:32:24 -05001177 printf(" vert prog %u\n", shProg->VertexProgram->Base.Id);
Brian Paul346250b2009-10-23 16:31:48 -06001178 if (shProg->FragmentProgram)
Kristian Høgsberg298be2b2010-02-19 12:32:24 -05001179 printf(" frag prog %u\n", shProg->FragmentProgram->Base.Id);
Brian Paul346250b2009-10-23 16:31:48 -06001180}
1181
1182
1183/**
Brian5b01c5e2006-12-19 18:02:03 -07001184 * Called via ctx->Driver.UseProgram()
Brian34ae99d2006-12-18 08:28:54 -07001185 */
Brian5b01c5e2006-12-19 18:02:03 -07001186void
1187_mesa_use_program(GLcontext *ctx, GLuint program)
Brian34ae99d2006-12-18 08:28:54 -07001188{
Brian3c008a02007-04-12 15:22:32 -06001189 struct gl_shader_program *shProg;
Brian Paulfef6e362010-05-10 21:11:21 -06001190 struct gl_transform_feedback_object *obj =
1191 ctx->TransformFeedback.CurrentObject;
Brian3c008a02007-04-12 15:22:32 -06001192
Brian Paulfef6e362010-05-10 21:11:21 -06001193 if (obj->Active) {
Brian Paul1a148662010-04-01 22:15:16 -06001194 _mesa_error(ctx, GL_INVALID_OPERATION,
1195 "glUseProgram(transform feedback active)");
1196 return;
1197 }
1198
Brian00d63aa2007-02-03 11:35:02 -07001199 if (ctx->Shader.CurrentProgram &&
1200 ctx->Shader.CurrentProgram->Name == program) {
1201 /* no-op */
1202 return;
1203 }
1204
Brian5b01c5e2006-12-19 18:02:03 -07001205 if (program) {
Brian Paul530df582008-07-03 16:21:11 -06001206 shProg = _mesa_lookup_shader_program_err(ctx, program, "glUseProgram");
Brian65a18442006-12-19 18:46:56 -07001207 if (!shProg) {
Brian Paul530df582008-07-03 16:21:11 -06001208 return;
1209 }
1210 if (!shProg->LinkStatus) {
Brian Paul621c9992009-02-18 13:28:12 -07001211 _mesa_error(ctx, GL_INVALID_OPERATION,
1212 "glUseProgram(program %u not linked)", program);
Brian5b01c5e2006-12-19 18:02:03 -07001213 return;
1214 }
Brian Paul4eda17d2009-03-13 09:11:42 -06001215
1216 /* debug code */
Brian Paul2ee7fd82009-10-15 15:25:52 -06001217 if (ctx->Shader.Flags & GLSL_USE_PROG) {
Brian Paul346250b2009-10-23 16:31:48 -06001218 print_shader_info(shProg);
Brian Paul4eda17d2009-03-13 09:11:42 -06001219 }
Brian5b01c5e2006-12-19 18:02:03 -07001220 }
1221 else {
Brian3c008a02007-04-12 15:22:32 -06001222 shProg = NULL;
1223 }
1224
Brian Paulb44304e2009-10-27 20:09:33 -06001225 if (ctx->Shader.CurrentProgram != shProg) {
1226 FLUSH_VERTICES(ctx, _NEW_PROGRAM | _NEW_PROGRAM_CONSTANTS);
1227 _mesa_reference_shader_program(ctx, &ctx->Shader.CurrentProgram, shProg);
1228 }
Brian5b01c5e2006-12-19 18:02:03 -07001229}
Brian34ae99d2006-12-18 08:28:54 -07001230
Brian5b01c5e2006-12-19 18:02:03 -07001231
Brian Paulade50832008-05-14 16:09:46 -06001232
1233/**
Brian Paul517401a2008-11-06 15:04:11 -07001234 * Update the vertex/fragment program's TexturesUsed array.
1235 *
1236 * This needs to be called after glUniform(set sampler var) is called.
1237 * A call to glUniform(samplerVar, value) causes a sampler to point to a
1238 * particular texture unit. We know the sampler's texture target
1239 * (1D/2D/3D/etc) from compile time but the sampler's texture unit is
1240 * set by glUniform() calls.
1241 *
1242 * So, scan the program->SamplerUnits[] and program->SamplerTargets[]
1243 * information to update the prog->TexturesUsed[] values.
1244 * Each value of TexturesUsed[unit] is one of zero, TEXTURE_1D_INDEX,
1245 * TEXTURE_2D_INDEX, TEXTURE_3D_INDEX, etc.
1246 * We'll use that info for state validation before rendering.
Brian Paulade50832008-05-14 16:09:46 -06001247 */
Brian Paul517401a2008-11-06 15:04:11 -07001248void
1249_mesa_update_shader_textures_used(struct gl_program *prog)
Brian Paulade50832008-05-14 16:09:46 -06001250{
1251 GLuint s;
1252
1253 memset(prog->TexturesUsed, 0, sizeof(prog->TexturesUsed));
1254
1255 for (s = 0; s < MAX_SAMPLERS; s++) {
1256 if (prog->SamplersUsed & (1 << s)) {
Brian Paulf05344f2009-08-26 10:58:06 -06001257 GLuint unit = prog->SamplerUnits[s];
1258 GLuint tgt = prog->SamplerTargets[s];
1259 assert(unit < MAX_TEXTURE_IMAGE_UNITS);
1260 assert(tgt < NUM_TEXTURE_TARGETS);
1261 prog->TexturesUsed[unit] |= (1 << tgt);
Brian Paulade50832008-05-14 16:09:46 -06001262 }
1263 }
1264}
1265
1266
1267/**
Brian Paulc90fca32009-08-25 17:42:47 -06001268 * Validate a program's samplers.
1269 * Specifically, check that there aren't two samplers of different types
1270 * pointing to the same texture unit.
1271 * \return GL_TRUE if valid, GL_FALSE if invalid
1272 */
1273static GLboolean
1274validate_samplers(GLcontext *ctx, const struct gl_program *prog, char *errMsg)
Brian34ae99d2006-12-18 08:28:54 -07001275{
Brian Paulc90fca32009-08-25 17:42:47 -06001276 static const char *targetName[] = {
1277 "TEXTURE_2D_ARRAY",
1278 "TEXTURE_1D_ARRAY",
1279 "TEXTURE_CUBE",
1280 "TEXTURE_3D",
1281 "TEXTURE_RECT",
1282 "TEXTURE_2D",
1283 "TEXTURE_1D",
1284 };
1285 GLint targetUsed[MAX_TEXTURE_IMAGE_UNITS];
1286 GLbitfield samplersUsed = prog->SamplersUsed;
1287 GLuint i;
Brian Paulbc985b52008-07-21 14:16:07 -06001288
Brian Paulc90fca32009-08-25 17:42:47 -06001289 assert(Elements(targetName) == NUM_TEXTURE_TARGETS);
1290
1291 if (samplersUsed == 0x0)
1292 return GL_TRUE;
1293
1294 for (i = 0; i < Elements(targetUsed); i++)
1295 targetUsed[i] = -1;
1296
1297 /* walk over bits which are set in 'samplers' */
1298 while (samplersUsed) {
1299 GLuint unit;
1300 gl_texture_index target;
1301 GLint sampler = _mesa_ffs(samplersUsed) - 1;
1302 assert(sampler >= 0);
1303 assert(sampler < MAX_TEXTURE_IMAGE_UNITS);
1304 unit = prog->SamplerUnits[sampler];
1305 target = prog->SamplerTargets[sampler];
1306 if (targetUsed[unit] != -1 && targetUsed[unit] != target) {
Brian Paul78a0c352010-02-19 12:56:49 -07001307 _mesa_snprintf(errMsg, 100,
Kristian Høgsberg298be2b2010-02-19 12:32:24 -05001308 "Texture unit %d is accessed both as %s and %s",
1309 unit, targetName[targetUsed[unit]], targetName[target]);
Brian Paulc90fca32009-08-25 17:42:47 -06001310 return GL_FALSE;
1311 }
1312 targetUsed[unit] = target;
1313 samplersUsed ^= (1 << sampler);
Brian34ae99d2006-12-18 08:28:54 -07001314 }
1315
Brian Paulc90fca32009-08-25 17:42:47 -06001316 return GL_TRUE;
1317}
1318
1319
1320/**
1321 * Do validation of the given shader program.
1322 * \param errMsg returns error message if validation fails.
1323 * \return GL_TRUE if valid, GL_FALSE if invalid (and set errMsg)
1324 */
1325GLboolean
1326_mesa_validate_shader_program(GLcontext *ctx,
1327 const struct gl_shader_program *shProg,
1328 char *errMsg)
1329{
1330 const struct gl_vertex_program *vp = shProg->VertexProgram;
1331 const struct gl_fragment_program *fp = shProg->FragmentProgram;
1332
Brian Paulbc985b52008-07-21 14:16:07 -06001333 if (!shProg->LinkStatus) {
Brian Paulc90fca32009-08-25 17:42:47 -06001334 return GL_FALSE;
Brian Paulbc985b52008-07-21 14:16:07 -06001335 }
1336
1337 /* From the GL spec, a program is invalid if any of these are true:
1338
Brian5b01c5e2006-12-19 18:02:03 -07001339 any two active samplers in the current program object are of
1340 different types, but refer to the same texture image unit,
1341
1342 any active sampler in the current program object refers to a texture
1343 image unit where fixed-function fragment processing accesses a
1344 texture target that does not match the sampler type, or
1345
1346 the sum of the number of active samplers in the program and the
1347 number of texture image units enabled for fixed-function fragment
1348 processing exceeds the combined limit on the total number of texture
1349 image units allowed.
1350 */
Brian Paulbc985b52008-07-21 14:16:07 -06001351
Brian Paulc90fca32009-08-25 17:42:47 -06001352
1353 /*
1354 * Check: any two active samplers in the current program object are of
1355 * different types, but refer to the same texture image unit,
1356 */
1357 if (vp && !validate_samplers(ctx, &vp->Base, errMsg)) {
1358 return GL_FALSE;
1359 }
1360 if (fp && !validate_samplers(ctx, &fp->Base, errMsg)) {
1361 return GL_FALSE;
1362 }
1363
1364 return GL_TRUE;
1365}
1366
1367
1368/**
1369 * Called via glValidateProgram()
1370 */
1371static void
1372_mesa_validate_program(GLcontext *ctx, GLuint program)
1373{
1374 struct gl_shader_program *shProg;
1375 char errMsg[100];
1376
1377 shProg = _mesa_lookup_shader_program_err(ctx, program, "glValidateProgram");
1378 if (!shProg) {
1379 return;
1380 }
1381
1382 shProg->Validated = _mesa_validate_shader_program(ctx, shProg, errMsg);
1383 if (!shProg->Validated) {
1384 /* update info log */
1385 if (shProg->InfoLog) {
Kristian Høgsberg32f2fd12010-02-19 11:58:49 -05001386 free(shProg->InfoLog);
Brian Paulc90fca32009-08-25 17:42:47 -06001387 }
1388 shProg->InfoLog = _mesa_strdup(errMsg);
1389 }
Brian34ae99d2006-12-18 08:28:54 -07001390}
Brian Paulfd59f192008-05-18 16:04:55 -06001391
1392
1393/**
1394 * Plug in Mesa's GLSL functions into the device driver function table.
1395 */
1396void
1397_mesa_init_glsl_driver_functions(struct dd_function_table *driver)
1398{
1399 driver->AttachShader = _mesa_attach_shader;
1400 driver->BindAttribLocation = _mesa_bind_attrib_location;
1401 driver->CompileShader = _mesa_compile_shader;
1402 driver->CreateProgram = _mesa_create_program;
1403 driver->CreateShader = _mesa_create_shader;
1404 driver->DeleteProgram2 = _mesa_delete_program2;
1405 driver->DeleteShader = _mesa_delete_shader;
1406 driver->DetachShader = _mesa_detach_shader;
1407 driver->GetActiveAttrib = _mesa_get_active_attrib;
Brian Paulfd59f192008-05-18 16:04:55 -06001408 driver->GetAttachedShaders = _mesa_get_attached_shaders;
1409 driver->GetAttribLocation = _mesa_get_attrib_location;
1410 driver->GetHandle = _mesa_get_handle;
1411 driver->GetProgramiv = _mesa_get_programiv;
1412 driver->GetProgramInfoLog = _mesa_get_program_info_log;
1413 driver->GetShaderiv = _mesa_get_shaderiv;
1414 driver->GetShaderInfoLog = _mesa_get_shader_info_log;
1415 driver->GetShaderSource = _mesa_get_shader_source;
Brian Paulfd59f192008-05-18 16:04:55 -06001416 driver->IsProgram = _mesa_is_program;
1417 driver->IsShader = _mesa_is_shader;
1418 driver->LinkProgram = _mesa_link_program;
1419 driver->ShaderSource = _mesa_shader_source;
Brian Paulfd59f192008-05-18 16:04:55 -06001420 driver->UseProgram = _mesa_use_program;
1421 driver->ValidateProgram = _mesa_validate_program;
Brian Paul69861ae2010-05-26 22:24:58 -06001422
1423 _mesa_init_uniform_functions(driver);
Brian Paulfd59f192008-05-18 16:04:55 -06001424}