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