summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIan Romanick <idr@freedesktop.org>2010-07-18 17:20:18 -0700
committerIan Romanick <idr@freedesktop.org>2010-07-18 17:20:18 -0700
commit4f57c041039e897a3183aa13943f2bac67c937ea (patch)
treef42ef8793bb87bd4aa44faa44b84ba262138daaf
parent9a48bdd102c7cc51a8049e5df86c8e538d0f1d13 (diff)
Add initial version of shading language helper functionsshader_helper
-rw-r--r--include/glu3.h109
-rw-r--r--src/Makefile.am2
-rw-r--r--src/shader.c261
3 files changed, 371 insertions, 1 deletions
diff --git a/include/glu3.h b/include/glu3.h
index 98688d3..f93de5f 100644
--- a/include/glu3.h
+++ b/include/glu3.h
@@ -37,6 +37,8 @@
#include <GL/gl.h>
#include <GL/glext.h>
+#include <stdbool.h>
+
#define GLU3_VERSION_0_1
struct GLUmat4;
@@ -1219,6 +1221,113 @@ inline GLUmat4 GLUarcball::drag(unsigned end_x, unsigned end_y)
}
#endif /* __cplusplus */
+#if defined(__cplusplus)
+extern "C" {
+#endif
+/**
+ * \name Shading language helper functions
+ */
+/*@{*/
+/**
+ * Initialize the GLSL compiler infrastructure
+ *
+ * This function \b must be called before any of the GLU3 GLSL helper functions
+ * can be used. On Windows, this function must be called each time a context
+ * with a different color depth is made current.
+ *
+ * It is the responsibility of the caller to verify that the required version
+ * of GLSL and the required shader targets (e.g., geometry) are supported.
+ *
+ * \return
+ * If GLSL is available, \c true is returned. Otherwise \c false is returned.
+ */
+extern bool gluInitializeCompiler(void);
+
+/**
+ * Compile a shader
+ *
+ * Creates a new shader object for the specified target and compiles the
+ * supplied code into that shader object. If \c log_ptr is not \c NULL, a
+ * buffer will be allocated and filled with diagnostic messages from the
+ * shading language compiler. A pointer to this buffer will stored in
+ * \c log_ptr.
+ *
+ * The pointer stored in \c log_ptr must be later released with
+ * \c gluReleaseInfoLog.
+ *
+ * \param target Shader execution unit (e.g., \c GL_VERTEX_SHADER)
+ * \param code Shader source code
+ * \param log_ptr Location to store a pointer to the compiler generate info log
+ *
+ * \return
+ * If compilation was successful, the shader object is returned. On failure
+ * zero is returned.
+ *
+ * \sa gluReleaseInfoLog
+ */
+extern GLint gluCompileShader(GLenum target, const char *code, char **log_ptr);
+
+/**
+ * Link a shader program
+ *
+ * Links the specified shader program. If \c log_ptr is not \c NULL, a buffer
+ * will be allocated and filled with diagnostic messages from the shading
+ * language linker. A pointer to this buffer will stored in \c log_ptr.
+ *
+ * The pointer stored in \c log_ptr must be later released with
+ * \c gluReleaseInfoLog.
+ *
+ * \param prog Shading language program to be linked
+ * \param log_ptr Location to store a pointer to the compiler generate info log
+ *
+ * \return
+ * If linking was successful, \c true is returned. Otherwise \c false is
+ * returned.
+ *
+ * \sa gluReleaseInfoLog
+ */
+extern bool gluLinkProgram(GLuint prog, char **log_ptr);
+
+/**
+ * Attach a list of shader objects to a program
+ *
+ * Attaches a zero-terminated list of shader objects to a program object.
+ *
+ * \param prog Shading language program to which shaders will be attached
+ * \param shader First shader to be attached to the program
+ */
+extern void gluAttachShaders(GLuint prog, GLuint shader, ...);
+
+/**
+ * Bind a set of shader program attributes to locations
+ *
+ * Bind the locations of a set of attributes. The list of attributes is
+ * terminate by a \c NULL \c name pointer.
+ *
+ * \param prog Shading language program whose attribute locations will
+ * be set
+ * \param name Name of the first attribute to set
+ * \param location Location of the first attribute
+ */
+extern void gluBindAttributes(GLuint prog, const char *name, unsigned location,
+ ...);
+
+/**
+ * Release an info log
+ *
+ * Release an info log generated by a call to \c gluLinkProgram or
+ * \c gluCompileShader.
+ *
+ * \param log Info log buffer to be released
+ *
+ * \sa gluCompileShader, gluLinkProgram
+ */
+extern void gluReleaseInfoLog(char *log);
+/*@}*/
+#if defined(__cplusplus)
+};
+#endif
+
#include "glu3_scalar.h"
#endif /* __glu3_h__ */
diff --git a/src/Makefile.am b/src/Makefile.am
index 624d383..790c30d 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -25,7 +25,7 @@ AM_CFLAGS=-I../include
lib_LIBRARIES = libGLU3.a
libGLU3_a_SOURCES = matrix.c load_text.c arcball.c revolve.c mesh.c \
- sphere.cpp cube.cpp
+ sphere.cpp cube.cpp shader.c
libGLU3includedir = ${includedir}
libGLU3include_HEADERS = ../include/glu3.h ../include/glu3_scalar.h
diff --git a/src/shader.c b/src/shader.c
new file mode 100644
index 0000000..8e7f271
--- /dev/null
+++ b/src/shader.c
@@ -0,0 +1,261 @@
+/*
+ * Copyright © 2009, 2010 Ian D. Romanick
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+#include "config.h"
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
+#include <stdbool.h>
+
+#define GL_GLEXT_PROTOTYPES
+#include <GL/gl.h>
+#include <GL/glext.h>
+
+#if defined(HAVE_GLX)
+#include <GL/glx.h>
+#define GetProcAddress(x) glXGetProcAddress(#x)
+#elif defined(HAVE_EGL)
+#include <EGL/egl.h>
+#define GetProcAddress(x) eglGetProcAddress(#x)
+#elif defined(HAVE_WGL)
+#include <GL/wgl.h>
+#define GetProcAddress(x) wglGetProcAddress(#x)
+#else
+#define GetProcAddress(x) (x)
+#endif
+
+static PFNGLSHADERSOURCEPROC ShaderSource = NULL;
+static PFNGLCREATESHADERPROC CreateShader = NULL;
+static PFNGLCOMPILESHADERPROC CompileShader = NULL;
+static PFNGLGETSHADERIVPROC GetShaderiv = NULL;
+static PFNGLGETSHADERINFOLOGPROC GetShaderInfoLog = NULL;
+static PFNGLDELETESHADERPROC DeleteShader = NULL;
+
+static PFNGLLINKPROGRAMPROC LinkProgram = NULL;
+static PFNGLATTACHSHADERPROC AttachShader = NULL;
+static PFNGLBINDATTRIBLOCATIONPROC BindAttribLocation = NULL;
+static PFNGLGETPROGRAMIVPROC GetProgramiv = NULL;
+static PFNGLGETPROGRAMINFOLOGPROC GetProgramInfoLog = NULL;
+
+bool
+gluInitializeCompiler(void)
+{
+ /* Determine which set of interfaces are available for accessing GLSL.
+ * This will either be from OpenGL 2.0+ (or OpenGL ES 2.0) or from
+ * GL_ARB_shader_objects.
+ */
+ const char *const version_string = glGetString(GL_VERSION);
+ float version = strtof(version_string, NULL);
+
+ if (version >= 2.0f) {
+ ShaderSource = (PFNGLSHADERSOURCEPROC)
+ GetProcAddress(glShaderSource);
+ CreateShader = (PFNGLCREATESHADERPROC)
+ GetProcAddress(glCreateShader);
+ CompileShader = (PFNGLCOMPILESHADERPROC)
+ GetProcAddress(glCompileShader);
+ GetShaderiv = (PFNGLGETSHADERIVPROC)
+ GetProcAddress(glGetShaderiv);
+ GetShaderInfoLog = (PFNGLGETSHADERINFOLOGPROC)
+ GetProcAddress(glGetShaderInfoLog);
+ DeleteShader = (PFNGLDELETESHADERPROC)
+ GetProcAddress(glDeleteShader);
+
+ LinkProgram = (PFNGLLINKPROGRAMPROC)
+ GetProcAddress(glLinkProgram);
+ AttachShader = (PFNGLATTACHSHADERPROC)
+ GetProcAddress(glAttachShader);
+ BindAttribLocation = (PFNGLBINDATTRIBLOCATIONPROC)
+ GetProcAddress(glBindAttribLocation);
+ GetProgramiv = (PFNGLGETPROGRAMIVPROC)
+ GetProcAddress(glGetProgramiv);
+ GetProgramInfoLog = (PFNGLGETPROGRAMINFOLOGPROC)
+ GetProcAddress(glGetProgramInfoLog);
+ } else {
+ const char *const extension_string = glGetString(GL_EXTENSIONS);
+ const unsigned len = strlen("GL_ARB_shader_objects");
+ const char *x;
+
+ x = extension_string;
+ while ((x = strstr(x, "GL_ARB_shader_objects")) != NULL) {
+ if (x[len] == ' ' || x[len] == '\0')
+ break;
+
+ x += len;
+ }
+
+ if (strcmp(x, "GL_ARB_shader_objects") != 0)
+ return false;
+
+ ShaderSource = (PFNGLSHADERSOURCEPROC)
+ GetProcAddress(glShaderSourceARB);
+ CreateShader = (PFNGLCREATESHADERPROC)
+ GetProcAddress(glCreateShaderARB);
+ CompileShader = (PFNGLCOMPILESHADERPROC)
+ GetProcAddress(glCompileShaderARB);
+ DeleteShader = (PFNGLDELETESHADERPROC)
+ GetProcAddress(glDeleteShaderARB);
+
+ LinkProgram = (PFNGLLINKPROGRAMPROC)
+ GetProcAddress(glLinkProgramARB);
+ AttachShader = (PFNGLATTACHSHADERPROC)
+ GetProcAddress(glAttachShaderARB);
+ BindAttribLocation = (PFNGLBINDATTRIBLOCATIONPROC)
+ GetProcAddress(glBindAttribLocationARB);
+
+
+ /* These functions break the mold a little bit. Here the API
+ * changed between the extension and core GL. For the uses
+ * internal to this library, we can work around the change by
+ * using glGetObjectParameterivARB for both glGetShaderiv and
+ * glGetProgramiv. Likewise glGetInfoLogARB can be used for
+ * both glGetShaderInfoLog and glGetProgramInfoLog.
+ */
+ GetShaderiv = (PFNGLGETSHADERIVPROC)
+ GetProcAddress(glGetObjectParameterivARB);
+ GetProgramiv = (PFNGLGETPROGRAMIVPROC) GetShaderiv;
+
+ GetShaderInfoLog = (PFNGLGETSHADERINFOLOGPROC)
+ GetProcAddress(glGetInfoLogARB);
+ GetProgramInfoLog = (PFNGLGETSHADERIVPROC) GetShaderInfoLog;
+ }
+}
+
+
+void
+gluReleaseInfoLog(char *log)
+{
+ free(log);
+}
+
+
+GLint
+gluCompileShader(GLenum target, const char *code, char **log_ptr)
+{
+ GLint status;
+ GLuint shad = CreateShader(target);
+
+ ShaderSource(shad, 1, &code, NULL);
+ CompileShader(shad);
+
+ if (log_ptr != NULL) {
+ GLint len;
+
+ /* The spec says that 0 is returned when no log is available.
+ * However, Nvidia's drivers like to return a log length of 1,
+ * and return a log that is just a NUL terminator.
+ */
+ GetShaderiv(shad, GL_INFO_LOG_LENGTH, &len);
+ if (len > 1) {
+ char *log = (char *) malloc(len + 1);
+
+ if (log != NULL) {
+ GetShaderInfoLog(shad, len + 1, NULL, log);
+ *log_ptr = log;
+ }
+ }
+ }
+
+ GetShaderiv(shad, GL_COMPILE_STATUS, &status);
+ if (!status) {
+ DeleteShader(shad);
+ return 0;
+ }
+
+ return shad;
+}
+
+
+bool
+gluLinkProgram(GLuint prog, char **log_ptr)
+{
+ GLint status;
+
+ LinkProgram(prog);
+
+ if (log_ptr != NULL) {
+ GLint len;
+
+ /* The spec says that 0 is returned when no log is available.
+ * However, Nvidia's drivers like to return a log length of 1,
+ * and return a log that is just a NUL terminator.
+ */
+ GetProgramiv(prog, GL_INFO_LOG_LENGTH, &len);
+ if (len > 1) {
+ char *log = (char *) malloc(len + 1);
+
+ if (log != NULL) {
+ GetProgramInfoLog(prog, len + 1, NULL, log);
+ *log_ptr = log;
+ }
+ }
+ }
+
+ GetProgramiv(prog, GL_LINK_STATUS, &status);
+ return status == GL_TRUE;
+}
+
+
+void
+gluAttachShaders(GLuint prog, GLuint shader, ...)
+{
+ va_list args;
+
+ AttachShader(prog, shader);
+
+ va_start(args, prog);
+
+ while (true) {
+ GLuint s = va_arg(args, GLuint);
+
+ if (s == 0)
+ break;
+
+ AttachShader(prog, s);
+ }
+
+ va_end(args);
+}
+
+
+void
+gluBindAttributes(GLuint prog, const char *name, GLuint location, ...)
+{
+ va_list args;
+
+ BindAttribLocation(prog, location, name);
+
+ va_start(args, prog);
+
+ while (true) {
+ const char *name = va_arg(args, char *);
+ GLuint idx;
+
+ if (name == NULL)
+ break;
+
+ idx = va_arg(args, unsigned);
+ BindAttribLocation(prog, idx, name);
+ }
+
+ va_end(args);
+}