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