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