a005c902e1922bdca6337511716ebe82fb5e1c3a
[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 GLuint n;
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 n = shProg->NumShaders;
382
383 for (i = 0; i < n; i++) {
384 if (shProg->Shaders[i] == sh) {
385 /* already attached */
386 return;
387 }
388 }
389
390 /* grow list */
391 shProg->Shaders = (struct gl_shader **)
392 _mesa_realloc(shProg->Shaders,
393 n * sizeof(struct gl_shader *),
394 (n + 1) * sizeof(struct gl_shader *));
395 if (!shProg->Shaders) {
396 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glAttachShader");
397 return;
398 }
399
400 /* append */
401 shProg->Shaders[n] = NULL; /* since realloc() didn't zero the new space */
402 _mesa_reference_shader(ctx, &shProg->Shaders[n], sh);
403 shProg->NumShaders++;
404 }
405
406
407 static GLint
408 _mesa_get_attrib_location(GLcontext *ctx, GLuint program,
409 const GLchar *name)
410 {
411 struct gl_shader_program *shProg
412 = _mesa_lookup_shader_program(ctx, program);
413
414 if (!shProg) {
415 _mesa_error(ctx, GL_INVALID_VALUE, "glGetAttribLocation");
416 return -1;
417 }
418
419 if (!shProg->LinkStatus) {
420 _mesa_error(ctx, GL_INVALID_OPERATION,
421 "glGetAttribLocation(program not linked)");
422 return -1;
423 }
424
425 if (!name)
426 return -1;
427
428 if (shProg->Attributes) {
429 GLint i = _mesa_lookup_parameter_index(shProg->Attributes, -1, name);
430 if (i >= 0) {
431 return shProg->Attributes->Parameters[i].StateIndexes[0];
432 }
433 }
434 return -1;
435 }
436
437
438 static void
439 _mesa_bind_attrib_location(GLcontext *ctx, GLuint program, GLuint index,
440 const GLchar *name)
441 {
442 struct gl_shader_program *shProg
443 = _mesa_lookup_shader_program(ctx, program);
444 const GLint size = -1; /* unknown size */
445 GLint i, oldIndex;
446
447 if (!shProg) {
448 _mesa_error(ctx, GL_INVALID_VALUE, "glBindAttribLocation(program)");
449 return;
450 }
451
452 if (!name)
453 return;
454
455 if (strncmp(name, "gl_", 3) == 0) {
456 _mesa_error(ctx, GL_INVALID_OPERATION,
457 "glBindAttribLocation(illegal name)");
458 return;
459 }
460
461 if (shProg->LinkStatus) {
462 /* get current index/location for the attribute */
463 oldIndex = _mesa_get_attrib_location(ctx, program, name);
464 }
465 else {
466 oldIndex = -1;
467 }
468
469 /* this will replace the current value if it's already in the list */
470 i = _mesa_add_attribute(shProg->Attributes, name, size, index);
471 if (i < 0) {
472 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBindAttribLocation");
473 }
474
475 if (shProg->VertexProgram && oldIndex >= 0 && oldIndex != index) {
476 /* If the index changed, need to search/replace references to that attribute
477 * in the vertex program.
478 */
479 _slang_remap_attribute(&shProg->VertexProgram->Base, oldIndex, index);
480 }
481 }
482
483
484 static GLuint
485 _mesa_create_shader(GLcontext *ctx, GLenum type)
486 {
487 struct gl_shader *sh;
488 GLuint name;
489
490 name = _mesa_HashFindFreeKeyBlock(ctx->Shared->ShaderObjects, 1);
491
492 switch (type) {
493 case GL_FRAGMENT_SHADER:
494 case GL_VERTEX_SHADER:
495 sh = _mesa_new_shader(ctx, name, type);
496 break;
497 default:
498 _mesa_error(ctx, GL_INVALID_ENUM, "CreateShader(type)");
499 return 0;
500 }
501
502 _mesa_HashInsert(ctx->Shared->ShaderObjects, name, sh);
503
504 return name;
505 }
506
507
508 static GLuint
509 _mesa_create_program(GLcontext *ctx)
510 {
511 GLuint name;
512 struct gl_shader_program *shProg;
513
514 name = _mesa_HashFindFreeKeyBlock(ctx->Shared->ShaderObjects, 1);
515 shProg = _mesa_new_shader_program(ctx, name);
516
517 _mesa_HashInsert(ctx->Shared->ShaderObjects, name, shProg);
518
519 assert(shProg->RefCount == 1);
520
521 return name;
522 }
523
524
525 /**
526 * Named w/ "2" to indicate OpenGL 2.x vs GL_ARB_fragment_programs's
527 * DeleteProgramARB.
528 */
529 static void
530 _mesa_delete_program2(GLcontext *ctx, GLuint name)
531 {
532 /*
533 * NOTE: deleting shaders/programs works a bit differently than
534 * texture objects (and buffer objects, etc). Shader/program
535 * handles/IDs exist in the hash table until the object is really
536 * deleted (refcount==0). With texture objects, the handle/ID is
537 * removed from the hash table in glDeleteTextures() while the tex
538 * object itself might linger until its refcount goes to zero.
539 */
540 struct gl_shader_program *shProg;
541
542 shProg = _mesa_lookup_shader_program(ctx, name);
543 if (!shProg) {
544 _mesa_error(ctx, GL_INVALID_VALUE, "glDeleteProgram(name)");
545 return;
546 }
547
548 shProg->DeletePending = GL_TRUE;
549
550 /* effectively, decr shProg's refcount */
551 _mesa_reference_shader_program(ctx, &shProg, NULL);
552 }
553
554
555 static void
556 _mesa_delete_shader(GLcontext *ctx, GLuint shader)
557 {
558 struct gl_shader *sh = _mesa_lookup_shader(ctx, shader);
559 if (!sh) {
560 return;
561 }
562
563 sh->DeletePending = GL_TRUE;
564
565 /* effectively, decr sh's refcount */
566 _mesa_reference_shader(ctx, &sh, NULL);
567 }
568
569
570 static void
571 _mesa_detach_shader(GLcontext *ctx, GLuint program, GLuint shader)
572 {
573 struct gl_shader_program *shProg
574 = _mesa_lookup_shader_program(ctx, program);
575 GLuint n;
576 GLuint i, j;
577
578 if (!shProg) {
579 _mesa_error(ctx, GL_INVALID_VALUE,
580 "glDetachShader(bad program or shader name)");
581 return;
582 }
583
584 n = shProg->NumShaders;
585
586 for (i = 0; i < n; i++) {
587 if (shProg->Shaders[i]->Name == shader) {
588 /* found it */
589 struct gl_shader **newList;
590
591 /* derefernce */
592 _mesa_reference_shader(ctx, &shProg->Shaders[i], NULL);
593
594 /* alloc new, smaller array */
595 newList = (struct gl_shader **)
596 _mesa_malloc((n - 1) * sizeof(struct gl_shader *));
597 if (!newList) {
598 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glDetachShader");
599 return;
600 }
601 for (j = 0; j < i; j++) {
602 newList[j] = shProg->Shaders[j];
603 }
604 while (++i < n)
605 newList[j++] = shProg->Shaders[i];
606 _mesa_free(shProg->Shaders);
607
608 shProg->Shaders = newList;
609 shProg->NumShaders = n - 1;
610
611 #ifdef DEBUG
612 /* sanity check */
613 {
614 for (j = 0; j < shProg->NumShaders; j++) {
615 assert(shProg->Shaders[j]->Type == GL_VERTEX_SHADER ||
616 shProg->Shaders[j]->Type == GL_FRAGMENT_SHADER);
617 assert(shProg->Shaders[j]->RefCount > 0);
618 }
619 }
620 #endif
621
622 return;
623 }
624 }
625
626 /* not found */
627 _mesa_error(ctx, GL_INVALID_VALUE,
628 "glDetachShader(shader not found)");
629 }
630
631
632 static void
633 _mesa_get_active_attrib(GLcontext *ctx, GLuint program, GLuint index,
634 GLsizei maxLength, GLsizei *length, GLint *size,
635 GLenum *type, GLchar *nameOut)
636 {
637 static const GLenum vec_types[] = {
638 GL_FLOAT, GL_FLOAT_VEC2, GL_FLOAT_VEC3, GL_FLOAT_VEC4
639 };
640 struct gl_shader_program *shProg
641 = _mesa_lookup_shader_program(ctx, program);
642 GLint sz;
643
644 if (!shProg) {
645 _mesa_error(ctx, GL_INVALID_VALUE, "glGetActiveAttrib");
646 return;
647 }
648
649 if (!shProg->Attributes || index >= shProg->Attributes->NumParameters) {
650 _mesa_error(ctx, GL_INVALID_VALUE, "glGetActiveAttrib(index)");
651 return;
652 }
653
654 copy_string(nameOut, maxLength, length,
655 shProg->Attributes->Parameters[index].Name);
656 sz = shProg->Attributes->Parameters[index].Size;
657 if (size)
658 *size = sz;
659 if (type)
660 *type = vec_types[sz]; /* XXX this is a temporary hack */
661 }
662
663
664 /**
665 * Called via ctx->Driver.GetActiveUniform().
666 */
667 static void
668 _mesa_get_active_uniform(GLcontext *ctx, GLuint program, GLuint index,
669 GLsizei maxLength, GLsizei *length, GLint *size,
670 GLenum *type, GLchar *nameOut)
671 {
672 const struct gl_shader_program *shProg
673 = _mesa_lookup_shader_program(ctx, program);
674 const struct gl_program *prog;
675 GLint progPos;
676
677 if (!shProg) {
678 _mesa_error(ctx, GL_INVALID_VALUE, "glGetActiveUniform");
679 return;
680 }
681
682 if (!shProg->Uniforms || index >= shProg->Uniforms->NumUniforms) {
683 _mesa_error(ctx, GL_INVALID_VALUE, "glGetActiveUniform(index)");
684 return;
685 }
686
687 progPos = shProg->Uniforms->Uniforms[index].VertPos;
688 if (progPos >= 0) {
689 prog = &shProg->VertexProgram->Base;
690 }
691 else {
692 progPos = shProg->Uniforms->Uniforms[index].FragPos;
693 if (progPos >= 0) {
694 prog = &shProg->FragmentProgram->Base;
695 }
696 }
697
698 if (!prog || progPos < 0)
699 return; /* should never happen */
700
701 if (nameOut)
702 copy_string(nameOut, maxLength, length,
703 prog->Parameters->Parameters[progPos].Name);
704 if (size)
705 *size = prog->Parameters->Parameters[progPos].Size;
706
707 if (type)
708 *type = prog->Parameters->Parameters[progPos].DataType;
709 }
710
711
712 /**
713 * Called via ctx->Driver.GetAttachedShaders().
714 */
715 static void
716 _mesa_get_attached_shaders(GLcontext *ctx, GLuint program, GLsizei maxCount,
717 GLsizei *count, GLuint *obj)
718 {
719 struct gl_shader_program *shProg
720 = _mesa_lookup_shader_program(ctx, program);
721 if (shProg) {
722 GLuint i;
723 for (i = 0; i < maxCount && i < shProg->NumShaders; i++) {
724 obj[i] = shProg->Shaders[i]->Name;
725 }
726 if (count)
727 *count = i;
728 }
729 else {
730 _mesa_error(ctx, GL_INVALID_VALUE, "glGetAttachedShaders");
731 }
732 }
733
734
735 static GLuint
736 _mesa_get_handle(GLcontext *ctx, GLenum pname)
737 {
738 #if 0
739 GET_CURRENT_CONTEXT(ctx);
740
741 switch (pname) {
742 case GL_PROGRAM_OBJECT_ARB:
743 {
744 struct gl2_program_intf **pro = ctx->Shader.CurrentProgram;
745
746 if (pro != NULL)
747 return (**pro)._container._generic.
748 GetName((struct gl2_generic_intf **) (pro));
749 }
750 break;
751 default:
752 _mesa_error(ctx, GL_INVALID_ENUM, "glGetHandleARB");
753 }
754 #endif
755 return 0;
756 }
757
758
759 static void
760 _mesa_get_programiv(GLcontext *ctx, GLuint program,
761 GLenum pname, GLint *params)
762 {
763 struct gl_shader_program *shProg
764 = _mesa_lookup_shader_program(ctx, program);
765
766 if (!shProg) {
767 _mesa_error(ctx, GL_INVALID_VALUE, "glGetProgramiv(program)");
768 return;
769 }
770
771 switch (pname) {
772 case GL_DELETE_STATUS:
773 *params = shProg->DeletePending;
774 break;
775 case GL_LINK_STATUS:
776 *params = shProg->LinkStatus;
777 break;
778 case GL_VALIDATE_STATUS:
779 *params = shProg->Validated;
780 break;
781 case GL_INFO_LOG_LENGTH:
782 *params = shProg->InfoLog ? strlen(shProg->InfoLog) + 1 : 0;
783 break;
784 case GL_ATTACHED_SHADERS:
785 *params = shProg->NumShaders;
786 break;
787 case GL_ACTIVE_ATTRIBUTES:
788 *params = shProg->Attributes ? shProg->Attributes->NumParameters : 0;
789 break;
790 case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH:
791 *params = _mesa_longest_parameter_name(shProg->Attributes,
792 PROGRAM_INPUT) + 1;
793 break;
794 case GL_ACTIVE_UNIFORMS:
795 *params = shProg->Uniforms ? shProg->Uniforms->NumUniforms : 0;
796 break;
797 case GL_ACTIVE_UNIFORM_MAX_LENGTH:
798 *params = _mesa_longest_uniform_name(shProg->Uniforms);
799 if (*params > 0)
800 (*params)++; /* add one for terminating zero */
801 break;
802 default:
803 _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramiv(pname)");
804 return;
805 }
806 }
807
808
809 static void
810 _mesa_get_shaderiv(GLcontext *ctx, GLuint name, GLenum pname, GLint *params)
811 {
812 struct gl_shader *shader = _mesa_lookup_shader(ctx, name);
813
814 if (!shader) {
815 _mesa_error(ctx, GL_INVALID_VALUE, "glGetShaderiv(shader)");
816 return;
817 }
818
819 switch (pname) {
820 case GL_SHADER_TYPE:
821 *params = shader->Type;
822 break;
823 case GL_DELETE_STATUS:
824 *params = shader->DeletePending;
825 break;
826 case GL_COMPILE_STATUS:
827 *params = shader->CompileStatus;
828 break;
829 case GL_INFO_LOG_LENGTH:
830 *params = shader->InfoLog ? strlen(shader->InfoLog) + 1 : 0;
831 break;
832 case GL_SHADER_SOURCE_LENGTH:
833 *params = shader->Source ? strlen((char *) shader->Source) + 1 : 0;
834 break;
835 default:
836 _mesa_error(ctx, GL_INVALID_ENUM, "glGetShaderiv(pname)");
837 return;
838 }
839 }
840
841
842 static void
843 _mesa_get_program_info_log(GLcontext *ctx, GLuint program, GLsizei bufSize,
844 GLsizei *length, GLchar *infoLog)
845 {
846 struct gl_shader_program *shProg
847 = _mesa_lookup_shader_program(ctx, program);
848 if (!shProg) {
849 _mesa_error(ctx, GL_INVALID_VALUE, "glGetProgramInfoLog(program)");
850 return;
851 }
852 copy_string(infoLog, bufSize, length, shProg->InfoLog);
853 }
854
855
856 static void
857 _mesa_get_shader_info_log(GLcontext *ctx, GLuint shader, GLsizei bufSize,
858 GLsizei *length, GLchar *infoLog)
859 {
860 struct gl_shader *sh = _mesa_lookup_shader(ctx, shader);
861 if (!sh) {
862 _mesa_error(ctx, GL_INVALID_VALUE, "glGetShaderInfoLog(shader)");
863 return;
864 }
865 copy_string(infoLog, bufSize, length, sh->InfoLog);
866 }
867
868
869 /**
870 * Called via ctx->Driver.GetShaderSource().
871 */
872 static void
873 _mesa_get_shader_source(GLcontext *ctx, GLuint shader, GLsizei maxLength,
874 GLsizei *length, GLchar *sourceOut)
875 {
876 struct gl_shader *sh = _mesa_lookup_shader(ctx, shader);
877 if (!sh) {
878 _mesa_error(ctx, GL_INVALID_VALUE, "glGetShaderSource(shader)");
879 return;
880 }
881 copy_string(sourceOut, maxLength, length, sh->Source);
882 }
883
884
885 /**
886 * Called via ctx->Driver.GetUniformfv().
887 */
888 static void
889 _mesa_get_uniformfv(GLcontext *ctx, GLuint program, GLint location,
890 GLfloat *params)
891 {
892 struct gl_shader_program *shProg
893 = _mesa_lookup_shader_program(ctx, program);
894 if (shProg) {
895 if (shProg->Uniforms &&
896 location >= 0 && location < shProg->Uniforms->NumUniforms) {
897 GLint progPos;
898 GLuint i;
899 const struct gl_program *prog = NULL;
900
901 progPos = shProg->Uniforms->Uniforms[location].VertPos;
902 if (progPos >= 0) {
903 prog = &shProg->VertexProgram->Base;
904 }
905 else {
906 progPos = shProg->Uniforms->Uniforms[location].FragPos;
907 if (progPos >= 0) {
908 prog = &shProg->FragmentProgram->Base;
909 }
910 }
911
912 ASSERT(prog);
913 if (prog) {
914 for (i = 0; i < prog->Parameters->Parameters[progPos].Size; i++) {
915 params[i] = prog->Parameters->ParameterValues[progPos][i];
916 }
917 }
918 }
919 else {
920 _mesa_error(ctx, GL_INVALID_OPERATION, "glGetUniformfv(location)");
921 }
922 }
923 else {
924 _mesa_error(ctx, GL_INVALID_OPERATION, "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, GLsizei 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 GLsizei 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 == -1)
1161 return; /* The standard specifies this as a no-op */
1162
1163
1164 if (location < 0 || location >= (GLint) shProg->Uniforms->NumUniforms) {
1165 _mesa_error(ctx, GL_INVALID_VALUE, "glUniform(location)");
1166 return;
1167 }
1168
1169 if (count < 0) {
1170 _mesa_error(ctx, GL_INVALID_VALUE, "glUniform(count < 0)");
1171 return;
1172 }
1173
1174 switch (type) {
1175 case GL_FLOAT:
1176 case GL_INT:
1177 elems = 1;
1178 break;
1179 case GL_FLOAT_VEC2:
1180 case GL_INT_VEC2:
1181 elems = 2;
1182 break;
1183 case GL_FLOAT_VEC3:
1184 case GL_INT_VEC3:
1185 elems = 3;
1186 break;
1187 case GL_FLOAT_VEC4:
1188 case GL_INT_VEC4:
1189 elems = 4;
1190 break;
1191 default:
1192 _mesa_problem(ctx, "Invalid type in _mesa_uniform");
1193 return;
1194 }
1195
1196 FLUSH_VERTICES(ctx, _NEW_PROGRAM);
1197
1198 /* A uniform var may be used by both a vertex shader and a fragment
1199 * shader. We may need to update one or both shader's uniform here:
1200 */
1201 if (shProg->VertexProgram) {
1202 GLint loc = shProg->Uniforms->Uniforms[location].VertPos;
1203 if (loc >= 0) {
1204 set_program_uniform(ctx, &shProg->VertexProgram->Base,
1205 loc, type, count, elems, values);
1206 }
1207 }
1208
1209 if (shProg->FragmentProgram) {
1210 GLint loc = shProg->Uniforms->Uniforms[location].FragPos;
1211 if (loc >= 0) {
1212 set_program_uniform(ctx, &shProg->FragmentProgram->Base,
1213 loc, type, count, elems, values);
1214 }
1215 }
1216 }
1217
1218
1219 static void
1220 set_program_uniform_matrix(GLcontext *ctx, struct gl_program *program,
1221 GLuint location, GLuint rows, GLuint cols,
1222 GLboolean transpose, const GLfloat *values)
1223 {
1224 /*
1225 * Note: the _columns_ of a matrix are stored in program registers, not
1226 * the rows.
1227 */
1228 /* XXXX need to test 3x3 and 2x2 matrices... */
1229 if (transpose) {
1230 GLuint row, col;
1231 for (col = 0; col < cols; col++) {
1232 GLfloat *v = program->Parameters->ParameterValues[location + col];
1233 for (row = 0; row < rows; row++) {
1234 v[row] = values[row * cols + col];
1235 }
1236 }
1237 }
1238 else {
1239 GLuint row, col;
1240 for (col = 0; col < cols; col++) {
1241 GLfloat *v = program->Parameters->ParameterValues[location + col];
1242 for (row = 0; row < rows; row++) {
1243 v[row] = values[col * rows + row];
1244 }
1245 }
1246 }
1247 }
1248
1249
1250 /**
1251 * Called by ctx->Driver.UniformMatrix().
1252 */
1253 static void
1254 _mesa_uniform_matrix(GLcontext *ctx, GLint cols, GLint rows,
1255 GLenum matrixType, GLint location, GLsizei count,
1256 GLboolean transpose, const GLfloat *values)
1257 {
1258 struct gl_shader_program *shProg = ctx->Shader.CurrentProgram;
1259
1260 if (!shProg || !shProg->LinkStatus) {
1261 _mesa_error(ctx, GL_INVALID_OPERATION,
1262 "glUniformMatrix(program not linked)");
1263 return;
1264 }
1265
1266 if (location == -1)
1267 return; /* The standard specifies this as a no-op */
1268
1269 if (location < 0 || location >= shProg->Uniforms->NumUniforms) {
1270 _mesa_error(ctx, GL_INVALID_VALUE, "glUniformMatrix(location)");
1271 return;
1272 }
1273 if (values == NULL) {
1274 _mesa_error(ctx, GL_INVALID_VALUE, "glUniformMatrix");
1275 return;
1276 }
1277
1278 FLUSH_VERTICES(ctx, _NEW_PROGRAM);
1279
1280 if (shProg->VertexProgram) {
1281 GLint loc = shProg->Uniforms->Uniforms[location].VertPos;
1282 if (loc >= 0) {
1283 set_program_uniform_matrix(ctx, &shProg->VertexProgram->Base,
1284 loc, rows, cols, transpose, values);
1285 }
1286 }
1287
1288 if (shProg->FragmentProgram) {
1289 GLint loc = shProg->Uniforms->Uniforms[location].FragPos;
1290 if (loc >= 0) {
1291 set_program_uniform_matrix(ctx, &shProg->FragmentProgram->Base,
1292 loc, rows, cols, transpose, values);
1293 }
1294 }
1295 }
1296
1297
1298 static void
1299 _mesa_validate_program(GLcontext *ctx, GLuint program)
1300 {
1301 struct gl_shader_program *shProg;
1302 shProg = _mesa_lookup_shader_program(ctx, program);
1303 if (!shProg) {
1304 _mesa_error(ctx, GL_INVALID_VALUE, "glValidateProgram(program)");
1305 return;
1306 }
1307 /* XXX temporary */
1308 shProg->Validated = GL_TRUE;
1309
1310 /* From the GL spec:
1311 any two active samplers in the current program object are of
1312 different types, but refer to the same texture image unit,
1313
1314 any active sampler in the current program object refers to a texture
1315 image unit where fixed-function fragment processing accesses a
1316 texture target that does not match the sampler type, or
1317
1318 the sum of the number of active samplers in the program and the
1319 number of texture image units enabled for fixed-function fragment
1320 processing exceeds the combined limit on the total number of texture
1321 image units allowed.
1322 */
1323 }
1324
1325
1326 /**
1327 * Plug in Mesa's GLSL functions into the device driver function table.
1328 */
1329 void
1330 _mesa_init_glsl_driver_functions(struct dd_function_table *driver)
1331 {
1332 driver->AttachShader = _mesa_attach_shader;
1333 driver->BindAttribLocation = _mesa_bind_attrib_location;
1334 driver->CompileShader = _mesa_compile_shader;
1335 driver->CreateProgram = _mesa_create_program;
1336 driver->CreateShader = _mesa_create_shader;
1337 driver->DeleteProgram2 = _mesa_delete_program2;
1338 driver->DeleteShader = _mesa_delete_shader;
1339 driver->DetachShader = _mesa_detach_shader;
1340 driver->GetActiveAttrib = _mesa_get_active_attrib;
1341 driver->GetActiveUniform = _mesa_get_active_uniform;
1342 driver->GetAttachedShaders = _mesa_get_attached_shaders;
1343 driver->GetAttribLocation = _mesa_get_attrib_location;
1344 driver->GetHandle = _mesa_get_handle;
1345 driver->GetProgramiv = _mesa_get_programiv;
1346 driver->GetProgramInfoLog = _mesa_get_program_info_log;
1347 driver->GetShaderiv = _mesa_get_shaderiv;
1348 driver->GetShaderInfoLog = _mesa_get_shader_info_log;
1349 driver->GetShaderSource = _mesa_get_shader_source;
1350 driver->GetUniformfv = _mesa_get_uniformfv;
1351 driver->GetUniformLocation = _mesa_get_uniform_location;
1352 driver->IsProgram = _mesa_is_program;
1353 driver->IsShader = _mesa_is_shader;
1354 driver->LinkProgram = _mesa_link_program;
1355 driver->ShaderSource = _mesa_shader_source;
1356 driver->Uniform = _mesa_uniform;
1357 driver->UniformMatrix = _mesa_uniform_matrix;
1358 driver->UseProgram = _mesa_use_program;
1359 driver->ValidateProgram = _mesa_validate_program;
1360 }