Merge branch 'gallium-0.1' into gallium-0.2
[mesa.git] / src / mesa / shader / shader_api.c
1 /*
2 * Mesa 3-D graphics library
3 * Version: 7.1
4 *
5 * Copyright (C) 2004-2008 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 "main/glheader.h"
39 #include "main/context.h"
40 #include "main/hash.h"
41 #include "main/macros.h"
42 #include "program.h"
43 #include "prog_parameter.h"
44 #include "prog_print.h"
45 #include "prog_statevars.h"
46 #include "prog_uniform.h"
47 #include "shader/shader_api.h"
48 #include "shader/slang/slang_compile.h"
49 #include "shader/slang/slang_link.h"
50
51
52
53 #ifndef GL_PROGRAM_BINARY_LENGTH_OES
54 #define GL_PROGRAM_BINARY_LENGTH_OES 0x8741
55 #endif
56
57
58 /**
59 * Allocate a new gl_shader_program object, initialize it.
60 */
61 static struct gl_shader_program *
62 _mesa_new_shader_program(GLcontext *ctx, GLuint name)
63 {
64 struct gl_shader_program *shProg;
65 shProg = CALLOC_STRUCT(gl_shader_program);
66 if (shProg) {
67 shProg->Type = GL_SHADER_PROGRAM_MESA;
68 shProg->Name = name;
69 shProg->RefCount = 1;
70 shProg->Attributes = _mesa_new_parameter_list();
71 }
72 return shProg;
73 }
74
75
76 /**
77 * Clear (free) the shader program state that gets produced by linking.
78 */
79 void
80 _mesa_clear_shader_program_data(GLcontext *ctx,
81 struct gl_shader_program *shProg)
82 {
83 _mesa_reference_vertprog(ctx, &shProg->VertexProgram, NULL);
84 _mesa_reference_fragprog(ctx, &shProg->FragmentProgram, NULL);
85
86 if (shProg->Uniforms) {
87 _mesa_free_uniform_list(shProg->Uniforms);
88 shProg->Uniforms = NULL;
89 }
90
91 if (shProg->Varying) {
92 _mesa_free_parameter_list(shProg->Varying);
93 shProg->Varying = NULL;
94 }
95 }
96
97
98 /**
99 * Free all the data that hangs off a shader program object, but not the
100 * object itself.
101 */
102 void
103 _mesa_free_shader_program_data(GLcontext *ctx,
104 struct gl_shader_program *shProg)
105 {
106 GLuint i;
107
108 assert(shProg->Type == GL_SHADER_PROGRAM_MESA);
109
110 _mesa_clear_shader_program_data(ctx, shProg);
111
112 if (shProg->Attributes) {
113 _mesa_free_parameter_list(shProg->Attributes);
114 shProg->Attributes = NULL;
115 }
116
117 /* detach shaders */
118 for (i = 0; i < shProg->NumShaders; i++) {
119 _mesa_reference_shader(ctx, &shProg->Shaders[i], NULL);
120 }
121 shProg->NumShaders = 0;
122
123 if (shProg->Shaders) {
124 _mesa_free(shProg->Shaders);
125 shProg->Shaders = NULL;
126 }
127
128 if (shProg->InfoLog) {
129 _mesa_free(shProg->InfoLog);
130 shProg->InfoLog = NULL;
131 }
132 }
133
134
135 /**
136 * Free/delete a shader program object.
137 */
138 void
139 _mesa_free_shader_program(GLcontext *ctx, struct gl_shader_program *shProg)
140 {
141 _mesa_free_shader_program_data(ctx, shProg);
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 #if 0
172 printf("ShaderProgram %p ID=%u RefCount-- to %d\n",
173 (void *) old, old->Name, old->RefCount);
174 #endif
175 deleteFlag = (old->RefCount == 0);
176
177 if (deleteFlag) {
178 _mesa_HashRemove(ctx->Shared->ShaderObjects, old->Name);
179 _mesa_free_shader_program(ctx, old);
180 }
181
182 *ptr = NULL;
183 }
184 assert(!*ptr);
185
186 if (shProg) {
187 shProg->RefCount++;
188 #if 0
189 printf("ShaderProgram %p ID=%u RefCount++ to %d\n",
190 (void *) shProg, shProg->Name, shProg->RefCount);
191 #endif
192 *ptr = shProg;
193 }
194 }
195
196
197 /**
198 * Lookup a GLSL program object.
199 */
200 struct gl_shader_program *
201 _mesa_lookup_shader_program(GLcontext *ctx, GLuint name)
202 {
203 struct gl_shader_program *shProg;
204 if (name) {
205 shProg = (struct gl_shader_program *)
206 _mesa_HashLookup(ctx->Shared->ShaderObjects, name);
207 /* Note that both gl_shader and gl_shader_program objects are kept
208 * in the same hash table. Check the object's type to be sure it's
209 * what we're expecting.
210 */
211 if (shProg && shProg->Type != GL_SHADER_PROGRAM_MESA) {
212 return NULL;
213 }
214 return shProg;
215 }
216 return NULL;
217 }
218
219
220 /**
221 * As above, but record an error if program is not found.
222 */
223 static struct gl_shader_program *
224 _mesa_lookup_shader_program_err(GLcontext *ctx, GLuint name,
225 const char *caller)
226 {
227 if (!name) {
228 _mesa_error(ctx, GL_INVALID_VALUE, caller);
229 return NULL;
230 }
231 else {
232 struct gl_shader_program *shProg = (struct gl_shader_program *)
233 _mesa_HashLookup(ctx->Shared->ShaderObjects, name);
234 if (!shProg) {
235 _mesa_error(ctx, GL_INVALID_VALUE, caller);
236 return NULL;
237 }
238 if (shProg->Type != GL_SHADER_PROGRAM_MESA) {
239 _mesa_error(ctx, GL_INVALID_OPERATION, caller);
240 return NULL;
241 }
242 return shProg;
243 }
244 }
245
246
247
248
249 /**
250 * Allocate a new gl_shader object, initialize it.
251 */
252 struct gl_shader *
253 _mesa_new_shader(GLcontext *ctx, GLuint name, GLenum type)
254 {
255 struct gl_shader *shader;
256 assert(type == GL_FRAGMENT_SHADER || type == GL_VERTEX_SHADER);
257 shader = CALLOC_STRUCT(gl_shader);
258 if (shader) {
259 shader->Type = type;
260 shader->Name = name;
261 shader->RefCount = 1;
262 }
263 return shader;
264 }
265
266
267 void
268 _mesa_free_shader(GLcontext *ctx, struct gl_shader *sh)
269 {
270 if (sh->Source)
271 _mesa_free((void *) sh->Source);
272 if (sh->InfoLog)
273 _mesa_free(sh->InfoLog);
274 _mesa_reference_program(ctx, &sh->Program, NULL);
275 _mesa_free(sh);
276 }
277
278
279 /**
280 * Set ptr to point to sh.
281 * If ptr is pointing to another shader, decrement its refcount (and delete
282 * if refcount hits zero).
283 * Then set ptr to point to sh, incrementing its refcount.
284 */
285 /* XXX this could be static */
286 void
287 _mesa_reference_shader(GLcontext *ctx, struct gl_shader **ptr,
288 struct gl_shader *sh)
289 {
290 assert(ptr);
291 if (*ptr == sh) {
292 /* no-op */
293 return;
294 }
295 if (*ptr) {
296 /* Unreference the old shader */
297 GLboolean deleteFlag = GL_FALSE;
298 struct gl_shader *old = *ptr;
299
300 ASSERT(old->RefCount > 0);
301 old->RefCount--;
302 /*printf("SHADER DECR %p (%d) to %d\n",
303 (void*) old, old->Name, old->RefCount);*/
304 deleteFlag = (old->RefCount == 0);
305
306 if (deleteFlag) {
307 _mesa_HashRemove(ctx->Shared->ShaderObjects, old->Name);
308 _mesa_free_shader(ctx, old);
309 }
310
311 *ptr = NULL;
312 }
313 assert(!*ptr);
314
315 if (sh) {
316 /* reference new */
317 sh->RefCount++;
318 /*printf("SHADER INCR %p (%d) to %d\n",
319 (void*) sh, sh->Name, sh->RefCount);*/
320 *ptr = sh;
321 }
322 }
323
324
325 /**
326 * Lookup a GLSL shader object.
327 */
328 struct gl_shader *
329 _mesa_lookup_shader(GLcontext *ctx, GLuint name)
330 {
331 if (name) {
332 struct gl_shader *sh = (struct gl_shader *)
333 _mesa_HashLookup(ctx->Shared->ShaderObjects, name);
334 /* Note that both gl_shader and gl_shader_program objects are kept
335 * in the same hash table. Check the object's type to be sure it's
336 * what we're expecting.
337 */
338 if (sh && sh->Type == GL_SHADER_PROGRAM_MESA) {
339 return NULL;
340 }
341 return sh;
342 }
343 return NULL;
344 }
345
346
347 /**
348 * As above, but record an error if shader is not found.
349 */
350 static struct gl_shader *
351 _mesa_lookup_shader_err(GLcontext *ctx, GLuint name, const char *caller)
352 {
353 if (!name) {
354 _mesa_error(ctx, GL_INVALID_VALUE, caller);
355 return NULL;
356 }
357 else {
358 struct gl_shader *sh = (struct gl_shader *)
359 _mesa_HashLookup(ctx->Shared->ShaderObjects, name);
360 if (!sh) {
361 _mesa_error(ctx, GL_INVALID_VALUE, caller);
362 return NULL;
363 }
364 if (sh->Type == GL_SHADER_PROGRAM_MESA) {
365 _mesa_error(ctx, GL_INVALID_OPERATION, caller);
366 return NULL;
367 }
368 return sh;
369 }
370 }
371
372
373
374 /**
375 * Initialize context's shader state.
376 */
377 void
378 _mesa_init_shader_state(GLcontext * ctx)
379 {
380 /* Device drivers may override these to control what kind of instructions
381 * are generated by the GLSL compiler.
382 */
383 ctx->Shader.EmitHighLevelInstructions = GL_TRUE;
384 ctx->Shader.EmitCondCodes = GL_FALSE;/*GL_TRUE;*/ /* XXX probably want GL_FALSE... */
385 ctx->Shader.EmitComments = GL_FALSE;
386 }
387
388
389 /**
390 * Free the per-context shader-related state.
391 */
392 void
393 _mesa_free_shader_state(GLcontext *ctx)
394 {
395 _mesa_reference_shader_program(ctx, &ctx->Shader.CurrentProgram, NULL);
396 }
397
398
399 /**
400 * Copy string from <src> to <dst>, up to maxLength characters, returning
401 * length of <dst> in <length>.
402 * \param src the strings source
403 * \param maxLength max chars to copy
404 * \param length returns number of chars copied
405 * \param dst the string destination
406 */
407 static void
408 copy_string(GLchar *dst, GLsizei maxLength, GLsizei *length, const GLchar *src)
409 {
410 GLsizei len;
411 for (len = 0; len < maxLength - 1 && src && src[len]; len++)
412 dst[len] = src[len];
413 if (maxLength > 0)
414 dst[len] = 0;
415 if (length)
416 *length = len;
417 }
418
419
420 static GLboolean
421 _mesa_is_program(GLcontext *ctx, GLuint name)
422 {
423 struct gl_shader_program *shProg = _mesa_lookup_shader_program(ctx, name);
424 return shProg ? GL_TRUE : GL_FALSE;
425 }
426
427
428 static GLboolean
429 _mesa_is_shader(GLcontext *ctx, GLuint name)
430 {
431 struct gl_shader *shader = _mesa_lookup_shader(ctx, name);
432 return shader ? GL_TRUE : GL_FALSE;
433 }
434
435
436 /**
437 * Called via ctx->Driver.AttachShader()
438 */
439 static void
440 _mesa_attach_shader(GLcontext *ctx, GLuint program, GLuint shader)
441 {
442 struct gl_shader_program *shProg;
443 struct gl_shader *sh;
444 GLuint i, n;
445
446 shProg = _mesa_lookup_shader_program_err(ctx, program, "glAttachShader");
447 if (!shProg)
448 return;
449
450 sh = _mesa_lookup_shader_err(ctx, shader, "glAttachShader");
451 if (!sh) {
452 return;
453 }
454
455 n = shProg->NumShaders;
456 for (i = 0; i < n; i++) {
457 if (shProg->Shaders[i] == sh) {
458 /* already attached */
459 return;
460 }
461 }
462
463 /* grow list */
464 shProg->Shaders = (struct gl_shader **)
465 _mesa_realloc(shProg->Shaders,
466 n * sizeof(struct gl_shader *),
467 (n + 1) * sizeof(struct gl_shader *));
468 if (!shProg->Shaders) {
469 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glAttachShader");
470 return;
471 }
472
473 /* append */
474 shProg->Shaders[n] = NULL; /* since realloc() didn't zero the new space */
475 _mesa_reference_shader(ctx, &shProg->Shaders[n], sh);
476 shProg->NumShaders++;
477 }
478
479
480 static GLint
481 _mesa_get_attrib_location(GLcontext *ctx, GLuint program,
482 const GLchar *name)
483 {
484 struct gl_shader_program *shProg
485 = _mesa_lookup_shader_program_err(ctx, program, "glGetAttribLocation");
486
487 if (!shProg) {
488 return -1;
489 }
490
491 if (!shProg->LinkStatus) {
492 _mesa_error(ctx, GL_INVALID_OPERATION,
493 "glGetAttribLocation(program not linked)");
494 return -1;
495 }
496
497 if (!name)
498 return -1;
499
500 if (shProg->Attributes) {
501 GLint i = _mesa_lookup_parameter_index(shProg->Attributes, -1, name);
502 if (i >= 0) {
503 return shProg->Attributes->Parameters[i].StateIndexes[0];
504 }
505 }
506 return -1;
507 }
508
509
510 static void
511 _mesa_bind_attrib_location(GLcontext *ctx, GLuint program, GLuint index,
512 const GLchar *name)
513 {
514 struct gl_shader_program *shProg;
515 const GLint size = -1; /* unknown size */
516 GLint i, oldIndex;
517 GLenum datatype = GL_FLOAT_VEC4;
518
519 shProg = _mesa_lookup_shader_program_err(ctx, program,
520 "glBindAttribLocation");
521 if (!shProg) {
522 return;
523 }
524
525 if (!name)
526 return;
527
528 if (strncmp(name, "gl_", 3) == 0) {
529 _mesa_error(ctx, GL_INVALID_OPERATION,
530 "glBindAttribLocation(illegal name)");
531 return;
532 }
533
534 if (index >= ctx->Const.VertexProgram.MaxAttribs) {
535 _mesa_error(ctx, GL_INVALID_VALUE, "glBindAttribLocation(index)");
536 return;
537 }
538
539 if (shProg->LinkStatus) {
540 /* get current index/location for the attribute */
541 oldIndex = _mesa_get_attrib_location(ctx, program, name);
542 }
543 else {
544 oldIndex = -1;
545 }
546
547 /* this will replace the current value if it's already in the list */
548 i = _mesa_add_attribute(shProg->Attributes, name, size, datatype, index);
549 if (i < 0) {
550 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBindAttribLocation");
551 return;
552 }
553
554 if (shProg->VertexProgram && oldIndex >= 0 && oldIndex != index) {
555 /* If the index changed, need to search/replace references to that attribute
556 * in the vertex program.
557 */
558 _slang_remap_attribute(&shProg->VertexProgram->Base, oldIndex, index);
559 }
560 }
561
562
563 static GLuint
564 _mesa_create_shader(GLcontext *ctx, GLenum type)
565 {
566 struct gl_shader *sh;
567 GLuint name;
568
569 name = _mesa_HashFindFreeKeyBlock(ctx->Shared->ShaderObjects, 1);
570
571 switch (type) {
572 case GL_FRAGMENT_SHADER:
573 case GL_VERTEX_SHADER:
574 sh = _mesa_new_shader(ctx, name, type);
575 break;
576 default:
577 _mesa_error(ctx, GL_INVALID_ENUM, "CreateShader(type)");
578 return 0;
579 }
580
581 _mesa_HashInsert(ctx->Shared->ShaderObjects, name, sh);
582
583 return name;
584 }
585
586
587 static GLuint
588 _mesa_create_program(GLcontext *ctx)
589 {
590 GLuint name;
591 struct gl_shader_program *shProg;
592
593 name = _mesa_HashFindFreeKeyBlock(ctx->Shared->ShaderObjects, 1);
594 shProg = _mesa_new_shader_program(ctx, name);
595
596 _mesa_HashInsert(ctx->Shared->ShaderObjects, name, shProg);
597
598 assert(shProg->RefCount == 1);
599
600 return name;
601 }
602
603
604 /**
605 * Named w/ "2" to indicate OpenGL 2.x vs GL_ARB_fragment_programs's
606 * DeleteProgramARB.
607 */
608 static void
609 _mesa_delete_program2(GLcontext *ctx, GLuint name)
610 {
611 /*
612 * NOTE: deleting shaders/programs works a bit differently than
613 * texture objects (and buffer objects, etc). Shader/program
614 * handles/IDs exist in the hash table until the object is really
615 * deleted (refcount==0). With texture objects, the handle/ID is
616 * removed from the hash table in glDeleteTextures() while the tex
617 * object itself might linger until its refcount goes to zero.
618 */
619 struct gl_shader_program *shProg;
620
621 shProg = _mesa_lookup_shader_program_err(ctx, name, "glDeleteProgram");
622 if (!shProg)
623 return;
624
625 shProg->DeletePending = GL_TRUE;
626
627 /* effectively, decr shProg's refcount */
628 _mesa_reference_shader_program(ctx, &shProg, NULL);
629 }
630
631
632 static void
633 _mesa_delete_shader(GLcontext *ctx, GLuint shader)
634 {
635 struct gl_shader *sh;
636
637 sh = _mesa_lookup_shader_err(ctx, shader, "glDeleteShader");
638 if (!sh)
639 return;
640
641 sh->DeletePending = GL_TRUE;
642
643 /* effectively, decr sh's refcount */
644 _mesa_reference_shader(ctx, &sh, NULL);
645 }
646
647
648 static void
649 _mesa_detach_shader(GLcontext *ctx, GLuint program, GLuint shader)
650 {
651 struct gl_shader_program *shProg;
652 GLuint n;
653 GLuint i, j;
654
655 shProg = _mesa_lookup_shader_program_err(ctx, program, "glDetachShader");
656 if (!shProg)
657 return;
658
659 n = shProg->NumShaders;
660
661 for (i = 0; i < n; i++) {
662 if (shProg->Shaders[i]->Name == shader) {
663 /* found it */
664 struct gl_shader **newList;
665
666 /* release */
667 _mesa_reference_shader(ctx, &shProg->Shaders[i], NULL);
668
669 /* alloc new, smaller array */
670 newList = (struct gl_shader **)
671 _mesa_malloc((n - 1) * sizeof(struct gl_shader *));
672 if (!newList) {
673 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glDetachShader");
674 return;
675 }
676 for (j = 0; j < i; j++) {
677 newList[j] = shProg->Shaders[j];
678 }
679 while (++i < n)
680 newList[j++] = shProg->Shaders[i];
681 _mesa_free(shProg->Shaders);
682
683 shProg->Shaders = newList;
684 shProg->NumShaders = n - 1;
685
686 #ifdef DEBUG
687 /* sanity check */
688 {
689 for (j = 0; j < shProg->NumShaders; j++) {
690 assert(shProg->Shaders[j]->Type == GL_VERTEX_SHADER ||
691 shProg->Shaders[j]->Type == GL_FRAGMENT_SHADER);
692 assert(shProg->Shaders[j]->RefCount > 0);
693 }
694 }
695 #endif
696
697 return;
698 }
699 }
700
701 /* not found */
702 {
703 GLenum err;
704 if (_mesa_is_shader(ctx, shader))
705 err = GL_INVALID_OPERATION;
706 else if (_mesa_is_program(ctx, shader))
707 err = GL_INVALID_OPERATION;
708 else
709 err = GL_INVALID_VALUE;
710 _mesa_error(ctx, err, "glDetachProgram(shader)");
711 return;
712 }
713 }
714
715
716 static GLint
717 sizeof_glsl_type(GLenum type)
718 {
719 switch (type) {
720 case GL_FLOAT:
721 case GL_INT:
722 case GL_BOOL:
723 case GL_SAMPLER_1D:
724 case GL_SAMPLER_2D:
725 case GL_SAMPLER_3D:
726 case GL_SAMPLER_CUBE:
727 case GL_SAMPLER_1D_SHADOW:
728 case GL_SAMPLER_2D_SHADOW:
729 case GL_SAMPLER_2D_RECT_ARB:
730 case GL_SAMPLER_2D_RECT_SHADOW_ARB:
731 case GL_SAMPLER_1D_ARRAY_SHADOW_EXT:
732 case GL_SAMPLER_2D_ARRAY_SHADOW_EXT:
733 case GL_SAMPLER_CUBE_SHADOW_EXT:
734 return 1;
735 case GL_FLOAT_VEC2:
736 case GL_INT_VEC2:
737 case GL_BOOL_VEC2:
738 return 2;
739 case GL_FLOAT_VEC3:
740 case GL_INT_VEC3:
741 case GL_BOOL_VEC3:
742 return 3;
743 case GL_FLOAT_VEC4:
744 case GL_INT_VEC4:
745 case GL_BOOL_VEC4:
746 return 4;
747 case GL_FLOAT_MAT2:
748 case GL_FLOAT_MAT2x3:
749 case GL_FLOAT_MAT2x4:
750 return 8; /* two float[4] vectors */
751 case GL_FLOAT_MAT3:
752 case GL_FLOAT_MAT3x2:
753 case GL_FLOAT_MAT3x4:
754 return 12; /* three float[4] vectors */
755 case GL_FLOAT_MAT4:
756 case GL_FLOAT_MAT4x2:
757 case GL_FLOAT_MAT4x3:
758 return 16; /* four float[4] vectors */
759 default:
760 _mesa_problem(NULL, "Invalid type in sizeof_glsl_type()");
761 return 1;
762 }
763 }
764
765
766 static GLboolean
767 is_boolean_type(GLenum type)
768 {
769 switch (type) {
770 case GL_BOOL:
771 case GL_BOOL_VEC2:
772 case GL_BOOL_VEC3:
773 case GL_BOOL_VEC4:
774 return GL_TRUE;
775 default:
776 return GL_FALSE;
777 }
778 }
779
780
781 static GLboolean
782 is_integer_type(GLenum type)
783 {
784 switch (type) {
785 case GL_INT:
786 case GL_INT_VEC2:
787 case GL_INT_VEC3:
788 case GL_INT_VEC4:
789 return GL_TRUE;
790 default:
791 return GL_FALSE;
792 }
793 }
794
795
796 static void
797 _mesa_get_active_attrib(GLcontext *ctx, GLuint program, GLuint index,
798 GLsizei maxLength, GLsizei *length, GLint *size,
799 GLenum *type, GLchar *nameOut)
800 {
801 struct gl_shader_program *shProg;
802
803 shProg = _mesa_lookup_shader_program_err(ctx, program, "glGetActiveAttrib");
804 if (!shProg)
805 return;
806
807 if (!shProg->Attributes || index >= shProg->Attributes->NumParameters) {
808 _mesa_error(ctx, GL_INVALID_VALUE, "glGetActiveAttrib(index)");
809 return;
810 }
811
812 copy_string(nameOut, maxLength, length,
813 shProg->Attributes->Parameters[index].Name);
814 if (size)
815 *size = shProg->Attributes->Parameters[index].Size
816 / sizeof_glsl_type(shProg->Attributes->Parameters[index].DataType);
817 if (type)
818 *type = shProg->Attributes->Parameters[index].DataType;
819 }
820
821
822 static struct gl_program_parameter *
823 get_uniform_parameter(const struct gl_shader_program *shProg, GLuint index)
824 {
825 const struct gl_program *prog;
826 GLint progPos;
827
828 progPos = shProg->Uniforms->Uniforms[index].VertPos;
829 if (progPos >= 0) {
830 prog = &shProg->VertexProgram->Base;
831 }
832 else {
833 progPos = shProg->Uniforms->Uniforms[index].FragPos;
834 if (progPos >= 0) {
835 prog = &shProg->FragmentProgram->Base;
836 }
837 }
838
839 if (!prog || progPos < 0)
840 return NULL; /* should never happen */
841
842 return &prog->Parameters->Parameters[progPos];
843 }
844
845
846 /**
847 * Called via ctx->Driver.GetActiveUniform().
848 */
849 static void
850 _mesa_get_active_uniform(GLcontext *ctx, GLuint program, GLuint index,
851 GLsizei maxLength, GLsizei *length, GLint *size,
852 GLenum *type, GLchar *nameOut)
853 {
854 const struct gl_shader_program *shProg;
855 const struct gl_program *prog;
856 GLint progPos;
857
858 shProg = _mesa_lookup_shader_program_err(ctx, program, "glGetActiveUniform");
859 if (!shProg)
860 return;
861
862 if (!shProg->Uniforms || index >= shProg->Uniforms->NumUniforms) {
863 _mesa_error(ctx, GL_INVALID_VALUE, "glGetActiveUniform(index)");
864 return;
865 }
866
867 progPos = shProg->Uniforms->Uniforms[index].VertPos;
868 if (progPos >= 0) {
869 prog = &shProg->VertexProgram->Base;
870 }
871 else {
872 progPos = shProg->Uniforms->Uniforms[index].FragPos;
873 if (progPos >= 0) {
874 prog = &shProg->FragmentProgram->Base;
875 }
876 }
877
878 if (!prog || progPos < 0)
879 return; /* should never happen */
880
881 if (nameOut)
882 copy_string(nameOut, maxLength, length,
883 prog->Parameters->Parameters[progPos].Name);
884 if (size)
885 *size = prog->Parameters->Parameters[progPos].Size
886 / sizeof_glsl_type(prog->Parameters->Parameters[progPos].DataType);
887 if (type)
888 *type = prog->Parameters->Parameters[progPos].DataType;
889 }
890
891
892 /**
893 * Called via ctx->Driver.GetAttachedShaders().
894 */
895 static void
896 _mesa_get_attached_shaders(GLcontext *ctx, GLuint program, GLsizei maxCount,
897 GLsizei *count, GLuint *obj)
898 {
899 struct gl_shader_program *shProg =
900 _mesa_lookup_shader_program_err(ctx, program, "glGetAttachedShaders");
901 if (shProg) {
902 GLuint i;
903 for (i = 0; i < (GLuint) maxCount && i < shProg->NumShaders; i++) {
904 obj[i] = shProg->Shaders[i]->Name;
905 }
906 if (count)
907 *count = i;
908 }
909 }
910
911
912 static GLuint
913 _mesa_get_handle(GLcontext *ctx, GLenum pname)
914 {
915 #if 0
916 GET_CURRENT_CONTEXT(ctx);
917
918 switch (pname) {
919 case GL_PROGRAM_OBJECT_ARB:
920 {
921 struct gl2_program_intf **pro = ctx->Shader.CurrentProgram;
922
923 if (pro != NULL)
924 return (**pro)._container._generic.
925 GetName((struct gl2_generic_intf **) (pro));
926 }
927 break;
928 default:
929 _mesa_error(ctx, GL_INVALID_ENUM, "glGetHandleARB");
930 }
931 #endif
932 return 0;
933 }
934
935
936 static void
937 _mesa_get_programiv(GLcontext *ctx, GLuint program,
938 GLenum pname, GLint *params)
939 {
940 struct gl_shader_program *shProg
941 = _mesa_lookup_shader_program(ctx, program);
942
943 if (!shProg) {
944 _mesa_error(ctx, GL_INVALID_VALUE, "glGetProgramiv(program)");
945 return;
946 }
947
948 switch (pname) {
949 case GL_DELETE_STATUS:
950 *params = shProg->DeletePending;
951 break;
952 case GL_LINK_STATUS:
953 *params = shProg->LinkStatus;
954 break;
955 case GL_VALIDATE_STATUS:
956 *params = shProg->Validated;
957 break;
958 case GL_INFO_LOG_LENGTH:
959 *params = shProg->InfoLog ? strlen(shProg->InfoLog) + 1 : 0;
960 break;
961 case GL_ATTACHED_SHADERS:
962 *params = shProg->NumShaders;
963 break;
964 case GL_ACTIVE_ATTRIBUTES:
965 *params = shProg->Attributes ? shProg->Attributes->NumParameters : 0;
966 break;
967 case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH:
968 *params = _mesa_longest_parameter_name(shProg->Attributes,
969 PROGRAM_INPUT) + 1;
970 break;
971 case GL_ACTIVE_UNIFORMS:
972 *params = shProg->Uniforms ? shProg->Uniforms->NumUniforms : 0;
973 break;
974 case GL_ACTIVE_UNIFORM_MAX_LENGTH:
975 *params = _mesa_longest_uniform_name(shProg->Uniforms);
976 if (*params > 0)
977 (*params)++; /* add one for terminating zero */
978 break;
979 case GL_PROGRAM_BINARY_LENGTH_OES:
980 *params = 0;
981 break;
982 default:
983 _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramiv(pname)");
984 return;
985 }
986 }
987
988
989 static void
990 _mesa_get_shaderiv(GLcontext *ctx, GLuint name, GLenum pname, GLint *params)
991 {
992 struct gl_shader *shader = _mesa_lookup_shader_err(ctx, name, "glGetShaderiv");
993
994 if (!shader) {
995 return;
996 }
997
998 switch (pname) {
999 case GL_SHADER_TYPE:
1000 *params = shader->Type;
1001 break;
1002 case GL_DELETE_STATUS:
1003 *params = shader->DeletePending;
1004 break;
1005 case GL_COMPILE_STATUS:
1006 *params = shader->CompileStatus;
1007 break;
1008 case GL_INFO_LOG_LENGTH:
1009 *params = shader->InfoLog ? strlen(shader->InfoLog) + 1 : 0;
1010 break;
1011 case GL_SHADER_SOURCE_LENGTH:
1012 *params = shader->Source ? strlen((char *) shader->Source) + 1 : 0;
1013 break;
1014 default:
1015 _mesa_error(ctx, GL_INVALID_ENUM, "glGetShaderiv(pname)");
1016 return;
1017 }
1018 }
1019
1020
1021 static void
1022 _mesa_get_program_info_log(GLcontext *ctx, GLuint program, GLsizei bufSize,
1023 GLsizei *length, GLchar *infoLog)
1024 {
1025 struct gl_shader_program *shProg
1026 = _mesa_lookup_shader_program(ctx, program);
1027 if (!shProg) {
1028 _mesa_error(ctx, GL_INVALID_VALUE, "glGetProgramInfoLog(program)");
1029 return;
1030 }
1031 copy_string(infoLog, bufSize, length, shProg->InfoLog);
1032 }
1033
1034
1035 static void
1036 _mesa_get_shader_info_log(GLcontext *ctx, GLuint shader, GLsizei bufSize,
1037 GLsizei *length, GLchar *infoLog)
1038 {
1039 struct gl_shader *sh = _mesa_lookup_shader(ctx, shader);
1040 if (!sh) {
1041 _mesa_error(ctx, GL_INVALID_VALUE, "glGetShaderInfoLog(shader)");
1042 return;
1043 }
1044 copy_string(infoLog, bufSize, length, sh->InfoLog);
1045 }
1046
1047
1048 /**
1049 * Called via ctx->Driver.GetShaderSource().
1050 */
1051 static void
1052 _mesa_get_shader_source(GLcontext *ctx, GLuint shader, GLsizei maxLength,
1053 GLsizei *length, GLchar *sourceOut)
1054 {
1055 struct gl_shader *sh;
1056 sh = _mesa_lookup_shader_err(ctx, shader, "glGetShaderSource");
1057 if (!sh) {
1058 return;
1059 }
1060 copy_string(sourceOut, maxLength, length, sh->Source);
1061 }
1062
1063
1064 static void
1065 get_matrix_dims(GLenum type, GLint *rows, GLint *cols)
1066 {
1067 switch (type) {
1068 case GL_FLOAT_MAT2:
1069 *rows = *cols = 2;
1070 break;
1071 case GL_FLOAT_MAT2x3:
1072 *rows = 3;
1073 *cols = 2;
1074 break;
1075 case GL_FLOAT_MAT2x4:
1076 *rows = 4;
1077 *cols = 2;
1078 break;
1079 case GL_FLOAT_MAT3:
1080 *rows = 3;
1081 *cols = 3;
1082 break;
1083 case GL_FLOAT_MAT3x2:
1084 *rows = 2;
1085 *cols = 3;
1086 break;
1087 case GL_FLOAT_MAT3x4:
1088 *rows = 4;
1089 *cols = 3;
1090 break;
1091 case GL_FLOAT_MAT4:
1092 *rows = 4;
1093 *cols = 4;
1094 break;
1095 case GL_FLOAT_MAT4x2:
1096 *rows = 2;
1097 *cols = 4;
1098 break;
1099 case GL_FLOAT_MAT4x3:
1100 *rows = 3;
1101 *cols = 4;
1102 break;
1103 default:
1104 *rows = *cols = 0;
1105 }
1106 }
1107
1108
1109 /**
1110 * Determine the number of rows and columns occupied by a uniform
1111 * according to its datatype.
1112 */
1113 static void
1114 get_uniform_rows_cols(const struct gl_program_parameter *p,
1115 GLint *rows, GLint *cols)
1116 {
1117 get_matrix_dims(p->DataType, rows, cols);
1118 if (*rows == 0 && *cols == 0) {
1119 /* not a matrix type, probably a float or vector */
1120 *rows = p->Size / 4 + 1;
1121 if (p->Size % 4 == 0)
1122 *cols = 4;
1123 else
1124 *cols = p->Size % 4;
1125 }
1126 }
1127
1128
1129 #define MAX_UNIFORM_ELEMENTS 16
1130
1131 /**
1132 * Helper for GetUniformfv(), GetUniformiv()
1133 * Returns number of elements written to 'params' output.
1134 */
1135 static GLuint
1136 get_uniformfv(GLcontext *ctx, GLuint program, GLint location,
1137 GLfloat *params)
1138 {
1139 struct gl_shader_program *shProg
1140 = _mesa_lookup_shader_program_err(ctx, program, "glGetUniform[if]v");
1141 if (shProg) {
1142 if (shProg->Uniforms &&
1143 location >= 0 && location < (GLint) shProg->Uniforms->NumUniforms) {
1144 GLint progPos;
1145 const struct gl_program *prog = NULL;
1146
1147 progPos = shProg->Uniforms->Uniforms[location].VertPos;
1148 if (progPos >= 0) {
1149 prog = &shProg->VertexProgram->Base;
1150 }
1151 else {
1152 progPos = shProg->Uniforms->Uniforms[location].FragPos;
1153 if (progPos >= 0) {
1154 prog = &shProg->FragmentProgram->Base;
1155 }
1156 }
1157
1158 ASSERT(prog);
1159 if (prog) {
1160 const struct gl_program_parameter *p =
1161 &prog->Parameters->Parameters[progPos];
1162 GLint rows, cols, i, j, k;
1163
1164 /* See uniformiv() below */
1165 assert(p->Size <= MAX_UNIFORM_ELEMENTS);
1166
1167 get_uniform_rows_cols(p, &rows, &cols);
1168
1169 k = 0;
1170 for (i = 0; i < rows; i++) {
1171 for (j = 0; j < cols; j++ ) {
1172 params[k++] = prog->Parameters->ParameterValues[progPos+i][j];
1173 }
1174 }
1175
1176 return p->Size;
1177 }
1178 }
1179 else {
1180 _mesa_error(ctx, GL_INVALID_OPERATION, "glGetUniformfv(location)");
1181 }
1182 }
1183 return 0;
1184 }
1185
1186
1187 /**
1188 * Called via ctx->Driver.GetUniformfv().
1189 */
1190 static void
1191 _mesa_get_uniformfv(GLcontext *ctx, GLuint program, GLint location,
1192 GLfloat *params)
1193 {
1194 (void) get_uniformfv(ctx, program, location, params);
1195 }
1196
1197
1198 /**
1199 * Called via ctx->Driver.GetUniformiv().
1200 */
1201 static void
1202 _mesa_get_uniformiv(GLcontext *ctx, GLuint program, GLint location,
1203 GLint *params)
1204 {
1205 GLfloat fparams[MAX_UNIFORM_ELEMENTS];
1206 GLuint n = get_uniformfv(ctx, program, location, fparams);
1207 GLuint i;
1208 assert(n <= MAX_UNIFORM_ELEMENTS);
1209 for (i = 0; i < n; i++) {
1210 params[i] = (GLint) fparams[i];
1211 }
1212 }
1213
1214
1215 /**
1216 * The value returned by GetUniformLocation actually encodes two things:
1217 * 1. the index into the prog->Uniforms[] array for the uniform
1218 * 2. an offset in the prog->ParameterValues[] array for specifying array
1219 * elements or structure fields.
1220 * This function merges those two values.
1221 */
1222 static void
1223 merge_location_offset(GLint *location, GLint offset)
1224 {
1225 *location = *location | (offset << 16);
1226 }
1227
1228
1229 /**
1230 * Seperate the uniform location and parameter offset. See above.
1231 */
1232 static void
1233 split_location_offset(GLint *location, GLint *offset)
1234 {
1235 *offset = (*location >> 16);
1236 *location = *location & 0xffff;
1237 }
1238
1239
1240 /**
1241 * Called via ctx->Driver.GetUniformLocation().
1242 *
1243 * The return value will encode two values, the uniform location and an
1244 * offset (used for arrays, structs).
1245 */
1246 static GLint
1247 _mesa_get_uniform_location(GLcontext *ctx, GLuint program, const GLchar *name)
1248 {
1249 GLint offset = 0, location = -1;
1250
1251 struct gl_shader_program *shProg =
1252 _mesa_lookup_shader_program_err(ctx, program, "glGetUniformLocation");
1253
1254 if (!shProg)
1255 return -1;
1256
1257 if (shProg->LinkStatus == GL_FALSE) {
1258 _mesa_error(ctx, GL_INVALID_OPERATION, "glGetUniformfv(program)");
1259 return -1;
1260 }
1261
1262 /* XXX we should return -1 if the uniform was declared, but not
1263 * actually used.
1264 */
1265
1266 /* XXX we need to be able to parse uniform names for structs and arrays
1267 * such as:
1268 * mymatrix[1]
1269 * mystruct.field1
1270 */
1271
1272 {
1273 /* handle 1-dimension arrays here... */
1274 char *c = strchr(name, '[');
1275 if (c) {
1276 /* truncate name at [ */
1277 const GLint len = c - name;
1278 GLchar *newName = _mesa_malloc(len + 1);
1279 if (!newName)
1280 return -1; /* out of mem */
1281 _mesa_memcpy(newName, name, len);
1282 newName[len] = 0;
1283
1284 location = _mesa_lookup_uniform(shProg->Uniforms, newName);
1285 if (location >= 0) {
1286 const GLint element = _mesa_atoi(c + 1);
1287 if (element > 0) {
1288 /* get type of the uniform array element */
1289 struct gl_program_parameter *p;
1290 p = get_uniform_parameter(shProg, location);
1291 if (p) {
1292 GLint rows, cols;
1293 get_matrix_dims(p->DataType, &rows, &cols);
1294 if (rows < 1)
1295 rows = 1;
1296 offset = element * rows;
1297 }
1298 }
1299 }
1300
1301 _mesa_free(newName);
1302 }
1303 }
1304
1305 if (location < 0) {
1306 location = _mesa_lookup_uniform(shProg->Uniforms, name);
1307 }
1308
1309 if (location >= 0) {
1310 merge_location_offset(&location, offset);
1311 }
1312
1313 return location;
1314 }
1315
1316
1317
1318 /**
1319 * Called via ctx->Driver.ShaderSource()
1320 */
1321 static void
1322 _mesa_shader_source(GLcontext *ctx, GLuint shader, const GLchar *source)
1323 {
1324 struct gl_shader *sh;
1325
1326 sh = _mesa_lookup_shader_err(ctx, shader, "glShaderSource");
1327 if (!sh)
1328 return;
1329
1330 /* free old shader source string and install new one */
1331 if (sh->Source) {
1332 _mesa_free((void *) sh->Source);
1333 }
1334 sh->Source = source;
1335 sh->CompileStatus = GL_FALSE;
1336 }
1337
1338
1339 /**
1340 * Called via ctx->Driver.CompileShader()
1341 */
1342 static void
1343 _mesa_compile_shader(GLcontext *ctx, GLuint shaderObj)
1344 {
1345 struct gl_shader *sh;
1346
1347 sh = _mesa_lookup_shader_err(ctx, shaderObj, "glCompileShader");
1348 if (!sh)
1349 return;
1350
1351 sh->CompileStatus = _slang_compile(ctx, sh);
1352 }
1353
1354
1355 /**
1356 * Called via ctx->Driver.LinkProgram()
1357 */
1358 static void
1359 _mesa_link_program(GLcontext *ctx, GLuint program)
1360 {
1361 struct gl_shader_program *shProg;
1362
1363 shProg = _mesa_lookup_shader_program_err(ctx, program, "glLinkProgram");
1364 if (!shProg)
1365 return;
1366
1367 FLUSH_VERTICES(ctx, _NEW_PROGRAM);
1368
1369 _slang_link(ctx, program, shProg);
1370 }
1371
1372
1373 /**
1374 * Called via ctx->Driver.UseProgram()
1375 */
1376 void
1377 _mesa_use_program(GLcontext *ctx, GLuint program)
1378 {
1379 struct gl_shader_program *shProg;
1380
1381 if (ctx->Shader.CurrentProgram &&
1382 ctx->Shader.CurrentProgram->Name == program) {
1383 /* no-op */
1384 return;
1385 }
1386
1387 FLUSH_VERTICES(ctx, _NEW_PROGRAM);
1388
1389 if (program) {
1390 shProg = _mesa_lookup_shader_program_err(ctx, program, "glUseProgram");
1391 if (!shProg) {
1392 return;
1393 }
1394 if (!shProg->LinkStatus) {
1395 _mesa_error(ctx, GL_INVALID_OPERATION, "glUseProgram");
1396 return;
1397 }
1398 }
1399 else {
1400 shProg = NULL;
1401 }
1402
1403 _mesa_reference_shader_program(ctx, &ctx->Shader.CurrentProgram, shProg);
1404 }
1405
1406
1407
1408 /**
1409 * Update the vertex and fragment program's TexturesUsed arrays.
1410 */
1411 static void
1412 update_textures_used(struct gl_program *prog)
1413 {
1414 GLuint s;
1415
1416 memset(prog->TexturesUsed, 0, sizeof(prog->TexturesUsed));
1417
1418 for (s = 0; s < MAX_SAMPLERS; s++) {
1419 if (prog->SamplersUsed & (1 << s)) {
1420 GLuint u = prog->SamplerUnits[s];
1421 GLuint t = prog->SamplerTargets[s];
1422 assert(u < MAX_TEXTURE_IMAGE_UNITS);
1423 prog->TexturesUsed[u] |= (1 << t);
1424 }
1425 }
1426 }
1427
1428
1429 static GLboolean
1430 is_sampler_type(GLenum type)
1431 {
1432 switch (type) {
1433 case GL_SAMPLER_1D:
1434 case GL_SAMPLER_2D:
1435 case GL_SAMPLER_3D:
1436 case GL_SAMPLER_CUBE:
1437 case GL_SAMPLER_1D_SHADOW:
1438 case GL_SAMPLER_2D_SHADOW:
1439 case GL_SAMPLER_2D_RECT_ARB:
1440 case GL_SAMPLER_2D_RECT_SHADOW_ARB:
1441 case GL_SAMPLER_1D_ARRAY_EXT:
1442 case GL_SAMPLER_2D_ARRAY_EXT:
1443 return GL_TRUE;
1444 default:
1445 return GL_FALSE;
1446 }
1447 }
1448
1449
1450 /**
1451 * Check if the type given by userType is allowed to set a uniform of the
1452 * target type. Generally, equivalence is required, but setting Boolean
1453 * uniforms can be done with glUniformiv or glUniformfv.
1454 */
1455 static GLboolean
1456 compatible_types(GLenum userType, GLenum targetType)
1457 {
1458 if (userType == targetType)
1459 return GL_TRUE;
1460
1461 if (targetType == GL_BOOL && (userType == GL_FLOAT || userType == GL_INT))
1462 return GL_TRUE;
1463
1464 if (targetType == GL_BOOL_VEC2 && (userType == GL_FLOAT_VEC2 ||
1465 userType == GL_INT_VEC2))
1466 return GL_TRUE;
1467
1468 if (targetType == GL_BOOL_VEC3 && (userType == GL_FLOAT_VEC3 ||
1469 userType == GL_INT_VEC3))
1470 return GL_TRUE;
1471
1472 if (targetType == GL_BOOL_VEC4 && (userType == GL_FLOAT_VEC4 ||
1473 userType == GL_INT_VEC4))
1474 return GL_TRUE;
1475
1476 if (is_sampler_type(targetType) && userType == GL_INT)
1477 return GL_TRUE;
1478
1479 return GL_FALSE;
1480 }
1481
1482
1483 /**
1484 * Set the value of a program's uniform variable.
1485 * \param program the program whose uniform to update
1486 * \param index the index of the program parameter for the uniform
1487 * \param offset additional parameter slot offset (for arrays)
1488 * \param type the datatype of the uniform
1489 * \param count the number of uniforms to set
1490 * \param elems number of elements per uniform
1491 * \param values the new values
1492 */
1493 static void
1494 set_program_uniform(GLcontext *ctx, struct gl_program *program,
1495 GLint index, GLint offset,
1496 GLenum type, GLsizei count, GLint elems,
1497 const void *values)
1498 {
1499 assert(offset >= 0);
1500
1501 if (!compatible_types(type,
1502 program->Parameters->Parameters[index].DataType)) {
1503 _mesa_error(ctx, GL_INVALID_OPERATION, "glUniform(type mismatch)");
1504 return;
1505 }
1506
1507 if (index + offset > (GLint) program->Parameters->Size) {
1508 /* out of bounds! */
1509 return;
1510 }
1511
1512 if (program->Parameters->Parameters[index].Type == PROGRAM_SAMPLER) {
1513 /* This controls which texture unit which is used by a sampler */
1514 GLuint texUnit, sampler;
1515
1516 /* data type for setting samplers must be int */
1517 if (type != GL_INT || count != 1) {
1518 _mesa_error(ctx, GL_INVALID_OPERATION,
1519 "glUniform(only glUniform1i can be used "
1520 "to set sampler uniforms)");
1521 return;
1522 }
1523
1524 sampler = (GLuint) program->Parameters->ParameterValues[index][0];
1525 texUnit = ((GLuint *) values)[0];
1526
1527 /* check that the sampler (tex unit index) is legal */
1528 if (texUnit >= ctx->Const.MaxTextureImageUnits) {
1529 _mesa_error(ctx, GL_INVALID_VALUE,
1530 "glUniform1(invalid sampler/tex unit index)");
1531 return;
1532 }
1533
1534 /* This maps a sampler to a texture unit: */
1535 program->SamplerUnits[sampler] = texUnit;
1536 update_textures_used(program);
1537
1538 FLUSH_VERTICES(ctx, _NEW_TEXTURE);
1539 }
1540 else {
1541 /* ordinary uniform variable */
1542 GLsizei k, i;
1543 GLint slots = (program->Parameters->Parameters[index].Size + 3) / 4;
1544
1545 if (count * elems > (GLint) program->Parameters->Parameters[index].Size) {
1546 _mesa_error(ctx, GL_INVALID_OPERATION, "glUniform(count too large)");
1547 return;
1548 }
1549
1550 if (count > slots)
1551 count = slots;
1552
1553 for (k = 0; k < count; k++) {
1554 GLfloat *uniformVal = program->Parameters->ParameterValues[index + offset + k];
1555 if (is_integer_type(type)) {
1556 const GLint *iValues = ((const GLint *) values) + k * elems;
1557 for (i = 0; i < elems; i++) {
1558 uniformVal[i] = (GLfloat) iValues[i];
1559 }
1560 }
1561 else {
1562 const GLfloat *fValues = ((const GLfloat *) values) + k * elems;
1563 for (i = 0; i < elems; i++) {
1564 uniformVal[i] = fValues[i];
1565 }
1566 }
1567
1568 /* if the uniform is bool-valued, convert to 1.0 or 0.0 */
1569 if (is_boolean_type(program->Parameters->Parameters[index].DataType)) {
1570 for (i = 0; i < elems; i++) {
1571 uniformVal[i] = uniformVal[i] ? 1.0f : 0.0f;
1572 }
1573 }
1574 }
1575 }
1576 }
1577
1578
1579 /**
1580 * Called via ctx->Driver.Uniform().
1581 */
1582 static void
1583 _mesa_uniform(GLcontext *ctx, GLint location, GLsizei count,
1584 const GLvoid *values, GLenum type)
1585 {
1586 struct gl_shader_program *shProg = ctx->Shader.CurrentProgram;
1587 GLint elems, offset;
1588
1589 if (!shProg || !shProg->LinkStatus) {
1590 _mesa_error(ctx, GL_INVALID_OPERATION, "glUniform(program not linked)");
1591 return;
1592 }
1593
1594 if (location == -1)
1595 return; /* The standard specifies this as a no-op */
1596
1597 split_location_offset(&location, &offset);
1598
1599 if (location < 0 || location >= (GLint) shProg->Uniforms->NumUniforms) {
1600 _mesa_error(ctx, GL_INVALID_VALUE, "glUniform(location)");
1601 return;
1602 }
1603
1604 if (count < 0) {
1605 _mesa_error(ctx, GL_INVALID_VALUE, "glUniform(count < 0)");
1606 return;
1607 }
1608
1609 switch (type) {
1610 case GL_FLOAT:
1611 case GL_INT:
1612 elems = 1;
1613 break;
1614 case GL_FLOAT_VEC2:
1615 case GL_INT_VEC2:
1616 elems = 2;
1617 break;
1618 case GL_FLOAT_VEC3:
1619 case GL_INT_VEC3:
1620 elems = 3;
1621 break;
1622 case GL_FLOAT_VEC4:
1623 case GL_INT_VEC4:
1624 elems = 4;
1625 break;
1626 default:
1627 _mesa_problem(ctx, "Invalid type in _mesa_uniform");
1628 return;
1629 }
1630
1631 FLUSH_VERTICES(ctx, _NEW_PROGRAM);
1632
1633 /* A uniform var may be used by both a vertex shader and a fragment
1634 * shader. We may need to update one or both shader's uniform here:
1635 */
1636 if (shProg->VertexProgram) {
1637 /* convert uniform location to program parameter index */
1638 GLint index = shProg->Uniforms->Uniforms[location].VertPos;
1639 if (index >= 0) {
1640 set_program_uniform(ctx, &shProg->VertexProgram->Base,
1641 index, offset, type, count, elems, values);
1642 }
1643 }
1644
1645 if (shProg->FragmentProgram) {
1646 /* convert uniform location to program parameter index */
1647 GLint index = shProg->Uniforms->Uniforms[location].FragPos;
1648 if (index >= 0) {
1649 set_program_uniform(ctx, &shProg->FragmentProgram->Base,
1650 index, offset, type, count, elems, values);
1651 }
1652 }
1653 }
1654
1655
1656 /**
1657 * Set a matrix-valued program parameter.
1658 */
1659 static void
1660 set_program_uniform_matrix(GLcontext *ctx, struct gl_program *program,
1661 GLuint index, GLuint offset,
1662 GLuint count, GLuint rows, GLuint cols,
1663 GLboolean transpose, const GLfloat *values)
1664 {
1665 GLuint mat, row, col;
1666 GLuint dst = index + offset, src = 0;
1667 GLint nr, nc;
1668
1669 /* check that the number of rows, columns is correct */
1670 get_matrix_dims(program->Parameters->Parameters[index].DataType, &nr, &nc);
1671 if (rows != nr || cols != nc) {
1672 _mesa_error(ctx, GL_INVALID_OPERATION,
1673 "glUniformMatrix(matrix size mismatch)");
1674 return;
1675 }
1676
1677 if (index + offset > program->Parameters->Size) {
1678 /* out of bounds! */
1679 return;
1680 }
1681
1682 /*
1683 * Note: the _columns_ of a matrix are stored in program registers, not
1684 * the rows. So, the loops below look a little funny.
1685 * XXX could optimize this a bit...
1686 */
1687
1688 /* loop over matrices */
1689 for (mat = 0; mat < count; mat++) {
1690
1691 /* each matrix: */
1692 for (col = 0; col < cols; col++) {
1693 GLfloat *v = program->Parameters->ParameterValues[dst];
1694 for (row = 0; row < rows; row++) {
1695 if (transpose) {
1696 v[row] = values[src + row * cols + col];
1697 }
1698 else {
1699 v[row] = values[src + col * rows + row];
1700 }
1701 }
1702 dst++;
1703 }
1704
1705 src += rows * cols; /* next matrix */
1706 }
1707 }
1708
1709
1710 /**
1711 * Called by ctx->Driver.UniformMatrix().
1712 * Note: cols=2, rows=4 ==> array[2] of vec4
1713 */
1714 static void
1715 _mesa_uniform_matrix(GLcontext *ctx, GLint cols, GLint rows,
1716 GLenum matrixType, GLint location, GLsizei count,
1717 GLboolean transpose, const GLfloat *values)
1718 {
1719 GLint offset;
1720 struct gl_shader_program *shProg = ctx->Shader.CurrentProgram;
1721
1722 if (!shProg || !shProg->LinkStatus) {
1723 _mesa_error(ctx, GL_INVALID_OPERATION,
1724 "glUniformMatrix(program not linked)");
1725 return;
1726 }
1727
1728 if (location == -1)
1729 return; /* The standard specifies this as a no-op */
1730
1731 split_location_offset(&location, &offset);
1732
1733 if (location < 0 || location >= (GLint) shProg->Uniforms->NumUniforms) {
1734 _mesa_error(ctx, GL_INVALID_VALUE, "glUniformMatrix(location)");
1735 return;
1736 }
1737 if (values == NULL) {
1738 _mesa_error(ctx, GL_INVALID_VALUE, "glUniformMatrix");
1739 return;
1740 }
1741
1742 FLUSH_VERTICES(ctx, _NEW_PROGRAM);
1743
1744 if (shProg->VertexProgram) {
1745 /* convert uniform location to program parameter index */
1746 GLint index = shProg->Uniforms->Uniforms[location].VertPos;
1747 if (index >= 0) {
1748 set_program_uniform_matrix(ctx, &shProg->VertexProgram->Base,
1749 index, offset,
1750 count, rows, cols, transpose, values);
1751 }
1752 }
1753
1754 if (shProg->FragmentProgram) {
1755 /* convert uniform location to program parameter index */
1756 GLint index = shProg->Uniforms->Uniforms[location].FragPos;
1757 if (index >= 0) {
1758 set_program_uniform_matrix(ctx, &shProg->FragmentProgram->Base,
1759 index, offset,
1760 count, rows, cols, transpose, values);
1761 }
1762 }
1763 }
1764
1765
1766 static void
1767 _mesa_validate_program(GLcontext *ctx, GLuint program)
1768 {
1769 struct gl_shader_program *shProg;
1770
1771 shProg = _mesa_lookup_shader_program_err(ctx, program, "glValidateProgram");
1772 if (!shProg) {
1773 return;
1774 }
1775
1776 if (!shProg->LinkStatus) {
1777 shProg->Validated = GL_FALSE;
1778 return;
1779 }
1780
1781 /* From the GL spec, a program is invalid if any of these are true:
1782
1783 any two active samplers in the current program object are of
1784 different types, but refer to the same texture image unit,
1785
1786 any active sampler in the current program object refers to a texture
1787 image unit where fixed-function fragment processing accesses a
1788 texture target that does not match the sampler type, or
1789
1790 the sum of the number of active samplers in the program and the
1791 number of texture image units enabled for fixed-function fragment
1792 processing exceeds the combined limit on the total number of texture
1793 image units allowed.
1794 */
1795
1796 shProg->Validated = GL_TRUE;
1797 }
1798
1799
1800 /**
1801 * Plug in Mesa's GLSL functions into the device driver function table.
1802 */
1803 void
1804 _mesa_init_glsl_driver_functions(struct dd_function_table *driver)
1805 {
1806 driver->AttachShader = _mesa_attach_shader;
1807 driver->BindAttribLocation = _mesa_bind_attrib_location;
1808 driver->CompileShader = _mesa_compile_shader;
1809 driver->CreateProgram = _mesa_create_program;
1810 driver->CreateShader = _mesa_create_shader;
1811 driver->DeleteProgram2 = _mesa_delete_program2;
1812 driver->DeleteShader = _mesa_delete_shader;
1813 driver->DetachShader = _mesa_detach_shader;
1814 driver->GetActiveAttrib = _mesa_get_active_attrib;
1815 driver->GetActiveUniform = _mesa_get_active_uniform;
1816 driver->GetAttachedShaders = _mesa_get_attached_shaders;
1817 driver->GetAttribLocation = _mesa_get_attrib_location;
1818 driver->GetHandle = _mesa_get_handle;
1819 driver->GetProgramiv = _mesa_get_programiv;
1820 driver->GetProgramInfoLog = _mesa_get_program_info_log;
1821 driver->GetShaderiv = _mesa_get_shaderiv;
1822 driver->GetShaderInfoLog = _mesa_get_shader_info_log;
1823 driver->GetShaderSource = _mesa_get_shader_source;
1824 driver->GetUniformfv = _mesa_get_uniformfv;
1825 driver->GetUniformiv = _mesa_get_uniformiv;
1826 driver->GetUniformLocation = _mesa_get_uniform_location;
1827 driver->IsProgram = _mesa_is_program;
1828 driver->IsShader = _mesa_is_shader;
1829 driver->LinkProgram = _mesa_link_program;
1830 driver->ShaderSource = _mesa_shader_source;
1831 driver->Uniform = _mesa_uniform;
1832 driver->UniformMatrix = _mesa_uniform_matrix;
1833 driver->UseProgram = _mesa_use_program;
1834 driver->ValidateProgram = _mesa_validate_program;
1835 }