blob: 70ceb70fe74619e774f9d89756f111948695a672 [file] [log] [blame]
Brian34ae99d2006-12-18 08:28:54 -07001/*
2 * Mesa 3-D graphics library
Brian5b01c5e2006-12-19 18:02:03 -07003 * Version: 6.5.3
Brian34ae99d2006-12-18 08:28:54 -07004 *
Brian5b01c5e2006-12-19 18:02:03 -07005 * Copyright (C) 2004-2007 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
38#include "glheader.h"
39#include "context.h"
40#include "hash.h"
Brian34ae99d2006-12-18 08:28:54 -070041#include "program.h"
42#include "prog_parameter.h"
Brian3209c3e2007-01-09 17:49:24 -070043#include "prog_print.h"
44#include "prog_statevars.h"
Brian34ae99d2006-12-18 08:28:54 -070045#include "shader_api.h"
46
47#include "slang_compile.h"
48#include "slang_link.h"
49
50
51
Brianf2923612006-12-20 09:56:44 -070052/**
53 * Allocate a new gl_shader_program object, initialize it.
54 */
55struct gl_shader_program *
56_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) {
61 shProg->Type = GL_SHADER_PROGRAM;
62 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
70void
71_mesa_free_shader_program_data(GLcontext *ctx,
72 struct gl_shader_program *shProg)
73{
74 assert(shProg->Type == GL_SHADER_PROGRAM);
75
76 if (shProg->VertexProgram) {
77 if (shProg->VertexProgram->Base.Parameters == shProg->Uniforms) {
78 /* to prevent a double-free in the next call */
79 shProg->VertexProgram->Base.Parameters = NULL;
80 }
81 _mesa_delete_program(ctx, &shProg->VertexProgram->Base);
82 shProg->VertexProgram = NULL;
83 }
84
85 if (shProg->FragmentProgram) {
86 if (shProg->FragmentProgram->Base.Parameters == shProg->Uniforms) {
87 /* to prevent a double-free in the next call */
88 shProg->FragmentProgram->Base.Parameters = NULL;
89 }
90 _mesa_delete_program(ctx, &shProg->FragmentProgram->Base);
91 shProg->FragmentProgram = NULL;
92 }
93
94
95 if (shProg->Uniforms) {
96 _mesa_free_parameter_list(shProg->Uniforms);
97 shProg->Uniforms = NULL;
98 }
99
100 if (shProg->Varying) {
101 _mesa_free_parameter_list(shProg->Varying);
102 shProg->Varying = NULL;
103 }
104}
105
106
107
108void
109_mesa_free_shader_program(GLcontext *ctx, struct gl_shader_program *shProg)
110{
111 _mesa_free_shader_program_data(ctx, shProg);
112 _mesa_free(shProg);
113}
114
115
116/**
117 * Lookup a GLSL program object.
118 */
119struct gl_shader_program *
120_mesa_lookup_shader_program(GLcontext *ctx, GLuint name)
121{
122 struct gl_shader_program *shProg;
123 if (name) {
124 shProg = (struct gl_shader_program *)
125 _mesa_HashLookup(ctx->Shared->ShaderObjects, name);
126 /* Note that both gl_shader and gl_shader_program objects are kept
127 * in the same hash table. Check the object's type to be sure it's
128 * what we're expecting.
129 */
130 if (shProg && shProg->Type != GL_SHADER_PROGRAM) {
131 return NULL;
132 }
133 return shProg;
134 }
135 return NULL;
136}
137
138
139/**
140 * Allocate a new gl_shader object, initialize it.
141 */
142struct gl_shader *
143_mesa_new_shader(GLcontext *ctx, GLuint name, GLenum type)
144{
145 struct gl_shader *shader;
146 assert(type == GL_FRAGMENT_SHADER || type == GL_VERTEX_SHADER);
147 shader = CALLOC_STRUCT(gl_shader);
148 if (shader) {
149 shader->Type = type;
150 shader->Name = name;
151 shader->RefCount = 1;
152 }
153 return shader;
154}
155
156
157void
158_mesa_free_shader(GLcontext *ctx, struct gl_shader *sh)
159{
160 GLuint i;
161 if (sh->Source)
162 _mesa_free((void *) sh->Source);
163 if (sh->InfoLog)
164 _mesa_free(sh->InfoLog);
165 for (i = 0; i < sh->NumPrograms; i++) {
166 assert(sh->Programs[i]);
167 _mesa_delete_program(ctx, sh->Programs[i]);
168 }
169 if (sh->Programs)
170 _mesa_free(sh->Programs);
171 _mesa_free(sh);
172}
173
174
175/**
176 * Lookup a GLSL shader object.
177 */
178struct gl_shader *
179_mesa_lookup_shader(GLcontext *ctx, GLuint name)
180{
181 if (name) {
182 struct gl_shader *sh = (struct gl_shader *)
183 _mesa_HashLookup(ctx->Shared->ShaderObjects, name);
184 /* Note that both gl_shader and gl_shader_program objects are kept
185 * in the same hash table. Check the object's type to be sure it's
186 * what we're expecting.
187 */
188 if (sh && sh->Type == GL_SHADER_PROGRAM) {
189 assert(sh->Type == GL_VERTEX_SHADER ||
190 sh->Type == GL_FRAGMENT_SHADER);
191 return NULL;
192 }
193 return sh;
194 }
195 return NULL;
196}
197
198
199void
200_mesa_init_shader_state(GLcontext * ctx)
201{
Brian5e80c622007-02-24 15:39:37 -0700202 /* no-op */
Brianf2923612006-12-20 09:56:44 -0700203}
204
205
206
Brian34ae99d2006-12-18 08:28:54 -0700207
Brian5b01c5e2006-12-19 18:02:03 -0700208
209/**
210 * Copy string from <src> to <dst>, up to maxLength characters, returning
211 * length of <dst> in <length>.
212 * \param src the strings source
213 * \param maxLength max chars to copy
214 * \param length returns number of chars copied
215 * \param dst the string destination
216 */
217static void
218copy_string(GLchar *dst, GLsizei maxLength, GLsizei *length, const GLchar *src)
219{
220 GLsizei len;
221 for (len = 0; len < maxLength - 1 && src && src[len]; len++)
222 dst[len] = src[len];
223 if (maxLength > 0)
224 dst[len] = 0;
225 if (length)
226 *length = len;
227}
228
229
230
231
232/**
233 * Called via ctx->Driver.AttachShader()
234 */
235void
236_mesa_attach_shader(GLcontext *ctx, GLuint program, GLuint shader)
237{
Brian65a18442006-12-19 18:46:56 -0700238 struct gl_shader_program *shProg
239 = _mesa_lookup_shader_program(ctx, program);
240 struct gl_shader *sh = _mesa_lookup_shader(ctx, shader);
241 const GLuint n = shProg->NumShaders;
Brian5b01c5e2006-12-19 18:02:03 -0700242 GLuint i;
243
Brian65a18442006-12-19 18:46:56 -0700244 if (!shProg || !sh) {
Brian43975832007-01-04 08:21:09 -0700245 _mesa_error(ctx, GL_INVALID_VALUE,
Brian5b01c5e2006-12-19 18:02:03 -0700246 "glAttachShader(bad program or shader name)");
247 return;
248 }
249
250 for (i = 0; i < n; i++) {
Brian65a18442006-12-19 18:46:56 -0700251 if (shProg->Shaders[i] == sh) {
Brian5b01c5e2006-12-19 18:02:03 -0700252 /* already attached */
253 return;
Brian34ae99d2006-12-18 08:28:54 -0700254 }
255 }
Brian5b01c5e2006-12-19 18:02:03 -0700256
257 /* grow list */
Brian65a18442006-12-19 18:46:56 -0700258 shProg->Shaders = (struct gl_shader **)
259 _mesa_realloc(shProg->Shaders,
260 n * sizeof(struct gl_shader *),
261 (n + 1) * sizeof(struct gl_shader *));
262 if (!shProg->Shaders) {
Brian5b01c5e2006-12-19 18:02:03 -0700263 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glAttachShader");
264 return;
265 }
266
267 /* append */
Brian65a18442006-12-19 18:46:56 -0700268 shProg->Shaders[n] = sh;
269 sh->RefCount++;
270 shProg->NumShaders++;
Brian5b01c5e2006-12-19 18:02:03 -0700271}
272
273
274void
275_mesa_bind_attrib_location(GLcontext *ctx, GLuint program, GLuint index,
276 const GLchar *name)
277{
Brian65a18442006-12-19 18:46:56 -0700278 struct gl_shader_program *shProg
279 = _mesa_lookup_shader_program(ctx, program);
Brianb7978af2007-01-09 19:17:17 -0700280 const GLint size = -1; /* unknown size */
281 GLint i, oldIndex;
Brian5b01c5e2006-12-19 18:02:03 -0700282
Brian65a18442006-12-19 18:46:56 -0700283 if (!shProg) {
Brian43975832007-01-04 08:21:09 -0700284 _mesa_error(ctx, GL_INVALID_VALUE, "glBindAttribLocation(program)");
Brian5b01c5e2006-12-19 18:02:03 -0700285 return;
286 }
287
Brian9e4bae92006-12-20 09:27:42 -0700288 if (!name)
289 return;
290
291 if (strncmp(name, "gl_", 3) == 0) {
292 _mesa_error(ctx, GL_INVALID_OPERATION,
293 "glBindAttribLocation(illegal name)");
294 return;
295 }
296
Brian3209c3e2007-01-09 17:49:24 -0700297 oldIndex = _mesa_get_attrib_location(ctx, program, name);
298
299 /* this will replace the current value if it's already in the list */
Brianb7978af2007-01-09 19:17:17 -0700300 i = _mesa_add_attribute(shProg->Attributes, name, size, index);
Brian3209c3e2007-01-09 17:49:24 -0700301 if (i < 0) {
302 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBindAttribLocation");
303 }
304
305 if (shProg->VertexProgram && oldIndex >= 0) {
306 _slang_remap_attribute(&shProg->VertexProgram->Base, oldIndex, index);
307 }
308
Brian88e2dbf2007-01-10 13:33:38 -0700309#if 0
Brian3209c3e2007-01-09 17:49:24 -0700310 printf("===== post BindAttrib:\n");
311 _mesa_print_program(&shProg->VertexProgram->Base);
Brian88e2dbf2007-01-10 13:33:38 -0700312#endif
Brian34ae99d2006-12-18 08:28:54 -0700313}
314
315
Brian5b01c5e2006-12-19 18:02:03 -0700316GLuint
317_mesa_create_shader(GLcontext *ctx, GLenum type)
318{
Brian65a18442006-12-19 18:46:56 -0700319 struct gl_shader *sh;
Brian5b01c5e2006-12-19 18:02:03 -0700320 GLuint name;
321
322 name = _mesa_HashFindFreeKeyBlock(ctx->Shared->ShaderObjects, 1);
323
324 switch (type) {
Brian65a18442006-12-19 18:46:56 -0700325 case GL_FRAGMENT_SHADER:
326 case GL_VERTEX_SHADER:
327 sh = _mesa_new_shader(ctx, name, type);
Brian5b01c5e2006-12-19 18:02:03 -0700328 break;
329 default:
330 _mesa_error(ctx, GL_INVALID_ENUM, "CreateShader(type)");
331 return 0;
332 }
333
Brian65a18442006-12-19 18:46:56 -0700334 _mesa_HashInsert(ctx->Shared->ShaderObjects, name, sh);
Brian5b01c5e2006-12-19 18:02:03 -0700335
336 return name;
337}
338
339
340GLuint
341_mesa_create_program(GLcontext *ctx)
342{
343 GLuint name;
Brian65a18442006-12-19 18:46:56 -0700344 struct gl_shader_program *shProg;
Brian5b01c5e2006-12-19 18:02:03 -0700345
Brian65a18442006-12-19 18:46:56 -0700346 name = _mesa_HashFindFreeKeyBlock(ctx->Shared->ShaderObjects, 1);
347 shProg = _mesa_new_shader_program(ctx, name);
Brian5b01c5e2006-12-19 18:02:03 -0700348
Brian65a18442006-12-19 18:46:56 -0700349 _mesa_HashInsert(ctx->Shared->ShaderObjects, name, shProg);
Brian5b01c5e2006-12-19 18:02:03 -0700350
351 return name;
352}
353
354
355void
356_mesa_delete_program2(GLcontext *ctx, GLuint name)
357{
Brian65a18442006-12-19 18:46:56 -0700358 struct gl_shader_program *shProg;
Brian5b01c5e2006-12-19 18:02:03 -0700359
Brian65a18442006-12-19 18:46:56 -0700360 shProg = _mesa_lookup_shader_program(ctx, name);
361 if (!shProg) {
Brian43975832007-01-04 08:21:09 -0700362 _mesa_error(ctx, GL_INVALID_VALUE, "glDeleteProgram(name)");
Brian5b01c5e2006-12-19 18:02:03 -0700363 return;
364 }
365
Brian9e4bae92006-12-20 09:27:42 -0700366 /* always remove from hash table */
Brian65a18442006-12-19 18:46:56 -0700367 _mesa_HashRemove(ctx->Shared->ShaderObjects, name);
Brian9e4bae92006-12-20 09:27:42 -0700368
369 shProg->DeletePending = GL_TRUE;
370
371 /* decrement refcount, delete if zero */
372 shProg->RefCount--;
373 if (shProg->RefCount <= 0) {
374 _mesa_free_shader_program(ctx, shProg);
375 }
Brian5b01c5e2006-12-19 18:02:03 -0700376}
377
378
379void
380_mesa_delete_shader(GLcontext *ctx, GLuint shader)
381{
Brian9e4bae92006-12-20 09:27:42 -0700382 struct gl_shader *sh = _mesa_lookup_shader(ctx, shader);
383 if (!sh) {
384 return;
385 }
Brian5b01c5e2006-12-19 18:02:03 -0700386
Brian9e4bae92006-12-20 09:27:42 -0700387 sh->DeletePending = GL_TRUE;
388 sh->RefCount--;
389 if (sh->RefCount <= 0) {
390 _mesa_free_shader(ctx, sh);
391 }
Brian5b01c5e2006-12-19 18:02:03 -0700392}
393
394
395void
396_mesa_detach_shader(GLcontext *ctx, GLuint program, GLuint shader)
397{
Brian65a18442006-12-19 18:46:56 -0700398 struct gl_shader_program *shProg
399 = _mesa_lookup_shader_program(ctx, program);
400 const GLuint n = shProg->NumShaders;
Brian5b01c5e2006-12-19 18:02:03 -0700401 GLuint i, j;
402
Brian65a18442006-12-19 18:46:56 -0700403 if (!shProg) {
Brian43975832007-01-04 08:21:09 -0700404 _mesa_error(ctx, GL_INVALID_VALUE,
Brian5b01c5e2006-12-19 18:02:03 -0700405 "glDetachShader(bad program or shader name)");
406 return;
407 }
408
409 for (i = 0; i < n; i++) {
Brian65a18442006-12-19 18:46:56 -0700410 if (shProg->Shaders[i]->Name == shader) {
411 struct gl_shader **newList;
Brian5b01c5e2006-12-19 18:02:03 -0700412 /* found it */
Brian9e4bae92006-12-20 09:27:42 -0700413
414 shProg->Shaders[i]->RefCount--;
415
Brian5b01c5e2006-12-19 18:02:03 -0700416 /* alloc new, smaller array */
Brian65a18442006-12-19 18:46:56 -0700417 newList = (struct gl_shader **)
418 _mesa_malloc((n - 1) * sizeof(struct gl_shader *));
Brian5b01c5e2006-12-19 18:02:03 -0700419 if (!newList) {
420 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glDetachShader");
421 return;
422 }
423 for (j = 0; j < i; j++) {
Brian65a18442006-12-19 18:46:56 -0700424 newList[j] = shProg->Shaders[j];
Brian5b01c5e2006-12-19 18:02:03 -0700425 }
426 while (++i < n)
Brian65a18442006-12-19 18:46:56 -0700427 newList[j++] = shProg->Shaders[i];
428 _mesa_free(shProg->Shaders);
Brian5b01c5e2006-12-19 18:02:03 -0700429
430 /* XXX refcounting! */
431
Brian65a18442006-12-19 18:46:56 -0700432 shProg->Shaders = newList;
Brian5b01c5e2006-12-19 18:02:03 -0700433 return;
434 }
435 }
436
437 /* not found */
Brian43975832007-01-04 08:21:09 -0700438 _mesa_error(ctx, GL_INVALID_VALUE,
Brian5b01c5e2006-12-19 18:02:03 -0700439 "glDetachShader(shader not found)");
440}
441
442
443void
444_mesa_get_active_attrib(GLcontext *ctx, GLuint program, GLuint index,
445 GLsizei maxLength, GLsizei *length, GLint *size,
446 GLenum *type, GLchar *nameOut)
447{
448 static const GLenum vec_types[] = {
449 GL_FLOAT, GL_FLOAT_VEC2, GL_FLOAT_VEC3, GL_FLOAT_VEC4
450 };
Brian65a18442006-12-19 18:46:56 -0700451 struct gl_shader_program *shProg
452 = _mesa_lookup_shader_program(ctx, program);
Brian5b01c5e2006-12-19 18:02:03 -0700453 GLint sz;
454
Brian65a18442006-12-19 18:46:56 -0700455 if (!shProg) {
Brian43975832007-01-04 08:21:09 -0700456 _mesa_error(ctx, GL_INVALID_VALUE, "glGetActiveUniform");
Brian5b01c5e2006-12-19 18:02:03 -0700457 return;
458 }
459
Brian65a18442006-12-19 18:46:56 -0700460 if (!shProg->Attributes || index >= shProg->Attributes->NumParameters) {
Brian5b01c5e2006-12-19 18:02:03 -0700461 _mesa_error(ctx, GL_INVALID_VALUE, "glGetActiveUniform(index)");
462 return;
463 }
464
465 copy_string(nameOut, maxLength, length,
Brian65a18442006-12-19 18:46:56 -0700466 shProg->Attributes->Parameters[index].Name);
467 sz = shProg->Attributes->Parameters[index].Size;
Brian5b01c5e2006-12-19 18:02:03 -0700468 if (size)
469 *size = sz;
470 if (type)
471 *type = vec_types[sz]; /* XXX this is a temporary hack */
472}
473
474
475/**
476 * Called via ctx->Driver.GetActiveUniform().
477 */
478void
479_mesa_get_active_uniform(GLcontext *ctx, GLuint program, GLuint index,
480 GLsizei maxLength, GLsizei *length, GLint *size,
481 GLenum *type, GLchar *nameOut)
482{
483 static const GLenum vec_types[] = {
484 GL_FLOAT, GL_FLOAT_VEC2, GL_FLOAT_VEC3, GL_FLOAT_VEC4
485 };
Brian65a18442006-12-19 18:46:56 -0700486 struct gl_shader_program *shProg
487 = _mesa_lookup_shader_program(ctx, program);
Brian5b01c5e2006-12-19 18:02:03 -0700488 GLint sz;
489
Brian65a18442006-12-19 18:46:56 -0700490 if (!shProg) {
Brian43975832007-01-04 08:21:09 -0700491 _mesa_error(ctx, GL_INVALID_VALUE, "glGetActiveUniform");
Brian5b01c5e2006-12-19 18:02:03 -0700492 return;
493 }
494
Brian65a18442006-12-19 18:46:56 -0700495 if (!shProg->Uniforms || index >= shProg->Uniforms->NumParameters) {
Brian5b01c5e2006-12-19 18:02:03 -0700496 _mesa_error(ctx, GL_INVALID_VALUE, "glGetActiveUniform(index)");
497 return;
498 }
499
500 copy_string(nameOut, maxLength, length,
Brian65a18442006-12-19 18:46:56 -0700501 shProg->Uniforms->Parameters[index].Name);
502 sz = shProg->Uniforms->Parameters[index].Size;
Brian5b01c5e2006-12-19 18:02:03 -0700503 if (size)
504 *size = sz;
505 if (type)
506 *type = vec_types[sz]; /* XXX this is a temporary hack */
507}
508
509
510/**
511 * Called via ctx->Driver.GetAttachedShaders().
512 */
513void
514_mesa_get_attached_shaders(GLcontext *ctx, GLuint program, GLsizei maxCount,
515 GLsizei *count, GLuint *obj)
516{
Brian65a18442006-12-19 18:46:56 -0700517 struct gl_shader_program *shProg
518 = _mesa_lookup_shader_program(ctx, program);
519 if (shProg) {
Brian223d7cb2007-01-23 16:37:51 -0700520 GLint i;
Brian65a18442006-12-19 18:46:56 -0700521 for (i = 0; i < maxCount && i < shProg->NumShaders; i++) {
522 obj[i] = shProg->Shaders[i]->Name;
Brian5b01c5e2006-12-19 18:02:03 -0700523 }
524 if (count)
525 *count = i;
526 }
527 else {
Brian43975832007-01-04 08:21:09 -0700528 _mesa_error(ctx, GL_INVALID_VALUE, "glGetAttachedShaders");
Brian5b01c5e2006-12-19 18:02:03 -0700529 }
530}
531
532
533GLint
534_mesa_get_attrib_location(GLcontext *ctx, GLuint program,
535 const GLchar *name)
536{
Brian65a18442006-12-19 18:46:56 -0700537 struct gl_shader_program *shProg
538 = _mesa_lookup_shader_program(ctx, program);
Brian5b01c5e2006-12-19 18:02:03 -0700539
Brian65a18442006-12-19 18:46:56 -0700540 if (!shProg) {
Brian43975832007-01-04 08:21:09 -0700541 _mesa_error(ctx, GL_INVALID_VALUE, "glGetAttribLocation");
Brian5b01c5e2006-12-19 18:02:03 -0700542 return -1;
543 }
544
Brian65a18442006-12-19 18:46:56 -0700545 if (!shProg->LinkStatus) {
Brian5b01c5e2006-12-19 18:02:03 -0700546 _mesa_error(ctx, GL_INVALID_OPERATION,
547 "glGetAttribLocation(program not linked)");
548 return -1;
549 }
550
551 if (!name)
552 return -1;
553
Brian65a18442006-12-19 18:46:56 -0700554 if (shProg->Attributes) {
Brian3209c3e2007-01-09 17:49:24 -0700555 GLint i = _mesa_lookup_parameter_index(shProg->Attributes, -1, name);
556 if (i >= 0) {
Brian01a91eb2007-01-09 19:26:22 -0700557 return shProg->Attributes->Parameters[i].StateIndexes[0];
Brian5b01c5e2006-12-19 18:02:03 -0700558 }
559 }
560 return -1;
561}
562
563
564GLuint
565_mesa_get_handle(GLcontext *ctx, GLenum pname)
Brian34ae99d2006-12-18 08:28:54 -0700566{
567#if 0
568 GET_CURRENT_CONTEXT(ctx);
569
570 switch (pname) {
571 case GL_PROGRAM_OBJECT_ARB:
572 {
Brian5b01c5e2006-12-19 18:02:03 -0700573 struct gl2_program_intf **pro = ctx->Shader.CurrentProgram;
Brian34ae99d2006-12-18 08:28:54 -0700574
575 if (pro != NULL)
576 return (**pro)._container._generic.
577 GetName((struct gl2_generic_intf **) (pro));
578 }
579 break;
580 default:
581 _mesa_error(ctx, GL_INVALID_ENUM, "glGetHandleARB");
582 }
583#endif
584 return 0;
585}
586
587
Brian5b01c5e2006-12-19 18:02:03 -0700588void
589_mesa_get_programiv(GLcontext *ctx, GLuint program,
590 GLenum pname, GLint *params)
Brian34ae99d2006-12-18 08:28:54 -0700591{
Brian65a18442006-12-19 18:46:56 -0700592 struct gl_shader_program *shProg
593 = _mesa_lookup_shader_program(ctx, program);
Brian34ae99d2006-12-18 08:28:54 -0700594
Brian65a18442006-12-19 18:46:56 -0700595 if (!shProg) {
Brian5b01c5e2006-12-19 18:02:03 -0700596 _mesa_error(ctx, GL_INVALID_VALUE, "glGetProgramiv(program)");
Brian34ae99d2006-12-18 08:28:54 -0700597 return;
598 }
599
Brian5b01c5e2006-12-19 18:02:03 -0700600 switch (pname) {
601 case GL_DELETE_STATUS:
Brian65a18442006-12-19 18:46:56 -0700602 *params = shProg->DeletePending;
Brian5b01c5e2006-12-19 18:02:03 -0700603 break;
604 case GL_LINK_STATUS:
Brian65a18442006-12-19 18:46:56 -0700605 *params = shProg->LinkStatus;
Brian34ae99d2006-12-18 08:28:54 -0700606 break;
Brian5b01c5e2006-12-19 18:02:03 -0700607 case GL_VALIDATE_STATUS:
Brian65a18442006-12-19 18:46:56 -0700608 *params = shProg->Validated;
Brian5b01c5e2006-12-19 18:02:03 -0700609 break;
610 case GL_INFO_LOG_LENGTH:
Brian65a18442006-12-19 18:46:56 -0700611 *params = shProg->InfoLog ? strlen(shProg->InfoLog) : 0;
Brian5b01c5e2006-12-19 18:02:03 -0700612 break;
613 case GL_ATTACHED_SHADERS:
Brian65a18442006-12-19 18:46:56 -0700614 *params = shProg->NumShaders;
Brian5b01c5e2006-12-19 18:02:03 -0700615 break;
616 case GL_ACTIVE_ATTRIBUTES:
Brian3209c3e2007-01-09 17:49:24 -0700617 *params = shProg->Attributes ? shProg->Attributes->NumParameters : 0;
Brian5b01c5e2006-12-19 18:02:03 -0700618 break;
619 case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH:
Brian65a18442006-12-19 18:46:56 -0700620 *params = _mesa_parameter_longest_name(shProg->Attributes);
Brian5b01c5e2006-12-19 18:02:03 -0700621 break;
622 case GL_ACTIVE_UNIFORMS:
Brian65a18442006-12-19 18:46:56 -0700623 *params = shProg->Uniforms ? shProg->Uniforms->NumParameters : 0;
Brian5b01c5e2006-12-19 18:02:03 -0700624 break;
625 case GL_ACTIVE_UNIFORM_MAX_LENGTH:
Brian65a18442006-12-19 18:46:56 -0700626 *params = _mesa_parameter_longest_name(shProg->Uniforms);
Brian34ae99d2006-12-18 08:28:54 -0700627 break;
628 default:
Brian5b01c5e2006-12-19 18:02:03 -0700629 _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramiv(pname)");
630 return;
Brian34ae99d2006-12-18 08:28:54 -0700631 }
Brian5b01c5e2006-12-19 18:02:03 -0700632}
Brian34ae99d2006-12-18 08:28:54 -0700633
Brian34ae99d2006-12-18 08:28:54 -0700634
Brian5b01c5e2006-12-19 18:02:03 -0700635void
636_mesa_get_shaderiv(GLcontext *ctx, GLuint name, GLenum pname, GLint *params)
637{
Brian65a18442006-12-19 18:46:56 -0700638 struct gl_shader *shader = _mesa_lookup_shader(ctx, name);
Brian5b01c5e2006-12-19 18:02:03 -0700639
640 if (!shader) {
641 _mesa_error(ctx, GL_INVALID_VALUE, "glGetShaderiv(shader)");
642 return;
643 }
Brian65a18442006-12-19 18:46:56 -0700644
Brian5b01c5e2006-12-19 18:02:03 -0700645 switch (pname) {
646 case GL_SHADER_TYPE:
647 *params = shader->Type;
648 break;
649 case GL_DELETE_STATUS:
650 *params = shader->DeletePending;
651 break;
652 case GL_COMPILE_STATUS:
653 *params = shader->CompileStatus;
654 break;
655 case GL_INFO_LOG_LENGTH:
656 *params = shader->InfoLog ? strlen(shader->InfoLog) : 0;
657 break;
658 case GL_SHADER_SOURCE_LENGTH:
659 *params = shader->Source ? strlen((char *) shader->Source) : 0;
660 break;
661 default:
662 _mesa_error(ctx, GL_INVALID_ENUM, "glGetShaderiv(pname)");
663 return;
664 }
665}
666
667
668void
669_mesa_get_program_info_log(GLcontext *ctx, GLuint program, GLsizei bufSize,
670 GLsizei *length, GLchar *infoLog)
671{
Brian65a18442006-12-19 18:46:56 -0700672 struct gl_shader_program *shProg
673 = _mesa_lookup_shader_program(ctx, program);
674 if (!shProg) {
Brian5b01c5e2006-12-19 18:02:03 -0700675 _mesa_error(ctx, GL_INVALID_VALUE, "glGetProgramInfoLog(program)");
676 return;
677 }
Brian65a18442006-12-19 18:46:56 -0700678 copy_string(infoLog, bufSize, length, shProg->InfoLog);
Brian5b01c5e2006-12-19 18:02:03 -0700679}
680
681
682void
683_mesa_get_shader_info_log(GLcontext *ctx, GLuint shader, GLsizei bufSize,
684 GLsizei *length, GLchar *infoLog)
685{
Brian65a18442006-12-19 18:46:56 -0700686 struct gl_shader *sh = _mesa_lookup_shader(ctx, shader);
687 if (!sh) {
Brian5b01c5e2006-12-19 18:02:03 -0700688 _mesa_error(ctx, GL_INVALID_VALUE, "glGetShaderInfoLog(shader)");
689 return;
690 }
Brian65a18442006-12-19 18:46:56 -0700691 copy_string(infoLog, bufSize, length, sh->InfoLog);
Brian5b01c5e2006-12-19 18:02:03 -0700692}
693
694
695/**
696 * Called via ctx->Driver.GetShaderSource().
697 */
698void
699_mesa_get_shader_source(GLcontext *ctx, GLuint shader, GLsizei maxLength,
700 GLsizei *length, GLchar *sourceOut)
701{
Brian65a18442006-12-19 18:46:56 -0700702 struct gl_shader *sh = _mesa_lookup_shader(ctx, shader);
703 if (!sh) {
Brian5b01c5e2006-12-19 18:02:03 -0700704 _mesa_error(ctx, GL_INVALID_VALUE, "glGetShaderSource(shader)");
705 return;
706 }
Brian65a18442006-12-19 18:46:56 -0700707 copy_string(sourceOut, maxLength, length, sh->Source);
Brian5b01c5e2006-12-19 18:02:03 -0700708}
709
710
711/**
712 * Called via ctx->Driver.GetUniformfv().
713 */
714void
715_mesa_get_uniformfv(GLcontext *ctx, GLuint program, GLint location,
716 GLfloat *params)
717{
Brian65a18442006-12-19 18:46:56 -0700718 struct gl_shader_program *shProg
719 = _mesa_lookup_shader_program(ctx, program);
720 if (shProg) {
Brian223d7cb2007-01-23 16:37:51 -0700721 GLint i;
Brian65a18442006-12-19 18:46:56 -0700722 if (location >= 0 && location < shProg->Uniforms->NumParameters) {
723 for (i = 0; i < shProg->Uniforms->Parameters[location].Size; i++) {
724 params[i] = shProg->Uniforms->ParameterValues[location][i];
Brian5b01c5e2006-12-19 18:02:03 -0700725 }
726 }
727 else {
728 _mesa_error(ctx, GL_INVALID_VALUE, "glGetUniformfv(location)");
729 }
730 }
731 else {
Brian43975832007-01-04 08:21:09 -0700732 _mesa_error(ctx, GL_INVALID_VALUE, "glGetUniformfv(program)");
Brian5b01c5e2006-12-19 18:02:03 -0700733 }
734}
735
736
737/**
738 * Called via ctx->Driver.GetUniformLocation().
739 */
740GLint
741_mesa_get_uniform_location(GLcontext *ctx, GLuint program, const GLchar *name)
742{
Brian71623982007-01-30 16:55:03 -0700743 struct gl_shader_program *shProg
744 = _mesa_lookup_shader_program(ctx, program);
745 if (shProg) {
Brian5b01c5e2006-12-19 18:02:03 -0700746 GLuint loc;
Brian65a18442006-12-19 18:46:56 -0700747 for (loc = 0; loc < shProg->Uniforms->NumParameters; loc++) {
Brian5b01c5e2006-12-19 18:02:03 -0700748 const struct gl_program_parameter *u
Brian65a18442006-12-19 18:46:56 -0700749 = shProg->Uniforms->Parameters + loc;
Brian29053852006-12-21 11:21:26 -0700750 /* XXX this is a temporary simplification / short-cut.
751 * We need to handle things like "e.c[0].b" as seen in the
752 * GLSL orange book, page 189.
753 */
Brian5cf73262007-01-05 16:02:45 -0700754 if ((u->Type == PROGRAM_UNIFORM ||
755 u->Type == PROGRAM_SAMPLER) && !strcmp(u->Name, name)) {
Brian5b01c5e2006-12-19 18:02:03 -0700756 return loc;
757 }
758 }
759 }
760 return -1;
761
762}
763
764
765GLboolean
766_mesa_is_program(GLcontext *ctx, GLuint name)
767{
Brian65a18442006-12-19 18:46:56 -0700768 struct gl_shader_program *shProg = _mesa_lookup_shader_program(ctx, name);
769 return shProg ? GL_TRUE : GL_FALSE;
Brian5b01c5e2006-12-19 18:02:03 -0700770}
771
772
773GLboolean
774_mesa_is_shader(GLcontext *ctx, GLuint name)
775{
Brian65a18442006-12-19 18:46:56 -0700776 struct gl_shader *shader = _mesa_lookup_shader(ctx, name);
Brian5b01c5e2006-12-19 18:02:03 -0700777 return shader ? GL_TRUE : GL_FALSE;
Brian34ae99d2006-12-18 08:28:54 -0700778}
779
780
781
Brian5b01c5e2006-12-19 18:02:03 -0700782/**
783 * Called via ctx->Driver.ShaderSource()
784 */
785void
786_mesa_shader_source(GLcontext *ctx, GLuint shader, const GLchar *source)
Brian34ae99d2006-12-18 08:28:54 -0700787{
Brian65a18442006-12-19 18:46:56 -0700788 struct gl_shader *sh = _mesa_lookup_shader(ctx, shader);
789 if (!sh) {
Brian5b01c5e2006-12-19 18:02:03 -0700790 _mesa_error(ctx, GL_INVALID_VALUE, "glShaderSource(shaderObj)");
Brian34ae99d2006-12-18 08:28:54 -0700791 return;
792 }
793
Brian34ae99d2006-12-18 08:28:54 -0700794 /* free old shader source string and install new one */
Brian65a18442006-12-19 18:46:56 -0700795 if (sh->Source) {
796 _mesa_free((void *) sh->Source);
Brian34ae99d2006-12-18 08:28:54 -0700797 }
Brian65a18442006-12-19 18:46:56 -0700798 sh->Source = source;
Brian9e4bae92006-12-20 09:27:42 -0700799 sh->CompileStatus = GL_FALSE;
Brian34ae99d2006-12-18 08:28:54 -0700800}
801
802
Brian5b01c5e2006-12-19 18:02:03 -0700803/**
804 * Called via ctx->Driver.CompileShader()
805 */
806void
807_mesa_compile_shader(GLcontext *ctx, GLuint shaderObj)
Brian34ae99d2006-12-18 08:28:54 -0700808{
Brian65a18442006-12-19 18:46:56 -0700809 struct gl_shader *sh = _mesa_lookup_shader(ctx, shaderObj);
Brian34ae99d2006-12-18 08:28:54 -0700810
Brian65a18442006-12-19 18:46:56 -0700811 if (!sh) {
Brian34ae99d2006-12-18 08:28:54 -0700812 _mesa_error(ctx, GL_INVALID_VALUE, "glCompileShader(shaderObj)");
813 return;
814 }
815
Brian43975832007-01-04 08:21:09 -0700816 sh->CompileStatus = _slang_compile(ctx, sh);
Brian34ae99d2006-12-18 08:28:54 -0700817}
818
819
Brian5b01c5e2006-12-19 18:02:03 -0700820/**
821 * Called via ctx->Driver.LinkProgram()
822 */
823void
824_mesa_link_program(GLcontext *ctx, GLuint program)
Brian34ae99d2006-12-18 08:28:54 -0700825{
Brian65a18442006-12-19 18:46:56 -0700826 struct gl_shader_program *shProg;
Brian34ae99d2006-12-18 08:28:54 -0700827
Brian65a18442006-12-19 18:46:56 -0700828 shProg = _mesa_lookup_shader_program(ctx, program);
829 if (!shProg) {
Brian43975832007-01-04 08:21:09 -0700830 _mesa_error(ctx, GL_INVALID_VALUE, "glLinkProgram(program)");
Brian34ae99d2006-12-18 08:28:54 -0700831 return;
832 }
833
Brianc1771912007-02-16 09:56:19 -0700834 _slang_link(ctx, program, shProg);
Brian34ae99d2006-12-18 08:28:54 -0700835}
836
837
838/**
Brian5b01c5e2006-12-19 18:02:03 -0700839 * Called via ctx->Driver.UseProgram()
Brian34ae99d2006-12-18 08:28:54 -0700840 */
Brian5b01c5e2006-12-19 18:02:03 -0700841void
842_mesa_use_program(GLcontext *ctx, GLuint program)
Brian34ae99d2006-12-18 08:28:54 -0700843{
Brian00d63aa2007-02-03 11:35:02 -0700844 if (ctx->Shader.CurrentProgram &&
845 ctx->Shader.CurrentProgram->Name == program) {
846 /* no-op */
847 return;
848 }
849
850 FLUSH_VERTICES(ctx, _NEW_PROGRAM);
851
Brian9e4bae92006-12-20 09:27:42 -0700852 /* unbind old */
853 if (ctx->Shader.CurrentProgram) {
854 ctx->Shader.CurrentProgram->RefCount--;
855 if (ctx->Shader.CurrentProgram->RefCount <= 0) {
856 _mesa_free_shader_program(ctx, ctx->Shader.CurrentProgram);
857 }
858 ctx->Shader.CurrentProgram = NULL;
859 }
860
Brian5b01c5e2006-12-19 18:02:03 -0700861 if (program) {
Brian65a18442006-12-19 18:46:56 -0700862 struct gl_shader_program *shProg;
863 shProg = _mesa_lookup_shader_program(ctx, program);
864 if (!shProg) {
Brian43975832007-01-04 08:21:09 -0700865 _mesa_error(ctx, GL_INVALID_VALUE,
Brian5b01c5e2006-12-19 18:02:03 -0700866 "glUseProgramObjectARB(programObj)");
867 return;
868 }
Brian65a18442006-12-19 18:46:56 -0700869 ctx->Shader.CurrentProgram = shProg;
Brian9e4bae92006-12-20 09:27:42 -0700870 shProg->RefCount++;
Brian5b01c5e2006-12-19 18:02:03 -0700871 }
872 else {
873 /* don't use a shader program */
874 ctx->Shader.CurrentProgram = NULL;
875 }
876}
Brian34ae99d2006-12-18 08:28:54 -0700877
Brian5b01c5e2006-12-19 18:02:03 -0700878
879/**
880 * Called via ctx->Driver.Uniform().
881 */
882void
883_mesa_uniform(GLcontext *ctx, GLint location, GLsizei count,
884 const GLvoid *values, GLenum type)
885{
Brian3a8e2772006-12-20 17:19:16 -0700886 struct gl_shader_program *shProg = ctx->Shader.CurrentProgram;
Brian89dc4852007-01-04 14:35:44 -0700887 GLfloat *uniformVal;
Brian3a8e2772006-12-20 17:19:16 -0700888
889 if (!shProg || !shProg->LinkStatus) {
Brian5b01c5e2006-12-19 18:02:03 -0700890 _mesa_error(ctx, GL_INVALID_OPERATION, "glUniform(program not linked)");
Brian3a8e2772006-12-20 17:19:16 -0700891 return;
892 }
893
Brian223d7cb2007-01-23 16:37:51 -0700894 if (location < 0 || location >= (GLint) shProg->Uniforms->NumParameters) {
Brian3a8e2772006-12-20 17:19:16 -0700895 _mesa_error(ctx, GL_INVALID_VALUE, "glUniform(location)");
896 return;
897 }
898
899 FLUSH_VERTICES(ctx, _NEW_PROGRAM);
900
Brianfee9bbe2007-02-02 18:05:43 -0700901 /*
902 * If we're setting a sampler, we must use glUniformi1()!
903 */
904 if (shProg->Uniforms->Parameters[location].Type == PROGRAM_SAMPLER) {
905 if (type != GL_INT || count != 1) {
906 _mesa_error(ctx, GL_INVALID_OPERATION,
907 "glUniform(only glUniform1i can be used "
908 "to set sampler uniforms)");
909 return;
910 }
911 }
912
Brian89dc4852007-01-04 14:35:44 -0700913 uniformVal = shProg->Uniforms->ParameterValues[location];
Brian3a8e2772006-12-20 17:19:16 -0700914
Brianfee9bbe2007-02-02 18:05:43 -0700915 /* XXX obey 'count' parameter! */
916
Brian89dc4852007-01-04 14:35:44 -0700917 if (type == GL_INT ||
918 type == GL_INT_VEC2 ||
919 type == GL_INT_VEC3 ||
920 type == GL_INT_VEC4) {
921 const GLint *iValues = (const GLint *) values;
922 switch (type) {
923 case GL_INT_VEC4:
924 uniformVal[3] = (GLfloat) iValues[3];
925 /* fall-through */
926 case GL_INT_VEC3:
927 uniformVal[2] = (GLfloat) iValues[2];
928 /* fall-through */
929 case GL_INT_VEC2:
930 uniformVal[1] = (GLfloat) iValues[1];
931 /* fall-through */
932 case GL_INT:
933 uniformVal[0] = (GLfloat) iValues[0];
934 break;
935 default:
936 _mesa_problem(ctx, "Invalid type in _mesa_uniform");
937 return;
938 }
939 }
940 else {
Brian8a48f352007-01-10 12:18:50 -0700941 const GLfloat *fValues = (const GLfloat *) values;
Brian89dc4852007-01-04 14:35:44 -0700942 switch (type) {
943 case GL_FLOAT_VEC4:
944 uniformVal[3] = fValues[3];
945 /* fall-through */
946 case GL_FLOAT_VEC3:
947 uniformVal[2] = fValues[2];
948 /* fall-through */
949 case GL_FLOAT_VEC2:
950 uniformVal[1] = fValues[1];
951 /* fall-through */
952 case GL_FLOAT:
953 uniformVal[0] = fValues[0];
954 break;
955 default:
956 _mesa_problem(ctx, "Invalid type in _mesa_uniform");
957 return;
958 }
Brian5b01c5e2006-12-19 18:02:03 -0700959 }
Brian5cf73262007-01-05 16:02:45 -0700960
961 if (shProg->Uniforms->Parameters[location].Type == PROGRAM_SAMPLER) {
962 _slang_resolve_samplers(shProg, &shProg->VertexProgram->Base);
963 _slang_resolve_samplers(shProg, &shProg->FragmentProgram->Base);
964 FLUSH_VERTICES(ctx, _NEW_TEXTURE);
965 }
Brian34ae99d2006-12-18 08:28:54 -0700966}
967
968
969/**
Brian5b01c5e2006-12-19 18:02:03 -0700970 * Called by ctx->Driver.UniformMatrix().
Brian34ae99d2006-12-18 08:28:54 -0700971 */
Brian5b01c5e2006-12-19 18:02:03 -0700972void
973_mesa_uniform_matrix(GLcontext *ctx, GLint cols, GLint rows,
974 GLenum matrixType, GLint location, GLsizei count,
975 GLboolean transpose, const GLfloat *values)
Brian34ae99d2006-12-18 08:28:54 -0700976{
Brian3a8e2772006-12-20 17:19:16 -0700977 struct gl_shader_program *shProg = ctx->Shader.CurrentProgram;
978 if (!shProg || !shProg->LinkStatus) {
979 _mesa_error(ctx, GL_INVALID_OPERATION,
980 "glUniformMatrix(program not linked)");
981 return;
982 }
983 if (location < 0 || location >= shProg->Uniforms->NumParameters) {
984 _mesa_error(ctx, GL_INVALID_VALUE, "glUniformMatrix(location)");
985 return;
986 }
Brian34ae99d2006-12-18 08:28:54 -0700987 if (values == NULL) {
Brian3a8e2772006-12-20 17:19:16 -0700988 _mesa_error(ctx, GL_INVALID_VALUE, "glUniformMatrix");
Brian34ae99d2006-12-18 08:28:54 -0700989 return;
990 }
991
992 FLUSH_VERTICES(ctx, _NEW_PROGRAM);
993
Brian3a8e2772006-12-20 17:19:16 -0700994 /*
995 * Note: the _columns_ of a matrix are stored in program registers, not
996 * the rows.
997 */
998 /* XXXX need to test 3x3 and 2x2 matrices... */
Brian34ae99d2006-12-18 08:28:54 -0700999 if (transpose) {
Brian3a8e2772006-12-20 17:19:16 -07001000 GLuint row, col;
1001 for (col = 0; col < cols; col++) {
1002 GLfloat *v = shProg->Uniforms->ParameterValues[location + col];
1003 for (row = 0; row < rows; row++) {
1004 v[row] = values[col * rows + row];
Brian34ae99d2006-12-18 08:28:54 -07001005 }
Brian34ae99d2006-12-18 08:28:54 -07001006 }
Brian34ae99d2006-12-18 08:28:54 -07001007 }
1008 else {
Brian3a8e2772006-12-20 17:19:16 -07001009 GLuint row, col;
1010 for (col = 0; col < cols; col++) {
1011 GLfloat *v = shProg->Uniforms->ParameterValues[location + col];
1012 for (row = 0; row < rows; row++) {
1013 v[row] = values[row * cols + col];
1014 }
1015 }
Brian34ae99d2006-12-18 08:28:54 -07001016 }
1017}
1018
1019
Brian5b01c5e2006-12-19 18:02:03 -07001020void
1021_mesa_validate_program(GLcontext *ctx, GLuint program)
Brian34ae99d2006-12-18 08:28:54 -07001022{
Brian65a18442006-12-19 18:46:56 -07001023 struct gl_shader_program *shProg;
1024 shProg = _mesa_lookup_shader_program(ctx, program);
1025 if (!shProg) {
Brian43975832007-01-04 08:21:09 -07001026 _mesa_error(ctx, GL_INVALID_VALUE, "glValidateProgram(program)");
Brian34ae99d2006-12-18 08:28:54 -07001027 return;
1028 }
Brian5b01c5e2006-12-19 18:02:03 -07001029 /* XXX temporary */
Brian65a18442006-12-19 18:46:56 -07001030 shProg->Validated = GL_TRUE;
Brian34ae99d2006-12-18 08:28:54 -07001031
Brian5b01c5e2006-12-19 18:02:03 -07001032 /* From the GL spec:
1033 any two active samplers in the current program object are of
1034 different types, but refer to the same texture image unit,
1035
1036 any active sampler in the current program object refers to a texture
1037 image unit where fixed-function fragment processing accesses a
1038 texture target that does not match the sampler type, or
1039
1040 the sum of the number of active samplers in the program and the
1041 number of texture image units enabled for fixed-function fragment
1042 processing exceeds the combined limit on the total number of texture
1043 image units allowed.
1044 */
Brian34ae99d2006-12-18 08:28:54 -07001045}