blob: aab522e292cfad91135b0dfd3815281b796d6dbc [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
Brianfa4d0362007-02-26 18:33:50 -0700199/**
200 * Initialize context's shader state.
201 */
Brianf2923612006-12-20 09:56:44 -0700202void
203_mesa_init_shader_state(GLcontext * ctx)
204{
Brianfa4d0362007-02-26 18:33:50 -0700205 /* Device drivers may override these to control what kind of instructions
206 * are generated by the GLSL compiler.
207 */
208 ctx->Shader.EmitHighLevelInstructions = GL_TRUE;
209 ctx->Shader.EmitComments = GL_FALSE;
Brianf2923612006-12-20 09:56:44 -0700210}
211
212
Brian5b01c5e2006-12-19 18:02:03 -0700213/**
214 * Copy string from <src> to <dst>, up to maxLength characters, returning
215 * length of <dst> in <length>.
216 * \param src the strings source
217 * \param maxLength max chars to copy
218 * \param length returns number of chars copied
219 * \param dst the string destination
220 */
221static void
222copy_string(GLchar *dst, GLsizei maxLength, GLsizei *length, const GLchar *src)
223{
224 GLsizei len;
225 for (len = 0; len < maxLength - 1 && src && src[len]; len++)
226 dst[len] = src[len];
227 if (maxLength > 0)
228 dst[len] = 0;
229 if (length)
230 *length = len;
231}
232
233
Brian5b01c5e2006-12-19 18:02:03 -0700234/**
235 * Called via ctx->Driver.AttachShader()
236 */
237void
238_mesa_attach_shader(GLcontext *ctx, GLuint program, GLuint shader)
239{
Brian65a18442006-12-19 18:46:56 -0700240 struct gl_shader_program *shProg
241 = _mesa_lookup_shader_program(ctx, program);
242 struct gl_shader *sh = _mesa_lookup_shader(ctx, shader);
243 const GLuint n = shProg->NumShaders;
Brian5b01c5e2006-12-19 18:02:03 -0700244 GLuint i;
245
Brian65a18442006-12-19 18:46:56 -0700246 if (!shProg || !sh) {
Brian43975832007-01-04 08:21:09 -0700247 _mesa_error(ctx, GL_INVALID_VALUE,
Brian5b01c5e2006-12-19 18:02:03 -0700248 "glAttachShader(bad program or shader name)");
249 return;
250 }
251
252 for (i = 0; i < n; i++) {
Brian65a18442006-12-19 18:46:56 -0700253 if (shProg->Shaders[i] == sh) {
Brian5b01c5e2006-12-19 18:02:03 -0700254 /* already attached */
255 return;
Brian34ae99d2006-12-18 08:28:54 -0700256 }
257 }
Brian5b01c5e2006-12-19 18:02:03 -0700258
259 /* grow list */
Brian65a18442006-12-19 18:46:56 -0700260 shProg->Shaders = (struct gl_shader **)
261 _mesa_realloc(shProg->Shaders,
262 n * sizeof(struct gl_shader *),
263 (n + 1) * sizeof(struct gl_shader *));
264 if (!shProg->Shaders) {
Brian5b01c5e2006-12-19 18:02:03 -0700265 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glAttachShader");
266 return;
267 }
268
269 /* append */
Brian65a18442006-12-19 18:46:56 -0700270 shProg->Shaders[n] = sh;
271 sh->RefCount++;
272 shProg->NumShaders++;
Brian5b01c5e2006-12-19 18:02:03 -0700273}
274
275
276void
277_mesa_bind_attrib_location(GLcontext *ctx, GLuint program, GLuint index,
278 const GLchar *name)
279{
Brian65a18442006-12-19 18:46:56 -0700280 struct gl_shader_program *shProg
281 = _mesa_lookup_shader_program(ctx, program);
Brianb7978af2007-01-09 19:17:17 -0700282 const GLint size = -1; /* unknown size */
283 GLint i, oldIndex;
Brian5b01c5e2006-12-19 18:02:03 -0700284
Brian65a18442006-12-19 18:46:56 -0700285 if (!shProg) {
Brian43975832007-01-04 08:21:09 -0700286 _mesa_error(ctx, GL_INVALID_VALUE, "glBindAttribLocation(program)");
Brian5b01c5e2006-12-19 18:02:03 -0700287 return;
288 }
289
Brian9e4bae92006-12-20 09:27:42 -0700290 if (!name)
291 return;
292
293 if (strncmp(name, "gl_", 3) == 0) {
294 _mesa_error(ctx, GL_INVALID_OPERATION,
295 "glBindAttribLocation(illegal name)");
296 return;
297 }
298
Brian3209c3e2007-01-09 17:49:24 -0700299 oldIndex = _mesa_get_attrib_location(ctx, program, name);
300
301 /* this will replace the current value if it's already in the list */
Brianb7978af2007-01-09 19:17:17 -0700302 i = _mesa_add_attribute(shProg->Attributes, name, size, index);
Brian3209c3e2007-01-09 17:49:24 -0700303 if (i < 0) {
304 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBindAttribLocation");
305 }
306
307 if (shProg->VertexProgram && oldIndex >= 0) {
308 _slang_remap_attribute(&shProg->VertexProgram->Base, oldIndex, index);
309 }
310
Brian88e2dbf2007-01-10 13:33:38 -0700311#if 0
Brian3209c3e2007-01-09 17:49:24 -0700312 printf("===== post BindAttrib:\n");
313 _mesa_print_program(&shProg->VertexProgram->Base);
Brian88e2dbf2007-01-10 13:33:38 -0700314#endif
Brian34ae99d2006-12-18 08:28:54 -0700315}
316
317
Brian5b01c5e2006-12-19 18:02:03 -0700318GLuint
319_mesa_create_shader(GLcontext *ctx, GLenum type)
320{
Brian65a18442006-12-19 18:46:56 -0700321 struct gl_shader *sh;
Brian5b01c5e2006-12-19 18:02:03 -0700322 GLuint name;
323
324 name = _mesa_HashFindFreeKeyBlock(ctx->Shared->ShaderObjects, 1);
325
326 switch (type) {
Brian65a18442006-12-19 18:46:56 -0700327 case GL_FRAGMENT_SHADER:
328 case GL_VERTEX_SHADER:
329 sh = _mesa_new_shader(ctx, name, type);
Brian5b01c5e2006-12-19 18:02:03 -0700330 break;
331 default:
332 _mesa_error(ctx, GL_INVALID_ENUM, "CreateShader(type)");
333 return 0;
334 }
335
Brian65a18442006-12-19 18:46:56 -0700336 _mesa_HashInsert(ctx->Shared->ShaderObjects, name, sh);
Brian5b01c5e2006-12-19 18:02:03 -0700337
338 return name;
339}
340
341
342GLuint
343_mesa_create_program(GLcontext *ctx)
344{
345 GLuint name;
Brian65a18442006-12-19 18:46:56 -0700346 struct gl_shader_program *shProg;
Brian5b01c5e2006-12-19 18:02:03 -0700347
Brian65a18442006-12-19 18:46:56 -0700348 name = _mesa_HashFindFreeKeyBlock(ctx->Shared->ShaderObjects, 1);
349 shProg = _mesa_new_shader_program(ctx, name);
Brian5b01c5e2006-12-19 18:02:03 -0700350
Brian65a18442006-12-19 18:46:56 -0700351 _mesa_HashInsert(ctx->Shared->ShaderObjects, name, shProg);
Brian5b01c5e2006-12-19 18:02:03 -0700352
353 return name;
354}
355
356
357void
358_mesa_delete_program2(GLcontext *ctx, GLuint name)
359{
Brian65a18442006-12-19 18:46:56 -0700360 struct gl_shader_program *shProg;
Brian5b01c5e2006-12-19 18:02:03 -0700361
Brian65a18442006-12-19 18:46:56 -0700362 shProg = _mesa_lookup_shader_program(ctx, name);
363 if (!shProg) {
Brian43975832007-01-04 08:21:09 -0700364 _mesa_error(ctx, GL_INVALID_VALUE, "glDeleteProgram(name)");
Brian5b01c5e2006-12-19 18:02:03 -0700365 return;
366 }
367
Brian9e4bae92006-12-20 09:27:42 -0700368 /* always remove from hash table */
Brian65a18442006-12-19 18:46:56 -0700369 _mesa_HashRemove(ctx->Shared->ShaderObjects, name);
Brian9e4bae92006-12-20 09:27:42 -0700370
371 shProg->DeletePending = GL_TRUE;
372
373 /* decrement refcount, delete if zero */
374 shProg->RefCount--;
375 if (shProg->RefCount <= 0) {
376 _mesa_free_shader_program(ctx, shProg);
377 }
Brian5b01c5e2006-12-19 18:02:03 -0700378}
379
380
381void
382_mesa_delete_shader(GLcontext *ctx, GLuint shader)
383{
Brian9e4bae92006-12-20 09:27:42 -0700384 struct gl_shader *sh = _mesa_lookup_shader(ctx, shader);
385 if (!sh) {
386 return;
387 }
Brian5b01c5e2006-12-19 18:02:03 -0700388
Brian9e4bae92006-12-20 09:27:42 -0700389 sh->DeletePending = GL_TRUE;
390 sh->RefCount--;
391 if (sh->RefCount <= 0) {
392 _mesa_free_shader(ctx, sh);
393 }
Brian5b01c5e2006-12-19 18:02:03 -0700394}
395
396
397void
398_mesa_detach_shader(GLcontext *ctx, GLuint program, GLuint shader)
399{
Brian65a18442006-12-19 18:46:56 -0700400 struct gl_shader_program *shProg
401 = _mesa_lookup_shader_program(ctx, program);
402 const GLuint n = shProg->NumShaders;
Brian5b01c5e2006-12-19 18:02:03 -0700403 GLuint i, j;
404
Brian65a18442006-12-19 18:46:56 -0700405 if (!shProg) {
Brian43975832007-01-04 08:21:09 -0700406 _mesa_error(ctx, GL_INVALID_VALUE,
Brian5b01c5e2006-12-19 18:02:03 -0700407 "glDetachShader(bad program or shader name)");
408 return;
409 }
410
411 for (i = 0; i < n; i++) {
Brian65a18442006-12-19 18:46:56 -0700412 if (shProg->Shaders[i]->Name == shader) {
413 struct gl_shader **newList;
Brian5b01c5e2006-12-19 18:02:03 -0700414 /* found it */
Brian9e4bae92006-12-20 09:27:42 -0700415
416 shProg->Shaders[i]->RefCount--;
417
Brian5b01c5e2006-12-19 18:02:03 -0700418 /* alloc new, smaller array */
Brian65a18442006-12-19 18:46:56 -0700419 newList = (struct gl_shader **)
420 _mesa_malloc((n - 1) * sizeof(struct gl_shader *));
Brian5b01c5e2006-12-19 18:02:03 -0700421 if (!newList) {
422 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glDetachShader");
423 return;
424 }
425 for (j = 0; j < i; j++) {
Brian65a18442006-12-19 18:46:56 -0700426 newList[j] = shProg->Shaders[j];
Brian5b01c5e2006-12-19 18:02:03 -0700427 }
428 while (++i < n)
Brian65a18442006-12-19 18:46:56 -0700429 newList[j++] = shProg->Shaders[i];
430 _mesa_free(shProg->Shaders);
Brian5b01c5e2006-12-19 18:02:03 -0700431
432 /* XXX refcounting! */
433
Brian65a18442006-12-19 18:46:56 -0700434 shProg->Shaders = newList;
Brian5b01c5e2006-12-19 18:02:03 -0700435 return;
436 }
437 }
438
439 /* not found */
Brian43975832007-01-04 08:21:09 -0700440 _mesa_error(ctx, GL_INVALID_VALUE,
Brian5b01c5e2006-12-19 18:02:03 -0700441 "glDetachShader(shader not found)");
442}
443
444
445void
446_mesa_get_active_attrib(GLcontext *ctx, GLuint program, GLuint index,
447 GLsizei maxLength, GLsizei *length, GLint *size,
448 GLenum *type, GLchar *nameOut)
449{
450 static const GLenum vec_types[] = {
451 GL_FLOAT, GL_FLOAT_VEC2, GL_FLOAT_VEC3, GL_FLOAT_VEC4
452 };
Brian65a18442006-12-19 18:46:56 -0700453 struct gl_shader_program *shProg
454 = _mesa_lookup_shader_program(ctx, program);
Brian5b01c5e2006-12-19 18:02:03 -0700455 GLint sz;
456
Brian65a18442006-12-19 18:46:56 -0700457 if (!shProg) {
Brian43975832007-01-04 08:21:09 -0700458 _mesa_error(ctx, GL_INVALID_VALUE, "glGetActiveUniform");
Brian5b01c5e2006-12-19 18:02:03 -0700459 return;
460 }
461
Brian65a18442006-12-19 18:46:56 -0700462 if (!shProg->Attributes || index >= shProg->Attributes->NumParameters) {
Brian5b01c5e2006-12-19 18:02:03 -0700463 _mesa_error(ctx, GL_INVALID_VALUE, "glGetActiveUniform(index)");
464 return;
465 }
466
467 copy_string(nameOut, maxLength, length,
Brian65a18442006-12-19 18:46:56 -0700468 shProg->Attributes->Parameters[index].Name);
469 sz = shProg->Attributes->Parameters[index].Size;
Brian5b01c5e2006-12-19 18:02:03 -0700470 if (size)
471 *size = sz;
472 if (type)
473 *type = vec_types[sz]; /* XXX this is a temporary hack */
474}
475
476
477/**
478 * Called via ctx->Driver.GetActiveUniform().
479 */
480void
481_mesa_get_active_uniform(GLcontext *ctx, GLuint program, GLuint index,
482 GLsizei maxLength, GLsizei *length, GLint *size,
483 GLenum *type, GLchar *nameOut)
484{
485 static const GLenum vec_types[] = {
486 GL_FLOAT, GL_FLOAT_VEC2, GL_FLOAT_VEC3, GL_FLOAT_VEC4
487 };
Brian65a18442006-12-19 18:46:56 -0700488 struct gl_shader_program *shProg
489 = _mesa_lookup_shader_program(ctx, program);
Brian5b01c5e2006-12-19 18:02:03 -0700490 GLint sz;
491
Brian65a18442006-12-19 18:46:56 -0700492 if (!shProg) {
Brian43975832007-01-04 08:21:09 -0700493 _mesa_error(ctx, GL_INVALID_VALUE, "glGetActiveUniform");
Brian5b01c5e2006-12-19 18:02:03 -0700494 return;
495 }
496
Brian65a18442006-12-19 18:46:56 -0700497 if (!shProg->Uniforms || index >= shProg->Uniforms->NumParameters) {
Brian5b01c5e2006-12-19 18:02:03 -0700498 _mesa_error(ctx, GL_INVALID_VALUE, "glGetActiveUniform(index)");
499 return;
500 }
501
502 copy_string(nameOut, maxLength, length,
Brian65a18442006-12-19 18:46:56 -0700503 shProg->Uniforms->Parameters[index].Name);
504 sz = shProg->Uniforms->Parameters[index].Size;
Brian5b01c5e2006-12-19 18:02:03 -0700505 if (size)
506 *size = sz;
507 if (type)
508 *type = vec_types[sz]; /* XXX this is a temporary hack */
509}
510
511
512/**
513 * Called via ctx->Driver.GetAttachedShaders().
514 */
515void
516_mesa_get_attached_shaders(GLcontext *ctx, GLuint program, GLsizei maxCount,
517 GLsizei *count, GLuint *obj)
518{
Brian65a18442006-12-19 18:46:56 -0700519 struct gl_shader_program *shProg
520 = _mesa_lookup_shader_program(ctx, program);
521 if (shProg) {
Brian223d7cb2007-01-23 16:37:51 -0700522 GLint i;
Brian65a18442006-12-19 18:46:56 -0700523 for (i = 0; i < maxCount && i < shProg->NumShaders; i++) {
524 obj[i] = shProg->Shaders[i]->Name;
Brian5b01c5e2006-12-19 18:02:03 -0700525 }
526 if (count)
527 *count = i;
528 }
529 else {
Brian43975832007-01-04 08:21:09 -0700530 _mesa_error(ctx, GL_INVALID_VALUE, "glGetAttachedShaders");
Brian5b01c5e2006-12-19 18:02:03 -0700531 }
532}
533
534
535GLint
536_mesa_get_attrib_location(GLcontext *ctx, GLuint program,
537 const GLchar *name)
538{
Brian65a18442006-12-19 18:46:56 -0700539 struct gl_shader_program *shProg
540 = _mesa_lookup_shader_program(ctx, program);
Brian5b01c5e2006-12-19 18:02:03 -0700541
Brian65a18442006-12-19 18:46:56 -0700542 if (!shProg) {
Brian43975832007-01-04 08:21:09 -0700543 _mesa_error(ctx, GL_INVALID_VALUE, "glGetAttribLocation");
Brian5b01c5e2006-12-19 18:02:03 -0700544 return -1;
545 }
546
Brian65a18442006-12-19 18:46:56 -0700547 if (!shProg->LinkStatus) {
Brian5b01c5e2006-12-19 18:02:03 -0700548 _mesa_error(ctx, GL_INVALID_OPERATION,
549 "glGetAttribLocation(program not linked)");
550 return -1;
551 }
552
553 if (!name)
554 return -1;
555
Brian65a18442006-12-19 18:46:56 -0700556 if (shProg->Attributes) {
Brian3209c3e2007-01-09 17:49:24 -0700557 GLint i = _mesa_lookup_parameter_index(shProg->Attributes, -1, name);
558 if (i >= 0) {
Brian01a91eb2007-01-09 19:26:22 -0700559 return shProg->Attributes->Parameters[i].StateIndexes[0];
Brian5b01c5e2006-12-19 18:02:03 -0700560 }
561 }
562 return -1;
563}
564
565
566GLuint
567_mesa_get_handle(GLcontext *ctx, GLenum pname)
Brian34ae99d2006-12-18 08:28:54 -0700568{
569#if 0
570 GET_CURRENT_CONTEXT(ctx);
571
572 switch (pname) {
573 case GL_PROGRAM_OBJECT_ARB:
574 {
Brian5b01c5e2006-12-19 18:02:03 -0700575 struct gl2_program_intf **pro = ctx->Shader.CurrentProgram;
Brian34ae99d2006-12-18 08:28:54 -0700576
577 if (pro != NULL)
578 return (**pro)._container._generic.
579 GetName((struct gl2_generic_intf **) (pro));
580 }
581 break;
582 default:
583 _mesa_error(ctx, GL_INVALID_ENUM, "glGetHandleARB");
584 }
585#endif
586 return 0;
587}
588
589
Brian5b01c5e2006-12-19 18:02:03 -0700590void
591_mesa_get_programiv(GLcontext *ctx, GLuint program,
592 GLenum pname, GLint *params)
Brian34ae99d2006-12-18 08:28:54 -0700593{
Brian65a18442006-12-19 18:46:56 -0700594 struct gl_shader_program *shProg
595 = _mesa_lookup_shader_program(ctx, program);
Brian34ae99d2006-12-18 08:28:54 -0700596
Brian65a18442006-12-19 18:46:56 -0700597 if (!shProg) {
Brian5b01c5e2006-12-19 18:02:03 -0700598 _mesa_error(ctx, GL_INVALID_VALUE, "glGetProgramiv(program)");
Brian34ae99d2006-12-18 08:28:54 -0700599 return;
600 }
601
Brian5b01c5e2006-12-19 18:02:03 -0700602 switch (pname) {
603 case GL_DELETE_STATUS:
Brian65a18442006-12-19 18:46:56 -0700604 *params = shProg->DeletePending;
Brian5b01c5e2006-12-19 18:02:03 -0700605 break;
606 case GL_LINK_STATUS:
Brian65a18442006-12-19 18:46:56 -0700607 *params = shProg->LinkStatus;
Brian34ae99d2006-12-18 08:28:54 -0700608 break;
Brian5b01c5e2006-12-19 18:02:03 -0700609 case GL_VALIDATE_STATUS:
Brian65a18442006-12-19 18:46:56 -0700610 *params = shProg->Validated;
Brian5b01c5e2006-12-19 18:02:03 -0700611 break;
612 case GL_INFO_LOG_LENGTH:
Brian65a18442006-12-19 18:46:56 -0700613 *params = shProg->InfoLog ? strlen(shProg->InfoLog) : 0;
Brian5b01c5e2006-12-19 18:02:03 -0700614 break;
615 case GL_ATTACHED_SHADERS:
Brian65a18442006-12-19 18:46:56 -0700616 *params = shProg->NumShaders;
Brian5b01c5e2006-12-19 18:02:03 -0700617 break;
618 case GL_ACTIVE_ATTRIBUTES:
Brian3209c3e2007-01-09 17:49:24 -0700619 *params = shProg->Attributes ? shProg->Attributes->NumParameters : 0;
Brian5b01c5e2006-12-19 18:02:03 -0700620 break;
621 case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH:
Brian65a18442006-12-19 18:46:56 -0700622 *params = _mesa_parameter_longest_name(shProg->Attributes);
Brian5b01c5e2006-12-19 18:02:03 -0700623 break;
624 case GL_ACTIVE_UNIFORMS:
Brian65a18442006-12-19 18:46:56 -0700625 *params = shProg->Uniforms ? shProg->Uniforms->NumParameters : 0;
Brian5b01c5e2006-12-19 18:02:03 -0700626 break;
627 case GL_ACTIVE_UNIFORM_MAX_LENGTH:
Brian65a18442006-12-19 18:46:56 -0700628 *params = _mesa_parameter_longest_name(shProg->Uniforms);
Brian34ae99d2006-12-18 08:28:54 -0700629 break;
630 default:
Brian5b01c5e2006-12-19 18:02:03 -0700631 _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramiv(pname)");
632 return;
Brian34ae99d2006-12-18 08:28:54 -0700633 }
Brian5b01c5e2006-12-19 18:02:03 -0700634}
Brian34ae99d2006-12-18 08:28:54 -0700635
Brian34ae99d2006-12-18 08:28:54 -0700636
Brian5b01c5e2006-12-19 18:02:03 -0700637void
638_mesa_get_shaderiv(GLcontext *ctx, GLuint name, GLenum pname, GLint *params)
639{
Brian65a18442006-12-19 18:46:56 -0700640 struct gl_shader *shader = _mesa_lookup_shader(ctx, name);
Brian5b01c5e2006-12-19 18:02:03 -0700641
642 if (!shader) {
643 _mesa_error(ctx, GL_INVALID_VALUE, "glGetShaderiv(shader)");
644 return;
645 }
Brian65a18442006-12-19 18:46:56 -0700646
Brian5b01c5e2006-12-19 18:02:03 -0700647 switch (pname) {
648 case GL_SHADER_TYPE:
649 *params = shader->Type;
650 break;
651 case GL_DELETE_STATUS:
652 *params = shader->DeletePending;
653 break;
654 case GL_COMPILE_STATUS:
655 *params = shader->CompileStatus;
656 break;
657 case GL_INFO_LOG_LENGTH:
658 *params = shader->InfoLog ? strlen(shader->InfoLog) : 0;
659 break;
660 case GL_SHADER_SOURCE_LENGTH:
661 *params = shader->Source ? strlen((char *) shader->Source) : 0;
662 break;
663 default:
664 _mesa_error(ctx, GL_INVALID_ENUM, "glGetShaderiv(pname)");
665 return;
666 }
667}
668
669
670void
671_mesa_get_program_info_log(GLcontext *ctx, GLuint program, GLsizei bufSize,
672 GLsizei *length, GLchar *infoLog)
673{
Brian65a18442006-12-19 18:46:56 -0700674 struct gl_shader_program *shProg
675 = _mesa_lookup_shader_program(ctx, program);
676 if (!shProg) {
Brian5b01c5e2006-12-19 18:02:03 -0700677 _mesa_error(ctx, GL_INVALID_VALUE, "glGetProgramInfoLog(program)");
678 return;
679 }
Brian65a18442006-12-19 18:46:56 -0700680 copy_string(infoLog, bufSize, length, shProg->InfoLog);
Brian5b01c5e2006-12-19 18:02:03 -0700681}
682
683
684void
685_mesa_get_shader_info_log(GLcontext *ctx, GLuint shader, GLsizei bufSize,
686 GLsizei *length, GLchar *infoLog)
687{
Brian65a18442006-12-19 18:46:56 -0700688 struct gl_shader *sh = _mesa_lookup_shader(ctx, shader);
689 if (!sh) {
Brian5b01c5e2006-12-19 18:02:03 -0700690 _mesa_error(ctx, GL_INVALID_VALUE, "glGetShaderInfoLog(shader)");
691 return;
692 }
Brian65a18442006-12-19 18:46:56 -0700693 copy_string(infoLog, bufSize, length, sh->InfoLog);
Brian5b01c5e2006-12-19 18:02:03 -0700694}
695
696
697/**
698 * Called via ctx->Driver.GetShaderSource().
699 */
700void
701_mesa_get_shader_source(GLcontext *ctx, GLuint shader, GLsizei maxLength,
702 GLsizei *length, GLchar *sourceOut)
703{
Brian65a18442006-12-19 18:46:56 -0700704 struct gl_shader *sh = _mesa_lookup_shader(ctx, shader);
705 if (!sh) {
Brian5b01c5e2006-12-19 18:02:03 -0700706 _mesa_error(ctx, GL_INVALID_VALUE, "glGetShaderSource(shader)");
707 return;
708 }
Brian65a18442006-12-19 18:46:56 -0700709 copy_string(sourceOut, maxLength, length, sh->Source);
Brian5b01c5e2006-12-19 18:02:03 -0700710}
711
712
713/**
714 * Called via ctx->Driver.GetUniformfv().
715 */
716void
717_mesa_get_uniformfv(GLcontext *ctx, GLuint program, GLint location,
718 GLfloat *params)
719{
Brian65a18442006-12-19 18:46:56 -0700720 struct gl_shader_program *shProg
721 = _mesa_lookup_shader_program(ctx, program);
722 if (shProg) {
Brian223d7cb2007-01-23 16:37:51 -0700723 GLint i;
Brian65a18442006-12-19 18:46:56 -0700724 if (location >= 0 && location < shProg->Uniforms->NumParameters) {
725 for (i = 0; i < shProg->Uniforms->Parameters[location].Size; i++) {
726 params[i] = shProg->Uniforms->ParameterValues[location][i];
Brian5b01c5e2006-12-19 18:02:03 -0700727 }
728 }
729 else {
730 _mesa_error(ctx, GL_INVALID_VALUE, "glGetUniformfv(location)");
731 }
732 }
733 else {
Brian43975832007-01-04 08:21:09 -0700734 _mesa_error(ctx, GL_INVALID_VALUE, "glGetUniformfv(program)");
Brian5b01c5e2006-12-19 18:02:03 -0700735 }
736}
737
738
739/**
740 * Called via ctx->Driver.GetUniformLocation().
741 */
742GLint
743_mesa_get_uniform_location(GLcontext *ctx, GLuint program, const GLchar *name)
744{
Brian71623982007-01-30 16:55:03 -0700745 struct gl_shader_program *shProg
746 = _mesa_lookup_shader_program(ctx, program);
747 if (shProg) {
Brian5b01c5e2006-12-19 18:02:03 -0700748 GLuint loc;
Brian65a18442006-12-19 18:46:56 -0700749 for (loc = 0; loc < shProg->Uniforms->NumParameters; loc++) {
Brian5b01c5e2006-12-19 18:02:03 -0700750 const struct gl_program_parameter *u
Brian65a18442006-12-19 18:46:56 -0700751 = shProg->Uniforms->Parameters + loc;
Brian29053852006-12-21 11:21:26 -0700752 /* XXX this is a temporary simplification / short-cut.
753 * We need to handle things like "e.c[0].b" as seen in the
754 * GLSL orange book, page 189.
755 */
Brian5cf73262007-01-05 16:02:45 -0700756 if ((u->Type == PROGRAM_UNIFORM ||
757 u->Type == PROGRAM_SAMPLER) && !strcmp(u->Name, name)) {
Brian5b01c5e2006-12-19 18:02:03 -0700758 return loc;
759 }
760 }
761 }
762 return -1;
763
764}
765
766
767GLboolean
768_mesa_is_program(GLcontext *ctx, GLuint name)
769{
Brian65a18442006-12-19 18:46:56 -0700770 struct gl_shader_program *shProg = _mesa_lookup_shader_program(ctx, name);
771 return shProg ? GL_TRUE : GL_FALSE;
Brian5b01c5e2006-12-19 18:02:03 -0700772}
773
774
775GLboolean
776_mesa_is_shader(GLcontext *ctx, GLuint name)
777{
Brian65a18442006-12-19 18:46:56 -0700778 struct gl_shader *shader = _mesa_lookup_shader(ctx, name);
Brian5b01c5e2006-12-19 18:02:03 -0700779 return shader ? GL_TRUE : GL_FALSE;
Brian34ae99d2006-12-18 08:28:54 -0700780}
781
782
783
Brian5b01c5e2006-12-19 18:02:03 -0700784/**
785 * Called via ctx->Driver.ShaderSource()
786 */
787void
788_mesa_shader_source(GLcontext *ctx, GLuint shader, const GLchar *source)
Brian34ae99d2006-12-18 08:28:54 -0700789{
Brian65a18442006-12-19 18:46:56 -0700790 struct gl_shader *sh = _mesa_lookup_shader(ctx, shader);
791 if (!sh) {
Brian5b01c5e2006-12-19 18:02:03 -0700792 _mesa_error(ctx, GL_INVALID_VALUE, "glShaderSource(shaderObj)");
Brian34ae99d2006-12-18 08:28:54 -0700793 return;
794 }
795
Brian34ae99d2006-12-18 08:28:54 -0700796 /* free old shader source string and install new one */
Brian65a18442006-12-19 18:46:56 -0700797 if (sh->Source) {
798 _mesa_free((void *) sh->Source);
Brian34ae99d2006-12-18 08:28:54 -0700799 }
Brian65a18442006-12-19 18:46:56 -0700800 sh->Source = source;
Brian9e4bae92006-12-20 09:27:42 -0700801 sh->CompileStatus = GL_FALSE;
Brian34ae99d2006-12-18 08:28:54 -0700802}
803
804
Brian5b01c5e2006-12-19 18:02:03 -0700805/**
806 * Called via ctx->Driver.CompileShader()
807 */
808void
809_mesa_compile_shader(GLcontext *ctx, GLuint shaderObj)
Brian34ae99d2006-12-18 08:28:54 -0700810{
Brian65a18442006-12-19 18:46:56 -0700811 struct gl_shader *sh = _mesa_lookup_shader(ctx, shaderObj);
Brian34ae99d2006-12-18 08:28:54 -0700812
Brian65a18442006-12-19 18:46:56 -0700813 if (!sh) {
Brian34ae99d2006-12-18 08:28:54 -0700814 _mesa_error(ctx, GL_INVALID_VALUE, "glCompileShader(shaderObj)");
815 return;
816 }
817
Brian43975832007-01-04 08:21:09 -0700818 sh->CompileStatus = _slang_compile(ctx, sh);
Brian34ae99d2006-12-18 08:28:54 -0700819}
820
821
Brian5b01c5e2006-12-19 18:02:03 -0700822/**
823 * Called via ctx->Driver.LinkProgram()
824 */
825void
826_mesa_link_program(GLcontext *ctx, GLuint program)
Brian34ae99d2006-12-18 08:28:54 -0700827{
Brian65a18442006-12-19 18:46:56 -0700828 struct gl_shader_program *shProg;
Brian34ae99d2006-12-18 08:28:54 -0700829
Brian65a18442006-12-19 18:46:56 -0700830 shProg = _mesa_lookup_shader_program(ctx, program);
831 if (!shProg) {
Brian43975832007-01-04 08:21:09 -0700832 _mesa_error(ctx, GL_INVALID_VALUE, "glLinkProgram(program)");
Brian34ae99d2006-12-18 08:28:54 -0700833 return;
834 }
835
Brianc1771912007-02-16 09:56:19 -0700836 _slang_link(ctx, program, shProg);
Brian34ae99d2006-12-18 08:28:54 -0700837}
838
839
840/**
Brian5b01c5e2006-12-19 18:02:03 -0700841 * Called via ctx->Driver.UseProgram()
Brian34ae99d2006-12-18 08:28:54 -0700842 */
Brian5b01c5e2006-12-19 18:02:03 -0700843void
844_mesa_use_program(GLcontext *ctx, GLuint program)
Brian34ae99d2006-12-18 08:28:54 -0700845{
Brian00d63aa2007-02-03 11:35:02 -0700846 if (ctx->Shader.CurrentProgram &&
847 ctx->Shader.CurrentProgram->Name == program) {
848 /* no-op */
849 return;
850 }
851
852 FLUSH_VERTICES(ctx, _NEW_PROGRAM);
853
Brian9e4bae92006-12-20 09:27:42 -0700854 /* unbind old */
855 if (ctx->Shader.CurrentProgram) {
856 ctx->Shader.CurrentProgram->RefCount--;
857 if (ctx->Shader.CurrentProgram->RefCount <= 0) {
858 _mesa_free_shader_program(ctx, ctx->Shader.CurrentProgram);
859 }
860 ctx->Shader.CurrentProgram = NULL;
861 }
862
Brian5b01c5e2006-12-19 18:02:03 -0700863 if (program) {
Brian65a18442006-12-19 18:46:56 -0700864 struct gl_shader_program *shProg;
865 shProg = _mesa_lookup_shader_program(ctx, program);
866 if (!shProg) {
Brian43975832007-01-04 08:21:09 -0700867 _mesa_error(ctx, GL_INVALID_VALUE,
Brian5b01c5e2006-12-19 18:02:03 -0700868 "glUseProgramObjectARB(programObj)");
869 return;
870 }
Brian65a18442006-12-19 18:46:56 -0700871 ctx->Shader.CurrentProgram = shProg;
Brian9e4bae92006-12-20 09:27:42 -0700872 shProg->RefCount++;
Brian5b01c5e2006-12-19 18:02:03 -0700873 }
874 else {
875 /* don't use a shader program */
876 ctx->Shader.CurrentProgram = NULL;
877 }
878}
Brian34ae99d2006-12-18 08:28:54 -0700879
Brian5b01c5e2006-12-19 18:02:03 -0700880
881/**
882 * Called via ctx->Driver.Uniform().
883 */
884void
885_mesa_uniform(GLcontext *ctx, GLint location, GLsizei count,
886 const GLvoid *values, GLenum type)
887{
Brian3a8e2772006-12-20 17:19:16 -0700888 struct gl_shader_program *shProg = ctx->Shader.CurrentProgram;
Brian98650bd2007-03-13 16:32:48 -0600889 GLint elems, i, k;
Brian3a8e2772006-12-20 17:19:16 -0700890
891 if (!shProg || !shProg->LinkStatus) {
Brian5b01c5e2006-12-19 18:02:03 -0700892 _mesa_error(ctx, GL_INVALID_OPERATION, "glUniform(program not linked)");
Brian3a8e2772006-12-20 17:19:16 -0700893 return;
894 }
895
Brian223d7cb2007-01-23 16:37:51 -0700896 if (location < 0 || location >= (GLint) shProg->Uniforms->NumParameters) {
Brian3a8e2772006-12-20 17:19:16 -0700897 _mesa_error(ctx, GL_INVALID_VALUE, "glUniform(location)");
898 return;
899 }
900
901 FLUSH_VERTICES(ctx, _NEW_PROGRAM);
902
Brianfee9bbe2007-02-02 18:05:43 -0700903 /*
904 * If we're setting a sampler, we must use glUniformi1()!
905 */
906 if (shProg->Uniforms->Parameters[location].Type == PROGRAM_SAMPLER) {
907 if (type != GL_INT || count != 1) {
908 _mesa_error(ctx, GL_INVALID_OPERATION,
909 "glUniform(only glUniform1i can be used "
910 "to set sampler uniforms)");
911 return;
912 }
913 }
914
Brian52363952007-03-13 16:50:24 -0600915 if (count < 0) {
916 _mesa_error(ctx, GL_INVALID_VALUE, "glUniform(count < 0)");
917 return;
918 }
919
Brian98650bd2007-03-13 16:32:48 -0600920 switch (type) {
921 case GL_FLOAT:
922 case GL_INT:
923 elems = 1;
924 break;
925 case GL_FLOAT_VEC2:
926 case GL_INT_VEC2:
927 elems = 2;
928 break;
929 case GL_FLOAT_VEC3:
930 case GL_INT_VEC3:
931 elems = 3;
932 break;
933 case GL_FLOAT_VEC4:
934 case GL_INT_VEC4:
935 elems = 4;
936 break;
937 default:
938 _mesa_problem(ctx, "Invalid type in _mesa_uniform");
939 return;
Brian89dc4852007-01-04 14:35:44 -0700940 }
Brian98650bd2007-03-13 16:32:48 -0600941
942 if (count * elems > shProg->Uniforms->Parameters[location].Size) {
943 _mesa_error(ctx, GL_INVALID_OPERATION, "glUniform(count too large)");
944 return;
945 }
946
947 for (k = 0; k < count; k++) {
948 GLfloat *uniformVal = shProg->Uniforms->ParameterValues[location + k];
949 if (type == GL_INT ||
950 type == GL_INT_VEC2 ||
951 type == GL_INT_VEC3 ||
952 type == GL_INT_VEC4) {
Brian52363952007-03-13 16:50:24 -0600953 const GLint *iValues = ((const GLint *) values) + k * elems;
Brian98650bd2007-03-13 16:32:48 -0600954 for (i = 0; i < elems; i++) {
955 uniformVal[i] = (GLfloat) iValues[i];
956 }
957 }
958 else {
Brian52363952007-03-13 16:50:24 -0600959 const GLfloat *fValues = ((const GLfloat *) values) + k * elems;
Brian98650bd2007-03-13 16:32:48 -0600960 for (i = 0; i < elems; i++) {
961 uniformVal[i] = fValues[i];
962 }
Brian89dc4852007-01-04 14:35:44 -0700963 }
Brian5b01c5e2006-12-19 18:02:03 -0700964 }
Brian5cf73262007-01-05 16:02:45 -0700965
966 if (shProg->Uniforms->Parameters[location].Type == PROGRAM_SAMPLER) {
Briancec81ee2007-03-07 08:04:06 -0700967 if (shProg->VertexProgram)
968 _slang_resolve_samplers(shProg, &shProg->VertexProgram->Base);
969 if (shProg->FragmentProgram)
970 _slang_resolve_samplers(shProg, &shProg->FragmentProgram->Base);
Brian5cf73262007-01-05 16:02:45 -0700971 FLUSH_VERTICES(ctx, _NEW_TEXTURE);
972 }
Brian34ae99d2006-12-18 08:28:54 -0700973}
974
975
976/**
Brian5b01c5e2006-12-19 18:02:03 -0700977 * Called by ctx->Driver.UniformMatrix().
Brian34ae99d2006-12-18 08:28:54 -0700978 */
Brian5b01c5e2006-12-19 18:02:03 -0700979void
980_mesa_uniform_matrix(GLcontext *ctx, GLint cols, GLint rows,
981 GLenum matrixType, GLint location, GLsizei count,
982 GLboolean transpose, const GLfloat *values)
Brian34ae99d2006-12-18 08:28:54 -0700983{
Brian3a8e2772006-12-20 17:19:16 -0700984 struct gl_shader_program *shProg = ctx->Shader.CurrentProgram;
985 if (!shProg || !shProg->LinkStatus) {
986 _mesa_error(ctx, GL_INVALID_OPERATION,
987 "glUniformMatrix(program not linked)");
988 return;
989 }
990 if (location < 0 || location >= shProg->Uniforms->NumParameters) {
991 _mesa_error(ctx, GL_INVALID_VALUE, "glUniformMatrix(location)");
992 return;
993 }
Brian34ae99d2006-12-18 08:28:54 -0700994 if (values == NULL) {
Brian3a8e2772006-12-20 17:19:16 -0700995 _mesa_error(ctx, GL_INVALID_VALUE, "glUniformMatrix");
Brian34ae99d2006-12-18 08:28:54 -0700996 return;
997 }
998
999 FLUSH_VERTICES(ctx, _NEW_PROGRAM);
1000
Brian3a8e2772006-12-20 17:19:16 -07001001 /*
1002 * Note: the _columns_ of a matrix are stored in program registers, not
1003 * the rows.
1004 */
1005 /* XXXX need to test 3x3 and 2x2 matrices... */
Brian34ae99d2006-12-18 08:28:54 -07001006 if (transpose) {
Brian3a8e2772006-12-20 17:19:16 -07001007 GLuint row, col;
1008 for (col = 0; col < cols; col++) {
1009 GLfloat *v = shProg->Uniforms->ParameterValues[location + col];
1010 for (row = 0; row < rows; row++) {
Brian9f442472007-03-09 11:34:18 -07001011 v[row] = values[row * cols + col];
Brian34ae99d2006-12-18 08:28:54 -07001012 }
Brian34ae99d2006-12-18 08:28:54 -07001013 }
Brian34ae99d2006-12-18 08:28:54 -07001014 }
1015 else {
Brian3a8e2772006-12-20 17:19:16 -07001016 GLuint row, col;
1017 for (col = 0; col < cols; col++) {
1018 GLfloat *v = shProg->Uniforms->ParameterValues[location + col];
1019 for (row = 0; row < rows; row++) {
Brian9f442472007-03-09 11:34:18 -07001020 v[row] = values[col * rows + row];
Brian3a8e2772006-12-20 17:19:16 -07001021 }
1022 }
Brian34ae99d2006-12-18 08:28:54 -07001023 }
1024}
1025
1026
Brian5b01c5e2006-12-19 18:02:03 -07001027void
1028_mesa_validate_program(GLcontext *ctx, GLuint program)
Brian34ae99d2006-12-18 08:28:54 -07001029{
Brian65a18442006-12-19 18:46:56 -07001030 struct gl_shader_program *shProg;
1031 shProg = _mesa_lookup_shader_program(ctx, program);
1032 if (!shProg) {
Brian43975832007-01-04 08:21:09 -07001033 _mesa_error(ctx, GL_INVALID_VALUE, "glValidateProgram(program)");
Brian34ae99d2006-12-18 08:28:54 -07001034 return;
1035 }
Brian5b01c5e2006-12-19 18:02:03 -07001036 /* XXX temporary */
Brian65a18442006-12-19 18:46:56 -07001037 shProg->Validated = GL_TRUE;
Brian34ae99d2006-12-18 08:28:54 -07001038
Brian5b01c5e2006-12-19 18:02:03 -07001039 /* From the GL spec:
1040 any two active samplers in the current program object are of
1041 different types, but refer to the same texture image unit,
1042
1043 any active sampler in the current program object refers to a texture
1044 image unit where fixed-function fragment processing accesses a
1045 texture target that does not match the sampler type, or
1046
1047 the sum of the number of active samplers in the program and the
1048 number of texture image units enabled for fixed-function fragment
1049 processing exceeds the combined limit on the total number of texture
1050 image units allowed.
1051 */
Brian34ae99d2006-12-18 08:28:54 -07001052}