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