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