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 "prog_print.h"
44 #include "prog_statevars.h"
45 #include "shader_api.h"
47 #include "slang_compile.h"
48 #include "slang_link.h"
53 * Allocate a new gl_shader_program object, initialize it.
55 struct gl_shader_program
*
56 _mesa_new_shader_program(GLcontext
*ctx
, GLuint name
)
58 struct gl_shader_program
*shProg
;
59 shProg
= CALLOC_STRUCT(gl_shader_program
);
61 shProg
->Type
= GL_SHADER_PROGRAM
;
64 shProg
->Attributes
= _mesa_new_parameter_list();
71 _mesa_free_shader_program_data(GLcontext
*ctx
,
72 struct gl_shader_program
*shProg
)
74 assert(shProg
->Type
== GL_SHADER_PROGRAM
);
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
;
81 _mesa_delete_program(ctx
, &shProg
->VertexProgram
->Base
);
82 shProg
->VertexProgram
= NULL
;
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
;
90 _mesa_delete_program(ctx
, &shProg
->FragmentProgram
->Base
);
91 shProg
->FragmentProgram
= NULL
;
95 if (shProg
->Uniforms
) {
96 _mesa_free_parameter_list(shProg
->Uniforms
);
97 shProg
->Uniforms
= NULL
;
100 if (shProg
->Varying
) {
101 _mesa_free_parameter_list(shProg
->Varying
);
102 shProg
->Varying
= NULL
;
109 _mesa_free_shader_program(GLcontext
*ctx
, struct gl_shader_program
*shProg
)
111 _mesa_free_shader_program_data(ctx
, shProg
);
117 * Lookup a GLSL program object.
119 struct gl_shader_program
*
120 _mesa_lookup_shader_program(GLcontext
*ctx
, GLuint name
)
122 struct gl_shader_program
*shProg
;
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.
130 if (shProg
&& shProg
->Type
!= GL_SHADER_PROGRAM
) {
140 * Allocate a new gl_shader object, initialize it.
143 _mesa_new_shader(GLcontext
*ctx
, GLuint name
, GLenum type
)
145 struct gl_shader
*shader
;
146 assert(type
== GL_FRAGMENT_SHADER
|| type
== GL_VERTEX_SHADER
);
147 shader
= CALLOC_STRUCT(gl_shader
);
151 shader
->RefCount
= 1;
158 _mesa_free_shader(GLcontext
*ctx
, struct gl_shader
*sh
)
162 _mesa_free((void *) sh
->Source
);
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
]);
170 _mesa_free(sh
->Programs
);
176 * Lookup a GLSL shader object.
179 _mesa_lookup_shader(GLcontext
*ctx
, GLuint 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.
188 if (sh
&& sh
->Type
== GL_SHADER_PROGRAM
) {
189 assert(sh
->Type
== GL_VERTEX_SHADER
||
190 sh
->Type
== GL_FRAGMENT_SHADER
);
200 * Initialize context's shader state.
203 _mesa_init_shader_state(GLcontext
* ctx
)
205 /* Device drivers may override these to control what kind of instructions
206 * are generated by the GLSL compiler.
208 ctx
->Shader
.EmitHighLevelInstructions
= GL_TRUE
;
209 ctx
->Shader
.EmitComments
= GL_FALSE
;
214 * Copy string from <src> to <dst>, up to maxLength characters, returning
215 * length of <dst> in <length>.
216 * \param src the strings source
217 * \param maxLength max chars to copy
218 * \param length returns number of chars copied
219 * \param dst the string destination
222 copy_string(GLchar
*dst
, GLsizei maxLength
, GLsizei
*length
, const GLchar
*src
)
225 for (len
= 0; len
< maxLength
- 1 && src
&& src
[len
]; len
++)
235 * Called via ctx->Driver.AttachShader()
238 _mesa_attach_shader(GLcontext
*ctx
, GLuint program
, GLuint shader
)
240 struct gl_shader_program
*shProg
241 = _mesa_lookup_shader_program(ctx
, program
);
242 struct gl_shader
*sh
= _mesa_lookup_shader(ctx
, shader
);
243 const GLuint n
= shProg
->NumShaders
;
246 if (!shProg
|| !sh
) {
247 _mesa_error(ctx
, GL_INVALID_VALUE
,
248 "glAttachShader(bad program or shader name)");
252 for (i
= 0; i
< n
; i
++) {
253 if (shProg
->Shaders
[i
] == sh
) {
254 /* already attached */
260 shProg
->Shaders
= (struct gl_shader
**)
261 _mesa_realloc(shProg
->Shaders
,
262 n
* sizeof(struct gl_shader
*),
263 (n
+ 1) * sizeof(struct gl_shader
*));
264 if (!shProg
->Shaders
) {
265 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glAttachShader");
270 shProg
->Shaders
[n
] = sh
;
272 shProg
->NumShaders
++;
277 _mesa_bind_attrib_location(GLcontext
*ctx
, GLuint program
, GLuint index
,
280 struct gl_shader_program
*shProg
281 = _mesa_lookup_shader_program(ctx
, program
);
282 const GLint size
= -1; /* unknown size */
286 _mesa_error(ctx
, GL_INVALID_VALUE
, "glBindAttribLocation(program)");
293 if (strncmp(name
, "gl_", 3) == 0) {
294 _mesa_error(ctx
, GL_INVALID_OPERATION
,
295 "glBindAttribLocation(illegal name)");
299 oldIndex
= _mesa_get_attrib_location(ctx
, program
, name
);
301 /* this will replace the current value if it's already in the list */
302 i
= _mesa_add_attribute(shProg
->Attributes
, name
, size
, index
);
304 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glBindAttribLocation");
307 if (shProg
->VertexProgram
&& oldIndex
>= 0) {
308 _slang_remap_attribute(&shProg
->VertexProgram
->Base
, oldIndex
, index
);
312 printf("===== post BindAttrib:\n");
313 _mesa_print_program(&shProg
->VertexProgram
->Base
);
319 _mesa_create_shader(GLcontext
*ctx
, GLenum type
)
321 struct gl_shader
*sh
;
324 name
= _mesa_HashFindFreeKeyBlock(ctx
->Shared
->ShaderObjects
, 1);
327 case GL_FRAGMENT_SHADER
:
328 case GL_VERTEX_SHADER
:
329 sh
= _mesa_new_shader(ctx
, name
, type
);
332 _mesa_error(ctx
, GL_INVALID_ENUM
, "CreateShader(type)");
336 _mesa_HashInsert(ctx
->Shared
->ShaderObjects
, name
, sh
);
343 _mesa_create_program(GLcontext
*ctx
)
346 struct gl_shader_program
*shProg
;
348 name
= _mesa_HashFindFreeKeyBlock(ctx
->Shared
->ShaderObjects
, 1);
349 shProg
= _mesa_new_shader_program(ctx
, name
);
351 _mesa_HashInsert(ctx
->Shared
->ShaderObjects
, name
, shProg
);
358 _mesa_delete_program2(GLcontext
*ctx
, GLuint name
)
360 struct gl_shader_program
*shProg
;
362 shProg
= _mesa_lookup_shader_program(ctx
, name
);
364 _mesa_error(ctx
, GL_INVALID_VALUE
, "glDeleteProgram(name)");
368 /* always remove from hash table */
369 _mesa_HashRemove(ctx
->Shared
->ShaderObjects
, name
);
371 shProg
->DeletePending
= GL_TRUE
;
373 /* decrement refcount, delete if zero */
375 if (shProg
->RefCount
<= 0) {
376 _mesa_free_shader_program(ctx
, shProg
);
382 _mesa_delete_shader(GLcontext
*ctx
, GLuint shader
)
384 struct gl_shader
*sh
= _mesa_lookup_shader(ctx
, shader
);
389 sh
->DeletePending
= GL_TRUE
;
391 if (sh
->RefCount
<= 0) {
392 _mesa_free_shader(ctx
, sh
);
398 _mesa_detach_shader(GLcontext
*ctx
, GLuint program
, GLuint shader
)
400 struct gl_shader_program
*shProg
401 = _mesa_lookup_shader_program(ctx
, program
);
402 const GLuint n
= shProg
->NumShaders
;
406 _mesa_error(ctx
, GL_INVALID_VALUE
,
407 "glDetachShader(bad program or shader name)");
411 for (i
= 0; i
< n
; i
++) {
412 if (shProg
->Shaders
[i
]->Name
== shader
) {
413 struct gl_shader
**newList
;
416 shProg
->Shaders
[i
]->RefCount
--;
418 /* alloc new, smaller array */
419 newList
= (struct gl_shader
**)
420 _mesa_malloc((n
- 1) * sizeof(struct gl_shader
*));
422 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glDetachShader");
425 for (j
= 0; j
< i
; j
++) {
426 newList
[j
] = shProg
->Shaders
[j
];
429 newList
[j
++] = shProg
->Shaders
[i
];
430 _mesa_free(shProg
->Shaders
);
432 /* XXX refcounting! */
434 shProg
->Shaders
= newList
;
440 _mesa_error(ctx
, GL_INVALID_VALUE
,
441 "glDetachShader(shader not found)");
446 _mesa_get_active_attrib(GLcontext
*ctx
, GLuint program
, GLuint index
,
447 GLsizei maxLength
, GLsizei
*length
, GLint
*size
,
448 GLenum
*type
, GLchar
*nameOut
)
450 static const GLenum vec_types
[] = {
451 GL_FLOAT
, GL_FLOAT_VEC2
, GL_FLOAT_VEC3
, GL_FLOAT_VEC4
453 struct gl_shader_program
*shProg
454 = _mesa_lookup_shader_program(ctx
, program
);
458 _mesa_error(ctx
, GL_INVALID_VALUE
, "glGetActiveUniform");
462 if (!shProg
->Attributes
|| index
>= shProg
->Attributes
->NumParameters
) {
463 _mesa_error(ctx
, GL_INVALID_VALUE
, "glGetActiveUniform(index)");
467 copy_string(nameOut
, maxLength
, length
,
468 shProg
->Attributes
->Parameters
[index
].Name
);
469 sz
= shProg
->Attributes
->Parameters
[index
].Size
;
473 *type
= vec_types
[sz
]; /* XXX this is a temporary hack */
478 * Called via ctx->Driver.GetActiveUniform().
481 _mesa_get_active_uniform(GLcontext
*ctx
, GLuint program
, GLuint index
,
482 GLsizei maxLength
, GLsizei
*length
, GLint
*size
,
483 GLenum
*type
, GLchar
*nameOut
)
485 static const GLenum vec_types
[] = {
486 GL_FLOAT
, GL_FLOAT_VEC2
, GL_FLOAT_VEC3
, GL_FLOAT_VEC4
488 struct gl_shader_program
*shProg
489 = _mesa_lookup_shader_program(ctx
, program
);
493 _mesa_error(ctx
, GL_INVALID_VALUE
, "glGetActiveUniform");
497 if (!shProg
->Uniforms
|| index
>= shProg
->Uniforms
->NumParameters
) {
498 _mesa_error(ctx
, GL_INVALID_VALUE
, "glGetActiveUniform(index)");
502 copy_string(nameOut
, maxLength
, length
,
503 shProg
->Uniforms
->Parameters
[index
].Name
);
504 sz
= shProg
->Uniforms
->Parameters
[index
].Size
;
508 *type
= vec_types
[sz
]; /* XXX this is a temporary hack */
513 * Called via ctx->Driver.GetAttachedShaders().
516 _mesa_get_attached_shaders(GLcontext
*ctx
, GLuint program
, GLsizei maxCount
,
517 GLsizei
*count
, GLuint
*obj
)
519 struct gl_shader_program
*shProg
520 = _mesa_lookup_shader_program(ctx
, program
);
523 for (i
= 0; i
< maxCount
&& i
< shProg
->NumShaders
; i
++) {
524 obj
[i
] = shProg
->Shaders
[i
]->Name
;
530 _mesa_error(ctx
, GL_INVALID_VALUE
, "glGetAttachedShaders");
536 _mesa_get_attrib_location(GLcontext
*ctx
, GLuint program
,
539 struct gl_shader_program
*shProg
540 = _mesa_lookup_shader_program(ctx
, program
);
543 _mesa_error(ctx
, GL_INVALID_VALUE
, "glGetAttribLocation");
547 if (!shProg
->LinkStatus
) {
548 _mesa_error(ctx
, GL_INVALID_OPERATION
,
549 "glGetAttribLocation(program not linked)");
556 if (shProg
->Attributes
) {
557 GLint i
= _mesa_lookup_parameter_index(shProg
->Attributes
, -1, name
);
559 return shProg
->Attributes
->Parameters
[i
].StateIndexes
[0];
567 _mesa_get_handle(GLcontext
*ctx
, GLenum pname
)
570 GET_CURRENT_CONTEXT(ctx
);
573 case GL_PROGRAM_OBJECT_ARB
:
575 struct gl2_program_intf
**pro
= ctx
->Shader
.CurrentProgram
;
578 return (**pro
)._container
._generic
.
579 GetName((struct gl2_generic_intf
**) (pro
));
583 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetHandleARB");
591 _mesa_get_programiv(GLcontext
*ctx
, GLuint program
,
592 GLenum pname
, GLint
*params
)
594 struct gl_shader_program
*shProg
595 = _mesa_lookup_shader_program(ctx
, program
);
598 _mesa_error(ctx
, GL_INVALID_VALUE
, "glGetProgramiv(program)");
603 case GL_DELETE_STATUS
:
604 *params
= shProg
->DeletePending
;
607 *params
= shProg
->LinkStatus
;
609 case GL_VALIDATE_STATUS
:
610 *params
= shProg
->Validated
;
612 case GL_INFO_LOG_LENGTH
:
613 *params
= shProg
->InfoLog
? strlen(shProg
->InfoLog
) : 0;
615 case GL_ATTACHED_SHADERS
:
616 *params
= shProg
->NumShaders
;
618 case GL_ACTIVE_ATTRIBUTES
:
619 *params
= shProg
->Attributes
? shProg
->Attributes
->NumParameters
: 0;
621 case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH
:
622 *params
= _mesa_parameter_longest_name(shProg
->Attributes
);
624 case GL_ACTIVE_UNIFORMS
:
625 *params
= shProg
->Uniforms
? shProg
->Uniforms
->NumParameters
: 0;
627 case GL_ACTIVE_UNIFORM_MAX_LENGTH
:
628 *params
= _mesa_parameter_longest_name(shProg
->Uniforms
);
631 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetProgramiv(pname)");
638 _mesa_get_shaderiv(GLcontext
*ctx
, GLuint name
, GLenum pname
, GLint
*params
)
640 struct gl_shader
*shader
= _mesa_lookup_shader(ctx
, name
);
643 _mesa_error(ctx
, GL_INVALID_VALUE
, "glGetShaderiv(shader)");
649 *params
= shader
->Type
;
651 case GL_DELETE_STATUS
:
652 *params
= shader
->DeletePending
;
654 case GL_COMPILE_STATUS
:
655 *params
= shader
->CompileStatus
;
657 case GL_INFO_LOG_LENGTH
:
658 *params
= shader
->InfoLog
? strlen(shader
->InfoLog
) : 0;
660 case GL_SHADER_SOURCE_LENGTH
:
661 *params
= shader
->Source
? strlen((char *) shader
->Source
) : 0;
664 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetShaderiv(pname)");
671 _mesa_get_program_info_log(GLcontext
*ctx
, GLuint program
, GLsizei bufSize
,
672 GLsizei
*length
, GLchar
*infoLog
)
674 struct gl_shader_program
*shProg
675 = _mesa_lookup_shader_program(ctx
, program
);
677 _mesa_error(ctx
, GL_INVALID_VALUE
, "glGetProgramInfoLog(program)");
680 copy_string(infoLog
, bufSize
, length
, shProg
->InfoLog
);
685 _mesa_get_shader_info_log(GLcontext
*ctx
, GLuint shader
, GLsizei bufSize
,
686 GLsizei
*length
, GLchar
*infoLog
)
688 struct gl_shader
*sh
= _mesa_lookup_shader(ctx
, shader
);
690 _mesa_error(ctx
, GL_INVALID_VALUE
, "glGetShaderInfoLog(shader)");
693 copy_string(infoLog
, bufSize
, length
, sh
->InfoLog
);
698 * Called via ctx->Driver.GetShaderSource().
701 _mesa_get_shader_source(GLcontext
*ctx
, GLuint shader
, GLsizei maxLength
,
702 GLsizei
*length
, GLchar
*sourceOut
)
704 struct gl_shader
*sh
= _mesa_lookup_shader(ctx
, shader
);
706 _mesa_error(ctx
, GL_INVALID_VALUE
, "glGetShaderSource(shader)");
709 copy_string(sourceOut
, maxLength
, length
, sh
->Source
);
714 * Called via ctx->Driver.GetUniformfv().
717 _mesa_get_uniformfv(GLcontext
*ctx
, GLuint program
, GLint location
,
720 struct gl_shader_program
*shProg
721 = _mesa_lookup_shader_program(ctx
, program
);
724 if (location
>= 0 && location
< shProg
->Uniforms
->NumParameters
) {
725 for (i
= 0; i
< shProg
->Uniforms
->Parameters
[location
].Size
; i
++) {
726 params
[i
] = shProg
->Uniforms
->ParameterValues
[location
][i
];
730 _mesa_error(ctx
, GL_INVALID_VALUE
, "glGetUniformfv(location)");
734 _mesa_error(ctx
, GL_INVALID_VALUE
, "glGetUniformfv(program)");
740 * Called via ctx->Driver.GetUniformLocation().
743 _mesa_get_uniform_location(GLcontext
*ctx
, GLuint program
, const GLchar
*name
)
745 struct gl_shader_program
*shProg
746 = _mesa_lookup_shader_program(ctx
, program
);
749 for (loc
= 0; loc
< shProg
->Uniforms
->NumParameters
; loc
++) {
750 const struct gl_program_parameter
*u
751 = shProg
->Uniforms
->Parameters
+ loc
;
752 /* XXX this is a temporary simplification / short-cut.
753 * We need to handle things like "e.c[0].b" as seen in the
754 * GLSL orange book, page 189.
756 if ((u
->Type
== PROGRAM_UNIFORM
||
757 u
->Type
== PROGRAM_SAMPLER
) && !strcmp(u
->Name
, name
)) {
768 _mesa_is_program(GLcontext
*ctx
, GLuint name
)
770 struct gl_shader_program
*shProg
= _mesa_lookup_shader_program(ctx
, name
);
771 return shProg
? GL_TRUE
: GL_FALSE
;
776 _mesa_is_shader(GLcontext
*ctx
, GLuint name
)
778 struct gl_shader
*shader
= _mesa_lookup_shader(ctx
, name
);
779 return shader
? GL_TRUE
: GL_FALSE
;
785 * Called via ctx->Driver.ShaderSource()
788 _mesa_shader_source(GLcontext
*ctx
, GLuint shader
, const GLchar
*source
)
790 struct gl_shader
*sh
= _mesa_lookup_shader(ctx
, shader
);
792 _mesa_error(ctx
, GL_INVALID_VALUE
, "glShaderSource(shaderObj)");
796 /* free old shader source string and install new one */
798 _mesa_free((void *) sh
->Source
);
801 sh
->CompileStatus
= GL_FALSE
;
806 * Called via ctx->Driver.CompileShader()
809 _mesa_compile_shader(GLcontext
*ctx
, GLuint shaderObj
)
811 struct gl_shader
*sh
= _mesa_lookup_shader(ctx
, shaderObj
);
814 _mesa_error(ctx
, GL_INVALID_VALUE
, "glCompileShader(shaderObj)");
818 sh
->CompileStatus
= _slang_compile(ctx
, sh
);
823 * Called via ctx->Driver.LinkProgram()
826 _mesa_link_program(GLcontext
*ctx
, GLuint program
)
828 struct gl_shader_program
*shProg
;
830 shProg
= _mesa_lookup_shader_program(ctx
, program
);
832 _mesa_error(ctx
, GL_INVALID_VALUE
, "glLinkProgram(program)");
836 _slang_link(ctx
, program
, shProg
);
841 * Called via ctx->Driver.UseProgram()
844 _mesa_use_program(GLcontext
*ctx
, GLuint program
)
846 if (ctx
->Shader
.CurrentProgram
&&
847 ctx
->Shader
.CurrentProgram
->Name
== program
) {
852 FLUSH_VERTICES(ctx
, _NEW_PROGRAM
);
855 if (ctx
->Shader
.CurrentProgram
) {
856 ctx
->Shader
.CurrentProgram
->RefCount
--;
857 if (ctx
->Shader
.CurrentProgram
->RefCount
<= 0) {
858 _mesa_free_shader_program(ctx
, ctx
->Shader
.CurrentProgram
);
860 ctx
->Shader
.CurrentProgram
= NULL
;
864 struct gl_shader_program
*shProg
;
865 shProg
= _mesa_lookup_shader_program(ctx
, program
);
867 _mesa_error(ctx
, GL_INVALID_VALUE
,
868 "glUseProgramObjectARB(programObj)");
871 ctx
->Shader
.CurrentProgram
= shProg
;
875 /* don't use a shader program */
876 ctx
->Shader
.CurrentProgram
= NULL
;
882 * Called via ctx->Driver.Uniform().
885 _mesa_uniform(GLcontext
*ctx
, GLint location
, GLsizei count
,
886 const GLvoid
*values
, GLenum type
)
888 struct gl_shader_program
*shProg
= ctx
->Shader
.CurrentProgram
;
891 if (!shProg
|| !shProg
->LinkStatus
) {
892 _mesa_error(ctx
, GL_INVALID_OPERATION
, "glUniform(program not linked)");
896 if (location
< 0 || location
>= (GLint
) shProg
->Uniforms
->NumParameters
) {
897 _mesa_error(ctx
, GL_INVALID_VALUE
, "glUniform(location)");
901 FLUSH_VERTICES(ctx
, _NEW_PROGRAM
);
904 * If we're setting a sampler, we must use glUniformi1()!
906 if (shProg
->Uniforms
->Parameters
[location
].Type
== PROGRAM_SAMPLER
) {
907 if (type
!= GL_INT
|| count
!= 1) {
908 _mesa_error(ctx
, GL_INVALID_OPERATION
,
909 "glUniform(only glUniform1i can be used "
910 "to set sampler uniforms)");
915 uniformVal
= shProg
->Uniforms
->ParameterValues
[location
];
917 /* XXX obey 'count' parameter! */
919 if (type
== GL_INT
||
920 type
== GL_INT_VEC2
||
921 type
== GL_INT_VEC3
||
922 type
== GL_INT_VEC4
) {
923 const GLint
*iValues
= (const GLint
*) values
;
926 uniformVal
[3] = (GLfloat
) iValues
[3];
929 uniformVal
[2] = (GLfloat
) iValues
[2];
932 uniformVal
[1] = (GLfloat
) iValues
[1];
935 uniformVal
[0] = (GLfloat
) iValues
[0];
938 _mesa_problem(ctx
, "Invalid type in _mesa_uniform");
943 const GLfloat
*fValues
= (const GLfloat
*) values
;
946 uniformVal
[3] = fValues
[3];
949 uniformVal
[2] = fValues
[2];
952 uniformVal
[1] = fValues
[1];
955 uniformVal
[0] = fValues
[0];
958 _mesa_problem(ctx
, "Invalid type in _mesa_uniform");
963 if (shProg
->Uniforms
->Parameters
[location
].Type
== PROGRAM_SAMPLER
) {
964 if (shProg
->VertexProgram
)
965 _slang_resolve_samplers(shProg
, &shProg
->VertexProgram
->Base
);
966 if (shProg
->FragmentProgram
)
967 _slang_resolve_samplers(shProg
, &shProg
->FragmentProgram
->Base
);
968 FLUSH_VERTICES(ctx
, _NEW_TEXTURE
);
974 * Called by ctx->Driver.UniformMatrix().
977 _mesa_uniform_matrix(GLcontext
*ctx
, GLint cols
, GLint rows
,
978 GLenum matrixType
, GLint location
, GLsizei count
,
979 GLboolean transpose
, const GLfloat
*values
)
981 struct gl_shader_program
*shProg
= ctx
->Shader
.CurrentProgram
;
982 if (!shProg
|| !shProg
->LinkStatus
) {
983 _mesa_error(ctx
, GL_INVALID_OPERATION
,
984 "glUniformMatrix(program not linked)");
987 if (location
< 0 || location
>= shProg
->Uniforms
->NumParameters
) {
988 _mesa_error(ctx
, GL_INVALID_VALUE
, "glUniformMatrix(location)");
991 if (values
== NULL
) {
992 _mesa_error(ctx
, GL_INVALID_VALUE
, "glUniformMatrix");
996 FLUSH_VERTICES(ctx
, _NEW_PROGRAM
);
999 * Note: the _columns_ of a matrix are stored in program registers, not
1002 /* XXXX need to test 3x3 and 2x2 matrices... */
1005 for (col
= 0; col
< cols
; col
++) {
1006 GLfloat
*v
= shProg
->Uniforms
->ParameterValues
[location
+ col
];
1007 for (row
= 0; row
< rows
; row
++) {
1008 v
[row
] = values
[row
* cols
+ col
];
1014 for (col
= 0; col
< cols
; col
++) {
1015 GLfloat
*v
= shProg
->Uniforms
->ParameterValues
[location
+ col
];
1016 for (row
= 0; row
< rows
; row
++) {
1017 v
[row
] = values
[col
* rows
+ row
];
1025 _mesa_validate_program(GLcontext
*ctx
, GLuint program
)
1027 struct gl_shader_program
*shProg
;
1028 shProg
= _mesa_lookup_shader_program(ctx
, program
);
1030 _mesa_error(ctx
, GL_INVALID_VALUE
, "glValidateProgram(program)");
1034 shProg
->Validated
= GL_TRUE
;
1036 /* From the GL spec:
1037 any two active samplers in the current program object are of
1038 different types, but refer to the same texture image unit,
1040 any active sampler in the current program object refers to a texture
1041 image unit where fixed-function fragment processing accesses a
1042 texture target that does not match the sampler type, or
1044 the sum of the number of active samplers in the program and the
1045 number of texture image units enabled for fixed-function fragment
1046 processing exceeds the combined limit on the total number of texture
1047 image units allowed.