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