blob: 004c9c8ec3adf059f591c8b61250b060cb89fca3 [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) {
Brianf3e8c322007-04-18 14:53:23 -060061 shProg->Type = GL_SHADER_PROGRAM_MESA;
Brianf2923612006-12-20 09:56:44 -070062 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
Brianb9fbedd2007-03-26 09:23:44 -060070/**
Brian3c008a02007-04-12 15:22:32 -060071 * Clear (free) the shader program state that gets produced by linking.
Brianb9fbedd2007-03-26 09:23:44 -060072 */
Brianf2923612006-12-20 09:56:44 -070073void
Brian3c008a02007-04-12 15:22:32 -060074_mesa_clear_shader_program_data(GLcontext *ctx,
75 struct gl_shader_program *shProg)
Brianf2923612006-12-20 09:56:44 -070076{
Brianf2923612006-12-20 09:56:44 -070077 if (shProg->VertexProgram) {
78 if (shProg->VertexProgram->Base.Parameters == shProg->Uniforms) {
79 /* to prevent a double-free in the next call */
80 shProg->VertexProgram->Base.Parameters = NULL;
81 }
82 _mesa_delete_program(ctx, &shProg->VertexProgram->Base);
83 shProg->VertexProgram = NULL;
84 }
85
86 if (shProg->FragmentProgram) {
87 if (shProg->FragmentProgram->Base.Parameters == shProg->Uniforms) {
88 /* to prevent a double-free in the next call */
89 shProg->FragmentProgram->Base.Parameters = NULL;
90 }
91 _mesa_delete_program(ctx, &shProg->FragmentProgram->Base);
92 shProg->FragmentProgram = NULL;
93 }
94
Brianf2923612006-12-20 09:56:44 -070095 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
Brianb9fbedd2007-03-26 09:23:44 -0600107/**
Brian3c008a02007-04-12 15:22:32 -0600108 * Free all the data that hangs off a shader program object, but not the
109 * object itself.
110 */
111void
112_mesa_free_shader_program_data(GLcontext *ctx,
113 struct gl_shader_program *shProg)
114{
115 GLuint i;
116
Brianf3e8c322007-04-18 14:53:23 -0600117 assert(shProg->Type == GL_SHADER_PROGRAM_MESA);
Brian3c008a02007-04-12 15:22:32 -0600118
119 _mesa_clear_shader_program_data(ctx, shProg);
120
121 /* detach shaders */
122 for (i = 0; i < shProg->NumShaders; i++) {
123 _mesa_reference_shader(ctx, &shProg->Shaders[i], NULL);
124 }
125 if (shProg->Shaders) {
126 _mesa_free(shProg->Shaders);
127 shProg->Shaders = NULL;
128 }
129}
130
131
132/**
Brianb9fbedd2007-03-26 09:23:44 -0600133 * Free/delete a shader program object.
134 */
Brianf2923612006-12-20 09:56:44 -0700135void
136_mesa_free_shader_program(GLcontext *ctx, struct gl_shader_program *shProg)
137{
138 _mesa_free_shader_program_data(ctx, shProg);
Brianb9fbedd2007-03-26 09:23:44 -0600139 if (shProg->Shaders) {
140 _mesa_free(shProg->Shaders);
141 shProg->Shaders = NULL;
142 }
Brianf2923612006-12-20 09:56:44 -0700143 _mesa_free(shProg);
144}
145
146
147/**
Brian3c008a02007-04-12 15:22:32 -0600148 * Set ptr to point to shProg.
149 * If ptr is pointing to another object, decrement its refcount (and delete
150 * if refcount hits zero).
151 * Then set ptr to point to shProg, incrementing its refcount.
152 */
153/* XXX this could be static */
154void
155_mesa_reference_shader_program(GLcontext *ctx,
156 struct gl_shader_program **ptr,
157 struct gl_shader_program *shProg)
158{
159 assert(ptr);
160 if (*ptr == shProg) {
161 /* no-op */
162 return;
163 }
164 if (*ptr) {
165 /* Unreference the old shader program */
166 GLboolean deleteFlag = GL_FALSE;
167 struct gl_shader_program *old = *ptr;
168
169 ASSERT(old->RefCount > 0);
170 old->RefCount--;
171 /*printf("SHPROG DECR %p (%d) to %d\n",
172 (void*) old, old->Name, old->RefCount);*/
173 deleteFlag = (old->RefCount == 0);
174
175 if (deleteFlag) {
176 _mesa_HashRemove(ctx->Shared->ShaderObjects, old->Name);
177 _mesa_free_shader_program(ctx, old);
178 }
179
180 *ptr = NULL;
181 }
182 assert(!*ptr);
183
184 if (shProg) {
185 shProg->RefCount++;
Brian99193e42007-04-12 15:45:02 -0600186 /*printf("SHPROG INCR %p (%d) to %d\n",
187 (void*) shProg, shProg->Name, shProg->RefCount);*/
Brian3c008a02007-04-12 15:22:32 -0600188 *ptr = shProg;
189 }
190}
191
192
193/**
Brianf2923612006-12-20 09:56:44 -0700194 * Lookup a GLSL program object.
195 */
196struct gl_shader_program *
197_mesa_lookup_shader_program(GLcontext *ctx, GLuint name)
198{
199 struct gl_shader_program *shProg;
200 if (name) {
201 shProg = (struct gl_shader_program *)
202 _mesa_HashLookup(ctx->Shared->ShaderObjects, name);
203 /* Note that both gl_shader and gl_shader_program objects are kept
204 * in the same hash table. Check the object's type to be sure it's
205 * what we're expecting.
206 */
Brianf3e8c322007-04-18 14:53:23 -0600207 if (shProg && shProg->Type != GL_SHADER_PROGRAM_MESA) {
Brianf2923612006-12-20 09:56:44 -0700208 return NULL;
209 }
210 return shProg;
211 }
212 return NULL;
213}
214
215
216/**
217 * Allocate a new gl_shader object, initialize it.
218 */
219struct gl_shader *
220_mesa_new_shader(GLcontext *ctx, GLuint name, GLenum type)
221{
222 struct gl_shader *shader;
223 assert(type == GL_FRAGMENT_SHADER || type == GL_VERTEX_SHADER);
224 shader = CALLOC_STRUCT(gl_shader);
225 if (shader) {
226 shader->Type = type;
227 shader->Name = name;
228 shader->RefCount = 1;
229 }
230 return shader;
231}
232
233
234void
235_mesa_free_shader(GLcontext *ctx, struct gl_shader *sh)
236{
237 GLuint i;
238 if (sh->Source)
239 _mesa_free((void *) sh->Source);
240 if (sh->InfoLog)
241 _mesa_free(sh->InfoLog);
242 for (i = 0; i < sh->NumPrograms; i++) {
243 assert(sh->Programs[i]);
244 _mesa_delete_program(ctx, sh->Programs[i]);
245 }
246 if (sh->Programs)
247 _mesa_free(sh->Programs);
248 _mesa_free(sh);
249}
250
251
252/**
Brian3c008a02007-04-12 15:22:32 -0600253 * Set ptr to point to sh.
254 * If ptr is pointing to another shader, decrement its refcount (and delete
255 * if refcount hits zero).
256 * Then set ptr to point to sh, incrementing its refcount.
257 */
258/* XXX this could be static */
259void
260_mesa_reference_shader(GLcontext *ctx, struct gl_shader **ptr,
261 struct gl_shader *sh)
262{
263 assert(ptr);
264 if (*ptr == sh) {
265 /* no-op */
266 return;
267 }
268 if (*ptr) {
269 /* Unreference the old shader */
270 GLboolean deleteFlag = GL_FALSE;
271 struct gl_shader *old = *ptr;
272
273 ASSERT(old->RefCount > 0);
274 old->RefCount--;
Brian99193e42007-04-12 15:45:02 -0600275 /*printf("SHADER DECR %p (%d) to %d\n",
276 (void*) old, old->Name, old->RefCount);*/
Brian3c008a02007-04-12 15:22:32 -0600277 deleteFlag = (old->RefCount == 0);
278
279 if (deleteFlag) {
280 _mesa_HashRemove(ctx->Shared->ShaderObjects, old->Name);
281 _mesa_free_shader(ctx, old);
282 }
283
284 *ptr = NULL;
285 }
286 assert(!*ptr);
287
288 if (sh) {
289 /* reference new */
290 sh->RefCount++;
Brian99193e42007-04-12 15:45:02 -0600291 /*printf("SHADER INCR %p (%d) to %d\n",
292 (void*) sh, sh->Name, sh->RefCount);*/
Brian3c008a02007-04-12 15:22:32 -0600293 *ptr = sh;
294 }
295}
296
297
298/**
Brianf2923612006-12-20 09:56:44 -0700299 * Lookup a GLSL shader object.
300 */
301struct gl_shader *
302_mesa_lookup_shader(GLcontext *ctx, GLuint name)
303{
304 if (name) {
305 struct gl_shader *sh = (struct gl_shader *)
306 _mesa_HashLookup(ctx->Shared->ShaderObjects, name);
307 /* Note that both gl_shader and gl_shader_program objects are kept
308 * in the same hash table. Check the object's type to be sure it's
309 * what we're expecting.
310 */
Brianf3e8c322007-04-18 14:53:23 -0600311 if (sh && sh->Type == GL_SHADER_PROGRAM_MESA) {
Brianf2923612006-12-20 09:56:44 -0700312 assert(sh->Type == GL_VERTEX_SHADER ||
313 sh->Type == GL_FRAGMENT_SHADER);
314 return NULL;
315 }
316 return sh;
317 }
318 return NULL;
319}
320
321
Brianfa4d0362007-02-26 18:33:50 -0700322/**
323 * Initialize context's shader state.
324 */
Brianf2923612006-12-20 09:56:44 -0700325void
326_mesa_init_shader_state(GLcontext * ctx)
327{
Brianfa4d0362007-02-26 18:33:50 -0700328 /* Device drivers may override these to control what kind of instructions
329 * are generated by the GLSL compiler.
330 */
331 ctx->Shader.EmitHighLevelInstructions = GL_TRUE;
Brian63556fa2007-03-23 14:47:46 -0600332 ctx->Shader.EmitCondCodes = GL_TRUE; /* XXX probably want GL_FALSE... */
Brianfa4d0362007-02-26 18:33:50 -0700333 ctx->Shader.EmitComments = GL_FALSE;
Brianf2923612006-12-20 09:56:44 -0700334}
335
336
Brian5b01c5e2006-12-19 18:02:03 -0700337/**
Brian935f93f2007-03-24 16:20:02 -0600338 * Free the per-context shader-related state.
339 */
340void
341_mesa_free_shader_state(GLcontext *ctx)
342{
Brian3c008a02007-04-12 15:22:32 -0600343 _mesa_reference_shader_program(ctx, &ctx->Shader.CurrentProgram, NULL);
Brian935f93f2007-03-24 16:20:02 -0600344}
345
346
347/**
Brian5b01c5e2006-12-19 18:02:03 -0700348 * Copy string from <src> to <dst>, up to maxLength characters, returning
349 * length of <dst> in <length>.
350 * \param src the strings source
351 * \param maxLength max chars to copy
352 * \param length returns number of chars copied
353 * \param dst the string destination
354 */
355static void
356copy_string(GLchar *dst, GLsizei maxLength, GLsizei *length, const GLchar *src)
357{
358 GLsizei len;
359 for (len = 0; len < maxLength - 1 && src && src[len]; len++)
360 dst[len] = src[len];
361 if (maxLength > 0)
362 dst[len] = 0;
363 if (length)
364 *length = len;
365}
366
367
Brian5b01c5e2006-12-19 18:02:03 -0700368/**
369 * Called via ctx->Driver.AttachShader()
370 */
371void
372_mesa_attach_shader(GLcontext *ctx, GLuint program, GLuint shader)
373{
Brian65a18442006-12-19 18:46:56 -0700374 struct gl_shader_program *shProg
375 = _mesa_lookup_shader_program(ctx, program);
376 struct gl_shader *sh = _mesa_lookup_shader(ctx, shader);
377 const GLuint n = shProg->NumShaders;
Brian5b01c5e2006-12-19 18:02:03 -0700378 GLuint i;
379
Brian65a18442006-12-19 18:46:56 -0700380 if (!shProg || !sh) {
Brian43975832007-01-04 08:21:09 -0700381 _mesa_error(ctx, GL_INVALID_VALUE,
Brian5b01c5e2006-12-19 18:02:03 -0700382 "glAttachShader(bad program or shader name)");
383 return;
384 }
385
386 for (i = 0; i < n; i++) {
Brian65a18442006-12-19 18:46:56 -0700387 if (shProg->Shaders[i] == sh) {
Brian5b01c5e2006-12-19 18:02:03 -0700388 /* already attached */
389 return;
Brian34ae99d2006-12-18 08:28:54 -0700390 }
391 }
Brian5b01c5e2006-12-19 18:02:03 -0700392
393 /* grow list */
Brian65a18442006-12-19 18:46:56 -0700394 shProg->Shaders = (struct gl_shader **)
395 _mesa_realloc(shProg->Shaders,
396 n * sizeof(struct gl_shader *),
397 (n + 1) * sizeof(struct gl_shader *));
398 if (!shProg->Shaders) {
Brian5b01c5e2006-12-19 18:02:03 -0700399 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glAttachShader");
400 return;
401 }
402
403 /* append */
Brian3c008a02007-04-12 15:22:32 -0600404 shProg->Shaders[n] = NULL; /* since realloc() didn't zero the new space */
405 _mesa_reference_shader(ctx, &shProg->Shaders[n], sh);
Brian65a18442006-12-19 18:46:56 -0700406 shProg->NumShaders++;
Brian5b01c5e2006-12-19 18:02:03 -0700407}
408
409
410void
411_mesa_bind_attrib_location(GLcontext *ctx, GLuint program, GLuint index,
412 const GLchar *name)
413{
Brian65a18442006-12-19 18:46:56 -0700414 struct gl_shader_program *shProg
415 = _mesa_lookup_shader_program(ctx, program);
Brianb7978af2007-01-09 19:17:17 -0700416 const GLint size = -1; /* unknown size */
417 GLint i, oldIndex;
Brian5b01c5e2006-12-19 18:02:03 -0700418
Brian65a18442006-12-19 18:46:56 -0700419 if (!shProg) {
Brian43975832007-01-04 08:21:09 -0700420 _mesa_error(ctx, GL_INVALID_VALUE, "glBindAttribLocation(program)");
Brian5b01c5e2006-12-19 18:02:03 -0700421 return;
422 }
423
Brian9e4bae92006-12-20 09:27:42 -0700424 if (!name)
425 return;
426
427 if (strncmp(name, "gl_", 3) == 0) {
428 _mesa_error(ctx, GL_INVALID_OPERATION,
429 "glBindAttribLocation(illegal name)");
430 return;
431 }
432
Brian9f660252007-04-11 09:00:56 -0600433 if (shProg->LinkStatus) {
434 /* get current index/location for the attribute */
435 oldIndex = _mesa_get_attrib_location(ctx, program, name);
436 }
437 else {
438 oldIndex = -1;
439 }
Brian3209c3e2007-01-09 17:49:24 -0700440
441 /* this will replace the current value if it's already in the list */
Brianb7978af2007-01-09 19:17:17 -0700442 i = _mesa_add_attribute(shProg->Attributes, name, size, index);
Brian3209c3e2007-01-09 17:49:24 -0700443 if (i < 0) {
444 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBindAttribLocation");
445 }
446
Brian9f660252007-04-11 09:00:56 -0600447 if (shProg->VertexProgram && oldIndex >= 0 && oldIndex != index) {
448 /* If the index changed, need to search/replace references to that attribute
449 * in the vertex program.
450 */
Brian3209c3e2007-01-09 17:49:24 -0700451 _slang_remap_attribute(&shProg->VertexProgram->Base, oldIndex, index);
452 }
Brian34ae99d2006-12-18 08:28:54 -0700453}
454
455
Brian5b01c5e2006-12-19 18:02:03 -0700456GLuint
457_mesa_create_shader(GLcontext *ctx, GLenum type)
458{
Brian65a18442006-12-19 18:46:56 -0700459 struct gl_shader *sh;
Brian5b01c5e2006-12-19 18:02:03 -0700460 GLuint name;
461
462 name = _mesa_HashFindFreeKeyBlock(ctx->Shared->ShaderObjects, 1);
463
464 switch (type) {
Brian65a18442006-12-19 18:46:56 -0700465 case GL_FRAGMENT_SHADER:
466 case GL_VERTEX_SHADER:
467 sh = _mesa_new_shader(ctx, name, type);
Brian5b01c5e2006-12-19 18:02:03 -0700468 break;
469 default:
470 _mesa_error(ctx, GL_INVALID_ENUM, "CreateShader(type)");
471 return 0;
472 }
473
Brian65a18442006-12-19 18:46:56 -0700474 _mesa_HashInsert(ctx->Shared->ShaderObjects, name, sh);
Brian5b01c5e2006-12-19 18:02:03 -0700475
476 return name;
477}
478
479
480GLuint
481_mesa_create_program(GLcontext *ctx)
482{
483 GLuint name;
Brian65a18442006-12-19 18:46:56 -0700484 struct gl_shader_program *shProg;
Brian5b01c5e2006-12-19 18:02:03 -0700485
Brian65a18442006-12-19 18:46:56 -0700486 name = _mesa_HashFindFreeKeyBlock(ctx->Shared->ShaderObjects, 1);
487 shProg = _mesa_new_shader_program(ctx, name);
Brian5b01c5e2006-12-19 18:02:03 -0700488
Brian65a18442006-12-19 18:46:56 -0700489 _mesa_HashInsert(ctx->Shared->ShaderObjects, name, shProg);
Brian5b01c5e2006-12-19 18:02:03 -0700490
Brian3c008a02007-04-12 15:22:32 -0600491 assert(shProg->RefCount == 1);
492
Brian5b01c5e2006-12-19 18:02:03 -0700493 return name;
494}
495
496
Brian3c008a02007-04-12 15:22:32 -0600497/**
498 * Named w/ "2" to indicate OpenGL 2.x vs GL_ARB_fragment_programs's
499 * DeleteProgramARB.
500 */
Brian5b01c5e2006-12-19 18:02:03 -0700501void
502_mesa_delete_program2(GLcontext *ctx, GLuint name)
503{
Brian3c008a02007-04-12 15:22:32 -0600504 /*
505 * NOTE: deleting shaders/programs works a bit differently than
506 * texture objects (and buffer objects, etc). Shader/program
507 * handles/IDs exist in the hash table until the object is really
508 * deleted (refcount==0). With texture objects, the handle/ID is
509 * removed from the hash table in glDeleteTextures() while the tex
510 * object itself might linger until its refcount goes to zero.
511 */
Brian65a18442006-12-19 18:46:56 -0700512 struct gl_shader_program *shProg;
Brian5b01c5e2006-12-19 18:02:03 -0700513
Brian65a18442006-12-19 18:46:56 -0700514 shProg = _mesa_lookup_shader_program(ctx, name);
515 if (!shProg) {
Brian43975832007-01-04 08:21:09 -0700516 _mesa_error(ctx, GL_INVALID_VALUE, "glDeleteProgram(name)");
Brian5b01c5e2006-12-19 18:02:03 -0700517 return;
518 }
519
Brian9e4bae92006-12-20 09:27:42 -0700520 shProg->DeletePending = GL_TRUE;
521
Brian3c008a02007-04-12 15:22:32 -0600522 /* effectively, decr shProg's refcount */
523 _mesa_reference_shader_program(ctx, &shProg, NULL);
Brian5b01c5e2006-12-19 18:02:03 -0700524}
525
526
527void
528_mesa_delete_shader(GLcontext *ctx, GLuint shader)
529{
Brian9e4bae92006-12-20 09:27:42 -0700530 struct gl_shader *sh = _mesa_lookup_shader(ctx, shader);
531 if (!sh) {
532 return;
533 }
Brian5b01c5e2006-12-19 18:02:03 -0700534
Brian9e4bae92006-12-20 09:27:42 -0700535 sh->DeletePending = GL_TRUE;
Brian3c008a02007-04-12 15:22:32 -0600536
537 /* effectively, decr sh's refcount */
538 _mesa_reference_shader(ctx, &sh, NULL);
Brian5b01c5e2006-12-19 18:02:03 -0700539}
540
541
542void
543_mesa_detach_shader(GLcontext *ctx, GLuint program, GLuint shader)
544{
Brian65a18442006-12-19 18:46:56 -0700545 struct gl_shader_program *shProg
546 = _mesa_lookup_shader_program(ctx, program);
547 const GLuint n = shProg->NumShaders;
Brian5b01c5e2006-12-19 18:02:03 -0700548 GLuint i, j;
549
Brian65a18442006-12-19 18:46:56 -0700550 if (!shProg) {
Brian43975832007-01-04 08:21:09 -0700551 _mesa_error(ctx, GL_INVALID_VALUE,
Brian5b01c5e2006-12-19 18:02:03 -0700552 "glDetachShader(bad program or shader name)");
553 return;
554 }
555
556 for (i = 0; i < n; i++) {
Brian65a18442006-12-19 18:46:56 -0700557 if (shProg->Shaders[i]->Name == shader) {
Brian5b01c5e2006-12-19 18:02:03 -0700558 /* found it */
Brian3c008a02007-04-12 15:22:32 -0600559 struct gl_shader **newList;
Brian9e4bae92006-12-20 09:27:42 -0700560
Brian3c008a02007-04-12 15:22:32 -0600561 /* derefernce */
562 _mesa_reference_shader(ctx, &shProg->Shaders[i], NULL);
Brian9e4bae92006-12-20 09:27:42 -0700563
Brian5b01c5e2006-12-19 18:02:03 -0700564 /* alloc new, smaller array */
Brian65a18442006-12-19 18:46:56 -0700565 newList = (struct gl_shader **)
566 _mesa_malloc((n - 1) * sizeof(struct gl_shader *));
Brian5b01c5e2006-12-19 18:02:03 -0700567 if (!newList) {
568 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glDetachShader");
569 return;
570 }
571 for (j = 0; j < i; j++) {
Brian65a18442006-12-19 18:46:56 -0700572 newList[j] = shProg->Shaders[j];
Brian5b01c5e2006-12-19 18:02:03 -0700573 }
574 while (++i < n)
Brian65a18442006-12-19 18:46:56 -0700575 newList[j++] = shProg->Shaders[i];
576 _mesa_free(shProg->Shaders);
Brian5b01c5e2006-12-19 18:02:03 -0700577
Brian65a18442006-12-19 18:46:56 -0700578 shProg->Shaders = newList;
Brian5b01c5e2006-12-19 18:02:03 -0700579 return;
580 }
581 }
582
583 /* not found */
Brian43975832007-01-04 08:21:09 -0700584 _mesa_error(ctx, GL_INVALID_VALUE,
Brian5b01c5e2006-12-19 18:02:03 -0700585 "glDetachShader(shader not found)");
586}
587
588
589void
590_mesa_get_active_attrib(GLcontext *ctx, GLuint program, GLuint index,
591 GLsizei maxLength, GLsizei *length, GLint *size,
592 GLenum *type, GLchar *nameOut)
593{
594 static const GLenum vec_types[] = {
595 GL_FLOAT, GL_FLOAT_VEC2, GL_FLOAT_VEC3, GL_FLOAT_VEC4
596 };
Brian65a18442006-12-19 18:46:56 -0700597 struct gl_shader_program *shProg
598 = _mesa_lookup_shader_program(ctx, program);
Brian5b01c5e2006-12-19 18:02:03 -0700599 GLint sz;
600
Brian65a18442006-12-19 18:46:56 -0700601 if (!shProg) {
Brian43975832007-01-04 08:21:09 -0700602 _mesa_error(ctx, GL_INVALID_VALUE, "glGetActiveUniform");
Brian5b01c5e2006-12-19 18:02:03 -0700603 return;
604 }
605
Brian65a18442006-12-19 18:46:56 -0700606 if (!shProg->Attributes || index >= shProg->Attributes->NumParameters) {
Brian5b01c5e2006-12-19 18:02:03 -0700607 _mesa_error(ctx, GL_INVALID_VALUE, "glGetActiveUniform(index)");
608 return;
609 }
610
611 copy_string(nameOut, maxLength, length,
Brian65a18442006-12-19 18:46:56 -0700612 shProg->Attributes->Parameters[index].Name);
613 sz = shProg->Attributes->Parameters[index].Size;
Brian5b01c5e2006-12-19 18:02:03 -0700614 if (size)
615 *size = sz;
616 if (type)
617 *type = vec_types[sz]; /* XXX this is a temporary hack */
618}
619
620
621/**
622 * Called via ctx->Driver.GetActiveUniform().
623 */
624void
625_mesa_get_active_uniform(GLcontext *ctx, GLuint program, GLuint index,
626 GLsizei maxLength, GLsizei *length, GLint *size,
627 GLenum *type, GLchar *nameOut)
628{
629 static const GLenum vec_types[] = {
630 GL_FLOAT, GL_FLOAT_VEC2, GL_FLOAT_VEC3, GL_FLOAT_VEC4
631 };
Brian65a18442006-12-19 18:46:56 -0700632 struct gl_shader_program *shProg
633 = _mesa_lookup_shader_program(ctx, program);
Brian5b01c5e2006-12-19 18:02:03 -0700634 GLint sz;
635
Brian65a18442006-12-19 18:46:56 -0700636 if (!shProg) {
Brian43975832007-01-04 08:21:09 -0700637 _mesa_error(ctx, GL_INVALID_VALUE, "glGetActiveUniform");
Brian5b01c5e2006-12-19 18:02:03 -0700638 return;
639 }
640
Brian65a18442006-12-19 18:46:56 -0700641 if (!shProg->Uniforms || index >= shProg->Uniforms->NumParameters) {
Brian5b01c5e2006-12-19 18:02:03 -0700642 _mesa_error(ctx, GL_INVALID_VALUE, "glGetActiveUniform(index)");
643 return;
644 }
645
646 copy_string(nameOut, maxLength, length,
Brian65a18442006-12-19 18:46:56 -0700647 shProg->Uniforms->Parameters[index].Name);
648 sz = shProg->Uniforms->Parameters[index].Size;
Brian5b01c5e2006-12-19 18:02:03 -0700649 if (size)
650 *size = sz;
651 if (type)
652 *type = vec_types[sz]; /* XXX this is a temporary hack */
653}
654
655
656/**
657 * Called via ctx->Driver.GetAttachedShaders().
658 */
659void
660_mesa_get_attached_shaders(GLcontext *ctx, GLuint program, GLsizei maxCount,
661 GLsizei *count, GLuint *obj)
662{
Brian65a18442006-12-19 18:46:56 -0700663 struct gl_shader_program *shProg
664 = _mesa_lookup_shader_program(ctx, program);
665 if (shProg) {
Brian223d7cb2007-01-23 16:37:51 -0700666 GLint i;
Brian65a18442006-12-19 18:46:56 -0700667 for (i = 0; i < maxCount && i < shProg->NumShaders; i++) {
668 obj[i] = shProg->Shaders[i]->Name;
Brian5b01c5e2006-12-19 18:02:03 -0700669 }
670 if (count)
671 *count = i;
672 }
673 else {
Brian43975832007-01-04 08:21:09 -0700674 _mesa_error(ctx, GL_INVALID_VALUE, "glGetAttachedShaders");
Brian5b01c5e2006-12-19 18:02:03 -0700675 }
676}
677
678
679GLint
680_mesa_get_attrib_location(GLcontext *ctx, GLuint program,
681 const GLchar *name)
682{
Brian65a18442006-12-19 18:46:56 -0700683 struct gl_shader_program *shProg
684 = _mesa_lookup_shader_program(ctx, program);
Brian5b01c5e2006-12-19 18:02:03 -0700685
Brian65a18442006-12-19 18:46:56 -0700686 if (!shProg) {
Brian43975832007-01-04 08:21:09 -0700687 _mesa_error(ctx, GL_INVALID_VALUE, "glGetAttribLocation");
Brian5b01c5e2006-12-19 18:02:03 -0700688 return -1;
689 }
690
Brian65a18442006-12-19 18:46:56 -0700691 if (!shProg->LinkStatus) {
Brian5b01c5e2006-12-19 18:02:03 -0700692 _mesa_error(ctx, GL_INVALID_OPERATION,
693 "glGetAttribLocation(program not linked)");
694 return -1;
695 }
696
697 if (!name)
698 return -1;
699
Brian65a18442006-12-19 18:46:56 -0700700 if (shProg->Attributes) {
Brian3209c3e2007-01-09 17:49:24 -0700701 GLint i = _mesa_lookup_parameter_index(shProg->Attributes, -1, name);
702 if (i >= 0) {
Brian01a91eb2007-01-09 19:26:22 -0700703 return shProg->Attributes->Parameters[i].StateIndexes[0];
Brian5b01c5e2006-12-19 18:02:03 -0700704 }
705 }
706 return -1;
707}
708
709
710GLuint
711_mesa_get_handle(GLcontext *ctx, GLenum pname)
Brian34ae99d2006-12-18 08:28:54 -0700712{
713#if 0
714 GET_CURRENT_CONTEXT(ctx);
715
716 switch (pname) {
717 case GL_PROGRAM_OBJECT_ARB:
718 {
Brian5b01c5e2006-12-19 18:02:03 -0700719 struct gl2_program_intf **pro = ctx->Shader.CurrentProgram;
Brian34ae99d2006-12-18 08:28:54 -0700720
721 if (pro != NULL)
722 return (**pro)._container._generic.
723 GetName((struct gl2_generic_intf **) (pro));
724 }
725 break;
726 default:
727 _mesa_error(ctx, GL_INVALID_ENUM, "glGetHandleARB");
728 }
729#endif
730 return 0;
731}
732
733
Brian5b01c5e2006-12-19 18:02:03 -0700734void
735_mesa_get_programiv(GLcontext *ctx, GLuint program,
736 GLenum pname, GLint *params)
Brian34ae99d2006-12-18 08:28:54 -0700737{
Brian65a18442006-12-19 18:46:56 -0700738 struct gl_shader_program *shProg
739 = _mesa_lookup_shader_program(ctx, program);
Brian34ae99d2006-12-18 08:28:54 -0700740
Brian65a18442006-12-19 18:46:56 -0700741 if (!shProg) {
Brian5b01c5e2006-12-19 18:02:03 -0700742 _mesa_error(ctx, GL_INVALID_VALUE, "glGetProgramiv(program)");
Brian34ae99d2006-12-18 08:28:54 -0700743 return;
744 }
745
Brian5b01c5e2006-12-19 18:02:03 -0700746 switch (pname) {
747 case GL_DELETE_STATUS:
Brian65a18442006-12-19 18:46:56 -0700748 *params = shProg->DeletePending;
Brian5b01c5e2006-12-19 18:02:03 -0700749 break;
750 case GL_LINK_STATUS:
Brian65a18442006-12-19 18:46:56 -0700751 *params = shProg->LinkStatus;
Brian34ae99d2006-12-18 08:28:54 -0700752 break;
Brian5b01c5e2006-12-19 18:02:03 -0700753 case GL_VALIDATE_STATUS:
Brian65a18442006-12-19 18:46:56 -0700754 *params = shProg->Validated;
Brian5b01c5e2006-12-19 18:02:03 -0700755 break;
756 case GL_INFO_LOG_LENGTH:
Brian65a18442006-12-19 18:46:56 -0700757 *params = shProg->InfoLog ? strlen(shProg->InfoLog) : 0;
Brian5b01c5e2006-12-19 18:02:03 -0700758 break;
759 case GL_ATTACHED_SHADERS:
Brian65a18442006-12-19 18:46:56 -0700760 *params = shProg->NumShaders;
Brian5b01c5e2006-12-19 18:02:03 -0700761 break;
762 case GL_ACTIVE_ATTRIBUTES:
Brian3209c3e2007-01-09 17:49:24 -0700763 *params = shProg->Attributes ? shProg->Attributes->NumParameters : 0;
Brian5b01c5e2006-12-19 18:02:03 -0700764 break;
765 case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH:
Brian6d3d9c12007-04-18 14:19:17 -0600766 *params = _mesa_longest_parameter_name(shProg->Attributes, PROGRAM_INPUT);
Brian5b01c5e2006-12-19 18:02:03 -0700767 break;
768 case GL_ACTIVE_UNIFORMS:
Brian65a18442006-12-19 18:46:56 -0700769 *params = shProg->Uniforms ? shProg->Uniforms->NumParameters : 0;
Brian5b01c5e2006-12-19 18:02:03 -0700770 break;
771 case GL_ACTIVE_UNIFORM_MAX_LENGTH:
Brian6d3d9c12007-04-18 14:19:17 -0600772 *params = _mesa_longest_parameter_name(shProg->Uniforms, PROGRAM_UNIFORM);
Brian34ae99d2006-12-18 08:28:54 -0700773 break;
774 default:
Brian5b01c5e2006-12-19 18:02:03 -0700775 _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramiv(pname)");
776 return;
Brian34ae99d2006-12-18 08:28:54 -0700777 }
Brian5b01c5e2006-12-19 18:02:03 -0700778}
Brian34ae99d2006-12-18 08:28:54 -0700779
Brian34ae99d2006-12-18 08:28:54 -0700780
Brian5b01c5e2006-12-19 18:02:03 -0700781void
782_mesa_get_shaderiv(GLcontext *ctx, GLuint name, GLenum pname, GLint *params)
783{
Brian65a18442006-12-19 18:46:56 -0700784 struct gl_shader *shader = _mesa_lookup_shader(ctx, name);
Brian5b01c5e2006-12-19 18:02:03 -0700785
786 if (!shader) {
787 _mesa_error(ctx, GL_INVALID_VALUE, "glGetShaderiv(shader)");
788 return;
789 }
Brian65a18442006-12-19 18:46:56 -0700790
Brian5b01c5e2006-12-19 18:02:03 -0700791 switch (pname) {
792 case GL_SHADER_TYPE:
793 *params = shader->Type;
794 break;
795 case GL_DELETE_STATUS:
796 *params = shader->DeletePending;
797 break;
798 case GL_COMPILE_STATUS:
799 *params = shader->CompileStatus;
800 break;
801 case GL_INFO_LOG_LENGTH:
802 *params = shader->InfoLog ? strlen(shader->InfoLog) : 0;
803 break;
804 case GL_SHADER_SOURCE_LENGTH:
805 *params = shader->Source ? strlen((char *) shader->Source) : 0;
806 break;
807 default:
808 _mesa_error(ctx, GL_INVALID_ENUM, "glGetShaderiv(pname)");
809 return;
810 }
811}
812
813
814void
815_mesa_get_program_info_log(GLcontext *ctx, GLuint program, GLsizei bufSize,
816 GLsizei *length, GLchar *infoLog)
817{
Brian65a18442006-12-19 18:46:56 -0700818 struct gl_shader_program *shProg
819 = _mesa_lookup_shader_program(ctx, program);
820 if (!shProg) {
Brian5b01c5e2006-12-19 18:02:03 -0700821 _mesa_error(ctx, GL_INVALID_VALUE, "glGetProgramInfoLog(program)");
822 return;
823 }
Brian65a18442006-12-19 18:46:56 -0700824 copy_string(infoLog, bufSize, length, shProg->InfoLog);
Brian5b01c5e2006-12-19 18:02:03 -0700825}
826
827
828void
829_mesa_get_shader_info_log(GLcontext *ctx, GLuint shader, GLsizei bufSize,
830 GLsizei *length, GLchar *infoLog)
831{
Brian65a18442006-12-19 18:46:56 -0700832 struct gl_shader *sh = _mesa_lookup_shader(ctx, shader);
833 if (!sh) {
Brian5b01c5e2006-12-19 18:02:03 -0700834 _mesa_error(ctx, GL_INVALID_VALUE, "glGetShaderInfoLog(shader)");
835 return;
836 }
Brian65a18442006-12-19 18:46:56 -0700837 copy_string(infoLog, bufSize, length, sh->InfoLog);
Brian5b01c5e2006-12-19 18:02:03 -0700838}
839
840
841/**
842 * Called via ctx->Driver.GetShaderSource().
843 */
844void
845_mesa_get_shader_source(GLcontext *ctx, GLuint shader, GLsizei maxLength,
846 GLsizei *length, GLchar *sourceOut)
847{
Brian65a18442006-12-19 18:46:56 -0700848 struct gl_shader *sh = _mesa_lookup_shader(ctx, shader);
849 if (!sh) {
Brian5b01c5e2006-12-19 18:02:03 -0700850 _mesa_error(ctx, GL_INVALID_VALUE, "glGetShaderSource(shader)");
851 return;
852 }
Brian65a18442006-12-19 18:46:56 -0700853 copy_string(sourceOut, maxLength, length, sh->Source);
Brian5b01c5e2006-12-19 18:02:03 -0700854}
855
856
857/**
858 * Called via ctx->Driver.GetUniformfv().
859 */
860void
861_mesa_get_uniformfv(GLcontext *ctx, GLuint program, GLint location,
862 GLfloat *params)
863{
Brian65a18442006-12-19 18:46:56 -0700864 struct gl_shader_program *shProg
865 = _mesa_lookup_shader_program(ctx, program);
866 if (shProg) {
Brian223d7cb2007-01-23 16:37:51 -0700867 GLint i;
Brian65a18442006-12-19 18:46:56 -0700868 if (location >= 0 && location < shProg->Uniforms->NumParameters) {
869 for (i = 0; i < shProg->Uniforms->Parameters[location].Size; i++) {
870 params[i] = shProg->Uniforms->ParameterValues[location][i];
Brian5b01c5e2006-12-19 18:02:03 -0700871 }
872 }
873 else {
874 _mesa_error(ctx, GL_INVALID_VALUE, "glGetUniformfv(location)");
875 }
876 }
877 else {
Brian43975832007-01-04 08:21:09 -0700878 _mesa_error(ctx, GL_INVALID_VALUE, "glGetUniformfv(program)");
Brian5b01c5e2006-12-19 18:02:03 -0700879 }
880}
881
882
883/**
884 * Called via ctx->Driver.GetUniformLocation().
885 */
886GLint
887_mesa_get_uniform_location(GLcontext *ctx, GLuint program, const GLchar *name)
888{
Brian71623982007-01-30 16:55:03 -0700889 struct gl_shader_program *shProg
890 = _mesa_lookup_shader_program(ctx, program);
891 if (shProg) {
Brian5b01c5e2006-12-19 18:02:03 -0700892 GLuint loc;
Brian65a18442006-12-19 18:46:56 -0700893 for (loc = 0; loc < shProg->Uniforms->NumParameters; loc++) {
Brian5b01c5e2006-12-19 18:02:03 -0700894 const struct gl_program_parameter *u
Brian65a18442006-12-19 18:46:56 -0700895 = shProg->Uniforms->Parameters + loc;
Brian29053852006-12-21 11:21:26 -0700896 /* XXX this is a temporary simplification / short-cut.
897 * We need to handle things like "e.c[0].b" as seen in the
898 * GLSL orange book, page 189.
899 */
Brian5cf73262007-01-05 16:02:45 -0700900 if ((u->Type == PROGRAM_UNIFORM ||
901 u->Type == PROGRAM_SAMPLER) && !strcmp(u->Name, name)) {
Brian5b01c5e2006-12-19 18:02:03 -0700902 return loc;
903 }
904 }
905 }
906 return -1;
907
908}
909
910
911GLboolean
912_mesa_is_program(GLcontext *ctx, GLuint name)
913{
Brian65a18442006-12-19 18:46:56 -0700914 struct gl_shader_program *shProg = _mesa_lookup_shader_program(ctx, name);
915 return shProg ? GL_TRUE : GL_FALSE;
Brian5b01c5e2006-12-19 18:02:03 -0700916}
917
918
919GLboolean
920_mesa_is_shader(GLcontext *ctx, GLuint name)
921{
Brian65a18442006-12-19 18:46:56 -0700922 struct gl_shader *shader = _mesa_lookup_shader(ctx, name);
Brian5b01c5e2006-12-19 18:02:03 -0700923 return shader ? GL_TRUE : GL_FALSE;
Brian34ae99d2006-12-18 08:28:54 -0700924}
925
926
927
Brian5b01c5e2006-12-19 18:02:03 -0700928/**
929 * Called via ctx->Driver.ShaderSource()
930 */
931void
932_mesa_shader_source(GLcontext *ctx, GLuint shader, const GLchar *source)
Brian34ae99d2006-12-18 08:28:54 -0700933{
Brian65a18442006-12-19 18:46:56 -0700934 struct gl_shader *sh = _mesa_lookup_shader(ctx, shader);
935 if (!sh) {
Brian5b01c5e2006-12-19 18:02:03 -0700936 _mesa_error(ctx, GL_INVALID_VALUE, "glShaderSource(shaderObj)");
Brian34ae99d2006-12-18 08:28:54 -0700937 return;
938 }
939
Brian34ae99d2006-12-18 08:28:54 -0700940 /* free old shader source string and install new one */
Brian65a18442006-12-19 18:46:56 -0700941 if (sh->Source) {
942 _mesa_free((void *) sh->Source);
Brian34ae99d2006-12-18 08:28:54 -0700943 }
Brian65a18442006-12-19 18:46:56 -0700944 sh->Source = source;
Brian9e4bae92006-12-20 09:27:42 -0700945 sh->CompileStatus = GL_FALSE;
Brian34ae99d2006-12-18 08:28:54 -0700946}
947
948
Brian5b01c5e2006-12-19 18:02:03 -0700949/**
950 * Called via ctx->Driver.CompileShader()
951 */
952void
953_mesa_compile_shader(GLcontext *ctx, GLuint shaderObj)
Brian34ae99d2006-12-18 08:28:54 -0700954{
Brian65a18442006-12-19 18:46:56 -0700955 struct gl_shader *sh = _mesa_lookup_shader(ctx, shaderObj);
Brian34ae99d2006-12-18 08:28:54 -0700956
Brian65a18442006-12-19 18:46:56 -0700957 if (!sh) {
Brian34ae99d2006-12-18 08:28:54 -0700958 _mesa_error(ctx, GL_INVALID_VALUE, "glCompileShader(shaderObj)");
959 return;
960 }
961
Brian43975832007-01-04 08:21:09 -0700962 sh->CompileStatus = _slang_compile(ctx, sh);
Brian34ae99d2006-12-18 08:28:54 -0700963}
964
965
Brian5b01c5e2006-12-19 18:02:03 -0700966/**
967 * Called via ctx->Driver.LinkProgram()
968 */
969void
970_mesa_link_program(GLcontext *ctx, GLuint program)
Brian34ae99d2006-12-18 08:28:54 -0700971{
Brian65a18442006-12-19 18:46:56 -0700972 struct gl_shader_program *shProg;
Brian34ae99d2006-12-18 08:28:54 -0700973
Brian65a18442006-12-19 18:46:56 -0700974 shProg = _mesa_lookup_shader_program(ctx, program);
975 if (!shProg) {
Brian43975832007-01-04 08:21:09 -0700976 _mesa_error(ctx, GL_INVALID_VALUE, "glLinkProgram(program)");
Brian34ae99d2006-12-18 08:28:54 -0700977 return;
978 }
979
Brianc1771912007-02-16 09:56:19 -0700980 _slang_link(ctx, program, shProg);
Brian34ae99d2006-12-18 08:28:54 -0700981}
982
983
984/**
Brian5b01c5e2006-12-19 18:02:03 -0700985 * Called via ctx->Driver.UseProgram()
Brian34ae99d2006-12-18 08:28:54 -0700986 */
Brian5b01c5e2006-12-19 18:02:03 -0700987void
988_mesa_use_program(GLcontext *ctx, GLuint program)
Brian34ae99d2006-12-18 08:28:54 -0700989{
Brian3c008a02007-04-12 15:22:32 -0600990 struct gl_shader_program *shProg;
991
Brian00d63aa2007-02-03 11:35:02 -0700992 if (ctx->Shader.CurrentProgram &&
993 ctx->Shader.CurrentProgram->Name == program) {
994 /* no-op */
995 return;
996 }
997
998 FLUSH_VERTICES(ctx, _NEW_PROGRAM);
999
Brian5b01c5e2006-12-19 18:02:03 -07001000 if (program) {
Brian65a18442006-12-19 18:46:56 -07001001 shProg = _mesa_lookup_shader_program(ctx, program);
1002 if (!shProg) {
Brian43975832007-01-04 08:21:09 -07001003 _mesa_error(ctx, GL_INVALID_VALUE,
Brian5b01c5e2006-12-19 18:02:03 -07001004 "glUseProgramObjectARB(programObj)");
1005 return;
1006 }
Brian5b01c5e2006-12-19 18:02:03 -07001007 }
1008 else {
Brian3c008a02007-04-12 15:22:32 -06001009 shProg = NULL;
1010 }
1011
1012 _mesa_reference_shader_program(ctx, &ctx->Shader.CurrentProgram, shProg);
Brian5b01c5e2006-12-19 18:02:03 -07001013}
Brian34ae99d2006-12-18 08:28:54 -07001014
Brian5b01c5e2006-12-19 18:02:03 -07001015
1016/**
1017 * Called via ctx->Driver.Uniform().
1018 */
1019void
1020_mesa_uniform(GLcontext *ctx, GLint location, GLsizei count,
1021 const GLvoid *values, GLenum type)
1022{
Brian3a8e2772006-12-20 17:19:16 -07001023 struct gl_shader_program *shProg = ctx->Shader.CurrentProgram;
Brian98650bd2007-03-13 16:32:48 -06001024 GLint elems, i, k;
Brian3a8e2772006-12-20 17:19:16 -07001025
1026 if (!shProg || !shProg->LinkStatus) {
Brian5b01c5e2006-12-19 18:02:03 -07001027 _mesa_error(ctx, GL_INVALID_OPERATION, "glUniform(program not linked)");
Brian3a8e2772006-12-20 17:19:16 -07001028 return;
1029 }
1030
Brian223d7cb2007-01-23 16:37:51 -07001031 if (location < 0 || location >= (GLint) shProg->Uniforms->NumParameters) {
Brian3a8e2772006-12-20 17:19:16 -07001032 _mesa_error(ctx, GL_INVALID_VALUE, "glUniform(location)");
1033 return;
1034 }
1035
1036 FLUSH_VERTICES(ctx, _NEW_PROGRAM);
1037
Brianfee9bbe2007-02-02 18:05:43 -07001038 /*
1039 * If we're setting a sampler, we must use glUniformi1()!
1040 */
1041 if (shProg->Uniforms->Parameters[location].Type == PROGRAM_SAMPLER) {
1042 if (type != GL_INT || count != 1) {
1043 _mesa_error(ctx, GL_INVALID_OPERATION,
1044 "glUniform(only glUniform1i can be used "
1045 "to set sampler uniforms)");
1046 return;
1047 }
1048 }
1049
Brian52363952007-03-13 16:50:24 -06001050 if (count < 0) {
1051 _mesa_error(ctx, GL_INVALID_VALUE, "glUniform(count < 0)");
1052 return;
1053 }
1054
Brian98650bd2007-03-13 16:32:48 -06001055 switch (type) {
1056 case GL_FLOAT:
1057 case GL_INT:
1058 elems = 1;
1059 break;
1060 case GL_FLOAT_VEC2:
1061 case GL_INT_VEC2:
1062 elems = 2;
1063 break;
1064 case GL_FLOAT_VEC3:
1065 case GL_INT_VEC3:
1066 elems = 3;
1067 break;
1068 case GL_FLOAT_VEC4:
1069 case GL_INT_VEC4:
1070 elems = 4;
1071 break;
1072 default:
1073 _mesa_problem(ctx, "Invalid type in _mesa_uniform");
1074 return;
Brian89dc4852007-01-04 14:35:44 -07001075 }
Brian98650bd2007-03-13 16:32:48 -06001076
1077 if (count * elems > shProg->Uniforms->Parameters[location].Size) {
1078 _mesa_error(ctx, GL_INVALID_OPERATION, "glUniform(count too large)");
1079 return;
1080 }
1081
1082 for (k = 0; k < count; k++) {
1083 GLfloat *uniformVal = shProg->Uniforms->ParameterValues[location + k];
1084 if (type == GL_INT ||
1085 type == GL_INT_VEC2 ||
1086 type == GL_INT_VEC3 ||
1087 type == GL_INT_VEC4) {
Brian52363952007-03-13 16:50:24 -06001088 const GLint *iValues = ((const GLint *) values) + k * elems;
Brian98650bd2007-03-13 16:32:48 -06001089 for (i = 0; i < elems; i++) {
1090 uniformVal[i] = (GLfloat) iValues[i];
1091 }
1092 }
1093 else {
Brian52363952007-03-13 16:50:24 -06001094 const GLfloat *fValues = ((const GLfloat *) values) + k * elems;
Brian98650bd2007-03-13 16:32:48 -06001095 for (i = 0; i < elems; i++) {
1096 uniformVal[i] = fValues[i];
1097 }
Brian89dc4852007-01-04 14:35:44 -07001098 }
Brian5b01c5e2006-12-19 18:02:03 -07001099 }
Brian5cf73262007-01-05 16:02:45 -07001100
1101 if (shProg->Uniforms->Parameters[location].Type == PROGRAM_SAMPLER) {
Briancec81ee2007-03-07 08:04:06 -07001102 if (shProg->VertexProgram)
1103 _slang_resolve_samplers(shProg, &shProg->VertexProgram->Base);
1104 if (shProg->FragmentProgram)
1105 _slang_resolve_samplers(shProg, &shProg->FragmentProgram->Base);
Brian5cf73262007-01-05 16:02:45 -07001106 FLUSH_VERTICES(ctx, _NEW_TEXTURE);
1107 }
Brian34ae99d2006-12-18 08:28:54 -07001108}
1109
1110
1111/**
Brian5b01c5e2006-12-19 18:02:03 -07001112 * Called by ctx->Driver.UniformMatrix().
Brian34ae99d2006-12-18 08:28:54 -07001113 */
Brian5b01c5e2006-12-19 18:02:03 -07001114void
1115_mesa_uniform_matrix(GLcontext *ctx, GLint cols, GLint rows,
1116 GLenum matrixType, GLint location, GLsizei count,
1117 GLboolean transpose, const GLfloat *values)
Brian34ae99d2006-12-18 08:28:54 -07001118{
Brian3a8e2772006-12-20 17:19:16 -07001119 struct gl_shader_program *shProg = ctx->Shader.CurrentProgram;
1120 if (!shProg || !shProg->LinkStatus) {
1121 _mesa_error(ctx, GL_INVALID_OPERATION,
1122 "glUniformMatrix(program not linked)");
1123 return;
1124 }
1125 if (location < 0 || location >= shProg->Uniforms->NumParameters) {
1126 _mesa_error(ctx, GL_INVALID_VALUE, "glUniformMatrix(location)");
1127 return;
1128 }
Brian34ae99d2006-12-18 08:28:54 -07001129 if (values == NULL) {
Brian3a8e2772006-12-20 17:19:16 -07001130 _mesa_error(ctx, GL_INVALID_VALUE, "glUniformMatrix");
Brian34ae99d2006-12-18 08:28:54 -07001131 return;
1132 }
1133
1134 FLUSH_VERTICES(ctx, _NEW_PROGRAM);
1135
Brian3a8e2772006-12-20 17:19:16 -07001136 /*
1137 * Note: the _columns_ of a matrix are stored in program registers, not
1138 * the rows.
1139 */
1140 /* XXXX need to test 3x3 and 2x2 matrices... */
Brian34ae99d2006-12-18 08:28:54 -07001141 if (transpose) {
Brian3a8e2772006-12-20 17:19:16 -07001142 GLuint row, col;
1143 for (col = 0; col < cols; col++) {
1144 GLfloat *v = shProg->Uniforms->ParameterValues[location + col];
1145 for (row = 0; row < rows; row++) {
Brian9f442472007-03-09 11:34:18 -07001146 v[row] = values[row * cols + col];
Brian34ae99d2006-12-18 08:28:54 -07001147 }
Brian34ae99d2006-12-18 08:28:54 -07001148 }
Brian34ae99d2006-12-18 08:28:54 -07001149 }
1150 else {
Brian3a8e2772006-12-20 17:19:16 -07001151 GLuint row, col;
1152 for (col = 0; col < cols; col++) {
1153 GLfloat *v = shProg->Uniforms->ParameterValues[location + col];
1154 for (row = 0; row < rows; row++) {
Brian9f442472007-03-09 11:34:18 -07001155 v[row] = values[col * rows + row];
Brian3a8e2772006-12-20 17:19:16 -07001156 }
1157 }
Brian34ae99d2006-12-18 08:28:54 -07001158 }
1159}
1160
1161
Brian5b01c5e2006-12-19 18:02:03 -07001162void
1163_mesa_validate_program(GLcontext *ctx, GLuint program)
Brian34ae99d2006-12-18 08:28:54 -07001164{
Brian65a18442006-12-19 18:46:56 -07001165 struct gl_shader_program *shProg;
1166 shProg = _mesa_lookup_shader_program(ctx, program);
1167 if (!shProg) {
Brian43975832007-01-04 08:21:09 -07001168 _mesa_error(ctx, GL_INVALID_VALUE, "glValidateProgram(program)");
Brian34ae99d2006-12-18 08:28:54 -07001169 return;
1170 }
Brian5b01c5e2006-12-19 18:02:03 -07001171 /* XXX temporary */
Brian65a18442006-12-19 18:46:56 -07001172 shProg->Validated = GL_TRUE;
Brian34ae99d2006-12-18 08:28:54 -07001173
Brian5b01c5e2006-12-19 18:02:03 -07001174 /* From the GL spec:
1175 any two active samplers in the current program object are of
1176 different types, but refer to the same texture image unit,
1177
1178 any active sampler in the current program object refers to a texture
1179 image unit where fixed-function fragment processing accesses a
1180 texture target that does not match the sampler type, or
1181
1182 the sum of the number of active samplers in the program and the
1183 number of texture image units enabled for fixed-function fragment
1184 processing exceeds the combined limit on the total number of texture
1185 image units allowed.
1186 */
Brian34ae99d2006-12-18 08:28:54 -07001187}