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