Be more consistant with paths in #includes. Eventually, eliminate a bunch of -I...
[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 "shader/shader_api.h"
47 #include "shader/slang/slang_compile.h"
48 #include "shader/slang/slang_link.h"
49
50
51
52 /**
53 * Allocate a new gl_shader_program object, initialize it.
54 */
55 struct gl_shader_program *
56 _mesa_new_shader_program(GLcontext *ctx, GLuint name)
57 {
58 struct gl_shader_program *shProg;
59 shProg = CALLOC_STRUCT(gl_shader_program);
60 if (shProg) {
61 shProg->Type = GL_SHADER_PROGRAM_MESA;
62 shProg->Name = name;
63 shProg->RefCount = 1;
64 shProg->Attributes = _mesa_new_parameter_list();
65 }
66 return shProg;
67 }
68
69
70 /**
71 * Clear (free) the shader program state that gets produced by linking.
72 */
73 void
74 _mesa_clear_shader_program_data(GLcontext *ctx,
75 struct gl_shader_program *shProg)
76 {
77 if (shProg->VertexProgram) {
78 if (shProg->VertexProgram->Base.Parameters == shProg->Uniforms) {
79 /* to prevent a double-free in the next call */
80 shProg->VertexProgram->Base.Parameters = NULL;
81 }
82 _mesa_delete_program(ctx, &shProg->VertexProgram->Base);
83 shProg->VertexProgram = NULL;
84 }
85
86 if (shProg->FragmentProgram) {
87 if (shProg->FragmentProgram->Base.Parameters == shProg->Uniforms) {
88 /* to prevent a double-free in the next call */
89 shProg->FragmentProgram->Base.Parameters = NULL;
90 }
91 _mesa_delete_program(ctx, &shProg->FragmentProgram->Base);
92 shProg->FragmentProgram = NULL;
93 }
94
95 if (shProg->Uniforms) {
96 _mesa_free_parameter_list(shProg->Uniforms);
97 shProg->Uniforms = NULL;
98 }
99
100 if (shProg->Varying) {
101 _mesa_free_parameter_list(shProg->Varying);
102 shProg->Varying = NULL;
103 }
104 }
105
106
107 /**
108 * Free all the data that hangs off a shader program object, but not the
109 * object itself.
110 */
111 void
112 _mesa_free_shader_program_data(GLcontext *ctx,
113 struct gl_shader_program *shProg)
114 {
115 GLuint i;
116
117 assert(shProg->Type == GL_SHADER_PROGRAM_MESA);
118
119 _mesa_clear_shader_program_data(ctx, shProg);
120
121 if (shProg->Attributes) {
122 _mesa_free_parameter_list(shProg->Attributes);
123 shProg->Attributes = NULL;
124 }
125
126 /* detach shaders */
127 for (i = 0; i < shProg->NumShaders; i++) {
128 _mesa_reference_shader(ctx, &shProg->Shaders[i], NULL);
129 }
130 if (shProg->Shaders) {
131 _mesa_free(shProg->Shaders);
132 shProg->Shaders = NULL;
133 }
134 }
135
136
137 /**
138 * Free/delete a shader program object.
139 */
140 void
141 _mesa_free_shader_program(GLcontext *ctx, struct gl_shader_program *shProg)
142 {
143 _mesa_free_shader_program_data(ctx, shProg);
144 if (shProg->Shaders) {
145 _mesa_free(shProg->Shaders);
146 shProg->Shaders = NULL;
147 }
148 _mesa_free(shProg);
149 }
150
151
152 /**
153 * Set ptr to point to shProg.
154 * If ptr is pointing to another object, decrement its refcount (and delete
155 * if refcount hits zero).
156 * Then set ptr to point to shProg, incrementing its refcount.
157 */
158 /* XXX this could be static */
159 void
160 _mesa_reference_shader_program(GLcontext *ctx,
161 struct gl_shader_program **ptr,
162 struct gl_shader_program *shProg)
163 {
164 assert(ptr);
165 if (*ptr == shProg) {
166 /* no-op */
167 return;
168 }
169 if (*ptr) {
170 /* Unreference the old shader program */
171 GLboolean deleteFlag = GL_FALSE;
172 struct gl_shader_program *old = *ptr;
173
174 ASSERT(old->RefCount > 0);
175 old->RefCount--;
176 /*printf("SHPROG DECR %p (%d) to %d\n",
177 (void*) old, old->Name, old->RefCount);*/
178 deleteFlag = (old->RefCount == 0);
179
180 if (deleteFlag) {
181 _mesa_HashRemove(ctx->Shared->ShaderObjects, old->Name);
182 _mesa_free_shader_program(ctx, old);
183 }
184
185 *ptr = NULL;
186 }
187 assert(!*ptr);
188
189 if (shProg) {
190 shProg->RefCount++;
191 /*printf("SHPROG INCR %p (%d) to %d\n",
192 (void*) shProg, shProg->Name, shProg->RefCount);*/
193 *ptr = shProg;
194 }
195 }
196
197
198 /**
199 * Lookup a GLSL program object.
200 */
201 struct gl_shader_program *
202 _mesa_lookup_shader_program(GLcontext *ctx, GLuint name)
203 {
204 struct gl_shader_program *shProg;
205 if (name) {
206 shProg = (struct gl_shader_program *)
207 _mesa_HashLookup(ctx->Shared->ShaderObjects, name);
208 /* Note that both gl_shader and gl_shader_program objects are kept
209 * in the same hash table. Check the object's type to be sure it's
210 * what we're expecting.
211 */
212 if (shProg && shProg->Type != GL_SHADER_PROGRAM_MESA) {
213 return NULL;
214 }
215 return shProg;
216 }
217 return NULL;
218 }
219
220
221 /**
222 * Allocate a new gl_shader object, initialize it.
223 */
224 struct gl_shader *
225 _mesa_new_shader(GLcontext *ctx, GLuint name, GLenum type)
226 {
227 struct gl_shader *shader;
228 assert(type == GL_FRAGMENT_SHADER || type == GL_VERTEX_SHADER);
229 shader = CALLOC_STRUCT(gl_shader);
230 if (shader) {
231 shader->Type = type;
232 shader->Name = name;
233 shader->RefCount = 1;
234 }
235 return shader;
236 }
237
238
239 void
240 _mesa_free_shader(GLcontext *ctx, struct gl_shader *sh)
241 {
242 GLuint i;
243 if (sh->Source)
244 _mesa_free((void *) sh->Source);
245 if (sh->InfoLog)
246 _mesa_free(sh->InfoLog);
247 for (i = 0; i < sh->NumPrograms; i++) {
248 assert(sh->Programs[i]);
249 _mesa_delete_program(ctx, sh->Programs[i]);
250 }
251 if (sh->Programs)
252 _mesa_free(sh->Programs);
253 _mesa_free(sh);
254 }
255
256
257 /**
258 * Set ptr to point to sh.
259 * If ptr is pointing to another shader, decrement its refcount (and delete
260 * if refcount hits zero).
261 * Then set ptr to point to sh, incrementing its refcount.
262 */
263 /* XXX this could be static */
264 void
265 _mesa_reference_shader(GLcontext *ctx, struct gl_shader **ptr,
266 struct gl_shader *sh)
267 {
268 assert(ptr);
269 if (*ptr == sh) {
270 /* no-op */
271 return;
272 }
273 if (*ptr) {
274 /* Unreference the old shader */
275 GLboolean deleteFlag = GL_FALSE;
276 struct gl_shader *old = *ptr;
277
278 ASSERT(old->RefCount > 0);
279 old->RefCount--;
280 /*printf("SHADER DECR %p (%d) to %d\n",
281 (void*) old, old->Name, old->RefCount);*/
282 deleteFlag = (old->RefCount == 0);
283
284 if (deleteFlag) {
285 _mesa_HashRemove(ctx->Shared->ShaderObjects, old->Name);
286 _mesa_free_shader(ctx, old);
287 }
288
289 *ptr = NULL;
290 }
291 assert(!*ptr);
292
293 if (sh) {
294 /* reference new */
295 sh->RefCount++;
296 /*printf("SHADER INCR %p (%d) to %d\n",
297 (void*) sh, sh->Name, sh->RefCount);*/
298 *ptr = sh;
299 }
300 }
301
302
303 /**
304 * Lookup a GLSL shader object.
305 */
306 struct gl_shader *
307 _mesa_lookup_shader(GLcontext *ctx, GLuint name)
308 {
309 if (name) {
310 struct gl_shader *sh = (struct gl_shader *)
311 _mesa_HashLookup(ctx->Shared->ShaderObjects, name);
312 /* Note that both gl_shader and gl_shader_program objects are kept
313 * in the same hash table. Check the object's type to be sure it's
314 * what we're expecting.
315 */
316 if (sh && sh->Type == GL_SHADER_PROGRAM_MESA) {
317 return NULL;
318 }
319 return sh;
320 }
321 return NULL;
322 }
323
324
325 /**
326 * Initialize context's shader state.
327 */
328 void
329 _mesa_init_shader_state(GLcontext * ctx)
330 {
331 /* Device drivers may override these to control what kind of instructions
332 * are generated by the GLSL compiler.
333 */
334 ctx->Shader.EmitHighLevelInstructions = GL_TRUE;
335 ctx->Shader.EmitCondCodes = GL_TRUE; /* XXX probably want GL_FALSE... */
336 ctx->Shader.EmitComments = GL_FALSE;
337 }
338
339
340 /**
341 * Free the per-context shader-related state.
342 */
343 void
344 _mesa_free_shader_state(GLcontext *ctx)
345 {
346 _mesa_reference_shader_program(ctx, &ctx->Shader.CurrentProgram, NULL);
347 }
348
349
350 /**
351 * Copy string from <src> to <dst>, up to maxLength characters, returning
352 * length of <dst> in <length>.
353 * \param src the strings source
354 * \param maxLength max chars to copy
355 * \param length returns number of chars copied
356 * \param dst the string destination
357 */
358 static void
359 copy_string(GLchar *dst, GLsizei maxLength, GLsizei *length, const GLchar *src)
360 {
361 GLsizei len;
362 for (len = 0; len < maxLength - 1 && src && src[len]; len++)
363 dst[len] = src[len];
364 if (maxLength > 0)
365 dst[len] = 0;
366 if (length)
367 *length = len;
368 }
369
370
371 /**
372 * Called via ctx->Driver.AttachShader()
373 */
374 void
375 _mesa_attach_shader(GLcontext *ctx, GLuint program, GLuint shader)
376 {
377 struct gl_shader_program *shProg
378 = _mesa_lookup_shader_program(ctx, program);
379 struct gl_shader *sh = _mesa_lookup_shader(ctx, shader);
380 const GLuint n = shProg->NumShaders;
381 GLuint i;
382
383 if (!shProg || !sh) {
384 _mesa_error(ctx, GL_INVALID_VALUE,
385 "glAttachShader(bad program or shader name)");
386 return;
387 }
388
389 for (i = 0; i < n; i++) {
390 if (shProg->Shaders[i] == sh) {
391 /* already attached */
392 return;
393 }
394 }
395
396 /* grow list */
397 shProg->Shaders = (struct gl_shader **)
398 _mesa_realloc(shProg->Shaders,
399 n * sizeof(struct gl_shader *),
400 (n + 1) * sizeof(struct gl_shader *));
401 if (!shProg->Shaders) {
402 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glAttachShader");
403 return;
404 }
405
406 /* append */
407 shProg->Shaders[n] = NULL; /* since realloc() didn't zero the new space */
408 _mesa_reference_shader(ctx, &shProg->Shaders[n], sh);
409 shProg->NumShaders++;
410 }
411
412
413 void
414 _mesa_bind_attrib_location(GLcontext *ctx, GLuint program, GLuint index,
415 const GLchar *name)
416 {
417 struct gl_shader_program *shProg
418 = _mesa_lookup_shader_program(ctx, program);
419 const GLint size = -1; /* unknown size */
420 GLint i, oldIndex;
421
422 if (!shProg) {
423 _mesa_error(ctx, GL_INVALID_VALUE, "glBindAttribLocation(program)");
424 return;
425 }
426
427 if (!name)
428 return;
429
430 if (strncmp(name, "gl_", 3) == 0) {
431 _mesa_error(ctx, GL_INVALID_OPERATION,
432 "glBindAttribLocation(illegal name)");
433 return;
434 }
435
436 if (shProg->LinkStatus) {
437 /* get current index/location for the attribute */
438 oldIndex = _mesa_get_attrib_location(ctx, program, name);
439 }
440 else {
441 oldIndex = -1;
442 }
443
444 /* this will replace the current value if it's already in the list */
445 i = _mesa_add_attribute(shProg->Attributes, name, size, index);
446 if (i < 0) {
447 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBindAttribLocation");
448 }
449
450 if (shProg->VertexProgram && oldIndex >= 0 && oldIndex != index) {
451 /* If the index changed, need to search/replace references to that attribute
452 * in the vertex program.
453 */
454 _slang_remap_attribute(&shProg->VertexProgram->Base, oldIndex, index);
455 }
456 }
457
458
459 GLuint
460 _mesa_create_shader(GLcontext *ctx, GLenum type)
461 {
462 struct gl_shader *sh;
463 GLuint name;
464
465 name = _mesa_HashFindFreeKeyBlock(ctx->Shared->ShaderObjects, 1);
466
467 switch (type) {
468 case GL_FRAGMENT_SHADER:
469 case GL_VERTEX_SHADER:
470 sh = _mesa_new_shader(ctx, name, type);
471 break;
472 default:
473 _mesa_error(ctx, GL_INVALID_ENUM, "CreateShader(type)");
474 return 0;
475 }
476
477 _mesa_HashInsert(ctx->Shared->ShaderObjects, name, sh);
478
479 return name;
480 }
481
482
483 GLuint
484 _mesa_create_program(GLcontext *ctx)
485 {
486 GLuint name;
487 struct gl_shader_program *shProg;
488
489 name = _mesa_HashFindFreeKeyBlock(ctx->Shared->ShaderObjects, 1);
490 shProg = _mesa_new_shader_program(ctx, name);
491
492 _mesa_HashInsert(ctx->Shared->ShaderObjects, name, shProg);
493
494 assert(shProg->RefCount == 1);
495
496 return name;
497 }
498
499
500 /**
501 * Named w/ "2" to indicate OpenGL 2.x vs GL_ARB_fragment_programs's
502 * DeleteProgramARB.
503 */
504 void
505 _mesa_delete_program2(GLcontext *ctx, GLuint name)
506 {
507 /*
508 * NOTE: deleting shaders/programs works a bit differently than
509 * texture objects (and buffer objects, etc). Shader/program
510 * handles/IDs exist in the hash table until the object is really
511 * deleted (refcount==0). With texture objects, the handle/ID is
512 * removed from the hash table in glDeleteTextures() while the tex
513 * object itself might linger until its refcount goes to zero.
514 */
515 struct gl_shader_program *shProg;
516
517 shProg = _mesa_lookup_shader_program(ctx, name);
518 if (!shProg) {
519 _mesa_error(ctx, GL_INVALID_VALUE, "glDeleteProgram(name)");
520 return;
521 }
522
523 shProg->DeletePending = GL_TRUE;
524
525 /* effectively, decr shProg's refcount */
526 _mesa_reference_shader_program(ctx, &shProg, NULL);
527 }
528
529
530 void
531 _mesa_delete_shader(GLcontext *ctx, GLuint shader)
532 {
533 struct gl_shader *sh = _mesa_lookup_shader(ctx, shader);
534 if (!sh) {
535 return;
536 }
537
538 sh->DeletePending = GL_TRUE;
539
540 /* effectively, decr sh's refcount */
541 _mesa_reference_shader(ctx, &sh, NULL);
542 }
543
544
545 void
546 _mesa_detach_shader(GLcontext *ctx, GLuint program, GLuint shader)
547 {
548 struct gl_shader_program *shProg
549 = _mesa_lookup_shader_program(ctx, program);
550 const GLuint n = shProg->NumShaders;
551 GLuint i, j;
552
553 if (!shProg) {
554 _mesa_error(ctx, GL_INVALID_VALUE,
555 "glDetachShader(bad program or shader name)");
556 return;
557 }
558
559 for (i = 0; i < n; i++) {
560 if (shProg->Shaders[i]->Name == shader) {
561 /* found it */
562 struct gl_shader **newList;
563
564 /* derefernce */
565 _mesa_reference_shader(ctx, &shProg->Shaders[i], NULL);
566
567 /* alloc new, smaller array */
568 newList = (struct gl_shader **)
569 _mesa_malloc((n - 1) * sizeof(struct gl_shader *));
570 if (!newList) {
571 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glDetachShader");
572 return;
573 }
574 for (j = 0; j < i; j++) {
575 newList[j] = shProg->Shaders[j];
576 }
577 while (++i < n)
578 newList[j++] = shProg->Shaders[i];
579 _mesa_free(shProg->Shaders);
580
581 shProg->Shaders = newList;
582 shProg->NumShaders = n - 1;
583
584 #ifdef DEBUG
585 /* sanity check */
586 {
587 for (j = 0; j < shProg->NumShaders; j++) {
588 assert(shProg->Shaders[j]->Type == GL_VERTEX_SHADER ||
589 shProg->Shaders[j]->Type == GL_FRAGMENT_SHADER);
590 assert(shProg->Shaders[j]->RefCount > 0);
591 }
592 }
593 #endif
594
595 return;
596 }
597 }
598
599 /* not found */
600 _mesa_error(ctx, GL_INVALID_VALUE,
601 "glDetachShader(shader not found)");
602 }
603
604
605 void
606 _mesa_get_active_attrib(GLcontext *ctx, GLuint program, GLuint index,
607 GLsizei maxLength, GLsizei *length, GLint *size,
608 GLenum *type, GLchar *nameOut)
609 {
610 static const GLenum vec_types[] = {
611 GL_FLOAT, GL_FLOAT_VEC2, GL_FLOAT_VEC3, GL_FLOAT_VEC4
612 };
613 struct gl_shader_program *shProg
614 = _mesa_lookup_shader_program(ctx, program);
615 GLint sz;
616
617 if (!shProg) {
618 _mesa_error(ctx, GL_INVALID_VALUE, "glGetActiveAttrib");
619 return;
620 }
621
622 if (!shProg->Attributes || index >= shProg->Attributes->NumParameters) {
623 _mesa_error(ctx, GL_INVALID_VALUE, "glGetActiveAttrib(index)");
624 return;
625 }
626
627 copy_string(nameOut, maxLength, length,
628 shProg->Attributes->Parameters[index].Name);
629 sz = shProg->Attributes->Parameters[index].Size;
630 if (size)
631 *size = sz;
632 if (type)
633 *type = vec_types[sz]; /* XXX this is a temporary hack */
634 }
635
636
637 /**
638 * Called via ctx->Driver.GetActiveUniform().
639 */
640 void
641 _mesa_get_active_uniform(GLcontext *ctx, GLuint program, GLuint index,
642 GLsizei maxLength, GLsizei *length, GLint *size,
643 GLenum *type, GLchar *nameOut)
644 {
645 struct gl_shader_program *shProg
646 = _mesa_lookup_shader_program(ctx, program);
647 GLuint ind, j;
648
649 if (!shProg) {
650 _mesa_error(ctx, GL_INVALID_VALUE, "glGetActiveUniform");
651 return;
652 }
653
654 if (!shProg->Uniforms || index >= shProg->Uniforms->NumParameters) {
655 _mesa_error(ctx, GL_INVALID_VALUE, "glGetActiveUniform(index)");
656 return;
657 }
658
659 ind = 0;
660 for (j = 0; j < shProg->Uniforms->NumParameters; j++) {
661 if (shProg->Uniforms->Parameters[j].Type == PROGRAM_UNIFORM ||
662 shProg->Uniforms->Parameters[j].Type == PROGRAM_SAMPLER) {
663 if (ind == index) {
664 /* found it */
665 copy_string(nameOut, maxLength, length,
666 shProg->Uniforms->Parameters[j].Name);
667 if (size)
668 *size = shProg->Uniforms->Parameters[j].Size;
669 if (type)
670 *type = shProg->Uniforms->Parameters[j].DataType;
671 return;
672 }
673 ind++;
674 }
675 }
676
677 _mesa_error(ctx, GL_INVALID_VALUE, "glGetActiveUniform(index)");
678 }
679
680
681 /**
682 * Called via ctx->Driver.GetAttachedShaders().
683 */
684 void
685 _mesa_get_attached_shaders(GLcontext *ctx, GLuint program, GLsizei maxCount,
686 GLsizei *count, GLuint *obj)
687 {
688 struct gl_shader_program *shProg
689 = _mesa_lookup_shader_program(ctx, program);
690 if (shProg) {
691 GLint i;
692 for (i = 0; i < maxCount && i < shProg->NumShaders; i++) {
693 obj[i] = shProg->Shaders[i]->Name;
694 }
695 if (count)
696 *count = i;
697 }
698 else {
699 _mesa_error(ctx, GL_INVALID_VALUE, "glGetAttachedShaders");
700 }
701 }
702
703
704 GLint
705 _mesa_get_attrib_location(GLcontext *ctx, GLuint program,
706 const GLchar *name)
707 {
708 struct gl_shader_program *shProg
709 = _mesa_lookup_shader_program(ctx, program);
710
711 if (!shProg) {
712 _mesa_error(ctx, GL_INVALID_VALUE, "glGetAttribLocation");
713 return -1;
714 }
715
716 if (!shProg->LinkStatus) {
717 _mesa_error(ctx, GL_INVALID_OPERATION,
718 "glGetAttribLocation(program not linked)");
719 return -1;
720 }
721
722 if (!name)
723 return -1;
724
725 if (shProg->Attributes) {
726 GLint i = _mesa_lookup_parameter_index(shProg->Attributes, -1, name);
727 if (i >= 0) {
728 return shProg->Attributes->Parameters[i].StateIndexes[0];
729 }
730 }
731 return -1;
732 }
733
734
735 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 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) : 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
796 = _mesa_num_parameters_of_type(shProg->Uniforms, PROGRAM_UNIFORM)
797 + _mesa_num_parameters_of_type(shProg->Uniforms, PROGRAM_SAMPLER);
798 break;
799 case GL_ACTIVE_UNIFORM_MAX_LENGTH:
800 *params = MAX2(
801 _mesa_longest_parameter_name(shProg->Uniforms, PROGRAM_UNIFORM),
802 _mesa_longest_parameter_name(shProg->Uniforms, PROGRAM_SAMPLER));
803 if (*params > 0)
804 (*params)++; /* add one for terminating zero */
805 break;
806 default:
807 _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramiv(pname)");
808 return;
809 }
810 }
811
812
813 void
814 _mesa_get_shaderiv(GLcontext *ctx, GLuint name, GLenum pname, GLint *params)
815 {
816 struct gl_shader *shader = _mesa_lookup_shader(ctx, name);
817
818 if (!shader) {
819 _mesa_error(ctx, GL_INVALID_VALUE, "glGetShaderiv(shader)");
820 return;
821 }
822
823 switch (pname) {
824 case GL_SHADER_TYPE:
825 *params = shader->Type;
826 break;
827 case GL_DELETE_STATUS:
828 *params = shader->DeletePending;
829 break;
830 case GL_COMPILE_STATUS:
831 *params = shader->CompileStatus;
832 break;
833 case GL_INFO_LOG_LENGTH:
834 *params = shader->InfoLog ? strlen(shader->InfoLog) : 0;
835 break;
836 case GL_SHADER_SOURCE_LENGTH:
837 *params = shader->Source ? strlen((char *) shader->Source) : 0;
838 break;
839 default:
840 _mesa_error(ctx, GL_INVALID_ENUM, "glGetShaderiv(pname)");
841 return;
842 }
843 }
844
845
846 void
847 _mesa_get_program_info_log(GLcontext *ctx, GLuint program, GLsizei bufSize,
848 GLsizei *length, GLchar *infoLog)
849 {
850 struct gl_shader_program *shProg
851 = _mesa_lookup_shader_program(ctx, program);
852 if (!shProg) {
853 _mesa_error(ctx, GL_INVALID_VALUE, "glGetProgramInfoLog(program)");
854 return;
855 }
856 copy_string(infoLog, bufSize, length, shProg->InfoLog);
857 }
858
859
860 void
861 _mesa_get_shader_info_log(GLcontext *ctx, GLuint shader, GLsizei bufSize,
862 GLsizei *length, GLchar *infoLog)
863 {
864 struct gl_shader *sh = _mesa_lookup_shader(ctx, shader);
865 if (!sh) {
866 _mesa_error(ctx, GL_INVALID_VALUE, "glGetShaderInfoLog(shader)");
867 return;
868 }
869 copy_string(infoLog, bufSize, length, sh->InfoLog);
870 }
871
872
873 /**
874 * Called via ctx->Driver.GetShaderSource().
875 */
876 void
877 _mesa_get_shader_source(GLcontext *ctx, GLuint shader, GLsizei maxLength,
878 GLsizei *length, GLchar *sourceOut)
879 {
880 struct gl_shader *sh = _mesa_lookup_shader(ctx, shader);
881 if (!sh) {
882 _mesa_error(ctx, GL_INVALID_VALUE, "glGetShaderSource(shader)");
883 return;
884 }
885 copy_string(sourceOut, maxLength, length, sh->Source);
886 }
887
888
889 /**
890 * Called via ctx->Driver.GetUniformfv().
891 */
892 void
893 _mesa_get_uniformfv(GLcontext *ctx, GLuint program, GLint location,
894 GLfloat *params)
895 {
896 struct gl_shader_program *shProg
897 = _mesa_lookup_shader_program(ctx, program);
898 if (shProg) {
899 GLint i;
900 if (location >= 0 && location < shProg->Uniforms->NumParameters) {
901 for (i = 0; i < shProg->Uniforms->Parameters[location].Size; i++) {
902 params[i] = shProg->Uniforms->ParameterValues[location][i];
903 }
904 }
905 else {
906 _mesa_error(ctx, GL_INVALID_VALUE, "glGetUniformfv(location)");
907 }
908 }
909 else {
910 _mesa_error(ctx, GL_INVALID_VALUE, "glGetUniformfv(program)");
911 }
912 }
913
914
915 /**
916 * Called via ctx->Driver.GetUniformLocation().
917 */
918 GLint
919 _mesa_get_uniform_location(GLcontext *ctx, GLuint program, const GLchar *name)
920 {
921 struct gl_shader_program *shProg
922 = _mesa_lookup_shader_program(ctx, program);
923 if (shProg) {
924 GLuint loc;
925 for (loc = 0; loc < shProg->Uniforms->NumParameters; loc++) {
926 const struct gl_program_parameter *u
927 = shProg->Uniforms->Parameters + loc;
928 /* XXX this is a temporary simplification / short-cut.
929 * We need to handle things like "e.c[0].b" as seen in the
930 * GLSL orange book, page 189.
931 */
932 if ((u->Type == PROGRAM_UNIFORM ||
933 u->Type == PROGRAM_SAMPLER) && !strcmp(u->Name, name)) {
934 return loc;
935 }
936 }
937 }
938 return -1;
939
940 }
941
942
943 GLboolean
944 _mesa_is_program(GLcontext *ctx, GLuint name)
945 {
946 struct gl_shader_program *shProg = _mesa_lookup_shader_program(ctx, name);
947 return shProg ? GL_TRUE : GL_FALSE;
948 }
949
950
951 GLboolean
952 _mesa_is_shader(GLcontext *ctx, GLuint name)
953 {
954 struct gl_shader *shader = _mesa_lookup_shader(ctx, name);
955 return shader ? GL_TRUE : GL_FALSE;
956 }
957
958
959
960 /**
961 * Called via ctx->Driver.ShaderSource()
962 */
963 void
964 _mesa_shader_source(GLcontext *ctx, GLuint shader, const GLchar *source)
965 {
966 struct gl_shader *sh = _mesa_lookup_shader(ctx, shader);
967 if (!sh) {
968 _mesa_error(ctx, GL_INVALID_VALUE, "glShaderSource(shaderObj)");
969 return;
970 }
971
972 /* free old shader source string and install new one */
973 if (sh->Source) {
974 _mesa_free((void *) sh->Source);
975 }
976 sh->Source = source;
977 sh->CompileStatus = GL_FALSE;
978 }
979
980
981 /**
982 * Called via ctx->Driver.CompileShader()
983 */
984 void
985 _mesa_compile_shader(GLcontext *ctx, GLuint shaderObj)
986 {
987 struct gl_shader *sh = _mesa_lookup_shader(ctx, shaderObj);
988
989 if (!sh) {
990 _mesa_error(ctx, GL_INVALID_VALUE, "glCompileShader(shaderObj)");
991 return;
992 }
993
994 sh->CompileStatus = _slang_compile(ctx, sh);
995 }
996
997
998 /**
999 * Called via ctx->Driver.LinkProgram()
1000 */
1001 void
1002 _mesa_link_program(GLcontext *ctx, GLuint program)
1003 {
1004 struct gl_shader_program *shProg;
1005
1006 shProg = _mesa_lookup_shader_program(ctx, program);
1007 if (!shProg) {
1008 _mesa_error(ctx, GL_INVALID_VALUE, "glLinkProgram(program)");
1009 return;
1010 }
1011
1012 _slang_link(ctx, program, shProg);
1013 }
1014
1015
1016 /**
1017 * Called via ctx->Driver.UseProgram()
1018 */
1019 void
1020 _mesa_use_program(GLcontext *ctx, GLuint program)
1021 {
1022 struct gl_shader_program *shProg;
1023
1024 if (ctx->Shader.CurrentProgram &&
1025 ctx->Shader.CurrentProgram->Name == program) {
1026 /* no-op */
1027 return;
1028 }
1029
1030 FLUSH_VERTICES(ctx, _NEW_PROGRAM);
1031
1032 if (program) {
1033 shProg = _mesa_lookup_shader_program(ctx, program);
1034 if (!shProg) {
1035 _mesa_error(ctx, GL_INVALID_VALUE,
1036 "glUseProgramObjectARB(programObj)");
1037 return;
1038 }
1039 }
1040 else {
1041 shProg = NULL;
1042 }
1043
1044 _mesa_reference_shader_program(ctx, &ctx->Shader.CurrentProgram, shProg);
1045 }
1046
1047
1048 /**
1049 * Called via ctx->Driver.Uniform().
1050 */
1051 void
1052 _mesa_uniform(GLcontext *ctx, GLint location, GLsizei count,
1053 const GLvoid *values, GLenum type)
1054 {
1055 struct gl_shader_program *shProg = ctx->Shader.CurrentProgram;
1056 GLint elems, i, k;
1057
1058 if (!shProg || !shProg->LinkStatus) {
1059 _mesa_error(ctx, GL_INVALID_OPERATION, "glUniform(program not linked)");
1060 return;
1061 }
1062
1063 if (location < 0 || location >= (GLint) shProg->Uniforms->NumParameters) {
1064 _mesa_error(ctx, GL_INVALID_VALUE, "glUniform(location)");
1065 return;
1066 }
1067
1068 FLUSH_VERTICES(ctx, _NEW_PROGRAM);
1069
1070 /*
1071 * If we're setting a sampler, we must use glUniformi1()!
1072 */
1073 if (shProg->Uniforms->Parameters[location].Type == PROGRAM_SAMPLER) {
1074 GLint unit;
1075 if (type != GL_INT || count != 1) {
1076 _mesa_error(ctx, GL_INVALID_OPERATION,
1077 "glUniform(only glUniform1i can be used "
1078 "to set sampler uniforms)");
1079 return;
1080 }
1081 /* check that the sampler (tex unit index) is legal */
1082 unit = ((GLint *) values)[0];
1083 if (unit >= ctx->Const.MaxTextureImageUnits) {
1084 _mesa_error(ctx, GL_INVALID_VALUE,
1085 "glUniform1(invalid sampler/tex unit index)");
1086 return;
1087 }
1088 }
1089
1090 if (count < 0) {
1091 _mesa_error(ctx, GL_INVALID_VALUE, "glUniform(count < 0)");
1092 return;
1093 }
1094
1095 switch (type) {
1096 case GL_FLOAT:
1097 case GL_INT:
1098 elems = 1;
1099 break;
1100 case GL_FLOAT_VEC2:
1101 case GL_INT_VEC2:
1102 elems = 2;
1103 break;
1104 case GL_FLOAT_VEC3:
1105 case GL_INT_VEC3:
1106 elems = 3;
1107 break;
1108 case GL_FLOAT_VEC4:
1109 case GL_INT_VEC4:
1110 elems = 4;
1111 break;
1112 default:
1113 _mesa_problem(ctx, "Invalid type in _mesa_uniform");
1114 return;
1115 }
1116
1117 if (count * elems > shProg->Uniforms->Parameters[location].Size) {
1118 _mesa_error(ctx, GL_INVALID_OPERATION, "glUniform(count too large)");
1119 return;
1120 }
1121
1122 for (k = 0; k < count; k++) {
1123 GLfloat *uniformVal = shProg->Uniforms->ParameterValues[location + k];
1124 if (type == GL_INT ||
1125 type == GL_INT_VEC2 ||
1126 type == GL_INT_VEC3 ||
1127 type == GL_INT_VEC4) {
1128 const GLint *iValues = ((const GLint *) values) + k * elems;
1129 for (i = 0; i < elems; i++) {
1130 uniformVal[i] = (GLfloat) iValues[i];
1131 }
1132 }
1133 else {
1134 const GLfloat *fValues = ((const GLfloat *) values) + k * elems;
1135 for (i = 0; i < elems; i++) {
1136 uniformVal[i] = fValues[i];
1137 }
1138 }
1139 }
1140
1141 if (shProg->Uniforms->Parameters[location].Type == PROGRAM_SAMPLER) {
1142 if (shProg->VertexProgram)
1143 _slang_resolve_samplers(shProg, &shProg->VertexProgram->Base);
1144 if (shProg->FragmentProgram)
1145 _slang_resolve_samplers(shProg, &shProg->FragmentProgram->Base);
1146 FLUSH_VERTICES(ctx, _NEW_TEXTURE);
1147 }
1148 }
1149
1150
1151 /**
1152 * Called by ctx->Driver.UniformMatrix().
1153 */
1154 void
1155 _mesa_uniform_matrix(GLcontext *ctx, GLint cols, GLint rows,
1156 GLenum matrixType, GLint location, GLsizei count,
1157 GLboolean transpose, const GLfloat *values)
1158 {
1159 struct gl_shader_program *shProg = ctx->Shader.CurrentProgram;
1160 if (!shProg || !shProg->LinkStatus) {
1161 _mesa_error(ctx, GL_INVALID_OPERATION,
1162 "glUniformMatrix(program not linked)");
1163 return;
1164 }
1165 if (location < 0 || location >= shProg->Uniforms->NumParameters) {
1166 _mesa_error(ctx, GL_INVALID_VALUE, "glUniformMatrix(location)");
1167 return;
1168 }
1169 if (values == NULL) {
1170 _mesa_error(ctx, GL_INVALID_VALUE, "glUniformMatrix");
1171 return;
1172 }
1173
1174 FLUSH_VERTICES(ctx, _NEW_PROGRAM);
1175
1176 /*
1177 * Note: the _columns_ of a matrix are stored in program registers, not
1178 * the rows.
1179 */
1180 /* XXXX need to test 3x3 and 2x2 matrices... */
1181 if (transpose) {
1182 GLuint row, col;
1183 for (col = 0; col < cols; col++) {
1184 GLfloat *v = shProg->Uniforms->ParameterValues[location + col];
1185 for (row = 0; row < rows; row++) {
1186 v[row] = values[row * cols + col];
1187 }
1188 }
1189 }
1190 else {
1191 GLuint row, col;
1192 for (col = 0; col < cols; col++) {
1193 GLfloat *v = shProg->Uniforms->ParameterValues[location + col];
1194 for (row = 0; row < rows; row++) {
1195 v[row] = values[col * rows + row];
1196 }
1197 }
1198 }
1199 }
1200
1201
1202 void
1203 _mesa_validate_program(GLcontext *ctx, GLuint program)
1204 {
1205 struct gl_shader_program *shProg;
1206 shProg = _mesa_lookup_shader_program(ctx, program);
1207 if (!shProg) {
1208 _mesa_error(ctx, GL_INVALID_VALUE, "glValidateProgram(program)");
1209 return;
1210 }
1211 /* XXX temporary */
1212 shProg->Validated = GL_TRUE;
1213
1214 /* From the GL spec:
1215 any two active samplers in the current program object are of
1216 different types, but refer to the same texture image unit,
1217
1218 any active sampler in the current program object refers to a texture
1219 image unit where fixed-function fragment processing accesses a
1220 texture target that does not match the sampler type, or
1221
1222 the sum of the number of active samplers in the program and the
1223 number of texture image units enabled for fixed-function fragment
1224 processing exceeds the combined limit on the total number of texture
1225 image units allowed.
1226 */
1227 }