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