X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fmesa%2Fmain%2Fshaderapi.c;h=2ffd8be0eb40aad83240989d83dc9d4c28022211;hb=7f48278edc70ad0841cbee2c46add7653b4fac15;hp=1335f0f4111f0858d627e1a0d56e766962c0c01e;hpb=001a7bfdfc8b3c8930d5ced21982dbdfb8cd35b3;p=mesa.git diff --git a/src/mesa/main/shaderapi.c b/src/mesa/main/shaderapi.c index 1335f0f4111..2ffd8be0eb4 100644 --- a/src/mesa/main/shaderapi.c +++ b/src/mesa/main/shaderapi.c @@ -41,13 +41,16 @@ #include "main/dispatch.h" #include "main/enums.h" #include "main/hash.h" +#include "main/mfeatures.h" +#include "main/mtypes.h" #include "main/shaderapi.h" #include "main/shaderobj.h" #include "program/program.h" #include "program/prog_parameter.h" #include "program/prog_uniform.h" #include "talloc.h" - +#include +#include "../glsl/glsl_parser_extras.h" /** Define this to enable shader substitution (see below) */ #define SHADER_SUBST 0 @@ -89,23 +92,24 @@ get_shader_flags(void) * Initialize context's shader state. */ void -_mesa_init_shader_state(GLcontext *ctx) +_mesa_init_shader_state(struct gl_context *ctx) { /* Device drivers may override these to control what kind of instructions * are generated by the GLSL compiler. */ - ctx->Shader.EmitHighLevelInstructions = GL_TRUE; - ctx->Shader.EmitContReturn = GL_TRUE; - ctx->Shader.EmitCondCodes = GL_FALSE; - ctx->Shader.EmitComments = GL_FALSE; - ctx->Shader.EmitNoIfs = GL_FALSE; - ctx->Shader.Flags = get_shader_flags(); + struct gl_shader_compiler_options options; + gl_shader_type sh; + + memset(&options, 0, sizeof(options)); + options.MaxUnrollIterations = 32; /* Default pragma settings */ - ctx->Shader.DefaultPragmas.IgnoreOptimize = GL_FALSE; - ctx->Shader.DefaultPragmas.IgnoreDebug = GL_FALSE; - ctx->Shader.DefaultPragmas.Optimize = GL_TRUE; - ctx->Shader.DefaultPragmas.Debug = GL_FALSE; + options.DefaultPragmas.Optimize = GL_TRUE; + + for (sh = 0; sh < MESA_SHADER_TYPES; ++sh) + memcpy(&ctx->ShaderCompilerOptions[sh], &options, sizeof(options)); + + ctx->Shader.Flags = get_shader_flags(); } @@ -113,9 +117,14 @@ _mesa_init_shader_state(GLcontext *ctx) * Free the per-context shader-related state. */ void -_mesa_free_shader_state(GLcontext *ctx) +_mesa_free_shader_state(struct gl_context *ctx) { - _mesa_reference_shader_program(ctx, &ctx->Shader.CurrentProgram, NULL); + _mesa_reference_shader_program(ctx, &ctx->Shader.CurrentVertexProgram, NULL); + _mesa_reference_shader_program(ctx, &ctx->Shader.CurrentGeometryProgram, + NULL); + _mesa_reference_shader_program(ctx, &ctx->Shader.CurrentFragmentProgram, + NULL); + _mesa_reference_shader_program(ctx, &ctx->Shader.ActiveProgram, NULL); } @@ -200,6 +209,35 @@ _mesa_copy_string(GLchar *dst, GLsizei maxLength, +/** + * Confirm that the a shader type is valid and supported by the implementation + * + * \param ctx Current GL context + * \param type Shader target + * + */ +static bool +validate_shader_target(const struct gl_context *ctx, GLenum type) +{ + switch (type) { +#if FEATURE_ARB_fragment_shader + case GL_FRAGMENT_SHADER: + return ctx->Extensions.ARB_fragment_shader; +#endif +#if FEATURE_ARB_vertex_shader + case GL_VERTEX_SHADER: + return ctx->Extensions.ARB_vertex_shader; +#endif +#if FEATURE_ARB_geometry_shader4 + case GL_GEOMETRY_SHADER_ARB: + return ctx->Extensions.ARB_geometry_shader4; +#endif + default: + return false; + } +} + + /** * Find the length of the longest transform feedback varying name * which was specified with glTransformFeedbackVaryings(). @@ -220,7 +258,7 @@ longest_feedback_varying_name(const struct gl_shader_program *shProg) static GLboolean -is_program(GLcontext *ctx, GLuint name) +is_program(struct gl_context *ctx, GLuint name) { struct gl_shader_program *shProg = _mesa_lookup_shader_program(ctx, name); return shProg ? GL_TRUE : GL_FALSE; @@ -228,7 +266,7 @@ is_program(GLcontext *ctx, GLuint name) static GLboolean -is_shader(GLcontext *ctx, GLuint name) +is_shader(struct gl_context *ctx, GLuint name) { struct gl_shader *shader = _mesa_lookup_shader(ctx, name); return shader ? GL_TRUE : GL_FALSE; @@ -239,7 +277,7 @@ is_shader(GLcontext *ctx, GLuint name) * Attach shader to a shader program. */ static void -attach_shader(GLcontext *ctx, GLuint program, GLuint shader) +attach_shader(struct gl_context *ctx, GLuint program, GLuint shader) { struct gl_shader_program *shProg; struct gl_shader *sh; @@ -286,7 +324,7 @@ attach_shader(GLcontext *ctx, GLuint program, GLuint shader) static GLint -get_attrib_location(GLcontext *ctx, GLuint program, const GLchar *name) +get_attrib_location(struct gl_context *ctx, GLuint program, const GLchar *name) { struct gl_shader_program *shProg = _mesa_lookup_shader_program_err(ctx, program, "glGetAttribLocation"); @@ -319,7 +357,7 @@ get_attrib_location(GLcontext *ctx, GLuint program, const GLchar *name) static void -bind_attrib_location(GLcontext *ctx, GLuint program, GLuint index, +bind_attrib_location(struct gl_context *ctx, GLuint program, GLuint index, const GLchar *name) { struct gl_shader_program *shProg; @@ -369,25 +407,27 @@ bind_attrib_location(GLcontext *ctx, GLuint program, GLuint index, } +static void +bind_frag_data_location(struct gl_context *ctx, GLuint program, + GLuint colorNumber, const GLchar *name) +{ + _mesa_problem(ctx, "bind_frag_data_location() not implemented yet"); +} + + static GLuint -create_shader(GLcontext *ctx, GLenum type) +create_shader(struct gl_context *ctx, GLenum type) { struct gl_shader *sh; GLuint name; - name = _mesa_HashFindFreeKeyBlock(ctx->Shared->ShaderObjects, 1); - - switch (type) { - case GL_FRAGMENT_SHADER: - case GL_VERTEX_SHADER: - case GL_GEOMETRY_SHADER_ARB: - sh = ctx->Driver.NewShader(ctx, name, type); - break; - default: + if (!validate_shader_target(ctx, type)) { _mesa_error(ctx, GL_INVALID_ENUM, "CreateShader(type)"); return 0; } + name = _mesa_HashFindFreeKeyBlock(ctx->Shared->ShaderObjects, 1); + sh = ctx->Driver.NewShader(ctx, name, type); _mesa_HashInsert(ctx->Shared->ShaderObjects, name, sh); return name; @@ -395,7 +435,7 @@ create_shader(GLcontext *ctx, GLenum type) static GLuint -create_shader_program(GLcontext *ctx) +create_shader_program(struct gl_context *ctx) { GLuint name; struct gl_shader_program *shProg; @@ -417,7 +457,7 @@ create_shader_program(GLcontext *ctx) * DeleteProgramARB. */ static void -delete_shader_program(GLcontext *ctx, GLuint name) +delete_shader_program(struct gl_context *ctx, GLuint name) { /* * NOTE: deleting shaders/programs works a bit differently than @@ -441,7 +481,7 @@ delete_shader_program(GLcontext *ctx, GLuint name) static void -delete_shader(GLcontext *ctx, GLuint shader) +delete_shader(struct gl_context *ctx, GLuint shader) { struct gl_shader *sh; @@ -457,7 +497,7 @@ delete_shader(GLcontext *ctx, GLuint shader) static void -detach_shader(GLcontext *ctx, GLuint program, GLuint shader) +detach_shader(struct gl_context *ctx, GLuint program, GLuint shader) { struct gl_shader_program *shProg; GLuint n; @@ -525,7 +565,7 @@ detach_shader(GLcontext *ctx, GLuint program, GLuint shader) static void -get_active_attrib(GLcontext *ctx, GLuint program, GLuint index, +get_active_attrib(struct gl_context *ctx, GLuint program, GLuint index, GLsizei maxLength, GLsizei *length, GLint *size, GLenum *type, GLchar *nameOut) { @@ -560,7 +600,7 @@ get_active_attrib(GLcontext *ctx, GLuint program, GLuint index, * Return list of shaders attached to shader program. */ static void -get_attached_shaders(GLcontext *ctx, GLuint program, GLsizei maxCount, +get_attached_shaders(struct gl_context *ctx, GLuint program, GLsizei maxCount, GLsizei *count, GLuint *obj) { struct gl_shader_program *shProg = @@ -576,15 +616,25 @@ get_attached_shaders(GLcontext *ctx, GLuint program, GLsizei maxCount, } +static GLint +get_frag_data_location(struct gl_context *ctx, GLuint program, + const GLchar *name) +{ + _mesa_problem(ctx, "get_frag_data_location() not implemented yet"); + return -1; +} + + + /** * glGetHandleARB() - return ID/name of currently bound shader program. */ static GLuint -get_handle(GLcontext *ctx, GLenum pname) +get_handle(struct gl_context *ctx, GLenum pname) { if (pname == GL_PROGRAM_OBJECT_ARB) { - if (ctx->Shader.CurrentProgram) - return ctx->Shader.CurrentProgram->Name; + if (ctx->Shader.ActiveProgram) + return ctx->Shader.ActiveProgram->Name; else return 0; } @@ -601,7 +651,7 @@ get_handle(GLcontext *ctx, GLenum pname) * programs (see glGetProgramivARB). */ static void -get_programiv(GLcontext *ctx, GLuint program, GLenum pname, GLint *params) +get_programiv(struct gl_context *ctx, GLuint program, GLenum pname, GLint *params) { const struct gl_program_parameter_list *attribs; struct gl_shader_program *shProg @@ -644,6 +694,8 @@ get_programiv(GLcontext *ctx, GLuint program, GLenum pname, GLint *params) break; case GL_ACTIVE_UNIFORM_MAX_LENGTH: *params = _mesa_longest_uniform_name(shProg->Uniforms); + if (*params > 0) + (*params)++; /* add one for terminating zero */ break; case GL_PROGRAM_BINARY_LENGTH_OES: *params = 0; @@ -681,7 +733,7 @@ get_programiv(GLcontext *ctx, GLuint program, GLenum pname, GLint *params) * glGetShaderiv() - get GLSL shader state */ static void -get_shaderiv(GLcontext *ctx, GLuint name, GLenum pname, GLint *params) +get_shaderiv(struct gl_context *ctx, GLuint name, GLenum pname, GLint *params) { struct gl_shader *shader = _mesa_lookup_shader_err(ctx, name, "glGetShaderiv"); @@ -714,7 +766,7 @@ get_shaderiv(GLcontext *ctx, GLuint name, GLenum pname, GLint *params) static void -get_program_info_log(GLcontext *ctx, GLuint program, GLsizei bufSize, +get_program_info_log(struct gl_context *ctx, GLuint program, GLsizei bufSize, GLsizei *length, GLchar *infoLog) { struct gl_shader_program *shProg @@ -728,7 +780,7 @@ get_program_info_log(GLcontext *ctx, GLuint program, GLsizei bufSize, static void -get_shader_info_log(GLcontext *ctx, GLuint shader, GLsizei bufSize, +get_shader_info_log(struct gl_context *ctx, GLuint shader, GLsizei bufSize, GLsizei *length, GLchar *infoLog) { struct gl_shader *sh = _mesa_lookup_shader(ctx, shader); @@ -744,7 +796,7 @@ get_shader_info_log(GLcontext *ctx, GLuint shader, GLsizei bufSize, * Return shader source code. */ static void -get_shader_source(GLcontext *ctx, GLuint shader, GLsizei maxLength, +get_shader_source(struct gl_context *ctx, GLuint shader, GLsizei maxLength, GLsizei *length, GLchar *sourceOut) { struct gl_shader *sh; @@ -760,7 +812,7 @@ get_shader_source(GLcontext *ctx, GLuint shader, GLsizei maxLength, * Set/replace shader source code. */ static void -shader_source(GLcontext *ctx, GLuint shader, const GLchar *source) +shader_source(struct gl_context *ctx, GLuint shader, const GLchar *source) { struct gl_shader *sh; @@ -784,16 +836,19 @@ shader_source(GLcontext *ctx, GLuint shader, const GLchar *source) * Compile a shader. */ static void -compile_shader(GLcontext *ctx, GLuint shaderObj) +compile_shader(struct gl_context *ctx, GLuint shaderObj) { struct gl_shader *sh; + struct gl_shader_compiler_options *options; sh = _mesa_lookup_shader_err(ctx, shaderObj, "glCompileShader"); if (!sh) return; + options = &ctx->ShaderCompilerOptions[_mesa_shader_type_to_index(sh->Type)]; + /* set default pragma state for shader */ - sh->Pragmas = ctx->Shader.DefaultPragmas; + sh->Pragmas = options->DefaultPragmas; /* this call will set the sh->CompileStatus field to indicate if * compilation was successful. @@ -806,7 +861,7 @@ compile_shader(GLcontext *ctx, GLuint shaderObj) * Link a program's shaders. */ static void -link_program(GLcontext *ctx, GLuint program) +link_program(struct gl_context *ctx, GLuint program) { struct gl_shader_program *shProg; struct gl_transform_feedback_object *obj = @@ -816,7 +871,10 @@ link_program(GLcontext *ctx, GLuint program) if (!shProg) return; - if (obj->Active && shProg == ctx->Shader.CurrentProgram) { + if (obj->Active + && (shProg == ctx->Shader.CurrentVertexProgram + || shProg == ctx->Shader.CurrentGeometryProgram + || shProg == ctx->Shader.CurrentFragmentProgram)) { _mesa_error(ctx, GL_INVALID_OPERATION, "glLinkProgram(transform feedback active"); return; @@ -879,52 +937,83 @@ print_shader_info(const struct gl_shader_program *shProg) /** - * Use the named shader program for subsequent rendering. + * Use the named shader program for subsequent glUniform calls */ void -_mesa_use_program(GLcontext *ctx, GLuint program) +_mesa_active_program(struct gl_context *ctx, struct gl_shader_program *shProg, + const char *caller) { - struct gl_shader_program *shProg; - struct gl_transform_feedback_object *obj = - ctx->TransformFeedback.CurrentObject; - - if (obj->Active) { + if ((shProg != NULL) && !shProg->LinkStatus) { _mesa_error(ctx, GL_INVALID_OPERATION, - "glUseProgram(transform feedback active)"); + "%s(program %u not linked)", caller, shProg->Name); return; } - if (ctx->Shader.CurrentProgram && - ctx->Shader.CurrentProgram->Name == program) { - /* no-op */ - return; + if (ctx->Shader.ActiveProgram != shProg) { + _mesa_reference_shader_program(ctx, &ctx->Shader.ActiveProgram, shProg); } +} - if (program) { - shProg = _mesa_lookup_shader_program_err(ctx, program, "glUseProgram"); - if (!shProg) { - return; +/** + */ +static bool +use_shader_program(struct gl_context *ctx, GLenum type, + struct gl_shader_program *shProg) +{ + struct gl_shader_program **target; + + switch (type) { +#if FEATURE_ARB_vertex_shader + case GL_VERTEX_SHADER: + target = &ctx->Shader.CurrentVertexProgram; + if ((shProg == NULL) + || (shProg->_LinkedShaders[MESA_SHADER_VERTEX] == NULL)) { + shProg = NULL; } - if (!shProg->LinkStatus) { - _mesa_error(ctx, GL_INVALID_OPERATION, - "glUseProgram(program %u not linked)", program); - return; + break; +#endif +#if FEATURE_ARB_geometry_shader4 + case GL_GEOMETRY_SHADER_ARB: + target = &ctx->Shader.CurrentGeometryProgram; + if ((shProg == NULL) + || (shProg->_LinkedShaders[MESA_SHADER_GEOMETRY] == NULL)) { + shProg = NULL; } - - /* debug code */ - if (ctx->Shader.Flags & GLSL_USE_PROG) { - print_shader_info(shProg); + break; +#endif +#if FEATURE_ARB_fragment_shader + case GL_FRAGMENT_SHADER: + target = &ctx->Shader.CurrentFragmentProgram; + if ((shProg == NULL) + || (shProg->_LinkedShaders[MESA_SHADER_FRAGMENT] == NULL)) { + shProg = NULL; } - } - else { - shProg = NULL; + break; +#endif + default: + return false; } - if (ctx->Shader.CurrentProgram != shProg) { + if (*target != shProg) { FLUSH_VERTICES(ctx, _NEW_PROGRAM | _NEW_PROGRAM_CONSTANTS); - _mesa_reference_shader_program(ctx, &ctx->Shader.CurrentProgram, shProg); + _mesa_reference_shader_program(ctx, target, shProg); + return true; } + return false; +} + +/** + * Use the named shader program for subsequent rendering. + */ +void +_mesa_use_program(struct gl_context *ctx, struct gl_shader_program *shProg) +{ + use_shader_program(ctx, GL_VERTEX_SHADER, shProg); + use_shader_program(ctx, GL_GEOMETRY_SHADER_ARB, shProg); + use_shader_program(ctx, GL_FRAGMENT_SHADER, shProg); + _mesa_active_program(ctx, shProg, "glUseProgram"); + if (ctx->Driver.UseProgram) ctx->Driver.UseProgram(ctx, shProg); } @@ -937,7 +1026,7 @@ _mesa_use_program(GLcontext *ctx, GLuint program) * \return GL_TRUE if valid, GL_FALSE if invalid */ static GLboolean -validate_samplers(GLcontext *ctx, const struct gl_program *prog, char *errMsg) +validate_samplers(const struct gl_program *prog, char *errMsg) { static const char *targetName[] = { "TEXTURE_2D_ARRAY", @@ -969,7 +1058,7 @@ validate_samplers(GLcontext *ctx, const struct gl_program *prog, char *errMsg) assert(sampler < MAX_TEXTURE_IMAGE_UNITS); unit = prog->SamplerUnits[sampler]; target = prog->SamplerTargets[sampler]; - if (targetUsed[unit] != -1 && targetUsed[unit] != target) { + if (targetUsed[unit] != -1 && targetUsed[unit] != (int) target) { _mesa_snprintf(errMsg, 100, "Texture unit %d is accessed both as %s and %s", unit, targetName[targetUsed[unit]], targetName[target]); @@ -989,8 +1078,7 @@ validate_samplers(GLcontext *ctx, const struct gl_program *prog, char *errMsg) * \return GL_TRUE if valid, GL_FALSE if invalid (and set errMsg) */ static GLboolean -validate_shader_program(GLcontext *ctx, - const struct gl_shader_program *shProg, +validate_shader_program(const struct gl_shader_program *shProg, char *errMsg) { const struct gl_vertex_program *vp = shProg->VertexProgram; @@ -1020,10 +1108,10 @@ validate_shader_program(GLcontext *ctx, * Check: any two active samplers in the current program object are of * different types, but refer to the same texture image unit, */ - if (vp && !validate_samplers(ctx, &vp->Base, errMsg)) { + if (vp && !validate_samplers(&vp->Base, errMsg)) { return GL_FALSE; } - if (fp && !validate_samplers(ctx, &fp->Base, errMsg)) { + if (fp && !validate_samplers(&fp->Base, errMsg)) { return GL_FALSE; } @@ -1035,7 +1123,7 @@ validate_shader_program(GLcontext *ctx, * Called via glValidateProgram() */ static void -validate_program(GLcontext *ctx, GLuint program) +validate_program(struct gl_context *ctx, GLuint program) { struct gl_shader_program *shProg; char errMsg[100]; @@ -1045,7 +1133,7 @@ validate_program(GLcontext *ctx, GLuint program) return; } - shProg->Validated = validate_shader_program(ctx, shProg, errMsg); + shProg->Validated = validate_shader_program(shProg, errMsg); if (!shProg->Validated) { /* update info log */ if (shProg->InfoLog) { @@ -1082,6 +1170,16 @@ _mesa_BindAttribLocationARB(GLhandleARB program, GLuint index, } +/* GL_EXT_gpu_shader4, GL3 */ +void GLAPIENTRY +_mesa_BindFragDataLocation(GLuint program, GLuint colorNumber, + const GLchar *name) +{ + GET_CURRENT_CONTEXT(ctx); + bind_frag_data_location(ctx, program, colorNumber, name); +} + + void GLAPIENTRY _mesa_CompileShaderARB(GLhandleARB shaderObj) { @@ -1212,6 +1310,16 @@ _mesa_GetAttribLocationARB(GLhandleARB program, const GLcharARB * name) } +/* GL_EXT_gpu_shader4, GL3 */ +GLint GLAPIENTRY +_mesa_GetFragDataLocation(GLuint program, const GLchar *name) +{ + GET_CURRENT_CONTEXT(ctx); + return get_frag_data_location(ctx, program, name); +} + + + void GLAPIENTRY _mesa_GetInfoLogARB(GLhandleARB object, GLsizei maxLength, GLsizei * length, GLcharARB * infoLog) @@ -1473,8 +1581,37 @@ void GLAPIENTRY _mesa_UseProgramObjectARB(GLhandleARB program) { GET_CURRENT_CONTEXT(ctx); - FLUSH_VERTICES(ctx, _NEW_PROGRAM); - _mesa_use_program(ctx, program); + struct gl_shader_program *shProg; + struct gl_transform_feedback_object *obj = + ctx->TransformFeedback.CurrentObject; + + if (obj->Active) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glUseProgram(transform feedback active)"); + return; + } + + if (program) { + shProg = _mesa_lookup_shader_program_err(ctx, program, "glUseProgram"); + if (!shProg) { + return; + } + if (!shProg->LinkStatus) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glUseProgram(program %u not linked)", program); + return; + } + + /* debug code */ + if (ctx->Shader.Flags & GLSL_USE_PROG) { + print_shader_info(shProg); + } + } + else { + shProg = NULL; + } + + _mesa_use_program(ctx, shProg); } @@ -1492,6 +1629,10 @@ _mesa_GetShaderPrecisionFormat(GLenum shadertype, GLenum precisiontype, GLint* range, GLint* precision) { GET_CURRENT_CONTEXT(ctx); + (void) shadertype; + (void) precisiontype; + (void) range; + (void) precision; _mesa_error(ctx, GL_INVALID_OPERATION, __FUNCTION__); } @@ -1499,8 +1640,7 @@ _mesa_GetShaderPrecisionFormat(GLenum shadertype, GLenum precisiontype, void GLAPIENTRY _mesa_ReleaseShaderCompiler(void) { - GET_CURRENT_CONTEXT(ctx); - _mesa_error(ctx, GL_INVALID_OPERATION, __FUNCTION__); + _mesa_destroy_shader_compiler_caches(); } @@ -1509,6 +1649,11 @@ _mesa_ShaderBinary(GLint n, const GLuint* shaders, GLenum binaryformat, const void* binary, GLint length) { GET_CURRENT_CONTEXT(ctx); + (void) n; + (void) shaders; + (void) binaryformat; + (void) binary; + (void) length; _mesa_error(ctx, GL_INVALID_OPERATION, __FUNCTION__); } @@ -1534,7 +1679,7 @@ _mesa_ProgramParameteriARB(GLuint program, GLenum pname, switch (pname) { case GL_GEOMETRY_VERTICES_OUT_ARB: if (value < 1 || - value > ctx->Const.GeometryProgram.MaxGeometryOutputVertices) { + (unsigned) value > ctx->Const.GeometryProgram.MaxGeometryOutputVertices) { _mesa_error(ctx, GL_INVALID_VALUE, "glProgramParameteri(GL_GEOMETRY_VERTICES_OUT_ARB=%d", value); @@ -1581,6 +1726,104 @@ _mesa_ProgramParameteriARB(GLuint program, GLenum pname, #endif +void +_mesa_use_shader_program(struct gl_context *ctx, GLenum type, + struct gl_shader_program *shProg) +{ + use_shader_program(ctx, type, shProg); + + if (ctx->Driver.UseProgram) + ctx->Driver.UseProgram(ctx, shProg); +} + +void GLAPIENTRY +_mesa_UseShaderProgramEXT(GLenum type, GLuint program) +{ + GET_CURRENT_CONTEXT(ctx); + struct gl_shader_program *shProg = NULL; + + if (!validate_shader_target(ctx, type)) { + _mesa_error(ctx, GL_INVALID_ENUM, "glUseShaderProgramEXT(type)"); + return; + } + + if (ctx->TransformFeedback.CurrentObject->Active) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glUseShaderProgramEXT(transform feedback is active)"); + return; + } + + if (program) { + shProg = _mesa_lookup_shader_program_err(ctx, program, + "glUseShaderProgramEXT"); + if (shProg == NULL) + return; + + if (!shProg->LinkStatus) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glUseShaderProgramEXT(program not linked)"); + return; + } + } + + _mesa_use_shader_program(ctx, type, shProg); +} + +void GLAPIENTRY +_mesa_ActiveProgramEXT(GLuint program) +{ + GET_CURRENT_CONTEXT(ctx); + struct gl_shader_program *shProg = (program != 0) + ? _mesa_lookup_shader_program_err(ctx, program, "glActiveProgramEXT") + : NULL; + + _mesa_active_program(ctx, shProg, "glActiveProgramEXT"); + return; +} + +GLuint GLAPIENTRY +_mesa_CreateShaderProgramEXT(GLenum type, const GLchar *string) +{ + GET_CURRENT_CONTEXT(ctx); + const GLuint shader = create_shader(ctx, type); + GLuint program = 0; + + if (shader) { + shader_source(ctx, shader, _mesa_strdup(string)); + compile_shader(ctx, shader); + + program = create_shader_program(ctx); + if (program) { + struct gl_shader_program *shProg; + struct gl_shader *sh; + GLint compiled = GL_FALSE; + + shProg = _mesa_lookup_shader_program(ctx, program); + sh = _mesa_lookup_shader(ctx, shader); + + get_shaderiv(ctx, shader, GL_COMPILE_STATUS, &compiled); + if (compiled) { + attach_shader(ctx, program, shader); + link_program(ctx, program); + detach_shader(ctx, program, shader); + +#if 0 + /* Possibly... */ + if (active-user-defined-varyings-in-linked-program) { + append-error-to-info-log; + shProg->LinkStatus = GL_FALSE; + } +#endif + } + + shProg->InfoLog = talloc_strdup_append(shProg->InfoLog, sh->InfoLog); + } + + delete_shader(ctx, shader); + } + + return program; +} /** * Plug in shader-related functions into API dispatch table. @@ -1631,6 +1874,18 @@ _mesa_init_shader_dispatch(struct _glapi_table *exec) #if FEATURE_ARB_geometry_shader4 SET_ProgramParameteriARB(exec, _mesa_ProgramParameteriARB); #endif + + SET_UseShaderProgramEXT(exec, _mesa_UseShaderProgramEXT); + SET_ActiveProgramEXT(exec, _mesa_ActiveProgramEXT); + SET_CreateShaderProgramEXT(exec, _mesa_CreateShaderProgramEXT); + + /* GL_EXT_gpu_shader4 / GL 3.0 */ + SET_BindFragDataLocationEXT(exec, _mesa_BindFragDataLocation); + SET_GetFragDataLocationEXT(exec, _mesa_GetFragDataLocation); + + /* GL_ARB_ES2_compatibility */ + SET_ReleaseShaderCompiler(exec, _mesa_ReleaseShaderCompiler); + #endif /* FEATURE_GL */ }