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