blob: 47622fdd52192714e50c3cb66643ede772688928 [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
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
117 assert(shProg->Type == GL_SHADER_PROGRAM);
118
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{
Brian3c008a02007-04-12 15:22:32 -0600138 printf("FREE SHADER PROG %d\n", shProg->Name);
Brianf2923612006-12-20 09:56:44 -0700139 _mesa_free_shader_program_data(ctx, shProg);
Brianb9fbedd2007-03-26 09:23:44 -0600140 if (shProg->Shaders) {
141 _mesa_free(shProg->Shaders);
142 shProg->Shaders = NULL;
143 }
Brianf2923612006-12-20 09:56:44 -0700144 _mesa_free(shProg);
145}
146
147
148/**
Brian3c008a02007-04-12 15:22:32 -0600149 * Set ptr to point to shProg.
150 * If ptr is pointing to another object, decrement its refcount (and delete
151 * if refcount hits zero).
152 * Then set ptr to point to shProg, incrementing its refcount.
153 */
154/* XXX this could be static */
155void
156_mesa_reference_shader_program(GLcontext *ctx,
157 struct gl_shader_program **ptr,
158 struct gl_shader_program *shProg)
159{
160 assert(ptr);
161 if (*ptr == shProg) {
162 /* no-op */
163 return;
164 }
165 if (*ptr) {
166 /* Unreference the old shader program */
167 GLboolean deleteFlag = GL_FALSE;
168 struct gl_shader_program *old = *ptr;
169
170 ASSERT(old->RefCount > 0);
171 old->RefCount--;
172 /*printf("SHPROG DECR %p (%d) to %d\n",
173 (void*) old, old->Name, old->RefCount);*/
174 deleteFlag = (old->RefCount == 0);
175
176 if (deleteFlag) {
177 _mesa_HashRemove(ctx->Shared->ShaderObjects, old->Name);
178 _mesa_free_shader_program(ctx, old);
179 }
180
181 *ptr = NULL;
182 }
183 assert(!*ptr);
184
185 if (shProg) {
186 shProg->RefCount++;
187 printf("SHPROG INCR %p (%d) to %d\n",
188 (void*) shProg, shProg->Name, shProg->RefCount);
189 *ptr = shProg;
190 }
191}
192
193
194/**
Brianf2923612006-12-20 09:56:44 -0700195 * Lookup a GLSL program object.
196 */
197struct gl_shader_program *
198_mesa_lookup_shader_program(GLcontext *ctx, GLuint name)
199{
200 struct gl_shader_program *shProg;
201 if (name) {
202 shProg = (struct gl_shader_program *)
203 _mesa_HashLookup(ctx->Shared->ShaderObjects, name);
204 /* Note that both gl_shader and gl_shader_program objects are kept
205 * in the same hash table. Check the object's type to be sure it's
206 * what we're expecting.
207 */
208 if (shProg && shProg->Type != GL_SHADER_PROGRAM) {
209 return NULL;
210 }
211 return shProg;
212 }
213 return NULL;
214}
215
216
217/**
218 * Allocate a new gl_shader object, initialize it.
219 */
220struct gl_shader *
221_mesa_new_shader(GLcontext *ctx, GLuint name, GLenum type)
222{
223 struct gl_shader *shader;
224 assert(type == GL_FRAGMENT_SHADER || type == GL_VERTEX_SHADER);
225 shader = CALLOC_STRUCT(gl_shader);
226 if (shader) {
227 shader->Type = type;
228 shader->Name = name;
229 shader->RefCount = 1;
230 }
231 return shader;
232}
233
234
235void
236_mesa_free_shader(GLcontext *ctx, struct gl_shader *sh)
237{
238 GLuint i;
Brian3c008a02007-04-12 15:22:32 -0600239 printf("FREE SHADER %d\n", sh->Name);
Brianf2923612006-12-20 09:56:44 -0700240 if (sh->Source)
241 _mesa_free((void *) sh->Source);
242 if (sh->InfoLog)
243 _mesa_free(sh->InfoLog);
244 for (i = 0; i < sh->NumPrograms; i++) {
245 assert(sh->Programs[i]);
246 _mesa_delete_program(ctx, sh->Programs[i]);
247 }
248 if (sh->Programs)
249 _mesa_free(sh->Programs);
250 _mesa_free(sh);
251}
252
253
254/**
Brian3c008a02007-04-12 15:22:32 -0600255 * Set ptr to point to sh.
256 * If ptr is pointing to another shader, decrement its refcount (and delete
257 * if refcount hits zero).
258 * Then set ptr to point to sh, incrementing its refcount.
259 */
260/* XXX this could be static */
261void
262_mesa_reference_shader(GLcontext *ctx, struct gl_shader **ptr,
263 struct gl_shader *sh)
264{
265 assert(ptr);
266 if (*ptr == sh) {
267 /* no-op */
268 return;
269 }
270 if (*ptr) {
271 /* Unreference the old shader */
272 GLboolean deleteFlag = GL_FALSE;
273 struct gl_shader *old = *ptr;
274
275 ASSERT(old->RefCount > 0);
276 old->RefCount--;
277 printf("SHADER DECR %p (%d) to %d\n",
278 (void*) old, old->Name, old->RefCount);
279 deleteFlag = (old->RefCount == 0);
280
281 if (deleteFlag) {
282 _mesa_HashRemove(ctx->Shared->ShaderObjects, old->Name);
283 _mesa_free_shader(ctx, old);
284 }
285
286 *ptr = NULL;
287 }
288 assert(!*ptr);
289
290 if (sh) {
291 /* reference new */
292 sh->RefCount++;
293 printf("SHADER INCR %p (%d) to %d\n",
294 (void*) sh, sh->Name, sh->RefCount);
295 *ptr = sh;
296 }
297}
298
299
300/**
Brianf2923612006-12-20 09:56:44 -0700301 * Lookup a GLSL shader object.
302 */
303struct gl_shader *
304_mesa_lookup_shader(GLcontext *ctx, GLuint name)
305{
306 if (name) {
307 struct gl_shader *sh = (struct gl_shader *)
308 _mesa_HashLookup(ctx->Shared->ShaderObjects, name);
309 /* Note that both gl_shader and gl_shader_program objects are kept
310 * in the same hash table. Check the object's type to be sure it's
311 * what we're expecting.
312 */
313 if (sh && sh->Type == GL_SHADER_PROGRAM) {
314 assert(sh->Type == GL_VERTEX_SHADER ||
315 sh->Type == GL_FRAGMENT_SHADER);
316 return NULL;
317 }
318 return sh;
319 }
320 return NULL;
321}
322
323
Brianfa4d0362007-02-26 18:33:50 -0700324/**
325 * Initialize context's shader state.
326 */
Brianf2923612006-12-20 09:56:44 -0700327void
328_mesa_init_shader_state(GLcontext * ctx)
329{
Brianfa4d0362007-02-26 18:33:50 -0700330 /* Device drivers may override these to control what kind of instructions
331 * are generated by the GLSL compiler.
332 */
333 ctx->Shader.EmitHighLevelInstructions = GL_TRUE;
Brian63556fa2007-03-23 14:47:46 -0600334 ctx->Shader.EmitCondCodes = GL_TRUE; /* XXX probably want GL_FALSE... */
Brianfa4d0362007-02-26 18:33:50 -0700335 ctx->Shader.EmitComments = GL_FALSE;
Brianf2923612006-12-20 09:56:44 -0700336}
337
338
Brian5b01c5e2006-12-19 18:02:03 -0700339/**
Brian935f93f2007-03-24 16:20:02 -0600340 * Free the per-context shader-related state.
341 */
342void
343_mesa_free_shader_state(GLcontext *ctx)
344{
Brian3c008a02007-04-12 15:22:32 -0600345 _mesa_reference_shader_program(ctx, &ctx->Shader.CurrentProgram, NULL);
Brian935f93f2007-03-24 16:20:02 -0600346}
347
348
349/**
Brian5b01c5e2006-12-19 18:02:03 -0700350 * Copy string from <src> to <dst>, up to maxLength characters, returning
351 * length of <dst> in <length>.
352 * \param src the strings source
353 * \param maxLength max chars to copy
354 * \param length returns number of chars copied
355 * \param dst the string destination
356 */
357static void
358copy_string(GLchar *dst, GLsizei maxLength, GLsizei *length, const GLchar *src)
359{
360 GLsizei len;
361 for (len = 0; len < maxLength - 1 && src && src[len]; len++)
362 dst[len] = src[len];
363 if (maxLength > 0)
364 dst[len] = 0;
365 if (length)
366 *length = len;
367}
368
369
Brian5b01c5e2006-12-19 18:02:03 -0700370/**
371 * Called via ctx->Driver.AttachShader()
372 */
373void
374_mesa_attach_shader(GLcontext *ctx, GLuint program, GLuint shader)
375{
Brian65a18442006-12-19 18:46:56 -0700376 struct gl_shader_program *shProg
377 = _mesa_lookup_shader_program(ctx, program);
378 struct gl_shader *sh = _mesa_lookup_shader(ctx, shader);
379 const GLuint n = shProg->NumShaders;
Brian5b01c5e2006-12-19 18:02:03 -0700380 GLuint i;
381
Brian65a18442006-12-19 18:46:56 -0700382 if (!shProg || !sh) {
Brian43975832007-01-04 08:21:09 -0700383 _mesa_error(ctx, GL_INVALID_VALUE,
Brian5b01c5e2006-12-19 18:02:03 -0700384 "glAttachShader(bad program or shader name)");
385 return;
386 }
387
388 for (i = 0; i < n; i++) {
Brian65a18442006-12-19 18:46:56 -0700389 if (shProg->Shaders[i] == sh) {
Brian5b01c5e2006-12-19 18:02:03 -0700390 /* already attached */
391 return;
Brian34ae99d2006-12-18 08:28:54 -0700392 }
393 }
Brian5b01c5e2006-12-19 18:02:03 -0700394
395 /* grow list */
Brian65a18442006-12-19 18:46:56 -0700396 shProg->Shaders = (struct gl_shader **)
397 _mesa_realloc(shProg->Shaders,
398 n * sizeof(struct gl_shader *),
399 (n + 1) * sizeof(struct gl_shader *));
400 if (!shProg->Shaders) {
Brian5b01c5e2006-12-19 18:02:03 -0700401 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glAttachShader");
402 return;
403 }
404
405 /* append */
Brian3c008a02007-04-12 15:22:32 -0600406 shProg->Shaders[n] = NULL; /* since realloc() didn't zero the new space */
407 _mesa_reference_shader(ctx, &shProg->Shaders[n], sh);
Brian65a18442006-12-19 18:46:56 -0700408 shProg->NumShaders++;
Brian5b01c5e2006-12-19 18:02:03 -0700409}
410
411
412void
413_mesa_bind_attrib_location(GLcontext *ctx, GLuint program, GLuint index,
414 const GLchar *name)
415{
Brian65a18442006-12-19 18:46:56 -0700416 struct gl_shader_program *shProg
417 = _mesa_lookup_shader_program(ctx, program);
Brianb7978af2007-01-09 19:17:17 -0700418 const GLint size = -1; /* unknown size */
419 GLint i, oldIndex;
Brian5b01c5e2006-12-19 18:02:03 -0700420
Brian65a18442006-12-19 18:46:56 -0700421 if (!shProg) {
Brian43975832007-01-04 08:21:09 -0700422 _mesa_error(ctx, GL_INVALID_VALUE, "glBindAttribLocation(program)");
Brian5b01c5e2006-12-19 18:02:03 -0700423 return;
424 }
425
Brian9e4bae92006-12-20 09:27:42 -0700426 if (!name)
427 return;
428
429 if (strncmp(name, "gl_", 3) == 0) {
430 _mesa_error(ctx, GL_INVALID_OPERATION,
431 "glBindAttribLocation(illegal name)");
432 return;
433 }
434
Brian9f660252007-04-11 09:00:56 -0600435 if (shProg->LinkStatus) {
436 /* get current index/location for the attribute */
437 oldIndex = _mesa_get_attrib_location(ctx, program, name);
438 }
439 else {
440 oldIndex = -1;
441 }
Brian3209c3e2007-01-09 17:49:24 -0700442
443 /* this will replace the current value if it's already in the list */
Brianb7978af2007-01-09 19:17:17 -0700444 i = _mesa_add_attribute(shProg->Attributes, name, size, index);
Brian3209c3e2007-01-09 17:49:24 -0700445 if (i < 0) {
446 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBindAttribLocation");
447 }
448
Brian9f660252007-04-11 09:00:56 -0600449 if (shProg->VertexProgram && oldIndex >= 0 && oldIndex != index) {
450 /* If the index changed, need to search/replace references to that attribute
451 * in the vertex program.
452 */
Brian3209c3e2007-01-09 17:49:24 -0700453 _slang_remap_attribute(&shProg->VertexProgram->Base, oldIndex, index);
454 }
Brian34ae99d2006-12-18 08:28:54 -0700455}
456
457
Brian5b01c5e2006-12-19 18:02:03 -0700458GLuint
459_mesa_create_shader(GLcontext *ctx, GLenum type)
460{
Brian65a18442006-12-19 18:46:56 -0700461 struct gl_shader *sh;
Brian5b01c5e2006-12-19 18:02:03 -0700462 GLuint name;
463
464 name = _mesa_HashFindFreeKeyBlock(ctx->Shared->ShaderObjects, 1);
465
466 switch (type) {
Brian65a18442006-12-19 18:46:56 -0700467 case GL_FRAGMENT_SHADER:
468 case GL_VERTEX_SHADER:
469 sh = _mesa_new_shader(ctx, name, type);
Brian5b01c5e2006-12-19 18:02:03 -0700470 break;
471 default:
472 _mesa_error(ctx, GL_INVALID_ENUM, "CreateShader(type)");
473 return 0;
474 }
475
Brian65a18442006-12-19 18:46:56 -0700476 _mesa_HashInsert(ctx->Shared->ShaderObjects, name, sh);
Brian5b01c5e2006-12-19 18:02:03 -0700477
478 return name;
479}
480
481
482GLuint
483_mesa_create_program(GLcontext *ctx)
484{
485 GLuint name;
Brian65a18442006-12-19 18:46:56 -0700486 struct gl_shader_program *shProg;
Brian5b01c5e2006-12-19 18:02:03 -0700487
Brian65a18442006-12-19 18:46:56 -0700488 name = _mesa_HashFindFreeKeyBlock(ctx->Shared->ShaderObjects, 1);
489 shProg = _mesa_new_shader_program(ctx, name);
Brian5b01c5e2006-12-19 18:02:03 -0700490
Brian65a18442006-12-19 18:46:56 -0700491 _mesa_HashInsert(ctx->Shared->ShaderObjects, name, shProg);
Brian5b01c5e2006-12-19 18:02:03 -0700492
Brian3c008a02007-04-12 15:22:32 -0600493 assert(shProg->RefCount == 1);
494
Brian5b01c5e2006-12-19 18:02:03 -0700495 return name;
496}
497
498
Brian3c008a02007-04-12 15:22:32 -0600499/**
500 * Named w/ "2" to indicate OpenGL 2.x vs GL_ARB_fragment_programs's
501 * DeleteProgramARB.
502 */
Brian5b01c5e2006-12-19 18:02:03 -0700503void
504_mesa_delete_program2(GLcontext *ctx, GLuint name)
505{
Brian3c008a02007-04-12 15:22:32 -0600506 /*
507 * NOTE: deleting shaders/programs works a bit differently than
508 * texture objects (and buffer objects, etc). Shader/program
509 * handles/IDs exist in the hash table until the object is really
510 * deleted (refcount==0). With texture objects, the handle/ID is
511 * removed from the hash table in glDeleteTextures() while the tex
512 * object itself might linger until its refcount goes to zero.
513 */
Brian65a18442006-12-19 18:46:56 -0700514 struct gl_shader_program *shProg;
Brian5b01c5e2006-12-19 18:02:03 -0700515
Brian65a18442006-12-19 18:46:56 -0700516 shProg = _mesa_lookup_shader_program(ctx, name);
517 if (!shProg) {
Brian43975832007-01-04 08:21:09 -0700518 _mesa_error(ctx, GL_INVALID_VALUE, "glDeleteProgram(name)");
Brian5b01c5e2006-12-19 18:02:03 -0700519 return;
520 }
521
Brian9e4bae92006-12-20 09:27:42 -0700522 shProg->DeletePending = GL_TRUE;
523
Brian3c008a02007-04-12 15:22:32 -0600524 /* effectively, decr shProg's refcount */
525 _mesa_reference_shader_program(ctx, &shProg, NULL);
Brian5b01c5e2006-12-19 18:02:03 -0700526}
527
528
529void
530_mesa_delete_shader(GLcontext *ctx, GLuint shader)
531{
Brian9e4bae92006-12-20 09:27:42 -0700532 struct gl_shader *sh = _mesa_lookup_shader(ctx, shader);
533 if (!sh) {
534 return;
535 }
Brian5b01c5e2006-12-19 18:02:03 -0700536
Brian9e4bae92006-12-20 09:27:42 -0700537 sh->DeletePending = GL_TRUE;
Brian3c008a02007-04-12 15:22:32 -0600538
539 /* effectively, decr sh's refcount */
540 _mesa_reference_shader(ctx, &sh, NULL);
Brian5b01c5e2006-12-19 18:02:03 -0700541}
542
543
544void
545_mesa_detach_shader(GLcontext *ctx, GLuint program, GLuint shader)
546{
Brian65a18442006-12-19 18:46:56 -0700547 struct gl_shader_program *shProg
548 = _mesa_lookup_shader_program(ctx, program);
549 const GLuint n = shProg->NumShaders;
Brian5b01c5e2006-12-19 18:02:03 -0700550 GLuint i, j;
551
Brian65a18442006-12-19 18:46:56 -0700552 if (!shProg) {
Brian43975832007-01-04 08:21:09 -0700553 _mesa_error(ctx, GL_INVALID_VALUE,
Brian5b01c5e2006-12-19 18:02:03 -0700554 "glDetachShader(bad program or shader name)");
555 return;
556 }
557
558 for (i = 0; i < n; i++) {
Brian65a18442006-12-19 18:46:56 -0700559 if (shProg->Shaders[i]->Name == shader) {
Brian5b01c5e2006-12-19 18:02:03 -0700560 /* found it */
Brian3c008a02007-04-12 15:22:32 -0600561 struct gl_shader **newList;
Brian9e4bae92006-12-20 09:27:42 -0700562
Brian3c008a02007-04-12 15:22:32 -0600563 /* derefernce */
564 _mesa_reference_shader(ctx, &shProg->Shaders[i], NULL);
Brian9e4bae92006-12-20 09:27:42 -0700565
Brian5b01c5e2006-12-19 18:02:03 -0700566 /* alloc new, smaller array */
Brian65a18442006-12-19 18:46:56 -0700567 newList = (struct gl_shader **)
568 _mesa_malloc((n - 1) * sizeof(struct gl_shader *));
Brian5b01c5e2006-12-19 18:02:03 -0700569 if (!newList) {
570 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glDetachShader");
571 return;
572 }
573 for (j = 0; j < i; j++) {
Brian65a18442006-12-19 18:46:56 -0700574 newList[j] = shProg->Shaders[j];
Brian5b01c5e2006-12-19 18:02:03 -0700575 }
576 while (++i < n)
Brian65a18442006-12-19 18:46:56 -0700577 newList[j++] = shProg->Shaders[i];
578 _mesa_free(shProg->Shaders);
Brian5b01c5e2006-12-19 18:02:03 -0700579
Brian65a18442006-12-19 18:46:56 -0700580 shProg->Shaders = newList;
Brian5b01c5e2006-12-19 18:02:03 -0700581 return;
582 }
583 }
584
585 /* not found */
Brian43975832007-01-04 08:21:09 -0700586 _mesa_error(ctx, GL_INVALID_VALUE,
Brian5b01c5e2006-12-19 18:02:03 -0700587 "glDetachShader(shader not found)");
588}
589
590
591void
592_mesa_get_active_attrib(GLcontext *ctx, GLuint program, GLuint index,
593 GLsizei maxLength, GLsizei *length, GLint *size,
594 GLenum *type, GLchar *nameOut)
595{
596 static const GLenum vec_types[] = {
597 GL_FLOAT, GL_FLOAT_VEC2, GL_FLOAT_VEC3, GL_FLOAT_VEC4
598 };
Brian65a18442006-12-19 18:46:56 -0700599 struct gl_shader_program *shProg
600 = _mesa_lookup_shader_program(ctx, program);
Brian5b01c5e2006-12-19 18:02:03 -0700601 GLint sz;
602
Brian65a18442006-12-19 18:46:56 -0700603 if (!shProg) {
Brian43975832007-01-04 08:21:09 -0700604 _mesa_error(ctx, GL_INVALID_VALUE, "glGetActiveUniform");
Brian5b01c5e2006-12-19 18:02:03 -0700605 return;
606 }
607
Brian65a18442006-12-19 18:46:56 -0700608 if (!shProg->Attributes || index >= shProg->Attributes->NumParameters) {
Brian5b01c5e2006-12-19 18:02:03 -0700609 _mesa_error(ctx, GL_INVALID_VALUE, "glGetActiveUniform(index)");
610 return;
611 }
612
613 copy_string(nameOut, maxLength, length,
Brian65a18442006-12-19 18:46:56 -0700614 shProg->Attributes->Parameters[index].Name);
615 sz = shProg->Attributes->Parameters[index].Size;
Brian5b01c5e2006-12-19 18:02:03 -0700616 if (size)
617 *size = sz;
618 if (type)
619 *type = vec_types[sz]; /* XXX this is a temporary hack */
620}
621
622
623/**
624 * Called via ctx->Driver.GetActiveUniform().
625 */
626void
627_mesa_get_active_uniform(GLcontext *ctx, GLuint program, GLuint index,
628 GLsizei maxLength, GLsizei *length, GLint *size,
629 GLenum *type, GLchar *nameOut)
630{
631 static const GLenum vec_types[] = {
632 GL_FLOAT, GL_FLOAT_VEC2, GL_FLOAT_VEC3, GL_FLOAT_VEC4
633 };
Brian65a18442006-12-19 18:46:56 -0700634 struct gl_shader_program *shProg
635 = _mesa_lookup_shader_program(ctx, program);
Brian5b01c5e2006-12-19 18:02:03 -0700636 GLint sz;
637
Brian65a18442006-12-19 18:46:56 -0700638 if (!shProg) {
Brian43975832007-01-04 08:21:09 -0700639 _mesa_error(ctx, GL_INVALID_VALUE, "glGetActiveUniform");
Brian5b01c5e2006-12-19 18:02:03 -0700640 return;
641 }
642
Brian65a18442006-12-19 18:46:56 -0700643 if (!shProg->Uniforms || index >= shProg->Uniforms->NumParameters) {
Brian5b01c5e2006-12-19 18:02:03 -0700644 _mesa_error(ctx, GL_INVALID_VALUE, "glGetActiveUniform(index)");
645 return;
646 }
647
648 copy_string(nameOut, maxLength, length,
Brian65a18442006-12-19 18:46:56 -0700649 shProg->Uniforms->Parameters[index].Name);
650 sz = shProg->Uniforms->Parameters[index].Size;
Brian5b01c5e2006-12-19 18:02:03 -0700651 if (size)
652 *size = sz;
653 if (type)
654 *type = vec_types[sz]; /* XXX this is a temporary hack */
655}
656
657
658/**
659 * Called via ctx->Driver.GetAttachedShaders().
660 */
661void
662_mesa_get_attached_shaders(GLcontext *ctx, GLuint program, GLsizei maxCount,
663 GLsizei *count, GLuint *obj)
664{
Brian65a18442006-12-19 18:46:56 -0700665 struct gl_shader_program *shProg
666 = _mesa_lookup_shader_program(ctx, program);
667 if (shProg) {
Brian223d7cb2007-01-23 16:37:51 -0700668 GLint i;
Brian65a18442006-12-19 18:46:56 -0700669 for (i = 0; i < maxCount && i < shProg->NumShaders; i++) {
670 obj[i] = shProg->Shaders[i]->Name;
Brian5b01c5e2006-12-19 18:02:03 -0700671 }
672 if (count)
673 *count = i;
674 }
675 else {
Brian43975832007-01-04 08:21:09 -0700676 _mesa_error(ctx, GL_INVALID_VALUE, "glGetAttachedShaders");
Brian5b01c5e2006-12-19 18:02:03 -0700677 }
678}
679
680
681GLint
682_mesa_get_attrib_location(GLcontext *ctx, GLuint program,
683 const GLchar *name)
684{
Brian65a18442006-12-19 18:46:56 -0700685 struct gl_shader_program *shProg
686 = _mesa_lookup_shader_program(ctx, program);
Brian5b01c5e2006-12-19 18:02:03 -0700687
Brian65a18442006-12-19 18:46:56 -0700688 if (!shProg) {
Brian43975832007-01-04 08:21:09 -0700689 _mesa_error(ctx, GL_INVALID_VALUE, "glGetAttribLocation");
Brian5b01c5e2006-12-19 18:02:03 -0700690 return -1;
691 }
692
Brian65a18442006-12-19 18:46:56 -0700693 if (!shProg->LinkStatus) {
Brian5b01c5e2006-12-19 18:02:03 -0700694 _mesa_error(ctx, GL_INVALID_OPERATION,
695 "glGetAttribLocation(program not linked)");
696 return -1;
697 }
698
699 if (!name)
700 return -1;
701
Brian65a18442006-12-19 18:46:56 -0700702 if (shProg->Attributes) {
Brian3209c3e2007-01-09 17:49:24 -0700703 GLint i = _mesa_lookup_parameter_index(shProg->Attributes, -1, name);
704 if (i >= 0) {
Brian01a91eb2007-01-09 19:26:22 -0700705 return shProg->Attributes->Parameters[i].StateIndexes[0];
Brian5b01c5e2006-12-19 18:02:03 -0700706 }
707 }
708 return -1;
709}
710
711
712GLuint
713_mesa_get_handle(GLcontext *ctx, GLenum pname)
Brian34ae99d2006-12-18 08:28:54 -0700714{
715#if 0
716 GET_CURRENT_CONTEXT(ctx);
717
718 switch (pname) {
719 case GL_PROGRAM_OBJECT_ARB:
720 {
Brian5b01c5e2006-12-19 18:02:03 -0700721 struct gl2_program_intf **pro = ctx->Shader.CurrentProgram;
Brian34ae99d2006-12-18 08:28:54 -0700722
723 if (pro != NULL)
724 return (**pro)._container._generic.
725 GetName((struct gl2_generic_intf **) (pro));
726 }
727 break;
728 default:
729 _mesa_error(ctx, GL_INVALID_ENUM, "glGetHandleARB");
730 }
731#endif
732 return 0;
733}
734
735
Brian5b01c5e2006-12-19 18:02:03 -0700736void
737_mesa_get_programiv(GLcontext *ctx, GLuint program,
738 GLenum pname, GLint *params)
Brian34ae99d2006-12-18 08:28:54 -0700739{
Brian65a18442006-12-19 18:46:56 -0700740 struct gl_shader_program *shProg
741 = _mesa_lookup_shader_program(ctx, program);
Brian34ae99d2006-12-18 08:28:54 -0700742
Brian65a18442006-12-19 18:46:56 -0700743 if (!shProg) {
Brian5b01c5e2006-12-19 18:02:03 -0700744 _mesa_error(ctx, GL_INVALID_VALUE, "glGetProgramiv(program)");
Brian34ae99d2006-12-18 08:28:54 -0700745 return;
746 }
747
Brian5b01c5e2006-12-19 18:02:03 -0700748 switch (pname) {
749 case GL_DELETE_STATUS:
Brian65a18442006-12-19 18:46:56 -0700750 *params = shProg->DeletePending;
Brian5b01c5e2006-12-19 18:02:03 -0700751 break;
752 case GL_LINK_STATUS:
Brian65a18442006-12-19 18:46:56 -0700753 *params = shProg->LinkStatus;
Brian34ae99d2006-12-18 08:28:54 -0700754 break;
Brian5b01c5e2006-12-19 18:02:03 -0700755 case GL_VALIDATE_STATUS:
Brian65a18442006-12-19 18:46:56 -0700756 *params = shProg->Validated;
Brian5b01c5e2006-12-19 18:02:03 -0700757 break;
758 case GL_INFO_LOG_LENGTH:
Brian65a18442006-12-19 18:46:56 -0700759 *params = shProg->InfoLog ? strlen(shProg->InfoLog) : 0;
Brian5b01c5e2006-12-19 18:02:03 -0700760 break;
761 case GL_ATTACHED_SHADERS:
Brian65a18442006-12-19 18:46:56 -0700762 *params = shProg->NumShaders;
Brian5b01c5e2006-12-19 18:02:03 -0700763 break;
764 case GL_ACTIVE_ATTRIBUTES:
Brian3209c3e2007-01-09 17:49:24 -0700765 *params = shProg->Attributes ? shProg->Attributes->NumParameters : 0;
Brian5b01c5e2006-12-19 18:02:03 -0700766 break;
767 case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH:
Brian65a18442006-12-19 18:46:56 -0700768 *params = _mesa_parameter_longest_name(shProg->Attributes);
Brian5b01c5e2006-12-19 18:02:03 -0700769 break;
770 case GL_ACTIVE_UNIFORMS:
Brian65a18442006-12-19 18:46:56 -0700771 *params = shProg->Uniforms ? shProg->Uniforms->NumParameters : 0;
Brian5b01c5e2006-12-19 18:02:03 -0700772 break;
773 case GL_ACTIVE_UNIFORM_MAX_LENGTH:
Brian65a18442006-12-19 18:46:56 -0700774 *params = _mesa_parameter_longest_name(shProg->Uniforms);
Brian34ae99d2006-12-18 08:28:54 -0700775 break;
776 default:
Brian5b01c5e2006-12-19 18:02:03 -0700777 _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramiv(pname)");
778 return;
Brian34ae99d2006-12-18 08:28:54 -0700779 }
Brian5b01c5e2006-12-19 18:02:03 -0700780}
Brian34ae99d2006-12-18 08:28:54 -0700781
Brian34ae99d2006-12-18 08:28:54 -0700782
Brian5b01c5e2006-12-19 18:02:03 -0700783void
784_mesa_get_shaderiv(GLcontext *ctx, GLuint name, GLenum pname, GLint *params)
785{
Brian65a18442006-12-19 18:46:56 -0700786 struct gl_shader *shader = _mesa_lookup_shader(ctx, name);
Brian5b01c5e2006-12-19 18:02:03 -0700787
788 if (!shader) {
789 _mesa_error(ctx, GL_INVALID_VALUE, "glGetShaderiv(shader)");
790 return;
791 }
Brian65a18442006-12-19 18:46:56 -0700792
Brian5b01c5e2006-12-19 18:02:03 -0700793 switch (pname) {
794 case GL_SHADER_TYPE:
795 *params = shader->Type;
796 break;
797 case GL_DELETE_STATUS:
798 *params = shader->DeletePending;
799 break;
800 case GL_COMPILE_STATUS:
801 *params = shader->CompileStatus;
802 break;
803 case GL_INFO_LOG_LENGTH:
804 *params = shader->InfoLog ? strlen(shader->InfoLog) : 0;
805 break;
806 case GL_SHADER_SOURCE_LENGTH:
807 *params = shader->Source ? strlen((char *) shader->Source) : 0;
808 break;
809 default:
810 _mesa_error(ctx, GL_INVALID_ENUM, "glGetShaderiv(pname)");
811 return;
812 }
813}
814
815
816void
817_mesa_get_program_info_log(GLcontext *ctx, GLuint program, GLsizei bufSize,
818 GLsizei *length, GLchar *infoLog)
819{
Brian65a18442006-12-19 18:46:56 -0700820 struct gl_shader_program *shProg
821 = _mesa_lookup_shader_program(ctx, program);
822 if (!shProg) {
Brian5b01c5e2006-12-19 18:02:03 -0700823 _mesa_error(ctx, GL_INVALID_VALUE, "glGetProgramInfoLog(program)");
824 return;
825 }
Brian65a18442006-12-19 18:46:56 -0700826 copy_string(infoLog, bufSize, length, shProg->InfoLog);
Brian5b01c5e2006-12-19 18:02:03 -0700827}
828
829
830void
831_mesa_get_shader_info_log(GLcontext *ctx, GLuint shader, GLsizei bufSize,
832 GLsizei *length, GLchar *infoLog)
833{
Brian65a18442006-12-19 18:46:56 -0700834 struct gl_shader *sh = _mesa_lookup_shader(ctx, shader);
835 if (!sh) {
Brian5b01c5e2006-12-19 18:02:03 -0700836 _mesa_error(ctx, GL_INVALID_VALUE, "glGetShaderInfoLog(shader)");
837 return;
838 }
Brian65a18442006-12-19 18:46:56 -0700839 copy_string(infoLog, bufSize, length, sh->InfoLog);
Brian5b01c5e2006-12-19 18:02:03 -0700840}
841
842
843/**
844 * Called via ctx->Driver.GetShaderSource().
845 */
846void
847_mesa_get_shader_source(GLcontext *ctx, GLuint shader, GLsizei maxLength,
848 GLsizei *length, GLchar *sourceOut)
849{
Brian65a18442006-12-19 18:46:56 -0700850 struct gl_shader *sh = _mesa_lookup_shader(ctx, shader);
851 if (!sh) {
Brian5b01c5e2006-12-19 18:02:03 -0700852 _mesa_error(ctx, GL_INVALID_VALUE, "glGetShaderSource(shader)");
853 return;
854 }
Brian65a18442006-12-19 18:46:56 -0700855 copy_string(sourceOut, maxLength, length, sh->Source);
Brian5b01c5e2006-12-19 18:02:03 -0700856}
857
858
859/**
860 * Called via ctx->Driver.GetUniformfv().
861 */
862void
863_mesa_get_uniformfv(GLcontext *ctx, GLuint program, GLint location,
864 GLfloat *params)
865{
Brian65a18442006-12-19 18:46:56 -0700866 struct gl_shader_program *shProg
867 = _mesa_lookup_shader_program(ctx, program);
868 if (shProg) {
Brian223d7cb2007-01-23 16:37:51 -0700869 GLint i;
Brian65a18442006-12-19 18:46:56 -0700870 if (location >= 0 && location < shProg->Uniforms->NumParameters) {
871 for (i = 0; i < shProg->Uniforms->Parameters[location].Size; i++) {
872 params[i] = shProg->Uniforms->ParameterValues[location][i];
Brian5b01c5e2006-12-19 18:02:03 -0700873 }
874 }
875 else {
876 _mesa_error(ctx, GL_INVALID_VALUE, "glGetUniformfv(location)");
877 }
878 }
879 else {
Brian43975832007-01-04 08:21:09 -0700880 _mesa_error(ctx, GL_INVALID_VALUE, "glGetUniformfv(program)");
Brian5b01c5e2006-12-19 18:02:03 -0700881 }
882}
883
884
885/**
886 * Called via ctx->Driver.GetUniformLocation().
887 */
888GLint
889_mesa_get_uniform_location(GLcontext *ctx, GLuint program, const GLchar *name)
890{
Brian71623982007-01-30 16:55:03 -0700891 struct gl_shader_program *shProg
892 = _mesa_lookup_shader_program(ctx, program);
893 if (shProg) {
Brian5b01c5e2006-12-19 18:02:03 -0700894 GLuint loc;
Brian65a18442006-12-19 18:46:56 -0700895 for (loc = 0; loc < shProg->Uniforms->NumParameters; loc++) {
Brian5b01c5e2006-12-19 18:02:03 -0700896 const struct gl_program_parameter *u
Brian65a18442006-12-19 18:46:56 -0700897 = shProg->Uniforms->Parameters + loc;
Brian29053852006-12-21 11:21:26 -0700898 /* XXX this is a temporary simplification / short-cut.
899 * We need to handle things like "e.c[0].b" as seen in the
900 * GLSL orange book, page 189.
901 */
Brian5cf73262007-01-05 16:02:45 -0700902 if ((u->Type == PROGRAM_UNIFORM ||
903 u->Type == PROGRAM_SAMPLER) && !strcmp(u->Name, name)) {
Brian5b01c5e2006-12-19 18:02:03 -0700904 return loc;
905 }
906 }
907 }
908 return -1;
909
910}
911
912
913GLboolean
914_mesa_is_program(GLcontext *ctx, GLuint name)
915{
Brian65a18442006-12-19 18:46:56 -0700916 struct gl_shader_program *shProg = _mesa_lookup_shader_program(ctx, name);
917 return shProg ? GL_TRUE : GL_FALSE;
Brian5b01c5e2006-12-19 18:02:03 -0700918}
919
920
921GLboolean
922_mesa_is_shader(GLcontext *ctx, GLuint name)
923{
Brian65a18442006-12-19 18:46:56 -0700924 struct gl_shader *shader = _mesa_lookup_shader(ctx, name);
Brian5b01c5e2006-12-19 18:02:03 -0700925 return shader ? GL_TRUE : GL_FALSE;
Brian34ae99d2006-12-18 08:28:54 -0700926}
927
928
929
Brian5b01c5e2006-12-19 18:02:03 -0700930/**
931 * Called via ctx->Driver.ShaderSource()
932 */
933void
934_mesa_shader_source(GLcontext *ctx, GLuint shader, const GLchar *source)
Brian34ae99d2006-12-18 08:28:54 -0700935{
Brian65a18442006-12-19 18:46:56 -0700936 struct gl_shader *sh = _mesa_lookup_shader(ctx, shader);
937 if (!sh) {
Brian5b01c5e2006-12-19 18:02:03 -0700938 _mesa_error(ctx, GL_INVALID_VALUE, "glShaderSource(shaderObj)");
Brian34ae99d2006-12-18 08:28:54 -0700939 return;
940 }
941
Brian34ae99d2006-12-18 08:28:54 -0700942 /* free old shader source string and install new one */
Brian65a18442006-12-19 18:46:56 -0700943 if (sh->Source) {
944 _mesa_free((void *) sh->Source);
Brian34ae99d2006-12-18 08:28:54 -0700945 }
Brian65a18442006-12-19 18:46:56 -0700946 sh->Source = source;
Brian9e4bae92006-12-20 09:27:42 -0700947 sh->CompileStatus = GL_FALSE;
Brian34ae99d2006-12-18 08:28:54 -0700948}
949
950
Brian5b01c5e2006-12-19 18:02:03 -0700951/**
952 * Called via ctx->Driver.CompileShader()
953 */
954void
955_mesa_compile_shader(GLcontext *ctx, GLuint shaderObj)
Brian34ae99d2006-12-18 08:28:54 -0700956{
Brian65a18442006-12-19 18:46:56 -0700957 struct gl_shader *sh = _mesa_lookup_shader(ctx, shaderObj);
Brian34ae99d2006-12-18 08:28:54 -0700958
Brian65a18442006-12-19 18:46:56 -0700959 if (!sh) {
Brian34ae99d2006-12-18 08:28:54 -0700960 _mesa_error(ctx, GL_INVALID_VALUE, "glCompileShader(shaderObj)");
961 return;
962 }
963
Brian43975832007-01-04 08:21:09 -0700964 sh->CompileStatus = _slang_compile(ctx, sh);
Brian34ae99d2006-12-18 08:28:54 -0700965}
966
967
Brian5b01c5e2006-12-19 18:02:03 -0700968/**
969 * Called via ctx->Driver.LinkProgram()
970 */
971void
972_mesa_link_program(GLcontext *ctx, GLuint program)
Brian34ae99d2006-12-18 08:28:54 -0700973{
Brian65a18442006-12-19 18:46:56 -0700974 struct gl_shader_program *shProg;
Brian34ae99d2006-12-18 08:28:54 -0700975
Brian65a18442006-12-19 18:46:56 -0700976 shProg = _mesa_lookup_shader_program(ctx, program);
977 if (!shProg) {
Brian43975832007-01-04 08:21:09 -0700978 _mesa_error(ctx, GL_INVALID_VALUE, "glLinkProgram(program)");
Brian34ae99d2006-12-18 08:28:54 -0700979 return;
980 }
981
Brianc1771912007-02-16 09:56:19 -0700982 _slang_link(ctx, program, shProg);
Brian34ae99d2006-12-18 08:28:54 -0700983}
984
985
986/**
Brian5b01c5e2006-12-19 18:02:03 -0700987 * Called via ctx->Driver.UseProgram()
Brian34ae99d2006-12-18 08:28:54 -0700988 */
Brian5b01c5e2006-12-19 18:02:03 -0700989void
990_mesa_use_program(GLcontext *ctx, GLuint program)
Brian34ae99d2006-12-18 08:28:54 -0700991{
Brian3c008a02007-04-12 15:22:32 -0600992 struct gl_shader_program *shProg;
993
Brian00d63aa2007-02-03 11:35:02 -0700994 if (ctx->Shader.CurrentProgram &&
995 ctx->Shader.CurrentProgram->Name == program) {
996 /* no-op */
997 return;
998 }
999
1000 FLUSH_VERTICES(ctx, _NEW_PROGRAM);
1001
Brian5b01c5e2006-12-19 18:02:03 -07001002 if (program) {
Brian65a18442006-12-19 18:46:56 -07001003 shProg = _mesa_lookup_shader_program(ctx, program);
1004 if (!shProg) {
Brian43975832007-01-04 08:21:09 -07001005 _mesa_error(ctx, GL_INVALID_VALUE,
Brian5b01c5e2006-12-19 18:02:03 -07001006 "glUseProgramObjectARB(programObj)");
1007 return;
1008 }
Brian5b01c5e2006-12-19 18:02:03 -07001009 }
1010 else {
Brian3c008a02007-04-12 15:22:32 -06001011 shProg = NULL;
1012 }
1013
1014 _mesa_reference_shader_program(ctx, &ctx->Shader.CurrentProgram, shProg);
Brian5b01c5e2006-12-19 18:02:03 -07001015}
Brian34ae99d2006-12-18 08:28:54 -07001016
Brian5b01c5e2006-12-19 18:02:03 -07001017
1018/**
1019 * Called via ctx->Driver.Uniform().
1020 */
1021void
1022_mesa_uniform(GLcontext *ctx, GLint location, GLsizei count,
1023 const GLvoid *values, GLenum type)
1024{
Brian3a8e2772006-12-20 17:19:16 -07001025 struct gl_shader_program *shProg = ctx->Shader.CurrentProgram;
Brian98650bd2007-03-13 16:32:48 -06001026 GLint elems, i, k;
Brian3a8e2772006-12-20 17:19:16 -07001027
1028 if (!shProg || !shProg->LinkStatus) {
Brian5b01c5e2006-12-19 18:02:03 -07001029 _mesa_error(ctx, GL_INVALID_OPERATION, "glUniform(program not linked)");
Brian3a8e2772006-12-20 17:19:16 -07001030 return;
1031 }
1032
Brian223d7cb2007-01-23 16:37:51 -07001033 if (location < 0 || location >= (GLint) shProg->Uniforms->NumParameters) {
Brian3a8e2772006-12-20 17:19:16 -07001034 _mesa_error(ctx, GL_INVALID_VALUE, "glUniform(location)");
1035 return;
1036 }
1037
1038 FLUSH_VERTICES(ctx, _NEW_PROGRAM);
1039
Brianfee9bbe2007-02-02 18:05:43 -07001040 /*
1041 * If we're setting a sampler, we must use glUniformi1()!
1042 */
1043 if (shProg->Uniforms->Parameters[location].Type == PROGRAM_SAMPLER) {
1044 if (type != GL_INT || count != 1) {
1045 _mesa_error(ctx, GL_INVALID_OPERATION,
1046 "glUniform(only glUniform1i can be used "
1047 "to set sampler uniforms)");
1048 return;
1049 }
1050 }
1051
Brian52363952007-03-13 16:50:24 -06001052 if (count < 0) {
1053 _mesa_error(ctx, GL_INVALID_VALUE, "glUniform(count < 0)");
1054 return;
1055 }
1056
Brian98650bd2007-03-13 16:32:48 -06001057 switch (type) {
1058 case GL_FLOAT:
1059 case GL_INT:
1060 elems = 1;
1061 break;
1062 case GL_FLOAT_VEC2:
1063 case GL_INT_VEC2:
1064 elems = 2;
1065 break;
1066 case GL_FLOAT_VEC3:
1067 case GL_INT_VEC3:
1068 elems = 3;
1069 break;
1070 case GL_FLOAT_VEC4:
1071 case GL_INT_VEC4:
1072 elems = 4;
1073 break;
1074 default:
1075 _mesa_problem(ctx, "Invalid type in _mesa_uniform");
1076 return;
Brian89dc4852007-01-04 14:35:44 -07001077 }
Brian98650bd2007-03-13 16:32:48 -06001078
1079 if (count * elems > shProg->Uniforms->Parameters[location].Size) {
1080 _mesa_error(ctx, GL_INVALID_OPERATION, "glUniform(count too large)");
1081 return;
1082 }
1083
1084 for (k = 0; k < count; k++) {
1085 GLfloat *uniformVal = shProg->Uniforms->ParameterValues[location + k];
1086 if (type == GL_INT ||
1087 type == GL_INT_VEC2 ||
1088 type == GL_INT_VEC3 ||
1089 type == GL_INT_VEC4) {
Brian52363952007-03-13 16:50:24 -06001090 const GLint *iValues = ((const GLint *) values) + k * elems;
Brian98650bd2007-03-13 16:32:48 -06001091 for (i = 0; i < elems; i++) {
1092 uniformVal[i] = (GLfloat) iValues[i];
1093 }
1094 }
1095 else {
Brian52363952007-03-13 16:50:24 -06001096 const GLfloat *fValues = ((const GLfloat *) values) + k * elems;
Brian98650bd2007-03-13 16:32:48 -06001097 for (i = 0; i < elems; i++) {
1098 uniformVal[i] = fValues[i];
1099 }
Brian89dc4852007-01-04 14:35:44 -07001100 }
Brian5b01c5e2006-12-19 18:02:03 -07001101 }
Brian5cf73262007-01-05 16:02:45 -07001102
1103 if (shProg->Uniforms->Parameters[location].Type == PROGRAM_SAMPLER) {
Briancec81ee2007-03-07 08:04:06 -07001104 if (shProg->VertexProgram)
1105 _slang_resolve_samplers(shProg, &shProg->VertexProgram->Base);
1106 if (shProg->FragmentProgram)
1107 _slang_resolve_samplers(shProg, &shProg->FragmentProgram->Base);
Brian5cf73262007-01-05 16:02:45 -07001108 FLUSH_VERTICES(ctx, _NEW_TEXTURE);
1109 }
Brian34ae99d2006-12-18 08:28:54 -07001110}
1111
1112
1113/**
Brian5b01c5e2006-12-19 18:02:03 -07001114 * Called by ctx->Driver.UniformMatrix().
Brian34ae99d2006-12-18 08:28:54 -07001115 */
Brian5b01c5e2006-12-19 18:02:03 -07001116void
1117_mesa_uniform_matrix(GLcontext *ctx, GLint cols, GLint rows,
1118 GLenum matrixType, GLint location, GLsizei count,
1119 GLboolean transpose, const GLfloat *values)
Brian34ae99d2006-12-18 08:28:54 -07001120{
Brian3a8e2772006-12-20 17:19:16 -07001121 struct gl_shader_program *shProg = ctx->Shader.CurrentProgram;
1122 if (!shProg || !shProg->LinkStatus) {
1123 _mesa_error(ctx, GL_INVALID_OPERATION,
1124 "glUniformMatrix(program not linked)");
1125 return;
1126 }
1127 if (location < 0 || location >= shProg->Uniforms->NumParameters) {
1128 _mesa_error(ctx, GL_INVALID_VALUE, "glUniformMatrix(location)");
1129 return;
1130 }
Brian34ae99d2006-12-18 08:28:54 -07001131 if (values == NULL) {
Brian3a8e2772006-12-20 17:19:16 -07001132 _mesa_error(ctx, GL_INVALID_VALUE, "glUniformMatrix");
Brian34ae99d2006-12-18 08:28:54 -07001133 return;
1134 }
1135
1136 FLUSH_VERTICES(ctx, _NEW_PROGRAM);
1137
Brian3a8e2772006-12-20 17:19:16 -07001138 /*
1139 * Note: the _columns_ of a matrix are stored in program registers, not
1140 * the rows.
1141 */
1142 /* XXXX need to test 3x3 and 2x2 matrices... */
Brian34ae99d2006-12-18 08:28:54 -07001143 if (transpose) {
Brian3a8e2772006-12-20 17:19:16 -07001144 GLuint row, col;
1145 for (col = 0; col < cols; col++) {
1146 GLfloat *v = shProg->Uniforms->ParameterValues[location + col];
1147 for (row = 0; row < rows; row++) {
Brian9f442472007-03-09 11:34:18 -07001148 v[row] = values[row * cols + col];
Brian34ae99d2006-12-18 08:28:54 -07001149 }
Brian34ae99d2006-12-18 08:28:54 -07001150 }
Brian34ae99d2006-12-18 08:28:54 -07001151 }
1152 else {
Brian3a8e2772006-12-20 17:19:16 -07001153 GLuint row, col;
1154 for (col = 0; col < cols; col++) {
1155 GLfloat *v = shProg->Uniforms->ParameterValues[location + col];
1156 for (row = 0; row < rows; row++) {
Brian9f442472007-03-09 11:34:18 -07001157 v[row] = values[col * rows + row];
Brian3a8e2772006-12-20 17:19:16 -07001158 }
1159 }
Brian34ae99d2006-12-18 08:28:54 -07001160 }
1161}
1162
1163
Brian5b01c5e2006-12-19 18:02:03 -07001164void
1165_mesa_validate_program(GLcontext *ctx, GLuint program)
Brian34ae99d2006-12-18 08:28:54 -07001166{
Brian65a18442006-12-19 18:46:56 -07001167 struct gl_shader_program *shProg;
1168 shProg = _mesa_lookup_shader_program(ctx, program);
1169 if (!shProg) {
Brian43975832007-01-04 08:21:09 -07001170 _mesa_error(ctx, GL_INVALID_VALUE, "glValidateProgram(program)");
Brian34ae99d2006-12-18 08:28:54 -07001171 return;
1172 }
Brian5b01c5e2006-12-19 18:02:03 -07001173 /* XXX temporary */
Brian65a18442006-12-19 18:46:56 -07001174 shProg->Validated = GL_TRUE;
Brian34ae99d2006-12-18 08:28:54 -07001175
Brian5b01c5e2006-12-19 18:02:03 -07001176 /* From the GL spec:
1177 any two active samplers in the current program object are of
1178 different types, but refer to the same texture image unit,
1179
1180 any active sampler in the current program object refers to a texture
1181 image unit where fixed-function fragment processing accesses a
1182 texture target that does not match the sampler type, or
1183
1184 the sum of the number of active samplers in the program and the
1185 number of texture image units enabled for fixed-function fragment
1186 processing exceeds the combined limit on the total number of texture
1187 image units allowed.
1188 */
Brian34ae99d2006-12-18 08:28:54 -07001189}