Merge branch 'mesa_7_6_branch' into mesa_7_7_branch
[mesa.git] / progs / util / shaderutil.c
index 2f1c4e38b3004b180d37a38cd4cc9b215ef8c05b..2f44c388d8a3b7769851de09d6be8bd546ca32e3 100644 (file)
@@ -9,27 +9,27 @@
 #include <assert.h>
 #include <stdio.h>
 #include <stdlib.h>
+#include <string.h>
+#include <GL/glew.h>
 #include <GL/glut.h>
-#include "extfuncs.h"
 #include "shaderutil.h"
 
+/** time to compile previous shader */
+static GLdouble CompileTime = 0.0;
 
-static void
-Init(void)
-{
-   static GLboolean firstCall = GL_TRUE;
-   if (firstCall) {
-      GetExtensionFuncs();
-      firstCall = GL_FALSE;
-   }
-}
+/** time to linke previous program */
+static GLdouble LinkTime = 0.0;
 
 
 GLboolean
 ShadersSupported(void)
 {
    const char *version = (const char *) glGetString(GL_VERSION);
-   if (version[0] == '2' && version[1] == '.') {
+
+   /* NVIDIA binary drivers will return "3.0.0", and they clearly support
+    * shaders.
+    */
+   if (version[0] >= '2' && version[1] == '.') {
       return GL_TRUE;
    }
    else if (glutExtensionSupported("GL_ARB_vertex_shader")
@@ -38,7 +38,8 @@ ShadersSupported(void)
       fprintf(stderr, "Warning: Trying ARB GLSL instead of OpenGL 2.x.  This may not work.\n");
       return GL_TRUE;
    }
-   return GL_TRUE;
+   fprintf(stderr, "Sorry, GLSL not supported with this OpenGL.\n");
+   return GL_FALSE;
 }
 
 
@@ -47,17 +48,22 @@ CompileShaderText(GLenum shaderType, const char *text)
 {
    GLuint shader;
    GLint stat;
+   GLdouble t0, t1;
+
+   shader = glCreateShader(shaderType);
+   glShaderSource(shader, 1, (const GLchar **) &text, NULL);
 
-   Init();
+   t0 = glutGet(GLUT_ELAPSED_TIME) * 0.001;
+   glCompileShader(shader);
+   t1 = glutGet(GLUT_ELAPSED_TIME) * 0.001;
 
-   shader = glCreateShader_func(shaderType);
-   glShaderSource_func(shader, 1, (const GLchar **) &text, NULL);
-   glCompileShader_func(shader);
-   glGetShaderiv_func(shader, GL_COMPILE_STATUS, &stat);
+   CompileTime = t1 - t0;
+
+   glGetShaderiv(shader, GL_COMPILE_STATUS, &stat);
    if (!stat) {
       GLchar log[1000];
       GLsizei len;
-      glGetShaderInfoLog_func(shader, 1000, &len, log);
+      glGetShaderInfoLog(shader, 1000, &len, log);
       fprintf(stderr, "Error: problem compiling shader: %s\n", log);
       exit(1);
    }
@@ -78,10 +84,12 @@ CompileShaderFile(GLenum shaderType, const char *filename)
    int n;
    char *buffer = (char*) malloc(max);
    GLuint shader;
+   FILE *f;
 
-   FILE *f = fopen(filename, "r");
+   f = fopen(filename, "r");
    if (!f) {
       fprintf(stderr, "Unable to open shader file %s\n", filename);
+      free(buffer);
       return 0;
    }
 
@@ -92,6 +100,8 @@ CompileShaderFile(GLenum shaderType, const char *filename)
       shader = CompileShaderText(shaderType, buffer);
    }
    else {
+      fclose(f);
+      free(buffer);
       return 0;
    }
 
@@ -105,24 +115,30 @@ CompileShaderFile(GLenum shaderType, const char *filename)
 GLuint
 LinkShaders(GLuint vertShader, GLuint fragShader)
 {
-   GLuint program = glCreateProgram_func();
+   GLuint program = glCreateProgram();
+   GLdouble t0, t1;
 
    assert(vertShader || fragShader);
 
    if (fragShader)
-      glAttachShader_func(program, fragShader);
+      glAttachShader(program, fragShader);
    if (vertShader)
-      glAttachShader_func(program, vertShader);
-   glLinkProgram_func(program);
+      glAttachShader(program, vertShader);
+
+   t0 = glutGet(GLUT_ELAPSED_TIME) * 0.001;
+   glLinkProgram(program);
+   t1 = glutGet(GLUT_ELAPSED_TIME) * 0.001;
+
+   LinkTime = t1 - t0;
 
    /* check link */
    {
       GLint stat;
-      glGetProgramiv_func(program, GL_LINK_STATUS, &stat);
+      glGetProgramiv(program, GL_LINK_STATUS, &stat);
       if (!stat) {
          GLchar log[1000];
          GLsizei len;
-         glGetProgramInfoLog_func(program, 1000, &len, log);
+         glGetProgramInfoLog(program, 1000, &len, log);
          fprintf(stderr, "Shader link error:\n%s\n", log);
          return 0;
       }
@@ -132,37 +148,176 @@ LinkShaders(GLuint vertShader, GLuint fragShader)
 }
 
 
+GLboolean
+ValidateShaderProgram(GLuint program)
+{
+   GLint stat;
+   glValidateProgramARB(program);
+   glGetProgramiv(program, GL_VALIDATE_STATUS, &stat);
+
+   if (!stat) {
+      GLchar log[1000];
+      GLsizei len;
+      glGetProgramInfoLog(program, 1000, &len, log);
+      fprintf(stderr, "Program validation error:\n%s\n", log);
+      return 0;
+   }
+
+   return (GLboolean) stat;
+}
+
+
+GLdouble
+GetShaderCompileTime(void)
+{
+   return CompileTime;
+}
+
+
+GLdouble
+GetShaderLinkTime(void)
+{
+   return LinkTime;
+}
+
+
 void
-InitUniforms(GLuint program, struct uniform_info uniforms[])
+SetUniformValues(GLuint program, struct uniform_info uniforms[])
 {
    GLuint i;
 
    for (i = 0; uniforms[i].name; i++) {
       uniforms[i].location
-         = glGetUniformLocation_func(program, uniforms[i].name);
-
-      printf("Uniform %s location: %d\n", uniforms[i].name,
-             uniforms[i].location);
-
-      switch (uniforms[i].size) {
-      case 1:
-         if (uniforms[i].type == GL_INT)
-            glUniform1i_func(uniforms[i].location,
-                             (GLint) uniforms[i].value[0]);
-         else
-            glUniform1fv_func(uniforms[i].location, 1, uniforms[i].value);
+         = glGetUniformLocation(program, uniforms[i].name);
+
+      switch (uniforms[i].type) {
+      case GL_INT:
+      case GL_SAMPLER_1D:
+      case GL_SAMPLER_2D:
+      case GL_SAMPLER_3D:
+      case GL_SAMPLER_CUBE:
+      case GL_SAMPLER_2D_RECT_ARB:
+         assert(uniforms[i].value[0] >= 0.0F);
+         glUniform1i(uniforms[i].location,
+                     (GLint) uniforms[i].value[0]);
          break;
-      case 2:
-         glUniform2fv_func(uniforms[i].location, 1, uniforms[i].value);
+      case GL_FLOAT:
+         glUniform1fv(uniforms[i].location, 1, uniforms[i].value);
          break;
-      case 3:
-         glUniform3fv_func(uniforms[i].location, 1, uniforms[i].value);
+      case GL_FLOAT_VEC2:
+         glUniform2fv(uniforms[i].location, 1, uniforms[i].value);
          break;
-      case 4:
-         glUniform4fv_func(uniforms[i].location, 1, uniforms[i].value);
+      case GL_FLOAT_VEC3:
+         glUniform3fv(uniforms[i].location, 1, uniforms[i].value);
+         break;
+      case GL_FLOAT_VEC4:
+         glUniform4fv(uniforms[i].location, 1, uniforms[i].value);
          break;
       default:
-         abort();
+         if (strncmp(uniforms[i].name, "gl_", 3) == 0) {
+            /* built-in uniform: ignore */
+         }
+         else {
+            fprintf(stderr,
+                    "Unexpected uniform data type in SetUniformValues\n");
+            abort();
+         }
       }
    }
 }
+
+
+/** Get list of uniforms used in the program */
+GLuint
+GetUniforms(GLuint program, struct uniform_info uniforms[])
+{
+   GLint n, max, i;
+
+   glGetProgramiv(program, GL_ACTIVE_UNIFORMS, &n);
+   glGetProgramiv(program, GL_ACTIVE_UNIFORM_MAX_LENGTH, &max);
+
+   for (i = 0; i < n; i++) {
+      GLint size, len;
+      GLenum type;
+      char name[100];
+
+      glGetActiveUniform(program, i, 100, &len, &size, &type, name);
+
+      uniforms[i].name = strdup(name);
+      uniforms[i].size = size;
+      uniforms[i].type = type;
+      uniforms[i].location = glGetUniformLocation(program, name);
+   }
+
+   uniforms[i].name = NULL; /* end of list */
+
+   return n;
+}
+
+
+void
+PrintUniforms(const struct uniform_info uniforms[])
+{
+   GLint i;
+
+   printf("Uniforms:\n");
+
+   for (i = 0; uniforms[i].name; i++) {
+      printf("  %d: %s size=%d type=0x%x loc=%d value=%g, %g, %g, %g\n",
+             i,
+             uniforms[i].name,
+             uniforms[i].size,
+             uniforms[i].type,
+             uniforms[i].location,
+             uniforms[i].value[0],
+             uniforms[i].value[1],
+             uniforms[i].value[2],
+             uniforms[i].value[3]);
+   }
+}
+
+
+/** Get list of attribs used in the program */
+GLuint
+GetAttribs(GLuint program, struct attrib_info attribs[])
+{
+   GLint n, max, i;
+
+   glGetProgramiv(program, GL_ACTIVE_ATTRIBUTES, &n);
+   glGetProgramiv(program, GL_ACTIVE_ATTRIBUTE_MAX_LENGTH, &max);
+
+   for (i = 0; i < n; i++) {
+      GLint size, len;
+      GLenum type;
+      char name[100];
+
+      glGetActiveAttrib(program, i, 100, &len, &size, &type, name);
+
+      attribs[i].name = strdup(name);
+      attribs[i].size = size;
+      attribs[i].type = type;
+      attribs[i].location = glGetAttribLocation(program, name);
+   }
+
+   attribs[i].name = NULL; /* end of list */
+
+   return n;
+}
+
+
+void
+PrintAttribs(const struct attrib_info attribs[])
+{
+   GLint i;
+
+   printf("Attribs:\n");
+
+   for (i = 0; attribs[i].name; i++) {
+      printf("  %d: %s size=%d type=0x%x loc=%d\n",
+             i,
+             attribs[i].name,
+             attribs[i].size,
+             attribs[i].type,
+             attribs[i].location);
+   }
+}