diff mbox

[Branch,~glcompbench-dev/glcompbench/trunk] Rev 67: Merge the shader-source branch. This adds the ShaderSource and ancillary objects

Message ID 20111206163515.16365.96746.launchpad@ackee.canonical.com
State Accepted
Headers show

Commit Message

Jesse Barker Dec. 6, 2011, 4:35 p.m. UTC
Merge authors:
  Jesse Barker (jesse-barker)
Related merge proposals:
  https://code.launchpad.net/~jesse-barker/glcompbench/shader-source/+merge/84520
  proposed by: Jesse Barker (jesse-barker)
  review: Approve - Alexandros Frantzis (afrantzis)
------------------------------------------------------------
revno: 67 [merge]
committer: Jesse Barker <jesse.barker@linaro.org>
branch nick: trunk
timestamp: Tue 2011-12-06 08:29:56 -0800
message:
  Merge the shader-source branch.  This adds the ShaderSource and ancillary objects
  from the glmark2 project for managing shaders.  The changes also incorporates
  those objects into the GL-based scenarios; a by-product of this is that the
  fragment shader for the fade effect goes away since it can now be generated from
  the shader for the default scenario.
removed:
  data/fade.frag
added:
  src/shader-source.cc
  src/shader-source.h
  src/util.cc
  src/util.h
modified:
  data/brick.frag
  data/brick.vert
  data/default.frag
  data/default.vert
  src/composite-test-simple-base.cc
  src/composite-test-simple-default.cc
  src/composite-test-simple-fade.cc
  src/composite-test.h


--
lp:glcompbench
https://code.launchpad.net/~glcompbench-dev/glcompbench/trunk

You are subscribed to branch lp:glcompbench.
To unsubscribe from this branch go to https://code.launchpad.net/~glcompbench-dev/glcompbench/trunk/+edit-subscription
diff mbox

Patch

=== modified file 'data/brick.frag'
--- data/brick.frag	2011-07-29 20:28:24 +0000
+++ data/brick.frag	2011-12-05 19:01:24 +0000
@@ -1,6 +1,3 @@ 
-#ifdef GL_ES
-precision mediump float;
-#endif
 uniform vec2 BrickSize;
 uniform vec2 BrickPct;
 

=== modified file 'data/brick.vert'
--- data/brick.vert	2011-07-29 20:28:24 +0000
+++ data/brick.vert	2011-12-05 19:01:24 +0000
@@ -1,6 +1,3 @@ 
-#ifdef GL_ES
-precision mediump float;
-#endif
 uniform mat4 modelview;
 uniform mat4 projection;
 uniform vec4 LightPosition;

=== modified file 'data/default.frag'
--- data/default.frag	2011-07-18 17:14:16 +0000
+++ data/default.frag	2011-12-05 19:01:24 +0000
@@ -1,12 +1,9 @@ 
-#ifdef GL_ES
-precision mediump float;
-#endif
-
 uniform sampler2D Texture0;
 varying vec2 TextureCoord;
 
 void main(void)
 {
+    float alpha = 1.0 - alpha_bias;
     vec4 texel = texture2D(Texture0, TextureCoord);
-    gl_FragColor = vec4(texel.xyz, 0.5);
+    gl_FragColor = vec4(texel.xyz, alpha);
 }

=== modified file 'data/default.vert'
--- data/default.vert	2011-07-18 17:14:16 +0000
+++ data/default.vert	2011-12-05 19:01:24 +0000
@@ -1,7 +1,3 @@ 
-#ifdef GL_ES
-precision mediump float;
-#endif
-
 attribute vec3 position;
 attribute vec2 texcoord;
 uniform mat4 projection;

=== removed file 'data/fade.frag'
--- data/fade.frag	2011-10-13 22:48:52 +0000
+++ data/fade.frag	1970-01-01 00:00:00 +0000
@@ -1,14 +0,0 @@ 
-#ifdef GL_ES
-precision mediump float;
-#endif
-
-uniform float alpha_bias;
-uniform sampler2D Texture0;
-varying vec2 TextureCoord;
-
-void main(void)
-{
-    float alpha = 1.0 - alpha_bias;
-    vec4 texel = texture2D(Texture0, TextureCoord);
-    gl_FragColor = vec4(texel.xyz, alpha);
-}

=== modified file 'src/composite-test-simple-base.cc'
--- src/composite-test-simple-base.cc	2011-09-05 15:23:11 +0000
+++ src/composite-test-simple-base.cc	2011-12-05 19:01:24 +0000
@@ -45,6 +45,26 @@ 
                                                 "Whether to use VBOs for rendering [true,false]");
 }
 
+bool
+CompositeTestSimpleBase::init_shaders(ShaderSource& vtx, ShaderSource& frg)
+{
+    if (vtx.type() == ShaderSource::ShaderTypeUnknown)
+    {
+        return false;
+    }
+    if (frg.type() == ShaderSource::ShaderTypeUnknown)
+    {
+        return false;
+    }
+
+    static const string precisionString("default,default,default,default");
+    static const ShaderSource::Precision precision(precisionString);
+    vtx.precision(precision);
+    frg.precision(precision);
+
+    return true;
+}
+
 void
 CompositeTestSimpleBase::init()
 {
@@ -52,16 +72,11 @@ 
         return;
 
     // Initialize shader sources from input files
-    if (!gotSource(vs_filename_, vertex_shader_))
-    {
-        Log::error("Failed to get vertex shader source for test\n");
-        return;
-    }
-    if (!gotSource(fs_filename_, fragment_shader_))
-    {
-        Log::error("Failed to get fragment shader source for test\n");
-        return;
-    }
+    ShaderSource vtx_source(vs_filename_);
+    ShaderSource frg_source(fs_filename_);
+    init_shaders(vtx_source, frg_source);
+    vertex_shader_ = vtx_source.str();
+    fragment_shader_ = frg_source.str();
 
     program_.init();
     if (!program_.valid())

=== modified file 'src/composite-test-simple-default.cc'
--- src/composite-test-simple-default.cc	2011-09-05 15:23:11 +0000
+++ src/composite-test-simple-default.cc	2011-12-05 19:01:24 +0000
@@ -29,6 +29,18 @@ 
 using std::string;
 using std::map;
 
+bool
+CompositeTestSimpleDefault::init_shaders(ShaderSource& vtx, ShaderSource& frg)
+{
+    static const string precisionString("default,default,default,default");
+    static const ShaderSource::Precision precision(precisionString);
+    vtx.precision(precision);
+    frg.precision(precision);
+    static const float alpha_bias(0.5);
+    frg.add_const("alpha_bias", alpha_bias);
+
+    return true;
+}
 void
 CompositeTestSimpleDefault::draw(std::list<CompositeWindow *> &window_list)
 {

=== modified file 'src/composite-test-simple-fade.cc'
--- src/composite-test-simple-fade.cc	2011-10-14 12:41:30 +0000
+++ src/composite-test-simple-fade.cc	2011-12-05 19:01:24 +0000
@@ -31,6 +31,18 @@ 
 
 const string CompositeTestSimpleFade::fade_bias_name_("alpha_bias");
 
+bool
+CompositeTestSimpleFade::init_shaders(ShaderSource& vtx, ShaderSource& frg)
+{
+    static const string precisionString("default,default,default,default");
+    static const ShaderSource::Precision precision(precisionString);
+    vtx.precision(precision);
+    frg.precision(precision);
+    static const string uniform("uniform float alpha_bias;");
+    frg.add(uniform);
+    return true;
+}
+
 // We want to fade smoothly across the test duration, so take a timestamp
 // at the beginning of the test (beginning of the first draw), and take one
 // each time we'll update the fade bias to see if we should.  We know based

=== modified file 'src/composite-test.h'
--- src/composite-test.h	2011-10-14 02:09:08 +0000
+++ src/composite-test.h	2011-12-05 18:14:07 +0000
@@ -34,6 +34,7 @@ 
 #include "program.h"
 #include "composite-window.h"
 #include "vbo.h"
+#include "shader-source.h"
 
 class CompositeCanvas;
 
@@ -141,7 +142,7 @@ 
 
     LibMatrix::Stack4 projection_matrix;
     LibMatrix::Stack4 model_view_matrix;
-
+    virtual bool init_shaders(ShaderSource& vtx, ShaderSource& frg);
 };
 
 class CompositeTestSimpleDefault : public CompositeTestSimpleBase
@@ -154,6 +155,7 @@ 
         {}
 
     virtual void draw(std::list<CompositeWindow*> &window_list);
+    virtual bool init_shaders(ShaderSource& vtx, ShaderSource& frg);
 };
 
 class CompositeTestSimpleBrick : public CompositeTestSimpleBase
@@ -216,10 +218,11 @@ 
     CompositeTestSimpleFade() : 
         CompositeTestSimpleBase("fade",
                                 GLCOMPBENCH_DATA_PATH"/default.vert",
-                                GLCOMPBENCH_DATA_PATH"/fade.frag")
+                                GLCOMPBENCH_DATA_PATH"/default.frag")
         {}
 
     virtual void draw(std::list<CompositeWindow*> &window_list);
+    virtual bool init_shaders(ShaderSource& vtx, ShaderSource& frg);
 };
 
 #endif // COMPOSITE_TEST_H_

=== added file 'src/shader-source.cc'
--- src/shader-source.cc	1970-01-01 00:00:00 +0000
+++ src/shader-source.cc	2011-12-02 21:54:50 +0000
@@ -0,0 +1,622 @@ 
+/*
+ * Copyright © 2010-2011 Linaro Limited
+ *
+ * This file is part of the glmark2 OpenGL (ES) 2.0 benchmark.
+ *
+ * glmark2 is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later
+ * version.
+ *
+ * glmark2 is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * glmark2.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Authors:
+ *  Alexandros Frantzis (glmark2)
+ */
+
+#include <istream>
+#include <memory>
+
+#include "shader-source.h"
+#include "log.h"
+#include "vec.h"
+#include "util.h"
+
+/**
+ * Holds default precision values for all shader types
+ * (even the unknown type, which is hardwired to default precision values)
+ */
+std::vector<ShaderSource::Precision>
+ShaderSource::default_precision_(ShaderSource::ShaderTypeUnknown + 1);
+
+/**
+ * Loads the contents of a file into a string.
+ *
+ * @param filename the name of the file
+ * @param str the string to put the contents of the file into
+ */
+bool
+ShaderSource::load_file(const std::string& filename, std::string& str)
+{
+    std::auto_ptr<std::istream> is_ptr(Util::get_resource(filename));
+    std::istream& inputFile(*is_ptr);
+
+    if (!inputFile)
+    {
+        Log::error("Failed to open \"%s\"\n", filename.c_str());
+        return false;
+    }
+
+    std::string curLine;
+    while (getline(inputFile, curLine))
+    {
+        str += curLine;
+        str += '\n';
+    }
+
+    return true;
+}
+
+
+/**
+ * Appends a string to the shader source.
+ *
+ * @param str the string to append
+ */
+void
+ShaderSource::append(const std::string &str)
+{
+    source_ << str;
+}
+
+/**
+ * Appends the contents of a file to the shader source.
+ *
+ * @param filename the name of the file to append
+ */
+void
+ShaderSource::append_file(const std::string &filename)
+{
+    std::string source;
+    if (load_file(filename, source))
+        source_ << source;
+}
+
+/**
+ * Replaces a string in the source with another string.
+ *
+ * @param remove the string to replace
+ * @param insert the string to replace with
+ */
+void
+ShaderSource::replace(const std::string &remove, const std::string &insert)
+{
+    std::string::size_type pos = 0;
+    std::string str(source_.str());
+
+    while ((pos = str.find(remove, pos)) != std::string::npos) {
+        str.replace(pos, remove.size(), insert);
+        pos++;
+    }
+
+    source_.clear();
+    source_.str(str);
+}
+
+/**
+ * Replaces a string in the source with the contents of a file.
+ *
+ * @param remove the string to replace
+ * @param filename the name of the file to read from
+ */
+void
+ShaderSource::replace_with_file(const std::string &remove, const std::string &filename)
+{
+    std::string source;
+    if (load_file(filename, source))
+        replace(remove, source);
+}
+
+/**
+ * Adds a string (usually containing a constant definition) at
+ * global (per shader) scope.
+ *
+ * The string is placed after any default precision qualifiers.
+ *
+ * @param str the string to add
+ */
+void
+ShaderSource::add_global(const std::string &str)
+{
+    std::string::size_type pos = 0;
+    std::string source(source_.str());
+
+    /* Find the last precision qualifier */
+    pos = source.rfind("precision");
+
+    if (pos != std::string::npos) {
+        /*
+         * Find the next #endif line of a preprocessor block that contains
+         * the precision qualifier.
+         */
+        std::string::size_type pos_if = source.find("#if", pos);
+        std::string::size_type pos_endif = source.find("#endif", pos);
+
+        if (pos_endif != std::string::npos && pos_endif < pos_if)
+            pos = pos_endif;
+
+        /* Go to the next line */
+        pos = source.find("\n", pos);
+        if (pos != std::string::npos)
+            pos++;
+    }
+    else
+        pos = 0;
+
+    source.insert(pos, str);
+
+    source_.clear();
+    source_.str(source);
+}
+
+/**
+ * Adds a string (usually containing a constant definition) at
+ * global (per shader) scope.
+ *
+ * The string is placed after any default precision qualifiers.
+ *
+ * @param function the function to add the string into
+ * @param str the string to add
+ */
+void
+ShaderSource::add_local(const std::string &str, const std::string &function)
+{
+    std::string::size_type pos = 0;
+    std::string source(source_.str());
+
+    /* Find the function */
+    pos = source.find(function);
+    pos = source.find('{', pos);
+
+    /* Go to the next line */
+    pos = source.find("\n", pos);
+    if (pos != std::string::npos)
+        pos++;
+
+    source.insert(pos, str);
+
+    source_.clear();
+    source_.str(source);
+}
+
+/**
+ * Adds a string (usually containing a constant definition) to a shader source
+ *
+ * If the function parameter is empty, the string will be added to global
+ * scope, after any precision definitions.
+ *
+ * @param str the string to add
+ * @param function if not empty, the function to add the string into
+ */
+void
+ShaderSource::add(const std::string &str, const std::string &function)
+{
+    if (!function.empty())
+        add_local(str, function);
+    else
+        add_global(str);
+}
+
+/**
+ * Adds a float constant definition.
+ *
+ * @param name the name of the constant
+ * @param f the value of the constant
+ * @param function if not empty, the function to put the definition in
+ */
+void
+ShaderSource::add_const(const std::string &name, float f,
+                        const std::string &function)
+{
+    std::stringstream ss;
+
+    ss << "const float " << name << " = " << std::fixed << f << ";" << std::endl;
+
+    add(ss.str(), function);
+}
+
+/**
+ * Adds a float array constant definition.
+ *
+ * Note that various GLSL versions (including ES) don't support
+ * array constants.
+ *
+ * @param name the name of the constant
+ * @param v the value of the constant
+ * @param function if not empty, the function to put the definition in
+ */
+void
+ShaderSource::add_const(const std::string &name, std::vector<float> &array,
+                        const std::string &function)
+{
+    std::stringstream ss;
+
+    ss << "const float " << name << "[" << array.size() << "] = {" << std::fixed;
+    for(std::vector<float>::const_iterator iter = array.begin();
+        iter != array.end();
+        iter++)
+    {
+        ss << *iter;
+        if (iter + 1 != array.end())
+            ss << ", " << std::endl;
+    }
+
+    ss << "};" << std::endl;
+
+    add(ss.str(), function);
+}
+
+/**
+ * Adds a vec2 constant definition.
+ *
+ * @param name the name of the constant
+ * @param v the value of the constant
+ * @param function if not empty, the function to put the definition in
+ */
+void
+ShaderSource::add_const(const std::string &name, const LibMatrix::vec2 &v,
+                        const std::string &function)
+{
+    std::stringstream ss;
+
+    ss << "const vec2 " << name << " = vec2(" << std::fixed;
+    ss << v.x() << ", " << v.y() << ");" << std::endl;
+
+    add(ss.str(), function);
+}
+
+/**
+ * Adds a vec3 constant definition.
+ *
+ * @param name the name of the constant
+ * @param v the value of the constant
+ * @param function if not empty, the function to put the definition in
+ */
+void
+ShaderSource::add_const(const std::string &name, const LibMatrix::vec3 &v,
+                        const std::string &function)
+{
+    std::stringstream ss;
+
+    ss << "const vec3 " << name << " = vec3(" << std::fixed;
+    ss << v.x() << ", " << v.y() << ", " << v.z() << ");" << std::endl;
+
+    add(ss.str(), function);
+}
+
+/**
+ * Adds a vec4 constant definition.
+ *
+ * @param name the name of the constant
+ * @param v the value of the constant
+ * @param function if not empty, the function to put the definition in
+ */
+void
+ShaderSource::add_const(const std::string &name, const LibMatrix::vec4 &v,
+                        const std::string &function)
+{
+    std::stringstream ss;
+
+    ss << "const vec4 " << name << " = vec4(" << std::fixed;
+    ss << v.x() << ", " << v.y() << ", " << v.z() << ", " << v.w() << ");" << std::endl;
+
+    add(ss.str(), function);
+}
+
+/**
+ * Adds a mat3 constant definition.
+ *
+ * @param name the name of the constant
+ * @param v the value of the constant
+ * @param function if not empty, the function to put the definition in
+ */
+void
+ShaderSource::add_const(const std::string &name, const LibMatrix::mat3 &m,
+                        const std::string &function)
+{
+    std::stringstream ss;
+
+    ss << "const mat3 " << name << " = mat3(" << std::fixed;
+    ss << m[0][0] << ", " << m[1][0] << ", " << m[2][0] << "," << std::endl;
+    ss << m[0][1] << ", " << m[1][1] << ", " << m[2][1] << "," << std::endl;
+    ss << m[0][2] << ", " << m[1][2] << ", " << m[2][2] << std::endl;
+    ss << ");" << std::endl;
+
+    add(ss.str(), function);
+}
+
+/**
+ * Adds a float array declaration and initialization.
+ *
+ * @param name the name of the array
+ * @param array the array values
+ * @param init_function the function to put the initialization in
+ * @param decl_function if not empty, the function to put the declaration in
+ */
+void
+ShaderSource::add_array(const std::string &name, std::vector<float> &array,
+                        const std::string &init_function,
+                        const std::string &decl_function)
+{
+    if (init_function.empty() || name.empty())
+        return;
+
+    std::stringstream ss;
+    ss << "float " << name << "[" << array.size() << "];" << std::endl;
+
+    std::string decl(ss.str());
+
+    ss.clear();
+    ss.str("");
+    ss << std::fixed;
+
+    for(std::vector<float>::const_iterator iter = array.begin();
+        iter != array.end();
+        iter++)
+    {
+        ss << name << "[" << iter - array.begin() << "] = " << *iter << ";" << std::endl;
+    }
+
+    add(ss.str(), init_function);
+
+    add(decl, decl_function);
+}
+
+/**
+ * Gets the ShaderType for this ShaderSource.
+ *
+ * If the ShaderType is unknown, an attempt is made to infer
+ * the type from the shader source contents.
+ *
+ * @return the ShaderType
+ */
+ShaderSource::ShaderType
+ShaderSource::type()
+{
+    /* Try to infer the type from the source contents */
+    if (type_ == ShaderSource::ShaderTypeUnknown) {
+        std::string source(source_.str());
+
+        if (source.find("gl_FragColor") != std::string::npos)
+            type_ = ShaderSource::ShaderTypeFragment;
+        else if (source.find("gl_Position") != std::string::npos)
+            type_ = ShaderSource::ShaderTypeVertex;
+        else
+            Log::debug("Cannot infer shader type from contents. Leaving it Unknown.\n");
+    }
+
+    return type_;
+}
+
+/**
+ * Helper function that emits a precision statement.
+ *
+ * @param ss the stringstream to add the statement to
+ * @param val the precision value
+ * @param type_str the variable type to apply the precision value to
+ */
+void
+ShaderSource::emit_precision(std::stringstream& ss, ShaderSource::PrecisionValue val,
+                             const std::string& type_str)
+{
+    static const char *precision_map[] = {
+        "lowp", "mediump", "highp", NULL
+    };
+
+    if (val == ShaderSource::PrecisionValueHigh) {
+        if (type_ == ShaderSource::ShaderTypeFragment)
+            ss << "#ifdef GL_FRAGMENT_PRECISION_HIGH" << std::endl;
+
+        ss << "precision highp " << type_str << ";" << std::endl;
+
+        if (type_ == ShaderSource::ShaderTypeFragment) {
+            ss << "#else" << std::endl;
+            ss << "precision mediump " << type_str << ";" << std::endl;
+            ss << "#endif" << std::endl;
+        }
+    }
+    else if (val >= 0 && val < ShaderSource::PrecisionValueDefault) {
+        ss << "precision " << precision_map[val] << " ";
+        ss << type_str << ";" << std::endl;
+    }
+
+    /* There is no default precision in the fragment shader, so set it to mediump */
+    if (val == ShaderSource::PrecisionValueDefault
+        && type_str == "float" && type_ == ShaderSource::ShaderTypeFragment)
+    {
+        ss << "precision mediump float;" << std::endl;
+    }
+}
+
+/**
+ * Gets a string containing the complete shader source.
+ *
+ * Precision statements are applied at this point.
+ *
+ * @return the shader source
+ */
+std::string
+ShaderSource::str()
+{
+    /* Decide which precision values to use */
+    ShaderSource::Precision precision;
+
+    if (precision_has_been_set_)
+        precision = precision_;
+    else
+        precision = default_precision(type());
+
+    /* Create the precision statements */
+    std::stringstream ss;
+
+    emit_precision(ss, precision.int_precision, "int");
+    emit_precision(ss, precision.float_precision, "float");
+    emit_precision(ss, precision.sampler2d_precision, "sampler2D");
+    emit_precision(ss, precision.samplercube_precision, "samplerCube");
+
+    std::string precision_str(ss.str());
+    if (!precision_str.empty()) {
+        precision_str.insert(0, "#ifdef GL_ES\n");
+        precision_str.insert(precision_str.size(), "#endif\n");
+    }
+
+    return precision_str + source_.str();
+}
+
+/**
+ * Sets the precision that will be used for this shader.
+ *
+ * This overrides any default values set with ShaderSource::default_*_precision().
+ *
+ * @param precision the precision to set
+ */
+void
+ShaderSource::precision(const ShaderSource::Precision& precision)
+{
+    precision_ = precision;
+    precision_has_been_set_ = true;
+}
+
+/**
+ * Gets the precision that will be used for this shader.
+ *
+ * @return the precision
+ */
+const ShaderSource::Precision&
+ShaderSource::precision()
+{
+    return precision_;
+}
+
+/**
+ * Sets the default precision that will be used for a shaders type.
+ *
+ * If type is ShaderTypeUnknown the supplied precision is used for all
+ * shader types.
+ *
+ * This can be overriden per ShaderSource object by using ::precision().
+ *
+ * @param precision the default precision to set
+ * @param type the ShaderType to use the precision for
+ */
+void
+ShaderSource::default_precision(const ShaderSource::Precision& precision,
+                                ShaderSource::ShaderType type)
+{
+    if (type < 0 || type > ShaderSource::ShaderTypeUnknown)
+        type = ShaderSource::ShaderTypeUnknown;
+
+    if (type == ShaderSource::ShaderTypeUnknown) {
+        for (size_t i = 0; i < ShaderSource::ShaderTypeUnknown; i++)
+            default_precision_[i] = precision;
+    }
+    else {
+        default_precision_[type] = precision;
+    }
+}
+
+/**
+ * Gets the default precision that will be used for a shader type.
+ *
+ * It is valid to use a type of ShaderTypeUnknown. This will always
+ * return a Precision with default values.
+ *
+ * @param type the ShaderType to get the precision of
+ *
+ * @return the precision
+ */
+const ShaderSource::Precision&
+ShaderSource::default_precision(ShaderSource::ShaderType type)
+{
+    if (type < 0 || type > ShaderSource::ShaderTypeUnknown)
+        type = ShaderSource::ShaderTypeUnknown;
+
+    return default_precision_[type];
+}
+
+/****************************************
+ * ShaderSource::Precision constructors *
+ ****************************************/
+
+/**
+ * Creates a ShaderSource::Precision with default precision values.
+ */
+ShaderSource::Precision::Precision() :
+    int_precision(ShaderSource::PrecisionValueDefault),
+    float_precision(ShaderSource::PrecisionValueDefault),
+    sampler2d_precision(ShaderSource::PrecisionValueDefault),
+    samplercube_precision(ShaderSource::PrecisionValueDefault)
+{
+}
+
+/**
+ * Creates a ShaderSource::Precision using the supplied precision values.
+ */
+ShaderSource::Precision::Precision(ShaderSource::PrecisionValue int_p,
+                                   ShaderSource::PrecisionValue float_p,
+                                   ShaderSource::PrecisionValue sampler2d_p,
+                                   ShaderSource::PrecisionValue samplercube_p) :
+    int_precision(int_p), float_precision(float_p),
+    sampler2d_precision(sampler2d_p), samplercube_precision(samplercube_p)
+{
+}
+
+/**
+ * Creates a ShaderSource::Precision from a string representation of
+ * precision values.
+ *
+ * The string format is:
+ * "<int>,<float>,<sampler2d>,<samplercube>"
+ *
+ * Each precision value is one of "high", "medium", "low" or "default".
+ *
+ * @param precision_values the string representation of the precision values
+ */
+ShaderSource::Precision::Precision(const std::string& precision_values) :
+    int_precision(ShaderSource::PrecisionValueDefault),
+    float_precision(ShaderSource::PrecisionValueDefault),
+    sampler2d_precision(ShaderSource::PrecisionValueDefault),
+    samplercube_precision(ShaderSource::PrecisionValueDefault)
+{
+    std::vector<std::string> elems;
+
+    Util::split(precision_values, ',', elems);
+
+    for (size_t i = 0; i < elems.size() && i < 4; i++) {
+        const std::string& pstr(elems[i]);
+        ShaderSource::PrecisionValue pval;
+
+        if (pstr == "high")
+            pval = ShaderSource::PrecisionValueHigh;
+        else if (pstr == "medium")
+            pval = ShaderSource::PrecisionValueMedium;
+        else if (pstr == "low")
+            pval = ShaderSource::PrecisionValueLow;
+        else
+            pval = ShaderSource::PrecisionValueDefault;
+
+        switch(i) {
+            case 0: int_precision = pval; break;
+            case 1: float_precision = pval; break;
+            case 2: sampler2d_precision = pval; break;
+            case 3: samplercube_precision = pval; break;
+            default: break;
+        }
+    }
+}

=== added file 'src/shader-source.h'
--- src/shader-source.h	1970-01-01 00:00:00 +0000
+++ src/shader-source.h	2011-12-02 21:54:50 +0000
@@ -0,0 +1,113 @@ 
+/*
+ * Copyright © 2010-2011 Linaro Limited
+ *
+ * This file is part of the glmark2 OpenGL (ES) 2.0 benchmark.
+ *
+ * glmark2 is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later
+ * version.
+ *
+ * glmark2 is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * glmark2.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Authors:
+ *  Alexandros Frantzis (glmark2)
+ */
+
+#include <string>
+#include <sstream>
+#include <vector>
+#include "vec.h"
+#include "mat.h"
+
+/**
+ * Helper class for loading and manipulating shader sources.
+ */
+class ShaderSource
+{
+public:
+    enum ShaderType {
+        ShaderTypeVertex,
+        ShaderTypeFragment,
+        ShaderTypeUnknown
+    };
+
+    ShaderSource(ShaderType type = ShaderTypeUnknown) :
+        precision_has_been_set_(false), type_(type) {}
+    ShaderSource(const std::string &filename, ShaderType type = ShaderTypeUnknown) :
+        precision_has_been_set_(false), type_(type) { append_file(filename); }
+
+    void append(const std::string &str);
+    void append_file(const std::string &filename);
+
+    void replace(const std::string &remove, const std::string &insert);
+    void replace_with_file(const std::string &remove, const std::string &filename);
+
+    void add(const std::string &str, const std::string &function = "");
+
+    void add_const(const std::string &name, float f,
+                   const std::string &function = "");
+    void add_const(const std::string &name, std::vector<float> &f,
+                   const std::string &function = "");
+    void add_const(const std::string &name, const LibMatrix::vec2 &v,
+                   const std::string &function = "");
+    void add_const(const std::string &name, const LibMatrix::vec3 &v,
+                   const std::string &function = "");
+    void add_const(const std::string &name, const LibMatrix::vec4 &v,
+                   const std::string &function = "");
+    void add_const(const std::string &name, const LibMatrix::mat3 &m,
+                   const std::string &function = "");
+
+    void add_array(const std::string &name, std::vector<float> &array,
+                   const std::string &init_function,
+                   const std::string &decl_function = "");
+
+    ShaderType type();
+    std::string str();
+
+    enum PrecisionValue {
+        PrecisionValueLow,
+        PrecisionValueMedium,
+        PrecisionValueHigh,
+        PrecisionValueDefault,
+    };
+
+    struct Precision {
+        Precision();
+        Precision(PrecisionValue int_p, PrecisionValue float_p,
+                  PrecisionValue sampler2d_p, PrecisionValue samplercube_p);
+        Precision(const std::string& list);
+
+        PrecisionValue int_precision;
+        PrecisionValue float_precision;
+        PrecisionValue sampler2d_precision;
+        PrecisionValue samplercube_precision;
+    };
+
+    void precision(const Precision& precision);
+    const Precision& precision();
+
+    static void default_precision(const Precision& precision,
+                                  ShaderType type = ShaderTypeUnknown);
+    static const Precision& default_precision(ShaderType type);
+
+private:
+    void add_global(const std::string &str);
+    void add_local(const std::string &str, const std::string &function);
+    bool load_file(const std::string& filename, std::string& str);
+    void emit_precision(std::stringstream& ss, ShaderSource::PrecisionValue val,
+                        const std::string& type_str);
+
+    std::stringstream source_;
+    Precision precision_;
+    bool precision_has_been_set_;
+    ShaderType type_;
+
+    static std::vector<Precision> default_precision_;
+};

=== added file 'src/util.cc'
--- src/util.cc	1970-01-01 00:00:00 +0000
+++ src/util.cc	2011-12-02 21:54:50 +0000
@@ -0,0 +1,90 @@ 
+/*
+ * Copyright © 2011 Linaro Limited
+ *
+ * This file is part of glcompbench.
+ *
+ * glcompbench is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * glcompbench is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with glcompbench.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Authors:
+ *  Alexandros Frantzis <alexandros.frantzis@linaro.org>
+ *  Jesse Barker <jesse.barker@linaro.org>
+ */
+
+#include <sstream>
+#include <fstream>
+#include <sys/time.h>
+#include <dirent.h>
+
+#include "log.h"
+#include "util.h"
+
+/**
+ * Splits a string using a delimiter
+ *
+ * @param s the string to split
+ * @param delim the delimitir to use
+ * @param elems the string vector to populate
+ */
+void
+Util::split(const std::string &s, char delim, std::vector<std::string> &elems)
+{
+    std::stringstream ss(s);
+
+    std::string item;
+    while(std::getline(ss, item, delim))
+        elems.push_back(item);
+}
+
+uint64_t
+Util::get_timestamp_us()
+{
+    struct timeval tv;
+    gettimeofday(&tv, NULL);
+    uint64_t now = static_cast<uint64_t>(tv.tv_sec) * 1000000 +
+                   static_cast<double>(tv.tv_usec);
+    return now;
+}
+
+std::istream *
+Util::get_resource(const std::string &path)
+{
+    std::ifstream *ifs = new std::ifstream(path.c_str());
+
+    return static_cast<std::istream *>(ifs);
+}
+
+void
+Util::list_files(const std::string& dirName, std::vector<std::string>& fileVec)
+{
+    DIR* dir = opendir(dirName.c_str());
+    if (!dir)
+    {
+        Log::error("Failed to open models directory '%s'\n", dirName.c_str());
+        return;
+    }
+
+    struct dirent* entry = readdir(dir);
+    while (entry)
+    {
+        std::string pathname(dirName + "/");
+        pathname += std::string(entry->d_name);
+        // Skip '.' and '..'
+        if (entry->d_name[0] != '.')
+        {
+            fileVec.push_back(pathname);
+        }
+        entry = readdir(dir);
+    }
+    closedir(dir);
+}

=== added file 'src/util.h'
--- src/util.h	1970-01-01 00:00:00 +0000
+++ src/util.h	2011-12-02 21:54:50 +0000
@@ -0,0 +1,69 @@ 
+/*
+ * Copyright © 2011 Linaro Limited
+ *
+ * This file is part of glcompbench.
+ *
+ * glcompbench is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * glcompbench is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with glcompbench.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Authors:
+ *  Alexandros Frantzis <alexandros.frantzis@linaro.org>
+ *  Jesse Barker <jesse.barker@linaro.org>
+ */
+
+#ifndef UTIL_H_
+#define UTIL_H_
+
+#include <string>
+#include <vector>
+#include <istream>
+#include <sstream>
+#include <stdint.h>
+
+struct Util {
+    static void split(const std::string &s, char delim, std::vector<std::string> &elems);
+    static uint64_t get_timestamp_us();
+    static std::istream *get_resource(const std::string &path);
+    static void list_files(const std::string& dirName, std::vector<std::string>& fileVec);
+    template <class T> static void dispose_pointer_vector(std::vector<T*> &vec)
+    {
+        for (typename std::vector<T*>::const_iterator iter = vec.begin();
+             iter != vec.end();
+             iter++)
+        {
+            delete *iter;
+        }
+
+        vec.clear();
+    }
+    template<typename T>
+    static T
+    fromString(const std::string& asString)
+    {
+        std::stringstream ss(asString);
+        T retVal;
+        ss >> retVal;
+        return retVal;
+    }
+
+    template<typename T>
+    static std::string
+    toString(const T t)
+    {
+        std::stringstream ss;
+        ss << t;
+        return ss.str();
+    }
+};
+
+#endif /* UTIL_H */