2 * Mesa 3-D graphics library
5 * Copyright (C) 2004-2008 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.
29 #include "shader/shader_api.h"
32 /** Define this to enable shader substitution (see below) */
33 #define SHADER_SUBST 0
38 * These are basically just wrappers/adaptors for calling the
39 * ctx->Driver.foobar() GLSL-related functions.
41 * Things are biased toward the OpenGL 2.0 functions rather than the
42 * ARB extensions (i.e. the ARB functions are layered on the 2.0 functions).
44 * The general idea here is to allow enough modularity such that a
45 * completely different GLSL implemenation can be plugged in and co-exist
46 * with Mesa's native GLSL code.
52 _mesa_AttachObjectARB(GLhandleARB program
, GLhandleARB shader
)
54 GET_CURRENT_CONTEXT(ctx
);
55 ctx
->Driver
.AttachShader(ctx
, program
, shader
);
60 _mesa_AttachShader(GLuint program
, GLuint shader
)
62 GET_CURRENT_CONTEXT(ctx
);
63 ctx
->Driver
.AttachShader(ctx
, program
, shader
);
68 _mesa_BindAttribLocationARB(GLhandleARB program
, GLuint index
,
69 const GLcharARB
*name
)
71 GET_CURRENT_CONTEXT(ctx
);
72 ctx
->Driver
.BindAttribLocation(ctx
, program
, index
, name
);
77 _mesa_CompileShaderARB(GLhandleARB shaderObj
)
79 GET_CURRENT_CONTEXT(ctx
);
80 ctx
->Driver
.CompileShader(ctx
, shaderObj
);
85 _mesa_CreateShader(GLenum type
)
87 GET_CURRENT_CONTEXT(ctx
);
88 return ctx
->Driver
.CreateShader(ctx
, type
);
92 GLhandleARB GLAPIENTRY
93 _mesa_CreateShaderObjectARB(GLenum type
)
95 GET_CURRENT_CONTEXT(ctx
);
96 return ctx
->Driver
.CreateShader(ctx
, type
);
101 _mesa_CreateProgram(void)
103 GET_CURRENT_CONTEXT(ctx
);
104 return ctx
->Driver
.CreateProgram(ctx
);
108 GLhandleARB GLAPIENTRY
109 _mesa_CreateProgramObjectARB(void)
111 GET_CURRENT_CONTEXT(ctx
);
112 return ctx
->Driver
.CreateProgram(ctx
);
117 _mesa_DeleteObjectARB(GLhandleARB obj
)
120 GET_CURRENT_CONTEXT(ctx
);
121 if (ctx
->Driver
.IsProgram(ctx
, obj
)) {
122 ctx
->Driver
.DeleteProgram2(ctx
, obj
);
124 else if (ctx
->Driver
.IsShader(ctx
, obj
)) {
125 ctx
->Driver
.DeleteShader(ctx
, obj
);
135 _mesa_DeleteProgram(GLuint name
)
138 GET_CURRENT_CONTEXT(ctx
);
139 ctx
->Driver
.DeleteProgram2(ctx
, name
);
145 _mesa_DeleteShader(GLuint name
)
148 GET_CURRENT_CONTEXT(ctx
);
149 ctx
->Driver
.DeleteShader(ctx
, name
);
155 _mesa_DetachObjectARB(GLhandleARB program
, GLhandleARB shader
)
157 GET_CURRENT_CONTEXT(ctx
);
158 ctx
->Driver
.DetachShader(ctx
, program
, shader
);
163 _mesa_DetachShader(GLuint program
, GLuint shader
)
165 GET_CURRENT_CONTEXT(ctx
);
166 ctx
->Driver
.DetachShader(ctx
, program
, shader
);
171 _mesa_GetActiveAttribARB(GLhandleARB program
, GLuint index
,
172 GLsizei maxLength
, GLsizei
* length
, GLint
* size
,
173 GLenum
* type
, GLcharARB
* name
)
175 GET_CURRENT_CONTEXT(ctx
);
176 ctx
->Driver
.GetActiveAttrib(ctx
, program
, index
, maxLength
, length
, size
,
182 _mesa_GetActiveUniformARB(GLhandleARB program
, GLuint index
,
183 GLsizei maxLength
, GLsizei
* length
, GLint
* size
,
184 GLenum
* type
, GLcharARB
* name
)
186 GET_CURRENT_CONTEXT(ctx
);
187 ctx
->Driver
.GetActiveUniform(ctx
, program
, index
, maxLength
, length
, size
,
193 _mesa_GetAttachedObjectsARB(GLhandleARB container
, GLsizei maxCount
,
194 GLsizei
* count
, GLhandleARB
* obj
)
196 GET_CURRENT_CONTEXT(ctx
);
197 ctx
->Driver
.GetAttachedShaders(ctx
, container
, maxCount
, count
, obj
);
202 _mesa_GetAttachedShaders(GLuint program
, GLsizei maxCount
,
203 GLsizei
*count
, GLuint
*obj
)
205 GET_CURRENT_CONTEXT(ctx
);
206 ctx
->Driver
.GetAttachedShaders(ctx
, program
, maxCount
, count
, obj
);
211 _mesa_GetAttribLocationARB(GLhandleARB program
, const GLcharARB
* name
)
213 GET_CURRENT_CONTEXT(ctx
);
214 return ctx
->Driver
.GetAttribLocation(ctx
, program
, name
);
219 _mesa_GetInfoLogARB(GLhandleARB object
, GLsizei maxLength
, GLsizei
* length
,
222 GET_CURRENT_CONTEXT(ctx
);
223 /* Implement in terms of GetProgramInfoLog, GetShaderInfoLog */
224 if (ctx
->Driver
.IsProgram(ctx
, object
)) {
225 ctx
->Driver
.GetProgramInfoLog(ctx
, object
, maxLength
, length
, infoLog
);
227 else if (ctx
->Driver
.IsShader(ctx
, object
)) {
228 ctx
->Driver
.GetShaderInfoLog(ctx
, object
, maxLength
, length
, infoLog
);
231 _mesa_error(ctx
, GL_INVALID_OPERATION
, "glGetInfoLogARB");
237 _mesa_GetObjectParameterivARB(GLhandleARB object
, GLenum pname
, GLint
*params
)
239 GET_CURRENT_CONTEXT(ctx
);
240 /* Implement in terms of GetProgramiv, GetShaderiv */
241 if (ctx
->Driver
.IsProgram(ctx
, object
)) {
242 if (pname
== GL_OBJECT_TYPE_ARB
) {
243 *params
= GL_PROGRAM_OBJECT_ARB
;
246 ctx
->Driver
.GetProgramiv(ctx
, object
, pname
, params
);
249 else if (ctx
->Driver
.IsShader(ctx
, object
)) {
250 if (pname
== GL_OBJECT_TYPE_ARB
) {
251 *params
= GL_SHADER_OBJECT_ARB
;
254 ctx
->Driver
.GetShaderiv(ctx
, object
, pname
, params
);
258 _mesa_error(ctx
, GL_INVALID_VALUE
, "glGetObjectParameterivARB");
264 _mesa_GetObjectParameterfvARB(GLhandleARB object
, GLenum pname
,
267 GLint iparams
[1]; /* XXX is one element enough? */
268 _mesa_GetObjectParameterivARB(object
, pname
, iparams
);
269 params
[0] = (GLfloat
) iparams
[0];
274 _mesa_GetProgramiv(GLuint program
, GLenum pname
, GLint
*params
)
276 GET_CURRENT_CONTEXT(ctx
);
277 ctx
->Driver
.GetProgramiv(ctx
, program
, pname
, params
);
282 _mesa_GetShaderiv(GLuint shader
, GLenum pname
, GLint
*params
)
284 GET_CURRENT_CONTEXT(ctx
);
285 ctx
->Driver
.GetShaderiv(ctx
, shader
, pname
, params
);
290 _mesa_GetProgramInfoLog(GLuint program
, GLsizei bufSize
,
291 GLsizei
*length
, GLchar
*infoLog
)
293 GET_CURRENT_CONTEXT(ctx
);
294 ctx
->Driver
.GetProgramInfoLog(ctx
, program
, bufSize
, length
, infoLog
);
299 _mesa_GetShaderInfoLog(GLuint shader
, GLsizei bufSize
,
300 GLsizei
*length
, GLchar
*infoLog
)
302 GET_CURRENT_CONTEXT(ctx
);
303 ctx
->Driver
.GetShaderInfoLog(ctx
, shader
, bufSize
, length
, infoLog
);
308 _mesa_GetShaderSourceARB(GLhandleARB shader
, GLsizei maxLength
,
309 GLsizei
*length
, GLcharARB
*sourceOut
)
311 GET_CURRENT_CONTEXT(ctx
);
312 ctx
->Driver
.GetShaderSource(ctx
, shader
, maxLength
, length
, sourceOut
);
317 _mesa_GetUniformfvARB(GLhandleARB program
, GLint location
, GLfloat
* params
)
319 GET_CURRENT_CONTEXT(ctx
);
320 ctx
->Driver
.GetUniformfv(ctx
, program
, location
, params
);
325 _mesa_GetUniformivARB(GLhandleARB program
, GLint location
, GLint
* params
)
327 GET_CURRENT_CONTEXT(ctx
);
328 ctx
->Driver
.GetUniformiv(ctx
, program
, location
, params
);
335 _mesa_GetUniformLocation(GLuint program
, const GLcharARB
*name
)
337 GET_CURRENT_CONTEXT(ctx
);
338 return ctx
->Driver
.GetUniformLocation(ctx
, program
, name
);
343 GLhandleARB GLAPIENTRY
344 _mesa_GetHandleARB(GLenum pname
)
346 GET_CURRENT_CONTEXT(ctx
);
347 return ctx
->Driver
.GetHandle(ctx
, pname
);
352 _mesa_GetUniformLocationARB(GLhandleARB programObj
, const GLcharARB
*name
)
354 GET_CURRENT_CONTEXT(ctx
);
355 return ctx
->Driver
.GetUniformLocation(ctx
, programObj
, name
);
360 _mesa_IsProgram(GLuint name
)
362 GET_CURRENT_CONTEXT(ctx
);
363 return ctx
->Driver
.IsProgram(ctx
, name
);
368 _mesa_IsShader(GLuint name
)
370 GET_CURRENT_CONTEXT(ctx
);
371 return ctx
->Driver
.IsShader(ctx
, name
);
376 _mesa_LinkProgramARB(GLhandleARB programObj
)
378 GET_CURRENT_CONTEXT(ctx
);
379 ctx
->Driver
.LinkProgram(ctx
, programObj
);
385 * Read shader source code from a file.
386 * Useful for debugging to override an app's shader.
389 _mesa_read_shader(const char *fname
)
391 const int max
= 50*1000;
392 FILE *f
= fopen(fname
, "r");
393 GLcharARB
*buffer
, *shader
;
400 buffer
= (char *) malloc(max
);
401 len
= fread(buffer
, 1, max
, f
);
406 shader
= _mesa_strdup(buffer
);
414 * Called via glShaderSource() and glShaderSourceARB() API functions.
415 * Basically, concatenate the source code strings into one long string
416 * and pass it to ctx->Driver.ShaderSource().
419 _mesa_ShaderSourceARB(GLhandleARB shaderObj
, GLsizei count
,
420 const GLcharARB
** string
, const GLint
* length
)
422 GET_CURRENT_CONTEXT(ctx
);
424 GLsizei i
, totalLength
;
428 if (!shaderObj
|| string
== NULL
) {
429 _mesa_error(ctx
, GL_INVALID_VALUE
, "glShaderSourceARB");
434 * This array holds offsets of where the appropriate string ends, thus the
435 * last element will be set to the total length of the source code.
437 offsets
= (GLint
*) _mesa_malloc(count
* sizeof(GLint
));
438 if (offsets
== NULL
) {
439 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glShaderSourceARB");
443 for (i
= 0; i
< count
; i
++) {
444 if (string
[i
] == NULL
) {
445 _mesa_free((GLvoid
*) offsets
);
446 _mesa_error(ctx
, GL_INVALID_OPERATION
, "glShaderSourceARB(null string)");
449 if (length
== NULL
|| length
[i
] < 0)
450 offsets
[i
] = _mesa_strlen(string
[i
]);
452 offsets
[i
] = length
[i
];
453 /* accumulate string lengths */
455 offsets
[i
] += offsets
[i
- 1];
458 /* Total length of source string is sum off all strings plus two.
459 * One extra byte for terminating zero, another extra byte to silence
460 * valgrind warnings in the parser/grammer code.
462 totalLength
= offsets
[count
- 1] + 2;
463 source
= (GLcharARB
*) _mesa_malloc(totalLength
* sizeof(GLcharARB
));
464 if (source
== NULL
) {
465 _mesa_free((GLvoid
*) offsets
);
466 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glShaderSourceARB");
470 for (i
= 0; i
< count
; i
++) {
471 GLint start
= (i
> 0) ? offsets
[i
- 1] : 0;
472 _mesa_memcpy(source
+ start
, string
[i
],
473 (offsets
[i
] - start
) * sizeof(GLcharARB
));
475 source
[totalLength
- 1] = '\0';
476 source
[totalLength
- 2] = '\0';
479 /* Compute the shader's source code checksum then try to open a file
480 * named newshader_<CHECKSUM>. If it exists, use it in place of the
481 * original shader source code. For debugging.
484 GLcharARB
*newSource
;
486 checksum
= _mesa_str_checksum(source
);
488 sprintf(filename
, "newshader_%d", checksum
);
490 newSource
= _mesa_read_shader(filename
);
492 _mesa_fprintf(stderr
, "Mesa: Replacing shader %u chksum=%d with %s\n",
493 shaderObj
, checksum
, filename
);
499 ctx
->Driver
.ShaderSource(ctx
, shaderObj
, source
);
502 struct gl_shader
*sh
= _mesa_lookup_shader(ctx
, shaderObj
);
504 sh
->SourceChecksum
= checksum
; /* save original checksum */
512 _mesa_Uniform1fARB(GLint location
, GLfloat v0
)
514 GET_CURRENT_CONTEXT(ctx
);
515 ctx
->Driver
.Uniform(ctx
, location
, 1, &v0
, GL_FLOAT
);
519 _mesa_Uniform2fARB(GLint location
, GLfloat v0
, GLfloat v1
)
521 GET_CURRENT_CONTEXT(ctx
);
525 ctx
->Driver
.Uniform(ctx
, location
, 1, v
, GL_FLOAT_VEC2
);
529 _mesa_Uniform3fARB(GLint location
, GLfloat v0
, GLfloat v1
, GLfloat v2
)
531 GET_CURRENT_CONTEXT(ctx
);
536 ctx
->Driver
.Uniform(ctx
, location
, 1, v
, GL_FLOAT_VEC3
);
540 _mesa_Uniform4fARB(GLint location
, GLfloat v0
, GLfloat v1
, GLfloat v2
,
543 GET_CURRENT_CONTEXT(ctx
);
549 ctx
->Driver
.Uniform(ctx
, location
, 1, v
, GL_FLOAT_VEC4
);
553 _mesa_Uniform1iARB(GLint location
, GLint v0
)
555 GET_CURRENT_CONTEXT(ctx
);
556 ctx
->Driver
.Uniform(ctx
, location
, 1, &v0
, GL_INT
);
560 _mesa_Uniform2iARB(GLint location
, GLint v0
, GLint v1
)
562 GET_CURRENT_CONTEXT(ctx
);
566 ctx
->Driver
.Uniform(ctx
, location
, 1, v
, GL_INT_VEC2
);
570 _mesa_Uniform3iARB(GLint location
, GLint v0
, GLint v1
, GLint v2
)
572 GET_CURRENT_CONTEXT(ctx
);
577 ctx
->Driver
.Uniform(ctx
, location
, 1, v
, GL_INT_VEC3
);
581 _mesa_Uniform4iARB(GLint location
, GLint v0
, GLint v1
, GLint v2
, GLint v3
)
583 GET_CURRENT_CONTEXT(ctx
);
589 ctx
->Driver
.Uniform(ctx
, location
, 1, v
, GL_INT_VEC4
);
593 _mesa_Uniform1fvARB(GLint location
, GLsizei count
, const GLfloat
* value
)
595 GET_CURRENT_CONTEXT(ctx
);
596 ctx
->Driver
.Uniform(ctx
, location
, count
, value
, GL_FLOAT
);
600 _mesa_Uniform2fvARB(GLint location
, GLsizei count
, const GLfloat
* value
)
602 GET_CURRENT_CONTEXT(ctx
);
603 ctx
->Driver
.Uniform(ctx
, location
, count
, value
, GL_FLOAT_VEC2
);
607 _mesa_Uniform3fvARB(GLint location
, GLsizei count
, const GLfloat
* value
)
609 GET_CURRENT_CONTEXT(ctx
);
610 ctx
->Driver
.Uniform(ctx
, location
, count
, value
, GL_FLOAT_VEC3
);
614 _mesa_Uniform4fvARB(GLint location
, GLsizei count
, const GLfloat
* value
)
616 GET_CURRENT_CONTEXT(ctx
);
617 ctx
->Driver
.Uniform(ctx
, location
, count
, value
, GL_FLOAT_VEC4
);
621 _mesa_Uniform1ivARB(GLint location
, GLsizei count
, const GLint
* value
)
623 GET_CURRENT_CONTEXT(ctx
);
624 ctx
->Driver
.Uniform(ctx
, location
, count
, value
, GL_INT
);
628 _mesa_Uniform2ivARB(GLint location
, GLsizei count
, const GLint
* value
)
630 GET_CURRENT_CONTEXT(ctx
);
631 ctx
->Driver
.Uniform(ctx
, location
, count
, value
, GL_INT_VEC2
);
635 _mesa_Uniform3ivARB(GLint location
, GLsizei count
, const GLint
* value
)
637 GET_CURRENT_CONTEXT(ctx
);
638 ctx
->Driver
.Uniform(ctx
, location
, count
, value
, GL_INT_VEC3
);
642 _mesa_Uniform4ivARB(GLint location
, GLsizei count
, const GLint
* value
)
644 GET_CURRENT_CONTEXT(ctx
);
645 ctx
->Driver
.Uniform(ctx
, location
, count
, value
, GL_INT_VEC4
);
650 _mesa_UniformMatrix2fvARB(GLint location
, GLsizei count
, GLboolean transpose
,
651 const GLfloat
* value
)
653 GET_CURRENT_CONTEXT(ctx
);
654 ctx
->Driver
.UniformMatrix(ctx
, 2, 2, location
, count
, transpose
, value
);
658 _mesa_UniformMatrix3fvARB(GLint location
, GLsizei count
, GLboolean transpose
,
659 const GLfloat
* value
)
661 GET_CURRENT_CONTEXT(ctx
);
662 ctx
->Driver
.UniformMatrix(ctx
, 3, 3, location
, count
, transpose
, value
);
666 _mesa_UniformMatrix4fvARB(GLint location
, GLsizei count
, GLboolean transpose
,
667 const GLfloat
* value
)
669 GET_CURRENT_CONTEXT(ctx
);
670 ctx
->Driver
.UniformMatrix(ctx
, 4, 4, location
, count
, transpose
, value
);
675 * Non-square UniformMatrix are OpenGL 2.1
678 _mesa_UniformMatrix2x3fv(GLint location
, GLsizei count
, GLboolean transpose
,
679 const GLfloat
*value
)
681 GET_CURRENT_CONTEXT(ctx
);
682 ctx
->Driver
.UniformMatrix(ctx
, 2, 3, location
, count
, transpose
, value
);
686 _mesa_UniformMatrix3x2fv(GLint location
, GLsizei count
, GLboolean transpose
,
687 const GLfloat
*value
)
689 GET_CURRENT_CONTEXT(ctx
);
690 ctx
->Driver
.UniformMatrix(ctx
, 3, 2, location
, count
, transpose
, value
);
694 _mesa_UniformMatrix2x4fv(GLint location
, GLsizei count
, GLboolean transpose
,
695 const GLfloat
*value
)
697 GET_CURRENT_CONTEXT(ctx
);
698 ctx
->Driver
.UniformMatrix(ctx
, 2, 4, location
, count
, transpose
, value
);
702 _mesa_UniformMatrix4x2fv(GLint location
, GLsizei count
, GLboolean transpose
,
703 const GLfloat
*value
)
705 GET_CURRENT_CONTEXT(ctx
);
706 ctx
->Driver
.UniformMatrix(ctx
, 4, 2, location
, count
, transpose
, value
);
710 _mesa_UniformMatrix3x4fv(GLint location
, GLsizei count
, GLboolean transpose
,
711 const GLfloat
*value
)
713 GET_CURRENT_CONTEXT(ctx
);
714 ctx
->Driver
.UniformMatrix(ctx
, 3, 4, location
, count
, transpose
, value
);
718 _mesa_UniformMatrix4x3fv(GLint location
, GLsizei count
, GLboolean transpose
,
719 const GLfloat
*value
)
721 GET_CURRENT_CONTEXT(ctx
);
722 ctx
->Driver
.UniformMatrix(ctx
, 4, 3, location
, count
, transpose
, value
);
727 _mesa_UseProgramObjectARB(GLhandleARB program
)
729 GET_CURRENT_CONTEXT(ctx
);
730 FLUSH_VERTICES(ctx
, _NEW_PROGRAM
);
731 ctx
->Driver
.UseProgram(ctx
, program
);
736 _mesa_ValidateProgramARB(GLhandleARB program
)
738 GET_CURRENT_CONTEXT(ctx
);
739 ctx
->Driver
.ValidateProgram(ctx
, program
);