ab2fd438c8c585367ad8ae858ac50bfdf7fc94cc
[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 "shader_api.h"
44
45 #include "slang_compile.h"
46 #include "slang_link.h"
47
48
49
50
51
52 /**
53 * Copy string from <src> to <dst>, up to maxLength characters, returning
54 * length of <dst> in <length>.
55 * \param src the strings source
56 * \param maxLength max chars to copy
57 * \param length returns number of chars copied
58 * \param dst the string destination
59 */
60 static void
61 copy_string(GLchar *dst, GLsizei maxLength, GLsizei *length, const GLchar *src)
62 {
63 GLsizei len;
64 for (len = 0; len < maxLength - 1 && src && src[len]; len++)
65 dst[len] = src[len];
66 if (maxLength > 0)
67 dst[len] = 0;
68 if (length)
69 *length = len;
70 }
71
72
73
74
75 /**
76 * Called via ctx->Driver.AttachShader()
77 */
78 void
79 _mesa_attach_shader(GLcontext *ctx, GLuint program, GLuint shader)
80 {
81 struct gl_linked_program *linked
82 = _mesa_lookup_linked_program(ctx, program);
83 struct gl_program *prog = _mesa_lookup_shader(ctx, shader);
84 const GLuint n = linked->NumShaders;
85 GLuint i;
86
87 if (!linked || !prog) {
88 _mesa_error(ctx, GL_INVALID_OPERATION,
89 "glAttachShader(bad program or shader name)");
90 return;
91 }
92
93 for (i = 0; i < n; i++) {
94 if (linked->Shaders[i] == prog) {
95 /* already attached */
96 return;
97 }
98 }
99
100 /* grow list */
101 linked->Shaders = (struct gl_program **)
102 _mesa_realloc(linked->Shaders,
103 n * sizeof(struct gl_program *),
104 (n + 1) * sizeof(struct gl_program *));
105 if (!linked->Shaders) {
106 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glAttachShader");
107 return;
108 }
109
110 /* append */
111 linked->Shaders[n] = prog;
112 prog->RefCount++;
113 linked->NumShaders++;
114 }
115
116
117 void
118 _mesa_bind_attrib_location(GLcontext *ctx, GLuint program, GLuint index,
119 const GLchar *name)
120 {
121 struct gl_linked_program *linked
122 = _mesa_lookup_linked_program(ctx, program);
123
124 if (!linked) {
125 _mesa_error(ctx, GL_INVALID_OPERATION, "glBindAttribLocation(program)");
126 return;
127 }
128
129 #if 0 /* XXXX */
130 if (name == NULL || index >= MAX_VERTEX_ATTRIBS)
131 _mesa_error(ctx, GL_INVALID_VALUE, "glBindAttribLocationARB");
132 else if (IS_NAME_WITH_GL_PREFIX(name))
133 _mesa_error(ctx, GL_INVALID_OPERATION, "glBindAttribLocationARB");
134 else
135 (**pro).OverrideAttribBinding(pro, index, name);
136 RELEASE_PROGRAM(pro);
137 #endif
138 }
139
140
141 GLuint
142 _mesa_create_shader(GLcontext *ctx, GLenum type)
143 {
144 struct gl_program *newProg;
145 GLuint name;
146
147 name = _mesa_HashFindFreeKeyBlock(ctx->Shared->ShaderObjects, 1);
148
149 switch (type) {
150 case GL_FRAGMENT_SHADER_ARB:
151 /* alloc new gl_fragment_program */
152 newProg = ctx->Driver.NewProgram(ctx, GL_FRAGMENT_PROGRAM_ARB, name);
153 break;
154 case GL_VERTEX_SHADER_ARB:
155 /* alloc new gl_vertex_program */
156 newProg = ctx->Driver.NewProgram(ctx, GL_VERTEX_PROGRAM_ARB, name);
157 break;
158 default:
159 _mesa_error(ctx, GL_INVALID_ENUM, "CreateShader(type)");
160 return 0;
161 }
162
163 _mesa_HashInsert(ctx->Shared->ShaderObjects, name, newProg);
164
165 return name;
166 }
167
168
169 GLuint
170 _mesa_create_program(GLcontext *ctx)
171 {
172 GLuint name;
173 struct gl_linked_program *linked;
174
175 name = _mesa_HashFindFreeKeyBlock(ctx->Shared->ProgramObjects, 1);
176 linked = _mesa_new_linked_program(ctx, name);
177
178 _mesa_HashInsert(ctx->Shared->ProgramObjects, name, linked);
179
180 return name;
181 }
182
183
184 void
185 _mesa_delete_program2(GLcontext *ctx, GLuint name)
186 {
187 struct gl_linked_program *linked;
188
189 linked = _mesa_lookup_linked_program(ctx, name);
190 if (!linked) {
191 _mesa_error(ctx, GL_INVALID_OPERATION, "glDeleteProgram(name)");
192 return;
193 }
194
195 /* XXX refcounting! */
196 _mesa_HashRemove(ctx->Shared->ProgramObjects, name);
197 _mesa_delete_linked_program(ctx, linked);
198 }
199
200
201 void
202 _mesa_delete_shader(GLcontext *ctx, GLuint shader)
203 {
204 /* XXX refcounting! */
205
206 /*
207 _mesa_DeleteObjectARB(shader);
208 */
209 }
210
211
212 void
213 _mesa_detach_shader(GLcontext *ctx, GLuint program, GLuint shader)
214 {
215 struct gl_linked_program *linked
216 = _mesa_lookup_linked_program(ctx, program);
217 const GLuint n = linked->NumShaders;
218 GLuint i, j;
219
220 if (!linked) {
221 _mesa_error(ctx, GL_INVALID_OPERATION,
222 "glDetachShader(bad program or shader name)");
223 return;
224 }
225
226 for (i = 0; i < n; i++) {
227 if (linked->Shaders[i]->Id == shader) {
228 struct gl_program **newList;
229 /* found it */
230 /* alloc new, smaller array */
231 newList = (struct gl_program **)
232 _mesa_malloc((n - 1) * sizeof(struct gl_program *));
233 if (!newList) {
234 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glDetachShader");
235 return;
236 }
237 for (j = 0; j < i; j++) {
238 newList[j] = linked->Shaders[j];
239 }
240 while (++i < n)
241 newList[j++] = linked->Shaders[i];
242 _mesa_free(linked->Shaders);
243
244 /* XXX refcounting! */
245
246 linked->Shaders = newList;
247 return;
248 }
249 }
250
251 /* not found */
252 _mesa_error(ctx, GL_INVALID_OPERATION,
253 "glDetachShader(shader not found)");
254 }
255
256
257 void
258 _mesa_get_active_attrib(GLcontext *ctx, GLuint program, GLuint index,
259 GLsizei maxLength, GLsizei *length, GLint *size,
260 GLenum *type, GLchar *nameOut)
261 {
262 static const GLenum vec_types[] = {
263 GL_FLOAT, GL_FLOAT_VEC2, GL_FLOAT_VEC3, GL_FLOAT_VEC4
264 };
265 struct gl_linked_program *linked
266 = _mesa_lookup_linked_program(ctx, program);
267 GLint sz;
268
269 if (!linked) {
270 _mesa_error(ctx, GL_INVALID_OPERATION, "glGetActiveUniform");
271 return;
272 }
273
274 if (!linked->Attributes || index >= linked->Attributes->NumParameters) {
275 _mesa_error(ctx, GL_INVALID_VALUE, "glGetActiveUniform(index)");
276 return;
277 }
278
279 copy_string(nameOut, maxLength, length,
280 linked->Attributes->Parameters[index].Name);
281 sz = linked->Attributes->Parameters[index].Size;
282 if (size)
283 *size = sz;
284 if (type)
285 *type = vec_types[sz]; /* XXX this is a temporary hack */
286 }
287
288
289 /**
290 * Called via ctx->Driver.GetActiveUniform().
291 */
292 void
293 _mesa_get_active_uniform(GLcontext *ctx, GLuint program, GLuint index,
294 GLsizei maxLength, GLsizei *length, GLint *size,
295 GLenum *type, GLchar *nameOut)
296 {
297 static const GLenum vec_types[] = {
298 GL_FLOAT, GL_FLOAT_VEC2, GL_FLOAT_VEC3, GL_FLOAT_VEC4
299 };
300 struct gl_linked_program *linked
301 = _mesa_lookup_linked_program(ctx, program);
302 GLint sz;
303
304 if (!linked) {
305 _mesa_error(ctx, GL_INVALID_OPERATION, "glGetActiveUniform");
306 return;
307 }
308
309 if (!linked->Uniforms || index >= linked->Uniforms->NumParameters) {
310 _mesa_error(ctx, GL_INVALID_VALUE, "glGetActiveUniform(index)");
311 return;
312 }
313
314 copy_string(nameOut, maxLength, length,
315 linked->Uniforms->Parameters[index].Name);
316 sz = linked->Uniforms->Parameters[index].Size;
317 if (size)
318 *size = sz;
319 if (type)
320 *type = vec_types[sz]; /* XXX this is a temporary hack */
321 }
322
323
324 /**
325 * Called via ctx->Driver.GetAttachedShaders().
326 */
327 void
328 _mesa_get_attached_shaders(GLcontext *ctx, GLuint program, GLsizei maxCount,
329 GLsizei *count, GLuint *obj)
330 {
331 struct gl_linked_program *linked
332 = _mesa_lookup_linked_program(ctx, program);
333 if (linked) {
334 GLuint i;
335 for (i = 0; i < maxCount && i < linked->NumShaders; i++) {
336 obj[i] = linked->Shaders[i]->Id;
337 }
338 if (count)
339 *count = i;
340 }
341 else {
342 _mesa_error(ctx, GL_INVALID_OPERATION, "glGetAttachedShaders");
343 }
344 }
345
346
347 GLint
348 _mesa_get_attrib_location(GLcontext *ctx, GLuint program,
349 const GLchar *name)
350 {
351 struct gl_linked_program *linked
352 = _mesa_lookup_linked_program(ctx, program);
353
354 if (!linked) {
355 _mesa_error(ctx, GL_INVALID_OPERATION, "glGetAttribLocation");
356 return -1;
357 }
358
359 if (!linked->LinkStatus) {
360 _mesa_error(ctx, GL_INVALID_OPERATION,
361 "glGetAttribLocation(program not linked)");
362 return -1;
363 }
364
365 if (!name)
366 return -1;
367
368 if (linked->Attributes) {
369 GLuint i;
370 for (i = 0; i < linked->Attributes->NumParameters; i++) {
371 if (!strcmp(linked->Attributes->Parameters[i].Name, name)) {
372 return i;
373 }
374 }
375 }
376 return -1;
377 }
378
379
380 GLuint
381 _mesa_get_handle(GLcontext *ctx, GLenum pname)
382 {
383 #if 0
384 GET_CURRENT_CONTEXT(ctx);
385
386 switch (pname) {
387 case GL_PROGRAM_OBJECT_ARB:
388 {
389 struct gl2_program_intf **pro = ctx->Shader.CurrentProgram;
390
391 if (pro != NULL)
392 return (**pro)._container._generic.
393 GetName((struct gl2_generic_intf **) (pro));
394 }
395 break;
396 default:
397 _mesa_error(ctx, GL_INVALID_ENUM, "glGetHandleARB");
398 }
399 #endif
400 return 0;
401 }
402
403
404 void
405 _mesa_get_programiv(GLcontext *ctx, GLuint program,
406 GLenum pname, GLint *params)
407 {
408 struct gl_linked_program *linked
409 = _mesa_lookup_linked_program(ctx, program);
410
411 if (!linked) {
412 _mesa_error(ctx, GL_INVALID_VALUE, "glGetProgramiv(program)");
413 return;
414 }
415
416 switch (pname) {
417 case GL_DELETE_STATUS:
418 *params = linked->DeletePending;
419 break;
420 case GL_LINK_STATUS:
421 *params = linked->LinkStatus;
422 break;
423 case GL_VALIDATE_STATUS:
424 *params = linked->Validated;
425 break;
426 case GL_INFO_LOG_LENGTH:
427 *params = linked->InfoLog ? strlen(linked->InfoLog) : 0;
428 break;
429 case GL_ATTACHED_SHADERS:
430 *params = linked->NumShaders;
431 break;
432 case GL_ACTIVE_ATTRIBUTES:
433 *params = linked->Uniforms ? linked->Uniforms->NumParameters : 0;
434 break;
435 case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH:
436 *params = _mesa_parameter_longest_name(linked->Attributes);
437 break;
438 case GL_ACTIVE_UNIFORMS:
439 *params = linked->Uniforms ? linked->Uniforms->NumParameters : 0;
440 break;
441 case GL_ACTIVE_UNIFORM_MAX_LENGTH:
442 *params = _mesa_parameter_longest_name(linked->Uniforms);
443 break;
444 default:
445 _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramiv(pname)");
446 return;
447 }
448 }
449
450
451 void
452 _mesa_get_shaderiv(GLcontext *ctx, GLuint name, GLenum pname, GLint *params)
453 {
454 #if 0
455 struct gl_program *shader = _mesa_lookup_shader(ctx, name);
456
457 if (!shader) {
458 _mesa_error(ctx, GL_INVALID_VALUE, "glGetShaderiv(shader)");
459 return;
460 }
461 #else
462 struct gl_shader *shader;
463 #endif
464 switch (pname) {
465 case GL_SHADER_TYPE:
466 *params = shader->Type;
467 break;
468 case GL_DELETE_STATUS:
469 *params = shader->DeletePending;
470 break;
471 case GL_COMPILE_STATUS:
472 *params = shader->CompileStatus;
473 break;
474 case GL_INFO_LOG_LENGTH:
475 *params = shader->InfoLog ? strlen(shader->InfoLog) : 0;
476 break;
477 case GL_SHADER_SOURCE_LENGTH:
478 *params = shader->Source ? strlen((char *) shader->Source) : 0;
479 break;
480 default:
481 _mesa_error(ctx, GL_INVALID_ENUM, "glGetShaderiv(pname)");
482 return;
483 }
484 }
485
486
487 void
488 _mesa_get_program_info_log(GLcontext *ctx, GLuint program, GLsizei bufSize,
489 GLsizei *length, GLchar *infoLog)
490 {
491 struct gl_linked_program *linked
492 = _mesa_lookup_linked_program(ctx, program);
493 if (!linked) {
494 _mesa_error(ctx, GL_INVALID_VALUE, "glGetProgramInfoLog(program)");
495 return;
496 }
497 /* XXX also test length, infoLog params for NULL? */
498 copy_string(linked->InfoLog, bufSize, length, infoLog);
499 }
500
501
502 void
503 _mesa_get_shader_info_log(GLcontext *ctx, GLuint shader, GLsizei bufSize,
504 GLsizei *length, GLchar *infoLog)
505 {
506 struct gl_program *shProg = _mesa_lookup_shader(ctx, shader);
507 if (!shProg) {
508 _mesa_error(ctx, GL_INVALID_VALUE, "glGetShaderInfoLog(shader)");
509 return;
510 }
511 /*
512 copy_string(shProg->InfoLog, bufSize, length, infoLog);
513 */
514 }
515
516
517 /**
518 * Called via ctx->Driver.GetShaderSource().
519 */
520 void
521 _mesa_get_shader_source(GLcontext *ctx, GLuint shader, GLsizei maxLength,
522 GLsizei *length, GLchar *sourceOut)
523 {
524 struct gl_program *shProg = _mesa_lookup_shader(ctx, shader);
525 if (!shProg) {
526 _mesa_error(ctx, GL_INVALID_VALUE, "glGetShaderSource(shader)");
527 return;
528 }
529 copy_string((GLchar *) shProg->String, maxLength, length, sourceOut);
530 }
531
532
533 /**
534 * Called via ctx->Driver.GetUniformfv().
535 */
536 void
537 _mesa_get_uniformfv(GLcontext *ctx, GLuint program, GLint location,
538 GLfloat *params)
539 {
540 struct gl_linked_program *linked
541 = _mesa_lookup_linked_program(ctx, program);
542 if (linked) {
543 GLuint i;
544 if (location >= 0 && location < linked->Uniforms->NumParameters) {
545 for (i = 0; i < linked->Uniforms->Parameters[location].Size; i++) {
546 params[i] = linked->Uniforms->ParameterValues[location][i];
547 }
548 }
549 else {
550 _mesa_error(ctx, GL_INVALID_VALUE, "glGetUniformfv(location)");
551 }
552 }
553 else {
554 _mesa_error(ctx, GL_INVALID_OPERATION, "glGetUniformfv(program)");
555 }
556 }
557
558
559 /**
560 * Called via ctx->Driver.GetUniformLocation().
561 */
562 GLint
563 _mesa_get_uniform_location(GLcontext *ctx, GLuint program, const GLchar *name)
564 {
565 if (ctx->Shader.CurrentProgram) {
566 const struct gl_linked_program *linked = ctx->Shader.CurrentProgram;
567 GLuint loc;
568 for (loc = 0; loc < linked->Uniforms->NumParameters; loc++) {
569 const struct gl_program_parameter *u
570 = linked->Uniforms->Parameters + loc;
571 if (u->Type == PROGRAM_UNIFORM && !strcmp(u->Name, name)) {
572 return loc;
573 }
574 }
575 }
576 return -1;
577
578 }
579
580
581 GLboolean
582 _mesa_is_program(GLcontext *ctx, GLuint name)
583 {
584 struct gl_linked_program *linked = _mesa_lookup_linked_program(ctx, name);
585 return linked ? GL_TRUE : GL_FALSE;
586 }
587
588
589 GLboolean
590 _mesa_is_shader(GLcontext *ctx, GLuint name)
591 {
592 struct gl_program *shader = _mesa_lookup_shader(ctx, name);
593 return shader ? GL_TRUE : GL_FALSE;
594 }
595
596
597
598 /**
599 * Called via ctx->Driver.ShaderSource()
600 */
601 void
602 _mesa_shader_source(GLcontext *ctx, GLuint shader, const GLchar *source)
603 {
604 struct gl_program *shProg = _mesa_lookup_shader(ctx, shader);
605 if (!shProg) {
606 _mesa_error(ctx, GL_INVALID_VALUE, "glShaderSource(shaderObj)");
607 return;
608 }
609
610 /* free old shader source string and install new one */
611 if (shProg->String) {
612 _mesa_free(shProg->String);
613 }
614 shProg->String = (GLubyte *) source;
615 }
616
617
618 /**
619 * Called via ctx->Driver.CompileShader()
620 */
621 void
622 _mesa_compile_shader(GLcontext *ctx, GLuint shaderObj)
623 {
624 struct gl_program *prog = _mesa_lookup_shader(ctx, shaderObj);
625 slang_info_log info_log;
626 slang_code_object obj;
627 slang_unit_type type;
628
629 if (!prog) {
630 _mesa_error(ctx, GL_INVALID_VALUE, "glCompileShader(shaderObj)");
631 return;
632 }
633
634 slang_info_log_construct(&info_log);
635 _slang_code_object_ctr(&obj);
636
637 if (prog->Target == GL_VERTEX_PROGRAM_ARB) {
638 type = slang_unit_vertex_shader;
639 }
640 else {
641 assert(prog->Target == GL_FRAGMENT_PROGRAM_ARB);
642 type = slang_unit_fragment_shader;
643 }
644
645 if (_slang_compile((const char*) prog->String, &obj,
646 type, &info_log, prog)) {
647 /*
648 prog->CompileStatus = GL_TRUE;
649 */
650 }
651 else {
652 /*
653 prog->CompileStatus = GL_FALSE;
654 */
655 _mesa_problem(ctx, "Program did not compile!");
656 }
657 }
658
659
660 /**
661 * Called via ctx->Driver.LinkProgram()
662 */
663 void
664 _mesa_link_program(GLcontext *ctx, GLuint program)
665 {
666 struct gl_linked_program *linked;
667
668 linked = _mesa_lookup_linked_program(ctx, program);
669 if (!linked) {
670 _mesa_error(ctx, GL_INVALID_OPERATION, "glLinkProgram(program)");
671 return;
672 }
673
674 _slang_link2(ctx, program, linked);
675 }
676
677
678 /**
679 * Called via ctx->Driver.UseProgram()
680 */
681 void
682 _mesa_use_program(GLcontext *ctx, GLuint program)
683 {
684 /* XXXX need to handle reference counting here! */
685 if (program) {
686 struct gl_linked_program *linked;
687 linked = _mesa_lookup_linked_program(ctx, program);
688 if (!linked) {
689 _mesa_error(ctx, GL_INVALID_OPERATION,
690 "glUseProgramObjectARB(programObj)");
691 return;
692 }
693 ctx->Shader.CurrentProgram = linked;
694 }
695 else {
696 /* don't use a shader program */
697 ctx->Shader.CurrentProgram = NULL;
698 }
699 }
700
701
702 /**
703 * Called via ctx->Driver.Uniform().
704 */
705 void
706 _mesa_uniform(GLcontext *ctx, GLint location, GLsizei count,
707 const GLvoid *values, GLenum type)
708 {
709 if (ctx->Shader.CurrentProgram) {
710 struct gl_linked_program *linked = ctx->Shader.CurrentProgram;
711 if (location >= 0 && location < linked->Uniforms->NumParameters) {
712 GLfloat *v = linked->Uniforms->ParameterValues[location];
713 const GLfloat *fValues = (const GLfloat *) values; /* XXX */
714 GLint i;
715 if (type == GL_FLOAT_VEC4)
716 count *= 4;
717 else if (type == GL_FLOAT_VEC3)
718 count *= 3;
719 else
720 abort();
721
722 for (i = 0; i < count; i++)
723 v[i] = fValues[i];
724 return;
725 }
726 }
727 else {
728 _mesa_error(ctx, GL_INVALID_OPERATION, "glUniform(program not linked)");
729 }
730 }
731
732
733 /**
734 * Called by ctx->Driver.UniformMatrix().
735 */
736 void
737 _mesa_uniform_matrix(GLcontext *ctx, GLint cols, GLint rows,
738 GLenum matrixType, GLint location, GLsizei count,
739 GLboolean transpose, const GLfloat *values)
740 {
741 const char *caller = "glUniformMatrix";
742 const GLint matElements = rows * cols;
743
744 if (values == NULL) {
745 _mesa_error(ctx, GL_INVALID_VALUE, caller);
746 return;
747 }
748
749 FLUSH_VERTICES(ctx, _NEW_PROGRAM);
750
751 if (transpose) {
752 GLfloat *trans, *pt;
753 const GLfloat *pv;
754 GLint i, j, k;
755
756 trans = (GLfloat *) _mesa_malloc(count * matElements * sizeof(GLfloat));
757 if (!trans) {
758 _mesa_error(ctx, GL_OUT_OF_MEMORY, caller);
759 return;
760 }
761
762 pt = trans;
763 pv = values;
764 for (i = 0; i < count; i++) {
765 /* transpose from pv matrix into pt matrix */
766 for (j = 0; j < cols; j++) {
767 for (k = 0; k < rows; k++) {
768 /* XXX verify this */
769 pt[j * rows + k] = pv[k * cols + j];
770 }
771 }
772 pt += matElements;
773 pv += matElements;
774 }
775
776 #ifdef OLD
777 if (!(**pro).WriteUniform(pro, location, count, trans, matrixType))
778 _mesa_error(ctx, GL_INVALID_OPERATION, caller);
779 #endif
780 _mesa_free(trans);
781 }
782 else {
783 #ifdef OLD
784 if (!(**pro).WriteUniform(pro, location, count, values, matrixType))
785 _mesa_error(ctx, GL_INVALID_OPERATION, caller);
786 #endif
787 }
788 }
789
790
791 void
792 _mesa_validate_program(GLcontext *ctx, GLuint program)
793 {
794 struct gl_linked_program *linked;
795 linked = _mesa_lookup_linked_program(ctx, program);
796 if (!linked) {
797 _mesa_error(ctx, GL_INVALID_OPERATION, "glValidateProgram(program)");
798 return;
799 }
800 /* XXX temporary */
801 linked->Validated = GL_TRUE;
802
803 /* From the GL spec:
804 any two active samplers in the current program object are of
805 different types, but refer to the same texture image unit,
806
807 any active sampler in the current program object refers to a texture
808 image unit where fixed-function fragment processing accesses a
809 texture target that does not match the sampler type, or
810
811 the sum of the number of active samplers in the program and the
812 number of texture image units enabled for fixed-function fragment
813 processing exceeds the combined limit on the total number of texture
814 image units allowed.
815 */
816 }
817
818
819
820 /**********************************************************************/
821
822
823 /**
824 * Create a new GLSL program object.
825 */
826 struct gl_linked_program *
827 _mesa_new_linked_program(GLcontext *ctx, GLuint name)
828 {
829 struct gl_linked_program *linked;
830 linked = CALLOC_STRUCT(gl_linked_program);
831 if (linked) {
832 linked->Name = name;
833 }
834 return linked;
835 }
836
837
838 void
839 _mesa_free_linked_program_data(GLcontext *ctx,
840 struct gl_linked_program *linked)
841 {
842 if (linked->VertexProgram) {
843 if (linked->VertexProgram->Base.Parameters == linked->Uniforms) {
844 /* to prevent a double-free in the next call */
845 linked->VertexProgram->Base.Parameters = NULL;
846 }
847 _mesa_delete_program(ctx, &linked->VertexProgram->Base);
848 linked->VertexProgram = NULL;
849 }
850
851 if (linked->FragmentProgram) {
852 if (linked->FragmentProgram->Base.Parameters == linked->Uniforms) {
853 /* to prevent a double-free in the next call */
854 linked->FragmentProgram->Base.Parameters = NULL;
855 }
856 _mesa_delete_program(ctx, &linked->FragmentProgram->Base);
857 linked->FragmentProgram = NULL;
858 }
859
860
861 if (linked->Uniforms) {
862 _mesa_free_parameter_list(linked->Uniforms);
863 linked->Uniforms = NULL;
864 }
865
866 if (linked->Varying) {
867 _mesa_free_parameter_list(linked->Varying);
868 linked->Varying = NULL;
869 }
870 }
871
872
873
874 void
875 _mesa_delete_linked_program(GLcontext *ctx, struct gl_linked_program *linked)
876 {
877 _mesa_free_linked_program_data(ctx, linked);
878 _mesa_free(linked);
879 }
880
881
882 /**
883 * Lookup a GLSL program object.
884 */
885 struct gl_linked_program *
886 _mesa_lookup_linked_program(GLcontext *ctx, GLuint name)
887 {
888 if (name)
889 return (struct gl_linked_program *)
890 _mesa_HashLookup(ctx->Shared->ProgramObjects, name);
891 else
892 return NULL;
893 }
894
895
896 struct gl_shader *
897 _mesa_new_shader(GLcontext *ctx, GLuint name, GLenum type)
898 {
899 struct gl_shader *shader;
900 assert(type == GL_FRAGMENT_SHADER || type == GL_VERTEX_SHADER);
901 shader = CALLOC_STRUCT(gl_shader);
902 if (shader) {
903 shader->Name = name;
904 shader->Type = type;
905 }
906 return shader;
907 }
908
909
910 /**
911 * Lookup a GLSL shader object.
912 */
913 struct gl_program *
914 _mesa_lookup_shader(GLcontext *ctx, GLuint name)
915 {
916 if (name)
917 return (struct gl_program *)
918 _mesa_HashLookup(ctx->Shared->ShaderObjects, name);
919 else
920 return NULL;
921 }
922
923
924 void
925 _mesa_init_shader_state(GLcontext * ctx)
926 {
927 ctx->Shader._FragmentShaderPresent = GL_FALSE;
928 ctx->Shader._VertexShaderPresent = GL_FALSE;
929 }