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