mesa: add some minor fixes for geometry shaders
[mesa.git] / src / mesa / main / shaderapi.c
index 030236e7350b296e5b4b77b4079b78be91e3edb9..b58e30de9c4c14f3cd24c396c5507f50c6634dfa 100644 (file)
 #include "main/dispatch.h"
 #include "main/enums.h"
 #include "main/hash.h"
+#include "main/mfeatures.h"
+#include "main/mtypes.h"
 #include "main/shaderapi.h"
 #include "main/shaderobj.h"
 #include "program/program.h"
 #include "program/prog_parameter.h"
 #include "program/prog_uniform.h"
-#include "talloc.h"
+#include "ralloc.h"
 #include <stdbool.h>
+#include "../glsl/glsl_parser_extras.h"
 
 /** Define this to enable shader substitution (see below) */
 #define SHADER_SUBST 0
@@ -95,7 +98,7 @@ _mesa_init_shader_state(struct gl_context *ctx)
     * are generated by the GLSL compiler.
     */
    struct gl_shader_compiler_options options;
-   GLuint i;
+   gl_shader_type sh;
 
    memset(&options, 0, sizeof(options));
    options.MaxUnrollIterations = 32;
@@ -103,8 +106,8 @@ _mesa_init_shader_state(struct gl_context *ctx)
    /* Default pragma settings */
    options.DefaultPragmas.Optimize = GL_TRUE;
 
-   for(i = 0; i < MESA_SHADER_TYPES; ++i)
-      memcpy(&ctx->ShaderCompilerOptions[i], &options, sizeof(options));
+   for (sh = 0; sh < MESA_SHADER_TYPES; ++sh)
+      memcpy(&ctx->ShaderCompilerOptions[sh], &options, sizeof(options));
 
    ctx->Shader.Flags = get_shader_flags();
 }
@@ -359,7 +362,7 @@ bind_attrib_location(struct gl_context *ctx, GLuint program, GLuint index,
 {
    struct gl_shader_program *shProg;
    const GLint size = -1; /* unknown size */
-   GLint i, oldIndex;
+   GLint i;
    GLenum datatype = GL_FLOAT_VEC4;
 
    shProg = _mesa_lookup_shader_program_err(ctx, program,
@@ -382,14 +385,6 @@ bind_attrib_location(struct gl_context *ctx, GLuint program, GLuint index,
       return;
    }
 
-   if (shProg->LinkStatus) {
-      /* get current index/location for the attribute */
-      oldIndex = get_attrib_location(ctx, program, name);
-   }
-   else {
-      oldIndex = -1;
-   }
-
    /* this will replace the current value if it's already in the list */
    i = _mesa_add_attribute(shProg->Attributes, name, size, datatype, index);
    if (i < 0) {
@@ -930,6 +925,8 @@ print_shader_info(const struct gl_shader_program *shProg)
       printf("  vert prog %u\n", shProg->VertexProgram->Base.Id);
    if (shProg->FragmentProgram)
       printf("  frag prog %u\n", shProg->FragmentProgram->Base.Id);
+   if (shProg->GeometryProgram)
+      printf("  geom prog %u\n", shProg->GeometryProgram->Base.Id);
 }
 
 
@@ -1026,6 +1023,7 @@ static GLboolean
 validate_samplers(const struct gl_program *prog, char *errMsg)
 {
    static const char *targetName[] = {
+      "TEXTURE_BUFFER",
       "TEXTURE_2D_ARRAY",
       "TEXTURE_1D_ARRAY",
       "TEXTURE_CUBE",
@@ -1079,6 +1077,7 @@ validate_shader_program(const struct gl_shader_program *shProg,
                         char *errMsg)
 {
    const struct gl_vertex_program *vp = shProg->VertexProgram;
+   const struct gl_geometry_program *gp = shProg->GeometryProgram;
    const struct gl_fragment_program *fp = shProg->FragmentProgram;
 
    if (!shProg->LinkStatus) {
@@ -1108,6 +1107,9 @@ validate_shader_program(const struct gl_shader_program *shProg,
    if (vp && !validate_samplers(&vp->Base, errMsg)) {
       return GL_FALSE;
    }
+   if (gp && !validate_samplers(&gp->Base, errMsg)) {
+      return GL_FALSE;
+   }
    if (fp && !validate_samplers(&fp->Base, errMsg)) {
       return GL_FALSE;
    }
@@ -1134,9 +1136,9 @@ validate_program(struct gl_context *ctx, GLuint program)
    if (!shProg->Validated) {
       /* update info log */
       if (shProg->InfoLog) {
-         talloc_free(shProg->InfoLog);
+         ralloc_free(shProg->InfoLog);
       }
-      shProg->InfoLog = talloc_strdup(shProg, errMsg);
+      shProg->InfoLog = ralloc_strdup(shProg, errMsg);
    }
 }
 
@@ -1181,6 +1183,8 @@ void GLAPIENTRY
 _mesa_CompileShaderARB(GLhandleARB shaderObj)
 {
    GET_CURRENT_CONTEXT(ctx);
+   if (MESA_VERBOSE & VERBOSE_API)
+      _mesa_debug(ctx, "glCompileShader %u\n", shaderObj);
    compile_shader(ctx, shaderObj);
 }
 
@@ -1189,6 +1193,8 @@ GLuint GLAPIENTRY
 _mesa_CreateShader(GLenum type)
 {
    GET_CURRENT_CONTEXT(ctx);
+   if (MESA_VERBOSE & VERBOSE_API)
+      _mesa_debug(ctx, "glCreateShader %s\n", _mesa_lookup_enum_by_nr(type));
    return create_shader(ctx, type);
 }
 
@@ -1205,6 +1211,8 @@ GLuint GLAPIENTRY
 _mesa_CreateProgram(void)
 {
    GET_CURRENT_CONTEXT(ctx);
+   if (MESA_VERBOSE & VERBOSE_API)
+      _mesa_debug(ctx, "glCreateProgram\n");
    return create_shader_program(ctx);
 }
 
@@ -1220,8 +1228,14 @@ _mesa_CreateProgramObjectARB(void)
 void GLAPIENTRY
 _mesa_DeleteObjectARB(GLhandleARB obj)
 {
+   if (MESA_VERBOSE & VERBOSE_API) {
+      GET_CURRENT_CONTEXT(ctx);
+      _mesa_debug(ctx, "glDeleteObjectARB(%u)\n", obj);
+   }
+
    if (obj) {
       GET_CURRENT_CONTEXT(ctx);
+      FLUSH_VERTICES(ctx, 0);
       if (is_program(ctx, obj)) {
          delete_shader_program(ctx, obj);
       }
@@ -1240,6 +1254,7 @@ _mesa_DeleteProgram(GLuint name)
 {
    if (name) {
       GET_CURRENT_CONTEXT(ctx);
+      FLUSH_VERTICES(ctx, 0);
       delete_shader_program(ctx, name);
    }
 }
@@ -1250,6 +1265,7 @@ _mesa_DeleteShader(GLuint name)
 {
    if (name) {
       GET_CURRENT_CONTEXT(ctx);
+      FLUSH_VERTICES(ctx, 0);
       delete_shader(ctx, name);
    }
 }
@@ -1509,7 +1525,8 @@ _mesa_ShaderSourceARB(GLhandleARB shaderObj, GLsizei count,
    for (i = 0; i < count; i++) {
       if (string[i] == NULL) {
          free((GLvoid *) offsets);
-         _mesa_error(ctx, GL_INVALID_OPERATION, "glShaderSourceARB(null string)");
+         _mesa_error(ctx, GL_INVALID_OPERATION,
+                     "glShaderSourceARB(null string)");
          return;
       }
       if (length == NULL || length[i] < 0)
@@ -1560,7 +1577,7 @@ _mesa_ShaderSourceARB(GLhandleARB shaderObj, GLsizei count,
          free(source);
          source = newSource;
       }
-   }      
+   }
 
    shader_source(ctx, shaderObj, source);
 
@@ -1582,6 +1599,8 @@ _mesa_UseProgramObjectARB(GLhandleARB program)
    struct gl_transform_feedback_object *obj =
       ctx->TransformFeedback.CurrentObject;
 
+   ASSERT_OUTSIDE_BEGIN_END(ctx);
+
    if (obj->Active) {
       _mesa_error(ctx, GL_INVALID_OPERATION,
                   "glUseProgram(transform feedback active)");
@@ -1625,20 +1644,58 @@ void GLAPIENTRY
 _mesa_GetShaderPrecisionFormat(GLenum shadertype, GLenum precisiontype,
                                GLint* range, GLint* precision)
 {
+   const struct gl_program_constants *limits;
+   const struct gl_precision *p;
    GET_CURRENT_CONTEXT(ctx);
-   (void) shadertype;
-   (void) precisiontype;
-   (void) range;
-   (void) precision;
-   _mesa_error(ctx, GL_INVALID_OPERATION, __FUNCTION__);
+
+   switch (shadertype) {
+   case GL_VERTEX_SHADER:
+      limits = &ctx->Const.VertexProgram;
+      break;
+   case GL_FRAGMENT_SHADER:
+      limits = &ctx->Const.FragmentProgram;
+      break;
+   default:
+      _mesa_error(ctx, GL_INVALID_ENUM,
+                  "glGetShaderPrecisionFormat(shadertype)");
+      return;
+   }
+
+   switch (precisiontype) {
+   case GL_LOW_FLOAT:
+      p = &limits->LowFloat;
+      break;
+   case GL_MEDIUM_FLOAT:
+      p = &limits->MediumFloat;
+      break;
+   case GL_HIGH_FLOAT:
+      p = &limits->HighFloat;
+      break;
+   case GL_LOW_INT:
+      p = &limits->LowInt;
+      break;
+   case GL_MEDIUM_INT:
+      p = &limits->MediumInt;
+      break;
+   case GL_HIGH_INT:
+      p = &limits->HighInt;
+      break;
+   default:
+      _mesa_error(ctx, GL_INVALID_ENUM,
+                  "glGetShaderPrecisionFormat(precisiontype)");
+      return;
+   }
+
+   range[0] = p->RangeMin;
+   range[1] = p->RangeMax;
+   precision[0] = p->Precision;
 }
 
 
 void GLAPIENTRY
 _mesa_ReleaseShaderCompiler(void)
 {
-   GET_CURRENT_CONTEXT(ctx);
-   _mesa_error(ctx, GL_INVALID_OPERATION, __FUNCTION__);
+   _mesa_destroy_shader_compiler_caches();
 }
 
 
@@ -1661,8 +1718,7 @@ _mesa_ShaderBinary(GLint n, const GLuint* shaders, GLenum binaryformat,
 #if FEATURE_ARB_geometry_shader4
 
 void GLAPIENTRY
-_mesa_ProgramParameteriARB(GLuint program, GLenum pname,
-                           GLint value)
+_mesa_ProgramParameteriARB(GLuint program, GLenum pname, GLint value)
 {
    struct gl_shader_program *shProg;
    GET_CURRENT_CONTEXT(ctx);
@@ -1677,7 +1733,7 @@ _mesa_ProgramParameteriARB(GLuint program, GLenum pname,
    switch (pname) {
    case GL_GEOMETRY_VERTICES_OUT_ARB:
       if (value < 1 ||
-          (unsigned) value > ctx->Const.GeometryProgram.MaxGeometryOutputVertices) {
+          (unsigned) value > ctx->Const.MaxGeometryOutputVertices) {
          _mesa_error(ctx, GL_INVALID_VALUE,
                      "glProgramParameteri(GL_GEOMETRY_VERTICES_OUT_ARB=%d",
                      value);
@@ -1740,6 +1796,8 @@ _mesa_UseShaderProgramEXT(GLenum type, GLuint program)
    GET_CURRENT_CONTEXT(ctx);
    struct gl_shader_program *shProg = NULL;
 
+   ASSERT_OUTSIDE_BEGIN_END(ctx);
+
    if (!validate_shader_target(ctx, type)) {
       _mesa_error(ctx, GL_INVALID_ENUM, "glUseShaderProgramEXT(type)");
       return;
@@ -1814,7 +1872,7 @@ _mesa_CreateShaderProgramEXT(GLenum type, const GLchar *string)
 #endif
         }
 
-        shProg->InfoLog = talloc_strdup_append(shProg->InfoLog, sh->InfoLog);
+        ralloc_strcat(&shProg->InfoLog, sh->InfoLog);
       }
 
       delete_shader(ctx, shader);
@@ -1881,6 +1939,10 @@ _mesa_init_shader_dispatch(struct _glapi_table *exec)
    SET_BindFragDataLocationEXT(exec, _mesa_BindFragDataLocation);
    SET_GetFragDataLocationEXT(exec, _mesa_GetFragDataLocation);
 
+   /* GL_ARB_ES2_compatibility */
+   SET_ReleaseShaderCompiler(exec, _mesa_ReleaseShaderCompiler);
+   SET_GetShaderPrecisionFormat(exec, _mesa_GetShaderPrecisionFormat);
+
 #endif /* FEATURE_GL */
 }