mesa: Free all shader program data before deleting all
[mesa.git] / src / mesa / shader / shader_api.c
1 /*
2 * Mesa 3-D graphics library
3 * Version: 7.0
4 *
5 * Copyright (C) 2004-2007 Brian Paul All Rights Reserved.
6 *
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
27 * Implementation of GLSL-related API functions
28 * \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.
34 * 2. Insert FLUSH_VERTICES calls in various places
35 */
36
37
38 #include "glheader.h"
39 #include "context.h"
40 #include "hash.h"
41 #include "macros.h"
42 #include "program.h"
43 #include "prog_parameter.h"
44 #include "prog_print.h"
45 #include "prog_statevars.h"
46 #include "shader/shader_api.h"
47 #include "shader/slang/slang_compile.h"
48 #include "shader/slang/slang_link.h"
49
50
51
52 /**
53 * Allocate a new gl_shader_program object, initialize it.
54 */
55 struct 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_MESA;
62 shProg->Name = name;
63 shProg->RefCount = 1;
64 shProg->Attributes = _mesa_new_parameter_list();
65 }
66 return shProg;
67 }
68
69
70 /**
71 * Clear (free) the shader program state that gets produced by linking.
72 */
73 void
74 _mesa_clear_shader_program_data(GLcontext *ctx,
75 struct gl_shader_program *shProg)
76 {
77 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 ctx->Driver.DeleteProgram(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 ctx->Driver.DeleteProgram(ctx, &shProg->FragmentProgram->Base);
92 shProg->FragmentProgram = NULL;
93 }
94
95 if (shProg->Uniforms) {
96 _mesa_free_parameter_list(shProg->Uniforms);
97 shProg->Uniforms = NULL;
98 }
99
100 if (shProg->Varying) {
101 _mesa_free_parameter_list(shProg->Varying);
102 shProg->Varying = NULL;
103 }
104 }
105
106
107 /**
108 * Free all the data that hangs off a shader program object, but not the
109 * object itself.
110 */
111 void
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_MESA);
118
119 _mesa_clear_shader_program_data(ctx, shProg);
120
121 if (shProg->Attributes) {
122 _mesa_free_parameter_list(shProg->Attributes);
123 shProg->Attributes = NULL;
124 }
125
126 /* detach shaders */
127 for (i = 0; i < shProg->NumShaders; i++) {
128 _mesa_reference_shader(ctx, &shProg->Shaders[i], NULL);
129 }
130 shProg->NumShaders = 0;
131
132 if (shProg->Shaders) {
133 _mesa_free(shProg->Shaders);
134 shProg->Shaders = NULL;
135 }
136 }
137
138
139 /**
140 * Free/delete a shader program object.
141 */
142 void
143 _mesa_free_shader_program(GLcontext *ctx, struct gl_shader_program *shProg)
144 {
145 _mesa_free_shader_program_data(ctx, shProg);
146 if (shProg->Shaders) {
147 _mesa_free(shProg->Shaders);
148 shProg->Shaders = NULL;
149 }
150 _mesa_free(shProg);
151 }
152
153
154 /**
155 * Set ptr to point to shProg.
156 * If ptr is pointing to another object, decrement its refcount (and delete
157 * if refcount hits zero).
158 * Then set ptr to point to shProg, incrementing its refcount.
159 */
160 /* XXX this could be static */
161 void
162 _mesa_reference_shader_program(GLcontext *ctx,
163 struct gl_shader_program **ptr,
164 struct gl_shader_program *shProg)
165 {
166 assert(ptr);
167 if (*ptr == shProg) {
168 /* no-op */
169 return;
170 }
171 if (*ptr) {
172 /* Unreference the old shader program */
173 GLboolean deleteFlag = GL_FALSE;
174 struct gl_shader_program *old = *ptr;
175
176 ASSERT(old->RefCount > 0);
177 old->RefCount--;
178 /*printf("SHPROG DECR %p (%d) to %d\n",
179 (void*) old, old->Name, old->RefCount);*/
180 deleteFlag = (old->RefCount == 0);
181
182 if (deleteFlag) {
183 _mesa_HashRemove(ctx->Shared->ShaderObjects, old->Name);
184 _mesa_free_shader_program(ctx, old);
185 }
186
187 *ptr = NULL;
188 }
189 assert(!*ptr);
190
191 if (shProg) {
192 shProg->RefCount++;
193 /*printf("SHPROG INCR %p (%d) to %d\n",
194 (void*) shProg, shProg->Name, shProg->RefCount);*/
195 *ptr = shProg;
196 }
197 }
198
199
200 /**
201 * Lookup a GLSL program object.
202 */
203 struct gl_shader_program *
204 _mesa_lookup_shader_program(GLcontext *ctx, GLuint name)
205 {
206 struct gl_shader_program *shProg;
207 if (name) {
208 shProg = (struct gl_shader_program *)
209 _mesa_HashLookup(ctx->Shared->ShaderObjects, name);
210 /* Note that both gl_shader and gl_shader_program objects are kept
211 * in the same hash table. Check the object's type to be sure it's
212 * what we're expecting.
213 */
214 if (shProg && shProg->Type != GL_SHADER_PROGRAM_MESA) {
215 return NULL;
216 }
217 return shProg;
218 }
219 return NULL;
220 }
221
222
223 /**
224 * Allocate a new gl_shader object, initialize it.
225 */
226 struct gl_shader *
227 _mesa_new_shader(GLcontext *ctx, GLuint name, GLenum type)
228 {
229 struct gl_shader *shader;
230 assert(type == GL_FRAGMENT_SHADER || type == GL_VERTEX_SHADER);
231 shader = CALLOC_STRUCT(gl_shader);
232 if (shader) {
233 shader->Type = type;
234 shader->Name = name;
235 shader->RefCount = 1;
236 }
237 return shader;
238 }
239
240
241 void
242 _mesa_free_shader(GLcontext *ctx, struct gl_shader *sh)
243 {
244 GLuint i;
245 if (sh->Source)
246 _mesa_free((void *) sh->Source);
247 if (sh->InfoLog)
248 _mesa_free(sh->InfoLog);
249 for (i = 0; i < sh->NumPrograms; i++) {
250 assert(sh->Programs[i]);
251 ctx->Driver.DeleteProgram(ctx, sh->Programs[i]);
252 }
253 if (sh->Programs)
254 _mesa_free(sh->Programs);
255 _mesa_free(sh);
256 }
257
258
259 /**
260 * Set ptr to point to sh.
261 * If ptr is pointing to another shader, decrement its refcount (and delete
262 * if refcount hits zero).
263 * Then set ptr to point to sh, incrementing its refcount.
264 */
265 /* XXX this could be static */
266 void
267 _mesa_reference_shader(GLcontext *ctx, struct gl_shader **ptr,
268 struct gl_shader *sh)
269 {
270 assert(ptr);
271 if (*ptr == sh) {
272 /* no-op */
273 return;
274 }
275 if (*ptr) {
276 /* Unreference the old shader */
277 GLboolean deleteFlag = GL_FALSE;
278 struct gl_shader *old = *ptr;
279
280 ASSERT(old->RefCount > 0);
281 old->RefCount--;
282 /*printf("SHADER DECR %p (%d) to %d\n",
283 (void*) old, old->Name, old->RefCount);*/
284 deleteFlag = (old->RefCount == 0);
285
286 if (deleteFlag) {
287 _mesa_HashRemove(ctx->Shared->ShaderObjects, old->Name);
288 _mesa_free_shader(ctx, old);
289 }
290
291 *ptr = NULL;
292 }
293 assert(!*ptr);
294
295 if (sh) {
296 /* reference new */
297 sh->RefCount++;
298 /*printf("SHADER INCR %p (%d) to %d\n",
299 (void*) sh, sh->Name, sh->RefCount);*/
300 *ptr = sh;
301 }
302 }
303
304
305 /**
306 * Lookup a GLSL shader object.
307 */
308 struct gl_shader *
309 _mesa_lookup_shader(GLcontext *ctx, GLuint name)
310 {
311 if (name) {
312 struct gl_shader *sh = (struct gl_shader *)
313 _mesa_HashLookup(ctx->Shared->ShaderObjects, name);
314 /* Note that both gl_shader and gl_shader_program objects are kept
315 * in the same hash table. Check the object's type to be sure it's
316 * what we're expecting.
317 */
318 if (sh && sh->Type == GL_SHADER_PROGRAM_MESA) {
319 return NULL;
320 }
321 return sh;
322 }
323 return NULL;
324 }
325
326
327 /**
328 * Initialize context's shader state.
329 */
330 void
331 _mesa_init_shader_state(GLcontext * ctx)
332 {
333 /* Device drivers may override these to control what kind of instructions
334 * are generated by the GLSL compiler.
335 */
336 ctx->Shader.EmitHighLevelInstructions = GL_TRUE;
337 ctx->Shader.EmitCondCodes = GL_TRUE; /* XXX probably want GL_FALSE... */
338 ctx->Shader.EmitComments = GL_FALSE;
339 }
340
341
342 /**
343 * Free the per-context shader-related state.
344 */
345 void
346 _mesa_free_shader_state(GLcontext *ctx)
347 {
348 _mesa_reference_shader_program(ctx, &ctx->Shader.CurrentProgram, NULL);
349 }
350
351
352 /**
353 * Copy string from <src> to <dst>, up to maxLength characters, returning
354 * length of <dst> in <length>.
355 * \param src the strings source
356 * \param maxLength max chars to copy
357 * \param length returns number of chars copied
358 * \param dst the string destination
359 */
360 static void
361 copy_string(GLchar *dst, GLsizei maxLength, GLsizei *length, const GLchar *src)
362 {
363 GLsizei len;
364 for (len = 0; len < maxLength - 1 && src && src[len]; len++)
365 dst[len] = src[len];
366 if (maxLength > 0)
367 dst[len] = 0;
368 if (length)
369 *length = len;
370 }
371
372
373 /**
374 * Return size (in floats) of the given GLSL type.
375 * See also _slang_sizeof_type_specifier().
376 */
377 static GLint
378 sizeof_glsl_type(GLenum type)
379 {
380 switch (type) {
381 case GL_BOOL:
382 case GL_FLOAT:
383 case GL_INT:
384 return 1;
385 case GL_BOOL_VEC2:
386 case GL_FLOAT_VEC2:
387 case GL_INT_VEC2:
388 return 2;
389 case GL_BOOL_VEC3:
390 case GL_FLOAT_VEC3:
391 case GL_INT_VEC3:
392 return 3;
393 case GL_BOOL_VEC4:
394 case GL_FLOAT_VEC4:
395 case GL_INT_VEC4:
396 return 4;
397 case GL_FLOAT_MAT2:
398 return 8; /* 2 rows of 4, actually */
399 case GL_FLOAT_MAT3:
400 return 12; /* 3 rows of 4, actually */
401 case GL_FLOAT_MAT4:
402 return 16;
403 case GL_FLOAT_MAT2x3:
404 return 8; /* 2 rows of 4, actually */
405 case GL_FLOAT_MAT2x4:
406 return 8;
407 case GL_FLOAT_MAT3x2:
408 return 12; /* 3 rows of 4, actually */
409 case GL_FLOAT_MAT3x4:
410 return 12;
411 case GL_FLOAT_MAT4x2:
412 return 16; /* 4 rows of 4, actually */
413 case GL_FLOAT_MAT4x3:
414 return 16; /* 4 rows of 4, actually */
415 default:
416 return 0; /* error */
417 }
418 }
419
420
421 /**
422 * Called via ctx->Driver.AttachShader()
423 */
424 void
425 _mesa_attach_shader(GLcontext *ctx, GLuint program, GLuint shader)
426 {
427 struct gl_shader_program *shProg
428 = _mesa_lookup_shader_program(ctx, program);
429 struct gl_shader *sh = _mesa_lookup_shader(ctx, shader);
430 GLuint n;
431 GLuint i;
432
433 if (!shProg || !sh) {
434 _mesa_error(ctx, GL_INVALID_VALUE,
435 "glAttachShader(bad program or shader name)");
436 return;
437 }
438
439 n = shProg->NumShaders;
440
441 for (i = 0; i < n; i++) {
442 if (shProg->Shaders[i] == sh) {
443 /* already attached */
444 return;
445 }
446 }
447
448 /* grow list */
449 shProg->Shaders = (struct gl_shader **)
450 _mesa_realloc(shProg->Shaders,
451 n * sizeof(struct gl_shader *),
452 (n + 1) * sizeof(struct gl_shader *));
453 if (!shProg->Shaders) {
454 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glAttachShader");
455 return;
456 }
457
458 /* append */
459 shProg->Shaders[n] = NULL; /* since realloc() didn't zero the new space */
460 _mesa_reference_shader(ctx, &shProg->Shaders[n], sh);
461 shProg->NumShaders++;
462 }
463
464
465 void
466 _mesa_bind_attrib_location(GLcontext *ctx, GLuint program, GLuint index,
467 const GLchar *name)
468 {
469 struct gl_shader_program *shProg
470 = _mesa_lookup_shader_program(ctx, program);
471 const GLint size = -1; /* unknown size */
472 GLint i, oldIndex;
473
474 if (!shProg) {
475 _mesa_error(ctx, GL_INVALID_VALUE, "glBindAttribLocation(program)");
476 return;
477 }
478
479 if (!name)
480 return;
481
482 if (strncmp(name, "gl_", 3) == 0) {
483 _mesa_error(ctx, GL_INVALID_OPERATION,
484 "glBindAttribLocation(illegal name)");
485 return;
486 }
487
488 if (shProg->LinkStatus) {
489 /* get current index/location for the attribute */
490 oldIndex = _mesa_get_attrib_location(ctx, program, name);
491 }
492 else {
493 oldIndex = -1;
494 }
495
496 /* this will replace the current value if it's already in the list */
497 i = _mesa_add_attribute(shProg->Attributes, name, size, index);
498 if (i < 0) {
499 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBindAttribLocation");
500 }
501
502 if (shProg->VertexProgram && oldIndex >= 0 && oldIndex != index) {
503 /* If the index changed, need to search/replace references to that attribute
504 * in the vertex program.
505 */
506 _slang_remap_attribute(&shProg->VertexProgram->Base, oldIndex, index);
507 }
508 }
509
510
511 GLuint
512 _mesa_create_shader(GLcontext *ctx, GLenum type)
513 {
514 struct gl_shader *sh;
515 GLuint name;
516
517 name = _mesa_HashFindFreeKeyBlock(ctx->Shared->ShaderObjects, 1);
518
519 switch (type) {
520 case GL_FRAGMENT_SHADER:
521 case GL_VERTEX_SHADER:
522 sh = _mesa_new_shader(ctx, name, type);
523 break;
524 default:
525 _mesa_error(ctx, GL_INVALID_ENUM, "CreateShader(type)");
526 return 0;
527 }
528
529 _mesa_HashInsert(ctx->Shared->ShaderObjects, name, sh);
530
531 return name;
532 }
533
534
535 GLuint
536 _mesa_create_program(GLcontext *ctx)
537 {
538 GLuint name;
539 struct gl_shader_program *shProg;
540
541 name = _mesa_HashFindFreeKeyBlock(ctx->Shared->ShaderObjects, 1);
542 shProg = _mesa_new_shader_program(ctx, name);
543
544 _mesa_HashInsert(ctx->Shared->ShaderObjects, name, shProg);
545
546 assert(shProg->RefCount == 1);
547
548 return name;
549 }
550
551
552 /**
553 * Named w/ "2" to indicate OpenGL 2.x vs GL_ARB_fragment_programs's
554 * DeleteProgramARB.
555 */
556 void
557 _mesa_delete_program2(GLcontext *ctx, GLuint name)
558 {
559 /*
560 * NOTE: deleting shaders/programs works a bit differently than
561 * texture objects (and buffer objects, etc). Shader/program
562 * handles/IDs exist in the hash table until the object is really
563 * deleted (refcount==0). With texture objects, the handle/ID is
564 * removed from the hash table in glDeleteTextures() while the tex
565 * object itself might linger until its refcount goes to zero.
566 */
567 struct gl_shader_program *shProg;
568
569 shProg = _mesa_lookup_shader_program(ctx, name);
570 if (!shProg) {
571 _mesa_error(ctx, GL_INVALID_VALUE, "glDeleteProgram(name)");
572 return;
573 }
574
575 shProg->DeletePending = GL_TRUE;
576
577 /* effectively, decr shProg's refcount */
578 _mesa_reference_shader_program(ctx, &shProg, NULL);
579 }
580
581
582 void
583 _mesa_delete_shader(GLcontext *ctx, GLuint shader)
584 {
585 struct gl_shader *sh = _mesa_lookup_shader(ctx, shader);
586 if (!sh) {
587 return;
588 }
589
590 sh->DeletePending = GL_TRUE;
591
592 /* effectively, decr sh's refcount */
593 _mesa_reference_shader(ctx, &sh, NULL);
594 }
595
596
597 void
598 _mesa_detach_shader(GLcontext *ctx, GLuint program, GLuint shader)
599 {
600 struct gl_shader_program *shProg
601 = _mesa_lookup_shader_program(ctx, program);
602 GLuint n;
603 GLuint i, j;
604
605 if (!shProg) {
606 _mesa_error(ctx, GL_INVALID_VALUE,
607 "glDetachShader(bad program or shader name)");
608 return;
609 }
610
611 n = shProg->NumShaders;
612
613 for (i = 0; i < n; i++) {
614 if (shProg->Shaders[i]->Name == shader) {
615 /* found it */
616 struct gl_shader **newList;
617
618 /* derefernce */
619 _mesa_reference_shader(ctx, &shProg->Shaders[i], NULL);
620
621 /* alloc new, smaller array */
622 newList = (struct gl_shader **)
623 _mesa_malloc((n - 1) * sizeof(struct gl_shader *));
624 if (!newList) {
625 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glDetachShader");
626 return;
627 }
628 for (j = 0; j < i; j++) {
629 newList[j] = shProg->Shaders[j];
630 }
631 while (++i < n)
632 newList[j++] = shProg->Shaders[i];
633 _mesa_free(shProg->Shaders);
634
635 shProg->Shaders = newList;
636 shProg->NumShaders = n - 1;
637
638 #ifdef DEBUG
639 /* sanity check */
640 {
641 for (j = 0; j < shProg->NumShaders; j++) {
642 assert(shProg->Shaders[j]->Type == GL_VERTEX_SHADER ||
643 shProg->Shaders[j]->Type == GL_FRAGMENT_SHADER);
644 assert(shProg->Shaders[j]->RefCount > 0);
645 }
646 }
647 #endif
648
649 return;
650 }
651 }
652
653 /* not found */
654 _mesa_error(ctx, GL_INVALID_VALUE,
655 "glDetachShader(shader not found)");
656 }
657
658
659 void
660 _mesa_get_active_attrib(GLcontext *ctx, GLuint program, GLuint index,
661 GLsizei maxLength, GLsizei *length, GLint *size,
662 GLenum *type, GLchar *nameOut)
663 {
664 static const GLenum vec_types[] = {
665 GL_FLOAT, GL_FLOAT_VEC2, GL_FLOAT_VEC3, GL_FLOAT_VEC4
666 };
667 struct gl_shader_program *shProg
668 = _mesa_lookup_shader_program(ctx, program);
669 GLint sz;
670
671 if (!shProg) {
672 _mesa_error(ctx, GL_INVALID_VALUE, "glGetActiveAttrib");
673 return;
674 }
675
676 if (!shProg->Attributes || index >= shProg->Attributes->NumParameters) {
677 _mesa_error(ctx, GL_INVALID_VALUE, "glGetActiveAttrib(index)");
678 return;
679 }
680
681 copy_string(nameOut, maxLength, length,
682 shProg->Attributes->Parameters[index].Name);
683 sz = shProg->Attributes->Parameters[index].Size;
684 if (size)
685 *size = 1; /* attributes may not be arrays */
686 if (type && sz > 0 && sz <= 4) /* XXX this is a temporary hack */
687 *type = vec_types[sz - 1];
688 }
689
690
691 /**
692 * Called via ctx->Driver.GetActiveUniform().
693 */
694 void
695 _mesa_get_active_uniform(GLcontext *ctx, GLuint program, GLuint index,
696 GLsizei maxLength, GLsizei *length, GLint *size,
697 GLenum *type, GLchar *nameOut)
698 {
699 struct gl_shader_program *shProg
700 = _mesa_lookup_shader_program(ctx, program);
701 GLuint ind, j;
702
703 if (!shProg) {
704 _mesa_error(ctx, GL_INVALID_VALUE, "glGetActiveUniform");
705 return;
706 }
707
708 if (!shProg->Uniforms || index >= shProg->Uniforms->NumParameters) {
709 _mesa_error(ctx, GL_INVALID_VALUE, "glGetActiveUniform(index)");
710 return;
711 }
712
713 ind = 0;
714 for (j = 0; j < shProg->Uniforms->NumParameters; j++) {
715 if (shProg->Uniforms->Parameters[j].Type == PROGRAM_UNIFORM ||
716 shProg->Uniforms->Parameters[j].Type == PROGRAM_SAMPLER) {
717 if (ind == index) {
718 GLuint uSize = shProg->Uniforms->Parameters[j].Size;
719 GLenum uType = shProg->Uniforms->Parameters[j].DataType;
720 /* found it */
721 copy_string(nameOut, maxLength, length,
722 shProg->Uniforms->Parameters[j].Name);
723 if (size) {
724 /* convert from floats to 'type' (eg: sizeof(mat4x4)=1) */
725 *size = uSize / sizeof_glsl_type(uType);
726 }
727 if (type)
728 *type = uType;
729 return;
730 }
731 ind++;
732 }
733 }
734
735 _mesa_error(ctx, GL_INVALID_VALUE, "glGetActiveUniform(index)");
736 }
737
738
739 /**
740 * Called via ctx->Driver.GetAttachedShaders().
741 */
742 void
743 _mesa_get_attached_shaders(GLcontext *ctx, GLuint program, GLsizei maxCount,
744 GLsizei *count, GLuint *obj)
745 {
746 struct gl_shader_program *shProg
747 = _mesa_lookup_shader_program(ctx, program);
748 if (shProg) {
749 GLint i;
750 for (i = 0; i < maxCount && i < shProg->NumShaders; i++) {
751 obj[i] = shProg->Shaders[i]->Name;
752 }
753 if (count)
754 *count = i;
755 }
756 else {
757 _mesa_error(ctx, GL_INVALID_VALUE, "glGetAttachedShaders");
758 }
759 }
760
761
762 GLint
763 _mesa_get_attrib_location(GLcontext *ctx, GLuint program,
764 const GLchar *name)
765 {
766 struct gl_shader_program *shProg
767 = _mesa_lookup_shader_program(ctx, program);
768
769 if (!shProg) {
770 _mesa_error(ctx, GL_INVALID_VALUE, "glGetAttribLocation");
771 return -1;
772 }
773
774 if (!shProg->LinkStatus) {
775 _mesa_error(ctx, GL_INVALID_OPERATION,
776 "glGetAttribLocation(program not linked)");
777 return -1;
778 }
779
780 if (!name)
781 return -1;
782
783 if (shProg->Attributes) {
784 GLint i = _mesa_lookup_parameter_index(shProg->Attributes, -1, name);
785 if (i >= 0) {
786 return shProg->Attributes->Parameters[i].StateIndexes[0];
787 }
788 }
789 return -1;
790 }
791
792
793 GLuint
794 _mesa_get_handle(GLcontext *ctx, GLenum pname)
795 {
796 #if 0
797 GET_CURRENT_CONTEXT(ctx);
798
799 switch (pname) {
800 case GL_PROGRAM_OBJECT_ARB:
801 {
802 struct gl2_program_intf **pro = ctx->Shader.CurrentProgram;
803
804 if (pro != NULL)
805 return (**pro)._container._generic.
806 GetName((struct gl2_generic_intf **) (pro));
807 }
808 break;
809 default:
810 _mesa_error(ctx, GL_INVALID_ENUM, "glGetHandleARB");
811 }
812 #endif
813 return 0;
814 }
815
816
817 void
818 _mesa_get_programiv(GLcontext *ctx, GLuint program,
819 GLenum pname, GLint *params)
820 {
821 struct gl_shader_program *shProg
822 = _mesa_lookup_shader_program(ctx, program);
823
824 if (!shProg) {
825 _mesa_error(ctx, GL_INVALID_VALUE, "glGetProgramiv(program)");
826 return;
827 }
828
829 switch (pname) {
830 case GL_DELETE_STATUS:
831 *params = shProg->DeletePending;
832 break;
833 case GL_LINK_STATUS:
834 *params = shProg->LinkStatus;
835 break;
836 case GL_VALIDATE_STATUS:
837 *params = shProg->Validated;
838 break;
839 case GL_INFO_LOG_LENGTH:
840 *params = shProg->InfoLog ? strlen(shProg->InfoLog) + 1 : 0;
841 break;
842 case GL_ATTACHED_SHADERS:
843 *params = shProg->NumShaders;
844 break;
845 case GL_ACTIVE_ATTRIBUTES:
846 *params = shProg->Attributes ? shProg->Attributes->NumParameters : 0;
847 break;
848 case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH:
849 *params = _mesa_longest_parameter_name(shProg->Attributes,
850 PROGRAM_INPUT) + 1;
851 break;
852 case GL_ACTIVE_UNIFORMS:
853 *params
854 = _mesa_num_parameters_of_type(shProg->Uniforms, PROGRAM_UNIFORM)
855 + _mesa_num_parameters_of_type(shProg->Uniforms, PROGRAM_SAMPLER);
856 break;
857 case GL_ACTIVE_UNIFORM_MAX_LENGTH:
858 *params = MAX2(
859 _mesa_longest_parameter_name(shProg->Uniforms, PROGRAM_UNIFORM),
860 _mesa_longest_parameter_name(shProg->Uniforms, PROGRAM_SAMPLER));
861 if (*params > 0)
862 (*params)++; /* add one for terminating zero */
863 break;
864 default:
865 _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramiv(pname)");
866 return;
867 }
868 }
869
870
871 void
872 _mesa_get_shaderiv(GLcontext *ctx, GLuint name, GLenum pname, GLint *params)
873 {
874 struct gl_shader *shader = _mesa_lookup_shader(ctx, name);
875
876 if (!shader) {
877 _mesa_error(ctx, GL_INVALID_VALUE, "glGetShaderiv(shader)");
878 return;
879 }
880
881 switch (pname) {
882 case GL_SHADER_TYPE:
883 *params = shader->Type;
884 break;
885 case GL_DELETE_STATUS:
886 *params = shader->DeletePending;
887 break;
888 case GL_COMPILE_STATUS:
889 *params = shader->CompileStatus;
890 break;
891 case GL_INFO_LOG_LENGTH:
892 *params = shader->InfoLog ? strlen(shader->InfoLog) + 1 : 0;
893 break;
894 case GL_SHADER_SOURCE_LENGTH:
895 *params = shader->Source ? strlen((char *) shader->Source) + 1 : 0;
896 break;
897 default:
898 _mesa_error(ctx, GL_INVALID_ENUM, "glGetShaderiv(pname)");
899 return;
900 }
901 }
902
903
904 void
905 _mesa_get_program_info_log(GLcontext *ctx, GLuint program, GLsizei bufSize,
906 GLsizei *length, GLchar *infoLog)
907 {
908 struct gl_shader_program *shProg
909 = _mesa_lookup_shader_program(ctx, program);
910 if (!shProg) {
911 _mesa_error(ctx, GL_INVALID_VALUE, "glGetProgramInfoLog(program)");
912 return;
913 }
914 copy_string(infoLog, bufSize, length, shProg->InfoLog);
915 }
916
917
918 void
919 _mesa_get_shader_info_log(GLcontext *ctx, GLuint shader, GLsizei bufSize,
920 GLsizei *length, GLchar *infoLog)
921 {
922 struct gl_shader *sh = _mesa_lookup_shader(ctx, shader);
923 if (!sh) {
924 _mesa_error(ctx, GL_INVALID_VALUE, "glGetShaderInfoLog(shader)");
925 return;
926 }
927 copy_string(infoLog, bufSize, length, sh->InfoLog);
928 }
929
930
931 /**
932 * Called via ctx->Driver.GetShaderSource().
933 */
934 void
935 _mesa_get_shader_source(GLcontext *ctx, GLuint shader, GLsizei maxLength,
936 GLsizei *length, GLchar *sourceOut)
937 {
938 struct gl_shader *sh = _mesa_lookup_shader(ctx, shader);
939 if (!sh) {
940 _mesa_error(ctx, GL_INVALID_VALUE, "glGetShaderSource(shader)");
941 return;
942 }
943 copy_string(sourceOut, maxLength, length, sh->Source);
944 }
945
946
947 /**
948 * Called via ctx->Driver.GetUniformfv().
949 */
950 void
951 _mesa_get_uniformfv(GLcontext *ctx, GLuint program, GLint location,
952 GLfloat *params)
953 {
954 struct gl_shader_program *shProg
955 = _mesa_lookup_shader_program(ctx, program);
956 if (shProg) {
957 GLint i;
958 if (location >= 0 && location < shProg->Uniforms->NumParameters) {
959 GLuint uSize;
960 GLenum uType;
961 GLint rows = 0;
962 uType = shProg->Uniforms->Parameters[location].DataType;
963 uSize = sizeof_glsl_type(uType);
964 /* Matrix types need special handling, because they span several
965 * parameters, and may also not be fully packed.
966 */
967 switch (shProg->Uniforms->Parameters[location].DataType) {
968 case GL_FLOAT_MAT2:
969 case GL_FLOAT_MAT3x2:
970 case GL_FLOAT_MAT4x2:
971 rows = 2;
972 break;
973 case GL_FLOAT_MAT2x3:
974 case GL_FLOAT_MAT3:
975 case GL_FLOAT_MAT4x3:
976 rows = 3;
977 break;
978 case GL_FLOAT_MAT2x4:
979 case GL_FLOAT_MAT3x4:
980 case GL_FLOAT_MAT4:
981 rows = 4;
982 }
983 if (rows != 0) {
984 GLint r, c;
985 for (c = 0, i = 0; c * 4 < uSize; c++)
986 for (r = 0; r < rows; r++, i++)
987 params[i] = shProg->Uniforms->ParameterValues[location + c][r];
988 }
989 else
990 for (i = 0; i < uSize; i++) {
991 params[i] = shProg->Uniforms->ParameterValues[location][i];
992 }
993 }
994 else {
995 _mesa_error(ctx, GL_INVALID_VALUE, "glGetUniformfv(location)");
996 }
997 }
998 else {
999 _mesa_error(ctx, GL_INVALID_VALUE, "glGetUniformfv(program)");
1000 }
1001 }
1002
1003
1004 /**
1005 * Called via ctx->Driver.GetUniformLocation().
1006 */
1007 GLint
1008 _mesa_get_uniform_location(GLcontext *ctx, GLuint program, const GLchar *name)
1009 {
1010 struct gl_shader_program *shProg
1011 = _mesa_lookup_shader_program(ctx, program);
1012 if (shProg) {
1013 GLuint loc;
1014 for (loc = 0; loc < shProg->Uniforms->NumParameters; loc++) {
1015 const struct gl_program_parameter *u
1016 = shProg->Uniforms->Parameters + loc;
1017 /* XXX this is a temporary simplification / short-cut.
1018 * We need to handle things like "e.c[0].b" as seen in the
1019 * GLSL orange book, page 189.
1020 */
1021 if ((u->Type == PROGRAM_UNIFORM ||
1022 u->Type == PROGRAM_SAMPLER) && !strcmp(u->Name, name)) {
1023 return loc;
1024 }
1025 }
1026 }
1027 return -1;
1028
1029 }
1030
1031
1032 GLboolean
1033 _mesa_is_program(GLcontext *ctx, GLuint name)
1034 {
1035 struct gl_shader_program *shProg = _mesa_lookup_shader_program(ctx, name);
1036 return shProg ? GL_TRUE : GL_FALSE;
1037 }
1038
1039
1040 GLboolean
1041 _mesa_is_shader(GLcontext *ctx, GLuint name)
1042 {
1043 struct gl_shader *shader = _mesa_lookup_shader(ctx, name);
1044 return shader ? GL_TRUE : GL_FALSE;
1045 }
1046
1047
1048
1049 /**
1050 * Called via ctx->Driver.ShaderSource()
1051 */
1052 void
1053 _mesa_shader_source(GLcontext *ctx, GLuint shader, const GLchar *source)
1054 {
1055 struct gl_shader *sh = _mesa_lookup_shader(ctx, shader);
1056 if (!sh) {
1057 _mesa_error(ctx, GL_INVALID_VALUE, "glShaderSource(shaderObj)");
1058 return;
1059 }
1060
1061 /* free old shader source string and install new one */
1062 if (sh->Source) {
1063 _mesa_free((void *) sh->Source);
1064 }
1065 sh->Source = source;
1066 sh->CompileStatus = GL_FALSE;
1067 }
1068
1069
1070 /**
1071 * Called via ctx->Driver.CompileShader()
1072 */
1073 void
1074 _mesa_compile_shader(GLcontext *ctx, GLuint shaderObj)
1075 {
1076 struct gl_shader *sh = _mesa_lookup_shader(ctx, shaderObj);
1077
1078 if (!sh) {
1079 _mesa_error(ctx, GL_INVALID_VALUE, "glCompileShader(shaderObj)");
1080 return;
1081 }
1082
1083 sh->CompileStatus = _slang_compile(ctx, sh);
1084 }
1085
1086
1087 /**
1088 * Called via ctx->Driver.LinkProgram()
1089 */
1090 void
1091 _mesa_link_program(GLcontext *ctx, GLuint program)
1092 {
1093 struct gl_shader_program *shProg;
1094
1095 shProg = _mesa_lookup_shader_program(ctx, program);
1096 if (!shProg) {
1097 _mesa_error(ctx, GL_INVALID_VALUE, "glLinkProgram(program)");
1098 return;
1099 }
1100
1101 _slang_link(ctx, program, shProg);
1102 }
1103
1104
1105 /**
1106 * Called via ctx->Driver.UseProgram()
1107 */
1108 void
1109 _mesa_use_program(GLcontext *ctx, GLuint program)
1110 {
1111 struct gl_shader_program *shProg;
1112
1113 if (ctx->Shader.CurrentProgram &&
1114 ctx->Shader.CurrentProgram->Name == program) {
1115 /* no-op */
1116 return;
1117 }
1118
1119 FLUSH_VERTICES(ctx, _NEW_PROGRAM);
1120
1121 if (program) {
1122 shProg = _mesa_lookup_shader_program(ctx, program);
1123 if (!shProg) {
1124 _mesa_error(ctx, GL_INVALID_VALUE,
1125 "glUseProgramObjectARB(programObj)");
1126 return;
1127 }
1128 }
1129 else {
1130 shProg = NULL;
1131 }
1132
1133 _mesa_reference_shader_program(ctx, &ctx->Shader.CurrentProgram, shProg);
1134 }
1135
1136
1137 /**
1138 * Called via ctx->Driver.Uniform().
1139 */
1140 void
1141 _mesa_uniform(GLcontext *ctx, GLint location, GLsizei count,
1142 const GLvoid *values, GLenum type)
1143 {
1144 struct gl_shader_program *shProg = ctx->Shader.CurrentProgram;
1145 GLint elems, i, k;
1146 GLenum uType;
1147 GLsizei maxCount;
1148
1149 if (!shProg || !shProg->LinkStatus) {
1150 _mesa_error(ctx, GL_INVALID_OPERATION, "glUniform(program not linked)");
1151 return;
1152 }
1153
1154 if (location == -1)
1155 return; /* The standard specifies this as a no-op */
1156
1157 /* The spec says this is GL_INVALID_OPERATION, although it seems like it
1158 * ought to be GL_INVALID_VALUE
1159 */
1160 if (location < 0 || location >= (GLint) shProg->Uniforms->NumParameters) {
1161 _mesa_error(ctx, GL_INVALID_OPERATION, "glUniform(location)");
1162 return;
1163 }
1164
1165 FLUSH_VERTICES(ctx, _NEW_PROGRAM);
1166
1167 uType = shProg->Uniforms->Parameters[location].DataType;
1168 /*
1169 * If we're setting a sampler, we must use glUniformi1()!
1170 */
1171 if (shProg->Uniforms->Parameters[location].Type == PROGRAM_SAMPLER) {
1172 GLint unit;
1173 if (type != GL_INT || count != 1) {
1174 _mesa_error(ctx, GL_INVALID_OPERATION,
1175 "glUniform(only glUniform1i can be used "
1176 "to set sampler uniforms)");
1177 return;
1178 }
1179 /* check that the sampler (tex unit index) is legal */
1180 unit = ((GLint *) values)[0];
1181 if (unit >= ctx->Const.MaxTextureImageUnits) {
1182 _mesa_error(ctx, GL_INVALID_VALUE,
1183 "glUniform1(invalid sampler/tex unit index)");
1184 return;
1185 }
1186 }
1187
1188 if (count < 0) {
1189 _mesa_error(ctx, GL_INVALID_VALUE, "glUniform(count < 0)");
1190 return;
1191 }
1192
1193 switch (type) {
1194 case GL_FLOAT:
1195 case GL_INT:
1196 elems = 1;
1197 break;
1198 case GL_FLOAT_VEC2:
1199 case GL_INT_VEC2:
1200 elems = 2;
1201 break;
1202 case GL_FLOAT_VEC3:
1203 case GL_INT_VEC3:
1204 elems = 3;
1205 break;
1206 case GL_FLOAT_VEC4:
1207 case GL_INT_VEC4:
1208 elems = 4;
1209 break;
1210 default:
1211 _mesa_problem(ctx, "Invalid type in _mesa_uniform");
1212 return;
1213 }
1214
1215 /* OpenGL requires types to match exactly, except that one can convert
1216 * float or int array to boolean array.
1217 */
1218 switch (uType)
1219 {
1220 case GL_BOOL:
1221 case GL_BOOL_VEC2:
1222 case GL_BOOL_VEC3:
1223 case GL_BOOL_VEC4:
1224 if (elems != sizeof_glsl_type(uType)) {
1225 _mesa_error(ctx, GL_INVALID_OPERATION, "glUniform(count mismatch)");
1226 }
1227 break;
1228 case PROGRAM_SAMPLER:
1229 break;
1230 default:
1231 if (shProg->Uniforms->Parameters[location].Type != PROGRAM_SAMPLER
1232 && uType != type) {
1233 _mesa_error(ctx, GL_INVALID_OPERATION, "glUniform(type mismatch)");
1234 }
1235 break;
1236 }
1237
1238 /* XXX if this is a base type, then count must equal 1. However, we
1239 * don't have enough information from the compiler to distinguish a
1240 * base type from a 1-element array of that type. The standard allows
1241 * count to overrun an array, in which case the overflow is ignored.
1242 */
1243 maxCount = shProg->Uniforms->Parameters[location].Size / elems;
1244 if (count > maxCount) count = maxCount;
1245
1246 for (k = 0; k < count; k++) {
1247 GLfloat *uniformVal = shProg->Uniforms->ParameterValues[location + k];
1248 if (type == GL_INT ||
1249 type == GL_INT_VEC2 ||
1250 type == GL_INT_VEC3 ||
1251 type == GL_INT_VEC4) {
1252 const GLint *iValues = ((const GLint *) values) + k * elems;
1253 for (i = 0; i < elems; i++) {
1254 uniformVal[i] = (GLfloat) iValues[i];
1255 }
1256 }
1257 else {
1258 const GLfloat *fValues = ((const GLfloat *) values) + k * elems;
1259 for (i = 0; i < elems; i++) {
1260 uniformVal[i] = fValues[i];
1261 }
1262 }
1263 if (uType == GL_BOOL ||
1264 uType == GL_BOOL_VEC2 ||
1265 uType == GL_BOOL_VEC3 ||
1266 uType == GL_BOOL_VEC4) {
1267 for (i = 0; i < elems; i++)
1268 uniformVal[i] = uniformVal[i] ? 1.0f : 0.0f;
1269 }
1270 }
1271
1272 if (shProg->Uniforms->Parameters[location].Type == PROGRAM_SAMPLER) {
1273 if (shProg->VertexProgram)
1274 _slang_resolve_samplers(shProg, &shProg->VertexProgram->Base);
1275 if (shProg->FragmentProgram)
1276 _slang_resolve_samplers(shProg, &shProg->FragmentProgram->Base);
1277 FLUSH_VERTICES(ctx, _NEW_TEXTURE);
1278 }
1279 }
1280
1281
1282 /**
1283 * Called by ctx->Driver.UniformMatrix().
1284 */
1285 void
1286 _mesa_uniform_matrix(GLcontext *ctx, GLint cols, GLint rows,
1287 GLenum matrixType, GLint location, GLsizei count,
1288 GLboolean transpose, const GLfloat *values)
1289 {
1290 GLsizei maxCount, i;
1291 struct gl_shader_program *shProg = ctx->Shader.CurrentProgram;
1292 if (!shProg || !shProg->LinkStatus) {
1293 _mesa_error(ctx, GL_INVALID_OPERATION,
1294 "glUniformMatrix(program not linked)");
1295 return;
1296 }
1297 if (location == -1)
1298 return; /* The standard specifies this as a no-op */
1299 /* The spec says this is GL_INVALID_OPERATION, although it seems like it
1300 * ought to be GL_INVALID_VALUE
1301 */
1302 if (location < 0 || location >= (GLint) shProg->Uniforms->NumParameters) {
1303 _mesa_error(ctx, GL_INVALID_OPERATION, "glUniformMatrix(location)");
1304 return;
1305 }
1306 if (values == NULL) {
1307 _mesa_error(ctx, GL_INVALID_VALUE, "glUniformMatrix");
1308 return;
1309 }
1310 if (count < 0) {
1311 _mesa_error(ctx, GL_INVALID_VALUE, "glUniformMatrix(count < 0)");
1312 return;
1313 }
1314
1315 FLUSH_VERTICES(ctx, _NEW_PROGRAM);
1316
1317 /*
1318 * Note: the _columns_ of a matrix are stored in program registers, not
1319 * the rows.
1320 */
1321 /* XXXX need to test 3x3 and 2x2 matrices... */
1322 maxCount = shProg->Uniforms->Parameters[location].Size / (4 * cols);
1323 if (count > maxCount)
1324 count = maxCount;
1325 for (i = 0; i < count; i++) {
1326 if (transpose) {
1327 GLuint row, col;
1328 for (col = 0; col < cols; col++) {
1329 GLfloat *v = shProg->Uniforms->ParameterValues[location + col];
1330 for (row = 0; row < rows; row++) {
1331 v[row] = values[row * cols + col];
1332 }
1333 }
1334 }
1335 else {
1336 GLuint row, col;
1337 for (col = 0; col < cols; col++) {
1338 GLfloat *v = shProg->Uniforms->ParameterValues[location + col];
1339 for (row = 0; row < rows; row++) {
1340 v[row] = values[col * rows + row];
1341 }
1342 }
1343 }
1344 location += cols;
1345 values += rows * cols;
1346 }
1347 }
1348
1349
1350 void
1351 _mesa_validate_program(GLcontext *ctx, GLuint program)
1352 {
1353 struct gl_shader_program *shProg;
1354 shProg = _mesa_lookup_shader_program(ctx, program);
1355 if (!shProg) {
1356 _mesa_error(ctx, GL_INVALID_VALUE, "glValidateProgram(program)");
1357 return;
1358 }
1359 /* XXX temporary */
1360 shProg->Validated = GL_TRUE;
1361
1362 /* From the GL spec:
1363 any two active samplers in the current program object are of
1364 different types, but refer to the same texture image unit,
1365
1366 any active sampler in the current program object refers to a texture
1367 image unit where fixed-function fragment processing accesses a
1368 texture target that does not match the sampler type, or
1369
1370 the sum of the number of active samplers in the program and the
1371 number of texture image units enabled for fixed-function fragment
1372 processing exceeds the combined limit on the total number of texture
1373 image units allowed.
1374 */
1375 }