New _mesa_reference_shader/program() function to consolidate refcounting.
[mesa.git] / src / mesa / shader / shader_api.c
1 /*
2 * Mesa 3-D graphics library
3 * Version: 6.5.3
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 "program.h"
42 #include "prog_parameter.h"
43 #include "prog_print.h"
44 #include "prog_statevars.h"
45 #include "shader_api.h"
46
47 #include "slang_compile.h"
48 #include "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;
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 _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
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);
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 /**
133 * Free/delete a shader program object.
134 */
135 void
136 _mesa_free_shader_program(GLcontext *ctx, struct gl_shader_program *shProg)
137 {
138 printf("FREE SHADER PROG %d\n", shProg->Name);
139 _mesa_free_shader_program_data(ctx, shProg);
140 if (shProg->Shaders) {
141 _mesa_free(shProg->Shaders);
142 shProg->Shaders = NULL;
143 }
144 _mesa_free(shProg);
145 }
146
147
148 /**
149 * 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 */
155 void
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 /**
195 * Lookup a GLSL program object.
196 */
197 struct 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 */
220 struct 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
235 void
236 _mesa_free_shader(GLcontext *ctx, struct gl_shader *sh)
237 {
238 GLuint i;
239 printf("FREE SHADER %d\n", sh->Name);
240 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 /**
255 * 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 */
261 void
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 /**
301 * Lookup a GLSL shader object.
302 */
303 struct 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
324 /**
325 * Initialize context's shader state.
326 */
327 void
328 _mesa_init_shader_state(GLcontext * ctx)
329 {
330 /* 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;
334 ctx->Shader.EmitCondCodes = GL_TRUE; /* XXX probably want GL_FALSE... */
335 ctx->Shader.EmitComments = GL_FALSE;
336 }
337
338
339 /**
340 * Free the per-context shader-related state.
341 */
342 void
343 _mesa_free_shader_state(GLcontext *ctx)
344 {
345 _mesa_reference_shader_program(ctx, &ctx->Shader.CurrentProgram, NULL);
346 }
347
348
349 /**
350 * 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 */
357 static void
358 copy_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
370 /**
371 * Called via ctx->Driver.AttachShader()
372 */
373 void
374 _mesa_attach_shader(GLcontext *ctx, GLuint program, GLuint shader)
375 {
376 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;
380 GLuint i;
381
382 if (!shProg || !sh) {
383 _mesa_error(ctx, GL_INVALID_VALUE,
384 "glAttachShader(bad program or shader name)");
385 return;
386 }
387
388 for (i = 0; i < n; i++) {
389 if (shProg->Shaders[i] == sh) {
390 /* already attached */
391 return;
392 }
393 }
394
395 /* grow list */
396 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) {
401 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glAttachShader");
402 return;
403 }
404
405 /* append */
406 shProg->Shaders[n] = NULL; /* since realloc() didn't zero the new space */
407 _mesa_reference_shader(ctx, &shProg->Shaders[n], sh);
408 shProg->NumShaders++;
409 }
410
411
412 void
413 _mesa_bind_attrib_location(GLcontext *ctx, GLuint program, GLuint index,
414 const GLchar *name)
415 {
416 struct gl_shader_program *shProg
417 = _mesa_lookup_shader_program(ctx, program);
418 const GLint size = -1; /* unknown size */
419 GLint i, oldIndex;
420
421 if (!shProg) {
422 _mesa_error(ctx, GL_INVALID_VALUE, "glBindAttribLocation(program)");
423 return;
424 }
425
426 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
435 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 }
442
443 /* this will replace the current value if it's already in the list */
444 i = _mesa_add_attribute(shProg->Attributes, name, size, index);
445 if (i < 0) {
446 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBindAttribLocation");
447 }
448
449 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 */
453 _slang_remap_attribute(&shProg->VertexProgram->Base, oldIndex, index);
454 }
455 }
456
457
458 GLuint
459 _mesa_create_shader(GLcontext *ctx, GLenum type)
460 {
461 struct gl_shader *sh;
462 GLuint name;
463
464 name = _mesa_HashFindFreeKeyBlock(ctx->Shared->ShaderObjects, 1);
465
466 switch (type) {
467 case GL_FRAGMENT_SHADER:
468 case GL_VERTEX_SHADER:
469 sh = _mesa_new_shader(ctx, name, type);
470 break;
471 default:
472 _mesa_error(ctx, GL_INVALID_ENUM, "CreateShader(type)");
473 return 0;
474 }
475
476 _mesa_HashInsert(ctx->Shared->ShaderObjects, name, sh);
477
478 return name;
479 }
480
481
482 GLuint
483 _mesa_create_program(GLcontext *ctx)
484 {
485 GLuint name;
486 struct gl_shader_program *shProg;
487
488 name = _mesa_HashFindFreeKeyBlock(ctx->Shared->ShaderObjects, 1);
489 shProg = _mesa_new_shader_program(ctx, name);
490
491 _mesa_HashInsert(ctx->Shared->ShaderObjects, name, shProg);
492
493 assert(shProg->RefCount == 1);
494
495 return name;
496 }
497
498
499 /**
500 * Named w/ "2" to indicate OpenGL 2.x vs GL_ARB_fragment_programs's
501 * DeleteProgramARB.
502 */
503 void
504 _mesa_delete_program2(GLcontext *ctx, GLuint name)
505 {
506 /*
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 */
514 struct gl_shader_program *shProg;
515
516 shProg = _mesa_lookup_shader_program(ctx, name);
517 if (!shProg) {
518 _mesa_error(ctx, GL_INVALID_VALUE, "glDeleteProgram(name)");
519 return;
520 }
521
522 shProg->DeletePending = GL_TRUE;
523
524 /* effectively, decr shProg's refcount */
525 _mesa_reference_shader_program(ctx, &shProg, NULL);
526 }
527
528
529 void
530 _mesa_delete_shader(GLcontext *ctx, GLuint shader)
531 {
532 struct gl_shader *sh = _mesa_lookup_shader(ctx, shader);
533 if (!sh) {
534 return;
535 }
536
537 sh->DeletePending = GL_TRUE;
538
539 /* effectively, decr sh's refcount */
540 _mesa_reference_shader(ctx, &sh, NULL);
541 }
542
543
544 void
545 _mesa_detach_shader(GLcontext *ctx, GLuint program, GLuint shader)
546 {
547 struct gl_shader_program *shProg
548 = _mesa_lookup_shader_program(ctx, program);
549 const GLuint n = shProg->NumShaders;
550 GLuint i, j;
551
552 if (!shProg) {
553 _mesa_error(ctx, GL_INVALID_VALUE,
554 "glDetachShader(bad program or shader name)");
555 return;
556 }
557
558 for (i = 0; i < n; i++) {
559 if (shProg->Shaders[i]->Name == shader) {
560 /* found it */
561 struct gl_shader **newList;
562
563 /* derefernce */
564 _mesa_reference_shader(ctx, &shProg->Shaders[i], NULL);
565
566 /* alloc new, smaller array */
567 newList = (struct gl_shader **)
568 _mesa_malloc((n - 1) * sizeof(struct gl_shader *));
569 if (!newList) {
570 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glDetachShader");
571 return;
572 }
573 for (j = 0; j < i; j++) {
574 newList[j] = shProg->Shaders[j];
575 }
576 while (++i < n)
577 newList[j++] = shProg->Shaders[i];
578 _mesa_free(shProg->Shaders);
579
580 shProg->Shaders = newList;
581 return;
582 }
583 }
584
585 /* not found */
586 _mesa_error(ctx, GL_INVALID_VALUE,
587 "glDetachShader(shader not found)");
588 }
589
590
591 void
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 };
599 struct gl_shader_program *shProg
600 = _mesa_lookup_shader_program(ctx, program);
601 GLint sz;
602
603 if (!shProg) {
604 _mesa_error(ctx, GL_INVALID_VALUE, "glGetActiveUniform");
605 return;
606 }
607
608 if (!shProg->Attributes || index >= shProg->Attributes->NumParameters) {
609 _mesa_error(ctx, GL_INVALID_VALUE, "glGetActiveUniform(index)");
610 return;
611 }
612
613 copy_string(nameOut, maxLength, length,
614 shProg->Attributes->Parameters[index].Name);
615 sz = shProg->Attributes->Parameters[index].Size;
616 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 */
626 void
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 };
634 struct gl_shader_program *shProg
635 = _mesa_lookup_shader_program(ctx, program);
636 GLint sz;
637
638 if (!shProg) {
639 _mesa_error(ctx, GL_INVALID_VALUE, "glGetActiveUniform");
640 return;
641 }
642
643 if (!shProg->Uniforms || index >= shProg->Uniforms->NumParameters) {
644 _mesa_error(ctx, GL_INVALID_VALUE, "glGetActiveUniform(index)");
645 return;
646 }
647
648 copy_string(nameOut, maxLength, length,
649 shProg->Uniforms->Parameters[index].Name);
650 sz = shProg->Uniforms->Parameters[index].Size;
651 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 */
661 void
662 _mesa_get_attached_shaders(GLcontext *ctx, GLuint program, GLsizei maxCount,
663 GLsizei *count, GLuint *obj)
664 {
665 struct gl_shader_program *shProg
666 = _mesa_lookup_shader_program(ctx, program);
667 if (shProg) {
668 GLint i;
669 for (i = 0; i < maxCount && i < shProg->NumShaders; i++) {
670 obj[i] = shProg->Shaders[i]->Name;
671 }
672 if (count)
673 *count = i;
674 }
675 else {
676 _mesa_error(ctx, GL_INVALID_VALUE, "glGetAttachedShaders");
677 }
678 }
679
680
681 GLint
682 _mesa_get_attrib_location(GLcontext *ctx, GLuint program,
683 const GLchar *name)
684 {
685 struct gl_shader_program *shProg
686 = _mesa_lookup_shader_program(ctx, program);
687
688 if (!shProg) {
689 _mesa_error(ctx, GL_INVALID_VALUE, "glGetAttribLocation");
690 return -1;
691 }
692
693 if (!shProg->LinkStatus) {
694 _mesa_error(ctx, GL_INVALID_OPERATION,
695 "glGetAttribLocation(program not linked)");
696 return -1;
697 }
698
699 if (!name)
700 return -1;
701
702 if (shProg->Attributes) {
703 GLint i = _mesa_lookup_parameter_index(shProg->Attributes, -1, name);
704 if (i >= 0) {
705 return shProg->Attributes->Parameters[i].StateIndexes[0];
706 }
707 }
708 return -1;
709 }
710
711
712 GLuint
713 _mesa_get_handle(GLcontext *ctx, GLenum pname)
714 {
715 #if 0
716 GET_CURRENT_CONTEXT(ctx);
717
718 switch (pname) {
719 case GL_PROGRAM_OBJECT_ARB:
720 {
721 struct gl2_program_intf **pro = ctx->Shader.CurrentProgram;
722
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
736 void
737 _mesa_get_programiv(GLcontext *ctx, GLuint program,
738 GLenum pname, GLint *params)
739 {
740 struct gl_shader_program *shProg
741 = _mesa_lookup_shader_program(ctx, program);
742
743 if (!shProg) {
744 _mesa_error(ctx, GL_INVALID_VALUE, "glGetProgramiv(program)");
745 return;
746 }
747
748 switch (pname) {
749 case GL_DELETE_STATUS:
750 *params = shProg->DeletePending;
751 break;
752 case GL_LINK_STATUS:
753 *params = shProg->LinkStatus;
754 break;
755 case GL_VALIDATE_STATUS:
756 *params = shProg->Validated;
757 break;
758 case GL_INFO_LOG_LENGTH:
759 *params = shProg->InfoLog ? strlen(shProg->InfoLog) : 0;
760 break;
761 case GL_ATTACHED_SHADERS:
762 *params = shProg->NumShaders;
763 break;
764 case GL_ACTIVE_ATTRIBUTES:
765 *params = shProg->Attributes ? shProg->Attributes->NumParameters : 0;
766 break;
767 case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH:
768 *params = _mesa_parameter_longest_name(shProg->Attributes);
769 break;
770 case GL_ACTIVE_UNIFORMS:
771 *params = shProg->Uniforms ? shProg->Uniforms->NumParameters : 0;
772 break;
773 case GL_ACTIVE_UNIFORM_MAX_LENGTH:
774 *params = _mesa_parameter_longest_name(shProg->Uniforms);
775 break;
776 default:
777 _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramiv(pname)");
778 return;
779 }
780 }
781
782
783 void
784 _mesa_get_shaderiv(GLcontext *ctx, GLuint name, GLenum pname, GLint *params)
785 {
786 struct gl_shader *shader = _mesa_lookup_shader(ctx, name);
787
788 if (!shader) {
789 _mesa_error(ctx, GL_INVALID_VALUE, "glGetShaderiv(shader)");
790 return;
791 }
792
793 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
816 void
817 _mesa_get_program_info_log(GLcontext *ctx, GLuint program, GLsizei bufSize,
818 GLsizei *length, GLchar *infoLog)
819 {
820 struct gl_shader_program *shProg
821 = _mesa_lookup_shader_program(ctx, program);
822 if (!shProg) {
823 _mesa_error(ctx, GL_INVALID_VALUE, "glGetProgramInfoLog(program)");
824 return;
825 }
826 copy_string(infoLog, bufSize, length, shProg->InfoLog);
827 }
828
829
830 void
831 _mesa_get_shader_info_log(GLcontext *ctx, GLuint shader, GLsizei bufSize,
832 GLsizei *length, GLchar *infoLog)
833 {
834 struct gl_shader *sh = _mesa_lookup_shader(ctx, shader);
835 if (!sh) {
836 _mesa_error(ctx, GL_INVALID_VALUE, "glGetShaderInfoLog(shader)");
837 return;
838 }
839 copy_string(infoLog, bufSize, length, sh->InfoLog);
840 }
841
842
843 /**
844 * Called via ctx->Driver.GetShaderSource().
845 */
846 void
847 _mesa_get_shader_source(GLcontext *ctx, GLuint shader, GLsizei maxLength,
848 GLsizei *length, GLchar *sourceOut)
849 {
850 struct gl_shader *sh = _mesa_lookup_shader(ctx, shader);
851 if (!sh) {
852 _mesa_error(ctx, GL_INVALID_VALUE, "glGetShaderSource(shader)");
853 return;
854 }
855 copy_string(sourceOut, maxLength, length, sh->Source);
856 }
857
858
859 /**
860 * Called via ctx->Driver.GetUniformfv().
861 */
862 void
863 _mesa_get_uniformfv(GLcontext *ctx, GLuint program, GLint location,
864 GLfloat *params)
865 {
866 struct gl_shader_program *shProg
867 = _mesa_lookup_shader_program(ctx, program);
868 if (shProg) {
869 GLint i;
870 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];
873 }
874 }
875 else {
876 _mesa_error(ctx, GL_INVALID_VALUE, "glGetUniformfv(location)");
877 }
878 }
879 else {
880 _mesa_error(ctx, GL_INVALID_VALUE, "glGetUniformfv(program)");
881 }
882 }
883
884
885 /**
886 * Called via ctx->Driver.GetUniformLocation().
887 */
888 GLint
889 _mesa_get_uniform_location(GLcontext *ctx, GLuint program, const GLchar *name)
890 {
891 struct gl_shader_program *shProg
892 = _mesa_lookup_shader_program(ctx, program);
893 if (shProg) {
894 GLuint loc;
895 for (loc = 0; loc < shProg->Uniforms->NumParameters; loc++) {
896 const struct gl_program_parameter *u
897 = shProg->Uniforms->Parameters + loc;
898 /* 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 */
902 if ((u->Type == PROGRAM_UNIFORM ||
903 u->Type == PROGRAM_SAMPLER) && !strcmp(u->Name, name)) {
904 return loc;
905 }
906 }
907 }
908 return -1;
909
910 }
911
912
913 GLboolean
914 _mesa_is_program(GLcontext *ctx, GLuint name)
915 {
916 struct gl_shader_program *shProg = _mesa_lookup_shader_program(ctx, name);
917 return shProg ? GL_TRUE : GL_FALSE;
918 }
919
920
921 GLboolean
922 _mesa_is_shader(GLcontext *ctx, GLuint name)
923 {
924 struct gl_shader *shader = _mesa_lookup_shader(ctx, name);
925 return shader ? GL_TRUE : GL_FALSE;
926 }
927
928
929
930 /**
931 * Called via ctx->Driver.ShaderSource()
932 */
933 void
934 _mesa_shader_source(GLcontext *ctx, GLuint shader, const GLchar *source)
935 {
936 struct gl_shader *sh = _mesa_lookup_shader(ctx, shader);
937 if (!sh) {
938 _mesa_error(ctx, GL_INVALID_VALUE, "glShaderSource(shaderObj)");
939 return;
940 }
941
942 /* free old shader source string and install new one */
943 if (sh->Source) {
944 _mesa_free((void *) sh->Source);
945 }
946 sh->Source = source;
947 sh->CompileStatus = GL_FALSE;
948 }
949
950
951 /**
952 * Called via ctx->Driver.CompileShader()
953 */
954 void
955 _mesa_compile_shader(GLcontext *ctx, GLuint shaderObj)
956 {
957 struct gl_shader *sh = _mesa_lookup_shader(ctx, shaderObj);
958
959 if (!sh) {
960 _mesa_error(ctx, GL_INVALID_VALUE, "glCompileShader(shaderObj)");
961 return;
962 }
963
964 sh->CompileStatus = _slang_compile(ctx, sh);
965 }
966
967
968 /**
969 * Called via ctx->Driver.LinkProgram()
970 */
971 void
972 _mesa_link_program(GLcontext *ctx, GLuint program)
973 {
974 struct gl_shader_program *shProg;
975
976 shProg = _mesa_lookup_shader_program(ctx, program);
977 if (!shProg) {
978 _mesa_error(ctx, GL_INVALID_VALUE, "glLinkProgram(program)");
979 return;
980 }
981
982 _slang_link(ctx, program, shProg);
983 }
984
985
986 /**
987 * Called via ctx->Driver.UseProgram()
988 */
989 void
990 _mesa_use_program(GLcontext *ctx, GLuint program)
991 {
992 struct gl_shader_program *shProg;
993
994 if (ctx->Shader.CurrentProgram &&
995 ctx->Shader.CurrentProgram->Name == program) {
996 /* no-op */
997 return;
998 }
999
1000 FLUSH_VERTICES(ctx, _NEW_PROGRAM);
1001
1002 if (program) {
1003 shProg = _mesa_lookup_shader_program(ctx, program);
1004 if (!shProg) {
1005 _mesa_error(ctx, GL_INVALID_VALUE,
1006 "glUseProgramObjectARB(programObj)");
1007 return;
1008 }
1009 }
1010 else {
1011 shProg = NULL;
1012 }
1013
1014 _mesa_reference_shader_program(ctx, &ctx->Shader.CurrentProgram, shProg);
1015 }
1016
1017
1018 /**
1019 * Called via ctx->Driver.Uniform().
1020 */
1021 void
1022 _mesa_uniform(GLcontext *ctx, GLint location, GLsizei count,
1023 const GLvoid *values, GLenum type)
1024 {
1025 struct gl_shader_program *shProg = ctx->Shader.CurrentProgram;
1026 GLint elems, i, k;
1027
1028 if (!shProg || !shProg->LinkStatus) {
1029 _mesa_error(ctx, GL_INVALID_OPERATION, "glUniform(program not linked)");
1030 return;
1031 }
1032
1033 if (location < 0 || location >= (GLint) shProg->Uniforms->NumParameters) {
1034 _mesa_error(ctx, GL_INVALID_VALUE, "glUniform(location)");
1035 return;
1036 }
1037
1038 FLUSH_VERTICES(ctx, _NEW_PROGRAM);
1039
1040 /*
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
1052 if (count < 0) {
1053 _mesa_error(ctx, GL_INVALID_VALUE, "glUniform(count < 0)");
1054 return;
1055 }
1056
1057 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;
1077 }
1078
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) {
1090 const GLint *iValues = ((const GLint *) values) + k * elems;
1091 for (i = 0; i < elems; i++) {
1092 uniformVal[i] = (GLfloat) iValues[i];
1093 }
1094 }
1095 else {
1096 const GLfloat *fValues = ((const GLfloat *) values) + k * elems;
1097 for (i = 0; i < elems; i++) {
1098 uniformVal[i] = fValues[i];
1099 }
1100 }
1101 }
1102
1103 if (shProg->Uniforms->Parameters[location].Type == PROGRAM_SAMPLER) {
1104 if (shProg->VertexProgram)
1105 _slang_resolve_samplers(shProg, &shProg->VertexProgram->Base);
1106 if (shProg->FragmentProgram)
1107 _slang_resolve_samplers(shProg, &shProg->FragmentProgram->Base);
1108 FLUSH_VERTICES(ctx, _NEW_TEXTURE);
1109 }
1110 }
1111
1112
1113 /**
1114 * Called by ctx->Driver.UniformMatrix().
1115 */
1116 void
1117 _mesa_uniform_matrix(GLcontext *ctx, GLint cols, GLint rows,
1118 GLenum matrixType, GLint location, GLsizei count,
1119 GLboolean transpose, const GLfloat *values)
1120 {
1121 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 }
1131 if (values == NULL) {
1132 _mesa_error(ctx, GL_INVALID_VALUE, "glUniformMatrix");
1133 return;
1134 }
1135
1136 FLUSH_VERTICES(ctx, _NEW_PROGRAM);
1137
1138 /*
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... */
1143 if (transpose) {
1144 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++) {
1148 v[row] = values[row * cols + col];
1149 }
1150 }
1151 }
1152 else {
1153 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++) {
1157 v[row] = values[col * rows + row];
1158 }
1159 }
1160 }
1161 }
1162
1163
1164 void
1165 _mesa_validate_program(GLcontext *ctx, GLuint program)
1166 {
1167 struct gl_shader_program *shProg;
1168 shProg = _mesa_lookup_shader_program(ctx, program);
1169 if (!shProg) {
1170 _mesa_error(ctx, GL_INVALID_VALUE, "glValidateProgram(program)");
1171 return;
1172 }
1173 /* XXX temporary */
1174 shProg->Validated = GL_TRUE;
1175
1176 /* 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 */
1189 }