blob: 290717ff55748d074b9404786edcacb52ba872dd [file] [log] [blame]
Brian34ae99d2006-12-18 08:28:54 -07001/*
2 * Mesa 3-D graphics library
Brian Paul27341a92008-09-16 16:28:36 -06003 * Version: 7.2
Brian34ae99d2006-12-18 08:28:54 -07004 *
Brian Paul8c51e002008-08-11 15:09:47 -06005 * Copyright (C) 2004-2008 Brian Paul All Rights Reserved.
Brian34ae99d2006-12-18 08:28:54 -07006 *
7 * Permission is hereby granted, free of charge, to any person obtaining a
8 * copy of this software and associated documentation files (the "Software"),
9 * to deal in the Software without restriction, including without limitation
10 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11 * and/or sell copies of the Software, and to permit persons to whom the
12 * Software is furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included
15 * in all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
21 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 */
24
25/**
26 * \file shader_api.c
Brian5b01c5e2006-12-19 18:02:03 -070027 * Implementation of GLSL-related API functions
Brian34ae99d2006-12-18 08:28:54 -070028 * \author Brian Paul
29 */
30
31/**
32 * XXX things to do:
33 * 1. Check that the right error code is generated for all _mesa_error() calls.
Brian5b01c5e2006-12-19 18:02:03 -070034 * 2. Insert FLUSH_VERTICES calls in various places
Brian34ae99d2006-12-18 08:28:54 -070035 */
36
37
Brian Paulbbd28712008-09-18 12:26:54 -060038#include "main/glheader.h"
39#include "main/context.h"
40#include "main/hash.h"
41#include "main/macros.h"
42#include "shader/program.h"
43#include "shader/prog_parameter.h"
44#include "shader/prog_print.h"
45#include "shader/prog_statevars.h"
46#include "shader/prog_uniform.h"
Brianc223c6b2007-07-04 13:15:20 -060047#include "shader/shader_api.h"
48#include "shader/slang/slang_compile.h"
49#include "shader/slang/slang_link.h"
Ian Romanick905d8e02008-09-29 12:27:00 -070050#include "glapi/dispatch.h"
Brian34ae99d2006-12-18 08:28:54 -070051
52
Brian Paulbda6ad22008-08-06 12:45:14 -060053#ifndef GL_PROGRAM_BINARY_LENGTH_OES
54#define GL_PROGRAM_BINARY_LENGTH_OES 0x8741
55#endif
56
57
Brianf2923612006-12-20 09:56:44 -070058/**
59 * Allocate a new gl_shader_program object, initialize it.
60 */
Brian Paulfd59f192008-05-18 16:04:55 -060061static struct gl_shader_program *
Brianf2923612006-12-20 09:56:44 -070062_mesa_new_shader_program(GLcontext *ctx, GLuint name)
63{
64 struct gl_shader_program *shProg;
65 shProg = CALLOC_STRUCT(gl_shader_program);
66 if (shProg) {
Brianf3e8c322007-04-18 14:53:23 -060067 shProg->Type = GL_SHADER_PROGRAM_MESA;
Brianf2923612006-12-20 09:56:44 -070068 shProg->Name = name;
69 shProg->RefCount = 1;
Brian3209c3e2007-01-09 17:49:24 -070070 shProg->Attributes = _mesa_new_parameter_list();
Brianf2923612006-12-20 09:56:44 -070071 }
72 return shProg;
73}
74
75
Brianb9fbedd2007-03-26 09:23:44 -060076/**
Brian3c008a02007-04-12 15:22:32 -060077 * Clear (free) the shader program state that gets produced by linking.
Brianb9fbedd2007-03-26 09:23:44 -060078 */
Brianf2923612006-12-20 09:56:44 -070079void
Brian3c008a02007-04-12 15:22:32 -060080_mesa_clear_shader_program_data(GLcontext *ctx,
81 struct gl_shader_program *shProg)
Brianf2923612006-12-20 09:56:44 -070082{
Brian Paul8bdf5b62008-05-16 09:56:59 -060083 _mesa_reference_vertprog(ctx, &shProg->VertexProgram, NULL);
84 _mesa_reference_fragprog(ctx, &shProg->FragmentProgram, NULL);
Brianf2923612006-12-20 09:56:44 -070085
Brianf2923612006-12-20 09:56:44 -070086 if (shProg->Uniforms) {
Brian Paulade50832008-05-14 16:09:46 -060087 _mesa_free_uniform_list(shProg->Uniforms);
Brianf2923612006-12-20 09:56:44 -070088 shProg->Uniforms = NULL;
89 }
90
91 if (shProg->Varying) {
92 _mesa_free_parameter_list(shProg->Varying);
93 shProg->Varying = NULL;
94 }
95}
96
97
Brianb9fbedd2007-03-26 09:23:44 -060098/**
Brian3c008a02007-04-12 15:22:32 -060099 * Free all the data that hangs off a shader program object, but not the
100 * object itself.
101 */
102void
103_mesa_free_shader_program_data(GLcontext *ctx,
104 struct gl_shader_program *shProg)
105{
106 GLuint i;
107
Brianf3e8c322007-04-18 14:53:23 -0600108 assert(shProg->Type == GL_SHADER_PROGRAM_MESA);
Brian3c008a02007-04-12 15:22:32 -0600109
110 _mesa_clear_shader_program_data(ctx, shProg);
111
Brian4b7c6fc2007-04-19 15:23:34 -0600112 if (shProg->Attributes) {
113 _mesa_free_parameter_list(shProg->Attributes);
114 shProg->Attributes = NULL;
115 }
116
Brian3c008a02007-04-12 15:22:32 -0600117 /* detach shaders */
118 for (i = 0; i < shProg->NumShaders; i++) {
119 _mesa_reference_shader(ctx, &shProg->Shaders[i], NULL);
120 }
Xiang, Haihao63d8a842008-03-31 17:02:47 +0800121 shProg->NumShaders = 0;
122
Brian3c008a02007-04-12 15:22:32 -0600123 if (shProg->Shaders) {
124 _mesa_free(shProg->Shaders);
125 shProg->Shaders = NULL;
126 }
Alan Hourihaneeec20c32008-04-22 20:29:42 +0100127
128 if (shProg->InfoLog) {
129 _mesa_free(shProg->InfoLog);
130 shProg->InfoLog = NULL;
131 }
Brian3c008a02007-04-12 15:22:32 -0600132}
133
134
135/**
Brianb9fbedd2007-03-26 09:23:44 -0600136 * Free/delete a shader program object.
137 */
Brianf2923612006-12-20 09:56:44 -0700138void
139_mesa_free_shader_program(GLcontext *ctx, struct gl_shader_program *shProg)
140{
141 _mesa_free_shader_program_data(ctx, shProg);
Alan Hourihaneeec20c32008-04-22 20:29:42 +0100142
Brianf2923612006-12-20 09:56:44 -0700143 _mesa_free(shProg);
144}
145
146
147/**
Brian3c008a02007-04-12 15:22:32 -0600148 * Set ptr to point to shProg.
149 * If ptr is pointing to another object, decrement its refcount (and delete
150 * if refcount hits zero).
151 * Then set ptr to point to shProg, incrementing its refcount.
152 */
153/* XXX this could be static */
154void
155_mesa_reference_shader_program(GLcontext *ctx,
156 struct gl_shader_program **ptr,
157 struct gl_shader_program *shProg)
158{
159 assert(ptr);
160 if (*ptr == shProg) {
161 /* no-op */
162 return;
163 }
164 if (*ptr) {
165 /* Unreference the old shader program */
166 GLboolean deleteFlag = GL_FALSE;
167 struct gl_shader_program *old = *ptr;
168
169 ASSERT(old->RefCount > 0);
170 old->RefCount--;
Brian Paul8bdf5b62008-05-16 09:56:59 -0600171#if 0
172 printf("ShaderProgram %p ID=%u RefCount-- to %d\n",
173 (void *) old, old->Name, old->RefCount);
174#endif
Brian3c008a02007-04-12 15:22:32 -0600175 deleteFlag = (old->RefCount == 0);
176
177 if (deleteFlag) {
Xiang, Haihaoaef47c42008-03-31 16:27:47 +0800178 _mesa_HashRemove(ctx->Shared->ShaderObjects, old->Name);
Brian3c008a02007-04-12 15:22:32 -0600179 _mesa_free_shader_program(ctx, old);
180 }
181
182 *ptr = NULL;
183 }
184 assert(!*ptr);
185
186 if (shProg) {
187 shProg->RefCount++;
Brian Paul8bdf5b62008-05-16 09:56:59 -0600188#if 0
189 printf("ShaderProgram %p ID=%u RefCount++ to %d\n",
190 (void *) shProg, shProg->Name, shProg->RefCount);
191#endif
Brian3c008a02007-04-12 15:22:32 -0600192 *ptr = shProg;
193 }
194}
195
196
197/**
Brianf2923612006-12-20 09:56:44 -0700198 * Lookup a GLSL program object.
199 */
200struct gl_shader_program *
201_mesa_lookup_shader_program(GLcontext *ctx, GLuint name)
202{
203 struct gl_shader_program *shProg;
204 if (name) {
205 shProg = (struct gl_shader_program *)
Xiang, Haihaoaef47c42008-03-31 16:27:47 +0800206 _mesa_HashLookup(ctx->Shared->ShaderObjects, name);
Brianf2923612006-12-20 09:56:44 -0700207 /* Note that both gl_shader and gl_shader_program objects are kept
208 * in the same hash table. Check the object's type to be sure it's
209 * what we're expecting.
210 */
Brianf3e8c322007-04-18 14:53:23 -0600211 if (shProg && shProg->Type != GL_SHADER_PROGRAM_MESA) {
Brianf2923612006-12-20 09:56:44 -0700212 return NULL;
213 }
214 return shProg;
215 }
216 return NULL;
217}
218
219
220/**
Brian Paul530df582008-07-03 16:21:11 -0600221 * As above, but record an error if program is not found.
222 */
223static struct gl_shader_program *
224_mesa_lookup_shader_program_err(GLcontext *ctx, GLuint name,
225 const char *caller)
226{
227 if (!name) {
228 _mesa_error(ctx, GL_INVALID_VALUE, caller);
229 return NULL;
230 }
231 else {
232 struct gl_shader_program *shProg = (struct gl_shader_program *)
233 _mesa_HashLookup(ctx->Shared->ShaderObjects, name);
234 if (!shProg) {
235 _mesa_error(ctx, GL_INVALID_VALUE, caller);
236 return NULL;
237 }
238 if (shProg->Type != GL_SHADER_PROGRAM_MESA) {
239 _mesa_error(ctx, GL_INVALID_OPERATION, caller);
240 return NULL;
241 }
242 return shProg;
243 }
244}
245
246
247
248
249/**
Brianf2923612006-12-20 09:56:44 -0700250 * Allocate a new gl_shader object, initialize it.
251 */
252struct gl_shader *
253_mesa_new_shader(GLcontext *ctx, GLuint name, GLenum type)
254{
255 struct gl_shader *shader;
256 assert(type == GL_FRAGMENT_SHADER || type == GL_VERTEX_SHADER);
257 shader = CALLOC_STRUCT(gl_shader);
258 if (shader) {
259 shader->Type = type;
260 shader->Name = name;
261 shader->RefCount = 1;
262 }
263 return shader;
264}
265
266
267void
268_mesa_free_shader(GLcontext *ctx, struct gl_shader *sh)
269{
Brianf2923612006-12-20 09:56:44 -0700270 if (sh->Source)
271 _mesa_free((void *) sh->Source);
272 if (sh->InfoLog)
273 _mesa_free(sh->InfoLog);
Brian Paul3d500f02008-07-24 14:56:54 -0600274 _mesa_reference_program(ctx, &sh->Program, NULL);
Brianf2923612006-12-20 09:56:44 -0700275 _mesa_free(sh);
276}
277
278
279/**
Brian3c008a02007-04-12 15:22:32 -0600280 * Set ptr to point to sh.
281 * If ptr is pointing to another shader, decrement its refcount (and delete
282 * if refcount hits zero).
283 * Then set ptr to point to sh, incrementing its refcount.
284 */
285/* XXX this could be static */
286void
287_mesa_reference_shader(GLcontext *ctx, struct gl_shader **ptr,
288 struct gl_shader *sh)
289{
290 assert(ptr);
291 if (*ptr == sh) {
292 /* no-op */
293 return;
294 }
295 if (*ptr) {
296 /* Unreference the old shader */
297 GLboolean deleteFlag = GL_FALSE;
298 struct gl_shader *old = *ptr;
299
300 ASSERT(old->RefCount > 0);
301 old->RefCount--;
Brian99193e42007-04-12 15:45:02 -0600302 /*printf("SHADER DECR %p (%d) to %d\n",
303 (void*) old, old->Name, old->RefCount);*/
Brian3c008a02007-04-12 15:22:32 -0600304 deleteFlag = (old->RefCount == 0);
305
306 if (deleteFlag) {
307 _mesa_HashRemove(ctx->Shared->ShaderObjects, old->Name);
308 _mesa_free_shader(ctx, old);
309 }
310
311 *ptr = NULL;
312 }
313 assert(!*ptr);
314
315 if (sh) {
316 /* reference new */
317 sh->RefCount++;
Brian99193e42007-04-12 15:45:02 -0600318 /*printf("SHADER INCR %p (%d) to %d\n",
319 (void*) sh, sh->Name, sh->RefCount);*/
Brian3c008a02007-04-12 15:22:32 -0600320 *ptr = sh;
321 }
322}
323
324
325/**
Brianf2923612006-12-20 09:56:44 -0700326 * Lookup a GLSL shader object.
327 */
328struct gl_shader *
329_mesa_lookup_shader(GLcontext *ctx, GLuint name)
330{
331 if (name) {
332 struct gl_shader *sh = (struct gl_shader *)
333 _mesa_HashLookup(ctx->Shared->ShaderObjects, name);
334 /* Note that both gl_shader and gl_shader_program objects are kept
335 * in the same hash table. Check the object's type to be sure it's
336 * what we're expecting.
337 */
Brianf3e8c322007-04-18 14:53:23 -0600338 if (sh && sh->Type == GL_SHADER_PROGRAM_MESA) {
Brianf2923612006-12-20 09:56:44 -0700339 return NULL;
340 }
341 return sh;
342 }
343 return NULL;
344}
345
346
Brianfa4d0362007-02-26 18:33:50 -0700347/**
Brian Paul530df582008-07-03 16:21:11 -0600348 * As above, but record an error if shader is not found.
349 */
350static struct gl_shader *
351_mesa_lookup_shader_err(GLcontext *ctx, GLuint name, const char *caller)
352{
353 if (!name) {
354 _mesa_error(ctx, GL_INVALID_VALUE, caller);
355 return NULL;
356 }
357 else {
358 struct gl_shader *sh = (struct gl_shader *)
359 _mesa_HashLookup(ctx->Shared->ShaderObjects, name);
360 if (!sh) {
361 _mesa_error(ctx, GL_INVALID_VALUE, caller);
362 return NULL;
363 }
364 if (sh->Type == GL_SHADER_PROGRAM_MESA) {
365 _mesa_error(ctx, GL_INVALID_OPERATION, caller);
366 return NULL;
367 }
368 return sh;
369 }
370}
371
372
Brian Paule01a03d2009-02-06 10:21:36 -0700373/**
374 * Return mask of GLSL_x flags by examining the MESA_GLSL env var.
375 */
376static GLbitfield
377get_shader_flags(void)
378{
379 GLbitfield flags = 0x0;
380 const char *env = _mesa_getenv("MESA_GLSL");
381
382 if (env) {
383 if (_mesa_strstr(env, "dump"))
384 flags |= GLSL_DUMP;
385 if (_mesa_strstr(env, "log"))
386 flags |= GLSL_LOG;
387 if (_mesa_strstr(env, "nopt"))
388 flags |= GLSL_NO_OPT;
389 else if (_mesa_strstr(env, "opt"))
390 flags |= GLSL_OPT;
391 if (_mesa_strstr(env, "uniform"))
392 flags |= GLSL_UNIFORMS;
393 }
394
395 return flags;
396}
397
Brian Paul530df582008-07-03 16:21:11 -0600398
399/**
Brianfa4d0362007-02-26 18:33:50 -0700400 * Initialize context's shader state.
401 */
Brianf2923612006-12-20 09:56:44 -0700402void
403_mesa_init_shader_state(GLcontext * ctx)
404{
Brianfa4d0362007-02-26 18:33:50 -0700405 /* Device drivers may override these to control what kind of instructions
406 * are generated by the GLSL compiler.
407 */
408 ctx->Shader.EmitHighLevelInstructions = GL_TRUE;
michal4a470f62007-08-07 15:34:11 +0100409 ctx->Shader.EmitCondCodes = GL_FALSE;/*GL_TRUE;*/ /* XXX probably want GL_FALSE... */
Brianfa4d0362007-02-26 18:33:50 -0700410 ctx->Shader.EmitComments = GL_FALSE;
Brian Paule01a03d2009-02-06 10:21:36 -0700411 ctx->Shader.Flags = get_shader_flags();
Brianf2923612006-12-20 09:56:44 -0700412}
413
414
Brian5b01c5e2006-12-19 18:02:03 -0700415/**
Brian935f93f2007-03-24 16:20:02 -0600416 * Free the per-context shader-related state.
417 */
418void
419_mesa_free_shader_state(GLcontext *ctx)
420{
Brian3c008a02007-04-12 15:22:32 -0600421 _mesa_reference_shader_program(ctx, &ctx->Shader.CurrentProgram, NULL);
Brian935f93f2007-03-24 16:20:02 -0600422}
423
424
425/**
Brian5b01c5e2006-12-19 18:02:03 -0700426 * Copy string from <src> to <dst>, up to maxLength characters, returning
427 * length of <dst> in <length>.
428 * \param src the strings source
429 * \param maxLength max chars to copy
430 * \param length returns number of chars copied
431 * \param dst the string destination
432 */
433static void
434copy_string(GLchar *dst, GLsizei maxLength, GLsizei *length, const GLchar *src)
435{
436 GLsizei len;
437 for (len = 0; len < maxLength - 1 && src && src[len]; len++)
438 dst[len] = src[len];
439 if (maxLength > 0)
440 dst[len] = 0;
441 if (length)
442 *length = len;
443}
444
445
Brian Paul7acb7c12008-07-03 13:49:48 -0600446static GLboolean
447_mesa_is_program(GLcontext *ctx, GLuint name)
448{
449 struct gl_shader_program *shProg = _mesa_lookup_shader_program(ctx, name);
450 return shProg ? GL_TRUE : GL_FALSE;
451}
452
453
454static GLboolean
455_mesa_is_shader(GLcontext *ctx, GLuint name)
456{
457 struct gl_shader *shader = _mesa_lookup_shader(ctx, name);
458 return shader ? GL_TRUE : GL_FALSE;
459}
460
461
Brian5b01c5e2006-12-19 18:02:03 -0700462/**
463 * Called via ctx->Driver.AttachShader()
464 */
Brian Paulfd59f192008-05-18 16:04:55 -0600465static void
Brian5b01c5e2006-12-19 18:02:03 -0700466_mesa_attach_shader(GLcontext *ctx, GLuint program, GLuint shader)
467{
Brian Paul530df582008-07-03 16:21:11 -0600468 struct gl_shader_program *shProg;
469 struct gl_shader *sh;
470 GLuint i, n;
Brian5b01c5e2006-12-19 18:02:03 -0700471
Brian Paul530df582008-07-03 16:21:11 -0600472 shProg = _mesa_lookup_shader_program_err(ctx, program, "glAttachShader");
473 if (!shProg)
Brian5b01c5e2006-12-19 18:02:03 -0700474 return;
Brian5b01c5e2006-12-19 18:02:03 -0700475
Brian Paul530df582008-07-03 16:21:11 -0600476 sh = _mesa_lookup_shader_err(ctx, shader, "glAttachShader");
Brian Paul7acb7c12008-07-03 13:49:48 -0600477 if (!sh) {
Brian Paul7acb7c12008-07-03 13:49:48 -0600478 return;
479 }
480
Brian237b9852007-08-07 21:48:31 +0100481 n = shProg->NumShaders;
Brian5b01c5e2006-12-19 18:02:03 -0700482 for (i = 0; i < n; i++) {
Brian65a18442006-12-19 18:46:56 -0700483 if (shProg->Shaders[i] == sh) {
Ian Romanickd806d452008-09-29 12:18:06 -0700484 /* The shader is already attched to this program. The
485 * GL_ARB_shader_objects spec says:
486 *
487 * "The error INVALID_OPERATION is generated by AttachObjectARB
488 * if <obj> is already attached to <containerObj>."
489 */
490 _mesa_error(ctx, GL_INVALID_OPERATION, "glAttachShader");
Brian5b01c5e2006-12-19 18:02:03 -0700491 return;
Brian34ae99d2006-12-18 08:28:54 -0700492 }
493 }
Brian5b01c5e2006-12-19 18:02:03 -0700494
495 /* grow list */
Brian65a18442006-12-19 18:46:56 -0700496 shProg->Shaders = (struct gl_shader **)
497 _mesa_realloc(shProg->Shaders,
498 n * sizeof(struct gl_shader *),
499 (n + 1) * sizeof(struct gl_shader *));
500 if (!shProg->Shaders) {
Brian5b01c5e2006-12-19 18:02:03 -0700501 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glAttachShader");
502 return;
503 }
504
505 /* append */
Brian3c008a02007-04-12 15:22:32 -0600506 shProg->Shaders[n] = NULL; /* since realloc() didn't zero the new space */
507 _mesa_reference_shader(ctx, &shProg->Shaders[n], sh);
Brian65a18442006-12-19 18:46:56 -0700508 shProg->NumShaders++;
Brian5b01c5e2006-12-19 18:02:03 -0700509}
510
511
Brian Paulfd59f192008-05-18 16:04:55 -0600512static GLint
Brian Paul896c0cc2008-05-16 15:47:55 -0600513_mesa_get_attrib_location(GLcontext *ctx, GLuint program,
514 const GLchar *name)
515{
516 struct gl_shader_program *shProg
Brian Paul530df582008-07-03 16:21:11 -0600517 = _mesa_lookup_shader_program_err(ctx, program, "glGetAttribLocation");
Brian Paul896c0cc2008-05-16 15:47:55 -0600518
519 if (!shProg) {
Brian Paul896c0cc2008-05-16 15:47:55 -0600520 return -1;
521 }
522
523 if (!shProg->LinkStatus) {
524 _mesa_error(ctx, GL_INVALID_OPERATION,
525 "glGetAttribLocation(program not linked)");
526 return -1;
527 }
528
529 if (!name)
530 return -1;
531
Brian Paul27341a92008-09-16 16:28:36 -0600532 if (shProg->VertexProgram) {
533 const struct gl_program_parameter_list *attribs =
534 shProg->VertexProgram->Base.Attributes;
535 if (attribs) {
536 GLint i = _mesa_lookup_parameter_index(attribs, -1, name);
537 if (i >= 0) {
538 return attribs->Parameters[i].StateIndexes[0];
539 }
Brian Paul896c0cc2008-05-16 15:47:55 -0600540 }
541 }
542 return -1;
543}
544
545
Brian Paulfd59f192008-05-18 16:04:55 -0600546static void
Brian5b01c5e2006-12-19 18:02:03 -0700547_mesa_bind_attrib_location(GLcontext *ctx, GLuint program, GLuint index,
548 const GLchar *name)
549{
Brian Paul530df582008-07-03 16:21:11 -0600550 struct gl_shader_program *shProg;
Brianb7978af2007-01-09 19:17:17 -0700551 const GLint size = -1; /* unknown size */
Brian Paul6bc87492008-07-25 08:34:54 -0600552 GLint i, oldIndex;
Brian Paul6f1abb92008-07-29 17:27:22 -0600553 GLenum datatype = GL_FLOAT_VEC4;
Brian5b01c5e2006-12-19 18:02:03 -0700554
Brian Paul530df582008-07-03 16:21:11 -0600555 shProg = _mesa_lookup_shader_program_err(ctx, program,
556 "glBindAttribLocation");
Brian65a18442006-12-19 18:46:56 -0700557 if (!shProg) {
Brian5b01c5e2006-12-19 18:02:03 -0700558 return;
559 }
560
Brian9e4bae92006-12-20 09:27:42 -0700561 if (!name)
562 return;
563
564 if (strncmp(name, "gl_", 3) == 0) {
565 _mesa_error(ctx, GL_INVALID_OPERATION,
566 "glBindAttribLocation(illegal name)");
567 return;
568 }
569
Brian Paul7acb7c12008-07-03 13:49:48 -0600570 if (index >= ctx->Const.VertexProgram.MaxAttribs) {
571 _mesa_error(ctx, GL_INVALID_VALUE, "glBindAttribLocation(index)");
572 return;
573 }
574
Brian Paul6bc87492008-07-25 08:34:54 -0600575 if (shProg->LinkStatus) {
576 /* get current index/location for the attribute */
577 oldIndex = _mesa_get_attrib_location(ctx, program, name);
578 }
579 else {
580 oldIndex = -1;
581 }
582
Brian3209c3e2007-01-09 17:49:24 -0700583 /* this will replace the current value if it's already in the list */
Brian Paulffbc66b2008-07-21 13:58:50 -0600584 i = _mesa_add_attribute(shProg->Attributes, name, size, datatype, index);
Brian3209c3e2007-01-09 17:49:24 -0700585 if (i < 0) {
586 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBindAttribLocation");
Brian Paul6f1abb92008-07-29 17:27:22 -0600587 return;
Brian3209c3e2007-01-09 17:49:24 -0700588 }
589
Brian Paul27341a92008-09-16 16:28:36 -0600590 /*
591 * Note that this attribute binding won't go into effect until
592 * glLinkProgram is called again.
593 */
Brian34ae99d2006-12-18 08:28:54 -0700594}
595
596
Brian Paulfd59f192008-05-18 16:04:55 -0600597static GLuint
Brian5b01c5e2006-12-19 18:02:03 -0700598_mesa_create_shader(GLcontext *ctx, GLenum type)
599{
Brian65a18442006-12-19 18:46:56 -0700600 struct gl_shader *sh;
Brian5b01c5e2006-12-19 18:02:03 -0700601 GLuint name;
602
603 name = _mesa_HashFindFreeKeyBlock(ctx->Shared->ShaderObjects, 1);
604
605 switch (type) {
Brian65a18442006-12-19 18:46:56 -0700606 case GL_FRAGMENT_SHADER:
607 case GL_VERTEX_SHADER:
608 sh = _mesa_new_shader(ctx, name, type);
Brian5b01c5e2006-12-19 18:02:03 -0700609 break;
610 default:
611 _mesa_error(ctx, GL_INVALID_ENUM, "CreateShader(type)");
612 return 0;
613 }
614
Brian65a18442006-12-19 18:46:56 -0700615 _mesa_HashInsert(ctx->Shared->ShaderObjects, name, sh);
Brian5b01c5e2006-12-19 18:02:03 -0700616
617 return name;
618}
619
620
Brian Paulfd59f192008-05-18 16:04:55 -0600621static GLuint
Brian5b01c5e2006-12-19 18:02:03 -0700622_mesa_create_program(GLcontext *ctx)
623{
624 GLuint name;
Brian65a18442006-12-19 18:46:56 -0700625 struct gl_shader_program *shProg;
Brian5b01c5e2006-12-19 18:02:03 -0700626
Xiang, Haihaoaef47c42008-03-31 16:27:47 +0800627 name = _mesa_HashFindFreeKeyBlock(ctx->Shared->ShaderObjects, 1);
Brian65a18442006-12-19 18:46:56 -0700628 shProg = _mesa_new_shader_program(ctx, name);
Brian5b01c5e2006-12-19 18:02:03 -0700629
Xiang, Haihaoaef47c42008-03-31 16:27:47 +0800630 _mesa_HashInsert(ctx->Shared->ShaderObjects, name, shProg);
Brian5b01c5e2006-12-19 18:02:03 -0700631
Brian3c008a02007-04-12 15:22:32 -0600632 assert(shProg->RefCount == 1);
633
Brian5b01c5e2006-12-19 18:02:03 -0700634 return name;
635}
636
637
Brian3c008a02007-04-12 15:22:32 -0600638/**
639 * Named w/ "2" to indicate OpenGL 2.x vs GL_ARB_fragment_programs's
640 * DeleteProgramARB.
641 */
Brian Paulfd59f192008-05-18 16:04:55 -0600642static void
Brian5b01c5e2006-12-19 18:02:03 -0700643_mesa_delete_program2(GLcontext *ctx, GLuint name)
644{
Brian3c008a02007-04-12 15:22:32 -0600645 /*
646 * NOTE: deleting shaders/programs works a bit differently than
647 * texture objects (and buffer objects, etc). Shader/program
648 * handles/IDs exist in the hash table until the object is really
649 * deleted (refcount==0). With texture objects, the handle/ID is
650 * removed from the hash table in glDeleteTextures() while the tex
651 * object itself might linger until its refcount goes to zero.
652 */
Brian65a18442006-12-19 18:46:56 -0700653 struct gl_shader_program *shProg;
Brian5b01c5e2006-12-19 18:02:03 -0700654
Brian Paul530df582008-07-03 16:21:11 -0600655 shProg = _mesa_lookup_shader_program_err(ctx, name, "glDeleteProgram");
656 if (!shProg)
Brian5b01c5e2006-12-19 18:02:03 -0700657 return;
Brian5b01c5e2006-12-19 18:02:03 -0700658
Brian9e4bae92006-12-20 09:27:42 -0700659 shProg->DeletePending = GL_TRUE;
660
Brian3c008a02007-04-12 15:22:32 -0600661 /* effectively, decr shProg's refcount */
662 _mesa_reference_shader_program(ctx, &shProg, NULL);
Brian5b01c5e2006-12-19 18:02:03 -0700663}
664
665
Brian Paulfd59f192008-05-18 16:04:55 -0600666static void
Brian5b01c5e2006-12-19 18:02:03 -0700667_mesa_delete_shader(GLcontext *ctx, GLuint shader)
668{
Brian Paul530df582008-07-03 16:21:11 -0600669 struct gl_shader *sh;
670
671 sh = _mesa_lookup_shader_err(ctx, shader, "glDeleteShader");
672 if (!sh)
Brian9e4bae92006-12-20 09:27:42 -0700673 return;
Brian5b01c5e2006-12-19 18:02:03 -0700674
Brian9e4bae92006-12-20 09:27:42 -0700675 sh->DeletePending = GL_TRUE;
Brian3c008a02007-04-12 15:22:32 -0600676
677 /* effectively, decr sh's refcount */
678 _mesa_reference_shader(ctx, &sh, NULL);
Brian5b01c5e2006-12-19 18:02:03 -0700679}
680
681
Brian Paulfd59f192008-05-18 16:04:55 -0600682static void
Brian5b01c5e2006-12-19 18:02:03 -0700683_mesa_detach_shader(GLcontext *ctx, GLuint program, GLuint shader)
684{
Brian Paul530df582008-07-03 16:21:11 -0600685 struct gl_shader_program *shProg;
Brian237b9852007-08-07 21:48:31 +0100686 GLuint n;
Brian5b01c5e2006-12-19 18:02:03 -0700687 GLuint i, j;
688
Brian Paul530df582008-07-03 16:21:11 -0600689 shProg = _mesa_lookup_shader_program_err(ctx, program, "glDetachShader");
690 if (!shProg)
Brian5b01c5e2006-12-19 18:02:03 -0700691 return;
Brian5b01c5e2006-12-19 18:02:03 -0700692
Brian237b9852007-08-07 21:48:31 +0100693 n = shProg->NumShaders;
694
Brian5b01c5e2006-12-19 18:02:03 -0700695 for (i = 0; i < n; i++) {
Brian65a18442006-12-19 18:46:56 -0700696 if (shProg->Shaders[i]->Name == shader) {
Brian5b01c5e2006-12-19 18:02:03 -0700697 /* found it */
Brian3c008a02007-04-12 15:22:32 -0600698 struct gl_shader **newList;
Brian9e4bae92006-12-20 09:27:42 -0700699
Brian Paul530df582008-07-03 16:21:11 -0600700 /* release */
Brian3c008a02007-04-12 15:22:32 -0600701 _mesa_reference_shader(ctx, &shProg->Shaders[i], NULL);
Brian9e4bae92006-12-20 09:27:42 -0700702
Brian5b01c5e2006-12-19 18:02:03 -0700703 /* alloc new, smaller array */
Brian65a18442006-12-19 18:46:56 -0700704 newList = (struct gl_shader **)
705 _mesa_malloc((n - 1) * sizeof(struct gl_shader *));
Brian5b01c5e2006-12-19 18:02:03 -0700706 if (!newList) {
707 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glDetachShader");
708 return;
709 }
710 for (j = 0; j < i; j++) {
Brian65a18442006-12-19 18:46:56 -0700711 newList[j] = shProg->Shaders[j];
Brian5b01c5e2006-12-19 18:02:03 -0700712 }
713 while (++i < n)
Brian65a18442006-12-19 18:46:56 -0700714 newList[j++] = shProg->Shaders[i];
715 _mesa_free(shProg->Shaders);
Brian5b01c5e2006-12-19 18:02:03 -0700716
Brian65a18442006-12-19 18:46:56 -0700717 shProg->Shaders = newList;
Brianbac15c82007-04-18 14:55:18 -0600718 shProg->NumShaders = n - 1;
Brianaaa57412007-04-18 15:22:43 -0600719
720#ifdef DEBUG
721 /* sanity check */
722 {
723 for (j = 0; j < shProg->NumShaders; j++) {
724 assert(shProg->Shaders[j]->Type == GL_VERTEX_SHADER ||
725 shProg->Shaders[j]->Type == GL_FRAGMENT_SHADER);
726 assert(shProg->Shaders[j]->RefCount > 0);
727 }
728 }
729#endif
730
Brian5b01c5e2006-12-19 18:02:03 -0700731 return;
732 }
733 }
734
735 /* not found */
Brian Paul530df582008-07-03 16:21:11 -0600736 {
737 GLenum err;
738 if (_mesa_is_shader(ctx, shader))
739 err = GL_INVALID_OPERATION;
740 else if (_mesa_is_program(ctx, shader))
741 err = GL_INVALID_OPERATION;
742 else
743 err = GL_INVALID_VALUE;
744 _mesa_error(ctx, err, "glDetachProgram(shader)");
745 return;
746 }
Brian5b01c5e2006-12-19 18:02:03 -0700747}
748
749
Brian Paulffbc66b2008-07-21 13:58:50 -0600750static GLint
751sizeof_glsl_type(GLenum type)
752{
753 switch (type) {
754 case GL_FLOAT:
755 case GL_INT:
756 case GL_BOOL:
Brian Paul8c51e002008-08-11 15:09:47 -0600757 case GL_SAMPLER_1D:
758 case GL_SAMPLER_2D:
759 case GL_SAMPLER_3D:
760 case GL_SAMPLER_CUBE:
761 case GL_SAMPLER_1D_SHADOW:
762 case GL_SAMPLER_2D_SHADOW:
763 case GL_SAMPLER_2D_RECT_ARB:
764 case GL_SAMPLER_2D_RECT_SHADOW_ARB:
765 case GL_SAMPLER_1D_ARRAY_SHADOW_EXT:
766 case GL_SAMPLER_2D_ARRAY_SHADOW_EXT:
767 case GL_SAMPLER_CUBE_SHADOW_EXT:
Brian Paulffbc66b2008-07-21 13:58:50 -0600768 return 1;
769 case GL_FLOAT_VEC2:
770 case GL_INT_VEC2:
771 case GL_BOOL_VEC2:
772 return 2;
773 case GL_FLOAT_VEC3:
774 case GL_INT_VEC3:
775 case GL_BOOL_VEC3:
776 return 3;
777 case GL_FLOAT_VEC4:
778 case GL_INT_VEC4:
779 case GL_BOOL_VEC4:
780 return 4;
781 case GL_FLOAT_MAT2:
782 case GL_FLOAT_MAT2x3:
783 case GL_FLOAT_MAT2x4:
784 return 8; /* two float[4] vectors */
785 case GL_FLOAT_MAT3:
786 case GL_FLOAT_MAT3x2:
787 case GL_FLOAT_MAT3x4:
788 return 12; /* three float[4] vectors */
789 case GL_FLOAT_MAT4:
790 case GL_FLOAT_MAT4x2:
791 case GL_FLOAT_MAT4x3:
792 return 16; /* four float[4] vectors */
793 default:
794 _mesa_problem(NULL, "Invalid type in sizeof_glsl_type()");
795 return 1;
796 }
797}
798
799
Brian Pauleda291e2008-08-06 16:26:47 -0600800static GLboolean
801is_boolean_type(GLenum type)
802{
803 switch (type) {
804 case GL_BOOL:
805 case GL_BOOL_VEC2:
806 case GL_BOOL_VEC3:
807 case GL_BOOL_VEC4:
808 return GL_TRUE;
809 default:
810 return GL_FALSE;
811 }
812}
813
814
815static GLboolean
816is_integer_type(GLenum type)
817{
818 switch (type) {
819 case GL_INT:
820 case GL_INT_VEC2:
821 case GL_INT_VEC3:
822 case GL_INT_VEC4:
823 return GL_TRUE;
824 default:
825 return GL_FALSE;
826 }
827}
828
829
Brian Paulfd59f192008-05-18 16:04:55 -0600830static void
Brian5b01c5e2006-12-19 18:02:03 -0700831_mesa_get_active_attrib(GLcontext *ctx, GLuint program, GLuint index,
832 GLsizei maxLength, GLsizei *length, GLint *size,
833 GLenum *type, GLchar *nameOut)
834{
Brian Paul27341a92008-09-16 16:28:36 -0600835 const struct gl_program_parameter_list *attribs = NULL;
Brian Paul530df582008-07-03 16:21:11 -0600836 struct gl_shader_program *shProg;
Brian5b01c5e2006-12-19 18:02:03 -0700837
Brian Paul530df582008-07-03 16:21:11 -0600838 shProg = _mesa_lookup_shader_program_err(ctx, program, "glGetActiveAttrib");
839 if (!shProg)
Brian5b01c5e2006-12-19 18:02:03 -0700840 return;
Brian5b01c5e2006-12-19 18:02:03 -0700841
Brian Paul27341a92008-09-16 16:28:36 -0600842 if (shProg->VertexProgram)
843 attribs = shProg->VertexProgram->Base.Attributes;
844
845 if (!attribs || index >= attribs->NumParameters) {
Brianaaa57412007-04-18 15:22:43 -0600846 _mesa_error(ctx, GL_INVALID_VALUE, "glGetActiveAttrib(index)");
Brian5b01c5e2006-12-19 18:02:03 -0700847 return;
848 }
849
Brian Paul27341a92008-09-16 16:28:36 -0600850 copy_string(nameOut, maxLength, length, attribs->Parameters[index].Name);
851
Brian5b01c5e2006-12-19 18:02:03 -0700852 if (size)
Brian Paul27341a92008-09-16 16:28:36 -0600853 *size = attribs->Parameters[index].Size
854 / sizeof_glsl_type(attribs->Parameters[index].DataType);
855
Brian Paulade50832008-05-14 16:09:46 -0600856 if (type)
Brian Paul27341a92008-09-16 16:28:36 -0600857 *type = attribs->Parameters[index].DataType;
Brian5b01c5e2006-12-19 18:02:03 -0700858}
859
860
Brian Pauleda291e2008-08-06 16:26:47 -0600861static struct gl_program_parameter *
862get_uniform_parameter(const struct gl_shader_program *shProg, GLuint index)
863{
864 const struct gl_program *prog;
865 GLint progPos;
866
867 progPos = shProg->Uniforms->Uniforms[index].VertPos;
868 if (progPos >= 0) {
869 prog = &shProg->VertexProgram->Base;
870 }
871 else {
872 progPos = shProg->Uniforms->Uniforms[index].FragPos;
873 if (progPos >= 0) {
874 prog = &shProg->FragmentProgram->Base;
875 }
876 }
877
878 if (!prog || progPos < 0)
879 return NULL; /* should never happen */
880
881 return &prog->Parameters->Parameters[progPos];
882}
883
884
Brian5b01c5e2006-12-19 18:02:03 -0700885/**
886 * Called via ctx->Driver.GetActiveUniform().
887 */
Brian Paulfd59f192008-05-18 16:04:55 -0600888static void
Brian5b01c5e2006-12-19 18:02:03 -0700889_mesa_get_active_uniform(GLcontext *ctx, GLuint program, GLuint index,
890 GLsizei maxLength, GLsizei *length, GLint *size,
891 GLenum *type, GLchar *nameOut)
892{
Brian Paul530df582008-07-03 16:21:11 -0600893 const struct gl_shader_program *shProg;
Brian Paulade50832008-05-14 16:09:46 -0600894 const struct gl_program *prog;
Brian Paul369d1852009-02-11 08:16:14 -0700895 const struct gl_program_parameter *param;
Brian Paulade50832008-05-14 16:09:46 -0600896 GLint progPos;
Brian5b01c5e2006-12-19 18:02:03 -0700897
Brian Paul530df582008-07-03 16:21:11 -0600898 shProg = _mesa_lookup_shader_program_err(ctx, program, "glGetActiveUniform");
899 if (!shProg)
Brian5b01c5e2006-12-19 18:02:03 -0700900 return;
Brian5b01c5e2006-12-19 18:02:03 -0700901
Brian Paulade50832008-05-14 16:09:46 -0600902 if (!shProg->Uniforms || index >= shProg->Uniforms->NumUniforms) {
Brian5b01c5e2006-12-19 18:02:03 -0700903 _mesa_error(ctx, GL_INVALID_VALUE, "glGetActiveUniform(index)");
904 return;
905 }
906
Brian Paulade50832008-05-14 16:09:46 -0600907 progPos = shProg->Uniforms->Uniforms[index].VertPos;
908 if (progPos >= 0) {
909 prog = &shProg->VertexProgram->Base;
910 }
911 else {
912 progPos = shProg->Uniforms->Uniforms[index].FragPos;
913 if (progPos >= 0) {
914 prog = &shProg->FragmentProgram->Base;
Brian274ac7a2007-04-18 16:05:53 -0600915 }
916 }
917
Brian Paulade50832008-05-14 16:09:46 -0600918 if (!prog || progPos < 0)
919 return; /* should never happen */
920
Brian Paul369d1852009-02-11 08:16:14 -0700921 ASSERT(progPos < prog->Parameters->NumParameters);
922 param = &prog->Parameters->Parameters[progPos];
923
924 if (nameOut) {
925 copy_string(nameOut, maxLength, length, param->Name);
926 }
927
928 if (size) {
929 GLint typeSize = sizeof_glsl_type(param->DataType);
930 if (param->Size > typeSize) {
931 /* This is an array.
932 * Array elements are placed on vector[4] boundaries so they're
933 * a multiple of four floats. We round typeSize up to next multiple
934 * of four to get the right size below.
935 */
936 typeSize = (typeSize + 3) & ~3;
937 }
938 /* Note that the returned size is in units of the <type>, not bytes */
939 *size = param->Size / typeSize;
940 }
941
942 if (type) {
943 *type = param->DataType;
944 }
Brian5b01c5e2006-12-19 18:02:03 -0700945}
946
947
948/**
949 * Called via ctx->Driver.GetAttachedShaders().
950 */
Brian Paulfd59f192008-05-18 16:04:55 -0600951static void
Brian5b01c5e2006-12-19 18:02:03 -0700952_mesa_get_attached_shaders(GLcontext *ctx, GLuint program, GLsizei maxCount,
953 GLsizei *count, GLuint *obj)
954{
Brian Paul530df582008-07-03 16:21:11 -0600955 struct gl_shader_program *shProg =
956 _mesa_lookup_shader_program_err(ctx, program, "glGetAttachedShaders");
Brian65a18442006-12-19 18:46:56 -0700957 if (shProg) {
Brian Paul530df582008-07-03 16:21:11 -0600958 GLuint i;
959 for (i = 0; i < (GLuint) maxCount && i < shProg->NumShaders; i++) {
Brian65a18442006-12-19 18:46:56 -0700960 obj[i] = shProg->Shaders[i]->Name;
Brian5b01c5e2006-12-19 18:02:03 -0700961 }
962 if (count)
963 *count = i;
964 }
Brian5b01c5e2006-12-19 18:02:03 -0700965}
966
967
Brian Paulfd59f192008-05-18 16:04:55 -0600968static GLuint
Brian5b01c5e2006-12-19 18:02:03 -0700969_mesa_get_handle(GLcontext *ctx, GLenum pname)
Brian34ae99d2006-12-18 08:28:54 -0700970{
Ian Romanick905d8e02008-09-29 12:27:00 -0700971 GLint handle = 0;
972
973 if (pname == GL_PROGRAM_OBJECT_ARB) {
974 CALL_GetIntegerv(ctx->Exec, (GL_CURRENT_PROGRAM, &handle));
975 } else {
Brian34ae99d2006-12-18 08:28:54 -0700976 _mesa_error(ctx, GL_INVALID_ENUM, "glGetHandleARB");
977 }
Ian Romanick905d8e02008-09-29 12:27:00 -0700978
979 return handle;
Brian34ae99d2006-12-18 08:28:54 -0700980}
981
982
Brian Paulfd59f192008-05-18 16:04:55 -0600983static void
Brian5b01c5e2006-12-19 18:02:03 -0700984_mesa_get_programiv(GLcontext *ctx, GLuint program,
985 GLenum pname, GLint *params)
Brian34ae99d2006-12-18 08:28:54 -0700986{
Brian Paul27341a92008-09-16 16:28:36 -0600987 const struct gl_program_parameter_list *attribs;
Brian65a18442006-12-19 18:46:56 -0700988 struct gl_shader_program *shProg
989 = _mesa_lookup_shader_program(ctx, program);
Brian34ae99d2006-12-18 08:28:54 -0700990
Brian65a18442006-12-19 18:46:56 -0700991 if (!shProg) {
Brian5b01c5e2006-12-19 18:02:03 -0700992 _mesa_error(ctx, GL_INVALID_VALUE, "glGetProgramiv(program)");
Brian34ae99d2006-12-18 08:28:54 -0700993 return;
994 }
995
Brian Paul27341a92008-09-16 16:28:36 -0600996 if (shProg->VertexProgram)
997 attribs = shProg->VertexProgram->Base.Attributes;
998 else
999 attribs = NULL;
1000
Brian5b01c5e2006-12-19 18:02:03 -07001001 switch (pname) {
1002 case GL_DELETE_STATUS:
Brian65a18442006-12-19 18:46:56 -07001003 *params = shProg->DeletePending;
Brian5b01c5e2006-12-19 18:02:03 -07001004 break;
1005 case GL_LINK_STATUS:
Brian65a18442006-12-19 18:46:56 -07001006 *params = shProg->LinkStatus;
Brian34ae99d2006-12-18 08:28:54 -07001007 break;
Brian5b01c5e2006-12-19 18:02:03 -07001008 case GL_VALIDATE_STATUS:
Brian65a18442006-12-19 18:46:56 -07001009 *params = shProg->Validated;
Brian5b01c5e2006-12-19 18:02:03 -07001010 break;
1011 case GL_INFO_LOG_LENGTH:
Jan Dvorak5a0f02a2007-07-13 16:36:00 -06001012 *params = shProg->InfoLog ? strlen(shProg->InfoLog) + 1 : 0;
Brian5b01c5e2006-12-19 18:02:03 -07001013 break;
1014 case GL_ATTACHED_SHADERS:
Brian65a18442006-12-19 18:46:56 -07001015 *params = shProg->NumShaders;
Brian5b01c5e2006-12-19 18:02:03 -07001016 break;
1017 case GL_ACTIVE_ATTRIBUTES:
Brian Paul27341a92008-09-16 16:28:36 -06001018 *params = attribs ? attribs->NumParameters : 0;
Brian5b01c5e2006-12-19 18:02:03 -07001019 break;
1020 case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH:
Brian Paul27341a92008-09-16 16:28:36 -06001021 *params = _mesa_longest_parameter_name(attribs, PROGRAM_INPUT) + 1;
Brian5b01c5e2006-12-19 18:02:03 -07001022 break;
1023 case GL_ACTIVE_UNIFORMS:
Brian Paulade50832008-05-14 16:09:46 -06001024 *params = shProg->Uniforms ? shProg->Uniforms->NumUniforms : 0;
Brian5b01c5e2006-12-19 18:02:03 -07001025 break;
1026 case GL_ACTIVE_UNIFORM_MAX_LENGTH:
Brian Paulade50832008-05-14 16:09:46 -06001027 *params = _mesa_longest_uniform_name(shProg->Uniforms);
Brian274ac7a2007-04-18 16:05:53 -06001028 if (*params > 0)
1029 (*params)++; /* add one for terminating zero */
Brian34ae99d2006-12-18 08:28:54 -07001030 break;
Brian Paulbda6ad22008-08-06 12:45:14 -06001031 case GL_PROGRAM_BINARY_LENGTH_OES:
1032 *params = 0;
1033 break;
Brian34ae99d2006-12-18 08:28:54 -07001034 default:
Brian5b01c5e2006-12-19 18:02:03 -07001035 _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramiv(pname)");
1036 return;
Brian34ae99d2006-12-18 08:28:54 -07001037 }
Brian5b01c5e2006-12-19 18:02:03 -07001038}
Brian34ae99d2006-12-18 08:28:54 -07001039
Brian34ae99d2006-12-18 08:28:54 -07001040
Brian Paulfd59f192008-05-18 16:04:55 -06001041static void
Brian5b01c5e2006-12-19 18:02:03 -07001042_mesa_get_shaderiv(GLcontext *ctx, GLuint name, GLenum pname, GLint *params)
1043{
Brian Paul530df582008-07-03 16:21:11 -06001044 struct gl_shader *shader = _mesa_lookup_shader_err(ctx, name, "glGetShaderiv");
Brian5b01c5e2006-12-19 18:02:03 -07001045
1046 if (!shader) {
Brian5b01c5e2006-12-19 18:02:03 -07001047 return;
1048 }
Brian65a18442006-12-19 18:46:56 -07001049
Brian5b01c5e2006-12-19 18:02:03 -07001050 switch (pname) {
1051 case GL_SHADER_TYPE:
1052 *params = shader->Type;
1053 break;
1054 case GL_DELETE_STATUS:
1055 *params = shader->DeletePending;
1056 break;
1057 case GL_COMPILE_STATUS:
1058 *params = shader->CompileStatus;
1059 break;
1060 case GL_INFO_LOG_LENGTH:
Jan Dvorak5a0f02a2007-07-13 16:36:00 -06001061 *params = shader->InfoLog ? strlen(shader->InfoLog) + 1 : 0;
Brian5b01c5e2006-12-19 18:02:03 -07001062 break;
1063 case GL_SHADER_SOURCE_LENGTH:
Jan Dvorak5a0f02a2007-07-13 16:36:00 -06001064 *params = shader->Source ? strlen((char *) shader->Source) + 1 : 0;
Brian5b01c5e2006-12-19 18:02:03 -07001065 break;
1066 default:
1067 _mesa_error(ctx, GL_INVALID_ENUM, "glGetShaderiv(pname)");
1068 return;
1069 }
1070}
1071
1072
Brian Paulfd59f192008-05-18 16:04:55 -06001073static void
Brian5b01c5e2006-12-19 18:02:03 -07001074_mesa_get_program_info_log(GLcontext *ctx, GLuint program, GLsizei bufSize,
1075 GLsizei *length, GLchar *infoLog)
1076{
Brian65a18442006-12-19 18:46:56 -07001077 struct gl_shader_program *shProg
1078 = _mesa_lookup_shader_program(ctx, program);
1079 if (!shProg) {
Brian5b01c5e2006-12-19 18:02:03 -07001080 _mesa_error(ctx, GL_INVALID_VALUE, "glGetProgramInfoLog(program)");
1081 return;
1082 }
Brian65a18442006-12-19 18:46:56 -07001083 copy_string(infoLog, bufSize, length, shProg->InfoLog);
Brian5b01c5e2006-12-19 18:02:03 -07001084}
1085
1086
Brian Paulfd59f192008-05-18 16:04:55 -06001087static void
Brian5b01c5e2006-12-19 18:02:03 -07001088_mesa_get_shader_info_log(GLcontext *ctx, GLuint shader, GLsizei bufSize,
1089 GLsizei *length, GLchar *infoLog)
1090{
Brian65a18442006-12-19 18:46:56 -07001091 struct gl_shader *sh = _mesa_lookup_shader(ctx, shader);
1092 if (!sh) {
Brian5b01c5e2006-12-19 18:02:03 -07001093 _mesa_error(ctx, GL_INVALID_VALUE, "glGetShaderInfoLog(shader)");
1094 return;
1095 }
Brian65a18442006-12-19 18:46:56 -07001096 copy_string(infoLog, bufSize, length, sh->InfoLog);
Brian5b01c5e2006-12-19 18:02:03 -07001097}
1098
1099
1100/**
1101 * Called via ctx->Driver.GetShaderSource().
1102 */
Brian Paulfd59f192008-05-18 16:04:55 -06001103static void
Brian5b01c5e2006-12-19 18:02:03 -07001104_mesa_get_shader_source(GLcontext *ctx, GLuint shader, GLsizei maxLength,
1105 GLsizei *length, GLchar *sourceOut)
1106{
Brian Paul530df582008-07-03 16:21:11 -06001107 struct gl_shader *sh;
1108 sh = _mesa_lookup_shader_err(ctx, shader, "glGetShaderSource");
Brian65a18442006-12-19 18:46:56 -07001109 if (!sh) {
Brian5b01c5e2006-12-19 18:02:03 -07001110 return;
1111 }
Brian65a18442006-12-19 18:46:56 -07001112 copy_string(sourceOut, maxLength, length, sh->Source);
Brian5b01c5e2006-12-19 18:02:03 -07001113}
1114
1115
Brian Paul5b982362008-08-06 13:07:09 -06001116static void
1117get_matrix_dims(GLenum type, GLint *rows, GLint *cols)
1118{
1119 switch (type) {
1120 case GL_FLOAT_MAT2:
1121 *rows = *cols = 2;
1122 break;
1123 case GL_FLOAT_MAT2x3:
1124 *rows = 3;
1125 *cols = 2;
1126 break;
1127 case GL_FLOAT_MAT2x4:
1128 *rows = 4;
1129 *cols = 2;
1130 break;
1131 case GL_FLOAT_MAT3:
1132 *rows = 3;
1133 *cols = 3;
1134 break;
1135 case GL_FLOAT_MAT3x2:
1136 *rows = 2;
1137 *cols = 3;
1138 break;
1139 case GL_FLOAT_MAT3x4:
1140 *rows = 4;
1141 *cols = 3;
1142 break;
1143 case GL_FLOAT_MAT4:
1144 *rows = 4;
1145 *cols = 4;
1146 break;
1147 case GL_FLOAT_MAT4x2:
1148 *rows = 2;
1149 *cols = 4;
1150 break;
1151 case GL_FLOAT_MAT4x3:
1152 *rows = 3;
1153 *cols = 4;
1154 break;
1155 default:
1156 *rows = *cols = 0;
1157 }
1158}
1159
1160
1161/**
1162 * Determine the number of rows and columns occupied by a uniform
Brian Paulea9568d2008-09-16 08:55:54 -06001163 * according to its datatype. For non-matrix types (such as GL_FLOAT_VEC4),
1164 * the number of rows = 1 and cols = number of elements in the vector.
Brian Paul5b982362008-08-06 13:07:09 -06001165 */
1166static void
1167get_uniform_rows_cols(const struct gl_program_parameter *p,
1168 GLint *rows, GLint *cols)
1169{
1170 get_matrix_dims(p->DataType, rows, cols);
1171 if (*rows == 0 && *cols == 0) {
1172 /* not a matrix type, probably a float or vector */
Brian Paulea9568d2008-09-16 08:55:54 -06001173 if (p->Size <= 4) {
1174 *rows = 1;
1175 *cols = p->Size;
1176 }
1177 else {
1178 *rows = p->Size / 4 + 1;
1179 if (p->Size % 4 == 0)
1180 *cols = 4;
1181 else
1182 *cols = p->Size % 4;
1183 }
Brian Paul5b982362008-08-06 13:07:09 -06001184 }
1185}
1186
1187
Brian5b01c5e2006-12-19 18:02:03 -07001188/**
Brian Paul4ef7a932009-02-11 09:03:16 -07001189 * Helper for get_uniform[fi]v() functions.
1190 * Given a shader program name and uniform location, return a pointer
1191 * to the shader program and return the program parameter position.
Brian5b01c5e2006-12-19 18:02:03 -07001192 */
Brian Paul4ef7a932009-02-11 09:03:16 -07001193static void
1194lookup_uniform_parameter(GLcontext *ctx, GLuint program, GLint location,
1195 struct gl_program **progOut, GLint *paramPosOut)
Brian5b01c5e2006-12-19 18:02:03 -07001196{
Brian65a18442006-12-19 18:46:56 -07001197 struct gl_shader_program *shProg
Brian Paulbda6ad22008-08-06 12:45:14 -06001198 = _mesa_lookup_shader_program_err(ctx, program, "glGetUniform[if]v");
Brian Paul4ef7a932009-02-11 09:03:16 -07001199 struct gl_program *prog = NULL;
1200 GLint progPos = -1;
Brian Paulade50832008-05-14 16:09:46 -06001201
Brian Paul4ef7a932009-02-11 09:03:16 -07001202 /* if shProg is NULL, we'll have already recorded an error */
1203
1204 if (shProg) {
1205 if (!shProg->Uniforms ||
1206 location < 0 ||
1207 location >= (GLint) shProg->Uniforms->NumUniforms) {
1208 _mesa_error(ctx, GL_INVALID_OPERATION, "glGetUniformfv(location)");
1209 }
1210 else {
1211 /* OK, find the gl_program and program parameter location */
Brian Paulade50832008-05-14 16:09:46 -06001212 progPos = shProg->Uniforms->Uniforms[location].VertPos;
1213 if (progPos >= 0) {
1214 prog = &shProg->VertexProgram->Base;
Brian5b01c5e2006-12-19 18:02:03 -07001215 }
Brian Paulade50832008-05-14 16:09:46 -06001216 else {
1217 progPos = shProg->Uniforms->Uniforms[location].FragPos;
1218 if (progPos >= 0) {
1219 prog = &shProg->FragmentProgram->Base;
Bruce Merryeeb03fa2007-12-21 14:41:45 +02001220 }
Brian Paulade50832008-05-14 16:09:46 -06001221 }
Brian5b01c5e2006-12-19 18:02:03 -07001222 }
1223 }
Brian Paul4ef7a932009-02-11 09:03:16 -07001224
1225 *progOut = prog;
1226 *paramPosOut = progPos;
Brian Paul2be54a82008-07-08 16:17:04 -06001227}
1228
1229
1230/**
1231 * Called via ctx->Driver.GetUniformfv().
1232 */
1233static void
1234_mesa_get_uniformfv(GLcontext *ctx, GLuint program, GLint location,
1235 GLfloat *params)
1236{
Brian Paul4ef7a932009-02-11 09:03:16 -07001237 struct gl_program *prog;
1238 GLint paramPos;
1239
1240 lookup_uniform_parameter(ctx, program, location, &prog, &paramPos);
1241
1242 if (prog) {
1243 const struct gl_program_parameter *p =
1244 &prog->Parameters->Parameters[paramPos];
1245 GLint rows, cols, i, j, k;
1246
1247 get_uniform_rows_cols(p, &rows, &cols);
1248
1249 k = 0;
1250 for (i = 0; i < rows; i++) {
1251 for (j = 0; j < cols; j++ ) {
1252 params[k++] = prog->Parameters->ParameterValues[paramPos+i][j];
1253 }
1254 }
1255 }
Brian Paul2be54a82008-07-08 16:17:04 -06001256}
1257
1258
1259/**
1260 * Called via ctx->Driver.GetUniformiv().
Brian Paul4ef7a932009-02-11 09:03:16 -07001261 * \sa _mesa_get_uniformfv, only difference is a cast.
Brian Paul2be54a82008-07-08 16:17:04 -06001262 */
1263static void
1264_mesa_get_uniformiv(GLcontext *ctx, GLuint program, GLint location,
1265 GLint *params)
1266{
Brian Paul4ef7a932009-02-11 09:03:16 -07001267 struct gl_program *prog;
1268 GLint paramPos;
1269
1270 lookup_uniform_parameter(ctx, program, location, &prog, &paramPos);
1271
1272 if (prog) {
1273 const struct gl_program_parameter *p =
1274 &prog->Parameters->Parameters[paramPos];
1275 GLint rows, cols, i, j, k;
1276
1277 get_uniform_rows_cols(p, &rows, &cols);
1278
1279 k = 0;
1280 for (i = 0; i < rows; i++) {
1281 for (j = 0; j < cols; j++ ) {
1282 params[k++] = (GLint) prog->Parameters->ParameterValues[paramPos+i][j];
1283 }
1284 }
Brian Paul2be54a82008-07-08 16:17:04 -06001285 }
Brian5b01c5e2006-12-19 18:02:03 -07001286}
1287
1288
1289/**
Brian Pauleda291e2008-08-06 16:26:47 -06001290 * The value returned by GetUniformLocation actually encodes two things:
1291 * 1. the index into the prog->Uniforms[] array for the uniform
1292 * 2. an offset in the prog->ParameterValues[] array for specifying array
1293 * elements or structure fields.
1294 * This function merges those two values.
1295 */
1296static void
1297merge_location_offset(GLint *location, GLint offset)
1298{
1299 *location = *location | (offset << 16);
1300}
1301
1302
1303/**
1304 * Seperate the uniform location and parameter offset. See above.
1305 */
1306static void
1307split_location_offset(GLint *location, GLint *offset)
1308{
1309 *offset = (*location >> 16);
1310 *location = *location & 0xffff;
1311}
1312
1313
1314/**
Brian5b01c5e2006-12-19 18:02:03 -07001315 * Called via ctx->Driver.GetUniformLocation().
Brian Pauleda291e2008-08-06 16:26:47 -06001316 *
1317 * The return value will encode two values, the uniform location and an
1318 * offset (used for arrays, structs).
Brian5b01c5e2006-12-19 18:02:03 -07001319 */
Brian Paulfd59f192008-05-18 16:04:55 -06001320static GLint
Brian5b01c5e2006-12-19 18:02:03 -07001321_mesa_get_uniform_location(GLcontext *ctx, GLuint program, const GLchar *name)
1322{
Brian Pauleda291e2008-08-06 16:26:47 -06001323 GLint offset = 0, location = -1;
1324
Brian Paul530df582008-07-03 16:21:11 -06001325 struct gl_shader_program *shProg =
1326 _mesa_lookup_shader_program_err(ctx, program, "glGetUniformLocation");
1327
Brian Paulade50832008-05-14 16:09:46 -06001328 if (!shProg)
1329 return -1;
Brian5b01c5e2006-12-19 18:02:03 -07001330
Brian Paule06565b2008-07-04 09:58:55 -06001331 if (shProg->LinkStatus == GL_FALSE) {
1332 _mesa_error(ctx, GL_INVALID_OPERATION, "glGetUniformfv(program)");
1333 return -1;
1334 }
1335
Brian Paul530df582008-07-03 16:21:11 -06001336 /* XXX we should return -1 if the uniform was declared, but not
1337 * actually used.
1338 */
1339
Brian Pauleda291e2008-08-06 16:26:47 -06001340 /* XXX we need to be able to parse uniform names for structs and arrays
1341 * such as:
1342 * mymatrix[1]
1343 * mystruct.field1
1344 */
1345
1346 {
1347 /* handle 1-dimension arrays here... */
1348 char *c = strchr(name, '[');
1349 if (c) {
1350 /* truncate name at [ */
1351 const GLint len = c - name;
1352 GLchar *newName = _mesa_malloc(len + 1);
1353 if (!newName)
1354 return -1; /* out of mem */
1355 _mesa_memcpy(newName, name, len);
1356 newName[len] = 0;
1357
1358 location = _mesa_lookup_uniform(shProg->Uniforms, newName);
1359 if (location >= 0) {
1360 const GLint element = _mesa_atoi(c + 1);
1361 if (element > 0) {
1362 /* get type of the uniform array element */
1363 struct gl_program_parameter *p;
1364 p = get_uniform_parameter(shProg, location);
1365 if (p) {
1366 GLint rows, cols;
1367 get_matrix_dims(p->DataType, &rows, &cols);
1368 if (rows < 1)
1369 rows = 1;
1370 offset = element * rows;
1371 }
1372 }
1373 }
1374
1375 _mesa_free(newName);
1376 }
1377 }
1378
1379 if (location < 0) {
1380 location = _mesa_lookup_uniform(shProg->Uniforms, name);
1381 }
1382
1383 if (location >= 0) {
1384 merge_location_offset(&location, offset);
1385 }
1386
1387 return location;
Brian5b01c5e2006-12-19 18:02:03 -07001388}
1389
1390
Brian34ae99d2006-12-18 08:28:54 -07001391
Brian5b01c5e2006-12-19 18:02:03 -07001392/**
1393 * Called via ctx->Driver.ShaderSource()
1394 */
Brian Paulfd59f192008-05-18 16:04:55 -06001395static void
Brian5b01c5e2006-12-19 18:02:03 -07001396_mesa_shader_source(GLcontext *ctx, GLuint shader, const GLchar *source)
Brian34ae99d2006-12-18 08:28:54 -07001397{
Brian Paul530df582008-07-03 16:21:11 -06001398 struct gl_shader *sh;
1399
1400 sh = _mesa_lookup_shader_err(ctx, shader, "glShaderSource");
1401 if (!sh)
Brian34ae99d2006-12-18 08:28:54 -07001402 return;
Brian34ae99d2006-12-18 08:28:54 -07001403
Brian34ae99d2006-12-18 08:28:54 -07001404 /* free old shader source string and install new one */
Brian65a18442006-12-19 18:46:56 -07001405 if (sh->Source) {
1406 _mesa_free((void *) sh->Source);
Brian34ae99d2006-12-18 08:28:54 -07001407 }
Brian65a18442006-12-19 18:46:56 -07001408 sh->Source = source;
Brian9e4bae92006-12-20 09:27:42 -07001409 sh->CompileStatus = GL_FALSE;
Brian34ae99d2006-12-18 08:28:54 -07001410}
1411
1412
Brian5b01c5e2006-12-19 18:02:03 -07001413/**
1414 * Called via ctx->Driver.CompileShader()
1415 */
Brian Paulfd59f192008-05-18 16:04:55 -06001416static void
Brian5b01c5e2006-12-19 18:02:03 -07001417_mesa_compile_shader(GLcontext *ctx, GLuint shaderObj)
Brian34ae99d2006-12-18 08:28:54 -07001418{
Brian Paul530df582008-07-03 16:21:11 -06001419 struct gl_shader *sh;
Brian34ae99d2006-12-18 08:28:54 -07001420
Brian Paul530df582008-07-03 16:21:11 -06001421 sh = _mesa_lookup_shader_err(ctx, shaderObj, "glCompileShader");
1422 if (!sh)
Brian34ae99d2006-12-18 08:28:54 -07001423 return;
Brian34ae99d2006-12-18 08:28:54 -07001424
Brian Paulcb136e02009-01-22 10:34:15 -07001425 /* this call will set the sh->CompileStatus field to indicate if
1426 * compilation was successful.
1427 */
1428 (void) _slang_compile(ctx, sh);
Brian34ae99d2006-12-18 08:28:54 -07001429}
1430
1431
Brian5b01c5e2006-12-19 18:02:03 -07001432/**
1433 * Called via ctx->Driver.LinkProgram()
1434 */
Brian Paulfd59f192008-05-18 16:04:55 -06001435static void
Brian5b01c5e2006-12-19 18:02:03 -07001436_mesa_link_program(GLcontext *ctx, GLuint program)
Brian34ae99d2006-12-18 08:28:54 -07001437{
Brian65a18442006-12-19 18:46:56 -07001438 struct gl_shader_program *shProg;
Brian34ae99d2006-12-18 08:28:54 -07001439
Brian Paul530df582008-07-03 16:21:11 -06001440 shProg = _mesa_lookup_shader_program_err(ctx, program, "glLinkProgram");
1441 if (!shProg)
Brian34ae99d2006-12-18 08:28:54 -07001442 return;
Brian34ae99d2006-12-18 08:28:54 -07001443
Briandf43fb62008-05-06 23:08:51 -06001444 FLUSH_VERTICES(ctx, _NEW_PROGRAM);
1445
Brianc1771912007-02-16 09:56:19 -07001446 _slang_link(ctx, program, shProg);
Brian34ae99d2006-12-18 08:28:54 -07001447}
1448
1449
1450/**
Brian5b01c5e2006-12-19 18:02:03 -07001451 * Called via ctx->Driver.UseProgram()
Brian34ae99d2006-12-18 08:28:54 -07001452 */
Brian5b01c5e2006-12-19 18:02:03 -07001453void
1454_mesa_use_program(GLcontext *ctx, GLuint program)
Brian34ae99d2006-12-18 08:28:54 -07001455{
Brian3c008a02007-04-12 15:22:32 -06001456 struct gl_shader_program *shProg;
1457
Brian00d63aa2007-02-03 11:35:02 -07001458 if (ctx->Shader.CurrentProgram &&
1459 ctx->Shader.CurrentProgram->Name == program) {
1460 /* no-op */
1461 return;
1462 }
1463
1464 FLUSH_VERTICES(ctx, _NEW_PROGRAM);
1465
Brian5b01c5e2006-12-19 18:02:03 -07001466 if (program) {
Brian Paul530df582008-07-03 16:21:11 -06001467 shProg = _mesa_lookup_shader_program_err(ctx, program, "glUseProgram");
Brian65a18442006-12-19 18:46:56 -07001468 if (!shProg) {
Brian Paul530df582008-07-03 16:21:11 -06001469 return;
1470 }
1471 if (!shProg->LinkStatus) {
1472 _mesa_error(ctx, GL_INVALID_OPERATION, "glUseProgram");
Brian5b01c5e2006-12-19 18:02:03 -07001473 return;
1474 }
Brian5b01c5e2006-12-19 18:02:03 -07001475 }
1476 else {
Brian3c008a02007-04-12 15:22:32 -06001477 shProg = NULL;
1478 }
1479
1480 _mesa_reference_shader_program(ctx, &ctx->Shader.CurrentProgram, shProg);
Brian5b01c5e2006-12-19 18:02:03 -07001481}
Brian34ae99d2006-12-18 08:28:54 -07001482
Brian5b01c5e2006-12-19 18:02:03 -07001483
Brian Paulade50832008-05-14 16:09:46 -06001484
1485/**
Brian Paul517401a2008-11-06 15:04:11 -07001486 * Update the vertex/fragment program's TexturesUsed array.
1487 *
1488 * This needs to be called after glUniform(set sampler var) is called.
1489 * A call to glUniform(samplerVar, value) causes a sampler to point to a
1490 * particular texture unit. We know the sampler's texture target
1491 * (1D/2D/3D/etc) from compile time but the sampler's texture unit is
1492 * set by glUniform() calls.
1493 *
1494 * So, scan the program->SamplerUnits[] and program->SamplerTargets[]
1495 * information to update the prog->TexturesUsed[] values.
1496 * Each value of TexturesUsed[unit] is one of zero, TEXTURE_1D_INDEX,
1497 * TEXTURE_2D_INDEX, TEXTURE_3D_INDEX, etc.
1498 * We'll use that info for state validation before rendering.
Brian Paulade50832008-05-14 16:09:46 -06001499 */
Brian Paul517401a2008-11-06 15:04:11 -07001500void
1501_mesa_update_shader_textures_used(struct gl_program *prog)
Brian Paulade50832008-05-14 16:09:46 -06001502{
1503 GLuint s;
1504
1505 memset(prog->TexturesUsed, 0, sizeof(prog->TexturesUsed));
1506
1507 for (s = 0; s < MAX_SAMPLERS; s++) {
1508 if (prog->SamplersUsed & (1 << s)) {
1509 GLuint u = prog->SamplerUnits[s];
1510 GLuint t = prog->SamplerTargets[s];
1511 assert(u < MAX_TEXTURE_IMAGE_UNITS);
1512 prog->TexturesUsed[u] |= (1 << t);
1513 }
1514 }
1515}
1516
1517
Brianb36749d2008-07-21 20:42:05 -06001518static GLboolean
1519is_sampler_type(GLenum type)
1520{
1521 switch (type) {
1522 case GL_SAMPLER_1D:
1523 case GL_SAMPLER_2D:
1524 case GL_SAMPLER_3D:
1525 case GL_SAMPLER_CUBE:
1526 case GL_SAMPLER_1D_SHADOW:
1527 case GL_SAMPLER_2D_SHADOW:
1528 case GL_SAMPLER_2D_RECT_ARB:
1529 case GL_SAMPLER_2D_RECT_SHADOW_ARB:
1530 case GL_SAMPLER_1D_ARRAY_EXT:
1531 case GL_SAMPLER_2D_ARRAY_EXT:
1532 return GL_TRUE;
1533 default:
1534 return GL_FALSE;
1535 }
1536}
1537
1538
Brian Paulade50832008-05-14 16:09:46 -06001539/**
Brian Paulffbc66b2008-07-21 13:58:50 -06001540 * Check if the type given by userType is allowed to set a uniform of the
1541 * target type. Generally, equivalence is required, but setting Boolean
1542 * uniforms can be done with glUniformiv or glUniformfv.
1543 */
1544static GLboolean
1545compatible_types(GLenum userType, GLenum targetType)
1546{
1547 if (userType == targetType)
1548 return GL_TRUE;
1549
1550 if (targetType == GL_BOOL && (userType == GL_FLOAT || userType == GL_INT))
1551 return GL_TRUE;
1552
1553 if (targetType == GL_BOOL_VEC2 && (userType == GL_FLOAT_VEC2 ||
1554 userType == GL_INT_VEC2))
1555 return GL_TRUE;
1556
1557 if (targetType == GL_BOOL_VEC3 && (userType == GL_FLOAT_VEC3 ||
1558 userType == GL_INT_VEC3))
1559 return GL_TRUE;
1560
1561 if (targetType == GL_BOOL_VEC4 && (userType == GL_FLOAT_VEC4 ||
1562 userType == GL_INT_VEC4))
1563 return GL_TRUE;
1564
Brianb36749d2008-07-21 20:42:05 -06001565 if (is_sampler_type(targetType) && userType == GL_INT)
1566 return GL_TRUE;
1567
Brian Paulffbc66b2008-07-21 13:58:50 -06001568 return GL_FALSE;
1569}
1570
1571
1572/**
Brian Paulade50832008-05-14 16:09:46 -06001573 * Set the value of a program's uniform variable.
1574 * \param program the program whose uniform to update
Brian Pauleda291e2008-08-06 16:26:47 -06001575 * \param index the index of the program parameter for the uniform
1576 * \param offset additional parameter slot offset (for arrays)
Brian Paulade50832008-05-14 16:09:46 -06001577 * \param type the datatype of the uniform
1578 * \param count the number of uniforms to set
1579 * \param elems number of elements per uniform
1580 * \param values the new values
1581 */
1582static void
Brian Pauleda291e2008-08-06 16:26:47 -06001583set_program_uniform(GLcontext *ctx, struct gl_program *program,
1584 GLint index, GLint offset,
1585 GLenum type, GLsizei count, GLint elems,
1586 const void *values)
Brian Paulade50832008-05-14 16:09:46 -06001587{
Brian Paul949e7382008-11-05 09:17:55 -07001588 struct gl_program_parameter *param =
1589 &program->Parameters->Parameters[index];
1590
Brian Pauleda291e2008-08-06 16:26:47 -06001591 assert(offset >= 0);
1592
Brian Paul949e7382008-11-05 09:17:55 -07001593 if (!compatible_types(type, param->DataType)) {
Brian Paulffbc66b2008-07-21 13:58:50 -06001594 _mesa_error(ctx, GL_INVALID_OPERATION, "glUniform(type mismatch)");
1595 return;
1596 }
1597
Michal Krolc5c71302008-08-07 16:23:15 +02001598 if (index + offset > (GLint) program->Parameters->Size) {
Brian Pauleda291e2008-08-06 16:26:47 -06001599 /* out of bounds! */
1600 return;
1601 }
1602
Brian Paul949e7382008-11-05 09:17:55 -07001603 if (param->Type == PROGRAM_SAMPLER) {
Brian Paulade50832008-05-14 16:09:46 -06001604 /* This controls which texture unit which is used by a sampler */
1605 GLuint texUnit, sampler;
1606
1607 /* data type for setting samplers must be int */
1608 if (type != GL_INT || count != 1) {
1609 _mesa_error(ctx, GL_INVALID_OPERATION,
1610 "glUniform(only glUniform1i can be used "
1611 "to set sampler uniforms)");
1612 return;
1613 }
1614
Brian Pauleda291e2008-08-06 16:26:47 -06001615 sampler = (GLuint) program->Parameters->ParameterValues[index][0];
Brian Paulade50832008-05-14 16:09:46 -06001616 texUnit = ((GLuint *) values)[0];
1617
1618 /* check that the sampler (tex unit index) is legal */
1619 if (texUnit >= ctx->Const.MaxTextureImageUnits) {
1620 _mesa_error(ctx, GL_INVALID_VALUE,
1621 "glUniform1(invalid sampler/tex unit index)");
1622 return;
1623 }
1624
1625 /* This maps a sampler to a texture unit: */
1626 program->SamplerUnits[sampler] = texUnit;
Brian Paul517401a2008-11-06 15:04:11 -07001627 _mesa_update_shader_textures_used(program);
Brian Paulade50832008-05-14 16:09:46 -06001628
1629 FLUSH_VERTICES(ctx, _NEW_TEXTURE);
1630 }
1631 else {
1632 /* ordinary uniform variable */
Brian Paul530df582008-07-03 16:21:11 -06001633 GLsizei k, i;
Brian Paul2c1ea072009-02-11 08:46:21 -07001634 const GLint slots = (param->Size + 3) / 4;
1635 const GLint typeSize = sizeof_glsl_type(param->DataType);
Brian Paulade50832008-05-14 16:09:46 -06001636
Brian Paul2c1ea072009-02-11 08:46:21 -07001637 if (param->Size > typeSize) {
1638 /* an array */
1639 /* we'll ignore extra data below */
1640 }
1641 else {
1642 /* non-array: count must be one */
1643 if (count != 1) {
1644 _mesa_error(ctx, GL_INVALID_OPERATION,
1645 "glUniform(uniform is not an array)");
1646 return;
1647 }
Brian Paulade50832008-05-14 16:09:46 -06001648 }
1649
1650 for (k = 0; k < count; k++) {
Brian Paul2c1ea072009-02-11 08:46:21 -07001651 GLfloat *uniformVal;
1652
1653 if (offset + k > slots) {
1654 /* Extra array data is ignored */
1655 break;
1656 }
1657
1658 uniformVal = program->Parameters->ParameterValues[index + offset + k];
Brian Pauleda291e2008-08-06 16:26:47 -06001659 if (is_integer_type(type)) {
Brian Paulade50832008-05-14 16:09:46 -06001660 const GLint *iValues = ((const GLint *) values) + k * elems;
1661 for (i = 0; i < elems; i++) {
1662 uniformVal[i] = (GLfloat) iValues[i];
1663 }
1664 }
1665 else {
1666 const GLfloat *fValues = ((const GLfloat *) values) + k * elems;
1667 for (i = 0; i < elems; i++) {
1668 uniformVal[i] = fValues[i];
1669 }
1670 }
Brian Pauleda291e2008-08-06 16:26:47 -06001671
1672 /* if the uniform is bool-valued, convert to 1.0 or 0.0 */
Brian Paul949e7382008-11-05 09:17:55 -07001673 if (is_boolean_type(param->DataType)) {
Brian Pauleda291e2008-08-06 16:26:47 -06001674 for (i = 0; i < elems; i++) {
Michal Krolc5c71302008-08-07 16:23:15 +02001675 uniformVal[i] = uniformVal[i] ? 1.0f : 0.0f;
Brian Pauleda291e2008-08-06 16:26:47 -06001676 }
1677 }
Brian Paulade50832008-05-14 16:09:46 -06001678 }
1679 }
1680}
1681
1682
Brian5b01c5e2006-12-19 18:02:03 -07001683/**
1684 * Called via ctx->Driver.Uniform().
1685 */
Brian Paulfd59f192008-05-18 16:04:55 -06001686static void
Brian5b01c5e2006-12-19 18:02:03 -07001687_mesa_uniform(GLcontext *ctx, GLint location, GLsizei count,
1688 const GLvoid *values, GLenum type)
1689{
Brian3a8e2772006-12-20 17:19:16 -07001690 struct gl_shader_program *shProg = ctx->Shader.CurrentProgram;
Brian Paul2d76a0d2008-11-10 12:33:17 -07001691 struct gl_uniform *uniform;
Brian Pauleda291e2008-08-06 16:26:47 -06001692 GLint elems, offset;
Brian Paule01a03d2009-02-06 10:21:36 -07001693 GLenum basicType;
Brian3a8e2772006-12-20 17:19:16 -07001694
1695 if (!shProg || !shProg->LinkStatus) {
Brian5b01c5e2006-12-19 18:02:03 -07001696 _mesa_error(ctx, GL_INVALID_OPERATION, "glUniform(program not linked)");
Brian3a8e2772006-12-20 17:19:16 -07001697 return;
1698 }
1699
Bruce Merryeeb03fa2007-12-21 14:41:45 +02001700 if (location == -1)
1701 return; /* The standard specifies this as a no-op */
1702
Brian Pauleda291e2008-08-06 16:26:47 -06001703 split_location_offset(&location, &offset);
1704
Brian Paulade50832008-05-14 16:09:46 -06001705 if (location < 0 || location >= (GLint) shProg->Uniforms->NumUniforms) {
1706 _mesa_error(ctx, GL_INVALID_VALUE, "glUniform(location)");
Brian3a8e2772006-12-20 17:19:16 -07001707 return;
1708 }
1709
Brian52363952007-03-13 16:50:24 -06001710 if (count < 0) {
1711 _mesa_error(ctx, GL_INVALID_VALUE, "glUniform(count < 0)");
1712 return;
1713 }
1714
Brian98650bd2007-03-13 16:32:48 -06001715 switch (type) {
1716 case GL_FLOAT:
Brian Paule01a03d2009-02-06 10:21:36 -07001717 basicType = GL_FLOAT;
1718 elems = 1;
1719 break;
Brian98650bd2007-03-13 16:32:48 -06001720 case GL_INT:
Brian Paule01a03d2009-02-06 10:21:36 -07001721 basicType = GL_INT;
Brian98650bd2007-03-13 16:32:48 -06001722 elems = 1;
1723 break;
1724 case GL_FLOAT_VEC2:
Brian Paule01a03d2009-02-06 10:21:36 -07001725 basicType = GL_FLOAT;
1726 elems = 2;
1727 break;
Brian98650bd2007-03-13 16:32:48 -06001728 case GL_INT_VEC2:
Brian Paule01a03d2009-02-06 10:21:36 -07001729 basicType = GL_INT;
Brian98650bd2007-03-13 16:32:48 -06001730 elems = 2;
1731 break;
1732 case GL_FLOAT_VEC3:
Brian Paule01a03d2009-02-06 10:21:36 -07001733 basicType = GL_FLOAT;
1734 elems = 3;
1735 break;
Brian98650bd2007-03-13 16:32:48 -06001736 case GL_INT_VEC3:
Brian Paule01a03d2009-02-06 10:21:36 -07001737 basicType = GL_INT;
Brian98650bd2007-03-13 16:32:48 -06001738 elems = 3;
1739 break;
1740 case GL_FLOAT_VEC4:
Brian Paule01a03d2009-02-06 10:21:36 -07001741 basicType = GL_FLOAT;
1742 elems = 4;
1743 break;
Brian98650bd2007-03-13 16:32:48 -06001744 case GL_INT_VEC4:
Brian Paule01a03d2009-02-06 10:21:36 -07001745 basicType = GL_INT;
Brian98650bd2007-03-13 16:32:48 -06001746 elems = 4;
1747 break;
1748 default:
1749 _mesa_problem(ctx, "Invalid type in _mesa_uniform");
1750 return;
Brian89dc4852007-01-04 14:35:44 -07001751 }
Brian98650bd2007-03-13 16:32:48 -06001752
Brian Paulade50832008-05-14 16:09:46 -06001753 FLUSH_VERTICES(ctx, _NEW_PROGRAM);
Brian98650bd2007-03-13 16:32:48 -06001754
Brian Paul2d76a0d2008-11-10 12:33:17 -07001755 uniform = &shProg->Uniforms->Uniforms[location];
1756
Brian Paule01a03d2009-02-06 10:21:36 -07001757 if (ctx->Shader.Flags & GLSL_UNIFORMS) {
1758 GLint i;
1759 _mesa_printf("Mesa: set program %u uniform %s (loc %d) to: ",
1760 shProg->Name, uniform->Name, location);
1761 if (basicType == GL_INT) {
1762 const GLint *v = (const GLint *) values;
1763 for (i = 0; i < count * elems; i++) {
1764 _mesa_printf("%d ", v[i]);
1765 }
1766 }
1767 else {
1768 const GLfloat *v = (const GLfloat *) values;
1769 for (i = 0; i < count * elems; i++) {
1770 _mesa_printf("%g ", v[i]);
1771 }
1772 }
1773 _mesa_printf("\n");
1774 }
1775
Brian Paulade50832008-05-14 16:09:46 -06001776 /* A uniform var may be used by both a vertex shader and a fragment
1777 * shader. We may need to update one or both shader's uniform here:
Bruce Merryeeb03fa2007-12-21 14:41:45 +02001778 */
Brian Paulade50832008-05-14 16:09:46 -06001779 if (shProg->VertexProgram) {
Brian Pauleda291e2008-08-06 16:26:47 -06001780 /* convert uniform location to program parameter index */
Brian Paul2d76a0d2008-11-10 12:33:17 -07001781 GLint index = uniform->VertPos;
Brian Pauleda291e2008-08-06 16:26:47 -06001782 if (index >= 0) {
Brian Paulade50832008-05-14 16:09:46 -06001783 set_program_uniform(ctx, &shProg->VertexProgram->Base,
Brian Pauleda291e2008-08-06 16:26:47 -06001784 index, offset, type, count, elems, values);
Bruce Merry2bf2a8c2007-12-21 23:18:40 +02001785 }
Brian5b01c5e2006-12-19 18:02:03 -07001786 }
Brian5cf73262007-01-05 16:02:45 -07001787
Brian Paulade50832008-05-14 16:09:46 -06001788 if (shProg->FragmentProgram) {
Brian Pauleda291e2008-08-06 16:26:47 -06001789 /* convert uniform location to program parameter index */
Brian Paul2d76a0d2008-11-10 12:33:17 -07001790 GLint index = uniform->FragPos;
Brian Pauleda291e2008-08-06 16:26:47 -06001791 if (index >= 0) {
Brian Paulade50832008-05-14 16:09:46 -06001792 set_program_uniform(ctx, &shProg->FragmentProgram->Base,
Brian Pauleda291e2008-08-06 16:26:47 -06001793 index, offset, type, count, elems, values);
Brian Paulade50832008-05-14 16:09:46 -06001794 }
1795 }
Brian Paul949e7382008-11-05 09:17:55 -07001796
Brian Paul2d76a0d2008-11-10 12:33:17 -07001797 uniform->Initialized = GL_TRUE;
Brian Paulade50832008-05-14 16:09:46 -06001798}
1799
1800
Brian Pauleda291e2008-08-06 16:26:47 -06001801/**
1802 * Set a matrix-valued program parameter.
1803 */
Brian Paulade50832008-05-14 16:09:46 -06001804static void
1805set_program_uniform_matrix(GLcontext *ctx, struct gl_program *program,
Brian Pauleda291e2008-08-06 16:26:47 -06001806 GLuint index, GLuint offset,
1807 GLuint count, GLuint rows, GLuint cols,
Brian Paulade50832008-05-14 16:09:46 -06001808 GLboolean transpose, const GLfloat *values)
1809{
Brian Paulffbc66b2008-07-21 13:58:50 -06001810 GLuint mat, row, col;
Brian Pauleda291e2008-08-06 16:26:47 -06001811 GLuint dst = index + offset, src = 0;
Brian Paulffbc66b2008-07-21 13:58:50 -06001812 GLint nr, nc;
1813
1814 /* check that the number of rows, columns is correct */
Brian Pauleda291e2008-08-06 16:26:47 -06001815 get_matrix_dims(program->Parameters->Parameters[index].DataType, &nr, &nc);
Brian Paulffbc66b2008-07-21 13:58:50 -06001816 if (rows != nr || cols != nc) {
1817 _mesa_error(ctx, GL_INVALID_OPERATION,
Brian Pauleda291e2008-08-06 16:26:47 -06001818 "glUniformMatrix(matrix size mismatch)");
1819 return;
1820 }
1821
1822 if (index + offset > program->Parameters->Size) {
1823 /* out of bounds! */
Brian Paulffbc66b2008-07-21 13:58:50 -06001824 return;
1825 }
1826
Brian Paulade50832008-05-14 16:09:46 -06001827 /*
1828 * Note: the _columns_ of a matrix are stored in program registers, not
Brian Paulf45ed0e2008-07-18 12:51:39 -06001829 * the rows. So, the loops below look a little funny.
1830 * XXX could optimize this a bit...
Brian Paulade50832008-05-14 16:09:46 -06001831 */
Brian Paulf45ed0e2008-07-18 12:51:39 -06001832
1833 /* loop over matrices */
1834 for (mat = 0; mat < count; mat++) {
1835
1836 /* each matrix: */
Brian Paulade50832008-05-14 16:09:46 -06001837 for (col = 0; col < cols; col++) {
Brian Paulf45ed0e2008-07-18 12:51:39 -06001838 GLfloat *v = program->Parameters->ParameterValues[dst];
Brian Paulade50832008-05-14 16:09:46 -06001839 for (row = 0; row < rows; row++) {
Brian Paulf45ed0e2008-07-18 12:51:39 -06001840 if (transpose) {
1841 v[row] = values[src + row * cols + col];
1842 }
1843 else {
1844 v[row] = values[src + col * rows + row];
1845 }
Brian Paulade50832008-05-14 16:09:46 -06001846 }
Brian Paulf45ed0e2008-07-18 12:51:39 -06001847 dst++;
Brian Paulade50832008-05-14 16:09:46 -06001848 }
Brian Paulf45ed0e2008-07-18 12:51:39 -06001849
1850 src += rows * cols; /* next matrix */
Brian5cf73262007-01-05 16:02:45 -07001851 }
Brian34ae99d2006-12-18 08:28:54 -07001852}
1853
1854
1855/**
Brian5b01c5e2006-12-19 18:02:03 -07001856 * Called by ctx->Driver.UniformMatrix().
Brian Paulf45ed0e2008-07-18 12:51:39 -06001857 * Note: cols=2, rows=4 ==> array[2] of vec4
Brian34ae99d2006-12-18 08:28:54 -07001858 */
Brian Paulfd59f192008-05-18 16:04:55 -06001859static void
Brian5b01c5e2006-12-19 18:02:03 -07001860_mesa_uniform_matrix(GLcontext *ctx, GLint cols, GLint rows,
1861 GLenum matrixType, GLint location, GLsizei count,
1862 GLboolean transpose, const GLfloat *values)
Brian34ae99d2006-12-18 08:28:54 -07001863{
Brian3a8e2772006-12-20 17:19:16 -07001864 struct gl_shader_program *shProg = ctx->Shader.CurrentProgram;
Brian Paul2d76a0d2008-11-10 12:33:17 -07001865 struct gl_uniform *uniform;
1866 GLint offset;
Brian Paulade50832008-05-14 16:09:46 -06001867
Brian3a8e2772006-12-20 17:19:16 -07001868 if (!shProg || !shProg->LinkStatus) {
1869 _mesa_error(ctx, GL_INVALID_OPERATION,
1870 "glUniformMatrix(program not linked)");
1871 return;
1872 }
Brian Paulade50832008-05-14 16:09:46 -06001873
Bruce Merry89b80322007-12-21 15:20:17 +02001874 if (location == -1)
1875 return; /* The standard specifies this as a no-op */
Brian Paulade50832008-05-14 16:09:46 -06001876
Brian Pauleda291e2008-08-06 16:26:47 -06001877 split_location_offset(&location, &offset);
1878
Brian Paul016701f2008-07-29 17:43:35 -06001879 if (location < 0 || location >= (GLint) shProg->Uniforms->NumUniforms) {
Brian Paulade50832008-05-14 16:09:46 -06001880 _mesa_error(ctx, GL_INVALID_VALUE, "glUniformMatrix(location)");
Brian3a8e2772006-12-20 17:19:16 -07001881 return;
1882 }
Brian34ae99d2006-12-18 08:28:54 -07001883 if (values == NULL) {
Brian3a8e2772006-12-20 17:19:16 -07001884 _mesa_error(ctx, GL_INVALID_VALUE, "glUniformMatrix");
Brian34ae99d2006-12-18 08:28:54 -07001885 return;
1886 }
1887
1888 FLUSH_VERTICES(ctx, _NEW_PROGRAM);
1889
Brian Paul2d76a0d2008-11-10 12:33:17 -07001890 uniform = &shProg->Uniforms->Uniforms[location];
1891
Brian Paulade50832008-05-14 16:09:46 -06001892 if (shProg->VertexProgram) {
Brian Pauleda291e2008-08-06 16:26:47 -06001893 /* convert uniform location to program parameter index */
Brian Paul2d76a0d2008-11-10 12:33:17 -07001894 GLint index = uniform->VertPos;
Brian Pauleda291e2008-08-06 16:26:47 -06001895 if (index >= 0) {
Brian Paulade50832008-05-14 16:09:46 -06001896 set_program_uniform_matrix(ctx, &shProg->VertexProgram->Base,
Brian Pauleda291e2008-08-06 16:26:47 -06001897 index, offset,
1898 count, rows, cols, transpose, values);
Brian34ae99d2006-12-18 08:28:54 -07001899 }
Brian Paulade50832008-05-14 16:09:46 -06001900 }
1901
1902 if (shProg->FragmentProgram) {
Brian Pauleda291e2008-08-06 16:26:47 -06001903 /* convert uniform location to program parameter index */
Brian Paul2d76a0d2008-11-10 12:33:17 -07001904 GLint index = uniform->FragPos;
Brian Pauleda291e2008-08-06 16:26:47 -06001905 if (index >= 0) {
Brian Paulade50832008-05-14 16:09:46 -06001906 set_program_uniform_matrix(ctx, &shProg->FragmentProgram->Base,
Brian Pauleda291e2008-08-06 16:26:47 -06001907 index, offset,
1908 count, rows, cols, transpose, values);
Brian3a8e2772006-12-20 17:19:16 -07001909 }
Brian34ae99d2006-12-18 08:28:54 -07001910 }
Brian Paul949e7382008-11-05 09:17:55 -07001911
Brian Paul2d76a0d2008-11-10 12:33:17 -07001912 uniform->Initialized = GL_TRUE;
Brian34ae99d2006-12-18 08:28:54 -07001913}
1914
1915
Brian Paulfd59f192008-05-18 16:04:55 -06001916static void
Brian5b01c5e2006-12-19 18:02:03 -07001917_mesa_validate_program(GLcontext *ctx, GLuint program)
Brian34ae99d2006-12-18 08:28:54 -07001918{
Brian65a18442006-12-19 18:46:56 -07001919 struct gl_shader_program *shProg;
Brian Paulbc985b52008-07-21 14:16:07 -06001920
1921 shProg = _mesa_lookup_shader_program_err(ctx, program, "glValidateProgram");
Brian65a18442006-12-19 18:46:56 -07001922 if (!shProg) {
Brian34ae99d2006-12-18 08:28:54 -07001923 return;
1924 }
1925
Brian Paulbc985b52008-07-21 14:16:07 -06001926 if (!shProg->LinkStatus) {
1927 shProg->Validated = GL_FALSE;
1928 return;
1929 }
1930
1931 /* From the GL spec, a program is invalid if any of these are true:
1932
Brian5b01c5e2006-12-19 18:02:03 -07001933 any two active samplers in the current program object are of
1934 different types, but refer to the same texture image unit,
1935
1936 any active sampler in the current program object refers to a texture
1937 image unit where fixed-function fragment processing accesses a
1938 texture target that does not match the sampler type, or
1939
1940 the sum of the number of active samplers in the program and the
1941 number of texture image units enabled for fixed-function fragment
1942 processing exceeds the combined limit on the total number of texture
1943 image units allowed.
1944 */
Brian Paulbc985b52008-07-21 14:16:07 -06001945
1946 shProg->Validated = GL_TRUE;
Brian34ae99d2006-12-18 08:28:54 -07001947}
Brian Paulfd59f192008-05-18 16:04:55 -06001948
1949
1950/**
1951 * Plug in Mesa's GLSL functions into the device driver function table.
1952 */
1953void
1954_mesa_init_glsl_driver_functions(struct dd_function_table *driver)
1955{
1956 driver->AttachShader = _mesa_attach_shader;
1957 driver->BindAttribLocation = _mesa_bind_attrib_location;
1958 driver->CompileShader = _mesa_compile_shader;
1959 driver->CreateProgram = _mesa_create_program;
1960 driver->CreateShader = _mesa_create_shader;
1961 driver->DeleteProgram2 = _mesa_delete_program2;
1962 driver->DeleteShader = _mesa_delete_shader;
1963 driver->DetachShader = _mesa_detach_shader;
1964 driver->GetActiveAttrib = _mesa_get_active_attrib;
1965 driver->GetActiveUniform = _mesa_get_active_uniform;
1966 driver->GetAttachedShaders = _mesa_get_attached_shaders;
1967 driver->GetAttribLocation = _mesa_get_attrib_location;
1968 driver->GetHandle = _mesa_get_handle;
1969 driver->GetProgramiv = _mesa_get_programiv;
1970 driver->GetProgramInfoLog = _mesa_get_program_info_log;
1971 driver->GetShaderiv = _mesa_get_shaderiv;
1972 driver->GetShaderInfoLog = _mesa_get_shader_info_log;
1973 driver->GetShaderSource = _mesa_get_shader_source;
1974 driver->GetUniformfv = _mesa_get_uniformfv;
Brian Paul2be54a82008-07-08 16:17:04 -06001975 driver->GetUniformiv = _mesa_get_uniformiv;
Brian Paulfd59f192008-05-18 16:04:55 -06001976 driver->GetUniformLocation = _mesa_get_uniform_location;
1977 driver->IsProgram = _mesa_is_program;
1978 driver->IsShader = _mesa_is_shader;
1979 driver->LinkProgram = _mesa_link_program;
1980 driver->ShaderSource = _mesa_shader_source;
1981 driver->Uniform = _mesa_uniform;
1982 driver->UniformMatrix = _mesa_uniform_matrix;
1983 driver->UseProgram = _mesa_use_program;
1984 driver->ValidateProgram = _mesa_validate_program;
1985}