assorted code clean-ups
[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 printf("===== post BindAttrib:\n");
311 _mesa_print_program(&shProg->VertexProgram->Base);
312
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 GLuint 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 GLuint 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 if (ctx->Shader.CurrentProgram) {
744 const struct gl_shader_program *shProg = ctx->Shader.CurrentProgram;
745 GLuint loc;
746 for (loc = 0; loc < shProg->Uniforms->NumParameters; loc++) {
747 const struct gl_program_parameter *u
748 = shProg->Uniforms->Parameters + loc;
749 /* XXX this is a temporary simplification / short-cut.
750 * We need to handle things like "e.c[0].b" as seen in the
751 * GLSL orange book, page 189.
752 */
753 if ((u->Type == PROGRAM_UNIFORM ||
754 u->Type == PROGRAM_SAMPLER) && !strcmp(u->Name, name)) {
755 return loc;
756 }
757 }
758 }
759 return -1;
760
761 }
762
763
764 GLboolean
765 _mesa_is_program(GLcontext *ctx, GLuint name)
766 {
767 struct gl_shader_program *shProg = _mesa_lookup_shader_program(ctx, name);
768 return shProg ? GL_TRUE : GL_FALSE;
769 }
770
771
772 GLboolean
773 _mesa_is_shader(GLcontext *ctx, GLuint name)
774 {
775 struct gl_shader *shader = _mesa_lookup_shader(ctx, name);
776 return shader ? GL_TRUE : GL_FALSE;
777 }
778
779
780
781 /**
782 * Called via ctx->Driver.ShaderSource()
783 */
784 void
785 _mesa_shader_source(GLcontext *ctx, GLuint shader, const GLchar *source)
786 {
787 struct gl_shader *sh = _mesa_lookup_shader(ctx, shader);
788 if (!sh) {
789 _mesa_error(ctx, GL_INVALID_VALUE, "glShaderSource(shaderObj)");
790 return;
791 }
792
793 /* free old shader source string and install new one */
794 if (sh->Source) {
795 _mesa_free((void *) sh->Source);
796 }
797 sh->Source = source;
798 sh->CompileStatus = GL_FALSE;
799 }
800
801
802 /**
803 * Called via ctx->Driver.CompileShader()
804 */
805 void
806 _mesa_compile_shader(GLcontext *ctx, GLuint shaderObj)
807 {
808 struct gl_shader *sh = _mesa_lookup_shader(ctx, shaderObj);
809
810 if (!sh) {
811 _mesa_error(ctx, GL_INVALID_VALUE, "glCompileShader(shaderObj)");
812 return;
813 }
814
815 sh->CompileStatus = _slang_compile(ctx, sh);
816 }
817
818
819 /**
820 * Called via ctx->Driver.LinkProgram()
821 */
822 void
823 _mesa_link_program(GLcontext *ctx, GLuint program)
824 {
825 struct gl_shader_program *shProg;
826
827 shProg = _mesa_lookup_shader_program(ctx, program);
828 if (!shProg) {
829 _mesa_error(ctx, GL_INVALID_VALUE, "glLinkProgram(program)");
830 return;
831 }
832
833 _slang_link2(ctx, program, shProg);
834 }
835
836
837 /**
838 * Called via ctx->Driver.UseProgram()
839 */
840 void
841 _mesa_use_program(GLcontext *ctx, GLuint program)
842 {
843 /* unbind old */
844 if (ctx->Shader.CurrentProgram) {
845 ctx->Shader.CurrentProgram->RefCount--;
846 if (ctx->Shader.CurrentProgram->RefCount <= 0) {
847 _mesa_free_shader_program(ctx, ctx->Shader.CurrentProgram);
848 }
849 ctx->Shader.CurrentProgram = NULL;
850 }
851
852 if (program) {
853 struct gl_shader_program *shProg;
854 shProg = _mesa_lookup_shader_program(ctx, program);
855 if (!shProg) {
856 _mesa_error(ctx, GL_INVALID_VALUE,
857 "glUseProgramObjectARB(programObj)");
858 return;
859 }
860 ctx->Shader.CurrentProgram = shProg;
861 shProg->RefCount++;
862 }
863 else {
864 /* don't use a shader program */
865 ctx->Shader.CurrentProgram = NULL;
866 }
867 }
868
869
870 /**
871 * Called via ctx->Driver.Uniform().
872 */
873 void
874 _mesa_uniform(GLcontext *ctx, GLint location, GLsizei count,
875 const GLvoid *values, GLenum type)
876 {
877 struct gl_shader_program *shProg = ctx->Shader.CurrentProgram;
878 GLfloat *uniformVal;
879
880 if (!shProg || !shProg->LinkStatus) {
881 _mesa_error(ctx, GL_INVALID_OPERATION, "glUniform(program not linked)");
882 return;
883 }
884
885 if (location < 0 || location >= shProg->Uniforms->NumParameters) {
886 _mesa_error(ctx, GL_INVALID_VALUE, "glUniform(location)");
887 return;
888 }
889
890 FLUSH_VERTICES(ctx, _NEW_PROGRAM);
891
892 uniformVal = shProg->Uniforms->ParameterValues[location];
893
894 if (type == GL_INT ||
895 type == GL_INT_VEC2 ||
896 type == GL_INT_VEC3 ||
897 type == GL_INT_VEC4) {
898 const GLint *iValues = (const GLint *) values;
899 switch (type) {
900 case GL_INT_VEC4:
901 uniformVal[3] = (GLfloat) iValues[3];
902 /* fall-through */
903 case GL_INT_VEC3:
904 uniformVal[2] = (GLfloat) iValues[2];
905 /* fall-through */
906 case GL_INT_VEC2:
907 uniformVal[1] = (GLfloat) iValues[1];
908 /* fall-through */
909 case GL_INT:
910 uniformVal[0] = (GLfloat) iValues[0];
911 break;
912 default:
913 _mesa_problem(ctx, "Invalid type in _mesa_uniform");
914 return;
915 }
916 }
917 else {
918 const GLfloat *fValues = (const GLfloat *) values;
919 switch (type) {
920 case GL_FLOAT_VEC4:
921 uniformVal[3] = fValues[3];
922 /* fall-through */
923 case GL_FLOAT_VEC3:
924 uniformVal[2] = fValues[2];
925 /* fall-through */
926 case GL_FLOAT_VEC2:
927 uniformVal[1] = fValues[1];
928 /* fall-through */
929 case GL_FLOAT:
930 uniformVal[0] = fValues[0];
931 break;
932 default:
933 _mesa_problem(ctx, "Invalid type in _mesa_uniform");
934 return;
935 }
936 }
937
938 if (shProg->Uniforms->Parameters[location].Type == PROGRAM_SAMPLER) {
939 _slang_resolve_samplers(shProg, &shProg->VertexProgram->Base);
940 _slang_resolve_samplers(shProg, &shProg->FragmentProgram->Base);
941 FLUSH_VERTICES(ctx, _NEW_TEXTURE);
942 }
943 }
944
945
946 /**
947 * Called by ctx->Driver.UniformMatrix().
948 */
949 void
950 _mesa_uniform_matrix(GLcontext *ctx, GLint cols, GLint rows,
951 GLenum matrixType, GLint location, GLsizei count,
952 GLboolean transpose, const GLfloat *values)
953 {
954 struct gl_shader_program *shProg = ctx->Shader.CurrentProgram;
955 if (!shProg || !shProg->LinkStatus) {
956 _mesa_error(ctx, GL_INVALID_OPERATION,
957 "glUniformMatrix(program not linked)");
958 return;
959 }
960 if (location < 0 || location >= shProg->Uniforms->NumParameters) {
961 _mesa_error(ctx, GL_INVALID_VALUE, "glUniformMatrix(location)");
962 return;
963 }
964 if (values == NULL) {
965 _mesa_error(ctx, GL_INVALID_VALUE, "glUniformMatrix");
966 return;
967 }
968
969 FLUSH_VERTICES(ctx, _NEW_PROGRAM);
970
971 /*
972 * Note: the _columns_ of a matrix are stored in program registers, not
973 * the rows.
974 */
975 /* XXXX need to test 3x3 and 2x2 matrices... */
976 if (transpose) {
977 GLuint row, col;
978 for (col = 0; col < cols; col++) {
979 GLfloat *v = shProg->Uniforms->ParameterValues[location + col];
980 for (row = 0; row < rows; row++) {
981 v[row] = values[col * rows + row];
982 }
983 }
984 }
985 else {
986 GLuint row, col;
987 for (col = 0; col < cols; col++) {
988 GLfloat *v = shProg->Uniforms->ParameterValues[location + col];
989 for (row = 0; row < rows; row++) {
990 v[row] = values[row * cols + col];
991 }
992 }
993 }
994 }
995
996
997 void
998 _mesa_validate_program(GLcontext *ctx, GLuint program)
999 {
1000 struct gl_shader_program *shProg;
1001 shProg = _mesa_lookup_shader_program(ctx, program);
1002 if (!shProg) {
1003 _mesa_error(ctx, GL_INVALID_VALUE, "glValidateProgram(program)");
1004 return;
1005 }
1006 /* XXX temporary */
1007 shProg->Validated = GL_TRUE;
1008
1009 /* From the GL spec:
1010 any two active samplers in the current program object are of
1011 different types, but refer to the same texture image unit,
1012
1013 any active sampler in the current program object refers to a texture
1014 image unit where fixed-function fragment processing accesses a
1015 texture target that does not match the sampler type, or
1016
1017 the sum of the number of active samplers in the program and the
1018 number of texture image units enabled for fixed-function fragment
1019 processing exceeds the combined limit on the total number of texture
1020 image units allowed.
1021 */
1022 }