2 * Mesa 3-D graphics library
5 * Copyright (C) 2004-2007 Brian Paul All Rights Reserved.
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:
14 * The above copyright notice and this permission notice shall be included
15 * in all copies or substantial portions of the Software.
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.
27 * Implementation of GLSL-related API functions
33 * 1. Check that the right error code is generated for all _mesa_error() calls.
34 * 2. Insert FLUSH_VERTICES calls in various places
42 #include "prog_parameter.h"
43 #include "shader_api.h"
45 #include "slang_compile.h"
46 #include "slang_link.h"
51 * Allocate a new gl_shader_program object, initialize it.
53 struct gl_shader_program
*
54 _mesa_new_shader_program(GLcontext
*ctx
, GLuint name
)
56 struct gl_shader_program
*shProg
;
57 shProg
= CALLOC_STRUCT(gl_shader_program
);
59 shProg
->Type
= GL_SHADER_PROGRAM
;
68 _mesa_free_shader_program_data(GLcontext
*ctx
,
69 struct gl_shader_program
*shProg
)
71 assert(shProg
->Type
== GL_SHADER_PROGRAM
);
73 if (shProg
->VertexProgram
) {
74 if (shProg
->VertexProgram
->Base
.Parameters
== shProg
->Uniforms
) {
75 /* to prevent a double-free in the next call */
76 shProg
->VertexProgram
->Base
.Parameters
= NULL
;
78 _mesa_delete_program(ctx
, &shProg
->VertexProgram
->Base
);
79 shProg
->VertexProgram
= NULL
;
82 if (shProg
->FragmentProgram
) {
83 if (shProg
->FragmentProgram
->Base
.Parameters
== shProg
->Uniforms
) {
84 /* to prevent a double-free in the next call */
85 shProg
->FragmentProgram
->Base
.Parameters
= NULL
;
87 _mesa_delete_program(ctx
, &shProg
->FragmentProgram
->Base
);
88 shProg
->FragmentProgram
= NULL
;
92 if (shProg
->Uniforms
) {
93 _mesa_free_parameter_list(shProg
->Uniforms
);
94 shProg
->Uniforms
= NULL
;
97 if (shProg
->Varying
) {
98 _mesa_free_parameter_list(shProg
->Varying
);
99 shProg
->Varying
= NULL
;
106 _mesa_free_shader_program(GLcontext
*ctx
, struct gl_shader_program
*shProg
)
108 _mesa_free_shader_program_data(ctx
, shProg
);
114 * Lookup a GLSL program object.
116 struct gl_shader_program
*
117 _mesa_lookup_shader_program(GLcontext
*ctx
, GLuint name
)
119 struct gl_shader_program
*shProg
;
121 shProg
= (struct gl_shader_program
*)
122 _mesa_HashLookup(ctx
->Shared
->ShaderObjects
, name
);
123 /* Note that both gl_shader and gl_shader_program objects are kept
124 * in the same hash table. Check the object's type to be sure it's
125 * what we're expecting.
127 if (shProg
&& shProg
->Type
!= GL_SHADER_PROGRAM
) {
137 * Allocate a new gl_shader object, initialize it.
140 _mesa_new_shader(GLcontext
*ctx
, GLuint name
, GLenum type
)
142 struct gl_shader
*shader
;
143 assert(type
== GL_FRAGMENT_SHADER
|| type
== GL_VERTEX_SHADER
);
144 shader
= CALLOC_STRUCT(gl_shader
);
148 shader
->RefCount
= 1;
155 _mesa_free_shader(GLcontext
*ctx
, struct gl_shader
*sh
)
159 _mesa_free((void *) sh
->Source
);
161 _mesa_free(sh
->InfoLog
);
162 for (i
= 0; i
< sh
->NumPrograms
; i
++) {
163 assert(sh
->Programs
[i
]);
164 _mesa_delete_program(ctx
, sh
->Programs
[i
]);
167 _mesa_free(sh
->Programs
);
173 * Lookup a GLSL shader object.
176 _mesa_lookup_shader(GLcontext
*ctx
, GLuint name
)
179 struct gl_shader
*sh
= (struct gl_shader
*)
180 _mesa_HashLookup(ctx
->Shared
->ShaderObjects
, name
);
181 /* Note that both gl_shader and gl_shader_program objects are kept
182 * in the same hash table. Check the object's type to be sure it's
183 * what we're expecting.
185 if (sh
&& sh
->Type
== GL_SHADER_PROGRAM
) {
186 assert(sh
->Type
== GL_VERTEX_SHADER
||
187 sh
->Type
== GL_FRAGMENT_SHADER
);
197 _mesa_init_shader_state(GLcontext
* ctx
)
199 ctx
->Shader
._FragmentShaderPresent
= GL_FALSE
;
200 ctx
->Shader
._VertexShaderPresent
= GL_FALSE
;
208 * Copy string from <src> to <dst>, up to maxLength characters, returning
209 * length of <dst> in <length>.
210 * \param src the strings source
211 * \param maxLength max chars to copy
212 * \param length returns number of chars copied
213 * \param dst the string destination
216 copy_string(GLchar
*dst
, GLsizei maxLength
, GLsizei
*length
, const GLchar
*src
)
219 for (len
= 0; len
< maxLength
- 1 && src
&& src
[len
]; len
++)
231 * Called via ctx->Driver.AttachShader()
234 _mesa_attach_shader(GLcontext
*ctx
, GLuint program
, GLuint shader
)
236 struct gl_shader_program
*shProg
237 = _mesa_lookup_shader_program(ctx
, program
);
238 struct gl_shader
*sh
= _mesa_lookup_shader(ctx
, shader
);
239 const GLuint n
= shProg
->NumShaders
;
242 if (!shProg
|| !sh
) {
243 _mesa_error(ctx
, GL_INVALID_VALUE
,
244 "glAttachShader(bad program or shader name)");
248 for (i
= 0; i
< n
; i
++) {
249 if (shProg
->Shaders
[i
] == sh
) {
250 /* already attached */
256 shProg
->Shaders
= (struct gl_shader
**)
257 _mesa_realloc(shProg
->Shaders
,
258 n
* sizeof(struct gl_shader
*),
259 (n
+ 1) * sizeof(struct gl_shader
*));
260 if (!shProg
->Shaders
) {
261 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glAttachShader");
266 shProg
->Shaders
[n
] = sh
;
268 shProg
->NumShaders
++;
273 _mesa_bind_attrib_location(GLcontext
*ctx
, GLuint program
, GLuint index
,
276 struct gl_shader_program
*shProg
277 = _mesa_lookup_shader_program(ctx
, program
);
280 _mesa_error(ctx
, GL_INVALID_VALUE
, "glBindAttribLocation(program)");
287 if (strncmp(name
, "gl_", 3) == 0) {
288 _mesa_error(ctx
, GL_INVALID_OPERATION
,
289 "glBindAttribLocation(illegal name)");
294 if (name
== NULL
|| index
>= MAX_VERTEX_ATTRIBS
)
295 _mesa_error(ctx
, GL_INVALID_VALUE
, "glBindAttribLocationARB");
296 else if (IS_NAME_WITH_GL_PREFIX(name
))
297 _mesa_error(ctx
, GL_INVALID_OPERATION
, "glBindAttribLocationARB");
299 (**pro
).OverrideAttribBinding(pro
, index
, name
);
300 RELEASE_PROGRAM(pro
);
306 _mesa_create_shader(GLcontext
*ctx
, GLenum type
)
308 struct gl_shader
*sh
;
311 name
= _mesa_HashFindFreeKeyBlock(ctx
->Shared
->ShaderObjects
, 1);
314 case GL_FRAGMENT_SHADER
:
315 case GL_VERTEX_SHADER
:
316 sh
= _mesa_new_shader(ctx
, name
, type
);
319 _mesa_error(ctx
, GL_INVALID_ENUM
, "CreateShader(type)");
323 _mesa_HashInsert(ctx
->Shared
->ShaderObjects
, name
, sh
);
330 _mesa_create_program(GLcontext
*ctx
)
333 struct gl_shader_program
*shProg
;
335 name
= _mesa_HashFindFreeKeyBlock(ctx
->Shared
->ShaderObjects
, 1);
336 shProg
= _mesa_new_shader_program(ctx
, name
);
338 _mesa_HashInsert(ctx
->Shared
->ShaderObjects
, name
, shProg
);
345 _mesa_delete_program2(GLcontext
*ctx
, GLuint name
)
347 struct gl_shader_program
*shProg
;
349 shProg
= _mesa_lookup_shader_program(ctx
, name
);
351 _mesa_error(ctx
, GL_INVALID_VALUE
, "glDeleteProgram(name)");
355 /* always remove from hash table */
356 _mesa_HashRemove(ctx
->Shared
->ShaderObjects
, name
);
358 shProg
->DeletePending
= GL_TRUE
;
360 /* decrement refcount, delete if zero */
362 if (shProg
->RefCount
<= 0) {
363 _mesa_free_shader_program(ctx
, shProg
);
369 _mesa_delete_shader(GLcontext
*ctx
, GLuint shader
)
371 struct gl_shader
*sh
= _mesa_lookup_shader(ctx
, shader
);
376 sh
->DeletePending
= GL_TRUE
;
378 if (sh
->RefCount
<= 0) {
379 _mesa_free_shader(ctx
, sh
);
385 _mesa_detach_shader(GLcontext
*ctx
, GLuint program
, GLuint shader
)
387 struct gl_shader_program
*shProg
388 = _mesa_lookup_shader_program(ctx
, program
);
389 const GLuint n
= shProg
->NumShaders
;
393 _mesa_error(ctx
, GL_INVALID_VALUE
,
394 "glDetachShader(bad program or shader name)");
398 for (i
= 0; i
< n
; i
++) {
399 if (shProg
->Shaders
[i
]->Name
== shader
) {
400 struct gl_shader
**newList
;
403 shProg
->Shaders
[i
]->RefCount
--;
405 /* alloc new, smaller array */
406 newList
= (struct gl_shader
**)
407 _mesa_malloc((n
- 1) * sizeof(struct gl_shader
*));
409 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glDetachShader");
412 for (j
= 0; j
< i
; j
++) {
413 newList
[j
] = shProg
->Shaders
[j
];
416 newList
[j
++] = shProg
->Shaders
[i
];
417 _mesa_free(shProg
->Shaders
);
419 /* XXX refcounting! */
421 shProg
->Shaders
= newList
;
427 _mesa_error(ctx
, GL_INVALID_VALUE
,
428 "glDetachShader(shader not found)");
433 _mesa_get_active_attrib(GLcontext
*ctx
, GLuint program
, GLuint index
,
434 GLsizei maxLength
, GLsizei
*length
, GLint
*size
,
435 GLenum
*type
, GLchar
*nameOut
)
437 static const GLenum vec_types
[] = {
438 GL_FLOAT
, GL_FLOAT_VEC2
, GL_FLOAT_VEC3
, GL_FLOAT_VEC4
440 struct gl_shader_program
*shProg
441 = _mesa_lookup_shader_program(ctx
, program
);
445 _mesa_error(ctx
, GL_INVALID_VALUE
, "glGetActiveUniform");
449 if (!shProg
->Attributes
|| index
>= shProg
->Attributes
->NumParameters
) {
450 _mesa_error(ctx
, GL_INVALID_VALUE
, "glGetActiveUniform(index)");
454 copy_string(nameOut
, maxLength
, length
,
455 shProg
->Attributes
->Parameters
[index
].Name
);
456 sz
= shProg
->Attributes
->Parameters
[index
].Size
;
460 *type
= vec_types
[sz
]; /* XXX this is a temporary hack */
465 * Called via ctx->Driver.GetActiveUniform().
468 _mesa_get_active_uniform(GLcontext
*ctx
, GLuint program
, GLuint index
,
469 GLsizei maxLength
, GLsizei
*length
, GLint
*size
,
470 GLenum
*type
, GLchar
*nameOut
)
472 static const GLenum vec_types
[] = {
473 GL_FLOAT
, GL_FLOAT_VEC2
, GL_FLOAT_VEC3
, GL_FLOAT_VEC4
475 struct gl_shader_program
*shProg
476 = _mesa_lookup_shader_program(ctx
, program
);
480 _mesa_error(ctx
, GL_INVALID_VALUE
, "glGetActiveUniform");
484 if (!shProg
->Uniforms
|| index
>= shProg
->Uniforms
->NumParameters
) {
485 _mesa_error(ctx
, GL_INVALID_VALUE
, "glGetActiveUniform(index)");
489 copy_string(nameOut
, maxLength
, length
,
490 shProg
->Uniforms
->Parameters
[index
].Name
);
491 sz
= shProg
->Uniforms
->Parameters
[index
].Size
;
495 *type
= vec_types
[sz
]; /* XXX this is a temporary hack */
500 * Called via ctx->Driver.GetAttachedShaders().
503 _mesa_get_attached_shaders(GLcontext
*ctx
, GLuint program
, GLsizei maxCount
,
504 GLsizei
*count
, GLuint
*obj
)
506 struct gl_shader_program
*shProg
507 = _mesa_lookup_shader_program(ctx
, program
);
510 for (i
= 0; i
< maxCount
&& i
< shProg
->NumShaders
; i
++) {
511 obj
[i
] = shProg
->Shaders
[i
]->Name
;
517 _mesa_error(ctx
, GL_INVALID_VALUE
, "glGetAttachedShaders");
523 _mesa_get_attrib_location(GLcontext
*ctx
, GLuint program
,
526 struct gl_shader_program
*shProg
527 = _mesa_lookup_shader_program(ctx
, program
);
530 _mesa_error(ctx
, GL_INVALID_VALUE
, "glGetAttribLocation");
534 if (!shProg
->LinkStatus
) {
535 _mesa_error(ctx
, GL_INVALID_OPERATION
,
536 "glGetAttribLocation(program not linked)");
543 if (shProg
->Attributes
) {
545 for (i
= 0; i
< shProg
->Attributes
->NumParameters
; i
++) {
546 if (!strcmp(shProg
->Attributes
->Parameters
[i
].Name
, name
)) {
556 _mesa_get_handle(GLcontext
*ctx
, GLenum pname
)
559 GET_CURRENT_CONTEXT(ctx
);
562 case GL_PROGRAM_OBJECT_ARB
:
564 struct gl2_program_intf
**pro
= ctx
->Shader
.CurrentProgram
;
567 return (**pro
)._container
._generic
.
568 GetName((struct gl2_generic_intf
**) (pro
));
572 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetHandleARB");
580 _mesa_get_programiv(GLcontext
*ctx
, GLuint program
,
581 GLenum pname
, GLint
*params
)
583 struct gl_shader_program
*shProg
584 = _mesa_lookup_shader_program(ctx
, program
);
587 _mesa_error(ctx
, GL_INVALID_VALUE
, "glGetProgramiv(program)");
592 case GL_DELETE_STATUS
:
593 *params
= shProg
->DeletePending
;
596 *params
= shProg
->LinkStatus
;
598 case GL_VALIDATE_STATUS
:
599 *params
= shProg
->Validated
;
601 case GL_INFO_LOG_LENGTH
:
602 *params
= shProg
->InfoLog
? strlen(shProg
->InfoLog
) : 0;
604 case GL_ATTACHED_SHADERS
:
605 *params
= shProg
->NumShaders
;
607 case GL_ACTIVE_ATTRIBUTES
:
608 *params
= shProg
->Uniforms
? shProg
->Uniforms
->NumParameters
: 0;
610 case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH
:
611 *params
= _mesa_parameter_longest_name(shProg
->Attributes
);
613 case GL_ACTIVE_UNIFORMS
:
614 *params
= shProg
->Uniforms
? shProg
->Uniforms
->NumParameters
: 0;
616 case GL_ACTIVE_UNIFORM_MAX_LENGTH
:
617 *params
= _mesa_parameter_longest_name(shProg
->Uniforms
);
620 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetProgramiv(pname)");
627 _mesa_get_shaderiv(GLcontext
*ctx
, GLuint name
, GLenum pname
, GLint
*params
)
629 struct gl_shader
*shader
= _mesa_lookup_shader(ctx
, name
);
632 _mesa_error(ctx
, GL_INVALID_VALUE
, "glGetShaderiv(shader)");
638 *params
= shader
->Type
;
640 case GL_DELETE_STATUS
:
641 *params
= shader
->DeletePending
;
643 case GL_COMPILE_STATUS
:
644 *params
= shader
->CompileStatus
;
646 case GL_INFO_LOG_LENGTH
:
647 *params
= shader
->InfoLog
? strlen(shader
->InfoLog
) : 0;
649 case GL_SHADER_SOURCE_LENGTH
:
650 *params
= shader
->Source
? strlen((char *) shader
->Source
) : 0;
653 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetShaderiv(pname)");
660 _mesa_get_program_info_log(GLcontext
*ctx
, GLuint program
, GLsizei bufSize
,
661 GLsizei
*length
, GLchar
*infoLog
)
663 struct gl_shader_program
*shProg
664 = _mesa_lookup_shader_program(ctx
, program
);
666 _mesa_error(ctx
, GL_INVALID_VALUE
, "glGetProgramInfoLog(program)");
669 copy_string(infoLog
, bufSize
, length
, shProg
->InfoLog
);
674 _mesa_get_shader_info_log(GLcontext
*ctx
, GLuint shader
, GLsizei bufSize
,
675 GLsizei
*length
, GLchar
*infoLog
)
677 struct gl_shader
*sh
= _mesa_lookup_shader(ctx
, shader
);
679 _mesa_error(ctx
, GL_INVALID_VALUE
, "glGetShaderInfoLog(shader)");
682 copy_string(infoLog
, bufSize
, length
, sh
->InfoLog
);
687 * Called via ctx->Driver.GetShaderSource().
690 _mesa_get_shader_source(GLcontext
*ctx
, GLuint shader
, GLsizei maxLength
,
691 GLsizei
*length
, GLchar
*sourceOut
)
693 struct gl_shader
*sh
= _mesa_lookup_shader(ctx
, shader
);
695 _mesa_error(ctx
, GL_INVALID_VALUE
, "glGetShaderSource(shader)");
698 copy_string(sourceOut
, maxLength
, length
, sh
->Source
);
703 * Called via ctx->Driver.GetUniformfv().
706 _mesa_get_uniformfv(GLcontext
*ctx
, GLuint program
, GLint location
,
709 struct gl_shader_program
*shProg
710 = _mesa_lookup_shader_program(ctx
, program
);
713 if (location
>= 0 && location
< shProg
->Uniforms
->NumParameters
) {
714 for (i
= 0; i
< shProg
->Uniforms
->Parameters
[location
].Size
; i
++) {
715 params
[i
] = shProg
->Uniforms
->ParameterValues
[location
][i
];
719 _mesa_error(ctx
, GL_INVALID_VALUE
, "glGetUniformfv(location)");
723 _mesa_error(ctx
, GL_INVALID_VALUE
, "glGetUniformfv(program)");
729 * Called via ctx->Driver.GetUniformLocation().
732 _mesa_get_uniform_location(GLcontext
*ctx
, GLuint program
, const GLchar
*name
)
734 if (ctx
->Shader
.CurrentProgram
) {
735 const struct gl_shader_program
*shProg
= ctx
->Shader
.CurrentProgram
;
737 for (loc
= 0; loc
< shProg
->Uniforms
->NumParameters
; loc
++) {
738 const struct gl_program_parameter
*u
739 = shProg
->Uniforms
->Parameters
+ loc
;
740 /* XXX this is a temporary simplification / short-cut.
741 * We need to handle things like "e.c[0].b" as seen in the
742 * GLSL orange book, page 189.
744 if (u
->Type
== PROGRAM_UNIFORM
&& !strcmp(u
->Name
, name
)) {
755 _mesa_is_program(GLcontext
*ctx
, GLuint name
)
757 struct gl_shader_program
*shProg
= _mesa_lookup_shader_program(ctx
, name
);
758 return shProg
? GL_TRUE
: GL_FALSE
;
763 _mesa_is_shader(GLcontext
*ctx
, GLuint name
)
765 struct gl_shader
*shader
= _mesa_lookup_shader(ctx
, name
);
766 return shader
? GL_TRUE
: GL_FALSE
;
772 * Called via ctx->Driver.ShaderSource()
775 _mesa_shader_source(GLcontext
*ctx
, GLuint shader
, const GLchar
*source
)
777 struct gl_shader
*sh
= _mesa_lookup_shader(ctx
, shader
);
779 _mesa_error(ctx
, GL_INVALID_VALUE
, "glShaderSource(shaderObj)");
783 /* free old shader source string and install new one */
785 _mesa_free((void *) sh
->Source
);
788 sh
->CompileStatus
= GL_FALSE
;
793 * Called via ctx->Driver.CompileShader()
796 _mesa_compile_shader(GLcontext
*ctx
, GLuint shaderObj
)
798 struct gl_shader
*sh
= _mesa_lookup_shader(ctx
, shaderObj
);
801 _mesa_error(ctx
, GL_INVALID_VALUE
, "glCompileShader(shaderObj)");
805 sh
->CompileStatus
= _slang_compile(ctx
, sh
);
810 * Called via ctx->Driver.LinkProgram()
813 _mesa_link_program(GLcontext
*ctx
, GLuint program
)
815 struct gl_shader_program
*shProg
;
817 shProg
= _mesa_lookup_shader_program(ctx
, program
);
819 _mesa_error(ctx
, GL_INVALID_VALUE
, "glLinkProgram(program)");
823 _slang_link2(ctx
, program
, shProg
);
828 * Called via ctx->Driver.UseProgram()
831 _mesa_use_program(GLcontext
*ctx
, GLuint program
)
834 if (ctx
->Shader
.CurrentProgram
) {
835 ctx
->Shader
.CurrentProgram
->RefCount
--;
836 if (ctx
->Shader
.CurrentProgram
->RefCount
<= 0) {
837 _mesa_free_shader_program(ctx
, ctx
->Shader
.CurrentProgram
);
839 ctx
->Shader
.CurrentProgram
= NULL
;
842 /* XXXX need to handle reference counting here! */
844 struct gl_shader_program
*shProg
;
845 shProg
= _mesa_lookup_shader_program(ctx
, program
);
847 _mesa_error(ctx
, GL_INVALID_VALUE
,
848 "glUseProgramObjectARB(programObj)");
851 ctx
->Shader
.CurrentProgram
= shProg
;
855 /* don't use a shader program */
856 ctx
->Shader
.CurrentProgram
= NULL
;
862 * Called via ctx->Driver.Uniform().
865 _mesa_uniform(GLcontext
*ctx
, GLint location
, GLsizei count
,
866 const GLvoid
*values
, GLenum type
)
868 struct gl_shader_program
*shProg
= ctx
->Shader
.CurrentProgram
;
870 if (!shProg
|| !shProg
->LinkStatus
) {
871 _mesa_error(ctx
, GL_INVALID_OPERATION
, "glUniform(program not linked)");
875 if (location
< 0 || location
>= shProg
->Uniforms
->NumParameters
) {
876 _mesa_error(ctx
, GL_INVALID_VALUE
, "glUniform(location)");
880 FLUSH_VERTICES(ctx
, _NEW_PROGRAM
);
883 GLfloat
*v
= shProg
->Uniforms
->ParameterValues
[location
];
884 const GLfloat
*fValues
= (const GLfloat
*) values
; /* XXX */
886 if (type
== GL_FLOAT_VEC4
)
888 else if (type
== GL_FLOAT_VEC3
)
893 for (i
= 0; i
< count
; i
++)
901 * Called by ctx->Driver.UniformMatrix().
904 _mesa_uniform_matrix(GLcontext
*ctx
, GLint cols
, GLint rows
,
905 GLenum matrixType
, GLint location
, GLsizei count
,
906 GLboolean transpose
, const GLfloat
*values
)
908 struct gl_shader_program
*shProg
= ctx
->Shader
.CurrentProgram
;
909 if (!shProg
|| !shProg
->LinkStatus
) {
910 _mesa_error(ctx
, GL_INVALID_OPERATION
,
911 "glUniformMatrix(program not linked)");
914 if (location
< 0 || location
>= shProg
->Uniforms
->NumParameters
) {
915 _mesa_error(ctx
, GL_INVALID_VALUE
, "glUniformMatrix(location)");
918 if (values
== NULL
) {
919 _mesa_error(ctx
, GL_INVALID_VALUE
, "glUniformMatrix");
923 FLUSH_VERTICES(ctx
, _NEW_PROGRAM
);
926 * Note: the _columns_ of a matrix are stored in program registers, not
929 /* XXXX need to test 3x3 and 2x2 matrices... */
932 for (col
= 0; col
< cols
; col
++) {
933 GLfloat
*v
= shProg
->Uniforms
->ParameterValues
[location
+ col
];
934 for (row
= 0; row
< rows
; row
++) {
935 v
[row
] = values
[col
* rows
+ row
];
941 for (col
= 0; col
< cols
; col
++) {
942 GLfloat
*v
= shProg
->Uniforms
->ParameterValues
[location
+ col
];
943 for (row
= 0; row
< rows
; row
++) {
944 v
[row
] = values
[row
* cols
+ col
];
952 _mesa_validate_program(GLcontext
*ctx
, GLuint program
)
954 struct gl_shader_program
*shProg
;
955 shProg
= _mesa_lookup_shader_program(ctx
, program
);
957 _mesa_error(ctx
, GL_INVALID_VALUE
, "glValidateProgram(program)");
961 shProg
->Validated
= GL_TRUE
;
964 any two active samplers in the current program object are of
965 different types, but refer to the same texture image unit,
967 any active sampler in the current program object refers to a texture
968 image unit where fixed-function fragment processing accesses a
969 texture target that does not match the sampler type, or
971 the sum of the number of active samplers in the program and the
972 number of texture image units enabled for fixed-function fragment
973 processing exceeds the combined limit on the total number of texture