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