blob: 88aa8c50f5bf39e4a5684aaa489c9a0514d2a33a [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;
Brian63556fa2007-03-23 14:47:46 -0600209 ctx->Shader.EmitCondCodes = GL_TRUE; /* XXX probably want GL_FALSE... */
Brianfa4d0362007-02-26 18:33:50 -0700210 ctx->Shader.EmitComments = GL_FALSE;
Brianf2923612006-12-20 09:56:44 -0700211}
212
213
Brian5b01c5e2006-12-19 18:02:03 -0700214/**
215 * Copy string from <src> to <dst>, up to maxLength characters, returning
216 * length of <dst> in <length>.
217 * \param src the strings source
218 * \param maxLength max chars to copy
219 * \param length returns number of chars copied
220 * \param dst the string destination
221 */
222static void
223copy_string(GLchar *dst, GLsizei maxLength, GLsizei *length, const GLchar *src)
224{
225 GLsizei len;
226 for (len = 0; len < maxLength - 1 && src && src[len]; len++)
227 dst[len] = src[len];
228 if (maxLength > 0)
229 dst[len] = 0;
230 if (length)
231 *length = len;
232}
233
234
Brian5b01c5e2006-12-19 18:02:03 -0700235/**
236 * Called via ctx->Driver.AttachShader()
237 */
238void
239_mesa_attach_shader(GLcontext *ctx, GLuint program, GLuint shader)
240{
Brian65a18442006-12-19 18:46:56 -0700241 struct gl_shader_program *shProg
242 = _mesa_lookup_shader_program(ctx, program);
243 struct gl_shader *sh = _mesa_lookup_shader(ctx, shader);
244 const GLuint n = shProg->NumShaders;
Brian5b01c5e2006-12-19 18:02:03 -0700245 GLuint i;
246
Brian65a18442006-12-19 18:46:56 -0700247 if (!shProg || !sh) {
Brian43975832007-01-04 08:21:09 -0700248 _mesa_error(ctx, GL_INVALID_VALUE,
Brian5b01c5e2006-12-19 18:02:03 -0700249 "glAttachShader(bad program or shader name)");
250 return;
251 }
252
253 for (i = 0; i < n; i++) {
Brian65a18442006-12-19 18:46:56 -0700254 if (shProg->Shaders[i] == sh) {
Brian5b01c5e2006-12-19 18:02:03 -0700255 /* already attached */
256 return;
Brian34ae99d2006-12-18 08:28:54 -0700257 }
258 }
Brian5b01c5e2006-12-19 18:02:03 -0700259
260 /* grow list */
Brian65a18442006-12-19 18:46:56 -0700261 shProg->Shaders = (struct gl_shader **)
262 _mesa_realloc(shProg->Shaders,
263 n * sizeof(struct gl_shader *),
264 (n + 1) * sizeof(struct gl_shader *));
265 if (!shProg->Shaders) {
Brian5b01c5e2006-12-19 18:02:03 -0700266 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glAttachShader");
267 return;
268 }
269
270 /* append */
Brian65a18442006-12-19 18:46:56 -0700271 shProg->Shaders[n] = sh;
272 sh->RefCount++;
273 shProg->NumShaders++;
Brian5b01c5e2006-12-19 18:02:03 -0700274}
275
276
277void
278_mesa_bind_attrib_location(GLcontext *ctx, GLuint program, GLuint index,
279 const GLchar *name)
280{
Brian65a18442006-12-19 18:46:56 -0700281 struct gl_shader_program *shProg
282 = _mesa_lookup_shader_program(ctx, program);
Brianb7978af2007-01-09 19:17:17 -0700283 const GLint size = -1; /* unknown size */
284 GLint i, oldIndex;
Brian5b01c5e2006-12-19 18:02:03 -0700285
Brian65a18442006-12-19 18:46:56 -0700286 if (!shProg) {
Brian43975832007-01-04 08:21:09 -0700287 _mesa_error(ctx, GL_INVALID_VALUE, "glBindAttribLocation(program)");
Brian5b01c5e2006-12-19 18:02:03 -0700288 return;
289 }
290
Brian9e4bae92006-12-20 09:27:42 -0700291 if (!name)
292 return;
293
294 if (strncmp(name, "gl_", 3) == 0) {
295 _mesa_error(ctx, GL_INVALID_OPERATION,
296 "glBindAttribLocation(illegal name)");
297 return;
298 }
299
Brian3209c3e2007-01-09 17:49:24 -0700300 oldIndex = _mesa_get_attrib_location(ctx, program, name);
301
302 /* this will replace the current value if it's already in the list */
Brianb7978af2007-01-09 19:17:17 -0700303 i = _mesa_add_attribute(shProg->Attributes, name, size, index);
Brian3209c3e2007-01-09 17:49:24 -0700304 if (i < 0) {
305 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBindAttribLocation");
306 }
307
308 if (shProg->VertexProgram && oldIndex >= 0) {
309 _slang_remap_attribute(&shProg->VertexProgram->Base, oldIndex, index);
310 }
311
Brian88e2dbf2007-01-10 13:33:38 -0700312#if 0
Brian3209c3e2007-01-09 17:49:24 -0700313 printf("===== post BindAttrib:\n");
314 _mesa_print_program(&shProg->VertexProgram->Base);
Brian88e2dbf2007-01-10 13:33:38 -0700315#endif
Brian34ae99d2006-12-18 08:28:54 -0700316}
317
318
Brian5b01c5e2006-12-19 18:02:03 -0700319GLuint
320_mesa_create_shader(GLcontext *ctx, GLenum type)
321{
Brian65a18442006-12-19 18:46:56 -0700322 struct gl_shader *sh;
Brian5b01c5e2006-12-19 18:02:03 -0700323 GLuint name;
324
325 name = _mesa_HashFindFreeKeyBlock(ctx->Shared->ShaderObjects, 1);
326
327 switch (type) {
Brian65a18442006-12-19 18:46:56 -0700328 case GL_FRAGMENT_SHADER:
329 case GL_VERTEX_SHADER:
330 sh = _mesa_new_shader(ctx, name, type);
Brian5b01c5e2006-12-19 18:02:03 -0700331 break;
332 default:
333 _mesa_error(ctx, GL_INVALID_ENUM, "CreateShader(type)");
334 return 0;
335 }
336
Brian65a18442006-12-19 18:46:56 -0700337 _mesa_HashInsert(ctx->Shared->ShaderObjects, name, sh);
Brian5b01c5e2006-12-19 18:02:03 -0700338
339 return name;
340}
341
342
343GLuint
344_mesa_create_program(GLcontext *ctx)
345{
346 GLuint name;
Brian65a18442006-12-19 18:46:56 -0700347 struct gl_shader_program *shProg;
Brian5b01c5e2006-12-19 18:02:03 -0700348
Brian65a18442006-12-19 18:46:56 -0700349 name = _mesa_HashFindFreeKeyBlock(ctx->Shared->ShaderObjects, 1);
350 shProg = _mesa_new_shader_program(ctx, name);
Brian5b01c5e2006-12-19 18:02:03 -0700351
Brian65a18442006-12-19 18:46:56 -0700352 _mesa_HashInsert(ctx->Shared->ShaderObjects, name, shProg);
Brian5b01c5e2006-12-19 18:02:03 -0700353
354 return name;
355}
356
357
358void
359_mesa_delete_program2(GLcontext *ctx, GLuint name)
360{
Brian65a18442006-12-19 18:46:56 -0700361 struct gl_shader_program *shProg;
Brian5b01c5e2006-12-19 18:02:03 -0700362
Brian65a18442006-12-19 18:46:56 -0700363 shProg = _mesa_lookup_shader_program(ctx, name);
364 if (!shProg) {
Brian43975832007-01-04 08:21:09 -0700365 _mesa_error(ctx, GL_INVALID_VALUE, "glDeleteProgram(name)");
Brian5b01c5e2006-12-19 18:02:03 -0700366 return;
367 }
368
Brian9e4bae92006-12-20 09:27:42 -0700369 /* always remove from hash table */
Brian65a18442006-12-19 18:46:56 -0700370 _mesa_HashRemove(ctx->Shared->ShaderObjects, name);
Brian9e4bae92006-12-20 09:27:42 -0700371
372 shProg->DeletePending = GL_TRUE;
373
374 /* decrement refcount, delete if zero */
375 shProg->RefCount--;
376 if (shProg->RefCount <= 0) {
377 _mesa_free_shader_program(ctx, shProg);
378 }
Brian5b01c5e2006-12-19 18:02:03 -0700379}
380
381
382void
383_mesa_delete_shader(GLcontext *ctx, GLuint shader)
384{
Brian9e4bae92006-12-20 09:27:42 -0700385 struct gl_shader *sh = _mesa_lookup_shader(ctx, shader);
386 if (!sh) {
387 return;
388 }
Brian5b01c5e2006-12-19 18:02:03 -0700389
Brian9e4bae92006-12-20 09:27:42 -0700390 sh->DeletePending = GL_TRUE;
391 sh->RefCount--;
392 if (sh->RefCount <= 0) {
393 _mesa_free_shader(ctx, sh);
394 }
Brian5b01c5e2006-12-19 18:02:03 -0700395}
396
397
398void
399_mesa_detach_shader(GLcontext *ctx, GLuint program, GLuint shader)
400{
Brian65a18442006-12-19 18:46:56 -0700401 struct gl_shader_program *shProg
402 = _mesa_lookup_shader_program(ctx, program);
403 const GLuint n = shProg->NumShaders;
Brian5b01c5e2006-12-19 18:02:03 -0700404 GLuint i, j;
405
Brian65a18442006-12-19 18:46:56 -0700406 if (!shProg) {
Brian43975832007-01-04 08:21:09 -0700407 _mesa_error(ctx, GL_INVALID_VALUE,
Brian5b01c5e2006-12-19 18:02:03 -0700408 "glDetachShader(bad program or shader name)");
409 return;
410 }
411
412 for (i = 0; i < n; i++) {
Brian65a18442006-12-19 18:46:56 -0700413 if (shProg->Shaders[i]->Name == shader) {
414 struct gl_shader **newList;
Brian5b01c5e2006-12-19 18:02:03 -0700415 /* found it */
Brian9e4bae92006-12-20 09:27:42 -0700416
417 shProg->Shaders[i]->RefCount--;
418
Brian5b01c5e2006-12-19 18:02:03 -0700419 /* alloc new, smaller array */
Brian65a18442006-12-19 18:46:56 -0700420 newList = (struct gl_shader **)
421 _mesa_malloc((n - 1) * sizeof(struct gl_shader *));
Brian5b01c5e2006-12-19 18:02:03 -0700422 if (!newList) {
423 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glDetachShader");
424 return;
425 }
426 for (j = 0; j < i; j++) {
Brian65a18442006-12-19 18:46:56 -0700427 newList[j] = shProg->Shaders[j];
Brian5b01c5e2006-12-19 18:02:03 -0700428 }
429 while (++i < n)
Brian65a18442006-12-19 18:46:56 -0700430 newList[j++] = shProg->Shaders[i];
431 _mesa_free(shProg->Shaders);
Brian5b01c5e2006-12-19 18:02:03 -0700432
433 /* XXX refcounting! */
434
Brian65a18442006-12-19 18:46:56 -0700435 shProg->Shaders = newList;
Brian5b01c5e2006-12-19 18:02:03 -0700436 return;
437 }
438 }
439
440 /* not found */
Brian43975832007-01-04 08:21:09 -0700441 _mesa_error(ctx, GL_INVALID_VALUE,
Brian5b01c5e2006-12-19 18:02:03 -0700442 "glDetachShader(shader not found)");
443}
444
445
446void
447_mesa_get_active_attrib(GLcontext *ctx, GLuint program, GLuint index,
448 GLsizei maxLength, GLsizei *length, GLint *size,
449 GLenum *type, GLchar *nameOut)
450{
451 static const GLenum vec_types[] = {
452 GL_FLOAT, GL_FLOAT_VEC2, GL_FLOAT_VEC3, GL_FLOAT_VEC4
453 };
Brian65a18442006-12-19 18:46:56 -0700454 struct gl_shader_program *shProg
455 = _mesa_lookup_shader_program(ctx, program);
Brian5b01c5e2006-12-19 18:02:03 -0700456 GLint sz;
457
Brian65a18442006-12-19 18:46:56 -0700458 if (!shProg) {
Brian43975832007-01-04 08:21:09 -0700459 _mesa_error(ctx, GL_INVALID_VALUE, "glGetActiveUniform");
Brian5b01c5e2006-12-19 18:02:03 -0700460 return;
461 }
462
Brian65a18442006-12-19 18:46:56 -0700463 if (!shProg->Attributes || index >= shProg->Attributes->NumParameters) {
Brian5b01c5e2006-12-19 18:02:03 -0700464 _mesa_error(ctx, GL_INVALID_VALUE, "glGetActiveUniform(index)");
465 return;
466 }
467
468 copy_string(nameOut, maxLength, length,
Brian65a18442006-12-19 18:46:56 -0700469 shProg->Attributes->Parameters[index].Name);
470 sz = shProg->Attributes->Parameters[index].Size;
Brian5b01c5e2006-12-19 18:02:03 -0700471 if (size)
472 *size = sz;
473 if (type)
474 *type = vec_types[sz]; /* XXX this is a temporary hack */
475}
476
477
478/**
479 * Called via ctx->Driver.GetActiveUniform().
480 */
481void
482_mesa_get_active_uniform(GLcontext *ctx, GLuint program, GLuint index,
483 GLsizei maxLength, GLsizei *length, GLint *size,
484 GLenum *type, GLchar *nameOut)
485{
486 static const GLenum vec_types[] = {
487 GL_FLOAT, GL_FLOAT_VEC2, GL_FLOAT_VEC3, GL_FLOAT_VEC4
488 };
Brian65a18442006-12-19 18:46:56 -0700489 struct gl_shader_program *shProg
490 = _mesa_lookup_shader_program(ctx, program);
Brian5b01c5e2006-12-19 18:02:03 -0700491 GLint sz;
492
Brian65a18442006-12-19 18:46:56 -0700493 if (!shProg) {
Brian43975832007-01-04 08:21:09 -0700494 _mesa_error(ctx, GL_INVALID_VALUE, "glGetActiveUniform");
Brian5b01c5e2006-12-19 18:02:03 -0700495 return;
496 }
497
Brian65a18442006-12-19 18:46:56 -0700498 if (!shProg->Uniforms || index >= shProg->Uniforms->NumParameters) {
Brian5b01c5e2006-12-19 18:02:03 -0700499 _mesa_error(ctx, GL_INVALID_VALUE, "glGetActiveUniform(index)");
500 return;
501 }
502
503 copy_string(nameOut, maxLength, length,
Brian65a18442006-12-19 18:46:56 -0700504 shProg->Uniforms->Parameters[index].Name);
505 sz = shProg->Uniforms->Parameters[index].Size;
Brian5b01c5e2006-12-19 18:02:03 -0700506 if (size)
507 *size = sz;
508 if (type)
509 *type = vec_types[sz]; /* XXX this is a temporary hack */
510}
511
512
513/**
514 * Called via ctx->Driver.GetAttachedShaders().
515 */
516void
517_mesa_get_attached_shaders(GLcontext *ctx, GLuint program, GLsizei maxCount,
518 GLsizei *count, GLuint *obj)
519{
Brian65a18442006-12-19 18:46:56 -0700520 struct gl_shader_program *shProg
521 = _mesa_lookup_shader_program(ctx, program);
522 if (shProg) {
Brian223d7cb2007-01-23 16:37:51 -0700523 GLint i;
Brian65a18442006-12-19 18:46:56 -0700524 for (i = 0; i < maxCount && i < shProg->NumShaders; i++) {
525 obj[i] = shProg->Shaders[i]->Name;
Brian5b01c5e2006-12-19 18:02:03 -0700526 }
527 if (count)
528 *count = i;
529 }
530 else {
Brian43975832007-01-04 08:21:09 -0700531 _mesa_error(ctx, GL_INVALID_VALUE, "glGetAttachedShaders");
Brian5b01c5e2006-12-19 18:02:03 -0700532 }
533}
534
535
536GLint
537_mesa_get_attrib_location(GLcontext *ctx, GLuint program,
538 const GLchar *name)
539{
Brian65a18442006-12-19 18:46:56 -0700540 struct gl_shader_program *shProg
541 = _mesa_lookup_shader_program(ctx, program);
Brian5b01c5e2006-12-19 18:02:03 -0700542
Brian65a18442006-12-19 18:46:56 -0700543 if (!shProg) {
Brian43975832007-01-04 08:21:09 -0700544 _mesa_error(ctx, GL_INVALID_VALUE, "glGetAttribLocation");
Brian5b01c5e2006-12-19 18:02:03 -0700545 return -1;
546 }
547
Brian65a18442006-12-19 18:46:56 -0700548 if (!shProg->LinkStatus) {
Brian5b01c5e2006-12-19 18:02:03 -0700549 _mesa_error(ctx, GL_INVALID_OPERATION,
550 "glGetAttribLocation(program not linked)");
551 return -1;
552 }
553
554 if (!name)
555 return -1;
556
Brian65a18442006-12-19 18:46:56 -0700557 if (shProg->Attributes) {
Brian3209c3e2007-01-09 17:49:24 -0700558 GLint i = _mesa_lookup_parameter_index(shProg->Attributes, -1, name);
559 if (i >= 0) {
Brian01a91eb2007-01-09 19:26:22 -0700560 return shProg->Attributes->Parameters[i].StateIndexes[0];
Brian5b01c5e2006-12-19 18:02:03 -0700561 }
562 }
563 return -1;
564}
565
566
567GLuint
568_mesa_get_handle(GLcontext *ctx, GLenum pname)
Brian34ae99d2006-12-18 08:28:54 -0700569{
570#if 0
571 GET_CURRENT_CONTEXT(ctx);
572
573 switch (pname) {
574 case GL_PROGRAM_OBJECT_ARB:
575 {
Brian5b01c5e2006-12-19 18:02:03 -0700576 struct gl2_program_intf **pro = ctx->Shader.CurrentProgram;
Brian34ae99d2006-12-18 08:28:54 -0700577
578 if (pro != NULL)
579 return (**pro)._container._generic.
580 GetName((struct gl2_generic_intf **) (pro));
581 }
582 break;
583 default:
584 _mesa_error(ctx, GL_INVALID_ENUM, "glGetHandleARB");
585 }
586#endif
587 return 0;
588}
589
590
Brian5b01c5e2006-12-19 18:02:03 -0700591void
592_mesa_get_programiv(GLcontext *ctx, GLuint program,
593 GLenum pname, GLint *params)
Brian34ae99d2006-12-18 08:28:54 -0700594{
Brian65a18442006-12-19 18:46:56 -0700595 struct gl_shader_program *shProg
596 = _mesa_lookup_shader_program(ctx, program);
Brian34ae99d2006-12-18 08:28:54 -0700597
Brian65a18442006-12-19 18:46:56 -0700598 if (!shProg) {
Brian5b01c5e2006-12-19 18:02:03 -0700599 _mesa_error(ctx, GL_INVALID_VALUE, "glGetProgramiv(program)");
Brian34ae99d2006-12-18 08:28:54 -0700600 return;
601 }
602
Brian5b01c5e2006-12-19 18:02:03 -0700603 switch (pname) {
604 case GL_DELETE_STATUS:
Brian65a18442006-12-19 18:46:56 -0700605 *params = shProg->DeletePending;
Brian5b01c5e2006-12-19 18:02:03 -0700606 break;
607 case GL_LINK_STATUS:
Brian65a18442006-12-19 18:46:56 -0700608 *params = shProg->LinkStatus;
Brian34ae99d2006-12-18 08:28:54 -0700609 break;
Brian5b01c5e2006-12-19 18:02:03 -0700610 case GL_VALIDATE_STATUS:
Brian65a18442006-12-19 18:46:56 -0700611 *params = shProg->Validated;
Brian5b01c5e2006-12-19 18:02:03 -0700612 break;
613 case GL_INFO_LOG_LENGTH:
Brian65a18442006-12-19 18:46:56 -0700614 *params = shProg->InfoLog ? strlen(shProg->InfoLog) : 0;
Brian5b01c5e2006-12-19 18:02:03 -0700615 break;
616 case GL_ATTACHED_SHADERS:
Brian65a18442006-12-19 18:46:56 -0700617 *params = shProg->NumShaders;
Brian5b01c5e2006-12-19 18:02:03 -0700618 break;
619 case GL_ACTIVE_ATTRIBUTES:
Brian3209c3e2007-01-09 17:49:24 -0700620 *params = shProg->Attributes ? shProg->Attributes->NumParameters : 0;
Brian5b01c5e2006-12-19 18:02:03 -0700621 break;
622 case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH:
Brian65a18442006-12-19 18:46:56 -0700623 *params = _mesa_parameter_longest_name(shProg->Attributes);
Brian5b01c5e2006-12-19 18:02:03 -0700624 break;
625 case GL_ACTIVE_UNIFORMS:
Brian65a18442006-12-19 18:46:56 -0700626 *params = shProg->Uniforms ? shProg->Uniforms->NumParameters : 0;
Brian5b01c5e2006-12-19 18:02:03 -0700627 break;
628 case GL_ACTIVE_UNIFORM_MAX_LENGTH:
Brian65a18442006-12-19 18:46:56 -0700629 *params = _mesa_parameter_longest_name(shProg->Uniforms);
Brian34ae99d2006-12-18 08:28:54 -0700630 break;
631 default:
Brian5b01c5e2006-12-19 18:02:03 -0700632 _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramiv(pname)");
633 return;
Brian34ae99d2006-12-18 08:28:54 -0700634 }
Brian5b01c5e2006-12-19 18:02:03 -0700635}
Brian34ae99d2006-12-18 08:28:54 -0700636
Brian34ae99d2006-12-18 08:28:54 -0700637
Brian5b01c5e2006-12-19 18:02:03 -0700638void
639_mesa_get_shaderiv(GLcontext *ctx, GLuint name, GLenum pname, GLint *params)
640{
Brian65a18442006-12-19 18:46:56 -0700641 struct gl_shader *shader = _mesa_lookup_shader(ctx, name);
Brian5b01c5e2006-12-19 18:02:03 -0700642
643 if (!shader) {
644 _mesa_error(ctx, GL_INVALID_VALUE, "glGetShaderiv(shader)");
645 return;
646 }
Brian65a18442006-12-19 18:46:56 -0700647
Brian5b01c5e2006-12-19 18:02:03 -0700648 switch (pname) {
649 case GL_SHADER_TYPE:
650 *params = shader->Type;
651 break;
652 case GL_DELETE_STATUS:
653 *params = shader->DeletePending;
654 break;
655 case GL_COMPILE_STATUS:
656 *params = shader->CompileStatus;
657 break;
658 case GL_INFO_LOG_LENGTH:
659 *params = shader->InfoLog ? strlen(shader->InfoLog) : 0;
660 break;
661 case GL_SHADER_SOURCE_LENGTH:
662 *params = shader->Source ? strlen((char *) shader->Source) : 0;
663 break;
664 default:
665 _mesa_error(ctx, GL_INVALID_ENUM, "glGetShaderiv(pname)");
666 return;
667 }
668}
669
670
671void
672_mesa_get_program_info_log(GLcontext *ctx, GLuint program, GLsizei bufSize,
673 GLsizei *length, GLchar *infoLog)
674{
Brian65a18442006-12-19 18:46:56 -0700675 struct gl_shader_program *shProg
676 = _mesa_lookup_shader_program(ctx, program);
677 if (!shProg) {
Brian5b01c5e2006-12-19 18:02:03 -0700678 _mesa_error(ctx, GL_INVALID_VALUE, "glGetProgramInfoLog(program)");
679 return;
680 }
Brian65a18442006-12-19 18:46:56 -0700681 copy_string(infoLog, bufSize, length, shProg->InfoLog);
Brian5b01c5e2006-12-19 18:02:03 -0700682}
683
684
685void
686_mesa_get_shader_info_log(GLcontext *ctx, GLuint shader, GLsizei bufSize,
687 GLsizei *length, GLchar *infoLog)
688{
Brian65a18442006-12-19 18:46:56 -0700689 struct gl_shader *sh = _mesa_lookup_shader(ctx, shader);
690 if (!sh) {
Brian5b01c5e2006-12-19 18:02:03 -0700691 _mesa_error(ctx, GL_INVALID_VALUE, "glGetShaderInfoLog(shader)");
692 return;
693 }
Brian65a18442006-12-19 18:46:56 -0700694 copy_string(infoLog, bufSize, length, sh->InfoLog);
Brian5b01c5e2006-12-19 18:02:03 -0700695}
696
697
698/**
699 * Called via ctx->Driver.GetShaderSource().
700 */
701void
702_mesa_get_shader_source(GLcontext *ctx, GLuint shader, GLsizei maxLength,
703 GLsizei *length, GLchar *sourceOut)
704{
Brian65a18442006-12-19 18:46:56 -0700705 struct gl_shader *sh = _mesa_lookup_shader(ctx, shader);
706 if (!sh) {
Brian5b01c5e2006-12-19 18:02:03 -0700707 _mesa_error(ctx, GL_INVALID_VALUE, "glGetShaderSource(shader)");
708 return;
709 }
Brian65a18442006-12-19 18:46:56 -0700710 copy_string(sourceOut, maxLength, length, sh->Source);
Brian5b01c5e2006-12-19 18:02:03 -0700711}
712
713
714/**
715 * Called via ctx->Driver.GetUniformfv().
716 */
717void
718_mesa_get_uniformfv(GLcontext *ctx, GLuint program, GLint location,
719 GLfloat *params)
720{
Brian65a18442006-12-19 18:46:56 -0700721 struct gl_shader_program *shProg
722 = _mesa_lookup_shader_program(ctx, program);
723 if (shProg) {
Brian223d7cb2007-01-23 16:37:51 -0700724 GLint i;
Brian65a18442006-12-19 18:46:56 -0700725 if (location >= 0 && location < shProg->Uniforms->NumParameters) {
726 for (i = 0; i < shProg->Uniforms->Parameters[location].Size; i++) {
727 params[i] = shProg->Uniforms->ParameterValues[location][i];
Brian5b01c5e2006-12-19 18:02:03 -0700728 }
729 }
730 else {
731 _mesa_error(ctx, GL_INVALID_VALUE, "glGetUniformfv(location)");
732 }
733 }
734 else {
Brian43975832007-01-04 08:21:09 -0700735 _mesa_error(ctx, GL_INVALID_VALUE, "glGetUniformfv(program)");
Brian5b01c5e2006-12-19 18:02:03 -0700736 }
737}
738
739
740/**
741 * Called via ctx->Driver.GetUniformLocation().
742 */
743GLint
744_mesa_get_uniform_location(GLcontext *ctx, GLuint program, const GLchar *name)
745{
Brian71623982007-01-30 16:55:03 -0700746 struct gl_shader_program *shProg
747 = _mesa_lookup_shader_program(ctx, program);
748 if (shProg) {
Brian5b01c5e2006-12-19 18:02:03 -0700749 GLuint loc;
Brian65a18442006-12-19 18:46:56 -0700750 for (loc = 0; loc < shProg->Uniforms->NumParameters; loc++) {
Brian5b01c5e2006-12-19 18:02:03 -0700751 const struct gl_program_parameter *u
Brian65a18442006-12-19 18:46:56 -0700752 = shProg->Uniforms->Parameters + loc;
Brian29053852006-12-21 11:21:26 -0700753 /* XXX this is a temporary simplification / short-cut.
754 * We need to handle things like "e.c[0].b" as seen in the
755 * GLSL orange book, page 189.
756 */
Brian5cf73262007-01-05 16:02:45 -0700757 if ((u->Type == PROGRAM_UNIFORM ||
758 u->Type == PROGRAM_SAMPLER) && !strcmp(u->Name, name)) {
Brian5b01c5e2006-12-19 18:02:03 -0700759 return loc;
760 }
761 }
762 }
763 return -1;
764
765}
766
767
768GLboolean
769_mesa_is_program(GLcontext *ctx, GLuint name)
770{
Brian65a18442006-12-19 18:46:56 -0700771 struct gl_shader_program *shProg = _mesa_lookup_shader_program(ctx, name);
772 return shProg ? GL_TRUE : GL_FALSE;
Brian5b01c5e2006-12-19 18:02:03 -0700773}
774
775
776GLboolean
777_mesa_is_shader(GLcontext *ctx, GLuint name)
778{
Brian65a18442006-12-19 18:46:56 -0700779 struct gl_shader *shader = _mesa_lookup_shader(ctx, name);
Brian5b01c5e2006-12-19 18:02:03 -0700780 return shader ? GL_TRUE : GL_FALSE;
Brian34ae99d2006-12-18 08:28:54 -0700781}
782
783
784
Brian5b01c5e2006-12-19 18:02:03 -0700785/**
786 * Called via ctx->Driver.ShaderSource()
787 */
788void
789_mesa_shader_source(GLcontext *ctx, GLuint shader, const GLchar *source)
Brian34ae99d2006-12-18 08:28:54 -0700790{
Brian65a18442006-12-19 18:46:56 -0700791 struct gl_shader *sh = _mesa_lookup_shader(ctx, shader);
792 if (!sh) {
Brian5b01c5e2006-12-19 18:02:03 -0700793 _mesa_error(ctx, GL_INVALID_VALUE, "glShaderSource(shaderObj)");
Brian34ae99d2006-12-18 08:28:54 -0700794 return;
795 }
796
Brian34ae99d2006-12-18 08:28:54 -0700797 /* free old shader source string and install new one */
Brian65a18442006-12-19 18:46:56 -0700798 if (sh->Source) {
799 _mesa_free((void *) sh->Source);
Brian34ae99d2006-12-18 08:28:54 -0700800 }
Brian65a18442006-12-19 18:46:56 -0700801 sh->Source = source;
Brian9e4bae92006-12-20 09:27:42 -0700802 sh->CompileStatus = GL_FALSE;
Brian34ae99d2006-12-18 08:28:54 -0700803}
804
805
Brian5b01c5e2006-12-19 18:02:03 -0700806/**
807 * Called via ctx->Driver.CompileShader()
808 */
809void
810_mesa_compile_shader(GLcontext *ctx, GLuint shaderObj)
Brian34ae99d2006-12-18 08:28:54 -0700811{
Brian65a18442006-12-19 18:46:56 -0700812 struct gl_shader *sh = _mesa_lookup_shader(ctx, shaderObj);
Brian34ae99d2006-12-18 08:28:54 -0700813
Brian65a18442006-12-19 18:46:56 -0700814 if (!sh) {
Brian34ae99d2006-12-18 08:28:54 -0700815 _mesa_error(ctx, GL_INVALID_VALUE, "glCompileShader(shaderObj)");
816 return;
817 }
818
Brian43975832007-01-04 08:21:09 -0700819 sh->CompileStatus = _slang_compile(ctx, sh);
Brian34ae99d2006-12-18 08:28:54 -0700820}
821
822
Brian5b01c5e2006-12-19 18:02:03 -0700823/**
824 * Called via ctx->Driver.LinkProgram()
825 */
826void
827_mesa_link_program(GLcontext *ctx, GLuint program)
Brian34ae99d2006-12-18 08:28:54 -0700828{
Brian65a18442006-12-19 18:46:56 -0700829 struct gl_shader_program *shProg;
Brian34ae99d2006-12-18 08:28:54 -0700830
Brian65a18442006-12-19 18:46:56 -0700831 shProg = _mesa_lookup_shader_program(ctx, program);
832 if (!shProg) {
Brian43975832007-01-04 08:21:09 -0700833 _mesa_error(ctx, GL_INVALID_VALUE, "glLinkProgram(program)");
Brian34ae99d2006-12-18 08:28:54 -0700834 return;
835 }
836
Brianc1771912007-02-16 09:56:19 -0700837 _slang_link(ctx, program, shProg);
Brian34ae99d2006-12-18 08:28:54 -0700838}
839
840
841/**
Brian5b01c5e2006-12-19 18:02:03 -0700842 * Called via ctx->Driver.UseProgram()
Brian34ae99d2006-12-18 08:28:54 -0700843 */
Brian5b01c5e2006-12-19 18:02:03 -0700844void
845_mesa_use_program(GLcontext *ctx, GLuint program)
Brian34ae99d2006-12-18 08:28:54 -0700846{
Brian00d63aa2007-02-03 11:35:02 -0700847 if (ctx->Shader.CurrentProgram &&
848 ctx->Shader.CurrentProgram->Name == program) {
849 /* no-op */
850 return;
851 }
852
853 FLUSH_VERTICES(ctx, _NEW_PROGRAM);
854
Brian9e4bae92006-12-20 09:27:42 -0700855 /* unbind old */
856 if (ctx->Shader.CurrentProgram) {
857 ctx->Shader.CurrentProgram->RefCount--;
858 if (ctx->Shader.CurrentProgram->RefCount <= 0) {
859 _mesa_free_shader_program(ctx, ctx->Shader.CurrentProgram);
860 }
861 ctx->Shader.CurrentProgram = NULL;
862 }
863
Brian5b01c5e2006-12-19 18:02:03 -0700864 if (program) {
Brian65a18442006-12-19 18:46:56 -0700865 struct gl_shader_program *shProg;
866 shProg = _mesa_lookup_shader_program(ctx, program);
867 if (!shProg) {
Brian43975832007-01-04 08:21:09 -0700868 _mesa_error(ctx, GL_INVALID_VALUE,
Brian5b01c5e2006-12-19 18:02:03 -0700869 "glUseProgramObjectARB(programObj)");
870 return;
871 }
Brian65a18442006-12-19 18:46:56 -0700872 ctx->Shader.CurrentProgram = shProg;
Brian9e4bae92006-12-20 09:27:42 -0700873 shProg->RefCount++;
Brian5b01c5e2006-12-19 18:02:03 -0700874 }
875 else {
876 /* don't use a shader program */
877 ctx->Shader.CurrentProgram = NULL;
878 }
879}
Brian34ae99d2006-12-18 08:28:54 -0700880
Brian5b01c5e2006-12-19 18:02:03 -0700881
882/**
883 * Called via ctx->Driver.Uniform().
884 */
885void
886_mesa_uniform(GLcontext *ctx, GLint location, GLsizei count,
887 const GLvoid *values, GLenum type)
888{
Brian3a8e2772006-12-20 17:19:16 -0700889 struct gl_shader_program *shProg = ctx->Shader.CurrentProgram;
Brian98650bd2007-03-13 16:32:48 -0600890 GLint elems, i, k;
Brian3a8e2772006-12-20 17:19:16 -0700891
892 if (!shProg || !shProg->LinkStatus) {
Brian5b01c5e2006-12-19 18:02:03 -0700893 _mesa_error(ctx, GL_INVALID_OPERATION, "glUniform(program not linked)");
Brian3a8e2772006-12-20 17:19:16 -0700894 return;
895 }
896
Brian223d7cb2007-01-23 16:37:51 -0700897 if (location < 0 || location >= (GLint) shProg->Uniforms->NumParameters) {
Brian3a8e2772006-12-20 17:19:16 -0700898 _mesa_error(ctx, GL_INVALID_VALUE, "glUniform(location)");
899 return;
900 }
901
902 FLUSH_VERTICES(ctx, _NEW_PROGRAM);
903
Brianfee9bbe2007-02-02 18:05:43 -0700904 /*
905 * If we're setting a sampler, we must use glUniformi1()!
906 */
907 if (shProg->Uniforms->Parameters[location].Type == PROGRAM_SAMPLER) {
908 if (type != GL_INT || count != 1) {
909 _mesa_error(ctx, GL_INVALID_OPERATION,
910 "glUniform(only glUniform1i can be used "
911 "to set sampler uniforms)");
912 return;
913 }
914 }
915
Brian52363952007-03-13 16:50:24 -0600916 if (count < 0) {
917 _mesa_error(ctx, GL_INVALID_VALUE, "glUniform(count < 0)");
918 return;
919 }
920
Brian98650bd2007-03-13 16:32:48 -0600921 switch (type) {
922 case GL_FLOAT:
923 case GL_INT:
924 elems = 1;
925 break;
926 case GL_FLOAT_VEC2:
927 case GL_INT_VEC2:
928 elems = 2;
929 break;
930 case GL_FLOAT_VEC3:
931 case GL_INT_VEC3:
932 elems = 3;
933 break;
934 case GL_FLOAT_VEC4:
935 case GL_INT_VEC4:
936 elems = 4;
937 break;
938 default:
939 _mesa_problem(ctx, "Invalid type in _mesa_uniform");
940 return;
Brian89dc4852007-01-04 14:35:44 -0700941 }
Brian98650bd2007-03-13 16:32:48 -0600942
943 if (count * elems > shProg->Uniforms->Parameters[location].Size) {
944 _mesa_error(ctx, GL_INVALID_OPERATION, "glUniform(count too large)");
945 return;
946 }
947
948 for (k = 0; k < count; k++) {
949 GLfloat *uniformVal = shProg->Uniforms->ParameterValues[location + k];
950 if (type == GL_INT ||
951 type == GL_INT_VEC2 ||
952 type == GL_INT_VEC3 ||
953 type == GL_INT_VEC4) {
Brian52363952007-03-13 16:50:24 -0600954 const GLint *iValues = ((const GLint *) values) + k * elems;
Brian98650bd2007-03-13 16:32:48 -0600955 for (i = 0; i < elems; i++) {
956 uniformVal[i] = (GLfloat) iValues[i];
957 }
958 }
959 else {
Brian52363952007-03-13 16:50:24 -0600960 const GLfloat *fValues = ((const GLfloat *) values) + k * elems;
Brian98650bd2007-03-13 16:32:48 -0600961 for (i = 0; i < elems; i++) {
962 uniformVal[i] = fValues[i];
963 }
Brian89dc4852007-01-04 14:35:44 -0700964 }
Brian5b01c5e2006-12-19 18:02:03 -0700965 }
Brian5cf73262007-01-05 16:02:45 -0700966
967 if (shProg->Uniforms->Parameters[location].Type == PROGRAM_SAMPLER) {
Briancec81ee2007-03-07 08:04:06 -0700968 if (shProg->VertexProgram)
969 _slang_resolve_samplers(shProg, &shProg->VertexProgram->Base);
970 if (shProg->FragmentProgram)
971 _slang_resolve_samplers(shProg, &shProg->FragmentProgram->Base);
Brian5cf73262007-01-05 16:02:45 -0700972 FLUSH_VERTICES(ctx, _NEW_TEXTURE);
973 }
Brian34ae99d2006-12-18 08:28:54 -0700974}
975
976
977/**
Brian5b01c5e2006-12-19 18:02:03 -0700978 * Called by ctx->Driver.UniformMatrix().
Brian34ae99d2006-12-18 08:28:54 -0700979 */
Brian5b01c5e2006-12-19 18:02:03 -0700980void
981_mesa_uniform_matrix(GLcontext *ctx, GLint cols, GLint rows,
982 GLenum matrixType, GLint location, GLsizei count,
983 GLboolean transpose, const GLfloat *values)
Brian34ae99d2006-12-18 08:28:54 -0700984{
Brian3a8e2772006-12-20 17:19:16 -0700985 struct gl_shader_program *shProg = ctx->Shader.CurrentProgram;
986 if (!shProg || !shProg->LinkStatus) {
987 _mesa_error(ctx, GL_INVALID_OPERATION,
988 "glUniformMatrix(program not linked)");
989 return;
990 }
991 if (location < 0 || location >= shProg->Uniforms->NumParameters) {
992 _mesa_error(ctx, GL_INVALID_VALUE, "glUniformMatrix(location)");
993 return;
994 }
Brian34ae99d2006-12-18 08:28:54 -0700995 if (values == NULL) {
Brian3a8e2772006-12-20 17:19:16 -0700996 _mesa_error(ctx, GL_INVALID_VALUE, "glUniformMatrix");
Brian34ae99d2006-12-18 08:28:54 -0700997 return;
998 }
999
1000 FLUSH_VERTICES(ctx, _NEW_PROGRAM);
1001
Brian3a8e2772006-12-20 17:19:16 -07001002 /*
1003 * Note: the _columns_ of a matrix are stored in program registers, not
1004 * the rows.
1005 */
1006 /* XXXX need to test 3x3 and 2x2 matrices... */
Brian34ae99d2006-12-18 08:28:54 -07001007 if (transpose) {
Brian3a8e2772006-12-20 17:19:16 -07001008 GLuint row, col;
1009 for (col = 0; col < cols; col++) {
1010 GLfloat *v = shProg->Uniforms->ParameterValues[location + col];
1011 for (row = 0; row < rows; row++) {
Brian9f442472007-03-09 11:34:18 -07001012 v[row] = values[row * cols + col];
Brian34ae99d2006-12-18 08:28:54 -07001013 }
Brian34ae99d2006-12-18 08:28:54 -07001014 }
Brian34ae99d2006-12-18 08:28:54 -07001015 }
1016 else {
Brian3a8e2772006-12-20 17:19:16 -07001017 GLuint row, col;
1018 for (col = 0; col < cols; col++) {
1019 GLfloat *v = shProg->Uniforms->ParameterValues[location + col];
1020 for (row = 0; row < rows; row++) {
Brian9f442472007-03-09 11:34:18 -07001021 v[row] = values[col * rows + row];
Brian3a8e2772006-12-20 17:19:16 -07001022 }
1023 }
Brian34ae99d2006-12-18 08:28:54 -07001024 }
1025}
1026
1027
Brian5b01c5e2006-12-19 18:02:03 -07001028void
1029_mesa_validate_program(GLcontext *ctx, GLuint program)
Brian34ae99d2006-12-18 08:28:54 -07001030{
Brian65a18442006-12-19 18:46:56 -07001031 struct gl_shader_program *shProg;
1032 shProg = _mesa_lookup_shader_program(ctx, program);
1033 if (!shProg) {
Brian43975832007-01-04 08:21:09 -07001034 _mesa_error(ctx, GL_INVALID_VALUE, "glValidateProgram(program)");
Brian34ae99d2006-12-18 08:28:54 -07001035 return;
1036 }
Brian5b01c5e2006-12-19 18:02:03 -07001037 /* XXX temporary */
Brian65a18442006-12-19 18:46:56 -07001038 shProg->Validated = GL_TRUE;
Brian34ae99d2006-12-18 08:28:54 -07001039
Brian5b01c5e2006-12-19 18:02:03 -07001040 /* From the GL spec:
1041 any two active samplers in the current program object are of
1042 different types, but refer to the same texture image unit,
1043
1044 any active sampler in the current program object refers to a texture
1045 image unit where fixed-function fragment processing accesses a
1046 texture target that does not match the sampler type, or
1047
1048 the sum of the number of active samplers in the program and the
1049 number of texture image units enabled for fixed-function fragment
1050 processing exceeds the combined limit on the total number of texture
1051 image units allowed.
1052 */
Brian34ae99d2006-12-18 08:28:54 -07001053}