blob: bb8e9725414c03663c49a6c0bb530b4fdf25cab5 [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_statevars.h"
45#include "shader/prog_uniform.h"
Brianc223c6b2007-07-04 13:15:20 -060046#include "shader/shader_api.h"
47#include "shader/slang/slang_compile.h"
48#include "shader/slang/slang_link.h"
Chia-I Wu2cf44392010-02-24 12:01:14 +080049#include "main/dispatch.h"
Brian34ae99d2006-12-18 08:28:54 -070050
51
Brianf2923612006-12-20 09:56:44 -070052/**
53 * Allocate a new gl_shader_program object, initialize it.
54 */
Brian Paulfd59f192008-05-18 16:04:55 -060055static struct gl_shader_program *
Brianf2923612006-12-20 09:56:44 -070056_mesa_new_shader_program(GLcontext *ctx, GLuint name)
57{
58 struct gl_shader_program *shProg;
59 shProg = CALLOC_STRUCT(gl_shader_program);
60 if (shProg) {
Brianf3e8c322007-04-18 14:53:23 -060061 shProg->Type = GL_SHADER_PROGRAM_MESA;
Brianf2923612006-12-20 09:56:44 -070062 shProg->Name = name;
63 shProg->RefCount = 1;
Brian3209c3e2007-01-09 17:49:24 -070064 shProg->Attributes = _mesa_new_parameter_list();
Brianf2923612006-12-20 09:56:44 -070065 }
66 return shProg;
67}
68
69
Brianb9fbedd2007-03-26 09:23:44 -060070/**
Brian3c008a02007-04-12 15:22:32 -060071 * Clear (free) the shader program state that gets produced by linking.
Brianb9fbedd2007-03-26 09:23:44 -060072 */
Brianf2923612006-12-20 09:56:44 -070073void
Brian3c008a02007-04-12 15:22:32 -060074_mesa_clear_shader_program_data(GLcontext *ctx,
75 struct gl_shader_program *shProg)
Brianf2923612006-12-20 09:56:44 -070076{
Brian Paul8bdf5b62008-05-16 09:56:59 -060077 _mesa_reference_vertprog(ctx, &shProg->VertexProgram, NULL);
78 _mesa_reference_fragprog(ctx, &shProg->FragmentProgram, NULL);
Brianf2923612006-12-20 09:56:44 -070079
Brianf2923612006-12-20 09:56:44 -070080 if (shProg->Uniforms) {
Brian Paulade50832008-05-14 16:09:46 -060081 _mesa_free_uniform_list(shProg->Uniforms);
Brianf2923612006-12-20 09:56:44 -070082 shProg->Uniforms = NULL;
83 }
84
85 if (shProg->Varying) {
86 _mesa_free_parameter_list(shProg->Varying);
87 shProg->Varying = NULL;
88 }
89}
90
91
Brianb9fbedd2007-03-26 09:23:44 -060092/**
Brian3c008a02007-04-12 15:22:32 -060093 * Free all the data that hangs off a shader program object, but not the
94 * object itself.
95 */
96void
97_mesa_free_shader_program_data(GLcontext *ctx,
98 struct gl_shader_program *shProg)
99{
100 GLuint i;
101
Brianf3e8c322007-04-18 14:53:23 -0600102 assert(shProg->Type == GL_SHADER_PROGRAM_MESA);
Brian3c008a02007-04-12 15:22:32 -0600103
104 _mesa_clear_shader_program_data(ctx, shProg);
105
Brian4b7c6fc2007-04-19 15:23:34 -0600106 if (shProg->Attributes) {
107 _mesa_free_parameter_list(shProg->Attributes);
108 shProg->Attributes = NULL;
109 }
110
Brian3c008a02007-04-12 15:22:32 -0600111 /* detach shaders */
112 for (i = 0; i < shProg->NumShaders; i++) {
113 _mesa_reference_shader(ctx, &shProg->Shaders[i], NULL);
114 }
Xiang, Haihao63d8a842008-03-31 17:02:47 +0800115 shProg->NumShaders = 0;
116
Brian3c008a02007-04-12 15:22:32 -0600117 if (shProg->Shaders) {
Kristian Høgsberg32f2fd12010-02-19 11:58:49 -0500118 free(shProg->Shaders);
Brian3c008a02007-04-12 15:22:32 -0600119 shProg->Shaders = NULL;
120 }
Alan Hourihaneeec20c32008-04-22 20:29:42 +0100121
122 if (shProg->InfoLog) {
Kristian Høgsberg32f2fd12010-02-19 11:58:49 -0500123 free(shProg->InfoLog);
Alan Hourihaneeec20c32008-04-22 20:29:42 +0100124 shProg->InfoLog = NULL;
125 }
Brian Paule5c69642010-03-30 19:54:02 -0600126
127 /* Transform feedback varying vars */
128 for (i = 0; i < shProg->TransformFeedback.NumVarying; i++) {
129 free(shProg->TransformFeedback.VaryingNames[i]);
130 }
131 free(shProg->TransformFeedback.VaryingNames);
132 shProg->TransformFeedback.VaryingNames = NULL;
133 shProg->TransformFeedback.NumVarying = 0;
Brian3c008a02007-04-12 15:22:32 -0600134}
135
136
137/**
Brianb9fbedd2007-03-26 09:23:44 -0600138 * Free/delete a shader program object.
139 */
Brianf2923612006-12-20 09:56:44 -0700140void
141_mesa_free_shader_program(GLcontext *ctx, struct gl_shader_program *shProg)
142{
143 _mesa_free_shader_program_data(ctx, shProg);
Alan Hourihaneeec20c32008-04-22 20:29:42 +0100144
Kristian Høgsberg32f2fd12010-02-19 11:58:49 -0500145 free(shProg);
Brianf2923612006-12-20 09:56:44 -0700146}
147
148
149/**
Brian3c008a02007-04-12 15:22:32 -0600150 * Set ptr to point to shProg.
151 * If ptr is pointing to another object, decrement its refcount (and delete
152 * if refcount hits zero).
153 * Then set ptr to point to shProg, incrementing its refcount.
154 */
155/* XXX this could be static */
156void
157_mesa_reference_shader_program(GLcontext *ctx,
158 struct gl_shader_program **ptr,
159 struct gl_shader_program *shProg)
160{
161 assert(ptr);
162 if (*ptr == shProg) {
163 /* no-op */
164 return;
165 }
166 if (*ptr) {
167 /* Unreference the old shader program */
168 GLboolean deleteFlag = GL_FALSE;
169 struct gl_shader_program *old = *ptr;
170
171 ASSERT(old->RefCount > 0);
172 old->RefCount--;
Brian Paul8bdf5b62008-05-16 09:56:59 -0600173#if 0
174 printf("ShaderProgram %p ID=%u RefCount-- to %d\n",
175 (void *) old, old->Name, old->RefCount);
176#endif
Brian3c008a02007-04-12 15:22:32 -0600177 deleteFlag = (old->RefCount == 0);
178
179 if (deleteFlag) {
Xiang, Haihaoaef47c42008-03-31 16:27:47 +0800180 _mesa_HashRemove(ctx->Shared->ShaderObjects, old->Name);
Brian3c008a02007-04-12 15:22:32 -0600181 _mesa_free_shader_program(ctx, old);
182 }
183
184 *ptr = NULL;
185 }
186 assert(!*ptr);
187
188 if (shProg) {
189 shProg->RefCount++;
Brian Paul8bdf5b62008-05-16 09:56:59 -0600190#if 0
191 printf("ShaderProgram %p ID=%u RefCount++ to %d\n",
192 (void *) shProg, shProg->Name, shProg->RefCount);
193#endif
Brian3c008a02007-04-12 15:22:32 -0600194 *ptr = shProg;
195 }
196}
197
198
199/**
Brianf2923612006-12-20 09:56:44 -0700200 * Lookup a GLSL program object.
201 */
202struct gl_shader_program *
203_mesa_lookup_shader_program(GLcontext *ctx, GLuint name)
204{
205 struct gl_shader_program *shProg;
206 if (name) {
207 shProg = (struct gl_shader_program *)
Xiang, Haihaoaef47c42008-03-31 16:27:47 +0800208 _mesa_HashLookup(ctx->Shared->ShaderObjects, name);
Brianf2923612006-12-20 09:56:44 -0700209 /* Note that both gl_shader and gl_shader_program objects are kept
210 * in the same hash table. Check the object's type to be sure it's
211 * what we're expecting.
212 */
Brianf3e8c322007-04-18 14:53:23 -0600213 if (shProg && shProg->Type != GL_SHADER_PROGRAM_MESA) {
Brianf2923612006-12-20 09:56:44 -0700214 return NULL;
215 }
216 return shProg;
217 }
218 return NULL;
219}
220
221
222/**
Brian Paul530df582008-07-03 16:21:11 -0600223 * As above, but record an error if program is not found.
224 */
225static struct gl_shader_program *
226_mesa_lookup_shader_program_err(GLcontext *ctx, GLuint name,
227 const char *caller)
228{
229 if (!name) {
230 _mesa_error(ctx, GL_INVALID_VALUE, caller);
231 return NULL;
232 }
233 else {
234 struct gl_shader_program *shProg = (struct gl_shader_program *)
235 _mesa_HashLookup(ctx->Shared->ShaderObjects, name);
236 if (!shProg) {
237 _mesa_error(ctx, GL_INVALID_VALUE, caller);
238 return NULL;
239 }
240 if (shProg->Type != GL_SHADER_PROGRAM_MESA) {
241 _mesa_error(ctx, GL_INVALID_OPERATION, caller);
242 return NULL;
243 }
244 return shProg;
245 }
246}
247
248
249
250
251/**
Brianf2923612006-12-20 09:56:44 -0700252 * Allocate a new gl_shader object, initialize it.
253 */
254struct gl_shader *
255_mesa_new_shader(GLcontext *ctx, GLuint name, GLenum type)
256{
257 struct gl_shader *shader;
258 assert(type == GL_FRAGMENT_SHADER || type == GL_VERTEX_SHADER);
259 shader = CALLOC_STRUCT(gl_shader);
260 if (shader) {
261 shader->Type = type;
262 shader->Name = name;
263 shader->RefCount = 1;
264 }
265 return shader;
266}
267
268
269void
270_mesa_free_shader(GLcontext *ctx, struct gl_shader *sh)
271{
Brianf2923612006-12-20 09:56:44 -0700272 if (sh->Source)
Kristian Høgsberg32f2fd12010-02-19 11:58:49 -0500273 free((void *) sh->Source);
Brianf2923612006-12-20 09:56:44 -0700274 if (sh->InfoLog)
Kristian Høgsberg32f2fd12010-02-19 11:58:49 -0500275 free(sh->InfoLog);
Brian Paul3d500f02008-07-24 14:56:54 -0600276 _mesa_reference_program(ctx, &sh->Program, NULL);
Kristian Høgsberg32f2fd12010-02-19 11:58:49 -0500277 free(sh);
Brianf2923612006-12-20 09:56:44 -0700278}
279
280
281/**
Brian3c008a02007-04-12 15:22:32 -0600282 * Set ptr to point to sh.
283 * If ptr is pointing to another shader, decrement its refcount (and delete
284 * if refcount hits zero).
285 * Then set ptr to point to sh, incrementing its refcount.
286 */
287/* XXX this could be static */
288void
289_mesa_reference_shader(GLcontext *ctx, struct gl_shader **ptr,
290 struct gl_shader *sh)
291{
292 assert(ptr);
293 if (*ptr == sh) {
294 /* no-op */
295 return;
296 }
297 if (*ptr) {
298 /* Unreference the old shader */
299 GLboolean deleteFlag = GL_FALSE;
300 struct gl_shader *old = *ptr;
301
302 ASSERT(old->RefCount > 0);
303 old->RefCount--;
Brian99193e42007-04-12 15:45:02 -0600304 /*printf("SHADER DECR %p (%d) to %d\n",
305 (void*) old, old->Name, old->RefCount);*/
Brian3c008a02007-04-12 15:22:32 -0600306 deleteFlag = (old->RefCount == 0);
307
308 if (deleteFlag) {
309 _mesa_HashRemove(ctx->Shared->ShaderObjects, old->Name);
310 _mesa_free_shader(ctx, old);
311 }
312
313 *ptr = NULL;
314 }
315 assert(!*ptr);
316
317 if (sh) {
318 /* reference new */
319 sh->RefCount++;
Brian99193e42007-04-12 15:45:02 -0600320 /*printf("SHADER INCR %p (%d) to %d\n",
321 (void*) sh, sh->Name, sh->RefCount);*/
Brian3c008a02007-04-12 15:22:32 -0600322 *ptr = sh;
323 }
324}
325
326
327/**
Brianf2923612006-12-20 09:56:44 -0700328 * Lookup a GLSL shader object.
329 */
330struct gl_shader *
331_mesa_lookup_shader(GLcontext *ctx, GLuint name)
332{
333 if (name) {
334 struct gl_shader *sh = (struct gl_shader *)
335 _mesa_HashLookup(ctx->Shared->ShaderObjects, name);
336 /* Note that both gl_shader and gl_shader_program objects are kept
337 * in the same hash table. Check the object's type to be sure it's
338 * what we're expecting.
339 */
Brianf3e8c322007-04-18 14:53:23 -0600340 if (sh && sh->Type == GL_SHADER_PROGRAM_MESA) {
Brianf2923612006-12-20 09:56:44 -0700341 return NULL;
342 }
343 return sh;
344 }
345 return NULL;
346}
347
348
Brianfa4d0362007-02-26 18:33:50 -0700349/**
Brian Paul530df582008-07-03 16:21:11 -0600350 * As above, but record an error if shader is not found.
351 */
352static struct gl_shader *
353_mesa_lookup_shader_err(GLcontext *ctx, GLuint name, const char *caller)
354{
355 if (!name) {
356 _mesa_error(ctx, GL_INVALID_VALUE, caller);
357 return NULL;
358 }
359 else {
360 struct gl_shader *sh = (struct gl_shader *)
361 _mesa_HashLookup(ctx->Shared->ShaderObjects, name);
362 if (!sh) {
363 _mesa_error(ctx, GL_INVALID_VALUE, caller);
364 return NULL;
365 }
366 if (sh->Type == GL_SHADER_PROGRAM_MESA) {
367 _mesa_error(ctx, GL_INVALID_OPERATION, caller);
368 return NULL;
369 }
370 return sh;
371 }
372}
373
374
Brian Paule01a03d2009-02-06 10:21:36 -0700375/**
376 * Return mask of GLSL_x flags by examining the MESA_GLSL env var.
377 */
378static GLbitfield
379get_shader_flags(void)
380{
381 GLbitfield flags = 0x0;
382 const char *env = _mesa_getenv("MESA_GLSL");
383
384 if (env) {
Kenneth Graunke0aecdb62010-02-18 23:50:51 -0800385 if (strstr(env, "dump"))
Brian Paule01a03d2009-02-06 10:21:36 -0700386 flags |= GLSL_DUMP;
Kenneth Graunke0aecdb62010-02-18 23:50:51 -0800387 if (strstr(env, "log"))
Brian Paule01a03d2009-02-06 10:21:36 -0700388 flags |= GLSL_LOG;
Kenneth Graunke0aecdb62010-02-18 23:50:51 -0800389 if (strstr(env, "nopvert"))
Brian Paulcb0de062009-09-29 10:22:32 -0600390 flags |= GLSL_NOP_VERT;
Kenneth Graunke0aecdb62010-02-18 23:50:51 -0800391 if (strstr(env, "nopfrag"))
Brian Paulcb0de062009-09-29 10:22:32 -0600392 flags |= GLSL_NOP_FRAG;
Kenneth Graunke0aecdb62010-02-18 23:50:51 -0800393 if (strstr(env, "nopt"))
Brian Paule01a03d2009-02-06 10:21:36 -0700394 flags |= GLSL_NO_OPT;
Kenneth Graunke0aecdb62010-02-18 23:50:51 -0800395 else if (strstr(env, "opt"))
Brian Paule01a03d2009-02-06 10:21:36 -0700396 flags |= GLSL_OPT;
Kenneth Graunke0aecdb62010-02-18 23:50:51 -0800397 if (strstr(env, "uniform"))
Brian Paule01a03d2009-02-06 10:21:36 -0700398 flags |= GLSL_UNIFORMS;
Kenneth Graunke0aecdb62010-02-18 23:50:51 -0800399 if (strstr(env, "useprog"))
Brian Paul2ee7fd82009-10-15 15:25:52 -0600400 flags |= GLSL_USE_PROG;
Brian Paule01a03d2009-02-06 10:21:36 -0700401 }
402
403 return flags;
404}
405
Brian Paul530df582008-07-03 16:21:11 -0600406
407/**
Brian Paule5c69642010-03-30 19:54:02 -0600408 * Find the length of the longest transform feedback varying name
409 * which was specified with glTransformFeedbackVaryings().
410 */
411static GLint
412longest_feedback_varying_name(const struct gl_shader_program *shProg)
413{
414 GLuint i;
415 GLint max = 0;
416 for (i = 0; i < shProg->TransformFeedback.NumVarying; i++) {
417 GLint len = strlen(shProg->TransformFeedback.VaryingNames[i]);
418 if (len > max)
419 max = len;
420 }
421 return max;
422}
423
424
425
426/**
Brianfa4d0362007-02-26 18:33:50 -0700427 * Initialize context's shader state.
428 */
Brianf2923612006-12-20 09:56:44 -0700429void
430_mesa_init_shader_state(GLcontext * ctx)
431{
Brianfa4d0362007-02-26 18:33:50 -0700432 /* Device drivers may override these to control what kind of instructions
433 * are generated by the GLSL compiler.
434 */
435 ctx->Shader.EmitHighLevelInstructions = GL_TRUE;
Brian Paul4031ea12009-06-17 11:57:39 -0600436 ctx->Shader.EmitContReturn = GL_TRUE;
Brian Paulc5c38352009-02-16 11:50:05 -0700437 ctx->Shader.EmitCondCodes = GL_FALSE;
Brianfa4d0362007-02-26 18:33:50 -0700438 ctx->Shader.EmitComments = GL_FALSE;
Brian Paule01a03d2009-02-06 10:21:36 -0700439 ctx->Shader.Flags = get_shader_flags();
Brian Paul65fc2ca2009-03-19 10:25:24 -0600440
441 /* Default pragma settings */
442 ctx->Shader.DefaultPragmas.IgnoreOptimize = GL_FALSE;
443 ctx->Shader.DefaultPragmas.IgnoreDebug = GL_FALSE;
444 ctx->Shader.DefaultPragmas.Optimize = GL_TRUE;
445 ctx->Shader.DefaultPragmas.Debug = GL_FALSE;
Brianf2923612006-12-20 09:56:44 -0700446}
447
448
Brian5b01c5e2006-12-19 18:02:03 -0700449/**
Brian935f93f2007-03-24 16:20:02 -0600450 * Free the per-context shader-related state.
451 */
452void
453_mesa_free_shader_state(GLcontext *ctx)
454{
Brian3c008a02007-04-12 15:22:32 -0600455 _mesa_reference_shader_program(ctx, &ctx->Shader.CurrentProgram, NULL);
Brian935f93f2007-03-24 16:20:02 -0600456}
457
458
459/**
Brian5b01c5e2006-12-19 18:02:03 -0700460 * Copy string from <src> to <dst>, up to maxLength characters, returning
461 * length of <dst> in <length>.
462 * \param src the strings source
463 * \param maxLength max chars to copy
464 * \param length returns number of chars copied
465 * \param dst the string destination
466 */
Brian Paule5c69642010-03-30 19:54:02 -0600467void
468_mesa_copy_string(GLchar *dst, GLsizei maxLength,
469 GLsizei *length, const GLchar *src)
Brian5b01c5e2006-12-19 18:02:03 -0700470{
471 GLsizei len;
472 for (len = 0; len < maxLength - 1 && src && src[len]; len++)
473 dst[len] = src[len];
474 if (maxLength > 0)
475 dst[len] = 0;
476 if (length)
477 *length = len;
478}
479
480
Brian Paul7acb7c12008-07-03 13:49:48 -0600481static GLboolean
482_mesa_is_program(GLcontext *ctx, GLuint name)
483{
484 struct gl_shader_program *shProg = _mesa_lookup_shader_program(ctx, name);
485 return shProg ? GL_TRUE : GL_FALSE;
486}
487
488
489static GLboolean
490_mesa_is_shader(GLcontext *ctx, GLuint name)
491{
492 struct gl_shader *shader = _mesa_lookup_shader(ctx, name);
493 return shader ? GL_TRUE : GL_FALSE;
494}
495
496
Brian5b01c5e2006-12-19 18:02:03 -0700497/**
498 * Called via ctx->Driver.AttachShader()
499 */
Brian Paulfd59f192008-05-18 16:04:55 -0600500static void
Brian5b01c5e2006-12-19 18:02:03 -0700501_mesa_attach_shader(GLcontext *ctx, GLuint program, GLuint shader)
502{
Brian Paul530df582008-07-03 16:21:11 -0600503 struct gl_shader_program *shProg;
504 struct gl_shader *sh;
505 GLuint i, n;
Brian5b01c5e2006-12-19 18:02:03 -0700506
Brian Paul530df582008-07-03 16:21:11 -0600507 shProg = _mesa_lookup_shader_program_err(ctx, program, "glAttachShader");
508 if (!shProg)
Brian5b01c5e2006-12-19 18:02:03 -0700509 return;
Brian5b01c5e2006-12-19 18:02:03 -0700510
Brian Paul530df582008-07-03 16:21:11 -0600511 sh = _mesa_lookup_shader_err(ctx, shader, "glAttachShader");
Brian Paul7acb7c12008-07-03 13:49:48 -0600512 if (!sh) {
Brian Paul7acb7c12008-07-03 13:49:48 -0600513 return;
514 }
515
Brian237b9852007-08-07 21:48:31 +0100516 n = shProg->NumShaders;
Brian5b01c5e2006-12-19 18:02:03 -0700517 for (i = 0; i < n; i++) {
Brian65a18442006-12-19 18:46:56 -0700518 if (shProg->Shaders[i] == sh) {
Ian Romanickd806d452008-09-29 12:18:06 -0700519 /* The shader is already attched to this program. The
520 * GL_ARB_shader_objects spec says:
521 *
522 * "The error INVALID_OPERATION is generated by AttachObjectARB
523 * if <obj> is already attached to <containerObj>."
524 */
525 _mesa_error(ctx, GL_INVALID_OPERATION, "glAttachShader");
Brian5b01c5e2006-12-19 18:02:03 -0700526 return;
Brian34ae99d2006-12-18 08:28:54 -0700527 }
528 }
Brian5b01c5e2006-12-19 18:02:03 -0700529
530 /* grow list */
Brian65a18442006-12-19 18:46:56 -0700531 shProg->Shaders = (struct gl_shader **)
532 _mesa_realloc(shProg->Shaders,
533 n * sizeof(struct gl_shader *),
534 (n + 1) * sizeof(struct gl_shader *));
535 if (!shProg->Shaders) {
Brian5b01c5e2006-12-19 18:02:03 -0700536 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glAttachShader");
537 return;
538 }
539
540 /* append */
Brian3c008a02007-04-12 15:22:32 -0600541 shProg->Shaders[n] = NULL; /* since realloc() didn't zero the new space */
542 _mesa_reference_shader(ctx, &shProg->Shaders[n], sh);
Brian65a18442006-12-19 18:46:56 -0700543 shProg->NumShaders++;
Brian5b01c5e2006-12-19 18:02:03 -0700544}
545
546
Brian Paulfd59f192008-05-18 16:04:55 -0600547static GLint
Brian Paul896c0cc2008-05-16 15:47:55 -0600548_mesa_get_attrib_location(GLcontext *ctx, GLuint program,
549 const GLchar *name)
550{
551 struct gl_shader_program *shProg
Brian Paul530df582008-07-03 16:21:11 -0600552 = _mesa_lookup_shader_program_err(ctx, program, "glGetAttribLocation");
Brian Paul896c0cc2008-05-16 15:47:55 -0600553
554 if (!shProg) {
Brian Paul896c0cc2008-05-16 15:47:55 -0600555 return -1;
556 }
557
558 if (!shProg->LinkStatus) {
559 _mesa_error(ctx, GL_INVALID_OPERATION,
560 "glGetAttribLocation(program not linked)");
561 return -1;
562 }
563
564 if (!name)
565 return -1;
566
Brian Paul27341a92008-09-16 16:28:36 -0600567 if (shProg->VertexProgram) {
568 const struct gl_program_parameter_list *attribs =
569 shProg->VertexProgram->Base.Attributes;
570 if (attribs) {
571 GLint i = _mesa_lookup_parameter_index(attribs, -1, name);
572 if (i >= 0) {
573 return attribs->Parameters[i].StateIndexes[0];
574 }
Brian Paul896c0cc2008-05-16 15:47:55 -0600575 }
576 }
577 return -1;
578}
579
580
Brian Paulfd59f192008-05-18 16:04:55 -0600581static void
Brian5b01c5e2006-12-19 18:02:03 -0700582_mesa_bind_attrib_location(GLcontext *ctx, GLuint program, GLuint index,
583 const GLchar *name)
584{
Brian Paul530df582008-07-03 16:21:11 -0600585 struct gl_shader_program *shProg;
Brianb7978af2007-01-09 19:17:17 -0700586 const GLint size = -1; /* unknown size */
Brian Paul6bc87492008-07-25 08:34:54 -0600587 GLint i, oldIndex;
Brian Paul6f1abb92008-07-29 17:27:22 -0600588 GLenum datatype = GL_FLOAT_VEC4;
Brian5b01c5e2006-12-19 18:02:03 -0700589
Brian Paul530df582008-07-03 16:21:11 -0600590 shProg = _mesa_lookup_shader_program_err(ctx, program,
591 "glBindAttribLocation");
Brian65a18442006-12-19 18:46:56 -0700592 if (!shProg) {
Brian5b01c5e2006-12-19 18:02:03 -0700593 return;
594 }
595
Brian9e4bae92006-12-20 09:27:42 -0700596 if (!name)
597 return;
598
599 if (strncmp(name, "gl_", 3) == 0) {
600 _mesa_error(ctx, GL_INVALID_OPERATION,
601 "glBindAttribLocation(illegal name)");
602 return;
603 }
604
Brian Paul7acb7c12008-07-03 13:49:48 -0600605 if (index >= ctx->Const.VertexProgram.MaxAttribs) {
606 _mesa_error(ctx, GL_INVALID_VALUE, "glBindAttribLocation(index)");
607 return;
608 }
609
Brian Paul6bc87492008-07-25 08:34:54 -0600610 if (shProg->LinkStatus) {
611 /* get current index/location for the attribute */
612 oldIndex = _mesa_get_attrib_location(ctx, program, name);
613 }
614 else {
615 oldIndex = -1;
616 }
617
Brian3209c3e2007-01-09 17:49:24 -0700618 /* this will replace the current value if it's already in the list */
Brian Paulffbc66b2008-07-21 13:58:50 -0600619 i = _mesa_add_attribute(shProg->Attributes, name, size, datatype, index);
Brian3209c3e2007-01-09 17:49:24 -0700620 if (i < 0) {
621 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBindAttribLocation");
Brian Paul6f1abb92008-07-29 17:27:22 -0600622 return;
Brian3209c3e2007-01-09 17:49:24 -0700623 }
624
Brian Paul27341a92008-09-16 16:28:36 -0600625 /*
626 * Note that this attribute binding won't go into effect until
627 * glLinkProgram is called again.
628 */
Brian34ae99d2006-12-18 08:28:54 -0700629}
630
631
Brian Paulfd59f192008-05-18 16:04:55 -0600632static GLuint
Brian5b01c5e2006-12-19 18:02:03 -0700633_mesa_create_shader(GLcontext *ctx, GLenum type)
634{
Brian65a18442006-12-19 18:46:56 -0700635 struct gl_shader *sh;
Brian5b01c5e2006-12-19 18:02:03 -0700636 GLuint name;
637
638 name = _mesa_HashFindFreeKeyBlock(ctx->Shared->ShaderObjects, 1);
639
640 switch (type) {
Brian65a18442006-12-19 18:46:56 -0700641 case GL_FRAGMENT_SHADER:
642 case GL_VERTEX_SHADER:
643 sh = _mesa_new_shader(ctx, name, type);
Brian5b01c5e2006-12-19 18:02:03 -0700644 break;
645 default:
646 _mesa_error(ctx, GL_INVALID_ENUM, "CreateShader(type)");
647 return 0;
648 }
649
Brian65a18442006-12-19 18:46:56 -0700650 _mesa_HashInsert(ctx->Shared->ShaderObjects, name, sh);
Brian5b01c5e2006-12-19 18:02:03 -0700651
652 return name;
653}
654
655
Brian Paulfd59f192008-05-18 16:04:55 -0600656static GLuint
Brian5b01c5e2006-12-19 18:02:03 -0700657_mesa_create_program(GLcontext *ctx)
658{
659 GLuint name;
Brian65a18442006-12-19 18:46:56 -0700660 struct gl_shader_program *shProg;
Brian5b01c5e2006-12-19 18:02:03 -0700661
Xiang, Haihaoaef47c42008-03-31 16:27:47 +0800662 name = _mesa_HashFindFreeKeyBlock(ctx->Shared->ShaderObjects, 1);
Brian65a18442006-12-19 18:46:56 -0700663 shProg = _mesa_new_shader_program(ctx, name);
Brian5b01c5e2006-12-19 18:02:03 -0700664
Xiang, Haihaoaef47c42008-03-31 16:27:47 +0800665 _mesa_HashInsert(ctx->Shared->ShaderObjects, name, shProg);
Brian5b01c5e2006-12-19 18:02:03 -0700666
Brian3c008a02007-04-12 15:22:32 -0600667 assert(shProg->RefCount == 1);
668
Brian5b01c5e2006-12-19 18:02:03 -0700669 return name;
670}
671
672
Brian3c008a02007-04-12 15:22:32 -0600673/**
674 * Named w/ "2" to indicate OpenGL 2.x vs GL_ARB_fragment_programs's
675 * DeleteProgramARB.
676 */
Brian Paulfd59f192008-05-18 16:04:55 -0600677static void
Brian5b01c5e2006-12-19 18:02:03 -0700678_mesa_delete_program2(GLcontext *ctx, GLuint name)
679{
Brian3c008a02007-04-12 15:22:32 -0600680 /*
681 * NOTE: deleting shaders/programs works a bit differently than
682 * texture objects (and buffer objects, etc). Shader/program
683 * handles/IDs exist in the hash table until the object is really
684 * deleted (refcount==0). With texture objects, the handle/ID is
685 * removed from the hash table in glDeleteTextures() while the tex
686 * object itself might linger until its refcount goes to zero.
687 */
Brian65a18442006-12-19 18:46:56 -0700688 struct gl_shader_program *shProg;
Brian5b01c5e2006-12-19 18:02:03 -0700689
Brian Paul530df582008-07-03 16:21:11 -0600690 shProg = _mesa_lookup_shader_program_err(ctx, name, "glDeleteProgram");
691 if (!shProg)
Brian5b01c5e2006-12-19 18:02:03 -0700692 return;
Brian5b01c5e2006-12-19 18:02:03 -0700693
Brian9e4bae92006-12-20 09:27:42 -0700694 shProg->DeletePending = GL_TRUE;
695
Brian3c008a02007-04-12 15:22:32 -0600696 /* effectively, decr shProg's refcount */
697 _mesa_reference_shader_program(ctx, &shProg, NULL);
Brian5b01c5e2006-12-19 18:02:03 -0700698}
699
700
Brian Paulfd59f192008-05-18 16:04:55 -0600701static void
Brian5b01c5e2006-12-19 18:02:03 -0700702_mesa_delete_shader(GLcontext *ctx, GLuint shader)
703{
Brian Paul530df582008-07-03 16:21:11 -0600704 struct gl_shader *sh;
705
706 sh = _mesa_lookup_shader_err(ctx, shader, "glDeleteShader");
707 if (!sh)
Brian9e4bae92006-12-20 09:27:42 -0700708 return;
Brian5b01c5e2006-12-19 18:02:03 -0700709
Brian9e4bae92006-12-20 09:27:42 -0700710 sh->DeletePending = GL_TRUE;
Brian3c008a02007-04-12 15:22:32 -0600711
712 /* effectively, decr sh's refcount */
713 _mesa_reference_shader(ctx, &sh, NULL);
Brian5b01c5e2006-12-19 18:02:03 -0700714}
715
716
Brian Paulfd59f192008-05-18 16:04:55 -0600717static void
Brian5b01c5e2006-12-19 18:02:03 -0700718_mesa_detach_shader(GLcontext *ctx, GLuint program, GLuint shader)
719{
Brian Paul530df582008-07-03 16:21:11 -0600720 struct gl_shader_program *shProg;
Brian237b9852007-08-07 21:48:31 +0100721 GLuint n;
Brian5b01c5e2006-12-19 18:02:03 -0700722 GLuint i, j;
723
Brian Paul530df582008-07-03 16:21:11 -0600724 shProg = _mesa_lookup_shader_program_err(ctx, program, "glDetachShader");
725 if (!shProg)
Brian5b01c5e2006-12-19 18:02:03 -0700726 return;
Brian5b01c5e2006-12-19 18:02:03 -0700727
Brian237b9852007-08-07 21:48:31 +0100728 n = shProg->NumShaders;
729
Brian5b01c5e2006-12-19 18:02:03 -0700730 for (i = 0; i < n; i++) {
Brian65a18442006-12-19 18:46:56 -0700731 if (shProg->Shaders[i]->Name == shader) {
Brian5b01c5e2006-12-19 18:02:03 -0700732 /* found it */
Brian3c008a02007-04-12 15:22:32 -0600733 struct gl_shader **newList;
Brian9e4bae92006-12-20 09:27:42 -0700734
Brian Paul530df582008-07-03 16:21:11 -0600735 /* release */
Brian3c008a02007-04-12 15:22:32 -0600736 _mesa_reference_shader(ctx, &shProg->Shaders[i], NULL);
Brian9e4bae92006-12-20 09:27:42 -0700737
Brian5b01c5e2006-12-19 18:02:03 -0700738 /* alloc new, smaller array */
Brian65a18442006-12-19 18:46:56 -0700739 newList = (struct gl_shader **)
Kristian Høgsberg32f2fd12010-02-19 11:58:49 -0500740 malloc((n - 1) * sizeof(struct gl_shader *));
Brian5b01c5e2006-12-19 18:02:03 -0700741 if (!newList) {
742 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glDetachShader");
743 return;
744 }
745 for (j = 0; j < i; j++) {
Brian65a18442006-12-19 18:46:56 -0700746 newList[j] = shProg->Shaders[j];
Brian5b01c5e2006-12-19 18:02:03 -0700747 }
748 while (++i < n)
Brian65a18442006-12-19 18:46:56 -0700749 newList[j++] = shProg->Shaders[i];
Kristian Høgsberg32f2fd12010-02-19 11:58:49 -0500750 free(shProg->Shaders);
Brian5b01c5e2006-12-19 18:02:03 -0700751
Brian65a18442006-12-19 18:46:56 -0700752 shProg->Shaders = newList;
Brianbac15c82007-04-18 14:55:18 -0600753 shProg->NumShaders = n - 1;
Brianaaa57412007-04-18 15:22:43 -0600754
755#ifdef DEBUG
756 /* sanity check */
757 {
758 for (j = 0; j < shProg->NumShaders; j++) {
759 assert(shProg->Shaders[j]->Type == GL_VERTEX_SHADER ||
760 shProg->Shaders[j]->Type == GL_FRAGMENT_SHADER);
761 assert(shProg->Shaders[j]->RefCount > 0);
762 }
763 }
764#endif
765
Brian5b01c5e2006-12-19 18:02:03 -0700766 return;
767 }
768 }
769
770 /* not found */
Brian Paul530df582008-07-03 16:21:11 -0600771 {
772 GLenum err;
773 if (_mesa_is_shader(ctx, shader))
774 err = GL_INVALID_OPERATION;
775 else if (_mesa_is_program(ctx, shader))
776 err = GL_INVALID_OPERATION;
777 else
778 err = GL_INVALID_VALUE;
779 _mesa_error(ctx, err, "glDetachProgram(shader)");
780 return;
781 }
Brian5b01c5e2006-12-19 18:02:03 -0700782}
783
784
Brian Paul1a148662010-04-01 22:15:16 -0600785/**
786 * Return the size of the given GLSL datatype, in floats (components).
787 */
788GLint
789_mesa_sizeof_glsl_type(GLenum type)
Brian Paulffbc66b2008-07-21 13:58:50 -0600790{
791 switch (type) {
792 case GL_FLOAT:
793 case GL_INT:
794 case GL_BOOL:
Brian Paul8c51e002008-08-11 15:09:47 -0600795 case GL_SAMPLER_1D:
796 case GL_SAMPLER_2D:
797 case GL_SAMPLER_3D:
798 case GL_SAMPLER_CUBE:
799 case GL_SAMPLER_1D_SHADOW:
800 case GL_SAMPLER_2D_SHADOW:
801 case GL_SAMPLER_2D_RECT_ARB:
802 case GL_SAMPLER_2D_RECT_SHADOW_ARB:
Brian Paulac498f22010-02-25 19:05:11 -0700803 case GL_SAMPLER_1D_ARRAY_EXT:
804 case GL_SAMPLER_2D_ARRAY_EXT:
Brian Paul8c51e002008-08-11 15:09:47 -0600805 case GL_SAMPLER_1D_ARRAY_SHADOW_EXT:
806 case GL_SAMPLER_2D_ARRAY_SHADOW_EXT:
807 case GL_SAMPLER_CUBE_SHADOW_EXT:
Brian Paulffbc66b2008-07-21 13:58:50 -0600808 return 1;
809 case GL_FLOAT_VEC2:
810 case GL_INT_VEC2:
Brian Paul91f841a2010-05-25 18:39:47 -0600811 case GL_UNSIGNED_INT_VEC2:
Brian Paulffbc66b2008-07-21 13:58:50 -0600812 case GL_BOOL_VEC2:
813 return 2;
814 case GL_FLOAT_VEC3:
815 case GL_INT_VEC3:
Brian Paul91f841a2010-05-25 18:39:47 -0600816 case GL_UNSIGNED_INT_VEC3:
Brian Paulffbc66b2008-07-21 13:58:50 -0600817 case GL_BOOL_VEC3:
818 return 3;
819 case GL_FLOAT_VEC4:
820 case GL_INT_VEC4:
Brian Paul91f841a2010-05-25 18:39:47 -0600821 case GL_UNSIGNED_INT_VEC4:
Brian Paulffbc66b2008-07-21 13:58:50 -0600822 case GL_BOOL_VEC4:
823 return 4;
824 case GL_FLOAT_MAT2:
825 case GL_FLOAT_MAT2x3:
826 case GL_FLOAT_MAT2x4:
827 return 8; /* two float[4] vectors */
828 case GL_FLOAT_MAT3:
829 case GL_FLOAT_MAT3x2:
830 case GL_FLOAT_MAT3x4:
831 return 12; /* three float[4] vectors */
832 case GL_FLOAT_MAT4:
833 case GL_FLOAT_MAT4x2:
834 case GL_FLOAT_MAT4x3:
835 return 16; /* four float[4] vectors */
836 default:
Brian Paul1a148662010-04-01 22:15:16 -0600837 _mesa_problem(NULL, "Invalid type in _mesa_sizeof_glsl_type()");
Brian Paulffbc66b2008-07-21 13:58:50 -0600838 return 1;
839 }
840}
841
842
Brian Pauleda291e2008-08-06 16:26:47 -0600843static GLboolean
844is_boolean_type(GLenum type)
845{
846 switch (type) {
847 case GL_BOOL:
848 case GL_BOOL_VEC2:
849 case GL_BOOL_VEC3:
850 case GL_BOOL_VEC4:
851 return GL_TRUE;
852 default:
853 return GL_FALSE;
854 }
855}
856
857
858static GLboolean
859is_integer_type(GLenum type)
860{
861 switch (type) {
862 case GL_INT:
863 case GL_INT_VEC2:
864 case GL_INT_VEC3:
865 case GL_INT_VEC4:
866 return GL_TRUE;
867 default:
868 return GL_FALSE;
869 }
870}
871
872
Brian Paulc4ffbf02009-02-18 17:46:00 -0700873static GLboolean
Brian Paul91f841a2010-05-25 18:39:47 -0600874is_uint_type(GLenum type)
875{
876 switch (type) {
877 case GL_UNSIGNED_INT:
878 case GL_UNSIGNED_INT_VEC2:
879 case GL_UNSIGNED_INT_VEC3:
880 case GL_UNSIGNED_INT_VEC4:
881 return GL_TRUE;
882 default:
883 return GL_FALSE;
884 }
885}
886
887
888static GLboolean
Brian Paulc4ffbf02009-02-18 17:46:00 -0700889is_sampler_type(GLenum type)
890{
891 switch (type) {
892 case GL_SAMPLER_1D:
893 case GL_SAMPLER_2D:
894 case GL_SAMPLER_3D:
895 case GL_SAMPLER_CUBE:
896 case GL_SAMPLER_1D_SHADOW:
897 case GL_SAMPLER_2D_SHADOW:
898 case GL_SAMPLER_2D_RECT_ARB:
899 case GL_SAMPLER_2D_RECT_SHADOW_ARB:
900 case GL_SAMPLER_1D_ARRAY_EXT:
901 case GL_SAMPLER_2D_ARRAY_EXT:
Brian Paulac498f22010-02-25 19:05:11 -0700902 case GL_SAMPLER_1D_ARRAY_SHADOW_EXT:
903 case GL_SAMPLER_2D_ARRAY_SHADOW_EXT:
Brian Paulc4ffbf02009-02-18 17:46:00 -0700904 return GL_TRUE;
905 default:
906 return GL_FALSE;
907 }
908}
909
910
Brian Paulfd59f192008-05-18 16:04:55 -0600911static void
Brian5b01c5e2006-12-19 18:02:03 -0700912_mesa_get_active_attrib(GLcontext *ctx, GLuint program, GLuint index,
913 GLsizei maxLength, GLsizei *length, GLint *size,
914 GLenum *type, GLchar *nameOut)
915{
Brian Paul27341a92008-09-16 16:28:36 -0600916 const struct gl_program_parameter_list *attribs = NULL;
Brian Paul530df582008-07-03 16:21:11 -0600917 struct gl_shader_program *shProg;
Brian5b01c5e2006-12-19 18:02:03 -0700918
Brian Paul530df582008-07-03 16:21:11 -0600919 shProg = _mesa_lookup_shader_program_err(ctx, program, "glGetActiveAttrib");
920 if (!shProg)
Brian5b01c5e2006-12-19 18:02:03 -0700921 return;
Brian5b01c5e2006-12-19 18:02:03 -0700922
Brian Paul27341a92008-09-16 16:28:36 -0600923 if (shProg->VertexProgram)
924 attribs = shProg->VertexProgram->Base.Attributes;
925
926 if (!attribs || index >= attribs->NumParameters) {
Brianaaa57412007-04-18 15:22:43 -0600927 _mesa_error(ctx, GL_INVALID_VALUE, "glGetActiveAttrib(index)");
Brian5b01c5e2006-12-19 18:02:03 -0700928 return;
929 }
930
Brian Paule5c69642010-03-30 19:54:02 -0600931 _mesa_copy_string(nameOut, maxLength, length,
932 attribs->Parameters[index].Name);
Brian Paul27341a92008-09-16 16:28:36 -0600933
Brian5b01c5e2006-12-19 18:02:03 -0700934 if (size)
Brian Paul27341a92008-09-16 16:28:36 -0600935 *size = attribs->Parameters[index].Size
Brian Paul1a148662010-04-01 22:15:16 -0600936 / _mesa_sizeof_glsl_type(attribs->Parameters[index].DataType);
Brian Paul27341a92008-09-16 16:28:36 -0600937
Brian Paulade50832008-05-14 16:09:46 -0600938 if (type)
Brian Paul27341a92008-09-16 16:28:36 -0600939 *type = attribs->Parameters[index].DataType;
Brian5b01c5e2006-12-19 18:02:03 -0700940}
941
942
Brian Pauleda291e2008-08-06 16:26:47 -0600943static struct gl_program_parameter *
944get_uniform_parameter(const struct gl_shader_program *shProg, GLuint index)
945{
Brian Paula531a5c2009-08-13 13:44:01 -0600946 const struct gl_program *prog = NULL;
Brian Pauleda291e2008-08-06 16:26:47 -0600947 GLint progPos;
948
949 progPos = shProg->Uniforms->Uniforms[index].VertPos;
950 if (progPos >= 0) {
951 prog = &shProg->VertexProgram->Base;
952 }
953 else {
954 progPos = shProg->Uniforms->Uniforms[index].FragPos;
955 if (progPos >= 0) {
956 prog = &shProg->FragmentProgram->Base;
957 }
958 }
959
960 if (!prog || progPos < 0)
961 return NULL; /* should never happen */
962
963 return &prog->Parameters->Parameters[progPos];
964}
965
966
Brian5b01c5e2006-12-19 18:02:03 -0700967/**
968 * Called via ctx->Driver.GetActiveUniform().
969 */
Brian Paulfd59f192008-05-18 16:04:55 -0600970static void
Brian5b01c5e2006-12-19 18:02:03 -0700971_mesa_get_active_uniform(GLcontext *ctx, GLuint program, GLuint index,
972 GLsizei maxLength, GLsizei *length, GLint *size,
973 GLenum *type, GLchar *nameOut)
974{
Brian Paul530df582008-07-03 16:21:11 -0600975 const struct gl_shader_program *shProg;
Brian Paula531a5c2009-08-13 13:44:01 -0600976 const struct gl_program *prog = NULL;
Brian Paul369d1852009-02-11 08:16:14 -0700977 const struct gl_program_parameter *param;
Brian Paulade50832008-05-14 16:09:46 -0600978 GLint progPos;
Brian5b01c5e2006-12-19 18:02:03 -0700979
Brian Paul530df582008-07-03 16:21:11 -0600980 shProg = _mesa_lookup_shader_program_err(ctx, program, "glGetActiveUniform");
981 if (!shProg)
Brian5b01c5e2006-12-19 18:02:03 -0700982 return;
Brian5b01c5e2006-12-19 18:02:03 -0700983
Brian Paulade50832008-05-14 16:09:46 -0600984 if (!shProg->Uniforms || index >= shProg->Uniforms->NumUniforms) {
Brian5b01c5e2006-12-19 18:02:03 -0700985 _mesa_error(ctx, GL_INVALID_VALUE, "glGetActiveUniform(index)");
986 return;
987 }
988
Brian Paulade50832008-05-14 16:09:46 -0600989 progPos = shProg->Uniforms->Uniforms[index].VertPos;
990 if (progPos >= 0) {
991 prog = &shProg->VertexProgram->Base;
992 }
993 else {
994 progPos = shProg->Uniforms->Uniforms[index].FragPos;
995 if (progPos >= 0) {
996 prog = &shProg->FragmentProgram->Base;
Brian274ac7a2007-04-18 16:05:53 -0600997 }
998 }
999
Brian Paulade50832008-05-14 16:09:46 -06001000 if (!prog || progPos < 0)
1001 return; /* should never happen */
1002
Brian Paul369d1852009-02-11 08:16:14 -07001003 ASSERT(progPos < prog->Parameters->NumParameters);
1004 param = &prog->Parameters->Parameters[progPos];
1005
1006 if (nameOut) {
Brian Paule5c69642010-03-30 19:54:02 -06001007 _mesa_copy_string(nameOut, maxLength, length, param->Name);
Brian Paul369d1852009-02-11 08:16:14 -07001008 }
1009
1010 if (size) {
Brian Paul1a148662010-04-01 22:15:16 -06001011 GLint typeSize = _mesa_sizeof_glsl_type(param->DataType);
Brian Paul20fbb242010-01-27 17:03:04 -07001012 if ((GLint) param->Size > typeSize) {
Brian Paul369d1852009-02-11 08:16:14 -07001013 /* This is an array.
1014 * Array elements are placed on vector[4] boundaries so they're
1015 * a multiple of four floats. We round typeSize up to next multiple
1016 * of four to get the right size below.
1017 */
1018 typeSize = (typeSize + 3) & ~3;
1019 }
1020 /* Note that the returned size is in units of the <type>, not bytes */
1021 *size = param->Size / typeSize;
1022 }
1023
1024 if (type) {
1025 *type = param->DataType;
1026 }
Brian5b01c5e2006-12-19 18:02:03 -07001027}
1028
1029
1030/**
1031 * Called via ctx->Driver.GetAttachedShaders().
1032 */
Brian Paulfd59f192008-05-18 16:04:55 -06001033static void
Brian5b01c5e2006-12-19 18:02:03 -07001034_mesa_get_attached_shaders(GLcontext *ctx, GLuint program, GLsizei maxCount,
1035 GLsizei *count, GLuint *obj)
1036{
Brian Paul530df582008-07-03 16:21:11 -06001037 struct gl_shader_program *shProg =
1038 _mesa_lookup_shader_program_err(ctx, program, "glGetAttachedShaders");
Brian65a18442006-12-19 18:46:56 -07001039 if (shProg) {
Brian Paul530df582008-07-03 16:21:11 -06001040 GLuint i;
1041 for (i = 0; i < (GLuint) maxCount && i < shProg->NumShaders; i++) {
Brian65a18442006-12-19 18:46:56 -07001042 obj[i] = shProg->Shaders[i]->Name;
Brian5b01c5e2006-12-19 18:02:03 -07001043 }
1044 if (count)
1045 *count = i;
1046 }
Brian5b01c5e2006-12-19 18:02:03 -07001047}
1048
1049
Brian Paulfd59f192008-05-18 16:04:55 -06001050static GLuint
Brian5b01c5e2006-12-19 18:02:03 -07001051_mesa_get_handle(GLcontext *ctx, GLenum pname)
Brian34ae99d2006-12-18 08:28:54 -07001052{
Ian Romanick905d8e02008-09-29 12:27:00 -07001053 GLint handle = 0;
1054
1055 if (pname == GL_PROGRAM_OBJECT_ARB) {
1056 CALL_GetIntegerv(ctx->Exec, (GL_CURRENT_PROGRAM, &handle));
1057 } else {
Brian34ae99d2006-12-18 08:28:54 -07001058 _mesa_error(ctx, GL_INVALID_ENUM, "glGetHandleARB");
1059 }
Ian Romanick905d8e02008-09-29 12:27:00 -07001060
1061 return handle;
Brian34ae99d2006-12-18 08:28:54 -07001062}
1063
1064
Brian Paulfd59f192008-05-18 16:04:55 -06001065static void
Brian5b01c5e2006-12-19 18:02:03 -07001066_mesa_get_programiv(GLcontext *ctx, GLuint program,
1067 GLenum pname, GLint *params)
Brian34ae99d2006-12-18 08:28:54 -07001068{
Brian Paul27341a92008-09-16 16:28:36 -06001069 const struct gl_program_parameter_list *attribs;
Brian65a18442006-12-19 18:46:56 -07001070 struct gl_shader_program *shProg
1071 = _mesa_lookup_shader_program(ctx, program);
Brian34ae99d2006-12-18 08:28:54 -07001072
Brian65a18442006-12-19 18:46:56 -07001073 if (!shProg) {
Brian5b01c5e2006-12-19 18:02:03 -07001074 _mesa_error(ctx, GL_INVALID_VALUE, "glGetProgramiv(program)");
Brian34ae99d2006-12-18 08:28:54 -07001075 return;
1076 }
1077
Brian Paul27341a92008-09-16 16:28:36 -06001078 if (shProg->VertexProgram)
1079 attribs = shProg->VertexProgram->Base.Attributes;
1080 else
1081 attribs = NULL;
1082
Brian5b01c5e2006-12-19 18:02:03 -07001083 switch (pname) {
1084 case GL_DELETE_STATUS:
Brian65a18442006-12-19 18:46:56 -07001085 *params = shProg->DeletePending;
Brian5b01c5e2006-12-19 18:02:03 -07001086 break;
1087 case GL_LINK_STATUS:
Brian65a18442006-12-19 18:46:56 -07001088 *params = shProg->LinkStatus;
Brian34ae99d2006-12-18 08:28:54 -07001089 break;
Brian5b01c5e2006-12-19 18:02:03 -07001090 case GL_VALIDATE_STATUS:
Brian65a18442006-12-19 18:46:56 -07001091 *params = shProg->Validated;
Brian5b01c5e2006-12-19 18:02:03 -07001092 break;
1093 case GL_INFO_LOG_LENGTH:
Jan Dvorak5a0f02a2007-07-13 16:36:00 -06001094 *params = shProg->InfoLog ? strlen(shProg->InfoLog) + 1 : 0;
Brian5b01c5e2006-12-19 18:02:03 -07001095 break;
1096 case GL_ATTACHED_SHADERS:
Brian65a18442006-12-19 18:46:56 -07001097 *params = shProg->NumShaders;
Brian5b01c5e2006-12-19 18:02:03 -07001098 break;
1099 case GL_ACTIVE_ATTRIBUTES:
Brian Paul27341a92008-09-16 16:28:36 -06001100 *params = attribs ? attribs->NumParameters : 0;
Brian5b01c5e2006-12-19 18:02:03 -07001101 break;
1102 case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH:
Brian Paul27341a92008-09-16 16:28:36 -06001103 *params = _mesa_longest_parameter_name(attribs, PROGRAM_INPUT) + 1;
Brian5b01c5e2006-12-19 18:02:03 -07001104 break;
1105 case GL_ACTIVE_UNIFORMS:
Brian Paulade50832008-05-14 16:09:46 -06001106 *params = shProg->Uniforms ? shProg->Uniforms->NumUniforms : 0;
Brian5b01c5e2006-12-19 18:02:03 -07001107 break;
1108 case GL_ACTIVE_UNIFORM_MAX_LENGTH:
Brian Paulade50832008-05-14 16:09:46 -06001109 *params = _mesa_longest_uniform_name(shProg->Uniforms);
Brian274ac7a2007-04-18 16:05:53 -06001110 if (*params > 0)
1111 (*params)++; /* add one for terminating zero */
Brian34ae99d2006-12-18 08:28:54 -07001112 break;
Brian Paulbda6ad22008-08-06 12:45:14 -06001113 case GL_PROGRAM_BINARY_LENGTH_OES:
1114 *params = 0;
1115 break;
Brian Paule5c69642010-03-30 19:54:02 -06001116#if FEATURE_EXT_transform_feedback
1117 case GL_TRANSFORM_FEEDBACK_VARYINGS:
1118 *params = shProg->TransformFeedback.NumVarying;
1119 break;
1120 case GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH:
1121 *params = longest_feedback_varying_name(shProg) + 1;
1122 break;
1123 case GL_TRANSFORM_FEEDBACK_BUFFER_MODE:
1124 *params = shProg->TransformFeedback.BufferMode;
1125 break;
1126#endif
Brian34ae99d2006-12-18 08:28:54 -07001127 default:
Brian5b01c5e2006-12-19 18:02:03 -07001128 _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramiv(pname)");
1129 return;
Brian34ae99d2006-12-18 08:28:54 -07001130 }
Brian5b01c5e2006-12-19 18:02:03 -07001131}
Brian34ae99d2006-12-18 08:28:54 -07001132
Brian34ae99d2006-12-18 08:28:54 -07001133
Brian Paulfd59f192008-05-18 16:04:55 -06001134static void
Brian5b01c5e2006-12-19 18:02:03 -07001135_mesa_get_shaderiv(GLcontext *ctx, GLuint name, GLenum pname, GLint *params)
1136{
Brian Paul530df582008-07-03 16:21:11 -06001137 struct gl_shader *shader = _mesa_lookup_shader_err(ctx, name, "glGetShaderiv");
Brian5b01c5e2006-12-19 18:02:03 -07001138
1139 if (!shader) {
Brian5b01c5e2006-12-19 18:02:03 -07001140 return;
1141 }
Brian65a18442006-12-19 18:46:56 -07001142
Brian5b01c5e2006-12-19 18:02:03 -07001143 switch (pname) {
1144 case GL_SHADER_TYPE:
1145 *params = shader->Type;
1146 break;
1147 case GL_DELETE_STATUS:
1148 *params = shader->DeletePending;
1149 break;
1150 case GL_COMPILE_STATUS:
1151 *params = shader->CompileStatus;
1152 break;
1153 case GL_INFO_LOG_LENGTH:
Jan Dvorak5a0f02a2007-07-13 16:36:00 -06001154 *params = shader->InfoLog ? strlen(shader->InfoLog) + 1 : 0;
Brian5b01c5e2006-12-19 18:02:03 -07001155 break;
1156 case GL_SHADER_SOURCE_LENGTH:
Jan Dvorak5a0f02a2007-07-13 16:36:00 -06001157 *params = shader->Source ? strlen((char *) shader->Source) + 1 : 0;
Brian5b01c5e2006-12-19 18:02:03 -07001158 break;
1159 default:
1160 _mesa_error(ctx, GL_INVALID_ENUM, "glGetShaderiv(pname)");
1161 return;
1162 }
1163}
1164
1165
Brian Paulfd59f192008-05-18 16:04:55 -06001166static void
Brian5b01c5e2006-12-19 18:02:03 -07001167_mesa_get_program_info_log(GLcontext *ctx, GLuint program, GLsizei bufSize,
1168 GLsizei *length, GLchar *infoLog)
1169{
Brian65a18442006-12-19 18:46:56 -07001170 struct gl_shader_program *shProg
1171 = _mesa_lookup_shader_program(ctx, program);
1172 if (!shProg) {
Brian5b01c5e2006-12-19 18:02:03 -07001173 _mesa_error(ctx, GL_INVALID_VALUE, "glGetProgramInfoLog(program)");
1174 return;
1175 }
Brian Paule5c69642010-03-30 19:54:02 -06001176 _mesa_copy_string(infoLog, bufSize, length, shProg->InfoLog);
Brian5b01c5e2006-12-19 18:02:03 -07001177}
1178
1179
Brian Paulfd59f192008-05-18 16:04:55 -06001180static void
Brian5b01c5e2006-12-19 18:02:03 -07001181_mesa_get_shader_info_log(GLcontext *ctx, GLuint shader, GLsizei bufSize,
1182 GLsizei *length, GLchar *infoLog)
1183{
Brian65a18442006-12-19 18:46:56 -07001184 struct gl_shader *sh = _mesa_lookup_shader(ctx, shader);
1185 if (!sh) {
Brian5b01c5e2006-12-19 18:02:03 -07001186 _mesa_error(ctx, GL_INVALID_VALUE, "glGetShaderInfoLog(shader)");
1187 return;
1188 }
Brian Paule5c69642010-03-30 19:54:02 -06001189 _mesa_copy_string(infoLog, bufSize, length, sh->InfoLog);
Brian5b01c5e2006-12-19 18:02:03 -07001190}
1191
1192
1193/**
1194 * Called via ctx->Driver.GetShaderSource().
1195 */
Brian Paulfd59f192008-05-18 16:04:55 -06001196static void
Brian5b01c5e2006-12-19 18:02:03 -07001197_mesa_get_shader_source(GLcontext *ctx, GLuint shader, GLsizei maxLength,
1198 GLsizei *length, GLchar *sourceOut)
1199{
Brian Paul530df582008-07-03 16:21:11 -06001200 struct gl_shader *sh;
1201 sh = _mesa_lookup_shader_err(ctx, shader, "glGetShaderSource");
Brian65a18442006-12-19 18:46:56 -07001202 if (!sh) {
Brian5b01c5e2006-12-19 18:02:03 -07001203 return;
1204 }
Brian Paule5c69642010-03-30 19:54:02 -06001205 _mesa_copy_string(sourceOut, maxLength, length, sh->Source);
Brian5b01c5e2006-12-19 18:02:03 -07001206}
1207
1208
Brian Paul5b982362008-08-06 13:07:09 -06001209static void
1210get_matrix_dims(GLenum type, GLint *rows, GLint *cols)
1211{
1212 switch (type) {
1213 case GL_FLOAT_MAT2:
1214 *rows = *cols = 2;
1215 break;
1216 case GL_FLOAT_MAT2x3:
1217 *rows = 3;
1218 *cols = 2;
1219 break;
1220 case GL_FLOAT_MAT2x4:
1221 *rows = 4;
1222 *cols = 2;
1223 break;
1224 case GL_FLOAT_MAT3:
1225 *rows = 3;
1226 *cols = 3;
1227 break;
1228 case GL_FLOAT_MAT3x2:
1229 *rows = 2;
1230 *cols = 3;
1231 break;
1232 case GL_FLOAT_MAT3x4:
1233 *rows = 4;
1234 *cols = 3;
1235 break;
1236 case GL_FLOAT_MAT4:
1237 *rows = 4;
1238 *cols = 4;
1239 break;
1240 case GL_FLOAT_MAT4x2:
1241 *rows = 2;
1242 *cols = 4;
1243 break;
1244 case GL_FLOAT_MAT4x3:
1245 *rows = 3;
1246 *cols = 4;
1247 break;
1248 default:
1249 *rows = *cols = 0;
1250 }
1251}
1252
1253
1254/**
1255 * Determine the number of rows and columns occupied by a uniform
Brian Paulea9568d2008-09-16 08:55:54 -06001256 * according to its datatype. For non-matrix types (such as GL_FLOAT_VEC4),
1257 * the number of rows = 1 and cols = number of elements in the vector.
Brian Paul5b982362008-08-06 13:07:09 -06001258 */
1259static void
1260get_uniform_rows_cols(const struct gl_program_parameter *p,
1261 GLint *rows, GLint *cols)
1262{
1263 get_matrix_dims(p->DataType, rows, cols);
1264 if (*rows == 0 && *cols == 0) {
1265 /* not a matrix type, probably a float or vector */
Brian Paulea9568d2008-09-16 08:55:54 -06001266 if (p->Size <= 4) {
1267 *rows = 1;
1268 *cols = p->Size;
1269 }
1270 else {
1271 *rows = p->Size / 4 + 1;
1272 if (p->Size % 4 == 0)
1273 *cols = 4;
1274 else
1275 *cols = p->Size % 4;
1276 }
Brian Paul5b982362008-08-06 13:07:09 -06001277 }
1278}
1279
1280
Brian5b01c5e2006-12-19 18:02:03 -07001281/**
Brian Paul4ef7a932009-02-11 09:03:16 -07001282 * Helper for get_uniform[fi]v() functions.
1283 * Given a shader program name and uniform location, return a pointer
1284 * to the shader program and return the program parameter position.
Brian5b01c5e2006-12-19 18:02:03 -07001285 */
Brian Paul4ef7a932009-02-11 09:03:16 -07001286static void
1287lookup_uniform_parameter(GLcontext *ctx, GLuint program, GLint location,
1288 struct gl_program **progOut, GLint *paramPosOut)
Brian5b01c5e2006-12-19 18:02:03 -07001289{
Brian65a18442006-12-19 18:46:56 -07001290 struct gl_shader_program *shProg
Brian Paulbda6ad22008-08-06 12:45:14 -06001291 = _mesa_lookup_shader_program_err(ctx, program, "glGetUniform[if]v");
Brian Paul4ef7a932009-02-11 09:03:16 -07001292 struct gl_program *prog = NULL;
1293 GLint progPos = -1;
Brian Paulade50832008-05-14 16:09:46 -06001294
Brian Paul4ef7a932009-02-11 09:03:16 -07001295 /* if shProg is NULL, we'll have already recorded an error */
1296
1297 if (shProg) {
1298 if (!shProg->Uniforms ||
1299 location < 0 ||
1300 location >= (GLint) shProg->Uniforms->NumUniforms) {
1301 _mesa_error(ctx, GL_INVALID_OPERATION, "glGetUniformfv(location)");
1302 }
1303 else {
1304 /* OK, find the gl_program and program parameter location */
Brian Paulade50832008-05-14 16:09:46 -06001305 progPos = shProg->Uniforms->Uniforms[location].VertPos;
1306 if (progPos >= 0) {
1307 prog = &shProg->VertexProgram->Base;
Brian5b01c5e2006-12-19 18:02:03 -07001308 }
Brian Paulade50832008-05-14 16:09:46 -06001309 else {
1310 progPos = shProg->Uniforms->Uniforms[location].FragPos;
1311 if (progPos >= 0) {
1312 prog = &shProg->FragmentProgram->Base;
Bruce Merryeeb03fa2007-12-21 14:41:45 +02001313 }
Brian Paulade50832008-05-14 16:09:46 -06001314 }
Brian5b01c5e2006-12-19 18:02:03 -07001315 }
1316 }
Brian Paul4ef7a932009-02-11 09:03:16 -07001317
1318 *progOut = prog;
1319 *paramPosOut = progPos;
Brian Paul2be54a82008-07-08 16:17:04 -06001320}
1321
1322
1323/**
1324 * Called via ctx->Driver.GetUniformfv().
1325 */
1326static void
1327_mesa_get_uniformfv(GLcontext *ctx, GLuint program, GLint location,
1328 GLfloat *params)
1329{
Brian Paul4ef7a932009-02-11 09:03:16 -07001330 struct gl_program *prog;
1331 GLint paramPos;
1332
1333 lookup_uniform_parameter(ctx, program, location, &prog, &paramPos);
1334
1335 if (prog) {
1336 const struct gl_program_parameter *p =
1337 &prog->Parameters->Parameters[paramPos];
1338 GLint rows, cols, i, j, k;
1339
1340 get_uniform_rows_cols(p, &rows, &cols);
1341
1342 k = 0;
1343 for (i = 0; i < rows; i++) {
1344 for (j = 0; j < cols; j++ ) {
1345 params[k++] = prog->Parameters->ParameterValues[paramPos+i][j];
1346 }
1347 }
1348 }
Brian Paul2be54a82008-07-08 16:17:04 -06001349}
1350
1351
1352/**
1353 * Called via ctx->Driver.GetUniformiv().
Brian Paul4ef7a932009-02-11 09:03:16 -07001354 * \sa _mesa_get_uniformfv, only difference is a cast.
Brian Paul2be54a82008-07-08 16:17:04 -06001355 */
1356static void
1357_mesa_get_uniformiv(GLcontext *ctx, GLuint program, GLint location,
1358 GLint *params)
1359{
Brian Paul4ef7a932009-02-11 09:03:16 -07001360 struct gl_program *prog;
1361 GLint paramPos;
1362
1363 lookup_uniform_parameter(ctx, program, location, &prog, &paramPos);
1364
1365 if (prog) {
1366 const struct gl_program_parameter *p =
1367 &prog->Parameters->Parameters[paramPos];
1368 GLint rows, cols, i, j, k;
1369
1370 get_uniform_rows_cols(p, &rows, &cols);
1371
1372 k = 0;
1373 for (i = 0; i < rows; i++) {
1374 for (j = 0; j < cols; j++ ) {
1375 params[k++] = (GLint) prog->Parameters->ParameterValues[paramPos+i][j];
1376 }
1377 }
Brian Paul2be54a82008-07-08 16:17:04 -06001378 }
Brian5b01c5e2006-12-19 18:02:03 -07001379}
1380
1381
1382/**
Brian Pauleda291e2008-08-06 16:26:47 -06001383 * The value returned by GetUniformLocation actually encodes two things:
1384 * 1. the index into the prog->Uniforms[] array for the uniform
1385 * 2. an offset in the prog->ParameterValues[] array for specifying array
1386 * elements or structure fields.
1387 * This function merges those two values.
1388 */
1389static void
1390merge_location_offset(GLint *location, GLint offset)
1391{
1392 *location = *location | (offset << 16);
1393}
1394
1395
1396/**
1397 * Seperate the uniform location and parameter offset. See above.
1398 */
1399static void
1400split_location_offset(GLint *location, GLint *offset)
1401{
1402 *offset = (*location >> 16);
1403 *location = *location & 0xffff;
1404}
1405
1406
1407/**
Brian5b01c5e2006-12-19 18:02:03 -07001408 * Called via ctx->Driver.GetUniformLocation().
Brian Pauleda291e2008-08-06 16:26:47 -06001409 *
1410 * The return value will encode two values, the uniform location and an
1411 * offset (used for arrays, structs).
Brian5b01c5e2006-12-19 18:02:03 -07001412 */
Brian Paulfd59f192008-05-18 16:04:55 -06001413static GLint
Brian5b01c5e2006-12-19 18:02:03 -07001414_mesa_get_uniform_location(GLcontext *ctx, GLuint program, const GLchar *name)
1415{
Brian Pauleda291e2008-08-06 16:26:47 -06001416 GLint offset = 0, location = -1;
1417
Brian Paul530df582008-07-03 16:21:11 -06001418 struct gl_shader_program *shProg =
1419 _mesa_lookup_shader_program_err(ctx, program, "glGetUniformLocation");
1420
Brian Paulade50832008-05-14 16:09:46 -06001421 if (!shProg)
1422 return -1;
Brian5b01c5e2006-12-19 18:02:03 -07001423
Brian Paule06565b2008-07-04 09:58:55 -06001424 if (shProg->LinkStatus == GL_FALSE) {
1425 _mesa_error(ctx, GL_INVALID_OPERATION, "glGetUniformfv(program)");
1426 return -1;
1427 }
1428
Brian Paul530df582008-07-03 16:21:11 -06001429 /* XXX we should return -1 if the uniform was declared, but not
1430 * actually used.
1431 */
1432
Brian Pauleda291e2008-08-06 16:26:47 -06001433 /* XXX we need to be able to parse uniform names for structs and arrays
1434 * such as:
1435 * mymatrix[1]
1436 * mystruct.field1
1437 */
1438
1439 {
1440 /* handle 1-dimension arrays here... */
1441 char *c = strchr(name, '[');
1442 if (c) {
1443 /* truncate name at [ */
1444 const GLint len = c - name;
Kristian Høgsberg32f2fd12010-02-19 11:58:49 -05001445 GLchar *newName = malloc(len + 1);
Brian Pauleda291e2008-08-06 16:26:47 -06001446 if (!newName)
1447 return -1; /* out of mem */
Kenneth Graunkec7ac48622010-02-18 23:50:59 -08001448 memcpy(newName, name, len);
Brian Pauleda291e2008-08-06 16:26:47 -06001449 newName[len] = 0;
1450
1451 location = _mesa_lookup_uniform(shProg->Uniforms, newName);
1452 if (location >= 0) {
Kenneth Graunke60b0cae2010-02-18 23:50:58 -08001453 const GLint element = atoi(c + 1);
Brian Pauleda291e2008-08-06 16:26:47 -06001454 if (element > 0) {
1455 /* get type of the uniform array element */
1456 struct gl_program_parameter *p;
1457 p = get_uniform_parameter(shProg, location);
1458 if (p) {
1459 GLint rows, cols;
1460 get_matrix_dims(p->DataType, &rows, &cols);
1461 if (rows < 1)
1462 rows = 1;
1463 offset = element * rows;
1464 }
1465 }
1466 }
1467
Kristian Høgsberg32f2fd12010-02-19 11:58:49 -05001468 free(newName);
Brian Pauleda291e2008-08-06 16:26:47 -06001469 }
1470 }
1471
1472 if (location < 0) {
1473 location = _mesa_lookup_uniform(shProg->Uniforms, name);
1474 }
1475
1476 if (location >= 0) {
1477 merge_location_offset(&location, offset);
1478 }
1479
1480 return location;
Brian5b01c5e2006-12-19 18:02:03 -07001481}
1482
1483
Brian34ae99d2006-12-18 08:28:54 -07001484
Brian5b01c5e2006-12-19 18:02:03 -07001485/**
1486 * Called via ctx->Driver.ShaderSource()
1487 */
Brian Paulfd59f192008-05-18 16:04:55 -06001488static void
Brian5b01c5e2006-12-19 18:02:03 -07001489_mesa_shader_source(GLcontext *ctx, GLuint shader, const GLchar *source)
Brian34ae99d2006-12-18 08:28:54 -07001490{
Brian Paul530df582008-07-03 16:21:11 -06001491 struct gl_shader *sh;
1492
1493 sh = _mesa_lookup_shader_err(ctx, shader, "glShaderSource");
1494 if (!sh)
Brian34ae99d2006-12-18 08:28:54 -07001495 return;
Brian34ae99d2006-12-18 08:28:54 -07001496
Brian34ae99d2006-12-18 08:28:54 -07001497 /* free old shader source string and install new one */
Brian65a18442006-12-19 18:46:56 -07001498 if (sh->Source) {
Kristian Høgsberg32f2fd12010-02-19 11:58:49 -05001499 free((void *) sh->Source);
Brian34ae99d2006-12-18 08:28:54 -07001500 }
Brian65a18442006-12-19 18:46:56 -07001501 sh->Source = source;
Brian9e4bae92006-12-20 09:27:42 -07001502 sh->CompileStatus = GL_FALSE;
Brian Paulf7783ba2009-08-04 15:35:48 -06001503#ifdef DEBUG
1504 sh->SourceChecksum = _mesa_str_checksum(sh->Source);
1505#endif
Brian34ae99d2006-12-18 08:28:54 -07001506}
1507
1508
Brian5b01c5e2006-12-19 18:02:03 -07001509/**
1510 * Called via ctx->Driver.CompileShader()
1511 */
Brian Paulfd59f192008-05-18 16:04:55 -06001512static void
Brian5b01c5e2006-12-19 18:02:03 -07001513_mesa_compile_shader(GLcontext *ctx, GLuint shaderObj)
Brian34ae99d2006-12-18 08:28:54 -07001514{
Brian Paul530df582008-07-03 16:21:11 -06001515 struct gl_shader *sh;
Brian34ae99d2006-12-18 08:28:54 -07001516
Brian Paul530df582008-07-03 16:21:11 -06001517 sh = _mesa_lookup_shader_err(ctx, shaderObj, "glCompileShader");
1518 if (!sh)
Brian34ae99d2006-12-18 08:28:54 -07001519 return;
Brian34ae99d2006-12-18 08:28:54 -07001520
Brian Paul65fc2ca2009-03-19 10:25:24 -06001521 /* set default pragma state for shader */
1522 sh->Pragmas = ctx->Shader.DefaultPragmas;
1523
Brian Paulcb136e02009-01-22 10:34:15 -07001524 /* this call will set the sh->CompileStatus field to indicate if
1525 * compilation was successful.
1526 */
1527 (void) _slang_compile(ctx, sh);
Brian34ae99d2006-12-18 08:28:54 -07001528}
1529
1530
Brian5b01c5e2006-12-19 18:02:03 -07001531/**
1532 * Called via ctx->Driver.LinkProgram()
1533 */
Brian Paulfd59f192008-05-18 16:04:55 -06001534static void
Brian5b01c5e2006-12-19 18:02:03 -07001535_mesa_link_program(GLcontext *ctx, GLuint program)
Brian34ae99d2006-12-18 08:28:54 -07001536{
Brian65a18442006-12-19 18:46:56 -07001537 struct gl_shader_program *shProg;
Brian Paulfef6e362010-05-10 21:11:21 -06001538 struct gl_transform_feedback_object *obj =
1539 ctx->TransformFeedback.CurrentObject;
Brian34ae99d2006-12-18 08:28:54 -07001540
Brian Paul530df582008-07-03 16:21:11 -06001541 shProg = _mesa_lookup_shader_program_err(ctx, program, "glLinkProgram");
1542 if (!shProg)
Brian34ae99d2006-12-18 08:28:54 -07001543 return;
Brian34ae99d2006-12-18 08:28:54 -07001544
Brian Paulfef6e362010-05-10 21:11:21 -06001545 if (obj->Active && shProg == ctx->Shader.CurrentProgram) {
Brian Paul1a148662010-04-01 22:15:16 -06001546 _mesa_error(ctx, GL_INVALID_OPERATION,
1547 "glLinkProgram(transform feedback active");
1548 return;
1549 }
1550
Briandf43fb62008-05-06 23:08:51 -06001551 FLUSH_VERTICES(ctx, _NEW_PROGRAM);
1552
Brianc1771912007-02-16 09:56:19 -07001553 _slang_link(ctx, program, shProg);
Brian Paulac3c8e32009-09-14 17:32:03 -06001554
1555 /* debug code */
1556 if (0) {
1557 GLuint i;
1558
Kristian Høgsberg298be2b2010-02-19 12:32:24 -05001559 printf("Link %u shaders in program %u: %s\n",
Brian Paulac3c8e32009-09-14 17:32:03 -06001560 shProg->NumShaders, shProg->Name,
1561 shProg->LinkStatus ? "Success" : "Failed");
1562
1563 for (i = 0; i < shProg->NumShaders; i++) {
Kristian Høgsberg298be2b2010-02-19 12:32:24 -05001564 printf(" shader %u, type 0x%x\n",
Brian Paulac3c8e32009-09-14 17:32:03 -06001565 shProg->Shaders[i]->Name,
1566 shProg->Shaders[i]->Type);
1567 }
1568 }
Brian34ae99d2006-12-18 08:28:54 -07001569}
1570
1571
1572/**
Brian Paul346250b2009-10-23 16:31:48 -06001573 * Print basic shader info (for debug).
1574 */
1575static void
1576print_shader_info(const struct gl_shader_program *shProg)
1577{
1578 GLuint i;
1579
Kristian Høgsberg298be2b2010-02-19 12:32:24 -05001580 printf("Mesa: glUseProgram(%u)\n", shProg->Name);
Brian Paul346250b2009-10-23 16:31:48 -06001581 for (i = 0; i < shProg->NumShaders; i++) {
1582 const char *s;
1583 switch (shProg->Shaders[i]->Type) {
1584 case GL_VERTEX_SHADER:
1585 s = "vertex";
1586 break;
1587 case GL_FRAGMENT_SHADER:
1588 s = "fragment";
1589 break;
1590 case GL_GEOMETRY_SHADER:
1591 s = "geometry";
1592 break;
1593 default:
1594 s = "";
1595 }
Kristian Høgsberg298be2b2010-02-19 12:32:24 -05001596 printf(" %s shader %u, checksum %u\n", s,
1597 shProg->Shaders[i]->Name,
1598 shProg->Shaders[i]->SourceChecksum);
Brian Paul346250b2009-10-23 16:31:48 -06001599 }
1600 if (shProg->VertexProgram)
Kristian Høgsberg298be2b2010-02-19 12:32:24 -05001601 printf(" vert prog %u\n", shProg->VertexProgram->Base.Id);
Brian Paul346250b2009-10-23 16:31:48 -06001602 if (shProg->FragmentProgram)
Kristian Høgsberg298be2b2010-02-19 12:32:24 -05001603 printf(" frag prog %u\n", shProg->FragmentProgram->Base.Id);
Brian Paul346250b2009-10-23 16:31:48 -06001604}
1605
1606
1607/**
Brian5b01c5e2006-12-19 18:02:03 -07001608 * Called via ctx->Driver.UseProgram()
Brian34ae99d2006-12-18 08:28:54 -07001609 */
Brian5b01c5e2006-12-19 18:02:03 -07001610void
1611_mesa_use_program(GLcontext *ctx, GLuint program)
Brian34ae99d2006-12-18 08:28:54 -07001612{
Brian3c008a02007-04-12 15:22:32 -06001613 struct gl_shader_program *shProg;
Brian Paulfef6e362010-05-10 21:11:21 -06001614 struct gl_transform_feedback_object *obj =
1615 ctx->TransformFeedback.CurrentObject;
Brian3c008a02007-04-12 15:22:32 -06001616
Brian Paulfef6e362010-05-10 21:11:21 -06001617 if (obj->Active) {
Brian Paul1a148662010-04-01 22:15:16 -06001618 _mesa_error(ctx, GL_INVALID_OPERATION,
1619 "glUseProgram(transform feedback active)");
1620 return;
1621 }
1622
Brian00d63aa2007-02-03 11:35:02 -07001623 if (ctx->Shader.CurrentProgram &&
1624 ctx->Shader.CurrentProgram->Name == program) {
1625 /* no-op */
1626 return;
1627 }
1628
Brian5b01c5e2006-12-19 18:02:03 -07001629 if (program) {
Brian Paul530df582008-07-03 16:21:11 -06001630 shProg = _mesa_lookup_shader_program_err(ctx, program, "glUseProgram");
Brian65a18442006-12-19 18:46:56 -07001631 if (!shProg) {
Brian Paul530df582008-07-03 16:21:11 -06001632 return;
1633 }
1634 if (!shProg->LinkStatus) {
Brian Paul621c9992009-02-18 13:28:12 -07001635 _mesa_error(ctx, GL_INVALID_OPERATION,
1636 "glUseProgram(program %u not linked)", program);
Brian5b01c5e2006-12-19 18:02:03 -07001637 return;
1638 }
Brian Paul4eda17d2009-03-13 09:11:42 -06001639
1640 /* debug code */
Brian Paul2ee7fd82009-10-15 15:25:52 -06001641 if (ctx->Shader.Flags & GLSL_USE_PROG) {
Brian Paul346250b2009-10-23 16:31:48 -06001642 print_shader_info(shProg);
Brian Paul4eda17d2009-03-13 09:11:42 -06001643 }
Brian5b01c5e2006-12-19 18:02:03 -07001644 }
1645 else {
Brian3c008a02007-04-12 15:22:32 -06001646 shProg = NULL;
1647 }
1648
Brian Paulb44304e2009-10-27 20:09:33 -06001649 if (ctx->Shader.CurrentProgram != shProg) {
1650 FLUSH_VERTICES(ctx, _NEW_PROGRAM | _NEW_PROGRAM_CONSTANTS);
1651 _mesa_reference_shader_program(ctx, &ctx->Shader.CurrentProgram, shProg);
1652 }
Brian5b01c5e2006-12-19 18:02:03 -07001653}
Brian34ae99d2006-12-18 08:28:54 -07001654
Brian5b01c5e2006-12-19 18:02:03 -07001655
Brian Paulade50832008-05-14 16:09:46 -06001656
1657/**
Brian Paul517401a2008-11-06 15:04:11 -07001658 * Update the vertex/fragment program's TexturesUsed array.
1659 *
1660 * This needs to be called after glUniform(set sampler var) is called.
1661 * A call to glUniform(samplerVar, value) causes a sampler to point to a
1662 * particular texture unit. We know the sampler's texture target
1663 * (1D/2D/3D/etc) from compile time but the sampler's texture unit is
1664 * set by glUniform() calls.
1665 *
1666 * So, scan the program->SamplerUnits[] and program->SamplerTargets[]
1667 * information to update the prog->TexturesUsed[] values.
1668 * Each value of TexturesUsed[unit] is one of zero, TEXTURE_1D_INDEX,
1669 * TEXTURE_2D_INDEX, TEXTURE_3D_INDEX, etc.
1670 * We'll use that info for state validation before rendering.
Brian Paulade50832008-05-14 16:09:46 -06001671 */
Brian Paul517401a2008-11-06 15:04:11 -07001672void
1673_mesa_update_shader_textures_used(struct gl_program *prog)
Brian Paulade50832008-05-14 16:09:46 -06001674{
1675 GLuint s;
1676
1677 memset(prog->TexturesUsed, 0, sizeof(prog->TexturesUsed));
1678
1679 for (s = 0; s < MAX_SAMPLERS; s++) {
1680 if (prog->SamplersUsed & (1 << s)) {
Brian Paulf05344f2009-08-26 10:58:06 -06001681 GLuint unit = prog->SamplerUnits[s];
1682 GLuint tgt = prog->SamplerTargets[s];
1683 assert(unit < MAX_TEXTURE_IMAGE_UNITS);
1684 assert(tgt < NUM_TEXTURE_TARGETS);
1685 prog->TexturesUsed[unit] |= (1 << tgt);
Brian Paulade50832008-05-14 16:09:46 -06001686 }
1687 }
1688}
1689
1690
1691/**
Brian Paulffbc66b2008-07-21 13:58:50 -06001692 * Check if the type given by userType is allowed to set a uniform of the
1693 * target type. Generally, equivalence is required, but setting Boolean
1694 * uniforms can be done with glUniformiv or glUniformfv.
1695 */
1696static GLboolean
1697compatible_types(GLenum userType, GLenum targetType)
1698{
1699 if (userType == targetType)
1700 return GL_TRUE;
1701
Brian Paul91f841a2010-05-25 18:39:47 -06001702 if (targetType == GL_BOOL && (userType == GL_FLOAT ||
1703 userType == GL_UNSIGNED_INT ||
1704 userType == GL_INT))
Brian Paulffbc66b2008-07-21 13:58:50 -06001705 return GL_TRUE;
1706
1707 if (targetType == GL_BOOL_VEC2 && (userType == GL_FLOAT_VEC2 ||
Brian Paul91f841a2010-05-25 18:39:47 -06001708 userType == GL_UNSIGNED_INT_VEC2 ||
Brian Paulffbc66b2008-07-21 13:58:50 -06001709 userType == GL_INT_VEC2))
1710 return GL_TRUE;
1711
1712 if (targetType == GL_BOOL_VEC3 && (userType == GL_FLOAT_VEC3 ||
Brian Paul91f841a2010-05-25 18:39:47 -06001713 userType == GL_UNSIGNED_INT_VEC3 ||
Brian Paulffbc66b2008-07-21 13:58:50 -06001714 userType == GL_INT_VEC3))
1715 return GL_TRUE;
1716
1717 if (targetType == GL_BOOL_VEC4 && (userType == GL_FLOAT_VEC4 ||
Brian Paul91f841a2010-05-25 18:39:47 -06001718 userType == GL_UNSIGNED_INT_VEC4 ||
Brian Paulffbc66b2008-07-21 13:58:50 -06001719 userType == GL_INT_VEC4))
1720 return GL_TRUE;
1721
Brianb36749d2008-07-21 20:42:05 -06001722 if (is_sampler_type(targetType) && userType == GL_INT)
1723 return GL_TRUE;
1724
Brian Paulffbc66b2008-07-21 13:58:50 -06001725 return GL_FALSE;
1726}
1727
1728
1729/**
Brian Paulade50832008-05-14 16:09:46 -06001730 * Set the value of a program's uniform variable.
1731 * \param program the program whose uniform to update
Brian Pauleda291e2008-08-06 16:26:47 -06001732 * \param index the index of the program parameter for the uniform
1733 * \param offset additional parameter slot offset (for arrays)
Brian Paulc4ffbf02009-02-18 17:46:00 -07001734 * \param type the incoming datatype of 'values'
Brian Paulade50832008-05-14 16:09:46 -06001735 * \param count the number of uniforms to set
Brian Paulc4ffbf02009-02-18 17:46:00 -07001736 * \param elems number of elements per uniform (1, 2, 3 or 4)
1737 * \param values the new values, of datatype 'type'
Brian Paulade50832008-05-14 16:09:46 -06001738 */
1739static void
Brian Pauleda291e2008-08-06 16:26:47 -06001740set_program_uniform(GLcontext *ctx, struct gl_program *program,
1741 GLint index, GLint offset,
1742 GLenum type, GLsizei count, GLint elems,
1743 const void *values)
Brian Paulade50832008-05-14 16:09:46 -06001744{
Brian Paul6df38e62009-08-26 14:35:45 -06001745 const struct gl_program_parameter *param =
Brian Paul949e7382008-11-05 09:17:55 -07001746 &program->Parameters->Parameters[index];
1747
Brian Pauleda291e2008-08-06 16:26:47 -06001748 assert(offset >= 0);
Brian Paulc4ffbf02009-02-18 17:46:00 -07001749 assert(elems >= 1);
1750 assert(elems <= 4);
Brian Pauleda291e2008-08-06 16:26:47 -06001751
Brian Paul949e7382008-11-05 09:17:55 -07001752 if (!compatible_types(type, param->DataType)) {
Brian Paulffbc66b2008-07-21 13:58:50 -06001753 _mesa_error(ctx, GL_INVALID_OPERATION, "glUniform(type mismatch)");
1754 return;
1755 }
1756
Michal Krolc5c71302008-08-07 16:23:15 +02001757 if (index + offset > (GLint) program->Parameters->Size) {
Brian Pauleda291e2008-08-06 16:26:47 -06001758 /* out of bounds! */
1759 return;
1760 }
1761
Brian Paul949e7382008-11-05 09:17:55 -07001762 if (param->Type == PROGRAM_SAMPLER) {
Brian Paulade50832008-05-14 16:09:46 -06001763 /* This controls which texture unit which is used by a sampler */
Brian Paulbabb5ba2009-08-26 14:29:50 -06001764 GLboolean changed = GL_FALSE;
Brian Paul2b4f0212009-02-11 09:12:34 -07001765 GLint i;
Brian Paulade50832008-05-14 16:09:46 -06001766
Brian Paul6df38e62009-08-26 14:35:45 -06001767 /* this should have been caught by the compatible_types() check */
1768 ASSERT(type == GL_INT);
Brian Paulade50832008-05-14 16:09:46 -06001769
Brian Paul6df38e62009-08-26 14:35:45 -06001770 /* loop over number of samplers to change */
Brian Paul2b4f0212009-02-11 09:12:34 -07001771 for (i = 0; i < count; i++) {
Brian Paul04d17072009-08-26 11:39:24 -06001772 GLuint sampler =
1773 (GLuint) program->Parameters->ParameterValues[index + offset + i][0];
1774 GLuint texUnit = ((GLuint *) values)[i];
Brian Paulade50832008-05-14 16:09:46 -06001775
Brian Paul2b4f0212009-02-11 09:12:34 -07001776 /* check that the sampler (tex unit index) is legal */
1777 if (texUnit >= ctx->Const.MaxTextureImageUnits) {
1778 _mesa_error(ctx, GL_INVALID_VALUE,
Brian Paul16f8df892010-05-13 16:52:06 -06001779 "glUniform1(invalid sampler/tex unit index for '%s')",
1780 param->Name);
Brian Paul2b4f0212009-02-11 09:12:34 -07001781 return;
1782 }
1783
1784 /* This maps a sampler to a texture unit: */
1785 if (sampler < MAX_SAMPLERS) {
Brian Paul04d17072009-08-26 11:39:24 -06001786#if 0
Kristian Høgsberg298be2b2010-02-19 12:32:24 -05001787 printf("Set program %p sampler %d '%s' to unit %u\n",
1788 program, sampler, param->Name, texUnit);
Brian Paul04d17072009-08-26 11:39:24 -06001789#endif
Brian Paulbabb5ba2009-08-26 14:29:50 -06001790 if (program->SamplerUnits[sampler] != texUnit) {
1791 program->SamplerUnits[sampler] = texUnit;
1792 changed = GL_TRUE;
1793 }
Brian Paul2b4f0212009-02-11 09:12:34 -07001794 }
Brian Paulade50832008-05-14 16:09:46 -06001795 }
1796
Brian Paulbabb5ba2009-08-26 14:29:50 -06001797 if (changed) {
1798 /* When a sampler's value changes it usually requires rewriting
1799 * a GPU program's TEX instructions since there may not be a
1800 * sampler->texture lookup table. We signal this with the
1801 * ProgramStringNotify() callback.
1802 */
1803 FLUSH_VERTICES(ctx, _NEW_TEXTURE | _NEW_PROGRAM);
1804 _mesa_update_shader_textures_used(program);
Brian Paul4ac9c802010-02-04 16:49:35 -07001805 /* Do we need to care about the return value here?
1806 * This should not be the first time the driver was notified of
1807 * this program.
1808 */
1809 (void) ctx->Driver.ProgramStringNotify(ctx, program->Target, program);
Brian Paulbabb5ba2009-08-26 14:29:50 -06001810 }
Brian Paulade50832008-05-14 16:09:46 -06001811 }
1812 else {
1813 /* ordinary uniform variable */
Brian Paul6df38e62009-08-26 14:35:45 -06001814 const GLboolean isUniformBool = is_boolean_type(param->DataType);
1815 const GLboolean areIntValues = is_integer_type(type);
Brian Paul91f841a2010-05-25 18:39:47 -06001816 const GLboolean areUintValues = is_uint_type(type);
Brian Paul2c1ea072009-02-11 08:46:21 -07001817 const GLint slots = (param->Size + 3) / 4;
Brian Paul1a148662010-04-01 22:15:16 -06001818 const GLint typeSize = _mesa_sizeof_glsl_type(param->DataType);
Brian Paul6df38e62009-08-26 14:35:45 -06001819 GLsizei k, i;
Brian Paulade50832008-05-14 16:09:46 -06001820
Brian Paul20fbb242010-01-27 17:03:04 -07001821 if ((GLint) param->Size > typeSize) {
Brian Paul2c1ea072009-02-11 08:46:21 -07001822 /* an array */
1823 /* we'll ignore extra data below */
1824 }
1825 else {
Nicolai Hähnle9fde81b2009-10-03 16:30:16 +02001826 /* non-array: count must be at most one; count == 0 is handled by the loop below */
1827 if (count > 1) {
Brian Paul2c1ea072009-02-11 08:46:21 -07001828 _mesa_error(ctx, GL_INVALID_OPERATION,
Brian Paul16f8df892010-05-13 16:52:06 -06001829 "glUniform(uniform '%s' is not an array)",
1830 param->Name);
Brian Paul2c1ea072009-02-11 08:46:21 -07001831 return;
1832 }
Brian Paulade50832008-05-14 16:09:46 -06001833 }
1834
Brian Paulc4ffbf02009-02-18 17:46:00 -07001835 /* loop over number of array elements */
Brian Paulade50832008-05-14 16:09:46 -06001836 for (k = 0; k < count; k++) {
Brian Paul2c1ea072009-02-11 08:46:21 -07001837 GLfloat *uniformVal;
1838
Brian Paulb9d8f712009-02-18 17:40:44 -07001839 if (offset + k >= slots) {
Brian Paul2c1ea072009-02-11 08:46:21 -07001840 /* Extra array data is ignored */
1841 break;
1842 }
1843
Brian Paulc4ffbf02009-02-18 17:46:00 -07001844 /* uniformVal (the destination) is always float[4] */
Brian Paul2c1ea072009-02-11 08:46:21 -07001845 uniformVal = program->Parameters->ParameterValues[index + offset + k];
Brian Paulc4ffbf02009-02-18 17:46:00 -07001846
1847 if (areIntValues) {
1848 /* convert user's ints to floats */
Brian Paulade50832008-05-14 16:09:46 -06001849 const GLint *iValues = ((const GLint *) values) + k * elems;
1850 for (i = 0; i < elems; i++) {
1851 uniformVal[i] = (GLfloat) iValues[i];
1852 }
1853 }
Brian Paul91f841a2010-05-25 18:39:47 -06001854 else if (areUintValues) {
1855 /* convert user's uints to floats */
1856 const GLuint *iValues = ((const GLuint *) values) + k * elems;
1857 for (i = 0; i < elems; i++) {
1858 uniformVal[i] = (GLfloat) iValues[i];
1859 }
1860 }
Brian Paulade50832008-05-14 16:09:46 -06001861 else {
1862 const GLfloat *fValues = ((const GLfloat *) values) + k * elems;
1863 for (i = 0; i < elems; i++) {
1864 uniformVal[i] = fValues[i];
1865 }
1866 }
Brian Pauleda291e2008-08-06 16:26:47 -06001867
1868 /* if the uniform is bool-valued, convert to 1.0 or 0.0 */
Brian Paulc4ffbf02009-02-18 17:46:00 -07001869 if (isUniformBool) {
Brian Pauleda291e2008-08-06 16:26:47 -06001870 for (i = 0; i < elems; i++) {
Michal Krolc5c71302008-08-07 16:23:15 +02001871 uniformVal[i] = uniformVal[i] ? 1.0f : 0.0f;
Brian Pauleda291e2008-08-06 16:26:47 -06001872 }
1873 }
Brian Paulade50832008-05-14 16:09:46 -06001874 }
1875 }
1876}
1877
1878
Brian5b01c5e2006-12-19 18:02:03 -07001879/**
1880 * Called via ctx->Driver.Uniform().
1881 */
Brian Paulfd59f192008-05-18 16:04:55 -06001882static void
Brian5b01c5e2006-12-19 18:02:03 -07001883_mesa_uniform(GLcontext *ctx, GLint location, GLsizei count,
1884 const GLvoid *values, GLenum type)
1885{
Brian3a8e2772006-12-20 17:19:16 -07001886 struct gl_shader_program *shProg = ctx->Shader.CurrentProgram;
Brian Paul2d76a0d2008-11-10 12:33:17 -07001887 struct gl_uniform *uniform;
Brian Pauleda291e2008-08-06 16:26:47 -06001888 GLint elems, offset;
Brian Paule01a03d2009-02-06 10:21:36 -07001889 GLenum basicType;
Brian3a8e2772006-12-20 17:19:16 -07001890
1891 if (!shProg || !shProg->LinkStatus) {
Brian5b01c5e2006-12-19 18:02:03 -07001892 _mesa_error(ctx, GL_INVALID_OPERATION, "glUniform(program not linked)");
Brian3a8e2772006-12-20 17:19:16 -07001893 return;
1894 }
1895
Bruce Merryeeb03fa2007-12-21 14:41:45 +02001896 if (location == -1)
1897 return; /* The standard specifies this as a no-op */
1898
Brian Paul234f03e2009-02-11 09:05:08 -07001899 if (location < -1) {
Brian Paul16f8df892010-05-13 16:52:06 -06001900 _mesa_error(ctx, GL_INVALID_OPERATION, "glUniform(location=%d)",
1901 location);
Brian Paul234f03e2009-02-11 09:05:08 -07001902 return;
1903 }
1904
Brian Pauleda291e2008-08-06 16:26:47 -06001905 split_location_offset(&location, &offset);
1906
Brian Paulade50832008-05-14 16:09:46 -06001907 if (location < 0 || location >= (GLint) shProg->Uniforms->NumUniforms) {
Brian Paul16f8df892010-05-13 16:52:06 -06001908 _mesa_error(ctx, GL_INVALID_VALUE, "glUniform(location=%d)", location);
Brian3a8e2772006-12-20 17:19:16 -07001909 return;
1910 }
1911
Brian52363952007-03-13 16:50:24 -06001912 if (count < 0) {
1913 _mesa_error(ctx, GL_INVALID_VALUE, "glUniform(count < 0)");
1914 return;
1915 }
1916
Brian98650bd2007-03-13 16:32:48 -06001917 switch (type) {
1918 case GL_FLOAT:
Brian Paule01a03d2009-02-06 10:21:36 -07001919 basicType = GL_FLOAT;
1920 elems = 1;
1921 break;
Brian98650bd2007-03-13 16:32:48 -06001922 case GL_INT:
Brian Paule01a03d2009-02-06 10:21:36 -07001923 basicType = GL_INT;
Brian98650bd2007-03-13 16:32:48 -06001924 elems = 1;
1925 break;
Brian Paul91f841a2010-05-25 18:39:47 -06001926 case GL_UNSIGNED_INT:
1927 basicType = GL_UNSIGNED_INT;
1928 elems = 1;
1929 break;
Brian98650bd2007-03-13 16:32:48 -06001930 case GL_FLOAT_VEC2:
Brian Paule01a03d2009-02-06 10:21:36 -07001931 basicType = GL_FLOAT;
1932 elems = 2;
1933 break;
Brian98650bd2007-03-13 16:32:48 -06001934 case GL_INT_VEC2:
Brian Paule01a03d2009-02-06 10:21:36 -07001935 basicType = GL_INT;
Brian98650bd2007-03-13 16:32:48 -06001936 elems = 2;
1937 break;
Brian Paul91f841a2010-05-25 18:39:47 -06001938 case GL_UNSIGNED_INT_VEC2:
1939 basicType = GL_UNSIGNED_INT;
1940 elems = 2;
1941 break;
Brian98650bd2007-03-13 16:32:48 -06001942 case GL_FLOAT_VEC3:
Brian Paule01a03d2009-02-06 10:21:36 -07001943 basicType = GL_FLOAT;
1944 elems = 3;
1945 break;
Brian98650bd2007-03-13 16:32:48 -06001946 case GL_INT_VEC3:
Brian Paule01a03d2009-02-06 10:21:36 -07001947 basicType = GL_INT;
Brian98650bd2007-03-13 16:32:48 -06001948 elems = 3;
1949 break;
Brian Paul91f841a2010-05-25 18:39:47 -06001950 case GL_UNSIGNED_INT_VEC3:
1951 basicType = GL_UNSIGNED_INT;
1952 elems = 3;
1953 break;
Brian98650bd2007-03-13 16:32:48 -06001954 case GL_FLOAT_VEC4:
Brian Paule01a03d2009-02-06 10:21:36 -07001955 basicType = GL_FLOAT;
1956 elems = 4;
1957 break;
Brian98650bd2007-03-13 16:32:48 -06001958 case GL_INT_VEC4:
Brian Paule01a03d2009-02-06 10:21:36 -07001959 basicType = GL_INT;
Brian98650bd2007-03-13 16:32:48 -06001960 elems = 4;
1961 break;
Brian Paul91f841a2010-05-25 18:39:47 -06001962 case GL_UNSIGNED_INT_VEC4:
1963 basicType = GL_UNSIGNED_INT;
1964 elems = 4;
1965 break;
Brian98650bd2007-03-13 16:32:48 -06001966 default:
1967 _mesa_problem(ctx, "Invalid type in _mesa_uniform");
1968 return;
Brian89dc4852007-01-04 14:35:44 -07001969 }
Brian98650bd2007-03-13 16:32:48 -06001970
Brian Paul027ed1b2009-04-24 09:43:44 -06001971 FLUSH_VERTICES(ctx, _NEW_PROGRAM_CONSTANTS);
Brian98650bd2007-03-13 16:32:48 -06001972
Brian Paul2d76a0d2008-11-10 12:33:17 -07001973 uniform = &shProg->Uniforms->Uniforms[location];
1974
Brian Paule01a03d2009-02-06 10:21:36 -07001975 if (ctx->Shader.Flags & GLSL_UNIFORMS) {
1976 GLint i;
Kristian Høgsberg298be2b2010-02-19 12:32:24 -05001977 printf("Mesa: set program %u uniform %s (loc %d) to: ",
1978 shProg->Name, uniform->Name, location);
Brian Paule01a03d2009-02-06 10:21:36 -07001979 if (basicType == GL_INT) {
1980 const GLint *v = (const GLint *) values;
1981 for (i = 0; i < count * elems; i++) {
Kristian Høgsberg298be2b2010-02-19 12:32:24 -05001982 printf("%d ", v[i]);
Brian Paule01a03d2009-02-06 10:21:36 -07001983 }
1984 }
Brian Paul91f841a2010-05-25 18:39:47 -06001985 else if (basicType == GL_UNSIGNED_INT) {
1986 const GLuint *v = (const GLuint *) values;
1987 for (i = 0; i < count * elems; i++) {
1988 printf("%u ", v[i]);
1989 }
1990 }
Brian Paule01a03d2009-02-06 10:21:36 -07001991 else {
1992 const GLfloat *v = (const GLfloat *) values;
Brian Paul91f841a2010-05-25 18:39:47 -06001993 assert(basicType == GL_FLOAT);
Brian Paule01a03d2009-02-06 10:21:36 -07001994 for (i = 0; i < count * elems; i++) {
Kristian Høgsberg298be2b2010-02-19 12:32:24 -05001995 printf("%g ", v[i]);
Brian Paule01a03d2009-02-06 10:21:36 -07001996 }
1997 }
Kristian Høgsberg298be2b2010-02-19 12:32:24 -05001998 printf("\n");
Brian Paule01a03d2009-02-06 10:21:36 -07001999 }
2000
Brian Paulade50832008-05-14 16:09:46 -06002001 /* A uniform var may be used by both a vertex shader and a fragment
2002 * shader. We may need to update one or both shader's uniform here:
Bruce Merryeeb03fa2007-12-21 14:41:45 +02002003 */
Brian Paulade50832008-05-14 16:09:46 -06002004 if (shProg->VertexProgram) {
Brian Pauleda291e2008-08-06 16:26:47 -06002005 /* convert uniform location to program parameter index */
Brian Paul2d76a0d2008-11-10 12:33:17 -07002006 GLint index = uniform->VertPos;
Brian Pauleda291e2008-08-06 16:26:47 -06002007 if (index >= 0) {
Brian Paulade50832008-05-14 16:09:46 -06002008 set_program_uniform(ctx, &shProg->VertexProgram->Base,
Brian Pauleda291e2008-08-06 16:26:47 -06002009 index, offset, type, count, elems, values);
Bruce Merry2bf2a8c2007-12-21 23:18:40 +02002010 }
Brian5b01c5e2006-12-19 18:02:03 -07002011 }
Brian5cf73262007-01-05 16:02:45 -07002012
Brian Paulade50832008-05-14 16:09:46 -06002013 if (shProg->FragmentProgram) {
Brian Pauleda291e2008-08-06 16:26:47 -06002014 /* convert uniform location to program parameter index */
Brian Paul2d76a0d2008-11-10 12:33:17 -07002015 GLint index = uniform->FragPos;
Brian Pauleda291e2008-08-06 16:26:47 -06002016 if (index >= 0) {
Brian Paulade50832008-05-14 16:09:46 -06002017 set_program_uniform(ctx, &shProg->FragmentProgram->Base,
Brian Pauleda291e2008-08-06 16:26:47 -06002018 index, offset, type, count, elems, values);
Brian Paulade50832008-05-14 16:09:46 -06002019 }
2020 }
Brian Paul949e7382008-11-05 09:17:55 -07002021
Brian Paul2d76a0d2008-11-10 12:33:17 -07002022 uniform->Initialized = GL_TRUE;
Brian Paulade50832008-05-14 16:09:46 -06002023}
2024
2025
Brian Pauleda291e2008-08-06 16:26:47 -06002026/**
2027 * Set a matrix-valued program parameter.
2028 */
Brian Paulade50832008-05-14 16:09:46 -06002029static void
2030set_program_uniform_matrix(GLcontext *ctx, struct gl_program *program,
Brian Pauleda291e2008-08-06 16:26:47 -06002031 GLuint index, GLuint offset,
2032 GLuint count, GLuint rows, GLuint cols,
Brian Paulade50832008-05-14 16:09:46 -06002033 GLboolean transpose, const GLfloat *values)
2034{
Brian Paulffbc66b2008-07-21 13:58:50 -06002035 GLuint mat, row, col;
Nicolai Hähnle9fde81b2009-10-03 16:30:16 +02002036 GLuint src = 0;
2037 const struct gl_program_parameter * param = &program->Parameters->Parameters[index];
Brian Paul20fbb242010-01-27 17:03:04 -07002038 const GLuint slots = (param->Size + 3) / 4;
Brian Paul1a148662010-04-01 22:15:16 -06002039 const GLint typeSize = _mesa_sizeof_glsl_type(param->DataType);
Brian Paulffbc66b2008-07-21 13:58:50 -06002040 GLint nr, nc;
2041
2042 /* check that the number of rows, columns is correct */
Nicolai Hähnle9fde81b2009-10-03 16:30:16 +02002043 get_matrix_dims(param->DataType, &nr, &nc);
Brian Paulffbc66b2008-07-21 13:58:50 -06002044 if (rows != nr || cols != nc) {
2045 _mesa_error(ctx, GL_INVALID_OPERATION,
Brian Pauleda291e2008-08-06 16:26:47 -06002046 "glUniformMatrix(matrix size mismatch)");
2047 return;
2048 }
2049
Brian Paul20fbb242010-01-27 17:03:04 -07002050 if ((GLint) param->Size <= typeSize) {
Nicolai Hähnle9fde81b2009-10-03 16:30:16 +02002051 /* non-array: count must be at most one; count == 0 is handled by the loop below */
2052 if (count > 1) {
2053 _mesa_error(ctx, GL_INVALID_OPERATION,
2054 "glUniformMatrix(uniform is not an array)");
2055 return;
2056 }
Brian Paulffbc66b2008-07-21 13:58:50 -06002057 }
2058
Brian Paulade50832008-05-14 16:09:46 -06002059 /*
2060 * Note: the _columns_ of a matrix are stored in program registers, not
Brian Paulf45ed0e2008-07-18 12:51:39 -06002061 * the rows. So, the loops below look a little funny.
2062 * XXX could optimize this a bit...
Brian Paulade50832008-05-14 16:09:46 -06002063 */
Brian Paulf45ed0e2008-07-18 12:51:39 -06002064
2065 /* loop over matrices */
2066 for (mat = 0; mat < count; mat++) {
2067
2068 /* each matrix: */
Brian Paulade50832008-05-14 16:09:46 -06002069 for (col = 0; col < cols; col++) {
Nicolai Hähnle9fde81b2009-10-03 16:30:16 +02002070 GLfloat *v;
2071 if (offset >= slots) {
2072 /* Ignore writes beyond the end of (the used part of) an array */
2073 return;
2074 }
2075 v = program->Parameters->ParameterValues[index + offset];
Brian Paulade50832008-05-14 16:09:46 -06002076 for (row = 0; row < rows; row++) {
Brian Paulf45ed0e2008-07-18 12:51:39 -06002077 if (transpose) {
2078 v[row] = values[src + row * cols + col];
2079 }
2080 else {
2081 v[row] = values[src + col * rows + row];
2082 }
Brian Paulade50832008-05-14 16:09:46 -06002083 }
Nicolai Hähnle9fde81b2009-10-03 16:30:16 +02002084
2085 offset++;
Brian Paulade50832008-05-14 16:09:46 -06002086 }
Brian Paulf45ed0e2008-07-18 12:51:39 -06002087
2088 src += rows * cols; /* next matrix */
Brian5cf73262007-01-05 16:02:45 -07002089 }
Brian34ae99d2006-12-18 08:28:54 -07002090}
2091
2092
2093/**
Brian5b01c5e2006-12-19 18:02:03 -07002094 * Called by ctx->Driver.UniformMatrix().
Brian Paulf45ed0e2008-07-18 12:51:39 -06002095 * Note: cols=2, rows=4 ==> array[2] of vec4
Brian34ae99d2006-12-18 08:28:54 -07002096 */
Brian Paulfd59f192008-05-18 16:04:55 -06002097static void
Brian5b01c5e2006-12-19 18:02:03 -07002098_mesa_uniform_matrix(GLcontext *ctx, GLint cols, GLint rows,
Brian Paul0115a4f2009-04-14 20:00:28 -06002099 GLint location, GLsizei count,
Brian5b01c5e2006-12-19 18:02:03 -07002100 GLboolean transpose, const GLfloat *values)
Brian34ae99d2006-12-18 08:28:54 -07002101{
Brian3a8e2772006-12-20 17:19:16 -07002102 struct gl_shader_program *shProg = ctx->Shader.CurrentProgram;
Brian Paul2d76a0d2008-11-10 12:33:17 -07002103 struct gl_uniform *uniform;
2104 GLint offset;
Brian Paulade50832008-05-14 16:09:46 -06002105
Brian3a8e2772006-12-20 17:19:16 -07002106 if (!shProg || !shProg->LinkStatus) {
2107 _mesa_error(ctx, GL_INVALID_OPERATION,
2108 "glUniformMatrix(program not linked)");
2109 return;
2110 }
Brian Paulade50832008-05-14 16:09:46 -06002111
Bruce Merry89b80322007-12-21 15:20:17 +02002112 if (location == -1)
2113 return; /* The standard specifies this as a no-op */
Brian Paulade50832008-05-14 16:09:46 -06002114
Brian Paul234f03e2009-02-11 09:05:08 -07002115 if (location < -1) {
2116 _mesa_error(ctx, GL_INVALID_OPERATION, "glUniformMatrix(location)");
2117 return;
2118 }
2119
Brian Pauleda291e2008-08-06 16:26:47 -06002120 split_location_offset(&location, &offset);
2121
Brian Paul016701f2008-07-29 17:43:35 -06002122 if (location < 0 || location >= (GLint) shProg->Uniforms->NumUniforms) {
Brian Paulade50832008-05-14 16:09:46 -06002123 _mesa_error(ctx, GL_INVALID_VALUE, "glUniformMatrix(location)");
Brian3a8e2772006-12-20 17:19:16 -07002124 return;
2125 }
Brian34ae99d2006-12-18 08:28:54 -07002126 if (values == NULL) {
Brian3a8e2772006-12-20 17:19:16 -07002127 _mesa_error(ctx, GL_INVALID_VALUE, "glUniformMatrix");
Brian34ae99d2006-12-18 08:28:54 -07002128 return;
2129 }
2130
Brian Paul027ed1b2009-04-24 09:43:44 -06002131 FLUSH_VERTICES(ctx, _NEW_PROGRAM_CONSTANTS);
Brian34ae99d2006-12-18 08:28:54 -07002132
Brian Paul2d76a0d2008-11-10 12:33:17 -07002133 uniform = &shProg->Uniforms->Uniforms[location];
2134
Brian Paulade50832008-05-14 16:09:46 -06002135 if (shProg->VertexProgram) {
Brian Pauleda291e2008-08-06 16:26:47 -06002136 /* convert uniform location to program parameter index */
Brian Paul2d76a0d2008-11-10 12:33:17 -07002137 GLint index = uniform->VertPos;
Brian Pauleda291e2008-08-06 16:26:47 -06002138 if (index >= 0) {
Brian Paulade50832008-05-14 16:09:46 -06002139 set_program_uniform_matrix(ctx, &shProg->VertexProgram->Base,
Brian Pauleda291e2008-08-06 16:26:47 -06002140 index, offset,
2141 count, rows, cols, transpose, values);
Brian34ae99d2006-12-18 08:28:54 -07002142 }
Brian Paulade50832008-05-14 16:09:46 -06002143 }
2144
2145 if (shProg->FragmentProgram) {
Brian Pauleda291e2008-08-06 16:26:47 -06002146 /* convert uniform location to program parameter index */
Brian Paul2d76a0d2008-11-10 12:33:17 -07002147 GLint index = uniform->FragPos;
Brian Pauleda291e2008-08-06 16:26:47 -06002148 if (index >= 0) {
Brian Paulade50832008-05-14 16:09:46 -06002149 set_program_uniform_matrix(ctx, &shProg->FragmentProgram->Base,
Brian Pauleda291e2008-08-06 16:26:47 -06002150 index, offset,
2151 count, rows, cols, transpose, values);
Brian3a8e2772006-12-20 17:19:16 -07002152 }
Brian34ae99d2006-12-18 08:28:54 -07002153 }
Brian Paul949e7382008-11-05 09:17:55 -07002154
Brian Paul2d76a0d2008-11-10 12:33:17 -07002155 uniform->Initialized = GL_TRUE;
Brian34ae99d2006-12-18 08:28:54 -07002156}
2157
2158
Brian Paulc90fca32009-08-25 17:42:47 -06002159/**
2160 * Validate a program's samplers.
2161 * Specifically, check that there aren't two samplers of different types
2162 * pointing to the same texture unit.
2163 * \return GL_TRUE if valid, GL_FALSE if invalid
2164 */
2165static GLboolean
2166validate_samplers(GLcontext *ctx, const struct gl_program *prog, char *errMsg)
Brian34ae99d2006-12-18 08:28:54 -07002167{
Brian Paulc90fca32009-08-25 17:42:47 -06002168 static const char *targetName[] = {
2169 "TEXTURE_2D_ARRAY",
2170 "TEXTURE_1D_ARRAY",
2171 "TEXTURE_CUBE",
2172 "TEXTURE_3D",
2173 "TEXTURE_RECT",
2174 "TEXTURE_2D",
2175 "TEXTURE_1D",
2176 };
2177 GLint targetUsed[MAX_TEXTURE_IMAGE_UNITS];
2178 GLbitfield samplersUsed = prog->SamplersUsed;
2179 GLuint i;
Brian Paulbc985b52008-07-21 14:16:07 -06002180
Brian Paulc90fca32009-08-25 17:42:47 -06002181 assert(Elements(targetName) == NUM_TEXTURE_TARGETS);
2182
2183 if (samplersUsed == 0x0)
2184 return GL_TRUE;
2185
2186 for (i = 0; i < Elements(targetUsed); i++)
2187 targetUsed[i] = -1;
2188
2189 /* walk over bits which are set in 'samplers' */
2190 while (samplersUsed) {
2191 GLuint unit;
2192 gl_texture_index target;
2193 GLint sampler = _mesa_ffs(samplersUsed) - 1;
2194 assert(sampler >= 0);
2195 assert(sampler < MAX_TEXTURE_IMAGE_UNITS);
2196 unit = prog->SamplerUnits[sampler];
2197 target = prog->SamplerTargets[sampler];
2198 if (targetUsed[unit] != -1 && targetUsed[unit] != target) {
Brian Paul78a0c352010-02-19 12:56:49 -07002199 _mesa_snprintf(errMsg, 100,
Kristian Høgsberg298be2b2010-02-19 12:32:24 -05002200 "Texture unit %d is accessed both as %s and %s",
2201 unit, targetName[targetUsed[unit]], targetName[target]);
Brian Paulc90fca32009-08-25 17:42:47 -06002202 return GL_FALSE;
2203 }
2204 targetUsed[unit] = target;
2205 samplersUsed ^= (1 << sampler);
Brian34ae99d2006-12-18 08:28:54 -07002206 }
2207
Brian Paulc90fca32009-08-25 17:42:47 -06002208 return GL_TRUE;
2209}
2210
2211
2212/**
2213 * Do validation of the given shader program.
2214 * \param errMsg returns error message if validation fails.
2215 * \return GL_TRUE if valid, GL_FALSE if invalid (and set errMsg)
2216 */
2217GLboolean
2218_mesa_validate_shader_program(GLcontext *ctx,
2219 const struct gl_shader_program *shProg,
2220 char *errMsg)
2221{
2222 const struct gl_vertex_program *vp = shProg->VertexProgram;
2223 const struct gl_fragment_program *fp = shProg->FragmentProgram;
2224
Brian Paulbc985b52008-07-21 14:16:07 -06002225 if (!shProg->LinkStatus) {
Brian Paulc90fca32009-08-25 17:42:47 -06002226 return GL_FALSE;
Brian Paulbc985b52008-07-21 14:16:07 -06002227 }
2228
2229 /* From the GL spec, a program is invalid if any of these are true:
2230
Brian5b01c5e2006-12-19 18:02:03 -07002231 any two active samplers in the current program object are of
2232 different types, but refer to the same texture image unit,
2233
2234 any active sampler in the current program object refers to a texture
2235 image unit where fixed-function fragment processing accesses a
2236 texture target that does not match the sampler type, or
2237
2238 the sum of the number of active samplers in the program and the
2239 number of texture image units enabled for fixed-function fragment
2240 processing exceeds the combined limit on the total number of texture
2241 image units allowed.
2242 */
Brian Paulbc985b52008-07-21 14:16:07 -06002243
Brian Paulc90fca32009-08-25 17:42:47 -06002244
2245 /*
2246 * Check: any two active samplers in the current program object are of
2247 * different types, but refer to the same texture image unit,
2248 */
2249 if (vp && !validate_samplers(ctx, &vp->Base, errMsg)) {
2250 return GL_FALSE;
2251 }
2252 if (fp && !validate_samplers(ctx, &fp->Base, errMsg)) {
2253 return GL_FALSE;
2254 }
2255
2256 return GL_TRUE;
2257}
2258
2259
2260/**
2261 * Called via glValidateProgram()
2262 */
2263static void
2264_mesa_validate_program(GLcontext *ctx, GLuint program)
2265{
2266 struct gl_shader_program *shProg;
2267 char errMsg[100];
2268
2269 shProg = _mesa_lookup_shader_program_err(ctx, program, "glValidateProgram");
2270 if (!shProg) {
2271 return;
2272 }
2273
2274 shProg->Validated = _mesa_validate_shader_program(ctx, shProg, errMsg);
2275 if (!shProg->Validated) {
2276 /* update info log */
2277 if (shProg->InfoLog) {
Kristian Høgsberg32f2fd12010-02-19 11:58:49 -05002278 free(shProg->InfoLog);
Brian Paulc90fca32009-08-25 17:42:47 -06002279 }
2280 shProg->InfoLog = _mesa_strdup(errMsg);
2281 }
Brian34ae99d2006-12-18 08:28:54 -07002282}
Brian Paulfd59f192008-05-18 16:04:55 -06002283
2284
2285/**
2286 * Plug in Mesa's GLSL functions into the device driver function table.
2287 */
2288void
2289_mesa_init_glsl_driver_functions(struct dd_function_table *driver)
2290{
2291 driver->AttachShader = _mesa_attach_shader;
2292 driver->BindAttribLocation = _mesa_bind_attrib_location;
2293 driver->CompileShader = _mesa_compile_shader;
2294 driver->CreateProgram = _mesa_create_program;
2295 driver->CreateShader = _mesa_create_shader;
2296 driver->DeleteProgram2 = _mesa_delete_program2;
2297 driver->DeleteShader = _mesa_delete_shader;
2298 driver->DetachShader = _mesa_detach_shader;
2299 driver->GetActiveAttrib = _mesa_get_active_attrib;
2300 driver->GetActiveUniform = _mesa_get_active_uniform;
2301 driver->GetAttachedShaders = _mesa_get_attached_shaders;
2302 driver->GetAttribLocation = _mesa_get_attrib_location;
2303 driver->GetHandle = _mesa_get_handle;
2304 driver->GetProgramiv = _mesa_get_programiv;
2305 driver->GetProgramInfoLog = _mesa_get_program_info_log;
2306 driver->GetShaderiv = _mesa_get_shaderiv;
2307 driver->GetShaderInfoLog = _mesa_get_shader_info_log;
2308 driver->GetShaderSource = _mesa_get_shader_source;
2309 driver->GetUniformfv = _mesa_get_uniformfv;
Brian Paul2be54a82008-07-08 16:17:04 -06002310 driver->GetUniformiv = _mesa_get_uniformiv;
Brian Paulfd59f192008-05-18 16:04:55 -06002311 driver->GetUniformLocation = _mesa_get_uniform_location;
2312 driver->IsProgram = _mesa_is_program;
2313 driver->IsShader = _mesa_is_shader;
2314 driver->LinkProgram = _mesa_link_program;
2315 driver->ShaderSource = _mesa_shader_source;
2316 driver->Uniform = _mesa_uniform;
2317 driver->UniformMatrix = _mesa_uniform_matrix;
2318 driver->UseProgram = _mesa_use_program;
2319 driver->ValidateProgram = _mesa_validate_program;
2320}