diff mbox

[Branch,~glmark2-dev/glmark2/trunk] Rev 193: Merge of lp:~glmark2-dev/glmark2/libmatrix-util.

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

Commit Message

Jesse Barker Jan. 27, 2012, 10:15 p.m. UTC
Merge authors:
  Alexandros Frantzis (afrantzis)
  Jesse Barker (jesse-barker)
Related merge proposals:
  https://code.launchpad.net/~glmark2-dev/glmark2/libmatrix-util/+merge/90297
  proposed by: Jesse Barker (jesse-barker)
------------------------------------------------------------
revno: 193 [merge]
committer: Jesse Barker <jesse.barker@linaro.org>
branch nick: trunk
timestamp: Fri 2012-01-27 14:11:59 -0800
message:
  Merge of lp:~glmark2-dev/glmark2/libmatrix-util.
  
  This brings glmark2 up to date with the current libmatrix, including a couple of
  new features that resulted from the actual integration.  The primary result is
  that previously duplicated code is now consolidated in one common place
  (lp:libmatrix).
removed:
  src/libmatrix/matrix_inverse_test.cc
  src/log.cpp
  src/log.h
  src/shader-source.cpp
  src/shader-source.h
  src/util.cpp
  src/util.h
added:
  src/libmatrix/gl-if.h
  src/libmatrix/log.cc
  src/libmatrix/log.h
  src/libmatrix/shader-source.cc
  src/libmatrix/shader-source.h
  src/libmatrix/test/
  src/libmatrix/test/basic-global-const.vert
  src/libmatrix/test/basic.frag
  src/libmatrix/test/basic.vert
  src/libmatrix/test/const_vec_test.cc
  src/libmatrix/test/const_vec_test.h
  src/libmatrix/test/inverse_test.cc
  src/libmatrix/test/inverse_test.h
  src/libmatrix/test/libmatrix_test.cc
  src/libmatrix/test/libmatrix_test.h
  src/libmatrix/test/options.cc
  src/libmatrix/test/shader_source_test.cc
  src/libmatrix/test/shader_source_test.h
  src/libmatrix/test/transpose_test.cc
  src/libmatrix/test/transpose_test.h
  src/libmatrix/util.cc
  src/libmatrix/util.h
modified:
  android/jni/Android.mk
  android/jni/Android.ndk.mk
  src/android.cpp
  src/libmatrix/Makefile
  src/libmatrix/mat.h
  src/libmatrix/program.cc
  src/libmatrix/program.h
  src/libmatrix/vec.h
  src/main.cpp
  src/options.cpp
  src/scene-effect-2d.cpp
  src/wscript_build


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

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

Patch

=== modified file 'android/jni/Android.mk'
--- android/jni/Android.mk	2012-01-19 18:13:38 +0000
+++ android/jni/Android.mk	2012-01-27 12:00:56 +0000
@@ -6,8 +6,7 @@ 
 LOCAL_MODULE := libglmark2-matrix
 LOCAL_CFLAGS := -DUSE_GLESv2
 LOCAL_C_INCLUDES := $(LOCAL_PATH)/src
-LOCAL_SRC_FILES := src/libmatrix/mat.cc \
-                   src/libmatrix/program.cc
+LOCAL_SRC_FILES := $(subst $(LOCAL_PATH)/,,$(wildcard $(LOCAL_PATH)/src/libmatrix/*.cc))
 LOCAL_SHARED_LIBRARIES := libdl libstlport
 
 include external/stlport/libstlport.mk

=== modified file 'android/jni/Android.ndk.mk'
--- android/jni/Android.ndk.mk	2012-01-19 18:13:38 +0000
+++ android/jni/Android.ndk.mk	2012-01-27 12:00:56 +0000
@@ -6,8 +6,7 @@ 
 LOCAL_MODULE := libglmark2-matrix
 LOCAL_CFLAGS := -DUSE_GLESv2
 LOCAL_C_INCLUDES := $(LOCAL_PATH)/src
-LOCAL_SRC_FILES := src/libmatrix/mat.cc \
-                   src/libmatrix/program.cc
+LOCAL_SRC_FILES := $(subst $(LOCAL_PATH)/,,$(wildcard $(LOCAL_PATH)/src/libmatrix/*.cc))
 
 include $(BUILD_STATIC_LIBRARY)
 

=== modified file 'src/android.cpp'
--- src/android.cpp	2012-01-13 14:11:42 +0000
+++ src/android.cpp	2012-01-27 22:01:59 +0000
@@ -51,6 +51,7 @@ 
 Java_org_linaro_glmark2_Glmark2Renderer_nativeInit(JNIEnv* env, jclass clazz,
                                                    jobject asset_manager)
 {
+    Log::init("glmark2", false);
     Util::android_set_asset_manager(AAssetManager_fromJava(env, asset_manager));
 
     g_canvas = new CanvasAndroid(100, 100);

=== modified file 'src/libmatrix/Makefile'
--- src/libmatrix/Makefile	2011-09-19 15:30:13 +0000
+++ src/libmatrix/Makefile	2012-01-26 17:00:43 +0000
@@ -1,6 +1,6 @@ 
 CXXFLAGS = -Wall -Werror -pedantic -O3
 LIBMATRIX = libmatrix.a
-LIBSRCS = mat.cc program.cc
+LIBSRCS = mat.cc program.cc log.cc util.cc shader-source.cc
 LIBOBJS = $(LIBSRCS:.cc=.o)
 TESTDIR = test
 LIBMATRIX_TESTS = $(TESTDIR)/libmatrix_test
@@ -8,6 +8,7 @@ 
            $(TESTDIR)/const_vec_test.cc \
            $(TESTDIR)/inverse_test.cc \
            $(TESTDIR)/transpose_test.cc \
+           $(TESTDIR)/shader_source_test.cc \
            $(TESTDIR)/libmatrix_test.cc
 TESTOBJS = $(TESTSRCS:.cc=.o)
 
@@ -18,7 +19,10 @@ 
 # Main library targets here.
 mat.o : mat.cc mat.h vec.h
 program.o: program.cc program.h mat.h vec.h
-libmatrix.a : mat.o mat.h stack.h vec.h program.o program.h
+log.o: log.cc log.h
+util.o: util.cc util.h
+shader-source.o: shader-source.cc shader-source.h mat.h vec.h
+libmatrix.a : mat.o stack.h program.o log.o util.o shader-source.o
 	$(AR) -r $@  $(LIBOBJS)
 
 # Tests and execution targets here.
@@ -27,6 +31,7 @@ 
 $(TESTDIR)/const_vec_test.o: $(TESTDIR)/const_vec_test.cc $(TESTDIR)/const_vec_test.h $(TESTDIR)/libmatrix_test.h vec.h
 $(TESTDIR)/inverse_test.o: $(TESTDIR)/inverse_test.cc $(TESTDIR)/inverse_test.h $(TESTDIR)/libmatrix_test.h mat.h
 $(TESTDIR)/transpose_test.o: $(TESTDIR)/transpose_test.cc $(TESTDIR)/transpose_test.h $(TESTDIR)/libmatrix_test.h mat.h
+$(TESTDIR)/shader_source_test.o: $(TESTDIR)/shader_source_test.cc $(TESTDIR)/shader_source_test.h $(TESTDIR)/libmatrix_test.h shader-source.h
 $(TESTDIR)/libmatrix_test: $(TESTOBJS) libmatrix.a
 	$(CXX) -o $@ $^
 run_tests: $(LIBMATRIX_TESTS)

=== added file 'src/libmatrix/gl-if.h'
--- src/libmatrix/gl-if.h	1970-01-01 00:00:00 +0000
+++ src/libmatrix/gl-if.h	2012-01-26 17:00:43 +0000
@@ -0,0 +1,18 @@ 
+//
+// Copyright (c) 2012 Linaro Limited
+//
+// All rights reserved. This program and the accompanying materials
+// are made available under the terms of the MIT License which accompanies
+// this distribution, and is available at
+// http://www.opensource.org/licenses/mit-license.php
+//
+// Contributors:
+//     Jesse Barker - original implementation.
+//
+#ifndef GL_IF_H_
+#define GL_IF_H_
+// Inclusion abstraction to provide project specific interface headers for
+// whatever flavor of OpenGL(|ES) is appropriate.  For core libmatrix, this
+// is GLEW.
+#include "gl-headers.h"
+#endif // GL_IF_H_

=== added file 'src/libmatrix/log.cc'
--- src/libmatrix/log.cc	1970-01-01 00:00:00 +0000
+++ src/libmatrix/log.cc	2012-01-27 22:01:59 +0000
@@ -0,0 +1,178 @@ 
+//
+// Copyright (c) 2010-2012 Linaro Limited
+//
+// All rights reserved. This program and the accompanying materials
+// are made available under the terms of the MIT License which accompanies
+// this distribution, and is available at
+// http://www.opensource.org/licenses/mit-license.php
+//
+// Contributors:
+//     Alexandros Frantzis <alexandros.frantzis@linaro.org>
+//     Jesse Barker <jesse.barker@linaro.org>
+//
+#include <cstdio>
+#include <cstdarg>
+#include <string>
+#include <sstream>
+#include <iostream>
+#include "log.h"
+
+#ifdef ANDROID
+#include <android/log.h>
+#endif
+
+using std::string;
+
+const string Log::continuation_prefix("\x10");
+string Log::appname_;
+bool Log::do_debug_(false);
+
+#ifndef ANDROID
+
+static const string terminal_color_normal("\033[0m");
+static const string terminal_color_red("\033[1;31m");
+static const string terminal_color_cyan("\033[36m");
+static const string terminal_color_yellow("\033[33m");
+static const string empty;
+
+static void
+print_prefixed_message(std::ostream& stream, const string& color, const string& prefix,
+                       const string& fmt, va_list ap)
+{
+    va_list aq;
+
+    /* Estimate message size */
+    va_copy(aq, ap);
+    int msg_size = vsnprintf(NULL, 0, fmt.c_str(), aq);
+    va_end(aq);
+
+    /* Create the buffer to hold the message */
+    char *buf = new char[msg_size + 1];
+
+    /* Store the message in the buffer */
+    va_copy(aq, ap);
+    vsnprintf(buf, msg_size + 1, fmt.c_str(), aq);
+    va_end(aq);
+
+    /*
+     * Print the message lines prefixed with the supplied prefix.
+     * If the target stream is a terminal make the prefix colored.
+     */
+    string linePrefix;
+    if (!prefix.empty())
+    {
+        static const string colon(": ");
+        string start_color;
+        string end_color;
+        if (!color.empty())
+        {
+            start_color = color;
+            end_color = terminal_color_normal;
+        }
+        linePrefix = start_color + prefix + end_color + colon;
+    }
+
+    std::string line;
+    std::stringstream ss(buf);
+
+    while(std::getline(ss, line)) {
+        /*
+         * If this line is a continuation of a previous log message
+         * just print the line plainly.
+         */
+        if (line[0] == Log::continuation_prefix[0]) {
+            stream << line.c_str() + 1;
+        }
+        else {
+            /* Normal line, emit the prefix. */
+            stream << linePrefix << line;
+        }
+
+        /* Only emit a newline if the original message has it. */
+        if (!(ss.rdstate() & std::stringstream::eofbit))
+            stream << std::endl;
+    }
+
+    delete[] buf;
+}
+
+void
+Log::info(const char *fmt, ...)
+{
+    static const string infoprefix("Info");
+    static const string& infocolor(isatty(fileno(stdout)) ? terminal_color_cyan : empty);
+    va_list ap;
+    va_start(ap, fmt);
+    if (do_debug_)
+        print_prefixed_message(std::cout, infocolor, infoprefix, fmt, ap);
+    else
+        print_prefixed_message(std::cout, empty, empty, fmt, ap);
+    va_end(ap);
+}
+
+void
+Log::debug(const char *fmt, ...)
+{
+    static const string dbgprefix("Debug");
+    static const string& dbgcolor(isatty(fileno(stdout)) ? terminal_color_yellow : empty);
+    if (!do_debug_)
+        return;
+    va_list ap;
+    va_start(ap, fmt);
+    print_prefixed_message(std::cout, dbgcolor, dbgprefix, fmt, ap);
+    va_end(ap);
+}
+
+void
+Log::error(const char *fmt, ...)
+{
+    static const string errprefix("Error");
+    static const string& errcolor(isatty(fileno(stderr)) ? terminal_color_red : empty);
+    va_list ap;
+    va_start(ap, fmt);
+    print_prefixed_message(std::cerr, errcolor, errprefix, fmt, ap);
+    va_end(ap);
+}
+
+void
+Log::flush()
+{
+    std::cout.flush();
+    std::cerr.flush();
+}
+#else
+void
+Log::info(const char *fmt, ...)
+{
+    va_list ap;
+    va_start(ap, fmt);
+    __android_log_vprint(ANDROID_LOG_INFO, appname_.c_str(), fmt, ap);
+    va_end(ap);
+}
+
+void
+Log::debug(const char *fmt, ...)
+{
+    if (!do_debug_)
+        return;
+    va_list ap;
+    va_start(ap, fmt);
+    __android_log_vprint(ANDROID_LOG_DEBUG, appname_.c_str(), fmt, ap);
+    va_end(ap);
+}
+
+void
+Log::error(const char *fmt, ...)
+{
+    va_list ap;
+    va_start(ap, fmt);
+    __android_log_vprint(ANDROID_LOG_ERROR, appname_.c_str(), fmt, ap);
+    va_end(ap);
+}
+
+void
+Log::flush()
+{
+}
+
+#endif

=== added file 'src/libmatrix/log.h'
--- src/libmatrix/log.h	1970-01-01 00:00:00 +0000
+++ src/libmatrix/log.h	2012-01-27 22:01:59 +0000
@@ -0,0 +1,46 @@ 
+//
+// Copyright (c) 2010-2012 Linaro Limited
+//
+// All rights reserved. This program and the accompanying materials
+// are made available under the terms of the MIT License which accompanies
+// this distribution, and is available at
+// http://www.opensource.org/licenses/mit-license.php
+//
+// Contributors:
+//     Alexandros Frantzis <alexandros.frantzis@linaro.org>
+//     Jesse Barker <jesse.barker@linaro.org>
+//
+#ifndef LOG_H_
+#define LOG_H_
+
+#include <string>
+
+class Log
+{
+public:
+    static void init(const std::string& appname, bool do_debug = false)
+    {
+        appname_ = appname;
+        do_debug_ = do_debug;
+    }
+    // Emit an informational message
+    static void info(const char *fmt, ...);
+    // Emit a debugging message
+    static void debug(const char *fmt, ...);
+    // Emit an error message
+    static void error(const char *fmt, ...);
+    // Explicit flush of the log buffer
+    static void flush();
+    // A prefix constant that informs the logging infrastructure that the log
+    // message is a continuation of a previous log message to be put on the
+    // same line.
+    static const std::string continuation_prefix;
+private:
+    // A constant for identifying the log messages as originating from a
+    // particular application.
+    static std::string appname_;
+    // Indicates whether debug level messages should generate any output
+    static bool do_debug_;
+};
+
+#endif /* LOG_H_ */

=== modified file 'src/libmatrix/mat.h'
--- src/libmatrix/mat.h	2011-09-19 15:30:13 +0000
+++ src/libmatrix/mat.h	2012-01-26 17:00:43 +0000
@@ -15,6 +15,11 @@ 
 #include <iostream>
 #include <iomanip>
 #include "vec.h"
+#ifndef USE_EXCEPTIONS
+// If we're not throwing exceptions, we'll need the logger to make sure the
+// caller is informed of errors.
+#include "log.h"
+#endif // USE_EXCEPTIONS
 
 namespace LibMatrix
 {
@@ -46,6 +51,11 @@ 
 // However, the internal data representation is column-major, so when using 
 // the raw data access member to treat the data as a singly-dimensioned array,
 // it does not have to be transposed.
+//
+// A template class for creating, managing and operating on a 2x2 matrix
+// of any type you like (intended for built-in types, but as long as it 
+// supports the basic arithmetic and assignment operators, any type should
+// work).
 template<typename T>
 class tmat2
 {
@@ -70,6 +80,7 @@ 
     }
     ~tmat2() {}
 
+    // Reset this to the identity matrix.
     void setIdentity()
     {
         m_[0] = 1;
@@ -78,6 +89,7 @@ 
         m_[3] = 1;
     }
 
+    // Transpose this.  Return a reference to this.
     tmat2& transpose()
     {
         T tmp_val = m_[1];
@@ -86,22 +98,30 @@ 
         return *this;
     }
 
+    // Compute the determinant of this and return it.
     T determinant()
     {
         return (m_[0] * m_[3]) - (m_[2] * m_[1]);
     }
 
+    // Invert this.  Return a reference to this.
+    //
+    // NOTE: If this is non-invertible, we will
+    //       throw to avoid undefined behavior.
     tmat2& inverse()
 #ifdef USE_EXCEPTIONS
         throw(std::runtime_error)
-#endif
+#endif // USE_EXCEPTIONS
     {
         T d(determinant());
         if (d == static_cast<T>(0))
         {
 #ifdef USE_EXCEPTIONS
             throw std::runtime_error("Matrix is noninvertible!!!!");
-#endif
+#else // !USE_EXCEPTIONS
+            Log::error("Matrix is noninvertible!!!!\n");
+            return *this;
+#endif // USE_EXCEPTIONS
         }
         T c0r0(m_[3] / d);
         T c0r1(-m_[1] / d);
@@ -114,6 +134,8 @@ 
         return *this;
     }
 
+    // Print the elements of the matrix to standard out.
+    // Really only useful for debug and test.
     void print() const
     {
         static const int precision(6);
@@ -131,8 +153,12 @@ 
         std::cout << " |" << std::endl;
     }
 
+    // Allow raw data access for API calls and the like.
+    // For example, it is valid to pass a tmat2<float> into a call to
+    // the OpenGL command "glUniformMatrix2fv()".
     operator const T*() const { return &m_[0];}
 
+    // Test if 'rhs' is equal to this.
     bool operator==(const tmat2& rhs) const
     {
         return m_[0] == rhs.m_[0] &&
@@ -141,11 +167,13 @@ 
                m_[3] == rhs.m_[3];
     }
 
+    // Test if 'rhs' is not equal to this.
     bool operator!=(const tmat2& rhs) const
     {
         return !(*this == rhs);
     }
 
+    // A direct assignment of 'rhs' to this.  Return a reference to this.
     tmat2& operator=(const tmat2& rhs)
     {
         if (this != &rhs)
@@ -158,6 +186,7 @@ 
         return *this;
     }
 
+    // Add another matrix to this.  Return a reference to this.
     tmat2& operator+=(const tmat2& rhs)
     {
         m_[0] += rhs.m_[0];
@@ -167,11 +196,13 @@ 
         return *this;
     }
 
+    // Add another matrix to a copy of this.  Return the copy.
     const tmat2 operator+(const tmat2& rhs)
     {
         return tmat2(*this) += rhs;
     }
 
+    // Subtract another matrix from this.  Return a reference to this.
     tmat2& operator-=(const tmat2& rhs)
     {
         m_[0] -= rhs.m_[0];
@@ -181,11 +212,13 @@ 
         return *this;
     }
 
+    // Subtract another matrix from a copy of this.  Return the copy.
     const tmat2 operator-(const tmat2& rhs)
     {
         return tmat2(*this) += rhs;
     }
 
+    // Multiply this by another matrix.  Return a reference to this.
     tmat2& operator*=(const tmat2& rhs)
     {
         T c0r0((m_[0] * rhs.m_[0]) + (m_[2] * rhs.m_[1]));
@@ -199,11 +232,13 @@ 
         return *this;
     }
 
+    // Multiply a copy of this by another matrix.  Return the copy.
     const tmat2 operator*(const tmat2& rhs)
     {
         return tmat2(*this) *= rhs;
     }
 
+    // Multiply this by a scalar.  Return a reference to this.
     tmat2& operator*=(const T& rhs)
     {
         m_[0] *= rhs;
@@ -213,11 +248,13 @@ 
         return *this;
     }
 
+    // Multiply a copy of this by a scalar.  Return the copy.
     const tmat2 operator*(const T& rhs)
     {
         return tmat2(*this) *= rhs;
     }
 
+    // Divide this by a scalar.  Return a reference to this.
     tmat2& operator/=(const T& rhs)
     {
         m_[0] /= rhs;
@@ -227,11 +264,15 @@ 
         return *this;
     }
 
+    // Divide a copy of this by a scalar.  Return the copy.
     const tmat2 operator/(const T& rhs)
     {
         return tmat2(*this) /= rhs;
     }
 
+    // Use an instance of the ArrayProxy class to support double-indexed
+    // references to a matrix (i.e., m[1][1]).  See comments above the
+    // ArrayProxy definition for more details.
     ArrayProxy<T, 2> operator[](int index)
     {
         return ArrayProxy<T, 2>(&m_[index]);
@@ -245,12 +286,16 @@ 
     T m_[4];
 };
 
+// Multiply a scalar and a matrix just like the member operator, but allow
+// the scalar to be the left-hand operand.
 template<typename T>
 const tmat2<T> operator*(const T& lhs, const tmat2<T>& rhs)
 {
     return tmat2<T>(rhs) * lhs;
 }
 
+// Multiply a copy of a vector and a matrix (matrix is right-hand operand).
+// Return the copy.
 template<typename T>
 const tvec2<T> operator*(const tvec2<T>& lhs, const tmat2<T>& rhs)
 {
@@ -259,6 +304,8 @@ 
     return tvec2<T>(x,y);
 }
 
+// Multiply a copy of a vector and a matrix (matrix is left-hand operand).
+// Return the copy.
 template<typename T>
 const tvec2<T> operator*(const tmat2<T>& lhs, const tvec2<T>& rhs)
 {
@@ -267,6 +314,7 @@ 
     return tvec2<T>(x, y);
 }
 
+// Compute the outer product of two vectors.  Return the resultant matrix.
 template<typename T>
 const tmat2<T> outer(const tvec2<T>& a, const tvec2<T>& b)
 {
@@ -278,6 +326,10 @@ 
     return product;
 }
 
+// A template class for creating, managing and operating on a 3x3 matrix
+// of any type you like (intended for built-in types, but as long as it 
+// supports the basic arithmetic and assignment operators, any type should
+// work).
 template<typename T>
 class tmat3
 {
@@ -314,6 +366,7 @@ 
     }
     ~tmat3() {}
 
+    // Reset this to the identity matrix.
     void setIdentity()
     {
         m_[0] = 1;
@@ -327,6 +380,7 @@ 
         m_[8] = 1;
     }
 
+    // Transpose this.  Return a reference to this.
     tmat3& transpose()
     {
         T tmp_val = m_[1];
@@ -341,6 +395,7 @@ 
         return *this;
     }
 
+    // Compute the determinant of this and return it.
     T determinant()
     {
         tmat2<T> minor0(m_[4], m_[5], m_[7], m_[8]);
@@ -351,17 +406,24 @@ 
                (m_[6] * minor6.determinant());
     }
 
+    // Invert this.  Return a reference to this.
+    //
+    // NOTE: If this is non-invertible, we will
+    //       throw to avoid undefined behavior.
     tmat3& inverse()
 #ifdef USE_EXCEPTIONS
         throw(std::runtime_error)
-#endif
+#endif // USE_EXCEPTIONS
     {
         T d(determinant());
         if (d == static_cast<T>(0))
         {
 #ifdef USE_EXCEPTIONS
             throw std::runtime_error("Matrix is noninvertible!!!!");
-#endif
+#else // !USE_EXCEPTIONS
+            Log::error("Matrix is noninvertible!!!!\n");
+            return *this;
+#endif // USE_EXCEPTIONS
         }
         tmat2<T> minor0(m_[4], m_[5], m_[7], m_[8]);
         tmat2<T> minor1(m_[7], m_[8], m_[1], m_[2]);
@@ -384,6 +446,8 @@ 
         return *this;       
     }
 
+    // Print the elements of the matrix to standard out.
+    // Really only useful for debug and test.
     void print() const
     {
         static const int precision(6);
@@ -413,8 +477,12 @@ 
         std::cout << " |" << std::endl;
     }
 
+    // Allow raw data access for API calls and the like.
+    // For example, it is valid to pass a tmat3<float> into a call to
+    // the OpenGL command "glUniformMatrix3fv()".
     operator const T*() const { return &m_[0];}
 
+    // Test if 'rhs' is equal to this.
     bool operator==(const tmat3& rhs) const
     {
         return m_[0] == rhs.m_[0] &&
@@ -428,11 +496,13 @@ 
                m_[8] == rhs.m_[8];
     }
 
+    // Test if 'rhs' is not equal to this.
     bool operator!=(const tmat3& rhs) const
     {
         return !(*this == rhs);
     }
 
+    // A direct assignment of 'rhs' to this.  Return a reference to this.
     tmat3& operator=(const tmat3& rhs)
     {
         if (this != &rhs)
@@ -450,6 +520,7 @@ 
         return *this;
     }
 
+    // Add another matrix to this.  Return a reference to this.
     tmat3& operator+=(const tmat3& rhs)
     {
         m_[0] += rhs.m_[0];
@@ -464,11 +535,13 @@ 
         return *this;
     }
 
+    // Add another matrix to a copy of this.  Return the copy.
     const tmat3 operator+(const tmat3& rhs)
     {
         return tmat3(*this) += rhs;
     }
 
+    // Subtract another matrix from this.  Return a reference to this.
     tmat3& operator-=(const tmat3& rhs)
     {
         m_[0] -= rhs.m_[0];
@@ -483,11 +556,13 @@ 
         return *this;
     }
 
+    // Subtract another matrix from a copy of this.  Return the copy.
     const tmat3 operator-(const tmat3& rhs)
     {
         return tmat3(*this) -= rhs;
     }
 
+    // Multiply this by another matrix.  Return a reference to this.
     tmat3& operator*=(const tmat3& rhs)
     {
         T c0r0((m_[0] * rhs.m_[0]) + (m_[3] * rhs.m_[1]) + (m_[6] * rhs.m_[2]));
@@ -511,11 +586,13 @@ 
         return *this;
     }
 
+    // Multiply a copy of this by another matrix.  Return the copy.
     const tmat3 operator*(const tmat3& rhs)
     {
         return tmat3(*this) *= rhs;
     }
 
+    // Multiply this by a scalar.  Return a reference to this.
     tmat3& operator*=(const T& rhs)
     {
         m_[0] *= rhs;
@@ -530,11 +607,13 @@ 
         return *this;
     }
 
+    // Multiply a copy of this by a scalar.  Return the copy.
     const tmat3 operator*(const T& rhs)
     {
         return tmat3(*this) *= rhs;
     }
 
+    // Divide this by a scalar.  Return a reference to this.
     tmat3& operator/=(const T& rhs)
     {
         m_[0] /= rhs;
@@ -549,11 +628,15 @@ 
         return *this;
     }
 
+    // Divide a copy of this by a scalar.  Return the copy.
     const tmat3 operator/(const T& rhs)
     {
         return tmat3(*this) /= rhs;
     }
 
+    // Use an instance of the ArrayProxy class to support double-indexed
+    // references to a matrix (i.e., m[1][1]).  See comments above the
+    // ArrayProxy definition for more details.
     ArrayProxy<T, 3> operator[](int index)
     {
         return ArrayProxy<T, 3>(&m_[index]);
@@ -567,12 +650,16 @@ 
     T m_[9];
 };
 
+// Multiply a scalar and a matrix just like the member operator, but allow
+// the scalar to be the left-hand operand.
 template<typename T>
 const tmat3<T> operator*(const T& lhs, const tmat3<T>& rhs)
 {
     return tmat3<T>(rhs) * lhs;
 }
 
+// Multiply a copy of a vector and a matrix (matrix is right-hand operand).
+// Return the copy.
 template<typename T>
 const tvec3<T> operator*(const tvec3<T>& lhs, const tmat3<T>& rhs)
 {
@@ -582,6 +669,8 @@ 
     return tvec3<T>(x, y, z);
 }
 
+// Multiply a copy of a vector and a matrix (matrix is left-hand operand).
+// Return the copy.
 template<typename T>
 const tvec3<T> operator*(const tmat3<T>& lhs, const tvec3<T>& rhs)
 {
@@ -591,6 +680,7 @@ 
     return tvec3<T>(x, y, z);
 }
 
+// Compute the outer product of two vectors.  Return the resultant matrix.
 template<typename T>
 const tmat3<T> outer(const tvec3<T>& a, const tvec3<T>& b)
 {
@@ -607,6 +697,10 @@ 
     return product;
 }
 
+// A template class for creating, managing and operating on a 4x4 matrix
+// of any type you like (intended for built-in types, but as long as it 
+// supports the basic arithmetic and assignment operators, any type should
+// work).
 template<typename T>
 class tmat4
 {
@@ -636,6 +730,7 @@ 
     }
     ~tmat4() {}
 
+    // Reset this to the identity matrix.
     void setIdentity()
     {
         m_[0] = 1;
@@ -656,6 +751,7 @@ 
         m_[15] = 1;
     }
 
+    // Transpose this.  Return a reference to this.
     tmat4& transpose()
     {
         T tmp_val = m_[1];
@@ -679,6 +775,7 @@ 
         return *this;
     }
 
+    // Compute the determinant of this and return it.
     T determinant()
     {
         tmat3<T> minor0(m_[5], m_[6], m_[7], m_[9], m_[10], m_[11], m_[13], m_[14], m_[15]);
@@ -691,17 +788,24 @@ 
                (m_[12] * minor12.determinant());
     }
 
+    // Invert this.  Return a reference to this.
+    //
+    // NOTE: If this is non-invertible, we will
+    //       throw to avoid undefined behavior.
     tmat4& inverse()
 #ifdef USE_EXCEPTIONS
         throw(std::runtime_error)
-#endif
+#endif // USE_EXCEPTIONS
     {
         T d(determinant());
         if (d == static_cast<T>(0))
         {
 #ifdef USE_EXCEPTIONS
             throw std::runtime_error("Matrix is noninvertible!!!!");
-#endif
+#else // !USE_EXCEPTIONS
+            Log::error("Matrix is noninvertible!!!!\n");
+            return *this;
+#endif // USE_EXCEPTIONS
         }
         tmat3<T> minor0(m_[5], m_[6], m_[7], m_[9], m_[10], m_[11], m_[13], m_[14], m_[15]);
         tmat3<T> minor1(m_[1], m_[2], m_[3], m_[13], m_[14], m_[15], m_[9], m_[10], m_[11]);
@@ -741,6 +845,8 @@ 
         return *this;
     }
 
+    // Print the elements of the matrix to standard out.
+    // Really only useful for debug and test.
     void print() const
     {
         static const int precision(6);
@@ -786,8 +892,12 @@ 
         std::cout << " |" << std::endl;
     }
 
+    // Allow raw data access for API calls and the like.
+    // For example, it is valid to pass a tmat4<float> into a call to
+    // the OpenGL command "glUniformMatrix4fv()".
     operator const T*() const { return &m_[0];}
 
+    // Test if 'rhs' is equal to this.
     bool operator==(const tmat4& rhs) const
     {
         return m_[0] == rhs.m_[0] &&
@@ -808,11 +918,13 @@ 
                m_[15] == rhs.m_[15];
     }
 
+    // Test if 'rhs' is not equal to this.
     bool operator!=(const tmat4& rhs) const
     {
         return !(*this == rhs);
     }
 
+    // A direct assignment of 'rhs' to this.  Return a reference to this.
     tmat4& operator=(const tmat4& rhs)
     {
         if (this != &rhs)
@@ -837,6 +949,7 @@ 
         return *this;
     }
 
+    // Add another matrix to this.  Return a reference to this.
     tmat4& operator+=(const tmat4& rhs)
     {
         m_[0] += rhs.m_[0];
@@ -858,11 +971,13 @@ 
         return *this;
     }
 
+    // Add another matrix to a copy of this.  Return the copy.
     const tmat4 operator+(const tmat4& rhs)
     {
         return tmat4(*this) += rhs;
     }
 
+    // Subtract another matrix from this.  Return a reference to this.
     tmat4& operator-=(const tmat4& rhs)
     {
         m_[0] -= rhs.m_[0];
@@ -884,11 +999,13 @@ 
         return *this;
     }
 
+    // Subtract another matrix from a copy of this.  Return the copy.
     const tmat4 operator-(const tmat4& rhs)
     {
         return tmat4(*this) -= rhs;
     }
 
+    // Multiply this by another matrix.  Return a reference to this.
     tmat4& operator*=(const tmat4& rhs)
     {
         T c0r0((m_[0] * rhs.m_[0]) + (m_[4] * rhs.m_[1]) + (m_[8] * rhs.m_[2]) + (m_[12] * rhs.m_[3]));
@@ -926,11 +1043,13 @@ 
         return *this;
     }
 
+    // Multiply a copy of this by another matrix.  Return the copy.
     const tmat4 operator*(const tmat4& rhs)
     {
         return tmat4(*this) *= rhs;
     }
 
+    // Multiply this by a scalar.  Return a reference to this.
     tmat4& operator*=(const T& rhs)
     {
         m_[0] *= rhs;
@@ -952,11 +1071,13 @@ 
         return *this;
     }
 
+    // Multiply a copy of this by a scalar.  Return the copy.
     const tmat4 operator*(const T& rhs)
     {
         return tmat4(*this) *= rhs;
     }
 
+    // Divide this by a scalar.  Return a reference to this.
     tmat4& operator/=(const T& rhs)
     {
         m_[0] /= rhs;
@@ -978,11 +1099,15 @@ 
         return *this;
     }
 
+    // Divide a copy of this by a scalar.  Return the copy.
     const tmat4 operator/(const T& rhs)
     {
         return tmat4(*this) /= rhs;
     }
 
+    // Use an instance of the ArrayProxy class to support double-indexed
+    // references to a matrix (i.e., m[1][1]).  See comments above the
+    // ArrayProxy definition for more details.
     ArrayProxy<T, 4> operator[](int index)
     {
         return ArrayProxy<T, 4>(&m_[index]);
@@ -996,12 +1121,16 @@ 
     T m_[16];
 };
 
+// Multiply a scalar and a matrix just like the member operator, but allow
+// the scalar to be the left-hand operand.
 template<typename T>
 const tmat4<T> operator*(const T& lhs, const tmat4<T>& rhs)
 {
     return tmat4<T>(rhs) * lhs;
 }
 
+// Multiply a copy of a vector and a matrix (matrix is right-hand operand).
+// Return the copy.
 template<typename T>
 const tvec4<T> operator*(const tvec4<T>& lhs, const tmat4<T>& rhs)
 {
@@ -1012,6 +1141,8 @@ 
     return tvec4<T>(x, y, z, w);
 }
 
+// Multiply a copy of a vector and a matrix (matrix is left-hand operand).
+// Return the copy.
 template<typename T>
 const tvec4<T> operator*(const tmat4<T>& lhs, const tvec4<T>& rhs)
 {
@@ -1022,6 +1153,7 @@ 
     return tvec4<T>(x, y, z, w);
 }
 
+// Compute the outer product of two vectors.  Return the resultant matrix.
 template<typename T>
 const tmat4<T> outer(const tvec4<T>& a, const tvec4<T>& b)
 {

=== removed file 'src/libmatrix/matrix_inverse_test.cc'
--- src/libmatrix/matrix_inverse_test.cc	2011-06-17 07:54:50 +0000
+++ src/libmatrix/matrix_inverse_test.cc	1970-01-01 00:00:00 +0000
@@ -1,152 +0,0 @@ 
-//
-// Copyright (c) 2010 Linaro Limited
-//
-// All rights reserved. This program and the accompanying materials
-// are made available under the terms of the MIT License which accompanies
-// this distribution, and is available at
-// http://www.opensource.org/licenses/mit-license.php
-//
-// Contributors:
-//     Jesse Barker - original implementation.
-//
-#include <iostream>
-#include "mat.h"
-
-using LibMatrix::mat4;
-using LibMatrix::mat3;
-using LibMatrix::mat2;
-using std::cerr;
-using std::cout;
-using std::endl;
-
-bool mat2OK()
-{
-    mat2 m;
-    cout << "Starting with mat2 (should be identity): " << endl << endl;
-    m.print();
-
-    m[0][1] = -2.5;
-    
-    cout << endl << "Matrix should now have (0, 1) == -2.500000" << endl << endl;
-    m.print();
-    
-    mat2 mi(m);
-
-    cout << endl << "Copy of previous matrix (should have (0, 1) == -2.500000)" << endl << endl;
-    mi.print();
-
-    mi.inverse();
-
-    cout << endl << "Inverse of copy: " << endl << endl;
-    mi.print();
-
-    mat2 i = m * mi;
-
-    cout << endl << "Product of original and inverse (should be identity): " << endl << endl;
-    i.print();
-
-    mat2 ident;
-    if (i != ident)
-    {
-        return false;
-    }
-
-    return true;
-}
-
-bool mat3OK()
-{
-    mat3 m;
-    cout << "Starting with mat3 (should be identity): " << endl << endl;
-    m.print();
-
-    m[1][2] = -2.5;
-    
-    cout << endl << "Matrix should now have (1, 2) == -2.500000" << endl << endl;
-    m.print();
-    
-    mat3 mi(m);
-
-    cout << endl << "Copy of previous matrix (should have (1, 2) == -2.500000)" << endl << endl;
-    mi.print();
-
-    mi.inverse();
-
-    cout << endl << "Inverse of copy: " << endl << endl;
-    mi.print();
-
-    mat3 i = m * mi;
-
-    cout << endl << "Product of original and inverse (should be identity): " << endl << endl;
-    i.print();
-
-    mat3 ident;
-    if (i != ident)
-    {
-        return false;
-    }
-
-    return true;
-}
-
-bool mat4OK()
-{
-    mat4 m;
-    cout << "Starting with mat4 (should be identity): " << endl << endl;
-    m.print();
-
-    m[2][3] = -2.5;
-    
-    cout << endl << "Matrix should now have (2, 3) == -2.500000" << endl << endl;
-    m.print();
-    
-    mat4 mi(m);
-
-    cout << endl << "Copy of previous matrix (should have (2, 3) == -2.500000)" << endl << endl;
-    mi.print();
-
-    mi.inverse();
-
-    cout << endl << "Inverse of copy: " << endl << endl;
-    mi.print();
-
-    mat4 i = m * mi;
-
-    cout << endl <<  "Product of original and inverse (should be identity): " << endl << endl;
-    i.print();
-
-    mat4 ident;
-    if (i != ident)
-    {
-        return false;
-    }
-
-    return true;
-}
-
-int
-main(int argc, char** argv)
-{
-    if (!mat2OK())
-    {
-        cerr << "mat2::inverse() does not work!" << endl;
-        return 1;
-    }
-    cout << "mat2::inverse() is okay!" << endl << endl;
-
-    if (!mat3OK())
-    {
-        cerr << "mat3::inverse() does not work!" << endl;
-        return 1;
-    }
-    cout << "mat3::inverse() is okay!" << endl << endl;
-
-    if (!mat4OK())
-    {
-        cerr << "mat4::inverse() does not work!" << endl;
-        return 1;
-    }
-    cout << "mat4::inverse() is okay!" << endl << endl;
-
-    return 0;
-}

=== modified file 'src/libmatrix/program.cc'
--- src/libmatrix/program.cc	2011-08-31 21:22:27 +0000
+++ src/libmatrix/program.cc	2012-01-26 17:00:43 +0000
@@ -1,5 +1,5 @@ 
 //
-// Copyright (c) 2011 Linaro Limited
+// Copyright (c) 2011-2012 Linaro Limited
 //
 // All rights reserved. This program and the accompanying materials
 // are made available under the terms of the MIT License which accompanies
@@ -14,8 +14,7 @@ 
 #include <sstream>
 #include <fstream>
 #include <iostream>
-
-#include "gl-headers.h"
+#include "gl-if.h"
 #include "program.h"
 
 using std::string;
@@ -24,27 +23,6 @@ 
 using LibMatrix::vec3;
 using LibMatrix::vec4;
 
-bool
-gotSource(const string& filename, string& source)
-{
-    using std::ifstream;
-    ifstream inputFile(filename.c_str());
-    if (!inputFile)
-    {
-        std::cerr << "Failed to open \"" << filename << "\"" << std::endl;
-        return false;
-    }
-
-    string curLine;
-    while (getline(inputFile, curLine))
-    {
-        source += curLine;
-        source += '\n';
-    }
-
-    return true;
-}
-
 Shader::Shader(unsigned int type, const string& source) :
     handle_(0),
     type_(type),
@@ -59,7 +37,7 @@ 
         message_ = string("Failed to create the new shader.");
         return;
     }
-    const char* shaderSource = source_.c_str();
+    const GLchar* shaderSource = source_.c_str();
     glShaderSource(handle_, 1, &shaderSource, NULL);
     GLint param = 0;
     glGetShaderiv(handle_, GL_SHADER_SOURCE_LENGTH, &param);
@@ -95,7 +73,7 @@ 
     if (param == GL_FALSE)
     {
         glGetShaderiv(handle_, GL_INFO_LOG_LENGTH, &param);
-        char* infoLog = new char[param + 1];
+        GLchar* infoLog = new GLchar[param + 1];
         glGetShaderInfoLog(handle_, param + 1, NULL, infoLog);
         message_ = infoLog;
         delete [] infoLog;
@@ -235,7 +213,7 @@ 
     if (param == GL_FALSE)
     {
         glGetProgramiv(handle_, GL_INFO_LOG_LENGTH, &param);
-        char* infoLog = new char[param + 1];
+        GLchar* infoLog = new GLchar[param + 1];
         glGetProgramInfoLog(handle_, param + 1, NULL, infoLog);
         message_ = infoLog;
         delete [] infoLog;

=== modified file 'src/libmatrix/program.h'
--- src/libmatrix/program.h	2011-08-31 21:22:27 +0000
+++ src/libmatrix/program.h	2012-01-26 17:00:43 +0000
@@ -1,5 +1,5 @@ 
 //
-// Copyright (c) 2011 Linaro Limited
+// Copyright (c) 2011-2012 Linaro Limited
 //
 // All rights reserved. This program and the accompanying materials
 // are made available under the terms of the MIT License which accompanies
@@ -161,7 +161,4 @@ 
     bool valid_;
 };
 
-// Handy utility for extracting shader source from a named file
-bool gotSource(const std::string& filename, std::string& sourceOut);
-
 #endif // PROGRAM_H_

=== added file 'src/libmatrix/shader-source.cc'
--- src/libmatrix/shader-source.cc	1970-01-01 00:00:00 +0000
+++ src/libmatrix/shader-source.cc	2012-01-26 17:00:43 +0000
@@ -0,0 +1,615 @@ 
+//
+// Copyright (c) 2010-2012 Linaro Limited
+//
+// All rights reserved. This program and the accompanying materials
+// are made available under the terms of the MIT License which accompanies
+// this distribution, and is available at
+// http://www.opensource.org/licenses/mit-license.php
+//
+// Contributors:
+//     Alexandros Frantzis <alexandros.frantzis@linaro.org>
+//     Jesse Barker <jesse.barker@linaro.org>
+//
+#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;
+
+    /* Ensure we have tried to infer the type from the contents */
+    type();
+
+    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/libmatrix/shader-source.h'
--- src/libmatrix/shader-source.h	1970-01-01 00:00:00 +0000
+++ src/libmatrix/shader-source.h	2012-01-26 17:00:43 +0000
@@ -0,0 +1,103 @@ 
+//
+// Copyright (c) 2010-2012 Linaro Limited
+//
+// All rights reserved. This program and the accompanying materials
+// are made available under the terms of the MIT License which accompanies
+// this distribution, and is available at
+// http://www.opensource.org/licenses/mit-license.php
+//
+// Contributors:
+//     Alexandros Frantzis <alexandros.frantzis@linaro.org>
+//     Jesse Barker <jesse.barker@linaro.org>
+//
+#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 directory 'src/libmatrix/test'
=== added file 'src/libmatrix/test/basic-global-const.vert'
--- src/libmatrix/test/basic-global-const.vert	1970-01-01 00:00:00 +0000
+++ src/libmatrix/test/basic-global-const.vert	2012-01-26 17:00:43 +0000
@@ -0,0 +1,15 @@ 
+const vec4 ConstantColor = vec4(1.000000, 1.000000, 1.000000, 1.000000);
+attribute vec3 position;
+
+uniform mat4 modelview;
+uniform mat4 projection;
+
+varying vec4 color;
+
+void
+main(void)
+{
+    vec4 curVertex = vec4(position, 1.0);
+    gl_Position = projection * modelview * curVertex;
+    color = ConstantColor;
+}

=== added file 'src/libmatrix/test/basic.frag'
--- src/libmatrix/test/basic.frag	1970-01-01 00:00:00 +0000
+++ src/libmatrix/test/basic.frag	2012-01-26 17:00:43 +0000
@@ -0,0 +1,7 @@ 
+varying vec4 color;
+
+void
+main(void)
+{
+    gl_FragColor = color;
+}

=== added file 'src/libmatrix/test/basic.vert'
--- src/libmatrix/test/basic.vert	1970-01-01 00:00:00 +0000
+++ src/libmatrix/test/basic.vert	2012-01-26 17:00:43 +0000
@@ -0,0 +1,14 @@ 
+attribute vec3 position;
+
+uniform mat4 modelview;
+uniform mat4 projection;
+
+varying vec4 color;
+
+void
+main(void)
+{
+    vec4 curVertex = vec4(position, 1.0);
+    gl_Position = projection * modelview * curVertex;
+    color = ConstantColor;
+}

=== added file 'src/libmatrix/test/const_vec_test.cc'
--- src/libmatrix/test/const_vec_test.cc	1970-01-01 00:00:00 +0000
+++ src/libmatrix/test/const_vec_test.cc	2012-01-26 17:00:43 +0000
@@ -0,0 +1,60 @@ 
+//
+// Copyright (c) 2011 Linaro Limited
+//
+// All rights reserved. This program and the accompanying materials
+// are made available under the terms of the MIT License which accompanies
+// this distribution, and is available at
+// http://www.opensource.org/licenses/mit-license.php
+//
+// Contributors:
+//     Jesse Barker - original implementation.
+//
+#include <iostream>
+#include "libmatrix_test.h"
+#include "const_vec_test.h"
+#include "../vec.h"
+
+using LibMatrix::vec2;
+using LibMatrix::vec3;
+using LibMatrix::vec4;
+using std::cout;
+using std::endl;
+
+void
+Vec2TestConstOperator::run(const Options& options)
+{
+    const vec2 a(1.0, 1.0);
+    const vec2 b(2.0, 2.0);
+    vec2 aplusb(a + b);
+    vec2 aminusb(a - b);
+    vec2 atimesb(a * b);
+    vec2 adivb(a / b);
+    const float s(2.5);
+    vec2 stimesb(s * b);
+}
+
+void
+Vec3TestConstOperator::run(const Options& options)
+{
+    const vec3 a(1.0, 1.0, 1.0);
+    const vec3 b(2.0, 2.0, 2.0);
+    vec3 aplusb(a + b);
+    vec3 aminusb(a - b);
+    vec3 atimesb(a * b);
+    vec3 adivb(a / b);
+    const float s(2.5);
+    vec3 stimesb(s * b);
+}
+
+void
+Vec4TestConstOperator::run(const Options& options)
+{
+    const vec4 a(1.0, 1.0, 1.0, 1.0);
+    const vec4 b(2.0, 2.0, 2.0, 2.0);
+    vec4 aplusb(a + b);
+    vec4 aminusb(a - b);
+    vec4 atimesb(a * b);
+    vec4 adivb(a / b);
+    const float s(2.5);
+    vec4 stimesb(s * b);
+}

=== added file 'src/libmatrix/test/const_vec_test.h'
--- src/libmatrix/test/const_vec_test.h	1970-01-01 00:00:00 +0000
+++ src/libmatrix/test/const_vec_test.h	2012-01-26 17:00:43 +0000
@@ -0,0 +1,39 @@ 
+//
+// Copyright (c) 2011 Linaro Limited
+//
+// All rights reserved. This program and the accompanying materials
+// are made available under the terms of the MIT License which accompanies
+// this distribution, and is available at
+// http://www.opensource.org/licenses/mit-license.php
+//
+// Contributors:
+//     Jesse Barker - original implementation.
+//
+#ifndef CONST_VEC_TEST_H_
+#define CONST_VEC_TEST_H_
+
+class MatrixTest;
+class Options;
+
+class Vec2TestConstOperator : public MatrixTest
+{
+public:
+    Vec2TestConstOperator() : MatrixTest("vec2::const") {}
+    virtual void run(const Options& options);
+};
+
+class Vec3TestConstOperator : public MatrixTest
+{
+public:
+    Vec3TestConstOperator() : MatrixTest("vec3::const") {}
+    virtual void run(const Options& options);
+};
+
+class Vec4TestConstOperator : public MatrixTest
+{
+public:
+    Vec4TestConstOperator() : MatrixTest("vec4::const") {}
+    virtual void run(const Options& options);
+};
+
+#endif // CONST_VEC_TEST_H_

=== added file 'src/libmatrix/test/inverse_test.cc'
--- src/libmatrix/test/inverse_test.cc	1970-01-01 00:00:00 +0000
+++ src/libmatrix/test/inverse_test.cc	2012-01-26 17:00:43 +0000
@@ -0,0 +1,172 @@ 
+//
+// Copyright (c) 2010 Linaro Limited
+//
+// All rights reserved. This program and the accompanying materials
+// are made available under the terms of the MIT License which accompanies
+// this distribution, and is available at
+// http://www.opensource.org/licenses/mit-license.php
+//
+// Contributors:
+//     Jesse Barker - original implementation.
+//
+#include <iostream>
+#include "libmatrix_test.h"
+#include "inverse_test.h"
+#include "../mat.h"
+
+using LibMatrix::mat2;
+using LibMatrix::mat3;
+using LibMatrix::mat4;
+using std::cout;
+using std::endl;
+
+void
+MatrixTest2x2Inverse::run(const Options& options)
+{
+    mat2 m;
+
+    if (options.beVerbose())
+    {
+        cout << "Starting with mat2 (should be identity): " << endl << endl;
+        m.print();
+    }
+
+    m[0][1] = -2.5;
+    
+    if (options.beVerbose())
+    {
+        cout << endl << "Matrix should now have (0, 1) == -2.500000" << endl << endl;
+        m.print();
+    }
+    
+    mat2 mi(m);
+
+    if (options.beVerbose())
+    {
+        cout << endl << "Copy of previous matrix (should have (0, 1) == -2.500000)" << endl << endl;
+        mi.print();
+    }
+
+    mi.inverse();
+
+    if (options.beVerbose())
+    {
+        cout << endl << "Inverse of copy: " << endl << endl;
+        mi.print();
+    }
+
+    mat2 i = m * mi;
+
+    if (options.beVerbose())
+    {
+        cout << endl << "Product of original and inverse (should be identity): " << endl << endl;
+        i.print();
+    }
+
+    mat2 ident;
+    if (i == ident)
+    {
+        pass_ = true;
+    }
+}
+
+void
+MatrixTest3x3Inverse::run(const Options& options)
+{
+    mat3 m;
+
+    if (options.beVerbose())
+    {
+        cout << "Starting with mat3 (should be identity): " << endl << endl;
+        m.print();
+    }
+
+    m[1][2] = -2.5;
+    
+    if (options.beVerbose())
+    {
+        cout << endl << "Matrix should now have (1, 2) == -2.500000" << endl << endl;
+        m.print();
+    }
+
+    mat3 mi(m);
+
+    if (options.beVerbose())
+    {
+        cout << endl << "Copy of previous matrix (should have (1, 2) == -2.500000)" << endl << endl;
+        mi.print();
+    }
+
+    mi.inverse();
+
+    if (options.beVerbose())
+    {
+        cout << endl << "Inverse of copy: " << endl << endl;
+        mi.print();
+    }
+
+    mat3 i = m * mi;
+
+    if (options.beVerbose())
+    {
+        cout << endl << "Product of original and inverse (should be identity): " << endl << endl;
+        i.print();
+    }
+
+    mat3 ident;
+    if (i == ident)
+    {
+        pass_ = true;
+    }
+}
+
+void
+MatrixTest4x4Inverse::run(const Options& options)
+{
+    mat4 m;
+
+    if (options.beVerbose())
+    {
+        cout << "Starting with mat4 (should be identity): " << endl << endl;
+        m.print();
+    }
+
+    m[2][3] = -2.5;
+    
+    if (options.beVerbose())
+    {
+        cout << endl << "Matrix should now have (2, 3) == -2.500000" << endl << endl;
+        m.print();
+    }
+
+    mat4 mi(m);
+
+    if (options.beVerbose())
+    {
+        cout << endl << "Copy of previous matrix (should have (2, 3) == -2.500000)" << endl << endl;
+        mi.print();
+    }
+
+    mi.inverse();
+
+    if (options.beVerbose())
+    {
+        cout << endl << "Inverse of copy: " << endl << endl;
+        mi.print();
+    }
+
+    mat4 i = m * mi;
+
+    if (options.beVerbose())
+    {
+        cout << endl <<  "Product of original and inverse (should be identity): " << endl << endl;
+        i.print();
+    }
+
+    mat4 ident;
+    if (i == ident)
+    {
+        pass_ = true;
+    }
+}
+

=== added file 'src/libmatrix/test/inverse_test.h'
--- src/libmatrix/test/inverse_test.h	1970-01-01 00:00:00 +0000
+++ src/libmatrix/test/inverse_test.h	2012-01-26 17:00:43 +0000
@@ -0,0 +1,39 @@ 
+//
+// Copyright (c) 2010 Linaro Limited
+//
+// All rights reserved. This program and the accompanying materials
+// are made available under the terms of the MIT License which accompanies
+// this distribution, and is available at
+// http://www.opensource.org/licenses/mit-license.php
+//
+// Contributors:
+//     Jesse Barker - original implementation.
+//
+#ifndef INVERSE_TEST_H_
+#define INVERSE_TEST_H_
+
+class MatrixTest;
+class Options;
+
+class MatrixTest2x2Inverse : public MatrixTest
+{
+public:
+    MatrixTest2x2Inverse() : MatrixTest("mat2::inverse") {}
+    virtual void run(const Options& options);
+};
+
+class MatrixTest3x3Inverse : public MatrixTest
+{
+public:
+    MatrixTest3x3Inverse() : MatrixTest("mat3::inverse") {}
+    virtual void run(const Options& options);
+};
+
+class MatrixTest4x4Inverse : public MatrixTest
+{
+public:
+    MatrixTest4x4Inverse() : MatrixTest("mat4::inverse") {}
+    virtual void run(const Options& options);
+};
+
+#endif // INVERSE_TEST_H_

=== added file 'src/libmatrix/test/libmatrix_test.cc'
--- src/libmatrix/test/libmatrix_test.cc	1970-01-01 00:00:00 +0000
+++ src/libmatrix/test/libmatrix_test.cc	2012-01-26 17:00:43 +0000
@@ -0,0 +1,68 @@ 
+//
+// Copyright (c) 2010 Linaro Limited
+//
+// All rights reserved. This program and the accompanying materials
+// are made available under the terms of the MIT License which accompanies
+// this distribution, and is available at
+// http://www.opensource.org/licenses/mit-license.php
+//
+// Contributors:
+//     Jesse Barker - original implementation.
+//
+#include <iostream>
+#include <string>
+#include <vector>
+#include "libmatrix_test.h"
+#include "inverse_test.h"
+#include "transpose_test.h"
+#include "const_vec_test.h"
+#include "shader_source_test.h"
+
+using std::cerr;
+using std::cout;
+using std::endl;
+
+int
+main(int argc, char** argv)
+{
+    Options testOptions("matrix_test");
+    testOptions.parseArgs(argc, argv);
+    if (testOptions.showHelp())
+    {
+        testOptions.printUsage();
+        return 0;
+    }
+
+    using std::vector;
+    vector<MatrixTest*> testVec;
+    testVec.push_back(new MatrixTest2x2Inverse());
+    testVec.push_back(new MatrixTest3x3Inverse());
+    testVec.push_back(new MatrixTest4x4Inverse());
+    testVec.push_back(new MatrixTest2x2Transpose());
+    testVec.push_back(new MatrixTest3x3Transpose());
+    testVec.push_back(new MatrixTest4x4Transpose());
+    testVec.push_back(new ShaderSourceBasic());
+
+    for (vector<MatrixTest*>::iterator testIt = testVec.begin();
+         testIt != testVec.end();
+         testIt++)
+    {
+        MatrixTest* curTest = *testIt;
+        if (testOptions.beVerbose())
+        {
+            cout << "Running test " << curTest->name() << endl;
+        }
+        curTest->run(testOptions);
+        if (!curTest->passed())
+        {
+            cerr << curTest->name() << " does not work!" << endl;
+            return 1;
+        }
+        if (testOptions.beVerbose())
+        {
+            cout << curTest->name() << " is okay!" << endl;
+        }
+    }
+
+    return 0;
+}

=== added file 'src/libmatrix/test/libmatrix_test.h'
--- src/libmatrix/test/libmatrix_test.h	1970-01-01 00:00:00 +0000
+++ src/libmatrix/test/libmatrix_test.h	2012-01-26 17:00:43 +0000
@@ -0,0 +1,51 @@ 
+//
+// Copyright (c) 2010 Linaro Limited
+//
+// All rights reserved. This program and the accompanying materials
+// are made available under the terms of the MIT License which accompanies
+// this distribution, and is available at
+// http://www.opensource.org/licenses/mit-license.php
+//
+// Contributors:
+//     Jesse Barker - original implementation.
+//
+#ifndef LIBMATRIX_TEST_H_
+#define LIBMATRIX_TEST_H_
+
+class Options
+{
+    Options();
+    static const std::string verbose_name_;
+    static const std::string help_name_;
+    std::string app_name_;
+    bool show_help_;
+    bool verbose_;
+public:
+    Options(const std::string& app_name) :
+        app_name_(app_name),
+        show_help_(false),
+        verbose_(false) {}
+    ~Options() {}
+    bool beVerbose() const { return verbose_; }
+    bool showHelp() const { return show_help_; }
+    void parseArgs(int argc, char** argv);
+    void printUsage();
+};
+
+class MatrixTest
+{
+    std::string name_;
+protected:
+    bool pass_;
+    MatrixTest();
+public:
+    MatrixTest(const std::string& name) : 
+        name_(name),
+        pass_(false) {}
+    ~MatrixTest();
+    const std::string& name() const { return name_; }
+    virtual void run(const Options& options) = 0;
+    const bool passed() const { return pass_; }
+};
+
+#endif // LIBMATRIX_TEST_H_

=== added file 'src/libmatrix/test/options.cc'
--- src/libmatrix/test/options.cc	1970-01-01 00:00:00 +0000
+++ src/libmatrix/test/options.cc	2012-01-26 17:00:43 +0000
@@ -0,0 +1,76 @@ 
+//
+// Copyright (c) 2010 Linaro Limited
+//
+// All rights reserved. This program and the accompanying materials
+// are made available under the terms of the MIT License which accompanies
+// this distribution, and is available at
+// http://www.opensource.org/licenses/mit-license.php
+//
+// Contributors:
+//     Jesse Barker - original implementation.
+//
+#include <iostream>
+#include <iomanip>
+#include <getopt.h>
+#include "libmatrix_test.h"
+
+using std::cout;
+using std::endl;
+
+const std::string Options::verbose_name_("verbose");
+const std::string Options::help_name_("help");
+
+void
+Options::parseArgs(int argc, char** argv)
+{
+    static struct option long_options[] = {
+        {"verbose", 0, 0, 0},
+        {"help", 0, 0, 0},
+        {0, 0, 0, 0}
+    };
+    int option_index(0);
+    int c =  getopt_long(argc, argv, "", long_options, &option_index);
+    while (c != -1) 
+    {
+        // getopt_long() returns '?' and prints an "unrecognized option" error
+        // to stderr if it does not recognize an option.  Just trigger
+        // the help/usage message, stop processing and get out.
+        if (c == '?')
+        {
+            show_help_ = true;
+            break;
+        }
+
+        std::string optname(long_options[option_index].name);
+
+        if (optname == verbose_name_)
+        {
+            verbose_ = true;
+        }
+        else if (optname == help_name_)
+        {
+            show_help_ = true;
+        }
+        c = getopt_long(argc, argv, "",
+                        long_options, &option_index);
+    }
+}
+
+
+static void
+emitColumnOne(const std::string& text)
+{
+    cout << std::setw(16) << text;
+}
+
+void
+Options::printUsage()
+{
+    cout << app_name_ << ": directed functional test utility for libmatrix." << endl;
+    cout << "Options:" << endl;
+    emitColumnOne("--verbose"); 
+    cout << std::setw(0) << " Enable verbose output during test runs." << endl;
+    emitColumnOne("--help");
+    cout << std::setw(0) << " Print this usage text." << endl;   
+}
+

=== added file 'src/libmatrix/test/shader_source_test.cc'
--- src/libmatrix/test/shader_source_test.cc	1970-01-01 00:00:00 +0000
+++ src/libmatrix/test/shader_source_test.cc	2012-01-26 17:00:43 +0000
@@ -0,0 +1,49 @@ 
+//
+// Copyright (c) 2012 Linaro Limited
+//
+// All rights reserved. This program and the accompanying materials
+// are made available under the terms of the MIT License which accompanies
+// this distribution, and is available at
+// http://www.opensource.org/licenses/mit-license.php
+//
+// Contributors:
+//     Jesse Barker - original implementation.
+//
+#include <string>
+#include "libmatrix_test.h"
+#include "shader_source_test.h"
+#include "../shader-source.h"
+#include "../vec.h"
+
+using std::string;
+using LibMatrix::vec4;
+
+void
+ShaderSourceBasic::run(const Options& options)
+{
+    static const string vtx_shader_filename("test/basic.vert");
+
+    ShaderSource vtx_source(vtx_shader_filename);
+    ShaderSource vtx_source2(vtx_shader_filename);
+    
+    pass_ = (vtx_source.str() == vtx_source2.str());
+}
+
+void
+ShaderSourceAddConstGlobal::run(const Options& options)
+{
+    // Load the original shader source.
+    static const string src_shader_filename("test/basic.vert");
+    ShaderSource src_shader(src_shader_filename);
+
+    // Add constant at global scope
+    static const vec4 constantColor(1.0, 1.0, 1.0, 1.0);
+    src_shader.add_const("ConstantColor", constantColor);
+
+    // Load the pre-modified shader
+    static const string result_shader_filename("test/basic-global-const.vert");
+    ShaderSource result_shader(result_shader_filename);
+
+    // Compare the output strings to confirm the results.
+    pass_ = (src_shader.str() == result_shader.str());
+}

=== added file 'src/libmatrix/test/shader_source_test.h'
--- src/libmatrix/test/shader_source_test.h	1970-01-01 00:00:00 +0000
+++ src/libmatrix/test/shader_source_test.h	2012-01-26 17:00:43 +0000
@@ -0,0 +1,32 @@ 
+//
+// Copyright (c) 2012 Linaro Limited
+//
+// All rights reserved. This program and the accompanying materials
+// are made available under the terms of the MIT License which accompanies
+// this distribution, and is available at
+// http://www.opensource.org/licenses/mit-license.php
+//
+// Contributors:
+//     Jesse Barker - original implementation.
+//
+#ifndef SHADER_SOURCE_TEST_H_
+#define SHADER_SOURCE_TEST_H_
+
+class MatrixTest;
+class Options;
+
+class ShaderSourceBasic : public MatrixTest
+{
+public:
+    ShaderSourceBasic() : MatrixTest("ShaderSource::basic") {}
+    virtual void run(const Options& options);
+};
+
+class ShaderSourceAddConstGlobal : public MatrixTest
+{
+public:
+    ShaderSourceAddConstGlobal() : MatrixTest("ShaderSource::AddConstGlobal") {}
+    virtual void run(const Options& options);
+};
+
+#endif // SHADER_SOURCE_TEST_H

=== added file 'src/libmatrix/test/transpose_test.cc'
--- src/libmatrix/test/transpose_test.cc	1970-01-01 00:00:00 +0000
+++ src/libmatrix/test/transpose_test.cc	2012-01-26 17:00:43 +0000
@@ -0,0 +1,297 @@ 
+//
+// Copyright (c) 2010 Linaro Limited
+//
+// All rights reserved. This program and the accompanying materials
+// are made available under the terms of the MIT License which accompanies
+// this distribution, and is available at
+// http://www.opensource.org/licenses/mit-license.php
+//
+// Contributors:
+//     Jesse Barker - original implementation.
+//
+#include <iostream>
+#include "libmatrix_test.h"
+#include "transpose_test.h"
+#include "../mat.h"
+
+using LibMatrix::mat2;
+using LibMatrix::mat3;
+using LibMatrix::mat4;
+using std::cout;
+using std::endl;
+
+void
+MatrixTest2x2Transpose::run(const Options& options)
+{
+    // First, a simple test to ensure that the transpose of the identity is
+    // the identity.
+    if (options.beVerbose())
+    {
+        cout << endl << "Assertion 1: Transpose of the identity is the identity." << endl << endl;
+    }
+
+    mat2 m;
+
+    if (options.beVerbose())
+    {
+        cout << "Starting with mat2 (should be identity): " << endl << endl;
+        m.print();
+    }
+
+    m.transpose();
+
+    if (options.beVerbose())
+    {
+        cout << endl << "Transpose of identity (should be identity): " << endl << endl;
+        m.print();
+    }
+
+    mat2 mi;
+    if (m != mi)
+    {
+        // FAIL! Transpose of the identity is the identity.
+        return;
+    }
+
+    // At this point, we have 2 identity matrices.
+    // Next, set an element in the matrix and transpose twice.  We should see
+    // the original matrix (with i,j set).
+    if (options.beVerbose())
+    {
+        cout << endl << "Assertion 2: Transposing a matrix twice yields the original matrix." << endl << endl;
+    }
+
+    m[0][1] = 6.3;
+
+    if (options.beVerbose())
+    {
+        cout << "Matrix should now have (0, 1) == 6.300000" << endl << endl;
+        m.print();
+    }
+    
+    mi = m;
+
+    m.transpose().transpose();
+
+    if (options.beVerbose())
+    {
+        cout << endl << "Matrix should now have (0, 1) == 6.300000" << endl << endl;
+        m.print();
+    }
+    
+    if (m != mi)
+    {
+        // FAIL! Transposing the same matrix twice should yield the original.
+        return;
+    }    
+
+    // Next, reset mi back to the identity.  Set element element j,i in this
+    // matrix and transpose m.  They should now be equal.
+    if (options.beVerbose())
+    {
+        cout << endl << "Assertion 3: Transpose of matrix (i,j) == x is equal to matrix (j,i) == x." << endl << endl;
+    }
+
+    mi.setIdentity();
+    mi[1][0] = 6.3;
+
+    m.transpose();
+
+    if (options.beVerbose())
+    {
+        cout << "Matrix should now have (1, 0) == 6.300000" << endl << endl;
+        m.print();
+        cout << endl;
+    }
+    
+    if (m == mi)
+    {
+        pass_ = true;
+    }
+
+    // FAIL! Transposing the same matrix twice should yield the original.
+}
+
+void
+MatrixTest3x3Transpose::run(const Options& options)
+{
+    // First, a simple test to ensure that the transpose of the identity is
+    // the identity.
+    if (options.beVerbose())
+    {
+        cout << endl << "Assertion 1: Transpose of the identity is the identity." << endl << endl;
+    }
+
+    mat3 m;
+
+    if (options.beVerbose())
+    {
+        cout << "Starting with mat2 (should be identity): " << endl << endl;
+        m.print();
+    }
+
+    m.transpose();
+
+    if (options.beVerbose())
+    {
+        cout << endl << "Transpose of identity (should be identity): " << endl << endl;
+        m.print();
+    }
+
+    mat3 mi;
+    if (m != mi)
+    {
+        // FAIL! Transpose of the identity is the identity.
+        return;
+    }
+
+    // At this point, we have 2 identity matrices.
+    // Next, set an element in the matrix and transpose twice.  We should see
+    // the original matrix (with i,j set).
+    if (options.beVerbose())
+    {
+        cout << endl << "Assertion 2: Transposing a matrix twice yields the original matrix." << endl << endl;
+    }
+
+    m[0][1] = 6.3;
+
+    if (options.beVerbose())
+    {
+        cout << "Matrix should now have (0, 1) == 6.300000" << endl << endl;
+        m.print();
+    }
+    
+    mi = m;
+
+    m.transpose().transpose();
+
+    if (options.beVerbose())
+    {
+        cout << endl << "Matrix should now have (0, 1) == 6.300000" << endl << endl;
+        m.print();
+    }
+    
+    if (m != mi)
+    {
+        // FAIL! Transposing the same matrix twice should yield the original.
+        return;
+    }    
+
+    // Next, reset mi back to the identity.  Set element element j,i in this
+    // matrix and transpose m.  They should now be equal.
+    if (options.beVerbose())
+    {
+        cout << endl << "Assertion 3: Transpose of matrix (i,j) == x is equal to matrix (j,i) == x." << endl << endl;
+    }
+
+    mi.setIdentity();
+    mi[1][0] = 6.3;
+
+    m.transpose();
+
+    if (options.beVerbose())
+    {
+        cout << "Matrix should now have (1, 0) == 6.300000" << endl << endl;
+        m.print();
+        cout << endl;
+    }
+    
+    if (m == mi)
+    {
+        pass_ = true;
+    }
+
+    // FAIL! Transposing the same matrix twice should yield the original.
+}
+
+void
+MatrixTest4x4Transpose::run(const Options& options)
+{
+    // First, a simple test to ensure that the transpose of the identity is
+    // the identity.
+    if (options.beVerbose())
+    {
+        cout << endl << "Assertion 1: Transpose of the identity is the identity." << endl << endl;
+    }
+
+    mat4 m;
+
+    if (options.beVerbose())
+    {
+        cout << "Starting with mat2 (should be identity): " << endl << endl;
+        m.print();
+    }
+
+    m.transpose();
+
+    if (options.beVerbose())
+    {
+        cout << endl << "Transpose of identity (should be identity): " << endl << endl;
+        m.print();
+    }
+
+    mat4 mi;
+    if (m != mi)
+    {
+        // FAIL! Transpose of the identity is the identity.
+        return;
+    }
+
+    // At this point, we have 2 identity matrices.
+    // Next, set an element in the matrix and transpose twice.  We should see
+    // the original matrix (with i,j set).
+    if (options.beVerbose())
+    {
+        cout << endl << "Assertion 2: Transposing a matrix twice yields the original matrix." << endl << endl;
+    }
+
+    m[0][1] = 6.3;
+
+    if (options.beVerbose())
+    {
+        cout << "Matrix should now have (0, 1) == 6.300000" << endl << endl;
+        m.print();
+    }
+    
+    mi = m;
+
+    m.transpose().transpose();
+
+    if (options.beVerbose())
+    {
+        cout << endl << "Matrix should now have (0, 1) == 6.300000" << endl << endl;
+        m.print();
+    }
+    
+    if (m != mi)
+    {
+        // FAIL! Transposing the same matrix twice should yield the original.
+        return;
+    }    
+
+    // Next, reset mi back to the identity.  Set element element j,i in this
+    // matrix and transpose m.  They should now be equal.
+    if (options.beVerbose())
+    {
+        cout << endl << "Assertion 3: Transpose of matrix (i,j) == x is equal to matrix (j,i) == x." << endl << endl;
+    }
+
+    mi.setIdentity();
+    mi[1][0] = 6.3;
+
+    m.transpose();
+
+    if (options.beVerbose())
+    {
+        cout << "Matrix should now have (1, 0) == 6.300000" << endl << endl;
+        m.print();
+        cout << endl;
+    }
+    
+    if (m == mi)
+    {
+        pass_ = true;
+    }
+
+    // FAIL! Transposing the same matrix twice should yield the original.
+}

=== added file 'src/libmatrix/test/transpose_test.h'
--- src/libmatrix/test/transpose_test.h	1970-01-01 00:00:00 +0000
+++ src/libmatrix/test/transpose_test.h	2012-01-26 17:00:43 +0000
@@ -0,0 +1,38 @@ 
+//
+// Copyright (c) 2010 Linaro Limited
+//
+// All rights reserved. This program and the accompanying materials
+// are made available under the terms of the MIT License which accompanies
+// this distribution, and is available at
+// http://www.opensource.org/licenses/mit-license.php
+//
+// Contributors:
+//     Jesse Barker - original implementation.
+//
+#ifndef TRANSPOSE_TEST_H_
+#define TRANSPOSE_TEST_H_
+
+class MatrixTest;
+class Options;
+
+class MatrixTest2x2Transpose : public MatrixTest
+{
+public:
+    MatrixTest2x2Transpose() : MatrixTest("mat2::transpose") {}
+    virtual void run(const Options& options);
+};
+
+class MatrixTest3x3Transpose : public MatrixTest
+{
+public:
+    MatrixTest3x3Transpose() : MatrixTest("mat3::transpose") {}
+    virtual void run(const Options& options);
+};
+
+class MatrixTest4x4Transpose : public MatrixTest
+{
+public:
+    MatrixTest4x4Transpose() : MatrixTest("mat4::transpose") {}
+    virtual void run(const Options& options);
+};
+#endif // TRANSPOSE_TEST_H_

=== added file 'src/libmatrix/util.cc'
--- src/libmatrix/util.cc	1970-01-01 00:00:00 +0000
+++ src/libmatrix/util.cc	2012-01-27 22:01:59 +0000
@@ -0,0 +1,165 @@ 
+//
+// Copyright (c) 2010-2011 Linaro Limited
+//
+// All rights reserved. This program and the accompanying materials
+// are made available under the terms of the MIT License which accompanies
+// this distribution, and is available at
+// http://www.opensource.org/licenses/mit-license.php
+//
+// Contributors:
+//     Alexandros Frantzis <alexandros.frantzis@linaro.org>
+//     Jesse Barker <jesse.barker@linaro.org>
+//
+#include <sstream>
+#include <fstream>
+#include <sys/time.h>
+#ifdef ANDROID
+#include <android/asset_manager.h>
+#else
+#include <dirent.h>
+#endif
+
+#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::string
+Util::appname_from_path(const std::string& path)
+{
+    std::string::size_type slashPos = path.rfind("/");
+    std::string::size_type startPos(0);
+    if (slashPos != std::string::npos)
+    {
+        startPos = slashPos + 1;
+    }
+    return std::string(path, startPos, std::string::npos);
+}
+
+#ifndef ANDROID
+
+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);
+}
+
+#else
+
+AAssetManager *Util::android_asset_manager = 0;
+
+void
+Util::android_set_asset_manager(AAssetManager *asset_manager)
+{
+    Util::android_asset_manager = asset_manager;
+}
+
+AAssetManager *
+Util::android_get_asset_manager()
+{
+    return Util::android_asset_manager;
+}
+
+std::istream *
+Util::get_resource(const std::string &path)
+{
+    std::string path2(path);
+    /* Remove leading '/' from path name, it confuses the AssetManager */
+    if (path2.size() > 0 && path2[0] == '/')
+        path2.erase(0, 1);
+
+    std::stringstream *ss = new std::stringstream;
+    AAsset *asset = AAssetManager_open(Util::android_asset_manager,
+                                       path2.c_str(), AASSET_MODE_RANDOM);
+    if (asset) {
+        ss->write(reinterpret_cast<const char *>(AAsset_getBuffer(asset)),
+                  AAsset_getLength(asset));
+        Log::debug("Load asset %s\n", path2.c_str());
+        AAsset_close(asset);
+    }
+    else {
+        Log::error("Couldn't load asset %s\n", path2.c_str());
+    }
+
+    return static_cast<std::istream *>(ss);
+}
+
+void
+Util::list_files(const std::string& dirName, std::vector<std::string>& fileVec)
+{
+    AAssetManager *mgr(Util::android_get_asset_manager());
+    std::string dir_name(dirName);
+
+    /* Remove leading '/' from path, it confuses the AssetManager */
+    if (dir_name.size() > 0 && dir_name[0] == '/')
+        dir_name.erase(0, 1);
+
+    AAssetDir* dir = AAssetManager_openDir(mgr, dir_name.c_str());
+    if (!dir)
+    {
+        Log::error("Failed to open models directory '%s'\n", dir_name.c_str());
+        return;
+    }
+
+    const char *filename(0);
+    while ((filename = AAssetDir_getNextFileName(dir)) != 0)
+    {
+        std::string pathname(dir_name + "/");
+        pathname += std::string(filename);
+        fileVec.push_back(pathname);
+    }
+    AAssetDir_close(dir);
+}
+#endif

=== added file 'src/libmatrix/util.h'
--- src/libmatrix/util.h	1970-01-01 00:00:00 +0000
+++ src/libmatrix/util.h	2012-01-27 22:01:59 +0000
@@ -0,0 +1,71 @@ 
+//
+// Copyright (c) 2010-2011 Linaro Limited
+//
+// All rights reserved. This program and the accompanying materials
+// are made available under the terms of the MIT License which accompanies
+// this distribution, and is available at
+// http://www.opensource.org/licenses/mit-license.php
+//
+// Contributors:
+//     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>
+
+#ifdef ANDROID
+#include <android/asset_manager_jni.h>
+#endif
+
+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();
+    }
+    static std::string
+    appname_from_path(const std::string& path);
+
+#ifdef ANDROID
+    static void android_set_asset_manager(AAssetManager *asset_manager);
+    static AAssetManager *android_get_asset_manager(void);
+private:
+    static AAssetManager *android_asset_manager;
+#endif
+};
+
+#endif /* UTIL_H */

=== modified file 'src/libmatrix/vec.h'
--- src/libmatrix/vec.h	2011-09-19 15:30:13 +0000
+++ src/libmatrix/vec.h	2012-01-26 17:00:43 +0000
@@ -17,6 +17,10 @@ 
 
 namespace LibMatrix
 {
+// A template class for creating, managing and operating on a 2-element vector
+// of any type you like (intended for built-in types, but as long as it 
+// supports the basic arithmetic and assignment operators, any type should
+// work).
 template<typename T>
 class tvec2
 {
@@ -24,10 +28,10 @@ 
     tvec2() :
         x_(0),
         y_(0) {}
-    tvec2(T t) :
+    tvec2(const T t) :
         x_(t),
         y_(t) {}
-    tvec2(T x, T y) :
+    tvec2(const T x, const T y) :
         x_(x),
         y_(y) {}
     tvec2(const tvec2& v) :
@@ -35,18 +39,26 @@ 
         y_(v.y_) {}
     ~tvec2() {}
 
+    // Print the elements of the vector to standard out.
+    // Really only useful for debug and test.
     void print() const
     {
         std::cout << "| " << x_ << " " << y_ << " |" << std::endl;
     }
+
+    // Allow raw data access for API calls and the like.
+    // For example, it is valid to pass a tvec2<float> into a call to
+    // the OpenGL command "glUniform2fv()".
     operator const T*() const { return &x_;}
 
+    // Get and set access members for the individual elements.
     const T x() const { return x_; }
     const T y() const { return y_; }
 
     void x(const T& val) { x_ = val; }
     void y(const T& val) { y_ = val; }
 
+    // A direct assignment of 'rhs' to this.  Return a reference to this.
     tvec2& operator=(const tvec2& rhs)
     {
         if (this != &rhs)
@@ -57,6 +69,7 @@ 
         return *this;
     }
 
+    // Divide this by a scalar.  Return a reference to this.
     tvec2& operator/=(const T& rhs)
     {
         x_ /= rhs;
@@ -64,11 +77,14 @@ 
         return *this;
     }
 
+    // Divide a copy of this by a scalar.  Return the copy.
     const tvec2 operator/(const T& rhs) const
     {
         return tvec2(*this) /= rhs;
     }
 
+    // Component-wise divide of this by another vector.
+    // Return a reference to this.
     tvec2& operator/=(const tvec2& rhs)
     {
         x_ /= rhs.x_;
@@ -76,11 +92,14 @@ 
         return *this;
     }
 
+    // Component-wise divide of a copy of this by another vector.
+    // Return the copy.
     const tvec2 operator/(const tvec2& rhs) const
     {
         return tvec2(*this) /= rhs;
     }
 
+    // Multiply this by a scalar.  Return a reference to this.
     tvec2& operator*=(const T& rhs)
     {
         x_ *= rhs;
@@ -88,11 +107,14 @@ 
         return *this;
     }
 
+    // Multiply a copy of this by a scalar.  Return the copy.
     const tvec2 operator*(const T& rhs) const
     {
         return tvec2(*this) *= rhs;
     }
 
+    // Component-wise multiply of this by another vector.
+    // Return a reference to this.
     tvec2& operator*=(const tvec2& rhs)
     {
         x_ *= rhs.x_;
@@ -100,11 +122,14 @@ 
         return *this;
     }
 
+    // Component-wise multiply of a copy of this by another vector.
+    // Return the copy.
     const tvec2 operator*(const tvec2& rhs) const
     {
         return tvec2(*this) *= rhs;
     }
 
+    // Add a scalar to this.  Return a reference to this.
     tvec2& operator+=(const T& rhs)
     {
         x_ += rhs;
@@ -112,11 +137,14 @@ 
         return *this;
     }
     
+    // Add a scalar to a copy of this.  Return the copy.
     const tvec2 operator+(const T& rhs) const
     {
         return tvec2(*this) += rhs;
     }
 
+    // Component-wise addition of another vector to this.
+    // Return a reference to this.
     tvec2& operator+=(const tvec2& rhs)
     {
         x_ += rhs.x_;
@@ -124,11 +152,14 @@ 
         return *this;
     }
 
+    // Component-wise addition of another vector to a copy of this.
+    // Return the copy.
     const tvec2 operator+(const tvec2& rhs) const
     {
         return tvec2(*this) += rhs;
     }
 
+    // Subtract a scalar from this.  Return a reference to this.
     tvec2& operator-=(const T& rhs)
     {
         x_ -= rhs;
@@ -136,11 +167,14 @@ 
         return *this;
     }
     
+    // Subtract a scalar from a copy of this.  Return the copy.
     const tvec2 operator-(const T& rhs) const
     {
         return tvec2(*this) -= rhs;
     }
 
+    // Component-wise subtraction of another vector from this.
+    // Return a reference to this.
     tvec2& operator-=(const tvec2& rhs)
     {
         x_ -= rhs.x_;
@@ -148,16 +182,20 @@ 
         return *this;
     }
 
+    // Component-wise subtraction of another vector from a copy of this.
+    // Return the copy.
     const tvec2 operator-(const tvec2& rhs) const
     {
         return tvec2(*this) -= rhs;
     }
 
+    // Compute the length of this and return it.
     float length() const
     {
         return sqrt(dot(*this, *this));
     }
 
+    // Make this a unit vector.
     void normalize()
     {
         float l = length();
@@ -165,6 +203,7 @@ 
         y_ /= l;
     }
 
+    // Compute the dot product of two vectors.
     static T dot(const tvec2& v1, const tvec2& v2)
     {
         return (v1.x_ * v2.x_) + (v1.y_ * v2.y_); 
@@ -175,6 +214,10 @@ 
     T y_;
 };
 
+// A template class for creating, managing and operating on a 3-element vector
+// of any type you like (intended for built-in types, but as long as it 
+// supports the basic arithmetic and assignment operators, any type should
+// work).
 template<typename T>
 class tvec3
 {
@@ -183,11 +226,11 @@ 
         x_(0),
         y_(0),
         z_(0) {}
-    tvec3(T t) :
+    tvec3(const T t) :
         x_(t),
         y_(t),
         z_(t) {}
-    tvec3(T x, T y, T z) :
+    tvec3(const T x, const T y, const T z) :
         x_(x),
         y_(y),
         z_(z) {}
@@ -197,12 +240,19 @@ 
         z_(v.z_) {}
     ~tvec3() {}
 
+    // Print the elements of the vector to standard out.
+    // Really only useful for debug and test.
     void print() const
     {
         std::cout << "| " << x_ << " " << y_ << " " << z_ << " |" << std::endl;
     }
+
+    // Allow raw data access for API calls and the like.
+    // For example, it is valid to pass a tvec3<float> into a call to
+    // the OpenGL command "glUniform3fv()".
     operator const T*() const { return &x_;}
 
+    // Get and set access members for the individual elements.
     const T x() const { return x_; }
     const T y() const { return y_; }
     const T z() const { return z_; }
@@ -211,6 +261,7 @@ 
     void y(const T& val) { y_ = val; }
     void z(const T& val) { z_ = val; }
 
+    // A direct assignment of 'rhs' to this.  Return a reference to this.
     tvec3& operator=(const tvec3& rhs)
     {
         if (this != &rhs)
@@ -222,6 +273,7 @@ 
         return *this;
     }
 
+    // Divide this by a scalar.  Return a reference to this.
     tvec3& operator/=(const T& rhs)
     {
         x_ /= rhs;
@@ -230,11 +282,14 @@ 
         return *this;
     }
 
+    // Divide a copy of this by a scalar.  Return the copy.
     const tvec3 operator/(const T& rhs) const
     {
         return tvec3(*this) /= rhs;
     }
 
+    // Component-wise divide of this by another vector.
+    // Return a reference to this.
     tvec3& operator/=(const tvec3& rhs)
     {
         x_ /= rhs.x_;
@@ -243,11 +298,14 @@ 
         return *this;
     }
 
+    // Component-wise divide of a copy of this by another vector.
+    // Return the copy.
     const tvec3 operator/(const tvec3& rhs) const
     {
         return tvec3(*this) /= rhs;
     }
 
+    // Multiply this by a scalar.  Return a reference to this.
     tvec3& operator*=(const T& rhs)
     {
         x_ *= rhs;
@@ -256,11 +314,14 @@ 
         return *this;
     }
 
+    // Multiply a copy of this by a scalar.  Return the copy.
     const tvec3 operator*(const T& rhs) const
     {
         return tvec3(*this) *= rhs;
     }
 
+    // Component-wise multiply of this by another vector.
+    // Return a reference to this.
     tvec3& operator*=(const tvec3& rhs)
     {
         x_ *= rhs.x_;
@@ -269,11 +330,14 @@ 
         return *this;
     }
 
+    // Component-wise multiply of a copy of this by another vector.
+    // Return the copy.
     const tvec3 operator*(const tvec3& rhs) const
     {
         return tvec3(*this) *= rhs;
     }
 
+    // Add a scalar to this.  Return a reference to this.
     tvec3& operator+=(const T& rhs)
     {
         x_ += rhs;
@@ -282,11 +346,14 @@ 
         return *this;
     }
 
+    // Add a scalar to a copy of this.  Return the copy.
     const tvec3 operator+(const T& rhs) const
     {
         return tvec3(*this) += rhs;
     }
 
+    // Component-wise addition of another vector to this.
+    // Return a reference to this.
     tvec3& operator+=(const tvec3& rhs)
     {
         x_ += rhs.x_;
@@ -295,11 +362,14 @@ 
         return *this;
     }
 
+    // Component-wise addition of another vector to a copy of this.
+    // Return the copy.
     const tvec3 operator+(const tvec3& rhs) const
     {
         return tvec3(*this) += rhs;
     }
 
+    // Subtract a scalar from this.  Return a reference to this.
     tvec3& operator-=(const T& rhs)
     {
         x_ -= rhs;
@@ -308,11 +378,14 @@ 
         return *this;
     }
 
+    // Subtract a scalar from a copy of this.  Return the copy.
     const tvec3 operator-(const T& rhs) const
     {
         return tvec3(*this) -= rhs;
     }
 
+    // Component-wise subtraction of another vector from this.
+    // Return a reference to this.
     tvec3& operator-=(const tvec3& rhs)
     {
         x_ -= rhs.x_;
@@ -321,16 +394,20 @@ 
         return *this;
     }
 
+    // Component-wise subtraction of another vector from a copy of this.
+    // Return the copy.
     const tvec3 operator-(const tvec3& rhs) const
     {
         return tvec3(*this) -= rhs;
     }
 
+    // Compute the length of this and return it.
     float length() const
     {
         return sqrt(dot(*this, *this));
     }
 
+    // Make this a unit vector.
     void normalize()
     {
         float l = length();
@@ -339,11 +416,13 @@ 
         z_ /= l;
     }
 
+    // Compute the dot product of two vectors.
     static T dot(const tvec3& v1, const tvec3& v2)
     {
         return (v1.x_ * v2.x_) + (v1.y_ * v2.y_) + (v1.z_ * v2.z_); 
     }
 
+    // Compute the cross product of two vectors.
     static tvec3 cross(const tvec3& u, const tvec3& v)
     {
         return tvec3((u.y_ * v.z_) - (u.z_ * v.y_),
@@ -357,6 +436,10 @@ 
     T z_;
 };
 
+// A template class for creating, managing and operating on a 4-element vector
+// of any type you like (intended for built-in types, but as long as it 
+// supports the basic arithmetic and assignment operators, any type should
+// work).
 template<typename T>
 class tvec4
 {
@@ -366,12 +449,12 @@ 
         y_(0),
         z_(0),
         w_(0) {}
-    tvec4(T t) :
+    tvec4(const T t) :
         x_(t),
         y_(t),
         z_(t),
         w_(t) {}
-    tvec4(T x, T y, T z, T w) :
+    tvec4(const T x, const T y, const T z, const T w) :
         x_(x),
         y_(y),
         z_(z),
@@ -383,12 +466,19 @@ 
         w_(v.w_) {}
     ~tvec4() {}
 
+    // Print the elements of the vector to standard out.
+    // Really only useful for debug and test.
     void print() const
     {
         std::cout << "| " << x_ << " " << y_ << " " << z_ << " " << w_ << " |" << std::endl;
     }
+
+    // Allow raw data access for API calls and the like.
+    // For example, it is valid to pass a tvec4<float> into a call to
+    // the OpenGL command "glUniform4fv()".
     operator const T*() const { return &x_;}
 
+    // Get and set access members for the individual elements.
     const T x() const { return x_; }
     const T y() const { return y_; }
     const T z() const { return z_; }
@@ -399,6 +489,7 @@ 
     void z(const T& val) { z_ = val; }
     void w(const T& val) { w_ = val; }
 
+    // A direct assignment of 'rhs' to this.  Return a reference to this.
     tvec4& operator=(const tvec4& rhs)
     {
         if (this != &rhs)
@@ -411,6 +502,7 @@ 
         return *this;
     }
 
+    // Divide this by a scalar.  Return a reference to this.
     tvec4& operator/=(const T& rhs)
     {
         x_ /= rhs;
@@ -420,11 +512,14 @@ 
         return *this;
     }
 
+    // Divide a copy of this by a scalar.  Return the copy.
     const tvec4 operator/(const T& rhs) const
     {
         return tvec4(*this) /= rhs;
     }
 
+    // Component-wise divide of this by another vector.
+    // Return a reference to this.
     tvec4& operator/=(const tvec4& rhs)
     {
         x_ /= rhs.x_;
@@ -434,11 +529,14 @@ 
         return *this;
     }
 
+    // Component-wise divide of a copy of this by another vector.
+    // Return the copy.
     const tvec4 operator/(const tvec4& rhs) const
     {
         return tvec4(*this) /= rhs;
     }
 
+    // Multiply this by a scalar.  Return a reference to this.
     tvec4& operator*=(const T& rhs)
     {
         x_ *= rhs;
@@ -448,11 +546,14 @@ 
         return *this;
     }
 
+    // Multiply a copy of this by a scalar.  Return the copy.
     const tvec4 operator*(const T& rhs) const
     {
         return tvec4(*this) *= rhs;
     }
 
+    // Component-wise multiply of this by another vector.
+    // Return a reference to this.
     tvec4& operator*=(const tvec4& rhs)
     {
         x_ *= rhs.x_;
@@ -462,11 +563,14 @@ 
         return *this;
     }
 
+    // Component-wise multiply of a copy of this by another vector.
+    // Return the copy.
     const tvec4 operator*(const tvec4& rhs) const
     {
         return tvec4(*this) *= rhs;
     }
 
+    // Add a scalar to this.  Return a reference to this.
     tvec4& operator+=(const T& rhs)
     {
         x_ += rhs;
@@ -476,11 +580,14 @@ 
         return *this;
     }
 
+    // Add a scalar to a copy of this.  Return the copy.
     const tvec4 operator+(const T& rhs) const
     {
         return tvec4(*this) += rhs;
     }
 
+    // Component-wise addition of another vector to this.
+    // Return a reference to this.
     tvec4& operator+=(const tvec4& rhs)
     {
         x_ += rhs.x_;
@@ -490,11 +597,14 @@ 
         return *this;
     }
 
+    // Component-wise addition of another vector to a copy of this.
+    // Return the copy.
     const tvec4 operator+(const tvec4& rhs) const
     {
         return tvec4(*this) += rhs;
     }
 
+    // Subtract a scalar from this.  Return a reference to this.
     tvec4& operator-=(const T& rhs)
     {
         x_ -= rhs;
@@ -504,11 +614,14 @@ 
         return *this;
     }
 
+    // Subtract a scalar from a copy of this.  Return the copy.
     const tvec4 operator-(const T& rhs) const
     {
         return tvec4(*this) -= rhs;
     }
 
+    // Component-wise subtraction of another vector from this.
+    // Return a reference to this.
     tvec4& operator-=(const tvec4& rhs)
     {
         x_ -= rhs.x_;
@@ -518,16 +631,20 @@ 
         return *this;
     }
 
+    // Component-wise subtraction of another vector from a copy of this.
+    // Return the copy.
     const tvec4 operator-(const tvec4& rhs) const
     {
         return tvec4(*this) -= rhs;
     }
 
+    // Compute the length of this and return it.
     float length() const
     {
         return sqrt(dot(*this, *this));
     }
 
+    // Make this a unit vector.
     void normalize()
     {
         float l = length();
@@ -537,6 +654,7 @@ 
         w_ /= l;
     }
 
+    // Compute the dot product of two vectors.
     static T dot(const tvec4& v1, const tvec4& v2)
     {
         return (v1.x_ * v2.x_) + (v1.y_ * v2.y_) + (v1.z_ * v2.z_) + (v1.w_ * v2.w_); 
@@ -575,4 +693,24 @@ 
 
 } // namespace LibMatrix
 
+// Global operators to allow for things like defining a new vector in terms of
+// a product of a scalar and a vector
+template<typename T>
+const LibMatrix::tvec2<T> operator*(const T t, const LibMatrix::tvec2<T>& v)
+{
+    return v * t;
+}
+
+template<typename T>
+const LibMatrix::tvec3<T> operator*(const T t, const LibMatrix::tvec3<T>& v)
+{
+    return v * t;
+}
+
+template<typename T>
+const LibMatrix::tvec4<T> operator*(const T t, const LibMatrix::tvec4<T>& v)
+{
+    return v * t;
+}
+
 #endif // VEC_H_

=== removed file 'src/log.cpp'
--- src/log.cpp	2011-11-11 10:36:48 +0000
+++ src/log.cpp	1970-01-01 00:00:00 +0000
@@ -1,182 +0,0 @@ 
-/*
- * 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 <cstdio>
-#include <cstdarg>
-#include <string>
-#include <sstream>
-
-#include "options.h"
-#include "log.h"
-
-#ifdef ANDROID
-#include <android/log.h>
-#endif
-
-#ifndef ANDROID
-
-static const char *terminal_color_normal("\033[0m");
-static const char *terminal_color_red("\033[1;31m");
-static const char *terminal_color_cyan("\033[36m");
-static const char *terminal_color_yellow("\033[33m");
-
-static void
-print_prefixed_message(FILE *stream, const char *color, const char *prefix,
-                       const char *fmt, va_list ap)
-{
-    va_list aq;
-
-    /* Estimate message size */
-    va_copy(aq, ap);
-    int msg_size = vsnprintf(NULL, 0, fmt, aq);
-    va_end(aq);
-
-    /* Create the buffer to hold the message */
-    char *buf = new char[msg_size + 1];
-
-    /* Store the message in the buffer */
-    va_copy(aq, ap);
-    vsnprintf(buf, msg_size + 1, fmt, aq);
-    va_end(aq);
-
-    /*
-     * Print the message lines prefixed with the supplied prefix.
-     * If the target stream is a terminal make the prefix colored.
-     */
-    bool use_color = isatty(fileno(stream));
-    const char *start_color(use_color ? color : "");
-    const char *end_color(use_color && *color ? terminal_color_normal : "");
-
-    std::string line;
-    std::stringstream ss(buf);
-
-    while(std::getline(ss, line)) {
-        /*
-         * If this line is a continuation of a previous log message
-         * just print the line plainly.
-         */
-        if (line[0] == LOG_CONTINUE[0]) {
-            fprintf(stream, "%s", line.c_str() + 1);
-        }
-        else {
-            /* Normal line, emit the prefix. */
-            fprintf(stream, "%s%s%s: %s", start_color, prefix, end_color,
-                    line.c_str());
-        }
-
-        /* Only emit a newline if the original message has it. */
-        if (!(ss.rdstate() & std::stringstream::eofbit))
-            fputs("\n", stream);
-    }
-
-    delete[] buf;
-}
-
-static void
-print_plain_message(FILE *stream, const char *fmt, va_list ap)
-{
-    va_list aq;
-    const char *msg = fmt;
-
-    if (msg[0] == LOG_CONTINUE[0])
-        msg++;
-
-    va_copy(aq, ap);
-    vfprintf(stream, msg, ap);
-    va_end(aq);
-}
-
-void
-Log::info(const char *fmt, ...)
-{
-    va_list ap;
-    va_start(ap, fmt);
-    if (Options::show_debug)
-        print_prefixed_message(stdout, terminal_color_cyan, "Info", fmt, ap);
-    else
-        print_plain_message(stdout, fmt, ap);
-    va_end(ap);
-}
-
-void
-Log::debug(const char *fmt, ...)
-{
-    if (!Options::show_debug)
-        return;
-    va_list ap;
-    va_start(ap, fmt);
-    print_prefixed_message(stdout, terminal_color_yellow, "Debug", fmt, ap);
-    va_end(ap);
-}
-
-void
-Log::error(const char *fmt, ...)
-{
-    va_list ap;
-    va_start(ap, fmt);
-    print_prefixed_message(stderr, terminal_color_red, "Error", fmt, ap);
-    va_end(ap);
-}
-
-void
-Log::flush()
-{
-    fflush(stdout);
-    fflush(stderr);
-}
-#else
-void
-Log::info(const char *fmt, ...)
-{
-    va_list ap;
-    va_start(ap, fmt);
-    __android_log_vprint(ANDROID_LOG_INFO, "glmark2", fmt, ap);
-    va_end(ap);
-}
-
-void
-Log::debug(const char *fmt, ...)
-{
-    if (!Options::show_debug)
-        return;
-    va_list ap;
-    va_start(ap, fmt);
-    __android_log_vprint(ANDROID_LOG_DEBUG, "glmark2", fmt, ap);
-    va_end(ap);
-}
-
-void
-Log::error(const char *fmt, ...)
-{
-    va_list ap;
-    va_start(ap, fmt);
-    __android_log_vprint(ANDROID_LOG_ERROR, "glmark2", fmt, ap);
-    va_end(ap);
-}
-
-void
-Log::flush()
-{
-}
-
-#endif

=== removed file 'src/log.h'
--- src/log.h	2011-11-10 10:33:26 +0000
+++ src/log.h	1970-01-01 00:00:00 +0000
@@ -1,43 +0,0 @@ 
-/*
- * 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 LOG_H_
-#define LOG_H_
-
-/**
- * A prefix that informs the logging infrastructure that the log
- * message is a continuation of a previous log message to be put
- * on the same line.
- */
-#define LOG_CONTINUE "\x10"
-
-class Log
-{
-public:
-    static void info(const char *fmt, ...);
-    static void debug(const char *fmt, ...);
-    static void error(const char *fmt, ...);
-    static void flush();
-};
-
-#endif /* LOG_H_ */

=== modified file 'src/main.cpp'
--- src/main.cpp	2012-01-19 10:58:18 +0000
+++ src/main.cpp	2012-01-27 22:01:59 +0000
@@ -1,6 +1,6 @@ 
 /*
  * Copyright © 2008 Ben Smith
- * Copyright © 2010-2011 Linaro Limited
+ * Copyright © 2010-2012 Linaro Limited
  *
  * This file is part of the glmark2 OpenGL (ES) 2.0 benchmark.
  *
@@ -20,6 +20,7 @@ 
  * Authors:
  *  Ben Smith (original glmark benchmark)
  *  Alexandros Frantzis (glmark2)
+ *  Jesse Barker (glmark2)
  */
 #include "gl-headers.h"
 #include "scene.h"
@@ -177,6 +178,7 @@ 
     unsigned score = 0;
     unsigned int last_fps = 0;
     unsigned int benchmarks_run = 0;
+    static const string format(Log::continuation_prefix + " FPS: %u\n");
 
     for (vector<Benchmark *>::iterator bench_iter = benchmarks.begin();
          bench_iter != benchmarks.end();
@@ -219,7 +221,7 @@ 
                 canvas.update();
             }
 
-            Log::info(LOG_CONTINUE" FPS: %u\n", scene.average_fps());
+            Log::info(format.c_str(), scene.average_fps());
             score += scene.average_fps();
             benchmarks_run++;
         }
@@ -242,6 +244,7 @@ 
 void
 do_validation(Canvas &canvas, vector<Benchmark *> &benchmarks)
 {
+    static const string format(Log::continuation_prefix + " Validation: %s\n");
     for (vector<Benchmark *>::iterator bench_iter = benchmarks.begin();
          bench_iter != benchmarks.end();
          bench_iter++)
@@ -275,7 +278,7 @@ 
                     break;
             }
 
-            Log::info(LOG_CONTINUE" Validation: %s\n", result.c_str());
+            Log::info(format.c_str(), result.c_str());
         }
 
         bench->teardown_scene();
@@ -289,6 +292,9 @@ 
     if (!Options::parse_args(argc, argv))
         return 1;
 
+    /* Initialize Log class */
+    Log::init(Util::appname_from_path(argv[0]), Options::show_debug);
+
     if (Options::show_help) {
         Options::print_help();
         return 0;

=== modified file 'src/options.cpp'
--- src/options.cpp	2012-01-18 17:13:28 +0000
+++ src/options.cpp	2012-01-27 12:10:17 +0000
@@ -1,5 +1,5 @@ 
 /*
- * Copyright © 2011 Linaro Limited
+ * Copyright © 2011-2012 Linaro Limited
  *
  * This file is part of glcompbench.
  *
@@ -29,7 +29,6 @@ 
 
 #include "options.h"
 #include "util.h"
-#include "log.h"
 
 std::vector<std::string> Options::benchmarks;
 std::vector<std::string> Options::benchmark_files;

=== modified file 'src/scene-effect-2d.cpp'
--- src/scene-effect-2d.cpp	2011-12-08 11:09:09 +0000
+++ src/scene-effect-2d.cpp	2012-01-26 17:36:24 +0000
@@ -1,5 +1,5 @@ 
 /*
- * Copyright © 2010-2011 Linaro Limited
+ * Copyright © 2010-2012 Linaro Limited
  *
  * This file is part of the glmark2 OpenGL (ES) 2.0 benchmark.
  *
@@ -196,6 +196,9 @@ 
     Util::split(str, ';', rows);
 
     Log::debug("Parsing kernel matrix:\n");
+    static const std::string format("%f ");
+    static const std::string format_cont(Log::continuation_prefix + format);
+    static const std::string newline(Log::continuation_prefix + "\n");
 
     for (std::vector<std::string>::const_iterator iter = rows.begin();
          iter != rows.end();
@@ -220,12 +223,12 @@ 
             float f(Util::fromString<float>(*iter_el));
             matrix.push_back(f);
             if (iter_el == elems.begin())
-                Log::debug("%f ", f);
+                Log::debug(format.c_str(), f);
             else
-                Log::debug(LOG_CONTINUE"%f ", f);
+                Log::debug(format_cont.c_str(), f);
         }
 
-        Log::debug(LOG_CONTINUE"\n");
+        Log::debug(newline.c_str());
     }
 
     width = w;

=== removed file 'src/shader-source.cpp'
--- src/shader-source.cpp	2011-12-12 12:39:00 +0000
+++ src/shader-source.cpp	1970-01-01 00:00:00 +0000
@@ -1,625 +0,0 @@ 
-/*
- * 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;
-
-    /* Ensure we have tried to infer the type from the contents */
-    type();
-
-    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;
-        }
-    }
-}

=== removed file 'src/shader-source.h'
--- src/shader-source.h	2011-11-29 10:36:37 +0000
+++ src/shader-source.h	1970-01-01 00:00:00 +0000
@@ -1,113 +0,0 @@ 
-/*
- * 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_;
-};

=== removed file 'src/util.cpp'
--- src/util.cpp	2011-11-08 20:41:46 +0000
+++ src/util.cpp	1970-01-01 00:00:00 +0000
@@ -1,164 +0,0 @@ 
-/*
- * 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>
-#ifdef ANDROID
-#include <android/asset_manager.h>
-#else
-#include <dirent.h>
-#endif
-
-#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;
-}
-
-#ifndef ANDROID
-
-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);
-}
-
-#else
-
-AAssetManager *Util::android_asset_manager = 0;
-
-void
-Util::android_set_asset_manager(AAssetManager *asset_manager)
-{
-    Util::android_asset_manager = asset_manager;
-}
-
-AAssetManager *
-Util::android_get_asset_manager()
-{
-    return Util::android_asset_manager;
-}
-
-std::istream *
-Util::get_resource(const std::string &path)
-{
-    std::string path2(path);
-    /* Remove leading '/' from path name, it confuses the AssetManager */
-    if (path2.size() > 0 && path2[0] == '/')
-        path2.erase(0, 1);
-
-    std::stringstream *ss = new std::stringstream;
-    AAsset *asset = AAssetManager_open(Util::android_asset_manager,
-                                       path2.c_str(), AASSET_MODE_RANDOM);
-    if (asset) {
-        ss->write(reinterpret_cast<const char *>(AAsset_getBuffer(asset)),
-                  AAsset_getLength(asset));
-        Log::debug("Load asset %s\n", path2.c_str());
-        AAsset_close(asset);
-    }
-    else {
-        Log::error("Couldn't load asset %s\n", path2.c_str());
-    }
-
-    return static_cast<std::istream *>(ss);
-}
-
-void
-Util::list_files(const std::string& dirName, std::vector<std::string>& fileVec)
-{
-    AAssetManager *mgr(Util::android_get_asset_manager());
-    std::string dir_name(dirName);
-
-    /* Remove leading '/' from path, it confuses the AssetManager */
-    if (dir_name.size() > 0 && dir_name[0] == '/')
-        dir_name.erase(0, 1);
-
-    AAssetDir* dir = AAssetManager_openDir(mgr, dir_name.c_str());
-    if (!dir)
-    {
-        Log::error("Failed to open models directory '%s'\n", dir_name.c_str());
-        return;
-    }
-
-    const char *filename(0);
-    while ((filename = AAssetDir_getNextFileName(dir)) != 0)
-    {
-        std::string pathname(dir_name + "/");
-        pathname += std::string(filename);
-        fileVec.push_back(pathname);
-    }
-    AAssetDir_close(dir);
-}
-#endif

=== removed file 'src/util.h'
--- src/util.h	2011-11-08 20:41:46 +0000
+++ src/util.h	1970-01-01 00:00:00 +0000
@@ -1,81 +0,0 @@ 
-/*
- * 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>
-
-#ifdef ANDROID
-#include <android/asset_manager_jni.h>
-#endif
-
-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();
-    }
-
-
-#ifdef ANDROID
-    static void android_set_asset_manager(AAssetManager *asset_manager);
-    static AAssetManager *android_get_asset_manager(void);
-private:
-    static AAssetManager *android_asset_manager;
-#endif
-};
-
-#endif /* UTIL_H */

=== modified file 'src/wscript_build'
--- src/wscript_build	2011-08-16 07:50:49 +0000
+++ src/wscript_build	2012-01-26 17:00:43 +0000
@@ -22,7 +22,7 @@ 
         target       = 'glmark2',
         use          = ['x11', 'gl', 'matrix', 'libpng12'],
         lib          = ['m'],
-        defines      = ['USE_GL']
+        defines      = ['USE_GL', 'USE_EXCEPTIONS']
         )
 
 if bld.env.USE_GLESv2:
@@ -41,5 +41,5 @@ 
         target       = 'glmark2-es2',
         use          = ['x11', 'egl', 'glesv2', 'matrix-es2', 'libpng12'],
         lib          = ['m', 'dl'],
-        defines      = ['USE_GLESv2']
+        defines      = ['USE_GLESv2', 'USE_EXCEPTIONS']
         )