blob: 842960099ea21898a95cb2c57741da4ee250dae7 [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{
202 ctx->Shader._FragmentShaderPresent = GL_FALSE;
203 ctx->Shader._VertexShaderPresent = GL_FALSE;
204}
205
206
207
Brian34ae99d2006-12-18 08:28:54 -0700208
Brian5b01c5e2006-12-19 18:02:03 -0700209
210/**
211 * Copy string from <src> to <dst>, up to maxLength characters, returning
212 * length of <dst> in <length>.
213 * \param src the strings source
214 * \param maxLength max chars to copy
215 * \param length returns number of chars copied
216 * \param dst the string destination
217 */
218static void
219copy_string(GLchar *dst, GLsizei maxLength, GLsizei *length, const GLchar *src)
220{
221 GLsizei len;
222 for (len = 0; len < maxLength - 1 && src && src[len]; len++)
223 dst[len] = src[len];
224 if (maxLength > 0)
225 dst[len] = 0;
226 if (length)
227 *length = len;
228}
229
230
231
232
233/**
234 * Called via ctx->Driver.AttachShader()
235 */
236void
237_mesa_attach_shader(GLcontext *ctx, GLuint program, GLuint shader)
238{
Brian65a18442006-12-19 18:46:56 -0700239 struct gl_shader_program *shProg
240 = _mesa_lookup_shader_program(ctx, program);
241 struct gl_shader *sh = _mesa_lookup_shader(ctx, shader);
242 const GLuint n = shProg->NumShaders;
Brian5b01c5e2006-12-19 18:02:03 -0700243 GLuint i;
244
Brian65a18442006-12-19 18:46:56 -0700245 if (!shProg || !sh) {
Brian43975832007-01-04 08:21:09 -0700246 _mesa_error(ctx, GL_INVALID_VALUE,
Brian5b01c5e2006-12-19 18:02:03 -0700247 "glAttachShader(bad program or shader name)");
248 return;
249 }
250
251 for (i = 0; i < n; i++) {
Brian65a18442006-12-19 18:46:56 -0700252 if (shProg->Shaders[i] == sh) {
Brian5b01c5e2006-12-19 18:02:03 -0700253 /* already attached */
254 return;
Brian34ae99d2006-12-18 08:28:54 -0700255 }
256 }
Brian5b01c5e2006-12-19 18:02:03 -0700257
258 /* grow list */
Brian65a18442006-12-19 18:46:56 -0700259 shProg->Shaders = (struct gl_shader **)
260 _mesa_realloc(shProg->Shaders,
261 n * sizeof(struct gl_shader *),
262 (n + 1) * sizeof(struct gl_shader *));
263 if (!shProg->Shaders) {
Brian5b01c5e2006-12-19 18:02:03 -0700264 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glAttachShader");
265 return;
266 }
267
268 /* append */
Brian65a18442006-12-19 18:46:56 -0700269 shProg->Shaders[n] = sh;
270 sh->RefCount++;
271 shProg->NumShaders++;
Brian5b01c5e2006-12-19 18:02:03 -0700272}
273
274
275void
276_mesa_bind_attrib_location(GLcontext *ctx, GLuint program, GLuint index,
277 const GLchar *name)
278{
Brian65a18442006-12-19 18:46:56 -0700279 struct gl_shader_program *shProg
280 = _mesa_lookup_shader_program(ctx, program);
Brianb7978af2007-01-09 19:17:17 -0700281 const GLint size = -1; /* unknown size */
282 GLint i, oldIndex;
Brian5b01c5e2006-12-19 18:02:03 -0700283
Brian65a18442006-12-19 18:46:56 -0700284 if (!shProg) {
Brian43975832007-01-04 08:21:09 -0700285 _mesa_error(ctx, GL_INVALID_VALUE, "glBindAttribLocation(program)");
Brian5b01c5e2006-12-19 18:02:03 -0700286 return;
287 }
288
Brian9e4bae92006-12-20 09:27:42 -0700289 if (!name)
290 return;
291
292 if (strncmp(name, "gl_", 3) == 0) {
293 _mesa_error(ctx, GL_INVALID_OPERATION,
294 "glBindAttribLocation(illegal name)");
295 return;
296 }
297
Brian3209c3e2007-01-09 17:49:24 -0700298 oldIndex = _mesa_get_attrib_location(ctx, program, name);
299
300 /* this will replace the current value if it's already in the list */
Brianb7978af2007-01-09 19:17:17 -0700301 i = _mesa_add_attribute(shProg->Attributes, name, size, index);
Brian3209c3e2007-01-09 17:49:24 -0700302 if (i < 0) {
303 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBindAttribLocation");
304 }
305
306 if (shProg->VertexProgram && oldIndex >= 0) {
307 _slang_remap_attribute(&shProg->VertexProgram->Base, oldIndex, index);
308 }
309
Brian88e2dbf2007-01-10 13:33:38 -0700310#if 0
Brian3209c3e2007-01-09 17:49:24 -0700311 printf("===== post BindAttrib:\n");
312 _mesa_print_program(&shProg->VertexProgram->Base);
Brian88e2dbf2007-01-10 13:33:38 -0700313#endif
Brian34ae99d2006-12-18 08:28:54 -0700314}
315
316
Brian5b01c5e2006-12-19 18:02:03 -0700317GLuint
318_mesa_create_shader(GLcontext *ctx, GLenum type)
319{
Brian65a18442006-12-19 18:46:56 -0700320 struct gl_shader *sh;
Brian5b01c5e2006-12-19 18:02:03 -0700321 GLuint name;
322
323 name = _mesa_HashFindFreeKeyBlock(ctx->Shared->ShaderObjects, 1);
324
325 switch (type) {
Brian65a18442006-12-19 18:46:56 -0700326 case GL_FRAGMENT_SHADER:
327 case GL_VERTEX_SHADER:
328 sh = _mesa_new_shader(ctx, name, type);
Brian5b01c5e2006-12-19 18:02:03 -0700329 break;
330 default:
331 _mesa_error(ctx, GL_INVALID_ENUM, "CreateShader(type)");
332 return 0;
333 }
334
Brian65a18442006-12-19 18:46:56 -0700335 _mesa_HashInsert(ctx->Shared->ShaderObjects, name, sh);
Brian5b01c5e2006-12-19 18:02:03 -0700336
337 return name;
338}
339
340
341GLuint
342_mesa_create_program(GLcontext *ctx)
343{
344 GLuint name;
Brian65a18442006-12-19 18:46:56 -0700345 struct gl_shader_program *shProg;
Brian5b01c5e2006-12-19 18:02:03 -0700346
Brian65a18442006-12-19 18:46:56 -0700347 name = _mesa_HashFindFreeKeyBlock(ctx->Shared->ShaderObjects, 1);
348 shProg = _mesa_new_shader_program(ctx, name);
Brian5b01c5e2006-12-19 18:02:03 -0700349
Brian65a18442006-12-19 18:46:56 -0700350 _mesa_HashInsert(ctx->Shared->ShaderObjects, name, shProg);
Brian5b01c5e2006-12-19 18:02:03 -0700351
352 return name;
353}
354
355
356void
357_mesa_delete_program2(GLcontext *ctx, GLuint name)
358{
Brian65a18442006-12-19 18:46:56 -0700359 struct gl_shader_program *shProg;
Brian5b01c5e2006-12-19 18:02:03 -0700360
Brian65a18442006-12-19 18:46:56 -0700361 shProg = _mesa_lookup_shader_program(ctx, name);
362 if (!shProg) {
Brian43975832007-01-04 08:21:09 -0700363 _mesa_error(ctx, GL_INVALID_VALUE, "glDeleteProgram(name)");
Brian5b01c5e2006-12-19 18:02:03 -0700364 return;
365 }
366
Brian9e4bae92006-12-20 09:27:42 -0700367 /* always remove from hash table */
Brian65a18442006-12-19 18:46:56 -0700368 _mesa_HashRemove(ctx->Shared->ShaderObjects, name);
Brian9e4bae92006-12-20 09:27:42 -0700369
370 shProg->DeletePending = GL_TRUE;
371
372 /* decrement refcount, delete if zero */
373 shProg->RefCount--;
374 if (shProg->RefCount <= 0) {
375 _mesa_free_shader_program(ctx, shProg);
376 }
Brian5b01c5e2006-12-19 18:02:03 -0700377}
378
379
380void
381_mesa_delete_shader(GLcontext *ctx, GLuint shader)
382{
Brian9e4bae92006-12-20 09:27:42 -0700383 struct gl_shader *sh = _mesa_lookup_shader(ctx, shader);
384 if (!sh) {
385 return;
386 }
Brian5b01c5e2006-12-19 18:02:03 -0700387
Brian9e4bae92006-12-20 09:27:42 -0700388 sh->DeletePending = GL_TRUE;
389 sh->RefCount--;
390 if (sh->RefCount <= 0) {
391 _mesa_free_shader(ctx, sh);
392 }
Brian5b01c5e2006-12-19 18:02:03 -0700393}
394
395
396void
397_mesa_detach_shader(GLcontext *ctx, GLuint program, GLuint shader)
398{
Brian65a18442006-12-19 18:46:56 -0700399 struct gl_shader_program *shProg
400 = _mesa_lookup_shader_program(ctx, program);
401 const GLuint n = shProg->NumShaders;
Brian5b01c5e2006-12-19 18:02:03 -0700402 GLuint i, j;
403
Brian65a18442006-12-19 18:46:56 -0700404 if (!shProg) {
Brian43975832007-01-04 08:21:09 -0700405 _mesa_error(ctx, GL_INVALID_VALUE,
Brian5b01c5e2006-12-19 18:02:03 -0700406 "glDetachShader(bad program or shader name)");
407 return;
408 }
409
410 for (i = 0; i < n; i++) {
Brian65a18442006-12-19 18:46:56 -0700411 if (shProg->Shaders[i]->Name == shader) {
412 struct gl_shader **newList;
Brian5b01c5e2006-12-19 18:02:03 -0700413 /* found it */
Brian9e4bae92006-12-20 09:27:42 -0700414
415 shProg->Shaders[i]->RefCount--;
416
Brian5b01c5e2006-12-19 18:02:03 -0700417 /* alloc new, smaller array */
Brian65a18442006-12-19 18:46:56 -0700418 newList = (struct gl_shader **)
419 _mesa_malloc((n - 1) * sizeof(struct gl_shader *));
Brian5b01c5e2006-12-19 18:02:03 -0700420 if (!newList) {
421 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glDetachShader");
422 return;
423 }
424 for (j = 0; j < i; j++) {
Brian65a18442006-12-19 18:46:56 -0700425 newList[j] = shProg->Shaders[j];
Brian5b01c5e2006-12-19 18:02:03 -0700426 }
427 while (++i < n)
Brian65a18442006-12-19 18:46:56 -0700428 newList[j++] = shProg->Shaders[i];
429 _mesa_free(shProg->Shaders);
Brian5b01c5e2006-12-19 18:02:03 -0700430
431 /* XXX refcounting! */
432
Brian65a18442006-12-19 18:46:56 -0700433 shProg->Shaders = newList;
Brian5b01c5e2006-12-19 18:02:03 -0700434 return;
435 }
436 }
437
438 /* not found */
Brian43975832007-01-04 08:21:09 -0700439 _mesa_error(ctx, GL_INVALID_VALUE,
Brian5b01c5e2006-12-19 18:02:03 -0700440 "glDetachShader(shader not found)");
441}
442
443
444void
445_mesa_get_active_attrib(GLcontext *ctx, GLuint program, GLuint index,
446 GLsizei maxLength, GLsizei *length, GLint *size,
447 GLenum *type, GLchar *nameOut)
448{
449 static const GLenum vec_types[] = {
450 GL_FLOAT, GL_FLOAT_VEC2, GL_FLOAT_VEC3, GL_FLOAT_VEC4
451 };
Brian65a18442006-12-19 18:46:56 -0700452 struct gl_shader_program *shProg
453 = _mesa_lookup_shader_program(ctx, program);
Brian5b01c5e2006-12-19 18:02:03 -0700454 GLint sz;
455
Brian65a18442006-12-19 18:46:56 -0700456 if (!shProg) {
Brian43975832007-01-04 08:21:09 -0700457 _mesa_error(ctx, GL_INVALID_VALUE, "glGetActiveUniform");
Brian5b01c5e2006-12-19 18:02:03 -0700458 return;
459 }
460
Brian65a18442006-12-19 18:46:56 -0700461 if (!shProg->Attributes || index >= shProg->Attributes->NumParameters) {
Brian5b01c5e2006-12-19 18:02:03 -0700462 _mesa_error(ctx, GL_INVALID_VALUE, "glGetActiveUniform(index)");
463 return;
464 }
465
466 copy_string(nameOut, maxLength, length,
Brian65a18442006-12-19 18:46:56 -0700467 shProg->Attributes->Parameters[index].Name);
468 sz = shProg->Attributes->Parameters[index].Size;
Brian5b01c5e2006-12-19 18:02:03 -0700469 if (size)
470 *size = sz;
471 if (type)
472 *type = vec_types[sz]; /* XXX this is a temporary hack */
473}
474
475
476/**
477 * Called via ctx->Driver.GetActiveUniform().
478 */
479void
480_mesa_get_active_uniform(GLcontext *ctx, GLuint program, GLuint index,
481 GLsizei maxLength, GLsizei *length, GLint *size,
482 GLenum *type, GLchar *nameOut)
483{
484 static const GLenum vec_types[] = {
485 GL_FLOAT, GL_FLOAT_VEC2, GL_FLOAT_VEC3, GL_FLOAT_VEC4
486 };
Brian65a18442006-12-19 18:46:56 -0700487 struct gl_shader_program *shProg
488 = _mesa_lookup_shader_program(ctx, program);
Brian5b01c5e2006-12-19 18:02:03 -0700489 GLint sz;
490
Brian65a18442006-12-19 18:46:56 -0700491 if (!shProg) {
Brian43975832007-01-04 08:21:09 -0700492 _mesa_error(ctx, GL_INVALID_VALUE, "glGetActiveUniform");
Brian5b01c5e2006-12-19 18:02:03 -0700493 return;
494 }
495
Brian65a18442006-12-19 18:46:56 -0700496 if (!shProg->Uniforms || index >= shProg->Uniforms->NumParameters) {
Brian5b01c5e2006-12-19 18:02:03 -0700497 _mesa_error(ctx, GL_INVALID_VALUE, "glGetActiveUniform(index)");
498 return;
499 }
500
501 copy_string(nameOut, maxLength, length,
Brian65a18442006-12-19 18:46:56 -0700502 shProg->Uniforms->Parameters[index].Name);
503 sz = shProg->Uniforms->Parameters[index].Size;
Brian5b01c5e2006-12-19 18:02:03 -0700504 if (size)
505 *size = sz;
506 if (type)
507 *type = vec_types[sz]; /* XXX this is a temporary hack */
508}
509
510
511/**
512 * Called via ctx->Driver.GetAttachedShaders().
513 */
514void
515_mesa_get_attached_shaders(GLcontext *ctx, GLuint program, GLsizei maxCount,
516 GLsizei *count, GLuint *obj)
517{
Brian65a18442006-12-19 18:46:56 -0700518 struct gl_shader_program *shProg
519 = _mesa_lookup_shader_program(ctx, program);
520 if (shProg) {
Brian223d7cb2007-01-23 16:37:51 -0700521 GLint i;
Brian65a18442006-12-19 18:46:56 -0700522 for (i = 0; i < maxCount && i < shProg->NumShaders; i++) {
523 obj[i] = shProg->Shaders[i]->Name;
Brian5b01c5e2006-12-19 18:02:03 -0700524 }
525 if (count)
526 *count = i;
527 }
528 else {
Brian43975832007-01-04 08:21:09 -0700529 _mesa_error(ctx, GL_INVALID_VALUE, "glGetAttachedShaders");
Brian5b01c5e2006-12-19 18:02:03 -0700530 }
531}
532
533
534GLint
535_mesa_get_attrib_location(GLcontext *ctx, GLuint program,
536 const GLchar *name)
537{
Brian65a18442006-12-19 18:46:56 -0700538 struct gl_shader_program *shProg
539 = _mesa_lookup_shader_program(ctx, program);
Brian5b01c5e2006-12-19 18:02:03 -0700540
Brian65a18442006-12-19 18:46:56 -0700541 if (!shProg) {
Brian43975832007-01-04 08:21:09 -0700542 _mesa_error(ctx, GL_INVALID_VALUE, "glGetAttribLocation");
Brian5b01c5e2006-12-19 18:02:03 -0700543 return -1;
544 }
545
Brian65a18442006-12-19 18:46:56 -0700546 if (!shProg->LinkStatus) {
Brian5b01c5e2006-12-19 18:02:03 -0700547 _mesa_error(ctx, GL_INVALID_OPERATION,
548 "glGetAttribLocation(program not linked)");
549 return -1;
550 }
551
552 if (!name)
553 return -1;
554
Brian65a18442006-12-19 18:46:56 -0700555 if (shProg->Attributes) {
Brian3209c3e2007-01-09 17:49:24 -0700556 GLint i = _mesa_lookup_parameter_index(shProg->Attributes, -1, name);
557 if (i >= 0) {
Brian01a91eb2007-01-09 19:26:22 -0700558 return shProg->Attributes->Parameters[i].StateIndexes[0];
Brian5b01c5e2006-12-19 18:02:03 -0700559 }
560 }
561 return -1;
562}
563
564
565GLuint
566_mesa_get_handle(GLcontext *ctx, GLenum pname)
Brian34ae99d2006-12-18 08:28:54 -0700567{
568#if 0
569 GET_CURRENT_CONTEXT(ctx);
570
571 switch (pname) {
572 case GL_PROGRAM_OBJECT_ARB:
573 {
Brian5b01c5e2006-12-19 18:02:03 -0700574 struct gl2_program_intf **pro = ctx->Shader.CurrentProgram;
Brian34ae99d2006-12-18 08:28:54 -0700575
576 if (pro != NULL)
577 return (**pro)._container._generic.
578 GetName((struct gl2_generic_intf **) (pro));
579 }
580 break;
581 default:
582 _mesa_error(ctx, GL_INVALID_ENUM, "glGetHandleARB");
583 }
584#endif
585 return 0;
586}
587
588
Brian5b01c5e2006-12-19 18:02:03 -0700589void
590_mesa_get_programiv(GLcontext *ctx, GLuint program,
591 GLenum pname, GLint *params)
Brian34ae99d2006-12-18 08:28:54 -0700592{
Brian65a18442006-12-19 18:46:56 -0700593 struct gl_shader_program *shProg
594 = _mesa_lookup_shader_program(ctx, program);
Brian34ae99d2006-12-18 08:28:54 -0700595
Brian65a18442006-12-19 18:46:56 -0700596 if (!shProg) {
Brian5b01c5e2006-12-19 18:02:03 -0700597 _mesa_error(ctx, GL_INVALID_VALUE, "glGetProgramiv(program)");
Brian34ae99d2006-12-18 08:28:54 -0700598 return;
599 }
600
Brian5b01c5e2006-12-19 18:02:03 -0700601 switch (pname) {
602 case GL_DELETE_STATUS:
Brian65a18442006-12-19 18:46:56 -0700603 *params = shProg->DeletePending;
Brian5b01c5e2006-12-19 18:02:03 -0700604 break;
605 case GL_LINK_STATUS:
Brian65a18442006-12-19 18:46:56 -0700606 *params = shProg->LinkStatus;
Brian34ae99d2006-12-18 08:28:54 -0700607 break;
Brian5b01c5e2006-12-19 18:02:03 -0700608 case GL_VALIDATE_STATUS:
Brian65a18442006-12-19 18:46:56 -0700609 *params = shProg->Validated;
Brian5b01c5e2006-12-19 18:02:03 -0700610 break;
611 case GL_INFO_LOG_LENGTH:
Brian65a18442006-12-19 18:46:56 -0700612 *params = shProg->InfoLog ? strlen(shProg->InfoLog) : 0;
Brian5b01c5e2006-12-19 18:02:03 -0700613 break;
614 case GL_ATTACHED_SHADERS:
Brian65a18442006-12-19 18:46:56 -0700615 *params = shProg->NumShaders;
Brian5b01c5e2006-12-19 18:02:03 -0700616 break;
617 case GL_ACTIVE_ATTRIBUTES:
Brian3209c3e2007-01-09 17:49:24 -0700618 *params = shProg->Attributes ? shProg->Attributes->NumParameters : 0;
Brian5b01c5e2006-12-19 18:02:03 -0700619 break;
620 case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH:
Brian65a18442006-12-19 18:46:56 -0700621 *params = _mesa_parameter_longest_name(shProg->Attributes);
Brian5b01c5e2006-12-19 18:02:03 -0700622 break;
623 case GL_ACTIVE_UNIFORMS:
Brian65a18442006-12-19 18:46:56 -0700624 *params = shProg->Uniforms ? shProg->Uniforms->NumParameters : 0;
Brian5b01c5e2006-12-19 18:02:03 -0700625 break;
626 case GL_ACTIVE_UNIFORM_MAX_LENGTH:
Brian65a18442006-12-19 18:46:56 -0700627 *params = _mesa_parameter_longest_name(shProg->Uniforms);
Brian34ae99d2006-12-18 08:28:54 -0700628 break;
629 default:
Brian5b01c5e2006-12-19 18:02:03 -0700630 _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramiv(pname)");
631 return;
Brian34ae99d2006-12-18 08:28:54 -0700632 }
Brian5b01c5e2006-12-19 18:02:03 -0700633}
Brian34ae99d2006-12-18 08:28:54 -0700634
Brian34ae99d2006-12-18 08:28:54 -0700635
Brian5b01c5e2006-12-19 18:02:03 -0700636void
637_mesa_get_shaderiv(GLcontext *ctx, GLuint name, GLenum pname, GLint *params)
638{
Brian65a18442006-12-19 18:46:56 -0700639 struct gl_shader *shader = _mesa_lookup_shader(ctx, name);
Brian5b01c5e2006-12-19 18:02:03 -0700640
641 if (!shader) {
642 _mesa_error(ctx, GL_INVALID_VALUE, "glGetShaderiv(shader)");
643 return;
644 }
Brian65a18442006-12-19 18:46:56 -0700645
Brian5b01c5e2006-12-19 18:02:03 -0700646 switch (pname) {
647 case GL_SHADER_TYPE:
648 *params = shader->Type;
649 break;
650 case GL_DELETE_STATUS:
651 *params = shader->DeletePending;
652 break;
653 case GL_COMPILE_STATUS:
654 *params = shader->CompileStatus;
655 break;
656 case GL_INFO_LOG_LENGTH:
657 *params = shader->InfoLog ? strlen(shader->InfoLog) : 0;
658 break;
659 case GL_SHADER_SOURCE_LENGTH:
660 *params = shader->Source ? strlen((char *) shader->Source) : 0;
661 break;
662 default:
663 _mesa_error(ctx, GL_INVALID_ENUM, "glGetShaderiv(pname)");
664 return;
665 }
666}
667
668
669void
670_mesa_get_program_info_log(GLcontext *ctx, GLuint program, GLsizei bufSize,
671 GLsizei *length, GLchar *infoLog)
672{
Brian65a18442006-12-19 18:46:56 -0700673 struct gl_shader_program *shProg
674 = _mesa_lookup_shader_program(ctx, program);
675 if (!shProg) {
Brian5b01c5e2006-12-19 18:02:03 -0700676 _mesa_error(ctx, GL_INVALID_VALUE, "glGetProgramInfoLog(program)");
677 return;
678 }
Brian65a18442006-12-19 18:46:56 -0700679 copy_string(infoLog, bufSize, length, shProg->InfoLog);
Brian5b01c5e2006-12-19 18:02:03 -0700680}
681
682
683void
684_mesa_get_shader_info_log(GLcontext *ctx, GLuint shader, GLsizei bufSize,
685 GLsizei *length, GLchar *infoLog)
686{
Brian65a18442006-12-19 18:46:56 -0700687 struct gl_shader *sh = _mesa_lookup_shader(ctx, shader);
688 if (!sh) {
Brian5b01c5e2006-12-19 18:02:03 -0700689 _mesa_error(ctx, GL_INVALID_VALUE, "glGetShaderInfoLog(shader)");
690 return;
691 }
Brian65a18442006-12-19 18:46:56 -0700692 copy_string(infoLog, bufSize, length, sh->InfoLog);
Brian5b01c5e2006-12-19 18:02:03 -0700693}
694
695
696/**
697 * Called via ctx->Driver.GetShaderSource().
698 */
699void
700_mesa_get_shader_source(GLcontext *ctx, GLuint shader, GLsizei maxLength,
701 GLsizei *length, GLchar *sourceOut)
702{
Brian65a18442006-12-19 18:46:56 -0700703 struct gl_shader *sh = _mesa_lookup_shader(ctx, shader);
704 if (!sh) {
Brian5b01c5e2006-12-19 18:02:03 -0700705 _mesa_error(ctx, GL_INVALID_VALUE, "glGetShaderSource(shader)");
706 return;
707 }
Brian65a18442006-12-19 18:46:56 -0700708 copy_string(sourceOut, maxLength, length, sh->Source);
Brian5b01c5e2006-12-19 18:02:03 -0700709}
710
711
712/**
713 * Called via ctx->Driver.GetUniformfv().
714 */
715void
716_mesa_get_uniformfv(GLcontext *ctx, GLuint program, GLint location,
717 GLfloat *params)
718{
Brian65a18442006-12-19 18:46:56 -0700719 struct gl_shader_program *shProg
720 = _mesa_lookup_shader_program(ctx, program);
721 if (shProg) {
Brian223d7cb2007-01-23 16:37:51 -0700722 GLint i;
Brian65a18442006-12-19 18:46:56 -0700723 if (location >= 0 && location < shProg->Uniforms->NumParameters) {
724 for (i = 0; i < shProg->Uniforms->Parameters[location].Size; i++) {
725 params[i] = shProg->Uniforms->ParameterValues[location][i];
Brian5b01c5e2006-12-19 18:02:03 -0700726 }
727 }
728 else {
729 _mesa_error(ctx, GL_INVALID_VALUE, "glGetUniformfv(location)");
730 }
731 }
732 else {
Brian43975832007-01-04 08:21:09 -0700733 _mesa_error(ctx, GL_INVALID_VALUE, "glGetUniformfv(program)");
Brian5b01c5e2006-12-19 18:02:03 -0700734 }
735}
736
737
738/**
739 * Called via ctx->Driver.GetUniformLocation().
740 */
741GLint
742_mesa_get_uniform_location(GLcontext *ctx, GLuint program, const GLchar *name)
743{
Brian71623982007-01-30 16:55:03 -0700744 struct gl_shader_program *shProg
745 = _mesa_lookup_shader_program(ctx, program);
746 if (shProg) {
Brian5b01c5e2006-12-19 18:02:03 -0700747 GLuint loc;
Brian65a18442006-12-19 18:46:56 -0700748 for (loc = 0; loc < shProg->Uniforms->NumParameters; loc++) {
Brian5b01c5e2006-12-19 18:02:03 -0700749 const struct gl_program_parameter *u
Brian65a18442006-12-19 18:46:56 -0700750 = shProg->Uniforms->Parameters + loc;
Brian29053852006-12-21 11:21:26 -0700751 /* XXX this is a temporary simplification / short-cut.
752 * We need to handle things like "e.c[0].b" as seen in the
753 * GLSL orange book, page 189.
754 */
Brian5cf73262007-01-05 16:02:45 -0700755 if ((u->Type == PROGRAM_UNIFORM ||
756 u->Type == PROGRAM_SAMPLER) && !strcmp(u->Name, name)) {
Brian5b01c5e2006-12-19 18:02:03 -0700757 return loc;
758 }
759 }
760 }
761 return -1;
762
763}
764
765
766GLboolean
767_mesa_is_program(GLcontext *ctx, GLuint name)
768{
Brian65a18442006-12-19 18:46:56 -0700769 struct gl_shader_program *shProg = _mesa_lookup_shader_program(ctx, name);
770 return shProg ? GL_TRUE : GL_FALSE;
Brian5b01c5e2006-12-19 18:02:03 -0700771}
772
773
774GLboolean
775_mesa_is_shader(GLcontext *ctx, GLuint name)
776{
Brian65a18442006-12-19 18:46:56 -0700777 struct gl_shader *shader = _mesa_lookup_shader(ctx, name);
Brian5b01c5e2006-12-19 18:02:03 -0700778 return shader ? GL_TRUE : GL_FALSE;
Brian34ae99d2006-12-18 08:28:54 -0700779}
780
781
782
Brian5b01c5e2006-12-19 18:02:03 -0700783/**
784 * Called via ctx->Driver.ShaderSource()
785 */
786void
787_mesa_shader_source(GLcontext *ctx, GLuint shader, const GLchar *source)
Brian34ae99d2006-12-18 08:28:54 -0700788{
Brian65a18442006-12-19 18:46:56 -0700789 struct gl_shader *sh = _mesa_lookup_shader(ctx, shader);
790 if (!sh) {
Brian5b01c5e2006-12-19 18:02:03 -0700791 _mesa_error(ctx, GL_INVALID_VALUE, "glShaderSource(shaderObj)");
Brian34ae99d2006-12-18 08:28:54 -0700792 return;
793 }
794
Brian34ae99d2006-12-18 08:28:54 -0700795 /* free old shader source string and install new one */
Brian65a18442006-12-19 18:46:56 -0700796 if (sh->Source) {
797 _mesa_free((void *) sh->Source);
Brian34ae99d2006-12-18 08:28:54 -0700798 }
Brian65a18442006-12-19 18:46:56 -0700799 sh->Source = source;
Brian9e4bae92006-12-20 09:27:42 -0700800 sh->CompileStatus = GL_FALSE;
Brian34ae99d2006-12-18 08:28:54 -0700801}
802
803
Brian5b01c5e2006-12-19 18:02:03 -0700804/**
805 * Called via ctx->Driver.CompileShader()
806 */
807void
808_mesa_compile_shader(GLcontext *ctx, GLuint shaderObj)
Brian34ae99d2006-12-18 08:28:54 -0700809{
Brian65a18442006-12-19 18:46:56 -0700810 struct gl_shader *sh = _mesa_lookup_shader(ctx, shaderObj);
Brian34ae99d2006-12-18 08:28:54 -0700811
Brian65a18442006-12-19 18:46:56 -0700812 if (!sh) {
Brian34ae99d2006-12-18 08:28:54 -0700813 _mesa_error(ctx, GL_INVALID_VALUE, "glCompileShader(shaderObj)");
814 return;
815 }
816
Brian43975832007-01-04 08:21:09 -0700817 sh->CompileStatus = _slang_compile(ctx, sh);
Brian34ae99d2006-12-18 08:28:54 -0700818}
819
820
Brian5b01c5e2006-12-19 18:02:03 -0700821/**
822 * Called via ctx->Driver.LinkProgram()
823 */
824void
825_mesa_link_program(GLcontext *ctx, GLuint program)
Brian34ae99d2006-12-18 08:28:54 -0700826{
Brian65a18442006-12-19 18:46:56 -0700827 struct gl_shader_program *shProg;
Brian34ae99d2006-12-18 08:28:54 -0700828
Brian65a18442006-12-19 18:46:56 -0700829 shProg = _mesa_lookup_shader_program(ctx, program);
830 if (!shProg) {
Brian43975832007-01-04 08:21:09 -0700831 _mesa_error(ctx, GL_INVALID_VALUE, "glLinkProgram(program)");
Brian34ae99d2006-12-18 08:28:54 -0700832 return;
833 }
834
Brian65a18442006-12-19 18:46:56 -0700835 _slang_link2(ctx, program, shProg);
Brian34ae99d2006-12-18 08:28:54 -0700836}
837
838
839/**
Brian5b01c5e2006-12-19 18:02:03 -0700840 * Called via ctx->Driver.UseProgram()
Brian34ae99d2006-12-18 08:28:54 -0700841 */
Brian5b01c5e2006-12-19 18:02:03 -0700842void
843_mesa_use_program(GLcontext *ctx, GLuint program)
Brian34ae99d2006-12-18 08:28:54 -0700844{
Brian00d63aa2007-02-03 11:35:02 -0700845 if (ctx->Shader.CurrentProgram &&
846 ctx->Shader.CurrentProgram->Name == program) {
847 /* no-op */
848 return;
849 }
850
851 FLUSH_VERTICES(ctx, _NEW_PROGRAM);
852
Brian9e4bae92006-12-20 09:27:42 -0700853 /* unbind old */
854 if (ctx->Shader.CurrentProgram) {
855 ctx->Shader.CurrentProgram->RefCount--;
856 if (ctx->Shader.CurrentProgram->RefCount <= 0) {
857 _mesa_free_shader_program(ctx, ctx->Shader.CurrentProgram);
858 }
859 ctx->Shader.CurrentProgram = NULL;
860 }
861
Brian5b01c5e2006-12-19 18:02:03 -0700862 if (program) {
Brian65a18442006-12-19 18:46:56 -0700863 struct gl_shader_program *shProg;
864 shProg = _mesa_lookup_shader_program(ctx, program);
865 if (!shProg) {
Brian43975832007-01-04 08:21:09 -0700866 _mesa_error(ctx, GL_INVALID_VALUE,
Brian5b01c5e2006-12-19 18:02:03 -0700867 "glUseProgramObjectARB(programObj)");
868 return;
869 }
Brian65a18442006-12-19 18:46:56 -0700870 ctx->Shader.CurrentProgram = shProg;
Brian9e4bae92006-12-20 09:27:42 -0700871 shProg->RefCount++;
Brian5b01c5e2006-12-19 18:02:03 -0700872 }
873 else {
874 /* don't use a shader program */
875 ctx->Shader.CurrentProgram = NULL;
876 }
877}
Brian34ae99d2006-12-18 08:28:54 -0700878
Brian5b01c5e2006-12-19 18:02:03 -0700879
880/**
881 * Called via ctx->Driver.Uniform().
882 */
883void
884_mesa_uniform(GLcontext *ctx, GLint location, GLsizei count,
885 const GLvoid *values, GLenum type)
886{
Brian3a8e2772006-12-20 17:19:16 -0700887 struct gl_shader_program *shProg = ctx->Shader.CurrentProgram;
Brian89dc4852007-01-04 14:35:44 -0700888 GLfloat *uniformVal;
Brian3a8e2772006-12-20 17:19:16 -0700889
890 if (!shProg || !shProg->LinkStatus) {
Brian5b01c5e2006-12-19 18:02:03 -0700891 _mesa_error(ctx, GL_INVALID_OPERATION, "glUniform(program not linked)");
Brian3a8e2772006-12-20 17:19:16 -0700892 return;
893 }
894
Brian223d7cb2007-01-23 16:37:51 -0700895 if (location < 0 || location >= (GLint) shProg->Uniforms->NumParameters) {
Brian3a8e2772006-12-20 17:19:16 -0700896 _mesa_error(ctx, GL_INVALID_VALUE, "glUniform(location)");
897 return;
898 }
899
900 FLUSH_VERTICES(ctx, _NEW_PROGRAM);
901
Brianfee9bbe2007-02-02 18:05:43 -0700902 /*
903 * If we're setting a sampler, we must use glUniformi1()!
904 */
905 if (shProg->Uniforms->Parameters[location].Type == PROGRAM_SAMPLER) {
906 if (type != GL_INT || count != 1) {
907 _mesa_error(ctx, GL_INVALID_OPERATION,
908 "glUniform(only glUniform1i can be used "
909 "to set sampler uniforms)");
910 return;
911 }
912 }
913
Brian89dc4852007-01-04 14:35:44 -0700914 uniformVal = shProg->Uniforms->ParameterValues[location];
Brian3a8e2772006-12-20 17:19:16 -0700915
Brianfee9bbe2007-02-02 18:05:43 -0700916 /* XXX obey 'count' parameter! */
917
Brian89dc4852007-01-04 14:35:44 -0700918 if (type == GL_INT ||
919 type == GL_INT_VEC2 ||
920 type == GL_INT_VEC3 ||
921 type == GL_INT_VEC4) {
922 const GLint *iValues = (const GLint *) values;
923 switch (type) {
924 case GL_INT_VEC4:
925 uniformVal[3] = (GLfloat) iValues[3];
926 /* fall-through */
927 case GL_INT_VEC3:
928 uniformVal[2] = (GLfloat) iValues[2];
929 /* fall-through */
930 case GL_INT_VEC2:
931 uniformVal[1] = (GLfloat) iValues[1];
932 /* fall-through */
933 case GL_INT:
934 uniformVal[0] = (GLfloat) iValues[0];
935 break;
936 default:
937 _mesa_problem(ctx, "Invalid type in _mesa_uniform");
938 return;
939 }
940 }
941 else {
Brian8a48f352007-01-10 12:18:50 -0700942 const GLfloat *fValues = (const GLfloat *) values;
Brian89dc4852007-01-04 14:35:44 -0700943 switch (type) {
944 case GL_FLOAT_VEC4:
945 uniformVal[3] = fValues[3];
946 /* fall-through */
947 case GL_FLOAT_VEC3:
948 uniformVal[2] = fValues[2];
949 /* fall-through */
950 case GL_FLOAT_VEC2:
951 uniformVal[1] = fValues[1];
952 /* fall-through */
953 case GL_FLOAT:
954 uniformVal[0] = fValues[0];
955 break;
956 default:
957 _mesa_problem(ctx, "Invalid type in _mesa_uniform");
958 return;
959 }
Brian5b01c5e2006-12-19 18:02:03 -0700960 }
Brian5cf73262007-01-05 16:02:45 -0700961
962 if (shProg->Uniforms->Parameters[location].Type == PROGRAM_SAMPLER) {
963 _slang_resolve_samplers(shProg, &shProg->VertexProgram->Base);
964 _slang_resolve_samplers(shProg, &shProg->FragmentProgram->Base);
965 FLUSH_VERTICES(ctx, _NEW_TEXTURE);
966 }
Brian34ae99d2006-12-18 08:28:54 -0700967}
968
969
970/**
Brian5b01c5e2006-12-19 18:02:03 -0700971 * Called by ctx->Driver.UniformMatrix().
Brian34ae99d2006-12-18 08:28:54 -0700972 */
Brian5b01c5e2006-12-19 18:02:03 -0700973void
974_mesa_uniform_matrix(GLcontext *ctx, GLint cols, GLint rows,
975 GLenum matrixType, GLint location, GLsizei count,
976 GLboolean transpose, const GLfloat *values)
Brian34ae99d2006-12-18 08:28:54 -0700977{
Brian3a8e2772006-12-20 17:19:16 -0700978 struct gl_shader_program *shProg = ctx->Shader.CurrentProgram;
979 if (!shProg || !shProg->LinkStatus) {
980 _mesa_error(ctx, GL_INVALID_OPERATION,
981 "glUniformMatrix(program not linked)");
982 return;
983 }
984 if (location < 0 || location >= shProg->Uniforms->NumParameters) {
985 _mesa_error(ctx, GL_INVALID_VALUE, "glUniformMatrix(location)");
986 return;
987 }
Brian34ae99d2006-12-18 08:28:54 -0700988 if (values == NULL) {
Brian3a8e2772006-12-20 17:19:16 -0700989 _mesa_error(ctx, GL_INVALID_VALUE, "glUniformMatrix");
Brian34ae99d2006-12-18 08:28:54 -0700990 return;
991 }
992
993 FLUSH_VERTICES(ctx, _NEW_PROGRAM);
994
Brian3a8e2772006-12-20 17:19:16 -0700995 /*
996 * Note: the _columns_ of a matrix are stored in program registers, not
997 * the rows.
998 */
999 /* XXXX need to test 3x3 and 2x2 matrices... */
Brian34ae99d2006-12-18 08:28:54 -07001000 if (transpose) {
Brian3a8e2772006-12-20 17:19:16 -07001001 GLuint row, col;
1002 for (col = 0; col < cols; col++) {
1003 GLfloat *v = shProg->Uniforms->ParameterValues[location + col];
1004 for (row = 0; row < rows; row++) {
1005 v[row] = values[col * rows + row];
Brian34ae99d2006-12-18 08:28:54 -07001006 }
Brian34ae99d2006-12-18 08:28:54 -07001007 }
Brian34ae99d2006-12-18 08:28:54 -07001008 }
1009 else {
Brian3a8e2772006-12-20 17:19:16 -07001010 GLuint row, col;
1011 for (col = 0; col < cols; col++) {
1012 GLfloat *v = shProg->Uniforms->ParameterValues[location + col];
1013 for (row = 0; row < rows; row++) {
1014 v[row] = values[row * cols + col];
1015 }
1016 }
Brian34ae99d2006-12-18 08:28:54 -07001017 }
1018}
1019
1020
Brian5b01c5e2006-12-19 18:02:03 -07001021void
1022_mesa_validate_program(GLcontext *ctx, GLuint program)
Brian34ae99d2006-12-18 08:28:54 -07001023{
Brian65a18442006-12-19 18:46:56 -07001024 struct gl_shader_program *shProg;
1025 shProg = _mesa_lookup_shader_program(ctx, program);
1026 if (!shProg) {
Brian43975832007-01-04 08:21:09 -07001027 _mesa_error(ctx, GL_INVALID_VALUE, "glValidateProgram(program)");
Brian34ae99d2006-12-18 08:28:54 -07001028 return;
1029 }
Brian5b01c5e2006-12-19 18:02:03 -07001030 /* XXX temporary */
Brian65a18442006-12-19 18:46:56 -07001031 shProg->Validated = GL_TRUE;
Brian34ae99d2006-12-18 08:28:54 -07001032
Brian5b01c5e2006-12-19 18:02:03 -07001033 /* From the GL spec:
1034 any two active samplers in the current program object are of
1035 different types, but refer to the same texture image unit,
1036
1037 any active sampler in the current program object refers to a texture
1038 image unit where fixed-function fragment processing accesses a
1039 texture target that does not match the sampler type, or
1040
1041 the sum of the number of active samplers in the program and the
1042 number of texture image units enabled for fixed-function fragment
1043 processing exceeds the combined limit on the total number of texture
1044 image units allowed.
1045 */
Brian34ae99d2006-12-18 08:28:54 -07001046}