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