blob: fbaaf8ddea550910c1e6b3c9f6e0ec7e22719834 [file] [log] [blame]
Brian34ae99d2006-12-18 08:28:54 -07001/*
2 * Mesa 3-D graphics library
Brian3e4302f2007-05-09 08:04:32 -06003 * Version: 7.0
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"
Brian274ac7a2007-04-18 16:05:53 -060041#include "macros.h"
Brian34ae99d2006-12-18 08:28:54 -070042#include "program.h"
43#include "prog_parameter.h"
Brian3209c3e2007-01-09 17:49:24 -070044#include "prog_print.h"
45#include "prog_statevars.h"
Brianbc029242008-04-04 18:59:21 -060046#include "prog_uniform.h"
Brianc223c6b2007-07-04 13:15:20 -060047#include "shader/shader_api.h"
48#include "shader/slang/slang_compile.h"
49#include "shader/slang/slang_link.h"
Brian34ae99d2006-12-18 08:28:54 -070050
51
52
Brianf2923612006-12-20 09:56:44 -070053/**
54 * Allocate a new gl_shader_program object, initialize it.
55 */
Brian2d2bb352007-12-07 17:11:30 -070056static struct gl_shader_program *
Brianf2923612006-12-20 09:56:44 -070057_mesa_new_shader_program(GLcontext *ctx, GLuint name)
58{
59 struct gl_shader_program *shProg;
60 shProg = CALLOC_STRUCT(gl_shader_program);
61 if (shProg) {
Brianf3e8c322007-04-18 14:53:23 -060062 shProg->Type = GL_SHADER_PROGRAM_MESA;
Brianf2923612006-12-20 09:56:44 -070063 shProg->Name = name;
64 shProg->RefCount = 1;
Brian3209c3e2007-01-09 17:49:24 -070065 shProg->Attributes = _mesa_new_parameter_list();
Brianf2923612006-12-20 09:56:44 -070066 }
67 return shProg;
68}
69
70
Brianb9fbedd2007-03-26 09:23:44 -060071/**
Brian3c008a02007-04-12 15:22:32 -060072 * Clear (free) the shader program state that gets produced by linking.
Brianb9fbedd2007-03-26 09:23:44 -060073 */
Brianf2923612006-12-20 09:56:44 -070074void
Brian3c008a02007-04-12 15:22:32 -060075_mesa_clear_shader_program_data(GLcontext *ctx,
76 struct gl_shader_program *shProg)
Brianf2923612006-12-20 09:56:44 -070077{
Brian Paul470f6992008-05-16 09:56:59 -060078 _mesa_reference_vertprog(ctx, &shProg->VertexProgram, NULL);
79 _mesa_reference_fragprog(ctx, &shProg->FragmentProgram, NULL);
Brianf2923612006-12-20 09:56:44 -070080
Brianf2923612006-12-20 09:56:44 -070081 if (shProg->Uniforms) {
Brianbc029242008-04-04 18:59:21 -060082 _mesa_free_uniform_list(shProg->Uniforms);
Brianf2923612006-12-20 09:56:44 -070083 shProg->Uniforms = NULL;
84 }
85
86 if (shProg->Varying) {
87 _mesa_free_parameter_list(shProg->Varying);
88 shProg->Varying = NULL;
89 }
90}
91
92
Brianb9fbedd2007-03-26 09:23:44 -060093/**
Brian3c008a02007-04-12 15:22:32 -060094 * Free all the data that hangs off a shader program object, but not the
95 * object itself.
96 */
97void
98_mesa_free_shader_program_data(GLcontext *ctx,
99 struct gl_shader_program *shProg)
100{
101 GLuint i;
102
Brianf3e8c322007-04-18 14:53:23 -0600103 assert(shProg->Type == GL_SHADER_PROGRAM_MESA);
Brian3c008a02007-04-12 15:22:32 -0600104
105 _mesa_clear_shader_program_data(ctx, shProg);
106
Brian4b7c6fc2007-04-19 15:23:34 -0600107 if (shProg->Attributes) {
108 _mesa_free_parameter_list(shProg->Attributes);
109 shProg->Attributes = NULL;
110 }
111
Brian3c008a02007-04-12 15:22:32 -0600112 /* detach shaders */
113 for (i = 0; i < shProg->NumShaders; i++) {
114 _mesa_reference_shader(ctx, &shProg->Shaders[i], NULL);
115 }
Brian Paul887bfee2008-05-14 16:44:08 -0600116 shProg->NumShaders = 0;
117
Brian3c008a02007-04-12 15:22:32 -0600118 if (shProg->Shaders) {
119 _mesa_free(shProg->Shaders);
120 shProg->Shaders = NULL;
121 }
Brian Paul887bfee2008-05-14 16:44:08 -0600122
123 if (shProg->InfoLog) {
124 _mesa_free(shProg->InfoLog);
125 shProg->InfoLog = NULL;
126 }
Brian3c008a02007-04-12 15:22:32 -0600127}
128
129
130/**
Brianb9fbedd2007-03-26 09:23:44 -0600131 * Free/delete a shader program object.
132 */
Brianf2923612006-12-20 09:56:44 -0700133void
134_mesa_free_shader_program(GLcontext *ctx, struct gl_shader_program *shProg)
135{
136 _mesa_free_shader_program_data(ctx, shProg);
Brian Paul887bfee2008-05-14 16:44:08 -0600137
Brianf2923612006-12-20 09:56:44 -0700138 _mesa_free(shProg);
139}
140
141
142/**
Brian3c008a02007-04-12 15:22:32 -0600143 * Set ptr to point to shProg.
144 * If ptr is pointing to another object, decrement its refcount (and delete
145 * if refcount hits zero).
146 * Then set ptr to point to shProg, incrementing its refcount.
147 */
148/* XXX this could be static */
149void
150_mesa_reference_shader_program(GLcontext *ctx,
151 struct gl_shader_program **ptr,
152 struct gl_shader_program *shProg)
153{
154 assert(ptr);
155 if (*ptr == shProg) {
156 /* no-op */
157 return;
158 }
159 if (*ptr) {
160 /* Unreference the old shader program */
161 GLboolean deleteFlag = GL_FALSE;
162 struct gl_shader_program *old = *ptr;
163
164 ASSERT(old->RefCount > 0);
165 old->RefCount--;
Brian Paul470f6992008-05-16 09:56:59 -0600166#if 0
167 printf("ShaderProgram %p ID=%u RefCount-- to %d\n",
168 (void *) old, old->Name, old->RefCount);
169#endif
Brian3c008a02007-04-12 15:22:32 -0600170 deleteFlag = (old->RefCount == 0);
171
172 if (deleteFlag) {
173 _mesa_HashRemove(ctx->Shared->ShaderObjects, old->Name);
174 _mesa_free_shader_program(ctx, old);
175 }
176
177 *ptr = NULL;
178 }
179 assert(!*ptr);
180
181 if (shProg) {
182 shProg->RefCount++;
Brian Paul470f6992008-05-16 09:56:59 -0600183#if 0
184 printf("ShaderProgram %p ID=%u RefCount++ to %d\n",
185 (void *) shProg, shProg->Name, shProg->RefCount);
186#endif
Brian3c008a02007-04-12 15:22:32 -0600187 *ptr = shProg;
188 }
189}
190
191
192/**
Brianf2923612006-12-20 09:56:44 -0700193 * Lookup a GLSL program object.
194 */
195struct gl_shader_program *
196_mesa_lookup_shader_program(GLcontext *ctx, GLuint name)
197{
198 struct gl_shader_program *shProg;
199 if (name) {
200 shProg = (struct gl_shader_program *)
201 _mesa_HashLookup(ctx->Shared->ShaderObjects, name);
202 /* Note that both gl_shader and gl_shader_program objects are kept
203 * in the same hash table. Check the object's type to be sure it's
204 * what we're expecting.
205 */
Brianf3e8c322007-04-18 14:53:23 -0600206 if (shProg && shProg->Type != GL_SHADER_PROGRAM_MESA) {
Brianf2923612006-12-20 09:56:44 -0700207 return NULL;
208 }
209 return shProg;
210 }
211 return NULL;
212}
213
214
215/**
216 * Allocate a new gl_shader object, initialize it.
217 */
218struct gl_shader *
219_mesa_new_shader(GLcontext *ctx, GLuint name, GLenum type)
220{
221 struct gl_shader *shader;
222 assert(type == GL_FRAGMENT_SHADER || type == GL_VERTEX_SHADER);
223 shader = CALLOC_STRUCT(gl_shader);
224 if (shader) {
225 shader->Type = type;
226 shader->Name = name;
227 shader->RefCount = 1;
228 }
229 return shader;
230}
231
232
233void
234_mesa_free_shader(GLcontext *ctx, struct gl_shader *sh)
235{
236 GLuint i;
237 if (sh->Source)
238 _mesa_free((void *) sh->Source);
239 if (sh->InfoLog)
240 _mesa_free(sh->InfoLog);
Brian Pauld7913862008-05-14 12:19:22 -0600241 for (i = 0; i < sh->NumPrograms; i++)
242 _mesa_reference_program(ctx, &sh->Programs[i], NULL);
Brianf2923612006-12-20 09:56:44 -0700243 if (sh->Programs)
244 _mesa_free(sh->Programs);
245 _mesa_free(sh);
246}
247
248
249/**
Brian3c008a02007-04-12 15:22:32 -0600250 * Set ptr to point to sh.
251 * If ptr is pointing to another shader, decrement its refcount (and delete
252 * if refcount hits zero).
253 * Then set ptr to point to sh, incrementing its refcount.
254 */
255/* XXX this could be static */
256void
257_mesa_reference_shader(GLcontext *ctx, struct gl_shader **ptr,
258 struct gl_shader *sh)
259{
260 assert(ptr);
261 if (*ptr == sh) {
262 /* no-op */
263 return;
264 }
265 if (*ptr) {
266 /* Unreference the old shader */
267 GLboolean deleteFlag = GL_FALSE;
268 struct gl_shader *old = *ptr;
269
270 ASSERT(old->RefCount > 0);
271 old->RefCount--;
Brian99193e42007-04-12 15:45:02 -0600272 /*printf("SHADER DECR %p (%d) to %d\n",
273 (void*) old, old->Name, old->RefCount);*/
Brian3c008a02007-04-12 15:22:32 -0600274 deleteFlag = (old->RefCount == 0);
275
276 if (deleteFlag) {
277 _mesa_HashRemove(ctx->Shared->ShaderObjects, old->Name);
278 _mesa_free_shader(ctx, old);
279 }
280
281 *ptr = NULL;
282 }
283 assert(!*ptr);
284
285 if (sh) {
286 /* reference new */
287 sh->RefCount++;
Brian99193e42007-04-12 15:45:02 -0600288 /*printf("SHADER INCR %p (%d) to %d\n",
289 (void*) sh, sh->Name, sh->RefCount);*/
Brian3c008a02007-04-12 15:22:32 -0600290 *ptr = sh;
291 }
292}
293
294
295/**
Brianf2923612006-12-20 09:56:44 -0700296 * Lookup a GLSL shader object.
297 */
298struct gl_shader *
299_mesa_lookup_shader(GLcontext *ctx, GLuint name)
300{
301 if (name) {
302 struct gl_shader *sh = (struct gl_shader *)
303 _mesa_HashLookup(ctx->Shared->ShaderObjects, name);
304 /* Note that both gl_shader and gl_shader_program objects are kept
305 * in the same hash table. Check the object's type to be sure it's
306 * what we're expecting.
307 */
Brianf3e8c322007-04-18 14:53:23 -0600308 if (sh && sh->Type == GL_SHADER_PROGRAM_MESA) {
Brianf2923612006-12-20 09:56:44 -0700309 return NULL;
310 }
311 return sh;
312 }
313 return NULL;
314}
315
316
Brianfa4d0362007-02-26 18:33:50 -0700317/**
318 * Initialize context's shader state.
319 */
Brianf2923612006-12-20 09:56:44 -0700320void
321_mesa_init_shader_state(GLcontext * ctx)
322{
Brianfa4d0362007-02-26 18:33:50 -0700323 /* Device drivers may override these to control what kind of instructions
324 * are generated by the GLSL compiler.
325 */
326 ctx->Shader.EmitHighLevelInstructions = GL_TRUE;
michal4a470f62007-08-07 15:34:11 +0100327 ctx->Shader.EmitCondCodes = GL_FALSE;/*GL_TRUE;*/ /* XXX probably want GL_FALSE... */
Brianfa4d0362007-02-26 18:33:50 -0700328 ctx->Shader.EmitComments = GL_FALSE;
Brianf2923612006-12-20 09:56:44 -0700329}
330
331
Brian5b01c5e2006-12-19 18:02:03 -0700332/**
Brian935f93f2007-03-24 16:20:02 -0600333 * Free the per-context shader-related state.
334 */
335void
336_mesa_free_shader_state(GLcontext *ctx)
337{
Brian3c008a02007-04-12 15:22:32 -0600338 _mesa_reference_shader_program(ctx, &ctx->Shader.CurrentProgram, NULL);
Brian935f93f2007-03-24 16:20:02 -0600339}
340
341
342/**
Brian5b01c5e2006-12-19 18:02:03 -0700343 * Copy string from <src> to <dst>, up to maxLength characters, returning
344 * length of <dst> in <length>.
345 * \param src the strings source
346 * \param maxLength max chars to copy
347 * \param length returns number of chars copied
348 * \param dst the string destination
349 */
350static void
351copy_string(GLchar *dst, GLsizei maxLength, GLsizei *length, const GLchar *src)
352{
353 GLsizei len;
354 for (len = 0; len < maxLength - 1 && src && src[len]; len++)
355 dst[len] = src[len];
356 if (maxLength > 0)
357 dst[len] = 0;
358 if (length)
359 *length = len;
360}
361
362
Brian5b01c5e2006-12-19 18:02:03 -0700363/**
364 * Called via ctx->Driver.AttachShader()
365 */
Brian2d2bb352007-12-07 17:11:30 -0700366static void
Brian5b01c5e2006-12-19 18:02:03 -0700367_mesa_attach_shader(GLcontext *ctx, GLuint program, GLuint shader)
368{
Brian65a18442006-12-19 18:46:56 -0700369 struct gl_shader_program *shProg
370 = _mesa_lookup_shader_program(ctx, program);
371 struct gl_shader *sh = _mesa_lookup_shader(ctx, shader);
372 const GLuint n = shProg->NumShaders;
Brian5b01c5e2006-12-19 18:02:03 -0700373 GLuint i;
374
Brian65a18442006-12-19 18:46:56 -0700375 if (!shProg || !sh) {
Brian43975832007-01-04 08:21:09 -0700376 _mesa_error(ctx, GL_INVALID_VALUE,
Brian5b01c5e2006-12-19 18:02:03 -0700377 "glAttachShader(bad program or shader name)");
378 return;
379 }
380
381 for (i = 0; i < n; i++) {
Brian65a18442006-12-19 18:46:56 -0700382 if (shProg->Shaders[i] == sh) {
Brian5b01c5e2006-12-19 18:02:03 -0700383 /* already attached */
384 return;
Brian34ae99d2006-12-18 08:28:54 -0700385 }
386 }
Brian5b01c5e2006-12-19 18:02:03 -0700387
388 /* grow list */
Brian65a18442006-12-19 18:46:56 -0700389 shProg->Shaders = (struct gl_shader **)
390 _mesa_realloc(shProg->Shaders,
391 n * sizeof(struct gl_shader *),
392 (n + 1) * sizeof(struct gl_shader *));
393 if (!shProg->Shaders) {
Brian5b01c5e2006-12-19 18:02:03 -0700394 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glAttachShader");
395 return;
396 }
397
398 /* append */
Brian3c008a02007-04-12 15:22:32 -0600399 shProg->Shaders[n] = NULL; /* since realloc() didn't zero the new space */
400 _mesa_reference_shader(ctx, &shProg->Shaders[n], sh);
Brian65a18442006-12-19 18:46:56 -0700401 shProg->NumShaders++;
Brian5b01c5e2006-12-19 18:02:03 -0700402}
403
404
Brian2d2bb352007-12-07 17:11:30 -0700405static GLint
406_mesa_get_attrib_location(GLcontext *ctx, GLuint program,
407 const GLchar *name)
408{
409 struct gl_shader_program *shProg
410 = _mesa_lookup_shader_program(ctx, program);
411
412 if (!shProg) {
413 _mesa_error(ctx, GL_INVALID_VALUE, "glGetAttribLocation");
414 return -1;
415 }
416
417 if (!shProg->LinkStatus) {
418 _mesa_error(ctx, GL_INVALID_OPERATION,
419 "glGetAttribLocation(program not linked)");
420 return -1;
421 }
422
423 if (!name)
424 return -1;
425
426 if (shProg->Attributes) {
427 GLint i = _mesa_lookup_parameter_index(shProg->Attributes, -1, name);
428 if (i >= 0) {
429 return shProg->Attributes->Parameters[i].StateIndexes[0];
430 }
431 }
432 return -1;
433}
434
435
436static void
Brian5b01c5e2006-12-19 18:02:03 -0700437_mesa_bind_attrib_location(GLcontext *ctx, GLuint program, GLuint index,
438 const GLchar *name)
439{
Brian65a18442006-12-19 18:46:56 -0700440 struct gl_shader_program *shProg
441 = _mesa_lookup_shader_program(ctx, program);
Brianb7978af2007-01-09 19:17:17 -0700442 const GLint size = -1; /* unknown size */
443 GLint i, oldIndex;
Brian5b01c5e2006-12-19 18:02:03 -0700444
Brian65a18442006-12-19 18:46:56 -0700445 if (!shProg) {
Brian43975832007-01-04 08:21:09 -0700446 _mesa_error(ctx, GL_INVALID_VALUE, "glBindAttribLocation(program)");
Brian5b01c5e2006-12-19 18:02:03 -0700447 return;
448 }
449
Brian9e4bae92006-12-20 09:27:42 -0700450 if (!name)
451 return;
452
453 if (strncmp(name, "gl_", 3) == 0) {
454 _mesa_error(ctx, GL_INVALID_OPERATION,
455 "glBindAttribLocation(illegal name)");
456 return;
457 }
458
Brian9f660252007-04-11 09:00:56 -0600459 if (shProg->LinkStatus) {
460 /* get current index/location for the attribute */
461 oldIndex = _mesa_get_attrib_location(ctx, program, name);
462 }
463 else {
464 oldIndex = -1;
465 }
Brian3209c3e2007-01-09 17:49:24 -0700466
467 /* this will replace the current value if it's already in the list */
Brianb7978af2007-01-09 19:17:17 -0700468 i = _mesa_add_attribute(shProg->Attributes, name, size, index);
Brian3209c3e2007-01-09 17:49:24 -0700469 if (i < 0) {
470 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBindAttribLocation");
471 }
472
Brian9f660252007-04-11 09:00:56 -0600473 if (shProg->VertexProgram && oldIndex >= 0 && oldIndex != index) {
474 /* If the index changed, need to search/replace references to that attribute
475 * in the vertex program.
476 */
Brian3209c3e2007-01-09 17:49:24 -0700477 _slang_remap_attribute(&shProg->VertexProgram->Base, oldIndex, index);
478 }
Brian34ae99d2006-12-18 08:28:54 -0700479}
480
481
Brian2d2bb352007-12-07 17:11:30 -0700482static GLuint
Brian5b01c5e2006-12-19 18:02:03 -0700483_mesa_create_shader(GLcontext *ctx, GLenum type)
484{
Brian65a18442006-12-19 18:46:56 -0700485 struct gl_shader *sh;
Brian5b01c5e2006-12-19 18:02:03 -0700486 GLuint name;
487
488 name = _mesa_HashFindFreeKeyBlock(ctx->Shared->ShaderObjects, 1);
489
490 switch (type) {
Brian65a18442006-12-19 18:46:56 -0700491 case GL_FRAGMENT_SHADER:
492 case GL_VERTEX_SHADER:
493 sh = _mesa_new_shader(ctx, name, type);
Brian5b01c5e2006-12-19 18:02:03 -0700494 break;
495 default:
496 _mesa_error(ctx, GL_INVALID_ENUM, "CreateShader(type)");
497 return 0;
498 }
499
Brian65a18442006-12-19 18:46:56 -0700500 _mesa_HashInsert(ctx->Shared->ShaderObjects, name, sh);
Brian5b01c5e2006-12-19 18:02:03 -0700501
502 return name;
503}
504
505
Brian2d2bb352007-12-07 17:11:30 -0700506static GLuint
Brian5b01c5e2006-12-19 18:02:03 -0700507_mesa_create_program(GLcontext *ctx)
508{
509 GLuint name;
Brian65a18442006-12-19 18:46:56 -0700510 struct gl_shader_program *shProg;
Brian5b01c5e2006-12-19 18:02:03 -0700511
Brian65a18442006-12-19 18:46:56 -0700512 name = _mesa_HashFindFreeKeyBlock(ctx->Shared->ShaderObjects, 1);
513 shProg = _mesa_new_shader_program(ctx, name);
Brian5b01c5e2006-12-19 18:02:03 -0700514
Brian65a18442006-12-19 18:46:56 -0700515 _mesa_HashInsert(ctx->Shared->ShaderObjects, name, shProg);
Brian5b01c5e2006-12-19 18:02:03 -0700516
Brian3c008a02007-04-12 15:22:32 -0600517 assert(shProg->RefCount == 1);
518
Brian5b01c5e2006-12-19 18:02:03 -0700519 return name;
520}
521
522
Brian3c008a02007-04-12 15:22:32 -0600523/**
524 * Named w/ "2" to indicate OpenGL 2.x vs GL_ARB_fragment_programs's
525 * DeleteProgramARB.
526 */
Brian2d2bb352007-12-07 17:11:30 -0700527static void
Brian5b01c5e2006-12-19 18:02:03 -0700528_mesa_delete_program2(GLcontext *ctx, GLuint name)
529{
Brian3c008a02007-04-12 15:22:32 -0600530 /*
531 * NOTE: deleting shaders/programs works a bit differently than
532 * texture objects (and buffer objects, etc). Shader/program
533 * handles/IDs exist in the hash table until the object is really
534 * deleted (refcount==0). With texture objects, the handle/ID is
535 * removed from the hash table in glDeleteTextures() while the tex
536 * object itself might linger until its refcount goes to zero.
537 */
Brian65a18442006-12-19 18:46:56 -0700538 struct gl_shader_program *shProg;
Brian5b01c5e2006-12-19 18:02:03 -0700539
Brian65a18442006-12-19 18:46:56 -0700540 shProg = _mesa_lookup_shader_program(ctx, name);
541 if (!shProg) {
Brian43975832007-01-04 08:21:09 -0700542 _mesa_error(ctx, GL_INVALID_VALUE, "glDeleteProgram(name)");
Brian5b01c5e2006-12-19 18:02:03 -0700543 return;
544 }
545
Brian9e4bae92006-12-20 09:27:42 -0700546 shProg->DeletePending = GL_TRUE;
547
Brian3c008a02007-04-12 15:22:32 -0600548 /* effectively, decr shProg's refcount */
549 _mesa_reference_shader_program(ctx, &shProg, NULL);
Brian5b01c5e2006-12-19 18:02:03 -0700550}
551
552
Brian2d2bb352007-12-07 17:11:30 -0700553static void
Brian5b01c5e2006-12-19 18:02:03 -0700554_mesa_delete_shader(GLcontext *ctx, GLuint shader)
555{
Brian9e4bae92006-12-20 09:27:42 -0700556 struct gl_shader *sh = _mesa_lookup_shader(ctx, shader);
557 if (!sh) {
558 return;
559 }
Brian5b01c5e2006-12-19 18:02:03 -0700560
Brian9e4bae92006-12-20 09:27:42 -0700561 sh->DeletePending = GL_TRUE;
Brian3c008a02007-04-12 15:22:32 -0600562
563 /* effectively, decr sh's refcount */
564 _mesa_reference_shader(ctx, &sh, NULL);
Brian5b01c5e2006-12-19 18:02:03 -0700565}
566
567
Brian2d2bb352007-12-07 17:11:30 -0700568static void
Brian5b01c5e2006-12-19 18:02:03 -0700569_mesa_detach_shader(GLcontext *ctx, GLuint program, GLuint shader)
570{
Brian65a18442006-12-19 18:46:56 -0700571 struct gl_shader_program *shProg
572 = _mesa_lookup_shader_program(ctx, program);
573 const GLuint n = shProg->NumShaders;
Brian5b01c5e2006-12-19 18:02:03 -0700574 GLuint i, j;
575
Brian65a18442006-12-19 18:46:56 -0700576 if (!shProg) {
Brian43975832007-01-04 08:21:09 -0700577 _mesa_error(ctx, GL_INVALID_VALUE,
Brian5b01c5e2006-12-19 18:02:03 -0700578 "glDetachShader(bad program or shader name)");
579 return;
580 }
581
582 for (i = 0; i < n; i++) {
Brian65a18442006-12-19 18:46:56 -0700583 if (shProg->Shaders[i]->Name == shader) {
Brian5b01c5e2006-12-19 18:02:03 -0700584 /* found it */
Brian3c008a02007-04-12 15:22:32 -0600585 struct gl_shader **newList;
Brian9e4bae92006-12-20 09:27:42 -0700586
Brian3c008a02007-04-12 15:22:32 -0600587 /* derefernce */
588 _mesa_reference_shader(ctx, &shProg->Shaders[i], NULL);
Brian9e4bae92006-12-20 09:27:42 -0700589
Brian5b01c5e2006-12-19 18:02:03 -0700590 /* alloc new, smaller array */
Brian65a18442006-12-19 18:46:56 -0700591 newList = (struct gl_shader **)
592 _mesa_malloc((n - 1) * sizeof(struct gl_shader *));
Brian5b01c5e2006-12-19 18:02:03 -0700593 if (!newList) {
594 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glDetachShader");
595 return;
596 }
597 for (j = 0; j < i; j++) {
Brian65a18442006-12-19 18:46:56 -0700598 newList[j] = shProg->Shaders[j];
Brian5b01c5e2006-12-19 18:02:03 -0700599 }
600 while (++i < n)
Brian65a18442006-12-19 18:46:56 -0700601 newList[j++] = shProg->Shaders[i];
602 _mesa_free(shProg->Shaders);
Brian5b01c5e2006-12-19 18:02:03 -0700603
Brian65a18442006-12-19 18:46:56 -0700604 shProg->Shaders = newList;
Brianbac15c82007-04-18 14:55:18 -0600605 shProg->NumShaders = n - 1;
Brianaaa57412007-04-18 15:22:43 -0600606
607#ifdef DEBUG
608 /* sanity check */
609 {
610 for (j = 0; j < shProg->NumShaders; j++) {
611 assert(shProg->Shaders[j]->Type == GL_VERTEX_SHADER ||
612 shProg->Shaders[j]->Type == GL_FRAGMENT_SHADER);
613 assert(shProg->Shaders[j]->RefCount > 0);
614 }
615 }
616#endif
617
Brian5b01c5e2006-12-19 18:02:03 -0700618 return;
619 }
620 }
621
622 /* not found */
Brian43975832007-01-04 08:21:09 -0700623 _mesa_error(ctx, GL_INVALID_VALUE,
Brian5b01c5e2006-12-19 18:02:03 -0700624 "glDetachShader(shader not found)");
625}
626
627
Brian2d2bb352007-12-07 17:11:30 -0700628static void
Brian5b01c5e2006-12-19 18:02:03 -0700629_mesa_get_active_attrib(GLcontext *ctx, GLuint program, GLuint index,
630 GLsizei maxLength, GLsizei *length, GLint *size,
631 GLenum *type, GLchar *nameOut)
632{
633 static const GLenum vec_types[] = {
634 GL_FLOAT, GL_FLOAT_VEC2, GL_FLOAT_VEC3, GL_FLOAT_VEC4
635 };
Brian65a18442006-12-19 18:46:56 -0700636 struct gl_shader_program *shProg
637 = _mesa_lookup_shader_program(ctx, program);
Brian5b01c5e2006-12-19 18:02:03 -0700638 GLint sz;
639
Brian65a18442006-12-19 18:46:56 -0700640 if (!shProg) {
Brianaaa57412007-04-18 15:22:43 -0600641 _mesa_error(ctx, GL_INVALID_VALUE, "glGetActiveAttrib");
Brian5b01c5e2006-12-19 18:02:03 -0700642 return;
643 }
644
Brian65a18442006-12-19 18:46:56 -0700645 if (!shProg->Attributes || index >= shProg->Attributes->NumParameters) {
Brianaaa57412007-04-18 15:22:43 -0600646 _mesa_error(ctx, GL_INVALID_VALUE, "glGetActiveAttrib(index)");
Brian5b01c5e2006-12-19 18:02:03 -0700647 return;
648 }
649
650 copy_string(nameOut, maxLength, length,
Brian65a18442006-12-19 18:46:56 -0700651 shProg->Attributes->Parameters[index].Name);
652 sz = shProg->Attributes->Parameters[index].Size;
Brian5b01c5e2006-12-19 18:02:03 -0700653 if (size)
654 *size = sz;
655 if (type)
656 *type = vec_types[sz]; /* XXX this is a temporary hack */
657}
658
659
660/**
661 * Called via ctx->Driver.GetActiveUniform().
662 */
Brian2d2bb352007-12-07 17:11:30 -0700663static void
Brian5b01c5e2006-12-19 18:02:03 -0700664_mesa_get_active_uniform(GLcontext *ctx, GLuint program, GLuint index,
665 GLsizei maxLength, GLsizei *length, GLint *size,
666 GLenum *type, GLchar *nameOut)
667{
Brianbc029242008-04-04 18:59:21 -0600668 const struct gl_shader_program *shProg
Brian65a18442006-12-19 18:46:56 -0700669 = _mesa_lookup_shader_program(ctx, program);
Brianbc029242008-04-04 18:59:21 -0600670 const struct gl_program *prog;
671 GLint progPos;
Brian5b01c5e2006-12-19 18:02:03 -0700672
Brian65a18442006-12-19 18:46:56 -0700673 if (!shProg) {
Brian43975832007-01-04 08:21:09 -0700674 _mesa_error(ctx, GL_INVALID_VALUE, "glGetActiveUniform");
Brian5b01c5e2006-12-19 18:02:03 -0700675 return;
676 }
677
Brianbc029242008-04-04 18:59:21 -0600678 if (!shProg->Uniforms || index >= shProg->Uniforms->NumUniforms) {
Brian5b01c5e2006-12-19 18:02:03 -0700679 _mesa_error(ctx, GL_INVALID_VALUE, "glGetActiveUniform(index)");
680 return;
681 }
682
Brianbc029242008-04-04 18:59:21 -0600683 progPos = shProg->Uniforms->Uniforms[index].VertPos;
684 if (progPos >= 0) {
685 prog = &shProg->VertexProgram->Base;
686 }
687 else {
688 progPos = shProg->Uniforms->Uniforms[index].FragPos;
689 if (progPos >= 0) {
690 prog = &shProg->FragmentProgram->Base;
Brian274ac7a2007-04-18 16:05:53 -0600691 }
692 }
693
Brianbc029242008-04-04 18:59:21 -0600694 if (!prog || progPos < 0)
695 return; /* should never happen */
696
697 if (nameOut)
698 copy_string(nameOut, maxLength, length,
699 prog->Parameters->Parameters[progPos].Name);
700 if (size)
701 *size = prog->Parameters->Parameters[progPos].Size;
702
703 if (type)
704 *type = prog->Parameters->Parameters[progPos].DataType;
Brian5b01c5e2006-12-19 18:02:03 -0700705}
706
707
708/**
709 * Called via ctx->Driver.GetAttachedShaders().
710 */
Brian2d2bb352007-12-07 17:11:30 -0700711static void
Brian5b01c5e2006-12-19 18:02:03 -0700712_mesa_get_attached_shaders(GLcontext *ctx, GLuint program, GLsizei maxCount,
713 GLsizei *count, GLuint *obj)
714{
Brian65a18442006-12-19 18:46:56 -0700715 struct gl_shader_program *shProg
716 = _mesa_lookup_shader_program(ctx, program);
717 if (shProg) {
Brian223d7cb2007-01-23 16:37:51 -0700718 GLint i;
Brian65a18442006-12-19 18:46:56 -0700719 for (i = 0; i < maxCount && i < shProg->NumShaders; i++) {
720 obj[i] = shProg->Shaders[i]->Name;
Brian5b01c5e2006-12-19 18:02:03 -0700721 }
722 if (count)
723 *count = i;
724 }
725 else {
Brian43975832007-01-04 08:21:09 -0700726 _mesa_error(ctx, GL_INVALID_VALUE, "glGetAttachedShaders");
Brian5b01c5e2006-12-19 18:02:03 -0700727 }
728}
729
730
Brian2d2bb352007-12-07 17:11:30 -0700731static GLuint
Brian5b01c5e2006-12-19 18:02:03 -0700732_mesa_get_handle(GLcontext *ctx, GLenum pname)
Brian34ae99d2006-12-18 08:28:54 -0700733{
734#if 0
735 GET_CURRENT_CONTEXT(ctx);
736
737 switch (pname) {
738 case GL_PROGRAM_OBJECT_ARB:
739 {
Brian5b01c5e2006-12-19 18:02:03 -0700740 struct gl2_program_intf **pro = ctx->Shader.CurrentProgram;
Brian34ae99d2006-12-18 08:28:54 -0700741
742 if (pro != NULL)
743 return (**pro)._container._generic.
744 GetName((struct gl2_generic_intf **) (pro));
745 }
746 break;
747 default:
748 _mesa_error(ctx, GL_INVALID_ENUM, "glGetHandleARB");
749 }
750#endif
751 return 0;
752}
753
754
Brian2d2bb352007-12-07 17:11:30 -0700755static void
Brian5b01c5e2006-12-19 18:02:03 -0700756_mesa_get_programiv(GLcontext *ctx, GLuint program,
757 GLenum pname, GLint *params)
Brian34ae99d2006-12-18 08:28:54 -0700758{
Brian65a18442006-12-19 18:46:56 -0700759 struct gl_shader_program *shProg
760 = _mesa_lookup_shader_program(ctx, program);
Brian34ae99d2006-12-18 08:28:54 -0700761
Brian65a18442006-12-19 18:46:56 -0700762 if (!shProg) {
Brian5b01c5e2006-12-19 18:02:03 -0700763 _mesa_error(ctx, GL_INVALID_VALUE, "glGetProgramiv(program)");
Brian34ae99d2006-12-18 08:28:54 -0700764 return;
765 }
766
Brian5b01c5e2006-12-19 18:02:03 -0700767 switch (pname) {
768 case GL_DELETE_STATUS:
Brian65a18442006-12-19 18:46:56 -0700769 *params = shProg->DeletePending;
Brian5b01c5e2006-12-19 18:02:03 -0700770 break;
771 case GL_LINK_STATUS:
Brian65a18442006-12-19 18:46:56 -0700772 *params = shProg->LinkStatus;
Brian34ae99d2006-12-18 08:28:54 -0700773 break;
Brian5b01c5e2006-12-19 18:02:03 -0700774 case GL_VALIDATE_STATUS:
Brian65a18442006-12-19 18:46:56 -0700775 *params = shProg->Validated;
Brian5b01c5e2006-12-19 18:02:03 -0700776 break;
777 case GL_INFO_LOG_LENGTH:
Jan Dvorak5a0f02a2007-07-13 16:36:00 -0600778 *params = shProg->InfoLog ? strlen(shProg->InfoLog) + 1 : 0;
Brian5b01c5e2006-12-19 18:02:03 -0700779 break;
780 case GL_ATTACHED_SHADERS:
Brian65a18442006-12-19 18:46:56 -0700781 *params = shProg->NumShaders;
Brian5b01c5e2006-12-19 18:02:03 -0700782 break;
783 case GL_ACTIVE_ATTRIBUTES:
Brian3209c3e2007-01-09 17:49:24 -0700784 *params = shProg->Attributes ? shProg->Attributes->NumParameters : 0;
Brian5b01c5e2006-12-19 18:02:03 -0700785 break;
786 case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH:
Brian274ac7a2007-04-18 16:05:53 -0600787 *params = _mesa_longest_parameter_name(shProg->Attributes,
788 PROGRAM_INPUT) + 1;
Brian5b01c5e2006-12-19 18:02:03 -0700789 break;
790 case GL_ACTIVE_UNIFORMS:
Brianbc029242008-04-04 18:59:21 -0600791 *params = shProg->Uniforms ? shProg->Uniforms->NumUniforms : 0;
Brian5b01c5e2006-12-19 18:02:03 -0700792 break;
793 case GL_ACTIVE_UNIFORM_MAX_LENGTH:
Brianbc029242008-04-04 18:59:21 -0600794 *params = _mesa_longest_uniform_name(shProg->Uniforms);
Brian274ac7a2007-04-18 16:05:53 -0600795 if (*params > 0)
796 (*params)++; /* add one for terminating zero */
Brian34ae99d2006-12-18 08:28:54 -0700797 break;
798 default:
Brian5b01c5e2006-12-19 18:02:03 -0700799 _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramiv(pname)");
800 return;
Brian34ae99d2006-12-18 08:28:54 -0700801 }
Brian5b01c5e2006-12-19 18:02:03 -0700802}
Brian34ae99d2006-12-18 08:28:54 -0700803
Brian34ae99d2006-12-18 08:28:54 -0700804
Brian2d2bb352007-12-07 17:11:30 -0700805static void
Brian5b01c5e2006-12-19 18:02:03 -0700806_mesa_get_shaderiv(GLcontext *ctx, GLuint name, GLenum pname, GLint *params)
807{
Brian65a18442006-12-19 18:46:56 -0700808 struct gl_shader *shader = _mesa_lookup_shader(ctx, name);
Brian5b01c5e2006-12-19 18:02:03 -0700809
810 if (!shader) {
811 _mesa_error(ctx, GL_INVALID_VALUE, "glGetShaderiv(shader)");
812 return;
813 }
Brian65a18442006-12-19 18:46:56 -0700814
Brian5b01c5e2006-12-19 18:02:03 -0700815 switch (pname) {
816 case GL_SHADER_TYPE:
817 *params = shader->Type;
818 break;
819 case GL_DELETE_STATUS:
820 *params = shader->DeletePending;
821 break;
822 case GL_COMPILE_STATUS:
823 *params = shader->CompileStatus;
824 break;
825 case GL_INFO_LOG_LENGTH:
Jan Dvorak5a0f02a2007-07-13 16:36:00 -0600826 *params = shader->InfoLog ? strlen(shader->InfoLog) + 1 : 0;
Brian5b01c5e2006-12-19 18:02:03 -0700827 break;
828 case GL_SHADER_SOURCE_LENGTH:
Jan Dvorak5a0f02a2007-07-13 16:36:00 -0600829 *params = shader->Source ? strlen((char *) shader->Source) + 1 : 0;
Brian5b01c5e2006-12-19 18:02:03 -0700830 break;
831 default:
832 _mesa_error(ctx, GL_INVALID_ENUM, "glGetShaderiv(pname)");
833 return;
834 }
835}
836
837
Brian2d2bb352007-12-07 17:11:30 -0700838static void
Brian5b01c5e2006-12-19 18:02:03 -0700839_mesa_get_program_info_log(GLcontext *ctx, GLuint program, GLsizei bufSize,
840 GLsizei *length, GLchar *infoLog)
841{
Brian65a18442006-12-19 18:46:56 -0700842 struct gl_shader_program *shProg
843 = _mesa_lookup_shader_program(ctx, program);
844 if (!shProg) {
Brian5b01c5e2006-12-19 18:02:03 -0700845 _mesa_error(ctx, GL_INVALID_VALUE, "glGetProgramInfoLog(program)");
846 return;
847 }
Brian65a18442006-12-19 18:46:56 -0700848 copy_string(infoLog, bufSize, length, shProg->InfoLog);
Brian5b01c5e2006-12-19 18:02:03 -0700849}
850
851
Brian2d2bb352007-12-07 17:11:30 -0700852static void
Brian5b01c5e2006-12-19 18:02:03 -0700853_mesa_get_shader_info_log(GLcontext *ctx, GLuint shader, GLsizei bufSize,
854 GLsizei *length, GLchar *infoLog)
855{
Brian65a18442006-12-19 18:46:56 -0700856 struct gl_shader *sh = _mesa_lookup_shader(ctx, shader);
857 if (!sh) {
Brian5b01c5e2006-12-19 18:02:03 -0700858 _mesa_error(ctx, GL_INVALID_VALUE, "glGetShaderInfoLog(shader)");
859 return;
860 }
Brian65a18442006-12-19 18:46:56 -0700861 copy_string(infoLog, bufSize, length, sh->InfoLog);
Brian5b01c5e2006-12-19 18:02:03 -0700862}
863
864
865/**
866 * Called via ctx->Driver.GetShaderSource().
867 */
Brian2d2bb352007-12-07 17:11:30 -0700868static void
Brian5b01c5e2006-12-19 18:02:03 -0700869_mesa_get_shader_source(GLcontext *ctx, GLuint shader, GLsizei maxLength,
870 GLsizei *length, GLchar *sourceOut)
871{
Brian65a18442006-12-19 18:46:56 -0700872 struct gl_shader *sh = _mesa_lookup_shader(ctx, shader);
873 if (!sh) {
Brian5b01c5e2006-12-19 18:02:03 -0700874 _mesa_error(ctx, GL_INVALID_VALUE, "glGetShaderSource(shader)");
875 return;
876 }
Brian65a18442006-12-19 18:46:56 -0700877 copy_string(sourceOut, maxLength, length, sh->Source);
Brian5b01c5e2006-12-19 18:02:03 -0700878}
879
880
881/**
882 * Called via ctx->Driver.GetUniformfv().
883 */
Brian2d2bb352007-12-07 17:11:30 -0700884static void
Brian5b01c5e2006-12-19 18:02:03 -0700885_mesa_get_uniformfv(GLcontext *ctx, GLuint program, GLint location,
886 GLfloat *params)
887{
Brian65a18442006-12-19 18:46:56 -0700888 struct gl_shader_program *shProg
889 = _mesa_lookup_shader_program(ctx, program);
890 if (shProg) {
Brianbc029242008-04-04 18:59:21 -0600891 if (location < shProg->Uniforms->NumUniforms) {
892 GLint progPos, i;
893 const struct gl_program *prog;
894
895 progPos = shProg->Uniforms->Uniforms[location].VertPos;
896 if (progPos >= 0) {
897 prog = &shProg->VertexProgram->Base;
898 }
899 else {
900 progPos = shProg->Uniforms->Uniforms[location].FragPos;
901 if (progPos >= 0) {
902 prog = &shProg->FragmentProgram->Base;
903 }
904 }
905
906 for (i = 0; i < prog->Parameters->Parameters[progPos].Size; i++) {
907 params[i] = prog->Parameters->ParameterValues[progPos][i];
Brian5b01c5e2006-12-19 18:02:03 -0700908 }
909 }
910 else {
911 _mesa_error(ctx, GL_INVALID_VALUE, "glGetUniformfv(location)");
912 }
913 }
914 else {
Brian43975832007-01-04 08:21:09 -0700915 _mesa_error(ctx, GL_INVALID_VALUE, "glGetUniformfv(program)");
Brian5b01c5e2006-12-19 18:02:03 -0700916 }
917}
918
919
920/**
921 * Called via ctx->Driver.GetUniformLocation().
922 */
Brian2d2bb352007-12-07 17:11:30 -0700923static GLint
Brian5b01c5e2006-12-19 18:02:03 -0700924_mesa_get_uniform_location(GLcontext *ctx, GLuint program, const GLchar *name)
925{
Brian71623982007-01-30 16:55:03 -0700926 struct gl_shader_program *shProg
927 = _mesa_lookup_shader_program(ctx, program);
Brianbc029242008-04-04 18:59:21 -0600928 if (!shProg)
929 return -1;
Brian5b01c5e2006-12-19 18:02:03 -0700930
Brianbc029242008-04-04 18:59:21 -0600931 return _mesa_lookup_uniform(shProg->Uniforms, name);
Brian5b01c5e2006-12-19 18:02:03 -0700932}
933
934
Brian2d2bb352007-12-07 17:11:30 -0700935static GLboolean
Brian5b01c5e2006-12-19 18:02:03 -0700936_mesa_is_program(GLcontext *ctx, GLuint name)
937{
Brian65a18442006-12-19 18:46:56 -0700938 struct gl_shader_program *shProg = _mesa_lookup_shader_program(ctx, name);
939 return shProg ? GL_TRUE : GL_FALSE;
Brian5b01c5e2006-12-19 18:02:03 -0700940}
941
942
Brian2d2bb352007-12-07 17:11:30 -0700943static GLboolean
Brian5b01c5e2006-12-19 18:02:03 -0700944_mesa_is_shader(GLcontext *ctx, GLuint name)
945{
Brian65a18442006-12-19 18:46:56 -0700946 struct gl_shader *shader = _mesa_lookup_shader(ctx, name);
Brian5b01c5e2006-12-19 18:02:03 -0700947 return shader ? GL_TRUE : GL_FALSE;
Brian34ae99d2006-12-18 08:28:54 -0700948}
949
950
951
Brian5b01c5e2006-12-19 18:02:03 -0700952/**
953 * Called via ctx->Driver.ShaderSource()
954 */
Brian2d2bb352007-12-07 17:11:30 -0700955static void
Brian5b01c5e2006-12-19 18:02:03 -0700956_mesa_shader_source(GLcontext *ctx, GLuint shader, const GLchar *source)
Brian34ae99d2006-12-18 08:28:54 -0700957{
Brian65a18442006-12-19 18:46:56 -0700958 struct gl_shader *sh = _mesa_lookup_shader(ctx, shader);
959 if (!sh) {
Brian5b01c5e2006-12-19 18:02:03 -0700960 _mesa_error(ctx, GL_INVALID_VALUE, "glShaderSource(shaderObj)");
Brian34ae99d2006-12-18 08:28:54 -0700961 return;
962 }
963
Brian34ae99d2006-12-18 08:28:54 -0700964 /* free old shader source string and install new one */
Brian65a18442006-12-19 18:46:56 -0700965 if (sh->Source) {
966 _mesa_free((void *) sh->Source);
Brian34ae99d2006-12-18 08:28:54 -0700967 }
Brian65a18442006-12-19 18:46:56 -0700968 sh->Source = source;
Brian9e4bae92006-12-20 09:27:42 -0700969 sh->CompileStatus = GL_FALSE;
Brian34ae99d2006-12-18 08:28:54 -0700970}
971
972
Brian5b01c5e2006-12-19 18:02:03 -0700973/**
974 * Called via ctx->Driver.CompileShader()
975 */
Brian2d2bb352007-12-07 17:11:30 -0700976static void
Brian5b01c5e2006-12-19 18:02:03 -0700977_mesa_compile_shader(GLcontext *ctx, GLuint shaderObj)
Brian34ae99d2006-12-18 08:28:54 -0700978{
Brian65a18442006-12-19 18:46:56 -0700979 struct gl_shader *sh = _mesa_lookup_shader(ctx, shaderObj);
Brian34ae99d2006-12-18 08:28:54 -0700980
Brian65a18442006-12-19 18:46:56 -0700981 if (!sh) {
Brian34ae99d2006-12-18 08:28:54 -0700982 _mesa_error(ctx, GL_INVALID_VALUE, "glCompileShader(shaderObj)");
983 return;
984 }
985
Brian43975832007-01-04 08:21:09 -0700986 sh->CompileStatus = _slang_compile(ctx, sh);
Brian34ae99d2006-12-18 08:28:54 -0700987}
988
989
Brian5b01c5e2006-12-19 18:02:03 -0700990/**
991 * Called via ctx->Driver.LinkProgram()
992 */
Brian2d2bb352007-12-07 17:11:30 -0700993static void
Brian5b01c5e2006-12-19 18:02:03 -0700994_mesa_link_program(GLcontext *ctx, GLuint program)
Brian34ae99d2006-12-18 08:28:54 -0700995{
Brian65a18442006-12-19 18:46:56 -0700996 struct gl_shader_program *shProg;
Brian34ae99d2006-12-18 08:28:54 -0700997
Brian65a18442006-12-19 18:46:56 -0700998 shProg = _mesa_lookup_shader_program(ctx, program);
999 if (!shProg) {
Brian43975832007-01-04 08:21:09 -07001000 _mesa_error(ctx, GL_INVALID_VALUE, "glLinkProgram(program)");
Brian34ae99d2006-12-18 08:28:54 -07001001 return;
1002 }
1003
Brianc1771912007-02-16 09:56:19 -07001004 _slang_link(ctx, program, shProg);
Brian34ae99d2006-12-18 08:28:54 -07001005}
1006
1007
1008/**
Brian5b01c5e2006-12-19 18:02:03 -07001009 * Called via ctx->Driver.UseProgram()
Brian34ae99d2006-12-18 08:28:54 -07001010 */
Brian5b01c5e2006-12-19 18:02:03 -07001011void
1012_mesa_use_program(GLcontext *ctx, GLuint program)
Brian34ae99d2006-12-18 08:28:54 -07001013{
Brian3c008a02007-04-12 15:22:32 -06001014 struct gl_shader_program *shProg;
1015
Brian00d63aa2007-02-03 11:35:02 -07001016 if (ctx->Shader.CurrentProgram &&
1017 ctx->Shader.CurrentProgram->Name == program) {
1018 /* no-op */
1019 return;
1020 }
1021
1022 FLUSH_VERTICES(ctx, _NEW_PROGRAM);
1023
Brian5b01c5e2006-12-19 18:02:03 -07001024 if (program) {
Brian65a18442006-12-19 18:46:56 -07001025 shProg = _mesa_lookup_shader_program(ctx, program);
1026 if (!shProg) {
Brian43975832007-01-04 08:21:09 -07001027 _mesa_error(ctx, GL_INVALID_VALUE,
Brian5b01c5e2006-12-19 18:02:03 -07001028 "glUseProgramObjectARB(programObj)");
1029 return;
1030 }
Brian5b01c5e2006-12-19 18:02:03 -07001031 }
1032 else {
Brian3c008a02007-04-12 15:22:32 -06001033 shProg = NULL;
1034 }
1035
1036 _mesa_reference_shader_program(ctx, &ctx->Shader.CurrentProgram, shProg);
Brian5b01c5e2006-12-19 18:02:03 -07001037}
Brian34ae99d2006-12-18 08:28:54 -07001038
Brian5b01c5e2006-12-19 18:02:03 -07001039
Brian8fed2462007-10-26 19:19:09 -06001040
1041/**
1042 * Update the vertex and fragment program's TexturesUsed arrays.
1043 */
1044static void
1045update_textures_used(struct gl_program *prog)
1046{
1047 GLuint s;
1048
1049 memset(prog->TexturesUsed, 0, sizeof(prog->TexturesUsed));
1050
1051 for (s = 0; s < MAX_SAMPLERS; s++) {
1052 if (prog->SamplersUsed & (1 << s)) {
1053 GLuint u = prog->SamplerUnits[s];
1054 GLuint t = prog->SamplerTargets[s];
1055 assert(u < MAX_TEXTURE_IMAGE_UNITS);
1056 prog->TexturesUsed[u] |= (1 << t);
1057 }
1058 }
1059}
1060
1061
Brian5b01c5e2006-12-19 18:02:03 -07001062/**
Brianbc029242008-04-04 18:59:21 -06001063 * Set the value of a program's uniform variable.
1064 * \param program the program whose uniform to update
1065 * \param location the location/index of the uniform
1066 * \param type the datatype of the uniform
1067 * \param count the number of uniforms to set
1068 * \param elems number of elements per uniform
1069 * \param values the new values
1070 */
1071static void
1072set_program_uniform(GLcontext *ctx, struct gl_program *program, GLint location,
1073 GLenum type, GLint count, GLint elems, const void *values)
1074{
1075 if (program->Parameters->Parameters[location].Type == PROGRAM_SAMPLER) {
1076 /* This controls which texture unit which is used by a sampler */
1077 GLuint texUnit, sampler;
1078
1079 /* data type for setting samplers must be int */
1080 if (type != GL_INT || count != 1) {
1081 _mesa_error(ctx, GL_INVALID_OPERATION,
1082 "glUniform(only glUniform1i can be used "
1083 "to set sampler uniforms)");
1084 return;
1085 }
1086
1087 sampler = (GLuint) program->Parameters->ParameterValues[location][0];
1088 texUnit = ((GLuint *) values)[0];
1089
1090 /* check that the sampler (tex unit index) is legal */
1091 if (texUnit >= ctx->Const.MaxTextureImageUnits) {
1092 _mesa_error(ctx, GL_INVALID_VALUE,
1093 "glUniform1(invalid sampler/tex unit index)");
1094 return;
1095 }
1096
1097 /* This maps a sampler to a texture unit: */
1098 program->SamplerUnits[sampler] = texUnit;
1099 update_textures_used(program);
1100
1101 FLUSH_VERTICES(ctx, _NEW_TEXTURE);
1102 }
1103 else {
1104 /* ordinary uniform variable */
1105 GLint k, i;
1106
1107 if (count * elems > program->Parameters->Parameters[location].Size) {
1108 _mesa_error(ctx, GL_INVALID_OPERATION, "glUniform(count too large)");
1109 return;
1110 }
1111
1112 for (k = 0; k < count; k++) {
1113 GLfloat *uniformVal = program->Parameters->ParameterValues[location + k];
1114 if (type == GL_INT ||
1115 type == GL_INT_VEC2 ||
1116 type == GL_INT_VEC3 ||
1117 type == GL_INT_VEC4) {
1118 const GLint *iValues = ((const GLint *) values) + k * elems;
1119 for (i = 0; i < elems; i++) {
1120 uniformVal[i] = (GLfloat) iValues[i];
1121 }
1122 }
1123 else {
1124 const GLfloat *fValues = ((const GLfloat *) values) + k * elems;
1125 for (i = 0; i < elems; i++) {
1126 uniformVal[i] = fValues[i];
1127 }
1128 }
1129 }
1130 }
1131}
1132
1133
1134/**
Brian5b01c5e2006-12-19 18:02:03 -07001135 * Called via ctx->Driver.Uniform().
1136 */
Brian2d2bb352007-12-07 17:11:30 -07001137static void
Brian5b01c5e2006-12-19 18:02:03 -07001138_mesa_uniform(GLcontext *ctx, GLint location, GLsizei count,
1139 const GLvoid *values, GLenum type)
1140{
Brian3a8e2772006-12-20 17:19:16 -07001141 struct gl_shader_program *shProg = ctx->Shader.CurrentProgram;
Brianbc029242008-04-04 18:59:21 -06001142 GLint elems;
Brian3a8e2772006-12-20 17:19:16 -07001143
1144 if (!shProg || !shProg->LinkStatus) {
Brian5b01c5e2006-12-19 18:02:03 -07001145 _mesa_error(ctx, GL_INVALID_OPERATION, "glUniform(program not linked)");
Brian3a8e2772006-12-20 17:19:16 -07001146 return;
1147 }
1148
Brian Paulf84005c2008-05-14 16:01:31 -06001149 if (location == -1)
1150 return; /* The standard specifies this as a no-op */
1151
1152
Brianbc029242008-04-04 18:59:21 -06001153 if (location < 0 || location >= (GLint) shProg->Uniforms->NumUniforms) {
Brian3a8e2772006-12-20 17:19:16 -07001154 _mesa_error(ctx, GL_INVALID_VALUE, "glUniform(location)");
1155 return;
1156 }
1157
Brian52363952007-03-13 16:50:24 -06001158 if (count < 0) {
1159 _mesa_error(ctx, GL_INVALID_VALUE, "glUniform(count < 0)");
1160 return;
1161 }
1162
Brian98650bd2007-03-13 16:32:48 -06001163 switch (type) {
1164 case GL_FLOAT:
1165 case GL_INT:
1166 elems = 1;
1167 break;
1168 case GL_FLOAT_VEC2:
1169 case GL_INT_VEC2:
1170 elems = 2;
1171 break;
1172 case GL_FLOAT_VEC3:
1173 case GL_INT_VEC3:
1174 elems = 3;
1175 break;
1176 case GL_FLOAT_VEC4:
1177 case GL_INT_VEC4:
1178 elems = 4;
1179 break;
1180 default:
1181 _mesa_problem(ctx, "Invalid type in _mesa_uniform");
1182 return;
Brian89dc4852007-01-04 14:35:44 -07001183 }
Brian98650bd2007-03-13 16:32:48 -06001184
Brianbc029242008-04-04 18:59:21 -06001185 FLUSH_VERTICES(ctx, _NEW_PROGRAM);
1186
1187 /* A uniform var may be used by both a vertex shader and a fragment
1188 * shader. We may need to update one or both shader's uniform here:
1189 */
1190 if (shProg->VertexProgram) {
1191 GLint loc = shProg->Uniforms->Uniforms[location].VertPos;
1192 if (loc >= 0) {
1193 set_program_uniform(ctx, &shProg->VertexProgram->Base,
1194 loc, type, count, elems, values);
1195 }
Brian98650bd2007-03-13 16:32:48 -06001196 }
1197
Brianbc029242008-04-04 18:59:21 -06001198 if (shProg->FragmentProgram) {
1199 GLint loc = shProg->Uniforms->Uniforms[location].FragPos;
1200 if (loc >= 0) {
1201 set_program_uniform(ctx, &shProg->FragmentProgram->Base,
1202 loc, type, count, elems, values);
Brian8fed2462007-10-26 19:19:09 -06001203 }
Brianbc029242008-04-04 18:59:21 -06001204 }
1205}
Brian8fed2462007-10-26 19:19:09 -06001206
Brian8fed2462007-10-26 19:19:09 -06001207
Brianbc029242008-04-04 18:59:21 -06001208static void
1209set_program_uniform_matrix(GLcontext *ctx, struct gl_program *program,
1210 GLuint location, GLuint rows, GLuint cols,
1211 GLboolean transpose, const GLfloat *values)
1212{
1213 /*
1214 * Note: the _columns_ of a matrix are stored in program registers, not
1215 * the rows.
1216 */
1217 /* XXXX need to test 3x3 and 2x2 matrices... */
1218 if (transpose) {
1219 GLuint row, col;
1220 for (col = 0; col < cols; col++) {
1221 GLfloat *v = program->Parameters->ParameterValues[location + col];
1222 for (row = 0; row < rows; row++) {
1223 v[row] = values[row * cols + col];
1224 }
Brian8fed2462007-10-26 19:19:09 -06001225 }
Brian5cf73262007-01-05 16:02:45 -07001226 }
Brian8fed2462007-10-26 19:19:09 -06001227 else {
Brianbc029242008-04-04 18:59:21 -06001228 GLuint row, col;
1229 for (col = 0; col < cols; col++) {
1230 GLfloat *v = program->Parameters->ParameterValues[location + col];
1231 for (row = 0; row < rows; row++) {
1232 v[row] = values[col * rows + row];
Brian8fed2462007-10-26 19:19:09 -06001233 }
1234 }
1235 }
Brian34ae99d2006-12-18 08:28:54 -07001236}
1237
1238
1239/**
Brian5b01c5e2006-12-19 18:02:03 -07001240 * Called by ctx->Driver.UniformMatrix().
Brian34ae99d2006-12-18 08:28:54 -07001241 */
Brian2d2bb352007-12-07 17:11:30 -07001242static void
Brian5b01c5e2006-12-19 18:02:03 -07001243_mesa_uniform_matrix(GLcontext *ctx, GLint cols, GLint rows,
1244 GLenum matrixType, GLint location, GLsizei count,
1245 GLboolean transpose, const GLfloat *values)
Brian34ae99d2006-12-18 08:28:54 -07001246{
Brian3a8e2772006-12-20 17:19:16 -07001247 struct gl_shader_program *shProg = ctx->Shader.CurrentProgram;
Brian Paulf84005c2008-05-14 16:01:31 -06001248
Brian3a8e2772006-12-20 17:19:16 -07001249 if (!shProg || !shProg->LinkStatus) {
1250 _mesa_error(ctx, GL_INVALID_OPERATION,
1251 "glUniformMatrix(program not linked)");
1252 return;
1253 }
Brian Paulf84005c2008-05-14 16:01:31 -06001254
1255 if (location == -1)
1256 return; /* The standard specifies this as a no-op */
1257
Brianbc029242008-04-04 18:59:21 -06001258 if (location < 0 || location >= shProg->Uniforms->NumUniforms) {
Brian3a8e2772006-12-20 17:19:16 -07001259 _mesa_error(ctx, GL_INVALID_VALUE, "glUniformMatrix(location)");
1260 return;
1261 }
Brian34ae99d2006-12-18 08:28:54 -07001262 if (values == NULL) {
Brian3a8e2772006-12-20 17:19:16 -07001263 _mesa_error(ctx, GL_INVALID_VALUE, "glUniformMatrix");
Brian34ae99d2006-12-18 08:28:54 -07001264 return;
1265 }
1266
1267 FLUSH_VERTICES(ctx, _NEW_PROGRAM);
1268
Brianbc029242008-04-04 18:59:21 -06001269 if (shProg->VertexProgram) {
1270 GLint loc = shProg->Uniforms->Uniforms[location].VertPos;
1271 if (loc >= 0) {
1272 set_program_uniform_matrix(ctx, &shProg->VertexProgram->Base,
1273 loc, rows, cols, transpose, values);
Brian34ae99d2006-12-18 08:28:54 -07001274 }
Brian34ae99d2006-12-18 08:28:54 -07001275 }
Brianbc029242008-04-04 18:59:21 -06001276
1277 if (shProg->FragmentProgram) {
1278 GLint loc = shProg->Uniforms->Uniforms[location].FragPos;
1279 if (loc >= 0) {
1280 set_program_uniform_matrix(ctx, &shProg->FragmentProgram->Base,
1281 loc, rows, cols, transpose, values);
Brian3a8e2772006-12-20 17:19:16 -07001282 }
Brian34ae99d2006-12-18 08:28:54 -07001283 }
1284}
1285
1286
Brian2d2bb352007-12-07 17:11:30 -07001287static void
Brian5b01c5e2006-12-19 18:02:03 -07001288_mesa_validate_program(GLcontext *ctx, GLuint program)
Brian34ae99d2006-12-18 08:28:54 -07001289{
Brian65a18442006-12-19 18:46:56 -07001290 struct gl_shader_program *shProg;
1291 shProg = _mesa_lookup_shader_program(ctx, program);
1292 if (!shProg) {
Brian43975832007-01-04 08:21:09 -07001293 _mesa_error(ctx, GL_INVALID_VALUE, "glValidateProgram(program)");
Brian34ae99d2006-12-18 08:28:54 -07001294 return;
1295 }
Brian5b01c5e2006-12-19 18:02:03 -07001296 /* XXX temporary */
Brian65a18442006-12-19 18:46:56 -07001297 shProg->Validated = GL_TRUE;
Brian34ae99d2006-12-18 08:28:54 -07001298
Brian5b01c5e2006-12-19 18:02:03 -07001299 /* From the GL spec:
1300 any two active samplers in the current program object are of
1301 different types, but refer to the same texture image unit,
1302
1303 any active sampler in the current program object refers to a texture
1304 image unit where fixed-function fragment processing accesses a
1305 texture target that does not match the sampler type, or
1306
1307 the sum of the number of active samplers in the program and the
1308 number of texture image units enabled for fixed-function fragment
1309 processing exceeds the combined limit on the total number of texture
1310 image units allowed.
1311 */
Brian34ae99d2006-12-18 08:28:54 -07001312}
Brian2d2bb352007-12-07 17:11:30 -07001313
1314
1315/**
1316 * Plug in Mesa's GLSL functions into the device driver function table.
1317 */
1318void
1319_mesa_init_glsl_driver_functions(struct dd_function_table *driver)
1320{
1321 driver->AttachShader = _mesa_attach_shader;
1322 driver->BindAttribLocation = _mesa_bind_attrib_location;
1323 driver->CompileShader = _mesa_compile_shader;
1324 driver->CreateProgram = _mesa_create_program;
1325 driver->CreateShader = _mesa_create_shader;
1326 driver->DeleteProgram2 = _mesa_delete_program2;
1327 driver->DeleteShader = _mesa_delete_shader;
1328 driver->DetachShader = _mesa_detach_shader;
1329 driver->GetActiveAttrib = _mesa_get_active_attrib;
1330 driver->GetActiveUniform = _mesa_get_active_uniform;
1331 driver->GetAttachedShaders = _mesa_get_attached_shaders;
1332 driver->GetAttribLocation = _mesa_get_attrib_location;
1333 driver->GetHandle = _mesa_get_handle;
1334 driver->GetProgramiv = _mesa_get_programiv;
1335 driver->GetProgramInfoLog = _mesa_get_program_info_log;
1336 driver->GetShaderiv = _mesa_get_shaderiv;
1337 driver->GetShaderInfoLog = _mesa_get_shader_info_log;
1338 driver->GetShaderSource = _mesa_get_shader_source;
1339 driver->GetUniformfv = _mesa_get_uniformfv;
1340 driver->GetUniformLocation = _mesa_get_uniform_location;
1341 driver->IsProgram = _mesa_is_program;
1342 driver->IsShader = _mesa_is_shader;
1343 driver->LinkProgram = _mesa_link_program;
1344 driver->ShaderSource = _mesa_shader_source;
1345 driver->Uniform = _mesa_uniform;
1346 driver->UniformMatrix = _mesa_uniform_matrix;
1347 driver->UseProgram = _mesa_use_program;
1348 driver->ValidateProgram = _mesa_validate_program;
1349}