shaderapi.c revision 3464ebd5
13464ebd5Sriastradh/* 23464ebd5Sriastradh * Mesa 3-D graphics library 33464ebd5Sriastradh * 43464ebd5Sriastradh * Copyright (C) 2004-2008 Brian Paul All Rights Reserved. 53464ebd5Sriastradh * Copyright (C) 2009-2010 VMware, Inc. All Rights Reserved. 63464ebd5Sriastradh * 73464ebd5Sriastradh * Permission is hereby granted, free of charge, to any person obtaining a 83464ebd5Sriastradh * copy of this software and associated documentation files (the "Software"), 93464ebd5Sriastradh * to deal in the Software without restriction, including without limitation 103464ebd5Sriastradh * the rights to use, copy, modify, merge, publish, distribute, sublicense, 113464ebd5Sriastradh * and/or sell copies of the Software, and to permit persons to whom the 123464ebd5Sriastradh * Software is furnished to do so, subject to the following conditions: 133464ebd5Sriastradh * 143464ebd5Sriastradh * The above copyright notice and this permission notice shall be included 153464ebd5Sriastradh * in all copies or substantial portions of the Software. 163464ebd5Sriastradh * 173464ebd5Sriastradh * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 183464ebd5Sriastradh * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 193464ebd5Sriastradh * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 203464ebd5Sriastradh * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 213464ebd5Sriastradh * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 223464ebd5Sriastradh * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 233464ebd5Sriastradh */ 243464ebd5Sriastradh 253464ebd5Sriastradh/** 263464ebd5Sriastradh * \file shaderapi.c 273464ebd5Sriastradh * \author Brian Paul 283464ebd5Sriastradh * 293464ebd5Sriastradh * Implementation of GLSL-related API functions. 303464ebd5Sriastradh * The glUniform* functions are in uniforms.c 313464ebd5Sriastradh * 323464ebd5Sriastradh * 333464ebd5Sriastradh * XXX things to do: 343464ebd5Sriastradh * 1. Check that the right error code is generated for all _mesa_error() calls. 353464ebd5Sriastradh * 2. Insert FLUSH_VERTICES calls in various places 363464ebd5Sriastradh */ 373464ebd5Sriastradh 383464ebd5Sriastradh 393464ebd5Sriastradh#include "main/glheader.h" 403464ebd5Sriastradh#include "main/context.h" 413464ebd5Sriastradh#include "main/dispatch.h" 423464ebd5Sriastradh#include "main/enums.h" 433464ebd5Sriastradh#include "main/hash.h" 443464ebd5Sriastradh#include "main/mfeatures.h" 453464ebd5Sriastradh#include "main/mtypes.h" 463464ebd5Sriastradh#include "main/shaderapi.h" 473464ebd5Sriastradh#include "main/shaderobj.h" 483464ebd5Sriastradh#include "program/program.h" 493464ebd5Sriastradh#include "program/prog_parameter.h" 503464ebd5Sriastradh#include "program/prog_uniform.h" 513464ebd5Sriastradh#include "ralloc.h" 523464ebd5Sriastradh#include <stdbool.h> 533464ebd5Sriastradh#include "../glsl/glsl_parser_extras.h" 543464ebd5Sriastradh 553464ebd5Sriastradh/** Define this to enable shader substitution (see below) */ 563464ebd5Sriastradh#define SHADER_SUBST 0 573464ebd5Sriastradh 583464ebd5Sriastradh 593464ebd5Sriastradh/** 603464ebd5Sriastradh * Return mask of GLSL_x flags by examining the MESA_GLSL env var. 613464ebd5Sriastradh */ 623464ebd5Sriastradhstatic GLbitfield 633464ebd5Sriastradhget_shader_flags(void) 643464ebd5Sriastradh{ 653464ebd5Sriastradh GLbitfield flags = 0x0; 663464ebd5Sriastradh const char *env = _mesa_getenv("MESA_GLSL"); 673464ebd5Sriastradh 683464ebd5Sriastradh if (env) { 693464ebd5Sriastradh if (strstr(env, "dump")) 703464ebd5Sriastradh flags |= GLSL_DUMP; 713464ebd5Sriastradh if (strstr(env, "log")) 723464ebd5Sriastradh flags |= GLSL_LOG; 733464ebd5Sriastradh if (strstr(env, "nopvert")) 743464ebd5Sriastradh flags |= GLSL_NOP_VERT; 753464ebd5Sriastradh if (strstr(env, "nopfrag")) 763464ebd5Sriastradh flags |= GLSL_NOP_FRAG; 773464ebd5Sriastradh if (strstr(env, "nopt")) 783464ebd5Sriastradh flags |= GLSL_NO_OPT; 793464ebd5Sriastradh else if (strstr(env, "opt")) 803464ebd5Sriastradh flags |= GLSL_OPT; 813464ebd5Sriastradh if (strstr(env, "uniform")) 823464ebd5Sriastradh flags |= GLSL_UNIFORMS; 833464ebd5Sriastradh if (strstr(env, "useprog")) 843464ebd5Sriastradh flags |= GLSL_USE_PROG; 853464ebd5Sriastradh } 863464ebd5Sriastradh 873464ebd5Sriastradh return flags; 883464ebd5Sriastradh} 893464ebd5Sriastradh 903464ebd5Sriastradh 913464ebd5Sriastradh/** 923464ebd5Sriastradh * Initialize context's shader state. 933464ebd5Sriastradh */ 943464ebd5Sriastradhvoid 953464ebd5Sriastradh_mesa_init_shader_state(struct gl_context *ctx) 963464ebd5Sriastradh{ 973464ebd5Sriastradh /* Device drivers may override these to control what kind of instructions 983464ebd5Sriastradh * are generated by the GLSL compiler. 993464ebd5Sriastradh */ 1003464ebd5Sriastradh struct gl_shader_compiler_options options; 1013464ebd5Sriastradh gl_shader_type sh; 1023464ebd5Sriastradh 1033464ebd5Sriastradh memset(&options, 0, sizeof(options)); 1043464ebd5Sriastradh options.MaxUnrollIterations = 32; 1053464ebd5Sriastradh 1063464ebd5Sriastradh /* Default pragma settings */ 1073464ebd5Sriastradh options.DefaultPragmas.Optimize = GL_TRUE; 1083464ebd5Sriastradh 1093464ebd5Sriastradh for (sh = 0; sh < MESA_SHADER_TYPES; ++sh) 1103464ebd5Sriastradh memcpy(&ctx->ShaderCompilerOptions[sh], &options, sizeof(options)); 1113464ebd5Sriastradh 1123464ebd5Sriastradh ctx->Shader.Flags = get_shader_flags(); 1133464ebd5Sriastradh} 1143464ebd5Sriastradh 1153464ebd5Sriastradh 1163464ebd5Sriastradh/** 1173464ebd5Sriastradh * Free the per-context shader-related state. 1183464ebd5Sriastradh */ 1193464ebd5Sriastradhvoid 1203464ebd5Sriastradh_mesa_free_shader_state(struct gl_context *ctx) 1213464ebd5Sriastradh{ 1223464ebd5Sriastradh _mesa_reference_shader_program(ctx, &ctx->Shader.CurrentVertexProgram, NULL); 1233464ebd5Sriastradh _mesa_reference_shader_program(ctx, &ctx->Shader.CurrentGeometryProgram, 1243464ebd5Sriastradh NULL); 1253464ebd5Sriastradh _mesa_reference_shader_program(ctx, &ctx->Shader.CurrentFragmentProgram, 1263464ebd5Sriastradh NULL); 1273464ebd5Sriastradh _mesa_reference_shader_program(ctx, &ctx->Shader.ActiveProgram, NULL); 1283464ebd5Sriastradh} 1293464ebd5Sriastradh 1303464ebd5Sriastradh 1313464ebd5Sriastradh/** 1323464ebd5Sriastradh * Return the size of the given GLSL datatype, in floats (components). 1333464ebd5Sriastradh */ 1343464ebd5SriastradhGLint 1353464ebd5Sriastradh_mesa_sizeof_glsl_type(GLenum type) 1363464ebd5Sriastradh{ 1373464ebd5Sriastradh switch (type) { 1383464ebd5Sriastradh case GL_FLOAT: 1393464ebd5Sriastradh case GL_INT: 1403464ebd5Sriastradh case GL_BOOL: 1413464ebd5Sriastradh case GL_SAMPLER_1D: 1423464ebd5Sriastradh case GL_SAMPLER_2D: 1433464ebd5Sriastradh case GL_SAMPLER_3D: 1443464ebd5Sriastradh case GL_SAMPLER_CUBE: 1453464ebd5Sriastradh case GL_SAMPLER_1D_SHADOW: 1463464ebd5Sriastradh case GL_SAMPLER_2D_SHADOW: 1473464ebd5Sriastradh case GL_SAMPLER_2D_RECT_ARB: 1483464ebd5Sriastradh case GL_SAMPLER_2D_RECT_SHADOW_ARB: 1493464ebd5Sriastradh case GL_SAMPLER_1D_ARRAY_EXT: 1503464ebd5Sriastradh case GL_SAMPLER_2D_ARRAY_EXT: 1513464ebd5Sriastradh case GL_SAMPLER_1D_ARRAY_SHADOW_EXT: 1523464ebd5Sriastradh case GL_SAMPLER_2D_ARRAY_SHADOW_EXT: 1533464ebd5Sriastradh case GL_SAMPLER_CUBE_SHADOW_EXT: 1543464ebd5Sriastradh return 1; 1553464ebd5Sriastradh case GL_FLOAT_VEC2: 1563464ebd5Sriastradh case GL_INT_VEC2: 1573464ebd5Sriastradh case GL_UNSIGNED_INT_VEC2: 1583464ebd5Sriastradh case GL_BOOL_VEC2: 1593464ebd5Sriastradh return 2; 1603464ebd5Sriastradh case GL_FLOAT_VEC3: 1613464ebd5Sriastradh case GL_INT_VEC3: 1623464ebd5Sriastradh case GL_UNSIGNED_INT_VEC3: 1633464ebd5Sriastradh case GL_BOOL_VEC3: 1643464ebd5Sriastradh return 3; 1653464ebd5Sriastradh case GL_FLOAT_VEC4: 1663464ebd5Sriastradh case GL_INT_VEC4: 1673464ebd5Sriastradh case GL_UNSIGNED_INT_VEC4: 1683464ebd5Sriastradh case GL_BOOL_VEC4: 1693464ebd5Sriastradh return 4; 1703464ebd5Sriastradh case GL_FLOAT_MAT2: 1713464ebd5Sriastradh case GL_FLOAT_MAT2x3: 1723464ebd5Sriastradh case GL_FLOAT_MAT2x4: 1733464ebd5Sriastradh return 8; /* two float[4] vectors */ 1743464ebd5Sriastradh case GL_FLOAT_MAT3: 1753464ebd5Sriastradh case GL_FLOAT_MAT3x2: 1763464ebd5Sriastradh case GL_FLOAT_MAT3x4: 1773464ebd5Sriastradh return 12; /* three float[4] vectors */ 1783464ebd5Sriastradh case GL_FLOAT_MAT4: 1793464ebd5Sriastradh case GL_FLOAT_MAT4x2: 1803464ebd5Sriastradh case GL_FLOAT_MAT4x3: 1813464ebd5Sriastradh return 16; /* four float[4] vectors */ 1823464ebd5Sriastradh default: 1833464ebd5Sriastradh _mesa_problem(NULL, "Invalid type in _mesa_sizeof_glsl_type()"); 1843464ebd5Sriastradh return 1; 1853464ebd5Sriastradh } 1863464ebd5Sriastradh} 1873464ebd5Sriastradh 1883464ebd5Sriastradh 1893464ebd5Sriastradh/** 1903464ebd5Sriastradh * Copy string from <src> to <dst>, up to maxLength characters, returning 1913464ebd5Sriastradh * length of <dst> in <length>. 1923464ebd5Sriastradh * \param src the strings source 1933464ebd5Sriastradh * \param maxLength max chars to copy 1943464ebd5Sriastradh * \param length returns number of chars copied 1953464ebd5Sriastradh * \param dst the string destination 1963464ebd5Sriastradh */ 1973464ebd5Sriastradhvoid 1983464ebd5Sriastradh_mesa_copy_string(GLchar *dst, GLsizei maxLength, 1993464ebd5Sriastradh GLsizei *length, const GLchar *src) 2003464ebd5Sriastradh{ 2013464ebd5Sriastradh GLsizei len; 2023464ebd5Sriastradh for (len = 0; len < maxLength - 1 && src && src[len]; len++) 2033464ebd5Sriastradh dst[len] = src[len]; 2043464ebd5Sriastradh if (maxLength > 0) 2053464ebd5Sriastradh dst[len] = 0; 2063464ebd5Sriastradh if (length) 2073464ebd5Sriastradh *length = len; 2083464ebd5Sriastradh} 2093464ebd5Sriastradh 2103464ebd5Sriastradh 2113464ebd5Sriastradh 2123464ebd5Sriastradh/** 2133464ebd5Sriastradh * Confirm that the a shader type is valid and supported by the implementation 2143464ebd5Sriastradh * 2153464ebd5Sriastradh * \param ctx Current GL context 2163464ebd5Sriastradh * \param type Shader target 2173464ebd5Sriastradh * 2183464ebd5Sriastradh */ 2193464ebd5Sriastradhstatic bool 2203464ebd5Sriastradhvalidate_shader_target(const struct gl_context *ctx, GLenum type) 2213464ebd5Sriastradh{ 2223464ebd5Sriastradh switch (type) { 2233464ebd5Sriastradh#if FEATURE_ARB_fragment_shader 2243464ebd5Sriastradh case GL_FRAGMENT_SHADER: 2253464ebd5Sriastradh return ctx->Extensions.ARB_fragment_shader; 2263464ebd5Sriastradh#endif 2273464ebd5Sriastradh#if FEATURE_ARB_vertex_shader 2283464ebd5Sriastradh case GL_VERTEX_SHADER: 2293464ebd5Sriastradh return ctx->Extensions.ARB_vertex_shader; 2303464ebd5Sriastradh#endif 2313464ebd5Sriastradh#if FEATURE_ARB_geometry_shader4 2323464ebd5Sriastradh case GL_GEOMETRY_SHADER_ARB: 2333464ebd5Sriastradh return ctx->Extensions.ARB_geometry_shader4; 2343464ebd5Sriastradh#endif 2353464ebd5Sriastradh default: 2363464ebd5Sriastradh return false; 2373464ebd5Sriastradh } 2383464ebd5Sriastradh} 2393464ebd5Sriastradh 2403464ebd5Sriastradh 2413464ebd5Sriastradh/** 2423464ebd5Sriastradh * Find the length of the longest transform feedback varying name 2433464ebd5Sriastradh * which was specified with glTransformFeedbackVaryings(). 2443464ebd5Sriastradh */ 2453464ebd5Sriastradhstatic GLint 2463464ebd5Sriastradhlongest_feedback_varying_name(const struct gl_shader_program *shProg) 2473464ebd5Sriastradh{ 2483464ebd5Sriastradh GLuint i; 2493464ebd5Sriastradh GLint max = 0; 2503464ebd5Sriastradh for (i = 0; i < shProg->TransformFeedback.NumVarying; i++) { 2513464ebd5Sriastradh GLint len = strlen(shProg->TransformFeedback.VaryingNames[i]); 2523464ebd5Sriastradh if (len > max) 2533464ebd5Sriastradh max = len; 2543464ebd5Sriastradh } 2553464ebd5Sriastradh return max; 2563464ebd5Sriastradh} 2573464ebd5Sriastradh 2583464ebd5Sriastradh 2593464ebd5Sriastradh 2603464ebd5Sriastradhstatic GLboolean 2613464ebd5Sriastradhis_program(struct gl_context *ctx, GLuint name) 2623464ebd5Sriastradh{ 2633464ebd5Sriastradh struct gl_shader_program *shProg = _mesa_lookup_shader_program(ctx, name); 2643464ebd5Sriastradh return shProg ? GL_TRUE : GL_FALSE; 2653464ebd5Sriastradh} 2663464ebd5Sriastradh 2673464ebd5Sriastradh 2683464ebd5Sriastradhstatic GLboolean 2693464ebd5Sriastradhis_shader(struct gl_context *ctx, GLuint name) 2703464ebd5Sriastradh{ 2713464ebd5Sriastradh struct gl_shader *shader = _mesa_lookup_shader(ctx, name); 2723464ebd5Sriastradh return shader ? GL_TRUE : GL_FALSE; 2733464ebd5Sriastradh} 2743464ebd5Sriastradh 2753464ebd5Sriastradh 2763464ebd5Sriastradh/** 2773464ebd5Sriastradh * Attach shader to a shader program. 2783464ebd5Sriastradh */ 2793464ebd5Sriastradhstatic void 2803464ebd5Sriastradhattach_shader(struct gl_context *ctx, GLuint program, GLuint shader) 2813464ebd5Sriastradh{ 2823464ebd5Sriastradh struct gl_shader_program *shProg; 2833464ebd5Sriastradh struct gl_shader *sh; 2843464ebd5Sriastradh GLuint i, n; 2853464ebd5Sriastradh 2863464ebd5Sriastradh shProg = _mesa_lookup_shader_program_err(ctx, program, "glAttachShader"); 2873464ebd5Sriastradh if (!shProg) 2883464ebd5Sriastradh return; 2893464ebd5Sriastradh 2903464ebd5Sriastradh sh = _mesa_lookup_shader_err(ctx, shader, "glAttachShader"); 2913464ebd5Sriastradh if (!sh) { 2923464ebd5Sriastradh return; 2933464ebd5Sriastradh } 2943464ebd5Sriastradh 2953464ebd5Sriastradh n = shProg->NumShaders; 2963464ebd5Sriastradh for (i = 0; i < n; i++) { 2973464ebd5Sriastradh if (shProg->Shaders[i] == sh) { 2983464ebd5Sriastradh /* The shader is already attched to this program. The 2993464ebd5Sriastradh * GL_ARB_shader_objects spec says: 3003464ebd5Sriastradh * 3013464ebd5Sriastradh * "The error INVALID_OPERATION is generated by AttachObjectARB 3023464ebd5Sriastradh * if <obj> is already attached to <containerObj>." 3033464ebd5Sriastradh */ 3043464ebd5Sriastradh _mesa_error(ctx, GL_INVALID_OPERATION, "glAttachShader"); 3053464ebd5Sriastradh return; 3063464ebd5Sriastradh } 3073464ebd5Sriastradh } 3083464ebd5Sriastradh 3093464ebd5Sriastradh /* grow list */ 3103464ebd5Sriastradh shProg->Shaders = (struct gl_shader **) 3113464ebd5Sriastradh _mesa_realloc(shProg->Shaders, 3123464ebd5Sriastradh n * sizeof(struct gl_shader *), 3133464ebd5Sriastradh (n + 1) * sizeof(struct gl_shader *)); 3143464ebd5Sriastradh if (!shProg->Shaders) { 3153464ebd5Sriastradh _mesa_error(ctx, GL_OUT_OF_MEMORY, "glAttachShader"); 3163464ebd5Sriastradh return; 3173464ebd5Sriastradh } 3183464ebd5Sriastradh 3193464ebd5Sriastradh /* append */ 3203464ebd5Sriastradh shProg->Shaders[n] = NULL; /* since realloc() didn't zero the new space */ 3213464ebd5Sriastradh _mesa_reference_shader(ctx, &shProg->Shaders[n], sh); 3223464ebd5Sriastradh shProg->NumShaders++; 3233464ebd5Sriastradh} 3243464ebd5Sriastradh 3253464ebd5Sriastradh 3263464ebd5Sriastradhstatic GLint 3273464ebd5Sriastradhget_attrib_location(struct gl_context *ctx, GLuint program, const GLchar *name) 3283464ebd5Sriastradh{ 3293464ebd5Sriastradh struct gl_shader_program *shProg 3303464ebd5Sriastradh = _mesa_lookup_shader_program_err(ctx, program, "glGetAttribLocation"); 3313464ebd5Sriastradh 3323464ebd5Sriastradh if (!shProg) { 3333464ebd5Sriastradh return -1; 3343464ebd5Sriastradh } 3353464ebd5Sriastradh 3363464ebd5Sriastradh if (!shProg->LinkStatus) { 3373464ebd5Sriastradh _mesa_error(ctx, GL_INVALID_OPERATION, 3383464ebd5Sriastradh "glGetAttribLocation(program not linked)"); 3393464ebd5Sriastradh return -1; 3403464ebd5Sriastradh } 3413464ebd5Sriastradh 3423464ebd5Sriastradh if (!name) 3433464ebd5Sriastradh return -1; 3443464ebd5Sriastradh 3453464ebd5Sriastradh if (shProg->VertexProgram) { 3463464ebd5Sriastradh const struct gl_program_parameter_list *attribs = 3473464ebd5Sriastradh shProg->VertexProgram->Base.Attributes; 3483464ebd5Sriastradh if (attribs) { 3493464ebd5Sriastradh GLint i = _mesa_lookup_parameter_index(attribs, -1, name); 3503464ebd5Sriastradh if (i >= 0) { 3513464ebd5Sriastradh return attribs->Parameters[i].StateIndexes[0]; 3523464ebd5Sriastradh } 3533464ebd5Sriastradh } 3543464ebd5Sriastradh } 3553464ebd5Sriastradh return -1; 3563464ebd5Sriastradh} 3573464ebd5Sriastradh 3583464ebd5Sriastradh 3593464ebd5Sriastradhstatic void 3603464ebd5Sriastradhbind_attrib_location(struct gl_context *ctx, GLuint program, GLuint index, 3613464ebd5Sriastradh const GLchar *name) 3623464ebd5Sriastradh{ 3633464ebd5Sriastradh struct gl_shader_program *shProg; 3643464ebd5Sriastradh const GLint size = -1; /* unknown size */ 3653464ebd5Sriastradh GLint i; 3663464ebd5Sriastradh GLenum datatype = GL_FLOAT_VEC4; 3673464ebd5Sriastradh 3683464ebd5Sriastradh shProg = _mesa_lookup_shader_program_err(ctx, program, 3693464ebd5Sriastradh "glBindAttribLocation"); 3703464ebd5Sriastradh if (!shProg) { 3713464ebd5Sriastradh return; 3723464ebd5Sriastradh } 3733464ebd5Sriastradh 3743464ebd5Sriastradh if (!name) 3753464ebd5Sriastradh return; 3763464ebd5Sriastradh 3773464ebd5Sriastradh if (strncmp(name, "gl_", 3) == 0) { 3783464ebd5Sriastradh _mesa_error(ctx, GL_INVALID_OPERATION, 3793464ebd5Sriastradh "glBindAttribLocation(illegal name)"); 3803464ebd5Sriastradh return; 3813464ebd5Sriastradh } 3823464ebd5Sriastradh 3833464ebd5Sriastradh if (index >= ctx->Const.VertexProgram.MaxAttribs) { 3843464ebd5Sriastradh _mesa_error(ctx, GL_INVALID_VALUE, "glBindAttribLocation(index)"); 3853464ebd5Sriastradh return; 3863464ebd5Sriastradh } 3873464ebd5Sriastradh 3883464ebd5Sriastradh /* this will replace the current value if it's already in the list */ 3893464ebd5Sriastradh i = _mesa_add_attribute(shProg->Attributes, name, size, datatype, index); 3903464ebd5Sriastradh if (i < 0) { 3913464ebd5Sriastradh _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBindAttribLocation"); 3923464ebd5Sriastradh return; 3933464ebd5Sriastradh } 3943464ebd5Sriastradh 3953464ebd5Sriastradh /* 3963464ebd5Sriastradh * Note that this attribute binding won't go into effect until 3973464ebd5Sriastradh * glLinkProgram is called again. 3983464ebd5Sriastradh */ 3993464ebd5Sriastradh} 4003464ebd5Sriastradh 4013464ebd5Sriastradh 4023464ebd5Sriastradhstatic void 4033464ebd5Sriastradhbind_frag_data_location(struct gl_context *ctx, GLuint program, 4043464ebd5Sriastradh GLuint colorNumber, const GLchar *name) 4053464ebd5Sriastradh{ 4063464ebd5Sriastradh _mesa_problem(ctx, "bind_frag_data_location() not implemented yet"); 4073464ebd5Sriastradh} 4083464ebd5Sriastradh 4093464ebd5Sriastradh 4103464ebd5Sriastradhstatic GLuint 4113464ebd5Sriastradhcreate_shader(struct gl_context *ctx, GLenum type) 4123464ebd5Sriastradh{ 4133464ebd5Sriastradh struct gl_shader *sh; 4143464ebd5Sriastradh GLuint name; 4153464ebd5Sriastradh 4163464ebd5Sriastradh if (!validate_shader_target(ctx, type)) { 4173464ebd5Sriastradh _mesa_error(ctx, GL_INVALID_ENUM, "CreateShader(type)"); 4183464ebd5Sriastradh return 0; 4193464ebd5Sriastradh } 4203464ebd5Sriastradh 4213464ebd5Sriastradh name = _mesa_HashFindFreeKeyBlock(ctx->Shared->ShaderObjects, 1); 4223464ebd5Sriastradh sh = ctx->Driver.NewShader(ctx, name, type); 4233464ebd5Sriastradh _mesa_HashInsert(ctx->Shared->ShaderObjects, name, sh); 4243464ebd5Sriastradh 4253464ebd5Sriastradh return name; 4263464ebd5Sriastradh} 4273464ebd5Sriastradh 4283464ebd5Sriastradh 4293464ebd5Sriastradhstatic GLuint 4303464ebd5Sriastradhcreate_shader_program(struct gl_context *ctx) 4313464ebd5Sriastradh{ 4323464ebd5Sriastradh GLuint name; 4333464ebd5Sriastradh struct gl_shader_program *shProg; 4343464ebd5Sriastradh 4353464ebd5Sriastradh name = _mesa_HashFindFreeKeyBlock(ctx->Shared->ShaderObjects, 1); 4363464ebd5Sriastradh 4373464ebd5Sriastradh shProg = ctx->Driver.NewShaderProgram(ctx, name); 4383464ebd5Sriastradh 4393464ebd5Sriastradh _mesa_HashInsert(ctx->Shared->ShaderObjects, name, shProg); 4403464ebd5Sriastradh 4413464ebd5Sriastradh assert(shProg->RefCount == 1); 4423464ebd5Sriastradh 4433464ebd5Sriastradh return name; 4443464ebd5Sriastradh} 4453464ebd5Sriastradh 4463464ebd5Sriastradh 4473464ebd5Sriastradh/** 4483464ebd5Sriastradh * Named w/ "2" to indicate OpenGL 2.x vs GL_ARB_fragment_programs's 4493464ebd5Sriastradh * DeleteProgramARB. 4503464ebd5Sriastradh */ 4513464ebd5Sriastradhstatic void 4523464ebd5Sriastradhdelete_shader_program(struct gl_context *ctx, GLuint name) 4533464ebd5Sriastradh{ 4543464ebd5Sriastradh /* 4553464ebd5Sriastradh * NOTE: deleting shaders/programs works a bit differently than 4563464ebd5Sriastradh * texture objects (and buffer objects, etc). Shader/program 4573464ebd5Sriastradh * handles/IDs exist in the hash table until the object is really 4583464ebd5Sriastradh * deleted (refcount==0). With texture objects, the handle/ID is 4593464ebd5Sriastradh * removed from the hash table in glDeleteTextures() while the tex 4603464ebd5Sriastradh * object itself might linger until its refcount goes to zero. 4613464ebd5Sriastradh */ 4623464ebd5Sriastradh struct gl_shader_program *shProg; 4633464ebd5Sriastradh 4643464ebd5Sriastradh shProg = _mesa_lookup_shader_program_err(ctx, name, "glDeleteProgram"); 4653464ebd5Sriastradh if (!shProg) 4663464ebd5Sriastradh return; 4673464ebd5Sriastradh 4683464ebd5Sriastradh shProg->DeletePending = GL_TRUE; 4693464ebd5Sriastradh 4703464ebd5Sriastradh /* effectively, decr shProg's refcount */ 4713464ebd5Sriastradh _mesa_reference_shader_program(ctx, &shProg, NULL); 4723464ebd5Sriastradh} 4733464ebd5Sriastradh 4743464ebd5Sriastradh 4753464ebd5Sriastradhstatic void 4763464ebd5Sriastradhdelete_shader(struct gl_context *ctx, GLuint shader) 4773464ebd5Sriastradh{ 4783464ebd5Sriastradh struct gl_shader *sh; 4793464ebd5Sriastradh 4803464ebd5Sriastradh sh = _mesa_lookup_shader_err(ctx, shader, "glDeleteShader"); 4813464ebd5Sriastradh if (!sh) 4823464ebd5Sriastradh return; 4833464ebd5Sriastradh 4843464ebd5Sriastradh sh->DeletePending = GL_TRUE; 4853464ebd5Sriastradh 4863464ebd5Sriastradh /* effectively, decr sh's refcount */ 4873464ebd5Sriastradh _mesa_reference_shader(ctx, &sh, NULL); 4883464ebd5Sriastradh} 4893464ebd5Sriastradh 4903464ebd5Sriastradh 4913464ebd5Sriastradhstatic void 4923464ebd5Sriastradhdetach_shader(struct gl_context *ctx, GLuint program, GLuint shader) 4933464ebd5Sriastradh{ 4943464ebd5Sriastradh struct gl_shader_program *shProg; 4953464ebd5Sriastradh GLuint n; 4963464ebd5Sriastradh GLuint i, j; 4973464ebd5Sriastradh 4983464ebd5Sriastradh shProg = _mesa_lookup_shader_program_err(ctx, program, "glDetachShader"); 4993464ebd5Sriastradh if (!shProg) 5003464ebd5Sriastradh return; 5013464ebd5Sriastradh 5023464ebd5Sriastradh n = shProg->NumShaders; 5033464ebd5Sriastradh 5043464ebd5Sriastradh for (i = 0; i < n; i++) { 5053464ebd5Sriastradh if (shProg->Shaders[i]->Name == shader) { 5063464ebd5Sriastradh /* found it */ 5073464ebd5Sriastradh struct gl_shader **newList; 5083464ebd5Sriastradh 5093464ebd5Sriastradh /* release */ 5103464ebd5Sriastradh _mesa_reference_shader(ctx, &shProg->Shaders[i], NULL); 5113464ebd5Sriastradh 5123464ebd5Sriastradh /* alloc new, smaller array */ 5133464ebd5Sriastradh newList = (struct gl_shader **) 5143464ebd5Sriastradh malloc((n - 1) * sizeof(struct gl_shader *)); 5153464ebd5Sriastradh if (!newList) { 5163464ebd5Sriastradh _mesa_error(ctx, GL_OUT_OF_MEMORY, "glDetachShader"); 5173464ebd5Sriastradh return; 5183464ebd5Sriastradh } 5193464ebd5Sriastradh for (j = 0; j < i; j++) { 5203464ebd5Sriastradh newList[j] = shProg->Shaders[j]; 5213464ebd5Sriastradh } 5223464ebd5Sriastradh while (++i < n) 5233464ebd5Sriastradh newList[j++] = shProg->Shaders[i]; 5243464ebd5Sriastradh free(shProg->Shaders); 5253464ebd5Sriastradh 5263464ebd5Sriastradh shProg->Shaders = newList; 5273464ebd5Sriastradh shProg->NumShaders = n - 1; 5283464ebd5Sriastradh 5293464ebd5Sriastradh#ifdef DEBUG 5303464ebd5Sriastradh /* sanity check */ 5313464ebd5Sriastradh { 5323464ebd5Sriastradh for (j = 0; j < shProg->NumShaders; j++) { 5333464ebd5Sriastradh assert(shProg->Shaders[j]->Type == GL_VERTEX_SHADER || 5343464ebd5Sriastradh shProg->Shaders[j]->Type == GL_FRAGMENT_SHADER); 5353464ebd5Sriastradh assert(shProg->Shaders[j]->RefCount > 0); 5363464ebd5Sriastradh } 5373464ebd5Sriastradh } 5383464ebd5Sriastradh#endif 5393464ebd5Sriastradh 5403464ebd5Sriastradh return; 5413464ebd5Sriastradh } 5423464ebd5Sriastradh } 5433464ebd5Sriastradh 5443464ebd5Sriastradh /* not found */ 5453464ebd5Sriastradh { 5463464ebd5Sriastradh GLenum err; 5473464ebd5Sriastradh if (is_shader(ctx, shader)) 5483464ebd5Sriastradh err = GL_INVALID_OPERATION; 5493464ebd5Sriastradh else if (is_program(ctx, shader)) 5503464ebd5Sriastradh err = GL_INVALID_OPERATION; 5513464ebd5Sriastradh else 5523464ebd5Sriastradh err = GL_INVALID_VALUE; 5533464ebd5Sriastradh _mesa_error(ctx, err, "glDetachProgram(shader)"); 5543464ebd5Sriastradh return; 5553464ebd5Sriastradh } 5563464ebd5Sriastradh} 5573464ebd5Sriastradh 5583464ebd5Sriastradh 5593464ebd5Sriastradhstatic void 5603464ebd5Sriastradhget_active_attrib(struct gl_context *ctx, GLuint program, GLuint index, 5613464ebd5Sriastradh GLsizei maxLength, GLsizei *length, GLint *size, 5623464ebd5Sriastradh GLenum *type, GLchar *nameOut) 5633464ebd5Sriastradh{ 5643464ebd5Sriastradh const struct gl_program_parameter_list *attribs = NULL; 5653464ebd5Sriastradh struct gl_shader_program *shProg; 5663464ebd5Sriastradh 5673464ebd5Sriastradh shProg = _mesa_lookup_shader_program_err(ctx, program, "glGetActiveAttrib"); 5683464ebd5Sriastradh if (!shProg) 5693464ebd5Sriastradh return; 5703464ebd5Sriastradh 5713464ebd5Sriastradh if (shProg->VertexProgram) 5723464ebd5Sriastradh attribs = shProg->VertexProgram->Base.Attributes; 5733464ebd5Sriastradh 5743464ebd5Sriastradh if (!attribs || index >= attribs->NumParameters) { 5753464ebd5Sriastradh _mesa_error(ctx, GL_INVALID_VALUE, "glGetActiveAttrib(index)"); 5763464ebd5Sriastradh return; 5773464ebd5Sriastradh } 5783464ebd5Sriastradh 5793464ebd5Sriastradh _mesa_copy_string(nameOut, maxLength, length, 5803464ebd5Sriastradh attribs->Parameters[index].Name); 5813464ebd5Sriastradh 5823464ebd5Sriastradh if (size) 5833464ebd5Sriastradh *size = attribs->Parameters[index].Size 5843464ebd5Sriastradh / _mesa_sizeof_glsl_type(attribs->Parameters[index].DataType); 5853464ebd5Sriastradh 5863464ebd5Sriastradh if (type) 5873464ebd5Sriastradh *type = attribs->Parameters[index].DataType; 5883464ebd5Sriastradh} 5893464ebd5Sriastradh 5903464ebd5Sriastradh 5913464ebd5Sriastradh/** 5923464ebd5Sriastradh * Return list of shaders attached to shader program. 5933464ebd5Sriastradh */ 5943464ebd5Sriastradhstatic void 5953464ebd5Sriastradhget_attached_shaders(struct gl_context *ctx, GLuint program, GLsizei maxCount, 5963464ebd5Sriastradh GLsizei *count, GLuint *obj) 5973464ebd5Sriastradh{ 5983464ebd5Sriastradh struct gl_shader_program *shProg = 5993464ebd5Sriastradh _mesa_lookup_shader_program_err(ctx, program, "glGetAttachedShaders"); 6003464ebd5Sriastradh if (shProg) { 6013464ebd5Sriastradh GLuint i; 6023464ebd5Sriastradh for (i = 0; i < (GLuint) maxCount && i < shProg->NumShaders; i++) { 6033464ebd5Sriastradh obj[i] = shProg->Shaders[i]->Name; 6043464ebd5Sriastradh } 6053464ebd5Sriastradh if (count) 6063464ebd5Sriastradh *count = i; 6073464ebd5Sriastradh } 6083464ebd5Sriastradh} 6093464ebd5Sriastradh 6103464ebd5Sriastradh 6113464ebd5Sriastradhstatic GLint 6123464ebd5Sriastradhget_frag_data_location(struct gl_context *ctx, GLuint program, 6133464ebd5Sriastradh const GLchar *name) 6143464ebd5Sriastradh{ 6153464ebd5Sriastradh _mesa_problem(ctx, "get_frag_data_location() not implemented yet"); 6163464ebd5Sriastradh return -1; 6173464ebd5Sriastradh} 6183464ebd5Sriastradh 6193464ebd5Sriastradh 6203464ebd5Sriastradh 6213464ebd5Sriastradh/** 6223464ebd5Sriastradh * glGetHandleARB() - return ID/name of currently bound shader program. 6233464ebd5Sriastradh */ 6243464ebd5Sriastradhstatic GLuint 6253464ebd5Sriastradhget_handle(struct gl_context *ctx, GLenum pname) 6263464ebd5Sriastradh{ 6273464ebd5Sriastradh if (pname == GL_PROGRAM_OBJECT_ARB) { 6283464ebd5Sriastradh if (ctx->Shader.ActiveProgram) 6293464ebd5Sriastradh return ctx->Shader.ActiveProgram->Name; 6303464ebd5Sriastradh else 6313464ebd5Sriastradh return 0; 6323464ebd5Sriastradh } 6333464ebd5Sriastradh else { 6343464ebd5Sriastradh _mesa_error(ctx, GL_INVALID_ENUM, "glGetHandleARB"); 6353464ebd5Sriastradh return 0; 6363464ebd5Sriastradh } 6373464ebd5Sriastradh} 6383464ebd5Sriastradh 6393464ebd5Sriastradh 6403464ebd5Sriastradh/** 6413464ebd5Sriastradh * glGetProgramiv() - get shader program state. 6423464ebd5Sriastradh * Note that this is for GLSL shader programs, not ARB vertex/fragment 6433464ebd5Sriastradh * programs (see glGetProgramivARB). 6443464ebd5Sriastradh */ 6453464ebd5Sriastradhstatic void 6463464ebd5Sriastradhget_programiv(struct gl_context *ctx, GLuint program, GLenum pname, GLint *params) 6473464ebd5Sriastradh{ 6483464ebd5Sriastradh const struct gl_program_parameter_list *attribs; 6493464ebd5Sriastradh struct gl_shader_program *shProg 6503464ebd5Sriastradh = _mesa_lookup_shader_program(ctx, program); 6513464ebd5Sriastradh 6523464ebd5Sriastradh if (!shProg) { 6533464ebd5Sriastradh _mesa_error(ctx, GL_INVALID_VALUE, "glGetProgramiv(program)"); 6543464ebd5Sriastradh return; 6553464ebd5Sriastradh } 6563464ebd5Sriastradh 6573464ebd5Sriastradh if (shProg->VertexProgram) 6583464ebd5Sriastradh attribs = shProg->VertexProgram->Base.Attributes; 6593464ebd5Sriastradh else 6603464ebd5Sriastradh attribs = NULL; 6613464ebd5Sriastradh 6623464ebd5Sriastradh switch (pname) { 6633464ebd5Sriastradh case GL_DELETE_STATUS: 6643464ebd5Sriastradh *params = shProg->DeletePending; 6653464ebd5Sriastradh break; 6663464ebd5Sriastradh case GL_LINK_STATUS: 6673464ebd5Sriastradh *params = shProg->LinkStatus; 6683464ebd5Sriastradh break; 6693464ebd5Sriastradh case GL_VALIDATE_STATUS: 6703464ebd5Sriastradh *params = shProg->Validated; 6713464ebd5Sriastradh break; 6723464ebd5Sriastradh case GL_INFO_LOG_LENGTH: 6733464ebd5Sriastradh *params = shProg->InfoLog ? strlen(shProg->InfoLog) + 1 : 0; 6743464ebd5Sriastradh break; 6753464ebd5Sriastradh case GL_ATTACHED_SHADERS: 6763464ebd5Sriastradh *params = shProg->NumShaders; 6773464ebd5Sriastradh break; 6783464ebd5Sriastradh case GL_ACTIVE_ATTRIBUTES: 6793464ebd5Sriastradh *params = attribs ? attribs->NumParameters : 0; 6803464ebd5Sriastradh break; 6813464ebd5Sriastradh case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH: 6823464ebd5Sriastradh *params = _mesa_longest_parameter_name(attribs, PROGRAM_INPUT) + 1; 6833464ebd5Sriastradh break; 6843464ebd5Sriastradh case GL_ACTIVE_UNIFORMS: 6853464ebd5Sriastradh *params = shProg->Uniforms ? shProg->Uniforms->NumUniforms : 0; 6863464ebd5Sriastradh break; 6873464ebd5Sriastradh case GL_ACTIVE_UNIFORM_MAX_LENGTH: 6883464ebd5Sriastradh *params = _mesa_longest_uniform_name(shProg->Uniforms); 6893464ebd5Sriastradh if (*params > 0) 6903464ebd5Sriastradh (*params)++; /* add one for terminating zero */ 6913464ebd5Sriastradh break; 6923464ebd5Sriastradh case GL_PROGRAM_BINARY_LENGTH_OES: 6933464ebd5Sriastradh *params = 0; 6943464ebd5Sriastradh break; 6953464ebd5Sriastradh#if FEATURE_EXT_transform_feedback 6963464ebd5Sriastradh case GL_TRANSFORM_FEEDBACK_VARYINGS: 6973464ebd5Sriastradh *params = shProg->TransformFeedback.NumVarying; 6983464ebd5Sriastradh break; 6993464ebd5Sriastradh case GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH: 7003464ebd5Sriastradh *params = longest_feedback_varying_name(shProg) + 1; 7013464ebd5Sriastradh break; 7023464ebd5Sriastradh case GL_TRANSFORM_FEEDBACK_BUFFER_MODE: 7033464ebd5Sriastradh *params = shProg->TransformFeedback.BufferMode; 7043464ebd5Sriastradh break; 7053464ebd5Sriastradh#endif 7063464ebd5Sriastradh#if FEATURE_ARB_geometry_shader4 7073464ebd5Sriastradh case GL_GEOMETRY_VERTICES_OUT_ARB: 7083464ebd5Sriastradh *params = shProg->Geom.VerticesOut; 7093464ebd5Sriastradh break; 7103464ebd5Sriastradh case GL_GEOMETRY_INPUT_TYPE_ARB: 7113464ebd5Sriastradh *params = shProg->Geom.InputType; 7123464ebd5Sriastradh break; 7133464ebd5Sriastradh case GL_GEOMETRY_OUTPUT_TYPE_ARB: 7143464ebd5Sriastradh *params = shProg->Geom.OutputType; 7153464ebd5Sriastradh break; 7163464ebd5Sriastradh#endif 7173464ebd5Sriastradh default: 7183464ebd5Sriastradh _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramiv(pname)"); 7193464ebd5Sriastradh return; 7203464ebd5Sriastradh } 7213464ebd5Sriastradh} 7223464ebd5Sriastradh 7233464ebd5Sriastradh 7243464ebd5Sriastradh/** 7253464ebd5Sriastradh * glGetShaderiv() - get GLSL shader state 7263464ebd5Sriastradh */ 7273464ebd5Sriastradhstatic void 7283464ebd5Sriastradhget_shaderiv(struct gl_context *ctx, GLuint name, GLenum pname, GLint *params) 7293464ebd5Sriastradh{ 7303464ebd5Sriastradh struct gl_shader *shader = 7313464ebd5Sriastradh _mesa_lookup_shader_err(ctx, name, "glGetShaderiv"); 7323464ebd5Sriastradh 7333464ebd5Sriastradh if (!shader) { 7343464ebd5Sriastradh return; 7353464ebd5Sriastradh } 7363464ebd5Sriastradh 7373464ebd5Sriastradh switch (pname) { 7383464ebd5Sriastradh case GL_SHADER_TYPE: 7393464ebd5Sriastradh *params = shader->Type; 7403464ebd5Sriastradh break; 7413464ebd5Sriastradh case GL_DELETE_STATUS: 7423464ebd5Sriastradh *params = shader->DeletePending; 7433464ebd5Sriastradh break; 7443464ebd5Sriastradh case GL_COMPILE_STATUS: 7453464ebd5Sriastradh *params = shader->CompileStatus; 7463464ebd5Sriastradh break; 7473464ebd5Sriastradh case GL_INFO_LOG_LENGTH: 7483464ebd5Sriastradh *params = shader->InfoLog ? strlen(shader->InfoLog) + 1 : 0; 7493464ebd5Sriastradh break; 7503464ebd5Sriastradh case GL_SHADER_SOURCE_LENGTH: 7513464ebd5Sriastradh *params = shader->Source ? strlen((char *) shader->Source) + 1 : 0; 7523464ebd5Sriastradh break; 7533464ebd5Sriastradh default: 7543464ebd5Sriastradh _mesa_error(ctx, GL_INVALID_ENUM, "glGetShaderiv(pname)"); 7553464ebd5Sriastradh return; 7563464ebd5Sriastradh } 7573464ebd5Sriastradh} 7583464ebd5Sriastradh 7593464ebd5Sriastradh 7603464ebd5Sriastradhstatic void 7613464ebd5Sriastradhget_program_info_log(struct gl_context *ctx, GLuint program, GLsizei bufSize, 7623464ebd5Sriastradh GLsizei *length, GLchar *infoLog) 7633464ebd5Sriastradh{ 7643464ebd5Sriastradh struct gl_shader_program *shProg 7653464ebd5Sriastradh = _mesa_lookup_shader_program(ctx, program); 7663464ebd5Sriastradh if (!shProg) { 7673464ebd5Sriastradh _mesa_error(ctx, GL_INVALID_VALUE, "glGetProgramInfoLog(program)"); 7683464ebd5Sriastradh return; 7693464ebd5Sriastradh } 7703464ebd5Sriastradh _mesa_copy_string(infoLog, bufSize, length, shProg->InfoLog); 7713464ebd5Sriastradh} 7723464ebd5Sriastradh 7733464ebd5Sriastradh 7743464ebd5Sriastradhstatic void 7753464ebd5Sriastradhget_shader_info_log(struct gl_context *ctx, GLuint shader, GLsizei bufSize, 7763464ebd5Sriastradh GLsizei *length, GLchar *infoLog) 7773464ebd5Sriastradh{ 7783464ebd5Sriastradh struct gl_shader *sh = _mesa_lookup_shader(ctx, shader); 7793464ebd5Sriastradh if (!sh) { 7803464ebd5Sriastradh _mesa_error(ctx, GL_INVALID_VALUE, "glGetShaderInfoLog(shader)"); 7813464ebd5Sriastradh return; 7823464ebd5Sriastradh } 7833464ebd5Sriastradh _mesa_copy_string(infoLog, bufSize, length, sh->InfoLog); 7843464ebd5Sriastradh} 7853464ebd5Sriastradh 7863464ebd5Sriastradh 7873464ebd5Sriastradh/** 7883464ebd5Sriastradh * Return shader source code. 7893464ebd5Sriastradh */ 7903464ebd5Sriastradhstatic void 7913464ebd5Sriastradhget_shader_source(struct gl_context *ctx, GLuint shader, GLsizei maxLength, 7923464ebd5Sriastradh GLsizei *length, GLchar *sourceOut) 7933464ebd5Sriastradh{ 7943464ebd5Sriastradh struct gl_shader *sh; 7953464ebd5Sriastradh sh = _mesa_lookup_shader_err(ctx, shader, "glGetShaderSource"); 7963464ebd5Sriastradh if (!sh) { 7973464ebd5Sriastradh return; 7983464ebd5Sriastradh } 7993464ebd5Sriastradh _mesa_copy_string(sourceOut, maxLength, length, sh->Source); 8003464ebd5Sriastradh} 8013464ebd5Sriastradh 8023464ebd5Sriastradh 8033464ebd5Sriastradh/** 8043464ebd5Sriastradh * Set/replace shader source code. 8053464ebd5Sriastradh */ 8063464ebd5Sriastradhstatic void 8073464ebd5Sriastradhshader_source(struct gl_context *ctx, GLuint shader, const GLchar *source) 8083464ebd5Sriastradh{ 8093464ebd5Sriastradh struct gl_shader *sh; 8103464ebd5Sriastradh 8113464ebd5Sriastradh sh = _mesa_lookup_shader_err(ctx, shader, "glShaderSource"); 8123464ebd5Sriastradh if (!sh) 8133464ebd5Sriastradh return; 8143464ebd5Sriastradh 8153464ebd5Sriastradh /* free old shader source string and install new one */ 8163464ebd5Sriastradh if (sh->Source) { 8173464ebd5Sriastradh free((void *) sh->Source); 8183464ebd5Sriastradh } 8193464ebd5Sriastradh sh->Source = source; 8203464ebd5Sriastradh sh->CompileStatus = GL_FALSE; 8213464ebd5Sriastradh#ifdef DEBUG 8223464ebd5Sriastradh sh->SourceChecksum = _mesa_str_checksum(sh->Source); 8233464ebd5Sriastradh#endif 8243464ebd5Sriastradh} 8253464ebd5Sriastradh 8263464ebd5Sriastradh 8273464ebd5Sriastradh/** 8283464ebd5Sriastradh * Compile a shader. 8293464ebd5Sriastradh */ 8303464ebd5Sriastradhstatic void 8313464ebd5Sriastradhcompile_shader(struct gl_context *ctx, GLuint shaderObj) 8323464ebd5Sriastradh{ 8333464ebd5Sriastradh struct gl_shader *sh; 8343464ebd5Sriastradh struct gl_shader_compiler_options *options; 8353464ebd5Sriastradh 8363464ebd5Sriastradh sh = _mesa_lookup_shader_err(ctx, shaderObj, "glCompileShader"); 8373464ebd5Sriastradh if (!sh) 8383464ebd5Sriastradh return; 8393464ebd5Sriastradh 8403464ebd5Sriastradh options = &ctx->ShaderCompilerOptions[_mesa_shader_type_to_index(sh->Type)]; 8413464ebd5Sriastradh 8423464ebd5Sriastradh /* set default pragma state for shader */ 8433464ebd5Sriastradh sh->Pragmas = options->DefaultPragmas; 8443464ebd5Sriastradh 8453464ebd5Sriastradh /* this call will set the sh->CompileStatus field to indicate if 8463464ebd5Sriastradh * compilation was successful. 8473464ebd5Sriastradh */ 8483464ebd5Sriastradh _mesa_glsl_compile_shader(ctx, sh); 8493464ebd5Sriastradh} 8503464ebd5Sriastradh 8513464ebd5Sriastradh 8523464ebd5Sriastradh/** 8533464ebd5Sriastradh * Link a program's shaders. 8543464ebd5Sriastradh */ 8553464ebd5Sriastradhstatic void 8563464ebd5Sriastradhlink_program(struct gl_context *ctx, GLuint program) 8573464ebd5Sriastradh{ 8583464ebd5Sriastradh struct gl_shader_program *shProg; 8593464ebd5Sriastradh struct gl_transform_feedback_object *obj = 8603464ebd5Sriastradh ctx->TransformFeedback.CurrentObject; 8613464ebd5Sriastradh 8623464ebd5Sriastradh shProg = _mesa_lookup_shader_program_err(ctx, program, "glLinkProgram"); 8633464ebd5Sriastradh if (!shProg) 8643464ebd5Sriastradh return; 8653464ebd5Sriastradh 8663464ebd5Sriastradh if (obj->Active 8673464ebd5Sriastradh && (shProg == ctx->Shader.CurrentVertexProgram 8683464ebd5Sriastradh || shProg == ctx->Shader.CurrentGeometryProgram 8693464ebd5Sriastradh || shProg == ctx->Shader.CurrentFragmentProgram)) { 8703464ebd5Sriastradh _mesa_error(ctx, GL_INVALID_OPERATION, 8713464ebd5Sriastradh "glLinkProgram(transform feedback active"); 8723464ebd5Sriastradh return; 8733464ebd5Sriastradh } 8743464ebd5Sriastradh 8753464ebd5Sriastradh FLUSH_VERTICES(ctx, _NEW_PROGRAM); 8763464ebd5Sriastradh 8773464ebd5Sriastradh _mesa_glsl_link_shader(ctx, shProg); 8783464ebd5Sriastradh 8793464ebd5Sriastradh /* debug code */ 8803464ebd5Sriastradh if (0) { 8813464ebd5Sriastradh GLuint i; 8823464ebd5Sriastradh 8833464ebd5Sriastradh printf("Link %u shaders in program %u: %s\n", 8843464ebd5Sriastradh shProg->NumShaders, shProg->Name, 8853464ebd5Sriastradh shProg->LinkStatus ? "Success" : "Failed"); 8863464ebd5Sriastradh 8873464ebd5Sriastradh for (i = 0; i < shProg->NumShaders; i++) { 8883464ebd5Sriastradh printf(" shader %u, type 0x%x\n", 8893464ebd5Sriastradh shProg->Shaders[i]->Name, 8903464ebd5Sriastradh shProg->Shaders[i]->Type); 8913464ebd5Sriastradh } 8923464ebd5Sriastradh } 8933464ebd5Sriastradh} 8943464ebd5Sriastradh 8953464ebd5Sriastradh 8963464ebd5Sriastradh/** 8973464ebd5Sriastradh * Print basic shader info (for debug). 8983464ebd5Sriastradh */ 8993464ebd5Sriastradhstatic void 9003464ebd5Sriastradhprint_shader_info(const struct gl_shader_program *shProg) 9013464ebd5Sriastradh{ 9023464ebd5Sriastradh GLuint i; 9033464ebd5Sriastradh 9043464ebd5Sriastradh printf("Mesa: glUseProgram(%u)\n", shProg->Name); 9053464ebd5Sriastradh for (i = 0; i < shProg->NumShaders; i++) { 9063464ebd5Sriastradh const char *s; 9073464ebd5Sriastradh switch (shProg->Shaders[i]->Type) { 9083464ebd5Sriastradh case GL_VERTEX_SHADER: 9093464ebd5Sriastradh s = "vertex"; 9103464ebd5Sriastradh break; 9113464ebd5Sriastradh case GL_FRAGMENT_SHADER: 9123464ebd5Sriastradh s = "fragment"; 9133464ebd5Sriastradh break; 9143464ebd5Sriastradh case GL_GEOMETRY_SHADER: 9153464ebd5Sriastradh s = "geometry"; 9163464ebd5Sriastradh break; 9173464ebd5Sriastradh default: 9183464ebd5Sriastradh s = ""; 9193464ebd5Sriastradh } 9203464ebd5Sriastradh printf(" %s shader %u, checksum %u\n", s, 9213464ebd5Sriastradh shProg->Shaders[i]->Name, 9223464ebd5Sriastradh shProg->Shaders[i]->SourceChecksum); 9233464ebd5Sriastradh } 9243464ebd5Sriastradh if (shProg->VertexProgram) 9253464ebd5Sriastradh printf(" vert prog %u\n", shProg->VertexProgram->Base.Id); 9263464ebd5Sriastradh if (shProg->FragmentProgram) 9273464ebd5Sriastradh printf(" frag prog %u\n", shProg->FragmentProgram->Base.Id); 9283464ebd5Sriastradh if (shProg->GeometryProgram) 9293464ebd5Sriastradh printf(" geom prog %u\n", shProg->GeometryProgram->Base.Id); 9303464ebd5Sriastradh} 9313464ebd5Sriastradh 9323464ebd5Sriastradh 9333464ebd5Sriastradh/** 9343464ebd5Sriastradh * Use the named shader program for subsequent glUniform calls 9353464ebd5Sriastradh */ 9363464ebd5Sriastradhvoid 9373464ebd5Sriastradh_mesa_active_program(struct gl_context *ctx, struct gl_shader_program *shProg, 9383464ebd5Sriastradh const char *caller) 9393464ebd5Sriastradh{ 9403464ebd5Sriastradh if ((shProg != NULL) && !shProg->LinkStatus) { 9413464ebd5Sriastradh _mesa_error(ctx, GL_INVALID_OPERATION, 9423464ebd5Sriastradh "%s(program %u not linked)", caller, shProg->Name); 9433464ebd5Sriastradh return; 9443464ebd5Sriastradh } 9453464ebd5Sriastradh 9463464ebd5Sriastradh if (ctx->Shader.ActiveProgram != shProg) { 9473464ebd5Sriastradh _mesa_reference_shader_program(ctx, &ctx->Shader.ActiveProgram, shProg); 9483464ebd5Sriastradh } 9493464ebd5Sriastradh} 9503464ebd5Sriastradh 9513464ebd5Sriastradh/** 9523464ebd5Sriastradh */ 9533464ebd5Sriastradhstatic bool 9543464ebd5Sriastradhuse_shader_program(struct gl_context *ctx, GLenum type, 9553464ebd5Sriastradh struct gl_shader_program *shProg) 9563464ebd5Sriastradh{ 9573464ebd5Sriastradh struct gl_shader_program **target; 9583464ebd5Sriastradh 9593464ebd5Sriastradh switch (type) { 9603464ebd5Sriastradh#if FEATURE_ARB_vertex_shader 9613464ebd5Sriastradh case GL_VERTEX_SHADER: 9623464ebd5Sriastradh target = &ctx->Shader.CurrentVertexProgram; 9633464ebd5Sriastradh if ((shProg == NULL) 9643464ebd5Sriastradh || (shProg->_LinkedShaders[MESA_SHADER_VERTEX] == NULL)) { 9653464ebd5Sriastradh shProg = NULL; 9663464ebd5Sriastradh } 9673464ebd5Sriastradh break; 9683464ebd5Sriastradh#endif 9693464ebd5Sriastradh#if FEATURE_ARB_geometry_shader4 9703464ebd5Sriastradh case GL_GEOMETRY_SHADER_ARB: 9713464ebd5Sriastradh target = &ctx->Shader.CurrentGeometryProgram; 9723464ebd5Sriastradh if ((shProg == NULL) 9733464ebd5Sriastradh || (shProg->_LinkedShaders[MESA_SHADER_GEOMETRY] == NULL)) { 9743464ebd5Sriastradh shProg = NULL; 9753464ebd5Sriastradh } 9763464ebd5Sriastradh break; 9773464ebd5Sriastradh#endif 9783464ebd5Sriastradh#if FEATURE_ARB_fragment_shader 9793464ebd5Sriastradh case GL_FRAGMENT_SHADER: 9803464ebd5Sriastradh target = &ctx->Shader.CurrentFragmentProgram; 9813464ebd5Sriastradh if ((shProg == NULL) 9823464ebd5Sriastradh || (shProg->_LinkedShaders[MESA_SHADER_FRAGMENT] == NULL)) { 9833464ebd5Sriastradh shProg = NULL; 9843464ebd5Sriastradh } 9853464ebd5Sriastradh break; 9863464ebd5Sriastradh#endif 9873464ebd5Sriastradh default: 9883464ebd5Sriastradh return false; 9893464ebd5Sriastradh } 9903464ebd5Sriastradh 9913464ebd5Sriastradh if (*target != shProg) { 9923464ebd5Sriastradh FLUSH_VERTICES(ctx, _NEW_PROGRAM | _NEW_PROGRAM_CONSTANTS); 9933464ebd5Sriastradh _mesa_reference_shader_program(ctx, target, shProg); 9943464ebd5Sriastradh return true; 9953464ebd5Sriastradh } 9963464ebd5Sriastradh 9973464ebd5Sriastradh return false; 9983464ebd5Sriastradh} 9993464ebd5Sriastradh 10003464ebd5Sriastradh/** 10013464ebd5Sriastradh * Use the named shader program for subsequent rendering. 10023464ebd5Sriastradh */ 10033464ebd5Sriastradhvoid 10043464ebd5Sriastradh_mesa_use_program(struct gl_context *ctx, struct gl_shader_program *shProg) 10053464ebd5Sriastradh{ 10063464ebd5Sriastradh use_shader_program(ctx, GL_VERTEX_SHADER, shProg); 10073464ebd5Sriastradh use_shader_program(ctx, GL_GEOMETRY_SHADER_ARB, shProg); 10083464ebd5Sriastradh use_shader_program(ctx, GL_FRAGMENT_SHADER, shProg); 10093464ebd5Sriastradh _mesa_active_program(ctx, shProg, "glUseProgram"); 10103464ebd5Sriastradh 10113464ebd5Sriastradh if (ctx->Driver.UseProgram) 10123464ebd5Sriastradh ctx->Driver.UseProgram(ctx, shProg); 10133464ebd5Sriastradh} 10143464ebd5Sriastradh 10153464ebd5Sriastradh 10163464ebd5Sriastradh/** 10173464ebd5Sriastradh * Validate a program's samplers. 10183464ebd5Sriastradh * Specifically, check that there aren't two samplers of different types 10193464ebd5Sriastradh * pointing to the same texture unit. 10203464ebd5Sriastradh * \return GL_TRUE if valid, GL_FALSE if invalid 10213464ebd5Sriastradh */ 10223464ebd5Sriastradhstatic GLboolean 10233464ebd5Sriastradhvalidate_samplers(const struct gl_program *prog, char *errMsg) 10243464ebd5Sriastradh{ 10253464ebd5Sriastradh static const char *targetName[] = { 10263464ebd5Sriastradh "TEXTURE_BUFFER", 10273464ebd5Sriastradh "TEXTURE_2D_ARRAY", 10283464ebd5Sriastradh "TEXTURE_1D_ARRAY", 10293464ebd5Sriastradh "TEXTURE_CUBE", 10303464ebd5Sriastradh "TEXTURE_3D", 10313464ebd5Sriastradh "TEXTURE_RECT", 10323464ebd5Sriastradh "TEXTURE_2D", 10333464ebd5Sriastradh "TEXTURE_1D", 10343464ebd5Sriastradh }; 10353464ebd5Sriastradh GLint targetUsed[MAX_COMBINED_TEXTURE_IMAGE_UNITS]; 10363464ebd5Sriastradh GLbitfield samplersUsed = prog->SamplersUsed; 10373464ebd5Sriastradh GLuint i; 10383464ebd5Sriastradh 10393464ebd5Sriastradh assert(Elements(targetName) == NUM_TEXTURE_TARGETS); 10403464ebd5Sriastradh 10413464ebd5Sriastradh if (samplersUsed == 0x0) 10423464ebd5Sriastradh return GL_TRUE; 10433464ebd5Sriastradh 10443464ebd5Sriastradh for (i = 0; i < Elements(targetUsed); i++) 10453464ebd5Sriastradh targetUsed[i] = -1; 10463464ebd5Sriastradh 10473464ebd5Sriastradh /* walk over bits which are set in 'samplers' */ 10483464ebd5Sriastradh while (samplersUsed) { 10493464ebd5Sriastradh GLuint unit; 10503464ebd5Sriastradh gl_texture_index target; 10513464ebd5Sriastradh GLint sampler = _mesa_ffs(samplersUsed) - 1; 10523464ebd5Sriastradh assert(sampler >= 0); 10533464ebd5Sriastradh assert(sampler < Elements(prog->SamplerUnits)); 10543464ebd5Sriastradh unit = prog->SamplerUnits[sampler]; 10553464ebd5Sriastradh target = prog->SamplerTargets[sampler]; 10563464ebd5Sriastradh if (targetUsed[unit] != -1 && targetUsed[unit] != (int) target) { 10573464ebd5Sriastradh _mesa_snprintf(errMsg, 100, 10583464ebd5Sriastradh "Texture unit %d is accessed both as %s and %s", 10593464ebd5Sriastradh unit, targetName[targetUsed[unit]], targetName[target]); 10603464ebd5Sriastradh return GL_FALSE; 10613464ebd5Sriastradh } 10623464ebd5Sriastradh targetUsed[unit] = target; 10633464ebd5Sriastradh samplersUsed ^= (1 << sampler); 10643464ebd5Sriastradh } 10653464ebd5Sriastradh 10663464ebd5Sriastradh return GL_TRUE; 10673464ebd5Sriastradh} 10683464ebd5Sriastradh 10693464ebd5Sriastradh 10703464ebd5Sriastradh/** 10713464ebd5Sriastradh * Do validation of the given shader program. 10723464ebd5Sriastradh * \param errMsg returns error message if validation fails. 10733464ebd5Sriastradh * \return GL_TRUE if valid, GL_FALSE if invalid (and set errMsg) 10743464ebd5Sriastradh */ 10753464ebd5Sriastradhstatic GLboolean 10763464ebd5Sriastradhvalidate_shader_program(const struct gl_shader_program *shProg, 10773464ebd5Sriastradh char *errMsg) 10783464ebd5Sriastradh{ 10793464ebd5Sriastradh const struct gl_vertex_program *vp = shProg->VertexProgram; 10803464ebd5Sriastradh const struct gl_geometry_program *gp = shProg->GeometryProgram; 10813464ebd5Sriastradh const struct gl_fragment_program *fp = shProg->FragmentProgram; 10823464ebd5Sriastradh 10833464ebd5Sriastradh if (!shProg->LinkStatus) { 10843464ebd5Sriastradh return GL_FALSE; 10853464ebd5Sriastradh } 10863464ebd5Sriastradh 10873464ebd5Sriastradh /* From the GL spec, a program is invalid if any of these are true: 10883464ebd5Sriastradh 10893464ebd5Sriastradh any two active samplers in the current program object are of 10903464ebd5Sriastradh different types, but refer to the same texture image unit, 10913464ebd5Sriastradh 10923464ebd5Sriastradh any active sampler in the current program object refers to a texture 10933464ebd5Sriastradh image unit where fixed-function fragment processing accesses a 10943464ebd5Sriastradh texture target that does not match the sampler type, or 10953464ebd5Sriastradh 10963464ebd5Sriastradh the sum of the number of active samplers in the program and the 10973464ebd5Sriastradh number of texture image units enabled for fixed-function fragment 10983464ebd5Sriastradh processing exceeds the combined limit on the total number of texture 10993464ebd5Sriastradh image units allowed. 11003464ebd5Sriastradh */ 11013464ebd5Sriastradh 11023464ebd5Sriastradh 11033464ebd5Sriastradh /* 11043464ebd5Sriastradh * Check: any two active samplers in the current program object are of 11053464ebd5Sriastradh * different types, but refer to the same texture image unit, 11063464ebd5Sriastradh */ 11073464ebd5Sriastradh if (vp && !validate_samplers(&vp->Base, errMsg)) { 11083464ebd5Sriastradh return GL_FALSE; 11093464ebd5Sriastradh } 11103464ebd5Sriastradh if (gp && !validate_samplers(&gp->Base, errMsg)) { 11113464ebd5Sriastradh return GL_FALSE; 11123464ebd5Sriastradh } 11133464ebd5Sriastradh if (fp && !validate_samplers(&fp->Base, errMsg)) { 11143464ebd5Sriastradh return GL_FALSE; 11153464ebd5Sriastradh } 11163464ebd5Sriastradh 11173464ebd5Sriastradh return GL_TRUE; 11183464ebd5Sriastradh} 11193464ebd5Sriastradh 11203464ebd5Sriastradh 11213464ebd5Sriastradh/** 11223464ebd5Sriastradh * Called via glValidateProgram() 11233464ebd5Sriastradh */ 11243464ebd5Sriastradhstatic void 11253464ebd5Sriastradhvalidate_program(struct gl_context *ctx, GLuint program) 11263464ebd5Sriastradh{ 11273464ebd5Sriastradh struct gl_shader_program *shProg; 11283464ebd5Sriastradh char errMsg[100] = ""; 11293464ebd5Sriastradh 11303464ebd5Sriastradh shProg = _mesa_lookup_shader_program_err(ctx, program, "glValidateProgram"); 11313464ebd5Sriastradh if (!shProg) { 11323464ebd5Sriastradh return; 11333464ebd5Sriastradh } 11343464ebd5Sriastradh 11353464ebd5Sriastradh shProg->Validated = validate_shader_program(shProg, errMsg); 11363464ebd5Sriastradh if (!shProg->Validated) { 11373464ebd5Sriastradh /* update info log */ 11383464ebd5Sriastradh if (shProg->InfoLog) { 11393464ebd5Sriastradh ralloc_free(shProg->InfoLog); 11403464ebd5Sriastradh } 11413464ebd5Sriastradh shProg->InfoLog = ralloc_strdup(shProg, errMsg); 11423464ebd5Sriastradh } 11433464ebd5Sriastradh} 11443464ebd5Sriastradh 11453464ebd5Sriastradh 11463464ebd5Sriastradh 11473464ebd5Sriastradhvoid GLAPIENTRY 11483464ebd5Sriastradh_mesa_AttachObjectARB(GLhandleARB program, GLhandleARB shader) 11493464ebd5Sriastradh{ 11503464ebd5Sriastradh GET_CURRENT_CONTEXT(ctx); 11513464ebd5Sriastradh attach_shader(ctx, program, shader); 11523464ebd5Sriastradh} 11533464ebd5Sriastradh 11543464ebd5Sriastradh 11553464ebd5Sriastradhvoid GLAPIENTRY 11563464ebd5Sriastradh_mesa_AttachShader(GLuint program, GLuint shader) 11573464ebd5Sriastradh{ 11583464ebd5Sriastradh GET_CURRENT_CONTEXT(ctx); 11593464ebd5Sriastradh attach_shader(ctx, program, shader); 11603464ebd5Sriastradh} 11613464ebd5Sriastradh 11623464ebd5Sriastradh 11633464ebd5Sriastradhvoid GLAPIENTRY 11643464ebd5Sriastradh_mesa_BindAttribLocationARB(GLhandleARB program, GLuint index, 11653464ebd5Sriastradh const GLcharARB *name) 11663464ebd5Sriastradh{ 11673464ebd5Sriastradh GET_CURRENT_CONTEXT(ctx); 11683464ebd5Sriastradh bind_attrib_location(ctx, program, index, name); 11693464ebd5Sriastradh} 11703464ebd5Sriastradh 11713464ebd5Sriastradh 11723464ebd5Sriastradh/* GL_EXT_gpu_shader4, GL3 */ 11733464ebd5Sriastradhvoid GLAPIENTRY 11743464ebd5Sriastradh_mesa_BindFragDataLocation(GLuint program, GLuint colorNumber, 11753464ebd5Sriastradh const GLchar *name) 11763464ebd5Sriastradh{ 11773464ebd5Sriastradh GET_CURRENT_CONTEXT(ctx); 11783464ebd5Sriastradh bind_frag_data_location(ctx, program, colorNumber, name); 11793464ebd5Sriastradh} 11803464ebd5Sriastradh 11813464ebd5Sriastradh 11823464ebd5Sriastradhvoid GLAPIENTRY 11833464ebd5Sriastradh_mesa_CompileShaderARB(GLhandleARB shaderObj) 11843464ebd5Sriastradh{ 11853464ebd5Sriastradh GET_CURRENT_CONTEXT(ctx); 11863464ebd5Sriastradh if (MESA_VERBOSE & VERBOSE_API) 11873464ebd5Sriastradh _mesa_debug(ctx, "glCompileShader %u\n", shaderObj); 11883464ebd5Sriastradh compile_shader(ctx, shaderObj); 11893464ebd5Sriastradh} 11903464ebd5Sriastradh 11913464ebd5Sriastradh 11923464ebd5SriastradhGLuint GLAPIENTRY 11933464ebd5Sriastradh_mesa_CreateShader(GLenum type) 11943464ebd5Sriastradh{ 11953464ebd5Sriastradh GET_CURRENT_CONTEXT(ctx); 11963464ebd5Sriastradh if (MESA_VERBOSE & VERBOSE_API) 11973464ebd5Sriastradh _mesa_debug(ctx, "glCreateShader %s\n", _mesa_lookup_enum_by_nr(type)); 11983464ebd5Sriastradh return create_shader(ctx, type); 11993464ebd5Sriastradh} 12003464ebd5Sriastradh 12013464ebd5Sriastradh 12023464ebd5SriastradhGLhandleARB GLAPIENTRY 12033464ebd5Sriastradh_mesa_CreateShaderObjectARB(GLenum type) 12043464ebd5Sriastradh{ 12053464ebd5Sriastradh GET_CURRENT_CONTEXT(ctx); 12063464ebd5Sriastradh return create_shader(ctx, type); 12073464ebd5Sriastradh} 12083464ebd5Sriastradh 12093464ebd5Sriastradh 12103464ebd5SriastradhGLuint GLAPIENTRY 12113464ebd5Sriastradh_mesa_CreateProgram(void) 12123464ebd5Sriastradh{ 12133464ebd5Sriastradh GET_CURRENT_CONTEXT(ctx); 12143464ebd5Sriastradh if (MESA_VERBOSE & VERBOSE_API) 12153464ebd5Sriastradh _mesa_debug(ctx, "glCreateProgram\n"); 12163464ebd5Sriastradh return create_shader_program(ctx); 12173464ebd5Sriastradh} 12183464ebd5Sriastradh 12193464ebd5Sriastradh 12203464ebd5SriastradhGLhandleARB GLAPIENTRY 12213464ebd5Sriastradh_mesa_CreateProgramObjectARB(void) 12223464ebd5Sriastradh{ 12233464ebd5Sriastradh GET_CURRENT_CONTEXT(ctx); 12243464ebd5Sriastradh return create_shader_program(ctx); 12253464ebd5Sriastradh} 12263464ebd5Sriastradh 12273464ebd5Sriastradh 12283464ebd5Sriastradhvoid GLAPIENTRY 12293464ebd5Sriastradh_mesa_DeleteObjectARB(GLhandleARB obj) 12303464ebd5Sriastradh{ 12313464ebd5Sriastradh if (MESA_VERBOSE & VERBOSE_API) { 12323464ebd5Sriastradh GET_CURRENT_CONTEXT(ctx); 12333464ebd5Sriastradh _mesa_debug(ctx, "glDeleteObjectARB(%u)\n", obj); 12343464ebd5Sriastradh } 12353464ebd5Sriastradh 12363464ebd5Sriastradh if (obj) { 12373464ebd5Sriastradh GET_CURRENT_CONTEXT(ctx); 12383464ebd5Sriastradh FLUSH_VERTICES(ctx, 0); 12393464ebd5Sriastradh if (is_program(ctx, obj)) { 12403464ebd5Sriastradh delete_shader_program(ctx, obj); 12413464ebd5Sriastradh } 12423464ebd5Sriastradh else if (is_shader(ctx, obj)) { 12433464ebd5Sriastradh delete_shader(ctx, obj); 12443464ebd5Sriastradh } 12453464ebd5Sriastradh else { 12463464ebd5Sriastradh /* error? */ 12473464ebd5Sriastradh } 12483464ebd5Sriastradh } 12493464ebd5Sriastradh} 12503464ebd5Sriastradh 12513464ebd5Sriastradh 12523464ebd5Sriastradhvoid GLAPIENTRY 12533464ebd5Sriastradh_mesa_DeleteProgram(GLuint name) 12543464ebd5Sriastradh{ 12553464ebd5Sriastradh if (name) { 12563464ebd5Sriastradh GET_CURRENT_CONTEXT(ctx); 12573464ebd5Sriastradh FLUSH_VERTICES(ctx, 0); 12583464ebd5Sriastradh delete_shader_program(ctx, name); 12593464ebd5Sriastradh } 12603464ebd5Sriastradh} 12613464ebd5Sriastradh 12623464ebd5Sriastradh 12633464ebd5Sriastradhvoid GLAPIENTRY 12643464ebd5Sriastradh_mesa_DeleteShader(GLuint name) 12653464ebd5Sriastradh{ 12663464ebd5Sriastradh if (name) { 12673464ebd5Sriastradh GET_CURRENT_CONTEXT(ctx); 12683464ebd5Sriastradh FLUSH_VERTICES(ctx, 0); 12693464ebd5Sriastradh delete_shader(ctx, name); 12703464ebd5Sriastradh } 12713464ebd5Sriastradh} 12723464ebd5Sriastradh 12733464ebd5Sriastradh 12743464ebd5Sriastradhvoid GLAPIENTRY 12753464ebd5Sriastradh_mesa_DetachObjectARB(GLhandleARB program, GLhandleARB shader) 12763464ebd5Sriastradh{ 12773464ebd5Sriastradh GET_CURRENT_CONTEXT(ctx); 12783464ebd5Sriastradh detach_shader(ctx, program, shader); 12793464ebd5Sriastradh} 12803464ebd5Sriastradh 12813464ebd5Sriastradh 12823464ebd5Sriastradhvoid GLAPIENTRY 12833464ebd5Sriastradh_mesa_DetachShader(GLuint program, GLuint shader) 12843464ebd5Sriastradh{ 12853464ebd5Sriastradh GET_CURRENT_CONTEXT(ctx); 12863464ebd5Sriastradh detach_shader(ctx, program, shader); 12873464ebd5Sriastradh} 12883464ebd5Sriastradh 12893464ebd5Sriastradh 12903464ebd5Sriastradhvoid GLAPIENTRY 12913464ebd5Sriastradh_mesa_GetActiveAttribARB(GLhandleARB program, GLuint index, 12923464ebd5Sriastradh GLsizei maxLength, GLsizei * length, GLint * size, 12933464ebd5Sriastradh GLenum * type, GLcharARB * name) 12943464ebd5Sriastradh{ 12953464ebd5Sriastradh GET_CURRENT_CONTEXT(ctx); 12963464ebd5Sriastradh get_active_attrib(ctx, program, index, maxLength, length, size, type, name); 12973464ebd5Sriastradh} 12983464ebd5Sriastradh 12993464ebd5Sriastradh 13003464ebd5Sriastradhvoid GLAPIENTRY 13013464ebd5Sriastradh_mesa_GetAttachedObjectsARB(GLhandleARB container, GLsizei maxCount, 13023464ebd5Sriastradh GLsizei * count, GLhandleARB * obj) 13033464ebd5Sriastradh{ 13043464ebd5Sriastradh GET_CURRENT_CONTEXT(ctx); 13053464ebd5Sriastradh get_attached_shaders(ctx, container, maxCount, count, obj); 13063464ebd5Sriastradh} 13073464ebd5Sriastradh 13083464ebd5Sriastradh 13093464ebd5Sriastradhvoid GLAPIENTRY 13103464ebd5Sriastradh_mesa_GetAttachedShaders(GLuint program, GLsizei maxCount, 13113464ebd5Sriastradh GLsizei *count, GLuint *obj) 13123464ebd5Sriastradh{ 13133464ebd5Sriastradh GET_CURRENT_CONTEXT(ctx); 13143464ebd5Sriastradh get_attached_shaders(ctx, program, maxCount, count, obj); 13153464ebd5Sriastradh} 13163464ebd5Sriastradh 13173464ebd5Sriastradh 13183464ebd5SriastradhGLint GLAPIENTRY 13193464ebd5Sriastradh_mesa_GetAttribLocationARB(GLhandleARB program, const GLcharARB * name) 13203464ebd5Sriastradh{ 13213464ebd5Sriastradh GET_CURRENT_CONTEXT(ctx); 13223464ebd5Sriastradh return get_attrib_location(ctx, program, name); 13233464ebd5Sriastradh} 13243464ebd5Sriastradh 13253464ebd5Sriastradh 13263464ebd5Sriastradh/* GL_EXT_gpu_shader4, GL3 */ 13273464ebd5SriastradhGLint GLAPIENTRY 13283464ebd5Sriastradh_mesa_GetFragDataLocation(GLuint program, const GLchar *name) 13293464ebd5Sriastradh{ 13303464ebd5Sriastradh GET_CURRENT_CONTEXT(ctx); 13313464ebd5Sriastradh return get_frag_data_location(ctx, program, name); 13323464ebd5Sriastradh} 13333464ebd5Sriastradh 13343464ebd5Sriastradh 13353464ebd5Sriastradh 13363464ebd5Sriastradhvoid GLAPIENTRY 13373464ebd5Sriastradh_mesa_GetInfoLogARB(GLhandleARB object, GLsizei maxLength, GLsizei * length, 13383464ebd5Sriastradh GLcharARB * infoLog) 13393464ebd5Sriastradh{ 13403464ebd5Sriastradh GET_CURRENT_CONTEXT(ctx); 13413464ebd5Sriastradh if (is_program(ctx, object)) { 13423464ebd5Sriastradh get_program_info_log(ctx, object, maxLength, length, infoLog); 13433464ebd5Sriastradh } 13443464ebd5Sriastradh else if (is_shader(ctx, object)) { 13453464ebd5Sriastradh get_shader_info_log(ctx, object, maxLength, length, infoLog); 13463464ebd5Sriastradh } 13473464ebd5Sriastradh else { 13483464ebd5Sriastradh _mesa_error(ctx, GL_INVALID_OPERATION, "glGetInfoLogARB"); 13493464ebd5Sriastradh } 13503464ebd5Sriastradh} 13513464ebd5Sriastradh 13523464ebd5Sriastradh 13533464ebd5Sriastradhvoid GLAPIENTRY 13543464ebd5Sriastradh_mesa_GetObjectParameterivARB(GLhandleARB object, GLenum pname, GLint *params) 13553464ebd5Sriastradh{ 13563464ebd5Sriastradh GET_CURRENT_CONTEXT(ctx); 13573464ebd5Sriastradh /* Implement in terms of GetProgramiv, GetShaderiv */ 13583464ebd5Sriastradh if (is_program(ctx, object)) { 13593464ebd5Sriastradh if (pname == GL_OBJECT_TYPE_ARB) { 13603464ebd5Sriastradh *params = GL_PROGRAM_OBJECT_ARB; 13613464ebd5Sriastradh } 13623464ebd5Sriastradh else { 13633464ebd5Sriastradh get_programiv(ctx, object, pname, params); 13643464ebd5Sriastradh } 13653464ebd5Sriastradh } 13663464ebd5Sriastradh else if (is_shader(ctx, object)) { 13673464ebd5Sriastradh if (pname == GL_OBJECT_TYPE_ARB) { 13683464ebd5Sriastradh *params = GL_SHADER_OBJECT_ARB; 13693464ebd5Sriastradh } 13703464ebd5Sriastradh else { 13713464ebd5Sriastradh get_shaderiv(ctx, object, pname, params); 13723464ebd5Sriastradh } 13733464ebd5Sriastradh } 13743464ebd5Sriastradh else { 13753464ebd5Sriastradh _mesa_error(ctx, GL_INVALID_VALUE, "glGetObjectParameterivARB"); 13763464ebd5Sriastradh } 13773464ebd5Sriastradh} 13783464ebd5Sriastradh 13793464ebd5Sriastradh 13803464ebd5Sriastradhvoid GLAPIENTRY 13813464ebd5Sriastradh_mesa_GetObjectParameterfvARB(GLhandleARB object, GLenum pname, 13823464ebd5Sriastradh GLfloat *params) 13833464ebd5Sriastradh{ 13843464ebd5Sriastradh GLint iparams[1]; /* XXX is one element enough? */ 13853464ebd5Sriastradh _mesa_GetObjectParameterivARB(object, pname, iparams); 13863464ebd5Sriastradh params[0] = (GLfloat) iparams[0]; 13873464ebd5Sriastradh} 13883464ebd5Sriastradh 13893464ebd5Sriastradh 13903464ebd5Sriastradhvoid GLAPIENTRY 13913464ebd5Sriastradh_mesa_GetProgramiv(GLuint program, GLenum pname, GLint *params) 13923464ebd5Sriastradh{ 13933464ebd5Sriastradh GET_CURRENT_CONTEXT(ctx); 13943464ebd5Sriastradh get_programiv(ctx, program, pname, params); 13953464ebd5Sriastradh} 13963464ebd5Sriastradh 13973464ebd5Sriastradh 13983464ebd5Sriastradhvoid GLAPIENTRY 13993464ebd5Sriastradh_mesa_GetShaderiv(GLuint shader, GLenum pname, GLint *params) 14003464ebd5Sriastradh{ 14013464ebd5Sriastradh GET_CURRENT_CONTEXT(ctx); 14023464ebd5Sriastradh get_shaderiv(ctx, shader, pname, params); 14033464ebd5Sriastradh} 14043464ebd5Sriastradh 14053464ebd5Sriastradh 14063464ebd5Sriastradhvoid GLAPIENTRY 14073464ebd5Sriastradh_mesa_GetProgramInfoLog(GLuint program, GLsizei bufSize, 14083464ebd5Sriastradh GLsizei *length, GLchar *infoLog) 14093464ebd5Sriastradh{ 14103464ebd5Sriastradh GET_CURRENT_CONTEXT(ctx); 14113464ebd5Sriastradh get_program_info_log(ctx, program, bufSize, length, infoLog); 14123464ebd5Sriastradh} 14133464ebd5Sriastradh 14143464ebd5Sriastradh 14153464ebd5Sriastradhvoid GLAPIENTRY 14163464ebd5Sriastradh_mesa_GetShaderInfoLog(GLuint shader, GLsizei bufSize, 14173464ebd5Sriastradh GLsizei *length, GLchar *infoLog) 14183464ebd5Sriastradh{ 14193464ebd5Sriastradh GET_CURRENT_CONTEXT(ctx); 14203464ebd5Sriastradh get_shader_info_log(ctx, shader, bufSize, length, infoLog); 14213464ebd5Sriastradh} 14223464ebd5Sriastradh 14233464ebd5Sriastradh 14243464ebd5Sriastradhvoid GLAPIENTRY 14253464ebd5Sriastradh_mesa_GetShaderSourceARB(GLhandleARB shader, GLsizei maxLength, 14263464ebd5Sriastradh GLsizei *length, GLcharARB *sourceOut) 14273464ebd5Sriastradh{ 14283464ebd5Sriastradh GET_CURRENT_CONTEXT(ctx); 14293464ebd5Sriastradh get_shader_source(ctx, shader, maxLength, length, sourceOut); 14303464ebd5Sriastradh} 14313464ebd5Sriastradh 14323464ebd5Sriastradh 14333464ebd5SriastradhGLhandleARB GLAPIENTRY 14343464ebd5Sriastradh_mesa_GetHandleARB(GLenum pname) 14353464ebd5Sriastradh{ 14363464ebd5Sriastradh GET_CURRENT_CONTEXT(ctx); 14373464ebd5Sriastradh return get_handle(ctx, pname); 14383464ebd5Sriastradh} 14393464ebd5Sriastradh 14403464ebd5Sriastradh 14413464ebd5SriastradhGLboolean GLAPIENTRY 14423464ebd5Sriastradh_mesa_IsProgram(GLuint name) 14433464ebd5Sriastradh{ 14443464ebd5Sriastradh GET_CURRENT_CONTEXT(ctx); 14453464ebd5Sriastradh return is_program(ctx, name); 14463464ebd5Sriastradh} 14473464ebd5Sriastradh 14483464ebd5Sriastradh 14493464ebd5SriastradhGLboolean GLAPIENTRY 14503464ebd5Sriastradh_mesa_IsShader(GLuint name) 14513464ebd5Sriastradh{ 14523464ebd5Sriastradh GET_CURRENT_CONTEXT(ctx); 14533464ebd5Sriastradh return is_shader(ctx, name); 14543464ebd5Sriastradh} 14553464ebd5Sriastradh 14563464ebd5Sriastradh 14573464ebd5Sriastradhvoid GLAPIENTRY 14583464ebd5Sriastradh_mesa_LinkProgramARB(GLhandleARB programObj) 14593464ebd5Sriastradh{ 14603464ebd5Sriastradh GET_CURRENT_CONTEXT(ctx); 14613464ebd5Sriastradh link_program(ctx, programObj); 14623464ebd5Sriastradh} 14633464ebd5Sriastradh 14643464ebd5Sriastradh 14653464ebd5Sriastradh 14663464ebd5Sriastradh/** 14673464ebd5Sriastradh * Read shader source code from a file. 14683464ebd5Sriastradh * Useful for debugging to override an app's shader. 14693464ebd5Sriastradh */ 14703464ebd5Sriastradhstatic GLcharARB * 14713464ebd5Sriastradhread_shader(const char *fname) 14723464ebd5Sriastradh{ 14733464ebd5Sriastradh const int max = 50*1000; 14743464ebd5Sriastradh FILE *f = fopen(fname, "r"); 14753464ebd5Sriastradh GLcharARB *buffer, *shader; 14763464ebd5Sriastradh int len; 14773464ebd5Sriastradh 14783464ebd5Sriastradh if (!f) { 14793464ebd5Sriastradh return NULL; 14803464ebd5Sriastradh } 14813464ebd5Sriastradh 14823464ebd5Sriastradh buffer = (char *) malloc(max); 14833464ebd5Sriastradh len = fread(buffer, 1, max, f); 14843464ebd5Sriastradh buffer[len] = 0; 14853464ebd5Sriastradh 14863464ebd5Sriastradh fclose(f); 14873464ebd5Sriastradh 14883464ebd5Sriastradh shader = _mesa_strdup(buffer); 14893464ebd5Sriastradh free(buffer); 14903464ebd5Sriastradh 14913464ebd5Sriastradh return shader; 14923464ebd5Sriastradh} 14933464ebd5Sriastradh 14943464ebd5Sriastradh 14953464ebd5Sriastradh/** 14963464ebd5Sriastradh * Called via glShaderSource() and glShaderSourceARB() API functions. 14973464ebd5Sriastradh * Basically, concatenate the source code strings into one long string 14983464ebd5Sriastradh * and pass it to _mesa_shader_source(). 14993464ebd5Sriastradh */ 15003464ebd5Sriastradhvoid GLAPIENTRY 15013464ebd5Sriastradh_mesa_ShaderSourceARB(GLhandleARB shaderObj, GLsizei count, 15023464ebd5Sriastradh const GLcharARB ** string, const GLint * length) 15033464ebd5Sriastradh{ 15043464ebd5Sriastradh GET_CURRENT_CONTEXT(ctx); 15053464ebd5Sriastradh GLint *offsets; 15063464ebd5Sriastradh GLsizei i, totalLength; 15073464ebd5Sriastradh GLcharARB *source; 15083464ebd5Sriastradh GLuint checksum; 15093464ebd5Sriastradh 15103464ebd5Sriastradh if (!shaderObj || string == NULL) { 15113464ebd5Sriastradh _mesa_error(ctx, GL_INVALID_VALUE, "glShaderSourceARB"); 15123464ebd5Sriastradh return; 15133464ebd5Sriastradh } 15143464ebd5Sriastradh 15153464ebd5Sriastradh /* 15163464ebd5Sriastradh * This array holds offsets of where the appropriate string ends, thus the 15173464ebd5Sriastradh * last element will be set to the total length of the source code. 15183464ebd5Sriastradh */ 15193464ebd5Sriastradh offsets = (GLint *) malloc(count * sizeof(GLint)); 15203464ebd5Sriastradh if (offsets == NULL) { 15213464ebd5Sriastradh _mesa_error(ctx, GL_OUT_OF_MEMORY, "glShaderSourceARB"); 15223464ebd5Sriastradh return; 15233464ebd5Sriastradh } 15243464ebd5Sriastradh 15253464ebd5Sriastradh for (i = 0; i < count; i++) { 15263464ebd5Sriastradh if (string[i] == NULL) { 15273464ebd5Sriastradh free((GLvoid *) offsets); 15283464ebd5Sriastradh _mesa_error(ctx, GL_INVALID_OPERATION, 15293464ebd5Sriastradh "glShaderSourceARB(null string)"); 15303464ebd5Sriastradh return; 15313464ebd5Sriastradh } 15323464ebd5Sriastradh if (length == NULL || length[i] < 0) 15333464ebd5Sriastradh offsets[i] = strlen(string[i]); 15343464ebd5Sriastradh else 15353464ebd5Sriastradh offsets[i] = length[i]; 15363464ebd5Sriastradh /* accumulate string lengths */ 15373464ebd5Sriastradh if (i > 0) 15383464ebd5Sriastradh offsets[i] += offsets[i - 1]; 15393464ebd5Sriastradh } 15403464ebd5Sriastradh 15413464ebd5Sriastradh /* Total length of source string is sum off all strings plus two. 15423464ebd5Sriastradh * One extra byte for terminating zero, another extra byte to silence 15433464ebd5Sriastradh * valgrind warnings in the parser/grammer code. 15443464ebd5Sriastradh */ 15453464ebd5Sriastradh totalLength = offsets[count - 1] + 2; 15463464ebd5Sriastradh source = (GLcharARB *) malloc(totalLength * sizeof(GLcharARB)); 15473464ebd5Sriastradh if (source == NULL) { 15483464ebd5Sriastradh free((GLvoid *) offsets); 15493464ebd5Sriastradh _mesa_error(ctx, GL_OUT_OF_MEMORY, "glShaderSourceARB"); 15503464ebd5Sriastradh return; 15513464ebd5Sriastradh } 15523464ebd5Sriastradh 15533464ebd5Sriastradh for (i = 0; i < count; i++) { 15543464ebd5Sriastradh GLint start = (i > 0) ? offsets[i - 1] : 0; 15553464ebd5Sriastradh memcpy(source + start, string[i], 15563464ebd5Sriastradh (offsets[i] - start) * sizeof(GLcharARB)); 15573464ebd5Sriastradh } 15583464ebd5Sriastradh source[totalLength - 1] = '\0'; 15593464ebd5Sriastradh source[totalLength - 2] = '\0'; 15603464ebd5Sriastradh 15613464ebd5Sriastradh if (SHADER_SUBST) { 15623464ebd5Sriastradh /* Compute the shader's source code checksum then try to open a file 15633464ebd5Sriastradh * named newshader_<CHECKSUM>. If it exists, use it in place of the 15643464ebd5Sriastradh * original shader source code. For debugging. 15653464ebd5Sriastradh */ 15663464ebd5Sriastradh char filename[100]; 15673464ebd5Sriastradh GLcharARB *newSource; 15683464ebd5Sriastradh 15693464ebd5Sriastradh checksum = _mesa_str_checksum(source); 15703464ebd5Sriastradh 15713464ebd5Sriastradh _mesa_snprintf(filename, sizeof(filename), "newshader_%d", checksum); 15723464ebd5Sriastradh 15733464ebd5Sriastradh newSource = read_shader(filename); 15743464ebd5Sriastradh if (newSource) { 15753464ebd5Sriastradh fprintf(stderr, "Mesa: Replacing shader %u chksum=%d with %s\n", 15763464ebd5Sriastradh shaderObj, checksum, filename); 15773464ebd5Sriastradh free(source); 15783464ebd5Sriastradh source = newSource; 15793464ebd5Sriastradh } 15803464ebd5Sriastradh } 15813464ebd5Sriastradh 15823464ebd5Sriastradh shader_source(ctx, shaderObj, source); 15833464ebd5Sriastradh 15843464ebd5Sriastradh if (SHADER_SUBST) { 15853464ebd5Sriastradh struct gl_shader *sh = _mesa_lookup_shader(ctx, shaderObj); 15863464ebd5Sriastradh if (sh) 15873464ebd5Sriastradh sh->SourceChecksum = checksum; /* save original checksum */ 15883464ebd5Sriastradh } 15893464ebd5Sriastradh 15903464ebd5Sriastradh free(offsets); 15913464ebd5Sriastradh} 15923464ebd5Sriastradh 15933464ebd5Sriastradh 15943464ebd5Sriastradhvoid GLAPIENTRY 15953464ebd5Sriastradh_mesa_UseProgramObjectARB(GLhandleARB program) 15963464ebd5Sriastradh{ 15973464ebd5Sriastradh GET_CURRENT_CONTEXT(ctx); 15983464ebd5Sriastradh struct gl_shader_program *shProg; 15993464ebd5Sriastradh struct gl_transform_feedback_object *obj = 16003464ebd5Sriastradh ctx->TransformFeedback.CurrentObject; 16013464ebd5Sriastradh 16023464ebd5Sriastradh ASSERT_OUTSIDE_BEGIN_END(ctx); 16033464ebd5Sriastradh 16043464ebd5Sriastradh if (obj->Active) { 16053464ebd5Sriastradh _mesa_error(ctx, GL_INVALID_OPERATION, 16063464ebd5Sriastradh "glUseProgram(transform feedback active)"); 16073464ebd5Sriastradh return; 16083464ebd5Sriastradh } 16093464ebd5Sriastradh 16103464ebd5Sriastradh if (program) { 16113464ebd5Sriastradh shProg = _mesa_lookup_shader_program_err(ctx, program, "glUseProgram"); 16123464ebd5Sriastradh if (!shProg) { 16133464ebd5Sriastradh return; 16143464ebd5Sriastradh } 16153464ebd5Sriastradh if (!shProg->LinkStatus) { 16163464ebd5Sriastradh _mesa_error(ctx, GL_INVALID_OPERATION, 16173464ebd5Sriastradh "glUseProgram(program %u not linked)", program); 16183464ebd5Sriastradh return; 16193464ebd5Sriastradh } 16203464ebd5Sriastradh 16213464ebd5Sriastradh /* debug code */ 16223464ebd5Sriastradh if (ctx->Shader.Flags & GLSL_USE_PROG) { 16233464ebd5Sriastradh print_shader_info(shProg); 16243464ebd5Sriastradh } 16253464ebd5Sriastradh } 16263464ebd5Sriastradh else { 16273464ebd5Sriastradh shProg = NULL; 16283464ebd5Sriastradh } 16293464ebd5Sriastradh 16303464ebd5Sriastradh _mesa_use_program(ctx, shProg); 16313464ebd5Sriastradh} 16323464ebd5Sriastradh 16333464ebd5Sriastradh 16343464ebd5Sriastradhvoid GLAPIENTRY 16353464ebd5Sriastradh_mesa_ValidateProgramARB(GLhandleARB program) 16363464ebd5Sriastradh{ 16373464ebd5Sriastradh GET_CURRENT_CONTEXT(ctx); 16383464ebd5Sriastradh validate_program(ctx, program); 16393464ebd5Sriastradh} 16403464ebd5Sriastradh 16413464ebd5Sriastradh#ifdef FEATURE_ES2 16423464ebd5Sriastradh 16433464ebd5Sriastradhvoid GLAPIENTRY 16443464ebd5Sriastradh_mesa_GetShaderPrecisionFormat(GLenum shadertype, GLenum precisiontype, 16453464ebd5Sriastradh GLint* range, GLint* precision) 16463464ebd5Sriastradh{ 16473464ebd5Sriastradh const struct gl_program_constants *limits; 16483464ebd5Sriastradh const struct gl_precision *p; 16493464ebd5Sriastradh GET_CURRENT_CONTEXT(ctx); 16503464ebd5Sriastradh 16513464ebd5Sriastradh switch (shadertype) { 16523464ebd5Sriastradh case GL_VERTEX_SHADER: 16533464ebd5Sriastradh limits = &ctx->Const.VertexProgram; 16543464ebd5Sriastradh break; 16553464ebd5Sriastradh case GL_FRAGMENT_SHADER: 16563464ebd5Sriastradh limits = &ctx->Const.FragmentProgram; 16573464ebd5Sriastradh break; 16583464ebd5Sriastradh default: 16593464ebd5Sriastradh _mesa_error(ctx, GL_INVALID_ENUM, 16603464ebd5Sriastradh "glGetShaderPrecisionFormat(shadertype)"); 16613464ebd5Sriastradh return; 16623464ebd5Sriastradh } 16633464ebd5Sriastradh 16643464ebd5Sriastradh switch (precisiontype) { 16653464ebd5Sriastradh case GL_LOW_FLOAT: 16663464ebd5Sriastradh p = &limits->LowFloat; 16673464ebd5Sriastradh break; 16683464ebd5Sriastradh case GL_MEDIUM_FLOAT: 16693464ebd5Sriastradh p = &limits->MediumFloat; 16703464ebd5Sriastradh break; 16713464ebd5Sriastradh case GL_HIGH_FLOAT: 16723464ebd5Sriastradh p = &limits->HighFloat; 16733464ebd5Sriastradh break; 16743464ebd5Sriastradh case GL_LOW_INT: 16753464ebd5Sriastradh p = &limits->LowInt; 16763464ebd5Sriastradh break; 16773464ebd5Sriastradh case GL_MEDIUM_INT: 16783464ebd5Sriastradh p = &limits->MediumInt; 16793464ebd5Sriastradh break; 16803464ebd5Sriastradh case GL_HIGH_INT: 16813464ebd5Sriastradh p = &limits->HighInt; 16823464ebd5Sriastradh break; 16833464ebd5Sriastradh default: 16843464ebd5Sriastradh _mesa_error(ctx, GL_INVALID_ENUM, 16853464ebd5Sriastradh "glGetShaderPrecisionFormat(precisiontype)"); 16863464ebd5Sriastradh return; 16873464ebd5Sriastradh } 16883464ebd5Sriastradh 16893464ebd5Sriastradh range[0] = p->RangeMin; 16903464ebd5Sriastradh range[1] = p->RangeMax; 16913464ebd5Sriastradh precision[0] = p->Precision; 16923464ebd5Sriastradh} 16933464ebd5Sriastradh 16943464ebd5Sriastradh 16953464ebd5Sriastradhvoid GLAPIENTRY 16963464ebd5Sriastradh_mesa_ReleaseShaderCompiler(void) 16973464ebd5Sriastradh{ 16983464ebd5Sriastradh _mesa_destroy_shader_compiler_caches(); 16993464ebd5Sriastradh} 17003464ebd5Sriastradh 17013464ebd5Sriastradh 17023464ebd5Sriastradhvoid GLAPIENTRY 17033464ebd5Sriastradh_mesa_ShaderBinary(GLint n, const GLuint* shaders, GLenum binaryformat, 17043464ebd5Sriastradh const void* binary, GLint length) 17053464ebd5Sriastradh{ 17063464ebd5Sriastradh GET_CURRENT_CONTEXT(ctx); 17073464ebd5Sriastradh (void) n; 17083464ebd5Sriastradh (void) shaders; 17093464ebd5Sriastradh (void) binaryformat; 17103464ebd5Sriastradh (void) binary; 17113464ebd5Sriastradh (void) length; 17123464ebd5Sriastradh _mesa_error(ctx, GL_INVALID_OPERATION, __FUNCTION__); 17133464ebd5Sriastradh} 17143464ebd5Sriastradh 17153464ebd5Sriastradh#endif /* FEATURE_ES2 */ 17163464ebd5Sriastradh 17173464ebd5Sriastradh 17183464ebd5Sriastradh#if FEATURE_ARB_geometry_shader4 17193464ebd5Sriastradh 17203464ebd5Sriastradhvoid GLAPIENTRY 17213464ebd5Sriastradh_mesa_ProgramParameteriARB(GLuint program, GLenum pname, GLint value) 17223464ebd5Sriastradh{ 17233464ebd5Sriastradh struct gl_shader_program *shProg; 17243464ebd5Sriastradh GET_CURRENT_CONTEXT(ctx); 17253464ebd5Sriastradh 17263464ebd5Sriastradh ASSERT_OUTSIDE_BEGIN_END(ctx); 17273464ebd5Sriastradh 17283464ebd5Sriastradh shProg = _mesa_lookup_shader_program_err(ctx, program, 17293464ebd5Sriastradh "glProgramParameteri"); 17303464ebd5Sriastradh if (!shProg) 17313464ebd5Sriastradh return; 17323464ebd5Sriastradh 17333464ebd5Sriastradh switch (pname) { 17343464ebd5Sriastradh case GL_GEOMETRY_VERTICES_OUT_ARB: 17353464ebd5Sriastradh if (value < 1 || 17363464ebd5Sriastradh (unsigned) value > ctx->Const.MaxGeometryOutputVertices) { 17373464ebd5Sriastradh _mesa_error(ctx, GL_INVALID_VALUE, 17383464ebd5Sriastradh "glProgramParameteri(GL_GEOMETRY_VERTICES_OUT_ARB=%d", 17393464ebd5Sriastradh value); 17403464ebd5Sriastradh return; 17413464ebd5Sriastradh } 17423464ebd5Sriastradh shProg->Geom.VerticesOut = value; 17433464ebd5Sriastradh break; 17443464ebd5Sriastradh case GL_GEOMETRY_INPUT_TYPE_ARB: 17453464ebd5Sriastradh switch (value) { 17463464ebd5Sriastradh case GL_POINTS: 17473464ebd5Sriastradh case GL_LINES: 17483464ebd5Sriastradh case GL_LINES_ADJACENCY_ARB: 17493464ebd5Sriastradh case GL_TRIANGLES: 17503464ebd5Sriastradh case GL_TRIANGLES_ADJACENCY_ARB: 17513464ebd5Sriastradh shProg->Geom.InputType = value; 17523464ebd5Sriastradh break; 17533464ebd5Sriastradh default: 17543464ebd5Sriastradh _mesa_error(ctx, GL_INVALID_VALUE, 17553464ebd5Sriastradh "glProgramParameteri(geometry input type = %s", 17563464ebd5Sriastradh _mesa_lookup_enum_by_nr(value)); 17573464ebd5Sriastradh return; 17583464ebd5Sriastradh } 17593464ebd5Sriastradh break; 17603464ebd5Sriastradh case GL_GEOMETRY_OUTPUT_TYPE_ARB: 17613464ebd5Sriastradh switch (value) { 17623464ebd5Sriastradh case GL_POINTS: 17633464ebd5Sriastradh case GL_LINE_STRIP: 17643464ebd5Sriastradh case GL_TRIANGLE_STRIP: 17653464ebd5Sriastradh shProg->Geom.OutputType = value; 17663464ebd5Sriastradh break; 17673464ebd5Sriastradh default: 17683464ebd5Sriastradh _mesa_error(ctx, GL_INVALID_VALUE, 17693464ebd5Sriastradh "glProgramParameteri(geometry output type = %s", 17703464ebd5Sriastradh _mesa_lookup_enum_by_nr(value)); 17713464ebd5Sriastradh return; 17723464ebd5Sriastradh } 17733464ebd5Sriastradh break; 17743464ebd5Sriastradh default: 17753464ebd5Sriastradh _mesa_error(ctx, GL_INVALID_ENUM, "glProgramParameteriARB(pname=%s)", 17763464ebd5Sriastradh _mesa_lookup_enum_by_nr(pname)); 17773464ebd5Sriastradh break; 17783464ebd5Sriastradh } 17793464ebd5Sriastradh} 17803464ebd5Sriastradh 17813464ebd5Sriastradh#endif 17823464ebd5Sriastradh 17833464ebd5Sriastradhvoid 17843464ebd5Sriastradh_mesa_use_shader_program(struct gl_context *ctx, GLenum type, 17853464ebd5Sriastradh struct gl_shader_program *shProg) 17863464ebd5Sriastradh{ 17873464ebd5Sriastradh use_shader_program(ctx, type, shProg); 17883464ebd5Sriastradh 17893464ebd5Sriastradh if (ctx->Driver.UseProgram) 17903464ebd5Sriastradh ctx->Driver.UseProgram(ctx, shProg); 17913464ebd5Sriastradh} 17923464ebd5Sriastradh 17933464ebd5Sriastradhvoid GLAPIENTRY 17943464ebd5Sriastradh_mesa_UseShaderProgramEXT(GLenum type, GLuint program) 17953464ebd5Sriastradh{ 17963464ebd5Sriastradh GET_CURRENT_CONTEXT(ctx); 17973464ebd5Sriastradh struct gl_shader_program *shProg = NULL; 17983464ebd5Sriastradh 17993464ebd5Sriastradh ASSERT_OUTSIDE_BEGIN_END(ctx); 18003464ebd5Sriastradh 18013464ebd5Sriastradh if (!validate_shader_target(ctx, type)) { 18023464ebd5Sriastradh _mesa_error(ctx, GL_INVALID_ENUM, "glUseShaderProgramEXT(type)"); 18033464ebd5Sriastradh return; 18043464ebd5Sriastradh } 18053464ebd5Sriastradh 18063464ebd5Sriastradh if (ctx->TransformFeedback.CurrentObject->Active) { 18073464ebd5Sriastradh _mesa_error(ctx, GL_INVALID_OPERATION, 18083464ebd5Sriastradh "glUseShaderProgramEXT(transform feedback is active)"); 18093464ebd5Sriastradh return; 18103464ebd5Sriastradh } 18113464ebd5Sriastradh 18123464ebd5Sriastradh if (program) { 18133464ebd5Sriastradh shProg = _mesa_lookup_shader_program_err(ctx, program, 18143464ebd5Sriastradh "glUseShaderProgramEXT"); 18153464ebd5Sriastradh if (shProg == NULL) 18163464ebd5Sriastradh return; 18173464ebd5Sriastradh 18183464ebd5Sriastradh if (!shProg->LinkStatus) { 18193464ebd5Sriastradh _mesa_error(ctx, GL_INVALID_OPERATION, 18203464ebd5Sriastradh "glUseShaderProgramEXT(program not linked)"); 18213464ebd5Sriastradh return; 18223464ebd5Sriastradh } 18233464ebd5Sriastradh } 18243464ebd5Sriastradh 18253464ebd5Sriastradh _mesa_use_shader_program(ctx, type, shProg); 18263464ebd5Sriastradh} 18273464ebd5Sriastradh 18283464ebd5Sriastradhvoid GLAPIENTRY 18293464ebd5Sriastradh_mesa_ActiveProgramEXT(GLuint program) 18303464ebd5Sriastradh{ 18313464ebd5Sriastradh GET_CURRENT_CONTEXT(ctx); 18323464ebd5Sriastradh struct gl_shader_program *shProg = (program != 0) 18333464ebd5Sriastradh ? _mesa_lookup_shader_program_err(ctx, program, "glActiveProgramEXT") 18343464ebd5Sriastradh : NULL; 18353464ebd5Sriastradh 18363464ebd5Sriastradh _mesa_active_program(ctx, shProg, "glActiveProgramEXT"); 18373464ebd5Sriastradh return; 18383464ebd5Sriastradh} 18393464ebd5Sriastradh 18403464ebd5SriastradhGLuint GLAPIENTRY 18413464ebd5Sriastradh_mesa_CreateShaderProgramEXT(GLenum type, const GLchar *string) 18423464ebd5Sriastradh{ 18433464ebd5Sriastradh GET_CURRENT_CONTEXT(ctx); 18443464ebd5Sriastradh const GLuint shader = create_shader(ctx, type); 18453464ebd5Sriastradh GLuint program = 0; 18463464ebd5Sriastradh 18473464ebd5Sriastradh if (shader) { 18483464ebd5Sriastradh shader_source(ctx, shader, _mesa_strdup(string)); 18493464ebd5Sriastradh compile_shader(ctx, shader); 18503464ebd5Sriastradh 18513464ebd5Sriastradh program = create_shader_program(ctx); 18523464ebd5Sriastradh if (program) { 18533464ebd5Sriastradh struct gl_shader_program *shProg; 18543464ebd5Sriastradh struct gl_shader *sh; 18553464ebd5Sriastradh GLint compiled = GL_FALSE; 18563464ebd5Sriastradh 18573464ebd5Sriastradh shProg = _mesa_lookup_shader_program(ctx, program); 18583464ebd5Sriastradh sh = _mesa_lookup_shader(ctx, shader); 18593464ebd5Sriastradh 18603464ebd5Sriastradh get_shaderiv(ctx, shader, GL_COMPILE_STATUS, &compiled); 18613464ebd5Sriastradh if (compiled) { 18623464ebd5Sriastradh attach_shader(ctx, program, shader); 18633464ebd5Sriastradh link_program(ctx, program); 18643464ebd5Sriastradh detach_shader(ctx, program, shader); 18653464ebd5Sriastradh 18663464ebd5Sriastradh#if 0 18673464ebd5Sriastradh /* Possibly... */ 18683464ebd5Sriastradh if (active-user-defined-varyings-in-linked-program) { 18693464ebd5Sriastradh append-error-to-info-log; 18703464ebd5Sriastradh shProg->LinkStatus = GL_FALSE; 18713464ebd5Sriastradh } 18723464ebd5Sriastradh#endif 18733464ebd5Sriastradh } 18743464ebd5Sriastradh 18753464ebd5Sriastradh ralloc_strcat(&shProg->InfoLog, sh->InfoLog); 18763464ebd5Sriastradh } 18773464ebd5Sriastradh 18783464ebd5Sriastradh delete_shader(ctx, shader); 18793464ebd5Sriastradh } 18803464ebd5Sriastradh 18813464ebd5Sriastradh return program; 18823464ebd5Sriastradh} 18833464ebd5Sriastradh 18843464ebd5Sriastradh/** 18853464ebd5Sriastradh * Plug in shader-related functions into API dispatch table. 18863464ebd5Sriastradh */ 18873464ebd5Sriastradhvoid 18883464ebd5Sriastradh_mesa_init_shader_dispatch(struct _glapi_table *exec) 18893464ebd5Sriastradh{ 18903464ebd5Sriastradh#if FEATURE_GL 18913464ebd5Sriastradh /* GL_ARB_vertex/fragment_shader */ 18923464ebd5Sriastradh SET_DeleteObjectARB(exec, _mesa_DeleteObjectARB); 18933464ebd5Sriastradh SET_GetHandleARB(exec, _mesa_GetHandleARB); 18943464ebd5Sriastradh SET_DetachObjectARB(exec, _mesa_DetachObjectARB); 18953464ebd5Sriastradh SET_CreateShaderObjectARB(exec, _mesa_CreateShaderObjectARB); 18963464ebd5Sriastradh SET_ShaderSourceARB(exec, _mesa_ShaderSourceARB); 18973464ebd5Sriastradh SET_CompileShaderARB(exec, _mesa_CompileShaderARB); 18983464ebd5Sriastradh SET_CreateProgramObjectARB(exec, _mesa_CreateProgramObjectARB); 18993464ebd5Sriastradh SET_AttachObjectARB(exec, _mesa_AttachObjectARB); 19003464ebd5Sriastradh SET_LinkProgramARB(exec, _mesa_LinkProgramARB); 19013464ebd5Sriastradh SET_UseProgramObjectARB(exec, _mesa_UseProgramObjectARB); 19023464ebd5Sriastradh SET_ValidateProgramARB(exec, _mesa_ValidateProgramARB); 19033464ebd5Sriastradh SET_GetObjectParameterfvARB(exec, _mesa_GetObjectParameterfvARB); 19043464ebd5Sriastradh SET_GetObjectParameterivARB(exec, _mesa_GetObjectParameterivARB); 19053464ebd5Sriastradh SET_GetInfoLogARB(exec, _mesa_GetInfoLogARB); 19063464ebd5Sriastradh SET_GetAttachedObjectsARB(exec, _mesa_GetAttachedObjectsARB); 19073464ebd5Sriastradh SET_GetShaderSourceARB(exec, _mesa_GetShaderSourceARB); 19083464ebd5Sriastradh 19093464ebd5Sriastradh /* OpenGL 2.0 */ 19103464ebd5Sriastradh SET_AttachShader(exec, _mesa_AttachShader); 19113464ebd5Sriastradh SET_CreateProgram(exec, _mesa_CreateProgram); 19123464ebd5Sriastradh SET_CreateShader(exec, _mesa_CreateShader); 19133464ebd5Sriastradh SET_DeleteProgram(exec, _mesa_DeleteProgram); 19143464ebd5Sriastradh SET_DeleteShader(exec, _mesa_DeleteShader); 19153464ebd5Sriastradh SET_DetachShader(exec, _mesa_DetachShader); 19163464ebd5Sriastradh SET_GetAttachedShaders(exec, _mesa_GetAttachedShaders); 19173464ebd5Sriastradh SET_GetProgramiv(exec, _mesa_GetProgramiv); 19183464ebd5Sriastradh SET_GetProgramInfoLog(exec, _mesa_GetProgramInfoLog); 19193464ebd5Sriastradh SET_GetShaderiv(exec, _mesa_GetShaderiv); 19203464ebd5Sriastradh SET_GetShaderInfoLog(exec, _mesa_GetShaderInfoLog); 19213464ebd5Sriastradh SET_IsProgram(exec, _mesa_IsProgram); 19223464ebd5Sriastradh SET_IsShader(exec, _mesa_IsShader); 19233464ebd5Sriastradh 19243464ebd5Sriastradh#if FEATURE_ARB_vertex_shader 19253464ebd5Sriastradh SET_BindAttribLocationARB(exec, _mesa_BindAttribLocationARB); 19263464ebd5Sriastradh SET_GetActiveAttribARB(exec, _mesa_GetActiveAttribARB); 19273464ebd5Sriastradh SET_GetAttribLocationARB(exec, _mesa_GetAttribLocationARB); 19283464ebd5Sriastradh#endif 19293464ebd5Sriastradh 19303464ebd5Sriastradh#if FEATURE_ARB_geometry_shader4 19313464ebd5Sriastradh SET_ProgramParameteriARB(exec, _mesa_ProgramParameteriARB); 19323464ebd5Sriastradh#endif 19333464ebd5Sriastradh 19343464ebd5Sriastradh SET_UseShaderProgramEXT(exec, _mesa_UseShaderProgramEXT); 19353464ebd5Sriastradh SET_ActiveProgramEXT(exec, _mesa_ActiveProgramEXT); 19363464ebd5Sriastradh SET_CreateShaderProgramEXT(exec, _mesa_CreateShaderProgramEXT); 19373464ebd5Sriastradh 19383464ebd5Sriastradh /* GL_EXT_gpu_shader4 / GL 3.0 */ 19393464ebd5Sriastradh SET_BindFragDataLocationEXT(exec, _mesa_BindFragDataLocation); 19403464ebd5Sriastradh SET_GetFragDataLocationEXT(exec, _mesa_GetFragDataLocation); 19413464ebd5Sriastradh 19423464ebd5Sriastradh /* GL_ARB_ES2_compatibility */ 19433464ebd5Sriastradh SET_ReleaseShaderCompiler(exec, _mesa_ReleaseShaderCompiler); 19443464ebd5Sriastradh SET_GetShaderPrecisionFormat(exec, _mesa_GetShaderPrecisionFormat); 19453464ebd5Sriastradh 19463464ebd5Sriastradh#endif /* FEATURE_GL */ 19473464ebd5Sriastradh} 19483464ebd5Sriastradh 1949