From patchwork Fri Jan 27 22:15:18 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Jesse Barker X-Patchwork-Id: 6428 Return-Path: X-Original-To: patchwork@peony.canonical.com Delivered-To: patchwork@peony.canonical.com Received: from fiordland.canonical.com (fiordland.canonical.com [91.189.94.145]) by peony.canonical.com (Postfix) with ESMTP id B0D1923F8D for ; Fri, 27 Jan 2012 22:15:21 +0000 (UTC) Received: from mail-bk0-f52.google.com (mail-bk0-f52.google.com [209.85.214.52]) by fiordland.canonical.com (Postfix) with ESMTP id 73F17A1805A for ; Fri, 27 Jan 2012 22:15:21 +0000 (UTC) Received: by bkar19 with SMTP id r19so2396407bka.11 for ; Fri, 27 Jan 2012 14:15:21 -0800 (PST) Received: by 10.204.200.197 with SMTP id ex5mr3847109bkb.128.1327702519288; Fri, 27 Jan 2012 14:15:19 -0800 (PST) X-Forwarded-To: linaro-patchwork@canonical.com X-Forwarded-For: patch@linaro.org linaro-patchwork@canonical.com Delivered-To: patches@linaro.org Received: by 10.204.130.220 with SMTP id u28cs86652bks; Fri, 27 Jan 2012 14:15:18 -0800 (PST) Received: by 10.180.84.201 with SMTP id b9mr13924091wiz.4.1327702518524; Fri, 27 Jan 2012 14:15:18 -0800 (PST) Received: from indium.canonical.com (indium.canonical.com. [91.189.90.7]) by mx.google.com with ESMTPS id v57si7519925weq.52.2012.01.27.14.15.18 (version=TLSv1/SSLv3 cipher=OTHER); Fri, 27 Jan 2012 14:15:18 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of bounces@canonical.com designates 91.189.90.7 as permitted sender) client-ip=91.189.90.7; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of bounces@canonical.com designates 91.189.90.7 as permitted sender) smtp.mail=bounces@canonical.com Received: from ackee.canonical.com ([91.189.89.26]) by indium.canonical.com with esmtp (Exim 4.71 #1 (Debian)) id 1Rqu4k-0004zh-74 for ; Fri, 27 Jan 2012 22:15:18 +0000 Received: from ackee.canonical.com (localhost [127.0.0.1]) by ackee.canonical.com (Postfix) with ESMTP id 1E57CE0785 for ; Fri, 27 Jan 2012 22:15:18 +0000 (UTC) MIME-Version: 1.0 X-Launchpad-Project: glmark2 X-Launchpad-Branch: ~glmark2-dev/glmark2/trunk X-Launchpad-Message-Rationale: Subscriber X-Launchpad-Branch-Revision-Number: 193 X-Launchpad-Notification-Type: branch-revision To: Linaro Patch Tracker From: noreply@launchpad.net Subject: [Branch ~glmark2-dev/glmark2/trunk] Rev 193: Merge of lp:~glmark2-dev/glmark2/libmatrix-util. Message-Id: <20120127221518.3499.84892.launchpad@ackee.canonical.com> Date: Fri, 27 Jan 2012 22:15:18 -0000 Reply-To: noreply@launchpad.net Sender: bounces@canonical.com Errors-To: bounces@canonical.com Precedence: bulk X-Generated-By: Launchpad (canonical.com); Revision="14727"; Instance="launchpad-lazr.conf" X-Launchpad-Hash: 3b93d41ef42605bfab3575a2f607f5923d0256ef 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 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 === 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 +// Jesse Barker +// +#include +#include +#include +#include +#include +#include "log.h" + +#ifdef ANDROID +#include +#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 +// Jesse Barker +// +#ifndef LOG_H_ +#define LOG_H_ + +#include + +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 #include #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 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(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 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 operator[](int index) { return ArrayProxy(&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 const tmat2 operator*(const T& lhs, const tmat2& rhs) { return tmat2(rhs) * lhs; } +// Multiply a copy of a vector and a matrix (matrix is right-hand operand). +// Return the copy. template const tvec2 operator*(const tvec2& lhs, const tmat2& rhs) { @@ -259,6 +304,8 @@ return tvec2(x,y); } +// Multiply a copy of a vector and a matrix (matrix is left-hand operand). +// Return the copy. template const tvec2 operator*(const tmat2& lhs, const tvec2& rhs) { @@ -267,6 +314,7 @@ return tvec2(x, y); } +// Compute the outer product of two vectors. Return the resultant matrix. template const tmat2 outer(const tvec2& a, const tvec2& 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 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 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(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 minor0(m_[4], m_[5], m_[7], m_[8]); tmat2 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 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 operator[](int index) { return ArrayProxy(&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 const tmat3 operator*(const T& lhs, const tmat3& rhs) { return tmat3(rhs) * lhs; } +// Multiply a copy of a vector and a matrix (matrix is right-hand operand). +// Return the copy. template const tvec3 operator*(const tvec3& lhs, const tmat3& rhs) { @@ -582,6 +669,8 @@ return tvec3(x, y, z); } +// Multiply a copy of a vector and a matrix (matrix is left-hand operand). +// Return the copy. template const tvec3 operator*(const tmat3& lhs, const tvec3& rhs) { @@ -591,6 +680,7 @@ return tvec3(x, y, z); } +// Compute the outer product of two vectors. Return the resultant matrix. template const tmat3 outer(const tvec3& a, const tvec3& 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 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 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(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 minor0(m_[5], m_[6], m_[7], m_[9], m_[10], m_[11], m_[13], m_[14], m_[15]); tmat3 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 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 operator[](int index) { return ArrayProxy(&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 const tmat4 operator*(const T& lhs, const tmat4& rhs) { return tmat4(rhs) * lhs; } +// Multiply a copy of a vector and a matrix (matrix is right-hand operand). +// Return the copy. template const tvec4 operator*(const tvec4& lhs, const tmat4& rhs) { @@ -1012,6 +1141,8 @@ return tvec4(x, y, z, w); } +// Multiply a copy of a vector and a matrix (matrix is left-hand operand). +// Return the copy. template const tvec4 operator*(const tmat4& lhs, const tvec4& rhs) { @@ -1022,6 +1153,7 @@ return tvec4(x, y, z, w); } +// Compute the outer product of two vectors. Return the resultant matrix. template const tmat4 outer(const tvec4& a, const tvec4& 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 -#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 #include #include - -#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, ¶m); @@ -95,7 +73,7 @@ if (param == GL_FALSE) { glGetShaderiv(handle_, GL_INFO_LOG_LENGTH, ¶m); - 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, ¶m); - 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 +// Jesse Barker +// +#include +#include + +#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::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 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 &array, + const std::string &function) +{ + std::stringstream ss; + + ss << "const float " << name << "[" << array.size() << "] = {" << std::fixed; + for(std::vector::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 &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::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: + * ",,," + * + * 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 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 +// Jesse Barker +// +#include +#include +#include +#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 &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 &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 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 +#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 +#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 +#include +#include +#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 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::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 +#include +#include +#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 +#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 +#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 +// Jesse Barker +// +#include +#include +#include +#ifdef ANDROID +#include +#else +#include +#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 &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(tv.tv_sec) * 1000000 + + static_cast(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(ifs); +} + +void +Util::list_files(const std::string& dirName, std::vector& 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(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(ss); +} + +void +Util::list_files(const std::string& dirName, std::vector& 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 +// Jesse Barker +// +#ifndef UTIL_H_ +#define UTIL_H_ + +#include +#include +#include +#include +#include + +#ifdef ANDROID +#include +#endif + +struct Util { + static void split(const std::string &s, char delim, std::vector &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& fileVec); + template static void dispose_pointer_vector(std::vector &vec) + { + for (typename std::vector::const_iterator iter = vec.begin(); + iter != vec.end(); + iter++) + { + delete *iter; + } + + vec.clear(); + } + template + static T + fromString(const std::string& asString) + { + std::stringstream ss(asString); + T retVal; + ss >> retVal; + return retVal; + } + + template + 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 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 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 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 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 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 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 +const LibMatrix::tvec2 operator*(const T t, const LibMatrix::tvec2& v) +{ + return v * t; +} + +template +const LibMatrix::tvec3 operator*(const T t, const LibMatrix::tvec3& v) +{ + return v * t; +} + +template +const LibMatrix::tvec4 operator*(const T t, const LibMatrix::tvec4& 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 . - * - * Authors: - * Alexandros Frantzis - * Jesse Barker - */ - -#include -#include -#include -#include - -#include "options.h" -#include "log.h" - -#ifdef ANDROID -#include -#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 . - * - * Authors: - * Alexandros Frantzis - * Jesse Barker - */ - -#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::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 &benchmarks) { + static const string format(Log::continuation_prefix + " Validation: %s\n"); for (vector::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 Options::benchmarks; std::vector 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::const_iterator iter = rows.begin(); iter != rows.end(); @@ -220,12 +223,12 @@ float f(Util::fromString(*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 . - * - * Authors: - * Alexandros Frantzis (glmark2) - */ - -#include -#include - -#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::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 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 &array, - const std::string &function) -{ - std::stringstream ss; - - ss << "const float " << name << "[" << array.size() << "] = {" << std::fixed; - for(std::vector::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 &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::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: - * ",,," - * - * 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 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 . - * - * Authors: - * Alexandros Frantzis (glmark2) - */ - -#include -#include -#include -#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 &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 &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 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 . - * - * Authors: - * Alexandros Frantzis - * Jesse Barker - */ - -#include -#include -#include -#ifdef ANDROID -#include -#else -#include -#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 &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(tv.tv_sec) * 1000000 + - static_cast(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(ifs); -} - -void -Util::list_files(const std::string& dirName, std::vector& 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(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(ss); -} - -void -Util::list_files(const std::string& dirName, std::vector& 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 . - * - * Authors: - * Alexandros Frantzis - * Jesse Barker - */ - -#ifndef UTIL_H_ -#define UTIL_H_ - -#include -#include -#include -#include -#include - -#ifdef ANDROID -#include -#endif - -struct Util { - static void split(const std::string &s, char delim, std::vector &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& fileVec); - template static void dispose_pointer_vector(std::vector &vec) - { - for (typename std::vector::const_iterator iter = vec.begin(); - iter != vec.end(); - iter++) - { - delete *iter; - } - - vec.clear(); - } - template - static T - fromString(const std::string& asString) - { - std::stringstream ss(asString); - T retVal; - ss >> retVal; - return retVal; - } - - template - 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'] )