Add SwiftShader dump from Feb 6 2013
diff --git a/src/GLES2/common/debug.cpp b/src/GLES2/common/debug.cpp
new file mode 100644
index 0000000..4ccb313
--- /dev/null
+++ b/src/GLES2/common/debug.cpp
@@ -0,0 +1,41 @@
+// SwiftShader Software Renderer

+//

+// Copyright(c) 2005-2012 TransGaming Inc.

+//

+// All rights reserved. No part of this software may be copied, distributed, transmitted,

+// transcribed, stored in a retrieval system, translated into any human or computer

+// language by any means, or disclosed to third parties without the explicit written

+// agreement of TransGaming Inc. Without such an agreement, no rights or licenses, express

+// or implied, including but not limited to any patent rights, are granted to you.

+//

+

+// debug.cpp: Debugging utilities.

+

+#include "common/debug.h"

+

+#include <stdio.h>

+#include <stdarg.h>

+

+namespace gl

+{

+	static void output(const char *format, va_list vararg)

+	{

+		#if 0

+			FILE* file = fopen(TRACE_OUTPUT_FILE, "a");

+

+			if(file)

+			{

+				vfprintf(file, format, vararg);

+				fclose(file);

+			}

+		#endif

+	}

+

+	void trace(const char *format, ...)

+	{

+		va_list vararg;

+		va_start(vararg, format);

+		output(format, vararg);

+		va_end(vararg);

+	}

+}

diff --git a/src/GLES2/common/debug.h b/src/GLES2/common/debug.h
new file mode 100644
index 0000000..2f5302c
--- /dev/null
+++ b/src/GLES2/common/debug.h
@@ -0,0 +1,86 @@
+// SwiftShader Software Renderer

+//

+// Copyright(c) 2005-2012 TransGaming Inc.

+//

+// All rights reserved. No part of this software may be copied, distributed, transmitted,

+// transcribed, stored in a retrieval system, translated into any human or computer

+// language by any means, or disclosed to third parties without the explicit written

+// agreement of TransGaming Inc. Without such an agreement, no rights or licenses, express

+// or implied, including but not limited to any patent rights, are granted to you.

+//

+

+// debug.h: Debugging utilities.

+

+#ifndef COMMON_DEBUG_H_

+#define COMMON_DEBUG_H_

+

+#include <stdio.h>

+#include <assert.h>

+

+#if !defined(TRACE_OUTPUT_FILE)

+#define TRACE_OUTPUT_FILE "debug.txt"

+#endif

+

+namespace gl

+{

+    // Outputs text to the debugging log

+    void trace(const char *format, ...);

+}

+

+// A macro to output a trace of a function call and its arguments to the debugging log

+#if defined(ANGLE_DISABLE_TRACE)

+#define TRACE(message, ...) (void(0))

+#else

+#define TRACE(message, ...) gl::trace("trace: %s(%d): "message"\n", __FUNCTION__, __LINE__, ##__VA_ARGS__)

+#endif

+

+// A macro to output a function call and its arguments to the debugging log, to denote an item in need of fixing.

+#if defined(ANGLE_DISABLE_TRACE)

+#define FIXME(message, ...) (void(0))

+#else

+#define FIXME(message, ...) do {gl::trace("fixme: %s(%d): "message"\n", __FUNCTION__, __LINE__, ##__VA_ARGS__); assert(false);} while(false)

+#endif

+

+// A macro to output a function call and its arguments to the debugging log, in case of error.

+#if defined(ANGLE_DISABLE_TRACE)

+#define ERR(message, ...) (void(0))

+#else

+#define ERR(message, ...) do {gl::trace("err: %s(%d): "message"\n", __FUNCTION__, __LINE__, ##__VA_ARGS__); assert(false);} while(false)

+#endif

+

+// A macro asserting a condition and outputting failures to the debug log

+#if !defined(NDEBUG)

+#define ASSERT(expression) do { \

+    if(!(expression)) \

+        ERR("\t! Assert failed in %s(%d): "#expression"\n", __FUNCTION__, __LINE__); \

+        assert(expression); \

+    } while(0)

+#else

+#define ASSERT(expression) (void(0))

+#endif

+

+// A macro to indicate unimplemented functionality

+#if !defined(NDEBUG)

+#define UNIMPLEMENTED() do { \

+    FIXME("\t! Unimplemented: %s(%d)\n", __FUNCTION__, __LINE__); \

+    assert(false); \

+    } while(0)

+#else

+    #define UNIMPLEMENTED() FIXME("\t! Unimplemented: %s(%d)\n", __FUNCTION__, __LINE__)

+#endif

+

+// A macro for code which is not expected to be reached under valid assumptions

+

+#if !defined(NDEBUG)

+#define UNREACHABLE() do { \

+    ERR("\t! Unreachable reached: %s(%d)\n", __FUNCTION__, __LINE__); \

+    assert(false); \

+    } while(0)

+#else

+    #define UNREACHABLE() ERR("\t! Unreachable reached: %s(%d)\n", __FUNCTION__, __LINE__)

+#endif

+

+// A macro functioning as a compile-time assert to validate constant conditions

+#define META_ASSERT(condition) typedef int COMPILE_TIME_ASSERT_##__LINE__[static_cast<bool>(condition) ? 1 : -1]

+

+#endif   // COMMON_DEBUG_H_

diff --git a/src/GLES2/compiler/BaseTypes.h b/src/GLES2/compiler/BaseTypes.h
new file mode 100644
index 0000000..3334436
--- /dev/null
+++ b/src/GLES2/compiler/BaseTypes.h
@@ -0,0 +1,148 @@
+//
+// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#ifndef _BASICTYPES_INCLUDED_
+#define _BASICTYPES_INCLUDED_
+
+//
+// Precision qualifiers
+//
+enum TPrecision
+{
+    // These need to be kept sorted
+    EbpUndefined,
+    EbpLow,
+    EbpMedium,
+    EbpHigh,
+};
+
+inline const char* getPrecisionString(TPrecision p)
+{
+    switch(p)
+    {
+    case EbpHigh:		return "highp";		break;
+    case EbpMedium:		return "mediump";	break;
+    case EbpLow:		return "lowp";		break;
+    default:			return "mediump";   break;   // Safest fallback
+    }
+}
+
+//
+// Basic type.  Arrays, vectors, etc., are orthogonal to this.
+//
+enum TBasicType
+{
+    EbtVoid,
+    EbtFloat,
+    EbtInt,
+    EbtBool,
+    EbtGuardSamplerBegin,  // non type:  see implementation of IsSampler()
+    EbtSampler2D,
+    EbtSamplerCube,
+    EbtGuardSamplerEnd,    // non type:  see implementation of IsSampler()
+    EbtStruct,
+    EbtAddress,            // should be deprecated??
+    EbtInvariant,          // used as a type when qualifying a previously declared variable as being invariant
+};
+
+inline const char* getBasicString(TBasicType t)
+{
+    switch (t)
+    {
+    case EbtVoid:              return "void";              break;
+    case EbtFloat:             return "float";             break;
+    case EbtInt:               return "int";               break;
+    case EbtBool:              return "bool";              break;
+    case EbtSampler2D:         return "sampler2D";         break;
+    case EbtSamplerCube:       return "samplerCube";       break;
+    case EbtStruct:            return "structure";         break;
+    default:                   return "unknown type";
+    }
+}
+
+inline bool IsSampler(TBasicType type)
+{
+    return type > EbtGuardSamplerBegin && type < EbtGuardSamplerEnd;
+}
+
+//
+// Qualifiers and built-ins.  These are mainly used to see what can be read
+// or written, and by the machine dependent translator to know which registers
+// to allocate variables in.  Since built-ins tend to go to different registers
+// than varying or uniform, it makes sense they are peers, not sub-classes.
+//
+enum TQualifier
+{
+    EvqTemporary,     // For temporaries (within a function), read/write
+    EvqGlobal,        // For globals read/write
+    EvqConst,         // User defined constants and non-output parameters in functions
+    EvqAttribute,     // Readonly
+    EvqVaryingIn,     // readonly, fragment shaders only
+    EvqVaryingOut,    // vertex shaders only  read/write
+    EvqInvariantVaryingIn,     // readonly, fragment shaders only
+    EvqInvariantVaryingOut,    // vertex shaders only  read/write
+    EvqUniform,       // Readonly, vertex and fragment
+
+    // pack/unpack input and output
+    EvqInput,
+    EvqOutput,
+
+    // parameters
+    EvqIn,
+    EvqOut,
+    EvqInOut,
+    EvqConstReadOnly,
+
+    // built-ins written by vertex shader
+    EvqPosition,
+    EvqPointSize,
+
+    // built-ins read by fragment shader
+    EvqFragCoord,
+    EvqFrontFacing,
+    EvqPointCoord,
+
+    // built-ins written by fragment shader
+    EvqFragColor,
+    EvqFragData,
+
+    // end of list
+    EvqLast,
+};
+
+//
+// This is just for debug print out, carried along with the definitions above.
+//
+inline const char* getQualifierString(TQualifier q)
+{
+    switch(q)
+    {
+    case EvqTemporary:      return "Temporary";      break;
+    case EvqGlobal:         return "Global";         break;
+    case EvqConst:          return "const";          break;
+    case EvqConstReadOnly:  return "const";          break;
+    case EvqAttribute:      return "attribute";      break;
+    case EvqVaryingIn:      return "varying";        break;
+    case EvqVaryingOut:     return "varying";        break;
+    case EvqInvariantVaryingIn: return "invariant varying";	break;
+    case EvqInvariantVaryingOut:return "invariant varying";	break;
+    case EvqUniform:        return "uniform";        break;
+    case EvqIn:             return "in";             break;
+    case EvqOut:            return "out";            break;
+    case EvqInOut:          return "inout";          break;
+    case EvqInput:          return "input";          break;
+    case EvqOutput:         return "output";         break;
+    case EvqPosition:       return "Position";       break;
+    case EvqPointSize:      return "PointSize";      break;
+    case EvqFragCoord:      return "FragCoord";      break;
+    case EvqFrontFacing:    return "FrontFacing";    break;
+    case EvqFragColor:      return "FragColor";      break;
+    case EvqFragData:       return "FragData";      break;
+    default:                return "unknown qualifier";
+    }
+}
+
+#endif // _BASICTYPES_INCLUDED_
diff --git a/src/GLES2/compiler/Common.h b/src/GLES2/compiler/Common.h
new file mode 100644
index 0000000..27a5598
--- /dev/null
+++ b/src/GLES2/compiler/Common.h
@@ -0,0 +1,89 @@
+//
+// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#ifndef _COMMON_INCLUDED_
+#define _COMMON_INCLUDED_
+
+#include <map>
+#include <sstream>
+#include <string>
+#include <vector>
+
+#include "compiler/PoolAlloc.h"
+
+// We need two pieces of information to report errors/warnings - string and
+// line number. We encode these into a single int so that it can be easily
+// incremented/decremented by lexer. The right SOURCE_LOC_LINE_SIZE bits store
+// line number while the rest store the string number. Since the shaders are
+// usually small, we should not run out of memory. SOURCE_LOC_LINE_SIZE
+// can be increased to alleviate this issue.
+typedef int TSourceLoc;
+const unsigned int SOURCE_LOC_LINE_SIZE = 16;  // in bits.
+const unsigned int SOURCE_LOC_LINE_MASK = (1 << SOURCE_LOC_LINE_SIZE) - 1;
+
+inline TSourceLoc EncodeSourceLoc(int string, int line) {
+    return (string << SOURCE_LOC_LINE_SIZE) | (line & SOURCE_LOC_LINE_MASK);
+}
+
+inline void DecodeSourceLoc(TSourceLoc loc, int* string, int* line) {
+    if (string) *string = loc >> SOURCE_LOC_LINE_SIZE;
+    if (line) *line = loc & SOURCE_LOC_LINE_MASK;
+}
+
+//
+// Put POOL_ALLOCATOR_NEW_DELETE in base classes to make them use this scheme.
+//
+#define POOL_ALLOCATOR_NEW_DELETE(A)                                  \
+    void* operator new(size_t s) { return (A).allocate(s); }          \
+    void* operator new(size_t, void *_Where) { return (_Where);	}     \
+    void operator delete(void*) { }                                   \
+    void operator delete(void *, void *) { }                          \
+    void* operator new[](size_t s) { return (A).allocate(s); }        \
+    void* operator new[](size_t, void *_Where) { return (_Where);	} \
+    void operator delete[](void*) { }                                 \
+    void operator delete[](void *, void *) { }
+
+//
+// Pool version of string.
+//
+typedef pool_allocator<char> TStringAllocator;
+typedef std::basic_string <char, std::char_traits<char>, TStringAllocator> TString;
+typedef std::basic_ostringstream<char, std::char_traits<char>, TStringAllocator> TStringStream;
+inline TString* NewPoolTString(const char* s)
+{
+	void* memory = GlobalPoolAllocator.allocate(sizeof(TString));
+	return new(memory) TString(s);
+}
+
+//
+// Persistent string memory.  Should only be used for strings that survive
+// across compiles.
+//
+#define TPersistString std::string
+#define TPersistStringStream std::ostringstream
+
+//
+// Pool allocator versions of vectors, lists, and maps
+//
+template <class T> class TVector : public std::vector<T, pool_allocator<T> > {
+public:
+    typedef typename std::vector<T, pool_allocator<T> >::size_type size_type;
+    TVector() : std::vector<T, pool_allocator<T> >() {}
+    TVector(const pool_allocator<T>& a) : std::vector<T, pool_allocator<T> >(a) {}
+    TVector(size_type i): std::vector<T, pool_allocator<T> >(i) {}
+};
+
+template <class K, class D, class CMP = std::less<K> > 
+class TMap : public std::map<K, D, CMP, pool_allocator<std::pair<const K, D> > > {
+public:
+    typedef pool_allocator<std::pair<const K, D> > tAllocator;
+
+    TMap() : std::map<K, D, CMP, tAllocator>() {}
+    // use correct two-stage name lookup supported in gcc 3.4 and above
+    TMap(const tAllocator& a) : std::map<K, D, CMP, tAllocator>(std::map<K, D, CMP, tAllocator>::key_compare(), a) {}
+};
+
+#endif // _COMMON_INCLUDED_
diff --git a/src/GLES2/compiler/Compiler.cpp b/src/GLES2/compiler/Compiler.cpp
new file mode 100644
index 0000000..59e8ffe
--- /dev/null
+++ b/src/GLES2/compiler/Compiler.cpp
@@ -0,0 +1,231 @@
+//
+// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "compiler/DetectRecursion.h"
+#include "compiler/Initialize.h"
+#include "compiler/InitializeParseContext.h"
+#include "compiler/ParseHelper.h"
+#include "compiler/ShHandle.h"
+#include "compiler/ValidateLimitations.h"
+
+namespace {
+bool InitializeSymbolTable(
+    const TBuiltInStrings& builtInStrings,
+    ShShaderType type, ShShaderSpec spec, const ShBuiltInResources& resources,
+    TInfoSink& infoSink, TSymbolTable& symbolTable)
+{
+    TIntermediate intermediate(infoSink);
+    TExtensionBehavior extBehavior;
+    InitExtensionBehavior(resources, extBehavior);
+    // The builtins deliberately don't specify precisions for the function
+    // arguments and return types. For that reason we don't try to check them.
+    TParseContext parseContext(symbolTable, extBehavior, intermediate, type, spec, 0, false, NULL, infoSink);
+
+    GlobalParseContext = &parseContext;
+
+    assert(symbolTable.isEmpty());       
+    //
+    // Parse the built-ins.  This should only happen once per
+    // language symbol table.
+    //
+    // Push the symbol table to give it an initial scope.  This
+    // push should not have a corresponding pop, so that built-ins
+    // are preserved, and the test for an empty table fails.
+    //
+    symbolTable.push();
+
+    for (TBuiltInStrings::const_iterator i = builtInStrings.begin(); i != builtInStrings.end(); ++i)
+    {
+        const char* builtInShaders = i->c_str();
+        int builtInLengths = static_cast<int>(i->size());
+        if (builtInLengths <= 0)
+          continue;
+
+        if (PaParseStrings(1, &builtInShaders, &builtInLengths, &parseContext) != 0)
+        {
+            infoSink.info.message(EPrefixInternalError, "Unable to parse built-ins");
+            return false;
+        }
+    }
+
+    IdentifyBuiltIns(type, spec, resources, symbolTable);
+
+    return true;
+}
+
+class TScopedPoolAllocator {
+public:
+    TScopedPoolAllocator(TPoolAllocator* allocator, bool pushPop)
+        : mAllocator(allocator), mPushPopAllocator(pushPop) {
+        if (mPushPopAllocator) mAllocator->push();
+        SetGlobalPoolAllocator(mAllocator);
+    }
+    ~TScopedPoolAllocator() {
+        SetGlobalPoolAllocator(NULL);
+        if (mPushPopAllocator) mAllocator->pop();
+    }
+
+private:
+    TPoolAllocator* mAllocator;
+    bool mPushPopAllocator;
+};
+}  // namespace
+
+TShHandleBase::TShHandleBase() {
+    allocator.push();
+    SetGlobalPoolAllocator(&allocator);
+}
+
+TShHandleBase::~TShHandleBase() {
+    SetGlobalPoolAllocator(NULL);
+    allocator.popAll();
+}
+
+TCompiler::TCompiler(ShShaderType type, ShShaderSpec spec)
+    : shaderType(type),
+      shaderSpec(spec)
+{
+}
+
+TCompiler::~TCompiler()
+{
+}
+
+bool TCompiler::Init(const ShBuiltInResources& resources)
+{
+    TScopedPoolAllocator scopedAlloc(&allocator, false);
+
+    // Generate built-in symbol table.
+    if (!InitBuiltInSymbolTable(resources))
+        return false;
+    InitExtensionBehavior(resources, extensionBehavior);
+
+    return true;
+}
+
+bool TCompiler::compile(const char* const shaderStrings[],
+                        const int numStrings,
+                        int compileOptions)
+{
+    TScopedPoolAllocator scopedAlloc(&allocator, true);
+    clearResults();
+
+    if (numStrings == 0)
+        return true;
+
+    // If compiling for WebGL, validate loop and indexing as well.
+    if (shaderSpec == SH_WEBGL_SPEC)
+        compileOptions |= SH_VALIDATE_LOOP_INDEXING;
+
+    // First string is path of source file if flag is set. The actual source follows.
+    const char* sourcePath = NULL;
+    int firstSource = 0;
+    if (compileOptions & SH_SOURCE_PATH)
+    {
+        sourcePath = shaderStrings[0];
+        ++firstSource;
+    }
+
+    TIntermediate intermediate(infoSink);
+    TParseContext parseContext(symbolTable, extensionBehavior, intermediate,
+                               shaderType, shaderSpec, compileOptions, true,
+                               sourcePath, infoSink);
+    GlobalParseContext = &parseContext;
+
+    // We preserve symbols at the built-in level from compile-to-compile.
+    // Start pushing the user-defined symbols at global level.
+    symbolTable.push();
+    if (!symbolTable.atGlobalLevel())
+        infoSink.info.message(EPrefixInternalError, "Wrong symbol table level");
+
+    // Parse shader.
+    bool success =
+        (PaParseStrings(numStrings - firstSource, &shaderStrings[firstSource], NULL, &parseContext) == 0) &&
+        (parseContext.treeRoot != NULL);
+    if (success) {
+        TIntermNode* root = parseContext.treeRoot;
+        success = intermediate.postProcess(root);
+
+        if (success)
+            success = detectRecursion(root);
+
+        if (success && (compileOptions & SH_VALIDATE_LOOP_INDEXING))
+            success = validateLimitations(root);
+
+        if (success && (compileOptions & SH_ATTRIBUTES_UNIFORMS))
+            collectAttribsUniforms(root);
+
+        if (success && (compileOptions & SH_INTERMEDIATE_TREE))
+            intermediate.outputTree(root);
+
+        if (success && (compileOptions & SH_OBJECT_CODE))
+            translate(root);
+    }
+
+    // Cleanup memory.
+    intermediate.remove(parseContext.treeRoot);
+    // Ensure symbol table is returned to the built-in level,
+    // throwing away all but the built-ins.
+    while (!symbolTable.atBuiltInLevel())
+        symbolTable.pop();
+
+    return success;
+}
+
+bool TCompiler::InitBuiltInSymbolTable(const ShBuiltInResources& resources)
+{
+    TBuiltIns builtIns;
+
+    builtIns.initialize(shaderType, shaderSpec, resources);
+    return InitializeSymbolTable(builtIns.getBuiltInStrings(),
+        shaderType, shaderSpec, resources, infoSink, symbolTable);
+}
+
+void TCompiler::clearResults()
+{
+    infoSink.info.erase();
+    infoSink.obj.erase();
+    infoSink.debug.erase();
+
+    attribs.clear();
+    uniforms.clear();
+}
+
+bool TCompiler::detectRecursion(TIntermNode* root)
+{
+    DetectRecursion detect;
+    root->traverse(&detect);
+    switch (detect.detectRecursion()) {
+        case DetectRecursion::kErrorNone:
+            return true;
+        case DetectRecursion::kErrorMissingMain:
+            infoSink.info.message(EPrefixError, "Missing main()");
+            return false;
+        case DetectRecursion::kErrorRecursion:
+            infoSink.info.message(EPrefixError, "Function recursion detected");
+            return false;
+        default:
+            UNREACHABLE();
+            return false;
+    }
+}
+
+bool TCompiler::validateLimitations(TIntermNode* root) {
+    ValidateLimitations validate(shaderType, infoSink.info);
+    root->traverse(&validate);
+    return validate.numErrors() == 0;
+}
+
+void TCompiler::collectAttribsUniforms(TIntermNode* root)
+{
+    CollectAttribsUniforms collect(attribs, uniforms);
+    root->traverse(&collect);
+}
+
+const TExtensionBehavior& TCompiler::getExtensionBehavior() const
+{
+    return extensionBehavior;
+}
diff --git a/src/GLES2/compiler/Compiler.vcxproj b/src/GLES2/compiler/Compiler.vcxproj
new file mode 100644
index 0000000..9ca34db
--- /dev/null
+++ b/src/GLES2/compiler/Compiler.vcxproj
@@ -0,0 +1,218 @@
+<?xml version="1.0" encoding="utf-8"?>

+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

+  <ItemGroup Label="ProjectConfigurations">

+    <ProjectConfiguration Include="Debug|Win32">

+      <Configuration>Debug</Configuration>

+      <Platform>Win32</Platform>

+    </ProjectConfiguration>

+    <ProjectConfiguration Include="Profile|Win32">

+      <Configuration>Profile</Configuration>

+      <Platform>Win32</Platform>

+    </ProjectConfiguration>

+    <ProjectConfiguration Include="Release|Win32">

+      <Configuration>Release</Configuration>

+      <Platform>Win32</Platform>

+    </ProjectConfiguration>

+  </ItemGroup>

+  <PropertyGroup Label="Globals">

+    <ProjectGuid>{5B3A6DB8-1E7E-40D7-92B9-DA8AAE619FAD}</ProjectGuid>

+    <RootNamespace>compiler</RootNamespace>

+    <Keyword>Win32Proj</Keyword>

+    <ProjectName>Compiler</ProjectName>

+  </PropertyGroup>

+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">

+    <ConfigurationType>StaticLibrary</ConfigurationType>

+    <CharacterSet>NotSet</CharacterSet>

+    <WholeProgramOptimization>true</WholeProgramOptimization>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Profile|Win32'" Label="Configuration">

+    <ConfigurationType>StaticLibrary</ConfigurationType>

+    <CharacterSet>NotSet</CharacterSet>

+    <WholeProgramOptimization>true</WholeProgramOptimization>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">

+    <ConfigurationType>StaticLibrary</ConfigurationType>

+    <CharacterSet>NotSet</CharacterSet>

+  </PropertyGroup>

+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />

+  <ImportGroup Label="ExtensionSettings">

+  </ImportGroup>

+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">

+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

+  </ImportGroup>

+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Profile|Win32'" Label="PropertySheets">

+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

+  </ImportGroup>

+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">

+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

+  </ImportGroup>

+  <PropertyGroup Label="UserMacros" />

+  <PropertyGroup>

+    <_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion>

+    <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(Platform)\$(Configuration)\</OutDir>

+    <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(Platform)\$(Configuration)\</IntDir>

+    <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(Platform)\$(Configuration)\</OutDir>

+    <OutDir Condition="'$(Configuration)|$(Platform)'=='Profile|Win32'">$(Platform)\$(Configuration)\</OutDir>

+    <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(Platform)\$(Configuration)\</IntDir>

+    <IntDir Condition="'$(Configuration)|$(Platform)'=='Profile|Win32'">$(Platform)\$(Configuration)\</IntDir>

+    <IncludePath Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">..\include;$(DXSDK_DIR)\Include;$(VCInstallDir)PlatformSDK\include;$(IncludePath)</IncludePath>

+    <IncludePath Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">..\include;$(DXSDK_DIR)\Include;$(VCInstallDir)PlatformSDK\include;$(IncludePath)</IncludePath>

+    <IncludePath Condition="'$(Configuration)|$(Platform)'=='Profile|Win32'">..\include;$(DXSDK_DIR)\Include;$(VCInstallDir)PlatformSDK\include;$(IncludePath)</IncludePath>

+  </PropertyGroup>

+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">

+    <ClCompile>

+      <Optimization>Disabled</Optimization>

+      <AdditionalIncludeDirectories>$(ProjectDir);$(ProjectDir)../;$(ProjectDir)../../;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>

+      <PreprocessorDefinitions>WIN32;_DEBUG;_LIB;_CRT_SECURE_NO_DEPRECATE;NOMINMAX;%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <MinimalRebuild>true</MinimalRebuild>

+      <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>

+      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>

+      <PrecompiledHeader>

+      </PrecompiledHeader>

+      <WarningLevel>Level3</WarningLevel>

+      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>

+      <BrowseInformation>true</BrowseInformation>

+    </ClCompile>

+  </ItemDefinitionGroup>

+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">

+    <ClCompile>

+      <Optimization>MaxSpeed</Optimization>

+      <InlineFunctionExpansion>AnySuitable</InlineFunctionExpansion>

+      <AdditionalIncludeDirectories>$(ProjectDir);$(ProjectDir)../;$(ProjectDir)../../;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>

+      <PreprocessorDefinitions>WIN32;NDEBUG;_LIB;_CRT_SECURE_NO_DEPRECATE;NOMINMAX;_SECURE_SCL=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>

+      <PrecompiledHeader>

+      </PrecompiledHeader>

+      <WarningLevel>Level3</WarningLevel>

+      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>

+    </ClCompile>

+  </ItemDefinitionGroup>

+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Profile|Win32'">

+    <ClCompile>

+      <Optimization>MaxSpeed</Optimization>

+      <InlineFunctionExpansion>AnySuitable</InlineFunctionExpansion>

+      <AdditionalIncludeDirectories>$(ProjectDir);$(ProjectDir)../;$(ProjectDir)../../;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>

+      <PreprocessorDefinitions>WIN32;NDEBUG;_LIB;_CRT_SECURE_NO_DEPRECATE;NOMINMAX;_SECURE_SCL=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>

+      <PrecompiledHeader>

+      </PrecompiledHeader>

+      <WarningLevel>Level3</WarningLevel>

+      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>

+      <OmitFramePointers>false</OmitFramePointers>

+    </ClCompile>

+  </ItemDefinitionGroup>

+  <ItemGroup>

+    <ClCompile Include="Compiler.cpp" />

+    <ClCompile Include="debug.cpp" />

+    <ClCompile Include="DetectRecursion.cpp" />

+    <ClCompile Include="Diagnostics.cpp" />

+    <ClCompile Include="DirectiveHandler.cpp" />

+    <ClCompile Include="InfoSink.cpp" />

+    <ClCompile Include="Initialize.cpp" />

+    <ClCompile Include="InitializeDll.cpp" />

+    <ClCompile Include="InitializeParseContext.cpp" />

+    <ClCompile Include="Intermediate.cpp" />

+    <ClCompile Include="intermOut.cpp" />

+    <ClCompile Include="IntermTraverse.cpp" />

+    <ClCompile Include="ossource_win.cpp" />

+    <ClCompile Include="OutputASM.cpp" />

+    <ClCompile Include="parseConst.cpp" />

+    <ClCompile Include="ParseHelper.cpp" />

+    <ClCompile Include="PoolAlloc.cpp" />

+    <ClCompile Include="QualifierAlive.cpp" />

+    <ClCompile Include="RemoveTree.cpp" />

+    <ClCompile Include="ShaderLang.cpp" />

+    <ClCompile Include="SymbolTable.cpp" />

+    <ClCompile Include="TranslatorASM.cpp" />

+    <ClCompile Include="util.cpp" />

+    <ClCompile Include="ValidateLimitations.cpp" />

+    <ClCompile Include="VariableInfo.cpp" />

+    <ClCompile Include="glslang_lex.cpp" />

+    <ClCompile Include="glslang_tab.cpp" />

+  </ItemGroup>

+  <ItemGroup>

+    <CustomBuild Include="glslang.l">

+      <Message Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">

+      </Message>

+      <Command Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">

+      </Command>

+      <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalInputs)</AdditionalInputs>

+      <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(Outputs)</Outputs>

+      <Message Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">

+      </Message>

+      <Message Condition="'$(Configuration)|$(Platform)'=='Profile|Win32'">

+      </Message>

+      <Command Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">

+      </Command>

+      <Command Condition="'$(Configuration)|$(Platform)'=='Profile|Win32'">

+      </Command>

+      <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalInputs)</AdditionalInputs>

+      <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Profile|Win32'">%(AdditionalInputs)</AdditionalInputs>

+      <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(Outputs)</Outputs>

+      <Outputs Condition="'$(Configuration)|$(Platform)'=='Profile|Win32'">%(Outputs)</Outputs>

+    </CustomBuild>

+    <CustomBuild Include="glslang.y">

+      <Message Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">

+      </Message>

+      <Command Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">

+      </Command>

+      <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(Outputs)</Outputs>

+      <Message Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">

+      </Message>

+      <Message Condition="'$(Configuration)|$(Platform)'=='Profile|Win32'">

+      </Message>

+      <Command Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">

+      </Command>

+      <Command Condition="'$(Configuration)|$(Platform)'=='Profile|Win32'">

+      </Command>

+      <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(Outputs)</Outputs>

+      <Outputs Condition="'$(Configuration)|$(Platform)'=='Profile|Win32'">%(Outputs)</Outputs>

+    </CustomBuild>

+  </ItemGroup>

+  <ItemGroup>

+    <ClInclude Include="..\include\GLSLANG\ShaderLang.h" />

+    <ClInclude Include="BaseTypes.h" />

+    <ClInclude Include="Common.h" />

+    <ClInclude Include="ConstantUnion.h" />

+    <ClInclude Include="debug.h" />

+    <ClInclude Include="DetectRecursion.h" />

+    <ClInclude Include="Diagnostics.h" />

+    <ClInclude Include="InfoSink.h" />

+    <ClInclude Include="Initialize.h" />

+    <ClInclude Include="InitializeDll.h" />

+    <ClInclude Include="InitializeGlobals.h" />

+    <ClInclude Include="InitializeParseContext.h" />

+    <ClInclude Include="intermediate.h" />

+    <ClInclude Include="localintermediate.h" />

+    <ClInclude Include="MMap.h" />

+    <ClInclude Include="osinclude.h" />

+    <ClInclude Include="OutputASM.h" />

+    <ClInclude Include="ParseHelper.h" />

+    <ClInclude Include="PoolAlloc.h" />

+    <ClInclude Include="Pragma.h" />

+    <ClInclude Include="QualifierAlive.h" />

+    <ClInclude Include="RemoveTree.h" />

+    <ClInclude Include="ShHandle.h" />

+    <ClInclude Include="SymbolTable.h" />

+    <ClInclude Include="TranslatorASM.h" />

+    <ClInclude Include="Types.h" />

+    <ClInclude Include="util.h" />

+    <ClInclude Include="ValidateLimitations.h" />

+    <ClInclude Include="VariableInfo.h" />

+    <ClInclude Include="glslang_tab.h" />

+  </ItemGroup>

+  <ItemGroup>

+    <ProjectReference Include="preprocessor\preprocessor.vcxproj">

+      <Project>{92940255-ab4b-42fb-a2c4-0fab19c3c48a}</Project>

+      <Private>true</Private>

+      <ReferenceOutputAssembly>true</ReferenceOutputAssembly>

+      <CopyLocalSatelliteAssemblies>false</CopyLocalSatelliteAssemblies>

+      <LinkLibraryDependencies>true</LinkLibraryDependencies>

+      <UseLibraryDependencyInputs>false</UseLibraryDependencyInputs>

+    </ProjectReference>

+  </ItemGroup>

+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />

+  <ImportGroup Label="ExtensionTargets">

+  </ImportGroup>

+</Project>
\ No newline at end of file
diff --git a/src/GLES2/compiler/Compiler.vcxproj.filters b/src/GLES2/compiler/Compiler.vcxproj.filters
new file mode 100644
index 0000000..cce0afb
--- /dev/null
+++ b/src/GLES2/compiler/Compiler.vcxproj.filters
@@ -0,0 +1,202 @@
+<?xml version="1.0" encoding="utf-8"?>

+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

+  <ItemGroup>

+    <Filter Include="Source Files">

+      <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>

+      <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>

+    </Filter>

+    <Filter Include="Source Files\generated">

+      <UniqueIdentifier>{1add4406-d193-4c4e-a8ec-c41c8d0bd499}</UniqueIdentifier>

+    </Filter>

+    <Filter Include="Header Files">

+      <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>

+      <Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>

+    </Filter>

+    <Filter Include="Header Files\generated">

+      <UniqueIdentifier>{a56a1771-4799-47ac-ace9-6955dd3f055b}</UniqueIdentifier>

+    </Filter>

+  </ItemGroup>

+  <ItemGroup>

+    <ClCompile Include="Compiler.cpp">

+      <Filter>Source Files</Filter>

+    </ClCompile>

+    <ClCompile Include="InfoSink.cpp">

+      <Filter>Source Files</Filter>

+    </ClCompile>

+    <ClCompile Include="Initialize.cpp">

+      <Filter>Source Files</Filter>

+    </ClCompile>

+    <ClCompile Include="InitializeDll.cpp">

+      <Filter>Source Files</Filter>

+    </ClCompile>

+    <ClCompile Include="Intermediate.cpp">

+      <Filter>Source Files</Filter>

+    </ClCompile>

+    <ClCompile Include="intermOut.cpp">

+      <Filter>Source Files</Filter>

+    </ClCompile>

+    <ClCompile Include="IntermTraverse.cpp">

+      <Filter>Source Files</Filter>

+    </ClCompile>

+    <ClCompile Include="ossource_win.cpp">

+      <Filter>Source Files</Filter>

+    </ClCompile>

+    <ClCompile Include="parseConst.cpp">

+      <Filter>Source Files</Filter>

+    </ClCompile>

+    <ClCompile Include="ParseHelper.cpp">

+      <Filter>Source Files</Filter>

+    </ClCompile>

+    <ClCompile Include="PoolAlloc.cpp">

+      <Filter>Source Files</Filter>

+    </ClCompile>

+    <ClCompile Include="QualifierAlive.cpp">

+      <Filter>Source Files</Filter>

+    </ClCompile>

+    <ClCompile Include="RemoveTree.cpp">

+      <Filter>Source Files</Filter>

+    </ClCompile>

+    <ClCompile Include="ShaderLang.cpp">

+      <Filter>Source Files</Filter>

+    </ClCompile>

+    <ClCompile Include="SymbolTable.cpp">

+      <Filter>Source Files</Filter>

+    </ClCompile>

+    <ClCompile Include="util.cpp">

+      <Filter>Source Files</Filter>

+    </ClCompile>

+    <ClCompile Include="ValidateLimitations.cpp">

+      <Filter>Source Files</Filter>

+    </ClCompile>

+    <ClCompile Include="VariableInfo.cpp">

+      <Filter>Source Files</Filter>

+    </ClCompile>

+    <ClCompile Include="glslang_lex.cpp">

+      <Filter>Source Files\generated</Filter>

+    </ClCompile>

+    <ClCompile Include="glslang_tab.cpp">

+      <Filter>Source Files\generated</Filter>

+    </ClCompile>

+    <ClCompile Include="DetectRecursion.cpp">

+      <Filter>Source Files</Filter>

+    </ClCompile>

+    <ClCompile Include="OutputASM.cpp">

+      <Filter>Source Files</Filter>

+    </ClCompile>

+    <ClCompile Include="TranslatorASM.cpp">

+      <Filter>Source Files</Filter>

+    </ClCompile>

+    <ClCompile Include="debug.cpp">

+      <Filter>Source Files</Filter>

+    </ClCompile>

+    <ClCompile Include="Diagnostics.cpp">

+      <Filter>Source Files</Filter>

+    </ClCompile>

+    <ClCompile Include="DirectiveHandler.cpp">

+      <Filter>Source Files</Filter>

+    </ClCompile>

+    <ClCompile Include="InitializeParseContext.cpp">

+      <Filter>Source Files</Filter>

+    </ClCompile>

+  </ItemGroup>

+  <ItemGroup>

+    <ClInclude Include="BaseTypes.h">

+      <Filter>Header Files</Filter>

+    </ClInclude>

+    <ClInclude Include="Common.h">

+      <Filter>Header Files</Filter>

+    </ClInclude>

+    <ClInclude Include="ConstantUnion.h">

+      <Filter>Header Files</Filter>

+    </ClInclude>

+    <ClInclude Include="InfoSink.h">

+      <Filter>Header Files</Filter>

+    </ClInclude>

+    <ClInclude Include="Initialize.h">

+      <Filter>Header Files</Filter>

+    </ClInclude>

+    <ClInclude Include="InitializeDll.h">

+      <Filter>Header Files</Filter>

+    </ClInclude>

+    <ClInclude Include="InitializeGlobals.h">

+      <Filter>Header Files</Filter>

+    </ClInclude>

+    <ClInclude Include="InitializeParseContext.h">

+      <Filter>Header Files</Filter>

+    </ClInclude>

+    <ClInclude Include="intermediate.h">

+      <Filter>Header Files</Filter>

+    </ClInclude>

+    <ClInclude Include="localintermediate.h">

+      <Filter>Header Files</Filter>

+    </ClInclude>

+    <ClInclude Include="MMap.h">

+      <Filter>Header Files</Filter>

+    </ClInclude>

+    <ClInclude Include="osinclude.h">

+      <Filter>Header Files</Filter>

+    </ClInclude>

+    <ClInclude Include="ParseHelper.h">

+      <Filter>Header Files</Filter>

+    </ClInclude>

+    <ClInclude Include="PoolAlloc.h">

+      <Filter>Header Files</Filter>

+    </ClInclude>

+    <ClInclude Include="QualifierAlive.h">

+      <Filter>Header Files</Filter>

+    </ClInclude>

+    <ClInclude Include="RemoveTree.h">

+      <Filter>Header Files</Filter>

+    </ClInclude>

+    <ClInclude Include="ShHandle.h">

+      <Filter>Header Files</Filter>

+    </ClInclude>

+    <ClInclude Include="SymbolTable.h">

+      <Filter>Header Files</Filter>

+    </ClInclude>

+    <ClInclude Include="Types.h">

+      <Filter>Header Files</Filter>

+    </ClInclude>

+    <ClInclude Include="util.h">

+      <Filter>Header Files</Filter>

+    </ClInclude>

+    <ClInclude Include="ValidateLimitations.h">

+      <Filter>Header Files</Filter>

+    </ClInclude>

+    <ClInclude Include="VariableInfo.h">

+      <Filter>Header Files</Filter>

+    </ClInclude>

+    <ClInclude Include="glslang_tab.h">

+      <Filter>Header Files\generated</Filter>

+    </ClInclude>

+    <ClInclude Include="DetectRecursion.h">

+      <Filter>Header Files</Filter>

+    </ClInclude>

+    <ClInclude Include="..\include\GLSLANG\ShaderLang.h">

+      <Filter>Header Files</Filter>

+    </ClInclude>

+    <ClInclude Include="OutputASM.h">

+      <Filter>Header Files</Filter>

+    </ClInclude>

+    <ClInclude Include="TranslatorASM.h">

+      <Filter>Header Files</Filter>

+    </ClInclude>

+    <ClInclude Include="debug.h">

+      <Filter>Header Files</Filter>

+    </ClInclude>

+    <ClInclude Include="Diagnostics.h">

+      <Filter>Header Files</Filter>

+    </ClInclude>

+    <ClInclude Include="Pragma.h">

+      <Filter>Header Files</Filter>

+    </ClInclude>

+  </ItemGroup>

+  <ItemGroup>

+    <CustomBuild Include="glslang.l">

+      <Filter>Source Files</Filter>

+    </CustomBuild>

+    <CustomBuild Include="glslang.y">

+      <Filter>Source Files</Filter>

+    </CustomBuild>

+  </ItemGroup>

+</Project>
\ No newline at end of file
diff --git a/src/GLES2/compiler/ConstantUnion.h b/src/GLES2/compiler/ConstantUnion.h
new file mode 100644
index 0000000..bac2e9a
--- /dev/null
+++ b/src/GLES2/compiler/ConstantUnion.h
@@ -0,0 +1,275 @@
+//
+// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#ifndef _CONSTANT_UNION_INCLUDED_
+#define _CONSTANT_UNION_INCLUDED_
+
+#include <assert.h>
+
+class ConstantUnion {
+public:
+    ConstantUnion()
+    {
+        iConst = 0;
+    }
+
+    POOL_ALLOCATOR_NEW_DELETE(GlobalPoolAllocator)        
+    void setIConst(int i) {iConst = i; type = EbtInt; }
+    void setFConst(float f) {fConst = f; type = EbtFloat; }
+    void setBConst(bool b) {bConst = b; type = EbtBool; }
+
+    int getIConst() { return iConst; }
+    float getFConst() { return fConst; }
+    bool getBConst() { return bConst; }
+    int getIConst() const { return iConst; }
+    float getFConst() const { return fConst; }
+    bool getBConst() const { return bConst; }
+
+	float getAsFloat()
+	{
+		const int FFFFFFFFh = 0xFFFFFFFF;
+
+		switch(type)
+		{
+        case EbtInt:   return (float)iConst;
+        case EbtFloat: return fConst;
+		case EbtBool:  return (bConst == true) ? (float&)FFFFFFFFh : 0;
+        default:       return 0;
+        }
+	}
+
+    bool operator==(const int i) const
+    {
+        return i == iConst;
+    }
+
+    bool operator==(const float f) const
+    {
+        return f == fConst;
+    }
+
+    bool operator==(const bool b) const
+    {
+        return b == bConst;
+    }
+
+    bool operator==(const ConstantUnion& constant) const
+    {
+        if (constant.type != type)
+            return false;
+
+        switch (type) {
+        case EbtInt:
+            return constant.iConst == iConst;
+        case EbtFloat:
+            return constant.fConst == fConst;
+        case EbtBool:
+            return constant.bConst == bConst;
+        default:
+            return false;
+        }
+
+        return false;
+    }
+
+    bool operator!=(const int i) const
+    {
+        return !operator==(i);
+    }
+
+    bool operator!=(const float f) const
+    {
+        return !operator==(f);
+    }
+
+    bool operator!=(const bool b) const
+    {
+        return !operator==(b);
+    }
+
+    bool operator!=(const ConstantUnion& constant) const
+    {
+        return !operator==(constant);
+    }
+
+    bool operator>(const ConstantUnion& constant) const
+    { 
+        assert(type == constant.type);
+        switch (type) {
+        case EbtInt:
+            return iConst > constant.iConst;
+        case EbtFloat:
+            return fConst > constant.fConst;
+        default:
+            return false;   // Invalid operation, handled at semantic analysis
+        }
+
+        return false;
+    }
+
+    bool operator<(const ConstantUnion& constant) const
+    { 
+        assert(type == constant.type);
+        switch (type) {
+        case EbtInt:
+            return iConst < constant.iConst;
+        case EbtFloat:
+            return fConst < constant.fConst;
+        default:
+            return false;   // Invalid operation, handled at semantic analysis
+        }
+
+        return false;
+    }
+
+    ConstantUnion operator+(const ConstantUnion& constant) const
+    { 
+        ConstantUnion returnValue;
+        assert(type == constant.type);
+        switch (type) {
+        case EbtInt: returnValue.setIConst(iConst + constant.iConst); break;
+        case EbtFloat: returnValue.setFConst(fConst + constant.fConst); break;
+        default: assert(false && "Default missing");
+        }
+
+        return returnValue;
+    }
+
+    ConstantUnion operator-(const ConstantUnion& constant) const
+    { 
+        ConstantUnion returnValue;
+        assert(type == constant.type);
+        switch (type) {
+        case EbtInt: returnValue.setIConst(iConst - constant.iConst); break;
+        case EbtFloat: returnValue.setFConst(fConst - constant.fConst); break;
+        default: assert(false && "Default missing");
+        }
+
+        return returnValue;
+    }
+
+    ConstantUnion operator*(const ConstantUnion& constant) const
+    { 
+        ConstantUnion returnValue;
+        assert(type == constant.type);
+        switch (type) {
+        case EbtInt: returnValue.setIConst(iConst * constant.iConst); break;
+        case EbtFloat: returnValue.setFConst(fConst * constant.fConst); break; 
+        default: assert(false && "Default missing");
+        }
+
+        return returnValue;
+    }
+
+    ConstantUnion operator%(const ConstantUnion& constant) const
+    { 
+        ConstantUnion returnValue;
+        assert(type == constant.type);
+        switch (type) {
+        case EbtInt: returnValue.setIConst(iConst % constant.iConst); break;
+        default:     assert(false && "Default missing");
+        }
+
+        return returnValue;
+    }
+
+    ConstantUnion operator>>(const ConstantUnion& constant) const
+    { 
+        ConstantUnion returnValue;
+        assert(type == constant.type);
+        switch (type) {
+        case EbtInt: returnValue.setIConst(iConst >> constant.iConst); break;
+        default:     assert(false && "Default missing");
+        }
+
+        return returnValue;
+    }
+
+    ConstantUnion operator<<(const ConstantUnion& constant) const
+    { 
+        ConstantUnion returnValue;
+        assert(type == constant.type);
+        switch (type) {
+        case EbtInt: returnValue.setIConst(iConst << constant.iConst); break;
+        default:     assert(false && "Default missing");
+        }
+
+        return returnValue;
+    }
+
+    ConstantUnion operator&(const ConstantUnion& constant) const
+    { 
+        ConstantUnion returnValue;
+        assert(type == constant.type);
+        switch (type) {
+        case EbtInt:  returnValue.setIConst(iConst & constant.iConst); break;
+        default:     assert(false && "Default missing");
+        }
+
+        return returnValue;
+    }
+
+    ConstantUnion operator|(const ConstantUnion& constant) const
+    { 
+        ConstantUnion returnValue;
+        assert(type == constant.type);
+        switch (type) {
+        case EbtInt:  returnValue.setIConst(iConst | constant.iConst); break;
+        default:     assert(false && "Default missing");
+        }
+
+        return returnValue;
+    }
+
+    ConstantUnion operator^(const ConstantUnion& constant) const
+    { 
+        ConstantUnion returnValue;
+        assert(type == constant.type);
+        switch (type) {
+        case EbtInt:  returnValue.setIConst(iConst ^ constant.iConst); break;
+        default:     assert(false && "Default missing");
+        }
+
+        return returnValue;
+    }
+
+    ConstantUnion operator&&(const ConstantUnion& constant) const
+    { 
+        ConstantUnion returnValue;
+        assert(type == constant.type);
+        switch (type) {
+        case EbtBool: returnValue.setBConst(bConst && constant.bConst); break;
+        default:     assert(false && "Default missing");
+        }
+
+        return returnValue;
+    }
+
+    ConstantUnion operator||(const ConstantUnion& constant) const
+    { 
+        ConstantUnion returnValue;
+        assert(type == constant.type);
+        switch (type) {
+        case EbtBool: returnValue.setBConst(bConst || constant.bConst); break;
+        default:     assert(false && "Default missing");
+        }
+
+        return returnValue;
+    }
+
+    TBasicType getType() const { return type; }
+private:
+
+    union  {
+        int iConst;  // used for ivec, scalar ints
+        bool bConst; // used for bvec, scalar bools
+        float fConst;   // used for vec, mat, scalar floats
+    } ;
+
+    TBasicType type;
+};
+
+#endif // _CONSTANT_UNION_INCLUDED_
diff --git a/src/GLES2/compiler/DetectRecursion.cpp b/src/GLES2/compiler/DetectRecursion.cpp
new file mode 100644
index 0000000..e79b70d
--- /dev/null
+++ b/src/GLES2/compiler/DetectRecursion.cpp
@@ -0,0 +1,125 @@
+//
+// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "compiler/DetectRecursion.h"
+
+DetectRecursion::FunctionNode::FunctionNode(const TString& fname)
+    : name(fname),
+      visit(PreVisit)
+{
+}
+
+const TString& DetectRecursion::FunctionNode::getName() const
+{
+    return name;
+}
+
+void DetectRecursion::FunctionNode::addCallee(
+    DetectRecursion::FunctionNode* callee)
+{
+    for (size_t i = 0; i < callees.size(); ++i) {
+        if (callees[i] == callee)
+            return;
+    }
+    callees.push_back(callee);
+}
+
+bool DetectRecursion::FunctionNode::detectRecursion()
+{
+    ASSERT(visit == PreVisit);
+    visit = InVisit;
+    for (size_t i = 0; i < callees.size(); ++i) {
+        switch (callees[i]->visit) {
+            case InVisit:
+                // cycle detected, i.e., recursion detected.
+                return true;
+            case PostVisit:
+                break;
+            case PreVisit: {
+                bool recursion = callees[i]->detectRecursion();
+                if (recursion)
+                    return true;
+                break;
+            }
+            default:
+                UNREACHABLE();
+                break;
+        }
+    }
+    visit = PostVisit;
+    return false;
+}
+
+DetectRecursion::DetectRecursion()
+    : currentFunction(NULL)
+{
+}
+
+DetectRecursion::~DetectRecursion()
+{
+    for (size_t i = 0; i < functions.size(); ++i)
+        delete functions[i];
+}
+
+bool DetectRecursion::visitAggregate(Visit visit, TIntermAggregate* node)
+{
+    switch (node->getOp())
+    {
+        case EOpPrototype:
+            // Function declaration.
+            // Don't add FunctionNode here because node->getName() is the
+            // unmangled function name.
+            break;
+        case EOpFunction: {
+            // Function definition.
+            if (visit == PreVisit) {
+                currentFunction = findFunctionByName(node->getName());
+                if (currentFunction == NULL) {
+                    currentFunction = new FunctionNode(node->getName());
+                    functions.push_back(currentFunction);
+                }
+            }
+            break;
+        }
+        case EOpFunctionCall: {
+            // Function call.
+            if (visit == PreVisit) {
+                ASSERT(currentFunction != NULL);
+                FunctionNode* func = findFunctionByName(node->getName());
+                if (func == NULL) {
+                    func = new FunctionNode(node->getName());
+                    functions.push_back(func);
+                }
+                currentFunction->addCallee(func);
+            }
+            break;
+        }
+        default:
+            break;
+    }
+    return true;
+}
+
+DetectRecursion::ErrorCode DetectRecursion::detectRecursion()
+{
+    FunctionNode* main = findFunctionByName("main(");
+    if (main == NULL)
+        return kErrorMissingMain;
+    if (main->detectRecursion())
+        return kErrorRecursion;
+    return kErrorNone;
+}
+
+DetectRecursion::FunctionNode* DetectRecursion::findFunctionByName(
+    const TString& name)
+{
+    for (size_t i = 0; i < functions.size(); ++i) {
+        if (functions[i]->getName() == name)
+            return functions[i];
+    }
+    return NULL;
+}
+
diff --git a/src/GLES2/compiler/DetectRecursion.h b/src/GLES2/compiler/DetectRecursion.h
new file mode 100644
index 0000000..bbac79d
--- /dev/null
+++ b/src/GLES2/compiler/DetectRecursion.h
@@ -0,0 +1,60 @@
+//
+// Copyright (c) 2002-2011 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#ifndef COMPILER_DETECT_RECURSION_H_
+#define COMPILER_DETECT_RECURSION_H_
+
+#include "GLSLANG/ShaderLang.h"
+
+#include "compiler/intermediate.h"
+#include "compiler/VariableInfo.h"
+
+// Traverses intermediate tree to detect function recursion.
+class DetectRecursion : public TIntermTraverser {
+public:
+    enum ErrorCode {
+        kErrorMissingMain,
+        kErrorRecursion,
+        kErrorNone
+    };
+
+    DetectRecursion();
+    ~DetectRecursion();
+
+    virtual bool visitAggregate(Visit, TIntermAggregate*);
+
+    ErrorCode detectRecursion();
+
+private:
+    class FunctionNode {
+    public:
+        FunctionNode(const TString& fname);
+
+        const TString& getName() const;
+
+        // If a function is already in the callee list, this becomes a no-op.
+        void addCallee(FunctionNode* callee);
+
+        // Return true if recursive function calls are detected.
+        bool detectRecursion();
+
+    private:
+        // mangled function name is unique.
+        TString name;
+
+        // functions that are directly called by this function.
+        TVector<FunctionNode*> callees;
+
+        Visit visit;
+    };
+
+    FunctionNode* findFunctionByName(const TString& name);
+
+    TVector<FunctionNode*> functions;
+    FunctionNode* currentFunction;
+};
+
+#endif  // COMPILER_DETECT_RECURSION_H_
diff --git a/src/GLES2/compiler/Diagnostics.cpp b/src/GLES2/compiler/Diagnostics.cpp
new file mode 100644
index 0000000..166a4a8
--- /dev/null
+++ b/src/GLES2/compiler/Diagnostics.cpp
@@ -0,0 +1,63 @@
+//
+// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "compiler/Diagnostics.h"
+
+#include "compiler/debug.h"
+#include "compiler/InfoSink.h"
+#include "compiler/preprocessor/SourceLocation.h"
+
+TDiagnostics::TDiagnostics(TInfoSink& infoSink) :
+    mInfoSink(infoSink),
+    mNumErrors(0),
+    mNumWarnings(0)
+{
+}
+
+TDiagnostics::~TDiagnostics()
+{
+}
+
+void TDiagnostics::writeInfo(Severity severity,
+                             const pp::SourceLocation& loc,
+                             const std::string& reason,
+                             const std::string& token,
+                             const std::string& extra)
+{
+    TPrefixType prefix = EPrefixNone;
+    switch (severity)
+    {
+      case PP_ERROR:
+        ++mNumErrors;
+        prefix = EPrefixError;
+        break;
+      case PP_WARNING:
+        ++mNumWarnings;
+        prefix = EPrefixWarning;
+        break;
+      default:
+        UNREACHABLE();
+        break;
+    }
+
+    TInfoSinkBase& sink = mInfoSink.info;
+    /* VC++ format: file(linenum) : error #: 'token' : extrainfo */
+    sink.prefix(prefix);
+    sink.location(EncodeSourceLoc(loc.file, loc.line));
+    sink << "'" << token <<  "' : " << reason << " " << extra << "\n";
+}
+
+void TDiagnostics::writeDebug(const std::string& str)
+{
+    mInfoSink.debug << str;
+}
+
+void TDiagnostics::print(ID id,
+                         const pp::SourceLocation& loc,
+                         const std::string& text)
+{
+    writeInfo(severity(id), loc, message(id), text, "");
+}
diff --git a/src/GLES2/compiler/Diagnostics.h b/src/GLES2/compiler/Diagnostics.h
new file mode 100644
index 0000000..43dfcb7
--- /dev/null
+++ b/src/GLES2/compiler/Diagnostics.h
@@ -0,0 +1,44 @@
+//
+// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#ifndef COMPILER_DIAGNOSTICS_H_
+#define COMPILER_DIAGNOSTICS_H_
+
+#include "compiler/preprocessor/Diagnostics.h"
+
+class TInfoSink;
+
+class TDiagnostics : public pp::Diagnostics
+{
+  public:
+    TDiagnostics(TInfoSink& infoSink);
+    virtual ~TDiagnostics();
+
+    TInfoSink& infoSink() { return mInfoSink; }
+
+    int numErrors() const { return mNumErrors; }
+    int numWarnings() const { return mNumWarnings; }
+
+    void writeInfo(Severity severity,
+                   const pp::SourceLocation& loc,
+                   const std::string& reason,
+                   const std::string& token,
+                   const std::string& extra);
+
+    void writeDebug(const std::string& str);
+
+  protected:
+    virtual void print(ID id,
+                       const pp::SourceLocation& loc,
+                       const std::string& text);
+
+  private:
+    TInfoSink& mInfoSink;
+    int mNumErrors;
+    int mNumWarnings;
+};
+
+#endif  // COMPILER_DIAGNOSTICS_H_
diff --git a/src/GLES2/compiler/DirectiveHandler.cpp b/src/GLES2/compiler/DirectiveHandler.cpp
new file mode 100644
index 0000000..f6a9a93
--- /dev/null
+++ b/src/GLES2/compiler/DirectiveHandler.cpp
@@ -0,0 +1,161 @@
+//
+// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "compiler/DirectiveHandler.h"
+
+#include <sstream>
+
+#include "compiler/debug.h"
+#include "compiler/Diagnostics.h"
+
+static TBehavior getBehavior(const std::string& str)
+{
+    static const std::string kRequire("require");
+    static const std::string kEnable("enable");
+    static const std::string kDisable("disable");
+    static const std::string kWarn("warn");
+
+    if (str == kRequire) return EBhRequire;
+    else if (str == kEnable) return EBhEnable;
+    else if (str == kDisable) return EBhDisable;
+    else if (str == kWarn) return EBhWarn;
+    return EBhUndefined;
+}
+
+TDirectiveHandler::TDirectiveHandler(TExtensionBehavior& extBehavior,
+                                     TDiagnostics& diagnostics)
+    : mExtensionBehavior(extBehavior),
+      mDiagnostics(diagnostics)
+{
+}
+
+TDirectiveHandler::~TDirectiveHandler()
+{
+}
+
+void TDirectiveHandler::handleError(const pp::SourceLocation& loc,
+                                    const std::string& msg)
+{
+    mDiagnostics.writeInfo(pp::Diagnostics::PP_ERROR, loc, msg, "", "");
+}
+
+void TDirectiveHandler::handlePragma(const pp::SourceLocation& loc,
+                                     const std::string& name,
+                                     const std::string& value)
+{
+    static const std::string kSTDGL("STDGL");
+    static const std::string kOptimize("optimize");
+    static const std::string kDebug("debug");
+    static const std::string kOn("on");
+    static const std::string kOff("off");
+
+    bool invalidValue = false;
+    if (name == kSTDGL)
+    {
+        // The STDGL pragma is used to reserve pragmas for use by future
+        // revisions of GLSL. Ignore it.
+        return;
+    }
+    else if (name == kOptimize)
+    {
+        if (value == kOn) mPragma.optimize = true;
+        else if (value == kOff) mPragma.optimize = false;
+        else invalidValue = true;
+    }
+    else if (name == kDebug)
+    {
+        if (value == kOn) mPragma.debug = true;
+        else if (value == kOff) mPragma.debug = false;
+        else invalidValue = true;
+    }
+    else
+    {
+        mDiagnostics.report(pp::Diagnostics::UNRECOGNIZED_PRAGMA, loc, name);
+        return;
+    }
+
+    if (invalidValue)
+      mDiagnostics.writeInfo(pp::Diagnostics::PP_ERROR, loc,
+                             "invalid pragma value", value,
+                             "'on' or 'off' expected");
+}
+
+void TDirectiveHandler::handleExtension(const pp::SourceLocation& loc,
+                                        const std::string& name,
+                                        const std::string& behavior)
+{
+    static const std::string kExtAll("all");
+
+    TBehavior behaviorVal = getBehavior(behavior);
+    if (behaviorVal == EBhUndefined)
+    {
+        mDiagnostics.writeInfo(pp::Diagnostics::PP_ERROR, loc,
+                               "behavior", name, "invalid");
+        return;
+    }
+
+    if (name == kExtAll)
+    {
+        if (behaviorVal == EBhRequire)
+        {
+            mDiagnostics.writeInfo(pp::Diagnostics::PP_ERROR, loc,
+                                   "extension", name,
+                                   "cannot have 'require' behavior");
+        }
+        else if (behaviorVal == EBhEnable)
+        {
+            mDiagnostics.writeInfo(pp::Diagnostics::PP_ERROR, loc,
+                                   "extension", name,
+                                   "cannot have 'enable' behavior");
+        }
+        else
+        {
+            for (TExtensionBehavior::iterator iter = mExtensionBehavior.begin();
+                 iter != mExtensionBehavior.end(); ++iter)
+                iter->second = behaviorVal;
+        }
+        return;
+    }
+
+    TExtensionBehavior::iterator iter = mExtensionBehavior.find(name);
+    if (iter != mExtensionBehavior.end())
+    {
+        iter->second = behaviorVal;
+        return;
+    }
+
+    pp::Diagnostics::Severity severity = pp::Diagnostics::PP_ERROR;
+    switch (behaviorVal) {
+      case EBhRequire:
+        severity = pp::Diagnostics::PP_ERROR;
+        break;
+      case EBhEnable:
+      case EBhWarn:
+      case EBhDisable:
+        severity = pp::Diagnostics::PP_WARNING;
+        break;
+      default:
+        UNREACHABLE();
+        break;
+    }
+    mDiagnostics.writeInfo(severity, loc,
+                           "extension", name, "is not supported");
+}
+
+void TDirectiveHandler::handleVersion(const pp::SourceLocation& loc,
+                                      int version)
+{
+    static const int kVersion = 100;
+
+    if (version != kVersion)
+    {
+        std::stringstream stream;
+        stream << version;
+        std::string str = stream.str();
+        mDiagnostics.writeInfo(pp::Diagnostics::PP_ERROR, loc,
+                               "version number", str, "not supported");
+    }
+}
diff --git a/src/GLES2/compiler/DirectiveHandler.h b/src/GLES2/compiler/DirectiveHandler.h
new file mode 100644
index 0000000..a08b7a8
--- /dev/null
+++ b/src/GLES2/compiler/DirectiveHandler.h
@@ -0,0 +1,46 @@
+//
+// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#ifndef COMPILER_DIRECTIVE_HANDLER_H_
+#define COMPILER_DIRECTIVE_HANDLER_H_
+
+#include "compiler/ExtensionBehavior.h"
+#include "compiler/Pragma.h"
+#include "compiler/preprocessor/DirectiveHandler.h"
+
+class TDiagnostics;
+
+class TDirectiveHandler : public pp::DirectiveHandler
+{
+  public:
+    TDirectiveHandler(TExtensionBehavior& extBehavior,
+                      TDiagnostics& diagnostics);
+    virtual ~TDirectiveHandler();
+
+    const TPragma& pragma() const { return mPragma; }
+    const TExtensionBehavior& extensionBehavior() const { return mExtensionBehavior; }
+
+    virtual void handleError(const pp::SourceLocation& loc,
+                             const std::string& msg);
+
+    virtual void handlePragma(const pp::SourceLocation& loc,
+                              const std::string& name,
+                              const std::string& value);
+
+    virtual void handleExtension(const pp::SourceLocation& loc,
+                                 const std::string& name,
+                                 const std::string& behavior);
+
+    virtual void handleVersion(const pp::SourceLocation& loc,
+                               int version);
+
+  private:
+    TPragma mPragma;
+    TExtensionBehavior& mExtensionBehavior;
+    TDiagnostics& mDiagnostics;
+};
+
+#endif  // COMPILER_DIRECTIVE_HANDLER_H_
diff --git a/src/GLES2/compiler/ExtensionBehavior.h b/src/GLES2/compiler/ExtensionBehavior.h
new file mode 100644
index 0000000..e369ddd
--- /dev/null
+++ b/src/GLES2/compiler/ExtensionBehavior.h
@@ -0,0 +1,37 @@
+//
+// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#ifndef _EXTENSION_BEHAVIOR_INCLUDED_
+#define _EXTENSION_BEHAVIOR_INCLUDED_
+
+#include <map>
+#include <string>
+
+typedef enum
+{
+    EBhRequire,
+    EBhEnable,
+    EBhWarn,
+    EBhDisable,
+    EBhUndefined,
+} TBehavior;
+
+inline const char *getBehaviorString(TBehavior b)
+{
+    switch(b)
+    {
+      case EBhRequire: return "require";
+      case EBhEnable:  return "enable";
+      case EBhWarn:    return "warn";
+      case EBhDisable: return "disable";
+      default: return NULL;
+    }
+}
+
+// Mapping between extension name and behavior.
+typedef std::map<std::string, TBehavior> TExtensionBehavior;
+
+#endif // _EXTENSION_TABLE_INCLUDED_
diff --git a/src/GLES2/compiler/InfoSink.cpp b/src/GLES2/compiler/InfoSink.cpp
new file mode 100644
index 0000000..ba32f78
--- /dev/null
+++ b/src/GLES2/compiler/InfoSink.cpp
@@ -0,0 +1,59 @@
+//
+// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "compiler/InfoSink.h"
+
+void TInfoSinkBase::prefix(TPrefixType message) {
+    switch(message) {
+        case EPrefixNone:
+            break;
+        case EPrefixWarning:
+            sink.append("WARNING: ");
+            break;
+        case EPrefixError:
+            sink.append("ERROR: ");
+            break;
+        case EPrefixInternalError:
+            sink.append("INTERNAL ERROR: ");
+            break;
+        case EPrefixUnimplemented:
+            sink.append("UNIMPLEMENTED: ");
+            break;
+        case EPrefixNote:
+            sink.append("NOTE: ");
+            break;
+        default:
+            sink.append("UNKOWN ERROR: ");
+            break;
+    }
+}
+
+void TInfoSinkBase::location(TSourceLoc loc) {
+    int string = 0, line = 0;
+    DecodeSourceLoc(loc, &string, &line);
+
+    TPersistStringStream stream;
+    if (line)
+        stream << string << ":" << line;
+    else
+        stream << string << ":? ";
+    stream << ": ";
+
+    sink.append(stream.str());
+}
+
+void TInfoSinkBase::message(TPrefixType message, const char* s) {
+    prefix(message);
+    sink.append(s);
+    sink.append("\n");
+}
+
+void TInfoSinkBase::message(TPrefixType message, const char* s, TSourceLoc loc) {
+    prefix(message);
+    location(loc);
+    sink.append(s);
+    sink.append("\n");
+}
diff --git a/src/GLES2/compiler/InfoSink.h b/src/GLES2/compiler/InfoSink.h
new file mode 100644
index 0000000..e2224e918
--- /dev/null
+++ b/src/GLES2/compiler/InfoSink.h
@@ -0,0 +1,115 @@
+//
+// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#ifndef _INFOSINK_INCLUDED_
+#define _INFOSINK_INCLUDED_
+
+#include <math.h>
+#include "compiler/Common.h"
+
+// Returns the fractional part of the given floating-point number.
+inline float fractionalPart(float f) {
+  float intPart = 0.0f;
+  return modff(f, &intPart);
+}
+
+//
+// TPrefixType is used to centralize how info log messages start.
+// See below.
+//
+enum TPrefixType {
+    EPrefixNone,
+    EPrefixWarning,
+    EPrefixError,
+    EPrefixInternalError,
+    EPrefixUnimplemented,
+    EPrefixNote
+};
+
+//
+// Encapsulate info logs for all objects that have them.
+//
+// The methods are a general set of tools for getting a variety of
+// messages and types inserted into the log.
+//
+class TInfoSinkBase {
+public:
+    TInfoSinkBase() {}
+
+    template <typename T>
+    TInfoSinkBase& operator<<(const T& t) {
+        TPersistStringStream stream;
+        stream << t;
+        sink.append(stream.str());
+        return *this;
+    }
+    // Override << operator for specific types. It is faster to append strings
+    // and characters directly to the sink.
+    TInfoSinkBase& operator<<(char c) {
+        sink.append(1, c);
+        return *this;
+    }
+    TInfoSinkBase& operator<<(const char* str) {
+        sink.append(str);
+        return *this;
+    }
+    TInfoSinkBase& operator<<(const TPersistString& str) {
+        sink.append(str);
+        return *this;
+    }
+    TInfoSinkBase& operator<<(const TString& str) {
+        sink.append(str.c_str());
+        return *this;
+    }
+    // Make sure floats are written with correct precision.
+    TInfoSinkBase& operator<<(float f) {
+        // Make sure that at least one decimal point is written. If a number
+        // does not have a fractional part, the default precision format does
+        // not write the decimal portion which gets interpreted as integer by
+        // the compiler.
+        TPersistStringStream stream;
+        if (fractionalPart(f) == 0.0f) {
+            stream.precision(1);
+            stream << std::showpoint << std::fixed << f;
+        } else {
+            stream.unsetf(std::ios::fixed);
+            stream.unsetf(std::ios::scientific);
+            stream.precision(8);
+            stream << f;
+        }
+        sink.append(stream.str());
+        return *this;
+    }
+    // Write boolean values as their names instead of integral value.
+    TInfoSinkBase& operator<<(bool b) {
+        const char* str = b ? "true" : "false";
+        sink.append(str);
+        return *this;
+    }
+
+    void erase() { sink.clear(); }
+    int size() { return static_cast<int>(sink.size()); }
+
+    const TPersistString& str() const { return sink; }
+    const char* c_str() const { return sink.c_str(); }
+
+    void prefix(TPrefixType message);
+    void location(TSourceLoc loc);
+    void message(TPrefixType message, const char* s);
+    void message(TPrefixType message, const char* s, TSourceLoc loc);
+
+private:
+    TPersistString sink;
+};
+
+class TInfoSink {
+public:
+    TInfoSinkBase info;
+    TInfoSinkBase debug;
+    TInfoSinkBase obj;
+};
+
+#endif // _INFOSINK_INCLUDED_
diff --git a/src/GLES2/compiler/Initialize.cpp b/src/GLES2/compiler/Initialize.cpp
new file mode 100644
index 0000000..401b9b8
--- /dev/null
+++ b/src/GLES2/compiler/Initialize.cpp
@@ -0,0 +1,628 @@
+//
+// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+//
+// Create strings that declare built-in definitions, add built-ins that
+// cannot be expressed in the files, and establish mappings between 
+// built-in functions and operators.
+//
+
+#include "compiler/Initialize.h"
+
+#include "compiler/intermediate.h"
+
+//============================================================================
+//
+// Prototypes for built-in functions seen by both vertex and fragment shaders.
+//
+//============================================================================
+static TString BuiltInFunctionsCommon()
+{
+    TString s;
+
+    //
+    // Angle and Trigonometric Functions.
+    //
+    s.append(TString("float radians(float degrees);"));
+    s.append(TString("vec2  radians(vec2  degrees);"));
+    s.append(TString("vec3  radians(vec3  degrees);"));
+    s.append(TString("vec4  radians(vec4  degrees);"));
+
+    s.append(TString("float degrees(float radians);"));
+    s.append(TString("vec2  degrees(vec2  radians);"));
+    s.append(TString("vec3  degrees(vec3  radians);"));
+    s.append(TString("vec4  degrees(vec4  radians);"));
+
+    s.append(TString("float sin(float angle);"));
+    s.append(TString("vec2  sin(vec2  angle);"));
+    s.append(TString("vec3  sin(vec3  angle);"));
+    s.append(TString("vec4  sin(vec4  angle);"));
+
+    s.append(TString("float cos(float angle);"));
+    s.append(TString("vec2  cos(vec2  angle);"));
+    s.append(TString("vec3  cos(vec3  angle);"));
+    s.append(TString("vec4  cos(vec4  angle);"));
+
+    s.append(TString("float tan(float angle);"));
+    s.append(TString("vec2  tan(vec2  angle);"));
+    s.append(TString("vec3  tan(vec3  angle);"));
+    s.append(TString("vec4  tan(vec4  angle);"));
+
+    s.append(TString("float asin(float x);"));
+    s.append(TString("vec2  asin(vec2  x);"));
+    s.append(TString("vec3  asin(vec3  x);"));
+    s.append(TString("vec4  asin(vec4  x);"));
+
+    s.append(TString("float acos(float x);"));
+    s.append(TString("vec2  acos(vec2  x);"));
+    s.append(TString("vec3  acos(vec3  x);"));
+    s.append(TString("vec4  acos(vec4  x);"));
+
+    s.append(TString("float atan(float y, float x);"));
+    s.append(TString("vec2  atan(vec2  y, vec2  x);"));
+    s.append(TString("vec3  atan(vec3  y, vec3  x);"));
+    s.append(TString("vec4  atan(vec4  y, vec4  x);"));
+
+    s.append(TString("float atan(float y_over_x);"));
+    s.append(TString("vec2  atan(vec2  y_over_x);"));
+    s.append(TString("vec3  atan(vec3  y_over_x);"));
+    s.append(TString("vec4  atan(vec4  y_over_x);"));
+
+    //
+    // Exponential Functions.
+    //
+    s.append(TString("float pow(float x, float y);"));
+    s.append(TString("vec2  pow(vec2  x, vec2  y);"));
+    s.append(TString("vec3  pow(vec3  x, vec3  y);"));
+    s.append(TString("vec4  pow(vec4  x, vec4  y);"));
+
+    s.append(TString("float exp(float x);"));
+    s.append(TString("vec2  exp(vec2  x);"));
+    s.append(TString("vec3  exp(vec3  x);"));
+    s.append(TString("vec4  exp(vec4  x);"));
+
+    s.append(TString("float log(float x);"));
+    s.append(TString("vec2  log(vec2  x);"));
+    s.append(TString("vec3  log(vec3  x);"));
+    s.append(TString("vec4  log(vec4  x);"));
+
+    s.append(TString("float exp2(float x);"));
+    s.append(TString("vec2  exp2(vec2  x);"));
+    s.append(TString("vec3  exp2(vec3  x);"));
+    s.append(TString("vec4  exp2(vec4  x);"));
+
+    s.append(TString("float log2(float x);"));
+    s.append(TString("vec2  log2(vec2  x);"));
+    s.append(TString("vec3  log2(vec3  x);"));
+    s.append(TString("vec4  log2(vec4  x);"));
+
+    s.append(TString("float sqrt(float x);"));
+    s.append(TString("vec2  sqrt(vec2  x);"));
+    s.append(TString("vec3  sqrt(vec3  x);"));
+    s.append(TString("vec4  sqrt(vec4  x);"));
+
+    s.append(TString("float inversesqrt(float x);"));
+    s.append(TString("vec2  inversesqrt(vec2  x);"));
+    s.append(TString("vec3  inversesqrt(vec3  x);"));
+    s.append(TString("vec4  inversesqrt(vec4  x);"));
+
+    //
+    // Common Functions.
+    //
+    s.append(TString("float abs(float x);"));
+    s.append(TString("vec2  abs(vec2  x);"));
+    s.append(TString("vec3  abs(vec3  x);"));
+    s.append(TString("vec4  abs(vec4  x);"));
+
+    s.append(TString("float sign(float x);"));
+    s.append(TString("vec2  sign(vec2  x);"));
+    s.append(TString("vec3  sign(vec3  x);"));
+    s.append(TString("vec4  sign(vec4  x);"));
+
+    s.append(TString("float floor(float x);"));
+    s.append(TString("vec2  floor(vec2  x);"));
+    s.append(TString("vec3  floor(vec3  x);"));
+    s.append(TString("vec4  floor(vec4  x);"));
+
+    s.append(TString("float ceil(float x);"));
+    s.append(TString("vec2  ceil(vec2  x);"));
+    s.append(TString("vec3  ceil(vec3  x);"));
+    s.append(TString("vec4  ceil(vec4  x);"));
+
+    s.append(TString("float fract(float x);"));
+    s.append(TString("vec2  fract(vec2  x);"));
+    s.append(TString("vec3  fract(vec3  x);"));
+    s.append(TString("vec4  fract(vec4  x);"));
+
+    s.append(TString("float mod(float x, float y);"));
+    s.append(TString("vec2  mod(vec2  x, float y);"));
+    s.append(TString("vec3  mod(vec3  x, float y);"));
+    s.append(TString("vec4  mod(vec4  x, float y);"));
+    s.append(TString("vec2  mod(vec2  x, vec2  y);"));
+    s.append(TString("vec3  mod(vec3  x, vec3  y);"));
+    s.append(TString("vec4  mod(vec4  x, vec4  y);"));
+
+    s.append(TString("float min(float x, float y);"));
+    s.append(TString("vec2  min(vec2  x, float y);"));
+    s.append(TString("vec3  min(vec3  x, float y);"));
+    s.append(TString("vec4  min(vec4  x, float y);"));
+    s.append(TString("vec2  min(vec2  x, vec2  y);"));
+    s.append(TString("vec3  min(vec3  x, vec3  y);"));
+    s.append(TString("vec4  min(vec4  x, vec4  y);"));
+
+    s.append(TString("float max(float x, float y);"));
+    s.append(TString("vec2  max(vec2  x, float y);"));
+    s.append(TString("vec3  max(vec3  x, float y);"));
+    s.append(TString("vec4  max(vec4  x, float y);"));
+    s.append(TString("vec2  max(vec2  x, vec2  y);"));
+    s.append(TString("vec3  max(vec3  x, vec3  y);"));
+    s.append(TString("vec4  max(vec4  x, vec4  y);"));
+
+    s.append(TString("float clamp(float x, float minVal, float maxVal);"));
+    s.append(TString("vec2  clamp(vec2  x, float minVal, float maxVal);"));
+    s.append(TString("vec3  clamp(vec3  x, float minVal, float maxVal);"));
+    s.append(TString("vec4  clamp(vec4  x, float minVal, float maxVal);"));
+    s.append(TString("vec2  clamp(vec2  x, vec2  minVal, vec2  maxVal);"));
+    s.append(TString("vec3  clamp(vec3  x, vec3  minVal, vec3  maxVal);"));
+    s.append(TString("vec4  clamp(vec4  x, vec4  minVal, vec4  maxVal);"));
+
+    s.append(TString("float mix(float x, float y, float a);"));
+    s.append(TString("vec2  mix(vec2  x, vec2  y, float a);"));
+    s.append(TString("vec3  mix(vec3  x, vec3  y, float a);"));
+    s.append(TString("vec4  mix(vec4  x, vec4  y, float a);"));
+    s.append(TString("vec2  mix(vec2  x, vec2  y, vec2  a);"));
+    s.append(TString("vec3  mix(vec3  x, vec3  y, vec3  a);"));
+    s.append(TString("vec4  mix(vec4  x, vec4  y, vec4  a);"));
+
+    s.append(TString("float step(float edge, float x);"));
+    s.append(TString("vec2  step(vec2  edge, vec2  x);"));
+    s.append(TString("vec3  step(vec3  edge, vec3  x);"));
+    s.append(TString("vec4  step(vec4  edge, vec4  x);"));
+    s.append(TString("vec2  step(float edge, vec2  x);"));
+    s.append(TString("vec3  step(float edge, vec3  x);"));
+    s.append(TString("vec4  step(float edge, vec4  x);"));
+
+    s.append(TString("float smoothstep(float edge0, float edge1, float x);"));
+    s.append(TString("vec2  smoothstep(vec2  edge0, vec2  edge1, vec2  x);"));
+    s.append(TString("vec3  smoothstep(vec3  edge0, vec3  edge1, vec3  x);"));
+    s.append(TString("vec4  smoothstep(vec4  edge0, vec4  edge1, vec4  x);"));
+    s.append(TString("vec2  smoothstep(float edge0, float edge1, vec2  x);"));
+    s.append(TString("vec3  smoothstep(float edge0, float edge1, vec3  x);"));
+    s.append(TString("vec4  smoothstep(float edge0, float edge1, vec4  x);"));
+
+    //
+    // Geometric Functions.
+    //
+    s.append(TString("float length(float x);"));
+    s.append(TString("float length(vec2  x);"));
+    s.append(TString("float length(vec3  x);"));
+    s.append(TString("float length(vec4  x);"));
+
+    s.append(TString("float distance(float p0, float p1);"));
+    s.append(TString("float distance(vec2  p0, vec2  p1);"));
+    s.append(TString("float distance(vec3  p0, vec3  p1);"));
+    s.append(TString("float distance(vec4  p0, vec4  p1);"));
+
+    s.append(TString("float dot(float x, float y);"));
+    s.append(TString("float dot(vec2  x, vec2  y);"));
+    s.append(TString("float dot(vec3  x, vec3  y);"));
+    s.append(TString("float dot(vec4  x, vec4  y);"));
+
+    s.append(TString("vec3 cross(vec3 x, vec3 y);"));
+    s.append(TString("float normalize(float x);"));
+    s.append(TString("vec2  normalize(vec2  x);"));
+    s.append(TString("vec3  normalize(vec3  x);"));
+    s.append(TString("vec4  normalize(vec4  x);"));
+
+    s.append(TString("float faceforward(float N, float I, float Nref);"));
+    s.append(TString("vec2  faceforward(vec2  N, vec2  I, vec2  Nref);"));
+    s.append(TString("vec3  faceforward(vec3  N, vec3  I, vec3  Nref);"));
+    s.append(TString("vec4  faceforward(vec4  N, vec4  I, vec4  Nref);"));
+
+    s.append(TString("float reflect(float I, float N);"));
+    s.append(TString("vec2  reflect(vec2  I, vec2  N);"));
+    s.append(TString("vec3  reflect(vec3  I, vec3  N);"));
+    s.append(TString("vec4  reflect(vec4  I, vec4  N);"));
+
+    s.append(TString("float refract(float I, float N, float eta);"));
+    s.append(TString("vec2  refract(vec2  I, vec2  N, float eta);"));
+    s.append(TString("vec3  refract(vec3  I, vec3  N, float eta);"));
+    s.append(TString("vec4  refract(vec4  I, vec4  N, float eta);"));
+
+    //
+    // Matrix Functions.
+    //
+    s.append(TString("mat2 matrixCompMult(mat2 x, mat2 y);"));
+    s.append(TString("mat3 matrixCompMult(mat3 x, mat3 y);"));
+    s.append(TString("mat4 matrixCompMult(mat4 x, mat4 y);"));
+
+    //
+    // Vector relational functions.
+    //
+    s.append(TString("bvec2 lessThan(vec2 x, vec2 y);"));
+    s.append(TString("bvec3 lessThan(vec3 x, vec3 y);"));
+    s.append(TString("bvec4 lessThan(vec4 x, vec4 y);"));
+
+    s.append(TString("bvec2 lessThan(ivec2 x, ivec2 y);"));
+    s.append(TString("bvec3 lessThan(ivec3 x, ivec3 y);"));
+    s.append(TString("bvec4 lessThan(ivec4 x, ivec4 y);"));
+
+    s.append(TString("bvec2 lessThanEqual(vec2 x, vec2 y);"));
+    s.append(TString("bvec3 lessThanEqual(vec3 x, vec3 y);"));
+    s.append(TString("bvec4 lessThanEqual(vec4 x, vec4 y);"));
+
+    s.append(TString("bvec2 lessThanEqual(ivec2 x, ivec2 y);"));
+    s.append(TString("bvec3 lessThanEqual(ivec3 x, ivec3 y);"));
+    s.append(TString("bvec4 lessThanEqual(ivec4 x, ivec4 y);"));
+
+    s.append(TString("bvec2 greaterThan(vec2 x, vec2 y);"));
+    s.append(TString("bvec3 greaterThan(vec3 x, vec3 y);"));
+    s.append(TString("bvec4 greaterThan(vec4 x, vec4 y);"));
+
+    s.append(TString("bvec2 greaterThan(ivec2 x, ivec2 y);"));
+    s.append(TString("bvec3 greaterThan(ivec3 x, ivec3 y);"));
+    s.append(TString("bvec4 greaterThan(ivec4 x, ivec4 y);"));
+
+    s.append(TString("bvec2 greaterThanEqual(vec2 x, vec2 y);"));
+    s.append(TString("bvec3 greaterThanEqual(vec3 x, vec3 y);"));
+    s.append(TString("bvec4 greaterThanEqual(vec4 x, vec4 y);"));
+
+    s.append(TString("bvec2 greaterThanEqual(ivec2 x, ivec2 y);"));
+    s.append(TString("bvec3 greaterThanEqual(ivec3 x, ivec3 y);"));
+    s.append(TString("bvec4 greaterThanEqual(ivec4 x, ivec4 y);"));
+
+    s.append(TString("bvec2 equal(vec2 x, vec2 y);"));
+    s.append(TString("bvec3 equal(vec3 x, vec3 y);"));
+    s.append(TString("bvec4 equal(vec4 x, vec4 y);"));
+
+    s.append(TString("bvec2 equal(ivec2 x, ivec2 y);"));
+    s.append(TString("bvec3 equal(ivec3 x, ivec3 y);"));
+    s.append(TString("bvec4 equal(ivec4 x, ivec4 y);"));
+
+    s.append(TString("bvec2 equal(bvec2 x, bvec2 y);"));
+    s.append(TString("bvec3 equal(bvec3 x, bvec3 y);"));
+    s.append(TString("bvec4 equal(bvec4 x, bvec4 y);"));
+
+    s.append(TString("bvec2 notEqual(vec2 x, vec2 y);"));
+    s.append(TString("bvec3 notEqual(vec3 x, vec3 y);"));
+    s.append(TString("bvec4 notEqual(vec4 x, vec4 y);"));
+
+    s.append(TString("bvec2 notEqual(ivec2 x, ivec2 y);"));
+    s.append(TString("bvec3 notEqual(ivec3 x, ivec3 y);"));
+    s.append(TString("bvec4 notEqual(ivec4 x, ivec4 y);"));
+
+    s.append(TString("bvec2 notEqual(bvec2 x, bvec2 y);"));
+    s.append(TString("bvec3 notEqual(bvec3 x, bvec3 y);"));
+    s.append(TString("bvec4 notEqual(bvec4 x, bvec4 y);"));
+
+    s.append(TString("bool any(bvec2 x);"));
+    s.append(TString("bool any(bvec3 x);"));
+    s.append(TString("bool any(bvec4 x);"));
+
+    s.append(TString("bool all(bvec2 x);"));
+    s.append(TString("bool all(bvec3 x);"));
+    s.append(TString("bool all(bvec4 x);"));
+
+    s.append(TString("bvec2 not(bvec2 x);"));
+    s.append(TString("bvec3 not(bvec3 x);"));
+    s.append(TString("bvec4 not(bvec4 x);"));
+
+    //
+    // Texture Functions.
+    //
+    s.append(TString("vec4 texture2D(sampler2D sampler, vec2 coord);"));
+    s.append(TString("vec4 texture2DProj(sampler2D sampler, vec3 coord);"));
+    s.append(TString("vec4 texture2DProj(sampler2D sampler, vec4 coord);"));
+    s.append(TString("vec4 textureCube(samplerCube sampler, vec3 coord);"));
+
+    //
+    // Noise functions.
+    //
+    //s.append(TString("float noise1(float x);"));
+    //s.append(TString("float noise1(vec2  x);"));
+    //s.append(TString("float noise1(vec3  x);"));
+    //s.append(TString("float noise1(vec4  x);"));
+
+    //s.append(TString("vec2 noise2(float x);"));
+    //s.append(TString("vec2 noise2(vec2  x);"));
+    //s.append(TString("vec2 noise2(vec3  x);"));
+    //s.append(TString("vec2 noise2(vec4  x);"));
+
+    //s.append(TString("vec3 noise3(float x);"));
+    //s.append(TString("vec3 noise3(vec2  x);"));
+    //s.append(TString("vec3 noise3(vec3  x);"));
+    //s.append(TString("vec3 noise3(vec4  x);"));
+
+    //s.append(TString("vec4 noise4(float x);"));
+    //s.append(TString("vec4 noise4(vec2  x);"));
+    //s.append(TString("vec4 noise4(vec3  x);"));
+    //s.append(TString("vec4 noise4(vec4  x);"));
+
+    return s;
+}
+
+//============================================================================
+//
+// Prototypes for built-in functions seen by vertex shaders only.
+//
+//============================================================================
+static TString BuiltInFunctionsVertex(const ShBuiltInResources& resources)
+{
+    TString s;
+
+    //
+    // Geometric Functions.
+    //
+    //s.append(TString("vec4 ftransform();"));
+
+    //
+    // Texture Functions.
+    //
+    s.append(TString("vec4 texture2DLod(sampler2D sampler, vec2 coord, float lod);"));
+    s.append(TString("vec4 texture2DProjLod(sampler2D sampler, vec3 coord, float lod);"));
+    s.append(TString("vec4 texture2DProjLod(sampler2D sampler, vec4 coord, float lod);"));
+    s.append(TString("vec4 textureCubeLod(samplerCube sampler, vec3 coord, float lod);"));
+
+    return s;
+}
+
+//============================================================================
+//
+// Prototypes for built-in functions seen by fragment shaders only.
+//
+//============================================================================
+static TString BuiltInFunctionsFragment(const ShBuiltInResources& resources)
+{
+    TString s;
+
+    //
+    // Texture Functions.
+    //
+    s.append(TString("vec4 texture2D(sampler2D sampler, vec2 coord, float bias);"));
+    s.append(TString("vec4 texture2DProj(sampler2D sampler, vec3 coord, float bias);"));
+    s.append(TString("vec4 texture2DProj(sampler2D sampler, vec4 coord, float bias);"));
+    s.append(TString("vec4 textureCube(samplerCube sampler, vec3 coord, float bias);"));
+
+    if (resources.OES_standard_derivatives)
+	{
+        s.append(TString("float dFdx(float p);"));
+        s.append(TString("vec2  dFdx(vec2  p);"));
+        s.append(TString("vec3  dFdx(vec3  p);"));
+        s.append(TString("vec4  dFdx(vec4  p);"));
+
+        s.append(TString("float dFdy(float p);"));
+        s.append(TString("vec2  dFdy(vec2  p);"));
+        s.append(TString("vec3  dFdy(vec3  p);"));
+        s.append(TString("vec4  dFdy(vec4  p);"));
+
+        s.append(TString("float fwidth(float p);"));
+        s.append(TString("vec2  fwidth(vec2  p);"));
+        s.append(TString("vec3  fwidth(vec3  p);"));
+        s.append(TString("vec4  fwidth(vec4  p);"));
+    }
+
+    return s;
+}
+
+//============================================================================
+//
+// Standard uniforms.
+//
+//============================================================================
+static TString StandardUniforms()
+{
+    TString s;
+
+    //
+    // Depth range in window coordinates
+    //
+    s.append(TString("struct gl_DepthRangeParameters {"));
+    s.append(TString("    highp float near;"));        // n
+    s.append(TString("    highp float far;"));         // f
+    s.append(TString("    highp float diff;"));        // f - n
+    s.append(TString("};"));
+    s.append(TString("uniform gl_DepthRangeParameters gl_DepthRange;"));
+
+    return s;
+}
+
+//============================================================================
+//
+// Default precision for vertex shaders.
+//
+//============================================================================
+static TString DefaultPrecisionVertex()
+{
+    TString s;
+
+    s.append(TString("precision highp int;"));
+    s.append(TString("precision highp float;"));
+
+    return s;
+}
+
+//============================================================================
+//
+// Default precision for fragment shaders.
+//
+//============================================================================
+static TString DefaultPrecisionFragment()
+{
+    TString s;
+
+    s.append(TString("precision mediump int;"));
+    // No default precision for float in fragment shaders
+
+    return s;
+}
+
+//============================================================================
+//
+// Implementation dependent built-in constants.
+//
+//============================================================================
+static TString BuiltInConstants(const ShBuiltInResources &resources)
+{
+    TStringStream s;
+
+    s << "const int gl_MaxVertexAttribs = " << resources.MaxVertexAttribs << ";";
+    s << "const int gl_MaxVertexUniformVectors = " << resources.MaxVertexUniformVectors << ";";
+
+    s << "const int gl_MaxVaryingVectors = " << resources.MaxVaryingVectors << ";";
+    s << "const int gl_MaxVertexTextureImageUnits = " << resources.MaxVertexTextureImageUnits << ";";
+    s << "const int gl_MaxCombinedTextureImageUnits = " << resources.MaxCombinedTextureImageUnits << ";";
+    s << "const int gl_MaxTextureImageUnits = " << resources.MaxTextureImageUnits << ";";
+    s << "const int gl_MaxFragmentUniformVectors = " << resources.MaxFragmentUniformVectors << ";";
+    s << "const int gl_MaxDrawBuffers = " << resources.MaxDrawBuffers << ";";
+
+    return s.str();
+}
+
+void TBuiltIns::initialize(ShShaderType type, ShShaderSpec spec,
+                           const ShBuiltInResources& resources)
+{
+    switch (type) {
+    case SH_FRAGMENT_SHADER:
+        builtInStrings.push_back(DefaultPrecisionFragment());
+        builtInStrings.push_back(BuiltInFunctionsCommon());
+        builtInStrings.push_back(BuiltInFunctionsFragment(resources));
+        builtInStrings.push_back(StandardUniforms());
+        break;
+
+    case SH_VERTEX_SHADER:
+        builtInStrings.push_back(DefaultPrecisionVertex());
+        builtInStrings.push_back(BuiltInFunctionsCommon());
+        builtInStrings.push_back(BuiltInFunctionsVertex(resources));
+        builtInStrings.push_back(StandardUniforms());
+        break;
+
+    default: assert(false && "Language not supported");
+    }
+
+    builtInStrings.push_back(BuiltInConstants(resources));
+}
+
+void IdentifyBuiltIns(ShShaderType type, ShShaderSpec spec,
+                      const ShBuiltInResources& resources,
+                      TSymbolTable& symbolTable)
+{
+    //
+    // First, insert some special built-in variables that are not in 
+    // the built-in header files.
+    //
+    switch(type) {
+    case SH_FRAGMENT_SHADER:
+        symbolTable.insert(*new TVariable(NewPoolTString("gl_FragCoord"),                   TType(EbtFloat, EbpMedium, EvqFragCoord,   4)));
+        symbolTable.insert(*new TVariable(NewPoolTString("gl_FrontFacing"),                 TType(EbtBool,  EbpUndefined, EvqFrontFacing, 1)));
+        symbolTable.insert(*new TVariable(NewPoolTString("gl_FragColor"),                   TType(EbtFloat, EbpMedium, EvqFragColor,   4)));
+        symbolTable.insert(*new TVariable(NewPoolTString("gl_FragData[gl_MaxDrawBuffers]"), TType(EbtFloat, EbpMedium, EvqFragData,    4)));
+        symbolTable.insert(*new TVariable(NewPoolTString("gl_PointCoord"),                  TType(EbtFloat, EbpMedium, EvqPointCoord,  2)));
+        break;
+    case SH_VERTEX_SHADER:
+        symbolTable.insert(*new TVariable(NewPoolTString("gl_Position"),    TType(EbtFloat, EbpHigh, EvqPosition,    4)));
+        symbolTable.insert(*new TVariable(NewPoolTString("gl_PointSize"),   TType(EbtFloat, EbpMedium, EvqPointSize,   1)));
+        break;
+    default: assert(false && "Language not supported");
+    }
+
+    //
+    // Next, identify which built-ins from the already loaded headers have
+    // a mapping to an operator.  Those that are not identified as such are
+    // expected to be resolved through a library of functions, versus as
+    // operations.
+    //
+    symbolTable.relateToOperator("not",              EOpVectorLogicalNot);
+
+    symbolTable.relateToOperator("matrixCompMult",   EOpMul);
+
+    symbolTable.relateToOperator("equal",            EOpVectorEqual);
+    symbolTable.relateToOperator("notEqual",         EOpVectorNotEqual);
+    symbolTable.relateToOperator("lessThan",         EOpLessThan);
+    symbolTable.relateToOperator("greaterThan",      EOpGreaterThan);
+    symbolTable.relateToOperator("lessThanEqual",    EOpLessThanEqual);
+    symbolTable.relateToOperator("greaterThanEqual", EOpGreaterThanEqual);
+    
+    symbolTable.relateToOperator("radians",      EOpRadians);
+    symbolTable.relateToOperator("degrees",      EOpDegrees);
+    symbolTable.relateToOperator("sin",          EOpSin);
+    symbolTable.relateToOperator("cos",          EOpCos);
+    symbolTable.relateToOperator("tan",          EOpTan);
+    symbolTable.relateToOperator("asin",         EOpAsin);
+    symbolTable.relateToOperator("acos",         EOpAcos);
+    symbolTable.relateToOperator("atan",         EOpAtan);
+
+    symbolTable.relateToOperator("pow",          EOpPow);
+    symbolTable.relateToOperator("exp2",         EOpExp2);
+    symbolTable.relateToOperator("log",          EOpLog);
+    symbolTable.relateToOperator("exp",          EOpExp);
+    symbolTable.relateToOperator("log2",         EOpLog2);
+    symbolTable.relateToOperator("sqrt",         EOpSqrt);
+    symbolTable.relateToOperator("inversesqrt",  EOpInverseSqrt);
+
+    symbolTable.relateToOperator("abs",          EOpAbs);
+    symbolTable.relateToOperator("sign",         EOpSign);
+    symbolTable.relateToOperator("floor",        EOpFloor);
+    symbolTable.relateToOperator("ceil",         EOpCeil);
+    symbolTable.relateToOperator("fract",        EOpFract);
+    symbolTable.relateToOperator("mod",          EOpMod);
+    symbolTable.relateToOperator("min",          EOpMin);
+    symbolTable.relateToOperator("max",          EOpMax);
+    symbolTable.relateToOperator("clamp",        EOpClamp);
+    symbolTable.relateToOperator("mix",          EOpMix);
+    symbolTable.relateToOperator("step",         EOpStep);
+    symbolTable.relateToOperator("smoothstep",   EOpSmoothStep);
+
+    symbolTable.relateToOperator("length",       EOpLength);
+    symbolTable.relateToOperator("distance",     EOpDistance);
+    symbolTable.relateToOperator("dot",          EOpDot);
+    symbolTable.relateToOperator("cross",        EOpCross);
+    symbolTable.relateToOperator("normalize",    EOpNormalize);
+    symbolTable.relateToOperator("faceforward",  EOpFaceForward);
+    symbolTable.relateToOperator("reflect",      EOpReflect);
+    symbolTable.relateToOperator("refract",      EOpRefract);
+    
+    symbolTable.relateToOperator("any",          EOpAny);
+    symbolTable.relateToOperator("all",          EOpAll);
+
+    // Map language-specific operators.
+    switch(type) {
+    case SH_VERTEX_SHADER:
+        break;
+    case SH_FRAGMENT_SHADER:
+        if (resources.OES_standard_derivatives) {
+            symbolTable.relateToOperator("dFdx",   EOpDFdx);
+            symbolTable.relateToOperator("dFdy",   EOpDFdy);
+            symbolTable.relateToOperator("fwidth", EOpFwidth);
+
+            symbolTable.relateToExtension("dFdx", "GL_OES_standard_derivatives");
+            symbolTable.relateToExtension("dFdy", "GL_OES_standard_derivatives");
+            symbolTable.relateToExtension("fwidth", "GL_OES_standard_derivatives");
+        }
+        break;
+    default: break;
+    }
+
+    // Finally add resource-specific variables.
+    switch(type)
+    {
+    case SH_FRAGMENT_SHADER:
+		{
+            // Set up gl_FragData.  The array size.
+            TType fragData(EbtFloat, EbpMedium, EvqFragData, 4, false, true);
+            fragData.setArraySize(resources.MaxDrawBuffers);
+            symbolTable.insert(*new TVariable(NewPoolTString("gl_FragData"), fragData));
+		}
+		break;
+    default: break;
+    }
+}
+
+void InitExtensionBehavior(const ShBuiltInResources& resources,
+                           TExtensionBehavior& extBehavior)
+{
+    if (resources.OES_standard_derivatives)
+        extBehavior["GL_OES_standard_derivatives"] = EBhUndefined;
+}
diff --git a/src/GLES2/compiler/Initialize.h b/src/GLES2/compiler/Initialize.h
new file mode 100644
index 0000000..8b0adc6
--- /dev/null
+++ b/src/GLES2/compiler/Initialize.h
@@ -0,0 +1,35 @@
+//
+// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#ifndef _INITIALIZE_INCLUDED_
+#define _INITIALIZE_INCLUDED_
+
+#include "compiler/Common.h"
+#include "compiler/ShHandle.h"
+#include "compiler/SymbolTable.h"
+
+typedef TVector<TString> TBuiltInStrings;
+
+class TBuiltIns {
+public:
+    POOL_ALLOCATOR_NEW_DELETE(GlobalPoolAllocator)
+
+    void initialize(ShShaderType type, ShShaderSpec spec,
+                    const ShBuiltInResources& resources);
+    const TBuiltInStrings& getBuiltInStrings() { return builtInStrings; }
+
+protected:
+    TBuiltInStrings builtInStrings;
+};
+
+void IdentifyBuiltIns(ShShaderType type, ShShaderSpec spec,
+                      const ShBuiltInResources& resources,
+                      TSymbolTable& symbolTable);
+
+void InitExtensionBehavior(const ShBuiltInResources& resources,
+                           TExtensionBehavior& extensionBehavior);
+
+#endif // _INITIALIZE_INCLUDED_
diff --git a/src/GLES2/compiler/InitializeDll.cpp b/src/GLES2/compiler/InitializeDll.cpp
new file mode 100644
index 0000000..8763cfe
--- /dev/null
+++ b/src/GLES2/compiler/InitializeDll.cpp
@@ -0,0 +1,115 @@
+//
+// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "compiler/InitializeDll.h"
+
+#include "compiler/InitializeGlobals.h"
+#include "compiler/InitializeParseContext.h"
+#include "compiler/osinclude.h"
+
+OS_TLSIndex ThreadInitializeIndex = OS_INVALID_TLS_INDEX;
+
+bool InitProcess()
+{
+    if (ThreadInitializeIndex != OS_INVALID_TLS_INDEX) {
+        //
+        // Function is re-entrant.
+        //
+        return true;
+    }
+
+    ThreadInitializeIndex = OS_AllocTLSIndex();
+
+    if (ThreadInitializeIndex == OS_INVALID_TLS_INDEX) {
+        assert(0 && "InitProcess(): Failed to allocate TLS area for init flag");
+        return false;
+    }
+
+
+    if (!InitializePoolIndex()) {
+        assert(0 && "InitProcess(): Failed to initalize global pool");
+        return false;
+    }
+
+    if (!InitializeParseContextIndex()) {
+        assert(0 && "InitProcess(): Failed to initalize parse context");
+        return false;
+    }
+
+    return InitThread();
+}
+
+bool DetachProcess()
+{
+    bool success = true;
+
+    if (ThreadInitializeIndex == OS_INVALID_TLS_INDEX)
+        return true;
+
+    success = DetachThread();
+
+    if (!FreeParseContextIndex())
+        success = false;
+
+    FreePoolIndex();
+
+    OS_FreeTLSIndex(ThreadInitializeIndex);
+    ThreadInitializeIndex = OS_INVALID_TLS_INDEX;
+
+    return success;
+}
+
+bool InitThread()
+{
+    //
+    // This function is re-entrant
+    //
+    if (ThreadInitializeIndex == OS_INVALID_TLS_INDEX) {
+        assert(0 && "InitThread(): Process hasn't been initalised.");
+        return false;
+    }
+
+    if (OS_GetTLSValue(ThreadInitializeIndex) != 0)
+        return true;
+
+    InitializeGlobalPools();
+
+    if (!InitializeGlobalParseContext())
+        return false;
+
+    if (!OS_SetTLSValue(ThreadInitializeIndex, (void *)1)) {
+        assert(0 && "InitThread(): Unable to set init flag.");
+        return false;
+    }
+
+    return true;
+}
+
+bool DetachThread()
+{
+    bool success = true;
+
+    if (ThreadInitializeIndex == OS_INVALID_TLS_INDEX)
+        return true;
+
+    //
+    // Function is re-entrant and this thread may not have been initalised.
+    //
+    if (OS_GetTLSValue(ThreadInitializeIndex) != 0) {
+        if (!OS_SetTLSValue(ThreadInitializeIndex, (void *)0)) {
+            assert(0 && "DetachThread(): Unable to clear init flag.");
+            success = false;
+        }
+
+        if (!FreeParseContext())
+            success = false;
+
+        FreeGlobalPools();
+    }
+
+    return success;
+}
+
diff --git a/src/GLES2/compiler/InitializeDll.h b/src/GLES2/compiler/InitializeDll.h
new file mode 100644
index 0000000..857238e
--- /dev/null
+++ b/src/GLES2/compiler/InitializeDll.h
@@ -0,0 +1,16 @@
+//
+// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+#ifndef __INITIALIZEDLL_H
+#define __INITIALIZEDLL_H
+
+bool InitProcess();
+bool DetachProcess();
+
+bool InitThread();
+bool DetachThread();
+
+#endif // __INITIALIZEDLL_H
+
diff --git a/src/GLES2/compiler/InitializeGlobals.h b/src/GLES2/compiler/InitializeGlobals.h
new file mode 100644
index 0000000..842a452
--- /dev/null
+++ b/src/GLES2/compiler/InitializeGlobals.h
@@ -0,0 +1,15 @@
+//
+// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#ifndef __INITIALIZE_GLOBALS_INCLUDED_
+#define __INITIALIZE_GLOBALS_INCLUDED_
+
+void InitializeGlobalPools();
+void FreeGlobalPools();
+bool InitializePoolIndex();
+void FreePoolIndex();
+
+#endif // __INITIALIZE_GLOBALS_INCLUDED_
diff --git a/src/GLES2/compiler/InitializeParseContext.cpp b/src/GLES2/compiler/InitializeParseContext.cpp
new file mode 100644
index 0000000..1f40cf5
--- /dev/null
+++ b/src/GLES2/compiler/InitializeParseContext.cpp
@@ -0,0 +1,96 @@
+//
+// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "compiler/InitializeParseContext.h"
+
+#include "compiler/osinclude.h"
+
+OS_TLSIndex GlobalParseContextIndex = OS_INVALID_TLS_INDEX;
+
+bool InitializeParseContextIndex()
+{
+    if (GlobalParseContextIndex != OS_INVALID_TLS_INDEX) {
+        assert(0 && "InitializeParseContextIndex(): Parse Context already initalized");
+        return false;
+    }
+
+    //
+    // Allocate a TLS index.
+    //
+    GlobalParseContextIndex = OS_AllocTLSIndex();
+    
+    if (GlobalParseContextIndex == OS_INVALID_TLS_INDEX) {
+        assert(0 && "InitializeParseContextIndex(): Parse Context already initalized");
+        return false;
+    }
+
+    return true;
+}
+
+bool FreeParseContextIndex()
+{
+    OS_TLSIndex tlsiIndex = GlobalParseContextIndex;
+
+    if (GlobalParseContextIndex == OS_INVALID_TLS_INDEX) {
+        assert(0 && "FreeParseContextIndex(): Parse Context index not initalized");
+        return false;
+    }
+
+    GlobalParseContextIndex = OS_INVALID_TLS_INDEX;
+
+    return OS_FreeTLSIndex(tlsiIndex);
+}
+
+bool InitializeGlobalParseContext()
+{
+    if (GlobalParseContextIndex == OS_INVALID_TLS_INDEX) {
+        assert(0 && "InitializeGlobalParseContext(): Parse Context index not initalized");
+        return false;
+    }
+
+    TThreadParseContext *lpParseContext = static_cast<TThreadParseContext *>(OS_GetTLSValue(GlobalParseContextIndex));
+    if (lpParseContext != 0) {
+        assert(0 && "InitializeParseContextIndex(): Parse Context already initalized");
+        return false;
+    }
+
+    TThreadParseContext *lpThreadData = new TThreadParseContext();
+    if (lpThreadData == 0) {
+        assert(0 && "InitializeGlobalParseContext(): Unable to create thread parse context");
+        return false;
+    }
+
+    lpThreadData->lpGlobalParseContext = 0;
+    OS_SetTLSValue(GlobalParseContextIndex, lpThreadData);
+
+    return true;
+}
+
+bool FreeParseContext()
+{
+    if (GlobalParseContextIndex == OS_INVALID_TLS_INDEX) {
+        assert(0 && "FreeParseContext(): Parse Context index not initalized");
+        return false;
+    }
+
+    TThreadParseContext *lpParseContext = static_cast<TThreadParseContext *>(OS_GetTLSValue(GlobalParseContextIndex));
+    if (lpParseContext)
+        delete lpParseContext;
+
+    return true;
+}
+
+TParseContextPointer& GetGlobalParseContext()
+{
+    //
+    // Minimal error checking for speed
+    //
+
+    TThreadParseContext *lpParseContext = static_cast<TThreadParseContext *>(OS_GetTLSValue(GlobalParseContextIndex));
+
+    return lpParseContext->lpGlobalParseContext;
+}
+
diff --git a/src/GLES2/compiler/InitializeParseContext.h b/src/GLES2/compiler/InitializeParseContext.h
new file mode 100644
index 0000000..354bfe1
--- /dev/null
+++ b/src/GLES2/compiler/InitializeParseContext.h
@@ -0,0 +1,26 @@
+//
+// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#ifndef __INITIALIZE_PARSE_CONTEXT_INCLUDED_
+#define __INITIALIZE_PARSE_CONTEXT_INCLUDED_
+
+bool InitializeParseContextIndex();
+bool FreeParseContextIndex();
+
+bool InitializeGlobalParseContext();
+bool FreeParseContext();
+
+struct TParseContext;
+typedef TParseContext* TParseContextPointer;
+extern TParseContextPointer& GetGlobalParseContext();
+#define GlobalParseContext GetGlobalParseContext()
+
+typedef struct TThreadParseContextRec
+{
+    TParseContext *lpGlobalParseContext;
+} TThreadParseContext;
+
+#endif // __INITIALIZE_PARSE_CONTEXT_INCLUDED_
diff --git a/src/GLES2/compiler/IntermTraverse.cpp b/src/GLES2/compiler/IntermTraverse.cpp
new file mode 100644
index 0000000..a13877f
--- /dev/null
+++ b/src/GLES2/compiler/IntermTraverse.cpp
@@ -0,0 +1,293 @@
+//
+// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "compiler/intermediate.h"
+
+//
+// Traverse the intermediate representation tree, and
+// call a node type specific function for each node.
+// Done recursively through the member function Traverse().
+// Node types can be skipped if their function to call is 0,
+// but their subtree will still be traversed.
+// Nodes with children can have their whole subtree skipped
+// if preVisit is turned on and the type specific function
+// returns false.
+//
+// preVisit, postVisit, and rightToLeft control what order
+// nodes are visited in.
+//
+
+//
+// Traversal functions for terminals are straighforward....
+//
+void TIntermSymbol::traverse(TIntermTraverser* it)
+{
+	it->visitSymbol(this);
+}
+
+void TIntermConstantUnion::traverse(TIntermTraverser* it)
+{
+	it->visitConstantUnion(this);
+}
+
+//
+// Traverse a binary node.
+//
+void TIntermBinary::traverse(TIntermTraverser* it)
+{
+	bool visit = true;
+
+	//
+	// visit the node before children if pre-visiting.
+	//
+	if(it->preVisit)
+	{
+		visit = it->visitBinary(PreVisit, this);
+	}
+	
+	//
+	// Visit the children, in the right order.
+	//
+	if(visit)
+	{
+		it->incrementDepth();
+
+		if(it->rightToLeft) 
+		{
+			if(right)
+			{
+				right->traverse(it);
+			}
+			
+			if(it->inVisit)
+			{
+				visit = it->visitBinary(InVisit, this);
+			}
+
+			if(visit && left)
+			{
+				left->traverse(it);
+			}
+		}
+		else
+		{
+			if(left)
+			{
+				left->traverse(it);
+			}
+			
+			if(it->inVisit)
+			{
+				visit = it->visitBinary(InVisit, this);
+			}
+
+			if(visit && right)
+			{
+				right->traverse(it);
+			}
+		}
+
+		it->decrementDepth();
+	}
+
+	//
+	// Visit the node after the children, if requested and the traversal
+	// hasn't been cancelled yet.
+	//
+	if(visit && it->postVisit)
+	{
+		it->visitBinary(PostVisit, this);
+	}
+}
+
+//
+// Traverse a unary node.  Same comments in binary node apply here.
+//
+void TIntermUnary::traverse(TIntermTraverser* it)
+{
+	bool visit = true;
+
+	if (it->preVisit)
+		visit = it->visitUnary(PreVisit, this);
+
+	if (visit) {
+		it->incrementDepth();
+		operand->traverse(it);
+		it->decrementDepth();
+	}
+	
+	if (visit && it->postVisit)
+		it->visitUnary(PostVisit, this);
+}
+
+//
+// Traverse an aggregate node.  Same comments in binary node apply here.
+//
+void TIntermAggregate::traverse(TIntermTraverser* it)
+{
+	bool visit = true;
+	
+	if(it->preVisit)
+	{
+		visit = it->visitAggregate(PreVisit, this);
+	}
+	
+	if(visit)
+	{
+		it->incrementDepth();
+
+		if(it->rightToLeft)
+		{
+			for(TIntermSequence::reverse_iterator sit = sequence.rbegin(); sit != sequence.rend(); sit++)
+			{
+				(*sit)->traverse(it);
+
+				if(visit && it->inVisit)
+				{
+					if(*sit != sequence.front())
+					{
+						visit = it->visitAggregate(InVisit, this);
+					}
+				}
+			}
+		}
+		else
+		{
+			for(TIntermSequence::iterator sit = sequence.begin(); sit != sequence.end(); sit++)
+			{
+				(*sit)->traverse(it);
+
+				if(visit && it->inVisit)
+				{
+					if(*sit != sequence.back())
+					{
+						visit = it->visitAggregate(InVisit, this);
+					}
+				}
+			}
+		}
+		
+		it->decrementDepth();
+	}
+
+	if(visit && it->postVisit)
+	{
+		it->visitAggregate(PostVisit, this);
+	}
+}
+
+//
+// Traverse a selection node.  Same comments in binary node apply here.
+//
+void TIntermSelection::traverse(TIntermTraverser* it)
+{
+	bool visit = true;
+
+	if (it->preVisit)
+		visit = it->visitSelection(PreVisit, this);
+	
+	if (visit) {
+		it->incrementDepth();
+		if (it->rightToLeft) {
+			if (falseBlock)
+				falseBlock->traverse(it);
+			if (trueBlock)
+				trueBlock->traverse(it);
+			condition->traverse(it);
+		} else {
+			condition->traverse(it);
+			if (trueBlock)
+				trueBlock->traverse(it);
+			if (falseBlock)
+				falseBlock->traverse(it);
+		}
+		it->decrementDepth();
+	}
+
+	if (visit && it->postVisit)
+		it->visitSelection(PostVisit, this);
+}
+
+//
+// Traverse a loop node.  Same comments in binary node apply here.
+//
+void TIntermLoop::traverse(TIntermTraverser* it)
+{
+	bool visit = true;
+
+	if(it->preVisit)
+	{
+		visit = it->visitLoop(PreVisit, this);
+	}
+	
+	if(visit)
+	{
+		it->incrementDepth();
+
+		if(it->rightToLeft)
+		{
+			if(expr)
+			{
+				expr->traverse(it);
+			}
+
+			if(body)
+			{
+				body->traverse(it);
+			}
+
+			if(cond)
+			{
+				cond->traverse(it);
+			}
+		}
+		else
+		{
+			if(cond)
+			{
+				cond->traverse(it);
+			}
+
+			if(body)
+			{
+				body->traverse(it);
+			}
+
+			if(expr)
+			{
+				expr->traverse(it);
+			}
+		}
+
+		it->decrementDepth();
+	}
+
+	if(visit && it->postVisit)
+	{
+		it->visitLoop(PostVisit, this);
+	}
+}
+
+//
+// Traverse a branch node.  Same comments in binary node apply here.
+//
+void TIntermBranch::traverse(TIntermTraverser* it)
+{
+	bool visit = true;
+
+	if (it->preVisit)
+		visit = it->visitBranch(PreVisit, this);
+	
+	if (visit && expression) {
+		it->incrementDepth();
+		expression->traverse(it);
+		it->decrementDepth();
+	}
+
+	if (visit && it->postVisit)
+		it->visitBranch(PostVisit, this);
+}
+
diff --git a/src/GLES2/compiler/Intermediate.cpp b/src/GLES2/compiler/Intermediate.cpp
new file mode 100644
index 0000000..5ef2789
--- /dev/null
+++ b/src/GLES2/compiler/Intermediate.cpp
@@ -0,0 +1,1452 @@
+//
+// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+//
+// Build the intermediate representation.
+//
+
+#include <float.h>
+#include <limits.h>
+#include <algorithm>
+
+#include "compiler/localintermediate.h"
+#include "compiler/QualifierAlive.h"
+#include "compiler/RemoveTree.h"
+
+bool CompareStructure(const TType& leftNodeType, ConstantUnion* rightUnionArray, ConstantUnion* leftUnionArray);
+
+static TPrecision GetHigherPrecision( TPrecision left, TPrecision right ){
+    return left > right ? left : right;
+}
+
+const char* getOperatorString(TOperator op) {
+    switch (op) {
+      case EOpInitialize: return "=";
+      case EOpAssign: return "=";
+      case EOpAddAssign: return "+=";
+      case EOpSubAssign: return "-=";
+      case EOpDivAssign: return "/=";
+
+      // Fall-through.
+      case EOpMulAssign: 
+      case EOpVectorTimesMatrixAssign:
+      case EOpVectorTimesScalarAssign:
+      case EOpMatrixTimesScalarAssign:
+      case EOpMatrixTimesMatrixAssign: return "*=";
+
+      // Fall-through.
+      case EOpIndexDirect:
+      case EOpIndexIndirect: return "[]";
+
+      case EOpIndexDirectStruct: return ".";
+      case EOpVectorSwizzle: return ".";
+      case EOpAdd: return "+";
+      case EOpSub: return "-";
+      case EOpMul: return "*";
+      case EOpDiv: return "/";
+      case EOpMod: UNIMPLEMENTED(); break;
+      case EOpEqual: return "==";
+      case EOpNotEqual: return "!=";
+      case EOpLessThan: return "<";
+      case EOpGreaterThan: return ">";
+      case EOpLessThanEqual: return "<=";
+      case EOpGreaterThanEqual: return ">=";
+
+      // Fall-through.
+      case EOpVectorTimesScalar:
+      case EOpVectorTimesMatrix:
+      case EOpMatrixTimesVector:
+      case EOpMatrixTimesScalar:
+      case EOpMatrixTimesMatrix: return "*";
+
+      case EOpLogicalOr: return "||";
+      case EOpLogicalXor: return "^^";
+      case EOpLogicalAnd: return "&&";
+      case EOpNegative: return "-";
+      case EOpVectorLogicalNot: return "not";
+      case EOpLogicalNot: return "!";
+      case EOpPostIncrement: return "++";
+      case EOpPostDecrement: return "--";
+      case EOpPreIncrement: return "++";
+      case EOpPreDecrement: return "--";
+
+      // Fall-through.
+      case EOpConvIntToBool:
+      case EOpConvFloatToBool: return "bool";
+ 
+      // Fall-through.
+      case EOpConvBoolToFloat:
+      case EOpConvIntToFloat: return "float";
+ 
+      // Fall-through.
+      case EOpConvFloatToInt:
+      case EOpConvBoolToInt: return "int";
+
+      case EOpRadians: return "radians";
+      case EOpDegrees: return "degrees";
+      case EOpSin: return "sin";
+      case EOpCos: return "cos";
+      case EOpTan: return "tan";
+      case EOpAsin: return "asin";
+      case EOpAcos: return "acos";
+      case EOpAtan: return "atan";
+      case EOpExp: return "exp";
+      case EOpLog: return "log";
+      case EOpExp2: return "exp2";
+      case EOpLog2: return "log2";
+      case EOpSqrt: return "sqrt";
+      case EOpInverseSqrt: return "inversesqrt";
+      case EOpAbs: return "abs";
+      case EOpSign: return "sign";
+      case EOpFloor: return "floor";
+      case EOpCeil: return "ceil";
+      case EOpFract: return "fract";
+      case EOpLength: return "length";
+      case EOpNormalize: return "normalize";
+      case EOpDFdx: return "dFdx";
+      case EOpDFdy: return "dFdy";
+      case EOpFwidth: return "fwidth";
+      case EOpAny: return "any";
+      case EOpAll: return "all";
+
+      default: break;
+    }
+    return "";
+}
+
+////////////////////////////////////////////////////////////////////////////
+//
+// First set of functions are to help build the intermediate representation.
+// These functions are not member functions of the nodes.
+// They are called from parser productions.
+//
+/////////////////////////////////////////////////////////////////////////////
+
+//
+// Add a terminal node for an identifier in an expression.
+//
+// Returns the added node.
+//
+TIntermSymbol* TIntermediate::addSymbol(int id, const TString& name, const TType& type, TSourceLoc line)
+{
+    TIntermSymbol* node = new TIntermSymbol(id, name, type);
+    node->setLine(line);
+
+    return node;
+}
+
+//
+// Connect two nodes with a new parent that does a binary operation on the nodes.
+//
+// Returns the added node.
+//
+TIntermTyped* TIntermediate::addBinaryMath(TOperator op, TIntermTyped* left, TIntermTyped* right, TSourceLoc line, TSymbolTable& symbolTable)
+{
+    switch (op) {
+        case EOpEqual:
+        case EOpNotEqual:
+            if (left->isArray())
+                return 0;
+            break;
+        case EOpLessThan:
+        case EOpGreaterThan:
+        case EOpLessThanEqual:
+        case EOpGreaterThanEqual:
+            if (left->isMatrix() || left->isArray() || left->isVector() || left->getBasicType() == EbtStruct) {
+                return 0;
+            }
+            break;
+        case EOpLogicalOr:
+        case EOpLogicalXor:
+        case EOpLogicalAnd:
+            if (left->getBasicType() != EbtBool || left->isMatrix() || left->isArray() || left->isVector()) {
+                return 0;
+            }
+            break;
+        case EOpAdd:
+        case EOpSub:
+        case EOpDiv:
+        case EOpMul:
+            if (left->getBasicType() == EbtStruct || left->getBasicType() == EbtBool)
+                return 0;
+        default: break;
+    }
+
+    //
+    // First try converting the children to compatible types.
+    //
+    if (left->getType().getStruct() && right->getType().getStruct()) {
+        if (left->getType() != right->getType())
+            return 0;
+    } else {
+        TIntermTyped* child = addConversion(op, left->getType(), right);
+        if (child)
+            right = child;
+        else {
+            child = addConversion(op, right->getType(), left);
+            if (child)
+                left = child;
+            else
+                return 0;
+        }
+    }
+
+    //
+    // Need a new node holding things together then.  Make
+    // one and promote it to the right type.
+    //
+    TIntermBinary* node = new TIntermBinary(op);
+    if (line == 0)
+        line = right->getLine();
+    node->setLine(line);
+
+    node->setLeft(left);
+    node->setRight(right);
+    if (!node->promote(infoSink))
+        return 0;
+
+    //
+    // See if we can fold constants.
+    //
+    TIntermTyped* typedReturnNode = 0;
+    TIntermConstantUnion *leftTempConstant = left->getAsConstantUnion();
+    TIntermConstantUnion *rightTempConstant = right->getAsConstantUnion();
+    if (leftTempConstant && rightTempConstant) {
+        typedReturnNode = leftTempConstant->fold(node->getOp(), rightTempConstant, infoSink);
+
+        if (typedReturnNode)
+            return typedReturnNode;
+    }
+
+    return node;
+}
+
+//
+// Connect two nodes through an assignment.
+//
+// Returns the added node.
+//
+TIntermTyped* TIntermediate::addAssign(TOperator op, TIntermTyped* left, TIntermTyped* right, TSourceLoc line)
+{
+    //
+    // Like adding binary math, except the conversion can only go
+    // from right to left.
+    //
+    TIntermBinary* node = new TIntermBinary(op);
+    if (line == 0)
+        line = left->getLine();
+    node->setLine(line);
+
+    TIntermTyped* child = addConversion(op, left->getType(), right);
+    if (child == 0)
+        return 0;
+
+    node->setLeft(left);
+    node->setRight(child);
+    if (! node->promote(infoSink))
+        return 0;
+
+    return node;
+}
+
+//
+// Connect two nodes through an index operator, where the left node is the base
+// of an array or struct, and the right node is a direct or indirect offset.
+//
+// Returns the added node.
+// The caller should set the type of the returned node.
+//
+TIntermTyped* TIntermediate::addIndex(TOperator op, TIntermTyped* base, TIntermTyped* index, TSourceLoc line)
+{
+    TIntermBinary* node = new TIntermBinary(op);
+    if (line == 0)
+        line = index->getLine();
+    node->setLine(line);
+    node->setLeft(base);
+    node->setRight(index);
+
+    // caller should set the type
+
+    return node;
+}
+
+//
+// Add one node as the parent of another that it operates on.
+//
+// Returns the added node.
+//
+TIntermTyped* TIntermediate::addUnaryMath(TOperator op, TIntermNode* childNode, TSourceLoc line, TSymbolTable& symbolTable)
+{
+    TIntermUnary* node;
+    TIntermTyped* child = childNode->getAsTyped();
+
+    if (child == 0) {
+        infoSink.info.message(EPrefixInternalError, "Bad type in AddUnaryMath", line);
+        return 0;
+    }
+
+    switch (op) {
+        case EOpLogicalNot:
+            if (child->getType().getBasicType() != EbtBool || child->getType().isMatrix() || child->getType().isArray() || child->getType().isVector()) {
+                return 0;
+            }
+            break;
+
+        case EOpPostIncrement:
+        case EOpPreIncrement:
+        case EOpPostDecrement:
+        case EOpPreDecrement:
+        case EOpNegative:
+            if (child->getType().getBasicType() == EbtStruct || child->getType().isArray())
+                return 0;
+        default: break;
+    }
+
+    //
+    // Do we need to promote the operand?
+    //
+    // Note: Implicit promotions were removed from the language.
+    //
+    TBasicType newType = EbtVoid;
+    switch (op) {
+        case EOpConstructInt:   newType = EbtInt;   break;
+        case EOpConstructBool:  newType = EbtBool;  break;
+        case EOpConstructFloat: newType = EbtFloat; break;
+        default: break;
+    }
+
+    if (newType != EbtVoid) {
+        child = addConversion(op, TType(newType, child->getPrecision(), EvqTemporary,
+            child->getNominalSize(),
+            child->isMatrix(),
+            child->isArray()),
+            child);
+        if (child == 0)
+            return 0;
+    }
+
+    //
+    // For constructors, we are now done, it's all in the conversion.
+    //
+    switch (op) {
+        case EOpConstructInt:
+        case EOpConstructBool:
+        case EOpConstructFloat:
+            return child;
+        default: break;
+    }
+
+    TIntermConstantUnion *childTempConstant = 0;
+    if (child->getAsConstantUnion())
+        childTempConstant = child->getAsConstantUnion();
+
+    //
+    // Make a new node for the operator.
+    //
+    node = new TIntermUnary(op);
+    if (line == 0)
+        line = child->getLine();
+    node->setLine(line);
+    node->setOperand(child);
+
+    if (! node->promote(infoSink))
+        return 0;
+
+    if (childTempConstant)  {
+        TIntermTyped* newChild = childTempConstant->fold(op, 0, infoSink);
+
+        if (newChild)
+            return newChild;
+    }
+
+    return node;
+}
+
+//
+// This is the safe way to change the operator on an aggregate, as it
+// does lots of error checking and fixing.  Especially for establishing
+// a function call's operation on it's set of parameters.  Sequences
+// of instructions are also aggregates, but they just direnctly set
+// their operator to EOpSequence.
+//
+// Returns an aggregate node, which could be the one passed in if
+// it was already an aggregate but no operator was set.
+//
+TIntermAggregate* TIntermediate::setAggregateOperator(TIntermNode* node, TOperator op, TSourceLoc line)
+{
+    TIntermAggregate* aggNode;
+
+    //
+    // Make sure we have an aggregate.  If not turn it into one.
+    //
+    if (node) {
+        aggNode = node->getAsAggregate();
+        if (aggNode == 0 || aggNode->getOp() != EOpNull) {
+            //
+            // Make an aggregate containing this node.
+            //
+            aggNode = new TIntermAggregate();
+            aggNode->getSequence().push_back(node);
+            if (line == 0)
+                line = node->getLine();
+        }
+    } else
+        aggNode = new TIntermAggregate();
+
+    //
+    // Set the operator.
+    //
+    aggNode->setOp(op);
+    if (line != 0)
+        aggNode->setLine(line);
+
+    return aggNode;
+}
+
+//
+// Convert one type to another.
+//
+// Returns the node representing the conversion, which could be the same
+// node passed in if no conversion was needed.
+//
+// Return 0 if a conversion can't be done.
+//
+TIntermTyped* TIntermediate::addConversion(TOperator op, const TType& type, TIntermTyped* node)
+{
+    //
+    // Does the base type allow operation?
+    //
+    switch (node->getBasicType()) {
+        case EbtVoid:
+        case EbtSampler2D:
+        case EbtSamplerCube:
+            return 0;
+        default: break;
+    }
+
+    //
+    // Otherwise, if types are identical, no problem
+    //
+    if (type == node->getType())
+        return node;
+
+    //
+    // If one's a structure, then no conversions.
+    //
+    if (type.getStruct() || node->getType().getStruct())
+        return 0;
+
+    //
+    // If one's an array, then no conversions.
+    //
+    if (type.isArray() || node->getType().isArray())
+        return 0;
+
+    TBasicType promoteTo;
+
+    switch (op) {
+        //
+        // Explicit conversions
+        //
+        case EOpConstructBool:
+            promoteTo = EbtBool;
+            break;
+        case EOpConstructFloat:
+            promoteTo = EbtFloat;
+            break;
+        case EOpConstructInt:
+            promoteTo = EbtInt;
+            break;
+        default:
+            //
+            // implicit conversions were removed from the language.
+            //
+            if (type.getBasicType() != node->getType().getBasicType())
+                return 0;
+            //
+            // Size and structure could still differ, but that's
+            // handled by operator promotion.
+            //
+            return node;
+    }
+
+    if (node->getAsConstantUnion()) {
+
+        return (promoteConstantUnion(promoteTo, node->getAsConstantUnion()));
+    } else {
+
+        //
+        // Add a new newNode for the conversion.
+        //
+        TIntermUnary* newNode = 0;
+
+        TOperator newOp = EOpNull;
+        switch (promoteTo) {
+            case EbtFloat:
+                switch (node->getBasicType()) {
+                    case EbtInt:   newOp = EOpConvIntToFloat;  break;
+                    case EbtBool:  newOp = EOpConvBoolToFloat; break;
+                    default:
+                        infoSink.info.message(EPrefixInternalError, "Bad promotion node", node->getLine());
+                        return 0;
+                }
+                break;
+            case EbtBool:
+                switch (node->getBasicType()) {
+                    case EbtInt:   newOp = EOpConvIntToBool;   break;
+                    case EbtFloat: newOp = EOpConvFloatToBool; break;
+                    default:
+                        infoSink.info.message(EPrefixInternalError, "Bad promotion node", node->getLine());
+                        return 0;
+                }
+                break;
+            case EbtInt:
+                switch (node->getBasicType()) {
+                    case EbtBool:   newOp = EOpConvBoolToInt;  break;
+                    case EbtFloat:  newOp = EOpConvFloatToInt; break;
+                    default:
+                        infoSink.info.message(EPrefixInternalError, "Bad promotion node", node->getLine());
+                        return 0;
+                }
+                break;
+            default:
+                infoSink.info.message(EPrefixInternalError, "Bad promotion type", node->getLine());
+                return 0;
+        }
+
+        TType type(promoteTo, node->getPrecision(), EvqTemporary, node->getNominalSize(), node->isMatrix(), node->isArray());
+        newNode = new TIntermUnary(newOp, type);
+        newNode->setLine(node->getLine());
+        newNode->setOperand(node);
+
+        return newNode;
+    }
+}
+
+//
+// Safe way to combine two nodes into an aggregate.  Works with null pointers,
+// a node that's not a aggregate yet, etc.
+//
+// Returns the resulting aggregate, unless 0 was passed in for
+// both existing nodes.
+//
+TIntermAggregate* TIntermediate::growAggregate(TIntermNode* left, TIntermNode* right, TSourceLoc line)
+{
+    if (left == 0 && right == 0)
+        return 0;
+
+    TIntermAggregate* aggNode = 0;
+    if (left)
+        aggNode = left->getAsAggregate();
+    if (!aggNode || aggNode->getOp() != EOpNull) {
+        aggNode = new TIntermAggregate;
+        if (left)
+            aggNode->getSequence().push_back(left);
+    }
+
+    if (right)
+        aggNode->getSequence().push_back(right);
+
+    if (line != 0)
+        aggNode->setLine(line);
+
+    return aggNode;
+}
+
+//
+// Turn an existing node into an aggregate.
+//
+// Returns an aggregate, unless 0 was passed in for the existing node.
+//
+TIntermAggregate* TIntermediate::makeAggregate(TIntermNode* node, TSourceLoc line)
+{
+    if (node == 0)
+        return 0;
+
+    TIntermAggregate* aggNode = new TIntermAggregate;
+    aggNode->getSequence().push_back(node);
+
+    if (line != 0)
+        aggNode->setLine(line);
+    else
+        aggNode->setLine(node->getLine());
+
+    return aggNode;
+}
+
+//
+// For "if" test nodes.  There are three children; a condition,
+// a true path, and a false path.  The two paths are in the
+// nodePair.
+//
+// Returns the selection node created.
+//
+TIntermNode* TIntermediate::addSelection(TIntermTyped* cond, TIntermNodePair nodePair, TSourceLoc line)
+{
+    //
+    // For compile time constant selections, prune the code and
+    // test now.
+    //
+
+    if (cond->getAsTyped() && cond->getAsTyped()->getAsConstantUnion()) {
+        if (cond->getAsTyped()->getAsConstantUnion()->getUnionArrayPointer()->getBConst() == true)
+            return nodePair.node1 ? setAggregateOperator(nodePair.node1, EOpSequence, nodePair.node1->getLine()) : NULL;
+        else
+            return nodePair.node2 ? setAggregateOperator(nodePair.node2, EOpSequence, nodePair.node2->getLine()) : NULL;
+    }
+
+    TIntermSelection* node = new TIntermSelection(cond, nodePair.node1, nodePair.node2);
+    node->setLine(line);
+
+    return node;
+}
+
+
+TIntermTyped* TIntermediate::addComma(TIntermTyped* left, TIntermTyped* right, TSourceLoc line)
+{
+    if (left->getType().getQualifier() == EvqConst && right->getType().getQualifier() == EvqConst) {
+        return right;
+    } else {
+        TIntermTyped *commaAggregate = growAggregate(left, right, line);
+        commaAggregate->getAsAggregate()->setOp(EOpComma);
+        commaAggregate->setType(right->getType());
+        commaAggregate->getTypePointer()->setQualifier(EvqTemporary);
+        return commaAggregate;
+    }
+}
+
+//
+// For "?:" test nodes.  There are three children; a condition,
+// a true path, and a false path.  The two paths are specified
+// as separate parameters.
+//
+// Returns the selection node created, or 0 if one could not be.
+//
+TIntermTyped* TIntermediate::addSelection(TIntermTyped* cond, TIntermTyped* trueBlock, TIntermTyped* falseBlock, TSourceLoc line)
+{
+    //
+    // Get compatible types.
+    //
+    TIntermTyped* child = addConversion(EOpSequence, trueBlock->getType(), falseBlock);
+    if (child)
+        falseBlock = child;
+    else {
+        child = addConversion(EOpSequence, falseBlock->getType(), trueBlock);
+        if (child)
+            trueBlock = child;
+        else
+            return 0;
+    }
+
+    //
+    // See if all the operands are constant, then fold it otherwise not.
+    //
+
+    if (cond->getAsConstantUnion() && trueBlock->getAsConstantUnion() && falseBlock->getAsConstantUnion()) {
+        if (cond->getAsConstantUnion()->getUnionArrayPointer()->getBConst())
+            return trueBlock;
+        else
+            return falseBlock;
+    }
+
+    //
+    // Make a selection node.
+    //
+    TIntermSelection* node = new TIntermSelection(cond, trueBlock, falseBlock, trueBlock->getType());
+    node->getTypePointer()->setQualifier(EvqTemporary);
+    node->setLine(line);
+
+    return node;
+}
+
+//
+// Constant terminal nodes.  Has a union that contains bool, float or int constants
+//
+// Returns the constant union node created.
+//
+
+TIntermConstantUnion* TIntermediate::addConstantUnion(ConstantUnion* unionArrayPointer, const TType& t, TSourceLoc line)
+{
+    TIntermConstantUnion* node = new TIntermConstantUnion(unionArrayPointer, t);
+    node->setLine(line);
+
+    return node;
+}
+
+TIntermTyped* TIntermediate::addSwizzle(TVectorFields& fields, TSourceLoc line)
+{
+
+    TIntermAggregate* node = new TIntermAggregate(EOpSequence);
+
+    node->setLine(line);
+    TIntermConstantUnion* constIntNode;
+    TIntermSequence &sequenceVector = node->getSequence();
+    ConstantUnion* unionArray;
+
+    for (int i = 0; i < fields.num; i++) {
+        unionArray = new ConstantUnion[1];
+        unionArray->setIConst(fields.offsets[i]);
+        constIntNode = addConstantUnion(unionArray, TType(EbtInt, EbpUndefined, EvqConst), line);
+        sequenceVector.push_back(constIntNode);
+    }
+
+    return node;
+}
+
+//
+// Create loop nodes.
+//
+TIntermNode* TIntermediate::addLoop(TLoopType type, TIntermNode* init, TIntermTyped* cond, TIntermTyped* expr, TIntermNode* body, TSourceLoc line)
+{
+    TIntermNode* node = new TIntermLoop(type, init, cond, expr, body);
+    node->setLine(line);
+
+    return node;
+}
+
+//
+// Add branches.
+//
+TIntermBranch* TIntermediate::addBranch(TOperator branchOp, TSourceLoc line)
+{
+    return addBranch(branchOp, 0, line);
+}
+
+TIntermBranch* TIntermediate::addBranch(TOperator branchOp, TIntermTyped* expression, TSourceLoc line)
+{
+    TIntermBranch* node = new TIntermBranch(branchOp, expression);
+    node->setLine(line);
+
+    return node;
+}
+
+//
+// This is to be executed once the final root is put on top by the parsing
+// process.
+//
+bool TIntermediate::postProcess(TIntermNode* root)
+{
+    if (root == 0)
+        return true;
+
+    //
+    // First, finish off the top level sequence, if any
+    //
+    TIntermAggregate* aggRoot = root->getAsAggregate();
+    if (aggRoot && aggRoot->getOp() == EOpNull)
+        aggRoot->setOp(EOpSequence);
+
+    return true;
+}
+
+//
+// This deletes the tree.
+//
+void TIntermediate::remove(TIntermNode* root)
+{
+    if (root)
+        RemoveAllTreeNodes(root);
+}
+
+////////////////////////////////////////////////////////////////
+//
+// Member functions of the nodes used for building the tree.
+//
+////////////////////////////////////////////////////////////////
+
+//
+// Say whether or not an operation node changes the value of a variable.
+//
+// Returns true if state is modified.
+//
+bool TIntermOperator::modifiesState() const
+{
+    switch (op) {
+        case EOpPostIncrement:
+        case EOpPostDecrement:
+        case EOpPreIncrement:
+        case EOpPreDecrement:
+        case EOpAssign:
+        case EOpAddAssign:
+        case EOpSubAssign:
+        case EOpMulAssign:
+        case EOpVectorTimesMatrixAssign:
+        case EOpVectorTimesScalarAssign:
+        case EOpMatrixTimesScalarAssign:
+        case EOpMatrixTimesMatrixAssign:
+        case EOpDivAssign:
+            return true;
+        default:
+            return false;
+    }
+}
+
+//
+// returns true if the operator is for one of the constructors
+//
+bool TIntermOperator::isConstructor() const
+{
+    switch (op) {
+        case EOpConstructVec2:
+        case EOpConstructVec3:
+        case EOpConstructVec4:
+        case EOpConstructMat2:
+        case EOpConstructMat3:
+        case EOpConstructMat4:
+        case EOpConstructFloat:
+        case EOpConstructIVec2:
+        case EOpConstructIVec3:
+        case EOpConstructIVec4:
+        case EOpConstructInt:
+        case EOpConstructBVec2:
+        case EOpConstructBVec3:
+        case EOpConstructBVec4:
+        case EOpConstructBool:
+        case EOpConstructStruct:
+            return true;
+        default:
+            return false;
+    }
+}
+//
+// Make sure the type of a unary operator is appropriate for its
+// combination of operation and operand type.
+//
+// Returns false in nothing makes sense.
+//
+bool TIntermUnary::promote(TInfoSink&)
+{
+    switch (op) {
+        case EOpLogicalNot:
+            if (operand->getBasicType() != EbtBool)
+                return false;
+            break;
+        case EOpNegative:
+        case EOpPostIncrement:
+        case EOpPostDecrement:
+        case EOpPreIncrement:
+        case EOpPreDecrement:
+            if (operand->getBasicType() == EbtBool)
+                return false;
+            break;
+
+            // operators for built-ins are already type checked against their prototype
+        case EOpAny:
+        case EOpAll:
+        case EOpVectorLogicalNot:
+            return true;
+
+        default:
+            if (operand->getBasicType() != EbtFloat)
+                return false;
+    }
+
+    setType(operand->getType());
+
+	// Unary operations results in temporary variables unless const.
+    if (operand->getQualifier() != EvqConst) {
+        getTypePointer()->setQualifier(EvqTemporary);
+    }
+
+    return true;
+}
+
+//
+// Establishes the type of the resultant operation, as well as
+// makes the operator the correct one for the operands.
+//
+// Returns false if operator can't work on operands.
+//
+bool TIntermBinary::promote(TInfoSink& infoSink)
+{
+    // This function only handles scalars, vectors, and matrices.
+    if (left->isArray() || right->isArray()) {
+        infoSink.info.message(EPrefixInternalError, "Invalid operation for arrays", getLine());
+        return false;
+    }
+
+    // GLSL ES 2.0 does not support implicit type casting.
+    // So the basic type should always match.
+    if (left->getBasicType() != right->getBasicType())
+        return false;
+
+    //
+    // Base assumption:  just make the type the same as the left
+    // operand.  Then only deviations from this need be coded.
+    //
+    setType(left->getType());
+
+    // The result gets promoted to the highest precision.
+    TPrecision higherPrecision = GetHigherPrecision(left->getPrecision(), right->getPrecision());
+    getTypePointer()->setPrecision(higherPrecision);
+
+    // Binary operations results in temporary variables unless both
+    // operands are const.
+    if (left->getQualifier() != EvqConst || right->getQualifier() != EvqConst) {
+        getTypePointer()->setQualifier(EvqTemporary);
+    }
+
+    int size = std::max(left->getNominalSize(), right->getNominalSize());
+
+    //
+    // All scalars. Code after this test assumes this case is removed!
+    //
+    if (size == 1) {
+        switch (op) {
+            //
+            // Promote to conditional
+            //
+            case EOpEqual:
+            case EOpNotEqual:
+            case EOpLessThan:
+            case EOpGreaterThan:
+            case EOpLessThanEqual:
+            case EOpGreaterThanEqual:
+                setType(TType(EbtBool, EbpUndefined));
+                break;
+
+            //
+            // And and Or operate on conditionals
+            //
+            case EOpLogicalAnd:
+            case EOpLogicalOr:
+                // Both operands must be of type bool.
+                if (left->getBasicType() != EbtBool || right->getBasicType() != EbtBool)
+                    return false;
+                setType(TType(EbtBool, EbpUndefined));
+                break;
+
+            default:
+                break;
+        }
+        return true;
+    }
+
+    // If we reach here, at least one of the operands is vector or matrix.
+    // The other operand could be a scalar, vector, or matrix.
+    // Are the sizes compatible?
+    //
+    if (left->getNominalSize() != right->getNominalSize()) {
+        // If the nominal size of operands do not match:
+        // One of them must be scalar.
+        if (left->getNominalSize() != 1 && right->getNominalSize() != 1)
+            return false;
+        // Operator cannot be of type pure assignment.
+        if (op == EOpAssign || op == EOpInitialize)
+            return false;
+    }
+
+    //
+    // Can these two operands be combined?
+    //
+    TBasicType basicType = left->getBasicType();
+    switch (op) {
+        case EOpMul:
+            if (!left->isMatrix() && right->isMatrix()) {
+                if (left->isVector())
+                    op = EOpVectorTimesMatrix;
+                else {
+                    op = EOpMatrixTimesScalar;
+                    setType(TType(basicType, higherPrecision, EvqTemporary, size, true));
+                }
+            } else if (left->isMatrix() && !right->isMatrix()) {
+                if (right->isVector()) {
+                    op = EOpMatrixTimesVector;
+                    setType(TType(basicType, higherPrecision, EvqTemporary, size, false));
+                } else {
+                    op = EOpMatrixTimesScalar;
+                }
+            } else if (left->isMatrix() && right->isMatrix()) {
+                op = EOpMatrixTimesMatrix;
+            } else if (!left->isMatrix() && !right->isMatrix()) {
+                if (left->isVector() && right->isVector()) {
+                    // leave as component product
+                } else if (left->isVector() || right->isVector()) {
+                    op = EOpVectorTimesScalar;
+                    setType(TType(basicType, higherPrecision, EvqTemporary, size, false));
+                }
+            } else {
+                infoSink.info.message(EPrefixInternalError, "Missing elses", getLine());
+                return false;
+            }
+            break;
+        case EOpMulAssign:
+            if (!left->isMatrix() && right->isMatrix()) {
+                if (left->isVector())
+                    op = EOpVectorTimesMatrixAssign;
+                else {
+                    return false;
+                }
+            } else if (left->isMatrix() && !right->isMatrix()) {
+                if (right->isVector()) {
+                    return false;
+                } else {
+                    op = EOpMatrixTimesScalarAssign;
+                }
+            } else if (left->isMatrix() && right->isMatrix()) {
+                op = EOpMatrixTimesMatrixAssign;
+            } else if (!left->isMatrix() && !right->isMatrix()) {
+                if (left->isVector() && right->isVector()) {
+                    // leave as component product
+                } else if (left->isVector() || right->isVector()) {
+                    if (! left->isVector())
+                        return false;
+                    op = EOpVectorTimesScalarAssign;
+                    setType(TType(basicType, higherPrecision, EvqTemporary, size, false));
+                }
+            } else {
+                infoSink.info.message(EPrefixInternalError, "Missing elses", getLine());
+                return false;
+            }
+            break;
+
+        case EOpAssign:
+        case EOpInitialize:
+        case EOpAdd:
+        case EOpSub:
+        case EOpDiv:
+        case EOpAddAssign:
+        case EOpSubAssign:
+        case EOpDivAssign:
+            if ((left->isMatrix() && right->isVector()) ||
+                (left->isVector() && right->isMatrix()))
+                return false;
+            setType(TType(basicType, higherPrecision, EvqTemporary, size, left->isMatrix() || right->isMatrix()));
+            break;
+
+        case EOpEqual:
+        case EOpNotEqual:
+        case EOpLessThan:
+        case EOpGreaterThan:
+        case EOpLessThanEqual:
+        case EOpGreaterThanEqual:
+            if ((left->isMatrix() && right->isVector()) ||
+                (left->isVector() && right->isMatrix()))
+                return false;
+            setType(TType(EbtBool, EbpUndefined));
+            break;
+
+        default:
+            return false;
+    }
+    
+    return true;
+}
+
+bool CompareStruct(const TType& leftNodeType, ConstantUnion* rightUnionArray, ConstantUnion* leftUnionArray)
+{
+    const TTypeList* fields = leftNodeType.getStruct();
+
+    size_t structSize = fields->size();
+    int index = 0;
+
+    for (size_t j = 0; j < structSize; j++) {
+        int size = (*fields)[j].type->getObjectSize();
+        for (int i = 0; i < size; i++) {
+            if ((*fields)[j].type->getBasicType() == EbtStruct) {
+                if (!CompareStructure(*(*fields)[j].type, &rightUnionArray[index], &leftUnionArray[index]))
+                    return false;
+            } else {
+                if (leftUnionArray[index] != rightUnionArray[index])
+                    return false;
+                index++;
+            }
+
+        }
+    }
+    return true;
+}
+
+bool CompareStructure(const TType& leftNodeType, ConstantUnion* rightUnionArray, ConstantUnion* leftUnionArray)
+{
+    if (leftNodeType.isArray()) {
+        TType typeWithoutArrayness = leftNodeType;
+        typeWithoutArrayness.clearArrayness();
+
+        int arraySize = leftNodeType.getArraySize();
+
+        for (int i = 0; i < arraySize; ++i) {
+            int offset = typeWithoutArrayness.getObjectSize() * i;
+            if (!CompareStruct(typeWithoutArrayness, &rightUnionArray[offset], &leftUnionArray[offset]))
+                return false;
+        }
+    } else
+        return CompareStruct(leftNodeType, rightUnionArray, leftUnionArray);
+
+    return true;
+}
+
+//
+// The fold functions see if an operation on a constant can be done in place,
+// without generating run-time code.
+//
+// Returns the node to keep using, which may or may not be the node passed in.
+//
+
+TIntermTyped* TIntermConstantUnion::fold(TOperator op, TIntermTyped* constantNode, TInfoSink& infoSink)
+{
+    ConstantUnion *unionArray = getUnionArrayPointer();
+    int objectSize = getType().getObjectSize();
+
+    if (constantNode) {  // binary operations
+        TIntermConstantUnion *node = constantNode->getAsConstantUnion();
+        ConstantUnion *rightUnionArray = node->getUnionArrayPointer();
+        TType returnType = getType();
+
+        // for a case like float f = 1.2 + vec4(2,3,4,5);
+        if (constantNode->getType().getObjectSize() == 1 && objectSize > 1) {
+            rightUnionArray = new ConstantUnion[objectSize];
+            for (int i = 0; i < objectSize; ++i)
+                rightUnionArray[i] = *node->getUnionArrayPointer();
+            returnType = getType();
+        } else if (constantNode->getType().getObjectSize() > 1 && objectSize == 1) {
+            // for a case like float f = vec4(2,3,4,5) + 1.2;
+            unionArray = new ConstantUnion[constantNode->getType().getObjectSize()];
+            for (int i = 0; i < constantNode->getType().getObjectSize(); ++i)
+                unionArray[i] = *getUnionArrayPointer();
+            returnType = node->getType();
+            objectSize = constantNode->getType().getObjectSize();
+        }
+
+        ConstantUnion* tempConstArray = 0;
+        TIntermConstantUnion *tempNode;
+
+        bool boolNodeFlag = false;
+        switch(op) {
+            case EOpAdd:
+                tempConstArray = new ConstantUnion[objectSize];
+                {// support MSVC++6.0
+                    for (int i = 0; i < objectSize; i++)
+                        tempConstArray[i] = unionArray[i] + rightUnionArray[i];
+                }
+                break;
+            case EOpSub:
+                tempConstArray = new ConstantUnion[objectSize];
+                {// support MSVC++6.0
+                    for (int i = 0; i < objectSize; i++)
+                        tempConstArray[i] = unionArray[i] - rightUnionArray[i];
+                }
+                break;
+
+            case EOpMul:
+            case EOpVectorTimesScalar:
+            case EOpMatrixTimesScalar:
+                tempConstArray = new ConstantUnion[objectSize];
+                {// support MSVC++6.0
+                    for (int i = 0; i < objectSize; i++)
+                        tempConstArray[i] = unionArray[i] * rightUnionArray[i];
+                }
+                break;
+            case EOpMatrixTimesMatrix:
+                if (getType().getBasicType() != EbtFloat || node->getBasicType() != EbtFloat) {
+                    infoSink.info.message(EPrefixInternalError, "Constant Folding cannot be done for matrix multiply", getLine());
+                    return 0;
+                }
+                {// support MSVC++6.0
+                    int size = getNominalSize();
+                    tempConstArray = new ConstantUnion[size*size];
+                    for (int row = 0; row < size; row++) {
+                        for (int column = 0; column < size; column++) {
+                            tempConstArray[size * column + row].setFConst(0.0f);
+                            for (int i = 0; i < size; i++) {
+                                tempConstArray[size * column + row].setFConst(tempConstArray[size * column + row].getFConst() + unionArray[i * size + row].getFConst() * (rightUnionArray[column * size + i].getFConst()));
+                            }
+                        }
+                    }
+                }
+                break;
+            case EOpDiv:
+                tempConstArray = new ConstantUnion[objectSize];
+                {// support MSVC++6.0
+                    for (int i = 0; i < objectSize; i++) {
+                        switch (getType().getBasicType()) {
+            case EbtFloat:
+                if (rightUnionArray[i] == 0.0f) {
+                    infoSink.info.message(EPrefixWarning, "Divide by zero error during constant folding", getLine());
+                    tempConstArray[i].setFConst(FLT_MAX);
+                } else
+                    tempConstArray[i].setFConst(unionArray[i].getFConst() / rightUnionArray[i].getFConst());
+                break;
+
+            case EbtInt:
+                if (rightUnionArray[i] == 0) {
+                    infoSink.info.message(EPrefixWarning, "Divide by zero error during constant folding", getLine());
+                    tempConstArray[i].setIConst(INT_MAX);
+                } else
+                    tempConstArray[i].setIConst(unionArray[i].getIConst() / rightUnionArray[i].getIConst());
+                break;
+            default:
+                infoSink.info.message(EPrefixInternalError, "Constant folding cannot be done for \"/\"", getLine());
+                return 0;
+                        }
+                    }
+                }
+                break;
+
+            case EOpMatrixTimesVector:
+                if (node->getBasicType() != EbtFloat) {
+                    infoSink.info.message(EPrefixInternalError, "Constant Folding cannot be done for matrix times vector", getLine());
+                    return 0;
+                }
+                tempConstArray = new ConstantUnion[getNominalSize()];
+
+                {// support MSVC++6.0
+                    for (int size = getNominalSize(), i = 0; i < size; i++) {
+                        tempConstArray[i].setFConst(0.0f);
+                        for (int j = 0; j < size; j++) {
+                            tempConstArray[i].setFConst(tempConstArray[i].getFConst() + ((unionArray[j*size + i].getFConst()) * rightUnionArray[j].getFConst()));
+                        }
+                    }
+                }
+
+                tempNode = new TIntermConstantUnion(tempConstArray, node->getType());
+                tempNode->setLine(getLine());
+
+                return tempNode;
+
+            case EOpVectorTimesMatrix:
+                if (getType().getBasicType() != EbtFloat) {
+                    infoSink.info.message(EPrefixInternalError, "Constant Folding cannot be done for vector times matrix", getLine());
+                    return 0;
+                }
+
+                tempConstArray = new ConstantUnion[getNominalSize()];
+                {// support MSVC++6.0
+                    for (int size = getNominalSize(), i = 0; i < size; i++) {
+                        tempConstArray[i].setFConst(0.0f);
+                        for (int j = 0; j < size; j++) {
+                            tempConstArray[i].setFConst(tempConstArray[i].getFConst() + ((unionArray[j].getFConst()) * rightUnionArray[i*size + j].getFConst()));
+                        }
+                    }
+                }
+                break;
+
+            case EOpLogicalAnd: // this code is written for possible future use, will not get executed currently
+                tempConstArray = new ConstantUnion[objectSize];
+                {// support MSVC++6.0
+                    for (int i = 0; i < objectSize; i++)
+                        tempConstArray[i] = unionArray[i] && rightUnionArray[i];
+                }
+                break;
+
+            case EOpLogicalOr: // this code is written for possible future use, will not get executed currently
+                tempConstArray = new ConstantUnion[objectSize];
+                {// support MSVC++6.0
+                    for (int i = 0; i < objectSize; i++)
+                        tempConstArray[i] = unionArray[i] || rightUnionArray[i];
+                }
+                break;
+
+            case EOpLogicalXor:
+                tempConstArray = new ConstantUnion[objectSize];
+                {// support MSVC++6.0
+                    for (int i = 0; i < objectSize; i++)
+                        switch (getType().getBasicType()) {
+            case EbtBool: tempConstArray[i].setBConst((unionArray[i] == rightUnionArray[i]) ? false : true); break;
+            default: assert(false && "Default missing");
+                    }
+                }
+                break;
+
+            case EOpLessThan:
+                assert(objectSize == 1);
+                tempConstArray = new ConstantUnion[1];
+                tempConstArray->setBConst(*unionArray < *rightUnionArray);
+                returnType = TType(EbtBool, EbpUndefined, EvqConst);
+                break;
+            case EOpGreaterThan:
+                assert(objectSize == 1);
+                tempConstArray = new ConstantUnion[1];
+                tempConstArray->setBConst(*unionArray > *rightUnionArray);
+                returnType = TType(EbtBool, EbpUndefined, EvqConst);
+                break;
+            case EOpLessThanEqual:
+                {
+                    assert(objectSize == 1);
+                    ConstantUnion constant;
+                    constant.setBConst(*unionArray > *rightUnionArray);
+                    tempConstArray = new ConstantUnion[1];
+                    tempConstArray->setBConst(!constant.getBConst());
+                    returnType = TType(EbtBool, EbpUndefined, EvqConst);
+                    break;
+                }
+            case EOpGreaterThanEqual:
+                {
+                    assert(objectSize == 1);
+                    ConstantUnion constant;
+                    constant.setBConst(*unionArray < *rightUnionArray);
+                    tempConstArray = new ConstantUnion[1];
+                    tempConstArray->setBConst(!constant.getBConst());
+                    returnType = TType(EbtBool, EbpUndefined, EvqConst);
+                    break;
+                }
+
+            case EOpEqual:
+                if (getType().getBasicType() == EbtStruct) {
+                    if (!CompareStructure(node->getType(), node->getUnionArrayPointer(), unionArray))
+                        boolNodeFlag = true;
+                } else {
+                    for (int i = 0; i < objectSize; i++) {
+                        if (unionArray[i] != rightUnionArray[i]) {
+                            boolNodeFlag = true;
+                            break;  // break out of for loop
+                        }
+                    }
+                }
+
+                tempConstArray = new ConstantUnion[1];
+                if (!boolNodeFlag) {
+                    tempConstArray->setBConst(true);
+                }
+                else {
+                    tempConstArray->setBConst(false);
+                }
+
+                tempNode = new TIntermConstantUnion(tempConstArray, TType(EbtBool, EbpUndefined, EvqConst));
+                tempNode->setLine(getLine());
+
+                return tempNode;
+
+            case EOpNotEqual:
+                if (getType().getBasicType() == EbtStruct) {
+                    if (CompareStructure(node->getType(), node->getUnionArrayPointer(), unionArray))
+                        boolNodeFlag = true;
+                } else {
+                    for (int i = 0; i < objectSize; i++) {
+                        if (unionArray[i] == rightUnionArray[i]) {
+                            boolNodeFlag = true;
+                            break;  // break out of for loop
+                        }
+                    }
+                }
+
+                tempConstArray = new ConstantUnion[1];
+                if (!boolNodeFlag) {
+                    tempConstArray->setBConst(true);
+                }
+                else {
+                    tempConstArray->setBConst(false);
+                }
+
+                tempNode = new TIntermConstantUnion(tempConstArray, TType(EbtBool, EbpUndefined, EvqConst));
+                tempNode->setLine(getLine());
+
+                return tempNode;
+
+            default:
+                infoSink.info.message(EPrefixInternalError, "Invalid operator for constant folding", getLine());
+                return 0;
+        }
+        tempNode = new TIntermConstantUnion(tempConstArray, returnType);
+        tempNode->setLine(getLine());
+
+        return tempNode;
+    } else {
+        //
+        // Do unary operations
+        //
+        TIntermConstantUnion *newNode = 0;
+        ConstantUnion* tempConstArray = new ConstantUnion[objectSize];
+        for (int i = 0; i < objectSize; i++) {
+            switch(op) {
+                case EOpNegative:
+                    switch (getType().getBasicType()) {
+                        case EbtFloat: tempConstArray[i].setFConst(-unionArray[i].getFConst()); break;
+                        case EbtInt:   tempConstArray[i].setIConst(-unionArray[i].getIConst()); break;
+                        default:
+                            infoSink.info.message(EPrefixInternalError, "Unary operation not folded into constant", getLine());
+                            return 0;
+                    }
+                    break;
+                case EOpLogicalNot: // this code is written for possible future use, will not get executed currently
+                    switch (getType().getBasicType()) {
+                        case EbtBool:  tempConstArray[i].setBConst(!unionArray[i].getBConst()); break;
+                        default:
+                            infoSink.info.message(EPrefixInternalError, "Unary operation not folded into constant", getLine());
+                            return 0;
+                    }
+                    break;
+                default:
+                    return 0;
+            }
+        }
+        newNode = new TIntermConstantUnion(tempConstArray, getType());
+        newNode->setLine(getLine());
+        return newNode;
+    }
+}
+
+TIntermTyped* TIntermediate::promoteConstantUnion(TBasicType promoteTo, TIntermConstantUnion* node)
+{
+    ConstantUnion *rightUnionArray = node->getUnionArrayPointer();
+    int size = node->getType().getObjectSize();
+
+    ConstantUnion *leftUnionArray = new ConstantUnion[size];
+
+    for (int i=0; i < size; i++) {
+
+        switch (promoteTo) {
+            case EbtFloat:
+                switch (node->getType().getBasicType()) {
+                    case EbtInt:
+                        leftUnionArray[i].setFConst(static_cast<float>(rightUnionArray[i].getIConst()));
+                        break;
+                    case EbtBool:
+                        leftUnionArray[i].setFConst(static_cast<float>(rightUnionArray[i].getBConst()));
+                        break;
+                    case EbtFloat:
+                        leftUnionArray[i] = rightUnionArray[i];
+                        break;
+                    default:
+                        infoSink.info.message(EPrefixInternalError, "Cannot promote", node->getLine());
+                        return 0;
+                }
+                break;
+            case EbtInt:
+                switch (node->getType().getBasicType()) {
+                    case EbtInt:
+                        leftUnionArray[i] = rightUnionArray[i];
+                        break;
+                    case EbtBool:
+                        leftUnionArray[i].setIConst(static_cast<int>(rightUnionArray[i].getBConst()));
+                        break;
+                    case EbtFloat:
+                        leftUnionArray[i].setIConst(static_cast<int>(rightUnionArray[i].getFConst()));
+                        break;
+                    default:
+                        infoSink.info.message(EPrefixInternalError, "Cannot promote", node->getLine());
+                        return 0;
+                }
+                break;
+            case EbtBool:
+                switch (node->getType().getBasicType()) {
+                    case EbtInt:
+                        leftUnionArray[i].setBConst(rightUnionArray[i].getIConst() != 0);
+                        break;
+                    case EbtBool:
+                        leftUnionArray[i] = rightUnionArray[i];
+                        break;
+                    case EbtFloat:
+                        leftUnionArray[i].setBConst(rightUnionArray[i].getFConst() != 0.0f);
+                        break;
+                    default:
+                        infoSink.info.message(EPrefixInternalError, "Cannot promote", node->getLine());
+                        return 0;
+                }
+
+                break;
+            default:
+                infoSink.info.message(EPrefixInternalError, "Incorrect data type found", node->getLine());
+                return 0;
+        }
+
+    }
+
+    const TType& t = node->getType();
+
+    return addConstantUnion(leftUnionArray, TType(promoteTo, t.getPrecision(), t.getQualifier(), t.getNominalSize(), t.isMatrix(), t.isArray()), node->getLine());
+}
+
diff --git a/src/GLES2/compiler/MMap.h b/src/GLES2/compiler/MMap.h
new file mode 100644
index 0000000..a308671
--- /dev/null
+++ b/src/GLES2/compiler/MMap.h
@@ -0,0 +1,56 @@
+//
+// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#ifndef _MMAP_INCLUDED_
+#define _MMAP_INCLUDED_
+
+//
+// Encapsulate memory mapped files
+//
+
+class TMMap {
+public:
+    TMMap(const char* fileName) : 
+        fSize(-1), // -1 is the error value returned by GetFileSize()
+        fp(NULL),
+        fBuff(0)   // 0 is the error value returned by MapViewOfFile()
+    {
+        if ((fp = fopen(fileName, "r")) == NULL)
+            return;
+        char c = getc(fp);
+        fSize = 0;
+        while (c != EOF) {
+            fSize++;
+            c = getc(fp);
+        }
+        if (c == EOF)
+            fSize++;
+        rewind(fp);
+        fBuff = (char*)malloc(sizeof(char) * fSize);
+        int count = 0;
+        c = getc(fp);
+        while (c != EOF) {
+            fBuff[count++] = c;
+            c = getc(fp);
+        }
+        fBuff[count++] = c;
+    }
+
+    char* getData() { return fBuff; }
+    int   getSize() { return fSize; }
+
+    ~TMMap() {
+        if (fp != NULL)
+            fclose(fp);
+    }
+    
+private:
+    int             fSize;      // size of file to map in
+    FILE *fp;
+    char*           fBuff;      // the actual data;
+};
+
+#endif // _MMAP_INCLUDED_
diff --git a/src/GLES2/compiler/OutputASM.cpp b/src/GLES2/compiler/OutputASM.cpp
new file mode 100644
index 0000000..713f031
--- /dev/null
+++ b/src/GLES2/compiler/OutputASM.cpp
@@ -0,0 +1,2250 @@
+// SwiftShader Software Renderer

+//

+// Copyright(c) 2005-2013 TransGaming Inc.

+//

+// All rights reserved. No part of this software may be copied, distributed, transmitted,

+// transcribed, stored in a retrieval system, translated into any human or computer

+// language by any means, or disclosed to third parties without the explicit written

+// agreement of TransGaming Inc. Without such an agreement, no rights or licenses, express

+// or implied, including but not limited to any patent rights, are granted to you.

+//

+

+#include "compiler/OutputASM.h"

+

+#include "common/debug.h"

+#include "compiler/InfoSink.h"

+

+#include "libGLESv2/Shader.h"

+

+#define GL_APICALL

+#include <GLES2/gl2.h>

+

+namespace sh

+{

+	static const unsigned char swizzleSize[5] = {0x00, 0x00, 0x54, 0xA4, 0xE4};   // (void), xxxx, xyyy, xyzz, xyzw

+

+	// Integer to TString conversion

+	TString str(int i)

+	{

+		char buffer[20];

+		sprintf(buffer, "%d", i);

+		return buffer;

+	}

+

+	class Temporary : public TIntermSymbol

+	{

+	public:

+		Temporary(OutputASM *assembler) : TIntermSymbol(0, "tmp", TType(EbtFloat, EbpHigh, EvqTemporary, 4, false, false)), assembler(assembler)

+		{

+		}

+

+		~Temporary()

+		{

+			assembler->freeTemporary(this);

+		}

+

+	private:

+		OutputASM *const assembler;

+	};

+

+	class Constant : public TIntermConstantUnion

+	{

+	public:

+		Constant(float x, float y, float z, float w) : TIntermConstantUnion(constants, TType(EbtFloat, EbpHigh, EvqConst, 4, false, false))

+		{

+			constants[0].setFConst(x);

+			constants[1].setFConst(y);

+			constants[2].setFConst(z);

+			constants[3].setFConst(w);

+		}

+

+		Constant(bool b) : TIntermConstantUnion(constants, TType(EbtBool, EbpHigh, EvqConst, 1, false, false))

+		{

+			constants[0].setBConst(b);

+		}

+

+		Constant(int i) : TIntermConstantUnion(constants, TType(EbtInt, EbpHigh, EvqConst, 1, false, false))

+		{

+			constants[0].setIConst(i);

+		}

+

+		~Constant()

+		{

+		}

+

+	private:

+		ConstantUnion constants[4];

+	};

+

+	Uniform::Uniform(GLenum type, const std::string &name, int arraySize, int registerIndex)

+	{

+		this->type = type;

+		this->name = name;

+		this->arraySize = arraySize;

+		this->registerIndex = registerIndex;

+	}

+

+	Attribute::Attribute()

+	{

+		type = GL_NONE;

+		arraySize = 0;

+		registerIndex = 0;

+	}

+

+	Attribute::Attribute(GLenum type, const std::string &name, int arraySize, int registerIndex)

+	{

+		this->type = type;

+		this->name = name;

+		this->arraySize = arraySize;

+		this->registerIndex = registerIndex;

+	}

+

+	OutputASM::OutputASM(TParseContext &context, gl::Shader *shaderObject) : TIntermTraverser(true, true, true), mContext(context), shaderObject(shaderObject)

+	{

+		shader = 0;

+		pixelShader = 0;

+		vertexShader = 0;

+

+		if(shaderObject)

+		{

+			shader = shaderObject->getShader();

+			pixelShader = shaderObject->getPixelShader();

+			vertexShader = shaderObject->getVertexShader();

+		}

+

+		functionArray.push_back(Function(0, "main(", 0, 0));

+		currentFunction = 0;

+	}

+

+	OutputASM::~OutputASM()

+	{

+	}

+

+	void OutputASM::output()

+	{

+		if(shader)

+		{

+			emitShader(GLOBAL);

+

+			if(functionArray.size() > 1)   // Only call main() when there are other functions

+			{

+				Instruction *callMain = emit(sw::Shader::OPCODE_CALL);

+				callMain->dst.type = sw::Shader::PARAMETER_LABEL;

+				callMain->dst.index = 0;   // main()

+

+				emit(sw::Shader::OPCODE_RET);

+			}

+

+			emitShader(FUNCTION);

+		}

+	}

+

+	void OutputASM::emitShader(Scope scope)

+	{

+		emitScope = scope;

+		currentScope = GLOBAL;

+		mContext.treeRoot->traverse(this);

+	}

+

+	void OutputASM::freeTemporary(Temporary *temporary)

+	{

+		free(temporaries, temporary);

+	}

+

+	void OutputASM::visitSymbol(TIntermSymbol *symbol)

+	{

+		if(symbol->getQualifier() == EvqVaryingOut || symbol->getQualifier() == EvqInvariantVaryingOut)

+		{

+			// Vertex varyings don't have to be actively used to successfully link

+			// against pixel shaders that use them. So make sure they're declared.

+			declareVarying(symbol, -1);

+		}

+	}

+

+	bool OutputASM::visitBinary(Visit visit, TIntermBinary *node)

+	{

+		if(currentScope != emitScope)

+		{

+			return false;

+		}

+

+		TIntermTyped *result = node;

+		TIntermTyped *left = node->getLeft();

+		TIntermTyped *right = node->getRight();

+		const TType &leftType = left->getType();

+		const TType &rightType = right->getType();

+		const TType &resultType = node->getType();

+		

+		switch(node->getOp())

+		{

+		case EOpAssign:

+			if(visit == PostVisit)

+			{

+				assignLvalue(left, right);

+				copy(result, right);

+			}

+			break;

+		case EOpInitialize:

+			if(visit == PostVisit)

+			{

+				copy(left, right);

+			}

+			break;

+		case EOpMatrixTimesScalarAssign:

+			if(visit == PostVisit)

+			{

+				for(int i = 0; i < leftType.getNominalSize(); i++)

+				{

+					Instruction *mul = emit(sw::Shader::OPCODE_MUL, result, left, right);

+					mul->dst.index += i;

+					argument(mul->src[0], left, i);

+				}

+

+				assignLvalue(left, result);

+			}

+			break;

+		case EOpVectorTimesMatrixAssign:

+			if(visit == PostVisit)

+			{

+				int size = leftType.getNominalSize();

+

+				for(int i = 0; i < size; i++)

+				{

+					Instruction *dot = emit(sw::Shader::OPCODE_DP(size), result, left, right);

+					dot->dst.mask = 1 << i;

+					argument(dot->src[1], right, i);

+				}

+

+				assignLvalue(left, result);

+			}

+			break;

+		case EOpMatrixTimesMatrixAssign:

+			if(visit == PostVisit)

+			{

+				int dim = leftType.getNominalSize();

+

+				for(int i = 0; i < dim; i++)

+				{

+					Instruction *mul = emit(sw::Shader::OPCODE_MUL, result, left, right);

+					mul->dst.index += i;

+					argument(mul->src[1], right, i);

+					mul->src[1].swizzle = 0x00;

+

+					for(int j = 1; j < dim; j++)

+					{

+						Instruction *mad = emit(sw::Shader::OPCODE_MAD, result, left, right, result);

+						mad->dst.index += i;

+						argument(mad->src[0], left, j);

+						argument(mad->src[1], right, i);

+						mad->src[1].swizzle = j * 0x55;

+						argument(mad->src[2], result, i);

+					}

+				}

+

+				assignLvalue(left, result);

+			}

+			break;

+		case EOpIndexDirect:

+			if(visit == PostVisit)

+			{

+				int index = right->getAsConstantUnion()->getUnionArrayPointer()->getIConst();

+

+				if(result->isMatrix() || result->isStruct())

+ 				{

+					ASSERT(left->isArray());

+					copy(result, left, index * left->elementRegisterCount());

+ 				}

+				else if(result->isRegister())

+ 				{

+					Instruction *mov = emit(sw::Shader::OPCODE_MOV, result, left);

+

+					if(left->isRegister())

+					{

+						mov->src[0].swizzle = index;

+					}

+					else if(left->isArray())

+					{

+						argument(mov->src[0], left, index * left->elementRegisterCount());

+					}

+					else if(left->isMatrix())

+					{

+						ASSERT(index < left->getNominalSize());   // FIXME: Report semantic error

+						argument(mov->src[0], left, index);

+					}

+					else UNREACHABLE();

+ 				}

+				else UNREACHABLE();

+			}

+			break;

+		case EOpIndexIndirect:

+			if(visit == PostVisit)

+			{

+				if(left->isArray() || left->isMatrix())

+				{

+					for(int index = 0; index < result->totalRegisterCount(); index++)

+					{

+						Instruction *mov = emit(sw::Shader::OPCODE_MOV, result, left);

+

+						mov->dst.index += index;

+						argument(mov->src[0], left, index);

+

+						if(left->totalRegisterCount() > 1)

+						{

+							sw::Shader::SourceParameter relativeRegister;

+							argument(relativeRegister, right);

+

+							mov->src[0].rel.type = relativeRegister.type;

+							mov->src[0].rel.index = relativeRegister.index;

+							mov->src[0].rel.scale =	result->totalRegisterCount();

+							mov->src[0].rel.deterministic = !(vertexShader && left->getQualifier() == EvqUniform);

+						}

+					}

+				}

+				else if(left->isRegister())

+				{

+					emit(sw::Shader::OPCODE_EXTRACT, result, left, right);

+				}

+				else UNREACHABLE();

+			}

+			break;

+		case EOpIndexDirectStruct:

+			if(visit == PostVisit)

+			{

+				ASSERT(leftType.isStruct());

+

+				const TTypeList *structure = leftType.getStruct();

+				const TString &fieldName = rightType.getFieldName();

+				int fieldOffset = 0;

+

+				for(size_t i = 0; i < structure->size(); i++)

+				{

+					const TType &fieldType = *(*structure)[i].type;

+

+					if(fieldType.getFieldName() == fieldName)

+					{

+						break;

+					}

+

+					fieldOffset += fieldType.totalRegisterCount();

+				}

+

+				copy(result, left, fieldOffset);

+			}

+			break;

+		case EOpVectorSwizzle:

+			if(visit == PostVisit)

+			{

+				int swizzle = 0;

+				TIntermAggregate *components = right->getAsAggregate();

+

+				if(components)

+				{

+					TIntermSequence &sequence = components->getSequence();

+					int component = 0;

+

+					for(TIntermSequence::iterator sit = sequence.begin(); sit != sequence.end(); sit++)

+					{

+						TIntermConstantUnion *element = (*sit)->getAsConstantUnion();

+

+						if(element)

+						{

+							int i = element->getUnionArrayPointer()[0].getIConst();

+							swizzle |= i << (component * 2);

+							component++;

+						}

+						else UNREACHABLE();

+					}

+				}

+				else UNREACHABLE();

+

+				Instruction *mov = emit(sw::Shader::OPCODE_MOV, result, left);

+				mov->src[0].swizzle = swizzle;

+			}

+			break;

+		case EOpAddAssign:               if(visit == PostVisit) emitAssign(sw::Shader::OPCODE_ADD, result, left, left, right); break;

+		case EOpAdd:                     if(visit == PostVisit) emit(sw::Shader::OPCODE_ADD, result, left, right); break;

+		case EOpSubAssign:               if(visit == PostVisit) emitAssign(sw::Shader::OPCODE_SUB, result, left, left, right); break;

+		case EOpSub:                     if(visit == PostVisit) emit(sw::Shader::OPCODE_SUB, result, left, right); break;

+		case EOpMulAssign:               if(visit == PostVisit) emitAssign(sw::Shader::OPCODE_MUL, result, left, left, right); break;

+		case EOpMul:                     if(visit == PostVisit) emit(sw::Shader::OPCODE_MUL, result, left, right); break;

+		case EOpDivAssign:               if(visit == PostVisit) emitAssign(sw::Shader::OPCODE_DIV, result, left, left, right); break;

+		case EOpDiv:                     if(visit == PostVisit) emit(sw::Shader::OPCODE_DIV, result, left, right); break;

+		case EOpEqual:

+			if(visit == PostVisit)

+			{

+				emitCmp(sw::Shader::CONTROL_EQ, result, left, right);

+

+				for(int index = 1; index < left->totalRegisterCount(); index++)

+				{

+					Temporary equal(this);

+					emitCmp(sw::Shader::CONTROL_EQ, &equal, left, right, index);

+					emit(sw::Shader::OPCODE_AND, result, result, &equal);

+				}

+			}

+			break;

+		case EOpNotEqual:

+			if(visit == PostVisit)

+			{

+				emitCmp(sw::Shader::CONTROL_NE, result, left, right);

+

+				for(int index = 1; index < left->totalRegisterCount(); index++)

+				{

+					Temporary notEqual(this);

+					emitCmp(sw::Shader::CONTROL_NE, &notEqual, left, right, index);

+					emit(sw::Shader::OPCODE_OR, result, result, &notEqual);

+				}

+			}

+			break;

+		case EOpLessThan:                if(visit == PostVisit) emitCmp(sw::Shader::CONTROL_LT, result, left, right); break;

+		case EOpGreaterThan:             if(visit == PostVisit) emitCmp(sw::Shader::CONTROL_GT, result, left, right); break;

+		case EOpLessThanEqual:           if(visit == PostVisit) emitCmp(sw::Shader::CONTROL_LE, result, left, right); break;

+		case EOpGreaterThanEqual:        if(visit == PostVisit) emitCmp(sw::Shader::CONTROL_GE, result, left, right); break;

+		case EOpVectorTimesScalarAssign: if(visit == PostVisit) emitAssign(sw::Shader::OPCODE_MUL, result, left, left, right); break;

+		case EOpVectorTimesScalar:       if(visit == PostVisit) emit(sw::Shader::OPCODE_MUL, result, left, right); break;

+		case EOpMatrixTimesScalar:

+			if(visit == PostVisit)

+			{

+				for(int i = 0; i < leftType.getNominalSize(); i++)

+				{

+					Instruction *mul = emit(sw::Shader::OPCODE_MUL, result, left, right);

+					mul->dst.index += i;

+					argument(mul->src[0], left, i);

+				}

+			}

+			break;

+		case EOpVectorTimesMatrix:

+			if(visit == PostVisit)

+			{

+				int size = leftType.getNominalSize();

+

+				for(int i = 0; i < size; i++)

+				{

+					Instruction *dot = emit(sw::Shader::OPCODE_DP(size), result, left, right);

+					dot->dst.mask = 1 << i;

+					argument(dot->src[1], right, i);

+				}

+			}

+			break;

+		case EOpMatrixTimesVector:

+			if(visit == PostVisit)

+			{

+				Instruction *mul = emit(sw::Shader::OPCODE_MUL, result, left, right);

+				mul->src[1].swizzle = 0x00;

+

+				for(int i = 1; i < leftType.getNominalSize(); i++)

+				{

+					Instruction *mad = emit(sw::Shader::OPCODE_MAD, result, left, right, result);

+					argument(mad->src[0], left, i);

+					mad->src[1].swizzle = i * 0x55;

+				}

+			}

+			break;

+		case EOpMatrixTimesMatrix:

+			if(visit == PostVisit)

+			{

+				int dim = leftType.getNominalSize();

+

+				for(int i = 0; i < dim; i++)

+				{

+					Instruction *mul = emit(sw::Shader::OPCODE_MUL, result, left, right);

+					mul->dst.index += i;

+					argument(mul->src[1], right, i);

+					mul->src[1].swizzle = 0x00;

+

+					for(int j = 1; j < dim; j++)

+					{

+						Instruction *mad = emit(sw::Shader::OPCODE_MAD, result, left, right, result);

+						mad->dst.index += i;

+						argument(mad->src[0], left, j);

+						argument(mad->src[1], right, i);

+						mad->src[1].swizzle = j * 0x55;

+						argument(mad->src[2], result, i);

+					}

+				}

+			}

+			break;

+		case EOpLogicalOr:

+			if(trivial(right, 6))

+			{

+				if(visit == PostVisit)

+				{

+					emit(sw::Shader::OPCODE_OR, result, left, right);

+				}

+			}

+			else   // Short-circuit evaluation

+			{

+				if(visit == InVisit)

+				{

+					emit(sw::Shader::OPCODE_MOV, result, left);

+					Instruction *ifnot = emit(sw::Shader::OPCODE_IF, 0, result);

+					ifnot->src[0].modifier = sw::Shader::MODIFIER_NOT;

+				}

+				else if(visit == PostVisit)

+				{

+					emit(sw::Shader::OPCODE_MOV, result, right);

+					emit(sw::Shader::OPCODE_ENDIF);

+				}

+			}

+			break;

+		case EOpLogicalXor:        if(visit == PostVisit) emit(sw::Shader::OPCODE_XOR, result, left, right); break;

+		case EOpLogicalAnd:

+			if(trivial(right, 6))

+			{

+				if(visit == PostVisit)

+				{

+					emit(sw::Shader::OPCODE_AND, result, left, right);

+				}

+			}

+			else   // Short-circuit evaluation

+			{

+				if(visit == InVisit)

+				{

+					emit(sw::Shader::OPCODE_MOV, result, left);

+					emit(sw::Shader::OPCODE_IF, 0, result);

+				}

+				else if(visit == PostVisit)

+				{

+					emit(sw::Shader::OPCODE_MOV, result, right);

+					emit(sw::Shader::OPCODE_ENDIF);

+				}

+			}

+			break;

+		default: UNREACHABLE();

+		}

+

+		return true;

+	}

+

+	bool OutputASM::visitUnary(Visit visit, TIntermUnary *node)

+	{

+		if(currentScope != emitScope)

+		{

+			return false;

+		}

+

+		Constant one(1.0f, 1.0f, 1.0f, 1.0f);

+		Constant rad(1.74532925e-2f, 1.74532925e-2f, 1.74532925e-2f, 1.74532925e-2f);

+		Constant deg(5.72957795e+1f, 5.72957795e+1f, 5.72957795e+1f, 5.72957795e+1f);

+

+		TIntermTyped *result = node;

+		TIntermTyped *arg = node->getOperand();

+

+		switch(node->getOp())

+		{

+		case EOpNegative:

+			if(visit == PostVisit)

+			{

+				for(int index = 0; index < arg->totalRegisterCount(); index++)

+				{

+					Instruction *neg = emit(sw::Shader::OPCODE_MOV, result, arg);

+					neg->dst.index += index;

+					argument(neg->src[0], arg, index);

+					neg->src[0].modifier = sw::Shader::MODIFIER_NEGATE;

+				}

+			}

+			break;

+		case EOpVectorLogicalNot: if(visit == PostVisit) emit(sw::Shader::OPCODE_NOT, result, arg); break;

+		case EOpLogicalNot:       if(visit == PostVisit) emit(sw::Shader::OPCODE_NOT, result, arg); break;

+		case EOpPostIncrement:

+			if(visit == PostVisit)

+			{

+				copy(result, arg);

+

+				for(int index = 0; index < arg->totalRegisterCount(); index++)

+				{

+					Instruction *add = emit(sw::Shader::OPCODE_ADD, arg, arg, &one);

+					add->dst.index += index;

+					argument(add->src[0], arg, index);

+				}

+

+				assignLvalue(arg, arg);

+			}

+			break;

+		case EOpPostDecrement:

+			if(visit == PostVisit)

+			{

+				copy(result, arg);

+

+				for(int index = 0; index < arg->totalRegisterCount(); index++)

+				{

+					Instruction *sub = emit(sw::Shader::OPCODE_SUB, arg, arg, &one);

+					sub->dst.index += index;

+					argument(sub->src[0], arg, index);

+				}

+

+				assignLvalue(arg, arg);

+			}

+			break;

+		case EOpPreIncrement:

+			if(visit == PostVisit)

+			{

+				for(int index = 0; index < arg->totalRegisterCount(); index++)

+				{

+					Instruction *add = emit(sw::Shader::OPCODE_ADD, result, arg, &one);

+					add->dst.index += index;

+					argument(add->src[0], arg, index);

+				}

+

+				assignLvalue(arg, result);

+			}

+			break;

+		case EOpPreDecrement:

+			if(visit == PostVisit)

+			{

+				for(int index = 0; index < arg->totalRegisterCount(); index++)

+				{

+					Instruction *sub = emit(sw::Shader::OPCODE_SUB, result, arg, &one);

+					sub->dst.index += index;

+					argument(sub->src[0], arg, index);

+				}

+

+				assignLvalue(arg, result);

+			}

+			break;

+		case EOpConvIntToBool:    if(visit == PostVisit) emit(sw::Shader::OPCODE_F2B, result, arg); break;     // Integers are implemented as float

+		case EOpConvFloatToBool:  if(visit == PostVisit) emit(sw::Shader::OPCODE_F2B, result, arg); break;

+		case EOpConvBoolToFloat:  if(visit == PostVisit) emit(sw::Shader::OPCODE_B2F, result, arg); break;

+		case EOpConvIntToFloat:   if(visit == PostVisit) emit(sw::Shader::OPCODE_MOV, result, arg); break;     // Integers are implemented as float

+		case EOpConvFloatToInt:   if(visit == PostVisit) emit(sw::Shader::OPCODE_TRUNC, result, arg); break;   // Integers are implemented as float

+		case EOpConvBoolToInt:    if(visit == PostVisit) emit(sw::Shader::OPCODE_B2F, result, arg); break;     // Integers are implemented as float

+		case EOpRadians:          if(visit == PostVisit) emit(sw::Shader::OPCODE_MUL, result, arg, &rad); break;

+		case EOpDegrees:          if(visit == PostVisit) emit(sw::Shader::OPCODE_MUL, result, arg, &deg); break;

+		case EOpSin:              if(visit == PostVisit) emit(sw::Shader::OPCODE_SIN, result, arg); break;

+		case EOpCos:              if(visit == PostVisit) emit(sw::Shader::OPCODE_COS, result, arg); break;

+		case EOpTan:              if(visit == PostVisit) emit(sw::Shader::OPCODE_TAN, result, arg); break;

+		case EOpAsin:             if(visit == PostVisit) emit(sw::Shader::OPCODE_ASIN, result, arg); break;

+		case EOpAcos:             if(visit == PostVisit) emit(sw::Shader::OPCODE_ACOS, result, arg); break;

+		case EOpAtan:             if(visit == PostVisit) emit(sw::Shader::OPCODE_ATAN, result, arg); break;

+		case EOpExp:              if(visit == PostVisit) emit(sw::Shader::OPCODE_EXP, result, arg); break;

+		case EOpLog:              if(visit == PostVisit) emit(sw::Shader::OPCODE_LOG, result, arg); break;

+		case EOpExp2:             if(visit == PostVisit) emit(sw::Shader::OPCODE_EXP2, result, arg); break;

+		case EOpLog2:             if(visit == PostVisit) emit(sw::Shader::OPCODE_LOG2, result, arg); break;

+		case EOpSqrt:             if(visit == PostVisit) emit(sw::Shader::OPCODE_SQRT, result, arg); break;

+		case EOpInverseSqrt:      if(visit == PostVisit) emit(sw::Shader::OPCODE_RSQ, result, arg); break;

+		case EOpAbs:              if(visit == PostVisit) emit(sw::Shader::OPCODE_ABS, result, arg); break;

+		case EOpSign:             if(visit == PostVisit) emit(sw::Shader::OPCODE_SGN, result, arg); break;

+		case EOpFloor:            if(visit == PostVisit) emit(sw::Shader::OPCODE_FLOOR, result, arg); break;

+		case EOpCeil:             if(visit == PostVisit) emit(sw::Shader::OPCODE_CEIL, result, arg, result);	break;

+		case EOpFract:            if(visit == PostVisit) emit(sw::Shader::OPCODE_FRC, result, arg); break;

+		case EOpLength:           if(visit == PostVisit) emit(sw::Shader::OPCODE_LEN(dim(arg)), result, arg); break;

+		case EOpNormalize:        if(visit == PostVisit) emit(sw::Shader::OPCODE_NRM(dim(arg)), result, arg); break;

+		case EOpDFdx:             if(visit == PostVisit) emit(sw::Shader::OPCODE_DFDX, result, arg); break;

+		case EOpDFdy:             if(visit == PostVisit) emit(sw::Shader::OPCODE_DFDY, result, arg); break;

+		case EOpFwidth:           if(visit == PostVisit) emit(sw::Shader::OPCODE_FWIDTH, result, arg); break;

+		case EOpAny:              if(visit == PostVisit) emit(sw::Shader::OPCODE_ANY, result, arg); break;

+		case EOpAll:              if(visit == PostVisit) emit(sw::Shader::OPCODE_ALL, result, arg); break;

+		default: UNREACHABLE();

+		}

+

+		return true;

+	}

+

+	bool OutputASM::visitAggregate(Visit visit, TIntermAggregate *node)

+	{

+		if(currentScope != emitScope && node->getOp() != EOpFunction && node->getOp() != EOpSequence)

+		{

+			return false;

+		}

+

+		TIntermTyped *result = node;

+		const TType &resultType = node->getType();

+		TIntermSequence &arg = node->getSequence();

+		int argumentCount = arg.size();

+

+		switch(node->getOp())

+		{

+		case EOpSequence:           break;

+		case EOpDeclaration:		break;

+		case EOpPrototype:          break;

+		case EOpComma:

+			if(visit == PostVisit)

+			{

+				copy(result, arg[1]);

+			}

+			break;

+		case EOpFunction:

+			if(visit == PreVisit)

+			{

+				const TString &name = node->getName();

+

+				if(emitScope == FUNCTION)

+				{

+					if(functionArray.size() > 1)   // No need for a label when there's only main()

+					{

+						Instruction *label = emit(sw::Shader::OPCODE_LABEL);

+						label->dst.type = sw::Shader::PARAMETER_LABEL;

+

+						const Function &function = findFunction(name);

+						label->dst.index = function.label;

+						currentFunction = function.label;

+					}

+				}

+				else if(emitScope == GLOBAL)

+				{

+					if(name != "main(")

+					{

+						TIntermSequence &arguments = node->getSequence()[0]->getAsAggregate()->getSequence();

+						functionArray.push_back(Function(functionArray.size(), name, &arguments, node));

+					}

+				}

+				else UNREACHABLE();

+

+				currentScope = FUNCTION;

+			}

+			else if(visit == PostVisit)

+			{

+				if(emitScope == FUNCTION)

+				{

+					if(functionArray.size() > 1)   // No need to return when there's only main()

+					{

+						emit(sw::Shader::OPCODE_RET);

+					}

+				}

+

+				currentScope = GLOBAL;

+			}

+			break;

+		case EOpFunctionCall:

+			if(visit == PostVisit)

+			{

+                if(node->isUserDefined())

+                {

+					const TString &name = node->getName();

+					const Function &function = findFunction(name);

+					TIntermSequence &arguments = *function.arg;

+

+					for(int i = 0; i < argumentCount; i++)

+					{

+						TIntermTyped *in = arguments[i]->getAsTyped();

+								

+						if(in->getQualifier() == EvqIn ||

+						   in->getQualifier() == EvqInOut ||

+						   in->getQualifier() == EvqConstReadOnly)

+						{

+							copy(in, arg[i]);

+						}

+					}

+

+					Instruction *call = emit(sw::Shader::OPCODE_CALL);

+					call->dst.type = sw::Shader::PARAMETER_LABEL;

+					call->dst.index = function.label;

+

+					if(function.ret && function.ret->getType().getBasicType() != EbtVoid)

+					{

+						copy(result, function.ret);

+					}

+

+					for(int i = 0; i < argumentCount; i++)

+					{

+						TIntermTyped *argument = arguments[i]->getAsTyped();

+						TIntermTyped *out = arg[i]->getAsTyped();

+								

+						if(argument->getQualifier() == EvqOut ||

+						   argument->getQualifier() == EvqInOut)

+						{

+							copy(out, argument);

+						}

+					}

+				}

+				else

+				{

+					TString name = TFunction::unmangleName(node->getName());

+

+					if(name == "texture2D" || name == "textureCube")

+					{

+						if(argumentCount == 2)

+						{	

+							emit(sw::Shader::OPCODE_TEX, result, arg[1], arg[0]);

+						}

+						else if(argumentCount == 3)   // bias

+						{

+							Temporary uvwb(this);

+							emit(sw::Shader::OPCODE_MOV, &uvwb, arg[1]);

+							Instruction *bias = emit(sw::Shader::OPCODE_MOV, &uvwb, arg[2]);

+							bias->dst.mask = 0x8;

+

+							Instruction *tex = emit(sw::Shader::OPCODE_TEX, result, &uvwb, arg[0]);   // FIXME: Implement an efficient TEXLDB instruction

+							tex->bias = true;

+						}

+						else UNREACHABLE();

+					}

+					else if(name == "texture2DProj")

+                    {

+						TIntermTyped *t = arg[1]->getAsTyped();

+

+                        if(argumentCount == 2)

+						{

+							Instruction *tex = emit(sw::Shader::OPCODE_TEX, result, arg[1], arg[0]);

+							tex->project = true;

+

+							if(t->getNominalSize() == 3)

+							{

+								tex->src[0].swizzle = 0xA4;

+							}

+							else ASSERT(t->getNominalSize() == 4);

+						}

+						else if(argumentCount == 3)   // bias

+						{

+							Temporary proj(this);

+							emit(sw::Shader::OPCODE_MOV, &proj, arg[1]);

+

+							if(t->getNominalSize() == 3)

+							{

+								Instruction *div = emit(sw::Shader::OPCODE_DIV, &proj, &proj);

+								div->src[0].swizzle = 0xAA;

+								div->dst.mask = 0x3;

+							}

+							else if(t->getNominalSize() == 4)

+							{

+								Instruction *div = emit(sw::Shader::OPCODE_DIV, &proj, &proj);

+								div->src[0].swizzle = 0xFF;

+								div->dst.mask = 0x3;

+							}

+							else UNREACHABLE();

+

+							Instruction *bias = emit(sw::Shader::OPCODE_MOV, &proj, arg[2]);

+							bias->dst.mask = 0x8;

+

+							Instruction *tex = emit(sw::Shader::OPCODE_TEX, result, &proj, arg[0]);

+							tex->bias = true;

+						}

+						else UNREACHABLE();

+                    }

+                    else if(name == "texture2DLod" || name == "textureCubeLod")

+                    {

+						Temporary uvwb(this);

+						emit(sw::Shader::OPCODE_MOV, &uvwb, arg[1]);

+						Instruction *lod = emit(sw::Shader::OPCODE_MOV, &uvwb, arg[2]);

+						lod->dst.mask = 0x8;

+

+						emit(sw::Shader::OPCODE_TEXLDL, result, &uvwb, arg[0]);

+                    }

+                    else if(name == "texture2DProjLod")

+                    {

+                        TIntermTyped *t = arg[1]->getAsTyped();

+

+						Temporary proj(this);

+						emit(sw::Shader::OPCODE_MOV, &proj, arg[1]);

+

+						if(t->getNominalSize() == 3)

+						{

+							Instruction *div = emit(sw::Shader::OPCODE_DIV, &proj, &proj);

+							div->src[0].swizzle = 0xAA;

+							div->dst.mask = 0x3;

+						}

+						else if(t->getNominalSize() == 4)

+						{

+							Instruction *div = emit(sw::Shader::OPCODE_DIV, &proj, &proj);

+							div->src[0].swizzle = 0xFF;

+							div->dst.mask = 0x3;

+						}

+						else UNREACHABLE();

+

+						Instruction *lod = emit(sw::Shader::OPCODE_MOV, &proj, arg[2]);

+						lod->dst.mask = 0x8;

+

+						emit(sw::Shader::OPCODE_TEXLDL, result, &proj, arg[0]);

+                    }

+					else UNREACHABLE();

+				}

+			}

+			break;

+		case EOpParameters: break;

+		case EOpConstructFloat:

+		case EOpConstructVec2:

+		case EOpConstructVec3:

+		case EOpConstructVec4:

+		case EOpConstructBool:

+		case EOpConstructBVec2:

+		case EOpConstructBVec3:

+		case EOpConstructBVec4:

+		case EOpConstructInt:

+		case EOpConstructIVec2:

+		case EOpConstructIVec3:

+		case EOpConstructIVec4:

+			if(visit == PostVisit)

+			{

+				int component = 0;

+

+				for(int i = 0; i < argumentCount; i++)

+                {

+                    TIntermTyped *argi = arg[i]->getAsTyped();

+					int size = argi->getNominalSize();

+					ASSERT(!argi->isMatrix());

+

+					Instruction *mov = emit(sw::Shader::OPCODE_MOV, result, argi);

+					mov->dst.mask = (0xF << component) & 0xF;

+					mov->src[0].swizzle = swizzleSize[size] << (component * 2);

+

+					component += size;

+				}

+			}

+			break;

+		case EOpConstructMat2:

+		case EOpConstructMat3:

+		case EOpConstructMat4:

+			if(visit == PostVisit)

+			{

+				TIntermTyped *arg0 = arg[0]->getAsTyped();

+				const int dim = result->getNominalSize();

+

+				if(arg0->isMatrix())

+				{

+					for(int i = 0; i < dim; i++)

+					{

+						if(dim > dim2(arg0))

+						{

+							// Initialize to identity matrix

+							Constant col((i == 0 ? 1.0f : 0.0f), (i == 1 ? 1.0f : 0.0f), (i == 2 ? 1.0f : 0.0f), (i == 3 ? 1.0f : 0.0f));

+							Instruction *mov = emit(sw::Shader::OPCODE_MOV, result, &col);

+							mov->dst.index += i;

+						}

+

+						if(i < dim2(arg0))

+						{

+							Instruction *mov = emit(sw::Shader::OPCODE_MOV, result, arg0);

+							mov->dst.index += i;

+							mov->dst.mask = 0xF >> (4 - dim2(arg0));

+							argument(mov->src[0], arg0, i);

+						}

+					}

+				}

+				else

+				{

+					int column = 0;

+					int row = 0;

+

+					for(int i = 0; i < argumentCount; i++)

+					{

+						TIntermTyped *argi = arg[i]->getAsTyped();

+						int size = argi->getNominalSize();

+						int element = 0;

+

+						while(element < size)

+						{

+							Instruction *mov = emit(sw::Shader::OPCODE_MOV, result, argi);

+							mov->dst.index += column;

+							mov->dst.mask = (0xF << row) & 0xF;

+							mov->src[0].swizzle = (swizzleSize[size] << (row * 2)) + 0x55 * element;

+					

+							int end = row + size - element;

+							column = end >= dim ? column + 1 : column;

+							element = element + dim - row;

+							row = end >= dim ? 0 : end;

+						}

+					}

+				}

+			}

+			break;

+		case EOpConstructStruct:

+			if(visit == PostVisit)

+			{

+				int offset = 0;

+				for(int i = 0; i < argumentCount; i++)

+				{

+					TIntermTyped *argi = arg[i]->getAsTyped();

+					int size = argi->totalRegisterCount();

+

+					for(int index = 0; index < size; index++)

+					{

+						Instruction *mov = emit(sw::Shader::OPCODE_MOV, result, argi);

+						mov->dst.index += index + offset;

+						mov->dst.mask = writeMask(result, offset + index);

+						argument(mov->src[0], argi, index);

+					}

+

+					offset += size;

+				}

+			}

+			break;

+		case EOpLessThan:         if(visit == PostVisit) emitCmp(sw::Shader::CONTROL_LT, result, arg[0], arg[1]); break;

+		case EOpGreaterThan:      if(visit == PostVisit) emitCmp(sw::Shader::CONTROL_GT, result, arg[0], arg[1]); break;

+		case EOpLessThanEqual:    if(visit == PostVisit) emitCmp(sw::Shader::CONTROL_LE, result, arg[0], arg[1]); break;

+		case EOpGreaterThanEqual: if(visit == PostVisit) emitCmp(sw::Shader::CONTROL_GE, result, arg[0], arg[1]); break;

+		case EOpVectorEqual:      if(visit == PostVisit) emitCmp(sw::Shader::CONTROL_EQ, result, arg[0], arg[1]); break;

+		case EOpVectorNotEqual:   if(visit == PostVisit) emitCmp(sw::Shader::CONTROL_NE, result, arg[0], arg[1]); break;

+		case EOpMod:              if(visit == PostVisit) emit(sw::Shader::OPCODE_MOD, result, arg[0], arg[1]); break;

+		case EOpPow:              if(visit == PostVisit) emit(sw::Shader::OPCODE_POW, result, arg[0], arg[1]); break;

+		case EOpAtan:             if(visit == PostVisit) emit(sw::Shader::OPCODE_ATAN2, result, arg[0], arg[1]); break;

+		case EOpMin:              if(visit == PostVisit) emit(sw::Shader::OPCODE_MIN, result, arg[0], arg[1]); break;

+		case EOpMax:              if(visit == PostVisit) emit(sw::Shader::OPCODE_MAX, result, arg[0], arg[1]); break;

+		case EOpClamp:

+			if(visit == PostVisit)

+			{

+				emit(sw::Shader::OPCODE_MAX, result, arg[0], arg[1]);

+				emit(sw::Shader::OPCODE_MIN, result, result, arg[2]);

+			}

+			break;

+		case EOpMix:         if(visit == PostVisit) emit(sw::Shader::OPCODE_LRP, result, arg[2], arg[1], arg[0]); break;

+		case EOpStep:        if(visit == PostVisit) emit(sw::Shader::OPCODE_STEP, result, arg[0], arg[1]); break;

+		case EOpSmoothStep:  if(visit == PostVisit) emit(sw::Shader::OPCODE_SMOOTH, result, arg[0], arg[1], arg[2]); break;

+		case EOpDistance:    if(visit == PostVisit) emit(sw::Shader::OPCODE_DIST(dim(arg[0])), result, arg[0], arg[1]); break;

+		case EOpDot:         if(visit == PostVisit) emit(sw::Shader::OPCODE_DP(dim(arg[0])), result, arg[0], arg[1]); break;

+		case EOpCross:       if(visit == PostVisit) emit(sw::Shader::OPCODE_CRS, result, arg[0], arg[1]); break;

+		case EOpFaceForward: if(visit == PostVisit) emit(sw::Shader::OPCODE_FORWARD(dim(arg[0])), result, arg[0], arg[1], arg[2]); break;

+		case EOpReflect:     if(visit == PostVisit) emit(sw::Shader::OPCODE_REFLECT(dim(arg[0])), result, arg[0], arg[1]); break;

+		case EOpRefract:     if(visit == PostVisit) emit(sw::Shader::OPCODE_REFRACT(dim(arg[0])), result, arg[0], arg[1], arg[2]); break;

+		case EOpMul:

+			if(visit == PostVisit)

+			{

+				ASSERT(dim2(arg[0]) == dim2(arg[1]));

+

+				for(int i = 0; i < dim2(arg[0]); i++)

+                {

+					Instruction *mul = emit(sw::Shader::OPCODE_MUL, result, arg[0], arg[1]);

+					mul->dst.index += i;

+					argument(mul->src[0], arg[0], i);

+					argument(mul->src[1], arg[1], i);

+				}

+			}

+			break;

+		default: UNREACHABLE();

+		}

+

+		return true;

+	}

+

+	bool OutputASM::visitSelection(Visit visit, TIntermSelection *node)

+	{

+		if(currentScope != emitScope)

+		{

+			return false;

+		}

+

+		TIntermTyped *condition = node->getCondition();

+		TIntermNode *trueBlock = node->getTrueBlock();

+		TIntermNode *falseBlock = node->getFalseBlock();

+		TIntermConstantUnion *constantCondition = condition->getAsConstantUnion();

+

+		condition->traverse(this);

+

+		if(node->usesTernaryOperator())

+		{

+			if(constantCondition)

+			{

+				bool trueCondition = constantCondition->getUnionArrayPointer()->getBConst();

+

+				if(trueCondition)

+				{

+					trueBlock->traverse(this);

+					copy(node, trueBlock);

+				}

+				else

+				{

+					falseBlock->traverse(this);

+					copy(node, falseBlock);

+				}

+			}

+			else if(trivial(node, 6))   // Fast to compute both potential results and no side effects

+			{

+				trueBlock->traverse(this);

+				falseBlock->traverse(this);

+				emit(sw::Shader::OPCODE_SELECT, node, condition, trueBlock, falseBlock);

+			}

+			else

+			{

+				emit(sw::Shader::OPCODE_IF, 0, condition);

+

+				if(trueBlock)

+				{

+					trueBlock->traverse(this);

+					copy(node, trueBlock);

+				}

+

+				if(falseBlock)

+				{

+					emit(sw::Shader::OPCODE_ELSE);

+					falseBlock->traverse(this);

+					copy(node, falseBlock);

+				}

+

+				emit(sw::Shader::OPCODE_ENDIF);

+			}

+		}

+		else  // if/else statement

+		{

+			if(constantCondition)

+			{

+				bool trueCondition = constantCondition->getUnionArrayPointer()->getBConst();

+

+				if(trueCondition)

+				{

+					if(trueBlock)

+					{

+						trueBlock->traverse(this);

+					}

+				}

+				else

+				{

+					if(falseBlock)

+					{

+						falseBlock->traverse(this);

+					}

+				}

+			}

+			else

+			{

+				emit(sw::Shader::OPCODE_IF, 0, condition);

+

+				if(trueBlock)

+				{

+					trueBlock->traverse(this);

+				}

+

+				if(falseBlock)

+				{

+					emit(sw::Shader::OPCODE_ELSE);

+					falseBlock->traverse(this);

+				}

+

+				emit(sw::Shader::OPCODE_ENDIF);

+			}

+		}

+

+		return false;

+	}

+

+	bool OutputASM::visitLoop(Visit visit, TIntermLoop *node)

+	{

+		if(currentScope != emitScope)

+		{

+			return false;

+		}

+

+		TIntermNode *init = node->getInit();

+		TIntermTyped *condition = node->getCondition();

+		TIntermTyped *expression = node->getExpression();

+		TIntermNode *body = node->getBody();

+

+		if(node->getType() == ELoopDoWhile)

+		{

+			Temporary iterate(this);

+			Constant True(true);

+			emit(sw::Shader::OPCODE_MOV, &iterate, &True);

+

+			emit(sw::Shader::OPCODE_WHILE, 0, &iterate);   // FIXME: Implement real do-while

+

+			if(body)

+			{

+				body->traverse(this);

+			}

+

+			emit(sw::Shader::OPCODE_TEST);

+

+			condition->traverse(this);

+			emit(sw::Shader::OPCODE_MOV, &iterate, condition);

+

+			emit(sw::Shader::OPCODE_ENDWHILE);

+		}

+		else

+		{

+			if(init)

+			{

+				init->traverse(this);

+			}

+

+			condition->traverse(this);

+

+			emit(sw::Shader::OPCODE_WHILE, 0, condition);

+

+			if(body)

+			{

+				body->traverse(this);

+			}

+

+			emit(sw::Shader::OPCODE_TEST);

+

+			if(expression)

+			{

+				expression->traverse(this);

+			}

+

+			condition->traverse(this);

+

+			emit(sw::Shader::OPCODE_ENDWHILE);

+		}

+

+		return false;

+	}

+

+	bool OutputASM::visitBranch(Visit visit, TIntermBranch *node)

+	{

+		if(currentScope != emitScope)

+		{

+			return false;

+		}

+

+		switch(node->getFlowOp())

+		{

+		case EOpKill:      if(visit == PostVisit) emit(sw::Shader::OPCODE_DISCARD); break;

+		case EOpBreak:     if(visit == PostVisit) emit(sw::Shader::OPCODE_BREAK); break;

+		case EOpContinue:  if(visit == PostVisit) emit(sw::Shader::OPCODE_CONTINUE); break;

+		case EOpReturn:

+			if(visit == PostVisit)

+			{

+				TIntermTyped *value = node->getExpression();

+

+				if(value)

+				{

+					copy(functionArray[currentFunction].ret, value);

+				}

+

+				emit(sw::Shader::OPCODE_LEAVE);

+			}

+			break;

+		default: UNREACHABLE();

+		}

+

+		return true;

+	}

+

+	Instruction *OutputASM::emit(sw::Shader::Opcode op, TIntermTyped *dst, TIntermNode *src0, TIntermNode *src1, TIntermNode *src2)

+	{

+		if(dst && registerType(dst) == sw::Shader::PARAMETER_SAMPLER)

+		{

+			op = sw::Shader::OPCODE_NOP;   // Can't assign to a sampler, but this will be hit when indexing sampler arrays

+		}

+

+		Instruction *instruction = new Instruction(op);

+

+		if(dst)

+		{

+			instruction->dst.type = registerType(dst);

+			instruction->dst.index = registerIndex(dst);

+			instruction->dst.mask = writeMask(dst);

+			instruction->dst.integer = (dst->getBasicType() == EbtInt);

+		}

+

+		argument(instruction->src[0], src0);

+		argument(instruction->src[1], src1);

+		argument(instruction->src[2], src2);

+

+		shader->append(instruction);

+

+		return instruction;

+	}

+

+	void OutputASM::emitAssign(sw::Shader::Opcode op, TIntermTyped *result, TIntermTyped *lhs, TIntermTyped *src0, TIntermTyped *src1)

+	{

+		emit(op, result, src0, src1);

+		assignLvalue(lhs, result);

+	}

+

+	void OutputASM::emitCmp(sw::Shader::Control cmpOp, TIntermTyped *dst, TIntermNode *left, TIntermNode *right, int index)

+	{

+		bool boolean = (left->getAsTyped()->getBasicType() == EbtBool);

+		sw::Shader::Opcode opcode = boolean ? sw::Shader::OPCODE_ICMP : sw::Shader::OPCODE_CMP;

+

+		Instruction *cmp = emit(opcode, dst, left, right);

+		cmp->control = cmpOp;

+		argument(cmp->src[0], left, index);

+		argument(cmp->src[1], right, index);

+	}

+

+	int componentCount(const TType &type, int registers)

+	{

+		if(registers == 0)

+		{

+			return 0;

+		}

+

+		if(type.isArray() && registers >= type.elementRegisterCount())

+		{

+			int index = registers / type.elementRegisterCount();

+			registers -= index * type.elementRegisterCount();

+			return index * type.getElementSize() + componentCount(type, registers);

+		}

+

+		if(type.isStruct())

+		{

+			TTypeList *structure = type.getStruct();

+			int elements = 0;

+

+			for(TTypeList::const_iterator field = structure->begin(); field != structure->end(); field++)

+			{

+				const TType &fieldType = *field->type;

+

+				if(fieldType.totalRegisterCount() <= registers)

+				{

+					registers -= fieldType.totalRegisterCount();

+					elements += fieldType.getObjectSize();

+				}

+				else   // Register within this field

+				{

+					return elements + componentCount(fieldType, registers);

+				}

+			}

+		}

+		else if(type.isMatrix())

+		{

+			return registers * type.getNominalSize();

+		}

+		

+		UNREACHABLE();

+		return 0;

+	}

+

+	int registerSize(const TType &type, int registers)

+	{

+		if(registers == 0)

+		{

+			if(type.isStruct())

+			{

+				return registerSize(*type.getStruct()->begin()->type, 0);

+			}

+

+			return type.getNominalSize();

+		}

+

+		if(type.isArray() && registers >= type.elementRegisterCount())

+		{

+			int index = registers / type.elementRegisterCount();

+			registers -= index * type.elementRegisterCount();

+			return registerSize(type, registers);

+		}

+

+		if(type.isStruct())

+		{

+			TTypeList *structure = type.getStruct();

+			int elements = 0;

+

+			for(TTypeList::const_iterator field = structure->begin(); field != structure->end(); field++)

+			{

+				const TType &fieldType = *field->type;

+				

+				if(fieldType.totalRegisterCount() <= registers)

+				{

+					registers -= fieldType.totalRegisterCount();

+					elements += fieldType.getObjectSize();

+				}

+				else   // Register within this field

+				{

+					return registerSize(fieldType, registers);

+				}

+			}

+		}

+		else if(type.isMatrix())

+		{

+			return registerSize(type, 0);

+		}

+		

+		UNREACHABLE();

+		return 0;

+	}

+

+	void OutputASM::argument(sw::Shader::SourceParameter &parameter, TIntermNode *argument, int index)

+	{

+		if(argument)

+		{

+			TIntermTyped *arg = argument->getAsTyped();

+			const TType &type = arg->getType();

+			const TTypeList *structure = type.getStruct();

+			ASSERT(index < arg->totalRegisterCount());

+

+			int size = registerSize(type, index);

+

+			parameter.type = registerType(arg);

+

+			if(arg->getQualifier() == EvqConst)

+			{

+				int component = componentCount(type, index);

+				ConstantUnion *constants = arg->getAsConstantUnion()->getUnionArrayPointer();

+

+				for(int i = 0; i < 4; i++)

+				{

+					if(size == 1)   // Replicate

+					{

+						parameter.value[i] = constants[component + 0].getAsFloat();

+					}

+					else if(i < size)

+					{

+						parameter.value[i] = constants[component + i].getAsFloat();

+					}

+					else

+					{

+						parameter.value[i] = 0.0f;

+					}

+				}

+			}

+			else

+			{

+				parameter.index = registerIndex(arg) + index;

+

+				if(registerType(arg) == sw::Shader::PARAMETER_SAMPLER)

+				{

+					TIntermBinary *binary = argument->getAsBinaryNode();

+

+					if(binary)

+					{

+						TIntermTyped *left = binary->getLeft();

+						TIntermTyped *right = binary->getRight();

+

+						if(binary->getOp() == EOpIndexDirect)

+						{

+							parameter.index += right->getAsConstantUnion()->getUnionArrayPointer()->getIConst();

+						}

+						else if(binary->getOp() == EOpIndexIndirect)

+						{

+							if(left->getArraySize() > 1)

+							{

+								parameter.rel.type = registerType(binary->getRight());

+								parameter.rel.index = registerIndex(binary->getRight());

+								parameter.rel.scale = 1;

+								parameter.rel.deterministic = true;

+							}

+						}

+						else UNREACHABLE();

+					}

+				}

+			}

+

+			if(!IsSampler(arg->getBasicType()))

+			{

+				parameter.swizzle = swizzleSize[size];

+			}

+		}

+	}

+

+	void OutputASM::copy(TIntermTyped *dst, TIntermNode *src, int offset)

+	{

+		for(int index = 0; index < dst->totalRegisterCount(); index++)

+		{

+			Instruction *mov = emit(sw::Shader::OPCODE_MOV, dst, src);

+			mov->dst.index += index;

+			mov->dst.mask = writeMask(dst, index);

+			argument(mov->src[0], src, offset + index);

+		}

+	}

+

+	int swizzleElement(int swizzle, int index)

+	{

+		return (swizzle >> (index * 2)) & 0x03;

+	}

+

+	int swizzleSwizzle(int leftSwizzle, int rightSwizzle)

+	{

+		return (swizzleElement(leftSwizzle, swizzleElement(rightSwizzle, 0)) << 0) |

+		       (swizzleElement(leftSwizzle, swizzleElement(rightSwizzle, 1)) << 2) |

+		       (swizzleElement(leftSwizzle, swizzleElement(rightSwizzle, 2)) << 4) |

+		       (swizzleElement(leftSwizzle, swizzleElement(rightSwizzle, 3)) << 6);

+	}

+

+	void OutputASM::assignLvalue(TIntermTyped *dst, TIntermNode *src)

+	{

+		TIntermBinary *binary = dst->getAsBinaryNode();

+

+		if(binary && binary->getOp() == EOpIndexIndirect && dst->isScalar())

+		{

+			Instruction *insert = new Instruction(sw::Shader::OPCODE_INSERT);

+			

+			Temporary address(this);

+			lvalue(insert->dst, address, dst);

+

+			insert->src[0].type = insert->dst.type;

+			insert->src[0].index = insert->dst.index;

+			insert->src[0].rel = insert->dst.rel;

+			argument(insert->src[1], src);

+			argument(insert->src[2], binary->getRight());

+

+			shader->append(insert);

+		}

+		else

+		{

+			for(int offset = 0; offset < dst->totalRegisterCount(); offset++)

+			{

+				Instruction *mov = new Instruction(sw::Shader::OPCODE_MOV);

+			

+				Temporary address(this);

+				int swizzle = lvalue(mov->dst, address, dst);

+				mov->dst.index += offset;

+

+				if(offset > 0)

+				{

+					mov->dst.mask = writeMask(dst, offset);

+				}

+

+				argument(mov->src[0], src, offset);

+				mov->src[0].swizzle = swizzleSwizzle(mov->src[0].swizzle, swizzle);

+

+				shader->append(mov);

+			}

+		}

+	}

+

+	int OutputASM::lvalue(sw::Shader::DestinationParameter &dst, Temporary &address, TIntermTyped *node)

+	{

+		TIntermTyped *result = node;

+		TIntermBinary *binary = node->getAsBinaryNode();

+		TIntermSymbol *symbol = node->getAsSymbolNode();

+

+		if(binary)

+		{

+			TIntermTyped *left = binary->getLeft();

+			TIntermTyped *right = binary->getRight();

+

+			int leftSwizzle = lvalue(dst, address, left);   // Resolve the l-value of the left side

+

+			switch(binary->getOp())

+			{

+			case EOpIndexDirect:

+				{

+					int rightIndex = right->getAsConstantUnion()->getUnionArrayPointer()->getIConst();

+

+					if(left->isRegister())

+					{

+						int leftMask = dst.mask;

+						

+						dst.mask = 1;

+						while((leftMask & dst.mask) == 0)

+						{

+							dst.mask = dst.mask << 1;

+						}

+

+						int element = swizzleElement(leftSwizzle, rightIndex);

+						dst.mask = 1 << element;

+						

+						return element;

+					}

+					else if(left->isArray() || left->isMatrix())

+					{

+						dst.index += rightIndex * result->totalRegisterCount();

+						return 0xE4;

+					}

+					else UNREACHABLE();

+				}

+				break;

+			case EOpIndexIndirect:

+				{

+					if(left->isRegister())

+					{

+						// Requires INSERT instruction (handled by calling function)

+					}

+					else if(left->isArray() || left->isMatrix())

+					{

+						int scale = result->totalRegisterCount();

+

+						if(dst.rel.type == sw::Shader::PARAMETER_VOID)   // Use the index register as the relative address directly

+						{

+							if(left->totalRegisterCount() > 1)

+							{

+								sw::Shader::SourceParameter relativeRegister;

+								argument(relativeRegister, right);

+

+								dst.rel.index = relativeRegister.index;

+								dst.rel.type = relativeRegister.type;

+								dst.rel.scale = scale;

+								dst.rel.deterministic = !(vertexShader && left->getQualifier() == EvqUniform);

+							}

+						}

+						else if(dst.rel.index != registerIndex(&address))   // Move the previous index register to the address register

+						{

+							if(scale == 1)

+							{

+								Constant oldScale((int)dst.rel.scale);

+								Instruction *mad = emit(sw::Shader::OPCODE_MAD, &address, &address, &oldScale, right);

+								mad->src[0].index = dst.rel.index;

+								mad->src[0].type = dst.rel.type;

+							}

+							else

+							{

+								Constant oldScale((int)dst.rel.scale);

+								Instruction *mul = emit(sw::Shader::OPCODE_MUL, &address, &address, &oldScale);

+								mul->src[0].index = dst.rel.index;

+								mul->src[0].type = dst.rel.type;

+

+								Constant newScale(scale);

+								emit(sw::Shader::OPCODE_MAD, &address, right, &newScale, &address);

+							}

+

+							dst.rel.type = sw::Shader::PARAMETER_TEMP;

+							dst.rel.index = registerIndex(&address);

+							dst.rel.scale = 1;

+						}

+						else   // Just add the new index to the address register

+						{

+							if(scale == 1)

+							{

+								emit(sw::Shader::OPCODE_ADD, &address, &address, right);

+							}

+							else

+							{

+								Constant newScale(scale);

+								emit(sw::Shader::OPCODE_MAD, &address, right, &newScale, &address);

+							}

+						}

+					}

+					else UNREACHABLE();

+				}

+				break;

+			case EOpIndexDirectStruct:

+				{

+					const TTypeList *structure = left->getType().getStruct();

+					const TString &fieldName = right->getType().getFieldName();

+

+					int offset = 0;

+					for(TTypeList::const_iterator field = structure->begin(); field != structure->end(); field++)

+					{

+						if(field->type->getFieldName() == fieldName)

+						{

+							dst.type = registerType(left);

+							dst.index += offset;

+							dst.mask = writeMask(right);

+							

+							return 0xE4;

+						}

+

+						offset += field->type->totalRegisterCount();

+					}

+				}

+				break;

+			case EOpVectorSwizzle:

+				{

+					ASSERT(left->isRegister());

+

+					int leftMask = dst.mask;

+

+					int swizzle = 0;

+					int rightMask = 0;

+

+					TIntermSequence &sequence = right->getAsAggregate()->getSequence();

+

+					for(unsigned int i = 0; i < sequence.size(); i++)

+					{

+						int index = sequence[i]->getAsConstantUnion()->getUnionArrayPointer()->getIConst();

+

+						int element = swizzleElement(leftSwizzle, index);

+						rightMask = rightMask | (1 << element);

+						swizzle = swizzle | swizzleElement(leftSwizzle, i) << (element * 2);

+					}

+					

+					dst.mask = leftMask & rightMask;

+

+					return swizzle;

+				}

+				break;

+			default:

+				UNREACHABLE();   // Not an l-value operator

+				break;

+			}

+		}

+		else if(symbol)

+		{

+			dst.type = registerType(symbol);

+			dst.index = registerIndex(symbol);

+			dst.mask = writeMask(symbol);

+			return 0xE4;

+		}

+

+		return 0xE4;

+	}

+

+	sw::Shader::ParameterType OutputASM::registerType(TIntermTyped *operand)

+	{

+		if(IsSampler(operand->getBasicType()) && (operand->getQualifier() == EvqUniform || operand->getQualifier() == EvqTemporary))   // Function parameters are temporaries

+		{

+			return sw::Shader::PARAMETER_SAMPLER;

+		}

+

+		switch(operand->getQualifier())

+		{

+		case EvqTemporary:           return sw::Shader::PARAMETER_TEMP;

+		case EvqGlobal:              return sw::Shader::PARAMETER_TEMP;

+		case EvqConst:               return sw::Shader::PARAMETER_FLOAT4LITERAL;   // All converted to float

+		case EvqAttribute:           return sw::Shader::PARAMETER_INPUT;

+		case EvqVaryingIn:           return sw::Shader::PARAMETER_INPUT;

+		case EvqVaryingOut:          return sw::Shader::PARAMETER_OUTPUT;

+		case EvqInvariantVaryingIn:  return sw::Shader::PARAMETER_INPUT;    // FIXME: Guarantee invariance at the backend

+		case EvqInvariantVaryingOut: return sw::Shader::PARAMETER_OUTPUT;   // FIXME: Guarantee invariance at the backend 

+		case EvqUniform:             return sw::Shader::PARAMETER_CONST;

+		case EvqIn:                  return sw::Shader::PARAMETER_TEMP;

+		case EvqOut:                 return sw::Shader::PARAMETER_TEMP;

+		case EvqInOut:               return sw::Shader::PARAMETER_TEMP;

+		case EvqConstReadOnly:       return sw::Shader::PARAMETER_TEMP;

+		case EvqPosition:            return sw::Shader::PARAMETER_OUTPUT;

+		case EvqPointSize:           return sw::Shader::PARAMETER_OUTPUT;

+		case EvqFragCoord:           return sw::Shader::PARAMETER_MISCTYPE;

+		case EvqFrontFacing:         return sw::Shader::PARAMETER_MISCTYPE;

+		case EvqPointCoord:          return sw::Shader::PARAMETER_INPUT;

+		case EvqFragColor:           return sw::Shader::PARAMETER_COLOROUT;

+		case EvqFragData:            return sw::Shader::PARAMETER_COLOROUT;

+		default: UNREACHABLE();

+		}

+

+		return sw::Shader::PARAMETER_VOID;

+	}

+

+	int OutputASM::registerIndex(TIntermTyped *operand)

+	{

+		if(registerType(operand) == sw::Shader::PARAMETER_SAMPLER)

+		{

+			return samplerRegister(operand);

+		}

+

+		switch(operand->getQualifier())

+		{

+		case EvqTemporary:           return temporaryRegister(operand);

+		case EvqGlobal:              return temporaryRegister(operand);

+		case EvqConst:               UNREACHABLE();

+		case EvqAttribute:           return attributeRegister(operand);

+		case EvqVaryingIn:           return varyingRegister(operand);

+		case EvqVaryingOut:          return varyingRegister(operand);

+		case EvqInvariantVaryingIn:  return varyingRegister(operand);

+		case EvqInvariantVaryingOut: return varyingRegister(operand);

+		case EvqUniform:             return uniformRegister(operand);

+		case EvqIn:                  return temporaryRegister(operand);

+		case EvqOut:                 return temporaryRegister(operand);

+		case EvqInOut:               return temporaryRegister(operand);

+		case EvqConstReadOnly:       return temporaryRegister(operand);

+		case EvqPosition:            return varyingRegister(operand);

+		case EvqPointSize:           return varyingRegister(operand);

+		case EvqFragCoord:           pixelShader->vPosDeclared = true;  return 0;

+		case EvqFrontFacing:         pixelShader->vFaceDeclared = true; return 1;

+		case EvqPointCoord:          return varyingRegister(operand);

+		case EvqFragColor:           return 0;

+		case EvqFragData:            return 0;

+		default: UNREACHABLE();

+		}

+

+		return 0;

+	}

+

+	int OutputASM::writeMask(TIntermTyped *destination, int index)

+	{

+		if(destination->getQualifier() == EvqPointSize)

+		{

+			return 0x2;   // Point size stored in the y component

+		}

+

+		return 0xF >> (4 - registerSize(destination->getType(), index));

+	}

+

+	// Conservatively checks whether an expression is fast to compute and has no side effects

+	bool OutputASM::trivial(TIntermTyped *expression, int budget)

+	{

+		if(!expression->isRegister())

+		{

+			return false;

+		}

+

+		return cost(expression, budget) >= 0;

+	}

+

+	// Returns the remaining computing budget (if < 0 the expression is too expensive or has side effects)

+	int OutputASM::cost(TIntermNode *expression, int budget)

+	{

+		if(budget < 0)

+		{

+			return budget;

+		}

+

+		if(expression->getAsSymbolNode())

+		{

+			return budget;

+		}

+		else if(expression->getAsConstantUnion())

+		{

+			return budget;

+		}

+		else if(expression->getAsBinaryNode())

+		{

+			TIntermBinary *binary = expression->getAsBinaryNode();

+

+			switch(binary->getOp())

+			{

+			case EOpVectorSwizzle:

+			case EOpIndexDirect:

+			case EOpIndexDirectStruct:

+				return cost(binary->getLeft(), budget - 0);

+			case EOpAdd:

+			case EOpSub:

+			case EOpMul:

+				return cost(binary->getLeft(), cost(binary->getRight(), budget - 1));

+			default:

+				return -1;

+			}

+		}

+		else if(expression->getAsUnaryNode())

+		{

+			TIntermUnary *unary = expression->getAsUnaryNode();

+

+			switch(unary->getOp())

+			{

+			case EOpAbs:

+			case EOpNegative:

+				return cost(unary->getOperand(), budget - 1);

+			default:

+				return -1;

+			}

+		}

+		else if(expression->getAsSelectionNode())

+		{

+			TIntermSelection *selection = expression->getAsSelectionNode();

+

+			if(selection->usesTernaryOperator())

+			{

+				TIntermTyped *condition = selection->getCondition();

+				TIntermNode *trueBlock = selection->getTrueBlock();

+				TIntermNode *falseBlock = selection->getFalseBlock();

+				TIntermConstantUnion *constantCondition = condition->getAsConstantUnion();

+

+				if(constantCondition)

+				{

+					bool trueCondition = constantCondition->getUnionArrayPointer()->getBConst();

+

+					if(trueCondition)

+					{

+						return cost(trueBlock, budget - 0);

+					}

+					else

+					{

+						return cost(falseBlock, budget - 0);

+					}

+				}

+				else

+				{

+					return cost(trueBlock, cost(falseBlock, budget - 2));

+				}

+			}

+		}

+

+		return -1;

+	}

+

+	const Function &OutputASM::findFunction(const TString &name)

+	{

+		for(unsigned int f = 0; f < functionArray.size(); f++)

+		{

+			if(functionArray[f].name == name)

+			{

+				return functionArray[f];

+			}

+		}

+

+		UNREACHABLE();

+		return functionArray[0];

+	}

+	

+	int OutputASM::temporaryRegister(TIntermTyped *temporary)

+	{

+		return allocate(temporaries, temporary);

+	}

+

+	int OutputASM::varyingRegister(TIntermTyped *varying)

+	{

+		int var = lookup(varyings, varying);

+

+		if(var == -1)

+		{

+			var = allocate(varyings, varying);

+			int componentCount = varying->getNominalSize();

+			int registerCount = varying->totalRegisterCount();

+

+			if(pixelShader && (var + registerCount) <= sw::PixelShader::MAX_INPUT_VARYINGS)

+			{

+				if(varying->getQualifier() == EvqPointCoord)

+				{

+					ASSERT(varying->isRegister());

+					if(componentCount >= 1) pixelShader->semantic[var][0] = sw::Shader::Semantic(sw::Shader::USAGE_TEXCOORD, var);

+					if(componentCount >= 2) pixelShader->semantic[var][1] = sw::Shader::Semantic(sw::Shader::USAGE_TEXCOORD, var);

+					if(componentCount >= 3) pixelShader->semantic[var][2] = sw::Shader::Semantic(sw::Shader::USAGE_TEXCOORD, var);

+					if(componentCount >= 4) pixelShader->semantic[var][3] = sw::Shader::Semantic(sw::Shader::USAGE_TEXCOORD, var);

+				}

+				else

+				{

+					for(int i = 0; i < varying->totalRegisterCount(); i++)

+					{

+						if(componentCount >= 1) pixelShader->semantic[var + i][0] = sw::Shader::Semantic(sw::Shader::USAGE_COLOR, var + i);

+						if(componentCount >= 2) pixelShader->semantic[var + i][1] = sw::Shader::Semantic(sw::Shader::USAGE_COLOR, var + i);

+						if(componentCount >= 3) pixelShader->semantic[var + i][2] = sw::Shader::Semantic(sw::Shader::USAGE_COLOR, var + i);

+						if(componentCount >= 4) pixelShader->semantic[var + i][3] = sw::Shader::Semantic(sw::Shader::USAGE_COLOR, var + i);

+					}

+				}

+			}

+			else if(vertexShader && (var + registerCount) <= sw::VertexShader::MAX_OUTPUT_VARYINGS)

+			{

+				if(varying->getQualifier() == EvqPosition)

+				{

+					ASSERT(varying->isRegister());

+					vertexShader->output[var][0] = sw::Shader::Semantic(sw::Shader::USAGE_POSITION, 0);

+					vertexShader->output[var][1] = sw::Shader::Semantic(sw::Shader::USAGE_POSITION, 0);

+					vertexShader->output[var][2] = sw::Shader::Semantic(sw::Shader::USAGE_POSITION, 0);

+					vertexShader->output[var][3] = sw::Shader::Semantic(sw::Shader::USAGE_POSITION, 0);

+					vertexShader->positionRegister = var;

+				}

+				else if(varying->getQualifier() == EvqPointSize)

+				{

+					ASSERT(varying->isRegister());

+					vertexShader->output[var][0] = sw::Shader::Semantic(sw::Shader::USAGE_PSIZE, 0);

+					vertexShader->output[var][1] = sw::Shader::Semantic(sw::Shader::USAGE_PSIZE, 0);

+					vertexShader->output[var][2] = sw::Shader::Semantic(sw::Shader::USAGE_PSIZE, 0);

+					vertexShader->output[var][3] = sw::Shader::Semantic(sw::Shader::USAGE_PSIZE, 0);

+					vertexShader->pointSizeRegister = var;

+				}

+				else

+				{

+					// Semantic indexes for user varyings will be assigned during program link to match the pixel shader

+				}

+			}

+			else UNREACHABLE();

+

+			declareVarying(varying, var);

+		}

+

+		return var;

+	}

+

+	void OutputASM::declareVarying(TIntermTyped *varying, int reg)

+	{

+		if(varying->getQualifier() != EvqPointCoord)   // gl_PointCoord does not need linking

+		{

+			const TType &type = varying->getType();

+			const char *name = varying->getAsSymbolNode()->getSymbol().c_str();

+			gl::VaryingList &activeVaryings = shaderObject->varyings;

+			

+			// Check if this varying has been declared before without having a register assigned

+			for(gl::VaryingList::iterator v = activeVaryings.begin(); v != activeVaryings.end(); v++)

+			{

+				if(v->name == name)

+				{

+					if(reg >= 0)

+					{

+						ASSERT(v->reg < 0 || v->reg == reg);

+						v->reg = reg;

+					}

+

+					return;

+				}

+			}

+			

+			activeVaryings.push_back(gl::Varying(glVariableType(type), name, varying->getArraySize(), reg, 0));

+		}

+	}

+

+	int OutputASM::uniformRegister(TIntermTyped *uniform)

+	{

+		const TType &type = uniform->getType();

+		ASSERT(!IsSampler(type.getBasicType()));

+		TIntermSymbol *symbol = uniform->getAsSymbolNode();

+		ASSERT(symbol);

+

+		if(symbol)

+		{

+			int index = lookup(uniforms, uniform);

+

+			if(index == -1)

+			{

+				index = allocate(uniforms, uniform);

+				const TString &name = symbol->getSymbol().c_str();

+

+				declareUniform(type, name, index);

+			}

+

+			return index;

+		}

+

+		return 0;

+	}

+

+	int OutputASM::attributeRegister(TIntermTyped *attribute)

+	{

+		ASSERT(!attribute->isArray());

+		ASSERT(attribute->getBasicType() == EbtFloat);

+

+		int index = lookup(attributes, attribute);

+

+		if(index == -1)

+		{

+			TIntermSymbol *symbol = attribute->getAsSymbolNode();

+			ASSERT(symbol);

+

+			if(symbol)

+			{

+				index = allocate(attributes, attribute);

+				const TType &type = attribute->getType();

+				int registerCount = attribute->totalRegisterCount();

+

+				if(vertexShader && (index + registerCount) <= sw::VertexShader::MAX_INPUT_ATTRIBUTES)

+				{

+					for(int i = 0; i < registerCount; i++)

+					{

+						vertexShader->input[index + i] = sw::Shader::Semantic(sw::Shader::USAGE_TEXCOORD, index + i);

+					}

+				}

+

+				ActiveAttributes &activeAttributes = shaderObject->activeAttributes;

+

+				const char *name = symbol->getSymbol().c_str();

+				activeAttributes.push_back(Attribute(glVariableType(type), name, 0, index));

+			}

+		}

+

+		return index;

+	}

+

+	int OutputASM::samplerRegister(TIntermTyped *sampler)

+	{

+		const TType &type = sampler->getType();

+		ASSERT(IsSampler(type.getBasicType()));

+		TIntermSymbol *symbol = sampler->getAsSymbolNode();

+		TIntermBinary *binary = sampler->getAsBinaryNode();

+

+		if(symbol)

+		{

+			int index = lookup(samplers, sampler);

+

+			if(index == -1)

+			{

+				index = allocate(samplers, sampler);

+				ActiveUniforms &activeUniforms = shaderObject->activeUniforms;

+				const char *name = symbol->getSymbol().c_str();

+				activeUniforms.push_back(Uniform(glVariableType(type), name, sampler->getArraySize(), index));

+

+				for(int i = 0; i < sampler->totalRegisterCount(); i++)

+				{

+					shader->declareSampler(index + i);

+				}

+			}

+

+			return index;

+		}

+		else if(binary)

+		{

+			ASSERT(binary->getOp() == EOpIndexDirect || binary->getOp() == EOpIndexIndirect);

+

+			return samplerRegister(binary->getLeft());   // Index added later

+		}

+		else UNREACHABLE();

+

+		return 0;

+	}

+

+	int OutputASM::lookup(VariableArray &list, TIntermTyped *variable)

+	{

+		for(unsigned int i = 0; i < list.size(); i++)

+		{

+			if(list[i] == variable)

+			{

+				return i;   // Pointer match

+			}

+		}

+

+		TIntermSymbol *varSymbol = variable->getAsSymbolNode();

+

+		if(varSymbol)

+		{

+			for(unsigned int i = 0; i < list.size(); i++)

+			{

+				if(list[i])

+				{

+					TIntermSymbol *listSymbol = list[i]->getAsSymbolNode();

+

+					if(listSymbol)

+					{

+						if(listSymbol->getId() == varSymbol->getId())

+						{

+							ASSERT(listSymbol->getSymbol() == varSymbol->getSymbol());

+							ASSERT(listSymbol->getType() == varSymbol->getType());

+							ASSERT(listSymbol->getQualifier() == varSymbol->getQualifier());

+

+							return i;

+						}

+					}

+				}

+			}

+		}

+

+		return -1;

+	}

+

+	int OutputASM::allocate(VariableArray &list, TIntermTyped *variable)

+	{

+		int index = lookup(list, variable);

+

+		if(index == -1)

+		{

+			unsigned int registerCount = variable->totalRegisterCount();

+

+			for(unsigned int i = 0; i < list.size(); i++)

+			{

+				if(list[i] == 0)

+				{

+					unsigned int j = 1;

+					for( ; j < registerCount && (i + j) < list.size(); j++)

+					{

+						if(list[i + j] != 0)

+						{

+							break;

+						}

+					}

+

+					if(j == registerCount)   // Found free slots

+					{

+						for(unsigned int j = 0; j < registerCount; j++)

+						{

+							list[i + j] = variable;

+						}

+

+						return i;

+					}

+				}

+			}

+

+			index = list.size();

+

+			for(unsigned int i = 0; i < registerCount; i++)

+			{

+				list.push_back(variable);

+			}

+		}

+

+		return index;

+	}

+

+	void OutputASM::free(VariableArray &list, TIntermTyped *variable)

+	{

+		int index = lookup(list, variable);

+

+		if(index >= 0)

+		{

+			list[index] = 0;

+		}

+	}

+

+	void OutputASM::declareUniform(const TType &type, const TString &name, int index)

+	{

+		const TTypeList *structure = type.getStruct();

+		ActiveUniforms &activeUniforms = shaderObject->activeUniforms;

+

+		if(!structure)

+		{

+			activeUniforms.push_back(Uniform(glVariableType(type), name.c_str(), type.getArraySize(), index));

+		}

+		else

+		{

+			if(type.isArray())

+			{

+				int elementIndex = index;

+

+				for(int i = 0; i < type.getArraySize(); i++)

+				{

+					for(size_t j = 0; j < structure->size(); j++)

+					{

+						const TType &fieldType = *(*structure)[j].type;

+						const TString &fieldName = fieldType.getFieldName();

+

+						const TString uniformName = name + "[" + str(i) + "]." + fieldName;

+						declareUniform(fieldType, uniformName, elementIndex);

+						elementIndex += fieldType.totalRegisterCount();

+					}

+				}

+			}

+			else

+			{

+				int fieldIndex = index;

+

+				for(size_t i = 0; i < structure->size(); i++)

+				{

+					const TType &fieldType = *(*structure)[i].type;

+					const TString &fieldName = fieldType.getFieldName();

+

+					const TString uniformName = name + "." + fieldName;

+					declareUniform(fieldType, uniformName, fieldIndex);

+					fieldIndex += fieldType.totalRegisterCount();

+				}

+			}

+		}

+	}

+

+	GLenum OutputASM::glVariableType(const TType &type)

+	{

+		if(type.getBasicType() == EbtFloat)

+		{

+			if(type.isScalar())

+			{

+				return GL_FLOAT;

+			}

+			else if(type.isVector())

+			{

+				switch(type.getNominalSize())

+				{

+				case 2: return GL_FLOAT_VEC2;

+				case 3: return GL_FLOAT_VEC3;

+				case 4: return GL_FLOAT_VEC4;

+				default: UNREACHABLE();

+				}

+			}

+			else if(type.isMatrix())

+			{

+				switch(type.getNominalSize())

+				{

+				case 2: return GL_FLOAT_MAT2;

+				case 3: return GL_FLOAT_MAT3;

+				case 4: return GL_FLOAT_MAT4;

+				default: UNREACHABLE();

+				}

+			}

+			else UNREACHABLE();

+		}

+		else if(type.getBasicType() == EbtInt)

+		{

+			if(type.isScalar())

+			{

+				return GL_INT;

+			}

+			else if(type.isVector())

+			{

+				switch(type.getNominalSize())

+				{

+				case 2: return GL_INT_VEC2;

+				case 3: return GL_INT_VEC3;

+				case 4: return GL_INT_VEC4;

+				default: UNREACHABLE();

+				}

+			}

+			else UNREACHABLE();

+		}

+		else if(type.getBasicType() == EbtBool)

+		{

+			if(type.isScalar())

+			{

+				return GL_BOOL;

+			}

+			else if(type.isVector())

+			{

+				switch(type.getNominalSize())

+				{

+				case 2: return GL_BOOL_VEC2;

+				case 3: return GL_BOOL_VEC3;

+				case 4: return GL_BOOL_VEC4;

+				default: UNREACHABLE();

+				}

+			}

+			else UNREACHABLE();

+		}

+		else if(type.getBasicType() == EbtSampler2D)

+		{

+			return GL_SAMPLER_2D;

+		}

+		else if(type.getBasicType() == EbtSamplerCube)

+		{

+			return GL_SAMPLER_CUBE;

+		}

+		else UNREACHABLE();

+

+		return GL_NONE;

+	}

+

+	int OutputASM::dim(TIntermNode *v)

+	{

+		TIntermTyped *vector = v->getAsTyped();

+		ASSERT(vector && vector->isRegister());

+		return vector->getNominalSize();

+	}

+

+	int OutputASM::dim2(TIntermNode *m)

+	{

+		TIntermTyped *matrix = m->getAsTyped();

+		ASSERT(matrix && matrix->isMatrix() && !matrix->isArray());

+		return matrix->getNominalSize();

+	}

+}

diff --git a/src/GLES2/compiler/OutputASM.h b/src/GLES2/compiler/OutputASM.h
new file mode 100644
index 0000000..c07864f
--- /dev/null
+++ b/src/GLES2/compiler/OutputASM.h
@@ -0,0 +1,162 @@
+// SwiftShader Software Renderer

+//

+// Copyright(c) 2005-2013 TransGaming Inc.

+//

+// All rights reserved. No part of this software may be copied, distributed, transmitted,

+// transcribed, stored in a retrieval system, translated into any human or computer

+// language by any means, or disclosed to third parties without the explicit written

+// agreement of TransGaming Inc. Without such an agreement, no rights or licenses, express

+// or implied, including but not limited to any patent rights, are granted to you.

+//

+

+#ifndef COMPILER_OUTPUTASM_H_

+#define COMPILER_OUTPUTASM_H_

+

+#include "intermediate.h"

+#include "ParseHelper.h"

+#include "Shader/PixelShader.hpp"

+#include "Shader/VertexShader.hpp"

+

+#define GL_APICALL

+#include <GLES2/gl2.h>

+

+#include <list>

+#include <set>

+#include <map>

+

+namespace gl

+{

+	class Shader;

+}

+

+namespace sh

+{

+	struct Uniform

+	{

+		Uniform(GLenum type, const std::string &name, int arraySize, int registerIndex);

+

+		GLenum type;

+		std::string name;

+		int arraySize;

+	

+		int registerIndex;

+	};

+

+	typedef std::vector<Uniform> ActiveUniforms;

+

+	struct Attribute

+	{

+		Attribute();

+		Attribute(GLenum type, const std::string &name, int arraySize, int registerIndex);

+

+		GLenum type;

+		std::string name;

+		int arraySize;

+	

+		int registerIndex;

+	};

+

+	struct Function

+	{

+		Function(int label, const char *name, TIntermSequence *arg, TIntermTyped *ret) : label(label), name(name), arg(arg), ret(ret)

+		{

+		}

+

+		Function(int label, const TString &name, TIntermSequence *arg, TIntermTyped *ret) : label(label), name(name), arg(arg), ret(ret)

+		{

+		}

+

+		int label;

+		TString name;

+		TIntermSequence *arg;

+		TIntermTyped *ret;

+	};

+	

+	typedef sw::Shader::Instruction Instruction;

+	typedef std::vector<Attribute> ActiveAttributes;

+

+	class Temporary;

+

+	class OutputASM : public TIntermTraverser

+	{

+	public:

+		explicit OutputASM(TParseContext &context, gl::Shader *shaderObject);

+		~OutputASM();

+

+		void output();

+

+		void freeTemporary(Temporary *temporary);

+

+	protected:

+		enum Scope

+		{

+			GLOBAL,

+			FUNCTION

+		};

+

+		void emitShader(Scope scope);

+

+		// Visit AST nodes and output their code to the body stream

+		virtual void visitSymbol(TIntermSymbol*);

+		virtual bool visitBinary(Visit visit, TIntermBinary*);

+		virtual bool visitUnary(Visit visit, TIntermUnary*);

+		virtual bool visitSelection(Visit visit, TIntermSelection*);

+		virtual bool visitAggregate(Visit visit, TIntermAggregate*);

+		virtual bool visitLoop(Visit visit, TIntermLoop*);

+		virtual bool visitBranch(Visit visit, TIntermBranch*);

+

+		Instruction *emit(sw::Shader::Opcode op, TIntermTyped *dst = 0, TIntermNode *src0 = 0, TIntermNode *src1 = 0, TIntermNode *src2 = 0);

+		void emitAssign(sw::Shader::Opcode op, TIntermTyped *result, TIntermTyped *lhs, TIntermTyped *src0, TIntermTyped *src1 = 0);

+		void emitCmp(sw::Shader::Control cmpOp, TIntermTyped *dst, TIntermNode *left, TIntermNode *right, int index = 0);

+		void argument(sw::Shader::SourceParameter &parameter, TIntermNode *argument, int index = 0);

+		void copy(TIntermTyped *dst, TIntermNode *src, int offset = 0);

+		void assignLvalue(TIntermTyped *dst, TIntermNode *src);

+		int lvalue(sw::Shader::DestinationParameter &dst, Temporary &address, TIntermTyped *node);

+		sw::Shader::ParameterType registerType(TIntermTyped *operand);

+		int registerIndex(TIntermTyped *operand);

+		int writeMask(TIntermTyped *destination, int index = 0);

+		bool trivial(TIntermTyped *expression, int budget);   // Fast to compute and no side effects

+		int cost(TIntermNode *expression, int budget);

+		const Function &findFunction(const TString &name);

+

+		int temporaryRegister(TIntermTyped *temporary);

+		int varyingRegister(TIntermTyped *varying);

+		void declareVarying(TIntermTyped *varying, int reg);

+		int uniformRegister(TIntermTyped *uniform);

+		int attributeRegister(TIntermTyped *attribute);

+		int samplerRegister(TIntermTyped *sampler);

+

+		typedef std::vector<TIntermTyped*> VariableArray;

+

+		int lookup(VariableArray &list, TIntermTyped *variable);

+		int allocate(VariableArray &list, TIntermTyped *variable);

+		void free(VariableArray &list, TIntermTyped *variable);

+

+		void declareUniform(const TType &type, const TString &name, int index);

+		GLenum glVariableType(const TType &type);

+

+		static int dim(TIntermNode *v);

+		static int dim2(TIntermNode *m);

+

+		gl::Shader *const shaderObject;

+		sw::Shader *shader;

+		sw::PixelShader *pixelShader;

+		sw::VertexShader *vertexShader;

+

+		VariableArray temporaries;

+		VariableArray uniforms;

+		VariableArray varyings;

+		VariableArray attributes;

+		VariableArray samplers;

+

+		Scope emitScope;

+		Scope currentScope;

+

+		int currentFunction;

+		std::vector<Function> functionArray;

+

+		TParseContext &mContext;

+	};

+}

+

+#endif   // COMPILER_OUTPUTASM_H_

diff --git a/src/GLES2/compiler/ParseHelper.cpp b/src/GLES2/compiler/ParseHelper.cpp
new file mode 100644
index 0000000..2107300
--- /dev/null
+++ b/src/GLES2/compiler/ParseHelper.cpp
@@ -0,0 +1,1524 @@
+//
+// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "compiler/ParseHelper.h"
+
+#include <stdarg.h>
+#include <stdio.h>
+
+#include "compiler/glslang.h"
+#include "compiler/preprocessor/SourceLocation.h"
+
+///////////////////////////////////////////////////////////////////////
+//
+// Sub- vector and matrix fields
+//
+////////////////////////////////////////////////////////////////////////
+
+//
+// Look at a '.' field selector string and change it into offsets
+// for a vector.
+//
+bool TParseContext::parseVectorFields(const TString& compString, int vecSize, TVectorFields& fields, int line)
+{
+    fields.num = (int) compString.size();
+    if (fields.num > 4) {
+        error(line, "illegal vector field selection", compString.c_str());
+        return false;
+    }
+
+    enum {
+        exyzw,
+        ergba,
+        estpq,
+    } fieldSet[4];
+
+    for (int i = 0; i < fields.num; ++i) {
+        switch (compString[i])  {
+        case 'x': 
+            fields.offsets[i] = 0;
+            fieldSet[i] = exyzw;
+            break;
+        case 'r': 
+            fields.offsets[i] = 0;
+            fieldSet[i] = ergba;
+            break;
+        case 's':
+            fields.offsets[i] = 0;
+            fieldSet[i] = estpq;
+            break;
+        case 'y': 
+            fields.offsets[i] = 1;
+            fieldSet[i] = exyzw;
+            break;
+        case 'g': 
+            fields.offsets[i] = 1;
+            fieldSet[i] = ergba;
+            break;
+        case 't':
+            fields.offsets[i] = 1;
+            fieldSet[i] = estpq;
+            break;
+        case 'z': 
+            fields.offsets[i] = 2;
+            fieldSet[i] = exyzw;
+            break;
+        case 'b': 
+            fields.offsets[i] = 2;
+            fieldSet[i] = ergba;
+            break;
+        case 'p':
+            fields.offsets[i] = 2;
+            fieldSet[i] = estpq;
+            break;
+        
+        case 'w': 
+            fields.offsets[i] = 3;
+            fieldSet[i] = exyzw;
+            break;
+        case 'a': 
+            fields.offsets[i] = 3;
+            fieldSet[i] = ergba;
+            break;
+        case 'q':
+            fields.offsets[i] = 3;
+            fieldSet[i] = estpq;
+            break;
+        default:
+            error(line, "illegal vector field selection", compString.c_str());
+            return false;
+        }
+    }
+
+    for (int i = 0; i < fields.num; ++i) {
+        if (fields.offsets[i] >= vecSize) {
+            error(line, "vector field selection out of range",  compString.c_str());
+            return false;
+        }
+
+        if (i > 0) {
+            if (fieldSet[i] != fieldSet[i-1]) {
+                error(line, "illegal - vector component fields not from the same set", compString.c_str());
+                return false;
+            }
+        }
+    }
+
+    return true;
+}
+
+
+//
+// Look at a '.' field selector string and change it into offsets
+// for a matrix.
+//
+bool TParseContext::parseMatrixFields(const TString& compString, int matSize, TMatrixFields& fields, int line)
+{
+    fields.wholeRow = false;
+    fields.wholeCol = false;
+    fields.row = -1;
+    fields.col = -1;
+
+    if (compString.size() != 2) {
+        error(line, "illegal length of matrix field selection", compString.c_str());
+        return false;
+    }
+
+    if (compString[0] == '_') {
+        if (compString[1] < '0' || compString[1] > '3') {
+            error(line, "illegal matrix field selection", compString.c_str());
+            return false;
+        }
+        fields.wholeCol = true;
+        fields.col = compString[1] - '0';
+    } else if (compString[1] == '_') {
+        if (compString[0] < '0' || compString[0] > '3') {
+            error(line, "illegal matrix field selection", compString.c_str());
+            return false;
+        }
+        fields.wholeRow = true;
+        fields.row = compString[0] - '0';
+    } else {
+        if (compString[0] < '0' || compString[0] > '3' ||
+            compString[1] < '0' || compString[1] > '3') {
+            error(line, "illegal matrix field selection", compString.c_str());
+            return false;
+        }
+        fields.row = compString[0] - '0';
+        fields.col = compString[1] - '0';
+    }
+
+    if (fields.row >= matSize || fields.col >= matSize) {
+        error(line, "matrix field selection out of range", compString.c_str());
+        return false;
+    }
+
+    return true;
+}
+
+///////////////////////////////////////////////////////////////////////
+//
+// Errors
+//
+////////////////////////////////////////////////////////////////////////
+
+//
+// Track whether errors have occurred.
+//
+void TParseContext::recover()
+{
+}
+
+//
+// Used by flex/bison to output all syntax and parsing errors.
+//
+void TParseContext::error(TSourceLoc loc,
+                          const char* reason, const char* token, 
+                          const char* extraInfo)
+{
+    pp::SourceLocation srcLoc;
+    DecodeSourceLoc(loc, &srcLoc.file, &srcLoc.line);
+    diagnostics.writeInfo(pp::Diagnostics::PP_ERROR,
+                          srcLoc, reason, token, extraInfo);
+
+}
+
+void TParseContext::warning(TSourceLoc loc,
+                            const char* reason, const char* token,
+                            const char* extraInfo) {
+    pp::SourceLocation srcLoc;
+    DecodeSourceLoc(loc, &srcLoc.file, &srcLoc.line);
+    diagnostics.writeInfo(pp::Diagnostics::PP_WARNING,
+                          srcLoc, reason, token, extraInfo);
+}
+
+void TParseContext::trace(const char* str)
+{
+    diagnostics.writeDebug(str);
+}
+
+//
+// Same error message for all places assignments don't work.
+//
+void TParseContext::assignError(int line, const char* op, TString left, TString right)
+{
+    std::stringstream extraInfoStream;
+    extraInfoStream << "cannot convert from '" << right << "' to '" << left << "'";
+    std::string extraInfo = extraInfoStream.str();
+    error(line, "", op, extraInfo.c_str());
+}
+
+//
+// Same error message for all places unary operations don't work.
+//
+void TParseContext::unaryOpError(int line, const char* op, TString operand)
+{
+    std::stringstream extraInfoStream;
+    extraInfoStream << "no operation '" << op << "' exists that takes an operand of type " << operand 
+                    << " (or there is no acceptable conversion)";
+    std::string extraInfo = extraInfoStream.str();
+    error(line, " wrong operand type", op, extraInfo.c_str());
+}
+
+//
+// Same error message for all binary operations don't work.
+//
+void TParseContext::binaryOpError(int line, const char* op, TString left, TString right)
+{
+    std::stringstream extraInfoStream;
+    extraInfoStream << "no operation '" << op << "' exists that takes a left-hand operand of type '" << left 
+                    << "' and a right operand of type '" << right << "' (or there is no acceptable conversion)";
+    std::string extraInfo = extraInfoStream.str();
+    error(line, " wrong operand types ", op, extraInfo.c_str()); 
+}
+
+bool TParseContext::precisionErrorCheck(int line, TPrecision precision, TBasicType type){
+    if (!checksPrecisionErrors)
+        return false;
+    switch( type ){
+    case EbtFloat:
+        if( precision == EbpUndefined ){
+            error( line, "No precision specified for (float)", "" );
+            return true;
+        }
+        break;
+    case EbtInt:
+        if( precision == EbpUndefined ){
+            error( line, "No precision specified (int)", "" );
+            return true;
+        }
+        break;
+    default:
+        return false;
+    }
+    return false;
+}
+
+//
+// Both test and if necessary, spit out an error, to see if the node is really
+// an l-value that can be operated on this way.
+//
+// Returns true if the was an error.
+//
+bool TParseContext::lValueErrorCheck(int line, const char* op, TIntermTyped* node)
+{
+    TIntermSymbol* symNode = node->getAsSymbolNode();
+    TIntermBinary* binaryNode = node->getAsBinaryNode();
+
+    if (binaryNode) {
+        bool errorReturn;
+
+        switch(binaryNode->getOp()) {
+        case EOpIndexDirect:
+        case EOpIndexIndirect:
+        case EOpIndexDirectStruct:
+            return lValueErrorCheck(line, op, binaryNode->getLeft());
+        case EOpVectorSwizzle:
+            errorReturn = lValueErrorCheck(line, op, binaryNode->getLeft());
+            if (!errorReturn) {
+                int offset[4] = {0,0,0,0};
+
+                TIntermTyped* rightNode = binaryNode->getRight();
+                TIntermAggregate *aggrNode = rightNode->getAsAggregate();
+                
+                for (TIntermSequence::iterator p = aggrNode->getSequence().begin(); 
+                                               p != aggrNode->getSequence().end(); p++) {
+                    int value = (*p)->getAsTyped()->getAsConstantUnion()->getUnionArrayPointer()->getIConst();
+                    offset[value]++;     
+                    if (offset[value] > 1) {
+                        error(line, " l-value of swizzle cannot have duplicate components", op);
+
+                        return true;
+                    }
+                }
+            } 
+
+            return errorReturn;
+        default: 
+            break;
+        }
+        error(line, " l-value required", op);
+
+        return true;
+    }
+
+
+    const char* symbol = 0;
+    if (symNode != 0)
+        symbol = symNode->getSymbol().c_str();
+
+    const char* message = 0;
+    switch (node->getQualifier()) {
+    case EvqConst:          message = "can't modify a const";        break;
+    case EvqConstReadOnly:  message = "can't modify a const";        break;
+    case EvqAttribute:      message = "can't modify an attribute";   break;
+    case EvqUniform:        message = "can't modify a uniform";      break;
+    case EvqVaryingIn:      message = "can't modify a varying";      break;
+    case EvqInput:          message = "can't modify an input";       break;
+    case EvqFragCoord:      message = "can't modify gl_FragCoord";   break;
+    case EvqFrontFacing:    message = "can't modify gl_FrontFacing"; break;
+    case EvqPointCoord:     message = "can't modify gl_PointCoord";  break;
+    default:
+
+        //
+        // Type that can't be written to?
+        //
+        switch (node->getBasicType()) {
+        case EbtSampler2D:
+        case EbtSamplerCube:
+            message = "can't modify a sampler";
+            break;
+        case EbtVoid:
+            message = "can't modify void";
+            break;
+        default: 
+            break;
+        }
+    }
+
+    if (message == 0 && binaryNode == 0 && symNode == 0) {
+        error(line, " l-value required", op);
+
+        return true;
+    }
+
+
+    //
+    // Everything else is okay, no error.
+    //
+    if (message == 0)
+        return false;
+
+    //
+    // If we get here, we have an error and a message.
+    //
+    if (symNode) {
+        std::stringstream extraInfoStream;
+        extraInfoStream << "\"" << symbol << "\" (" << message << ")";
+        std::string extraInfo = extraInfoStream.str();
+        error(line, " l-value required", op, extraInfo.c_str());
+    }
+    else {
+        std::stringstream extraInfoStream;
+        extraInfoStream << "(" << message << ")";
+        std::string extraInfo = extraInfoStream.str();
+        error(line, " l-value required", op, extraInfo.c_str());
+    }
+
+    return true;
+}
+
+//
+// Both test, and if necessary spit out an error, to see if the node is really
+// a constant.
+//
+// Returns true if the was an error.
+//
+bool TParseContext::constErrorCheck(TIntermTyped* node)
+{
+    if (node->getQualifier() == EvqConst)
+        return false;
+
+    error(node->getLine(), "constant expression required", "");
+
+    return true;
+}
+
+//
+// Both test, and if necessary spit out an error, to see if the node is really
+// an integer.
+//
+// Returns true if the was an error.
+//
+bool TParseContext::integerErrorCheck(TIntermTyped* node, const char* token)
+{
+    if (node->getBasicType() == EbtInt && node->getNominalSize() == 1)
+        return false;
+
+    error(node->getLine(), "integer expression required", token);
+
+    return true;
+}
+
+//
+// Both test, and if necessary spit out an error, to see if we are currently
+// globally scoped.
+//
+// Returns true if the was an error.
+//
+bool TParseContext::globalErrorCheck(int line, bool global, const char* token)
+{
+    if (global)
+        return false;
+
+    error(line, "only allowed at global scope", token);
+
+    return true;
+}
+
+//
+// For now, keep it simple:  if it starts "gl_", it's reserved, independent
+// of scope.  Except, if the symbol table is at the built-in push-level,
+// which is when we are parsing built-ins.
+// Also checks for "webgl_" and "_webgl_" reserved identifiers if parsing a
+// webgl shader.
+//
+// Returns true if there was an error.
+//
+bool TParseContext::reservedErrorCheck(int line, const TString& identifier)
+{
+    static const char* reservedErrMsg = "reserved built-in name";
+    if (!symbolTable.atBuiltInLevel()) {
+        if (identifier.compare(0, 3, "gl_") == 0) {
+            error(line, reservedErrMsg, "gl_");
+            return true;
+        }
+        if (shaderSpec == SH_WEBGL_SPEC) {
+            if (identifier.compare(0, 6, "webgl_") == 0) {
+                error(line, reservedErrMsg, "webgl_");
+                return true;
+            }
+            if (identifier.compare(0, 7, "_webgl_") == 0) {
+                error(line, reservedErrMsg, "_webgl_");
+                return true;
+            }
+        }
+        if (identifier.find("__") != TString::npos) {
+            error(line, "identifiers containing two consecutive underscores (__) are reserved as possible future keywords", identifier.c_str());
+            return true;
+        }
+    }
+
+    return false;
+}
+
+//
+// Make sure there is enough data provided to the constructor to build
+// something of the type of the constructor.  Also returns the type of
+// the constructor.
+//
+// Returns true if there was an error in construction.
+//
+bool TParseContext::constructorErrorCheck(int line, TIntermNode* node, TFunction& function, TOperator op, TType* type)
+{
+    *type = function.getReturnType();
+
+    bool constructingMatrix = false;
+    switch(op) {
+    case EOpConstructMat2:
+    case EOpConstructMat3:
+    case EOpConstructMat4:
+        constructingMatrix = true;
+        break;
+    default: 
+        break;
+    }
+
+    //
+    // Note: It's okay to have too many components available, but not okay to have unused
+    // arguments.  'full' will go to true when enough args have been seen.  If we loop
+    // again, there is an extra argument, so 'overfull' will become true.
+    //
+
+    int size = 0;
+    bool constType = true;
+    bool full = false;
+    bool overFull = false;
+    bool matrixInMatrix = false;
+    bool arrayArg = false;
+    for (int i = 0; i < function.getParamCount(); ++i) {
+        const TParameter& param = function.getParam(i);
+        size += param.type->getObjectSize();
+        
+        if (constructingMatrix && param.type->isMatrix())
+            matrixInMatrix = true;
+        if (full)
+            overFull = true;
+        if (op != EOpConstructStruct && !type->isArray() && size >= type->getObjectSize())
+            full = true;
+        if (param.type->getQualifier() != EvqConst)
+            constType = false;
+        if (param.type->isArray())
+            arrayArg = true;
+    }
+    
+    if (constType)
+        type->setQualifier(EvqConst);
+
+    if (type->isArray() && type->getArraySize() != function.getParamCount()) {
+        error(line, "array constructor needs one argument per array element", "constructor");
+        return true;
+    }
+
+    if (arrayArg && op != EOpConstructStruct) {
+        error(line, "constructing from a non-dereferenced array", "constructor");
+        return true;
+    }
+
+    if (matrixInMatrix && !type->isArray()) {
+        if (function.getParamCount() != 1) {
+          error(line, "constructing matrix from matrix can only take one argument", "constructor");
+          return true;
+        }
+    }
+
+    if (overFull) {
+        error(line, "too many arguments", "constructor");
+        return true;
+    }
+    
+    if (op == EOpConstructStruct && !type->isArray() && int(type->getStruct()->size()) != function.getParamCount()) {
+        error(line, "Number of constructor parameters does not match the number of structure fields", "constructor");
+        return true;
+    }
+
+    if (!type->isMatrix() || !matrixInMatrix) {
+        if ((op != EOpConstructStruct && size != 1 && size < type->getObjectSize()) ||
+            (op == EOpConstructStruct && size < type->getObjectSize())) {
+            error(line, "not enough data provided for construction", "constructor");
+            return true;
+        }
+    }
+
+    TIntermTyped *typed = node ? node->getAsTyped() : 0;
+    if (typed == 0) {
+        error(line, "constructor argument does not have a type", "constructor");
+        return true;
+    }
+    if (op != EOpConstructStruct && IsSampler(typed->getBasicType())) {
+        error(line, "cannot convert a sampler", "constructor");
+        return true;
+    }
+    if (typed->getBasicType() == EbtVoid) {
+        error(line, "cannot convert a void", "constructor");
+        return true;
+    }
+
+    return false;
+}
+
+// This function checks to see if a void variable has been declared and raise an error message for such a case
+//
+// returns true in case of an error
+//
+bool TParseContext::voidErrorCheck(int line, const TString& identifier, const TPublicType& pubType)
+{
+    if (pubType.type == EbtVoid) {
+        error(line, "illegal use of type 'void'", identifier.c_str());
+        return true;
+    } 
+
+    return false;
+}
+
+// This function checks to see if the node (for the expression) contains a scalar boolean expression or not
+//
+// returns true in case of an error
+//
+bool TParseContext::boolErrorCheck(int line, const TIntermTyped* type)
+{
+    if (type->getBasicType() != EbtBool || type->isArray() || type->isMatrix() || type->isVector()) {
+        error(line, "boolean expression expected", "");
+        return true;
+    } 
+
+    return false;
+}
+
+// This function checks to see if the node (for the expression) contains a scalar boolean expression or not
+//
+// returns true in case of an error
+//
+bool TParseContext::boolErrorCheck(int line, const TPublicType& pType)
+{
+    if (pType.type != EbtBool || pType.array || pType.matrix || (pType.size > 1)) {
+        error(line, "boolean expression expected", "");
+        return true;
+    } 
+
+    return false;
+}
+
+bool TParseContext::samplerErrorCheck(int line, const TPublicType& pType, const char* reason)
+{
+    if (pType.type == EbtStruct) {
+        if (containsSampler(*pType.userDef)) {
+            error(line, reason, getBasicString(pType.type), "(structure contains a sampler)");
+        
+            return true;
+        }
+        
+        return false;
+    } else if (IsSampler(pType.type)) {
+        error(line, reason, getBasicString(pType.type));
+
+        return true;
+    }
+
+    return false;
+}
+
+bool TParseContext::structQualifierErrorCheck(int line, const TPublicType& pType)
+{
+    if ((pType.qualifier == EvqVaryingIn || pType.qualifier == EvqVaryingOut || pType.qualifier == EvqAttribute) &&
+        pType.type == EbtStruct) {
+        error(line, "cannot be used with a structure", getQualifierString(pType.qualifier));
+        
+        return true;
+    }
+
+    if (pType.qualifier != EvqUniform && samplerErrorCheck(line, pType, "samplers must be uniform"))
+        return true;
+
+    return false;
+}
+
+bool TParseContext::parameterSamplerErrorCheck(int line, TQualifier qualifier, const TType& type)
+{
+    if ((qualifier == EvqOut || qualifier == EvqInOut) && 
+             type.getBasicType() != EbtStruct && IsSampler(type.getBasicType())) {
+        error(line, "samplers cannot be output parameters", type.getBasicString());
+        return true;
+    }
+
+    return false;
+}
+
+bool TParseContext::containsSampler(TType& type)
+{
+    if (IsSampler(type.getBasicType()))
+        return true;
+
+    if (type.getBasicType() == EbtStruct) {
+        TTypeList& structure = *type.getStruct();
+        for (unsigned int i = 0; i < structure.size(); ++i) {
+            if (containsSampler(*structure[i].type))
+                return true;
+        }
+    }
+
+    return false;
+}
+
+//
+// Do size checking for an array type's size.
+//
+// Returns true if there was an error.
+//
+bool TParseContext::arraySizeErrorCheck(int line, TIntermTyped* expr, int& size)
+{
+    TIntermConstantUnion* constant = expr->getAsConstantUnion();
+    if (constant == 0 || constant->getBasicType() != EbtInt) {
+        error(line, "array size must be a constant integer expression", "");
+        return true;
+    }
+
+    size = constant->getUnionArrayPointer()->getIConst();
+
+    if (size <= 0) {
+        error(line, "array size must be a positive integer", "");
+        size = 1;
+        return true;
+    }
+
+    return false;
+}
+
+//
+// See if this qualifier can be an array.
+//
+// Returns true if there is an error.
+//
+bool TParseContext::arrayQualifierErrorCheck(int line, TPublicType type)
+{
+    if ((type.qualifier == EvqAttribute) || (type.qualifier == EvqConst)) {
+        error(line, "cannot declare arrays of this qualifier", TType(type).getCompleteString().c_str());
+        return true;
+    }
+
+    return false;
+}
+
+//
+// See if this type can be an array.
+//
+// Returns true if there is an error.
+//
+bool TParseContext::arrayTypeErrorCheck(int line, TPublicType type)
+{
+    //
+    // Can the type be an array?
+    //
+    if (type.array) {
+        error(line, "cannot declare arrays of arrays", TType(type).getCompleteString().c_str());
+        return true;
+    }
+
+    return false;
+}
+
+//
+// Do all the semantic checking for declaring an array, with and 
+// without a size, and make the right changes to the symbol table.
+//
+// size == 0 means no specified size.
+//
+// Returns true if there was an error.
+//
+bool TParseContext::arrayErrorCheck(int line, TString& identifier, TPublicType type, TVariable*& variable)
+{
+    //
+    // Don't check for reserved word use until after we know it's not in the symbol table,
+    // because reserved arrays can be redeclared.
+    //
+
+    bool builtIn = false; 
+    bool sameScope = false;
+    TSymbol* symbol = symbolTable.find(identifier, &builtIn, &sameScope);
+    if (symbol == 0 || !sameScope) {
+        if (reservedErrorCheck(line, identifier))
+            return true;
+        
+        variable = new TVariable(&identifier, TType(type));
+
+        if (type.arraySize)
+            variable->getType().setArraySize(type.arraySize);
+
+        if (! symbolTable.insert(*variable)) {
+            delete variable;
+            error(line, "INTERNAL ERROR inserting new symbol", identifier.c_str());
+            return true;
+        }
+    } else {
+        if (! symbol->isVariable()) {
+            error(line, "variable expected", identifier.c_str());
+            return true;
+        }
+
+        variable = static_cast<TVariable*>(symbol);
+        if (! variable->getType().isArray()) {
+            error(line, "redeclaring non-array as array", identifier.c_str());
+            return true;
+        }
+        if (variable->getType().getArraySize() > 0) {
+            error(line, "redeclaration of array with size", identifier.c_str());
+            return true;
+        }
+        
+        if (! variable->getType().sameElementType(TType(type))) {
+            error(line, "redeclaration of array with a different type", identifier.c_str());
+            return true;
+        }
+
+        TType* t = variable->getArrayInformationType();
+        while (t != 0) {
+            if (t->getMaxArraySize() > type.arraySize) {
+                error(line, "higher index value already used for the array", identifier.c_str());
+                return true;
+            }
+            t->setArraySize(type.arraySize);
+            t = t->getArrayInformationType();
+        }
+
+        if (type.arraySize)
+            variable->getType().setArraySize(type.arraySize);
+    } 
+
+    if (voidErrorCheck(line, identifier, type))
+        return true;
+
+    return false;
+}
+
+bool TParseContext::arraySetMaxSize(TIntermSymbol *node, TType* type, int size, bool updateFlag, TSourceLoc line)
+{
+    bool builtIn = false;
+    TSymbol* symbol = symbolTable.find(node->getSymbol(), &builtIn);
+    if (symbol == 0) {
+        error(line, " undeclared identifier", node->getSymbol().c_str());
+        return true;
+    }
+    TVariable* variable = static_cast<TVariable*>(symbol);
+
+    type->setArrayInformationType(variable->getArrayInformationType());
+    variable->updateArrayInformationType(type);
+
+    // special casing to test index value of gl_FragData. If the accessed index is >= gl_MaxDrawBuffers
+    // its an error
+    if (node->getSymbol() == "gl_FragData") {
+        TSymbol* fragData = symbolTable.find("gl_MaxDrawBuffers", &builtIn);
+        ASSERT(fragData);
+
+        int fragDataValue = static_cast<TVariable*>(fragData)->getConstPointer()[0].getIConst();
+        if (fragDataValue <= size) {
+            error(line, "", "[", "gl_FragData can only have a max array size of up to gl_MaxDrawBuffers");
+            return true;
+        }
+    }
+
+    // we dont want to update the maxArraySize when this flag is not set, we just want to include this 
+    // node type in the chain of node types so that its updated when a higher maxArraySize comes in.
+    if (!updateFlag)
+        return false;
+
+    size++;
+    variable->getType().setMaxArraySize(size);
+    type->setMaxArraySize(size);
+    TType* tt = type;
+
+    while(tt->getArrayInformationType() != 0) {
+        tt = tt->getArrayInformationType();
+        tt->setMaxArraySize(size);
+    }
+
+    return false;
+}
+
+//
+// Enforce non-initializer type/qualifier rules.
+//
+// Returns true if there was an error.
+//
+bool TParseContext::nonInitConstErrorCheck(int line, TString& identifier, TPublicType& type, bool array)
+{
+    if (type.qualifier == EvqConst)
+    {
+        // Make the qualifier make sense.
+        type.qualifier = EvqTemporary;
+        
+        if (array)
+        {
+            error(line, "arrays may not be declared constant since they cannot be initialized", identifier.c_str());
+        }
+        else if (type.isStructureContainingArrays())
+        {
+            error(line, "structures containing arrays may not be declared constant since they cannot be initialized", identifier.c_str());
+        }
+        else
+        {
+            error(line, "variables with qualifier 'const' must be initialized", identifier.c_str());
+        }
+
+        return true;
+    }
+
+    return false;
+}
+
+//
+// Do semantic checking for a variable declaration that has no initializer,
+// and update the symbol table.
+//
+// Returns true if there was an error.
+//
+bool TParseContext::nonInitErrorCheck(int line, TString& identifier, TPublicType& type, TVariable*& variable)
+{
+    if (reservedErrorCheck(line, identifier))
+        recover();
+
+    variable = new TVariable(&identifier, TType(type));
+
+    if (! symbolTable.insert(*variable)) {
+        error(line, "redefinition", variable->getName().c_str());
+        delete variable;
+        variable = 0;
+        return true;
+    }
+
+    if (voidErrorCheck(line, identifier, type))
+        return true;
+
+    return false;
+}
+
+bool TParseContext::paramErrorCheck(int line, TQualifier qualifier, TQualifier paramQualifier, TType* type)
+{    
+    if (qualifier != EvqConst && qualifier != EvqTemporary) {
+        error(line, "qualifier not allowed on function parameter", getQualifierString(qualifier));
+        return true;
+    }
+    if (qualifier == EvqConst && paramQualifier != EvqIn) {
+        error(line, "qualifier not allowed with ", getQualifierString(qualifier), getQualifierString(paramQualifier));
+        return true;
+    }
+
+    if (qualifier == EvqConst)
+        type->setQualifier(EvqConstReadOnly);
+    else
+        type->setQualifier(paramQualifier);
+
+    return false;
+}
+
+bool TParseContext::extensionErrorCheck(int line, const TString& extension)
+{
+    const TExtensionBehavior& extBehavior = extensionBehavior();
+    TExtensionBehavior::const_iterator iter = extBehavior.find(extension.c_str());
+    if (iter == extBehavior.end()) {
+        error(line, "extension", extension.c_str(), "is not supported");
+        return true;
+    }
+    // In GLSL ES, an extension's default behavior is "disable".
+    if (iter->second == EBhDisable || iter->second == EBhUndefined) {
+        error(line, "extension", extension.c_str(), "is disabled");
+        return true;
+    }
+    if (iter->second == EBhWarn) {
+        warning(line, "extension", extension.c_str(), "is being used");
+        return false;
+    }
+
+    return false;
+}
+
+bool TParseContext::supportsExtension(const char* extension)
+{
+    const TExtensionBehavior& extbehavior = extensionBehavior();
+    TExtensionBehavior::const_iterator iter = extbehavior.find(extension);
+    return (iter != extbehavior.end());
+}
+
+void TParseContext::handleExtensionDirective(int line, const char* extName, const char* behavior)
+{
+    pp::SourceLocation loc;
+    DecodeSourceLoc(line, &loc.file, &loc.line);
+    directiveHandler.handleExtension(loc, extName, behavior);
+}
+
+void TParseContext::handlePragmaDirective(int line, const char* name, const char* value)
+{
+    pp::SourceLocation loc;
+    DecodeSourceLoc(line, &loc.file, &loc.line);
+    directiveHandler.handlePragma(loc, name, value);
+}
+
+/////////////////////////////////////////////////////////////////////////////////
+//
+// Non-Errors.
+//
+/////////////////////////////////////////////////////////////////////////////////
+
+//
+// Look up a function name in the symbol table, and make sure it is a function.
+//
+// Return the function symbol if found, otherwise 0.
+//
+const TFunction* TParseContext::findFunction(int line, TFunction* call, bool *builtIn)
+{
+    // First find by unmangled name to check whether the function name has been
+    // hidden by a variable name or struct typename.
+    const TSymbol* symbol = symbolTable.find(call->getName(), builtIn);
+    if (symbol == 0) {
+        symbol = symbolTable.find(call->getMangledName(), builtIn);
+    }
+
+    if (symbol == 0) {
+        error(line, "no matching overloaded function found", call->getName().c_str());
+        return 0;
+    }
+
+    if (!symbol->isFunction()) {
+        error(line, "function name expected", call->getName().c_str());
+        return 0;
+    }
+
+    return static_cast<const TFunction*>(symbol);
+}
+
+//
+// Initializers show up in several places in the grammar.  Have one set of
+// code to handle them here.
+//
+bool TParseContext::executeInitializer(TSourceLoc line, TString& identifier, TPublicType& pType, 
+                                       TIntermTyped* initializer, TIntermNode*& intermNode, TVariable* variable)
+{
+    TType type = TType(pType);
+
+    if (variable == 0) {
+        if (reservedErrorCheck(line, identifier))
+            return true;
+
+        if (voidErrorCheck(line, identifier, pType))
+            return true;
+
+        //
+        // add variable to symbol table
+        //
+        variable = new TVariable(&identifier, type);
+        if (! symbolTable.insert(*variable)) {
+            error(line, "redefinition", variable->getName().c_str());
+            return true;
+            // don't delete variable, it's used by error recovery, and the pool 
+            // pop will take care of the memory
+        }
+    }
+
+    //
+    // identifier must be of type constant, a global, or a temporary
+    //
+    TQualifier qualifier = variable->getType().getQualifier();
+    if ((qualifier != EvqTemporary) && (qualifier != EvqGlobal) && (qualifier != EvqConst)) {
+        error(line, " cannot initialize this type of qualifier ", variable->getType().getQualifierString());
+        return true;
+    }
+    //
+    // test for and propagate constant
+    //
+
+    if (qualifier == EvqConst) {
+        if (qualifier != initializer->getType().getQualifier()) {
+            std::stringstream extraInfoStream;
+            extraInfoStream << "'" << variable->getType().getCompleteString() << "'";
+            std::string extraInfo = extraInfoStream.str();
+            error(line, " assigning non-constant to", "=", extraInfo.c_str());
+            variable->getType().setQualifier(EvqTemporary);
+            return true;
+        }
+        if (type != initializer->getType()) {
+            error(line, " non-matching types for const initializer ", 
+                variable->getType().getQualifierString());
+            variable->getType().setQualifier(EvqTemporary);
+            return true;
+        }
+        if (initializer->getAsConstantUnion()) { 
+            ConstantUnion* unionArray = variable->getConstPointer();
+
+            if (type.getObjectSize() == 1 && type.getBasicType() != EbtStruct) {
+                *unionArray = (initializer->getAsConstantUnion()->getUnionArrayPointer())[0];
+            } else {
+                variable->shareConstPointer(initializer->getAsConstantUnion()->getUnionArrayPointer());
+            }
+        } else if (initializer->getAsSymbolNode()) {
+            const TSymbol* symbol = symbolTable.find(initializer->getAsSymbolNode()->getSymbol());
+            const TVariable* tVar = static_cast<const TVariable*>(symbol);
+
+            ConstantUnion* constArray = tVar->getConstPointer();
+            variable->shareConstPointer(constArray);
+        } else {
+            std::stringstream extraInfoStream;
+            extraInfoStream << "'" << variable->getType().getCompleteString() << "'";
+            std::string extraInfo = extraInfoStream.str();
+            error(line, " cannot assign to", "=", extraInfo.c_str());
+            variable->getType().setQualifier(EvqTemporary);
+            return true;
+        }
+    }
+ 
+    if (qualifier != EvqConst) {
+        TIntermSymbol* intermSymbol = intermediate.addSymbol(variable->getUniqueId(), variable->getName(), variable->getType(), line);
+        intermNode = intermediate.addAssign(EOpInitialize, intermSymbol, initializer, line);
+        if (intermNode == 0) {
+            assignError(line, "=", intermSymbol->getCompleteString(), initializer->getCompleteString());
+            return true;
+        }
+    } else 
+        intermNode = 0;
+
+    return false;
+}
+
+bool TParseContext::areAllChildConst(TIntermAggregate* aggrNode)
+{
+    ASSERT(aggrNode != NULL);
+    if (!aggrNode->isConstructor())
+        return false;
+
+    bool allConstant = true;
+
+    // check if all the child nodes are constants so that they can be inserted into 
+    // the parent node
+    TIntermSequence &sequence = aggrNode->getSequence() ;
+    for (TIntermSequence::iterator p = sequence.begin(); p != sequence.end(); ++p) {
+        if (!(*p)->getAsTyped()->getAsConstantUnion())
+            return false;
+    }
+
+    return allConstant;
+}
+
+// This function is used to test for the correctness of the parameters passed to various constructor functions
+// and also convert them to the right datatype if it is allowed and required. 
+//
+// Returns 0 for an error or the constructed node (aggregate or typed) for no error.
+//
+TIntermTyped* TParseContext::addConstructor(TIntermNode* node, const TType* type, TOperator op, TFunction* fnCall, TSourceLoc line)
+{
+    if (node == 0)
+        return 0;
+
+    TIntermAggregate* aggrNode = node->getAsAggregate();
+    
+    TTypeList::const_iterator memberTypes;
+    if (op == EOpConstructStruct)
+        memberTypes = type->getStruct()->begin();
+    
+    TType elementType = *type;
+    if (type->isArray())
+        elementType.clearArrayness();
+
+    bool singleArg;
+    if (aggrNode) {
+        if (aggrNode->getOp() != EOpNull || aggrNode->getSequence().size() == 1)
+            singleArg = true;
+        else
+            singleArg = false;
+    } else
+        singleArg = true;
+
+    TIntermTyped *newNode;
+    if (singleArg) {
+        // If structure constructor or array constructor is being called 
+        // for only one parameter inside the structure, we need to call constructStruct function once.
+        if (type->isArray())
+            newNode = constructStruct(node, &elementType, 1, node->getLine(), false);
+        else if (op == EOpConstructStruct)
+            newNode = constructStruct(node, (*memberTypes).type, 1, node->getLine(), false);
+        else
+            newNode = constructBuiltIn(type, op, node, node->getLine(), false);
+
+        if (newNode && newNode->getAsAggregate()) {
+            TIntermTyped* constConstructor = foldConstConstructor(newNode->getAsAggregate(), *type);
+            if (constConstructor)
+                return constConstructor;
+        }
+
+        return newNode;
+    }
+    
+    //
+    // Handle list of arguments.
+    //
+    TIntermSequence &sequenceVector = aggrNode->getSequence() ;    // Stores the information about the parameter to the constructor
+    // if the structure constructor contains more than one parameter, then construct
+    // each parameter
+    
+    int paramCount = 0;  // keeps a track of the constructor parameter number being checked    
+    
+    // for each parameter to the constructor call, check to see if the right type is passed or convert them 
+    // to the right type if possible (and allowed).
+    // for structure constructors, just check if the right type is passed, no conversion is allowed.
+    
+    for (TIntermSequence::iterator p = sequenceVector.begin(); 
+                                   p != sequenceVector.end(); p++, paramCount++) {
+        if (type->isArray())
+            newNode = constructStruct(*p, &elementType, paramCount+1, node->getLine(), true);
+        else if (op == EOpConstructStruct)
+            newNode = constructStruct(*p, (memberTypes[paramCount]).type, paramCount+1, node->getLine(), true);
+        else
+            newNode = constructBuiltIn(type, op, *p, node->getLine(), true);
+        
+        if (newNode) {
+            *p = newNode;
+        }
+    }
+
+    TIntermTyped* constructor = intermediate.setAggregateOperator(aggrNode, op, line);
+    TIntermTyped* constConstructor = foldConstConstructor(constructor->getAsAggregate(), *type);
+    if (constConstructor)
+        return constConstructor;
+
+    return constructor;
+}
+
+TIntermTyped* TParseContext::foldConstConstructor(TIntermAggregate* aggrNode, const TType& type)
+{
+    bool canBeFolded = areAllChildConst(aggrNode);
+    aggrNode->setType(type);
+    if (canBeFolded) {
+        bool returnVal = false;
+        ConstantUnion* unionArray = new ConstantUnion[type.getObjectSize()];
+        if (aggrNode->getSequence().size() == 1)  {
+            returnVal = intermediate.parseConstTree(aggrNode->getLine(), aggrNode, unionArray, aggrNode->getOp(), symbolTable,  type, true);
+        }
+        else {
+            returnVal = intermediate.parseConstTree(aggrNode->getLine(), aggrNode, unionArray, aggrNode->getOp(), symbolTable,  type);
+        }
+        if (returnVal)
+            return 0;
+
+        return intermediate.addConstantUnion(unionArray, type, aggrNode->getLine());
+    }
+
+    return 0;
+}
+
+// Function for constructor implementation. Calls addUnaryMath with appropriate EOp value
+// for the parameter to the constructor (passed to this function). Essentially, it converts
+// the parameter types correctly. If a constructor expects an int (like ivec2) and is passed a 
+// float, then float is converted to int.
+//
+// Returns 0 for an error or the constructed node.
+//
+TIntermTyped* TParseContext::constructBuiltIn(const TType* type, TOperator op, TIntermNode* node, TSourceLoc line, bool subset)
+{
+    TIntermTyped* newNode;
+    TOperator basicOp;
+
+    //
+    // First, convert types as needed.
+    //
+    switch (op) {
+    case EOpConstructVec2:
+    case EOpConstructVec3:
+    case EOpConstructVec4:
+    case EOpConstructMat2:
+    case EOpConstructMat3:
+    case EOpConstructMat4:
+    case EOpConstructFloat:
+        basicOp = EOpConstructFloat;
+        break;
+
+    case EOpConstructIVec2:
+    case EOpConstructIVec3:
+    case EOpConstructIVec4:
+    case EOpConstructInt:
+        basicOp = EOpConstructInt;
+        break;
+
+    case EOpConstructBVec2:
+    case EOpConstructBVec3:
+    case EOpConstructBVec4:
+    case EOpConstructBool:
+        basicOp = EOpConstructBool;
+        break;
+
+    default:
+        error(line, "unsupported construction", "");
+        recover();
+
+        return 0;
+    }
+    newNode = intermediate.addUnaryMath(basicOp, node, node->getLine(), symbolTable);
+    if (newNode == 0) {
+        error(line, "can't convert", "constructor");
+        return 0;
+    }
+
+    //
+    // Now, if there still isn't an operation to do the construction, and we need one, add one.
+    //
+    
+    // Otherwise, skip out early.
+    if (subset || (newNode != node && newNode->getType() == *type))
+        return newNode;
+
+    // setAggregateOperator will insert a new node for the constructor, as needed.
+    return intermediate.setAggregateOperator(newNode, op, line);
+}
+
+// This function tests for the type of the parameters to the structures constructors. Raises
+// an error message if the expected type does not match the parameter passed to the constructor.
+//
+// Returns 0 for an error or the input node itself if the expected and the given parameter types match.
+//
+TIntermTyped* TParseContext::constructStruct(TIntermNode* node, TType* type, int paramCount, TSourceLoc line, bool subset)
+{
+    if (*type == node->getAsTyped()->getType()) {
+        if (subset)
+            return node->getAsTyped();
+        else
+            return intermediate.setAggregateOperator(node->getAsTyped(), EOpConstructStruct, line);
+    } else {
+        std::stringstream extraInfoStream;
+        extraInfoStream << "cannot convert parameter " << paramCount 
+                        << " from '" << node->getAsTyped()->getType().getBasicString()
+                        << "' to '" << type->getBasicString() << "'";
+        std::string extraInfo = extraInfoStream.str();
+        error(line, "", "constructor", extraInfo.c_str());
+        recover();
+    }
+
+    return 0;
+}
+
+//
+// This function returns the tree representation for the vector field(s) being accessed from contant vector.
+// If only one component of vector is accessed (v.x or v[0] where v is a contant vector), then a contant node is
+// returned, else an aggregate node is returned (for v.xy). The input to this function could either be the symbol
+// node or it could be the intermediate tree representation of accessing fields in a constant structure or column of 
+// a constant matrix.
+//
+TIntermTyped* TParseContext::addConstVectorNode(TVectorFields& fields, TIntermTyped* node, TSourceLoc line)
+{
+    TIntermTyped* typedNode;
+    TIntermConstantUnion* tempConstantNode = node->getAsConstantUnion();
+
+    ConstantUnion *unionArray;
+    if (tempConstantNode) {
+        unionArray = tempConstantNode->getUnionArrayPointer();
+        ASSERT(unionArray);
+
+        if (!unionArray) {
+            return node;
+        }
+    } else { // The node has to be either a symbol node or an aggregate node or a tempConstant node, else, its an error
+        error(line, "Cannot offset into the vector", "Error");
+        recover();
+
+        return 0;
+    }
+
+    ConstantUnion* constArray = new ConstantUnion[fields.num];
+
+    for (int i = 0; i < fields.num; i++) {
+        if (fields.offsets[i] >= node->getType().getObjectSize()) {
+            std::stringstream extraInfoStream;
+            extraInfoStream << "vector field selection out of range '" << fields.offsets[i] << "'";
+            std::string extraInfo = extraInfoStream.str();
+            error(line, "", "[", extraInfo.c_str());
+            recover();
+            fields.offsets[i] = 0;
+        }
+        
+        constArray[i] = unionArray[fields.offsets[i]];
+
+    } 
+    typedNode = intermediate.addConstantUnion(constArray, node->getType(), line);
+    return typedNode;
+}
+
+//
+// This function returns the column being accessed from a constant matrix. The values are retrieved from
+// the symbol table and parse-tree is built for a vector (each column of a matrix is a vector). The input 
+// to the function could either be a symbol node (m[0] where m is a constant matrix)that represents a 
+// constant matrix or it could be the tree representation of the constant matrix (s.m1[0] where s is a constant structure)
+//
+TIntermTyped* TParseContext::addConstMatrixNode(int index, TIntermTyped* node, TSourceLoc line)
+{
+    TIntermTyped* typedNode;
+    TIntermConstantUnion* tempConstantNode = node->getAsConstantUnion();
+
+    if (index >= node->getType().getNominalSize()) {
+        std::stringstream extraInfoStream;
+        extraInfoStream << "matrix field selection out of range '" << index << "'";
+        std::string extraInfo = extraInfoStream.str();
+        error(line, "", "[", extraInfo.c_str());
+        recover();
+        index = 0;
+    }
+
+    if (tempConstantNode) {
+         ConstantUnion* unionArray = tempConstantNode->getUnionArrayPointer();
+         int size = tempConstantNode->getType().getNominalSize();
+         typedNode = intermediate.addConstantUnion(&unionArray[size*index], tempConstantNode->getType(), line);
+    } else {
+        error(line, "Cannot offset into the matrix", "Error");
+        recover();
+
+        return 0;
+    }
+
+    return typedNode;
+}
+
+
+//
+// This function returns an element of an array accessed from a constant array. The values are retrieved from
+// the symbol table and parse-tree is built for the type of the element. The input 
+// to the function could either be a symbol node (a[0] where a is a constant array)that represents a 
+// constant array or it could be the tree representation of the constant array (s.a1[0] where s is a constant structure)
+//
+TIntermTyped* TParseContext::addConstArrayNode(int index, TIntermTyped* node, TSourceLoc line)
+{
+    TIntermTyped* typedNode;
+    TIntermConstantUnion* tempConstantNode = node->getAsConstantUnion();
+    TType arrayElementType = node->getType();
+    arrayElementType.clearArrayness();
+
+    if (index >= node->getType().getArraySize()) {
+        std::stringstream extraInfoStream;
+        extraInfoStream << "array field selection out of range '" << index << "'";
+        std::string extraInfo = extraInfoStream.str();
+        error(line, "", "[", extraInfo.c_str());
+        recover();
+        index = 0;
+    }
+
+    int arrayElementSize = arrayElementType.getObjectSize();
+
+    if (tempConstantNode) {
+         ConstantUnion* unionArray = tempConstantNode->getUnionArrayPointer();
+         typedNode = intermediate.addConstantUnion(&unionArray[arrayElementSize * index], tempConstantNode->getType(), line);
+    } else {
+        error(line, "Cannot offset into the array", "Error");
+        recover();
+
+        return 0;
+    }
+
+    return typedNode;
+}
+
+
+//
+// This function returns the value of a particular field inside a constant structure from the symbol table. 
+// If there is an embedded/nested struct, it appropriately calls addConstStructNested or addConstStructFromAggr
+// function and returns the parse-tree with the values of the embedded/nested struct.
+//
+TIntermTyped* TParseContext::addConstStruct(TString& identifier, TIntermTyped* node, TSourceLoc line)
+{
+    const TTypeList* fields = node->getType().getStruct();
+    TIntermTyped *typedNode;
+    int instanceSize = 0;
+    unsigned int index = 0;
+    TIntermConstantUnion *tempConstantNode = node->getAsConstantUnion();
+
+    for ( index = 0; index < fields->size(); ++index) {
+        if ((*fields)[index].type->getFieldName() == identifier) {
+            break;
+        } else {
+            instanceSize += (*fields)[index].type->getObjectSize();
+        }
+    }
+
+    if (tempConstantNode) {
+         ConstantUnion* constArray = tempConstantNode->getUnionArrayPointer();
+
+         typedNode = intermediate.addConstantUnion(constArray+instanceSize, tempConstantNode->getType(), line); // type will be changed in the calling function
+    } else {
+        error(line, "Cannot offset into the structure", "Error");
+        recover();
+
+        return 0;
+    }
+
+    return typedNode;
+}
+
+bool TParseContext::enterStructDeclaration(int line, const TString& identifier)
+{
+    ++structNestingLevel;
+
+    // Embedded structure definitions are not supported per GLSL ES spec.
+    // They aren't allowed in GLSL either, but we need to detect this here
+    // so we don't rely on the GLSL compiler to catch it.
+    if (structNestingLevel > 1) {
+        error(line, "", "Embedded struct definitions are not allowed");
+        return true;
+    }
+
+    return false;
+}
+
+void TParseContext::exitStructDeclaration()
+{
+    --structNestingLevel;
+}
+
+namespace {
+
+const int kWebGLMaxStructNesting = 4;
+
+}  // namespace
+
+bool TParseContext::structNestingErrorCheck(TSourceLoc line, const TType& fieldType)
+{
+    if (shaderSpec != SH_WEBGL_SPEC) {
+        return false;
+    }
+
+    if (fieldType.getBasicType() != EbtStruct) {
+        return false;
+    }
+
+    // We're already inside a structure definition at this point, so add
+    // one to the field's struct nesting.
+    if (1 + fieldType.getDeepestStructNesting() > kWebGLMaxStructNesting) {
+        std::stringstream extraInfoStream;
+        extraInfoStream << "Reference of struct type " << fieldType.getTypeName() 
+                        << " exceeds maximum struct nesting of " << kWebGLMaxStructNesting;
+        std::string extraInfo = extraInfoStream.str();
+        error(line, "", "", extraInfo.c_str());
+        return true;
+    }
+
+    return false;
+}
+
+//
+// Parse an array of strings using yyparse.
+//
+// Returns 0 for success.
+//
+int PaParseStrings(int count, const char* const string[], const int length[],
+                   TParseContext* context) {
+    if ((count == 0) || (string == NULL))
+        return 1;
+
+    if (glslang_initialize(context))
+        return 1;
+
+    int error = glslang_scan(count, string, length, context);
+    if (!error)
+        error = glslang_parse(context);
+
+    glslang_finalize(context);
+
+    return (error == 0) && (context->numErrors() == 0) ? 0 : 1;
+}
+
+
+
diff --git a/src/GLES2/compiler/ParseHelper.h b/src/GLES2/compiler/ParseHelper.h
new file mode 100644
index 0000000..668e52a
--- /dev/null
+++ b/src/GLES2/compiler/ParseHelper.h
@@ -0,0 +1,140 @@
+//
+// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+#ifndef _PARSER_HELPER_INCLUDED_
+#define _PARSER_HELPER_INCLUDED_
+
+#include "compiler/Diagnostics.h"
+#include "compiler/DirectiveHandler.h"
+#include "compiler/localintermediate.h"
+#include "compiler/preprocessor/Preprocessor.h"
+#include "compiler/ShHandle.h"
+#include "compiler/SymbolTable.h"
+
+struct TMatrixFields {
+    bool wholeRow;
+    bool wholeCol;
+    int row;
+    int col;
+};
+
+//
+// The following are extra variables needed during parsing, grouped together so
+// they can be passed to the parser without needing a global.
+//
+struct TParseContext {
+    TParseContext(TSymbolTable& symt, TExtensionBehavior& ext, TIntermediate& interm, ShShaderType type, ShShaderSpec spec, int options, bool checksPrecErrors, const char* sourcePath, TInfoSink& is) :
+            intermediate(interm),
+            symbolTable(symt),
+            shaderType(type),
+            shaderSpec(spec),
+            compileOptions(options),
+            sourcePath(sourcePath),
+            treeRoot(0),
+            lexAfterType(false),
+            loopNestingLevel(0),
+            structNestingLevel(0),
+            inTypeParen(false),
+            currentFunctionType(NULL),
+            functionReturnsValue(false),
+            checksPrecisionErrors(checksPrecErrors),
+            diagnostics(is),
+            directiveHandler(ext, diagnostics),
+            preprocessor(&diagnostics, &directiveHandler),
+            scanner(NULL) {  }
+    TIntermediate& intermediate; // to hold and build a parse tree
+    TSymbolTable& symbolTable;   // symbol table that goes with the language currently being parsed
+    ShShaderType shaderType;              // vertex or fragment language (future: pack or unpack)
+    ShShaderSpec shaderSpec;              // The language specification compiler conforms to - GLES2 or WebGL.
+    int compileOptions;
+    const char* sourcePath;      // Path of source file or NULL.
+    TIntermNode* treeRoot;       // root of parse tree being created
+    bool lexAfterType;           // true if we've recognized a type, so can only be looking for an identifier
+    int loopNestingLevel;        // 0 if outside all loops
+    int structNestingLevel;      // incremented while parsing a struct declaration
+    bool inTypeParen;            // true if in parentheses, looking only for an identifier
+    const TType* currentFunctionType;  // the return type of the function that's currently being parsed
+    bool functionReturnsValue;   // true if a non-void function has a return
+    bool checksPrecisionErrors;  // true if an error will be generated when a variable is declared without precision, explicit or implicit.
+    TString HashErrMsg;
+    bool AfterEOF;
+    TDiagnostics diagnostics;
+    TDirectiveHandler directiveHandler;
+    pp::Preprocessor preprocessor;
+    void* scanner;
+
+    int numErrors() const { return diagnostics.numErrors(); }
+    TInfoSink& infoSink() { return diagnostics.infoSink(); }
+    void error(TSourceLoc loc, const char *reason, const char* token,
+               const char* extraInfo="");
+    void warning(TSourceLoc loc, const char* reason, const char* token,
+                 const char* extraInfo="");
+    void trace(const char* str);
+    void recover();
+
+    bool parseVectorFields(const TString&, int vecSize, TVectorFields&, int line);
+    bool parseMatrixFields(const TString&, int matSize, TMatrixFields&, int line);
+
+    bool reservedErrorCheck(int line, const TString& identifier);
+    void assignError(int line, const char* op, TString left, TString right);
+    void unaryOpError(int line, const char* op, TString operand);
+    void binaryOpError(int line, const char* op, TString left, TString right);
+    bool precisionErrorCheck(int line, TPrecision precision, TBasicType type);
+    bool lValueErrorCheck(int line, const char* op, TIntermTyped*);
+    bool constErrorCheck(TIntermTyped* node);
+    bool integerErrorCheck(TIntermTyped* node, const char* token);
+    bool globalErrorCheck(int line, bool global, const char* token);
+    bool constructorErrorCheck(int line, TIntermNode*, TFunction&, TOperator, TType*);
+    bool arraySizeErrorCheck(int line, TIntermTyped* expr, int& size);
+    bool arrayQualifierErrorCheck(int line, TPublicType type);
+    bool arrayTypeErrorCheck(int line, TPublicType type);
+    bool arrayErrorCheck(int line, TString& identifier, TPublicType type, TVariable*& variable);
+    bool voidErrorCheck(int, const TString&, const TPublicType&);
+    bool boolErrorCheck(int, const TIntermTyped*);
+    bool boolErrorCheck(int, const TPublicType&);
+    bool samplerErrorCheck(int line, const TPublicType& pType, const char* reason);
+    bool structQualifierErrorCheck(int line, const TPublicType& pType);
+    bool parameterSamplerErrorCheck(int line, TQualifier qualifier, const TType& type);
+    bool nonInitConstErrorCheck(int line, TString& identifier, TPublicType& type, bool array);
+    bool nonInitErrorCheck(int line, TString& identifier, TPublicType& type, TVariable*& variable);
+    bool paramErrorCheck(int line, TQualifier qualifier, TQualifier paramQualifier, TType* type);
+    bool extensionErrorCheck(int line, const TString&);
+
+    const TExtensionBehavior& extensionBehavior() const { return directiveHandler.extensionBehavior(); }
+    bool supportsExtension(const char* extension);
+    void handleExtensionDirective(int line, const char* extName, const char* behavior);
+
+    const TPragma& pragma() const { return directiveHandler.pragma(); }
+    void handlePragmaDirective(int line, const char* name, const char* value);
+
+    bool containsSampler(TType& type);
+    bool areAllChildConst(TIntermAggregate* aggrNode);
+    const TFunction* findFunction(int line, TFunction* pfnCall, bool *builtIn = 0);
+    bool executeInitializer(TSourceLoc line, TString& identifier, TPublicType& pType,
+                            TIntermTyped* initializer, TIntermNode*& intermNode, TVariable* variable = 0);
+    bool arraySetMaxSize(TIntermSymbol*, TType*, int, bool, TSourceLoc);
+
+    TIntermTyped* addConstructor(TIntermNode*, const TType*, TOperator, TFunction*, TSourceLoc);
+    TIntermTyped* foldConstConstructor(TIntermAggregate* aggrNode, const TType& type);
+    TIntermTyped* constructStruct(TIntermNode*, TType*, int, TSourceLoc, bool subset);
+    TIntermTyped* constructBuiltIn(const TType*, TOperator, TIntermNode*, TSourceLoc, bool subset);
+    TIntermTyped* addConstVectorNode(TVectorFields&, TIntermTyped*, TSourceLoc);
+    TIntermTyped* addConstMatrixNode(int , TIntermTyped*, TSourceLoc);
+    TIntermTyped* addConstArrayNode(int index, TIntermTyped* node, TSourceLoc line);
+    TIntermTyped* addConstStruct(TString& , TIntermTyped*, TSourceLoc);
+
+    // Performs an error check for embedded struct declarations.
+    // Returns true if an error was raised due to the declaration of
+    // this struct.
+    bool enterStructDeclaration(TSourceLoc line, const TString& identifier);
+    void exitStructDeclaration();
+
+    bool structNestingErrorCheck(TSourceLoc line, const TType& fieldType);
+};
+
+int PaParseStrings(int count, const char* const string[], const int length[],
+                   TParseContext* context);
+
+#endif // _PARSER_HELPER_INCLUDED_
diff --git a/src/GLES2/compiler/PoolAlloc.cpp b/src/GLES2/compiler/PoolAlloc.cpp
new file mode 100644
index 0000000..c0ae1ec
--- /dev/null
+++ b/src/GLES2/compiler/PoolAlloc.cpp
@@ -0,0 +1,309 @@
+//
+// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "compiler/PoolAlloc.h"
+
+#ifndef _MSC_VER
+#include <stdint.h>
+#endif
+#include <stdio.h>
+
+#include "compiler/InitializeGlobals.h"
+#include "compiler/osinclude.h"
+
+OS_TLSIndex PoolIndex = OS_INVALID_TLS_INDEX;
+
+void InitializeGlobalPools()
+{
+    TThreadGlobalPools* globalPools= static_cast<TThreadGlobalPools*>(OS_GetTLSValue(PoolIndex));    
+    if (globalPools)
+        return;
+
+    TThreadGlobalPools* threadData = new TThreadGlobalPools();
+    threadData->globalPoolAllocator = 0;
+
+    OS_SetTLSValue(PoolIndex, threadData);
+}
+
+void FreeGlobalPools()
+{
+    // Release the allocated memory for this thread.
+    TThreadGlobalPools* globalPools= static_cast<TThreadGlobalPools*>(OS_GetTLSValue(PoolIndex));    
+    if (!globalPools)
+        return;
+ 
+    delete globalPools;
+}
+
+bool InitializePoolIndex()
+{
+    // Allocate a TLS index.
+    if ((PoolIndex = OS_AllocTLSIndex()) == OS_INVALID_TLS_INDEX)
+        return false;
+
+    return true;
+}
+
+void FreePoolIndex()
+{
+    // Release the TLS index.
+    OS_FreeTLSIndex(PoolIndex);
+}
+
+TPoolAllocator& GetGlobalPoolAllocator()
+{
+    TThreadGlobalPools* threadData = static_cast<TThreadGlobalPools*>(OS_GetTLSValue(PoolIndex));
+
+    return *threadData->globalPoolAllocator;
+}
+
+void SetGlobalPoolAllocator(TPoolAllocator* poolAllocator)
+{
+    TThreadGlobalPools* threadData = static_cast<TThreadGlobalPools*>(OS_GetTLSValue(PoolIndex));
+
+    threadData->globalPoolAllocator = poolAllocator;
+}
+
+//
+// Implement the functionality of the TPoolAllocator class, which
+// is documented in PoolAlloc.h.
+//
+TPoolAllocator::TPoolAllocator(int growthIncrement, int allocationAlignment) : 
+    pageSize(growthIncrement),
+    alignment(allocationAlignment),
+    freeList(0),
+    inUseList(0),
+    numCalls(0),
+    totalBytes(0)
+{
+    //
+    // Don't allow page sizes we know are smaller than all common
+    // OS page sizes.
+    //
+    if (pageSize < 4*1024)
+        pageSize = 4*1024;
+
+    //
+    // A large currentPageOffset indicates a new page needs to
+    // be obtained to allocate memory.
+    //
+    currentPageOffset = pageSize;
+
+    //
+    // Adjust alignment to be at least pointer aligned and
+    // power of 2.
+    //
+    size_t minAlign = sizeof(void*);
+    alignment &= ~(minAlign - 1);
+    if (alignment < minAlign)
+        alignment = minAlign;
+    size_t a = 1;
+    while (a < alignment)
+        a <<= 1;
+    alignment = a;
+    alignmentMask = a - 1;
+
+    //
+    // Align header skip
+    //
+    headerSkip = minAlign;
+    if (headerSkip < sizeof(tHeader)) {
+        headerSkip = (sizeof(tHeader) + alignmentMask) & ~alignmentMask;
+    }
+}
+
+TPoolAllocator::~TPoolAllocator()
+{
+    while (inUseList) {
+        tHeader* next = inUseList->nextPage;
+        inUseList->~tHeader();
+        delete [] reinterpret_cast<char*>(inUseList);
+        inUseList = next;
+    }
+
+    // We should not check the guard blocks
+    // here, because we did it already when the block was
+    // placed into the free list.
+    //
+    while (freeList) {
+        tHeader* next = freeList->nextPage;
+        delete [] reinterpret_cast<char*>(freeList);
+        freeList = next;
+    }
+}
+
+// Support MSVC++ 6.0
+const unsigned char TAllocation::guardBlockBeginVal = 0xfb;
+const unsigned char TAllocation::guardBlockEndVal   = 0xfe;
+const unsigned char TAllocation::userDataFill       = 0xcd;
+
+#ifdef GUARD_BLOCKS
+    const size_t TAllocation::guardBlockSize = 16;
+#else
+    const size_t TAllocation::guardBlockSize = 0;
+#endif
+
+//
+// Check a single guard block for damage
+//
+void TAllocation::checkGuardBlock(unsigned char* blockMem, unsigned char val, const char* locText) const
+{
+#ifdef GUARD_BLOCKS
+    for (size_t x = 0; x < guardBlockSize; x++) {
+        if (blockMem[x] != val) {
+            char assertMsg[80];
+
+            // We don't print the assert message.  It's here just to be helpful.
+            #if defined(_MSC_VER)
+                _snprintf(assertMsg, sizeof(assertMsg), "PoolAlloc: Damage %s %Iu byte allocation at 0x%p\n",
+                          locText, size, data());
+            #else
+                snprintf(assertMsg, sizeof(assertMsg), "PoolAlloc: Damage %s %zu byte allocation at 0x%p\n",
+                         locText, size, data());
+            #endif
+            assert(0 && "PoolAlloc: Damage in guard block");
+        }
+    }
+#endif
+}
+
+
+void TPoolAllocator::push()
+{
+    tAllocState state = { currentPageOffset, inUseList };
+
+    stack.push_back(state);
+        
+    //
+    // Indicate there is no current page to allocate from.
+    //
+    currentPageOffset = pageSize;
+}
+
+//
+// Do a mass-deallocation of all the individual allocations
+// that have occurred since the last push(), or since the
+// last pop(), or since the object's creation.
+//
+// The deallocated pages are saved for future allocations.
+//
+void TPoolAllocator::pop()
+{
+    if (stack.size() < 1)
+        return;
+
+    tHeader* page = stack.back().page;
+    currentPageOffset = stack.back().offset;
+
+    while (inUseList != page) {
+        // invoke destructor to free allocation list
+        inUseList->~tHeader();
+        
+        tHeader* nextInUse = inUseList->nextPage;
+        if (inUseList->pageCount > 1)
+            delete [] reinterpret_cast<char*>(inUseList);
+        else {
+            inUseList->nextPage = freeList;
+            freeList = inUseList;
+        }
+        inUseList = nextInUse;
+    }
+
+    stack.pop_back();
+}
+
+//
+// Do a mass-deallocation of all the individual allocations
+// that have occurred.
+//
+void TPoolAllocator::popAll()
+{
+    while (stack.size() > 0)
+        pop();
+}
+
+void* TPoolAllocator::allocate(size_t numBytes)
+{
+    // If we are using guard blocks, all allocations are bracketed by
+    // them: [guardblock][allocation][guardblock].  numBytes is how
+    // much memory the caller asked for.  allocationSize is the total
+    // size including guard blocks.  In release build,
+    // guardBlockSize=0 and this all gets optimized away.
+    size_t allocationSize = TAllocation::allocationSize(numBytes);
+    
+    //
+    // Just keep some interesting statistics.
+    //
+    ++numCalls;
+    totalBytes += numBytes;
+
+    //
+    // Do the allocation, most likely case first, for efficiency.
+    // This step could be moved to be inline sometime.
+    //
+    if (currentPageOffset + allocationSize <= pageSize) {
+        //
+        // Safe to allocate from currentPageOffset.
+        //
+        unsigned char* memory = reinterpret_cast<unsigned char *>(inUseList) + currentPageOffset;
+        currentPageOffset += allocationSize;
+        currentPageOffset = (currentPageOffset + alignmentMask) & ~alignmentMask;
+
+        return initializeAllocation(inUseList, memory, numBytes);
+    }
+
+    if (allocationSize + headerSkip > pageSize) {
+        //
+        // Do a multi-page allocation.  Don't mix these with the others.
+        // The OS is efficient and allocating and free-ing multiple pages.
+        //
+        size_t numBytesToAlloc = allocationSize + headerSkip;
+        tHeader* memory = reinterpret_cast<tHeader*>(::new char[numBytesToAlloc]);
+        if (memory == 0)
+            return 0;
+
+        // Use placement-new to initialize header
+        new(memory) tHeader(inUseList, (numBytesToAlloc + pageSize - 1) / pageSize);
+        inUseList = memory;
+
+        currentPageOffset = pageSize;  // make next allocation come from a new page
+
+        // No guard blocks for multi-page allocations (yet)
+        return reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(memory) + headerSkip);
+    }
+
+    //
+    // Need a simple page to allocate from.
+    //
+    tHeader* memory;
+    if (freeList) {
+        memory = freeList;
+        freeList = freeList->nextPage;
+    } else {
+        memory = reinterpret_cast<tHeader*>(::new char[pageSize]);
+        if (memory == 0)
+            return 0;
+    }
+
+    // Use placement-new to initialize header
+    new(memory) tHeader(inUseList, 1);
+    inUseList = memory;
+    
+    unsigned char* ret = reinterpret_cast<unsigned char *>(inUseList) + headerSkip;
+    currentPageOffset = (headerSkip + allocationSize + alignmentMask) & ~alignmentMask;
+
+    return initializeAllocation(inUseList, ret, numBytes);
+}
+
+
+//
+// Check all allocations in a list for damage by calling check on each.
+//
+void TAllocation::checkAllocList() const
+{
+    for (const TAllocation* alloc = this; alloc != 0; alloc = alloc->prevAlloc)
+        alloc->check();
+}
diff --git a/src/GLES2/compiler/PoolAlloc.h b/src/GLES2/compiler/PoolAlloc.h
new file mode 100644
index 0000000..c33dfd9
--- /dev/null
+++ b/src/GLES2/compiler/PoolAlloc.h
@@ -0,0 +1,306 @@
+//
+// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#ifndef _POOLALLOC_INCLUDED_
+#define _POOLALLOC_INCLUDED_
+
+#ifdef _DEBUG
+#define GUARD_BLOCKS  // define to enable guard block sanity checking
+#endif
+
+//
+// This header defines an allocator that can be used to efficiently
+// allocate a large number of small requests for heap memory, with the 
+// intention that they are not individually deallocated, but rather 
+// collectively deallocated at one time.
+//
+// This simultaneously
+//
+// * Makes each individual allocation much more efficient; the
+//     typical allocation is trivial.
+// * Completely avoids the cost of doing individual deallocation.
+// * Saves the trouble of tracking down and plugging a large class of leaks.
+//
+// Individual classes can use this allocator by supplying their own
+// new and delete methods.
+//
+// STL containers can use this allocator by using the pool_allocator
+// class as the allocator (second) template argument.
+//
+
+#include <stddef.h>
+#include <string.h>
+#include <vector>
+
+// If we are using guard blocks, we must track each indivual
+// allocation.  If we aren't using guard blocks, these
+// never get instantiated, so won't have any impact.
+// 
+
+class TAllocation {
+public:
+    TAllocation(size_t size, unsigned char* mem, TAllocation* prev = 0) :
+        size(size), mem(mem), prevAlloc(prev) {
+        // Allocations are bracketed:
+        //    [allocationHeader][initialGuardBlock][userData][finalGuardBlock]
+        // This would be cleaner with if (guardBlockSize)..., but that
+        // makes the compiler print warnings about 0 length memsets,
+        // even with the if() protecting them.
+#ifdef GUARD_BLOCKS
+        memset(preGuard(), guardBlockBeginVal, guardBlockSize);
+        memset(data(),      userDataFill,       size);
+        memset(postGuard(), guardBlockEndVal,   guardBlockSize);
+#endif
+    }
+
+    void check() const {
+        checkGuardBlock(preGuard(),  guardBlockBeginVal, "before");
+        checkGuardBlock(postGuard(), guardBlockEndVal,   "after");
+    }
+
+    void checkAllocList() const;
+
+    // Return total size needed to accomodate user buffer of 'size',
+    // plus our tracking data.
+    inline static size_t allocationSize(size_t size) {
+        return size + 2 * guardBlockSize + headerSize();
+    }
+
+    // Offset from surrounding buffer to get to user data buffer.
+    inline static unsigned char* offsetAllocation(unsigned char* m) {
+        return m + guardBlockSize + headerSize();
+    }
+
+private:
+    void checkGuardBlock(unsigned char* blockMem, unsigned char val, const char* locText) const;
+
+    // Find offsets to pre and post guard blocks, and user data buffer
+    unsigned char* preGuard()  const { return mem + headerSize(); }
+    unsigned char* data()      const { return preGuard() + guardBlockSize; }
+    unsigned char* postGuard() const { return data() + size; }
+
+    size_t size;                  // size of the user data area
+    unsigned char* mem;           // beginning of our allocation (pts to header)
+    TAllocation* prevAlloc;       // prior allocation in the chain
+
+    // Support MSVC++ 6.0
+    const static unsigned char guardBlockBeginVal;
+    const static unsigned char guardBlockEndVal;
+    const static unsigned char userDataFill;
+
+    const static size_t guardBlockSize;
+#ifdef GUARD_BLOCKS
+    inline static size_t headerSize() { return sizeof(TAllocation); }
+#else
+    inline static size_t headerSize() { return 0; }
+#endif
+};
+
+//
+// There are several stacks.  One is to track the pushing and popping
+// of the user, and not yet implemented.  The others are simply a 
+// repositories of free pages or used pages.
+//
+// Page stacks are linked together with a simple header at the beginning
+// of each allocation obtained from the underlying OS.  Multi-page allocations
+// are returned to the OS.  Individual page allocations are kept for future
+// re-use.
+//
+// The "page size" used is not, nor must it match, the underlying OS
+// page size.  But, having it be about that size or equal to a set of 
+// pages is likely most optimal.
+//
+class TPoolAllocator {
+public:
+    TPoolAllocator(int growthIncrement = 8*1024, int allocationAlignment = 16);
+
+    //
+    // Don't call the destructor just to free up the memory, call pop()
+    //
+    ~TPoolAllocator();
+
+    //
+    // Call push() to establish a new place to pop memory too.  Does not
+    // have to be called to get things started.
+    //
+    void push();
+
+    //
+    // Call pop() to free all memory allocated since the last call to push(),
+    // or if no last call to push, frees all memory since first allocation.
+    //
+    void pop();
+
+    //
+    // Call popAll() to free all memory allocated.
+    //
+    void popAll();
+
+    //
+    // Call allocate() to actually acquire memory.  Returns 0 if no memory
+    // available, otherwise a properly aligned pointer to 'numBytes' of memory.
+    //
+    void* allocate(size_t numBytes);
+
+    //
+    // There is no deallocate.  The point of this class is that
+    // deallocation can be skipped by the user of it, as the model
+    // of use is to simultaneously deallocate everything at once
+    // by calling pop(), and to not have to solve memory leak problems.
+    //
+
+protected:
+    friend struct tHeader;
+    
+    struct tHeader {
+        tHeader(tHeader* nextPage, size_t pageCount) :
+            nextPage(nextPage),
+            pageCount(pageCount)
+#ifdef GUARD_BLOCKS
+          , lastAllocation(0)
+#endif
+            { }
+
+        ~tHeader() {
+#ifdef GUARD_BLOCKS
+            if (lastAllocation)
+                lastAllocation->checkAllocList();
+#endif
+        }
+
+        tHeader* nextPage;
+        size_t pageCount;
+#ifdef GUARD_BLOCKS
+        TAllocation* lastAllocation;
+#endif
+    };
+
+    struct tAllocState {
+        size_t offset;
+        tHeader* page;
+    };
+    typedef std::vector<tAllocState> tAllocStack;
+
+    // Track allocations if and only if we're using guard blocks
+    void* initializeAllocation(tHeader* block, unsigned char* memory, size_t numBytes) {
+#ifdef GUARD_BLOCKS
+        new(memory) TAllocation(numBytes, memory, block->lastAllocation);
+        block->lastAllocation = reinterpret_cast<TAllocation*>(memory);
+#endif
+        // This is optimized entirely away if GUARD_BLOCKS is not defined.
+        return TAllocation::offsetAllocation(memory);
+    }
+
+    size_t pageSize;        // granularity of allocation from the OS
+    size_t alignment;       // all returned allocations will be aligned at 
+                            // this granularity, which will be a power of 2
+    size_t alignmentMask;
+    size_t headerSkip;      // amount of memory to skip to make room for the
+                            //      header (basically, size of header, rounded
+                            //      up to make it aligned
+    size_t currentPageOffset;  // next offset in top of inUseList to allocate from
+    tHeader* freeList;      // list of popped memory
+    tHeader* inUseList;     // list of all memory currently being used
+    tAllocStack stack;      // stack of where to allocate from, to partition pool
+
+    int numCalls;           // just an interesting statistic
+    size_t totalBytes;      // just an interesting statistic
+private:
+    TPoolAllocator& operator=(const TPoolAllocator&);  // dont allow assignment operator
+    TPoolAllocator(const TPoolAllocator&);  // dont allow default copy constructor
+};
+
+
+//
+// There could potentially be many pools with pops happening at
+// different times.  But a simple use is to have a global pop
+// with everyone using the same global allocator.
+//
+extern TPoolAllocator& GetGlobalPoolAllocator();
+extern void SetGlobalPoolAllocator(TPoolAllocator* poolAllocator);
+#define GlobalPoolAllocator GetGlobalPoolAllocator()
+
+struct TThreadGlobalPools
+{
+    TPoolAllocator* globalPoolAllocator;
+};
+
+//
+// This STL compatible allocator is intended to be used as the allocator
+// parameter to templatized STL containers, like vector and map.
+//
+// It will use the pools for allocation, and not
+// do any deallocation, but will still do destruction.
+//
+template<class T>
+class pool_allocator {
+public:
+    typedef size_t size_type;
+    typedef ptrdiff_t difference_type;
+    typedef T* pointer;
+    typedef const T* const_pointer;
+    typedef T& reference;
+    typedef const T& const_reference;
+    typedef T value_type;
+
+    template<class Other> 
+    struct rebind {
+        typedef pool_allocator<Other> other;
+    };
+    pointer address(reference x) const { return &x; }
+    const_pointer address(const_reference x) const { return &x; }
+
+    pool_allocator() : allocator(&GlobalPoolAllocator) { }
+    pool_allocator(TPoolAllocator& a) : allocator(&a) { }
+    pool_allocator(const pool_allocator<T>& p) : allocator(p.allocator) { }
+
+    template <class Other>
+    pool_allocator<T>& operator=(const pool_allocator<Other>& p) {
+      allocator = p.allocator;
+      return *this;
+    }
+
+    template<class Other>
+    pool_allocator(const pool_allocator<Other>& p) : allocator(&p.getAllocator()) { }
+
+#if defined(__SUNPRO_CC) && !defined(_RWSTD_ALLOCATOR)
+    // libCStd on some platforms have a different allocate/deallocate interface.
+    // Caller pre-bakes sizeof(T) into 'n' which is the number of bytes to be
+    // allocated, not the number of elements.
+    void* allocate(size_type n) { 
+        return getAllocator().allocate(n);
+    }
+    void* allocate(size_type n, const void*) {
+        return getAllocator().allocate(n);
+    }
+    void deallocate(void*, size_type) {}
+#else
+    pointer allocate(size_type n) { 
+        return reinterpret_cast<pointer>(getAllocator().allocate(n * sizeof(T)));
+    }
+    pointer allocate(size_type n, const void*) { 
+        return reinterpret_cast<pointer>(getAllocator().allocate(n * sizeof(T)));
+    }
+    void deallocate(pointer, size_type) {}
+#endif  // _RWSTD_ALLOCATOR
+
+    void construct(pointer p, const T& val) { new ((void *)p) T(val); }
+    void destroy(pointer p) { p->T::~T(); }
+
+    bool operator==(const pool_allocator& rhs) const { return &getAllocator() == &rhs.getAllocator(); }
+    bool operator!=(const pool_allocator& rhs) const { return &getAllocator() != &rhs.getAllocator(); }
+
+    size_type max_size() const { return static_cast<size_type>(-1) / sizeof(T); }
+    size_type max_size(int size) const { return static_cast<size_type>(-1) / size; }
+
+    void setAllocator(TPoolAllocator *a) { allocator = a; }
+    TPoolAllocator& getAllocator() const { return *allocator; }
+
+protected:
+    TPoolAllocator *allocator;
+};
+
+#endif // _POOLALLOC_INCLUDED_
diff --git a/src/GLES2/compiler/Pragma.h b/src/GLES2/compiler/Pragma.h
new file mode 100644
index 0000000..2f74412
--- /dev/null
+++ b/src/GLES2/compiler/Pragma.h
@@ -0,0 +1,19 @@
+//
+// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#ifndef COMPILER_PRAGMA_H_
+#define COMPILER_PRAGMA_H_
+
+struct TPragma {
+    // By default optimization is turned on and debug is turned off.
+    TPragma() : optimize(true), debug(false) { }
+    TPragma(bool o, bool d) : optimize(o), debug(d) { }
+
+    bool optimize;
+    bool debug;
+};
+
+#endif // COMPILER_PRAGMA_H_
diff --git a/src/GLES2/compiler/QualifierAlive.cpp b/src/GLES2/compiler/QualifierAlive.cpp
new file mode 100644
index 0000000..92a6874
--- /dev/null
+++ b/src/GLES2/compiler/QualifierAlive.cpp
@@ -0,0 +1,58 @@
+//
+// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "compiler/intermediate.h"
+
+class TAliveTraverser : public TIntermTraverser {
+public:
+    TAliveTraverser(TQualifier q) : TIntermTraverser(true, false, false, true), found(false), qualifier(q)
+    {
+    }
+
+	bool wasFound() { return found; }
+
+protected:
+    bool found;
+    TQualifier qualifier;
+
+    void visitSymbol(TIntermSymbol*);
+    bool visitSelection(Visit, TIntermSelection*);
+};
+
+//
+// Report whether or not a variable of the given qualifier type
+// is guaranteed written.  Not always possible to determine if
+// it is written conditionally.
+//
+// ?? It does not do this well yet, this is just a place holder
+// that simply determines if it was reference at all, anywhere.
+//
+bool QualifierWritten(TIntermNode* node, TQualifier qualifier)
+{
+    TAliveTraverser it(qualifier);
+
+    if (node)
+        node->traverse(&it);
+
+    return it.wasFound();
+}
+
+void TAliveTraverser::visitSymbol(TIntermSymbol* node)
+{
+    //
+    // If it's what we're looking for, record it.
+    //
+    if (node->getQualifier() == qualifier)
+        found = true;
+}
+
+bool TAliveTraverser::visitSelection(Visit preVisit, TIntermSelection* node)
+{
+    if (wasFound())
+        return false;
+
+    return true;
+}
diff --git a/src/GLES2/compiler/QualifierAlive.h b/src/GLES2/compiler/QualifierAlive.h
new file mode 100644
index 0000000..872a06f
--- /dev/null
+++ b/src/GLES2/compiler/QualifierAlive.h
@@ -0,0 +1,7 @@
+//
+// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+bool QualifierWritten(TIntermNode* root, TQualifier);
diff --git a/src/GLES2/compiler/RemoveTree.cpp b/src/GLES2/compiler/RemoveTree.cpp
new file mode 100644
index 0000000..a4b8c1e
--- /dev/null
+++ b/src/GLES2/compiler/RemoveTree.cpp
@@ -0,0 +1,77 @@
+//
+// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "compiler/intermediate.h"
+#include "compiler/RemoveTree.h"
+
+//
+// Code to recursively delete the intermediate tree.
+//
+
+class RemoveTree : public TIntermTraverser
+{
+public:
+	RemoveTree() : TIntermTraverser(false, false, true)
+	{
+	}
+
+protected:
+	void visitSymbol(TIntermSymbol*);
+	void visitConstantUnion(TIntermConstantUnion*);
+	bool visitBinary(Visit visit, TIntermBinary*);
+	bool visitUnary(Visit visit, TIntermUnary*);
+	bool visitSelection(Visit visit, TIntermSelection*);
+	bool visitAggregate(Visit visit, TIntermAggregate*);
+};
+
+void RemoveTree::visitSymbol(TIntermSymbol* node)
+{
+	delete node;
+}
+
+bool RemoveTree::visitBinary(Visit visit, TIntermBinary* node)
+{
+	delete node;
+
+	return true;
+}
+
+bool RemoveTree::visitUnary(Visit visit, TIntermUnary* node)
+{
+    delete node;
+
+	return true;
+}
+
+bool RemoveTree::visitAggregate(Visit visit, TIntermAggregate* node)
+{
+	delete node;
+
+	return true;
+}
+
+bool RemoveTree::visitSelection(Visit visit, TIntermSelection* node)
+{
+	delete node;
+
+	return true;
+}
+
+void RemoveTree::visitConstantUnion(TIntermConstantUnion* node)
+{
+	delete node;
+}
+
+//
+// Entry point.
+//
+void RemoveAllTreeNodes(TIntermNode* root)
+{
+    RemoveTree it;
+
+    root->traverse(&it);
+}
+
diff --git a/src/GLES2/compiler/RemoveTree.h b/src/GLES2/compiler/RemoveTree.h
new file mode 100644
index 0000000..97a8216
--- /dev/null
+++ b/src/GLES2/compiler/RemoveTree.h
@@ -0,0 +1,7 @@
+//
+// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+void RemoveAllTreeNodes(TIntermNode*);
diff --git a/src/GLES2/compiler/ShHandle.h b/src/GLES2/compiler/ShHandle.h
new file mode 100644
index 0000000..a0105ab
--- /dev/null
+++ b/src/GLES2/compiler/ShHandle.h
@@ -0,0 +1,108 @@
+//
+// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#ifndef _SHHANDLE_INCLUDED_
+#define _SHHANDLE_INCLUDED_
+
+//
+// Machine independent part of the compiler private objects
+// sent as ShHandle to the driver.
+//
+// This should not be included by driver code.
+//
+
+#include "GLSLANG/ShaderLang.h"
+
+#include "compiler/ExtensionBehavior.h"
+#include "compiler/InfoSink.h"
+#include "compiler/SymbolTable.h"
+#include "compiler/VariableInfo.h"
+
+class TCompiler;
+
+//
+// The base class used to back handles returned to the driver.
+//
+class TShHandleBase {
+public:
+    TShHandleBase();
+    virtual ~TShHandleBase();
+    virtual TCompiler* getAsCompiler() { return 0; }
+
+protected:
+    // Memory allocator. Allocates and tracks memory required by the compiler.
+    // Deallocates all memory when compiler is destructed.
+    TPoolAllocator allocator;
+};
+
+//
+// The base class for the machine dependent compiler to derive from
+// for managing object code from the compile.
+//
+class TCompiler : public TShHandleBase {
+public:
+    TCompiler(ShShaderType type, ShShaderSpec spec);
+    virtual ~TCompiler();
+    virtual TCompiler* getAsCompiler() { return this; }
+
+    bool Init(const ShBuiltInResources& resources);
+    bool compile(const char* const shaderStrings[],
+                 const int numStrings,
+                 int compileOptions);
+
+    // Get results of the last compilation.
+    TInfoSink& getInfoSink() { return infoSink; }
+    const TVariableInfoList& getAttribs() const { return attribs; }
+    const TVariableInfoList& getUniforms() const { return uniforms; }
+
+protected:
+    ShShaderType getShaderType() const { return shaderType; }
+    ShShaderSpec getShaderSpec() const { return shaderSpec; }
+    // Initialize symbol-table with built-in symbols.
+    bool InitBuiltInSymbolTable(const ShBuiltInResources& resources);
+    // Clears the results from the previous compilation.
+    void clearResults();
+    // Return true if function recursion is detected.
+    bool detectRecursion(TIntermNode* root);
+    // Returns true if the given shader does not exceed the minimum
+    // functionality mandated in GLSL 1.0 spec Appendix A.
+    bool validateLimitations(TIntermNode* root);
+    // Collect info for all attribs and uniforms.
+    void collectAttribsUniforms(TIntermNode* root);
+    // Translate to object code.
+    virtual void translate(TIntermNode* root) = 0;
+    // Get built-in extensions with default behavior.
+    const TExtensionBehavior& getExtensionBehavior() const;
+
+private:
+    ShShaderType shaderType;
+    ShShaderSpec shaderSpec;
+
+    // Built-in symbol table for the given language, spec, and resources.
+    // It is preserved from compile-to-compile.
+    TSymbolTable symbolTable;
+    // Built-in extensions with default behavior.
+    TExtensionBehavior extensionBehavior;
+
+    // Results of compilation.
+    TInfoSink infoSink;  // Output sink.
+    TVariableInfoList attribs;  // Active attributes in the compiled shader.
+    TVariableInfoList uniforms;  // Active uniforms in the compiled shader.
+};
+
+//
+// This is the interface between the machine independent code
+// and the machine dependent code.
+//
+// The machine dependent code should derive from the classes
+// above. Then Construct*() and Delete*() will create and 
+// destroy the machine dependent objects, which contain the
+// above machine independent information.
+//
+TCompiler* ConstructCompiler(ShShaderType type, ShShaderSpec spec);
+void DeleteCompiler(TCompiler*);
+
+#endif // _SHHANDLE_INCLUDED_
diff --git a/src/GLES2/compiler/ShaderLang.cpp b/src/GLES2/compiler/ShaderLang.cpp
new file mode 100644
index 0000000..0da8247
--- /dev/null
+++ b/src/GLES2/compiler/ShaderLang.cpp
@@ -0,0 +1,259 @@
+//
+// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+//
+// Implement the top-level of interface to the compiler,
+// as defined in ShaderLang.h
+//
+
+#include "GLSLANG/ShaderLang.h"
+
+#include "compiler/InitializeDll.h"
+#include "compiler/preprocessor/length_limits.h"
+#include "compiler/ShHandle.h"
+
+//
+// This is the platform independent interface between an OGL driver
+// and the shading language compiler.
+//
+
+static bool checkActiveUniformAndAttribMaxLengths(const ShHandle handle,
+                                                  int expectedValue)
+{
+    int activeUniformLimit = 0;
+    ShGetInfo(handle, SH_ACTIVE_UNIFORM_MAX_LENGTH, &activeUniformLimit);
+    int activeAttribLimit = 0;
+    ShGetInfo(handle, SH_ACTIVE_ATTRIBUTE_MAX_LENGTH, &activeAttribLimit);
+    return (expectedValue == activeUniformLimit && expectedValue == activeAttribLimit);
+}
+
+static void getVariableInfo(ShShaderInfo varType,
+                            const ShHandle handle,
+                            int index,
+                            int* length,
+                            int* size,
+                            ShDataType* type,
+                            char* name)
+{
+    if (!handle || !size || !type || !name)
+        return;
+    ASSERT((varType == SH_ACTIVE_ATTRIBUTES) ||
+           (varType == SH_ACTIVE_UNIFORMS));
+
+    TShHandleBase* base = reinterpret_cast<TShHandleBase*>(handle);
+    TCompiler* compiler = base->getAsCompiler();
+    if (compiler == 0)
+        return;
+
+    const TVariableInfoList& varList = varType == SH_ACTIVE_ATTRIBUTES ?
+        compiler->getAttribs() : compiler->getUniforms();
+    if (index < 0 || index >= static_cast<int>(varList.size()))
+        return;
+
+    const TVariableInfo& varInfo = varList[index];
+    if (length) *length = varInfo.name.size();
+    *size = varInfo.size;
+    *type = varInfo.type;
+
+    // This size must match that queried by
+    // SH_ACTIVE_UNIFORM_MAX_LENGTH and SH_ACTIVE_ATTRIBUTE_MAX_LENGTH
+    // in ShGetInfo, below.
+    int activeUniformAndAttribLength = 1 + MAX_SYMBOL_NAME_LEN;
+    ASSERT(checkActiveUniformAndAttribMaxLengths(handle, activeUniformAndAttribLength));
+    strncpy(name, varInfo.name.c_str(), activeUniformAndAttribLength);
+    name[activeUniformAndAttribLength - 1] = 0;
+}
+
+//
+// Driver must call this first, once, before doing any other
+// compiler operations.
+//
+int ShInitialize()
+{
+    if (!InitProcess())
+        return 0;
+
+    return 1;
+}
+
+//
+// Cleanup symbol tables
+//
+int ShFinalize()
+{
+    if (!DetachProcess())
+        return 0;
+
+    return 1;
+}
+
+//
+// Initialize built-in resources with minimum expected values.
+//
+void ShInitBuiltInResources(ShBuiltInResources* resources)
+{
+    // Constants.
+    resources->MaxVertexAttribs = 8;
+    resources->MaxVertexUniformVectors = 128;
+    resources->MaxVaryingVectors = 8;
+    resources->MaxVertexTextureImageUnits = 0;
+    resources->MaxCombinedTextureImageUnits = 8;
+    resources->MaxTextureImageUnits = 8;
+    resources->MaxFragmentUniformVectors = 16;
+    resources->MaxDrawBuffers = 1;
+
+    // Extensions.
+    resources->OES_standard_derivatives = 0;
+}
+
+//
+// Driver calls these to create and destroy compiler objects.
+//
+ShHandle ShConstructCompiler(ShShaderType type, ShShaderSpec spec,
+                             const ShBuiltInResources* resources)
+{
+    if (!InitThread())
+        return 0;
+
+    TShHandleBase* base = static_cast<TShHandleBase*>(ConstructCompiler(type, spec));
+    TCompiler* compiler = base->getAsCompiler();
+    if (compiler == 0)
+        return 0;
+
+    // Generate built-in symbol table.
+    if (!compiler->Init(*resources)) {
+        ShDestruct(base);
+        return 0;
+    }
+
+    return reinterpret_cast<void*>(base);
+}
+
+void ShDestruct(ShHandle handle)
+{
+    if (handle == 0)
+        return;
+
+    TShHandleBase* base = static_cast<TShHandleBase*>(handle);
+
+    if (base->getAsCompiler())
+        DeleteCompiler(base->getAsCompiler());
+}
+
+//
+// Do an actual compile on the given strings.  The result is left 
+// in the given compile object.
+//
+// Return:  The return value of ShCompile is really boolean, indicating
+// success or failure.
+//
+int ShCompile(
+    const ShHandle handle,
+    const char* const shaderStrings[],
+    const int numStrings,
+    int compileOptions)
+{
+    if (!InitThread())
+        return 0;
+
+    if (handle == 0)
+        return 0;
+
+    TShHandleBase* base = reinterpret_cast<TShHandleBase*>(handle);
+    TCompiler* compiler = base->getAsCompiler();
+    if (compiler == 0)
+        return 0;
+
+    bool success = compiler->compile(shaderStrings, numStrings, compileOptions);
+    return success ? 1 : 0;
+}
+
+void ShGetInfo(const ShHandle handle, ShShaderInfo pname, int* params)
+{
+    if (!handle || !params)
+        return;
+
+    TShHandleBase* base = static_cast<TShHandleBase*>(handle);
+    TCompiler* compiler = base->getAsCompiler();
+    if (!compiler) return;
+
+    switch(pname)
+    {
+    case SH_INFO_LOG_LENGTH:
+        *params = compiler->getInfoSink().info.size() + 1;
+        break;
+    case SH_OBJECT_CODE_LENGTH:
+        *params = compiler->getInfoSink().obj.size() + 1;
+        break;
+    case SH_ACTIVE_UNIFORMS:
+        *params = compiler->getUniforms().size();
+        break;
+    case SH_ACTIVE_UNIFORM_MAX_LENGTH:
+        *params = 1 +  MAX_SYMBOL_NAME_LEN;
+        break;
+    case SH_ACTIVE_ATTRIBUTES:
+        *params = compiler->getAttribs().size();
+        break;
+    case SH_ACTIVE_ATTRIBUTE_MAX_LENGTH:
+        *params = 1 + MAX_SYMBOL_NAME_LEN;
+        break;
+    default: UNREACHABLE();
+    }
+}
+
+//
+// Return any compiler log of messages for the application.
+//
+void ShGetInfoLog(const ShHandle handle, char* infoLog)
+{
+    if (!handle || !infoLog)
+        return;
+
+    TShHandleBase* base = static_cast<TShHandleBase*>(handle);
+    TCompiler* compiler = base->getAsCompiler();
+    if (!compiler) return;
+
+    TInfoSink& infoSink = compiler->getInfoSink();
+    strcpy(infoLog, infoSink.info.c_str());
+}
+
+//
+// Return any object code.
+//
+void ShGetObjectCode(const ShHandle handle, char* objCode)
+{
+    if (!handle || !objCode)
+        return;
+
+    TShHandleBase* base = static_cast<TShHandleBase*>(handle);
+    TCompiler* compiler = base->getAsCompiler();
+    if (!compiler) return;
+
+    TInfoSink& infoSink = compiler->getInfoSink();
+    strcpy(objCode, infoSink.obj.c_str());
+}
+
+void ShGetActiveAttrib(const ShHandle handle,
+                       int index,
+                       int* length,
+                       int* size,
+                       ShDataType* type,
+                       char* name)
+{
+    getVariableInfo(SH_ACTIVE_ATTRIBUTES,
+                    handle, index, length, size, type, name);
+}
+
+void ShGetActiveUniform(const ShHandle handle,
+                        int index,
+                        int* length,
+                        int* size,
+                        ShDataType* type,
+                        char* name)
+{
+    getVariableInfo(SH_ACTIVE_UNIFORMS,
+                    handle, index, length, size, type, name);
+}
diff --git a/src/GLES2/compiler/SymbolTable.cpp b/src/GLES2/compiler/SymbolTable.cpp
new file mode 100644
index 0000000..adf56a8
--- /dev/null
+++ b/src/GLES2/compiler/SymbolTable.cpp
@@ -0,0 +1,284 @@
+//
+// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+//
+// Symbol table for parsing.  Most functionaliy and main ideas
+// are documented in the header file.
+//
+
+#if defined(_MSC_VER)
+#pragma warning(disable: 4718)
+#endif
+
+#include "compiler/SymbolTable.h"
+
+#include <stdio.h>
+#include <algorithm>
+
+#if defined(_MSC_VER)
+#define snprintf _snprintf
+#endif
+
+TType::TType(const TPublicType &p) :
+    type(p.type), precision(p.precision), qualifier(p.qualifier), size(p.size), matrix(p.matrix), array(p.array), arraySize(p.arraySize),
+    maxArraySize(0), arrayInformationType(0), structure(0), structureSize(0), deepestStructNesting(0), fieldName(0), mangled(0), typeName(0)
+{
+    if (p.userDef)
+    {
+        structure = p.userDef->getStruct();
+        typeName = NewPoolTString(p.userDef->getTypeName().c_str());
+        computeDeepestStructNesting();
+    }
+}
+
+//
+// Recursively generate mangled names.
+//
+void TType::buildMangledName(TString& mangledName)
+{
+    if (isMatrix())
+        mangledName += 'm';
+    else if (isVector())
+        mangledName += 'v';
+
+    switch (type) {
+    case EbtFloat:              mangledName += 'f';      break;
+    case EbtInt:                mangledName += 'i';      break;
+    case EbtBool:               mangledName += 'b';      break;
+    case EbtSampler2D:          mangledName += "s2";     break;
+    case EbtSamplerCube:        mangledName += "sC";     break;
+    case EbtStruct:
+        mangledName += "struct-";
+        if (typeName)
+            mangledName += *typeName;
+        {// support MSVC++6.0
+            for (unsigned int i = 0; i < structure->size(); ++i) {
+                mangledName += '-';
+                (*structure)[i].type->buildMangledName(mangledName);
+            }
+        }
+    default:
+        break;
+    }
+
+    mangledName += static_cast<char>('0' + getNominalSize());
+    if (isArray()) {
+        char buf[20];
+        snprintf(buf, sizeof(buf), "%d", arraySize);
+        mangledName += '[';
+        mangledName += buf;
+        mangledName += ']';
+    }
+}
+
+int TType::getStructSize() const
+{
+    if (!getStruct()) {
+        assert(false && "Not a struct");
+        return 0;
+    }
+
+    if (structureSize == 0)
+        for (TTypeList::const_iterator tl = getStruct()->begin(); tl != getStruct()->end(); tl++)
+            structureSize += ((*tl).type)->getObjectSize();
+
+    return structureSize;
+}
+
+void TType::computeDeepestStructNesting()
+{
+    if (!structure)
+    {
+        return;
+    }
+
+    int maxNesting = 0;
+    for (TTypeList::const_iterator tl = structure->begin(); tl != structure->end(); tl++)
+    {
+        maxNesting = std::max(maxNesting, ((*tl).type)->getDeepestStructNesting());
+    }
+
+    deepestStructNesting = 1 + maxNesting;
+}
+
+bool TType::isStructureContainingArrays() const
+{
+    if (!structure)
+    {
+        return false;
+    }
+
+    for (TTypeList::const_iterator member = structure->begin(); member != structure->end(); member++)
+    {
+        if (member->type->isArray() ||
+            member->type->isStructureContainingArrays())
+        {
+            return true;
+        }
+    }
+
+    return false;
+}
+
+//
+// Dump functions.
+//
+
+void TVariable::dump(TInfoSink& infoSink) const
+{
+    infoSink.debug << getName().c_str() << ": " << type.getQualifierString() << " " << type.getPrecisionString() << " " << type.getBasicString();
+    if (type.isArray()) {
+        infoSink.debug << "[0]";
+    }
+    infoSink.debug << "\n";
+}
+
+void TFunction::dump(TInfoSink &infoSink) const
+{
+    infoSink.debug << getName().c_str() << ": " <<  returnType.getBasicString() << " " << getMangledName().c_str() << "\n";
+}
+
+void TSymbolTableLevel::dump(TInfoSink &infoSink) const
+{
+    tLevel::const_iterator it;
+    for (it = level.begin(); it != level.end(); ++it)
+        (*it).second->dump(infoSink);
+}
+
+void TSymbolTable::dump(TInfoSink &infoSink) const
+{
+    for (int level = currentLevel(); level >= 0; --level) {
+        infoSink.debug << "LEVEL " << level << "\n";
+        table[level]->dump(infoSink);
+    }
+}
+
+//
+// Functions have buried pointers to delete.
+//
+TFunction::~TFunction()
+{
+    for (TParamList::iterator i = parameters.begin(); i != parameters.end(); ++i)
+        delete (*i).type;
+}
+
+//
+// Symbol table levels are a map of pointers to symbols that have to be deleted.
+//
+TSymbolTableLevel::~TSymbolTableLevel()
+{
+    for (tLevel::iterator it = level.begin(); it != level.end(); ++it)
+        delete (*it).second;
+}
+
+//
+// Change all function entries in the table with the non-mangled name
+// to be related to the provided built-in operation.  This is a low
+// performance operation, and only intended for symbol tables that
+// live across a large number of compiles.
+//
+void TSymbolTableLevel::relateToOperator(const char* name, TOperator op)
+{
+    tLevel::iterator it;
+    for (it = level.begin(); it != level.end(); ++it) {
+        if ((*it).second->isFunction()) {
+            TFunction* function = static_cast<TFunction*>((*it).second);
+            if (function->getName() == name)
+                function->relateToOperator(op);
+        }
+    }
+}
+
+//
+// Change all function entries in the table with the non-mangled name
+// to be related to the provided built-in extension. This is a low
+// performance operation, and only intended for symbol tables that
+// live across a large number of compiles.
+//
+void TSymbolTableLevel::relateToExtension(const char* name, const TString& ext)
+{
+    for (tLevel::iterator it = level.begin(); it != level.end(); ++it) {
+        if (it->second->isFunction()) {
+            TFunction* function = static_cast<TFunction*>(it->second);
+            if (function->getName() == name)
+                function->relateToExtension(ext);
+        }
+    }
+}
+
+TSymbol::TSymbol(const TSymbol& copyOf)
+{
+    name = NewPoolTString(copyOf.name->c_str());
+    uniqueId = copyOf.uniqueId;
+}
+
+TVariable::TVariable(const TVariable& copyOf, TStructureMap& remapper) : TSymbol(copyOf)
+{
+    type.copyType(copyOf.type, remapper);
+    userType = copyOf.userType;
+    // for builtIn symbol table level, unionArray and arrayInformation pointers should be NULL
+    assert(copyOf.arrayInformationType == 0);
+    arrayInformationType = 0;
+
+    if (copyOf.unionArray) {
+        assert(!copyOf.type.getStruct());
+        assert(copyOf.type.getObjectSize() == 1);
+        unionArray = new ConstantUnion[1];
+        unionArray[0] = copyOf.unionArray[0];
+    } else
+        unionArray = 0;
+}
+
+TVariable* TVariable::clone(TStructureMap& remapper)
+{
+    TVariable *variable = new TVariable(*this, remapper);
+
+    return variable;
+}
+
+TFunction::TFunction(const TFunction& copyOf, TStructureMap& remapper) : TSymbol(copyOf)
+{
+    for (unsigned int i = 0; i < copyOf.parameters.size(); ++i) {
+        TParameter param;
+        parameters.push_back(param);
+        parameters.back().copyParam(copyOf.parameters[i], remapper);
+    }
+
+    returnType.copyType(copyOf.returnType, remapper);
+    mangledName = copyOf.mangledName;
+    op = copyOf.op;
+    defined = copyOf.defined;
+}
+
+TFunction* TFunction::clone(TStructureMap& remapper)
+{
+    TFunction *function = new TFunction(*this, remapper);
+
+    return function;
+}
+
+TSymbolTableLevel* TSymbolTableLevel::clone(TStructureMap& remapper)
+{
+    TSymbolTableLevel *symTableLevel = new TSymbolTableLevel();
+    tLevel::iterator iter;
+    for (iter = level.begin(); iter != level.end(); ++iter) {
+        symTableLevel->insert(*iter->second->clone(remapper));
+    }
+
+    return symTableLevel;
+}
+
+void TSymbolTable::copyTable(const TSymbolTable& copyOf)
+{
+    TStructureMap remapper;
+    uniqueId = copyOf.uniqueId;
+    for (unsigned int i = 0; i < copyOf.table.size(); ++i) {
+        table.push_back(copyOf.table[i]->clone(remapper));
+    }
+    for( unsigned int i = 0; i < copyOf.precisionStack.size(); i++) {
+        precisionStack.push_back( copyOf.precisionStack[i] );
+    }
+}
diff --git a/src/GLES2/compiler/SymbolTable.h b/src/GLES2/compiler/SymbolTable.h
new file mode 100644
index 0000000..40d7012
--- /dev/null
+++ b/src/GLES2/compiler/SymbolTable.h
@@ -0,0 +1,359 @@
+//
+// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#ifndef _SYMBOL_TABLE_INCLUDED_
+#define _SYMBOL_TABLE_INCLUDED_
+
+//
+// Symbol table for parsing.  Has these design characteristics:
+//
+// * Same symbol table can be used to compile many shaders, to preserve
+//   effort of creating and loading with the large numbers of built-in
+//   symbols.
+//
+// * Name mangling will be used to give each function a unique name
+//   so that symbol table lookups are never ambiguous.  This allows
+//   a simpler symbol table structure.
+//
+// * Pushing and popping of scope, so symbol table will really be a stack 
+//   of symbol tables.  Searched from the top, with new inserts going into
+//   the top.
+//
+// * Constants:  Compile time constant symbols will keep their values
+//   in the symbol table.  The parser can substitute constants at parse
+//   time, including doing constant folding and constant propagation.
+//
+// * No temporaries:  Temporaries made from operations (+, --, .xy, etc.)
+//   are tracked in the intermediate representation, not the symbol table.
+//
+
+#include <assert.h>
+
+#include "compiler/InfoSink.h"
+#include "compiler/intermediate.h"
+
+//
+// Symbol base class.  (Can build functions or variables out of these...)
+//
+class TSymbol {    
+public:
+    POOL_ALLOCATOR_NEW_DELETE(GlobalPoolAllocator)
+    TSymbol(const TString *n) :  name(n) { }
+    virtual ~TSymbol() { /* don't delete name, it's from the pool */ }
+    const TString& getName() const { return *name; }
+    virtual const TString& getMangledName() const { return getName(); }
+    virtual bool isFunction() const { return false; }
+    virtual bool isVariable() const { return false; }
+    void setUniqueId(int id) { uniqueId = id; }
+    int getUniqueId() const { return uniqueId; }
+    virtual void dump(TInfoSink &infoSink) const = 0;	
+    TSymbol(const TSymbol&);
+    virtual TSymbol* clone(TStructureMap& remapper) = 0;
+
+protected:
+    const TString *name;
+    unsigned int uniqueId;      // For real comparing during code generation
+};
+
+//
+// Variable class, meaning a symbol that's not a function.
+// 
+// There could be a separate class heirarchy for Constant variables;
+// Only one of int, bool, or float, (or none) is correct for
+// any particular use, but it's easy to do this way, and doesn't
+// seem worth having separate classes, and "getConst" can't simply return
+// different values for different types polymorphically, so this is 
+// just simple and pragmatic.
+//
+class TVariable : public TSymbol {
+public:
+    TVariable(const TString *name, const TType& t, bool uT = false ) : TSymbol(name), type(t), userType(uT), unionArray(0), arrayInformationType(0) { }
+    virtual ~TVariable() { }
+    virtual bool isVariable() const { return true; }    
+    TType& getType() { return type; }    
+    const TType& getType() const { return type; }
+    bool isUserType() const { return userType; }
+    void setQualifier(TQualifier qualifier) { type.setQualifier(qualifier); }
+    void updateArrayInformationType(TType *t) { arrayInformationType = t; }
+    TType* getArrayInformationType() { return arrayInformationType; }
+
+    virtual void dump(TInfoSink &infoSink) const;
+
+    ConstantUnion* getConstPointer()
+    { 
+        if (!unionArray)
+            unionArray = new ConstantUnion[type.getObjectSize()];
+
+        return unionArray;
+    }
+
+    ConstantUnion* getConstPointer() const { return unionArray; }
+
+    void shareConstPointer( ConstantUnion *constArray)
+    {
+        if (unionArray == constArray)
+            return;
+
+        delete[] unionArray;
+        unionArray = constArray;  
+    }
+    TVariable(const TVariable&, TStructureMap& remapper); // copy constructor
+    virtual TVariable* clone(TStructureMap& remapper);
+
+protected:
+    TType type;
+    bool userType;
+    // we are assuming that Pool Allocator will free the memory allocated to unionArray
+    // when this object is destroyed
+    ConstantUnion *unionArray;
+    TType *arrayInformationType;  // this is used for updating maxArraySize in all the references to a given symbol
+};
+
+//
+// The function sub-class of symbols and the parser will need to
+// share this definition of a function parameter.
+//
+struct TParameter {
+    TString *name;
+    TType* type;
+    void copyParam(const TParameter& param, TStructureMap& remapper)
+    {
+        name = NewPoolTString(param.name->c_str());
+        type = param.type->clone(remapper);
+    }
+};
+
+//
+// The function sub-class of a symbol.  
+//
+class TFunction : public TSymbol {
+public:
+    TFunction(TOperator o) :
+        TSymbol(0),
+        returnType(TType(EbtVoid, EbpUndefined)),
+        op(o),
+        defined(false) { }
+    TFunction(const TString *name, TType& retType, TOperator tOp = EOpNull) : 
+        TSymbol(name), 
+        returnType(retType),
+        mangledName(TFunction::mangleName(*name)),
+        op(tOp),
+        defined(false) { }
+    virtual ~TFunction();
+    virtual bool isFunction() const { return true; }    
+
+    static TString mangleName(const TString& name) { return name + '('; }
+    static TString unmangleName(const TString& mangledName)
+    {
+        return TString(mangledName.c_str(), mangledName.find_first_of('('));
+    }
+
+    void addParameter(TParameter& p) 
+    { 
+        parameters.push_back(p);
+        mangledName = mangledName + p.type->getMangledName();
+    }
+
+    const TString& getMangledName() const { return mangledName; }
+    const TType& getReturnType() const { return returnType; }
+
+    void relateToOperator(TOperator o) { op = o; }
+    TOperator getBuiltInOp() const { return op; }
+
+    void relateToExtension(const TString& ext) { extension = ext; }
+    const TString& getExtension() const { return extension; }
+
+    void setDefined() { defined = true; }
+    bool isDefined() { return defined; }
+
+    int getParamCount() const { return static_cast<int>(parameters.size()); }  
+    const TParameter& getParam(int i) const { return parameters[i]; }
+
+    virtual void dump(TInfoSink &infoSink) const;
+    TFunction(const TFunction&, TStructureMap& remapper);
+    virtual TFunction* clone(TStructureMap& remapper);
+
+protected:
+    typedef TVector<TParameter> TParamList;
+    TParamList parameters;
+    TType returnType;
+    TString mangledName;
+    TOperator op;
+    TString extension;
+    bool defined;
+};
+
+
+class TSymbolTableLevel {
+public:
+    typedef TMap<TString, TSymbol*> tLevel;
+    typedef tLevel::const_iterator const_iterator;
+    typedef const tLevel::value_type tLevelPair;
+    typedef std::pair<tLevel::iterator, bool> tInsertResult;
+
+    POOL_ALLOCATOR_NEW_DELETE(GlobalPoolAllocator)
+    TSymbolTableLevel() { }
+    ~TSymbolTableLevel();
+
+    bool insert(TSymbol& symbol) 
+    {
+        //
+        // returning true means symbol was added to the table
+        //
+        tInsertResult result;
+        result = level.insert(tLevelPair(symbol.getMangledName(), &symbol));
+
+        return result.second;
+    }
+
+    TSymbol* find(const TString& name) const
+    {
+        tLevel::const_iterator it = level.find(name);
+        if (it == level.end())
+            return 0;
+        else
+            return (*it).second;
+    }
+
+    const_iterator begin() const
+    {
+        return level.begin();
+    }
+
+    const_iterator end() const
+    {
+        return level.end();
+    }
+
+    void relateToOperator(const char* name, TOperator op);
+    void relateToExtension(const char* name, const TString& ext);
+    void dump(TInfoSink &infoSink) const;
+    TSymbolTableLevel* clone(TStructureMap& remapper);
+
+protected:
+    tLevel level;
+};
+
+class TSymbolTable {
+public:
+    TSymbolTable() : uniqueId(0)
+    {
+        //
+        // The symbol table cannot be used until push() is called, but
+        // the lack of an initial call to push() can be used to detect
+        // that the symbol table has not been preloaded with built-ins.
+        //
+    }
+
+    ~TSymbolTable()
+    {
+        // level 0 is always built In symbols, so we never pop that out
+        while (table.size() > 1)
+            pop();
+    }
+
+    //
+    // When the symbol table is initialized with the built-ins, there should
+    // 'push' calls, so that built-ins are at level 0 and the shader
+    // globals are at level 1.
+    //
+    bool isEmpty() { return table.size() == 0; }
+    bool atBuiltInLevel() { return table.size() == 1; }
+    bool atGlobalLevel() { return table.size() <= 2; }
+    void push()
+    {
+        table.push_back(new TSymbolTableLevel);
+        precisionStack.push_back( PrecisionStackLevel() );
+    }
+
+    void pop()
+    { 
+        delete table[currentLevel()]; 
+        table.pop_back(); 
+        precisionStack.pop_back();
+    }
+
+    bool insert(TSymbol& symbol)
+    {
+        symbol.setUniqueId(++uniqueId);
+        return table[currentLevel()]->insert(symbol);
+    }
+
+    TSymbol* find(const TString& name, bool* builtIn = 0, bool *sameScope = 0) 
+    {
+        int level = currentLevel();
+        TSymbol* symbol;
+        do {
+            symbol = table[level]->find(name);
+            --level;
+        } while (symbol == 0 && level >= 0);
+        level++;
+        if (builtIn)
+            *builtIn = level == 0;
+        if (sameScope)
+            *sameScope = level == currentLevel();
+        return symbol;
+    }
+
+    TSymbol *findBuiltIn(const TString &name)
+    {
+        return table[0]->find(name);
+    }
+
+    TSymbolTableLevel* getGlobalLevel() {
+        assert(table.size() >= 2);
+        return table[1];
+    }
+
+    TSymbolTableLevel* getOuterLevel() {
+        assert(table.size() >= 2);
+        return table[currentLevel() - 1];
+    }
+
+    void relateToOperator(const char* name, TOperator op) {
+        table[0]->relateToOperator(name, op);
+    }
+    void relateToExtension(const char* name, const TString& ext) {
+        table[0]->relateToExtension(name, ext);
+    }
+    int getMaxSymbolId() { return uniqueId; }
+    void dump(TInfoSink &infoSink) const;
+    void copyTable(const TSymbolTable& copyOf);
+
+    void setDefaultPrecision( TBasicType type, TPrecision prec ){
+        if( type != EbtFloat && type != EbtInt ) return; // Only set default precision for int/float
+        int indexOfLastElement = static_cast<int>(precisionStack.size()) - 1;
+        precisionStack[indexOfLastElement][type] = prec; // Uses map operator [], overwrites the current value
+    }
+
+    // Searches down the precisionStack for a precision qualifier for the specified TBasicType
+    TPrecision getDefaultPrecision( TBasicType type){
+        if( type != EbtFloat && type != EbtInt ) return EbpUndefined;
+        int level = static_cast<int>(precisionStack.size()) - 1;
+        assert( level >= 0); // Just to be safe. Should not happen.
+        PrecisionStackLevel::iterator it;
+        TPrecision prec = EbpUndefined; // If we dont find anything we return this. Should we error check this?
+        while( level >= 0 ){
+            it = precisionStack[level].find( type );
+            if( it != precisionStack[level].end() ){
+                prec = (*it).second;
+                break;
+            }
+            level--;
+        }
+        return prec;
+    }
+
+protected:    
+    int currentLevel() const { return static_cast<int>(table.size()) - 1; }
+
+    std::vector<TSymbolTableLevel*> table;
+    typedef std::map< TBasicType, TPrecision > PrecisionStackLevel;
+    std::vector< PrecisionStackLevel > precisionStack;
+    int uniqueId;     // for unique identification in code generation
+};
+
+#endif // _SYMBOL_TABLE_INCLUDED_
diff --git a/src/GLES2/compiler/TranslatorASM.cpp b/src/GLES2/compiler/TranslatorASM.cpp
new file mode 100644
index 0000000..bffddf4
--- /dev/null
+++ b/src/GLES2/compiler/TranslatorASM.cpp
@@ -0,0 +1,44 @@
+// SwiftShader Software Renderer

+//

+// Copyright(c) 2005-2012 TransGaming Inc.

+//

+// All rights reserved. No part of this software may be copied, distributed, transmitted,

+// transcribed, stored in a retrieval system, translated into any human or computer

+// language by any means, or disclosed to third parties without the explicit written

+// agreement of TransGaming Inc. Without such an agreement, no rights or licenses, express

+// or implied, including but not limited to any patent rights, are granted to you.

+//

+

+#include "TranslatorASM.h"

+

+#include "InitializeParseContext.h"

+

+TranslatorASM::TranslatorASM(gl::Shader *shaderObject, ShShaderType type, ShShaderSpec spec) : TCompiler(type, spec), shaderObject(shaderObject)

+{

+}

+

+void TranslatorASM::translate(TIntermNode* root)

+{

+    TParseContext& parseContext = *GetGlobalParseContext();

+    sh::OutputASM outputASM(parseContext, shaderObject);

+

+	outputASM.output();

+}

+

+//

+// This function must be provided to create the actual

+// compile object used by higher level code.  It returns

+// a subclass of TCompiler.

+//

+TCompiler* ConstructCompiler(ShShaderType type, ShShaderSpec spec)

+{

+    return new TranslatorASM(0, type, spec);

+}

+

+//

+// Delete the compiler made by ConstructCompiler

+//

+void DeleteCompiler(TCompiler* compiler)

+{

+    delete compiler;

+}
\ No newline at end of file
diff --git a/src/GLES2/compiler/TranslatorASM.h b/src/GLES2/compiler/TranslatorASM.h
new file mode 100644
index 0000000..f6502dd
--- /dev/null
+++ b/src/GLES2/compiler/TranslatorASM.h
@@ -0,0 +1,37 @@
+// SwiftShader Software Renderer

+//

+// Copyright(c) 2005-2012 TransGaming Inc.

+//

+// All rights reserved. No part of this software may be copied, distributed, transmitted,

+// transcribed, stored in a retrieval system, translated into any human or computer

+// language by any means, or disclosed to third parties without the explicit written

+// agreement of TransGaming Inc. Without such an agreement, no rights or licenses, express

+// or implied, including but not limited to any patent rights, are granted to you.

+//

+

+#ifndef COMPILER_TRANSLATORASM_H_

+#define COMPILER_TRANSLATORASM_H_

+

+#include "ShHandle.h"

+#include "OutputASM.h"

+#include "Shader/PixelShader.hpp"

+#include "Shader/VertexShader.hpp"

+

+namespace gl

+{

+	class Shader;

+}

+

+class TranslatorASM : public TCompiler

+{

+public:

+    TranslatorASM(gl::Shader *shaderObject, ShShaderType type, ShShaderSpec spec);

+

+protected:

+    virtual void translate(TIntermNode* root);

+

+private:

+	gl::Shader *const shaderObject;

+};

+

+#endif  // COMPILER_TRANSLATORASM_H_

diff --git a/src/GLES2/compiler/Types.h b/src/GLES2/compiler/Types.h
new file mode 100644
index 0000000..460a433
--- /dev/null
+++ b/src/GLES2/compiler/Types.h
@@ -0,0 +1,368 @@
+//

+// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved.

+// Use of this source code is governed by a BSD-style license that can be

+// found in the LICENSE file.

+//

+

+#ifndef _TYPES_INCLUDED

+#define _TYPES_INCLUDED

+

+#include "compiler/BaseTypes.h"

+#include "compiler/Common.h"

+#include "compiler/debug.h"

+

+class TType;

+struct TPublicType;

+

+//

+// Need to have association of line numbers to types in a list for building structs.

+//

+struct TTypeLine {

+    TType* type;

+    int line;

+};

+typedef TVector<TTypeLine> TTypeList;

+

+inline TTypeList* NewPoolTTypeList()

+{

+    void* memory = GlobalPoolAllocator.allocate(sizeof(TTypeList));

+    return new(memory) TTypeList;

+}

+

+typedef TMap<TTypeList*, TTypeList*> TStructureMap;

+typedef TMap<TTypeList*, TTypeList*>::iterator TStructureMapIterator;

+

+//

+// Base class for things that have a type.

+//

+class TType

+{

+public:

+    POOL_ALLOCATOR_NEW_DELETE(GlobalPoolAllocator)

+    TType() {}

+    TType(TBasicType t, TPrecision p, TQualifier q = EvqTemporary, int s = 1, bool m = false, bool a = false) :

+            type(t), precision(p), qualifier(q), size(s), matrix(m), array(a), arraySize(0),

+            maxArraySize(0), arrayInformationType(0), structure(0), structureSize(0), deepestStructNesting(0), fieldName(0), mangled(0), typeName(0)

+    {

+    }

+    explicit TType(const TPublicType &p);

+    TType(TTypeList* userDef, const TString& n, TPrecision p = EbpUndefined) :

+            type(EbtStruct), precision(p), qualifier(EvqTemporary), size(1), matrix(false), array(false), arraySize(0),

+            maxArraySize(0), arrayInformationType(0), structure(userDef), structureSize(0), deepestStructNesting(0), fieldName(0), mangled(0)

+    {

+        typeName = NewPoolTString(n.c_str());

+    }

+

+    void copyType(const TType& copyOf, TStructureMap& remapper)

+    {

+        type = copyOf.type;

+        precision = copyOf.precision;

+        qualifier = copyOf.qualifier;

+        size = copyOf.size;

+        matrix = copyOf.matrix;

+        array = copyOf.array;

+        arraySize = copyOf.arraySize;

+

+        TStructureMapIterator iter;

+        if (copyOf.structure) {

+            if ((iter = remapper.find(structure)) == remapper.end()) {

+                // create the new structure here

+                structure = NewPoolTTypeList();

+                for (unsigned int i = 0; i < copyOf.structure->size(); ++i) {

+                    TTypeLine typeLine;

+                    typeLine.line = (*copyOf.structure)[i].line;

+                    typeLine.type = (*copyOf.structure)[i].type->clone(remapper);

+                    structure->push_back(typeLine);

+                }

+            } else {

+                structure = iter->second;

+            }

+        } else

+            structure = 0;

+

+        fieldName = 0;

+        if (copyOf.fieldName)

+            fieldName = NewPoolTString(copyOf.fieldName->c_str());

+        typeName = 0;

+        if (copyOf.typeName)

+            typeName = NewPoolTString(copyOf.typeName->c_str());

+

+        mangled = 0;

+        if (copyOf.mangled)

+            mangled = NewPoolTString(copyOf.mangled->c_str());

+

+        structureSize = copyOf.structureSize;

+        maxArraySize = copyOf.maxArraySize;

+        deepestStructNesting = copyOf.deepestStructNesting;

+        assert(copyOf.arrayInformationType == 0);

+        arrayInformationType = 0; // arrayInformationType should not be set for builtIn symbol table level

+    }

+

+    TType* clone(TStructureMap& remapper)

+    {

+        TType *newType = new TType();

+        newType->copyType(*this, remapper);

+

+        return newType;

+    }

+

+    TBasicType getBasicType() const { return type; }

+    void setBasicType(TBasicType t) { type = t; }

+

+    TPrecision getPrecision() const { return precision; }

+    void setPrecision(TPrecision p) { precision = p; }

+

+    TQualifier getQualifier() const { return qualifier; }

+    void setQualifier(TQualifier q) { qualifier = q; }

+

+    // One-dimensional size of single instance type

+    int getNominalSize() const { return size; }

+    void setNominalSize(int s) { size = s; }

+    // Full size of single instance of type

+	int getObjectSize() const

+	{

+		if(isArray())

+		{

+			return getElementSize() * std::max(getArraySize(), getMaxArraySize());

+		}

+		else

+		{

+			return getElementSize();

+		}

+	}

+

+	int getElementSize() const

+	{

+		if(getBasicType() == EbtStruct)

+		{

+			return getStructSize();

+		}

+		else if(matrix)

+		{

+			return size * size;

+		}

+		else   // Vector or scalar

+		{

+			return size;

+		}

+	}

+

+	int elementRegisterCount() const

+	{

+		TTypeList *structure = getStruct();

+

+		if(structure)

+		{

+			int registerCount = 0;

+

+			for(size_t i = 0; i < structure->size(); i++)

+			{

+				registerCount += (*structure)[i].type->totalRegisterCount();

+			}

+

+			return registerCount;

+		}

+		else if(isMatrix())

+		{

+			return getNominalSize();

+		}

+		else

+		{

+			return 1;

+		}

+	}

+

+	int totalRegisterCount() const

+	{

+		if(array)

+		{

+			return arraySize * elementRegisterCount();

+		}

+		else

+		{

+			return elementRegisterCount();

+		}

+	}

+

+    bool isMatrix() const { return matrix ? true : false; }

+    void setMatrix(bool m) { matrix = m; }

+

+    bool isArray() const  { return array ? true : false; }

+    int getArraySize() const { return arraySize; }

+    void setArraySize(int s) { array = true; arraySize = s; }

+    int getMaxArraySize () const { return maxArraySize; }

+    void setMaxArraySize (int s) { maxArraySize = s; }

+    void clearArrayness() { array = false; arraySize = 0; maxArraySize = 0; }

+    void setArrayInformationType(TType* t) { arrayInformationType = t; }

+    TType* getArrayInformationType() const { return arrayInformationType; }

+

+    bool isVector() const { return size > 1 && !matrix; }

+    bool isScalar() const { return size == 1 && !matrix && !structure; }

+	bool isRegister() const { return !matrix && !structure && !array; }   // Fits in a 4-element register

+	bool isStruct() const { return structure != 0; }

+

+    TTypeList* getStruct() const { return structure; }

+    void setStruct(TTypeList* s) { structure = s; computeDeepestStructNesting(); }

+

+    const TString& getTypeName() const

+    {

+        assert(typeName);

+        return *typeName;

+    }

+    void setTypeName(const TString& n)

+    {

+        typeName = NewPoolTString(n.c_str());

+    }

+

+    bool isField() const { return fieldName != 0; }

+    const TString& getFieldName() const

+    {

+        assert(fieldName);

+        return *fieldName;

+    }

+    void setFieldName(const TString& n)

+    {

+        fieldName = NewPoolTString(n.c_str());

+    }

+

+    TString& getMangledName() {

+        if (!mangled) {

+            mangled = NewPoolTString("");

+            buildMangledName(*mangled);

+            *mangled += ';' ;

+        }

+

+        return *mangled;

+    }

+

+    bool sameElementType(const TType& right) const {

+        return      type == right.type   &&

+                    size == right.size   &&

+                  matrix == right.matrix &&

+               structure == right.structure;

+    }

+    bool operator==(const TType& right) const {

+        return      type == right.type   &&

+                    size == right.size   &&

+                  matrix == right.matrix &&

+                   array == right.array  && (!array || arraySize == right.arraySize) &&

+               structure == right.structure;

+        // don't check the qualifier, it's not ever what's being sought after

+    }

+    bool operator!=(const TType& right) const {

+        return !operator==(right);

+    }

+    bool operator<(const TType& right) const {

+        if (type != right.type) return type < right.type;

+        if (size != right.size) return size < right.size;

+        if (matrix != right.matrix) return matrix < right.matrix;

+        if (array != right.array) return array < right.array;

+        if (arraySize != right.arraySize) return arraySize < right.arraySize;

+        if (structure != right.structure) return structure < right.structure;

+

+        return false;

+    }

+

+    const char* getBasicString() const { return ::getBasicString(type); }

+    const char* getPrecisionString() const { return ::getPrecisionString(precision); }

+    const char* getQualifierString() const { return ::getQualifierString(qualifier); }

+    TString getCompleteString() const;

+

+    // If this type is a struct, returns the deepest struct nesting of

+    // any field in the struct. For example:

+    //   struct nesting1 {

+    //     vec4 position;

+    //   };

+    //   struct nesting2 {

+    //     nesting1 field1;

+    //     vec4 field2;

+    //   };

+    // For type "nesting2", this method would return 2 -- the number

+    // of structures through which indirection must occur to reach the

+    // deepest field (nesting2.field1.position).

+    int getDeepestStructNesting() const { return deepestStructNesting; }

+

+    bool isStructureContainingArrays() const;

+

+protected:

+    void buildMangledName(TString&);

+    int getStructSize() const;

+    void computeDeepestStructNesting();

+

+    TBasicType type      : 6;

+    TPrecision precision;

+    TQualifier qualifier : 7;

+    int size             : 8; // size of vector or matrix, not size of array

+    unsigned int matrix  : 1;

+    unsigned int array   : 1;

+    int arraySize;

+    int maxArraySize;

+    TType* arrayInformationType;

+

+    TTypeList* structure;      // 0 unless this is a struct

+    mutable int structureSize;

+    int deepestStructNesting;

+

+    TString *fieldName;         // for structure field names

+    TString *mangled;

+    TString *typeName;          // for structure field type name

+};

+

+//

+// This is a workaround for a problem with the yacc stack,  It can't have

+// types that it thinks have non-trivial constructors.  It should

+// just be used while recognizing the grammar, not anything else.  Pointers

+// could be used, but also trying to avoid lots of memory management overhead.

+//

+// Not as bad as it looks, there is no actual assumption that the fields

+// match up or are name the same or anything like that.

+//

+struct TPublicType

+{

+    TBasicType type;

+    TQualifier qualifier;

+    TPrecision precision;

+    int size;          // size of vector or matrix, not size of array

+    bool matrix;

+    bool array;

+    int arraySize;

+    TType* userDef;

+    int line;

+

+    void setBasic(TBasicType bt, TQualifier q, int ln = 0)

+    {

+        type = bt;

+        qualifier = q;

+        precision = EbpUndefined;

+        size = 1;

+        matrix = false;

+        array = false;

+        arraySize = 0;

+        userDef = 0;

+        line = ln;

+    }

+

+    void setAggregate(int s, bool m = false)

+    {

+        size = s;

+        matrix = m;

+    }

+

+    void setArray(bool a, int s = 0)

+    {

+        array = a;

+        arraySize = s;

+    }

+

+    bool isStructureContainingArrays() const

+    {

+        if (!userDef)

+        {

+            return false;

+        }

+

+        return userDef->isStructureContainingArrays();

+    }

+};

+

+#endif // _TYPES_INCLUDED_

diff --git a/src/GLES2/compiler/ValidateLimitations.cpp b/src/GLES2/compiler/ValidateLimitations.cpp
new file mode 100644
index 0000000..5838d0f
--- /dev/null
+++ b/src/GLES2/compiler/ValidateLimitations.cpp
@@ -0,0 +1,512 @@
+//
+// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "compiler/ValidateLimitations.h"
+#include "compiler/InfoSink.h"
+#include "compiler/InitializeParseContext.h"
+#include "compiler/ParseHelper.h"
+
+namespace {
+bool IsLoopIndex(const TIntermSymbol* symbol, const TLoopStack& stack) {
+    for (TLoopStack::const_iterator i = stack.begin(); i != stack.end(); ++i) {
+        if (i->index.id == symbol->getId())
+            return true;
+    }
+    return false;
+}
+
+void MarkLoopForUnroll(const TIntermSymbol* symbol, TLoopStack& stack) {
+    for (TLoopStack::iterator i = stack.begin(); i != stack.end(); ++i) {
+        if (i->index.id == symbol->getId()) {
+            ASSERT(i->loop != NULL);
+            i->loop->setUnrollFlag(true);
+            return;
+        }
+    }
+    UNREACHABLE();
+}
+
+// Traverses a node to check if it represents a constant index expression.
+// Definition:
+// constant-index-expressions are a superset of constant-expressions.
+// Constant-index-expressions can include loop indices as defined in
+// GLSL ES 1.0 spec, Appendix A, section 4.
+// The following are constant-index-expressions:
+// - Constant expressions
+// - Loop indices as defined in section 4
+// - Expressions composed of both of the above
+class ValidateConstIndexExpr : public TIntermTraverser {
+public:
+    ValidateConstIndexExpr(const TLoopStack& stack)
+        : mValid(true), mLoopStack(stack) {}
+
+    // Returns true if the parsed node represents a constant index expression.
+    bool isValid() const { return mValid; }
+
+    virtual void visitSymbol(TIntermSymbol* symbol) {
+        // Only constants and loop indices are allowed in a
+        // constant index expression.
+        if (mValid) {
+            mValid = (symbol->getQualifier() == EvqConst) ||
+                     IsLoopIndex(symbol, mLoopStack);
+        }
+    }
+
+private:
+    bool mValid;
+    const TLoopStack& mLoopStack;
+};
+
+// Traverses a node to check if it uses a loop index.
+// If an int loop index is used in its body as a sampler array index,
+// mark the loop for unroll.
+class ValidateLoopIndexExpr : public TIntermTraverser {
+public:
+    ValidateLoopIndexExpr(TLoopStack& stack)
+        : mUsesFloatLoopIndex(false),
+          mUsesIntLoopIndex(false),
+          mLoopStack(stack) {}
+
+    bool usesFloatLoopIndex() const { return mUsesFloatLoopIndex; }
+    bool usesIntLoopIndex() const { return mUsesIntLoopIndex; }
+
+    virtual void visitSymbol(TIntermSymbol* symbol) {
+        if (IsLoopIndex(symbol, mLoopStack)) {
+            switch (symbol->getBasicType()) {
+              case EbtFloat:
+                mUsesFloatLoopIndex = true;
+                break;
+              case EbtInt:
+                mUsesIntLoopIndex = true;
+                MarkLoopForUnroll(symbol, mLoopStack);
+                break;
+              default:
+                UNREACHABLE();
+            }
+        }
+    }
+
+private:
+    bool mUsesFloatLoopIndex;
+    bool mUsesIntLoopIndex;
+    TLoopStack& mLoopStack;
+};
+}  // namespace
+
+ValidateLimitations::ValidateLimitations(ShShaderType shaderType,
+                                         TInfoSinkBase& sink)
+    : mShaderType(shaderType),
+      mSink(sink),
+      mNumErrors(0)
+{
+}
+
+bool ValidateLimitations::visitBinary(Visit, TIntermBinary* node)
+{
+    // Check if loop index is modified in the loop body.
+    validateOperation(node, node->getLeft());
+
+    // Check indexing.
+    switch (node->getOp()) {
+      case EOpIndexDirect:
+        validateIndexing(node);
+        break;
+      case EOpIndexIndirect:
+#if defined(__APPLE__)
+        // Loop unrolling is a work-around for a Mac Cg compiler bug where it
+        // crashes when a sampler array's index is also the loop index.
+        // Once Apple fixes this bug, we should remove the code in this CL.
+        // See http://codereview.appspot.com/4331048/.
+        if ((node->getLeft() != NULL) && (node->getRight() != NULL) &&
+            (node->getLeft()->getAsSymbolNode())) {
+            TIntermSymbol* symbol = node->getLeft()->getAsSymbolNode();
+            if (IsSampler(symbol->getBasicType()) && symbol->isArray()) {
+                ValidateLoopIndexExpr validate(mLoopStack);
+                node->getRight()->traverse(&validate);
+                if (validate.usesFloatLoopIndex()) {
+                    error(node->getLine(),
+                          "sampler array index is float loop index",
+                          "for");
+                }
+            }
+        }
+#endif
+        validateIndexing(node);
+        break;
+      default: break;
+    }
+    return true;
+}
+
+bool ValidateLimitations::visitUnary(Visit, TIntermUnary* node)
+{
+    // Check if loop index is modified in the loop body.
+    validateOperation(node, node->getOperand());
+
+    return true;
+}
+
+bool ValidateLimitations::visitAggregate(Visit, TIntermAggregate* node)
+{
+    switch (node->getOp()) {
+      case EOpFunctionCall:
+        validateFunctionCall(node);
+        break;
+      default:
+        break;
+    }
+    return true;
+}
+
+bool ValidateLimitations::visitLoop(Visit, TIntermLoop* node)
+{
+    if (!validateLoopType(node))
+        return false;
+
+    TLoopInfo info;
+    memset(&info, 0, sizeof(TLoopInfo));
+    info.loop = node;
+    if (!validateForLoopHeader(node, &info))
+        return false;
+
+    TIntermNode* body = node->getBody();
+    if (body != NULL) {
+        mLoopStack.push_back(info);
+        body->traverse(this);
+        mLoopStack.pop_back();
+    }
+
+    // The loop is fully processed - no need to visit children.
+    return false;
+}
+
+void ValidateLimitations::error(TSourceLoc loc,
+                                const char *reason, const char* token)
+{
+    mSink.prefix(EPrefixError);
+    mSink.location(loc);
+    mSink << "'" << token << "' : " << reason << "\n";
+    ++mNumErrors;
+}
+
+bool ValidateLimitations::withinLoopBody() const
+{
+    return !mLoopStack.empty();
+}
+
+bool ValidateLimitations::isLoopIndex(const TIntermSymbol* symbol) const
+{
+    return IsLoopIndex(symbol, mLoopStack);
+}
+
+bool ValidateLimitations::validateLoopType(TIntermLoop* node) {
+    TLoopType type = node->getType();
+    if (type == ELoopFor)
+        return true;
+
+    // Reject while and do-while loops.
+    error(node->getLine(),
+          "This type of loop is not allowed",
+          type == ELoopWhile ? "while" : "do");
+    return false;
+}
+
+bool ValidateLimitations::validateForLoopHeader(TIntermLoop* node,
+                                                TLoopInfo* info)
+{
+    ASSERT(node->getType() == ELoopFor);
+
+    //
+    // The for statement has the form:
+    //    for ( init-declaration ; condition ; expression ) statement
+    //
+    if (!validateForLoopInit(node, info))
+        return false;
+    if (!validateForLoopCond(node, info))
+        return false;
+    if (!validateForLoopExpr(node, info))
+        return false;
+
+    return true;
+}
+
+bool ValidateLimitations::validateForLoopInit(TIntermLoop* node,
+                                              TLoopInfo* info)
+{
+    TIntermNode* init = node->getInit();
+    if (init == NULL) {
+        error(node->getLine(), "Missing init declaration", "for");
+        return false;
+    }
+
+    //
+    // init-declaration has the form:
+    //     type-specifier identifier = constant-expression
+    //
+    TIntermAggregate* decl = init->getAsAggregate();
+    if ((decl == NULL) || (decl->getOp() != EOpDeclaration)) {
+        error(init->getLine(), "Invalid init declaration", "for");
+        return false;
+    }
+    // To keep things simple do not allow declaration list.
+    TIntermSequence& declSeq = decl->getSequence();
+    if (declSeq.size() != 1) {
+        error(decl->getLine(), "Invalid init declaration", "for");
+        return false;
+    }
+    TIntermBinary* declInit = declSeq[0]->getAsBinaryNode();
+    if ((declInit == NULL) || (declInit->getOp() != EOpInitialize)) {
+        error(decl->getLine(), "Invalid init declaration", "for");
+        return false;
+    }
+    TIntermSymbol* symbol = declInit->getLeft()->getAsSymbolNode();
+    if (symbol == NULL) {
+        error(declInit->getLine(), "Invalid init declaration", "for");
+        return false;
+    }
+    // The loop index has type int or float.
+    TBasicType type = symbol->getBasicType();
+    if ((type != EbtInt) && (type != EbtFloat)) {
+        error(symbol->getLine(),
+              "Invalid type for loop index", getBasicString(type));
+        return false;
+    }
+    // The loop index is initialized with constant expression.
+    if (!isConstExpr(declInit->getRight())) {
+        error(declInit->getLine(),
+              "Loop index cannot be initialized with non-constant expression",
+              symbol->getSymbol().c_str());
+        return false;
+    }
+
+    info->index.id = symbol->getId();
+    return true;
+}
+
+bool ValidateLimitations::validateForLoopCond(TIntermLoop* node,
+                                              TLoopInfo* info)
+{
+    TIntermNode* cond = node->getCondition();
+    if (cond == NULL) {
+        error(node->getLine(), "Missing condition", "for");
+        return false;
+    }
+    //
+    // condition has the form:
+    //     loop_index relational_operator constant_expression
+    //
+    TIntermBinary* binOp = cond->getAsBinaryNode();
+    if (binOp == NULL) {
+        error(node->getLine(), "Invalid condition", "for");
+        return false;
+    }
+    // Loop index should be to the left of relational operator.
+    TIntermSymbol* symbol = binOp->getLeft()->getAsSymbolNode();
+    if (symbol == NULL) {
+        error(binOp->getLine(), "Invalid condition", "for");
+        return false;
+    }
+    if (symbol->getId() != info->index.id) {
+        error(symbol->getLine(),
+              "Expected loop index", symbol->getSymbol().c_str());
+        return false;
+    }
+    // Relational operator is one of: > >= < <= == or !=.
+    switch (binOp->getOp()) {
+      case EOpEqual:
+      case EOpNotEqual:
+      case EOpLessThan:
+      case EOpGreaterThan:
+      case EOpLessThanEqual:
+      case EOpGreaterThanEqual:
+        break;
+      default:
+        error(binOp->getLine(),
+              "Invalid relational operator",
+              getOperatorString(binOp->getOp()));
+        break;
+    }
+    // Loop index must be compared with a constant.
+    if (!isConstExpr(binOp->getRight())) {
+        error(binOp->getLine(),
+              "Loop index cannot be compared with non-constant expression",
+              symbol->getSymbol().c_str());
+        return false;
+    }
+
+    return true;
+}
+
+bool ValidateLimitations::validateForLoopExpr(TIntermLoop* node,
+                                              TLoopInfo* info)
+{
+    TIntermNode* expr = node->getExpression();
+    if (expr == NULL) {
+        error(node->getLine(), "Missing expression", "for");
+        return false;
+    }
+
+    // for expression has one of the following forms:
+    //     loop_index++
+    //     loop_index--
+    //     loop_index += constant_expression
+    //     loop_index -= constant_expression
+    //     ++loop_index
+    //     --loop_index
+    // The last two forms are not specified in the spec, but I am assuming
+    // its an oversight.
+    TIntermUnary* unOp = expr->getAsUnaryNode();
+    TIntermBinary* binOp = unOp ? NULL : expr->getAsBinaryNode();
+
+    TOperator op = EOpNull;
+    TIntermSymbol* symbol = NULL;
+    if (unOp != NULL) {
+        op = unOp->getOp();
+        symbol = unOp->getOperand()->getAsSymbolNode();
+    } else if (binOp != NULL) {
+        op = binOp->getOp();
+        symbol = binOp->getLeft()->getAsSymbolNode();
+    }
+
+    // The operand must be loop index.
+    if (symbol == NULL) {
+        error(expr->getLine(), "Invalid expression", "for");
+        return false;
+    }
+    if (symbol->getId() != info->index.id) {
+        error(symbol->getLine(),
+              "Expected loop index", symbol->getSymbol().c_str());
+        return false;
+    }
+
+    // The operator is one of: ++ -- += -=.
+    switch (op) {
+        case EOpPostIncrement:
+        case EOpPostDecrement:
+        case EOpPreIncrement:
+        case EOpPreDecrement:
+            ASSERT((unOp != NULL) && (binOp == NULL));
+            break;
+        case EOpAddAssign:
+        case EOpSubAssign:
+            ASSERT((unOp == NULL) && (binOp != NULL));
+            break;
+        default:
+            error(expr->getLine(), "Invalid operator", getOperatorString(op));
+            return false;
+    }
+
+    // Loop index must be incremented/decremented with a constant.
+    if (binOp != NULL) {
+        if (!isConstExpr(binOp->getRight())) {
+            error(binOp->getLine(),
+                  "Loop index cannot be modified by non-constant expression",
+                  symbol->getSymbol().c_str());
+            return false;
+        }
+    }
+
+    return true;
+}
+
+bool ValidateLimitations::validateFunctionCall(TIntermAggregate* node)
+{
+    ASSERT(node->getOp() == EOpFunctionCall);
+
+    // If not within loop body, there is nothing to check.
+    if (!withinLoopBody())
+        return true;
+
+    // List of param indices for which loop indices are used as argument.
+    typedef std::vector<int> ParamIndex;
+    ParamIndex pIndex;
+    TIntermSequence& params = node->getSequence();
+    for (TIntermSequence::size_type i = 0; i < params.size(); ++i) {
+        TIntermSymbol* symbol = params[i]->getAsSymbolNode();
+        if (symbol && isLoopIndex(symbol))
+            pIndex.push_back(i);
+    }
+    // If none of the loop indices are used as arguments,
+    // there is nothing to check.
+    if (pIndex.empty())
+        return true;
+
+    bool valid = true;
+    TSymbolTable& symbolTable = GlobalParseContext->symbolTable;
+    TSymbol* symbol = symbolTable.find(node->getName());
+    ASSERT(symbol && symbol->isFunction());
+    TFunction* function = static_cast<TFunction*>(symbol);
+    for (ParamIndex::const_iterator i = pIndex.begin();
+         i != pIndex.end(); ++i) {
+        const TParameter& param = function->getParam(*i);
+        TQualifier qual = param.type->getQualifier();
+        if ((qual == EvqOut) || (qual == EvqInOut)) {
+            error(params[*i]->getLine(),
+                  "Loop index cannot be used as argument to a function out or inout parameter",
+                  params[*i]->getAsSymbolNode()->getSymbol().c_str());
+            valid = false;
+        }
+    }
+
+    return valid;
+}
+
+bool ValidateLimitations::validateOperation(TIntermOperator* node,
+                                            TIntermNode* operand) {
+    // Check if loop index is modified in the loop body.
+    if (!withinLoopBody() || !node->modifiesState())
+        return true;
+
+    const TIntermSymbol* symbol = operand->getAsSymbolNode();
+    if (symbol && isLoopIndex(symbol)) {
+        error(node->getLine(),
+              "Loop index cannot be statically assigned to within the body of the loop",
+              symbol->getSymbol().c_str());
+    }
+    return true;
+}
+
+bool ValidateLimitations::isConstExpr(TIntermNode* node)
+{
+    ASSERT(node != NULL);
+    return node->getAsConstantUnion() != NULL;
+}
+
+bool ValidateLimitations::isConstIndexExpr(TIntermNode* node)
+{
+    ASSERT(node != NULL);
+
+    ValidateConstIndexExpr validate(mLoopStack);
+    node->traverse(&validate);
+    return validate.isValid();
+}
+
+bool ValidateLimitations::validateIndexing(TIntermBinary* node)
+{
+    ASSERT((node->getOp() == EOpIndexDirect) ||
+           (node->getOp() == EOpIndexIndirect));
+
+    bool valid = true;
+    TIntermTyped* index = node->getRight();
+    // The index expression must have integral type.
+    if (!index->isScalar() || (index->getBasicType() != EbtInt)) {
+        error(index->getLine(),
+              "Index expression must have integral type",
+              index->getCompleteString().c_str());
+        valid = false;
+    }
+    // The index expession must be a constant-index-expression unless
+    // the operand is a uniform in a vertex shader.
+    TIntermTyped* operand = node->getLeft();
+    bool skip = (mShaderType == SH_VERTEX_SHADER) &&
+                (operand->getQualifier() == EvqUniform);
+    if (!skip && !isConstIndexExpr(index)) {
+        error(index->getLine(), "Index expression must be constant", "[]");
+        valid = false;
+    }
+    return valid;
+}
+
diff --git a/src/GLES2/compiler/ValidateLimitations.h b/src/GLES2/compiler/ValidateLimitations.h
new file mode 100644
index 0000000..a835cb3
--- /dev/null
+++ b/src/GLES2/compiler/ValidateLimitations.h
@@ -0,0 +1,59 @@
+//
+// Copyright (c) 2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "GLSLANG/ShaderLang.h"
+#include "compiler/intermediate.h"
+
+class TInfoSinkBase;
+
+struct TLoopInfo {
+    struct TIndex {
+        int id;  // symbol id.
+    } index;
+    TIntermLoop* loop;
+};
+typedef TVector<TLoopInfo> TLoopStack;
+
+// Traverses intermediate tree to ensure that the shader does not exceed the
+// minimum functionality mandated in GLSL 1.0 spec, Appendix A.
+class ValidateLimitations : public TIntermTraverser {
+public:
+    ValidateLimitations(ShShaderType shaderType, TInfoSinkBase& sink);
+
+    int numErrors() const { return mNumErrors; }
+
+    virtual bool visitBinary(Visit, TIntermBinary*);
+    virtual bool visitUnary(Visit, TIntermUnary*);
+    virtual bool visitAggregate(Visit, TIntermAggregate*);
+    virtual bool visitLoop(Visit, TIntermLoop*);
+
+private:
+    void error(TSourceLoc loc, const char *reason, const char* token);
+
+    bool withinLoopBody() const;
+    bool isLoopIndex(const TIntermSymbol* symbol) const;
+    bool validateLoopType(TIntermLoop* node);
+    bool validateForLoopHeader(TIntermLoop* node, TLoopInfo* info);
+    bool validateForLoopInit(TIntermLoop* node, TLoopInfo* info);
+    bool validateForLoopCond(TIntermLoop* node, TLoopInfo* info);
+    bool validateForLoopExpr(TIntermLoop* node, TLoopInfo* info);
+    // Returns true if none of the loop indices is used as the argument to
+    // the given function out or inout parameter.
+    bool validateFunctionCall(TIntermAggregate* node);
+    bool validateOperation(TIntermOperator* node, TIntermNode* operand);
+
+    // Returns true if indexing does not exceed the minimum functionality
+    // mandated in GLSL 1.0 spec, Appendix A, Section 5.
+    bool isConstExpr(TIntermNode* node);
+    bool isConstIndexExpr(TIntermNode* node);
+    bool validateIndexing(TIntermBinary* node);
+
+    ShShaderType mShaderType;
+    TInfoSinkBase& mSink;
+    int mNumErrors;
+    TLoopStack mLoopStack;
+};
+
diff --git a/src/GLES2/compiler/VariableInfo.cpp b/src/GLES2/compiler/VariableInfo.cpp
new file mode 100644
index 0000000..071d05e
--- /dev/null
+++ b/src/GLES2/compiler/VariableInfo.cpp
@@ -0,0 +1,210 @@
+//
+// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "compiler/VariableInfo.h"
+
+static TString arrayBrackets(int index)
+{
+    TStringStream stream;
+    stream << "[" << index << "]";
+    return stream.str();
+}
+
+// Returns the data type for an attribute or uniform.
+static ShDataType getVariableDataType(const TType& type)
+{
+    switch (type.getBasicType()) {
+      case EbtFloat:
+          if (type.isMatrix()) {
+              switch (type.getNominalSize()) {
+                case 2: return SH_FLOAT_MAT2;
+                case 3: return SH_FLOAT_MAT3;
+                case 4: return SH_FLOAT_MAT4;
+                default: UNREACHABLE();
+              }
+          } else if (type.isVector()) {
+              switch (type.getNominalSize()) {
+                case 2: return SH_FLOAT_VEC2;
+                case 3: return SH_FLOAT_VEC3;
+                case 4: return SH_FLOAT_VEC4;
+                default: UNREACHABLE();
+              }
+          } else {
+              return SH_FLOAT;
+          }
+      case EbtInt:
+          if (type.isMatrix()) {
+              UNREACHABLE();
+          } else if (type.isVector()) {
+              switch (type.getNominalSize()) {
+                case 2: return SH_INT_VEC2;
+                case 3: return SH_INT_VEC3;
+                case 4: return SH_INT_VEC4;
+                default: UNREACHABLE();
+              }
+          } else {
+              return SH_INT;
+          }
+      case EbtBool:
+          if (type.isMatrix()) {
+              UNREACHABLE();
+          } else if (type.isVector()) {
+              switch (type.getNominalSize()) {
+                case 2: return SH_BOOL_VEC2;
+                case 3: return SH_BOOL_VEC3;
+                case 4: return SH_BOOL_VEC4;
+                default: UNREACHABLE();
+              }
+          } else {
+              return SH_BOOL;
+          }
+      case EbtSampler2D: return SH_SAMPLER_2D;
+      case EbtSamplerCube: return SH_SAMPLER_CUBE;
+      default: UNREACHABLE();
+    }
+    return SH_NONE;
+}
+
+static void getBuiltInVariableInfo(const TType& type,
+                                   const TString& name,
+                                   TVariableInfoList& infoList);
+static void getUserDefinedVariableInfo(const TType& type,
+                                       const TString& name,
+                                       TVariableInfoList& infoList);
+
+// Returns info for an attribute or uniform.
+static void getVariableInfo(const TType& type,
+                            const TString& name,
+                            TVariableInfoList& infoList)
+{
+    if (type.getBasicType() == EbtStruct) {
+        if (type.isArray()) {
+            for (int i = 0; i < type.getArraySize(); ++i) {
+                TString lname = name + arrayBrackets(i);
+                getUserDefinedVariableInfo(type, lname, infoList);
+            }
+        } else {
+            getUserDefinedVariableInfo(type, name, infoList);
+        }
+    } else {
+        getBuiltInVariableInfo(type, name, infoList);
+    }
+}
+
+void getBuiltInVariableInfo(const TType& type,
+                            const TString& name,
+                            TVariableInfoList& infoList)
+{
+    ASSERT(type.getBasicType() != EbtStruct);
+
+    TVariableInfo varInfo;
+    if (type.isArray()) {
+        varInfo.name = (name + "[0]").c_str();
+        varInfo.size = type.getArraySize();
+    } else {
+        varInfo.name = name.c_str();
+        varInfo.size = 1;
+    }
+    varInfo.type = getVariableDataType(type);
+    infoList.push_back(varInfo);
+}
+
+void getUserDefinedVariableInfo(const TType& type,
+                                const TString& name,
+                                TVariableInfoList& infoList)
+{
+    ASSERT(type.getBasicType() == EbtStruct);
+
+    const TTypeList* structure = type.getStruct();
+    for (size_t i = 0; i < structure->size(); ++i) {
+        const TType* fieldType = (*structure)[i].type;
+        getVariableInfo(*fieldType,
+                        name + "." + fieldType->getFieldName(),
+                        infoList);
+    }
+}
+
+CollectAttribsUniforms::CollectAttribsUniforms(TVariableInfoList& attribs,
+                                               TVariableInfoList& uniforms)
+    : mAttribs(attribs),
+      mUniforms(uniforms)
+{
+}
+
+// We are only interested in attribute and uniform variable declaration.
+void CollectAttribsUniforms::visitSymbol(TIntermSymbol*)
+{
+}
+
+void CollectAttribsUniforms::visitConstantUnion(TIntermConstantUnion*)
+{
+}
+
+bool CollectAttribsUniforms::visitBinary(Visit, TIntermBinary*)
+{
+    return false;
+}
+
+bool CollectAttribsUniforms::visitUnary(Visit, TIntermUnary*)
+{
+    return false;
+}
+
+bool CollectAttribsUniforms::visitSelection(Visit, TIntermSelection*)
+{
+    return false;
+}
+
+bool CollectAttribsUniforms::visitAggregate(Visit, TIntermAggregate* node)
+{
+    bool visitChildren = false;
+
+    switch (node->getOp())
+    {
+    case EOpSequence:
+        // We need to visit sequence children to get to variable declarations.
+        visitChildren = true;
+        break;
+    case EOpDeclaration: {
+        const TIntermSequence& sequence = node->getSequence();
+        TQualifier qualifier = sequence.front()->getAsTyped()->getQualifier();
+        if (qualifier == EvqAttribute || qualifier == EvqUniform)
+        {
+            TVariableInfoList& infoList = qualifier == EvqAttribute ?
+                mAttribs : mUniforms;
+            for (TIntermSequence::const_iterator i = sequence.begin();
+                 i != sequence.end(); ++i)
+            {
+                const TIntermSymbol* variable = (*i)->getAsSymbolNode();
+                // The only case in which the sequence will not contain a
+                // TIntermSymbol node is initialization. It will contain a
+                // TInterBinary node in that case. Since attributes and unifroms
+                // cannot be initialized in a shader, we must have only
+                // TIntermSymbol nodes in the sequence.
+                ASSERT(variable != NULL);
+                getVariableInfo(variable->getType(),
+                                variable->getSymbol(),
+                                infoList);
+            }
+        }
+        break;
+    }
+    default: break;
+    }
+
+    return visitChildren;
+}
+
+bool CollectAttribsUniforms::visitLoop(Visit, TIntermLoop*)
+{
+    return false;
+}
+
+bool CollectAttribsUniforms::visitBranch(Visit, TIntermBranch*)
+{
+    return false;
+}
+
diff --git a/src/GLES2/compiler/VariableInfo.h b/src/GLES2/compiler/VariableInfo.h
new file mode 100644
index 0000000..77902d9
--- /dev/null
+++ b/src/GLES2/compiler/VariableInfo.h
@@ -0,0 +1,42 @@
+//
+// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#ifndef COMPILER_VARIABLE_INFO_H_
+#define COMPILER_VARIABLE_INFO_H_
+
+#include "GLSLANG/ShaderLang.h"
+#include "compiler/intermediate.h"
+
+// Provides information about a variable.
+// It is currently being used to store info about active attribs and uniforms.
+struct TVariableInfo {
+    TPersistString name;
+    ShDataType type;
+    int size;
+};
+typedef std::vector<TVariableInfo> TVariableInfoList;
+
+// Traverses intermediate tree to collect all attributes and uniforms.
+class CollectAttribsUniforms : public TIntermTraverser {
+public:
+    CollectAttribsUniforms(TVariableInfoList& attribs,
+                           TVariableInfoList& uniforms);
+
+    virtual void visitSymbol(TIntermSymbol*);
+    virtual void visitConstantUnion(TIntermConstantUnion*);
+    virtual bool visitBinary(Visit, TIntermBinary*);
+    virtual bool visitUnary(Visit, TIntermUnary*);
+    virtual bool visitSelection(Visit, TIntermSelection*);
+    virtual bool visitAggregate(Visit, TIntermAggregate*);
+    virtual bool visitLoop(Visit, TIntermLoop*);
+    virtual bool visitBranch(Visit, TIntermBranch*);
+
+private:
+    TVariableInfoList& mAttribs;
+    TVariableInfoList& mUniforms;
+};
+
+#endif  // COMPILER_VARIABLE_INFO_H_
diff --git a/src/GLES2/compiler/debug.cpp b/src/GLES2/compiler/debug.cpp
new file mode 100644
index 0000000..53778bd
--- /dev/null
+++ b/src/GLES2/compiler/debug.cpp
@@ -0,0 +1,37 @@
+//
+// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// debug.cpp: Debugging utilities.
+
+#include "compiler/debug.h"
+
+#include <stdarg.h>
+#include <stdio.h>
+
+#include "compiler/InitializeParseContext.h"
+#include "compiler/ParseHelper.h"
+
+static const int kTraceBufferLen = 1024;
+
+#ifdef TRACE_ENABLED
+extern "C" {
+void Trace(const char *format, ...) {
+    if (!format) return;
+
+    TParseContext* parseContext = GetGlobalParseContext();
+    if (parseContext) {
+        char buf[kTraceBufferLen];
+        va_list args;
+        va_start(args, format);
+        vsnprintf(buf, kTraceBufferLen, format, args);
+        va_end(args);
+
+        parseContext->trace(buf);
+    }
+}
+}  // extern "C"
+#endif  // TRACE_ENABLED
+
diff --git a/src/GLES2/compiler/debug.h b/src/GLES2/compiler/debug.h
new file mode 100644
index 0000000..7a37151
--- /dev/null
+++ b/src/GLES2/compiler/debug.h
@@ -0,0 +1,53 @@
+//
+// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// debug.h: Debugging utilities.
+
+#ifndef COMPILER_DEBUG_H_
+#define COMPILER_DEBUG_H_
+
+#include <assert.h>
+
+#ifdef _DEBUG
+#define TRACE_ENABLED  // define to enable debug message tracing
+#endif  // _DEBUG
+
+// Outputs text to the debug log
+#ifdef TRACE_ENABLED
+
+#ifdef  __cplusplus
+extern "C" {
+#endif  // __cplusplus
+void Trace(const char* format, ...);
+#ifdef  __cplusplus
+}
+#endif  // __cplusplus
+
+#else   // TRACE_ENABLED
+
+#define Trace(...) ((void)0)
+
+#endif  // TRACE_ENABLED
+
+// A macro asserting a condition and outputting failures to the debug log
+#define ASSERT(expression) do { \
+    if(!(expression)) \
+        Trace("Assert failed: %s(%d): "#expression"\n", __FUNCTION__, __LINE__); \
+    assert(expression); \
+} while(0)
+
+#define UNIMPLEMENTED() do { \
+    Trace("Unimplemented invoked: %s(%d)\n", __FUNCTION__, __LINE__); \
+    assert(false); \
+} while(0)
+
+#define UNREACHABLE() do { \
+    Trace("Unreachable reached: %s(%d)\n", __FUNCTION__, __LINE__); \
+    assert(false); \
+} while(0)
+
+#endif   // COMPILER_DEBUG_H_
+
diff --git a/src/GLES2/compiler/generate_parser.sh b/src/GLES2/compiler/generate_parser.sh
new file mode 100644
index 0000000..e472191
--- /dev/null
+++ b/src/GLES2/compiler/generate_parser.sh
@@ -0,0 +1,27 @@
+#!/bin/bash
+# Copyright (c) 2010 The ANGLE Project Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+# Generates GLSL ES parser - glslang_lex.cpp, glslang_tab.h, and glslang_tab.cpp
+
+run_flex()
+{
+input_file=$script_dir/$1.l
+output_source=$script_dir/$1_lex.cpp
+flex --noline --nounistd --outfile=$output_source $input_file
+}
+
+run_bison()
+{
+input_file=$script_dir/$1.y
+output_header=$script_dir/$1_tab.h
+output_source=$script_dir/$1_tab.cpp
+bison --no-lines --skeleton=yacc.c --defines=$output_header --output=$output_source $input_file
+}
+
+script_dir=$(dirname $0)
+
+# Generate Parser
+run_flex glslang
+run_bison glslang
diff --git a/src/GLES2/compiler/glslang.h b/src/GLES2/compiler/glslang.h
new file mode 100644
index 0000000..8e2d4d6
--- /dev/null
+++ b/src/GLES2/compiler/glslang.h
@@ -0,0 +1,16 @@
+//
+// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+struct TParseContext;
+extern int glslang_initialize(TParseContext* context);
+extern int glslang_finalize(TParseContext* context);
+
+extern int glslang_scan(int count,
+                        const char* const string[],
+                        const int length[],
+                        TParseContext* context);
+extern int glslang_parse(TParseContext* context);
+
diff --git a/src/GLES2/compiler/glslang.l b/src/GLES2/compiler/glslang.l
new file mode 100644
index 0000000..ca29a62
--- /dev/null
+++ b/src/GLES2/compiler/glslang.l
@@ -0,0 +1,365 @@
+/*
+//
+// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+This file contains the Lex specification for GLSL ES.
+Based on ANSI C grammar, Lex specification:
+http://www.lysator.liu.se/c/ANSI-C-grammar-l.html
+
+IF YOU MODIFY THIS FILE YOU ALSO NEED TO RUN generate_parser.sh,
+WHICH GENERATES THE GLSL ES LEXER (glslang_lex.cpp).
+*/
+
+%top{
+//
+// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// This file is auto-generated by generate_parser.sh. DO NOT EDIT!
+
+// Ignore errors in auto-generated code.
+#if defined(__GNUC__)
+#pragma GCC diagnostic ignored "-Wunused-function"
+#pragma GCC diagnostic ignored "-Wunused-variable"
+#pragma GCC diagnostic ignored "-Wswitch-enum"
+#elif defined(_MSC_VER)
+#pragma warning(disable: 4065)
+#pragma warning(disable: 4189)
+#pragma warning(disable: 4505)
+#pragma warning(disable: 4701)
+#endif
+}
+
+%{
+#include "compiler/glslang.h"
+#include "compiler/ParseHelper.h"
+#include "compiler/preprocessor/Token.h"
+#include "compiler/util.h"
+#include "glslang_tab.h"
+
+/* windows only pragma */
+#ifdef _MSC_VER
+#pragma warning(disable : 4102)
+#endif
+
+#define YY_USER_ACTION yylval->lex.line = yylineno;
+#define YY_INPUT(buf, result, max_size) \
+    result = string_input(buf, max_size, yyscanner);
+
+static int string_input(char* buf, int max_size, yyscan_t yyscanner);
+static int check_type(yyscan_t yyscanner);
+static int reserved_word(yyscan_t yyscanner);
+%}
+
+%option noyywrap nounput never-interactive
+%option yylineno reentrant bison-bridge
+%option stack
+%option extra-type="TParseContext*"
+%x COMMENT FIELDS
+
+D           [0-9]
+L           [a-zA-Z_]
+H           [a-fA-F0-9]
+E           [Ee][+-]?{D}+
+O           [0-7]
+
+%%
+
+%{
+    TParseContext* context = yyextra;
+%}
+
+    /* Single-line comments */
+"//"[^\n]* ;
+
+    /* Multi-line comments */
+"/*"           { yy_push_state(COMMENT, yyscanner); }
+<COMMENT>. |
+<COMMENT>\n ;
+<COMMENT>"*/"  { yy_pop_state(yyscanner); }
+
+"invariant"    { return(INVARIANT); }
+"highp"        { return(HIGH_PRECISION); }
+"mediump"      { return(MEDIUM_PRECISION); }
+"lowp"         { return(LOW_PRECISION); }
+"precision"    { return(PRECISION); }
+
+"attribute"    { return(ATTRIBUTE); }
+"const"        { return(CONST_QUAL); }
+"uniform"      { return(UNIFORM); }
+"varying"      { return(VARYING); }
+
+"break"        { return(BREAK); }
+"continue"     { return(CONTINUE); }
+"do"           { return(DO); }
+"for"          { return(FOR); }
+"while"        { return(WHILE); }
+
+"if"           { return(IF); }
+"else"         { return(ELSE); }
+
+"in"           { return(IN_QUAL); }
+"out"          { return(OUT_QUAL); }
+"inout"        { return(INOUT_QUAL); }
+
+"float"        { context->lexAfterType = true; return(FLOAT_TYPE); }
+"int"          { context->lexAfterType = true; return(INT_TYPE); }
+"void"         { context->lexAfterType = true; return(VOID_TYPE); }
+"bool"         { context->lexAfterType = true; return(BOOL_TYPE); }
+"true"         { yylval->lex.b = true;  return(BOOLCONSTANT); }
+"false"        { yylval->lex.b = false; return(BOOLCONSTANT); }
+
+"discard"      { return(DISCARD); }
+"return"       { return(RETURN); }
+
+"mat2"         { context->lexAfterType = true; return(MATRIX2); }
+"mat3"         { context->lexAfterType = true; return(MATRIX3); }
+"mat4"         { context->lexAfterType = true; return(MATRIX4); }
+
+"vec2"         { context->lexAfterType = true; return (VEC2); }
+"vec3"         { context->lexAfterType = true; return (VEC3); }
+"vec4"         { context->lexAfterType = true; return (VEC4); }
+"ivec2"        { context->lexAfterType = true; return (IVEC2); }
+"ivec3"        { context->lexAfterType = true; return (IVEC3); }
+"ivec4"        { context->lexAfterType = true; return (IVEC4); }
+"bvec2"        { context->lexAfterType = true; return (BVEC2); }
+"bvec3"        { context->lexAfterType = true; return (BVEC3); }
+"bvec4"        { context->lexAfterType = true; return (BVEC4); }
+
+"sampler2D"       { context->lexAfterType = true; return SAMPLER2D; }
+"samplerCube"     { context->lexAfterType = true; return SAMPLERCUBE; }
+
+"struct"       { context->lexAfterType = true; return(STRUCT); }
+
+"asm"          { return reserved_word(yyscanner); }
+
+"class"        { return reserved_word(yyscanner); }
+"union"        { return reserved_word(yyscanner); }
+"enum"         { return reserved_word(yyscanner); }
+"typedef"      { return reserved_word(yyscanner); }
+"template"     { return reserved_word(yyscanner); }
+"this"         { return reserved_word(yyscanner); }
+"packed"       { return reserved_word(yyscanner); }
+
+"goto"         { return reserved_word(yyscanner); }
+"switch"       { return reserved_word(yyscanner); }
+"default"      { return reserved_word(yyscanner); }
+
+"inline"       { return reserved_word(yyscanner); }
+"noinline"     { return reserved_word(yyscanner); }
+"volatile"     { return reserved_word(yyscanner); }
+"public"       { return reserved_word(yyscanner); }
+"static"       { return reserved_word(yyscanner); }
+"extern"       { return reserved_word(yyscanner); }
+"external"     { return reserved_word(yyscanner); }
+"interface"    { return reserved_word(yyscanner); }
+"flat"         { return reserved_word(yyscanner); }
+
+"long"         { return reserved_word(yyscanner); }
+"short"        { return reserved_word(yyscanner); }
+"double"       { return reserved_word(yyscanner); }
+"half"         { return reserved_word(yyscanner); }
+"fixed"        { return reserved_word(yyscanner); }
+"unsigned"     { return reserved_word(yyscanner); }
+"superp"       { return reserved_word(yyscanner); }
+
+"input"        { return reserved_word(yyscanner); }
+"output"       { return reserved_word(yyscanner); }
+
+"hvec2"        { return reserved_word(yyscanner); }
+"hvec3"        { return reserved_word(yyscanner); }
+"hvec4"        { return reserved_word(yyscanner); }
+"dvec2"        { return reserved_word(yyscanner); }
+"dvec3"        { return reserved_word(yyscanner); }
+"dvec4"        { return reserved_word(yyscanner); }
+"fvec2"        { return reserved_word(yyscanner); }
+"fvec3"        { return reserved_word(yyscanner); }
+"fvec4"        { return reserved_word(yyscanner); }
+
+"sampler1D"    { return reserved_word(yyscanner); }
+"sampler3D"    { return reserved_word(yyscanner); }
+
+"sampler1DShadow" { return reserved_word(yyscanner); }
+"sampler2DShadow" { return reserved_word(yyscanner); }
+
+"sampler2DRect" { return reserved_word(yyscanner); }
+"sampler3DRect" { return reserved_word(yyscanner); }
+"sampler2DRectShadow" { return reserved_word(yyscanner); }
+
+"sizeof"       { return reserved_word(yyscanner); }
+"cast"         { return reserved_word(yyscanner); }
+
+"namespace"    { return reserved_word(yyscanner); }
+"using"        { return reserved_word(yyscanner); }
+
+{L}({L}|{D})*       {
+   yylval->lex.string = NewPoolTString(yytext); 
+   return check_type(yyscanner);
+}
+
+0[xX]{H}+         { yylval->lex.i = strtol(yytext, 0, 0); return(INTCONSTANT); }
+0{O}+             { yylval->lex.i = strtol(yytext, 0, 0); return(INTCONSTANT); }
+0{D}+             { context->error(yylineno, "Invalid Octal number.", yytext); context->recover(); return 0;}
+{D}+              { yylval->lex.i = strtol(yytext, 0, 0); return(INTCONSTANT); }
+
+{D}+{E}           { yylval->lex.f = static_cast<float>(atof_dot(yytext)); return(FLOATCONSTANT); }
+{D}+"."{D}*({E})? { yylval->lex.f = static_cast<float>(atof_dot(yytext)); return(FLOATCONSTANT); }
+"."{D}+({E})?     { yylval->lex.f = static_cast<float>(atof_dot(yytext)); return(FLOATCONSTANT); }
+
+"+="            {  return(ADD_ASSIGN); }
+"-="            {  return(SUB_ASSIGN); }
+"*="            {  return(MUL_ASSIGN); }
+"/="            {  return(DIV_ASSIGN); }
+"%="            {  return(MOD_ASSIGN); }
+"<<="           {  return(LEFT_ASSIGN); }
+">>="           {  return(RIGHT_ASSIGN); }
+"&="            {  return(AND_ASSIGN); }
+"^="            {  return(XOR_ASSIGN); }
+"|="            {  return(OR_ASSIGN); }
+
+"++"            {  return(INC_OP); }
+"--"            {  return(DEC_OP); }
+"&&"            {  return(AND_OP); }
+"||"            {  return(OR_OP); }
+"^^"            {  return(XOR_OP); }
+"<="            {  return(LE_OP); }
+">="            {  return(GE_OP); }
+"=="            {  return(EQ_OP); }
+"!="            {  return(NE_OP); }
+"<<"            {  return(LEFT_OP); }
+">>"            {  return(RIGHT_OP); }
+";"             { context->lexAfterType = false; return(SEMICOLON); }
+("{"|"<%")      { context->lexAfterType = false; return(LEFT_BRACE); }
+("}"|"%>")      { return(RIGHT_BRACE); }
+","         { if (context->inTypeParen) context->lexAfterType = false; return(COMMA); }
+":"         { return(COLON); }
+"="         { context->lexAfterType = false; return(EQUAL); }
+"("         { context->lexAfterType = false; context->inTypeParen = true; return(LEFT_PAREN); }
+")"         { context->inTypeParen = false; return(RIGHT_PAREN); }
+("["|"<:")      { return(LEFT_BRACKET); }
+("]"|":>")      { return(RIGHT_BRACKET); }
+"."         { BEGIN(FIELDS);  return(DOT); }
+"!"         { return(BANG); }
+"-"         { return(DASH); }
+"~"         { return(TILDE); }
+"+"         { return(PLUS); }
+"*"         { return(STAR); }
+"/"         { return(SLASH); }
+"%"         { return(PERCENT); }
+"<"         { return(LEFT_ANGLE); }
+">"         { return(RIGHT_ANGLE); }
+"|"         { return(VERTICAL_BAR); }
+"^"         { return(CARET); }
+"&"         { return(AMPERSAND); }
+"?"         { return(QUESTION); }
+
+<FIELDS>{L}({L}|{D})* { 
+    BEGIN(INITIAL);
+    yylval->lex.string = NewPoolTString(yytext); 
+    return FIELD_SELECTION;
+}
+<FIELDS>[ \t\v\f\r] {}
+
+[ \t\v\n\f\r]   {  }
+<*><<EOF>>      { context->AfterEOF = true; yyterminate(); }
+<*>.            { context->warning(yylineno, "Unknown char", yytext, ""); return 0; }
+
+%%
+
+int string_input(char* buf, int max_size, yyscan_t yyscanner)
+{
+    int len = 0;
+
+    pp::Token token;
+    yyget_extra(yyscanner)->preprocessor.lex(&token);
+    len = token.type == pp::Token::LAST ? 0 : token.text.size();
+    if ((len > 0) && (len < max_size))
+        memcpy(buf, token.text.c_str(), len);
+    yyset_lineno(EncodeSourceLoc(token.location.file, token.location.line), yyscanner);
+
+    if (len >= max_size)
+        YY_FATAL_ERROR("Input buffer overflow");
+    else if (len > 0)
+        buf[len++] = ' ';
+    return len;
+}
+
+int check_type(yyscan_t yyscanner) {
+    struct yyguts_t* yyg = (struct yyguts_t*) yyscanner;
+    
+    int token = IDENTIFIER;
+    TSymbol* symbol = yyextra->symbolTable.find(yytext);
+    if (yyextra->lexAfterType == false && symbol && symbol->isVariable()) {
+        TVariable* variable = static_cast<TVariable*>(symbol);
+        if (variable->isUserType()) {
+            yyextra->lexAfterType = true;
+            token = TYPE_NAME;
+        }
+    }
+    yylval->lex.symbol = symbol;
+    return token;
+}
+
+int reserved_word(yyscan_t yyscanner) {
+    struct yyguts_t* yyg = (struct yyguts_t*) yyscanner;
+
+    yyextra->error(yylineno, "Illegal use of reserved word", yytext, "");
+    yyextra->recover();
+    return 0;
+}
+
+void yyerror(TParseContext* context, const char* reason) {
+    struct yyguts_t* yyg = (struct yyguts_t*) context->scanner;
+
+    if (context->AfterEOF) {
+        context->error(yylineno, reason, "unexpected EOF");
+    } else {
+        context->error(yylineno, reason, yytext);
+    }
+    context->recover();
+}
+
+int glslang_initialize(TParseContext* context) {
+    yyscan_t scanner = NULL;
+    if (yylex_init_extra(context, &scanner))
+        return 1;
+
+    context->scanner = scanner;
+    return 0;
+}
+
+int glslang_finalize(TParseContext* context) {
+    yyscan_t scanner = context->scanner;
+    if (scanner == NULL) return 0;
+    
+    context->scanner = NULL;
+    yylex_destroy(scanner);
+
+    return 0;
+}
+
+int glslang_scan(int count, const char* const string[], const int length[],
+                 TParseContext* context) {
+    yyrestart(NULL, context->scanner);
+    yyset_lineno(EncodeSourceLoc(0, 1), context->scanner);
+    context->AfterEOF = false;
+
+    // Initialize preprocessor.
+    if (!context->preprocessor.init(count, string, length))
+        return 1;
+
+    // Define extension macros.
+    const TExtensionBehavior& extBehavior = context->extensionBehavior();
+    for (TExtensionBehavior::const_iterator iter = extBehavior.begin();
+         iter != extBehavior.end(); ++iter)
+    {
+        context->preprocessor.predefineMacro(iter->first.c_str(), 1);
+    }
+    return 0;
+}
+
diff --git a/src/GLES2/compiler/glslang.y b/src/GLES2/compiler/glslang.y
new file mode 100644
index 0000000..ba8a0b8
--- /dev/null
+++ b/src/GLES2/compiler/glslang.y
@@ -0,0 +1,2124 @@
+/*
+//
+// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+This file contains the Yacc grammar for GLSL ES.
+Based on ANSI C Yacc grammar:
+http://www.lysator.liu.se/c/ANSI-C-grammar-y.html
+
+IF YOU MODIFY THIS FILE YOU ALSO NEED TO RUN generate_parser.sh,
+WHICH GENERATES THE GLSL ES PARSER (glslang_tab.cpp AND glslang_tab.h).
+*/
+
+%{
+//
+// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// This file is auto-generated by generate_parser.sh. DO NOT EDIT!
+
+// Ignore errors in auto-generated code.
+#if defined(__GNUC__)
+#pragma GCC diagnostic ignored "-Wunused-function"
+#pragma GCC diagnostic ignored "-Wunused-variable"
+#pragma GCC diagnostic ignored "-Wswitch-enum"
+#elif defined(_MSC_VER)
+#pragma warning(disable: 4065)
+#pragma warning(disable: 4189)
+#pragma warning(disable: 4505)
+#pragma warning(disable: 4701)
+#endif
+
+#include "compiler/SymbolTable.h"
+#include "compiler/ParseHelper.h"
+#include "GLSLANG/ShaderLang.h"
+
+#define YYLEX_PARAM context->scanner
+%}
+
+%expect 1 /* One shift reduce conflict because of if | else */
+%pure-parser
+%parse-param {TParseContext* context}
+
+%union {
+    struct {
+        TSourceLoc line;
+        union {
+            TString *string;
+            float f;
+            int i;
+            bool b;
+        };
+        TSymbol* symbol;
+    } lex;
+    struct {
+        TSourceLoc line;
+        TOperator op;
+        union {
+            TIntermNode* intermNode;
+            TIntermNodePair nodePair;
+            TIntermTyped* intermTypedNode;
+            TIntermAggregate* intermAggregate;
+        };
+        union {
+            TPublicType type;
+            TPrecision precision;
+            TQualifier qualifier;
+            TFunction* function;
+            TParameter param;
+            TTypeLine typeLine;
+            TTypeList* typeList;
+        };
+    } interm;
+}
+
+%{
+extern int yylex(YYSTYPE* yylval_param, void* yyscanner);
+extern void yyerror(TParseContext* context, const char* reason);
+
+#define FRAG_VERT_ONLY(S, L) {  \
+    if (context->shaderType != SH_FRAGMENT_SHADER &&  \
+        context->shaderType != SH_VERTEX_SHADER) {  \
+        context->error(L, " supported in vertex/fragment shaders only ", S);  \
+        context->recover();  \
+    }  \
+}
+
+#define VERTEX_ONLY(S, L) {  \
+    if (context->shaderType != SH_VERTEX_SHADER) {  \
+        context->error(L, " supported in vertex shaders only ", S);  \
+        context->recover();  \
+    }  \
+}
+
+#define FRAG_ONLY(S, L) {  \
+    if (context->shaderType != SH_FRAGMENT_SHADER) {  \
+        context->error(L, " supported in fragment shaders only ", S);  \
+        context->recover();  \
+    }  \
+}
+%}
+
+%token <lex> INVARIANT HIGH_PRECISION MEDIUM_PRECISION LOW_PRECISION PRECISION
+%token <lex> ATTRIBUTE CONST_QUAL BOOL_TYPE FLOAT_TYPE INT_TYPE
+%token <lex> BREAK CONTINUE DO ELSE FOR IF DISCARD RETURN
+%token <lex> BVEC2 BVEC3 BVEC4 IVEC2 IVEC3 IVEC4 VEC2 VEC3 VEC4
+%token <lex> MATRIX2 MATRIX3 MATRIX4 IN_QUAL OUT_QUAL INOUT_QUAL UNIFORM VARYING
+%token <lex> STRUCT VOID_TYPE WHILE
+%token <lex> SAMPLER2D SAMPLERCUBE
+
+%token <lex> IDENTIFIER TYPE_NAME FLOATCONSTANT INTCONSTANT BOOLCONSTANT
+%token <lex> FIELD_SELECTION
+%token <lex> LEFT_OP RIGHT_OP
+%token <lex> INC_OP DEC_OP LE_OP GE_OP EQ_OP NE_OP
+%token <lex> AND_OP OR_OP XOR_OP MUL_ASSIGN DIV_ASSIGN ADD_ASSIGN
+%token <lex> MOD_ASSIGN LEFT_ASSIGN RIGHT_ASSIGN AND_ASSIGN XOR_ASSIGN OR_ASSIGN
+%token <lex> SUB_ASSIGN
+
+%token <lex> LEFT_PAREN RIGHT_PAREN LEFT_BRACKET RIGHT_BRACKET LEFT_BRACE RIGHT_BRACE DOT
+%token <lex> COMMA COLON EQUAL SEMICOLON BANG DASH TILDE PLUS STAR SLASH PERCENT
+%token <lex> LEFT_ANGLE RIGHT_ANGLE VERTICAL_BAR CARET AMPERSAND QUESTION
+
+%type <interm> assignment_operator unary_operator
+%type <interm.intermTypedNode> variable_identifier primary_expression postfix_expression
+%type <interm.intermTypedNode> expression integer_expression assignment_expression
+%type <interm.intermTypedNode> unary_expression multiplicative_expression additive_expression
+%type <interm.intermTypedNode> relational_expression equality_expression
+%type <interm.intermTypedNode> conditional_expression constant_expression
+%type <interm.intermTypedNode> logical_or_expression logical_xor_expression logical_and_expression
+%type <interm.intermTypedNode> shift_expression and_expression exclusive_or_expression inclusive_or_expression
+%type <interm.intermTypedNode> function_call initializer condition conditionopt
+
+%type <interm.intermNode> translation_unit function_definition
+%type <interm.intermNode> statement simple_statement
+%type <interm.intermAggregate>  statement_list compound_statement
+%type <interm.intermNode> declaration_statement selection_statement expression_statement
+%type <interm.intermNode> declaration external_declaration
+%type <interm.intermNode> for_init_statement compound_statement_no_new_scope
+%type <interm.nodePair> selection_rest_statement for_rest_statement
+%type <interm.intermNode> iteration_statement jump_statement statement_no_new_scope statement_with_scope
+%type <interm> single_declaration init_declarator_list
+
+%type <interm> parameter_declaration parameter_declarator parameter_type_specifier
+%type <interm.qualifier> parameter_qualifier
+
+%type <interm.precision> precision_qualifier
+%type <interm.type> type_qualifier fully_specified_type type_specifier
+%type <interm.type> type_specifier_no_prec type_specifier_nonarray
+%type <interm.type> struct_specifier
+%type <interm.typeLine> struct_declarator
+%type <interm.typeList> struct_declarator_list struct_declaration struct_declaration_list
+%type <interm.function> function_header function_declarator function_identifier
+%type <interm.function> function_header_with_parameters function_call_header
+%type <interm> function_call_header_with_parameters function_call_header_no_parameters function_call_generic function_prototype
+%type <interm> function_call_or_method
+
+%start translation_unit
+%%
+
+variable_identifier
+    : IDENTIFIER {
+        // The symbol table search was done in the lexical phase
+        const TSymbol* symbol = $1.symbol;
+        const TVariable* variable;
+        if (symbol == 0) {
+            context->error($1.line, "undeclared identifier", $1.string->c_str());
+            context->recover();
+            TType type(EbtFloat, EbpUndefined);
+            TVariable* fakeVariable = new TVariable($1.string, type);
+            context->symbolTable.insert(*fakeVariable);
+            variable = fakeVariable;
+        } else {
+            // This identifier can only be a variable type symbol
+            if (! symbol->isVariable()) {
+                context->error($1.line, "variable expected", $1.string->c_str());
+                context->recover();
+            }
+            variable = static_cast<const TVariable*>(symbol);
+        }
+
+        // don't delete $1.string, it's used by error recovery, and the pool
+        // pop will reclaim the memory
+
+        if (variable->getType().getQualifier() == EvqConst ) {
+            ConstantUnion* constArray = variable->getConstPointer();
+            TType t(variable->getType());
+            $$ = context->intermediate.addConstantUnion(constArray, t, $1.line);
+        } else
+            $$ = context->intermediate.addSymbol(variable->getUniqueId(),
+                                                     variable->getName(),
+                                                     variable->getType(), $1.line);
+    }
+    ;
+
+primary_expression
+    : variable_identifier {
+        $$ = $1;
+    }
+    | INTCONSTANT {
+        //
+        // INT_TYPE is only 16-bit plus sign bit for vertex/fragment shaders,
+        // check for overflow for constants
+        //
+        if (abs($1.i) >= (1 << 16)) {
+            context->error($1.line, " integer constant overflow", "");
+            context->recover();
+        }
+        ConstantUnion *unionArray = new ConstantUnion[1];
+        unionArray->setIConst($1.i);
+        $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtInt, EbpUndefined, EvqConst), $1.line);
+    }
+    | FLOATCONSTANT {
+        ConstantUnion *unionArray = new ConstantUnion[1];
+        unionArray->setFConst($1.f);
+        $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtFloat, EbpUndefined, EvqConst), $1.line);
+    }
+    | BOOLCONSTANT {
+        ConstantUnion *unionArray = new ConstantUnion[1];
+        unionArray->setBConst($1.b);
+        $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), $1.line);
+    }
+    | LEFT_PAREN expression RIGHT_PAREN {
+        $$ = $2;
+    }
+    ;
+
+postfix_expression
+    : primary_expression {
+        $$ = $1;
+    }
+    | postfix_expression LEFT_BRACKET integer_expression RIGHT_BRACKET {
+        if (!$1->isArray() && !$1->isMatrix() && !$1->isVector()) {
+            if ($1->getAsSymbolNode())
+                context->error($2.line, " left of '[' is not of type array, matrix, or vector ", $1->getAsSymbolNode()->getSymbol().c_str());
+            else
+                context->error($2.line, " left of '[' is not of type array, matrix, or vector ", "expression");
+            context->recover();
+        }
+        if ($1->getType().getQualifier() == EvqConst && $3->getQualifier() == EvqConst) {
+            if ($1->isArray()) { // constant folding for arrays
+                $$ = context->addConstArrayNode($3->getAsConstantUnion()->getUnionArrayPointer()->getIConst(), $1, $2.line);
+            } else if ($1->isVector()) {  // constant folding for vectors
+                TVectorFields fields;
+                fields.num = 1;
+                fields.offsets[0] = $3->getAsConstantUnion()->getUnionArrayPointer()->getIConst(); // need to do it this way because v.xy sends fields integer array
+                $$ = context->addConstVectorNode(fields, $1, $2.line);
+            } else if ($1->isMatrix()) { // constant folding for matrices
+                $$ = context->addConstMatrixNode($3->getAsConstantUnion()->getUnionArrayPointer()->getIConst(), $1, $2.line);
+            }
+        } else {
+            if ($3->getQualifier() == EvqConst) {
+                if (($1->isVector() || $1->isMatrix()) && $1->getType().getNominalSize() <= $3->getAsConstantUnion()->getUnionArrayPointer()->getIConst() && !$1->isArray() ) {
+                    std::stringstream extraInfoStream;
+                    extraInfoStream << "field selection out of range '" << $3->getAsConstantUnion()->getUnionArrayPointer()->getIConst() << "'";
+                    std::string extraInfo = extraInfoStream.str();
+                    context->error($2.line, "", "[", extraInfo.c_str());
+                    context->recover();
+                } else {
+                    if ($1->isArray()) {
+                        if ($1->getType().getArraySize() == 0) {
+                            if ($1->getType().getMaxArraySize() <= $3->getAsConstantUnion()->getUnionArrayPointer()->getIConst()) {
+                                if (context->arraySetMaxSize($1->getAsSymbolNode(), $1->getTypePointer(), $3->getAsConstantUnion()->getUnionArrayPointer()->getIConst(), true, $2.line))
+                                    context->recover();
+                            } else {
+                                if (context->arraySetMaxSize($1->getAsSymbolNode(), $1->getTypePointer(), 0, false, $2.line))
+                                    context->recover();
+                            }
+                        } else if ( $3->getAsConstantUnion()->getUnionArrayPointer()->getIConst() >= $1->getType().getArraySize()) {
+                            std::stringstream extraInfoStream;
+                            extraInfoStream << "array index out of range '" << $3->getAsConstantUnion()->getUnionArrayPointer()->getIConst() << "'";
+                            std::string extraInfo = extraInfoStream.str();
+                            context->error($2.line, "", "[", extraInfo.c_str());
+                            context->recover();
+                        }
+                    }
+                    $$ = context->intermediate.addIndex(EOpIndexDirect, $1, $3, $2.line);
+                }
+            } else {
+                if ($1->isArray() && $1->getType().getArraySize() == 0) {
+                    context->error($2.line, "", "[", "array must be redeclared with a size before being indexed with a variable");
+                    context->recover();
+                }
+
+                $$ = context->intermediate.addIndex(EOpIndexIndirect, $1, $3, $2.line);
+            }
+        }
+        if ($$ == 0) {
+            ConstantUnion *unionArray = new ConstantUnion[1];
+            unionArray->setFConst(0.0f);
+            $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtFloat, EbpHigh, EvqConst), $2.line);
+        } else if ($1->isArray()) {
+            if ($1->getType().getStruct())
+                $$->setType(TType($1->getType().getStruct(), $1->getType().getTypeName()));
+            else
+                $$->setType(TType($1->getBasicType(), $1->getPrecision(), EvqTemporary, $1->getNominalSize(), $1->isMatrix()));
+
+            if ($1->getType().getQualifier() == EvqConst)
+                $$->getTypePointer()->setQualifier(EvqConst);
+        } else if ($1->isMatrix() && $1->getType().getQualifier() == EvqConst)
+            $$->setType(TType($1->getBasicType(), $1->getPrecision(), EvqConst, $1->getNominalSize()));
+        else if ($1->isMatrix())
+            $$->setType(TType($1->getBasicType(), $1->getPrecision(), EvqTemporary, $1->getNominalSize()));
+        else if ($1->isVector() && $1->getType().getQualifier() == EvqConst)
+            $$->setType(TType($1->getBasicType(), $1->getPrecision(), EvqConst));
+        else if ($1->isVector())
+            $$->setType(TType($1->getBasicType(), $1->getPrecision(), EvqTemporary));
+        else
+            $$->setType($1->getType());
+    }
+    | function_call {
+        $$ = $1;
+    }
+    | postfix_expression DOT FIELD_SELECTION {
+        if ($1->isArray()) {
+            context->error($3.line, "cannot apply dot operator to an array", ".");
+            context->recover();
+        }
+
+        if ($1->isVector()) {
+            TVectorFields fields;
+            if (! context->parseVectorFields(*$3.string, $1->getNominalSize(), fields, $3.line)) {
+                fields.num = 1;
+                fields.offsets[0] = 0;
+                context->recover();
+            }
+
+            if ($1->getType().getQualifier() == EvqConst) { // constant folding for vector fields
+                $$ = context->addConstVectorNode(fields, $1, $3.line);
+                if ($$ == 0) {
+                    context->recover();
+                    $$ = $1;
+                }
+                else
+                    $$->setType(TType($1->getBasicType(), $1->getPrecision(), EvqConst, (int) (*$3.string).size()));
+            } else {
+                TString vectorString = *$3.string;
+                TIntermTyped* index = context->intermediate.addSwizzle(fields, $3.line);
+                $$ = context->intermediate.addIndex(EOpVectorSwizzle, $1, index, $2.line);
+                $$->setType(TType($1->getBasicType(), $1->getPrecision(), EvqTemporary, (int) vectorString.size()));
+            }
+        } else if ($1->isMatrix()) {
+            TMatrixFields fields;
+            if (! context->parseMatrixFields(*$3.string, $1->getNominalSize(), fields, $3.line)) {
+                fields.wholeRow = false;
+                fields.wholeCol = false;
+                fields.row = 0;
+                fields.col = 0;
+                context->recover();
+            }
+
+            if (fields.wholeRow || fields.wholeCol) {
+                context->error($2.line, " non-scalar fields not implemented yet", ".");
+                context->recover();
+                ConstantUnion *unionArray = new ConstantUnion[1];
+                unionArray->setIConst(0);
+                TIntermTyped* index = context->intermediate.addConstantUnion(unionArray, TType(EbtInt, EbpUndefined, EvqConst), $3.line);
+                $$ = context->intermediate.addIndex(EOpIndexDirect, $1, index, $2.line);
+                $$->setType(TType($1->getBasicType(), $1->getPrecision(),EvqTemporary, $1->getNominalSize()));
+            } else {
+                ConstantUnion *unionArray = new ConstantUnion[1];
+                unionArray->setIConst(fields.col * $1->getNominalSize() + fields.row);
+                TIntermTyped* index = context->intermediate.addConstantUnion(unionArray, TType(EbtInt, EbpUndefined, EvqConst), $3.line);
+                $$ = context->intermediate.addIndex(EOpIndexDirect, $1, index, $2.line);
+                $$->setType(TType($1->getBasicType(), $1->getPrecision()));
+            }
+        } else if ($1->getBasicType() == EbtStruct) {
+            bool fieldFound = false;
+            const TTypeList* fields = $1->getType().getStruct();
+            if (fields == 0) {
+                context->error($2.line, "structure has no fields", "Internal Error");
+                context->recover();
+                $$ = $1;
+            } else {
+                unsigned int i;
+                for (i = 0; i < fields->size(); ++i) {
+                    if ((*fields)[i].type->getFieldName() == *$3.string) {
+                        fieldFound = true;
+                        break;
+                    }
+                }
+                if (fieldFound) {
+                    if ($1->getType().getQualifier() == EvqConst) {
+                        $$ = context->addConstStruct(*$3.string, $1, $2.line);
+                        if ($$ == 0) {
+                            context->recover();
+                            $$ = $1;
+                        }
+                        else {
+                            $$->setType(*(*fields)[i].type);
+                            // change the qualifier of the return type, not of the structure field
+                            // as the structure definition is shared between various structures.
+                            $$->getTypePointer()->setQualifier(EvqConst);
+                        }
+                    } else {
+                        ConstantUnion *unionArray = new ConstantUnion[1];
+                        unionArray->setIConst(i);
+                        TIntermTyped* index = context->intermediate.addConstantUnion(unionArray, *(*fields)[i].type, $3.line);
+                        $$ = context->intermediate.addIndex(EOpIndexDirectStruct, $1, index, $2.line);
+                        $$->setType(*(*fields)[i].type);
+                    }
+                } else {
+                    context->error($2.line, " no such field in structure", $3.string->c_str());
+                    context->recover();
+                    $$ = $1;
+                }
+            }
+        } else {
+            context->error($2.line, " field selection requires structure, vector, or matrix on left hand side", $3.string->c_str());
+            context->recover();
+            $$ = $1;
+        }
+        // don't delete $3.string, it's from the pool
+    }
+    | postfix_expression INC_OP {
+        if (context->lValueErrorCheck($2.line, "++", $1))
+            context->recover();
+        $$ = context->intermediate.addUnaryMath(EOpPostIncrement, $1, $2.line, context->symbolTable);
+        if ($$ == 0) {
+            context->unaryOpError($2.line, "++", $1->getCompleteString());
+            context->recover();
+            $$ = $1;
+        }
+    }
+    | postfix_expression DEC_OP {
+        if (context->lValueErrorCheck($2.line, "--", $1))
+            context->recover();
+        $$ = context->intermediate.addUnaryMath(EOpPostDecrement, $1, $2.line, context->symbolTable);
+        if ($$ == 0) {
+            context->unaryOpError($2.line, "--", $1->getCompleteString());
+            context->recover();
+            $$ = $1;
+        }
+    }
+    ;
+
+integer_expression
+    : expression {
+        if (context->integerErrorCheck($1, "[]"))
+            context->recover();
+        $$ = $1;
+    }
+    ;
+
+function_call
+    : function_call_or_method {
+        TFunction* fnCall = $1.function;
+        TOperator op = fnCall->getBuiltInOp();
+
+        if (op != EOpNull)
+        {
+            //
+            // Then this should be a constructor.
+            // Don't go through the symbol table for constructors.
+            // Their parameters will be verified algorithmically.
+            //
+            TType type(EbtVoid, EbpUndefined);  // use this to get the type back
+            if (context->constructorErrorCheck($1.line, $1.intermNode, *fnCall, op, &type)) {
+                $$ = 0;
+            } else {
+                //
+                // It's a constructor, of type 'type'.
+                //
+                $$ = context->addConstructor($1.intermNode, &type, op, fnCall, $1.line);
+            }
+
+            if ($$ == 0) {
+                context->recover();
+                $$ = context->intermediate.setAggregateOperator(0, op, $1.line);
+            }
+            $$->setType(type);
+        } else {
+            //
+            // Not a constructor.  Find it in the symbol table.
+            //
+            const TFunction* fnCandidate;
+            bool builtIn;
+            fnCandidate = context->findFunction($1.line, fnCall, &builtIn);
+            if (fnCandidate) {
+                //
+                // A declared function.
+                //
+                if (builtIn && !fnCandidate->getExtension().empty() &&
+                    context->extensionErrorCheck($1.line, fnCandidate->getExtension())) {
+                    context->recover();
+                }
+                op = fnCandidate->getBuiltInOp();
+                if (builtIn && op != EOpNull) {
+                    //
+                    // A function call mapped to a built-in operation.
+                    //
+                    if (fnCandidate->getParamCount() == 1) {
+                        //
+                        // Treat it like a built-in unary operator.
+                        //
+                        $$ = context->intermediate.addUnaryMath(op, $1.intermNode, 0, context->symbolTable);
+                        if ($$ == 0)  {
+                            std::stringstream extraInfoStream;
+                            extraInfoStream << "built in unary operator function.  Type: " << static_cast<TIntermTyped*>($1.intermNode)->getCompleteString();
+                            std::string extraInfo = extraInfoStream.str();
+                            context->error($1.intermNode->getLine(), " wrong operand type", "Internal Error", extraInfo.c_str());
+                            YYERROR;
+                        }
+                    } else {
+                        $$ = context->intermediate.setAggregateOperator($1.intermAggregate, op, $1.line);
+                    }
+                } else {
+                    // This is a real function call
+
+                    $$ = context->intermediate.setAggregateOperator($1.intermAggregate, EOpFunctionCall, $1.line);
+                    $$->setType(fnCandidate->getReturnType());
+
+                    // this is how we know whether the given function is a builtIn function or a user defined function
+                    // if builtIn == false, it's a userDefined -> could be an overloaded builtIn function also
+                    // if builtIn == true, it's definitely a builtIn function with EOpNull
+                    if (!builtIn)
+                        $$->getAsAggregate()->setUserDefined();
+                    $$->getAsAggregate()->setName(fnCandidate->getMangledName());
+
+                    TQualifier qual;
+                    for (int i = 0; i < fnCandidate->getParamCount(); ++i) {
+                        qual = fnCandidate->getParam(i).type->getQualifier();
+                        if (qual == EvqOut || qual == EvqInOut) {
+                            if (context->lValueErrorCheck($$->getLine(), "assign", $$->getAsAggregate()->getSequence()[i]->getAsTyped())) {
+                                context->error($1.intermNode->getLine(), "Constant value cannot be passed for 'out' or 'inout' parameters.", "Error");
+                                context->recover();
+                            }
+                        }
+                    }
+                }
+                $$->setType(fnCandidate->getReturnType());
+            } else {
+                // error message was put out by PaFindFunction()
+                // Put on a dummy node for error recovery
+                ConstantUnion *unionArray = new ConstantUnion[1];
+                unionArray->setFConst(0.0f);
+                $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtFloat, EbpUndefined, EvqConst), $1.line);
+                context->recover();
+            }
+        }
+        delete fnCall;
+    }
+    ;
+
+function_call_or_method
+    : function_call_generic {
+        $$ = $1;
+    }
+    | postfix_expression DOT function_call_generic {
+        context->error($3.line, "methods are not supported", "");
+        context->recover();
+        $$ = $3;
+    }
+    ;
+
+function_call_generic
+    : function_call_header_with_parameters RIGHT_PAREN {
+        $$ = $1;
+        $$.line = $2.line;
+    }
+    | function_call_header_no_parameters RIGHT_PAREN {
+        $$ = $1;
+        $$.line = $2.line;
+    }
+    ;
+
+function_call_header_no_parameters
+    : function_call_header VOID_TYPE {
+        $$.function = $1;
+        $$.intermNode = 0;
+    }
+    | function_call_header {
+        $$.function = $1;
+        $$.intermNode = 0;
+    }
+    ;
+
+function_call_header_with_parameters
+    : function_call_header assignment_expression {
+        TParameter param = { 0, new TType($2->getType()) };
+        $1->addParameter(param);
+        $$.function = $1;
+        $$.intermNode = $2;
+    }
+    | function_call_header_with_parameters COMMA assignment_expression {
+        TParameter param = { 0, new TType($3->getType()) };
+        $1.function->addParameter(param);
+        $$.function = $1.function;
+        $$.intermNode = context->intermediate.growAggregate($1.intermNode, $3, $2.line);
+    }
+    ;
+
+function_call_header
+    : function_identifier LEFT_PAREN {
+        $$ = $1;
+    }
+    ;
+
+// Grammar Note:  Constructors look like functions, but are recognized as types.
+
+function_identifier
+    : type_specifier_nonarray {
+        //
+        // Constructor
+        //
+        TOperator op = EOpNull;
+        if ($1.userDef) {
+            op = EOpConstructStruct;
+        } else {
+            switch ($1.type) {
+            case EbtFloat:
+                if ($1.matrix) {
+                    switch($1.size) {
+                    case 2:                                     op = EOpConstructMat2;  break;
+                    case 3:                                     op = EOpConstructMat3;  break;
+                    case 4:                                     op = EOpConstructMat4;  break;
+                    }
+                } else {
+                    switch($1.size) {
+                    case 1:                                     op = EOpConstructFloat; break;
+                    case 2:                                     op = EOpConstructVec2;  break;
+                    case 3:                                     op = EOpConstructVec3;  break;
+                    case 4:                                     op = EOpConstructVec4;  break;
+                    }
+                }
+                break;
+            case EbtInt:
+                switch($1.size) {
+                case 1:                                         op = EOpConstructInt;   break;
+                case 2:       FRAG_VERT_ONLY("ivec2", $1.line); op = EOpConstructIVec2; break;
+                case 3:       FRAG_VERT_ONLY("ivec3", $1.line); op = EOpConstructIVec3; break;
+                case 4:       FRAG_VERT_ONLY("ivec4", $1.line); op = EOpConstructIVec4; break;
+                }
+                break;
+            case EbtBool:
+                switch($1.size) {
+                case 1:                                         op = EOpConstructBool;  break;
+                case 2:       FRAG_VERT_ONLY("bvec2", $1.line); op = EOpConstructBVec2; break;
+                case 3:       FRAG_VERT_ONLY("bvec3", $1.line); op = EOpConstructBVec3; break;
+                case 4:       FRAG_VERT_ONLY("bvec4", $1.line); op = EOpConstructBVec4; break;
+                }
+                break;
+            default: break;
+            }
+            if (op == EOpNull) {
+                context->error($1.line, "cannot construct this type", getBasicString($1.type));
+                context->recover();
+                $1.type = EbtFloat;
+                op = EOpConstructFloat;
+            }
+        }
+        TString tempString;
+        TType type($1);
+        TFunction *function = new TFunction(&tempString, type, op);
+        $$ = function;
+    }
+    | IDENTIFIER {
+        if (context->reservedErrorCheck($1.line, *$1.string))
+            context->recover();
+        TType type(EbtVoid, EbpUndefined);
+        TFunction *function = new TFunction($1.string, type);
+        $$ = function;
+    }
+    | FIELD_SELECTION {
+        if (context->reservedErrorCheck($1.line, *$1.string))
+            context->recover();
+        TType type(EbtVoid, EbpUndefined);
+        TFunction *function = new TFunction($1.string, type);
+        $$ = function;
+    }
+    ;
+
+unary_expression
+    : postfix_expression {
+        $$ = $1;
+    }
+    | INC_OP unary_expression {
+        if (context->lValueErrorCheck($1.line, "++", $2))
+            context->recover();
+        $$ = context->intermediate.addUnaryMath(EOpPreIncrement, $2, $1.line, context->symbolTable);
+        if ($$ == 0) {
+            context->unaryOpError($1.line, "++", $2->getCompleteString());
+            context->recover();
+            $$ = $2;
+        }
+    }
+    | DEC_OP unary_expression {
+        if (context->lValueErrorCheck($1.line, "--", $2))
+            context->recover();
+        $$ = context->intermediate.addUnaryMath(EOpPreDecrement, $2, $1.line, context->symbolTable);
+        if ($$ == 0) {
+            context->unaryOpError($1.line, "--", $2->getCompleteString());
+            context->recover();
+            $$ = $2;
+        }
+    }
+    | unary_operator unary_expression {
+        if ($1.op != EOpNull) {
+            $$ = context->intermediate.addUnaryMath($1.op, $2, $1.line, context->symbolTable);
+            if ($$ == 0) {
+                const char* errorOp = "";
+                switch($1.op) {
+                case EOpNegative:   errorOp = "-"; break;
+                case EOpLogicalNot: errorOp = "!"; break;
+                default: break;
+                }
+                context->unaryOpError($1.line, errorOp, $2->getCompleteString());
+                context->recover();
+                $$ = $2;
+            }
+        } else
+            $$ = $2;
+    }
+    ;
+// Grammar Note:  No traditional style type casts.
+
+unary_operator
+    : PLUS  { $$.line = $1.line; $$.op = EOpNull; }
+    | DASH  { $$.line = $1.line; $$.op = EOpNegative; }
+    | BANG  { $$.line = $1.line; $$.op = EOpLogicalNot; }
+    ;
+// Grammar Note:  No '*' or '&' unary ops.  Pointers are not supported.
+
+multiplicative_expression
+    : unary_expression { $$ = $1; }
+    | multiplicative_expression STAR unary_expression {
+        FRAG_VERT_ONLY("*", $2.line);
+        $$ = context->intermediate.addBinaryMath(EOpMul, $1, $3, $2.line, context->symbolTable);
+        if ($$ == 0) {
+            context->binaryOpError($2.line, "*", $1->getCompleteString(), $3->getCompleteString());
+            context->recover();
+            $$ = $1;
+        }
+    }
+    | multiplicative_expression SLASH unary_expression {
+        FRAG_VERT_ONLY("/", $2.line);
+        $$ = context->intermediate.addBinaryMath(EOpDiv, $1, $3, $2.line, context->symbolTable);
+        if ($$ == 0) {
+            context->binaryOpError($2.line, "/", $1->getCompleteString(), $3->getCompleteString());
+            context->recover();
+            $$ = $1;
+        }
+    }
+    ;
+
+additive_expression
+    : multiplicative_expression { $$ = $1; }
+    | additive_expression PLUS multiplicative_expression {
+        $$ = context->intermediate.addBinaryMath(EOpAdd, $1, $3, $2.line, context->symbolTable);
+        if ($$ == 0) {
+            context->binaryOpError($2.line, "+", $1->getCompleteString(), $3->getCompleteString());
+            context->recover();
+            $$ = $1;
+        }
+    }
+    | additive_expression DASH multiplicative_expression {
+        $$ = context->intermediate.addBinaryMath(EOpSub, $1, $3, $2.line, context->symbolTable);
+        if ($$ == 0) {
+            context->binaryOpError($2.line, "-", $1->getCompleteString(), $3->getCompleteString());
+            context->recover();
+            $$ = $1;
+        }
+    }
+    ;
+
+shift_expression
+    : additive_expression { $$ = $1; }
+    ;
+
+relational_expression
+    : shift_expression { $$ = $1; }
+    | relational_expression LEFT_ANGLE shift_expression {
+        $$ = context->intermediate.addBinaryMath(EOpLessThan, $1, $3, $2.line, context->symbolTable);
+        if ($$ == 0) {
+            context->binaryOpError($2.line, "<", $1->getCompleteString(), $3->getCompleteString());
+            context->recover();
+            ConstantUnion *unionArray = new ConstantUnion[1];
+            unionArray->setBConst(false);
+            $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), $2.line);
+        }
+    }
+    | relational_expression RIGHT_ANGLE shift_expression  {
+        $$ = context->intermediate.addBinaryMath(EOpGreaterThan, $1, $3, $2.line, context->symbolTable);
+        if ($$ == 0) {
+            context->binaryOpError($2.line, ">", $1->getCompleteString(), $3->getCompleteString());
+            context->recover();
+            ConstantUnion *unionArray = new ConstantUnion[1];
+            unionArray->setBConst(false);
+            $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), $2.line);
+        }
+    }
+    | relational_expression LE_OP shift_expression  {
+        $$ = context->intermediate.addBinaryMath(EOpLessThanEqual, $1, $3, $2.line, context->symbolTable);
+        if ($$ == 0) {
+            context->binaryOpError($2.line, "<=", $1->getCompleteString(), $3->getCompleteString());
+            context->recover();
+            ConstantUnion *unionArray = new ConstantUnion[1];
+            unionArray->setBConst(false);
+            $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), $2.line);
+        }
+    }
+    | relational_expression GE_OP shift_expression  {
+        $$ = context->intermediate.addBinaryMath(EOpGreaterThanEqual, $1, $3, $2.line, context->symbolTable);
+        if ($$ == 0) {
+            context->binaryOpError($2.line, ">=", $1->getCompleteString(), $3->getCompleteString());
+            context->recover();
+            ConstantUnion *unionArray = new ConstantUnion[1];
+            unionArray->setBConst(false);
+            $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), $2.line);
+        }
+    }
+    ;
+
+equality_expression
+    : relational_expression { $$ = $1; }
+    | equality_expression EQ_OP relational_expression  {
+        $$ = context->intermediate.addBinaryMath(EOpEqual, $1, $3, $2.line, context->symbolTable);
+        if ($$ == 0) {
+            context->binaryOpError($2.line, "==", $1->getCompleteString(), $3->getCompleteString());
+            context->recover();
+            ConstantUnion *unionArray = new ConstantUnion[1];
+            unionArray->setBConst(false);
+            $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), $2.line);
+        }
+    }
+    | equality_expression NE_OP relational_expression {
+        $$ = context->intermediate.addBinaryMath(EOpNotEqual, $1, $3, $2.line, context->symbolTable);
+        if ($$ == 0) {
+            context->binaryOpError($2.line, "!=", $1->getCompleteString(), $3->getCompleteString());
+            context->recover();
+            ConstantUnion *unionArray = new ConstantUnion[1];
+            unionArray->setBConst(false);
+            $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), $2.line);
+        }
+    }
+    ;
+
+and_expression
+    : equality_expression { $$ = $1; }
+    ;
+
+exclusive_or_expression
+    : and_expression { $$ = $1; }
+    ;
+
+inclusive_or_expression
+    : exclusive_or_expression { $$ = $1; }
+    ;
+
+logical_and_expression
+    : inclusive_or_expression { $$ = $1; }
+    | logical_and_expression AND_OP inclusive_or_expression {
+        $$ = context->intermediate.addBinaryMath(EOpLogicalAnd, $1, $3, $2.line, context->symbolTable);
+        if ($$ == 0) {
+            context->binaryOpError($2.line, "&&", $1->getCompleteString(), $3->getCompleteString());
+            context->recover();
+            ConstantUnion *unionArray = new ConstantUnion[1];
+            unionArray->setBConst(false);
+            $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), $2.line);
+        }
+    }
+    ;
+
+logical_xor_expression
+    : logical_and_expression { $$ = $1; }
+    | logical_xor_expression XOR_OP logical_and_expression  {
+        $$ = context->intermediate.addBinaryMath(EOpLogicalXor, $1, $3, $2.line, context->symbolTable);
+        if ($$ == 0) {
+            context->binaryOpError($2.line, "^^", $1->getCompleteString(), $3->getCompleteString());
+            context->recover();
+            ConstantUnion *unionArray = new ConstantUnion[1];
+            unionArray->setBConst(false);
+            $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), $2.line);
+        }
+    }
+    ;
+
+logical_or_expression
+    : logical_xor_expression { $$ = $1; }
+    | logical_or_expression OR_OP logical_xor_expression  {
+        $$ = context->intermediate.addBinaryMath(EOpLogicalOr, $1, $3, $2.line, context->symbolTable);
+        if ($$ == 0) {
+            context->binaryOpError($2.line, "||", $1->getCompleteString(), $3->getCompleteString());
+            context->recover();
+            ConstantUnion *unionArray = new ConstantUnion[1];
+            unionArray->setBConst(false);
+            $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), $2.line);
+        }
+    }
+    ;
+
+conditional_expression
+    : logical_or_expression { $$ = $1; }
+    | logical_or_expression QUESTION expression COLON assignment_expression {
+       if (context->boolErrorCheck($2.line, $1))
+            context->recover();
+
+        $$ = context->intermediate.addSelection($1, $3, $5, $2.line);
+        if ($3->getType() != $5->getType())
+            $$ = 0;
+
+        if ($$ == 0) {
+            context->binaryOpError($2.line, ":", $3->getCompleteString(), $5->getCompleteString());
+            context->recover();
+            $$ = $5;
+        }
+    }
+    ;
+
+assignment_expression
+    : conditional_expression { $$ = $1; }
+    | unary_expression assignment_operator assignment_expression {
+        if (context->lValueErrorCheck($2.line, "assign", $1))
+            context->recover();
+        $$ = context->intermediate.addAssign($2.op, $1, $3, $2.line);
+        if ($$ == 0) {
+            context->assignError($2.line, "assign", $1->getCompleteString(), $3->getCompleteString());
+            context->recover();
+            $$ = $1;
+        }
+    }
+    ;
+
+assignment_operator
+    : EQUAL        {                                    $$.line = $1.line; $$.op = EOpAssign; }
+    | MUL_ASSIGN   { FRAG_VERT_ONLY("*=", $1.line);     $$.line = $1.line; $$.op = EOpMulAssign; }
+    | DIV_ASSIGN   { FRAG_VERT_ONLY("/=", $1.line);     $$.line = $1.line; $$.op = EOpDivAssign; }
+    | ADD_ASSIGN   {                                    $$.line = $1.line; $$.op = EOpAddAssign; }
+    | SUB_ASSIGN   {                                    $$.line = $1.line; $$.op = EOpSubAssign; }
+    ;
+
+expression
+    : assignment_expression {
+        $$ = $1;
+    }
+    | expression COMMA assignment_expression {
+        $$ = context->intermediate.addComma($1, $3, $2.line);
+        if ($$ == 0) {
+            context->binaryOpError($2.line, ",", $1->getCompleteString(), $3->getCompleteString());
+            context->recover();
+            $$ = $3;
+        }
+    }
+    ;
+
+constant_expression
+    : conditional_expression {
+        if (context->constErrorCheck($1))
+            context->recover();
+        $$ = $1;
+    }
+    ;
+
+declaration
+    : function_prototype SEMICOLON   {
+        TFunction &function = *($1.function);
+        
+        TIntermAggregate *prototype = new TIntermAggregate;
+        prototype->setType(function.getReturnType());
+        prototype->setName(function.getName());
+        
+        for (int i = 0; i < function.getParamCount(); i++)
+        {
+            const TParameter &param = function.getParam(i);
+            if (param.name != 0)
+            {
+                TVariable *variable = new TVariable(param.name, *param.type);
+                
+                prototype = context->intermediate.growAggregate(prototype, context->intermediate.addSymbol(variable->getUniqueId(), variable->getName(), variable->getType(), $1.line), $1.line);
+            }
+            else
+            {
+                prototype = context->intermediate.growAggregate(prototype, context->intermediate.addSymbol(0, "", *param.type, $1.line), $1.line);
+            }
+        }
+        
+        prototype->setOp(EOpPrototype);
+        $$ = prototype;
+
+        context->symbolTable.pop();
+    }
+    | init_declarator_list SEMICOLON {
+        if ($1.intermAggregate)
+            $1.intermAggregate->setOp(EOpDeclaration);
+        $$ = $1.intermAggregate;
+    }
+    | PRECISION precision_qualifier type_specifier_no_prec SEMICOLON {
+        context->symbolTable.setDefaultPrecision( $3.type, $2 );
+        $$ = 0;
+    }
+    ;
+
+function_prototype
+    : function_declarator RIGHT_PAREN  {
+        //
+        // Multiple declarations of the same function are allowed.
+        //
+        // If this is a definition, the definition production code will check for redefinitions
+        // (we don't know at this point if it's a definition or not).
+        //
+        // Redeclarations are allowed.  But, return types and parameter qualifiers must match.
+        //
+        TFunction* prevDec = static_cast<TFunction*>(context->symbolTable.find($1->getMangledName()));
+        if (prevDec) {
+            if (prevDec->getReturnType() != $1->getReturnType()) {
+                context->error($2.line, "overloaded functions must have the same return type", $1->getReturnType().getBasicString());
+                context->recover();
+            }
+            for (int i = 0; i < prevDec->getParamCount(); ++i) {
+                if (prevDec->getParam(i).type->getQualifier() != $1->getParam(i).type->getQualifier()) {
+                    context->error($2.line, "overloaded functions must have the same parameter qualifiers", $1->getParam(i).type->getQualifierString());
+                    context->recover();
+                }
+            }
+        }
+
+        //
+        // If this is a redeclaration, it could also be a definition,
+        // in which case, we want to use the variable names from this one, and not the one that's
+        // being redeclared.  So, pass back up this declaration, not the one in the symbol table.
+        //
+        $$.function = $1;
+        $$.line = $2.line;
+
+        // We're at the inner scope level of the function's arguments and body statement.
+        // Add the function prototype to the surrounding scope instead.
+        context->symbolTable.getOuterLevel()->insert(*$$.function);
+    }
+    ;
+
+function_declarator
+    : function_header {
+        $$ = $1;
+    }
+    | function_header_with_parameters {
+        $$ = $1;
+    }
+    ;
+
+
+function_header_with_parameters
+    : function_header parameter_declaration {
+        // Add the parameter
+        $$ = $1;
+        if ($2.param.type->getBasicType() != EbtVoid)
+            $1->addParameter($2.param);
+        else
+            delete $2.param.type;
+    }
+    | function_header_with_parameters COMMA parameter_declaration {
+        //
+        // Only first parameter of one-parameter functions can be void
+        // The check for named parameters not being void is done in parameter_declarator
+        //
+        if ($3.param.type->getBasicType() == EbtVoid) {
+            //
+            // This parameter > first is void
+            //
+            context->error($2.line, "cannot be an argument type except for '(void)'", "void");
+            context->recover();
+            delete $3.param.type;
+        } else {
+            // Add the parameter
+            $$ = $1;
+            $1->addParameter($3.param);
+        }
+    }
+    ;
+
+function_header
+    : fully_specified_type IDENTIFIER LEFT_PAREN {
+        if ($1.qualifier != EvqGlobal && $1.qualifier != EvqTemporary) {
+            context->error($2.line, "no qualifiers allowed for function return", getQualifierString($1.qualifier));
+            context->recover();
+        }
+        // make sure a sampler is not involved as well...
+        if (context->structQualifierErrorCheck($2.line, $1))
+            context->recover();
+
+        // Add the function as a prototype after parsing it (we do not support recursion)
+        TFunction *function;
+        TType type($1);
+        function = new TFunction($2.string, type);
+        $$ = function;
+        
+        context->symbolTable.push();
+    }
+    ;
+
+parameter_declarator
+    // Type + name
+    : type_specifier IDENTIFIER {
+        if ($1.type == EbtVoid) {
+            context->error($2.line, "illegal use of type 'void'", $2.string->c_str());
+            context->recover();
+        }
+        if (context->reservedErrorCheck($2.line, *$2.string))
+            context->recover();
+        TParameter param = {$2.string, new TType($1)};
+        $$.line = $2.line;
+        $$.param = param;
+    }
+    | type_specifier IDENTIFIER LEFT_BRACKET constant_expression RIGHT_BRACKET {
+        // Check that we can make an array out of this type
+        if (context->arrayTypeErrorCheck($3.line, $1))
+            context->recover();
+
+        if (context->reservedErrorCheck($2.line, *$2.string))
+            context->recover();
+
+        int size;
+        if (context->arraySizeErrorCheck($3.line, $4, size))
+            context->recover();
+        $1.setArray(true, size);
+
+        TType* type = new TType($1);
+        TParameter param = { $2.string, type };
+        $$.line = $2.line;
+        $$.param = param;
+    }
+    ;
+
+parameter_declaration
+    //
+    // The only parameter qualifier a parameter can have are
+    // IN_QUAL, OUT_QUAL, INOUT_QUAL, or CONST.
+    //
+
+    //
+    // Type + name
+    //
+    : type_qualifier parameter_qualifier parameter_declarator {
+        $$ = $3;
+        if (context->paramErrorCheck($3.line, $1.qualifier, $2, $$.param.type))
+            context->recover();
+    }
+    | parameter_qualifier parameter_declarator {
+        $$ = $2;
+        if (context->parameterSamplerErrorCheck($2.line, $1, *$2.param.type))
+            context->recover();
+        if (context->paramErrorCheck($2.line, EvqTemporary, $1, $$.param.type))
+            context->recover();
+    }
+    //
+    // Only type
+    //
+    | type_qualifier parameter_qualifier parameter_type_specifier {
+        $$ = $3;
+        if (context->paramErrorCheck($3.line, $1.qualifier, $2, $$.param.type))
+            context->recover();
+    }
+    | parameter_qualifier parameter_type_specifier {
+        $$ = $2;
+        if (context->parameterSamplerErrorCheck($2.line, $1, *$2.param.type))
+            context->recover();
+        if (context->paramErrorCheck($2.line, EvqTemporary, $1, $$.param.type))
+            context->recover();
+    }
+    ;
+
+parameter_qualifier
+    : /* empty */ {
+        $$ = EvqIn;
+    }
+    | IN_QUAL {
+        $$ = EvqIn;
+    }
+    | OUT_QUAL {
+        $$ = EvqOut;
+    }
+    | INOUT_QUAL {
+        $$ = EvqInOut;
+    }
+    ;
+
+parameter_type_specifier
+    : type_specifier {
+        TParameter param = { 0, new TType($1) };
+        $$.param = param;
+    }
+    ;
+
+init_declarator_list
+    : single_declaration {
+        $$ = $1;
+    }
+    | init_declarator_list COMMA IDENTIFIER {
+        if ($1.type.type == EbtInvariant && !$3.symbol)
+        {
+            context->error($3.line, "undeclared identifier declared as invariant", $3.string->c_str());
+            context->recover();
+        }
+
+        TIntermSymbol* symbol = context->intermediate.addSymbol(0, *$3.string, TType($1.type), $3.line);
+        $$.intermAggregate = context->intermediate.growAggregate($1.intermNode, symbol, $3.line);
+        
+        if (context->structQualifierErrorCheck($3.line, $$.type))
+            context->recover();
+
+        if (context->nonInitConstErrorCheck($3.line, *$3.string, $$.type, false))
+            context->recover();
+
+        TVariable* variable = 0;
+        if (context->nonInitErrorCheck($3.line, *$3.string, $$.type, variable))
+            context->recover();
+        if (symbol && variable)
+            symbol->setId(variable->getUniqueId());
+    }
+    | init_declarator_list COMMA IDENTIFIER LEFT_BRACKET RIGHT_BRACKET {
+        if (context->structQualifierErrorCheck($3.line, $1.type))
+            context->recover();
+
+        if (context->nonInitConstErrorCheck($3.line, *$3.string, $1.type, true))
+            context->recover();
+
+        $$ = $1;
+
+        if (context->arrayTypeErrorCheck($4.line, $1.type) || context->arrayQualifierErrorCheck($4.line, $1.type))
+            context->recover();
+        else {
+            $1.type.setArray(true);
+            TVariable* variable;
+            if (context->arrayErrorCheck($4.line, *$3.string, $1.type, variable))
+                context->recover();
+        }
+    }
+    | init_declarator_list COMMA IDENTIFIER LEFT_BRACKET constant_expression RIGHT_BRACKET {
+        if (context->structQualifierErrorCheck($3.line, $1.type))
+            context->recover();
+
+        if (context->nonInitConstErrorCheck($3.line, *$3.string, $1.type, true))
+            context->recover();
+
+        $$ = $1;
+
+        if (context->arrayTypeErrorCheck($4.line, $1.type) || context->arrayQualifierErrorCheck($4.line, $1.type))
+            context->recover();
+        else {
+            int size;
+            if (context->arraySizeErrorCheck($4.line, $5, size))
+                context->recover();
+            $1.type.setArray(true, size);
+            TVariable* variable = 0;
+            if (context->arrayErrorCheck($4.line, *$3.string, $1.type, variable))
+                context->recover();
+            TType type = TType($1.type);
+            type.setArraySize(size);
+            $$.intermAggregate = context->intermediate.growAggregate($1.intermNode, context->intermediate.addSymbol(variable ? variable->getUniqueId() : 0, *$3.string, type, $3.line), $3.line);
+        }
+    }
+    | init_declarator_list COMMA IDENTIFIER EQUAL initializer {
+        if (context->structQualifierErrorCheck($3.line, $1.type))
+            context->recover();
+
+        $$ = $1;
+
+        TIntermNode* intermNode;
+        if (!context->executeInitializer($3.line, *$3.string, $1.type, $5, intermNode)) {
+            //
+            // build the intermediate representation
+            //
+            if (intermNode)
+        $$.intermAggregate = context->intermediate.growAggregate($1.intermNode, intermNode, $4.line);
+            else
+                $$.intermAggregate = $1.intermAggregate;
+        } else {
+            context->recover();
+            $$.intermAggregate = 0;
+        }
+    }
+    ;
+
+single_declaration
+    : fully_specified_type {
+        $$.type = $1;
+        $$.intermAggregate = context->intermediate.makeAggregate(context->intermediate.addSymbol(0, "", TType($1), $1.line), $1.line);
+    }
+    | fully_specified_type IDENTIFIER {
+        TIntermSymbol* symbol = context->intermediate.addSymbol(0, *$2.string, TType($1), $2.line);
+        $$.intermAggregate = context->intermediate.makeAggregate(symbol, $2.line);
+        
+        if (context->structQualifierErrorCheck($2.line, $$.type))
+            context->recover();
+
+        if (context->nonInitConstErrorCheck($2.line, *$2.string, $$.type, false))
+            context->recover();
+            
+            $$.type = $1;
+
+        TVariable* variable = 0;
+        if (context->nonInitErrorCheck($2.line, *$2.string, $$.type, variable))
+            context->recover();
+        if (variable && symbol)
+            symbol->setId(variable->getUniqueId());
+    }
+    | fully_specified_type IDENTIFIER LEFT_BRACKET RIGHT_BRACKET {
+        context->error($2.line, "unsized array declarations not supported", $2.string->c_str());
+        context->recover();
+
+        TIntermSymbol* symbol = context->intermediate.addSymbol(0, *$2.string, TType($1), $2.line);
+        $$.intermAggregate = context->intermediate.makeAggregate(symbol, $2.line);
+        $$.type = $1;
+    }
+    | fully_specified_type IDENTIFIER LEFT_BRACKET constant_expression RIGHT_BRACKET {
+        TType type = TType($1);
+        int size;
+        if (context->arraySizeErrorCheck($2.line, $4, size))
+            context->recover();
+        type.setArraySize(size);
+        TIntermSymbol* symbol = context->intermediate.addSymbol(0, *$2.string, type, $2.line);
+        $$.intermAggregate = context->intermediate.makeAggregate(symbol, $2.line);
+        
+        if (context->structQualifierErrorCheck($2.line, $1))
+            context->recover();
+
+        if (context->nonInitConstErrorCheck($2.line, *$2.string, $1, true))
+            context->recover();
+
+        $$.type = $1;
+
+        if (context->arrayTypeErrorCheck($3.line, $1) || context->arrayQualifierErrorCheck($3.line, $1))
+            context->recover();
+        else {
+            int size;
+            if (context->arraySizeErrorCheck($3.line, $4, size))
+                context->recover();
+
+            $1.setArray(true, size);
+            TVariable* variable = 0;
+            if (context->arrayErrorCheck($3.line, *$2.string, $1, variable))
+                context->recover();
+            if (variable && symbol)
+                symbol->setId(variable->getUniqueId());
+        }
+    }
+    | fully_specified_type IDENTIFIER EQUAL initializer {
+        if (context->structQualifierErrorCheck($2.line, $1))
+            context->recover();
+
+        $$.type = $1;
+
+        TIntermNode* intermNode;
+        if (!context->executeInitializer($2.line, *$2.string, $1, $4, intermNode)) {
+        //
+        // Build intermediate representation
+        //
+            if(intermNode)
+                $$.intermAggregate = context->intermediate.makeAggregate(intermNode, $3.line);
+            else
+                $$.intermAggregate = 0;
+        } else {
+            context->recover();
+            $$.intermAggregate = 0;
+        }
+    }
+    | INVARIANT IDENTIFIER {
+        VERTEX_ONLY("invariant declaration", $1.line);
+        if (context->globalErrorCheck($1.line, context->symbolTable.atGlobalLevel(), "invariant varying"))
+            context->recover();
+        $$.type.setBasic(EbtInvariant, EvqInvariantVaryingOut, $2.line);
+        if (!$2.symbol)
+        {
+            context->error($2.line, "undeclared identifier declared as invariant", $2.string->c_str());
+            context->recover();
+            
+            $$.intermAggregate = 0;
+        }
+        else
+        {
+            TIntermSymbol *symbol = context->intermediate.addSymbol(0, *$2.string, TType($$.type), $2.line);
+            $$.intermAggregate = context->intermediate.makeAggregate(symbol, $2.line);
+        }
+    }
+
+//
+// Place holder for the pack/unpack languages.
+//
+//    | buffer_specifier {
+//        $$.intermAggregate = 0;
+//    }
+    ;
+
+// Grammar Note:  No 'enum', or 'typedef'.
+
+//
+// Place holder for the pack/unpack languages.
+//
+//%type <interm> buffer_declaration
+//%type <interm.type> buffer_specifier input_or_output buffer_declaration_list
+//buffer_specifier
+//    : input_or_output LEFT_BRACE buffer_declaration_list RIGHT_BRACE {
+//    }
+//    ;
+//
+//input_or_output
+//    : INPUT {
+//        if (context->globalErrorCheck($1.line, context->symbolTable.atGlobalLevel(), "input"))
+//            context->recover();
+//        UNPACK_ONLY("input", $1.line);
+//        $$.qualifier = EvqInput;
+//    }
+//    | OUTPUT {
+//        if (context->globalErrorCheck($1.line, context->symbolTable.atGlobalLevel(), "output"))
+//            context->recover();
+//        PACK_ONLY("output", $1.line);
+//        $$.qualifier = EvqOutput;
+//    }
+//    ;
+
+//
+// Place holder for the pack/unpack languages.
+//
+//buffer_declaration_list
+//    : buffer_declaration {
+//    }
+//    | buffer_declaration_list buffer_declaration {
+//    }
+//    ;
+
+//
+// Input/output semantics:
+//   float must be 16 or 32 bits
+//   float alignment restrictions?
+//   check for only one input and only one output
+//   sum of bitfields has to be multiple of 32
+//
+
+//
+// Place holder for the pack/unpack languages.
+//
+//buffer_declaration
+//    : type_specifier IDENTIFIER COLON constant_expression SEMICOLON {
+//        if (context->reservedErrorCheck($2.line, *$2.string, context))
+//            context->recover();
+//        $$.variable = new TVariable($2.string, $1);
+//        if (! context->symbolTable.insert(*$$.variable)) {
+//            context->error($2.line, "redefinition", $$.variable->getName().c_str());
+//            context->recover();
+//            // don't have to delete $$.variable, the pool pop will take care of it
+//        }
+//    }
+//    ;
+
+fully_specified_type
+    : type_specifier {
+        $$ = $1;
+
+        if ($1.array) {
+            context->error($1.line, "not supported", "first-class array");
+            context->recover();
+            $1.setArray(false);
+        }
+    }
+    | type_qualifier type_specifier  {
+        if ($2.array) {
+            context->error($2.line, "not supported", "first-class array");
+            context->recover();
+            $2.setArray(false);
+        }
+
+        if ($1.qualifier == EvqAttribute &&
+            ($2.type == EbtBool || $2.type == EbtInt)) {
+            context->error($2.line, "cannot be bool or int", getQualifierString($1.qualifier));
+            context->recover();
+        }
+        if (($1.qualifier == EvqVaryingIn || $1.qualifier == EvqVaryingOut) &&
+            ($2.type == EbtBool || $2.type == EbtInt)) {
+            context->error($2.line, "cannot be bool or int", getQualifierString($1.qualifier));
+            context->recover();
+        }
+        $$ = $2;
+        $$.qualifier = $1.qualifier;
+    }
+    ;
+
+type_qualifier
+    : CONST_QUAL {
+        $$.setBasic(EbtVoid, EvqConst, $1.line);
+    }
+    | ATTRIBUTE {
+        VERTEX_ONLY("attribute", $1.line);
+        if (context->globalErrorCheck($1.line, context->symbolTable.atGlobalLevel(), "attribute"))
+            context->recover();
+        $$.setBasic(EbtVoid, EvqAttribute, $1.line);
+    }
+    | VARYING {
+        if (context->globalErrorCheck($1.line, context->symbolTable.atGlobalLevel(), "varying"))
+            context->recover();
+        if (context->shaderType == SH_VERTEX_SHADER)
+            $$.setBasic(EbtVoid, EvqVaryingOut, $1.line);
+        else
+            $$.setBasic(EbtVoid, EvqVaryingIn, $1.line);
+    }
+    | INVARIANT VARYING {
+        if (context->globalErrorCheck($1.line, context->symbolTable.atGlobalLevel(), "invariant varying"))
+            context->recover();
+        if (context->shaderType == SH_VERTEX_SHADER)
+            $$.setBasic(EbtVoid, EvqInvariantVaryingOut, $1.line);
+        else
+            $$.setBasic(EbtVoid, EvqInvariantVaryingIn, $1.line);
+    }
+    | UNIFORM {
+        if (context->globalErrorCheck($1.line, context->symbolTable.atGlobalLevel(), "uniform"))
+            context->recover();
+        $$.setBasic(EbtVoid, EvqUniform, $1.line);
+    }
+    ;
+
+type_specifier
+    : type_specifier_no_prec {
+        $$ = $1;
+
+        if ($$.precision == EbpUndefined) {
+            $$.precision = context->symbolTable.getDefaultPrecision($1.type);
+            if (context->precisionErrorCheck($1.line, $$.precision, $1.type)) {
+                context->recover();
+            }
+        }
+    }
+    | precision_qualifier type_specifier_no_prec {
+        $$ = $2;
+        $$.precision = $1;
+    }
+    ;
+
+precision_qualifier
+    : HIGH_PRECISION {
+        $$ = EbpHigh;
+    }
+    | MEDIUM_PRECISION {
+        $$ = EbpMedium;
+    }
+    | LOW_PRECISION  {
+        $$ = EbpLow;
+    }
+    ;
+
+type_specifier_no_prec
+    : type_specifier_nonarray {
+        $$ = $1;
+    }
+    | type_specifier_nonarray LEFT_BRACKET constant_expression RIGHT_BRACKET {
+        $$ = $1;
+
+        if (context->arrayTypeErrorCheck($2.line, $1))
+            context->recover();
+        else {
+            int size;
+            if (context->arraySizeErrorCheck($2.line, $3, size))
+                context->recover();
+            $$.setArray(true, size);
+        }
+    }
+    ;
+
+type_specifier_nonarray
+    : VOID_TYPE {
+        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
+        $$.setBasic(EbtVoid, qual, $1.line);
+    }
+    | FLOAT_TYPE {
+        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
+        $$.setBasic(EbtFloat, qual, $1.line);
+    }
+    | INT_TYPE {
+        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
+        $$.setBasic(EbtInt, qual, $1.line);
+    }
+    | BOOL_TYPE {
+        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
+        $$.setBasic(EbtBool, qual, $1.line);
+    }
+//    | UNSIGNED INT_TYPE {
+//        PACK_UNPACK_ONLY("unsigned", $1.line);
+//        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
+//        $$.setBasic(EbtInt, qual, $1.line);
+//    }
+    | VEC2 {
+        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
+        $$.setBasic(EbtFloat, qual, $1.line);
+        $$.setAggregate(2);
+    }
+    | VEC3 {
+        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
+        $$.setBasic(EbtFloat, qual, $1.line);
+        $$.setAggregate(3);
+    }
+    | VEC4 {
+        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
+        $$.setBasic(EbtFloat, qual, $1.line);
+        $$.setAggregate(4);
+    }
+    | BVEC2 {
+        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
+        $$.setBasic(EbtBool, qual, $1.line);
+        $$.setAggregate(2);
+    }
+    | BVEC3 {
+        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
+        $$.setBasic(EbtBool, qual, $1.line);
+        $$.setAggregate(3);
+    }
+    | BVEC4 {
+        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
+        $$.setBasic(EbtBool, qual, $1.line);
+        $$.setAggregate(4);
+    }
+    | IVEC2 {
+        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
+        $$.setBasic(EbtInt, qual, $1.line);
+        $$.setAggregate(2);
+    }
+    | IVEC3 {
+        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
+        $$.setBasic(EbtInt, qual, $1.line);
+        $$.setAggregate(3);
+    }
+    | IVEC4 {
+        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
+        $$.setBasic(EbtInt, qual, $1.line);
+        $$.setAggregate(4);
+    }
+    | MATRIX2 {
+        FRAG_VERT_ONLY("mat2", $1.line);
+        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
+        $$.setBasic(EbtFloat, qual, $1.line);
+        $$.setAggregate(2, true);
+    }
+    | MATRIX3 {
+        FRAG_VERT_ONLY("mat3", $1.line);
+        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
+        $$.setBasic(EbtFloat, qual, $1.line);
+        $$.setAggregate(3, true);
+    }
+    | MATRIX4 {
+        FRAG_VERT_ONLY("mat4", $1.line);
+        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
+        $$.setBasic(EbtFloat, qual, $1.line);
+        $$.setAggregate(4, true);
+    }
+    | SAMPLER2D {
+        FRAG_VERT_ONLY("sampler2D", $1.line);
+        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
+        $$.setBasic(EbtSampler2D, qual, $1.line);
+    }
+    | SAMPLERCUBE {
+        FRAG_VERT_ONLY("samplerCube", $1.line);
+        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
+        $$.setBasic(EbtSamplerCube, qual, $1.line);
+    }
+    | struct_specifier {
+        FRAG_VERT_ONLY("struct", $1.line);
+        $$ = $1;
+        $$.qualifier = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
+    }
+    | TYPE_NAME {
+        //
+        // This is for user defined type names.  The lexical phase looked up the
+        // type.
+        //
+        TType& structure = static_cast<TVariable*>($1.symbol)->getType();
+        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
+        $$.setBasic(EbtStruct, qual, $1.line);
+        $$.userDef = &structure;
+    }
+    ;
+
+struct_specifier
+    : STRUCT IDENTIFIER LEFT_BRACE { if (context->enterStructDeclaration($2.line, *$2.string)) context->recover(); } struct_declaration_list RIGHT_BRACE {
+        if (context->reservedErrorCheck($2.line, *$2.string))
+            context->recover();
+
+        TType* structure = new TType($5, *$2.string);
+        TVariable* userTypeDef = new TVariable($2.string, *structure, true);
+        if (! context->symbolTable.insert(*userTypeDef)) {
+            context->error($2.line, "redefinition", $2.string->c_str(), "struct");
+            context->recover();
+        }
+        $$.setBasic(EbtStruct, EvqTemporary, $1.line);
+        $$.userDef = structure;
+        context->exitStructDeclaration();
+    }
+    | STRUCT LEFT_BRACE { if (context->enterStructDeclaration($2.line, *$2.string)) context->recover(); } struct_declaration_list RIGHT_BRACE {
+        TType* structure = new TType($4, TString(""));
+        $$.setBasic(EbtStruct, EvqTemporary, $1.line);
+        $$.userDef = structure;
+        context->exitStructDeclaration();
+    }
+    ;
+
+struct_declaration_list
+    : struct_declaration {
+        $$ = $1;
+    }
+    | struct_declaration_list struct_declaration {
+        $$ = $1;
+        for (unsigned int i = 0; i < $2->size(); ++i) {
+            for (unsigned int j = 0; j < $$->size(); ++j) {
+                if ((*$$)[j].type->getFieldName() == (*$2)[i].type->getFieldName()) {
+                    context->error((*$2)[i].line, "duplicate field name in structure:", "struct", (*$2)[i].type->getFieldName().c_str());
+                    context->recover();
+                }
+            }
+            $$->push_back((*$2)[i]);
+        }
+    }
+    ;
+
+struct_declaration
+    : type_specifier struct_declarator_list SEMICOLON {
+        $$ = $2;
+
+        if (context->voidErrorCheck($1.line, (*$2)[0].type->getFieldName(), $1)) {
+            context->recover();
+        }
+        for (unsigned int i = 0; i < $$->size(); ++i) {
+            //
+            // Careful not to replace already known aspects of type, like array-ness
+            //
+            TType* type = (*$$)[i].type;
+            type->setBasicType($1.type);
+            type->setNominalSize($1.size);
+            type->setMatrix($1.matrix);
+            type->setPrecision($1.precision);
+
+            // don't allow arrays of arrays
+            if (type->isArray()) {
+                if (context->arrayTypeErrorCheck($1.line, $1))
+                    context->recover();
+            }
+            if ($1.array)
+                type->setArraySize($1.arraySize);
+            if ($1.userDef) {
+                type->setStruct($1.userDef->getStruct());
+                type->setTypeName($1.userDef->getTypeName());
+            }
+
+            if (context->structNestingErrorCheck($1.line, *type)) {
+                context->recover();
+            }
+        }
+    }
+    ;
+
+struct_declarator_list
+    : struct_declarator {
+        $$ = NewPoolTTypeList();
+        $$->push_back($1);
+    }
+    | struct_declarator_list COMMA struct_declarator {
+        $$->push_back($3);
+    }
+    ;
+
+struct_declarator
+    : IDENTIFIER {
+        if (context->reservedErrorCheck($1.line, *$1.string))
+            context->recover();
+
+        $$.type = new TType(EbtVoid, EbpUndefined);
+        $$.line = $1.line;
+        $$.type->setFieldName(*$1.string);
+    }
+    | IDENTIFIER LEFT_BRACKET constant_expression RIGHT_BRACKET {
+        if (context->reservedErrorCheck($1.line, *$1.string))
+            context->recover();
+
+        $$.type = new TType(EbtVoid, EbpUndefined);
+        $$.line = $1.line;
+        $$.type->setFieldName(*$1.string);
+
+        int size;
+        if (context->arraySizeErrorCheck($2.line, $3, size))
+            context->recover();
+        $$.type->setArraySize(size);
+    }
+    ;
+
+initializer
+    : assignment_expression { $$ = $1; }
+    ;
+
+declaration_statement
+    : declaration { $$ = $1; }
+    ;
+
+statement
+    : compound_statement  { $$ = $1; }
+    | simple_statement    { $$ = $1; }
+    ;
+
+// Grammar Note:  No labeled statements; 'goto' is not supported.
+
+simple_statement
+    : declaration_statement { $$ = $1; }
+    | expression_statement  { $$ = $1; }
+    | selection_statement   { $$ = $1; }
+    | iteration_statement   { $$ = $1; }
+    | jump_statement        { $$ = $1; }
+    ;
+
+compound_statement
+    : LEFT_BRACE RIGHT_BRACE { $$ = 0; }
+    | LEFT_BRACE { context->symbolTable.push(); } statement_list { context->symbolTable.pop(); } RIGHT_BRACE {
+        if ($3 != 0) {
+            $3->setOp(EOpSequence);
+            $3->setEndLine($5.line);
+        }
+        $$ = $3;
+    }
+    ;
+
+statement_no_new_scope
+    : compound_statement_no_new_scope { $$ = $1; }
+    | simple_statement                { $$ = $1; }
+    ;
+
+statement_with_scope
+    : { context->symbolTable.push(); } compound_statement_no_new_scope { context->symbolTable.pop(); $$ = $2; }
+    | { context->symbolTable.push(); } simple_statement                { context->symbolTable.pop(); $$ = $2; }
+    ;
+
+compound_statement_no_new_scope
+    // Statement that doesn't create a new scope, for selection_statement, iteration_statement
+    : LEFT_BRACE RIGHT_BRACE {
+        $$ = 0;
+    }
+    | LEFT_BRACE statement_list RIGHT_BRACE {
+        if ($2) {
+            $2->setOp(EOpSequence);
+            $2->setEndLine($3.line);
+        }
+        $$ = $2;
+    }
+    ;
+
+statement_list
+    : statement {
+        $$ = context->intermediate.makeAggregate($1, 0);
+    }
+    | statement_list statement {
+        $$ = context->intermediate.growAggregate($1, $2, 0);
+    }
+    ;
+
+expression_statement
+    : SEMICOLON  { $$ = 0; }
+    | expression SEMICOLON  { $$ = static_cast<TIntermNode*>($1); }
+    ;
+
+selection_statement
+    : IF LEFT_PAREN expression RIGHT_PAREN selection_rest_statement {
+        if (context->boolErrorCheck($1.line, $3))
+            context->recover();
+        $$ = context->intermediate.addSelection($3, $5, $1.line);
+    }
+    ;
+
+selection_rest_statement
+    : statement_with_scope ELSE statement_with_scope {
+        $$.node1 = $1;
+        $$.node2 = $3;
+    }
+    | statement_with_scope {
+        $$.node1 = $1;
+        $$.node2 = 0;
+    }
+    ;
+
+// Grammar Note:  No 'switch'.  Switch statements not supported.
+
+condition
+    // In 1996 c++ draft, conditions can include single declarations
+    : expression {
+        $$ = $1;
+        if (context->boolErrorCheck($1->getLine(), $1))
+            context->recover();
+    }
+    | fully_specified_type IDENTIFIER EQUAL initializer {
+        TIntermNode* intermNode;
+        if (context->structQualifierErrorCheck($2.line, $1))
+            context->recover();
+        if (context->boolErrorCheck($2.line, $1))
+            context->recover();
+
+        if (!context->executeInitializer($2.line, *$2.string, $1, $4, intermNode))
+            $$ = $4;
+        else {
+            context->recover();
+            $$ = 0;
+        }
+    }
+    ;
+
+iteration_statement
+    : WHILE LEFT_PAREN { context->symbolTable.push(); ++context->loopNestingLevel; } condition RIGHT_PAREN statement_no_new_scope {
+        context->symbolTable.pop();
+        $$ = context->intermediate.addLoop(ELoopWhile, 0, $4, 0, $6, $1.line);
+        --context->loopNestingLevel;
+    }
+    | DO { ++context->loopNestingLevel; } statement_with_scope WHILE LEFT_PAREN expression RIGHT_PAREN SEMICOLON {
+        if (context->boolErrorCheck($8.line, $6))
+            context->recover();
+
+        $$ = context->intermediate.addLoop(ELoopDoWhile, 0, $6, 0, $3, $4.line);
+        --context->loopNestingLevel;
+    }
+    | FOR LEFT_PAREN { context->symbolTable.push(); ++context->loopNestingLevel; } for_init_statement for_rest_statement RIGHT_PAREN statement_no_new_scope {
+        context->symbolTable.pop();
+        $$ = context->intermediate.addLoop(ELoopFor, $4, reinterpret_cast<TIntermTyped*>($5.node1), reinterpret_cast<TIntermTyped*>($5.node2), $7, $1.line);
+        --context->loopNestingLevel;
+    }
+    ;
+
+for_init_statement
+    : expression_statement {
+        $$ = $1;
+    }
+    | declaration_statement {
+        $$ = $1;
+    }
+    ;
+
+conditionopt
+    : condition {
+        $$ = $1;
+    }
+    | /* May be null */ {
+        $$ = 0;
+    }
+    ;
+
+for_rest_statement
+    : conditionopt SEMICOLON {
+        $$.node1 = $1;
+        $$.node2 = 0;
+    }
+    | conditionopt SEMICOLON expression  {
+        $$.node1 = $1;
+        $$.node2 = $3;
+    }
+    ;
+
+jump_statement
+    : CONTINUE SEMICOLON {
+        if (context->loopNestingLevel <= 0) {
+            context->error($1.line, "continue statement only allowed in loops", "");
+            context->recover();
+        }
+        $$ = context->intermediate.addBranch(EOpContinue, $1.line);
+    }
+    | BREAK SEMICOLON {
+        if (context->loopNestingLevel <= 0) {
+            context->error($1.line, "break statement only allowed in loops", "");
+            context->recover();
+        }
+        $$ = context->intermediate.addBranch(EOpBreak, $1.line);
+    }
+    | RETURN SEMICOLON {
+        $$ = context->intermediate.addBranch(EOpReturn, $1.line);
+        if (context->currentFunctionType->getBasicType() != EbtVoid) {
+            context->error($1.line, "non-void function must return a value", "return");
+            context->recover();
+        }
+    }
+    | RETURN expression SEMICOLON {
+        $$ = context->intermediate.addBranch(EOpReturn, $2, $1.line);
+        context->functionReturnsValue = true;
+        if (context->currentFunctionType->getBasicType() == EbtVoid) {
+            context->error($1.line, "void function cannot return a value", "return");
+            context->recover();
+        } else if (*(context->currentFunctionType) != $2->getType()) {
+            context->error($1.line, "function return is not matching type:", "return");
+            context->recover();
+        }
+    }
+    | DISCARD SEMICOLON {
+        FRAG_ONLY("discard", $1.line);
+        $$ = context->intermediate.addBranch(EOpKill, $1.line);
+    }
+    ;
+
+// Grammar Note:  No 'goto'.  Gotos are not supported.
+
+translation_unit
+    : external_declaration {
+        $$ = $1;
+        context->treeRoot = $$;
+    }
+    | translation_unit external_declaration {
+        $$ = context->intermediate.growAggregate($1, $2, 0);
+        context->treeRoot = $$;
+    }
+    ;
+
+external_declaration
+    : function_definition {
+        $$ = $1;
+    }
+    | declaration {
+        $$ = $1;
+    }
+    ;
+
+function_definition
+    : function_prototype {
+        TFunction* function = $1.function;
+        
+        const TSymbol *builtIn = context->symbolTable.findBuiltIn(function->getMangledName());
+        
+        if (builtIn)
+        {
+            context->error($1.line, "built-in functions cannot be redefined", function->getName().c_str());
+            context->recover();
+        }
+        
+        TFunction* prevDec = static_cast<TFunction*>(context->symbolTable.find(function->getMangledName()));
+        //
+        // Note:  'prevDec' could be 'function' if this is the first time we've seen function
+        // as it would have just been put in the symbol table.  Otherwise, we're looking up
+        // an earlier occurance.
+        //
+        if (prevDec->isDefined()) {
+            //
+            // Then this function already has a body.
+            //
+            context->error($1.line, "function already has a body", function->getName().c_str());
+            context->recover();
+        }
+        prevDec->setDefined();
+
+        //
+        // Raise error message if main function takes any parameters or return anything other than void
+        //
+        if (function->getName() == "main") {
+            if (function->getParamCount() > 0) {
+                context->error($1.line, "function cannot take any parameter(s)", function->getName().c_str());
+                context->recover();
+            }
+            if (function->getReturnType().getBasicType() != EbtVoid) {
+                context->error($1.line, "", function->getReturnType().getBasicString(), "main function cannot return a value");
+                context->recover();
+            }
+        }
+
+        //
+        // Remember the return type for later checking for RETURN statements.
+        //
+        context->currentFunctionType = &(prevDec->getReturnType());
+        context->functionReturnsValue = false;
+
+        //
+        // Insert parameters into the symbol table.
+        // If the parameter has no name, it's not an error, just don't insert it
+        // (could be used for unused args).
+        //
+        // Also, accumulate the list of parameters into the HIL, so lower level code
+        // knows where to find parameters.
+        //
+        TIntermAggregate* paramNodes = new TIntermAggregate;
+        for (int i = 0; i < function->getParamCount(); i++) {
+            const TParameter& param = function->getParam(i);
+            if (param.name != 0) {
+                TVariable *variable = new TVariable(param.name, *param.type);
+                //
+                // Insert the parameters with name in the symbol table.
+                //
+                if (! context->symbolTable.insert(*variable)) {
+                    context->error($1.line, "redefinition", variable->getName().c_str());
+                    context->recover();
+                    delete variable;
+                }
+
+                //
+                // Add the parameter to the HIL
+                //
+                paramNodes = context->intermediate.growAggregate(
+                                               paramNodes,
+                                               context->intermediate.addSymbol(variable->getUniqueId(),
+                                                                       variable->getName(),
+                                                                       variable->getType(), $1.line),
+                                               $1.line);
+            } else {
+                paramNodes = context->intermediate.growAggregate(paramNodes, context->intermediate.addSymbol(0, "", *param.type, $1.line), $1.line);
+            }
+        }
+        context->intermediate.setAggregateOperator(paramNodes, EOpParameters, $1.line);
+        $1.intermAggregate = paramNodes;
+        context->loopNestingLevel = 0;
+    }
+    compound_statement_no_new_scope {
+        //?? Check that all paths return a value if return type != void ?
+        //   May be best done as post process phase on intermediate code
+        if (context->currentFunctionType->getBasicType() != EbtVoid && ! context->functionReturnsValue) {
+            context->error($1.line, "function does not return a value:", "", $1.function->getName().c_str());
+            context->recover();
+        }
+        
+        $$ = context->intermediate.growAggregate($1.intermAggregate, $3, 0);
+        context->intermediate.setAggregateOperator($$, EOpFunction, $1.line);
+        $$->getAsAggregate()->setName($1.function->getMangledName().c_str());
+        $$->getAsAggregate()->setType($1.function->getReturnType());
+
+        // store the pragma information for debug and optimize and other vendor specific
+        // information. This information can be queried from the parse tree
+        $$->getAsAggregate()->setOptimize(context->pragma().optimize);
+        $$->getAsAggregate()->setDebug(context->pragma().debug);
+
+        if ($3 && $3->getAsAggregate())
+            $$->getAsAggregate()->setEndLine($3->getAsAggregate()->getEndLine());
+
+        context->symbolTable.pop();
+    }
+    ;
+
+%%
+
+int glslang_parse(TParseContext* context) {
+    return yyparse(context);
+}
+
diff --git a/src/GLES2/compiler/glslang_lex.cpp b/src/GLES2/compiler/glslang_lex.cpp
new file mode 100644
index 0000000..e2c8a9e
--- /dev/null
+++ b/src/GLES2/compiler/glslang_lex.cpp
@@ -0,0 +1,3029 @@
+#line 17 "./glslang.l"
+//
+// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// This file is auto-generated by generate_parser.sh. DO NOT EDIT!
+
+// Ignore errors in auto-generated code.
+#if defined(__GNUC__)
+#pragma GCC diagnostic ignored "-Wunused-function"
+#pragma GCC diagnostic ignored "-Wunused-variable"
+#pragma GCC diagnostic ignored "-Wswitch-enum"
+#elif defined(_MSC_VER)
+#pragma warning(disable: 4065)
+#pragma warning(disable: 4189)
+#pragma warning(disable: 4505)
+#pragma warning(disable: 4701)
+#endif
+
+
+
+#line 25 "./glslang_lex.cpp"
+
+#define  YY_INT_ALIGNED short int
+
+/* A lexical scanner generated by flex */
+
+#define FLEX_SCANNER
+#define YY_FLEX_MAJOR_VERSION 2
+#define YY_FLEX_MINOR_VERSION 5
+#define YY_FLEX_SUBMINOR_VERSION 35
+#if YY_FLEX_SUBMINOR_VERSION > 0
+#define FLEX_BETA
+#endif
+
+/* First, we deal with  platform-specific or compiler-specific issues. */
+
+/* begin standard C headers. */
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <stdlib.h>
+
+/* end standard C headers. */
+
+/* flex integer type definitions */
+
+#ifndef FLEXINT_H
+#define FLEXINT_H
+
+/* C99 systems have <inttypes.h>. Non-C99 systems may or may not. */
+
+#if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
+
+/* C99 says to define __STDC_LIMIT_MACROS before including stdint.h,
+ * if you want the limit (max/min) macros for int types. 
+ */
+#ifndef __STDC_LIMIT_MACROS
+#define __STDC_LIMIT_MACROS 1
+#endif
+
+#include <inttypes.h>
+typedef int8_t flex_int8_t;
+typedef uint8_t flex_uint8_t;
+typedef int16_t flex_int16_t;
+typedef uint16_t flex_uint16_t;
+typedef int32_t flex_int32_t;
+typedef uint32_t flex_uint32_t;
+#else
+typedef signed char flex_int8_t;
+typedef short int flex_int16_t;
+typedef int flex_int32_t;
+typedef unsigned char flex_uint8_t; 
+typedef unsigned short int flex_uint16_t;
+typedef unsigned int flex_uint32_t;
+#endif /* ! C99 */
+
+/* Limits of integral types. */
+#ifndef INT8_MIN
+#define INT8_MIN               (-128)
+#endif
+#ifndef INT16_MIN
+#define INT16_MIN              (-32767-1)
+#endif
+#ifndef INT32_MIN
+#define INT32_MIN              (-2147483647-1)
+#endif
+#ifndef INT8_MAX
+#define INT8_MAX               (127)
+#endif
+#ifndef INT16_MAX
+#define INT16_MAX              (32767)
+#endif
+#ifndef INT32_MAX
+#define INT32_MAX              (2147483647)
+#endif
+#ifndef UINT8_MAX
+#define UINT8_MAX              (255U)
+#endif
+#ifndef UINT16_MAX
+#define UINT16_MAX             (65535U)
+#endif
+#ifndef UINT32_MAX
+#define UINT32_MAX             (4294967295U)
+#endif
+
+#endif /* ! FLEXINT_H */
+
+#ifdef __cplusplus
+
+/* The "const" storage-class-modifier is valid. */
+#define YY_USE_CONST
+
+#else	/* ! __cplusplus */
+
+/* C99 requires __STDC__ to be defined as 1. */
+#if defined (__STDC__)
+
+#define YY_USE_CONST
+
+#endif	/* defined (__STDC__) */
+#endif	/* ! __cplusplus */
+
+#ifdef YY_USE_CONST
+#define yyconst const
+#else
+#define yyconst
+#endif
+
+/* Returned upon end-of-file. */
+#define YY_NULL 0
+
+/* Promotes a possibly negative, possibly signed char to an unsigned
+ * integer for use as an array index.  If the signed char is negative,
+ * we want to instead treat it as an 8-bit unsigned char, hence the
+ * double cast.
+ */
+#define YY_SC_TO_UI(c) ((unsigned int) (unsigned char) c)
+
+/* An opaque pointer. */
+#ifndef YY_TYPEDEF_YY_SCANNER_T
+#define YY_TYPEDEF_YY_SCANNER_T
+typedef void* yyscan_t;
+#endif
+
+/* For convenience, these vars (plus the bison vars far below)
+   are macros in the reentrant scanner. */
+#define yyin yyg->yyin_r
+#define yyout yyg->yyout_r
+#define yyextra yyg->yyextra_r
+#define yyleng yyg->yyleng_r
+#define yytext yyg->yytext_r
+#define yylineno (YY_CURRENT_BUFFER_LVALUE->yy_bs_lineno)
+#define yycolumn (YY_CURRENT_BUFFER_LVALUE->yy_bs_column)
+#define yy_flex_debug yyg->yy_flex_debug_r
+
+/* Enter a start condition.  This macro really ought to take a parameter,
+ * but we do it the disgusting crufty way forced on us by the ()-less
+ * definition of BEGIN.
+ */
+#define BEGIN yyg->yy_start = 1 + 2 *
+
+/* Translate the current start state into a value that can be later handed
+ * to BEGIN to return to the state.  The YYSTATE alias is for lex
+ * compatibility.
+ */
+#define YY_START ((yyg->yy_start - 1) / 2)
+#define YYSTATE YY_START
+
+/* Action number for EOF rule of a given start state. */
+#define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1)
+
+/* Special action meaning "start processing a new file". */
+#define YY_NEW_FILE yyrestart(yyin ,yyscanner )
+
+#define YY_END_OF_BUFFER_CHAR 0
+
+/* Size of default input buffer. */
+#ifndef YY_BUF_SIZE
+#define YY_BUF_SIZE 16384
+#endif
+
+/* The state buf must be large enough to hold one state per character in the main buffer.
+ */
+#define YY_STATE_BUF_SIZE   ((YY_BUF_SIZE + 2) * sizeof(yy_state_type))
+
+#ifndef YY_TYPEDEF_YY_BUFFER_STATE
+#define YY_TYPEDEF_YY_BUFFER_STATE
+typedef struct yy_buffer_state *YY_BUFFER_STATE;
+#endif
+
+#define EOB_ACT_CONTINUE_SCAN 0
+#define EOB_ACT_END_OF_FILE 1
+#define EOB_ACT_LAST_MATCH 2
+
+    /* Note: We specifically omit the test for yy_rule_can_match_eol because it requires
+     *       access to the local variable yy_act. Since yyless() is a macro, it would break
+     *       existing scanners that call yyless() from OUTSIDE yylex. 
+     *       One obvious solution it to make yy_act a global. I tried that, and saw
+     *       a 5% performance hit in a non-yylineno scanner, because yy_act is
+     *       normally declared as a register variable-- so it is not worth it.
+     */
+    #define  YY_LESS_LINENO(n) \
+            do { \
+                int yyl;\
+                for ( yyl = n; yyl < yyleng; ++yyl )\
+                    if ( yytext[yyl] == '\n' )\
+                        --yylineno;\
+            }while(0)
+    
+/* Return all but the first "n" matched characters back to the input stream. */
+#define yyless(n) \
+	do \
+		{ \
+		/* Undo effects of setting up yytext. */ \
+        int yyless_macro_arg = (n); \
+        YY_LESS_LINENO(yyless_macro_arg);\
+		*yy_cp = yyg->yy_hold_char; \
+		YY_RESTORE_YY_MORE_OFFSET \
+		yyg->yy_c_buf_p = yy_cp = yy_bp + yyless_macro_arg - YY_MORE_ADJ; \
+		YY_DO_BEFORE_ACTION; /* set up yytext again */ \
+		} \
+	while ( 0 )
+
+#define unput(c) yyunput( c, yyg->yytext_ptr , yyscanner )
+
+#ifndef YY_TYPEDEF_YY_SIZE_T
+#define YY_TYPEDEF_YY_SIZE_T
+typedef size_t yy_size_t;
+#endif
+
+#ifndef YY_STRUCT_YY_BUFFER_STATE
+#define YY_STRUCT_YY_BUFFER_STATE
+struct yy_buffer_state
+	{
+	FILE *yy_input_file;
+
+	char *yy_ch_buf;		/* input buffer */
+	char *yy_buf_pos;		/* current position in input buffer */
+
+	/* Size of input buffer in bytes, not including room for EOB
+	 * characters.
+	 */
+	yy_size_t yy_buf_size;
+
+	/* Number of characters read into yy_ch_buf, not including EOB
+	 * characters.
+	 */
+	int yy_n_chars;
+
+	/* Whether we "own" the buffer - i.e., we know we created it,
+	 * and can realloc() it to grow it, and should free() it to
+	 * delete it.
+	 */
+	int yy_is_our_buffer;
+
+	/* Whether this is an "interactive" input source; if so, and
+	 * if we're using stdio for input, then we want to use getc()
+	 * instead of fread(), to make sure we stop fetching input after
+	 * each newline.
+	 */
+	int yy_is_interactive;
+
+	/* Whether we're considered to be at the beginning of a line.
+	 * If so, '^' rules will be active on the next match, otherwise
+	 * not.
+	 */
+	int yy_at_bol;
+
+    int yy_bs_lineno; /**< The line count. */
+    int yy_bs_column; /**< The column count. */
+    
+	/* Whether to try to fill the input buffer when we reach the
+	 * end of it.
+	 */
+	int yy_fill_buffer;
+
+	int yy_buffer_status;
+
+#define YY_BUFFER_NEW 0
+#define YY_BUFFER_NORMAL 1
+	/* When an EOF's been seen but there's still some text to process
+	 * then we mark the buffer as YY_EOF_PENDING, to indicate that we
+	 * shouldn't try reading from the input source any more.  We might
+	 * still have a bunch of tokens to match, though, because of
+	 * possible backing-up.
+	 *
+	 * When we actually see the EOF, we change the status to "new"
+	 * (via yyrestart()), so that the user can continue scanning by
+	 * just pointing yyin at a new input file.
+	 */
+#define YY_BUFFER_EOF_PENDING 2
+
+	};
+#endif /* !YY_STRUCT_YY_BUFFER_STATE */
+
+/* We provide macros for accessing buffer states in case in the
+ * future we want to put the buffer states in a more general
+ * "scanner state".
+ *
+ * Returns the top of the stack, or NULL.
+ */
+#define YY_CURRENT_BUFFER ( yyg->yy_buffer_stack \
+                          ? yyg->yy_buffer_stack[yyg->yy_buffer_stack_top] \
+                          : NULL)
+
+/* Same as previous macro, but useful when we know that the buffer stack is not
+ * NULL or when we need an lvalue. For internal use only.
+ */
+#define YY_CURRENT_BUFFER_LVALUE yyg->yy_buffer_stack[yyg->yy_buffer_stack_top]
+
+void yyrestart (FILE *input_file ,yyscan_t yyscanner );
+void yy_switch_to_buffer (YY_BUFFER_STATE new_buffer ,yyscan_t yyscanner );
+YY_BUFFER_STATE yy_create_buffer (FILE *file,int size ,yyscan_t yyscanner );
+void yy_delete_buffer (YY_BUFFER_STATE b ,yyscan_t yyscanner );
+void yy_flush_buffer (YY_BUFFER_STATE b ,yyscan_t yyscanner );
+void yypush_buffer_state (YY_BUFFER_STATE new_buffer ,yyscan_t yyscanner );
+void yypop_buffer_state (yyscan_t yyscanner );
+
+static void yyensure_buffer_stack (yyscan_t yyscanner );
+static void yy_load_buffer_state (yyscan_t yyscanner );
+static void yy_init_buffer (YY_BUFFER_STATE b,FILE *file ,yyscan_t yyscanner );
+
+#define YY_FLUSH_BUFFER yy_flush_buffer(YY_CURRENT_BUFFER ,yyscanner)
+
+YY_BUFFER_STATE yy_scan_buffer (char *base,yy_size_t size ,yyscan_t yyscanner );
+YY_BUFFER_STATE yy_scan_string (yyconst char *yy_str ,yyscan_t yyscanner );
+YY_BUFFER_STATE yy_scan_bytes (yyconst char *bytes,int len ,yyscan_t yyscanner );
+
+void *yyalloc (yy_size_t ,yyscan_t yyscanner );
+void *yyrealloc (void *,yy_size_t ,yyscan_t yyscanner );
+void yyfree (void * ,yyscan_t yyscanner );
+
+#define yy_new_buffer yy_create_buffer
+
+#define yy_set_interactive(is_interactive) \
+	{ \
+	if ( ! YY_CURRENT_BUFFER ){ \
+        yyensure_buffer_stack (yyscanner); \
+		YY_CURRENT_BUFFER_LVALUE =    \
+            yy_create_buffer(yyin,YY_BUF_SIZE ,yyscanner); \
+	} \
+	YY_CURRENT_BUFFER_LVALUE->yy_is_interactive = is_interactive; \
+	}
+
+#define yy_set_bol(at_bol) \
+	{ \
+	if ( ! YY_CURRENT_BUFFER ){\
+        yyensure_buffer_stack (yyscanner); \
+		YY_CURRENT_BUFFER_LVALUE =    \
+            yy_create_buffer(yyin,YY_BUF_SIZE ,yyscanner); \
+	} \
+	YY_CURRENT_BUFFER_LVALUE->yy_at_bol = at_bol; \
+	}
+
+#define YY_AT_BOL() (YY_CURRENT_BUFFER_LVALUE->yy_at_bol)
+
+/* Begin user sect3 */
+
+#define yywrap(n) 1
+#define YY_SKIP_YYWRAP
+
+typedef unsigned char YY_CHAR;
+
+typedef int yy_state_type;
+
+#define yytext_ptr yytext_r
+
+static yy_state_type yy_get_previous_state (yyscan_t yyscanner );
+static yy_state_type yy_try_NUL_trans (yy_state_type current_state  ,yyscan_t yyscanner);
+static int yy_get_next_buffer (yyscan_t yyscanner );
+static void yy_fatal_error (yyconst char msg[] ,yyscan_t yyscanner );
+
+/* Done after the current pattern has been matched and before the
+ * corresponding action - sets up yytext.
+ */
+#define YY_DO_BEFORE_ACTION \
+	yyg->yytext_ptr = yy_bp; \
+	yyleng = (size_t) (yy_cp - yy_bp); \
+	yyg->yy_hold_char = *yy_cp; \
+	*yy_cp = '\0'; \
+	yyg->yy_c_buf_p = yy_cp;
+
+#define YY_NUM_RULES 154
+#define YY_END_OF_BUFFER 155
+/* This struct is not used in this scanner,
+   but its presence is necessary. */
+struct yy_trans_info
+	{
+	flex_int32_t yy_verify;
+	flex_int32_t yy_nxt;
+	};
+static yyconst flex_int16_t yy_accept[448] =
+    {   0,
+        0,    0,    0,    0,    0,    0,  155,  153,  152,  152,
+      137,  143,  148,  132,  133,  141,  140,  129,  138,  136,
+      142,  101,  101,  130,  126,  144,  131,  145,  149,   97,
+      134,  135,  147,   97,   97,   97,   97,   97,   97,   97,
+       97,   97,   97,   97,   97,   97,   97,   97,   97,   97,
+       97,   97,   97,  127,  146,  128,  139,    3,    4,    3,
+      151,  154,  150,  123,  109,  128,  117,  112,  107,  115,
+      105,  116,  106,  104,    2,    1,  108,  103,   99,  100,
+        0,    0,  101,  135,  127,  134,  124,  120,  122,  121,
+      125,   97,  113,  119,   97,   97,   97,   97,   97,   97,
+
+       97,   97,   97,   97,   17,   97,   97,   97,   97,   97,
+       97,   97,   97,   97,   97,   97,   97,   97,   20,   22,
+       97,   97,   97,   97,   97,   97,   97,   97,   97,   97,
+       97,   97,   97,   97,   97,   97,   97,   97,   97,   97,
+       97,   97,   97,   97,   97,   97,   97,  114,  118,    5,
+      150,    0,    1,  103,    0,    0,  102,   98,  110,  111,
+       48,   97,   97,   97,   97,   97,   97,   97,   97,   97,
+       97,   97,   97,   97,   97,   97,   97,   97,   97,   18,
+       97,   97,   97,   97,   97,   97,   97,   97,   26,   97,
+       97,   97,   97,   97,   97,   97,   97,   23,   97,   97,
+
+       97,   97,   97,   97,   97,   97,   97,   97,   97,   97,
+       97,   97,   97,   97,   97,   97,   97,   97,   97,   97,
+       97,    0,  104,    0,  103,   97,   28,   97,   97,   94,
+       97,   97,   97,   97,   97,   97,   97,   21,   51,   97,
+       97,   97,   67,   97,   97,   56,   71,   97,   97,   97,
+       97,   97,   97,   97,   97,   68,    9,   33,   34,   35,
+       97,   97,   97,   97,   97,   97,   97,   97,   97,   97,
+       97,   97,   97,   97,   97,   97,   54,   29,   97,   97,
+       97,   97,   97,   97,   36,   37,   38,   27,   97,   97,
+       97,   15,   42,   43,   44,   49,   12,   97,   97,   97,
+
+       97,   80,   81,   82,   97,   30,   72,   25,   83,   84,
+       85,    7,   77,   78,   79,   97,   24,   75,   97,   97,
+       39,   40,   41,   97,   97,   97,   97,   97,   97,   97,
+       97,   97,   69,   97,   97,   97,   97,   97,   97,   97,
+       97,   50,   97,   96,   97,   97,   19,   97,   97,   97,
+       97,   70,   64,   59,   97,   97,   97,   97,   97,   76,
+       55,   97,   62,   32,   97,   93,   63,   47,   74,   57,
+       97,   97,   97,   97,   97,   97,   97,   97,   58,   31,
+       97,   97,   97,    8,   97,   97,   97,   97,   97,   52,
+       13,   97,   14,   97,   97,   16,   65,   97,   97,   97,
+
+       60,   97,   97,   97,   97,   97,   53,   73,   61,   11,
+       66,    6,   95,   10,   86,   45,   87,   97,   97,   97,
+       97,   97,   97,   97,   97,   97,   97,   46,   97,   97,
+       97,   97,   97,   90,   97,   91,   97,   97,   97,   88,
+       97,   89,   97,   97,   97,   92,    0
+    } ;
+
+static yyconst flex_int32_t yy_ec[256] =
+    {   0,
+        1,    1,    1,    1,    1,    1,    1,    1,    2,    3,
+        2,    2,    2,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    2,    4,    1,    1,    1,    5,    6,    1,    7,
+        8,    9,   10,   11,   12,   13,   14,   15,   16,   17,
+       18,   19,   20,   20,   20,   21,   21,   22,   23,   24,
+       25,   26,   27,    1,   28,   28,   29,   30,   31,   28,
+       32,   32,   32,   32,   32,   32,   32,   32,   32,   32,
+       32,   33,   34,   32,   32,   32,   32,   35,   32,   32,
+       36,    1,   37,   38,   32,    1,   39,   40,   41,   42,
+
+       43,   44,   45,   46,   47,   32,   48,   49,   50,   51,
+       52,   53,   32,   54,   55,   56,   57,   58,   59,   60,
+       61,   62,   63,   64,   65,   66,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1
+    } ;
+
+static yyconst flex_int32_t yy_meta[67] =
+    {   0,
+        1,    1,    2,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    3,    1,    4,    4,    4,    4,    4,    4,
+        4,    1,    1,    1,    1,    1,    1,    5,    5,    5,
+        4,    6,    6,    6,    6,    1,    1,    1,    5,    5,
+        5,    5,    4,    5,    6,    6,    6,    6,    6,    6,
+        6,    6,    6,    6,    6,    6,    6,    6,    6,    6,
+        6,    6,    1,    1,    1,    1
+    } ;
+
+static yyconst flex_int16_t yy_base[455] =
+    {   0,
+        0,    0,   64,   65,   74,    0,  649,  650,  650,  650,
+      623,   44,  135,  650,  650,  622,  132,  650,  131,  129,
+      144,  157,  148,  620,  650,  158,  620,   46,  650,    0,
+      650,  650,  126,   99,  113,  145,  138,  138,  154,  592,
+      160,  108,  591,  165,  163,  585,  156,  598,  175,  181,
+      154,  177,  594,  650,  161,  650,  650,  650,  650,  625,
+      650,  650,    0,  650,  650,  650,  650,  650,  650,  650,
+      650,  650,  650,  228,  650,    0,  650,  235,  176,  226,
+      264,    0,  227,  650,  650,  650,  613,  650,  650,  650,
+      612,    0,  650,  650,  586,  579,  582,  590,  589,  576,
+
+      591,  578,  584,  572,  569,  582,  569,  566,  566,  572,
+      560,  189,  565,  575,  561,  567,  570,  571,    0,  237,
+      570,  179,  556,  569,  560,  562,  552,  566,  563,  565,
+      548,  553,  550,  539,  221,  547,  552,  548,  550,  539,
+      542,  217,  547,  539,  551,  214,  544,  650,  650,  650,
+        0,  282,    0,  289,  306,  318,  325,    0,  650,  650,
+        0,  536,  540,  549,  546,  530,  530,  212,  545,  542,
+      542,  540,  537,  529,  535,  522,  533,  519,  535,    0,
+      532,  520,  527,  524,  528,  521,  510,  509,  522,  525,
+      522,  517,  508,  294,  513,  516,  507,  504,  508,  514,
+
+      505,  496,  499,  497,  507,  493,  491,  504,  490,  492,
+      489,  500,  499,  221,  494,  489,  478,  311,  496,  498,
+      487,  332,  339,  346,  353,  488,    0,  486,  358,    0,
+      478,  476,  484,  473,  490,  479,  361,    0,    0,  473,
+      483,  483,    0,  468,  364,    0,    0,  470,  367,  471,
+      465,  464,  465,  464,  370,    0,    0,    0,    0,    0,
+      460,  461,  466,  457,  470,  465,  464,  456,  460,  452,
+      455,  459,  464,  450,  462,  453,    0,    0,  459,  448,
+      448,  453,  452,  449,    0,    0,    0,    0,  439,  451,
+      453,    0,    0,    0,    0,    0,    0,  441,  442,  436,
+
+      446,    0,    0,    0,  437,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,  444,    0,    0,  442,  438,
+        0,    0,    0,  434,  430,  435,  425,  438,  424,  437,
+      426,  433,    0,  431,  433,  417,  419,  425,  431,  426,
+      414,    0,  416,    0,  415,  418,    0,  407,  406,  406,
+      419,    0,  421,    0,  420,  419,  404,  417,  404,    0,
+        0,  407,    0,    0,  399,    0,    0,    0,    0,    0,
+      396,  407,  400,  406,  403,  398,  390,  402,    0,    0,
+      395,  402,  391,    0,  400,  397,  387,  374,  395,    0,
+        0,  395,    0,  393,  392,    0,    0,  391,  377,  389,
+
+        0,  380,  400,  399,  398,  362,    0,    0,    0,    0,
+        0,    0,    0,    0,  368,  254,  368,  360,  353,  355,
+      351,  353,  352,  355,  352,  292,  278,    0,  275,  259,
+      272,  240,  239,  243,  210,    0,  178,  187,  167,    0,
+      184,    0,  177,  116,  103,    0,  650,  403,  407,  408,
+      411,  417,  421,  422
+    } ;
+
+static yyconst flex_int16_t yy_def[455] =
+    {   0,
+      447,    1,  448,  448,  447,    5,  447,  447,  447,  447,
+      447,  447,  447,  447,  447,  447,  447,  447,  447,  447,
+      447,  447,  449,  447,  447,  447,  447,  447,  447,  450,
+      447,  447,  447,  450,  450,  450,  450,  450,  450,  450,
+      450,  450,  450,  450,  450,  450,  450,  450,  450,  450,
+      450,  450,  450,  447,  447,  447,  447,  447,  447,  447,
+      447,  447,  451,  447,  447,  447,  447,  447,  447,  447,
+      447,  447,  447,  447,  447,  452,  447,  447,   22,  453,
+      447,  454,  449,  447,  447,  447,  447,  447,  447,  447,
+      447,  450,  447,  447,  450,  450,  450,  450,  450,  450,
+
+      450,  450,  450,  450,  450,  450,  450,  450,  450,  450,
+      450,  450,  450,  450,  450,  450,  450,  450,  450,  450,
+      450,  450,  450,  450,  450,  450,  450,  450,  450,  450,
+      450,  450,  450,  450,  450,  450,  450,  450,  450,  450,
+      450,  450,  450,  450,  450,  450,  450,  447,  447,  447,
+      451,  447,  452,  447,  447,  447,  447,  454,  447,  447,
+      450,  450,  450,  450,  450,  450,  450,  450,  450,  450,
+      450,  450,  450,  450,  450,  450,  450,  450,  450,  450,
+      450,  450,  450,  450,  450,  450,  450,  450,  450,  450,
+      450,  450,  450,  450,  450,  450,  450,  450,  450,  450,
+
+      450,  450,  450,  450,  450,  450,  450,  450,  450,  450,
+      450,  450,  450,  450,  450,  450,  450,  450,  450,  450,
+      450,  447,  447,  447,  447,  450,  450,  450,  450,  450,
+      450,  450,  450,  450,  450,  450,  450,  450,  450,  450,
+      450,  450,  450,  450,  450,  450,  450,  450,  450,  450,
+      450,  450,  450,  450,  450,  450,  450,  450,  450,  450,
+      450,  450,  450,  450,  450,  450,  450,  450,  450,  450,
+      450,  450,  450,  450,  450,  450,  450,  450,  450,  450,
+      450,  450,  450,  450,  450,  450,  450,  450,  450,  450,
+      450,  450,  450,  450,  450,  450,  450,  450,  450,  450,
+
+      450,  450,  450,  450,  450,  450,  450,  450,  450,  450,
+      450,  450,  450,  450,  450,  450,  450,  450,  450,  450,
+      450,  450,  450,  450,  450,  450,  450,  450,  450,  450,
+      450,  450,  450,  450,  450,  450,  450,  450,  450,  450,
+      450,  450,  450,  450,  450,  450,  450,  450,  450,  450,
+      450,  450,  450,  450,  450,  450,  450,  450,  450,  450,
+      450,  450,  450,  450,  450,  450,  450,  450,  450,  450,
+      450,  450,  450,  450,  450,  450,  450,  450,  450,  450,
+      450,  450,  450,  450,  450,  450,  450,  450,  450,  450,
+      450,  450,  450,  450,  450,  450,  450,  450,  450,  450,
+
+      450,  450,  450,  450,  450,  450,  450,  450,  450,  450,
+      450,  450,  450,  450,  450,  450,  450,  450,  450,  450,
+      450,  450,  450,  450,  450,  450,  450,  450,  450,  450,
+      450,  450,  450,  450,  450,  450,  450,  450,  450,  450,
+      450,  450,  450,  450,  450,  450,    0,  447,  447,  447,
+      447,  447,  447,  447
+    } ;
+
+static yyconst flex_int16_t yy_nxt[717] =
+    {   0,
+        8,    9,   10,   11,   12,   13,   14,   15,   16,   17,
+       18,   19,   20,   21,   22,   23,   23,   23,   23,   23,
+       23,   24,   25,   26,   27,   28,   29,   30,   30,   30,
+       30,   30,   30,   30,   30,   31,   32,   33,   34,   35,
+       36,   37,   38,   39,   40,   41,   42,   30,   43,   44,
+       45,   46,   47,   48,   49,   50,   51,   52,   53,   30,
+       30,   30,   54,   55,   56,   57,   59,   59,   65,   66,
+       90,   91,   60,   60,    8,   61,   62,    8,    8,    8,
+        8,    8,    8,    8,    8,    8,    8,    8,    8,    8,
+        8,    8,    8,    8,    8,    8,    8,    8,    8,    8,
+
+        8,   63,   63,   63,   63,   63,   63,   63,   63,    8,
+        8,    8,   63,   63,   63,   63,   63,   63,   63,   63,
+       63,   63,   63,   63,   63,   63,   63,   63,   63,   63,
+       63,   63,   63,   63,   63,   63,    8,    8,    8,    8,
+       67,   70,   72,   74,   74,   74,   74,   74,   74,   74,
+       93,  119,   75,   95,   96,   73,   71,   76,  120,   68,
+       78,  446,   85,   94,   97,  121,   98,  445,   77,   78,
+       99,   79,   79,   79,   79,   79,   79,   80,   81,   86,
+      103,   87,   88,  100,  104,  148,  107,   81,  108,  105,
+       81,   82,  110,  101,  128,  106,  102,  109,  116,   81,
+
+      111,  125,  112,  123,  142,  113,  117,  124,  143,  129,
+      447,  114,  130,  132,  126,  144,   82,  118,  444,  145,
+      133,  134,  443,  138,  149,  442,  139,  178,  146,  192,
+      135,  136,  441,  137,  140,  447,  440,  193,   78,   78,
+      179,  141,   74,   74,   74,   74,   74,   74,   74,  154,
+      154,  154,  154,  154,  154,  154,   81,   81,  152,  206,
+      219,  439,  220,  214,  280,  155,  232,  233,   81,   81,
+      152,  215,  281,  156,  207,  156,  438,  155,  157,  157,
+      157,  157,  157,  157,  157,  186,  420,  421,  187,  188,
+      437,  222,  189,  222,  190,  436,  223,  223,  223,  223,
+
+      223,  223,  223,  154,  154,  154,  154,  154,  154,  154,
+      258,  259,  260,  435,  434,  224,  433,  224,  432,  155,
+      225,  225,  225,  225,  225,  225,  225,  285,  286,  287,
+      431,  155,  157,  157,  157,  157,  157,  157,  157,  157,
+      157,  157,  157,  157,  157,  157,  223,  223,  223,  223,
+      223,  223,  223,  223,  223,  223,  223,  223,  223,  223,
+      225,  225,  225,  225,  225,  225,  225,  225,  225,  225,
+      225,  225,  225,  225,  293,  294,  295,  302,  303,  304,
+      309,  310,  311,  313,  314,  315,  321,  322,  323,  403,
+      404,  405,  430,  429,  428,  427,  426,  425,  424,  423,
+
+      422,  419,  406,   58,   58,   58,   58,   58,   58,   83,
+       83,   92,   92,   92,  151,  151,  151,  153,  418,  153,
+      153,  153,  153,   80,   80,  158,  158,  417,  416,  415,
+      414,  413,  412,  411,  410,  409,  408,  407,  402,  401,
+      400,  399,  398,  397,  396,  395,  394,  393,  392,  391,
+      390,  389,  388,  387,  386,  385,  384,  383,  382,  381,
+      380,  379,  378,  377,  376,  375,  374,  373,  372,  371,
+      370,  369,  368,  367,  366,  365,  364,  363,  362,  361,
+      360,  359,  358,  357,  356,  355,  354,  353,  352,  351,
+      350,  349,  348,  347,  346,  345,  344,  343,  342,  341,
+
+      340,  339,  338,  337,  336,  335,  334,  333,  332,  331,
+      330,  329,  328,  327,  326,  325,  324,  320,  319,  318,
+      317,  316,  312,  308,  307,  306,  305,  301,  300,  299,
+      298,  297,  296,  292,  291,  290,  289,  288,  284,  283,
+      282,  279,  278,  277,  276,  275,  274,  273,  272,  271,
+      270,  269,  268,  267,  266,  265,  264,  263,  262,  261,
+      257,  256,  255,  254,  253,  252,  251,  250,  249,  248,
+      247,  246,  245,  244,  243,  242,  241,  240,  239,  238,
+      237,  236,  235,  234,  231,  230,  229,  228,  227,  226,
+      221,  218,  217,  216,  213,  212,  211,  210,  209,  208,
+
+      205,  204,  203,  202,  201,  200,  199,  198,  197,  196,
+      195,  194,  191,  185,  184,  183,  182,  181,  180,  177,
+      176,  175,  174,  173,  172,  171,  170,  169,  168,  167,
+      166,  165,  164,  163,  162,  161,  160,  159,  150,  147,
+      131,  127,  122,  115,   89,   84,   69,   64,  447,    7,
+      447,  447,  447,  447,  447,  447,  447,  447,  447,  447,
+      447,  447,  447,  447,  447,  447,  447,  447,  447,  447,
+      447,  447,  447,  447,  447,  447,  447,  447,  447,  447,
+      447,  447,  447,  447,  447,  447,  447,  447,  447,  447,
+      447,  447,  447,  447,  447,  447,  447,  447,  447,  447,
+
+      447,  447,  447,  447,  447,  447,  447,  447,  447,  447,
+      447,  447,  447,  447,  447,  447
+    } ;
+
+static yyconst flex_int16_t yy_chk[717] =
+    {   0,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    3,    4,   12,   12,
+       28,   28,    3,    4,    5,    5,    5,    5,    5,    5,
+        5,    5,    5,    5,    5,    5,    5,    5,    5,    5,
+        5,    5,    5,    5,    5,    5,    5,    5,    5,    5,
+
+        5,    5,    5,    5,    5,    5,    5,    5,    5,    5,
+        5,    5,    5,    5,    5,    5,    5,    5,    5,    5,
+        5,    5,    5,    5,    5,    5,    5,    5,    5,    5,
+        5,    5,    5,    5,    5,    5,    5,    5,    5,    5,
+       13,   17,   19,   20,   20,   20,   20,   20,   20,   20,
+       33,   42,   21,   34,   34,   19,   17,   21,   42,   13,
+       23,  445,   26,   33,   35,   42,   35,  444,   21,   22,
+       35,   22,   22,   22,   22,   22,   22,   22,   23,   26,
+       37,   26,   26,   36,   37,   55,   38,   22,   38,   37,
+       23,   22,   39,   36,   47,   37,   36,   38,   41,   22,
+
+       39,   45,   39,   44,   51,   39,   41,   44,   51,   47,
+       79,   39,   47,   49,   45,   52,   22,   41,  443,   52,
+       49,   49,  441,   50,   55,  439,   50,  112,   52,  122,
+       49,   49,  438,   49,   50,   79,  437,  122,   80,   83,
+      112,   50,   74,   74,   74,   74,   74,   74,   74,   78,
+       78,   78,   78,   78,   78,   78,   80,   83,   74,  135,
+      146,  435,  146,  142,  214,   78,  168,  168,   80,   83,
+       74,  142,  214,   81,  135,   81,  434,   78,   81,   81,
+       81,   81,   81,   81,   81,  120,  416,  416,  120,  120,
+      433,  152,  120,  152,  120,  432,  152,  152,  152,  152,
+
+      152,  152,  152,  154,  154,  154,  154,  154,  154,  154,
+      194,  194,  194,  431,  430,  155,  429,  155,  427,  154,
+      155,  155,  155,  155,  155,  155,  155,  218,  218,  218,
+      426,  154,  156,  156,  156,  156,  156,  156,  156,  157,
+      157,  157,  157,  157,  157,  157,  222,  222,  222,  222,
+      222,  222,  222,  223,  223,  223,  223,  223,  223,  223,
+      224,  224,  224,  224,  224,  224,  224,  225,  225,  225,
+      225,  225,  225,  225,  229,  229,  229,  237,  237,  237,
+      245,  245,  245,  249,  249,  249,  255,  255,  255,  388,
+      388,  388,  425,  424,  423,  422,  421,  420,  419,  418,
+
+      417,  415,  388,  448,  448,  448,  448,  448,  448,  449,
+      449,  450,  450,  450,  451,  451,  451,  452,  406,  452,
+      452,  452,  452,  453,  453,  454,  454,  405,  404,  403,
+      402,  400,  399,  398,  395,  394,  392,  389,  387,  386,
+      385,  383,  382,  381,  378,  377,  376,  375,  374,  373,
+      372,  371,  365,  362,  359,  358,  357,  356,  355,  353,
+      351,  350,  349,  348,  346,  345,  343,  341,  340,  339,
+      338,  337,  336,  335,  334,  332,  331,  330,  329,  328,
+      327,  326,  325,  324,  320,  319,  316,  305,  301,  300,
+      299,  298,  291,  290,  289,  284,  283,  282,  281,  280,
+
+      279,  276,  275,  274,  273,  272,  271,  270,  269,  268,
+      267,  266,  265,  264,  263,  262,  261,  254,  253,  252,
+      251,  250,  248,  244,  242,  241,  240,  236,  235,  234,
+      233,  232,  231,  228,  226,  221,  220,  219,  217,  216,
+      215,  213,  212,  211,  210,  209,  208,  207,  206,  205,
+      204,  203,  202,  201,  200,  199,  198,  197,  196,  195,
+      193,  192,  191,  190,  189,  188,  187,  186,  185,  184,
+      183,  182,  181,  179,  178,  177,  176,  175,  174,  173,
+      172,  171,  170,  169,  167,  166,  165,  164,  163,  162,
+      147,  145,  144,  143,  141,  140,  139,  138,  137,  136,
+
+      134,  133,  132,  131,  130,  129,  128,  127,  126,  125,
+      124,  123,  121,  118,  117,  116,  115,  114,  113,  111,
+      110,  109,  108,  107,  106,  105,  104,  103,  102,  101,
+      100,   99,   98,   97,   96,   95,   91,   87,   60,   53,
+       48,   46,   43,   40,   27,   24,   16,   11,    7,  447,
+      447,  447,  447,  447,  447,  447,  447,  447,  447,  447,
+      447,  447,  447,  447,  447,  447,  447,  447,  447,  447,
+      447,  447,  447,  447,  447,  447,  447,  447,  447,  447,
+      447,  447,  447,  447,  447,  447,  447,  447,  447,  447,
+      447,  447,  447,  447,  447,  447,  447,  447,  447,  447,
+
+      447,  447,  447,  447,  447,  447,  447,  447,  447,  447,
+      447,  447,  447,  447,  447,  447
+    } ;
+
+/* Table of booleans, true if rule could match eol. */
+static yyconst flex_int32_t yy_rule_can_match_eol[155] =
+    {   0,
+0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0,     };
+
+/* The intent behind this definition is that it'll catch
+ * any uses of REJECT which flex missed.
+ */
+#define REJECT reject_used_but_not_detected
+#define yymore() yymore_used_but_not_detected
+#define YY_MORE_ADJ 0
+#define YY_RESTORE_YY_MORE_OFFSET
+/*
+//
+// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+This file contains the Lex specification for GLSL ES.
+Based on ANSI C grammar, Lex specification:
+http://www.lysator.liu.se/c/ANSI-C-grammar-l.html
+
+IF YOU MODIFY THIS FILE YOU ALSO NEED TO RUN generate_parser.sh,
+WHICH GENERATES THE GLSL ES LEXER (glslang_lex.cpp).
+*/
+
+#include "compiler/glslang.h"
+#include "compiler/ParseHelper.h"
+#include "compiler/preprocessor/Token.h"
+#include "compiler/util.h"
+#include "glslang_tab.h"
+
+/* windows only pragma */
+#ifdef _MSC_VER
+#pragma warning(disable : 4102)
+#endif
+
+#define YY_USER_ACTION yylval->lex.line = yylineno;
+#define YY_INPUT(buf, result, max_size) \
+    result = string_input(buf, max_size, yyscanner);
+
+static int string_input(char* buf, int max_size, yyscan_t yyscanner);
+static int check_type(yyscan_t yyscanner);
+static int reserved_word(yyscan_t yyscanner);
+
+#define INITIAL 0
+#define COMMENT 1
+#define FIELDS 2
+
+#define YY_EXTRA_TYPE TParseContext*
+
+/* Holds the entire state of the reentrant scanner. */
+struct yyguts_t
+    {
+
+    /* User-defined. Not touched by flex. */
+    YY_EXTRA_TYPE yyextra_r;
+
+    /* The rest are the same as the globals declared in the non-reentrant scanner. */
+    FILE *yyin_r, *yyout_r;
+    size_t yy_buffer_stack_top; /**< index of top of stack. */
+    size_t yy_buffer_stack_max; /**< capacity of stack. */
+    YY_BUFFER_STATE * yy_buffer_stack; /**< Stack as an array. */
+    char yy_hold_char;
+    int yy_n_chars;
+    int yyleng_r;
+    char *yy_c_buf_p;
+    int yy_init;
+    int yy_start;
+    int yy_did_buffer_switch_on_eof;
+    int yy_start_stack_ptr;
+    int yy_start_stack_depth;
+    int *yy_start_stack;
+    yy_state_type yy_last_accepting_state;
+    char* yy_last_accepting_cpos;
+
+    int yylineno_r;
+    int yy_flex_debug_r;
+
+    char *yytext_r;
+    int yy_more_flag;
+    int yy_more_len;
+
+    YYSTYPE * yylval_r;
+
+    }; /* end struct yyguts_t */
+
+static int yy_init_globals (yyscan_t yyscanner );
+
+    /* This must go here because YYSTYPE and YYLTYPE are included
+     * from bison output in section 1.*/
+    #    define yylval yyg->yylval_r
+    
+int yylex_init (yyscan_t* scanner);
+
+int yylex_init_extra (YY_EXTRA_TYPE user_defined,yyscan_t* scanner);
+
+/* Accessor methods to globals.
+   These are made visible to non-reentrant scanners for convenience. */
+
+int yylex_destroy (yyscan_t yyscanner );
+
+int yyget_debug (yyscan_t yyscanner );
+
+void yyset_debug (int debug_flag ,yyscan_t yyscanner );
+
+YY_EXTRA_TYPE yyget_extra (yyscan_t yyscanner );
+
+void yyset_extra (YY_EXTRA_TYPE user_defined ,yyscan_t yyscanner );
+
+FILE *yyget_in (yyscan_t yyscanner );
+
+void yyset_in  (FILE * in_str ,yyscan_t yyscanner );
+
+FILE *yyget_out (yyscan_t yyscanner );
+
+void yyset_out  (FILE * out_str ,yyscan_t yyscanner );
+
+int yyget_leng (yyscan_t yyscanner );
+
+char *yyget_text (yyscan_t yyscanner );
+
+int yyget_lineno (yyscan_t yyscanner );
+
+void yyset_lineno (int line_number ,yyscan_t yyscanner );
+
+YYSTYPE * yyget_lval (yyscan_t yyscanner );
+
+void yyset_lval (YYSTYPE * yylval_param ,yyscan_t yyscanner );
+
+/* Macros after this point can all be overridden by user definitions in
+ * section 1.
+ */
+
+#ifndef YY_SKIP_YYWRAP
+#ifdef __cplusplus
+extern "C" int yywrap (yyscan_t yyscanner );
+#else
+extern int yywrap (yyscan_t yyscanner );
+#endif
+#endif
+
+#ifndef yytext_ptr
+static void yy_flex_strncpy (char *,yyconst char *,int ,yyscan_t yyscanner);
+#endif
+
+#ifdef YY_NEED_STRLEN
+static int yy_flex_strlen (yyconst char * ,yyscan_t yyscanner);
+#endif
+
+#ifndef YY_NO_INPUT
+
+#ifdef __cplusplus
+static int yyinput (yyscan_t yyscanner );
+#else
+static int input (yyscan_t yyscanner );
+#endif
+
+#endif
+
+    static void yy_push_state (int new_state ,yyscan_t yyscanner);
+    
+    static void yy_pop_state (yyscan_t yyscanner );
+    
+    static int yy_top_state (yyscan_t yyscanner );
+    
+/* Amount of stuff to slurp up with each read. */
+#ifndef YY_READ_BUF_SIZE
+#define YY_READ_BUF_SIZE 8192
+#endif
+
+/* Copy whatever the last rule matched to the standard output. */
+#ifndef ECHO
+/* This used to be an fputs(), but since the string might contain NUL's,
+ * we now use fwrite().
+ */
+#define ECHO fwrite( yytext, yyleng, 1, yyout )
+#endif
+
+/* Gets input and stuffs it into "buf".  number of characters read, or YY_NULL,
+ * is returned in "result".
+ */
+#ifndef YY_INPUT
+#define YY_INPUT(buf,result,max_size) \
+	if ( YY_CURRENT_BUFFER_LVALUE->yy_is_interactive ) \
+		{ \
+		int c = '*'; \
+		int n; \
+		for ( n = 0; n < max_size && \
+			     (c = getc( yyin )) != EOF && c != '\n'; ++n ) \
+			buf[n] = (char) c; \
+		if ( c == '\n' ) \
+			buf[n++] = (char) c; \
+		if ( c == EOF && ferror( yyin ) ) \
+			YY_FATAL_ERROR( "input in flex scanner failed" ); \
+		result = n; \
+		} \
+	else \
+		{ \
+		errno=0; \
+		while ( (result = fread(buf, 1, max_size, yyin))==0 && ferror(yyin)) \
+			{ \
+			if( errno != EINTR) \
+				{ \
+				YY_FATAL_ERROR( "input in flex scanner failed" ); \
+				break; \
+				} \
+			errno=0; \
+			clearerr(yyin); \
+			} \
+		}\
+\
+
+#endif
+
+/* No semi-colon after return; correct usage is to write "yyterminate();" -
+ * we don't want an extra ';' after the "return" because that will cause
+ * some compilers to complain about unreachable statements.
+ */
+#ifndef yyterminate
+#define yyterminate() return YY_NULL
+#endif
+
+/* Number of entries by which start-condition stack grows. */
+#ifndef YY_START_STACK_INCR
+#define YY_START_STACK_INCR 25
+#endif
+
+/* Report a fatal error. */
+#ifndef YY_FATAL_ERROR
+#define YY_FATAL_ERROR(msg) yy_fatal_error( msg , yyscanner)
+#endif
+
+/* end tables serialization structures and prototypes */
+
+/* Default declaration of generated scanner - a define so the user can
+ * easily add parameters.
+ */
+#ifndef YY_DECL
+#define YY_DECL_IS_OURS 1
+
+extern int yylex \
+               (YYSTYPE * yylval_param ,yyscan_t yyscanner);
+
+#define YY_DECL int yylex \
+               (YYSTYPE * yylval_param , yyscan_t yyscanner)
+#endif /* !YY_DECL */
+
+/* Code executed at the beginning of each rule, after yytext and yyleng
+ * have been set up.
+ */
+#ifndef YY_USER_ACTION
+#define YY_USER_ACTION
+#endif
+
+/* Code executed at the end of each rule. */
+#ifndef YY_BREAK
+#define YY_BREAK break;
+#endif
+
+#define YY_RULE_SETUP \
+	YY_USER_ACTION
+
+/** The main scanner function which does all the work.
+ */
+YY_DECL
+{
+	register yy_state_type yy_current_state;
+	register char *yy_cp, *yy_bp;
+	register int yy_act;
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+    TParseContext* context = yyextra;
+
+    /* Single-line comments */
+
+    yylval = yylval_param;
+
+	if ( !yyg->yy_init )
+		{
+		yyg->yy_init = 1;
+
+#ifdef YY_USER_INIT
+		YY_USER_INIT;
+#endif
+
+		if ( ! yyg->yy_start )
+			yyg->yy_start = 1;	/* first start state */
+
+		if ( ! yyin )
+			yyin = stdin;
+
+		if ( ! yyout )
+			yyout = stdout;
+
+		if ( ! YY_CURRENT_BUFFER ) {
+			yyensure_buffer_stack (yyscanner);
+			YY_CURRENT_BUFFER_LVALUE =
+				yy_create_buffer(yyin,YY_BUF_SIZE ,yyscanner);
+		}
+
+		yy_load_buffer_state(yyscanner );
+		}
+
+	while ( 1 )		/* loops until end-of-file is reached */
+		{
+		yy_cp = yyg->yy_c_buf_p;
+
+		/* Support of yytext. */
+		*yy_cp = yyg->yy_hold_char;
+
+		/* yy_bp points to the position in yy_ch_buf of the start of
+		 * the current run.
+		 */
+		yy_bp = yy_cp;
+
+		yy_current_state = yyg->yy_start;
+yy_match:
+		do
+			{
+			register YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)];
+			if ( yy_accept[yy_current_state] )
+				{
+				yyg->yy_last_accepting_state = yy_current_state;
+				yyg->yy_last_accepting_cpos = yy_cp;
+				}
+			while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
+				{
+				yy_current_state = (int) yy_def[yy_current_state];
+				if ( yy_current_state >= 448 )
+					yy_c = yy_meta[(unsigned int) yy_c];
+				}
+			yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
+			++yy_cp;
+			}
+		while ( yy_current_state != 447 );
+		yy_cp = yyg->yy_last_accepting_cpos;
+		yy_current_state = yyg->yy_last_accepting_state;
+
+yy_find_action:
+		yy_act = yy_accept[yy_current_state];
+
+		YY_DO_BEFORE_ACTION;
+
+		if ( yy_act != YY_END_OF_BUFFER && yy_rule_can_match_eol[yy_act] )
+			{
+			int yyl;
+			for ( yyl = 0; yyl < yyleng; ++yyl )
+				if ( yytext[yyl] == '\n' )
+					   
+    do{ yylineno++;
+        yycolumn=0;
+    }while(0)
+;
+			}
+
+do_action:	/* This label is used only to access EOF actions. */
+
+		switch ( yy_act )
+	{ /* beginning of action switch */
+			case 0: /* must back up */
+			/* undo the effects of YY_DO_BEFORE_ACTION */
+			*yy_cp = yyg->yy_hold_char;
+			yy_cp = yyg->yy_last_accepting_cpos;
+			yy_current_state = yyg->yy_last_accepting_state;
+			goto yy_find_action;
+
+case 1:
+YY_RULE_SETUP
+;
+	YY_BREAK
+/* Multi-line comments */
+case 2:
+YY_RULE_SETUP
+{ yy_push_state(COMMENT, yyscanner); }
+	YY_BREAK
+case 3:
+case 4:
+/* rule 4 can match eol */
+YY_RULE_SETUP
+;
+	YY_BREAK
+case 5:
+YY_RULE_SETUP
+{ yy_pop_state(yyscanner); }
+	YY_BREAK
+case 6:
+YY_RULE_SETUP
+{ return(INVARIANT); }
+	YY_BREAK
+case 7:
+YY_RULE_SETUP
+{ return(HIGH_PRECISION); }
+	YY_BREAK
+case 8:
+YY_RULE_SETUP
+{ return(MEDIUM_PRECISION); }
+	YY_BREAK
+case 9:
+YY_RULE_SETUP
+{ return(LOW_PRECISION); }
+	YY_BREAK
+case 10:
+YY_RULE_SETUP
+{ return(PRECISION); }
+	YY_BREAK
+case 11:
+YY_RULE_SETUP
+{ return(ATTRIBUTE); }
+	YY_BREAK
+case 12:
+YY_RULE_SETUP
+{ return(CONST_QUAL); }
+	YY_BREAK
+case 13:
+YY_RULE_SETUP
+{ return(UNIFORM); }
+	YY_BREAK
+case 14:
+YY_RULE_SETUP
+{ return(VARYING); }
+	YY_BREAK
+case 15:
+YY_RULE_SETUP
+{ return(BREAK); }
+	YY_BREAK
+case 16:
+YY_RULE_SETUP
+{ return(CONTINUE); }
+	YY_BREAK
+case 17:
+YY_RULE_SETUP
+{ return(DO); }
+	YY_BREAK
+case 18:
+YY_RULE_SETUP
+{ return(FOR); }
+	YY_BREAK
+case 19:
+YY_RULE_SETUP
+{ return(WHILE); }
+	YY_BREAK
+case 20:
+YY_RULE_SETUP
+{ return(IF); }
+	YY_BREAK
+case 21:
+YY_RULE_SETUP
+{ return(ELSE); }
+	YY_BREAK
+case 22:
+YY_RULE_SETUP
+{ return(IN_QUAL); }
+	YY_BREAK
+case 23:
+YY_RULE_SETUP
+{ return(OUT_QUAL); }
+	YY_BREAK
+case 24:
+YY_RULE_SETUP
+{ return(INOUT_QUAL); }
+	YY_BREAK
+case 25:
+YY_RULE_SETUP
+{ context->lexAfterType = true; return(FLOAT_TYPE); }
+	YY_BREAK
+case 26:
+YY_RULE_SETUP
+{ context->lexAfterType = true; return(INT_TYPE); }
+	YY_BREAK
+case 27:
+YY_RULE_SETUP
+{ context->lexAfterType = true; return(VOID_TYPE); }
+	YY_BREAK
+case 28:
+YY_RULE_SETUP
+{ context->lexAfterType = true; return(BOOL_TYPE); }
+	YY_BREAK
+case 29:
+YY_RULE_SETUP
+{ yylval->lex.b = true;  return(BOOLCONSTANT); }
+	YY_BREAK
+case 30:
+YY_RULE_SETUP
+{ yylval->lex.b = false; return(BOOLCONSTANT); }
+	YY_BREAK
+case 31:
+YY_RULE_SETUP
+{ return(DISCARD); }
+	YY_BREAK
+case 32:
+YY_RULE_SETUP
+{ return(RETURN); }
+	YY_BREAK
+case 33:
+YY_RULE_SETUP
+{ context->lexAfterType = true; return(MATRIX2); }
+	YY_BREAK
+case 34:
+YY_RULE_SETUP
+{ context->lexAfterType = true; return(MATRIX3); }
+	YY_BREAK
+case 35:
+YY_RULE_SETUP
+{ context->lexAfterType = true; return(MATRIX4); }
+	YY_BREAK
+case 36:
+YY_RULE_SETUP
+{ context->lexAfterType = true; return (VEC2); }
+	YY_BREAK
+case 37:
+YY_RULE_SETUP
+{ context->lexAfterType = true; return (VEC3); }
+	YY_BREAK
+case 38:
+YY_RULE_SETUP
+{ context->lexAfterType = true; return (VEC4); }
+	YY_BREAK
+case 39:
+YY_RULE_SETUP
+{ context->lexAfterType = true; return (IVEC2); }
+	YY_BREAK
+case 40:
+YY_RULE_SETUP
+{ context->lexAfterType = true; return (IVEC3); }
+	YY_BREAK
+case 41:
+YY_RULE_SETUP
+{ context->lexAfterType = true; return (IVEC4); }
+	YY_BREAK
+case 42:
+YY_RULE_SETUP
+{ context->lexAfterType = true; return (BVEC2); }
+	YY_BREAK
+case 43:
+YY_RULE_SETUP
+{ context->lexAfterType = true; return (BVEC3); }
+	YY_BREAK
+case 44:
+YY_RULE_SETUP
+{ context->lexAfterType = true; return (BVEC4); }
+	YY_BREAK
+case 45:
+YY_RULE_SETUP
+{ context->lexAfterType = true; return SAMPLER2D; }
+	YY_BREAK
+case 46:
+YY_RULE_SETUP
+{ context->lexAfterType = true; return SAMPLERCUBE; }
+	YY_BREAK
+case 47:
+YY_RULE_SETUP
+{ context->lexAfterType = true; return(STRUCT); }
+	YY_BREAK
+case 48:
+YY_RULE_SETUP
+{ return reserved_word(yyscanner); }
+	YY_BREAK
+case 49:
+YY_RULE_SETUP
+{ return reserved_word(yyscanner); }
+	YY_BREAK
+case 50:
+YY_RULE_SETUP
+{ return reserved_word(yyscanner); }
+	YY_BREAK
+case 51:
+YY_RULE_SETUP
+{ return reserved_word(yyscanner); }
+	YY_BREAK
+case 52:
+YY_RULE_SETUP
+{ return reserved_word(yyscanner); }
+	YY_BREAK
+case 53:
+YY_RULE_SETUP
+{ return reserved_word(yyscanner); }
+	YY_BREAK
+case 54:
+YY_RULE_SETUP
+{ return reserved_word(yyscanner); }
+	YY_BREAK
+case 55:
+YY_RULE_SETUP
+{ return reserved_word(yyscanner); }
+	YY_BREAK
+case 56:
+YY_RULE_SETUP
+{ return reserved_word(yyscanner); }
+	YY_BREAK
+case 57:
+YY_RULE_SETUP
+{ return reserved_word(yyscanner); }
+	YY_BREAK
+case 58:
+YY_RULE_SETUP
+{ return reserved_word(yyscanner); }
+	YY_BREAK
+case 59:
+YY_RULE_SETUP
+{ return reserved_word(yyscanner); }
+	YY_BREAK
+case 60:
+YY_RULE_SETUP
+{ return reserved_word(yyscanner); }
+	YY_BREAK
+case 61:
+YY_RULE_SETUP
+{ return reserved_word(yyscanner); }
+	YY_BREAK
+case 62:
+YY_RULE_SETUP
+{ return reserved_word(yyscanner); }
+	YY_BREAK
+case 63:
+YY_RULE_SETUP
+{ return reserved_word(yyscanner); }
+	YY_BREAK
+case 64:
+YY_RULE_SETUP
+{ return reserved_word(yyscanner); }
+	YY_BREAK
+case 65:
+YY_RULE_SETUP
+{ return reserved_word(yyscanner); }
+	YY_BREAK
+case 66:
+YY_RULE_SETUP
+{ return reserved_word(yyscanner); }
+	YY_BREAK
+case 67:
+YY_RULE_SETUP
+{ return reserved_word(yyscanner); }
+	YY_BREAK
+case 68:
+YY_RULE_SETUP
+{ return reserved_word(yyscanner); }
+	YY_BREAK
+case 69:
+YY_RULE_SETUP
+{ return reserved_word(yyscanner); }
+	YY_BREAK
+case 70:
+YY_RULE_SETUP
+{ return reserved_word(yyscanner); }
+	YY_BREAK
+case 71:
+YY_RULE_SETUP
+{ return reserved_word(yyscanner); }
+	YY_BREAK
+case 72:
+YY_RULE_SETUP
+{ return reserved_word(yyscanner); }
+	YY_BREAK
+case 73:
+YY_RULE_SETUP
+{ return reserved_word(yyscanner); }
+	YY_BREAK
+case 74:
+YY_RULE_SETUP
+{ return reserved_word(yyscanner); }
+	YY_BREAK
+case 75:
+YY_RULE_SETUP
+{ return reserved_word(yyscanner); }
+	YY_BREAK
+case 76:
+YY_RULE_SETUP
+{ return reserved_word(yyscanner); }
+	YY_BREAK
+case 77:
+YY_RULE_SETUP
+{ return reserved_word(yyscanner); }
+	YY_BREAK
+case 78:
+YY_RULE_SETUP
+{ return reserved_word(yyscanner); }
+	YY_BREAK
+case 79:
+YY_RULE_SETUP
+{ return reserved_word(yyscanner); }
+	YY_BREAK
+case 80:
+YY_RULE_SETUP
+{ return reserved_word(yyscanner); }
+	YY_BREAK
+case 81:
+YY_RULE_SETUP
+{ return reserved_word(yyscanner); }
+	YY_BREAK
+case 82:
+YY_RULE_SETUP
+{ return reserved_word(yyscanner); }
+	YY_BREAK
+case 83:
+YY_RULE_SETUP
+{ return reserved_word(yyscanner); }
+	YY_BREAK
+case 84:
+YY_RULE_SETUP
+{ return reserved_word(yyscanner); }
+	YY_BREAK
+case 85:
+YY_RULE_SETUP
+{ return reserved_word(yyscanner); }
+	YY_BREAK
+case 86:
+YY_RULE_SETUP
+{ return reserved_word(yyscanner); }
+	YY_BREAK
+case 87:
+YY_RULE_SETUP
+{ return reserved_word(yyscanner); }
+	YY_BREAK
+case 88:
+YY_RULE_SETUP
+{ return reserved_word(yyscanner); }
+	YY_BREAK
+case 89:
+YY_RULE_SETUP
+{ return reserved_word(yyscanner); }
+	YY_BREAK
+case 90:
+YY_RULE_SETUP
+{ return reserved_word(yyscanner); }
+	YY_BREAK
+case 91:
+YY_RULE_SETUP
+{ return reserved_word(yyscanner); }
+	YY_BREAK
+case 92:
+YY_RULE_SETUP
+{ return reserved_word(yyscanner); }
+	YY_BREAK
+case 93:
+YY_RULE_SETUP
+{ return reserved_word(yyscanner); }
+	YY_BREAK
+case 94:
+YY_RULE_SETUP
+{ return reserved_word(yyscanner); }
+	YY_BREAK
+case 95:
+YY_RULE_SETUP
+{ return reserved_word(yyscanner); }
+	YY_BREAK
+case 96:
+YY_RULE_SETUP
+{ return reserved_word(yyscanner); }
+	YY_BREAK
+case 97:
+YY_RULE_SETUP
+{
+   yylval->lex.string = NewPoolTString(yytext); 
+   return check_type(yyscanner);
+}
+	YY_BREAK
+case 98:
+YY_RULE_SETUP
+{ yylval->lex.i = strtol(yytext, 0, 0); return(INTCONSTANT); }
+	YY_BREAK
+case 99:
+YY_RULE_SETUP
+{ yylval->lex.i = strtol(yytext, 0, 0); return(INTCONSTANT); }
+	YY_BREAK
+case 100:
+YY_RULE_SETUP
+{ context->error(yylineno, "Invalid Octal number.", yytext); context->recover(); return 0;}
+	YY_BREAK
+case 101:
+YY_RULE_SETUP
+{ yylval->lex.i = strtol(yytext, 0, 0); return(INTCONSTANT); }
+	YY_BREAK
+case 102:
+YY_RULE_SETUP
+{ yylval->lex.f = static_cast<float>(atof_dot(yytext)); return(FLOATCONSTANT); }
+	YY_BREAK
+case 103:
+YY_RULE_SETUP
+{ yylval->lex.f = static_cast<float>(atof_dot(yytext)); return(FLOATCONSTANT); }
+	YY_BREAK
+case 104:
+YY_RULE_SETUP
+{ yylval->lex.f = static_cast<float>(atof_dot(yytext)); return(FLOATCONSTANT); }
+	YY_BREAK
+case 105:
+YY_RULE_SETUP
+{  return(ADD_ASSIGN); }
+	YY_BREAK
+case 106:
+YY_RULE_SETUP
+{  return(SUB_ASSIGN); }
+	YY_BREAK
+case 107:
+YY_RULE_SETUP
+{  return(MUL_ASSIGN); }
+	YY_BREAK
+case 108:
+YY_RULE_SETUP
+{  return(DIV_ASSIGN); }
+	YY_BREAK
+case 109:
+YY_RULE_SETUP
+{  return(MOD_ASSIGN); }
+	YY_BREAK
+case 110:
+YY_RULE_SETUP
+{  return(LEFT_ASSIGN); }
+	YY_BREAK
+case 111:
+YY_RULE_SETUP
+{  return(RIGHT_ASSIGN); }
+	YY_BREAK
+case 112:
+YY_RULE_SETUP
+{  return(AND_ASSIGN); }
+	YY_BREAK
+case 113:
+YY_RULE_SETUP
+{  return(XOR_ASSIGN); }
+	YY_BREAK
+case 114:
+YY_RULE_SETUP
+{  return(OR_ASSIGN); }
+	YY_BREAK
+case 115:
+YY_RULE_SETUP
+{  return(INC_OP); }
+	YY_BREAK
+case 116:
+YY_RULE_SETUP
+{  return(DEC_OP); }
+	YY_BREAK
+case 117:
+YY_RULE_SETUP
+{  return(AND_OP); }
+	YY_BREAK
+case 118:
+YY_RULE_SETUP
+{  return(OR_OP); }
+	YY_BREAK
+case 119:
+YY_RULE_SETUP
+{  return(XOR_OP); }
+	YY_BREAK
+case 120:
+YY_RULE_SETUP
+{  return(LE_OP); }
+	YY_BREAK
+case 121:
+YY_RULE_SETUP
+{  return(GE_OP); }
+	YY_BREAK
+case 122:
+YY_RULE_SETUP
+{  return(EQ_OP); }
+	YY_BREAK
+case 123:
+YY_RULE_SETUP
+{  return(NE_OP); }
+	YY_BREAK
+case 124:
+YY_RULE_SETUP
+{  return(LEFT_OP); }
+	YY_BREAK
+case 125:
+YY_RULE_SETUP
+{  return(RIGHT_OP); }
+	YY_BREAK
+case 126:
+YY_RULE_SETUP
+{ context->lexAfterType = false; return(SEMICOLON); }
+	YY_BREAK
+case 127:
+YY_RULE_SETUP
+{ context->lexAfterType = false; return(LEFT_BRACE); }
+	YY_BREAK
+case 128:
+YY_RULE_SETUP
+{ return(RIGHT_BRACE); }
+	YY_BREAK
+case 129:
+YY_RULE_SETUP
+{ if (context->inTypeParen) context->lexAfterType = false; return(COMMA); }
+	YY_BREAK
+case 130:
+YY_RULE_SETUP
+{ return(COLON); }
+	YY_BREAK
+case 131:
+YY_RULE_SETUP
+{ context->lexAfterType = false; return(EQUAL); }
+	YY_BREAK
+case 132:
+YY_RULE_SETUP
+{ context->lexAfterType = false; context->inTypeParen = true; return(LEFT_PAREN); }
+	YY_BREAK
+case 133:
+YY_RULE_SETUP
+{ context->inTypeParen = false; return(RIGHT_PAREN); }
+	YY_BREAK
+case 134:
+YY_RULE_SETUP
+{ return(LEFT_BRACKET); }
+	YY_BREAK
+case 135:
+YY_RULE_SETUP
+{ return(RIGHT_BRACKET); }
+	YY_BREAK
+case 136:
+YY_RULE_SETUP
+{ BEGIN(FIELDS);  return(DOT); }
+	YY_BREAK
+case 137:
+YY_RULE_SETUP
+{ return(BANG); }
+	YY_BREAK
+case 138:
+YY_RULE_SETUP
+{ return(DASH); }
+	YY_BREAK
+case 139:
+YY_RULE_SETUP
+{ return(TILDE); }
+	YY_BREAK
+case 140:
+YY_RULE_SETUP
+{ return(PLUS); }
+	YY_BREAK
+case 141:
+YY_RULE_SETUP
+{ return(STAR); }
+	YY_BREAK
+case 142:
+YY_RULE_SETUP
+{ return(SLASH); }
+	YY_BREAK
+case 143:
+YY_RULE_SETUP
+{ return(PERCENT); }
+	YY_BREAK
+case 144:
+YY_RULE_SETUP
+{ return(LEFT_ANGLE); }
+	YY_BREAK
+case 145:
+YY_RULE_SETUP
+{ return(RIGHT_ANGLE); }
+	YY_BREAK
+case 146:
+YY_RULE_SETUP
+{ return(VERTICAL_BAR); }
+	YY_BREAK
+case 147:
+YY_RULE_SETUP
+{ return(CARET); }
+	YY_BREAK
+case 148:
+YY_RULE_SETUP
+{ return(AMPERSAND); }
+	YY_BREAK
+case 149:
+YY_RULE_SETUP
+{ return(QUESTION); }
+	YY_BREAK
+case 150:
+YY_RULE_SETUP
+{ 
+    BEGIN(INITIAL);
+    yylval->lex.string = NewPoolTString(yytext); 
+    return FIELD_SELECTION;
+}
+	YY_BREAK
+case 151:
+YY_RULE_SETUP
+{}
+	YY_BREAK
+case 152:
+/* rule 152 can match eol */
+YY_RULE_SETUP
+{  }
+	YY_BREAK
+case YY_STATE_EOF(INITIAL):
+case YY_STATE_EOF(COMMENT):
+case YY_STATE_EOF(FIELDS):
+{ context->AfterEOF = true; yyterminate(); }
+	YY_BREAK
+case 153:
+YY_RULE_SETUP
+{ context->warning(yylineno, "Unknown char", yytext, ""); return 0; }
+	YY_BREAK
+case 154:
+YY_RULE_SETUP
+ECHO;
+	YY_BREAK
+
+	case YY_END_OF_BUFFER:
+		{
+		/* Amount of text matched not including the EOB char. */
+		int yy_amount_of_matched_text = (int) (yy_cp - yyg->yytext_ptr) - 1;
+
+		/* Undo the effects of YY_DO_BEFORE_ACTION. */
+		*yy_cp = yyg->yy_hold_char;
+		YY_RESTORE_YY_MORE_OFFSET
+
+		if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_NEW )
+			{
+			/* We're scanning a new file or input source.  It's
+			 * possible that this happened because the user
+			 * just pointed yyin at a new source and called
+			 * yylex().  If so, then we have to assure
+			 * consistency between YY_CURRENT_BUFFER and our
+			 * globals.  Here is the right place to do so, because
+			 * this is the first action (other than possibly a
+			 * back-up) that will match for the new input source.
+			 */
+			yyg->yy_n_chars = YY_CURRENT_BUFFER_LVALUE->yy_n_chars;
+			YY_CURRENT_BUFFER_LVALUE->yy_input_file = yyin;
+			YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = YY_BUFFER_NORMAL;
+			}
+
+		/* Note that here we test for yy_c_buf_p "<=" to the position
+		 * of the first EOB in the buffer, since yy_c_buf_p will
+		 * already have been incremented past the NUL character
+		 * (since all states make transitions on EOB to the
+		 * end-of-buffer state).  Contrast this with the test
+		 * in input().
+		 */
+		if ( yyg->yy_c_buf_p <= &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars] )
+			{ /* This was really a NUL. */
+			yy_state_type yy_next_state;
+
+			yyg->yy_c_buf_p = yyg->yytext_ptr + yy_amount_of_matched_text;
+
+			yy_current_state = yy_get_previous_state( yyscanner );
+
+			/* Okay, we're now positioned to make the NUL
+			 * transition.  We couldn't have
+			 * yy_get_previous_state() go ahead and do it
+			 * for us because it doesn't know how to deal
+			 * with the possibility of jamming (and we don't
+			 * want to build jamming into it because then it
+			 * will run more slowly).
+			 */
+
+			yy_next_state = yy_try_NUL_trans( yy_current_state , yyscanner);
+
+			yy_bp = yyg->yytext_ptr + YY_MORE_ADJ;
+
+			if ( yy_next_state )
+				{
+				/* Consume the NUL. */
+				yy_cp = ++yyg->yy_c_buf_p;
+				yy_current_state = yy_next_state;
+				goto yy_match;
+				}
+
+			else
+				{
+				yy_cp = yyg->yy_last_accepting_cpos;
+				yy_current_state = yyg->yy_last_accepting_state;
+				goto yy_find_action;
+				}
+			}
+
+		else switch ( yy_get_next_buffer( yyscanner ) )
+			{
+			case EOB_ACT_END_OF_FILE:
+				{
+				yyg->yy_did_buffer_switch_on_eof = 0;
+
+				if ( yywrap(yyscanner ) )
+					{
+					/* Note: because we've taken care in
+					 * yy_get_next_buffer() to have set up
+					 * yytext, we can now set up
+					 * yy_c_buf_p so that if some total
+					 * hoser (like flex itself) wants to
+					 * call the scanner after we return the
+					 * YY_NULL, it'll still work - another
+					 * YY_NULL will get returned.
+					 */
+					yyg->yy_c_buf_p = yyg->yytext_ptr + YY_MORE_ADJ;
+
+					yy_act = YY_STATE_EOF(YY_START);
+					goto do_action;
+					}
+
+				else
+					{
+					if ( ! yyg->yy_did_buffer_switch_on_eof )
+						YY_NEW_FILE;
+					}
+				break;
+				}
+
+			case EOB_ACT_CONTINUE_SCAN:
+				yyg->yy_c_buf_p =
+					yyg->yytext_ptr + yy_amount_of_matched_text;
+
+				yy_current_state = yy_get_previous_state( yyscanner );
+
+				yy_cp = yyg->yy_c_buf_p;
+				yy_bp = yyg->yytext_ptr + YY_MORE_ADJ;
+				goto yy_match;
+
+			case EOB_ACT_LAST_MATCH:
+				yyg->yy_c_buf_p =
+				&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars];
+
+				yy_current_state = yy_get_previous_state( yyscanner );
+
+				yy_cp = yyg->yy_c_buf_p;
+				yy_bp = yyg->yytext_ptr + YY_MORE_ADJ;
+				goto yy_find_action;
+			}
+		break;
+		}
+
+	default:
+		YY_FATAL_ERROR(
+			"fatal flex scanner internal error--no action found" );
+	} /* end of action switch */
+		} /* end of scanning one token */
+} /* end of yylex */
+
+/* yy_get_next_buffer - try to read in a new buffer
+ *
+ * Returns a code representing an action:
+ *	EOB_ACT_LAST_MATCH -
+ *	EOB_ACT_CONTINUE_SCAN - continue scanning from current position
+ *	EOB_ACT_END_OF_FILE - end of file
+ */
+static int yy_get_next_buffer (yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+	register char *dest = YY_CURRENT_BUFFER_LVALUE->yy_ch_buf;
+	register char *source = yyg->yytext_ptr;
+	register int number_to_move, i;
+	int ret_val;
+
+	if ( yyg->yy_c_buf_p > &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars + 1] )
+		YY_FATAL_ERROR(
+		"fatal flex scanner internal error--end of buffer missed" );
+
+	if ( YY_CURRENT_BUFFER_LVALUE->yy_fill_buffer == 0 )
+		{ /* Don't try to fill the buffer, so this is an EOF. */
+		if ( yyg->yy_c_buf_p - yyg->yytext_ptr - YY_MORE_ADJ == 1 )
+			{
+			/* We matched a single character, the EOB, so
+			 * treat this as a final EOF.
+			 */
+			return EOB_ACT_END_OF_FILE;
+			}
+
+		else
+			{
+			/* We matched some text prior to the EOB, first
+			 * process it.
+			 */
+			return EOB_ACT_LAST_MATCH;
+			}
+		}
+
+	/* Try to read more data. */
+
+	/* First move last chars to start of buffer. */
+	number_to_move = (int) (yyg->yy_c_buf_p - yyg->yytext_ptr) - 1;
+
+	for ( i = 0; i < number_to_move; ++i )
+		*(dest++) = *(source++);
+
+	if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_EOF_PENDING )
+		/* don't do the read, it's not guaranteed to return an EOF,
+		 * just force an EOF
+		 */
+		YY_CURRENT_BUFFER_LVALUE->yy_n_chars = yyg->yy_n_chars = 0;
+
+	else
+		{
+			int num_to_read =
+			YY_CURRENT_BUFFER_LVALUE->yy_buf_size - number_to_move - 1;
+
+		while ( num_to_read <= 0 )
+			{ /* Not enough room in the buffer - grow it. */
+
+			/* just a shorter name for the current buffer */
+			YY_BUFFER_STATE b = YY_CURRENT_BUFFER;
+
+			int yy_c_buf_p_offset =
+				(int) (yyg->yy_c_buf_p - b->yy_ch_buf);
+
+			if ( b->yy_is_our_buffer )
+				{
+				int new_size = b->yy_buf_size * 2;
+
+				if ( new_size <= 0 )
+					b->yy_buf_size += b->yy_buf_size / 8;
+				else
+					b->yy_buf_size *= 2;
+
+				b->yy_ch_buf = (char *)
+					/* Include room in for 2 EOB chars. */
+					yyrealloc((void *) b->yy_ch_buf,b->yy_buf_size + 2 ,yyscanner );
+				}
+			else
+				/* Can't grow it, we don't own it. */
+				b->yy_ch_buf = 0;
+
+			if ( ! b->yy_ch_buf )
+				YY_FATAL_ERROR(
+				"fatal error - scanner input buffer overflow" );
+
+			yyg->yy_c_buf_p = &b->yy_ch_buf[yy_c_buf_p_offset];
+
+			num_to_read = YY_CURRENT_BUFFER_LVALUE->yy_buf_size -
+						number_to_move - 1;
+
+			}
+
+		if ( num_to_read > YY_READ_BUF_SIZE )
+			num_to_read = YY_READ_BUF_SIZE;
+
+		/* Read in more data. */
+		YY_INPUT( (&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]),
+			yyg->yy_n_chars, (size_t) num_to_read );
+
+		YY_CURRENT_BUFFER_LVALUE->yy_n_chars = yyg->yy_n_chars;
+		}
+
+	if ( yyg->yy_n_chars == 0 )
+		{
+		if ( number_to_move == YY_MORE_ADJ )
+			{
+			ret_val = EOB_ACT_END_OF_FILE;
+			yyrestart(yyin  ,yyscanner);
+			}
+
+		else
+			{
+			ret_val = EOB_ACT_LAST_MATCH;
+			YY_CURRENT_BUFFER_LVALUE->yy_buffer_status =
+				YY_BUFFER_EOF_PENDING;
+			}
+		}
+
+	else
+		ret_val = EOB_ACT_CONTINUE_SCAN;
+
+	if ((yy_size_t) (yyg->yy_n_chars + number_to_move) > YY_CURRENT_BUFFER_LVALUE->yy_buf_size) {
+		/* Extend the array by 50%, plus the number we really need. */
+		yy_size_t new_size = yyg->yy_n_chars + number_to_move + (yyg->yy_n_chars >> 1);
+		YY_CURRENT_BUFFER_LVALUE->yy_ch_buf = (char *) yyrealloc((void *) YY_CURRENT_BUFFER_LVALUE->yy_ch_buf,new_size ,yyscanner );
+		if ( ! YY_CURRENT_BUFFER_LVALUE->yy_ch_buf )
+			YY_FATAL_ERROR( "out of dynamic memory in yy_get_next_buffer()" );
+	}
+
+	yyg->yy_n_chars += number_to_move;
+	YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars] = YY_END_OF_BUFFER_CHAR;
+	YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars + 1] = YY_END_OF_BUFFER_CHAR;
+
+	yyg->yytext_ptr = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[0];
+
+	return ret_val;
+}
+
+/* yy_get_previous_state - get the state just before the EOB char was reached */
+
+    static yy_state_type yy_get_previous_state (yyscan_t yyscanner)
+{
+	register yy_state_type yy_current_state;
+	register char *yy_cp;
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+	yy_current_state = yyg->yy_start;
+
+	for ( yy_cp = yyg->yytext_ptr + YY_MORE_ADJ; yy_cp < yyg->yy_c_buf_p; ++yy_cp )
+		{
+		register YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1);
+		if ( yy_accept[yy_current_state] )
+			{
+			yyg->yy_last_accepting_state = yy_current_state;
+			yyg->yy_last_accepting_cpos = yy_cp;
+			}
+		while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
+			{
+			yy_current_state = (int) yy_def[yy_current_state];
+			if ( yy_current_state >= 448 )
+				yy_c = yy_meta[(unsigned int) yy_c];
+			}
+		yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
+		}
+
+	return yy_current_state;
+}
+
+/* yy_try_NUL_trans - try to make a transition on the NUL character
+ *
+ * synopsis
+ *	next_state = yy_try_NUL_trans( current_state );
+ */
+    static yy_state_type yy_try_NUL_trans  (yy_state_type yy_current_state , yyscan_t yyscanner)
+{
+	register int yy_is_jam;
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; /* This var may be unused depending upon options. */
+	register char *yy_cp = yyg->yy_c_buf_p;
+
+	register YY_CHAR yy_c = 1;
+	if ( yy_accept[yy_current_state] )
+		{
+		yyg->yy_last_accepting_state = yy_current_state;
+		yyg->yy_last_accepting_cpos = yy_cp;
+		}
+	while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
+		{
+		yy_current_state = (int) yy_def[yy_current_state];
+		if ( yy_current_state >= 448 )
+			yy_c = yy_meta[(unsigned int) yy_c];
+		}
+	yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
+	yy_is_jam = (yy_current_state == 447);
+
+	return yy_is_jam ? 0 : yy_current_state;
+}
+
+#ifndef YY_NO_INPUT
+#ifdef __cplusplus
+    static int yyinput (yyscan_t yyscanner)
+#else
+    static int input  (yyscan_t yyscanner)
+#endif
+
+{
+	int c;
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+	*yyg->yy_c_buf_p = yyg->yy_hold_char;
+
+	if ( *yyg->yy_c_buf_p == YY_END_OF_BUFFER_CHAR )
+		{
+		/* yy_c_buf_p now points to the character we want to return.
+		 * If this occurs *before* the EOB characters, then it's a
+		 * valid NUL; if not, then we've hit the end of the buffer.
+		 */
+		if ( yyg->yy_c_buf_p < &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars] )
+			/* This was really a NUL. */
+			*yyg->yy_c_buf_p = '\0';
+
+		else
+			{ /* need more input */
+			int offset = yyg->yy_c_buf_p - yyg->yytext_ptr;
+			++yyg->yy_c_buf_p;
+
+			switch ( yy_get_next_buffer( yyscanner ) )
+				{
+				case EOB_ACT_LAST_MATCH:
+					/* This happens because yy_g_n_b()
+					 * sees that we've accumulated a
+					 * token and flags that we need to
+					 * try matching the token before
+					 * proceeding.  But for input(),
+					 * there's no matching to consider.
+					 * So convert the EOB_ACT_LAST_MATCH
+					 * to EOB_ACT_END_OF_FILE.
+					 */
+
+					/* Reset buffer status. */
+					yyrestart(yyin ,yyscanner);
+
+					/*FALLTHROUGH*/
+
+				case EOB_ACT_END_OF_FILE:
+					{
+					if ( yywrap(yyscanner ) )
+						return EOF;
+
+					if ( ! yyg->yy_did_buffer_switch_on_eof )
+						YY_NEW_FILE;
+#ifdef __cplusplus
+					return yyinput(yyscanner);
+#else
+					return input(yyscanner);
+#endif
+					}
+
+				case EOB_ACT_CONTINUE_SCAN:
+					yyg->yy_c_buf_p = yyg->yytext_ptr + offset;
+					break;
+				}
+			}
+		}
+
+	c = *(unsigned char *) yyg->yy_c_buf_p;	/* cast for 8-bit char's */
+	*yyg->yy_c_buf_p = '\0';	/* preserve yytext */
+	yyg->yy_hold_char = *++yyg->yy_c_buf_p;
+
+	if ( c == '\n' )
+		   
+    do{ yylineno++;
+        yycolumn=0;
+    }while(0)
+;
+
+	return c;
+}
+#endif	/* ifndef YY_NO_INPUT */
+
+/** Immediately switch to a different input stream.
+ * @param input_file A readable stream.
+ * @param yyscanner The scanner object.
+ * @note This function does not reset the start condition to @c INITIAL .
+ */
+    void yyrestart  (FILE * input_file , yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+	if ( ! YY_CURRENT_BUFFER ){
+        yyensure_buffer_stack (yyscanner);
+		YY_CURRENT_BUFFER_LVALUE =
+            yy_create_buffer(yyin,YY_BUF_SIZE ,yyscanner);
+	}
+
+	yy_init_buffer(YY_CURRENT_BUFFER,input_file ,yyscanner);
+	yy_load_buffer_state(yyscanner );
+}
+
+/** Switch to a different input buffer.
+ * @param new_buffer The new input buffer.
+ * @param yyscanner The scanner object.
+ */
+    void yy_switch_to_buffer  (YY_BUFFER_STATE  new_buffer , yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+	/* TODO. We should be able to replace this entire function body
+	 * with
+	 *		yypop_buffer_state();
+	 *		yypush_buffer_state(new_buffer);
+     */
+	yyensure_buffer_stack (yyscanner);
+	if ( YY_CURRENT_BUFFER == new_buffer )
+		return;
+
+	if ( YY_CURRENT_BUFFER )
+		{
+		/* Flush out information for old buffer. */
+		*yyg->yy_c_buf_p = yyg->yy_hold_char;
+		YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = yyg->yy_c_buf_p;
+		YY_CURRENT_BUFFER_LVALUE->yy_n_chars = yyg->yy_n_chars;
+		}
+
+	YY_CURRENT_BUFFER_LVALUE = new_buffer;
+	yy_load_buffer_state(yyscanner );
+
+	/* We don't actually know whether we did this switch during
+	 * EOF (yywrap()) processing, but the only time this flag
+	 * is looked at is after yywrap() is called, so it's safe
+	 * to go ahead and always set it.
+	 */
+	yyg->yy_did_buffer_switch_on_eof = 1;
+}
+
+static void yy_load_buffer_state  (yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+	yyg->yy_n_chars = YY_CURRENT_BUFFER_LVALUE->yy_n_chars;
+	yyg->yytext_ptr = yyg->yy_c_buf_p = YY_CURRENT_BUFFER_LVALUE->yy_buf_pos;
+	yyin = YY_CURRENT_BUFFER_LVALUE->yy_input_file;
+	yyg->yy_hold_char = *yyg->yy_c_buf_p;
+}
+
+/** Allocate and initialize an input buffer state.
+ * @param file A readable stream.
+ * @param size The character buffer size in bytes. When in doubt, use @c YY_BUF_SIZE.
+ * @param yyscanner The scanner object.
+ * @return the allocated buffer state.
+ */
+    YY_BUFFER_STATE yy_create_buffer  (FILE * file, int  size , yyscan_t yyscanner)
+{
+	YY_BUFFER_STATE b;
+    
+	b = (YY_BUFFER_STATE) yyalloc(sizeof( struct yy_buffer_state ) ,yyscanner );
+	if ( ! b )
+		YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" );
+
+	b->yy_buf_size = size;
+
+	/* yy_ch_buf has to be 2 characters longer than the size given because
+	 * we need to put in 2 end-of-buffer characters.
+	 */
+	b->yy_ch_buf = (char *) yyalloc(b->yy_buf_size + 2 ,yyscanner );
+	if ( ! b->yy_ch_buf )
+		YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" );
+
+	b->yy_is_our_buffer = 1;
+
+	yy_init_buffer(b,file ,yyscanner);
+
+	return b;
+}
+
+/** Destroy the buffer.
+ * @param b a buffer created with yy_create_buffer()
+ * @param yyscanner The scanner object.
+ */
+    void yy_delete_buffer (YY_BUFFER_STATE  b , yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+	if ( ! b )
+		return;
+
+	if ( b == YY_CURRENT_BUFFER ) /* Not sure if we should pop here. */
+		YY_CURRENT_BUFFER_LVALUE = (YY_BUFFER_STATE) 0;
+
+	if ( b->yy_is_our_buffer )
+		yyfree((void *) b->yy_ch_buf ,yyscanner );
+
+	yyfree((void *) b ,yyscanner );
+}
+
+/* Initializes or reinitializes a buffer.
+ * This function is sometimes called more than once on the same buffer,
+ * such as during a yyrestart() or at EOF.
+ */
+    static void yy_init_buffer  (YY_BUFFER_STATE  b, FILE * file , yyscan_t yyscanner)
+
+{
+	int oerrno = errno;
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+	yy_flush_buffer(b ,yyscanner);
+
+	b->yy_input_file = file;
+	b->yy_fill_buffer = 1;
+
+    /* If b is the current buffer, then yy_init_buffer was _probably_
+     * called from yyrestart() or through yy_get_next_buffer.
+     * In that case, we don't want to reset the lineno or column.
+     */
+    if (b != YY_CURRENT_BUFFER){
+        b->yy_bs_lineno = 1;
+        b->yy_bs_column = 0;
+    }
+
+        b->yy_is_interactive = 0;
+    
+	errno = oerrno;
+}
+
+/** Discard all buffered characters. On the next scan, YY_INPUT will be called.
+ * @param b the buffer state to be flushed, usually @c YY_CURRENT_BUFFER.
+ * @param yyscanner The scanner object.
+ */
+    void yy_flush_buffer (YY_BUFFER_STATE  b , yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+	if ( ! b )
+		return;
+
+	b->yy_n_chars = 0;
+
+	/* We always need two end-of-buffer characters.  The first causes
+	 * a transition to the end-of-buffer state.  The second causes
+	 * a jam in that state.
+	 */
+	b->yy_ch_buf[0] = YY_END_OF_BUFFER_CHAR;
+	b->yy_ch_buf[1] = YY_END_OF_BUFFER_CHAR;
+
+	b->yy_buf_pos = &b->yy_ch_buf[0];
+
+	b->yy_at_bol = 1;
+	b->yy_buffer_status = YY_BUFFER_NEW;
+
+	if ( b == YY_CURRENT_BUFFER )
+		yy_load_buffer_state(yyscanner );
+}
+
+/** Pushes the new state onto the stack. The new state becomes
+ *  the current state. This function will allocate the stack
+ *  if necessary.
+ *  @param new_buffer The new state.
+ *  @param yyscanner The scanner object.
+ */
+void yypush_buffer_state (YY_BUFFER_STATE new_buffer , yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+	if (new_buffer == NULL)
+		return;
+
+	yyensure_buffer_stack(yyscanner);
+
+	/* This block is copied from yy_switch_to_buffer. */
+	if ( YY_CURRENT_BUFFER )
+		{
+		/* Flush out information for old buffer. */
+		*yyg->yy_c_buf_p = yyg->yy_hold_char;
+		YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = yyg->yy_c_buf_p;
+		YY_CURRENT_BUFFER_LVALUE->yy_n_chars = yyg->yy_n_chars;
+		}
+
+	/* Only push if top exists. Otherwise, replace top. */
+	if (YY_CURRENT_BUFFER)
+		yyg->yy_buffer_stack_top++;
+	YY_CURRENT_BUFFER_LVALUE = new_buffer;
+
+	/* copied from yy_switch_to_buffer. */
+	yy_load_buffer_state(yyscanner );
+	yyg->yy_did_buffer_switch_on_eof = 1;
+}
+
+/** Removes and deletes the top of the stack, if present.
+ *  The next element becomes the new top.
+ *  @param yyscanner The scanner object.
+ */
+void yypop_buffer_state (yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+	if (!YY_CURRENT_BUFFER)
+		return;
+
+	yy_delete_buffer(YY_CURRENT_BUFFER ,yyscanner);
+	YY_CURRENT_BUFFER_LVALUE = NULL;
+	if (yyg->yy_buffer_stack_top > 0)
+		--yyg->yy_buffer_stack_top;
+
+	if (YY_CURRENT_BUFFER) {
+		yy_load_buffer_state(yyscanner );
+		yyg->yy_did_buffer_switch_on_eof = 1;
+	}
+}
+
+/* Allocates the stack if it does not exist.
+ *  Guarantees space for at least one push.
+ */
+static void yyensure_buffer_stack (yyscan_t yyscanner)
+{
+	int num_to_alloc;
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+	if (!yyg->yy_buffer_stack) {
+
+		/* First allocation is just for 2 elements, since we don't know if this
+		 * scanner will even need a stack. We use 2 instead of 1 to avoid an
+		 * immediate realloc on the next call.
+         */
+		num_to_alloc = 1;
+		yyg->yy_buffer_stack = (struct yy_buffer_state**)yyalloc
+								(num_to_alloc * sizeof(struct yy_buffer_state*)
+								, yyscanner);
+		if ( ! yyg->yy_buffer_stack )
+			YY_FATAL_ERROR( "out of dynamic memory in yyensure_buffer_stack()" );
+								  
+		memset(yyg->yy_buffer_stack, 0, num_to_alloc * sizeof(struct yy_buffer_state*));
+				
+		yyg->yy_buffer_stack_max = num_to_alloc;
+		yyg->yy_buffer_stack_top = 0;
+		return;
+	}
+
+	if (yyg->yy_buffer_stack_top >= (yyg->yy_buffer_stack_max) - 1){
+
+		/* Increase the buffer to prepare for a possible push. */
+		int grow_size = 8 /* arbitrary grow size */;
+
+		num_to_alloc = yyg->yy_buffer_stack_max + grow_size;
+		yyg->yy_buffer_stack = (struct yy_buffer_state**)yyrealloc
+								(yyg->yy_buffer_stack,
+								num_to_alloc * sizeof(struct yy_buffer_state*)
+								, yyscanner);
+		if ( ! yyg->yy_buffer_stack )
+			YY_FATAL_ERROR( "out of dynamic memory in yyensure_buffer_stack()" );
+
+		/* zero only the new slots.*/
+		memset(yyg->yy_buffer_stack + yyg->yy_buffer_stack_max, 0, grow_size * sizeof(struct yy_buffer_state*));
+		yyg->yy_buffer_stack_max = num_to_alloc;
+	}
+}
+
+/** Setup the input buffer state to scan directly from a user-specified character buffer.
+ * @param base the character buffer
+ * @param size the size in bytes of the character buffer
+ * @param yyscanner The scanner object.
+ * @return the newly allocated buffer state object. 
+ */
+YY_BUFFER_STATE yy_scan_buffer  (char * base, yy_size_t  size , yyscan_t yyscanner)
+{
+	YY_BUFFER_STATE b;
+    
+	if ( size < 2 ||
+	     base[size-2] != YY_END_OF_BUFFER_CHAR ||
+	     base[size-1] != YY_END_OF_BUFFER_CHAR )
+		/* They forgot to leave room for the EOB's. */
+		return 0;
+
+	b = (YY_BUFFER_STATE) yyalloc(sizeof( struct yy_buffer_state ) ,yyscanner );
+	if ( ! b )
+		YY_FATAL_ERROR( "out of dynamic memory in yy_scan_buffer()" );
+
+	b->yy_buf_size = size - 2;	/* "- 2" to take care of EOB's */
+	b->yy_buf_pos = b->yy_ch_buf = base;
+	b->yy_is_our_buffer = 0;
+	b->yy_input_file = 0;
+	b->yy_n_chars = b->yy_buf_size;
+	b->yy_is_interactive = 0;
+	b->yy_at_bol = 1;
+	b->yy_fill_buffer = 0;
+	b->yy_buffer_status = YY_BUFFER_NEW;
+
+	yy_switch_to_buffer(b ,yyscanner );
+
+	return b;
+}
+
+/** Setup the input buffer state to scan a string. The next call to yylex() will
+ * scan from a @e copy of @a str.
+ * @param yystr a NUL-terminated string to scan
+ * @param yyscanner The scanner object.
+ * @return the newly allocated buffer state object.
+ * @note If you want to scan bytes that may contain NUL values, then use
+ *       yy_scan_bytes() instead.
+ */
+YY_BUFFER_STATE yy_scan_string (yyconst char * yystr , yyscan_t yyscanner)
+{
+    
+	return yy_scan_bytes(yystr,strlen(yystr) ,yyscanner);
+}
+
+/** Setup the input buffer state to scan the given bytes. The next call to yylex() will
+ * scan from a @e copy of @a bytes.
+ * @param bytes the byte buffer to scan
+ * @param len the number of bytes in the buffer pointed to by @a bytes.
+ * @param yyscanner The scanner object.
+ * @return the newly allocated buffer state object.
+ */
+YY_BUFFER_STATE yy_scan_bytes  (yyconst char * yybytes, int  _yybytes_len , yyscan_t yyscanner)
+{
+	YY_BUFFER_STATE b;
+	char *buf;
+	yy_size_t n;
+	int i;
+    
+	/* Get memory for full buffer, including space for trailing EOB's. */
+	n = _yybytes_len + 2;
+	buf = (char *) yyalloc(n ,yyscanner );
+	if ( ! buf )
+		YY_FATAL_ERROR( "out of dynamic memory in yy_scan_bytes()" );
+
+	for ( i = 0; i < _yybytes_len; ++i )
+		buf[i] = yybytes[i];
+
+	buf[_yybytes_len] = buf[_yybytes_len+1] = YY_END_OF_BUFFER_CHAR;
+
+	b = yy_scan_buffer(buf,n ,yyscanner);
+	if ( ! b )
+		YY_FATAL_ERROR( "bad buffer in yy_scan_bytes()" );
+
+	/* It's okay to grow etc. this buffer, and we should throw it
+	 * away when we're done.
+	 */
+	b->yy_is_our_buffer = 1;
+
+	return b;
+}
+
+    static void yy_push_state (int  new_state , yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+	if ( yyg->yy_start_stack_ptr >= yyg->yy_start_stack_depth )
+		{
+		yy_size_t new_size;
+
+		yyg->yy_start_stack_depth += YY_START_STACK_INCR;
+		new_size = yyg->yy_start_stack_depth * sizeof( int );
+
+		if ( ! yyg->yy_start_stack )
+			yyg->yy_start_stack = (int *) yyalloc(new_size ,yyscanner );
+
+		else
+			yyg->yy_start_stack = (int *) yyrealloc((void *) yyg->yy_start_stack,new_size ,yyscanner );
+
+		if ( ! yyg->yy_start_stack )
+			YY_FATAL_ERROR( "out of memory expanding start-condition stack" );
+		}
+
+	yyg->yy_start_stack[yyg->yy_start_stack_ptr++] = YY_START;
+
+	BEGIN(new_state);
+}
+
+    static void yy_pop_state  (yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+	if ( --yyg->yy_start_stack_ptr < 0 )
+		YY_FATAL_ERROR( "start-condition stack underflow" );
+
+	BEGIN(yyg->yy_start_stack[yyg->yy_start_stack_ptr]);
+}
+
+    static int yy_top_state  (yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+	return yyg->yy_start_stack[yyg->yy_start_stack_ptr - 1];
+}
+
+#ifndef YY_EXIT_FAILURE
+#define YY_EXIT_FAILURE 2
+#endif
+
+static void yy_fatal_error (yyconst char* msg , yyscan_t yyscanner)
+{
+    	(void) fprintf( stderr, "%s\n", msg );
+	exit( YY_EXIT_FAILURE );
+}
+
+/* Redefine yyless() so it works in section 3 code. */
+
+#undef yyless
+#define yyless(n) \
+	do \
+		{ \
+		/* Undo effects of setting up yytext. */ \
+        int yyless_macro_arg = (n); \
+        YY_LESS_LINENO(yyless_macro_arg);\
+		yytext[yyleng] = yyg->yy_hold_char; \
+		yyg->yy_c_buf_p = yytext + yyless_macro_arg; \
+		yyg->yy_hold_char = *yyg->yy_c_buf_p; \
+		*yyg->yy_c_buf_p = '\0'; \
+		yyleng = yyless_macro_arg; \
+		} \
+	while ( 0 )
+
+/* Accessor  methods (get/set functions) to struct members. */
+
+/** Get the user-defined data for this scanner.
+ * @param yyscanner The scanner object.
+ */
+YY_EXTRA_TYPE yyget_extra  (yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+    return yyextra;
+}
+
+/** Get the current line number.
+ * @param yyscanner The scanner object.
+ */
+int yyget_lineno  (yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+    
+        if (! YY_CURRENT_BUFFER)
+            return 0;
+    
+    return yylineno;
+}
+
+/** Get the current column number.
+ * @param yyscanner The scanner object.
+ */
+int yyget_column  (yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+    
+        if (! YY_CURRENT_BUFFER)
+            return 0;
+    
+    return yycolumn;
+}
+
+/** Get the input stream.
+ * @param yyscanner The scanner object.
+ */
+FILE *yyget_in  (yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+    return yyin;
+}
+
+/** Get the output stream.
+ * @param yyscanner The scanner object.
+ */
+FILE *yyget_out  (yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+    return yyout;
+}
+
+/** Get the length of the current token.
+ * @param yyscanner The scanner object.
+ */
+int yyget_leng  (yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+    return yyleng;
+}
+
+/** Get the current token.
+ * @param yyscanner The scanner object.
+ */
+
+char *yyget_text  (yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+    return yytext;
+}
+
+/** Set the user-defined data. This data is never touched by the scanner.
+ * @param user_defined The data to be associated with this scanner.
+ * @param yyscanner The scanner object.
+ */
+void yyset_extra (YY_EXTRA_TYPE  user_defined , yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+    yyextra = user_defined ;
+}
+
+/** Set the current line number.
+ * @param line_number
+ * @param yyscanner The scanner object.
+ */
+void yyset_lineno (int  line_number , yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+        /* lineno is only valid if an input buffer exists. */
+        if (! YY_CURRENT_BUFFER )
+           yy_fatal_error( "yyset_lineno called with no buffer" , yyscanner); 
+    
+    yylineno = line_number;
+}
+
+/** Set the current column.
+ * @param line_number
+ * @param yyscanner The scanner object.
+ */
+void yyset_column (int  column_no , yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+        /* column is only valid if an input buffer exists. */
+        if (! YY_CURRENT_BUFFER )
+           yy_fatal_error( "yyset_column called with no buffer" , yyscanner); 
+    
+    yycolumn = column_no;
+}
+
+/** Set the input stream. This does not discard the current
+ * input buffer.
+ * @param in_str A readable stream.
+ * @param yyscanner The scanner object.
+ * @see yy_switch_to_buffer
+ */
+void yyset_in (FILE *  in_str , yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+    yyin = in_str ;
+}
+
+void yyset_out (FILE *  out_str , yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+    yyout = out_str ;
+}
+
+int yyget_debug  (yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+    return yy_flex_debug;
+}
+
+void yyset_debug (int  bdebug , yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+    yy_flex_debug = bdebug ;
+}
+
+/* Accessor methods for yylval and yylloc */
+
+YYSTYPE * yyget_lval  (yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+    return yylval;
+}
+
+void yyset_lval (YYSTYPE *  yylval_param , yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+    yylval = yylval_param;
+}
+
+/* User-visible API */
+
+/* yylex_init is special because it creates the scanner itself, so it is
+ * the ONLY reentrant function that doesn't take the scanner as the last argument.
+ * That's why we explicitly handle the declaration, instead of using our macros.
+ */
+
+int yylex_init(yyscan_t* ptr_yy_globals)
+
+{
+    if (ptr_yy_globals == NULL){
+        errno = EINVAL;
+        return 1;
+    }
+
+    *ptr_yy_globals = (yyscan_t) yyalloc ( sizeof( struct yyguts_t ), NULL );
+
+    if (*ptr_yy_globals == NULL){
+        errno = ENOMEM;
+        return 1;
+    }
+
+    /* By setting to 0xAA, we expose bugs in yy_init_globals. Leave at 0x00 for releases. */
+    memset(*ptr_yy_globals,0x00,sizeof(struct yyguts_t));
+
+    return yy_init_globals ( *ptr_yy_globals );
+}
+
+/* yylex_init_extra has the same functionality as yylex_init, but follows the
+ * convention of taking the scanner as the last argument. Note however, that
+ * this is a *pointer* to a scanner, as it will be allocated by this call (and
+ * is the reason, too, why this function also must handle its own declaration).
+ * The user defined value in the first argument will be available to yyalloc in
+ * the yyextra field.
+ */
+
+int yylex_init_extra(YY_EXTRA_TYPE yy_user_defined,yyscan_t* ptr_yy_globals )
+
+{
+    struct yyguts_t dummy_yyguts;
+
+    yyset_extra (yy_user_defined, &dummy_yyguts);
+
+    if (ptr_yy_globals == NULL){
+        errno = EINVAL;
+        return 1;
+    }
+	
+    *ptr_yy_globals = (yyscan_t) yyalloc ( sizeof( struct yyguts_t ), &dummy_yyguts );
+	
+    if (*ptr_yy_globals == NULL){
+        errno = ENOMEM;
+        return 1;
+    }
+    
+    /* By setting to 0xAA, we expose bugs in
+    yy_init_globals. Leave at 0x00 for releases. */
+    memset(*ptr_yy_globals,0x00,sizeof(struct yyguts_t));
+    
+    yyset_extra (yy_user_defined, *ptr_yy_globals);
+    
+    return yy_init_globals ( *ptr_yy_globals );
+}
+
+static int yy_init_globals (yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+    /* Initialization is the same as for the non-reentrant scanner.
+     * This function is called from yylex_destroy(), so don't allocate here.
+     */
+
+    yyg->yy_buffer_stack = 0;
+    yyg->yy_buffer_stack_top = 0;
+    yyg->yy_buffer_stack_max = 0;
+    yyg->yy_c_buf_p = (char *) 0;
+    yyg->yy_init = 0;
+    yyg->yy_start = 0;
+
+    yyg->yy_start_stack_ptr = 0;
+    yyg->yy_start_stack_depth = 0;
+    yyg->yy_start_stack =  NULL;
+
+/* Defined in main.c */
+#ifdef YY_STDINIT
+    yyin = stdin;
+    yyout = stdout;
+#else
+    yyin = (FILE *) 0;
+    yyout = (FILE *) 0;
+#endif
+
+    /* For future reference: Set errno on error, since we are called by
+     * yylex_init()
+     */
+    return 0;
+}
+
+/* yylex_destroy is for both reentrant and non-reentrant scanners. */
+int yylex_destroy  (yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+    /* Pop the buffer stack, destroying each element. */
+	while(YY_CURRENT_BUFFER){
+		yy_delete_buffer(YY_CURRENT_BUFFER ,yyscanner );
+		YY_CURRENT_BUFFER_LVALUE = NULL;
+		yypop_buffer_state(yyscanner);
+	}
+
+	/* Destroy the stack itself. */
+	yyfree(yyg->yy_buffer_stack ,yyscanner);
+	yyg->yy_buffer_stack = NULL;
+
+    /* Destroy the start condition stack. */
+        yyfree(yyg->yy_start_stack ,yyscanner );
+        yyg->yy_start_stack = NULL;
+
+    /* Reset the globals. This is important in a non-reentrant scanner so the next time
+     * yylex() is called, initialization will occur. */
+    yy_init_globals( yyscanner);
+
+    /* Destroy the main struct (reentrant only). */
+    yyfree ( yyscanner , yyscanner );
+    yyscanner = NULL;
+    return 0;
+}
+
+/*
+ * Internal utility routines.
+ */
+
+#ifndef yytext_ptr
+static void yy_flex_strncpy (char* s1, yyconst char * s2, int n , yyscan_t yyscanner)
+{
+	register int i;
+	for ( i = 0; i < n; ++i )
+		s1[i] = s2[i];
+}
+#endif
+
+#ifdef YY_NEED_STRLEN
+static int yy_flex_strlen (yyconst char * s , yyscan_t yyscanner)
+{
+	register int n;
+	for ( n = 0; s[n]; ++n )
+		;
+
+	return n;
+}
+#endif
+
+void *yyalloc (yy_size_t  size , yyscan_t yyscanner)
+{
+	return (void *) malloc( size );
+}
+
+void *yyrealloc  (void * ptr, yy_size_t  size , yyscan_t yyscanner)
+{
+	/* The cast to (char *) in the following accommodates both
+	 * implementations that use char* generic pointers, and those
+	 * that use void* generic pointers.  It works with the latter
+	 * because both ANSI C and C++ allow castless assignment from
+	 * any pointer type to void*, and deal with argument conversions
+	 * as though doing an assignment.
+	 */
+	return (void *) realloc( (char *) ptr, size );
+}
+
+void yyfree (void * ptr , yyscan_t yyscanner)
+{
+	free( (char *) ptr );	/* see yyrealloc() for (char *) cast */
+}
+
+#define YYTABLES_NAME "yytables"
+
+int string_input(char* buf, int max_size, yyscan_t yyscanner)
+{
+    int len = 0;
+
+    pp::Token token;
+    yyget_extra(yyscanner)->preprocessor.lex(&token);
+    len = token.type == pp::Token::LAST ? 0 : token.text.size();
+    if ((len > 0) && (len < max_size))
+        memcpy(buf, token.text.c_str(), len);
+    yyset_lineno(EncodeSourceLoc(token.location.file, token.location.line),yyscanner);
+
+    if (len >= max_size)
+        YY_FATAL_ERROR("Input buffer overflow");
+    else if (len > 0)
+        buf[len++] = ' ';
+    return len;
+}
+
+int check_type(yyscan_t yyscanner) {
+    struct yyguts_t* yyg = (struct yyguts_t*) yyscanner;
+    
+    int token = IDENTIFIER;
+    TSymbol* symbol = yyextra->symbolTable.find(yytext);
+    if (yyextra->lexAfterType == false && symbol && symbol->isVariable()) {
+        TVariable* variable = static_cast<TVariable*>(symbol);
+        if (variable->isUserType()) {
+            yyextra->lexAfterType = true;
+            token = TYPE_NAME;
+        }
+    }
+    yylval->lex.symbol = symbol;
+    return token;
+}
+
+int reserved_word(yyscan_t yyscanner) {
+    struct yyguts_t* yyg = (struct yyguts_t*) yyscanner;
+
+    yyextra->error(yylineno, "Illegal use of reserved word", yytext, "");
+    yyextra->recover();
+    return 0;
+}
+
+void yyerror(TParseContext* context, const char* reason) {
+    struct yyguts_t* yyg = (struct yyguts_t*) context->scanner;
+
+    if (context->AfterEOF) {
+        context->error(yylineno, reason, "unexpected EOF");
+    } else {
+        context->error(yylineno, reason, yytext);
+    }
+    context->recover();
+}
+
+int glslang_initialize(TParseContext* context) {
+    yyscan_t scanner = NULL;
+    if (yylex_init_extra(context,&scanner))
+        return 1;
+
+    context->scanner = scanner;
+    return 0;
+}
+
+int glslang_finalize(TParseContext* context) {
+    yyscan_t scanner = context->scanner;
+    if (scanner == NULL) return 0;
+    
+    context->scanner = NULL;
+    yylex_destroy(scanner);
+
+    return 0;
+}
+
+int glslang_scan(int count, const char* const string[], const int length[],
+                 TParseContext* context) {
+    yyrestart(NULL,context->scanner);
+    yyset_lineno(EncodeSourceLoc(0, 1),context->scanner);
+    context->AfterEOF = false;
+
+    // Initialize preprocessor.
+    if (!context->preprocessor.init(count, string, length))
+        return 1;
+
+    // Define extension macros.
+    const TExtensionBehavior& extBehavior = context->extensionBehavior();
+    for (TExtensionBehavior::const_iterator iter = extBehavior.begin();
+         iter != extBehavior.end(); ++iter)
+    {
+        context->preprocessor.predefineMacro(iter->first.c_str(), 1);
+    }
+    return 0;
+}
+
diff --git a/src/GLES2/compiler/glslang_tab.cpp b/src/GLES2/compiler/glslang_tab.cpp
new file mode 100644
index 0000000..3784c5e
--- /dev/null
+++ b/src/GLES2/compiler/glslang_tab.cpp
@@ -0,0 +1,4714 @@
+/* A Bison parser, made by GNU Bison 2.4.2.  */
+
+/* Skeleton implementation for Bison's Yacc-like parsers in C
+   
+      Copyright (C) 1984, 1989-1990, 2000-2006, 2009-2010 Free Software
+   Foundation, Inc.
+   
+   This program 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.
+   
+   This program 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 this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+/* As a special exception, you may create a larger work that contains
+   part or all of the Bison parser skeleton and distribute that work
+   under terms of your choice, so long as that work isn't itself a
+   parser generator using the skeleton or a modified version thereof
+   as a parser skeleton.  Alternatively, if you modify or redistribute
+   the parser skeleton itself, you may (at your option) remove this
+   special exception, which will cause the skeleton and the resulting
+   Bison output files to be licensed under the GNU General Public
+   License without this special exception.
+   
+   This special exception was added by the Free Software Foundation in
+   version 2.2 of Bison.  */
+
+/* C LALR(1) parser skeleton written by Richard Stallman, by
+   simplifying the original so-called "semantic" parser.  */
+
+/* All symbols defined below should begin with yy or YY, to avoid
+   infringing on user name space.  This should be done even for local
+   variables, as they might otherwise be expanded by user macros.
+   There are some unavoidable exceptions within include files to
+   define necessary library symbols; they are noted "INFRINGES ON
+   USER NAME SPACE" below.  */
+
+/* Identify Bison output.  */
+#define YYBISON 1
+
+/* Bison version.  */
+#define YYBISON_VERSION "2.4.2"
+
+/* Skeleton name.  */
+#define YYSKELETON_NAME "yacc.c"
+
+/* Pure parsers.  */
+#define YYPURE 1
+
+/* Push parsers.  */
+#define YYPUSH 0
+
+/* Pull parsers.  */
+#define YYPULL 1
+
+/* Using locations.  */
+#define YYLSP_NEEDED 0
+
+
+
+/* Copy the first part of user declarations.  */
+
+
+//
+// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// This file is auto-generated by generate_parser.sh. DO NOT EDIT!
+
+// Ignore errors in auto-generated code.
+#if defined(__GNUC__)
+#pragma GCC diagnostic ignored "-Wunused-function"
+#pragma GCC diagnostic ignored "-Wunused-variable"
+#pragma GCC diagnostic ignored "-Wswitch-enum"
+#elif defined(_MSC_VER)
+#pragma warning(disable: 4065)
+#pragma warning(disable: 4189)
+#pragma warning(disable: 4505)
+#pragma warning(disable: 4701)
+#endif
+
+#include "compiler/SymbolTable.h"
+#include "compiler/ParseHelper.h"
+#include "GLSLANG/ShaderLang.h"
+
+#define YYLEX_PARAM context->scanner
+
+
+
+/* Enabling traces.  */
+#ifndef YYDEBUG
+# define YYDEBUG 0
+#endif
+
+/* Enabling verbose error messages.  */
+#ifdef YYERROR_VERBOSE
+# undef YYERROR_VERBOSE
+# define YYERROR_VERBOSE 1
+#else
+# define YYERROR_VERBOSE 0
+#endif
+
+/* Enabling the token table.  */
+#ifndef YYTOKEN_TABLE
+# define YYTOKEN_TABLE 0
+#endif
+
+
+/* Tokens.  */
+#ifndef YYTOKENTYPE
+# define YYTOKENTYPE
+   /* Put the tokens into the symbol table, so that GDB and other debuggers
+      know about them.  */
+   enum yytokentype {
+     INVARIANT = 258,
+     HIGH_PRECISION = 259,
+     MEDIUM_PRECISION = 260,
+     LOW_PRECISION = 261,
+     PRECISION = 262,
+     ATTRIBUTE = 263,
+     CONST_QUAL = 264,
+     BOOL_TYPE = 265,
+     FLOAT_TYPE = 266,
+     INT_TYPE = 267,
+     BREAK = 268,
+     CONTINUE = 269,
+     DO = 270,
+     ELSE = 271,
+     FOR = 272,
+     IF = 273,
+     DISCARD = 274,
+     RETURN = 275,
+     BVEC2 = 276,
+     BVEC3 = 277,
+     BVEC4 = 278,
+     IVEC2 = 279,
+     IVEC3 = 280,
+     IVEC4 = 281,
+     VEC2 = 282,
+     VEC3 = 283,
+     VEC4 = 284,
+     MATRIX2 = 285,
+     MATRIX3 = 286,
+     MATRIX4 = 287,
+     IN_QUAL = 288,
+     OUT_QUAL = 289,
+     INOUT_QUAL = 290,
+     UNIFORM = 291,
+     VARYING = 292,
+     STRUCT = 293,
+     VOID_TYPE = 294,
+     WHILE = 295,
+     SAMPLER2D = 296,
+     SAMPLERCUBE = 297,
+     IDENTIFIER = 298,
+     TYPE_NAME = 299,
+     FLOATCONSTANT = 300,
+     INTCONSTANT = 301,
+     BOOLCONSTANT = 302,
+     FIELD_SELECTION = 303,
+     LEFT_OP = 304,
+     RIGHT_OP = 305,
+     INC_OP = 306,
+     DEC_OP = 307,
+     LE_OP = 308,
+     GE_OP = 309,
+     EQ_OP = 310,
+     NE_OP = 311,
+     AND_OP = 312,
+     OR_OP = 313,
+     XOR_OP = 314,
+     MUL_ASSIGN = 315,
+     DIV_ASSIGN = 316,
+     ADD_ASSIGN = 317,
+     MOD_ASSIGN = 318,
+     LEFT_ASSIGN = 319,
+     RIGHT_ASSIGN = 320,
+     AND_ASSIGN = 321,
+     XOR_ASSIGN = 322,
+     OR_ASSIGN = 323,
+     SUB_ASSIGN = 324,
+     LEFT_PAREN = 325,
+     RIGHT_PAREN = 326,
+     LEFT_BRACKET = 327,
+     RIGHT_BRACKET = 328,
+     LEFT_BRACE = 329,
+     RIGHT_BRACE = 330,
+     DOT = 331,
+     COMMA = 332,
+     COLON = 333,
+     EQUAL = 334,
+     SEMICOLON = 335,
+     BANG = 336,
+     DASH = 337,
+     TILDE = 338,
+     PLUS = 339,
+     STAR = 340,
+     SLASH = 341,
+     PERCENT = 342,
+     LEFT_ANGLE = 343,
+     RIGHT_ANGLE = 344,
+     VERTICAL_BAR = 345,
+     CARET = 346,
+     AMPERSAND = 347,
+     QUESTION = 348
+   };
+#endif
+
+
+
+#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
+typedef union YYSTYPE
+{
+
+
+    struct {
+        TSourceLoc line;
+        union {
+            TString *string;
+            float f;
+            int i;
+            bool b;
+        };
+        TSymbol* symbol;
+    } lex;
+    struct {
+        TSourceLoc line;
+        TOperator op;
+        union {
+            TIntermNode* intermNode;
+            TIntermNodePair nodePair;
+            TIntermTyped* intermTypedNode;
+            TIntermAggregate* intermAggregate;
+        };
+        union {
+            TPublicType type;
+            TPrecision precision;
+            TQualifier qualifier;
+            TFunction* function;
+            TParameter param;
+            TTypeLine typeLine;
+            TTypeList* typeList;
+        };
+    } interm;
+
+
+
+} YYSTYPE;
+# define YYSTYPE_IS_TRIVIAL 1
+# define yystype YYSTYPE /* obsolescent; will be withdrawn */
+# define YYSTYPE_IS_DECLARED 1
+#endif
+
+
+/* Copy the second part of user declarations.  */
+
+
+extern int yylex(YYSTYPE* yylval_param, void* yyscanner);
+extern void yyerror(TParseContext* context, const char* reason);
+
+#define FRAG_VERT_ONLY(S, L) {  \
+    if (context->shaderType != SH_FRAGMENT_SHADER &&  \
+        context->shaderType != SH_VERTEX_SHADER) {  \
+        context->error(L, " supported in vertex/fragment shaders only ", S);  \
+        context->recover();  \
+    }  \
+}
+
+#define VERTEX_ONLY(S, L) {  \
+    if (context->shaderType != SH_VERTEX_SHADER) {  \
+        context->error(L, " supported in vertex shaders only ", S);  \
+        context->recover();  \
+    }  \
+}
+
+#define FRAG_ONLY(S, L) {  \
+    if (context->shaderType != SH_FRAGMENT_SHADER) {  \
+        context->error(L, " supported in fragment shaders only ", S);  \
+        context->recover();  \
+    }  \
+}
+
+
+
+#ifdef short
+# undef short
+#endif
+
+#ifdef YYTYPE_UINT8
+typedef YYTYPE_UINT8 yytype_uint8;
+#else
+typedef unsigned char yytype_uint8;
+#endif
+
+#ifdef YYTYPE_INT8
+typedef YYTYPE_INT8 yytype_int8;
+#elif (defined __STDC__ || defined __C99__FUNC__ \
+     || defined __cplusplus || defined _MSC_VER)
+typedef signed char yytype_int8;
+#else
+typedef short int yytype_int8;
+#endif
+
+#ifdef YYTYPE_UINT16
+typedef YYTYPE_UINT16 yytype_uint16;
+#else
+typedef unsigned short int yytype_uint16;
+#endif
+
+#ifdef YYTYPE_INT16
+typedef YYTYPE_INT16 yytype_int16;
+#else
+typedef short int yytype_int16;
+#endif
+
+#ifndef YYSIZE_T
+# ifdef __SIZE_TYPE__
+#  define YYSIZE_T __SIZE_TYPE__
+# elif defined size_t
+#  define YYSIZE_T size_t
+# elif ! defined YYSIZE_T && (defined __STDC__ || defined __C99__FUNC__ \
+     || defined __cplusplus || defined _MSC_VER)
+#  include <stddef.h> /* INFRINGES ON USER NAME SPACE */
+#  define YYSIZE_T size_t
+# else
+#  define YYSIZE_T unsigned int
+# endif
+#endif
+
+#define YYSIZE_MAXIMUM ((YYSIZE_T) -1)
+
+#ifndef YY_
+# if defined YYENABLE_NLS && YYENABLE_NLS
+#  if ENABLE_NLS
+#   include <libintl.h> /* INFRINGES ON USER NAME SPACE */
+#   define YY_(msgid) dgettext ("bison-runtime", msgid)
+#  endif
+# endif
+# ifndef YY_
+#  define YY_(msgid) msgid
+# endif
+#endif
+
+/* Suppress unused-variable warnings by "using" E.  */
+#if ! defined lint || defined __GNUC__
+# define YYUSE(e) ((void) (e))
+#else
+# define YYUSE(e) /* empty */
+#endif
+
+/* Identity function, used to suppress warnings about constant conditions.  */
+#ifndef lint
+# define YYID(n) (n)
+#else
+#if (defined __STDC__ || defined __C99__FUNC__ \
+     || defined __cplusplus || defined _MSC_VER)
+static int
+YYID (int yyi)
+#else
+static int
+YYID (yyi)
+    int yyi;
+#endif
+{
+  return yyi;
+}
+#endif
+
+#if ! defined yyoverflow || YYERROR_VERBOSE
+
+/* The parser invokes alloca or malloc; define the necessary symbols.  */
+
+# ifdef YYSTACK_USE_ALLOCA
+#  if YYSTACK_USE_ALLOCA
+#   ifdef __GNUC__
+#    define YYSTACK_ALLOC __builtin_alloca
+#   elif defined __BUILTIN_VA_ARG_INCR
+#    include <alloca.h> /* INFRINGES ON USER NAME SPACE */
+#   elif defined _AIX
+#    define YYSTACK_ALLOC __alloca
+#   elif defined _MSC_VER
+#    include <malloc.h> /* INFRINGES ON USER NAME SPACE */
+#    define alloca _alloca
+#   else
+#    define YYSTACK_ALLOC alloca
+#    if ! defined _ALLOCA_H && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \
+     || defined __cplusplus || defined _MSC_VER)
+#     include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
+#     ifndef _STDLIB_H
+#      define _STDLIB_H 1
+#     endif
+#    endif
+#   endif
+#  endif
+# endif
+
+# ifdef YYSTACK_ALLOC
+   /* Pacify GCC's `empty if-body' warning.  */
+#  define YYSTACK_FREE(Ptr) do { /* empty */; } while (YYID (0))
+#  ifndef YYSTACK_ALLOC_MAXIMUM
+    /* The OS might guarantee only one guard page at the bottom of the stack,
+       and a page size can be as small as 4096 bytes.  So we cannot safely
+       invoke alloca (N) if N exceeds 4096.  Use a slightly smaller number
+       to allow for a few compiler-allocated temporary stack slots.  */
+#   define YYSTACK_ALLOC_MAXIMUM 4032 /* reasonable circa 2006 */
+#  endif
+# else
+#  define YYSTACK_ALLOC YYMALLOC
+#  define YYSTACK_FREE YYFREE
+#  ifndef YYSTACK_ALLOC_MAXIMUM
+#   define YYSTACK_ALLOC_MAXIMUM YYSIZE_MAXIMUM
+#  endif
+#  if (defined __cplusplus && ! defined _STDLIB_H \
+       && ! ((defined YYMALLOC || defined malloc) \
+	     && (defined YYFREE || defined free)))
+#   include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
+#   ifndef _STDLIB_H
+#    define _STDLIB_H 1
+#   endif
+#  endif
+#  ifndef YYMALLOC
+#   define YYMALLOC malloc
+#   if ! defined malloc && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \
+     || defined __cplusplus || defined _MSC_VER)
+void *malloc (YYSIZE_T); /* INFRINGES ON USER NAME SPACE */
+#   endif
+#  endif
+#  ifndef YYFREE
+#   define YYFREE free
+#   if ! defined free && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \
+     || defined __cplusplus || defined _MSC_VER)
+void free (void *); /* INFRINGES ON USER NAME SPACE */
+#   endif
+#  endif
+# endif
+#endif /* ! defined yyoverflow || YYERROR_VERBOSE */
+
+
+#if (! defined yyoverflow \
+     && (! defined __cplusplus \
+	 || (defined YYSTYPE_IS_TRIVIAL && YYSTYPE_IS_TRIVIAL)))
+
+/* A type that is properly aligned for any stack member.  */
+union yyalloc
+{
+  yytype_int16 yyss_alloc;
+  YYSTYPE yyvs_alloc;
+};
+
+/* The size of the maximum gap between one aligned stack and the next.  */
+# define YYSTACK_GAP_MAXIMUM (sizeof (union yyalloc) - 1)
+
+/* The size of an array large to enough to hold all stacks, each with
+   N elements.  */
+# define YYSTACK_BYTES(N) \
+     ((N) * (sizeof (yytype_int16) + sizeof (YYSTYPE)) \
+      + YYSTACK_GAP_MAXIMUM)
+
+/* Copy COUNT objects from FROM to TO.  The source and destination do
+   not overlap.  */
+# ifndef YYCOPY
+#  if defined __GNUC__ && 1 < __GNUC__
+#   define YYCOPY(To, From, Count) \
+      __builtin_memcpy (To, From, (Count) * sizeof (*(From)))
+#  else
+#   define YYCOPY(To, From, Count)		\
+      do					\
+	{					\
+	  YYSIZE_T yyi;				\
+	  for (yyi = 0; yyi < (Count); yyi++)	\
+	    (To)[yyi] = (From)[yyi];		\
+	}					\
+      while (YYID (0))
+#  endif
+# endif
+
+/* Relocate STACK from its old location to the new one.  The
+   local variables YYSIZE and YYSTACKSIZE give the old and new number of
+   elements in the stack, and YYPTR gives the new location of the
+   stack.  Advance YYPTR to a properly aligned location for the next
+   stack.  */
+# define YYSTACK_RELOCATE(Stack_alloc, Stack)				\
+    do									\
+      {									\
+	YYSIZE_T yynewbytes;						\
+	YYCOPY (&yyptr->Stack_alloc, Stack, yysize);			\
+	Stack = &yyptr->Stack_alloc;					\
+	yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \
+	yyptr += yynewbytes / sizeof (*yyptr);				\
+      }									\
+    while (YYID (0))
+
+#endif
+
+/* YYFINAL -- State number of the termination state.  */
+#define YYFINAL  69
+/* YYLAST -- Last index in YYTABLE.  */
+#define YYLAST   1385
+
+/* YYNTOKENS -- Number of terminals.  */
+#define YYNTOKENS  94
+/* YYNNTS -- Number of nonterminals.  */
+#define YYNNTS  83
+/* YYNRULES -- Number of rules.  */
+#define YYNRULES  199
+/* YYNRULES -- Number of states.  */
+#define YYNSTATES  302
+
+/* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX.  */
+#define YYUNDEFTOK  2
+#define YYMAXUTOK   348
+
+#define YYTRANSLATE(YYX)						\
+  ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK)
+
+/* YYTRANSLATE[YYLEX] -- Bison symbol number corresponding to YYLEX.  */
+static const yytype_uint8 yytranslate[] =
+{
+       0,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     1,     2,     3,     4,
+       5,     6,     7,     8,     9,    10,    11,    12,    13,    14,
+      15,    16,    17,    18,    19,    20,    21,    22,    23,    24,
+      25,    26,    27,    28,    29,    30,    31,    32,    33,    34,
+      35,    36,    37,    38,    39,    40,    41,    42,    43,    44,
+      45,    46,    47,    48,    49,    50,    51,    52,    53,    54,
+      55,    56,    57,    58,    59,    60,    61,    62,    63,    64,
+      65,    66,    67,    68,    69,    70,    71,    72,    73,    74,
+      75,    76,    77,    78,    79,    80,    81,    82,    83,    84,
+      85,    86,    87,    88,    89,    90,    91,    92,    93
+};
+
+#if YYDEBUG
+/* YYPRHS[YYN] -- Index of the first RHS symbol of rule number YYN in
+   YYRHS.  */
+static const yytype_uint16 yyprhs[] =
+{
+       0,     0,     3,     5,     7,     9,    11,    13,    17,    19,
+      24,    26,    30,    33,    36,    38,    40,    42,    46,    49,
+      52,    55,    57,    60,    64,    67,    69,    71,    73,    75,
+      78,    81,    84,    86,    88,    90,    92,    96,   100,   102,
+     106,   110,   112,   114,   118,   122,   126,   130,   132,   136,
+     140,   142,   144,   146,   148,   152,   154,   158,   160,   164,
+     166,   172,   174,   178,   180,   182,   184,   186,   188,   190,
+     194,   196,   199,   202,   207,   210,   212,   214,   217,   221,
+     225,   228,   234,   238,   241,   245,   248,   249,   251,   253,
+     255,   257,   259,   263,   269,   276,   282,   284,   287,   292,
+     298,   303,   306,   308,   311,   313,   315,   317,   320,   322,
+     324,   327,   329,   331,   333,   335,   340,   342,   344,   346,
+     348,   350,   352,   354,   356,   358,   360,   362,   364,   366,
+     368,   370,   372,   374,   376,   378,   380,   381,   388,   389,
+     395,   397,   400,   404,   406,   410,   412,   417,   419,   421,
+     423,   425,   427,   429,   431,   433,   435,   438,   439,   440,
+     446,   448,   450,   451,   454,   455,   458,   461,   465,   467,
+     470,   472,   475,   481,   485,   487,   489,   494,   495,   502,
+     503,   512,   513,   521,   523,   525,   527,   528,   531,   535,
+     538,   541,   544,   548,   551,   553,   556,   558,   560,   561
+};
+
+/* YYRHS -- A `-1'-separated list of the rules' RHS.  */
+static const yytype_int16 yyrhs[] =
+{
+     173,     0,    -1,    43,    -1,    95,    -1,    46,    -1,    45,
+      -1,    47,    -1,    70,   122,    71,    -1,    96,    -1,    97,
+      72,    98,    73,    -1,    99,    -1,    97,    76,    48,    -1,
+      97,    51,    -1,    97,    52,    -1,   122,    -1,   100,    -1,
+     101,    -1,    97,    76,   101,    -1,   103,    71,    -1,   102,
+      71,    -1,   104,    39,    -1,   104,    -1,   104,   120,    -1,
+     103,    77,   120,    -1,   105,    70,    -1,   140,    -1,    43,
+      -1,    48,    -1,    97,    -1,    51,   106,    -1,    52,   106,
+      -1,   107,   106,    -1,    84,    -1,    82,    -1,    81,    -1,
+     106,    -1,   108,    85,   106,    -1,   108,    86,   106,    -1,
+     108,    -1,   109,    84,   108,    -1,   109,    82,   108,    -1,
+     109,    -1,   110,    -1,   111,    88,   110,    -1,   111,    89,
+     110,    -1,   111,    53,   110,    -1,   111,    54,   110,    -1,
+     111,    -1,   112,    55,   111,    -1,   112,    56,   111,    -1,
+     112,    -1,   113,    -1,   114,    -1,   115,    -1,   116,    57,
+     115,    -1,   116,    -1,   117,    59,   116,    -1,   117,    -1,
+     118,    58,   117,    -1,   118,    -1,   118,    93,   122,    78,
+     120,    -1,   119,    -1,   106,   121,   120,    -1,    79,    -1,
+      60,    -1,    61,    -1,    62,    -1,    69,    -1,   120,    -1,
+     122,    77,   120,    -1,   119,    -1,   125,    80,    -1,   133,
+      80,    -1,     7,   138,   139,    80,    -1,   126,    71,    -1,
+     128,    -1,   127,    -1,   128,   130,    -1,   127,    77,   130,
+      -1,   135,    43,    70,    -1,   137,    43,    -1,   137,    43,
+      72,   123,    73,    -1,   136,   131,   129,    -1,   131,   129,
+      -1,   136,   131,   132,    -1,   131,   132,    -1,    -1,    33,
+      -1,    34,    -1,    35,    -1,   137,    -1,   134,    -1,   133,
+      77,    43,    -1,   133,    77,    43,    72,    73,    -1,   133,
+      77,    43,    72,   123,    73,    -1,   133,    77,    43,    79,
+     148,    -1,   135,    -1,   135,    43,    -1,   135,    43,    72,
+      73,    -1,   135,    43,    72,   123,    73,    -1,   135,    43,
+      79,   148,    -1,     3,    43,    -1,   137,    -1,   136,   137,
+      -1,     9,    -1,     8,    -1,    37,    -1,     3,    37,    -1,
+      36,    -1,   139,    -1,   138,   139,    -1,     4,    -1,     5,
+      -1,     6,    -1,   140,    -1,   140,    72,   123,    73,    -1,
+      39,    -1,    11,    -1,    12,    -1,    10,    -1,    27,    -1,
+      28,    -1,    29,    -1,    21,    -1,    22,    -1,    23,    -1,
+      24,    -1,    25,    -1,    26,    -1,    30,    -1,    31,    -1,
+      32,    -1,    41,    -1,    42,    -1,   141,    -1,    44,    -1,
+      -1,    38,    43,    74,   142,   144,    75,    -1,    -1,    38,
+      74,   143,   144,    75,    -1,   145,    -1,   144,   145,    -1,
+     137,   146,    80,    -1,   147,    -1,   146,    77,   147,    -1,
+      43,    -1,    43,    72,   123,    73,    -1,   120,    -1,   124,
+      -1,   152,    -1,   151,    -1,   149,    -1,   161,    -1,   162,
+      -1,   165,    -1,   172,    -1,    74,    75,    -1,    -1,    -1,
+      74,   153,   160,   154,    75,    -1,   159,    -1,   151,    -1,
+      -1,   157,   159,    -1,    -1,   158,   151,    -1,    74,    75,
+      -1,    74,   160,    75,    -1,   150,    -1,   160,   150,    -1,
+      80,    -1,   122,    80,    -1,    18,    70,   122,    71,   163,
+      -1,   156,    16,   156,    -1,   156,    -1,   122,    -1,   135,
+      43,    79,   148,    -1,    -1,    40,    70,   166,   164,    71,
+     155,    -1,    -1,    15,   167,   156,    40,    70,   122,    71,
+      80,    -1,    -1,    17,    70,   168,   169,   171,    71,   155,
+      -1,   161,    -1,   149,    -1,   164,    -1,    -1,   170,    80,
+      -1,   170,    80,   122,    -1,    14,    80,    -1,    13,    80,
+      -1,    20,    80,    -1,    20,   122,    80,    -1,    19,    80,
+      -1,   174,    -1,   173,   174,    -1,   175,    -1,   124,    -1,
+      -1,   125,   176,   159,    -1
+};
+
+/* YYRLINE[YYN] -- source line where rule number YYN was defined.  */
+static const yytype_uint16 yyrline[] =
+{
+       0,   165,   165,   200,   203,   216,   221,   226,   232,   235,
+     314,   317,   418,   428,   441,   449,   549,   552,   560,   564,
+     571,   575,   582,   588,   597,   605,   660,   667,   677,   680,
+     690,   700,   721,   722,   723,   728,   729,   738,   750,   751,
+     759,   770,   774,   775,   785,   795,   805,   818,   819,   829,
+     842,   846,   850,   854,   855,   868,   869,   882,   883,   896,
+     897,   914,   915,   928,   929,   930,   931,   932,   936,   939,
+     950,   958,   985,   990,   997,  1035,  1038,  1045,  1053,  1074,
+    1095,  1106,  1135,  1140,  1150,  1155,  1165,  1168,  1171,  1174,
+    1180,  1187,  1190,  1212,  1230,  1254,  1277,  1281,  1299,  1307,
+    1339,  1359,  1448,  1457,  1480,  1483,  1489,  1497,  1505,  1513,
+    1523,  1530,  1533,  1536,  1542,  1545,  1560,  1564,  1568,  1572,
+    1581,  1586,  1591,  1596,  1601,  1606,  1611,  1616,  1621,  1626,
+    1632,  1638,  1644,  1649,  1654,  1659,  1672,  1672,  1686,  1686,
+    1695,  1698,  1713,  1749,  1753,  1759,  1767,  1783,  1787,  1791,
+    1792,  1798,  1799,  1800,  1801,  1802,  1806,  1807,  1807,  1807,
+    1817,  1818,  1822,  1822,  1823,  1823,  1828,  1831,  1841,  1844,
+    1850,  1851,  1855,  1863,  1867,  1877,  1882,  1899,  1899,  1904,
+    1904,  1911,  1911,  1919,  1922,  1928,  1931,  1937,  1941,  1948,
+    1955,  1962,  1969,  1980,  1989,  1993,  2000,  2003,  2009,  2009
+};
+#endif
+
+#if YYDEBUG || YYERROR_VERBOSE || YYTOKEN_TABLE
+/* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM.
+   First, the terminals, then, starting at YYNTOKENS, nonterminals.  */
+static const char *const yytname[] =
+{
+  "$end", "error", "$undefined", "INVARIANT", "HIGH_PRECISION",
+  "MEDIUM_PRECISION", "LOW_PRECISION", "PRECISION", "ATTRIBUTE",
+  "CONST_QUAL", "BOOL_TYPE", "FLOAT_TYPE", "INT_TYPE", "BREAK", "CONTINUE",
+  "DO", "ELSE", "FOR", "IF", "DISCARD", "RETURN", "BVEC2", "BVEC3",
+  "BVEC4", "IVEC2", "IVEC3", "IVEC4", "VEC2", "VEC3", "VEC4", "MATRIX2",
+  "MATRIX3", "MATRIX4", "IN_QUAL", "OUT_QUAL", "INOUT_QUAL", "UNIFORM",
+  "VARYING", "STRUCT", "VOID_TYPE", "WHILE", "SAMPLER2D", "SAMPLERCUBE",
+  "IDENTIFIER", "TYPE_NAME", "FLOATCONSTANT", "INTCONSTANT",
+  "BOOLCONSTANT", "FIELD_SELECTION", "LEFT_OP", "RIGHT_OP", "INC_OP",
+  "DEC_OP", "LE_OP", "GE_OP", "EQ_OP", "NE_OP", "AND_OP", "OR_OP",
+  "XOR_OP", "MUL_ASSIGN", "DIV_ASSIGN", "ADD_ASSIGN", "MOD_ASSIGN",
+  "LEFT_ASSIGN", "RIGHT_ASSIGN", "AND_ASSIGN", "XOR_ASSIGN", "OR_ASSIGN",
+  "SUB_ASSIGN", "LEFT_PAREN", "RIGHT_PAREN", "LEFT_BRACKET",
+  "RIGHT_BRACKET", "LEFT_BRACE", "RIGHT_BRACE", "DOT", "COMMA", "COLON",
+  "EQUAL", "SEMICOLON", "BANG", "DASH", "TILDE", "PLUS", "STAR", "SLASH",
+  "PERCENT", "LEFT_ANGLE", "RIGHT_ANGLE", "VERTICAL_BAR", "CARET",
+  "AMPERSAND", "QUESTION", "$accept", "variable_identifier",
+  "primary_expression", "postfix_expression", "integer_expression",
+  "function_call", "function_call_or_method", "function_call_generic",
+  "function_call_header_no_parameters",
+  "function_call_header_with_parameters", "function_call_header",
+  "function_identifier", "unary_expression", "unary_operator",
+  "multiplicative_expression", "additive_expression", "shift_expression",
+  "relational_expression", "equality_expression", "and_expression",
+  "exclusive_or_expression", "inclusive_or_expression",
+  "logical_and_expression", "logical_xor_expression",
+  "logical_or_expression", "conditional_expression",
+  "assignment_expression", "assignment_operator", "expression",
+  "constant_expression", "declaration", "function_prototype",
+  "function_declarator", "function_header_with_parameters",
+  "function_header", "parameter_declarator", "parameter_declaration",
+  "parameter_qualifier", "parameter_type_specifier",
+  "init_declarator_list", "single_declaration", "fully_specified_type",
+  "type_qualifier", "type_specifier", "precision_qualifier",
+  "type_specifier_no_prec", "type_specifier_nonarray", "struct_specifier",
+  "$@1", "$@2", "struct_declaration_list", "struct_declaration",
+  "struct_declarator_list", "struct_declarator", "initializer",
+  "declaration_statement", "statement", "simple_statement",
+  "compound_statement", "$@3", "$@4", "statement_no_new_scope",
+  "statement_with_scope", "$@5", "$@6", "compound_statement_no_new_scope",
+  "statement_list", "expression_statement", "selection_statement",
+  "selection_rest_statement", "condition", "iteration_statement", "$@7",
+  "$@8", "$@9", "for_init_statement", "conditionopt", "for_rest_statement",
+  "jump_statement", "translation_unit", "external_declaration",
+  "function_definition", "$@10", 0
+};
+#endif
+
+# ifdef YYPRINT
+/* YYTOKNUM[YYLEX-NUM] -- Internal token number corresponding to
+   token YYLEX-NUM.  */
+static const yytype_uint16 yytoknum[] =
+{
+       0,   256,   257,   258,   259,   260,   261,   262,   263,   264,
+     265,   266,   267,   268,   269,   270,   271,   272,   273,   274,
+     275,   276,   277,   278,   279,   280,   281,   282,   283,   284,
+     285,   286,   287,   288,   289,   290,   291,   292,   293,   294,
+     295,   296,   297,   298,   299,   300,   301,   302,   303,   304,
+     305,   306,   307,   308,   309,   310,   311,   312,   313,   314,
+     315,   316,   317,   318,   319,   320,   321,   322,   323,   324,
+     325,   326,   327,   328,   329,   330,   331,   332,   333,   334,
+     335,   336,   337,   338,   339,   340,   341,   342,   343,   344,
+     345,   346,   347,   348
+};
+# endif
+
+/* YYR1[YYN] -- Symbol number of symbol that rule YYN derives.  */
+static const yytype_uint8 yyr1[] =
+{
+       0,    94,    95,    96,    96,    96,    96,    96,    97,    97,
+      97,    97,    97,    97,    98,    99,   100,   100,   101,   101,
+     102,   102,   103,   103,   104,   105,   105,   105,   106,   106,
+     106,   106,   107,   107,   107,   108,   108,   108,   109,   109,
+     109,   110,   111,   111,   111,   111,   111,   112,   112,   112,
+     113,   114,   115,   116,   116,   117,   117,   118,   118,   119,
+     119,   120,   120,   121,   121,   121,   121,   121,   122,   122,
+     123,   124,   124,   124,   125,   126,   126,   127,   127,   128,
+     129,   129,   130,   130,   130,   130,   131,   131,   131,   131,
+     132,   133,   133,   133,   133,   133,   134,   134,   134,   134,
+     134,   134,   135,   135,   136,   136,   136,   136,   136,   137,
+     137,   138,   138,   138,   139,   139,   140,   140,   140,   140,
+     140,   140,   140,   140,   140,   140,   140,   140,   140,   140,
+     140,   140,   140,   140,   140,   140,   142,   141,   143,   141,
+     144,   144,   145,   146,   146,   147,   147,   148,   149,   150,
+     150,   151,   151,   151,   151,   151,   152,   153,   154,   152,
+     155,   155,   157,   156,   158,   156,   159,   159,   160,   160,
+     161,   161,   162,   163,   163,   164,   164,   166,   165,   167,
+     165,   168,   165,   169,   169,   170,   170,   171,   171,   172,
+     172,   172,   172,   172,   173,   173,   174,   174,   176,   175
+};
+
+/* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN.  */
+static const yytype_uint8 yyr2[] =
+{
+       0,     2,     1,     1,     1,     1,     1,     3,     1,     4,
+       1,     3,     2,     2,     1,     1,     1,     3,     2,     2,
+       2,     1,     2,     3,     2,     1,     1,     1,     1,     2,
+       2,     2,     1,     1,     1,     1,     3,     3,     1,     3,
+       3,     1,     1,     3,     3,     3,     3,     1,     3,     3,
+       1,     1,     1,     1,     3,     1,     3,     1,     3,     1,
+       5,     1,     3,     1,     1,     1,     1,     1,     1,     3,
+       1,     2,     2,     4,     2,     1,     1,     2,     3,     3,
+       2,     5,     3,     2,     3,     2,     0,     1,     1,     1,
+       1,     1,     3,     5,     6,     5,     1,     2,     4,     5,
+       4,     2,     1,     2,     1,     1,     1,     2,     1,     1,
+       2,     1,     1,     1,     1,     4,     1,     1,     1,     1,
+       1,     1,     1,     1,     1,     1,     1,     1,     1,     1,
+       1,     1,     1,     1,     1,     1,     0,     6,     0,     5,
+       1,     2,     3,     1,     3,     1,     4,     1,     1,     1,
+       1,     1,     1,     1,     1,     1,     2,     0,     0,     5,
+       1,     1,     0,     2,     0,     2,     2,     3,     1,     2,
+       1,     2,     5,     3,     1,     1,     4,     0,     6,     0,
+       8,     0,     7,     1,     1,     1,     0,     2,     3,     2,
+       2,     2,     3,     2,     1,     2,     1,     1,     0,     3
+};
+
+/* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state
+   STATE-NUM when YYTABLE doesn't specify something else to do.  Zero
+   means the default is an error.  */
+static const yytype_uint8 yydefact[] =
+{
+       0,     0,   111,   112,   113,     0,   105,   104,   119,   117,
+     118,   123,   124,   125,   126,   127,   128,   120,   121,   122,
+     129,   130,   131,   108,   106,     0,   116,   132,   133,   135,
+     197,   198,     0,    76,    86,     0,    91,    96,     0,   102,
+       0,   109,   114,   134,     0,   194,   196,   107,   101,     0,
+       0,   138,    71,     0,    74,    86,     0,    87,    88,    89,
+      77,     0,    86,     0,    72,    97,   103,   110,     0,     1,
+     195,     0,   136,     0,     0,   199,    78,    83,    85,    90,
+       0,    92,    79,     0,     0,     2,     5,     4,     6,    27,
+       0,     0,     0,    34,    33,    32,     3,     8,    28,    10,
+      15,    16,     0,     0,    21,     0,    35,     0,    38,    41,
+      42,    47,    50,    51,    52,    53,    55,    57,    59,    70,
+       0,    25,    73,     0,     0,     0,   140,     0,     0,   179,
+       0,     0,     0,     0,     0,   157,   166,   170,    35,    61,
+      68,     0,   148,     0,   114,   151,   168,   150,   149,     0,
+     152,   153,   154,   155,    80,    82,    84,     0,     0,    98,
+       0,   147,   100,    29,    30,     0,    12,    13,     0,     0,
+      19,    18,     0,    20,    22,    24,    31,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,   115,     0,   145,     0,   143,   139,   141,   190,   189,
+     164,   181,     0,   193,   191,     0,   177,   156,     0,    64,
+      65,    66,    67,    63,     0,     0,   171,   167,   169,     0,
+      93,     0,    95,    99,     7,     0,    14,    26,    11,    17,
+      23,    36,    37,    40,    39,    45,    46,    43,    44,    48,
+      49,    54,    56,    58,     0,   137,     0,     0,   142,     0,
+       0,     0,     0,     0,   192,     0,   158,    62,    69,     0,
+      94,     9,     0,     0,   144,     0,   163,   165,   184,   183,
+     186,   164,   175,     0,     0,     0,    81,    60,   146,     0,
+     185,     0,     0,   174,   172,     0,     0,   159,     0,   187,
+       0,   164,     0,   161,   178,   160,     0,   188,   182,   173,
+     176,   180
+};
+
+/* YYDEFGOTO[NTERM-NUM].  */
+static const yytype_int16 yydefgoto[] =
+{
+      -1,    96,    97,    98,   225,    99,   100,   101,   102,   103,
+     104,   105,   138,   107,   108,   109,   110,   111,   112,   113,
+     114,   115,   116,   117,   118,   139,   140,   214,   141,   120,
+     142,   143,    32,    33,    34,    77,    60,    61,    78,    35,
+      36,    37,    38,    39,    40,    41,   121,    43,   123,    73,
+     125,   126,   194,   195,   162,   145,   146,   147,   148,   208,
+     275,   294,   249,   250,   251,   295,   149,   150,   151,   284,
+     274,   152,   255,   200,   252,   270,   281,   282,   153,    44,
+      45,    46,    53
+};
+
+/* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing
+   STATE-NUM.  */
+#define YYPACT_NINF -260
+static const yytype_int16 yypact[] =
+{
+    1241,   -23,  -260,  -260,  -260,   152,  -260,  -260,  -260,  -260,
+    -260,  -260,  -260,  -260,  -260,  -260,  -260,  -260,  -260,  -260,
+    -260,  -260,  -260,  -260,  -260,   -32,  -260,  -260,  -260,  -260,
+    -260,   -18,   -35,    17,    82,    29,  -260,    26,  1282,  -260,
+    1341,  -260,    11,  -260,  1199,  -260,  -260,  -260,  -260,  1341,
+      28,  -260,  -260,    36,  -260,    62,    67,  -260,  -260,  -260,
+    -260,  1282,   126,    79,  -260,     7,  -260,  -260,   972,  -260,
+    -260,    40,  -260,  1282,   288,  -260,  -260,  -260,  -260,    87,
+    1282,   -13,  -260,   193,   972,    80,  -260,  -260,  -260,  -260,
+     972,   972,   972,  -260,  -260,  -260,  -260,  -260,    16,  -260,
+    -260,  -260,    81,   -40,  1036,    84,  -260,   972,    77,   -67,
+    -260,   -31,   111,  -260,  -260,  -260,   107,   115,   -29,  -260,
+     103,  -260,  -260,  1282,   138,  1103,  -260,   104,   105,  -260,
+     113,   116,   108,   844,   117,   118,  -260,  -260,   -34,  -260,
+    -260,    31,  -260,   -18,   -16,  -260,  -260,  -260,  -260,   370,
+    -260,  -260,  -260,  -260,   119,  -260,  -260,   908,   972,  -260,
+     121,  -260,  -260,  -260,  -260,     5,  -260,  -260,   972,  1306,
+    -260,  -260,   972,   120,  -260,  -260,  -260,   972,   972,   972,
+     972,   972,   972,   972,   972,   972,   972,   972,   972,   972,
+     972,  -260,  1144,   123,    44,  -260,  -260,  -260,  -260,  -260,
+     122,  -260,   972,  -260,  -260,    71,  -260,  -260,   452,  -260,
+    -260,  -260,  -260,  -260,   972,   972,  -260,  -260,  -260,   972,
+    -260,   124,  -260,  -260,  -260,   125,   129,  -260,   131,  -260,
+    -260,  -260,  -260,    77,    77,  -260,  -260,  -260,  -260,   -31,
+     -31,  -260,   107,   115,    91,  -260,   972,   138,  -260,   167,
+      36,   616,   698,    10,  -260,   780,   452,  -260,  -260,   137,
+    -260,  -260,   972,   139,  -260,   141,  -260,  -260,  -260,  -260,
+     780,   122,   129,   170,   155,   153,  -260,  -260,  -260,   972,
+    -260,   147,   158,   214,  -260,   154,   534,  -260,    30,   972,
+     534,   122,   972,  -260,  -260,  -260,   162,   129,  -260,  -260,
+    -260,  -260
+};
+
+/* YYPGOTO[NTERM-NUM].  */
+static const yytype_int16 yypgoto[] =
+{
+    -260,  -260,  -260,  -260,  -260,  -260,  -260,    74,  -260,  -260,
+    -260,  -260,   -44,  -260,    -9,  -260,   -55,    -8,  -260,  -260,
+    -260,    59,    60,    58,  -260,   -64,   -83,  -260,   -90,   -73,
+       6,     8,  -260,  -260,  -260,   169,   195,   191,   174,  -260,
+    -260,  -222,   -25,   -20,   252,   -15,     0,  -260,  -260,  -260,
+     135,  -120,  -260,    12,  -145,     9,  -142,  -235,  -260,  -260,
+    -260,   -30,  -259,  -260,  -260,   -50,    54,    13,  -260,  -260,
+      -6,  -260,  -260,  -260,  -260,  -260,  -260,  -260,  -260,  -260,
+     223,  -260,  -260
+};
+
+/* YYTABLE[YYPACT[STATE-NUM]].  What to do in state STATE-NUM.  If
+   positive, shift that token.  If negative, reduce the rule which
+   number is the opposite.  If zero, do what YYDEFACT says.
+   If YYTABLE_NINF, syntax error.  */
+#define YYTABLE_NINF -163
+static const yytype_int16 yytable[] =
+{
+      42,   161,   165,    75,   119,   197,    30,   218,    31,    62,
+     160,    50,   283,   222,    47,   179,   267,   180,    66,   119,
+      48,   174,   181,   182,   106,    67,   209,   210,   211,   189,
+      62,   171,   299,   273,    71,   212,    54,   172,    42,   106,
+      42,    79,    51,   205,    42,   213,   163,   164,   273,    42,
+      30,   293,    31,   124,   -25,   293,    68,   183,   184,   157,
+      79,    42,    52,   176,   190,    56,   158,   166,   167,    65,
+       6,     7,   197,    42,   144,   161,   224,    82,   226,    83,
+      42,   271,   215,    68,   221,    56,    84,   215,   168,   230,
+       6,     7,   169,   119,    55,    57,    58,    59,    23,    24,
+     244,   296,    72,   124,    47,   124,    63,   215,   215,    64,
+      74,   216,   253,   106,   218,    57,    58,    59,    23,    24,
+     122,   247,    81,    42,   248,    42,   235,   236,   237,   238,
+     154,   257,   258,   231,   232,   106,   106,   106,   106,   106,
+     106,   106,   106,   106,   106,   106,   259,   300,   215,   144,
+     -26,   254,   170,   -75,   175,   119,     2,     3,     4,    57,
+      58,    59,   177,   178,   187,   272,   185,   186,   215,   262,
+     233,   234,   124,   263,   188,   106,   191,   239,   240,   277,
+     272,   193,   119,   201,   198,   199,   202,   206,   203,   288,
+    -116,   219,    42,   207,   223,   246,  -162,   260,   261,   297,
+     266,   -27,   106,     8,     9,    10,   215,   265,   144,   161,
+     276,   279,   278,   285,    11,    12,    13,    14,    15,    16,
+      17,    18,    19,    20,    21,    22,   286,   289,   287,   290,
+     291,    25,    26,   292,    27,    28,    85,    29,    86,    87,
+      88,    89,   301,   229,    90,    91,   241,   243,   242,   155,
+      76,   144,   144,    80,   156,   144,   144,    49,   192,   264,
+     298,   268,   256,    92,   280,   269,   159,    70,     0,     0,
+     144,     0,     0,     0,    93,    94,     0,    95,     0,     0,
+       0,     0,     0,     0,     0,     0,   144,     0,     0,     0,
+     144,     1,     2,     3,     4,     5,     6,     7,     8,     9,
+      10,   127,   128,   129,     0,   130,   131,   132,   133,    11,
+      12,    13,    14,    15,    16,    17,    18,    19,    20,    21,
+      22,     0,     0,     0,    23,    24,    25,    26,   134,    27,
+      28,    85,    29,    86,    87,    88,    89,     0,     0,    90,
+      91,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,    92,     0,
+       0,     0,   135,   136,     0,     0,     0,     0,   137,    93,
+      94,     0,    95,     1,     2,     3,     4,     5,     6,     7,
+       8,     9,    10,   127,   128,   129,     0,   130,   131,   132,
+     133,    11,    12,    13,    14,    15,    16,    17,    18,    19,
+      20,    21,    22,     0,     0,     0,    23,    24,    25,    26,
+     134,    27,    28,    85,    29,    86,    87,    88,    89,     0,
+       0,    90,    91,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+      92,     0,     0,     0,   135,   217,     0,     0,     0,     0,
+     137,    93,    94,     0,    95,     1,     2,     3,     4,     5,
+       6,     7,     8,     9,    10,   127,   128,   129,     0,   130,
+     131,   132,   133,    11,    12,    13,    14,    15,    16,    17,
+      18,    19,    20,    21,    22,     0,     0,     0,    23,    24,
+      25,    26,   134,    27,    28,    85,    29,    86,    87,    88,
+      89,     0,     0,    90,    91,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,    92,     0,     0,     0,   135,     0,     0,     0,
+       0,     0,   137,    93,    94,     0,    95,     1,     2,     3,
+       4,     5,     6,     7,     8,     9,    10,   127,   128,   129,
+       0,   130,   131,   132,   133,    11,    12,    13,    14,    15,
+      16,    17,    18,    19,    20,    21,    22,     0,     0,     0,
+      23,    24,    25,    26,   134,    27,    28,    85,    29,    86,
+      87,    88,    89,     0,     0,    90,    91,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,    92,     0,     0,     0,    74,     0,
+       0,     0,     0,     0,   137,    93,    94,     0,    95,     1,
+       2,     3,     4,     5,     6,     7,     8,     9,    10,   127,
+     128,   129,     0,   130,   131,   132,   133,    11,    12,    13,
+      14,    15,    16,    17,    18,    19,    20,    21,    22,     0,
+       0,     0,    23,    24,    25,    26,   134,    27,    28,    85,
+      29,    86,    87,    88,    89,     0,     0,    90,    91,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,    92,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,   137,    93,    94,     0,
+      95,     1,     2,     3,     4,     5,     6,     7,     8,     9,
+      10,     0,     0,     0,     0,     0,     0,     0,     0,    11,
+      12,    13,    14,    15,    16,    17,    18,    19,    20,    21,
+      22,     0,     0,     0,    23,    24,    25,    26,     0,    27,
+      28,    85,    29,    86,    87,    88,    89,     0,     0,    90,
+      91,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,    92,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,   137,    93,
+      94,     0,    95,    56,     2,     3,     4,     0,     6,     7,
+       8,     9,    10,     0,     0,     0,     0,     0,     0,     0,
+       0,    11,    12,    13,    14,    15,    16,    17,    18,    19,
+      20,    21,    22,     0,     0,     0,    23,    24,    25,    26,
+       0,    27,    28,    85,    29,    86,    87,    88,    89,     0,
+       0,    90,    91,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+      92,     0,     0,     0,     8,     9,    10,     0,     0,     0,
+       0,    93,    94,     0,    95,    11,    12,    13,    14,    15,
+      16,    17,    18,    19,    20,    21,    22,     0,     0,     0,
+       0,     0,    25,    26,     0,    27,    28,    85,    29,    86,
+      87,    88,    89,     0,     0,    90,    91,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,    92,     0,     0,     0,     8,     9,
+      10,     0,     0,     0,   204,    93,    94,     0,    95,    11,
+      12,    13,    14,    15,    16,    17,    18,    19,    20,    21,
+      22,     0,     0,     0,     0,     0,    25,    26,     0,    27,
+      28,    85,    29,    86,    87,    88,    89,     0,     0,    90,
+      91,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,    92,     0,
+       0,   220,     8,     9,    10,     0,     0,     0,     0,    93,
+      94,     0,    95,    11,    12,    13,    14,    15,    16,    17,
+      18,    19,    20,    21,    22,     0,     0,     0,     0,     0,
+      25,    26,     0,    27,    28,    85,    29,    86,    87,    88,
+      89,     0,     0,    90,    91,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,    92,     0,     0,     0,     8,     9,    10,     0,
+       0,     0,     0,    93,    94,     0,    95,    11,    12,    13,
+      14,    15,    16,    17,    18,    19,    20,    21,    22,     0,
+       0,     0,     0,     0,    25,   173,     0,    27,    28,    85,
+      29,    86,    87,    88,    89,     0,     0,    90,    91,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,    92,     2,     3,     4,
+       0,     0,     0,     8,     9,    10,     0,    93,    94,     0,
+      95,     0,     0,     0,    11,    12,    13,    14,    15,    16,
+      17,    18,    19,    20,    21,    22,     0,     0,     0,     0,
+       0,    25,    26,     0,    27,    28,     0,    29,     2,     3,
+       4,     0,     0,     0,     8,     9,    10,     0,     0,     0,
+       0,     0,     0,     0,     0,    11,    12,    13,    14,    15,
+      16,    17,    18,    19,    20,    21,    22,     0,   196,     0,
+       0,     0,    25,    26,     0,    27,    28,     0,    29,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,    69,
+       0,     0,     1,     2,     3,     4,     5,     6,     7,     8,
+       9,    10,     0,     0,     0,     0,     0,     0,     0,   245,
+      11,    12,    13,    14,    15,    16,    17,    18,    19,    20,
+      21,    22,     0,     0,     0,    23,    24,    25,    26,     0,
+      27,    28,     0,    29,     1,     2,     3,     4,     5,     6,
+       7,     8,     9,    10,     0,     0,     0,     0,     0,     0,
+       0,     0,    11,    12,    13,    14,    15,    16,    17,    18,
+      19,    20,    21,    22,     0,     0,     0,    23,    24,    25,
+      26,     0,    27,    28,     0,    29,     2,     3,     4,     0,
+       0,     0,     8,     9,    10,     0,     0,     0,     0,     0,
+       0,     0,     0,    11,    12,    13,    14,    15,    16,    17,
+      18,    19,    20,    21,    22,     0,     8,     9,    10,     0,
+      25,    26,     0,    27,    28,     0,    29,    11,    12,    13,
+      14,    15,    16,    17,    18,    19,    20,    21,    22,     0,
+       0,     0,     0,     0,    25,    26,     0,    27,    28,   227,
+      29,     8,     9,    10,   228,     0,     0,     0,     0,     0,
+       0,     0,    11,    12,    13,    14,    15,    16,    17,    18,
+      19,    20,    21,    22,     0,     0,     0,     0,     0,    25,
+      26,     0,    27,    28,     0,    29
+};
+
+static const yytype_int16 yycheck[] =
+{
+       0,    84,    92,    53,    68,   125,     0,   149,     0,    34,
+      83,    43,   271,   158,    37,    82,   251,    84,    38,    83,
+      43,   104,    53,    54,    68,    40,    60,    61,    62,    58,
+      55,    71,   291,   255,    49,    69,    71,    77,    38,    83,
+      40,    61,    74,   133,    44,    79,    90,    91,   270,    49,
+      44,   286,    44,    73,    70,   290,    72,    88,    89,    72,
+      80,    61,    80,   107,    93,     3,    79,    51,    52,    43,
+       8,     9,   192,    73,    74,   158,    71,    70,   168,    72,
+      80,    71,    77,    72,   157,     3,    79,    77,    72,   172,
+       8,     9,    76,   157,    77,    33,    34,    35,    36,    37,
+     190,    71,    74,   123,    37,   125,    77,    77,    77,    80,
+      74,    80,   202,   157,   256,    33,    34,    35,    36,    37,
+      80,    77,    43,   123,    80,   125,   181,   182,   183,   184,
+      43,   214,   215,   177,   178,   179,   180,   181,   182,   183,
+     184,   185,   186,   187,   188,   189,   219,   292,    77,   149,
+      70,    80,    71,    71,    70,   219,     4,     5,     6,    33,
+      34,    35,    85,    86,    57,   255,    55,    56,    77,    78,
+     179,   180,   192,   246,    59,   219,    73,   185,   186,   262,
+     270,    43,   246,    70,    80,    80,    70,    70,    80,   279,
+      70,    72,   192,    75,    73,    72,    74,    73,    73,   289,
+     250,    70,   246,    10,    11,    12,    77,    40,   208,   292,
+      73,    70,    73,    43,    21,    22,    23,    24,    25,    26,
+      27,    28,    29,    30,    31,    32,    71,    80,    75,    71,
+      16,    38,    39,    79,    41,    42,    43,    44,    45,    46,
+      47,    48,    80,   169,    51,    52,   187,   189,   188,    80,
+      55,   251,   252,    62,    80,   255,   256,     5,   123,   247,
+     290,   252,   208,    70,   270,   252,    73,    44,    -1,    -1,
+     270,    -1,    -1,    -1,    81,    82,    -1,    84,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,   286,    -1,    -1,    -1,
+     290,     3,     4,     5,     6,     7,     8,     9,    10,    11,
+      12,    13,    14,    15,    -1,    17,    18,    19,    20,    21,
+      22,    23,    24,    25,    26,    27,    28,    29,    30,    31,
+      32,    -1,    -1,    -1,    36,    37,    38,    39,    40,    41,
+      42,    43,    44,    45,    46,    47,    48,    -1,    -1,    51,
+      52,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    70,    -1,
+      -1,    -1,    74,    75,    -1,    -1,    -1,    -1,    80,    81,
+      82,    -1,    84,     3,     4,     5,     6,     7,     8,     9,
+      10,    11,    12,    13,    14,    15,    -1,    17,    18,    19,
+      20,    21,    22,    23,    24,    25,    26,    27,    28,    29,
+      30,    31,    32,    -1,    -1,    -1,    36,    37,    38,    39,
+      40,    41,    42,    43,    44,    45,    46,    47,    48,    -1,
+      -1,    51,    52,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      70,    -1,    -1,    -1,    74,    75,    -1,    -1,    -1,    -1,
+      80,    81,    82,    -1,    84,     3,     4,     5,     6,     7,
+       8,     9,    10,    11,    12,    13,    14,    15,    -1,    17,
+      18,    19,    20,    21,    22,    23,    24,    25,    26,    27,
+      28,    29,    30,    31,    32,    -1,    -1,    -1,    36,    37,
+      38,    39,    40,    41,    42,    43,    44,    45,    46,    47,
+      48,    -1,    -1,    51,    52,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    70,    -1,    -1,    -1,    74,    -1,    -1,    -1,
+      -1,    -1,    80,    81,    82,    -1,    84,     3,     4,     5,
+       6,     7,     8,     9,    10,    11,    12,    13,    14,    15,
+      -1,    17,    18,    19,    20,    21,    22,    23,    24,    25,
+      26,    27,    28,    29,    30,    31,    32,    -1,    -1,    -1,
+      36,    37,    38,    39,    40,    41,    42,    43,    44,    45,
+      46,    47,    48,    -1,    -1,    51,    52,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    70,    -1,    -1,    -1,    74,    -1,
+      -1,    -1,    -1,    -1,    80,    81,    82,    -1,    84,     3,
+       4,     5,     6,     7,     8,     9,    10,    11,    12,    13,
+      14,    15,    -1,    17,    18,    19,    20,    21,    22,    23,
+      24,    25,    26,    27,    28,    29,    30,    31,    32,    -1,
+      -1,    -1,    36,    37,    38,    39,    40,    41,    42,    43,
+      44,    45,    46,    47,    48,    -1,    -1,    51,    52,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    70,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    80,    81,    82,    -1,
+      84,     3,     4,     5,     6,     7,     8,     9,    10,    11,
+      12,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    21,
+      22,    23,    24,    25,    26,    27,    28,    29,    30,    31,
+      32,    -1,    -1,    -1,    36,    37,    38,    39,    -1,    41,
+      42,    43,    44,    45,    46,    47,    48,    -1,    -1,    51,
+      52,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    70,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    80,    81,
+      82,    -1,    84,     3,     4,     5,     6,    -1,     8,     9,
+      10,    11,    12,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    21,    22,    23,    24,    25,    26,    27,    28,    29,
+      30,    31,    32,    -1,    -1,    -1,    36,    37,    38,    39,
+      -1,    41,    42,    43,    44,    45,    46,    47,    48,    -1,
+      -1,    51,    52,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      70,    -1,    -1,    -1,    10,    11,    12,    -1,    -1,    -1,
+      -1,    81,    82,    -1,    84,    21,    22,    23,    24,    25,
+      26,    27,    28,    29,    30,    31,    32,    -1,    -1,    -1,
+      -1,    -1,    38,    39,    -1,    41,    42,    43,    44,    45,
+      46,    47,    48,    -1,    -1,    51,    52,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    70,    -1,    -1,    -1,    10,    11,
+      12,    -1,    -1,    -1,    80,    81,    82,    -1,    84,    21,
+      22,    23,    24,    25,    26,    27,    28,    29,    30,    31,
+      32,    -1,    -1,    -1,    -1,    -1,    38,    39,    -1,    41,
+      42,    43,    44,    45,    46,    47,    48,    -1,    -1,    51,
+      52,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    70,    -1,
+      -1,    73,    10,    11,    12,    -1,    -1,    -1,    -1,    81,
+      82,    -1,    84,    21,    22,    23,    24,    25,    26,    27,
+      28,    29,    30,    31,    32,    -1,    -1,    -1,    -1,    -1,
+      38,    39,    -1,    41,    42,    43,    44,    45,    46,    47,
+      48,    -1,    -1,    51,    52,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    70,    -1,    -1,    -1,    10,    11,    12,    -1,
+      -1,    -1,    -1,    81,    82,    -1,    84,    21,    22,    23,
+      24,    25,    26,    27,    28,    29,    30,    31,    32,    -1,
+      -1,    -1,    -1,    -1,    38,    39,    -1,    41,    42,    43,
+      44,    45,    46,    47,    48,    -1,    -1,    51,    52,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    70,     4,     5,     6,
+      -1,    -1,    -1,    10,    11,    12,    -1,    81,    82,    -1,
+      84,    -1,    -1,    -1,    21,    22,    23,    24,    25,    26,
+      27,    28,    29,    30,    31,    32,    -1,    -1,    -1,    -1,
+      -1,    38,    39,    -1,    41,    42,    -1,    44,     4,     5,
+       6,    -1,    -1,    -1,    10,    11,    12,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    21,    22,    23,    24,    25,
+      26,    27,    28,    29,    30,    31,    32,    -1,    75,    -1,
+      -1,    -1,    38,    39,    -1,    41,    42,    -1,    44,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,     0,
+      -1,    -1,     3,     4,     5,     6,     7,     8,     9,    10,
+      11,    12,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    75,
+      21,    22,    23,    24,    25,    26,    27,    28,    29,    30,
+      31,    32,    -1,    -1,    -1,    36,    37,    38,    39,    -1,
+      41,    42,    -1,    44,     3,     4,     5,     6,     7,     8,
+       9,    10,    11,    12,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    21,    22,    23,    24,    25,    26,    27,    28,
+      29,    30,    31,    32,    -1,    -1,    -1,    36,    37,    38,
+      39,    -1,    41,    42,    -1,    44,     4,     5,     6,    -1,
+      -1,    -1,    10,    11,    12,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    21,    22,    23,    24,    25,    26,    27,
+      28,    29,    30,    31,    32,    -1,    10,    11,    12,    -1,
+      38,    39,    -1,    41,    42,    -1,    44,    21,    22,    23,
+      24,    25,    26,    27,    28,    29,    30,    31,    32,    -1,
+      -1,    -1,    -1,    -1,    38,    39,    -1,    41,    42,    43,
+      44,    10,    11,    12,    48,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    21,    22,    23,    24,    25,    26,    27,    28,
+      29,    30,    31,    32,    -1,    -1,    -1,    -1,    -1,    38,
+      39,    -1,    41,    42,    -1,    44
+};
+
+/* YYSTOS[STATE-NUM] -- The (internal number of the) accessing
+   symbol of state STATE-NUM.  */
+static const yytype_uint8 yystos[] =
+{
+       0,     3,     4,     5,     6,     7,     8,     9,    10,    11,
+      12,    21,    22,    23,    24,    25,    26,    27,    28,    29,
+      30,    31,    32,    36,    37,    38,    39,    41,    42,    44,
+     124,   125,   126,   127,   128,   133,   134,   135,   136,   137,
+     138,   139,   140,   141,   173,   174,   175,    37,    43,   138,
+      43,    74,    80,   176,    71,    77,     3,    33,    34,    35,
+     130,   131,   136,    77,    80,    43,   137,   139,    72,     0,
+     174,   139,    74,   143,    74,   159,   130,   129,   132,   137,
+     131,    43,    70,    72,    79,    43,    45,    46,    47,    48,
+      51,    52,    70,    81,    82,    84,    95,    96,    97,    99,
+     100,   101,   102,   103,   104,   105,   106,   107,   108,   109,
+     110,   111,   112,   113,   114,   115,   116,   117,   118,   119,
+     123,   140,    80,   142,   137,   144,   145,    13,    14,    15,
+      17,    18,    19,    20,    40,    74,    75,    80,   106,   119,
+     120,   122,   124,   125,   140,   149,   150,   151,   152,   160,
+     161,   162,   165,   172,    43,   129,   132,    72,    79,    73,
+     123,   120,   148,   106,   106,   122,    51,    52,    72,    76,
+      71,    71,    77,    39,   120,    70,   106,    85,    86,    82,
+      84,    53,    54,    88,    89,    55,    56,    57,    59,    58,
+      93,    73,   144,    43,   146,   147,    75,   145,    80,    80,
+     167,    70,    70,    80,    80,   122,    70,    75,   153,    60,
+      61,    62,    69,    79,   121,    77,    80,    75,   150,    72,
+      73,   123,   148,    73,    71,    98,   122,    43,    48,   101,
+     120,   106,   106,   108,   108,   110,   110,   110,   110,   111,
+     111,   115,   116,   117,   122,    75,    72,    77,    80,   156,
+     157,   158,   168,   122,    80,   166,   160,   120,   120,   123,
+      73,    73,    78,   123,   147,    40,   159,   151,   149,   161,
+     169,    71,   122,   135,   164,   154,    73,   120,    73,    70,
+     164,   170,   171,   156,   163,    43,    71,    75,   122,    80,
+      71,    16,    79,   151,   155,   159,    71,   122,   155,   156,
+     148,    80
+};
+
+#define yyerrok		(yyerrstatus = 0)
+#define yyclearin	(yychar = YYEMPTY)
+#define YYEMPTY		(-2)
+#define YYEOF		0
+
+#define YYACCEPT	goto yyacceptlab
+#define YYABORT		goto yyabortlab
+#define YYERROR		goto yyerrorlab
+
+
+/* Like YYERROR except do call yyerror.  This remains here temporarily
+   to ease the transition to the new meaning of YYERROR, for GCC.
+   Once GCC version 2 has supplanted version 1, this can go.  However,
+   YYFAIL appears to be in use.  Nevertheless, it is formally deprecated
+   in Bison 2.4.2's NEWS entry, where a plan to phase it out is
+   discussed.  */
+
+#define YYFAIL		goto yyerrlab
+#if defined YYFAIL
+  /* This is here to suppress warnings from the GCC cpp's
+     -Wunused-macros.  Normally we don't worry about that warning, but
+     some users do, and we want to make it easy for users to remove
+     YYFAIL uses, which will produce warnings from Bison 2.5.  */
+#endif
+
+#define YYRECOVERING()  (!!yyerrstatus)
+
+#define YYBACKUP(Token, Value)					\
+do								\
+  if (yychar == YYEMPTY && yylen == 1)				\
+    {								\
+      yychar = (Token);						\
+      yylval = (Value);						\
+      yytoken = YYTRANSLATE (yychar);				\
+      YYPOPSTACK (1);						\
+      goto yybackup;						\
+    }								\
+  else								\
+    {								\
+      yyerror (context, YY_("syntax error: cannot back up")); \
+      YYERROR;							\
+    }								\
+while (YYID (0))
+
+
+#define YYTERROR	1
+#define YYERRCODE	256
+
+
+/* YYLLOC_DEFAULT -- Set CURRENT to span from RHS[1] to RHS[N].
+   If N is 0, then set CURRENT to the empty location which ends
+   the previous symbol: RHS[0] (always defined).  */
+
+#define YYRHSLOC(Rhs, K) ((Rhs)[K])
+#ifndef YYLLOC_DEFAULT
+# define YYLLOC_DEFAULT(Current, Rhs, N)				\
+    do									\
+      if (YYID (N))                                                    \
+	{								\
+	  (Current).first_line   = YYRHSLOC (Rhs, 1).first_line;	\
+	  (Current).first_column = YYRHSLOC (Rhs, 1).first_column;	\
+	  (Current).last_line    = YYRHSLOC (Rhs, N).last_line;		\
+	  (Current).last_column  = YYRHSLOC (Rhs, N).last_column;	\
+	}								\
+      else								\
+	{								\
+	  (Current).first_line   = (Current).last_line   =		\
+	    YYRHSLOC (Rhs, 0).last_line;				\
+	  (Current).first_column = (Current).last_column =		\
+	    YYRHSLOC (Rhs, 0).last_column;				\
+	}								\
+    while (YYID (0))
+#endif
+
+
+/* YY_LOCATION_PRINT -- Print the location on the stream.
+   This macro was not mandated originally: define only if we know
+   we won't break user code: when these are the locations we know.  */
+
+#ifndef YY_LOCATION_PRINT
+# if defined YYLTYPE_IS_TRIVIAL && YYLTYPE_IS_TRIVIAL
+#  define YY_LOCATION_PRINT(File, Loc)			\
+     fprintf (File, "%d.%d-%d.%d",			\
+	      (Loc).first_line, (Loc).first_column,	\
+	      (Loc).last_line,  (Loc).last_column)
+# else
+#  define YY_LOCATION_PRINT(File, Loc) ((void) 0)
+# endif
+#endif
+
+
+/* YYLEX -- calling `yylex' with the right arguments.  */
+
+#ifdef YYLEX_PARAM
+# define YYLEX yylex (&yylval, YYLEX_PARAM)
+#else
+# define YYLEX yylex (&yylval)
+#endif
+
+/* Enable debugging if requested.  */
+#if YYDEBUG
+
+# ifndef YYFPRINTF
+#  include <stdio.h> /* INFRINGES ON USER NAME SPACE */
+#  define YYFPRINTF fprintf
+# endif
+
+# define YYDPRINTF(Args)			\
+do {						\
+  if (yydebug)					\
+    YYFPRINTF Args;				\
+} while (YYID (0))
+
+# define YY_SYMBOL_PRINT(Title, Type, Value, Location)			  \
+do {									  \
+  if (yydebug)								  \
+    {									  \
+      YYFPRINTF (stderr, "%s ", Title);					  \
+      yy_symbol_print (stderr,						  \
+		  Type, Value, context); \
+      YYFPRINTF (stderr, "\n");						  \
+    }									  \
+} while (YYID (0))
+
+
+/*--------------------------------.
+| Print this symbol on YYOUTPUT.  |
+`--------------------------------*/
+
+/*ARGSUSED*/
+#if (defined __STDC__ || defined __C99__FUNC__ \
+     || defined __cplusplus || defined _MSC_VER)
+static void
+yy_symbol_value_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep, TParseContext* context)
+#else
+static void
+yy_symbol_value_print (yyoutput, yytype, yyvaluep, context)
+    FILE *yyoutput;
+    int yytype;
+    YYSTYPE const * const yyvaluep;
+    TParseContext* context;
+#endif
+{
+  if (!yyvaluep)
+    return;
+  YYUSE (context);
+# ifdef YYPRINT
+  if (yytype < YYNTOKENS)
+    YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep);
+# else
+  YYUSE (yyoutput);
+# endif
+  switch (yytype)
+    {
+      default:
+	break;
+    }
+}
+
+
+/*--------------------------------.
+| Print this symbol on YYOUTPUT.  |
+`--------------------------------*/
+
+#if (defined __STDC__ || defined __C99__FUNC__ \
+     || defined __cplusplus || defined _MSC_VER)
+static void
+yy_symbol_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep, TParseContext* context)
+#else
+static void
+yy_symbol_print (yyoutput, yytype, yyvaluep, context)
+    FILE *yyoutput;
+    int yytype;
+    YYSTYPE const * const yyvaluep;
+    TParseContext* context;
+#endif
+{
+  if (yytype < YYNTOKENS)
+    YYFPRINTF (yyoutput, "token %s (", yytname[yytype]);
+  else
+    YYFPRINTF (yyoutput, "nterm %s (", yytname[yytype]);
+
+  yy_symbol_value_print (yyoutput, yytype, yyvaluep, context);
+  YYFPRINTF (yyoutput, ")");
+}
+
+/*------------------------------------------------------------------.
+| yy_stack_print -- Print the state stack from its BOTTOM up to its |
+| TOP (included).                                                   |
+`------------------------------------------------------------------*/
+
+#if (defined __STDC__ || defined __C99__FUNC__ \
+     || defined __cplusplus || defined _MSC_VER)
+static void
+yy_stack_print (yytype_int16 *yybottom, yytype_int16 *yytop)
+#else
+static void
+yy_stack_print (yybottom, yytop)
+    yytype_int16 *yybottom;
+    yytype_int16 *yytop;
+#endif
+{
+  YYFPRINTF (stderr, "Stack now");
+  for (; yybottom <= yytop; yybottom++)
+    {
+      int yybot = *yybottom;
+      YYFPRINTF (stderr, " %d", yybot);
+    }
+  YYFPRINTF (stderr, "\n");
+}
+
+# define YY_STACK_PRINT(Bottom, Top)				\
+do {								\
+  if (yydebug)							\
+    yy_stack_print ((Bottom), (Top));				\
+} while (YYID (0))
+
+
+/*------------------------------------------------.
+| Report that the YYRULE is going to be reduced.  |
+`------------------------------------------------*/
+
+#if (defined __STDC__ || defined __C99__FUNC__ \
+     || defined __cplusplus || defined _MSC_VER)
+static void
+yy_reduce_print (YYSTYPE *yyvsp, int yyrule, TParseContext* context)
+#else
+static void
+yy_reduce_print (yyvsp, yyrule, context)
+    YYSTYPE *yyvsp;
+    int yyrule;
+    TParseContext* context;
+#endif
+{
+  int yynrhs = yyr2[yyrule];
+  int yyi;
+  unsigned long int yylno = yyrline[yyrule];
+  YYFPRINTF (stderr, "Reducing stack by rule %d (line %lu):\n",
+	     yyrule - 1, yylno);
+  /* The symbols being reduced.  */
+  for (yyi = 0; yyi < yynrhs; yyi++)
+    {
+      YYFPRINTF (stderr, "   $%d = ", yyi + 1);
+      yy_symbol_print (stderr, yyrhs[yyprhs[yyrule] + yyi],
+		       &(yyvsp[(yyi + 1) - (yynrhs)])
+		       		       , context);
+      YYFPRINTF (stderr, "\n");
+    }
+}
+
+# define YY_REDUCE_PRINT(Rule)		\
+do {					\
+  if (yydebug)				\
+    yy_reduce_print (yyvsp, Rule, context); \
+} while (YYID (0))
+
+/* Nonzero means print parse trace.  It is left uninitialized so that
+   multiple parsers can coexist.  */
+int yydebug;
+#else /* !YYDEBUG */
+# define YYDPRINTF(Args)
+# define YY_SYMBOL_PRINT(Title, Type, Value, Location)
+# define YY_STACK_PRINT(Bottom, Top)
+# define YY_REDUCE_PRINT(Rule)
+#endif /* !YYDEBUG */
+
+
+/* YYINITDEPTH -- initial size of the parser's stacks.  */
+#ifndef	YYINITDEPTH
+# define YYINITDEPTH 200
+#endif
+
+/* YYMAXDEPTH -- maximum size the stacks can grow to (effective only
+   if the built-in stack extension method is used).
+
+   Do not make this value too large; the results are undefined if
+   YYSTACK_ALLOC_MAXIMUM < YYSTACK_BYTES (YYMAXDEPTH)
+   evaluated with infinite-precision integer arithmetic.  */
+
+#ifndef YYMAXDEPTH
+# define YYMAXDEPTH 10000
+#endif
+
+
+
+#if YYERROR_VERBOSE
+
+# ifndef yystrlen
+#  if defined __GLIBC__ && defined _STRING_H
+#   define yystrlen strlen
+#  else
+/* Return the length of YYSTR.  */
+#if (defined __STDC__ || defined __C99__FUNC__ \
+     || defined __cplusplus || defined _MSC_VER)
+static YYSIZE_T
+yystrlen (const char *yystr)
+#else
+static YYSIZE_T
+yystrlen (yystr)
+    const char *yystr;
+#endif
+{
+  YYSIZE_T yylen;
+  for (yylen = 0; yystr[yylen]; yylen++)
+    continue;
+  return yylen;
+}
+#  endif
+# endif
+
+# ifndef yystpcpy
+#  if defined __GLIBC__ && defined _STRING_H && defined _GNU_SOURCE
+#   define yystpcpy stpcpy
+#  else
+/* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in
+   YYDEST.  */
+#if (defined __STDC__ || defined __C99__FUNC__ \
+     || defined __cplusplus || defined _MSC_VER)
+static char *
+yystpcpy (char *yydest, const char *yysrc)
+#else
+static char *
+yystpcpy (yydest, yysrc)
+    char *yydest;
+    const char *yysrc;
+#endif
+{
+  char *yyd = yydest;
+  const char *yys = yysrc;
+
+  while ((*yyd++ = *yys++) != '\0')
+    continue;
+
+  return yyd - 1;
+}
+#  endif
+# endif
+
+# ifndef yytnamerr
+/* Copy to YYRES the contents of YYSTR after stripping away unnecessary
+   quotes and backslashes, so that it's suitable for yyerror.  The
+   heuristic is that double-quoting is unnecessary unless the string
+   contains an apostrophe, a comma, or backslash (other than
+   backslash-backslash).  YYSTR is taken from yytname.  If YYRES is
+   null, do not copy; instead, return the length of what the result
+   would have been.  */
+static YYSIZE_T
+yytnamerr (char *yyres, const char *yystr)
+{
+  if (*yystr == '"')
+    {
+      YYSIZE_T yyn = 0;
+      char const *yyp = yystr;
+
+      for (;;)
+	switch (*++yyp)
+	  {
+	  case '\'':
+	  case ',':
+	    goto do_not_strip_quotes;
+
+	  case '\\':
+	    if (*++yyp != '\\')
+	      goto do_not_strip_quotes;
+	    /* Fall through.  */
+	  default:
+	    if (yyres)
+	      yyres[yyn] = *yyp;
+	    yyn++;
+	    break;
+
+	  case '"':
+	    if (yyres)
+	      yyres[yyn] = '\0';
+	    return yyn;
+	  }
+    do_not_strip_quotes: ;
+    }
+
+  if (! yyres)
+    return yystrlen (yystr);
+
+  return yystpcpy (yyres, yystr) - yyres;
+}
+# endif
+
+/* Copy into YYRESULT an error message about the unexpected token
+   YYCHAR while in state YYSTATE.  Return the number of bytes copied,
+   including the terminating null byte.  If YYRESULT is null, do not
+   copy anything; just return the number of bytes that would be
+   copied.  As a special case, return 0 if an ordinary "syntax error"
+   message will do.  Return YYSIZE_MAXIMUM if overflow occurs during
+   size calculation.  */
+static YYSIZE_T
+yysyntax_error (char *yyresult, int yystate, int yychar)
+{
+  int yyn = yypact[yystate];
+
+  if (! (YYPACT_NINF < yyn && yyn <= YYLAST))
+    return 0;
+  else
+    {
+      int yytype = YYTRANSLATE (yychar);
+      YYSIZE_T yysize0 = yytnamerr (0, yytname[yytype]);
+      YYSIZE_T yysize = yysize0;
+      YYSIZE_T yysize1;
+      int yysize_overflow = 0;
+      enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 };
+      char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM];
+      int yyx;
+
+# if 0
+      /* This is so xgettext sees the translatable formats that are
+	 constructed on the fly.  */
+      YY_("syntax error, unexpected %s");
+      YY_("syntax error, unexpected %s, expecting %s");
+      YY_("syntax error, unexpected %s, expecting %s or %s");
+      YY_("syntax error, unexpected %s, expecting %s or %s or %s");
+      YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s");
+# endif
+      char *yyfmt;
+      char const *yyf;
+      static char const yyunexpected[] = "syntax error, unexpected %s";
+      static char const yyexpecting[] = ", expecting %s";
+      static char const yyor[] = " or %s";
+      char yyformat[sizeof yyunexpected
+		    + sizeof yyexpecting - 1
+		    + ((YYERROR_VERBOSE_ARGS_MAXIMUM - 2)
+		       * (sizeof yyor - 1))];
+      char const *yyprefix = yyexpecting;
+
+      /* Start YYX at -YYN if negative to avoid negative indexes in
+	 YYCHECK.  */
+      int yyxbegin = yyn < 0 ? -yyn : 0;
+
+      /* Stay within bounds of both yycheck and yytname.  */
+      int yychecklim = YYLAST - yyn + 1;
+      int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS;
+      int yycount = 1;
+
+      yyarg[0] = yytname[yytype];
+      yyfmt = yystpcpy (yyformat, yyunexpected);
+
+      for (yyx = yyxbegin; yyx < yyxend; ++yyx)
+	if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR)
+	  {
+	    if (yycount == YYERROR_VERBOSE_ARGS_MAXIMUM)
+	      {
+		yycount = 1;
+		yysize = yysize0;
+		yyformat[sizeof yyunexpected - 1] = '\0';
+		break;
+	      }
+	    yyarg[yycount++] = yytname[yyx];
+	    yysize1 = yysize + yytnamerr (0, yytname[yyx]);
+	    yysize_overflow |= (yysize1 < yysize);
+	    yysize = yysize1;
+	    yyfmt = yystpcpy (yyfmt, yyprefix);
+	    yyprefix = yyor;
+	  }
+
+      yyf = YY_(yyformat);
+      yysize1 = yysize + yystrlen (yyf);
+      yysize_overflow |= (yysize1 < yysize);
+      yysize = yysize1;
+
+      if (yysize_overflow)
+	return YYSIZE_MAXIMUM;
+
+      if (yyresult)
+	{
+	  /* Avoid sprintf, as that infringes on the user's name space.
+	     Don't have undefined behavior even if the translation
+	     produced a string with the wrong number of "%s"s.  */
+	  char *yyp = yyresult;
+	  int yyi = 0;
+	  while ((*yyp = *yyf) != '\0')
+	    {
+	      if (*yyp == '%' && yyf[1] == 's' && yyi < yycount)
+		{
+		  yyp += yytnamerr (yyp, yyarg[yyi++]);
+		  yyf += 2;
+		}
+	      else
+		{
+		  yyp++;
+		  yyf++;
+		}
+	    }
+	}
+      return yysize;
+    }
+}
+#endif /* YYERROR_VERBOSE */
+
+
+/*-----------------------------------------------.
+| Release the memory associated to this symbol.  |
+`-----------------------------------------------*/
+
+/*ARGSUSED*/
+#if (defined __STDC__ || defined __C99__FUNC__ \
+     || defined __cplusplus || defined _MSC_VER)
+static void
+yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep, TParseContext* context)
+#else
+static void
+yydestruct (yymsg, yytype, yyvaluep, context)
+    const char *yymsg;
+    int yytype;
+    YYSTYPE *yyvaluep;
+    TParseContext* context;
+#endif
+{
+  YYUSE (yyvaluep);
+  YYUSE (context);
+
+  if (!yymsg)
+    yymsg = "Deleting";
+  YY_SYMBOL_PRINT (yymsg, yytype, yyvaluep, yylocationp);
+
+  switch (yytype)
+    {
+
+      default:
+	break;
+    }
+}
+
+/* Prevent warnings from -Wmissing-prototypes.  */
+#ifdef YYPARSE_PARAM
+#if defined __STDC__ || defined __cplusplus
+int yyparse (void *YYPARSE_PARAM);
+#else
+int yyparse ();
+#endif
+#else /* ! YYPARSE_PARAM */
+#if defined __STDC__ || defined __cplusplus
+int yyparse (TParseContext* context);
+#else
+int yyparse ();
+#endif
+#endif /* ! YYPARSE_PARAM */
+
+
+
+
+
+/*-------------------------.
+| yyparse or yypush_parse.  |
+`-------------------------*/
+
+#ifdef YYPARSE_PARAM
+#if (defined __STDC__ || defined __C99__FUNC__ \
+     || defined __cplusplus || defined _MSC_VER)
+int
+yyparse (void *YYPARSE_PARAM)
+#else
+int
+yyparse (YYPARSE_PARAM)
+    void *YYPARSE_PARAM;
+#endif
+#else /* ! YYPARSE_PARAM */
+#if (defined __STDC__ || defined __C99__FUNC__ \
+     || defined __cplusplus || defined _MSC_VER)
+int
+yyparse (TParseContext* context)
+#else
+int
+yyparse (context)
+    TParseContext* context;
+#endif
+#endif
+{
+/* The lookahead symbol.  */
+int yychar;
+
+/* The semantic value of the lookahead symbol.  */
+YYSTYPE yylval;
+
+    /* Number of syntax errors so far.  */
+    int yynerrs;
+
+    int yystate;
+    /* Number of tokens to shift before error messages enabled.  */
+    int yyerrstatus;
+
+    /* The stacks and their tools:
+       `yyss': related to states.
+       `yyvs': related to semantic values.
+
+       Refer to the stacks thru separate pointers, to allow yyoverflow
+       to reallocate them elsewhere.  */
+
+    /* The state stack.  */
+    yytype_int16 yyssa[YYINITDEPTH];
+    yytype_int16 *yyss;
+    yytype_int16 *yyssp;
+
+    /* The semantic value stack.  */
+    YYSTYPE yyvsa[YYINITDEPTH];
+    YYSTYPE *yyvs;
+    YYSTYPE *yyvsp;
+
+    YYSIZE_T yystacksize;
+
+  int yyn;
+  int yyresult;
+  /* Lookahead token as an internal (translated) token number.  */
+  int yytoken;
+  /* The variables used to return semantic value and location from the
+     action routines.  */
+  YYSTYPE yyval;
+
+#if YYERROR_VERBOSE
+  /* Buffer for error messages, and its allocated size.  */
+  char yymsgbuf[128];
+  char *yymsg = yymsgbuf;
+  YYSIZE_T yymsg_alloc = sizeof yymsgbuf;
+#endif
+
+#define YYPOPSTACK(N)   (yyvsp -= (N), yyssp -= (N))
+
+  /* The number of symbols on the RHS of the reduced rule.
+     Keep to zero when no symbol should be popped.  */
+  int yylen = 0;
+
+  yytoken = 0;
+  yyss = yyssa;
+  yyvs = yyvsa;
+  yystacksize = YYINITDEPTH;
+
+  YYDPRINTF ((stderr, "Starting parse\n"));
+
+  yystate = 0;
+  yyerrstatus = 0;
+  yynerrs = 0;
+  yychar = YYEMPTY; /* Cause a token to be read.  */
+
+  /* Initialize stack pointers.
+     Waste one element of value and location stack
+     so that they stay on the same level as the state stack.
+     The wasted elements are never initialized.  */
+  yyssp = yyss;
+  yyvsp = yyvs;
+
+  goto yysetstate;
+
+/*------------------------------------------------------------.
+| yynewstate -- Push a new state, which is found in yystate.  |
+`------------------------------------------------------------*/
+ yynewstate:
+  /* In all cases, when you get here, the value and location stacks
+     have just been pushed.  So pushing a state here evens the stacks.  */
+  yyssp++;
+
+ yysetstate:
+  *yyssp = yystate;
+
+  if (yyss + yystacksize - 1 <= yyssp)
+    {
+      /* Get the current used size of the three stacks, in elements.  */
+      YYSIZE_T yysize = yyssp - yyss + 1;
+
+#ifdef yyoverflow
+      {
+	/* Give user a chance to reallocate the stack.  Use copies of
+	   these so that the &'s don't force the real ones into
+	   memory.  */
+	YYSTYPE *yyvs1 = yyvs;
+	yytype_int16 *yyss1 = yyss;
+
+	/* Each stack pointer address is followed by the size of the
+	   data in use in that stack, in bytes.  This used to be a
+	   conditional around just the two extra args, but that might
+	   be undefined if yyoverflow is a macro.  */
+	yyoverflow (YY_("memory exhausted"),
+		    &yyss1, yysize * sizeof (*yyssp),
+		    &yyvs1, yysize * sizeof (*yyvsp),
+		    &yystacksize);
+
+	yyss = yyss1;
+	yyvs = yyvs1;
+      }
+#else /* no yyoverflow */
+# ifndef YYSTACK_RELOCATE
+      goto yyexhaustedlab;
+# else
+      /* Extend the stack our own way.  */
+      if (YYMAXDEPTH <= yystacksize)
+	goto yyexhaustedlab;
+      yystacksize *= 2;
+      if (YYMAXDEPTH < yystacksize)
+	yystacksize = YYMAXDEPTH;
+
+      {
+	yytype_int16 *yyss1 = yyss;
+	union yyalloc *yyptr =
+	  (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize));
+	if (! yyptr)
+	  goto yyexhaustedlab;
+	YYSTACK_RELOCATE (yyss_alloc, yyss);
+	YYSTACK_RELOCATE (yyvs_alloc, yyvs);
+#  undef YYSTACK_RELOCATE
+	if (yyss1 != yyssa)
+	  YYSTACK_FREE (yyss1);
+      }
+# endif
+#endif /* no yyoverflow */
+
+      yyssp = yyss + yysize - 1;
+      yyvsp = yyvs + yysize - 1;
+
+      YYDPRINTF ((stderr, "Stack size increased to %lu\n",
+		  (unsigned long int) yystacksize));
+
+      if (yyss + yystacksize - 1 <= yyssp)
+	YYABORT;
+    }
+
+  YYDPRINTF ((stderr, "Entering state %d\n", yystate));
+
+  if (yystate == YYFINAL)
+    YYACCEPT;
+
+  goto yybackup;
+
+/*-----------.
+| yybackup.  |
+`-----------*/
+yybackup:
+
+  /* Do appropriate processing given the current state.  Read a
+     lookahead token if we need one and don't already have one.  */
+
+  /* First try to decide what to do without reference to lookahead token.  */
+  yyn = yypact[yystate];
+  if (yyn == YYPACT_NINF)
+    goto yydefault;
+
+  /* Not known => get a lookahead token if don't already have one.  */
+
+  /* YYCHAR is either YYEMPTY or YYEOF or a valid lookahead symbol.  */
+  if (yychar == YYEMPTY)
+    {
+      YYDPRINTF ((stderr, "Reading a token: "));
+      yychar = YYLEX;
+    }
+
+  if (yychar <= YYEOF)
+    {
+      yychar = yytoken = YYEOF;
+      YYDPRINTF ((stderr, "Now at end of input.\n"));
+    }
+  else
+    {
+      yytoken = YYTRANSLATE (yychar);
+      YY_SYMBOL_PRINT ("Next token is", yytoken, &yylval, &yylloc);
+    }
+
+  /* If the proper action on seeing token YYTOKEN is to reduce or to
+     detect an error, take that action.  */
+  yyn += yytoken;
+  if (yyn < 0 || YYLAST < yyn || yycheck[yyn] != yytoken)
+    goto yydefault;
+  yyn = yytable[yyn];
+  if (yyn <= 0)
+    {
+      if (yyn == 0 || yyn == YYTABLE_NINF)
+	goto yyerrlab;
+      yyn = -yyn;
+      goto yyreduce;
+    }
+
+  /* Count tokens shifted since error; after three, turn off error
+     status.  */
+  if (yyerrstatus)
+    yyerrstatus--;
+
+  /* Shift the lookahead token.  */
+  YY_SYMBOL_PRINT ("Shifting", yytoken, &yylval, &yylloc);
+
+  /* Discard the shifted token.  */
+  yychar = YYEMPTY;
+
+  yystate = yyn;
+  *++yyvsp = yylval;
+
+  goto yynewstate;
+
+
+/*-----------------------------------------------------------.
+| yydefault -- do the default action for the current state.  |
+`-----------------------------------------------------------*/
+yydefault:
+  yyn = yydefact[yystate];
+  if (yyn == 0)
+    goto yyerrlab;
+  goto yyreduce;
+
+
+/*-----------------------------.
+| yyreduce -- Do a reduction.  |
+`-----------------------------*/
+yyreduce:
+  /* yyn is the number of a rule to reduce with.  */
+  yylen = yyr2[yyn];
+
+  /* If YYLEN is nonzero, implement the default value of the action:
+     `$$ = $1'.
+
+     Otherwise, the following line sets YYVAL to garbage.
+     This behavior is undocumented and Bison
+     users should not rely upon it.  Assigning to YYVAL
+     unconditionally makes the parser a bit smaller, and it avoids a
+     GCC warning that YYVAL may be used uninitialized.  */
+  yyval = yyvsp[1-yylen];
+
+
+  YY_REDUCE_PRINT (yyn);
+  switch (yyn)
+    {
+        case 2:
+
+    {
+        // The symbol table search was done in the lexical phase
+        const TSymbol* symbol = (yyvsp[(1) - (1)].lex).symbol;
+        const TVariable* variable;
+        if (symbol == 0) {
+            context->error((yyvsp[(1) - (1)].lex).line, "undeclared identifier", (yyvsp[(1) - (1)].lex).string->c_str());
+            context->recover();
+            TType type(EbtFloat, EbpUndefined);
+            TVariable* fakeVariable = new TVariable((yyvsp[(1) - (1)].lex).string, type);
+            context->symbolTable.insert(*fakeVariable);
+            variable = fakeVariable;
+        } else {
+            // This identifier can only be a variable type symbol
+            if (! symbol->isVariable()) {
+                context->error((yyvsp[(1) - (1)].lex).line, "variable expected", (yyvsp[(1) - (1)].lex).string->c_str());
+                context->recover();
+            }
+            variable = static_cast<const TVariable*>(symbol);
+        }
+
+        // don't delete $1.string, it's used by error recovery, and the pool
+        // pop will reclaim the memory
+
+        if (variable->getType().getQualifier() == EvqConst ) {
+            ConstantUnion* constArray = variable->getConstPointer();
+            TType t(variable->getType());
+            (yyval.interm.intermTypedNode) = context->intermediate.addConstantUnion(constArray, t, (yyvsp[(1) - (1)].lex).line);
+        } else
+            (yyval.interm.intermTypedNode) = context->intermediate.addSymbol(variable->getUniqueId(),
+                                                     variable->getName(),
+                                                     variable->getType(), (yyvsp[(1) - (1)].lex).line);
+    }
+    break;
+
+  case 3:
+
+    {
+        (yyval.interm.intermTypedNode) = (yyvsp[(1) - (1)].interm.intermTypedNode);
+    }
+    break;
+
+  case 4:
+
+    {
+        //
+        // INT_TYPE is only 16-bit plus sign bit for vertex/fragment shaders,
+        // check for overflow for constants
+        //
+        if (abs((yyvsp[(1) - (1)].lex).i) >= (1 << 16)) {
+            context->error((yyvsp[(1) - (1)].lex).line, " integer constant overflow", "");
+            context->recover();
+        }
+        ConstantUnion *unionArray = new ConstantUnion[1];
+        unionArray->setIConst((yyvsp[(1) - (1)].lex).i);
+        (yyval.interm.intermTypedNode) = context->intermediate.addConstantUnion(unionArray, TType(EbtInt, EbpUndefined, EvqConst), (yyvsp[(1) - (1)].lex).line);
+    }
+    break;
+
+  case 5:
+
+    {
+        ConstantUnion *unionArray = new ConstantUnion[1];
+        unionArray->setFConst((yyvsp[(1) - (1)].lex).f);
+        (yyval.interm.intermTypedNode) = context->intermediate.addConstantUnion(unionArray, TType(EbtFloat, EbpUndefined, EvqConst), (yyvsp[(1) - (1)].lex).line);
+    }
+    break;
+
+  case 6:
+
+    {
+        ConstantUnion *unionArray = new ConstantUnion[1];
+        unionArray->setBConst((yyvsp[(1) - (1)].lex).b);
+        (yyval.interm.intermTypedNode) = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), (yyvsp[(1) - (1)].lex).line);
+    }
+    break;
+
+  case 7:
+
+    {
+        (yyval.interm.intermTypedNode) = (yyvsp[(2) - (3)].interm.intermTypedNode);
+    }
+    break;
+
+  case 8:
+
+    {
+        (yyval.interm.intermTypedNode) = (yyvsp[(1) - (1)].interm.intermTypedNode);
+    }
+    break;
+
+  case 9:
+
+    {
+        if (!(yyvsp[(1) - (4)].interm.intermTypedNode)->isArray() && !(yyvsp[(1) - (4)].interm.intermTypedNode)->isMatrix() && !(yyvsp[(1) - (4)].interm.intermTypedNode)->isVector()) {
+            if ((yyvsp[(1) - (4)].interm.intermTypedNode)->getAsSymbolNode())
+                context->error((yyvsp[(2) - (4)].lex).line, " left of '[' is not of type array, matrix, or vector ", (yyvsp[(1) - (4)].interm.intermTypedNode)->getAsSymbolNode()->getSymbol().c_str());
+            else
+                context->error((yyvsp[(2) - (4)].lex).line, " left of '[' is not of type array, matrix, or vector ", "expression");
+            context->recover();
+        }
+        if ((yyvsp[(1) - (4)].interm.intermTypedNode)->getType().getQualifier() == EvqConst && (yyvsp[(3) - (4)].interm.intermTypedNode)->getQualifier() == EvqConst) {
+            if ((yyvsp[(1) - (4)].interm.intermTypedNode)->isArray()) { // constant folding for arrays
+                (yyval.interm.intermTypedNode) = context->addConstArrayNode((yyvsp[(3) - (4)].interm.intermTypedNode)->getAsConstantUnion()->getUnionArrayPointer()->getIConst(), (yyvsp[(1) - (4)].interm.intermTypedNode), (yyvsp[(2) - (4)].lex).line);
+            } else if ((yyvsp[(1) - (4)].interm.intermTypedNode)->isVector()) {  // constant folding for vectors
+                TVectorFields fields;
+                fields.num = 1;
+                fields.offsets[0] = (yyvsp[(3) - (4)].interm.intermTypedNode)->getAsConstantUnion()->getUnionArrayPointer()->getIConst(); // need to do it this way because v.xy sends fields integer array
+                (yyval.interm.intermTypedNode) = context->addConstVectorNode(fields, (yyvsp[(1) - (4)].interm.intermTypedNode), (yyvsp[(2) - (4)].lex).line);
+            } else if ((yyvsp[(1) - (4)].interm.intermTypedNode)->isMatrix()) { // constant folding for matrices
+                (yyval.interm.intermTypedNode) = context->addConstMatrixNode((yyvsp[(3) - (4)].interm.intermTypedNode)->getAsConstantUnion()->getUnionArrayPointer()->getIConst(), (yyvsp[(1) - (4)].interm.intermTypedNode), (yyvsp[(2) - (4)].lex).line);
+            }
+        } else {
+            if ((yyvsp[(3) - (4)].interm.intermTypedNode)->getQualifier() == EvqConst) {
+                if (((yyvsp[(1) - (4)].interm.intermTypedNode)->isVector() || (yyvsp[(1) - (4)].interm.intermTypedNode)->isMatrix()) && (yyvsp[(1) - (4)].interm.intermTypedNode)->getType().getNominalSize() <= (yyvsp[(3) - (4)].interm.intermTypedNode)->getAsConstantUnion()->getUnionArrayPointer()->getIConst() && !(yyvsp[(1) - (4)].interm.intermTypedNode)->isArray() ) {
+                    std::stringstream extraInfoStream;
+                    extraInfoStream << "field selection out of range '" << (yyvsp[(3) - (4)].interm.intermTypedNode)->getAsConstantUnion()->getUnionArrayPointer()->getIConst() << "'";
+                    std::string extraInfo = extraInfoStream.str();
+                    context->error((yyvsp[(2) - (4)].lex).line, "", "[", extraInfo.c_str());
+                    context->recover();
+                } else {
+                    if ((yyvsp[(1) - (4)].interm.intermTypedNode)->isArray()) {
+                        if ((yyvsp[(1) - (4)].interm.intermTypedNode)->getType().getArraySize() == 0) {
+                            if ((yyvsp[(1) - (4)].interm.intermTypedNode)->getType().getMaxArraySize() <= (yyvsp[(3) - (4)].interm.intermTypedNode)->getAsConstantUnion()->getUnionArrayPointer()->getIConst()) {
+                                if (context->arraySetMaxSize((yyvsp[(1) - (4)].interm.intermTypedNode)->getAsSymbolNode(), (yyvsp[(1) - (4)].interm.intermTypedNode)->getTypePointer(), (yyvsp[(3) - (4)].interm.intermTypedNode)->getAsConstantUnion()->getUnionArrayPointer()->getIConst(), true, (yyvsp[(2) - (4)].lex).line))
+                                    context->recover();
+                            } else {
+                                if (context->arraySetMaxSize((yyvsp[(1) - (4)].interm.intermTypedNode)->getAsSymbolNode(), (yyvsp[(1) - (4)].interm.intermTypedNode)->getTypePointer(), 0, false, (yyvsp[(2) - (4)].lex).line))
+                                    context->recover();
+                            }
+                        } else if ( (yyvsp[(3) - (4)].interm.intermTypedNode)->getAsConstantUnion()->getUnionArrayPointer()->getIConst() >= (yyvsp[(1) - (4)].interm.intermTypedNode)->getType().getArraySize()) {
+                            std::stringstream extraInfoStream;
+                            extraInfoStream << "array index out of range '" << (yyvsp[(3) - (4)].interm.intermTypedNode)->getAsConstantUnion()->getUnionArrayPointer()->getIConst() << "'";
+                            std::string extraInfo = extraInfoStream.str();
+                            context->error((yyvsp[(2) - (4)].lex).line, "", "[", extraInfo.c_str());
+                            context->recover();
+                        }
+                    }
+                    (yyval.interm.intermTypedNode) = context->intermediate.addIndex(EOpIndexDirect, (yyvsp[(1) - (4)].interm.intermTypedNode), (yyvsp[(3) - (4)].interm.intermTypedNode), (yyvsp[(2) - (4)].lex).line);
+                }
+            } else {
+                if ((yyvsp[(1) - (4)].interm.intermTypedNode)->isArray() && (yyvsp[(1) - (4)].interm.intermTypedNode)->getType().getArraySize() == 0) {
+                    context->error((yyvsp[(2) - (4)].lex).line, "", "[", "array must be redeclared with a size before being indexed with a variable");
+                    context->recover();
+                }
+
+                (yyval.interm.intermTypedNode) = context->intermediate.addIndex(EOpIndexIndirect, (yyvsp[(1) - (4)].interm.intermTypedNode), (yyvsp[(3) - (4)].interm.intermTypedNode), (yyvsp[(2) - (4)].lex).line);
+            }
+        }
+        if ((yyval.interm.intermTypedNode) == 0) {
+            ConstantUnion *unionArray = new ConstantUnion[1];
+            unionArray->setFConst(0.0f);
+            (yyval.interm.intermTypedNode) = context->intermediate.addConstantUnion(unionArray, TType(EbtFloat, EbpHigh, EvqConst), (yyvsp[(2) - (4)].lex).line);
+        } else if ((yyvsp[(1) - (4)].interm.intermTypedNode)->isArray()) {
+            if ((yyvsp[(1) - (4)].interm.intermTypedNode)->getType().getStruct())
+                (yyval.interm.intermTypedNode)->setType(TType((yyvsp[(1) - (4)].interm.intermTypedNode)->getType().getStruct(), (yyvsp[(1) - (4)].interm.intermTypedNode)->getType().getTypeName()));
+            else
+                (yyval.interm.intermTypedNode)->setType(TType((yyvsp[(1) - (4)].interm.intermTypedNode)->getBasicType(), (yyvsp[(1) - (4)].interm.intermTypedNode)->getPrecision(), EvqTemporary, (yyvsp[(1) - (4)].interm.intermTypedNode)->getNominalSize(), (yyvsp[(1) - (4)].interm.intermTypedNode)->isMatrix()));
+
+            if ((yyvsp[(1) - (4)].interm.intermTypedNode)->getType().getQualifier() == EvqConst)
+                (yyval.interm.intermTypedNode)->getTypePointer()->setQualifier(EvqConst);
+        } else if ((yyvsp[(1) - (4)].interm.intermTypedNode)->isMatrix() && (yyvsp[(1) - (4)].interm.intermTypedNode)->getType().getQualifier() == EvqConst)
+            (yyval.interm.intermTypedNode)->setType(TType((yyvsp[(1) - (4)].interm.intermTypedNode)->getBasicType(), (yyvsp[(1) - (4)].interm.intermTypedNode)->getPrecision(), EvqConst, (yyvsp[(1) - (4)].interm.intermTypedNode)->getNominalSize()));
+        else if ((yyvsp[(1) - (4)].interm.intermTypedNode)->isMatrix())
+            (yyval.interm.intermTypedNode)->setType(TType((yyvsp[(1) - (4)].interm.intermTypedNode)->getBasicType(), (yyvsp[(1) - (4)].interm.intermTypedNode)->getPrecision(), EvqTemporary, (yyvsp[(1) - (4)].interm.intermTypedNode)->getNominalSize()));
+        else if ((yyvsp[(1) - (4)].interm.intermTypedNode)->isVector() && (yyvsp[(1) - (4)].interm.intermTypedNode)->getType().getQualifier() == EvqConst)
+            (yyval.interm.intermTypedNode)->setType(TType((yyvsp[(1) - (4)].interm.intermTypedNode)->getBasicType(), (yyvsp[(1) - (4)].interm.intermTypedNode)->getPrecision(), EvqConst));
+        else if ((yyvsp[(1) - (4)].interm.intermTypedNode)->isVector())
+            (yyval.interm.intermTypedNode)->setType(TType((yyvsp[(1) - (4)].interm.intermTypedNode)->getBasicType(), (yyvsp[(1) - (4)].interm.intermTypedNode)->getPrecision(), EvqTemporary));
+        else
+            (yyval.interm.intermTypedNode)->setType((yyvsp[(1) - (4)].interm.intermTypedNode)->getType());
+    }
+    break;
+
+  case 10:
+
+    {
+        (yyval.interm.intermTypedNode) = (yyvsp[(1) - (1)].interm.intermTypedNode);
+    }
+    break;
+
+  case 11:
+
+    {
+        if ((yyvsp[(1) - (3)].interm.intermTypedNode)->isArray()) {
+            context->error((yyvsp[(3) - (3)].lex).line, "cannot apply dot operator to an array", ".");
+            context->recover();
+        }
+
+        if ((yyvsp[(1) - (3)].interm.intermTypedNode)->isVector()) {
+            TVectorFields fields;
+            if (! context->parseVectorFields(*(yyvsp[(3) - (3)].lex).string, (yyvsp[(1) - (3)].interm.intermTypedNode)->getNominalSize(), fields, (yyvsp[(3) - (3)].lex).line)) {
+                fields.num = 1;
+                fields.offsets[0] = 0;
+                context->recover();
+            }
+
+            if ((yyvsp[(1) - (3)].interm.intermTypedNode)->getType().getQualifier() == EvqConst) { // constant folding for vector fields
+                (yyval.interm.intermTypedNode) = context->addConstVectorNode(fields, (yyvsp[(1) - (3)].interm.intermTypedNode), (yyvsp[(3) - (3)].lex).line);
+                if ((yyval.interm.intermTypedNode) == 0) {
+                    context->recover();
+                    (yyval.interm.intermTypedNode) = (yyvsp[(1) - (3)].interm.intermTypedNode);
+                }
+                else
+                    (yyval.interm.intermTypedNode)->setType(TType((yyvsp[(1) - (3)].interm.intermTypedNode)->getBasicType(), (yyvsp[(1) - (3)].interm.intermTypedNode)->getPrecision(), EvqConst, (int) (*(yyvsp[(3) - (3)].lex).string).size()));
+            } else {
+                TString vectorString = *(yyvsp[(3) - (3)].lex).string;
+                TIntermTyped* index = context->intermediate.addSwizzle(fields, (yyvsp[(3) - (3)].lex).line);
+                (yyval.interm.intermTypedNode) = context->intermediate.addIndex(EOpVectorSwizzle, (yyvsp[(1) - (3)].interm.intermTypedNode), index, (yyvsp[(2) - (3)].lex).line);
+                (yyval.interm.intermTypedNode)->setType(TType((yyvsp[(1) - (3)].interm.intermTypedNode)->getBasicType(), (yyvsp[(1) - (3)].interm.intermTypedNode)->getPrecision(), EvqTemporary, (int) vectorString.size()));
+            }
+        } else if ((yyvsp[(1) - (3)].interm.intermTypedNode)->isMatrix()) {
+            TMatrixFields fields;
+            if (! context->parseMatrixFields(*(yyvsp[(3) - (3)].lex).string, (yyvsp[(1) - (3)].interm.intermTypedNode)->getNominalSize(), fields, (yyvsp[(3) - (3)].lex).line)) {
+                fields.wholeRow = false;
+                fields.wholeCol = false;
+                fields.row = 0;
+                fields.col = 0;
+                context->recover();
+            }
+
+            if (fields.wholeRow || fields.wholeCol) {
+                context->error((yyvsp[(2) - (3)].lex).line, " non-scalar fields not implemented yet", ".");
+                context->recover();
+                ConstantUnion *unionArray = new ConstantUnion[1];
+                unionArray->setIConst(0);
+                TIntermTyped* index = context->intermediate.addConstantUnion(unionArray, TType(EbtInt, EbpUndefined, EvqConst), (yyvsp[(3) - (3)].lex).line);
+                (yyval.interm.intermTypedNode) = context->intermediate.addIndex(EOpIndexDirect, (yyvsp[(1) - (3)].interm.intermTypedNode), index, (yyvsp[(2) - (3)].lex).line);
+                (yyval.interm.intermTypedNode)->setType(TType((yyvsp[(1) - (3)].interm.intermTypedNode)->getBasicType(), (yyvsp[(1) - (3)].interm.intermTypedNode)->getPrecision(),EvqTemporary, (yyvsp[(1) - (3)].interm.intermTypedNode)->getNominalSize()));
+            } else {
+                ConstantUnion *unionArray = new ConstantUnion[1];
+                unionArray->setIConst(fields.col * (yyvsp[(1) - (3)].interm.intermTypedNode)->getNominalSize() + fields.row);
+                TIntermTyped* index = context->intermediate.addConstantUnion(unionArray, TType(EbtInt, EbpUndefined, EvqConst), (yyvsp[(3) - (3)].lex).line);
+                (yyval.interm.intermTypedNode) = context->intermediate.addIndex(EOpIndexDirect, (yyvsp[(1) - (3)].interm.intermTypedNode), index, (yyvsp[(2) - (3)].lex).line);
+                (yyval.interm.intermTypedNode)->setType(TType((yyvsp[(1) - (3)].interm.intermTypedNode)->getBasicType(), (yyvsp[(1) - (3)].interm.intermTypedNode)->getPrecision()));
+            }
+        } else if ((yyvsp[(1) - (3)].interm.intermTypedNode)->getBasicType() == EbtStruct) {
+            bool fieldFound = false;
+            const TTypeList* fields = (yyvsp[(1) - (3)].interm.intermTypedNode)->getType().getStruct();
+            if (fields == 0) {
+                context->error((yyvsp[(2) - (3)].lex).line, "structure has no fields", "Internal Error");
+                context->recover();
+                (yyval.interm.intermTypedNode) = (yyvsp[(1) - (3)].interm.intermTypedNode);
+            } else {
+                unsigned int i;
+                for (i = 0; i < fields->size(); ++i) {
+                    if ((*fields)[i].type->getFieldName() == *(yyvsp[(3) - (3)].lex).string) {
+                        fieldFound = true;
+                        break;
+                    }
+                }
+                if (fieldFound) {
+                    if ((yyvsp[(1) - (3)].interm.intermTypedNode)->getType().getQualifier() == EvqConst) {
+                        (yyval.interm.intermTypedNode) = context->addConstStruct(*(yyvsp[(3) - (3)].lex).string, (yyvsp[(1) - (3)].interm.intermTypedNode), (yyvsp[(2) - (3)].lex).line);
+                        if ((yyval.interm.intermTypedNode) == 0) {
+                            context->recover();
+                            (yyval.interm.intermTypedNode) = (yyvsp[(1) - (3)].interm.intermTypedNode);
+                        }
+                        else {
+                            (yyval.interm.intermTypedNode)->setType(*(*fields)[i].type);
+                            // change the qualifier of the return type, not of the structure field
+                            // as the structure definition is shared between various structures.
+                            (yyval.interm.intermTypedNode)->getTypePointer()->setQualifier(EvqConst);
+                        }
+                    } else {
+                        ConstantUnion *unionArray = new ConstantUnion[1];
+                        unionArray->setIConst(i);
+                        TIntermTyped* index = context->intermediate.addConstantUnion(unionArray, *(*fields)[i].type, (yyvsp[(3) - (3)].lex).line);
+                        (yyval.interm.intermTypedNode) = context->intermediate.addIndex(EOpIndexDirectStruct, (yyvsp[(1) - (3)].interm.intermTypedNode), index, (yyvsp[(2) - (3)].lex).line);
+                        (yyval.interm.intermTypedNode)->setType(*(*fields)[i].type);
+                    }
+                } else {
+                    context->error((yyvsp[(2) - (3)].lex).line, " no such field in structure", (yyvsp[(3) - (3)].lex).string->c_str());
+                    context->recover();
+                    (yyval.interm.intermTypedNode) = (yyvsp[(1) - (3)].interm.intermTypedNode);
+                }
+            }
+        } else {
+            context->error((yyvsp[(2) - (3)].lex).line, " field selection requires structure, vector, or matrix on left hand side", (yyvsp[(3) - (3)].lex).string->c_str());
+            context->recover();
+            (yyval.interm.intermTypedNode) = (yyvsp[(1) - (3)].interm.intermTypedNode);
+        }
+        // don't delete $3.string, it's from the pool
+    }
+    break;
+
+  case 12:
+
+    {
+        if (context->lValueErrorCheck((yyvsp[(2) - (2)].lex).line, "++", (yyvsp[(1) - (2)].interm.intermTypedNode)))
+            context->recover();
+        (yyval.interm.intermTypedNode) = context->intermediate.addUnaryMath(EOpPostIncrement, (yyvsp[(1) - (2)].interm.intermTypedNode), (yyvsp[(2) - (2)].lex).line, context->symbolTable);
+        if ((yyval.interm.intermTypedNode) == 0) {
+            context->unaryOpError((yyvsp[(2) - (2)].lex).line, "++", (yyvsp[(1) - (2)].interm.intermTypedNode)->getCompleteString());
+            context->recover();
+            (yyval.interm.intermTypedNode) = (yyvsp[(1) - (2)].interm.intermTypedNode);
+        }
+    }
+    break;
+
+  case 13:
+
+    {
+        if (context->lValueErrorCheck((yyvsp[(2) - (2)].lex).line, "--", (yyvsp[(1) - (2)].interm.intermTypedNode)))
+            context->recover();
+        (yyval.interm.intermTypedNode) = context->intermediate.addUnaryMath(EOpPostDecrement, (yyvsp[(1) - (2)].interm.intermTypedNode), (yyvsp[(2) - (2)].lex).line, context->symbolTable);
+        if ((yyval.interm.intermTypedNode) == 0) {
+            context->unaryOpError((yyvsp[(2) - (2)].lex).line, "--", (yyvsp[(1) - (2)].interm.intermTypedNode)->getCompleteString());
+            context->recover();
+            (yyval.interm.intermTypedNode) = (yyvsp[(1) - (2)].interm.intermTypedNode);
+        }
+    }
+    break;
+
+  case 14:
+
+    {
+        if (context->integerErrorCheck((yyvsp[(1) - (1)].interm.intermTypedNode), "[]"))
+            context->recover();
+        (yyval.interm.intermTypedNode) = (yyvsp[(1) - (1)].interm.intermTypedNode);
+    }
+    break;
+
+  case 15:
+
+    {
+        TFunction* fnCall = (yyvsp[(1) - (1)].interm).function;
+        TOperator op = fnCall->getBuiltInOp();
+
+        if (op != EOpNull)
+        {
+            //
+            // Then this should be a constructor.
+            // Don't go through the symbol table for constructors.
+            // Their parameters will be verified algorithmically.
+            //
+            TType type(EbtVoid, EbpUndefined);  // use this to get the type back
+            if (context->constructorErrorCheck((yyvsp[(1) - (1)].interm).line, (yyvsp[(1) - (1)].interm).intermNode, *fnCall, op, &type)) {
+                (yyval.interm.intermTypedNode) = 0;
+            } else {
+                //
+                // It's a constructor, of type 'type'.
+                //
+                (yyval.interm.intermTypedNode) = context->addConstructor((yyvsp[(1) - (1)].interm).intermNode, &type, op, fnCall, (yyvsp[(1) - (1)].interm).line);
+            }
+
+            if ((yyval.interm.intermTypedNode) == 0) {
+                context->recover();
+                (yyval.interm.intermTypedNode) = context->intermediate.setAggregateOperator(0, op, (yyvsp[(1) - (1)].interm).line);
+            }
+            (yyval.interm.intermTypedNode)->setType(type);
+        } else {
+            //
+            // Not a constructor.  Find it in the symbol table.
+            //
+            const TFunction* fnCandidate;
+            bool builtIn;
+            fnCandidate = context->findFunction((yyvsp[(1) - (1)].interm).line, fnCall, &builtIn);
+            if (fnCandidate) {
+                //
+                // A declared function.
+                //
+                if (builtIn && !fnCandidate->getExtension().empty() &&
+                    context->extensionErrorCheck((yyvsp[(1) - (1)].interm).line, fnCandidate->getExtension())) {
+                    context->recover();
+                }
+                op = fnCandidate->getBuiltInOp();
+                if (builtIn && op != EOpNull) {
+                    //
+                    // A function call mapped to a built-in operation.
+                    //
+                    if (fnCandidate->getParamCount() == 1) {
+                        //
+                        // Treat it like a built-in unary operator.
+                        //
+                        (yyval.interm.intermTypedNode) = context->intermediate.addUnaryMath(op, (yyvsp[(1) - (1)].interm).intermNode, 0, context->symbolTable);
+                        if ((yyval.interm.intermTypedNode) == 0)  {
+                            std::stringstream extraInfoStream;
+                            extraInfoStream << "built in unary operator function.  Type: " << static_cast<TIntermTyped*>((yyvsp[(1) - (1)].interm).intermNode)->getCompleteString();
+                            std::string extraInfo = extraInfoStream.str();
+                            context->error((yyvsp[(1) - (1)].interm).intermNode->getLine(), " wrong operand type", "Internal Error", extraInfo.c_str());
+                            YYERROR;
+                        }
+                    } else {
+                        (yyval.interm.intermTypedNode) = context->intermediate.setAggregateOperator((yyvsp[(1) - (1)].interm).intermAggregate, op, (yyvsp[(1) - (1)].interm).line);
+                    }
+                } else {
+                    // This is a real function call
+
+                    (yyval.interm.intermTypedNode) = context->intermediate.setAggregateOperator((yyvsp[(1) - (1)].interm).intermAggregate, EOpFunctionCall, (yyvsp[(1) - (1)].interm).line);
+                    (yyval.interm.intermTypedNode)->setType(fnCandidate->getReturnType());
+
+                    // this is how we know whether the given function is a builtIn function or a user defined function
+                    // if builtIn == false, it's a userDefined -> could be an overloaded builtIn function also
+                    // if builtIn == true, it's definitely a builtIn function with EOpNull
+                    if (!builtIn)
+                        (yyval.interm.intermTypedNode)->getAsAggregate()->setUserDefined();
+                    (yyval.interm.intermTypedNode)->getAsAggregate()->setName(fnCandidate->getMangledName());
+
+                    TQualifier qual;
+                    for (int i = 0; i < fnCandidate->getParamCount(); ++i) {
+                        qual = fnCandidate->getParam(i).type->getQualifier();
+                        if (qual == EvqOut || qual == EvqInOut) {
+                            if (context->lValueErrorCheck((yyval.interm.intermTypedNode)->getLine(), "assign", (yyval.interm.intermTypedNode)->getAsAggregate()->getSequence()[i]->getAsTyped())) {
+                                context->error((yyvsp[(1) - (1)].interm).intermNode->getLine(), "Constant value cannot be passed for 'out' or 'inout' parameters.", "Error");
+                                context->recover();
+                            }
+                        }
+                    }
+                }
+                (yyval.interm.intermTypedNode)->setType(fnCandidate->getReturnType());
+            } else {
+                // error message was put out by PaFindFunction()
+                // Put on a dummy node for error recovery
+                ConstantUnion *unionArray = new ConstantUnion[1];
+                unionArray->setFConst(0.0f);
+                (yyval.interm.intermTypedNode) = context->intermediate.addConstantUnion(unionArray, TType(EbtFloat, EbpUndefined, EvqConst), (yyvsp[(1) - (1)].interm).line);
+                context->recover();
+            }
+        }
+        delete fnCall;
+    }
+    break;
+
+  case 16:
+
+    {
+        (yyval.interm) = (yyvsp[(1) - (1)].interm);
+    }
+    break;
+
+  case 17:
+
+    {
+        context->error((yyvsp[(3) - (3)].interm).line, "methods are not supported", "");
+        context->recover();
+        (yyval.interm) = (yyvsp[(3) - (3)].interm);
+    }
+    break;
+
+  case 18:
+
+    {
+        (yyval.interm) = (yyvsp[(1) - (2)].interm);
+        (yyval.interm).line = (yyvsp[(2) - (2)].lex).line;
+    }
+    break;
+
+  case 19:
+
+    {
+        (yyval.interm) = (yyvsp[(1) - (2)].interm);
+        (yyval.interm).line = (yyvsp[(2) - (2)].lex).line;
+    }
+    break;
+
+  case 20:
+
+    {
+        (yyval.interm).function = (yyvsp[(1) - (2)].interm.function);
+        (yyval.interm).intermNode = 0;
+    }
+    break;
+
+  case 21:
+
+    {
+        (yyval.interm).function = (yyvsp[(1) - (1)].interm.function);
+        (yyval.interm).intermNode = 0;
+    }
+    break;
+
+  case 22:
+
+    {
+        TParameter param = { 0, new TType((yyvsp[(2) - (2)].interm.intermTypedNode)->getType()) };
+        (yyvsp[(1) - (2)].interm.function)->addParameter(param);
+        (yyval.interm).function = (yyvsp[(1) - (2)].interm.function);
+        (yyval.interm).intermNode = (yyvsp[(2) - (2)].interm.intermTypedNode);
+    }
+    break;
+
+  case 23:
+
+    {
+        TParameter param = { 0, new TType((yyvsp[(3) - (3)].interm.intermTypedNode)->getType()) };
+        (yyvsp[(1) - (3)].interm).function->addParameter(param);
+        (yyval.interm).function = (yyvsp[(1) - (3)].interm).function;
+        (yyval.interm).intermNode = context->intermediate.growAggregate((yyvsp[(1) - (3)].interm).intermNode, (yyvsp[(3) - (3)].interm.intermTypedNode), (yyvsp[(2) - (3)].lex).line);
+    }
+    break;
+
+  case 24:
+
+    {
+        (yyval.interm.function) = (yyvsp[(1) - (2)].interm.function);
+    }
+    break;
+
+  case 25:
+
+    {
+        //
+        // Constructor
+        //
+        TOperator op = EOpNull;
+        if ((yyvsp[(1) - (1)].interm.type).userDef) {
+            op = EOpConstructStruct;
+        } else {
+            switch ((yyvsp[(1) - (1)].interm.type).type) {
+            case EbtFloat:
+                if ((yyvsp[(1) - (1)].interm.type).matrix) {
+                    switch((yyvsp[(1) - (1)].interm.type).size) {
+                    case 2:                                     op = EOpConstructMat2;  break;
+                    case 3:                                     op = EOpConstructMat3;  break;
+                    case 4:                                     op = EOpConstructMat4;  break;
+                    }
+                } else {
+                    switch((yyvsp[(1) - (1)].interm.type).size) {
+                    case 1:                                     op = EOpConstructFloat; break;
+                    case 2:                                     op = EOpConstructVec2;  break;
+                    case 3:                                     op = EOpConstructVec3;  break;
+                    case 4:                                     op = EOpConstructVec4;  break;
+                    }
+                }
+                break;
+            case EbtInt:
+                switch((yyvsp[(1) - (1)].interm.type).size) {
+                case 1:                                         op = EOpConstructInt;   break;
+                case 2:       FRAG_VERT_ONLY("ivec2", (yyvsp[(1) - (1)].interm.type).line); op = EOpConstructIVec2; break;
+                case 3:       FRAG_VERT_ONLY("ivec3", (yyvsp[(1) - (1)].interm.type).line); op = EOpConstructIVec3; break;
+                case 4:       FRAG_VERT_ONLY("ivec4", (yyvsp[(1) - (1)].interm.type).line); op = EOpConstructIVec4; break;
+                }
+                break;
+            case EbtBool:
+                switch((yyvsp[(1) - (1)].interm.type).size) {
+                case 1:                                         op = EOpConstructBool;  break;
+                case 2:       FRAG_VERT_ONLY("bvec2", (yyvsp[(1) - (1)].interm.type).line); op = EOpConstructBVec2; break;
+                case 3:       FRAG_VERT_ONLY("bvec3", (yyvsp[(1) - (1)].interm.type).line); op = EOpConstructBVec3; break;
+                case 4:       FRAG_VERT_ONLY("bvec4", (yyvsp[(1) - (1)].interm.type).line); op = EOpConstructBVec4; break;
+                }
+                break;
+            default: break;
+            }
+            if (op == EOpNull) {
+                context->error((yyvsp[(1) - (1)].interm.type).line, "cannot construct this type", getBasicString((yyvsp[(1) - (1)].interm.type).type));
+                context->recover();
+                (yyvsp[(1) - (1)].interm.type).type = EbtFloat;
+                op = EOpConstructFloat;
+            }
+        }
+        TString tempString;
+        TType type((yyvsp[(1) - (1)].interm.type));
+        TFunction *function = new TFunction(&tempString, type, op);
+        (yyval.interm.function) = function;
+    }
+    break;
+
+  case 26:
+
+    {
+        if (context->reservedErrorCheck((yyvsp[(1) - (1)].lex).line, *(yyvsp[(1) - (1)].lex).string))
+            context->recover();
+        TType type(EbtVoid, EbpUndefined);
+        TFunction *function = new TFunction((yyvsp[(1) - (1)].lex).string, type);
+        (yyval.interm.function) = function;
+    }
+    break;
+
+  case 27:
+
+    {
+        if (context->reservedErrorCheck((yyvsp[(1) - (1)].lex).line, *(yyvsp[(1) - (1)].lex).string))
+            context->recover();
+        TType type(EbtVoid, EbpUndefined);
+        TFunction *function = new TFunction((yyvsp[(1) - (1)].lex).string, type);
+        (yyval.interm.function) = function;
+    }
+    break;
+
+  case 28:
+
+    {
+        (yyval.interm.intermTypedNode) = (yyvsp[(1) - (1)].interm.intermTypedNode);
+    }
+    break;
+
+  case 29:
+
+    {
+        if (context->lValueErrorCheck((yyvsp[(1) - (2)].lex).line, "++", (yyvsp[(2) - (2)].interm.intermTypedNode)))
+            context->recover();
+        (yyval.interm.intermTypedNode) = context->intermediate.addUnaryMath(EOpPreIncrement, (yyvsp[(2) - (2)].interm.intermTypedNode), (yyvsp[(1) - (2)].lex).line, context->symbolTable);
+        if ((yyval.interm.intermTypedNode) == 0) {
+            context->unaryOpError((yyvsp[(1) - (2)].lex).line, "++", (yyvsp[(2) - (2)].interm.intermTypedNode)->getCompleteString());
+            context->recover();
+            (yyval.interm.intermTypedNode) = (yyvsp[(2) - (2)].interm.intermTypedNode);
+        }
+    }
+    break;
+
+  case 30:
+
+    {
+        if (context->lValueErrorCheck((yyvsp[(1) - (2)].lex).line, "--", (yyvsp[(2) - (2)].interm.intermTypedNode)))
+            context->recover();
+        (yyval.interm.intermTypedNode) = context->intermediate.addUnaryMath(EOpPreDecrement, (yyvsp[(2) - (2)].interm.intermTypedNode), (yyvsp[(1) - (2)].lex).line, context->symbolTable);
+        if ((yyval.interm.intermTypedNode) == 0) {
+            context->unaryOpError((yyvsp[(1) - (2)].lex).line, "--", (yyvsp[(2) - (2)].interm.intermTypedNode)->getCompleteString());
+            context->recover();
+            (yyval.interm.intermTypedNode) = (yyvsp[(2) - (2)].interm.intermTypedNode);
+        }
+    }
+    break;
+
+  case 31:
+
+    {
+        if ((yyvsp[(1) - (2)].interm).op != EOpNull) {
+            (yyval.interm.intermTypedNode) = context->intermediate.addUnaryMath((yyvsp[(1) - (2)].interm).op, (yyvsp[(2) - (2)].interm.intermTypedNode), (yyvsp[(1) - (2)].interm).line, context->symbolTable);
+            if ((yyval.interm.intermTypedNode) == 0) {
+                const char* errorOp = "";
+                switch((yyvsp[(1) - (2)].interm).op) {
+                case EOpNegative:   errorOp = "-"; break;
+                case EOpLogicalNot: errorOp = "!"; break;
+                default: break;
+                }
+                context->unaryOpError((yyvsp[(1) - (2)].interm).line, errorOp, (yyvsp[(2) - (2)].interm.intermTypedNode)->getCompleteString());
+                context->recover();
+                (yyval.interm.intermTypedNode) = (yyvsp[(2) - (2)].interm.intermTypedNode);
+            }
+        } else
+            (yyval.interm.intermTypedNode) = (yyvsp[(2) - (2)].interm.intermTypedNode);
+    }
+    break;
+
+  case 32:
+
+    { (yyval.interm).line = (yyvsp[(1) - (1)].lex).line; (yyval.interm).op = EOpNull; }
+    break;
+
+  case 33:
+
+    { (yyval.interm).line = (yyvsp[(1) - (1)].lex).line; (yyval.interm).op = EOpNegative; }
+    break;
+
+  case 34:
+
+    { (yyval.interm).line = (yyvsp[(1) - (1)].lex).line; (yyval.interm).op = EOpLogicalNot; }
+    break;
+
+  case 35:
+
+    { (yyval.interm.intermTypedNode) = (yyvsp[(1) - (1)].interm.intermTypedNode); }
+    break;
+
+  case 36:
+
+    {
+        FRAG_VERT_ONLY("*", (yyvsp[(2) - (3)].lex).line);
+        (yyval.interm.intermTypedNode) = context->intermediate.addBinaryMath(EOpMul, (yyvsp[(1) - (3)].interm.intermTypedNode), (yyvsp[(3) - (3)].interm.intermTypedNode), (yyvsp[(2) - (3)].lex).line, context->symbolTable);
+        if ((yyval.interm.intermTypedNode) == 0) {
+            context->binaryOpError((yyvsp[(2) - (3)].lex).line, "*", (yyvsp[(1) - (3)].interm.intermTypedNode)->getCompleteString(), (yyvsp[(3) - (3)].interm.intermTypedNode)->getCompleteString());
+            context->recover();
+            (yyval.interm.intermTypedNode) = (yyvsp[(1) - (3)].interm.intermTypedNode);
+        }
+    }
+    break;
+
+  case 37:
+
+    {
+        FRAG_VERT_ONLY("/", (yyvsp[(2) - (3)].lex).line);
+        (yyval.interm.intermTypedNode) = context->intermediate.addBinaryMath(EOpDiv, (yyvsp[(1) - (3)].interm.intermTypedNode), (yyvsp[(3) - (3)].interm.intermTypedNode), (yyvsp[(2) - (3)].lex).line, context->symbolTable);
+        if ((yyval.interm.intermTypedNode) == 0) {
+            context->binaryOpError((yyvsp[(2) - (3)].lex).line, "/", (yyvsp[(1) - (3)].interm.intermTypedNode)->getCompleteString(), (yyvsp[(3) - (3)].interm.intermTypedNode)->getCompleteString());
+            context->recover();
+            (yyval.interm.intermTypedNode) = (yyvsp[(1) - (3)].interm.intermTypedNode);
+        }
+    }
+    break;
+
+  case 38:
+
+    { (yyval.interm.intermTypedNode) = (yyvsp[(1) - (1)].interm.intermTypedNode); }
+    break;
+
+  case 39:
+
+    {
+        (yyval.interm.intermTypedNode) = context->intermediate.addBinaryMath(EOpAdd, (yyvsp[(1) - (3)].interm.intermTypedNode), (yyvsp[(3) - (3)].interm.intermTypedNode), (yyvsp[(2) - (3)].lex).line, context->symbolTable);
+        if ((yyval.interm.intermTypedNode) == 0) {
+            context->binaryOpError((yyvsp[(2) - (3)].lex).line, "+", (yyvsp[(1) - (3)].interm.intermTypedNode)->getCompleteString(), (yyvsp[(3) - (3)].interm.intermTypedNode)->getCompleteString());
+            context->recover();
+            (yyval.interm.intermTypedNode) = (yyvsp[(1) - (3)].interm.intermTypedNode);
+        }
+    }
+    break;
+
+  case 40:
+
+    {
+        (yyval.interm.intermTypedNode) = context->intermediate.addBinaryMath(EOpSub, (yyvsp[(1) - (3)].interm.intermTypedNode), (yyvsp[(3) - (3)].interm.intermTypedNode), (yyvsp[(2) - (3)].lex).line, context->symbolTable);
+        if ((yyval.interm.intermTypedNode) == 0) {
+            context->binaryOpError((yyvsp[(2) - (3)].lex).line, "-", (yyvsp[(1) - (3)].interm.intermTypedNode)->getCompleteString(), (yyvsp[(3) - (3)].interm.intermTypedNode)->getCompleteString());
+            context->recover();
+            (yyval.interm.intermTypedNode) = (yyvsp[(1) - (3)].interm.intermTypedNode);
+        }
+    }
+    break;
+
+  case 41:
+
+    { (yyval.interm.intermTypedNode) = (yyvsp[(1) - (1)].interm.intermTypedNode); }
+    break;
+
+  case 42:
+
+    { (yyval.interm.intermTypedNode) = (yyvsp[(1) - (1)].interm.intermTypedNode); }
+    break;
+
+  case 43:
+
+    {
+        (yyval.interm.intermTypedNode) = context->intermediate.addBinaryMath(EOpLessThan, (yyvsp[(1) - (3)].interm.intermTypedNode), (yyvsp[(3) - (3)].interm.intermTypedNode), (yyvsp[(2) - (3)].lex).line, context->symbolTable);
+        if ((yyval.interm.intermTypedNode) == 0) {
+            context->binaryOpError((yyvsp[(2) - (3)].lex).line, "<", (yyvsp[(1) - (3)].interm.intermTypedNode)->getCompleteString(), (yyvsp[(3) - (3)].interm.intermTypedNode)->getCompleteString());
+            context->recover();
+            ConstantUnion *unionArray = new ConstantUnion[1];
+            unionArray->setBConst(false);
+            (yyval.interm.intermTypedNode) = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), (yyvsp[(2) - (3)].lex).line);
+        }
+    }
+    break;
+
+  case 44:
+
+    {
+        (yyval.interm.intermTypedNode) = context->intermediate.addBinaryMath(EOpGreaterThan, (yyvsp[(1) - (3)].interm.intermTypedNode), (yyvsp[(3) - (3)].interm.intermTypedNode), (yyvsp[(2) - (3)].lex).line, context->symbolTable);
+        if ((yyval.interm.intermTypedNode) == 0) {
+            context->binaryOpError((yyvsp[(2) - (3)].lex).line, ">", (yyvsp[(1) - (3)].interm.intermTypedNode)->getCompleteString(), (yyvsp[(3) - (3)].interm.intermTypedNode)->getCompleteString());
+            context->recover();
+            ConstantUnion *unionArray = new ConstantUnion[1];
+            unionArray->setBConst(false);
+            (yyval.interm.intermTypedNode) = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), (yyvsp[(2) - (3)].lex).line);
+        }
+    }
+    break;
+
+  case 45:
+
+    {
+        (yyval.interm.intermTypedNode) = context->intermediate.addBinaryMath(EOpLessThanEqual, (yyvsp[(1) - (3)].interm.intermTypedNode), (yyvsp[(3) - (3)].interm.intermTypedNode), (yyvsp[(2) - (3)].lex).line, context->symbolTable);
+        if ((yyval.interm.intermTypedNode) == 0) {
+            context->binaryOpError((yyvsp[(2) - (3)].lex).line, "<=", (yyvsp[(1) - (3)].interm.intermTypedNode)->getCompleteString(), (yyvsp[(3) - (3)].interm.intermTypedNode)->getCompleteString());
+            context->recover();
+            ConstantUnion *unionArray = new ConstantUnion[1];
+            unionArray->setBConst(false);
+            (yyval.interm.intermTypedNode) = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), (yyvsp[(2) - (3)].lex).line);
+        }
+    }
+    break;
+
+  case 46:
+
+    {
+        (yyval.interm.intermTypedNode) = context->intermediate.addBinaryMath(EOpGreaterThanEqual, (yyvsp[(1) - (3)].interm.intermTypedNode), (yyvsp[(3) - (3)].interm.intermTypedNode), (yyvsp[(2) - (3)].lex).line, context->symbolTable);
+        if ((yyval.interm.intermTypedNode) == 0) {
+            context->binaryOpError((yyvsp[(2) - (3)].lex).line, ">=", (yyvsp[(1) - (3)].interm.intermTypedNode)->getCompleteString(), (yyvsp[(3) - (3)].interm.intermTypedNode)->getCompleteString());
+            context->recover();
+            ConstantUnion *unionArray = new ConstantUnion[1];
+            unionArray->setBConst(false);
+            (yyval.interm.intermTypedNode) = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), (yyvsp[(2) - (3)].lex).line);
+        }
+    }
+    break;
+
+  case 47:
+
+    { (yyval.interm.intermTypedNode) = (yyvsp[(1) - (1)].interm.intermTypedNode); }
+    break;
+
+  case 48:
+
+    {
+        (yyval.interm.intermTypedNode) = context->intermediate.addBinaryMath(EOpEqual, (yyvsp[(1) - (3)].interm.intermTypedNode), (yyvsp[(3) - (3)].interm.intermTypedNode), (yyvsp[(2) - (3)].lex).line, context->symbolTable);
+        if ((yyval.interm.intermTypedNode) == 0) {
+            context->binaryOpError((yyvsp[(2) - (3)].lex).line, "==", (yyvsp[(1) - (3)].interm.intermTypedNode)->getCompleteString(), (yyvsp[(3) - (3)].interm.intermTypedNode)->getCompleteString());
+            context->recover();
+            ConstantUnion *unionArray = new ConstantUnion[1];
+            unionArray->setBConst(false);
+            (yyval.interm.intermTypedNode) = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), (yyvsp[(2) - (3)].lex).line);
+        }
+    }
+    break;
+
+  case 49:
+
+    {
+        (yyval.interm.intermTypedNode) = context->intermediate.addBinaryMath(EOpNotEqual, (yyvsp[(1) - (3)].interm.intermTypedNode), (yyvsp[(3) - (3)].interm.intermTypedNode), (yyvsp[(2) - (3)].lex).line, context->symbolTable);
+        if ((yyval.interm.intermTypedNode) == 0) {
+            context->binaryOpError((yyvsp[(2) - (3)].lex).line, "!=", (yyvsp[(1) - (3)].interm.intermTypedNode)->getCompleteString(), (yyvsp[(3) - (3)].interm.intermTypedNode)->getCompleteString());
+            context->recover();
+            ConstantUnion *unionArray = new ConstantUnion[1];
+            unionArray->setBConst(false);
+            (yyval.interm.intermTypedNode) = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), (yyvsp[(2) - (3)].lex).line);
+        }
+    }
+    break;
+
+  case 50:
+
+    { (yyval.interm.intermTypedNode) = (yyvsp[(1) - (1)].interm.intermTypedNode); }
+    break;
+
+  case 51:
+
+    { (yyval.interm.intermTypedNode) = (yyvsp[(1) - (1)].interm.intermTypedNode); }
+    break;
+
+  case 52:
+
+    { (yyval.interm.intermTypedNode) = (yyvsp[(1) - (1)].interm.intermTypedNode); }
+    break;
+
+  case 53:
+
+    { (yyval.interm.intermTypedNode) = (yyvsp[(1) - (1)].interm.intermTypedNode); }
+    break;
+
+  case 54:
+
+    {
+        (yyval.interm.intermTypedNode) = context->intermediate.addBinaryMath(EOpLogicalAnd, (yyvsp[(1) - (3)].interm.intermTypedNode), (yyvsp[(3) - (3)].interm.intermTypedNode), (yyvsp[(2) - (3)].lex).line, context->symbolTable);
+        if ((yyval.interm.intermTypedNode) == 0) {
+            context->binaryOpError((yyvsp[(2) - (3)].lex).line, "&&", (yyvsp[(1) - (3)].interm.intermTypedNode)->getCompleteString(), (yyvsp[(3) - (3)].interm.intermTypedNode)->getCompleteString());
+            context->recover();
+            ConstantUnion *unionArray = new ConstantUnion[1];
+            unionArray->setBConst(false);
+            (yyval.interm.intermTypedNode) = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), (yyvsp[(2) - (3)].lex).line);
+        }
+    }
+    break;
+
+  case 55:
+
+    { (yyval.interm.intermTypedNode) = (yyvsp[(1) - (1)].interm.intermTypedNode); }
+    break;
+
+  case 56:
+
+    {
+        (yyval.interm.intermTypedNode) = context->intermediate.addBinaryMath(EOpLogicalXor, (yyvsp[(1) - (3)].interm.intermTypedNode), (yyvsp[(3) - (3)].interm.intermTypedNode), (yyvsp[(2) - (3)].lex).line, context->symbolTable);
+        if ((yyval.interm.intermTypedNode) == 0) {
+            context->binaryOpError((yyvsp[(2) - (3)].lex).line, "^^", (yyvsp[(1) - (3)].interm.intermTypedNode)->getCompleteString(), (yyvsp[(3) - (3)].interm.intermTypedNode)->getCompleteString());
+            context->recover();
+            ConstantUnion *unionArray = new ConstantUnion[1];
+            unionArray->setBConst(false);
+            (yyval.interm.intermTypedNode) = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), (yyvsp[(2) - (3)].lex).line);
+        }
+    }
+    break;
+
+  case 57:
+
+    { (yyval.interm.intermTypedNode) = (yyvsp[(1) - (1)].interm.intermTypedNode); }
+    break;
+
+  case 58:
+
+    {
+        (yyval.interm.intermTypedNode) = context->intermediate.addBinaryMath(EOpLogicalOr, (yyvsp[(1) - (3)].interm.intermTypedNode), (yyvsp[(3) - (3)].interm.intermTypedNode), (yyvsp[(2) - (3)].lex).line, context->symbolTable);
+        if ((yyval.interm.intermTypedNode) == 0) {
+            context->binaryOpError((yyvsp[(2) - (3)].lex).line, "||", (yyvsp[(1) - (3)].interm.intermTypedNode)->getCompleteString(), (yyvsp[(3) - (3)].interm.intermTypedNode)->getCompleteString());
+            context->recover();
+            ConstantUnion *unionArray = new ConstantUnion[1];
+            unionArray->setBConst(false);
+            (yyval.interm.intermTypedNode) = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), (yyvsp[(2) - (3)].lex).line);
+        }
+    }
+    break;
+
+  case 59:
+
+    { (yyval.interm.intermTypedNode) = (yyvsp[(1) - (1)].interm.intermTypedNode); }
+    break;
+
+  case 60:
+
+    {
+       if (context->boolErrorCheck((yyvsp[(2) - (5)].lex).line, (yyvsp[(1) - (5)].interm.intermTypedNode)))
+            context->recover();
+
+        (yyval.interm.intermTypedNode) = context->intermediate.addSelection((yyvsp[(1) - (5)].interm.intermTypedNode), (yyvsp[(3) - (5)].interm.intermTypedNode), (yyvsp[(5) - (5)].interm.intermTypedNode), (yyvsp[(2) - (5)].lex).line);
+        if ((yyvsp[(3) - (5)].interm.intermTypedNode)->getType() != (yyvsp[(5) - (5)].interm.intermTypedNode)->getType())
+            (yyval.interm.intermTypedNode) = 0;
+
+        if ((yyval.interm.intermTypedNode) == 0) {
+            context->binaryOpError((yyvsp[(2) - (5)].lex).line, ":", (yyvsp[(3) - (5)].interm.intermTypedNode)->getCompleteString(), (yyvsp[(5) - (5)].interm.intermTypedNode)->getCompleteString());
+            context->recover();
+            (yyval.interm.intermTypedNode) = (yyvsp[(5) - (5)].interm.intermTypedNode);
+        }
+    }
+    break;
+
+  case 61:
+
+    { (yyval.interm.intermTypedNode) = (yyvsp[(1) - (1)].interm.intermTypedNode); }
+    break;
+
+  case 62:
+
+    {
+        if (context->lValueErrorCheck((yyvsp[(2) - (3)].interm).line, "assign", (yyvsp[(1) - (3)].interm.intermTypedNode)))
+            context->recover();
+        (yyval.interm.intermTypedNode) = context->intermediate.addAssign((yyvsp[(2) - (3)].interm).op, (yyvsp[(1) - (3)].interm.intermTypedNode), (yyvsp[(3) - (3)].interm.intermTypedNode), (yyvsp[(2) - (3)].interm).line);
+        if ((yyval.interm.intermTypedNode) == 0) {
+            context->assignError((yyvsp[(2) - (3)].interm).line, "assign", (yyvsp[(1) - (3)].interm.intermTypedNode)->getCompleteString(), (yyvsp[(3) - (3)].interm.intermTypedNode)->getCompleteString());
+            context->recover();
+            (yyval.interm.intermTypedNode) = (yyvsp[(1) - (3)].interm.intermTypedNode);
+        }
+    }
+    break;
+
+  case 63:
+
+    {                                    (yyval.interm).line = (yyvsp[(1) - (1)].lex).line; (yyval.interm).op = EOpAssign; }
+    break;
+
+  case 64:
+
+    { FRAG_VERT_ONLY("*=", (yyvsp[(1) - (1)].lex).line);     (yyval.interm).line = (yyvsp[(1) - (1)].lex).line; (yyval.interm).op = EOpMulAssign; }
+    break;
+
+  case 65:
+
+    { FRAG_VERT_ONLY("/=", (yyvsp[(1) - (1)].lex).line);     (yyval.interm).line = (yyvsp[(1) - (1)].lex).line; (yyval.interm).op = EOpDivAssign; }
+    break;
+
+  case 66:
+
+    {                                    (yyval.interm).line = (yyvsp[(1) - (1)].lex).line; (yyval.interm).op = EOpAddAssign; }
+    break;
+
+  case 67:
+
+    {                                    (yyval.interm).line = (yyvsp[(1) - (1)].lex).line; (yyval.interm).op = EOpSubAssign; }
+    break;
+
+  case 68:
+
+    {
+        (yyval.interm.intermTypedNode) = (yyvsp[(1) - (1)].interm.intermTypedNode);
+    }
+    break;
+
+  case 69:
+
+    {
+        (yyval.interm.intermTypedNode) = context->intermediate.addComma((yyvsp[(1) - (3)].interm.intermTypedNode), (yyvsp[(3) - (3)].interm.intermTypedNode), (yyvsp[(2) - (3)].lex).line);
+        if ((yyval.interm.intermTypedNode) == 0) {
+            context->binaryOpError((yyvsp[(2) - (3)].lex).line, ",", (yyvsp[(1) - (3)].interm.intermTypedNode)->getCompleteString(), (yyvsp[(3) - (3)].interm.intermTypedNode)->getCompleteString());
+            context->recover();
+            (yyval.interm.intermTypedNode) = (yyvsp[(3) - (3)].interm.intermTypedNode);
+        }
+    }
+    break;
+
+  case 70:
+
+    {
+        if (context->constErrorCheck((yyvsp[(1) - (1)].interm.intermTypedNode)))
+            context->recover();
+        (yyval.interm.intermTypedNode) = (yyvsp[(1) - (1)].interm.intermTypedNode);
+    }
+    break;
+
+  case 71:
+
+    {
+        TFunction &function = *((yyvsp[(1) - (2)].interm).function);
+        
+        TIntermAggregate *prototype = new TIntermAggregate;
+        prototype->setType(function.getReturnType());
+        prototype->setName(function.getName());
+        
+        for (int i = 0; i < function.getParamCount(); i++)
+        {
+            const TParameter &param = function.getParam(i);
+            if (param.name != 0)
+            {
+                TVariable *variable = new TVariable(param.name, *param.type);
+                
+                prototype = context->intermediate.growAggregate(prototype, context->intermediate.addSymbol(variable->getUniqueId(), variable->getName(), variable->getType(), (yyvsp[(1) - (2)].interm).line), (yyvsp[(1) - (2)].interm).line);
+            }
+            else
+            {
+                prototype = context->intermediate.growAggregate(prototype, context->intermediate.addSymbol(0, "", *param.type, (yyvsp[(1) - (2)].interm).line), (yyvsp[(1) - (2)].interm).line);
+            }
+        }
+        
+        prototype->setOp(EOpPrototype);
+        (yyval.interm.intermNode) = prototype;
+
+        context->symbolTable.pop();
+    }
+    break;
+
+  case 72:
+
+    {
+        if ((yyvsp[(1) - (2)].interm).intermAggregate)
+            (yyvsp[(1) - (2)].interm).intermAggregate->setOp(EOpDeclaration);
+        (yyval.interm.intermNode) = (yyvsp[(1) - (2)].interm).intermAggregate;
+    }
+    break;
+
+  case 73:
+
+    {
+        context->symbolTable.setDefaultPrecision( (yyvsp[(3) - (4)].interm.type).type, (yyvsp[(2) - (4)].interm.precision) );
+        (yyval.interm.intermNode) = 0;
+    }
+    break;
+
+  case 74:
+
+    {
+        //
+        // Multiple declarations of the same function are allowed.
+        //
+        // If this is a definition, the definition production code will check for redefinitions
+        // (we don't know at this point if it's a definition or not).
+        //
+        // Redeclarations are allowed.  But, return types and parameter qualifiers must match.
+        //
+        TFunction* prevDec = static_cast<TFunction*>(context->symbolTable.find((yyvsp[(1) - (2)].interm.function)->getMangledName()));
+        if (prevDec) {
+            if (prevDec->getReturnType() != (yyvsp[(1) - (2)].interm.function)->getReturnType()) {
+                context->error((yyvsp[(2) - (2)].lex).line, "overloaded functions must have the same return type", (yyvsp[(1) - (2)].interm.function)->getReturnType().getBasicString());
+                context->recover();
+            }
+            for (int i = 0; i < prevDec->getParamCount(); ++i) {
+                if (prevDec->getParam(i).type->getQualifier() != (yyvsp[(1) - (2)].interm.function)->getParam(i).type->getQualifier()) {
+                    context->error((yyvsp[(2) - (2)].lex).line, "overloaded functions must have the same parameter qualifiers", (yyvsp[(1) - (2)].interm.function)->getParam(i).type->getQualifierString());
+                    context->recover();
+                }
+            }
+        }
+
+        //
+        // If this is a redeclaration, it could also be a definition,
+        // in which case, we want to use the variable names from this one, and not the one that's
+        // being redeclared.  So, pass back up this declaration, not the one in the symbol table.
+        //
+        (yyval.interm).function = (yyvsp[(1) - (2)].interm.function);
+        (yyval.interm).line = (yyvsp[(2) - (2)].lex).line;
+
+        // We're at the inner scope level of the function's arguments and body statement.
+        // Add the function prototype to the surrounding scope instead.
+        context->symbolTable.getOuterLevel()->insert(*(yyval.interm).function);
+    }
+    break;
+
+  case 75:
+
+    {
+        (yyval.interm.function) = (yyvsp[(1) - (1)].interm.function);
+    }
+    break;
+
+  case 76:
+
+    {
+        (yyval.interm.function) = (yyvsp[(1) - (1)].interm.function);
+    }
+    break;
+
+  case 77:
+
+    {
+        // Add the parameter
+        (yyval.interm.function) = (yyvsp[(1) - (2)].interm.function);
+        if ((yyvsp[(2) - (2)].interm).param.type->getBasicType() != EbtVoid)
+            (yyvsp[(1) - (2)].interm.function)->addParameter((yyvsp[(2) - (2)].interm).param);
+        else
+            delete (yyvsp[(2) - (2)].interm).param.type;
+    }
+    break;
+
+  case 78:
+
+    {
+        //
+        // Only first parameter of one-parameter functions can be void
+        // The check for named parameters not being void is done in parameter_declarator
+        //
+        if ((yyvsp[(3) - (3)].interm).param.type->getBasicType() == EbtVoid) {
+            //
+            // This parameter > first is void
+            //
+            context->error((yyvsp[(2) - (3)].lex).line, "cannot be an argument type except for '(void)'", "void");
+            context->recover();
+            delete (yyvsp[(3) - (3)].interm).param.type;
+        } else {
+            // Add the parameter
+            (yyval.interm.function) = (yyvsp[(1) - (3)].interm.function);
+            (yyvsp[(1) - (3)].interm.function)->addParameter((yyvsp[(3) - (3)].interm).param);
+        }
+    }
+    break;
+
+  case 79:
+
+    {
+        if ((yyvsp[(1) - (3)].interm.type).qualifier != EvqGlobal && (yyvsp[(1) - (3)].interm.type).qualifier != EvqTemporary) {
+            context->error((yyvsp[(2) - (3)].lex).line, "no qualifiers allowed for function return", getQualifierString((yyvsp[(1) - (3)].interm.type).qualifier));
+            context->recover();
+        }
+        // make sure a sampler is not involved as well...
+        if (context->structQualifierErrorCheck((yyvsp[(2) - (3)].lex).line, (yyvsp[(1) - (3)].interm.type)))
+            context->recover();
+
+        // Add the function as a prototype after parsing it (we do not support recursion)
+        TFunction *function;
+        TType type((yyvsp[(1) - (3)].interm.type));
+        function = new TFunction((yyvsp[(2) - (3)].lex).string, type);
+        (yyval.interm.function) = function;
+        
+        context->symbolTable.push();
+    }
+    break;
+
+  case 80:
+
+    {
+        if ((yyvsp[(1) - (2)].interm.type).type == EbtVoid) {
+            context->error((yyvsp[(2) - (2)].lex).line, "illegal use of type 'void'", (yyvsp[(2) - (2)].lex).string->c_str());
+            context->recover();
+        }
+        if (context->reservedErrorCheck((yyvsp[(2) - (2)].lex).line, *(yyvsp[(2) - (2)].lex).string))
+            context->recover();
+        TParameter param = {(yyvsp[(2) - (2)].lex).string, new TType((yyvsp[(1) - (2)].interm.type))};
+        (yyval.interm).line = (yyvsp[(2) - (2)].lex).line;
+        (yyval.interm).param = param;
+    }
+    break;
+
+  case 81:
+
+    {
+        // Check that we can make an array out of this type
+        if (context->arrayTypeErrorCheck((yyvsp[(3) - (5)].lex).line, (yyvsp[(1) - (5)].interm.type)))
+            context->recover();
+
+        if (context->reservedErrorCheck((yyvsp[(2) - (5)].lex).line, *(yyvsp[(2) - (5)].lex).string))
+            context->recover();
+
+        int size;
+        if (context->arraySizeErrorCheck((yyvsp[(3) - (5)].lex).line, (yyvsp[(4) - (5)].interm.intermTypedNode), size))
+            context->recover();
+        (yyvsp[(1) - (5)].interm.type).setArray(true, size);
+
+        TType* type = new TType((yyvsp[(1) - (5)].interm.type));
+        TParameter param = { (yyvsp[(2) - (5)].lex).string, type };
+        (yyval.interm).line = (yyvsp[(2) - (5)].lex).line;
+        (yyval.interm).param = param;
+    }
+    break;
+
+  case 82:
+
+    {
+        (yyval.interm) = (yyvsp[(3) - (3)].interm);
+        if (context->paramErrorCheck((yyvsp[(3) - (3)].interm).line, (yyvsp[(1) - (3)].interm.type).qualifier, (yyvsp[(2) - (3)].interm.qualifier), (yyval.interm).param.type))
+            context->recover();
+    }
+    break;
+
+  case 83:
+
+    {
+        (yyval.interm) = (yyvsp[(2) - (2)].interm);
+        if (context->parameterSamplerErrorCheck((yyvsp[(2) - (2)].interm).line, (yyvsp[(1) - (2)].interm.qualifier), *(yyvsp[(2) - (2)].interm).param.type))
+            context->recover();
+        if (context->paramErrorCheck((yyvsp[(2) - (2)].interm).line, EvqTemporary, (yyvsp[(1) - (2)].interm.qualifier), (yyval.interm).param.type))
+            context->recover();
+    }
+    break;
+
+  case 84:
+
+    {
+        (yyval.interm) = (yyvsp[(3) - (3)].interm);
+        if (context->paramErrorCheck((yyvsp[(3) - (3)].interm).line, (yyvsp[(1) - (3)].interm.type).qualifier, (yyvsp[(2) - (3)].interm.qualifier), (yyval.interm).param.type))
+            context->recover();
+    }
+    break;
+
+  case 85:
+
+    {
+        (yyval.interm) = (yyvsp[(2) - (2)].interm);
+        if (context->parameterSamplerErrorCheck((yyvsp[(2) - (2)].interm).line, (yyvsp[(1) - (2)].interm.qualifier), *(yyvsp[(2) - (2)].interm).param.type))
+            context->recover();
+        if (context->paramErrorCheck((yyvsp[(2) - (2)].interm).line, EvqTemporary, (yyvsp[(1) - (2)].interm.qualifier), (yyval.interm).param.type))
+            context->recover();
+    }
+    break;
+
+  case 86:
+
+    {
+        (yyval.interm.qualifier) = EvqIn;
+    }
+    break;
+
+  case 87:
+
+    {
+        (yyval.interm.qualifier) = EvqIn;
+    }
+    break;
+
+  case 88:
+
+    {
+        (yyval.interm.qualifier) = EvqOut;
+    }
+    break;
+
+  case 89:
+
+    {
+        (yyval.interm.qualifier) = EvqInOut;
+    }
+    break;
+
+  case 90:
+
+    {
+        TParameter param = { 0, new TType((yyvsp[(1) - (1)].interm.type)) };
+        (yyval.interm).param = param;
+    }
+    break;
+
+  case 91:
+
+    {
+        (yyval.interm) = (yyvsp[(1) - (1)].interm);
+    }
+    break;
+
+  case 92:
+
+    {
+        if ((yyvsp[(1) - (3)].interm).type.type == EbtInvariant && !(yyvsp[(3) - (3)].lex).symbol)
+        {
+            context->error((yyvsp[(3) - (3)].lex).line, "undeclared identifier declared as invariant", (yyvsp[(3) - (3)].lex).string->c_str());
+            context->recover();
+        }
+
+        TIntermSymbol* symbol = context->intermediate.addSymbol(0, *(yyvsp[(3) - (3)].lex).string, TType((yyvsp[(1) - (3)].interm).type), (yyvsp[(3) - (3)].lex).line);
+        (yyval.interm).intermAggregate = context->intermediate.growAggregate((yyvsp[(1) - (3)].interm).intermNode, symbol, (yyvsp[(3) - (3)].lex).line);
+        
+        if (context->structQualifierErrorCheck((yyvsp[(3) - (3)].lex).line, (yyval.interm).type))
+            context->recover();
+
+        if (context->nonInitConstErrorCheck((yyvsp[(3) - (3)].lex).line, *(yyvsp[(3) - (3)].lex).string, (yyval.interm).type, false))
+            context->recover();
+
+        TVariable* variable = 0;
+        if (context->nonInitErrorCheck((yyvsp[(3) - (3)].lex).line, *(yyvsp[(3) - (3)].lex).string, (yyval.interm).type, variable))
+            context->recover();
+        if (symbol && variable)
+            symbol->setId(variable->getUniqueId());
+    }
+    break;
+
+  case 93:
+
+    {
+        if (context->structQualifierErrorCheck((yyvsp[(3) - (5)].lex).line, (yyvsp[(1) - (5)].interm).type))
+            context->recover();
+
+        if (context->nonInitConstErrorCheck((yyvsp[(3) - (5)].lex).line, *(yyvsp[(3) - (5)].lex).string, (yyvsp[(1) - (5)].interm).type, true))
+            context->recover();
+
+        (yyval.interm) = (yyvsp[(1) - (5)].interm);
+
+        if (context->arrayTypeErrorCheck((yyvsp[(4) - (5)].lex).line, (yyvsp[(1) - (5)].interm).type) || context->arrayQualifierErrorCheck((yyvsp[(4) - (5)].lex).line, (yyvsp[(1) - (5)].interm).type))
+            context->recover();
+        else {
+            (yyvsp[(1) - (5)].interm).type.setArray(true);
+            TVariable* variable;
+            if (context->arrayErrorCheck((yyvsp[(4) - (5)].lex).line, *(yyvsp[(3) - (5)].lex).string, (yyvsp[(1) - (5)].interm).type, variable))
+                context->recover();
+        }
+    }
+    break;
+
+  case 94:
+
+    {
+        if (context->structQualifierErrorCheck((yyvsp[(3) - (6)].lex).line, (yyvsp[(1) - (6)].interm).type))
+            context->recover();
+
+        if (context->nonInitConstErrorCheck((yyvsp[(3) - (6)].lex).line, *(yyvsp[(3) - (6)].lex).string, (yyvsp[(1) - (6)].interm).type, true))
+            context->recover();
+
+        (yyval.interm) = (yyvsp[(1) - (6)].interm);
+
+        if (context->arrayTypeErrorCheck((yyvsp[(4) - (6)].lex).line, (yyvsp[(1) - (6)].interm).type) || context->arrayQualifierErrorCheck((yyvsp[(4) - (6)].lex).line, (yyvsp[(1) - (6)].interm).type))
+            context->recover();
+        else {
+            int size;
+            if (context->arraySizeErrorCheck((yyvsp[(4) - (6)].lex).line, (yyvsp[(5) - (6)].interm.intermTypedNode), size))
+                context->recover();
+            (yyvsp[(1) - (6)].interm).type.setArray(true, size);
+            TVariable* variable = 0;
+            if (context->arrayErrorCheck((yyvsp[(4) - (6)].lex).line, *(yyvsp[(3) - (6)].lex).string, (yyvsp[(1) - (6)].interm).type, variable))
+                context->recover();
+            TType type = TType((yyvsp[(1) - (6)].interm).type);
+            type.setArraySize(size);
+            (yyval.interm).intermAggregate = context->intermediate.growAggregate((yyvsp[(1) - (6)].interm).intermNode, context->intermediate.addSymbol(variable ? variable->getUniqueId() : 0, *(yyvsp[(3) - (6)].lex).string, type, (yyvsp[(3) - (6)].lex).line), (yyvsp[(3) - (6)].lex).line);
+        }
+    }
+    break;
+
+  case 95:
+
+    {
+        if (context->structQualifierErrorCheck((yyvsp[(3) - (5)].lex).line, (yyvsp[(1) - (5)].interm).type))
+            context->recover();
+
+        (yyval.interm) = (yyvsp[(1) - (5)].interm);
+
+        TIntermNode* intermNode;
+        if (!context->executeInitializer((yyvsp[(3) - (5)].lex).line, *(yyvsp[(3) - (5)].lex).string, (yyvsp[(1) - (5)].interm).type, (yyvsp[(5) - (5)].interm.intermTypedNode), intermNode)) {
+            //
+            // build the intermediate representation
+            //
+            if (intermNode)
+        (yyval.interm).intermAggregate = context->intermediate.growAggregate((yyvsp[(1) - (5)].interm).intermNode, intermNode, (yyvsp[(4) - (5)].lex).line);
+            else
+                (yyval.interm).intermAggregate = (yyvsp[(1) - (5)].interm).intermAggregate;
+        } else {
+            context->recover();
+            (yyval.interm).intermAggregate = 0;
+        }
+    }
+    break;
+
+  case 96:
+
+    {
+        (yyval.interm).type = (yyvsp[(1) - (1)].interm.type);
+        (yyval.interm).intermAggregate = context->intermediate.makeAggregate(context->intermediate.addSymbol(0, "", TType((yyvsp[(1) - (1)].interm.type)), (yyvsp[(1) - (1)].interm.type).line), (yyvsp[(1) - (1)].interm.type).line);
+    }
+    break;
+
+  case 97:
+
+    {
+        TIntermSymbol* symbol = context->intermediate.addSymbol(0, *(yyvsp[(2) - (2)].lex).string, TType((yyvsp[(1) - (2)].interm.type)), (yyvsp[(2) - (2)].lex).line);
+        (yyval.interm).intermAggregate = context->intermediate.makeAggregate(symbol, (yyvsp[(2) - (2)].lex).line);
+        
+        if (context->structQualifierErrorCheck((yyvsp[(2) - (2)].lex).line, (yyval.interm).type))
+            context->recover();
+
+        if (context->nonInitConstErrorCheck((yyvsp[(2) - (2)].lex).line, *(yyvsp[(2) - (2)].lex).string, (yyval.interm).type, false))
+            context->recover();
+            
+            (yyval.interm).type = (yyvsp[(1) - (2)].interm.type);
+
+        TVariable* variable = 0;
+        if (context->nonInitErrorCheck((yyvsp[(2) - (2)].lex).line, *(yyvsp[(2) - (2)].lex).string, (yyval.interm).type, variable))
+            context->recover();
+        if (variable && symbol)
+            symbol->setId(variable->getUniqueId());
+    }
+    break;
+
+  case 98:
+
+    {
+        context->error((yyvsp[(2) - (4)].lex).line, "unsized array declarations not supported", (yyvsp[(2) - (4)].lex).string->c_str());
+        context->recover();
+
+        TIntermSymbol* symbol = context->intermediate.addSymbol(0, *(yyvsp[(2) - (4)].lex).string, TType((yyvsp[(1) - (4)].interm.type)), (yyvsp[(2) - (4)].lex).line);
+        (yyval.interm).intermAggregate = context->intermediate.makeAggregate(symbol, (yyvsp[(2) - (4)].lex).line);
+        (yyval.interm).type = (yyvsp[(1) - (4)].interm.type);
+    }
+    break;
+
+  case 99:
+
+    {
+        TType type = TType((yyvsp[(1) - (5)].interm.type));
+        int size;
+        if (context->arraySizeErrorCheck((yyvsp[(2) - (5)].lex).line, (yyvsp[(4) - (5)].interm.intermTypedNode), size))
+            context->recover();
+        type.setArraySize(size);
+        TIntermSymbol* symbol = context->intermediate.addSymbol(0, *(yyvsp[(2) - (5)].lex).string, type, (yyvsp[(2) - (5)].lex).line);
+        (yyval.interm).intermAggregate = context->intermediate.makeAggregate(symbol, (yyvsp[(2) - (5)].lex).line);
+        
+        if (context->structQualifierErrorCheck((yyvsp[(2) - (5)].lex).line, (yyvsp[(1) - (5)].interm.type)))
+            context->recover();
+
+        if (context->nonInitConstErrorCheck((yyvsp[(2) - (5)].lex).line, *(yyvsp[(2) - (5)].lex).string, (yyvsp[(1) - (5)].interm.type), true))
+            context->recover();
+
+        (yyval.interm).type = (yyvsp[(1) - (5)].interm.type);
+
+        if (context->arrayTypeErrorCheck((yyvsp[(3) - (5)].lex).line, (yyvsp[(1) - (5)].interm.type)) || context->arrayQualifierErrorCheck((yyvsp[(3) - (5)].lex).line, (yyvsp[(1) - (5)].interm.type)))
+            context->recover();
+        else {
+            int size;
+            if (context->arraySizeErrorCheck((yyvsp[(3) - (5)].lex).line, (yyvsp[(4) - (5)].interm.intermTypedNode), size))
+                context->recover();
+
+            (yyvsp[(1) - (5)].interm.type).setArray(true, size);
+            TVariable* variable = 0;
+            if (context->arrayErrorCheck((yyvsp[(3) - (5)].lex).line, *(yyvsp[(2) - (5)].lex).string, (yyvsp[(1) - (5)].interm.type), variable))
+                context->recover();
+            if (variable && symbol)
+                symbol->setId(variable->getUniqueId());
+        }
+    }
+    break;
+
+  case 100:
+
+    {
+        if (context->structQualifierErrorCheck((yyvsp[(2) - (4)].lex).line, (yyvsp[(1) - (4)].interm.type)))
+            context->recover();
+
+        (yyval.interm).type = (yyvsp[(1) - (4)].interm.type);
+
+        TIntermNode* intermNode;
+        if (!context->executeInitializer((yyvsp[(2) - (4)].lex).line, *(yyvsp[(2) - (4)].lex).string, (yyvsp[(1) - (4)].interm.type), (yyvsp[(4) - (4)].interm.intermTypedNode), intermNode)) {
+        //
+        // Build intermediate representation
+        //
+            if(intermNode)
+                (yyval.interm).intermAggregate = context->intermediate.makeAggregate(intermNode, (yyvsp[(3) - (4)].lex).line);
+            else
+                (yyval.interm).intermAggregate = 0;
+        } else {
+            context->recover();
+            (yyval.interm).intermAggregate = 0;
+        }
+    }
+    break;
+
+  case 101:
+
+    {
+        VERTEX_ONLY("invariant declaration", (yyvsp[(1) - (2)].lex).line);
+        if (context->globalErrorCheck((yyvsp[(1) - (2)].lex).line, context->symbolTable.atGlobalLevel(), "invariant varying"))
+            context->recover();
+        (yyval.interm).type.setBasic(EbtInvariant, EvqInvariantVaryingOut, (yyvsp[(2) - (2)].lex).line);
+        if (!(yyvsp[(2) - (2)].lex).symbol)
+        {
+            context->error((yyvsp[(2) - (2)].lex).line, "undeclared identifier declared as invariant", (yyvsp[(2) - (2)].lex).string->c_str());
+            context->recover();
+            
+            (yyval.interm).intermAggregate = 0;
+        }
+        else
+        {
+            TIntermSymbol *symbol = context->intermediate.addSymbol(0, *(yyvsp[(2) - (2)].lex).string, TType((yyval.interm).type), (yyvsp[(2) - (2)].lex).line);
+            (yyval.interm).intermAggregate = context->intermediate.makeAggregate(symbol, (yyvsp[(2) - (2)].lex).line);
+        }
+    }
+    break;
+
+  case 102:
+
+    {
+        (yyval.interm.type) = (yyvsp[(1) - (1)].interm.type);
+
+        if ((yyvsp[(1) - (1)].interm.type).array) {
+            context->error((yyvsp[(1) - (1)].interm.type).line, "not supported", "first-class array");
+            context->recover();
+            (yyvsp[(1) - (1)].interm.type).setArray(false);
+        }
+    }
+    break;
+
+  case 103:
+
+    {
+        if ((yyvsp[(2) - (2)].interm.type).array) {
+            context->error((yyvsp[(2) - (2)].interm.type).line, "not supported", "first-class array");
+            context->recover();
+            (yyvsp[(2) - (2)].interm.type).setArray(false);
+        }
+
+        if ((yyvsp[(1) - (2)].interm.type).qualifier == EvqAttribute &&
+            ((yyvsp[(2) - (2)].interm.type).type == EbtBool || (yyvsp[(2) - (2)].interm.type).type == EbtInt)) {
+            context->error((yyvsp[(2) - (2)].interm.type).line, "cannot be bool or int", getQualifierString((yyvsp[(1) - (2)].interm.type).qualifier));
+            context->recover();
+        }
+        if (((yyvsp[(1) - (2)].interm.type).qualifier == EvqVaryingIn || (yyvsp[(1) - (2)].interm.type).qualifier == EvqVaryingOut) &&
+            ((yyvsp[(2) - (2)].interm.type).type == EbtBool || (yyvsp[(2) - (2)].interm.type).type == EbtInt)) {
+            context->error((yyvsp[(2) - (2)].interm.type).line, "cannot be bool or int", getQualifierString((yyvsp[(1) - (2)].interm.type).qualifier));
+            context->recover();
+        }
+        (yyval.interm.type) = (yyvsp[(2) - (2)].interm.type);
+        (yyval.interm.type).qualifier = (yyvsp[(1) - (2)].interm.type).qualifier;
+    }
+    break;
+
+  case 104:
+
+    {
+        (yyval.interm.type).setBasic(EbtVoid, EvqConst, (yyvsp[(1) - (1)].lex).line);
+    }
+    break;
+
+  case 105:
+
+    {
+        VERTEX_ONLY("attribute", (yyvsp[(1) - (1)].lex).line);
+        if (context->globalErrorCheck((yyvsp[(1) - (1)].lex).line, context->symbolTable.atGlobalLevel(), "attribute"))
+            context->recover();
+        (yyval.interm.type).setBasic(EbtVoid, EvqAttribute, (yyvsp[(1) - (1)].lex).line);
+    }
+    break;
+
+  case 106:
+
+    {
+        if (context->globalErrorCheck((yyvsp[(1) - (1)].lex).line, context->symbolTable.atGlobalLevel(), "varying"))
+            context->recover();
+        if (context->shaderType == SH_VERTEX_SHADER)
+            (yyval.interm.type).setBasic(EbtVoid, EvqVaryingOut, (yyvsp[(1) - (1)].lex).line);
+        else
+            (yyval.interm.type).setBasic(EbtVoid, EvqVaryingIn, (yyvsp[(1) - (1)].lex).line);
+    }
+    break;
+
+  case 107:
+
+    {
+        if (context->globalErrorCheck((yyvsp[(1) - (2)].lex).line, context->symbolTable.atGlobalLevel(), "invariant varying"))
+            context->recover();
+        if (context->shaderType == SH_VERTEX_SHADER)
+            (yyval.interm.type).setBasic(EbtVoid, EvqInvariantVaryingOut, (yyvsp[(1) - (2)].lex).line);
+        else
+            (yyval.interm.type).setBasic(EbtVoid, EvqInvariantVaryingIn, (yyvsp[(1) - (2)].lex).line);
+    }
+    break;
+
+  case 108:
+
+    {
+        if (context->globalErrorCheck((yyvsp[(1) - (1)].lex).line, context->symbolTable.atGlobalLevel(), "uniform"))
+            context->recover();
+        (yyval.interm.type).setBasic(EbtVoid, EvqUniform, (yyvsp[(1) - (1)].lex).line);
+    }
+    break;
+
+  case 109:
+
+    {
+        (yyval.interm.type) = (yyvsp[(1) - (1)].interm.type);
+
+        if ((yyval.interm.type).precision == EbpUndefined) {
+            (yyval.interm.type).precision = context->symbolTable.getDefaultPrecision((yyvsp[(1) - (1)].interm.type).type);
+            if (context->precisionErrorCheck((yyvsp[(1) - (1)].interm.type).line, (yyval.interm.type).precision, (yyvsp[(1) - (1)].interm.type).type)) {
+                context->recover();
+            }
+        }
+    }
+    break;
+
+  case 110:
+
+    {
+        (yyval.interm.type) = (yyvsp[(2) - (2)].interm.type);
+        (yyval.interm.type).precision = (yyvsp[(1) - (2)].interm.precision);
+    }
+    break;
+
+  case 111:
+
+    {
+        (yyval.interm.precision) = EbpHigh;
+    }
+    break;
+
+  case 112:
+
+    {
+        (yyval.interm.precision) = EbpMedium;
+    }
+    break;
+
+  case 113:
+
+    {
+        (yyval.interm.precision) = EbpLow;
+    }
+    break;
+
+  case 114:
+
+    {
+        (yyval.interm.type) = (yyvsp[(1) - (1)].interm.type);
+    }
+    break;
+
+  case 115:
+
+    {
+        (yyval.interm.type) = (yyvsp[(1) - (4)].interm.type);
+
+        if (context->arrayTypeErrorCheck((yyvsp[(2) - (4)].lex).line, (yyvsp[(1) - (4)].interm.type)))
+            context->recover();
+        else {
+            int size;
+            if (context->arraySizeErrorCheck((yyvsp[(2) - (4)].lex).line, (yyvsp[(3) - (4)].interm.intermTypedNode), size))
+                context->recover();
+            (yyval.interm.type).setArray(true, size);
+        }
+    }
+    break;
+
+  case 116:
+
+    {
+        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
+        (yyval.interm.type).setBasic(EbtVoid, qual, (yyvsp[(1) - (1)].lex).line);
+    }
+    break;
+
+  case 117:
+
+    {
+        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
+        (yyval.interm.type).setBasic(EbtFloat, qual, (yyvsp[(1) - (1)].lex).line);
+    }
+    break;
+
+  case 118:
+
+    {
+        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
+        (yyval.interm.type).setBasic(EbtInt, qual, (yyvsp[(1) - (1)].lex).line);
+    }
+    break;
+
+  case 119:
+
+    {
+        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
+        (yyval.interm.type).setBasic(EbtBool, qual, (yyvsp[(1) - (1)].lex).line);
+    }
+    break;
+
+  case 120:
+
+    {
+        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
+        (yyval.interm.type).setBasic(EbtFloat, qual, (yyvsp[(1) - (1)].lex).line);
+        (yyval.interm.type).setAggregate(2);
+    }
+    break;
+
+  case 121:
+
+    {
+        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
+        (yyval.interm.type).setBasic(EbtFloat, qual, (yyvsp[(1) - (1)].lex).line);
+        (yyval.interm.type).setAggregate(3);
+    }
+    break;
+
+  case 122:
+
+    {
+        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
+        (yyval.interm.type).setBasic(EbtFloat, qual, (yyvsp[(1) - (1)].lex).line);
+        (yyval.interm.type).setAggregate(4);
+    }
+    break;
+
+  case 123:
+
+    {
+        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
+        (yyval.interm.type).setBasic(EbtBool, qual, (yyvsp[(1) - (1)].lex).line);
+        (yyval.interm.type).setAggregate(2);
+    }
+    break;
+
+  case 124:
+
+    {
+        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
+        (yyval.interm.type).setBasic(EbtBool, qual, (yyvsp[(1) - (1)].lex).line);
+        (yyval.interm.type).setAggregate(3);
+    }
+    break;
+
+  case 125:
+
+    {
+        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
+        (yyval.interm.type).setBasic(EbtBool, qual, (yyvsp[(1) - (1)].lex).line);
+        (yyval.interm.type).setAggregate(4);
+    }
+    break;
+
+  case 126:
+
+    {
+        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
+        (yyval.interm.type).setBasic(EbtInt, qual, (yyvsp[(1) - (1)].lex).line);
+        (yyval.interm.type).setAggregate(2);
+    }
+    break;
+
+  case 127:
+
+    {
+        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
+        (yyval.interm.type).setBasic(EbtInt, qual, (yyvsp[(1) - (1)].lex).line);
+        (yyval.interm.type).setAggregate(3);
+    }
+    break;
+
+  case 128:
+
+    {
+        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
+        (yyval.interm.type).setBasic(EbtInt, qual, (yyvsp[(1) - (1)].lex).line);
+        (yyval.interm.type).setAggregate(4);
+    }
+    break;
+
+  case 129:
+
+    {
+        FRAG_VERT_ONLY("mat2", (yyvsp[(1) - (1)].lex).line);
+        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
+        (yyval.interm.type).setBasic(EbtFloat, qual, (yyvsp[(1) - (1)].lex).line);
+        (yyval.interm.type).setAggregate(2, true);
+    }
+    break;
+
+  case 130:
+
+    {
+        FRAG_VERT_ONLY("mat3", (yyvsp[(1) - (1)].lex).line);
+        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
+        (yyval.interm.type).setBasic(EbtFloat, qual, (yyvsp[(1) - (1)].lex).line);
+        (yyval.interm.type).setAggregate(3, true);
+    }
+    break;
+
+  case 131:
+
+    {
+        FRAG_VERT_ONLY("mat4", (yyvsp[(1) - (1)].lex).line);
+        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
+        (yyval.interm.type).setBasic(EbtFloat, qual, (yyvsp[(1) - (1)].lex).line);
+        (yyval.interm.type).setAggregate(4, true);
+    }
+    break;
+
+  case 132:
+
+    {
+        FRAG_VERT_ONLY("sampler2D", (yyvsp[(1) - (1)].lex).line);
+        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
+        (yyval.interm.type).setBasic(EbtSampler2D, qual, (yyvsp[(1) - (1)].lex).line);
+    }
+    break;
+
+  case 133:
+
+    {
+        FRAG_VERT_ONLY("samplerCube", (yyvsp[(1) - (1)].lex).line);
+        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
+        (yyval.interm.type).setBasic(EbtSamplerCube, qual, (yyvsp[(1) - (1)].lex).line);
+    }
+    break;
+
+  case 134:
+
+    {
+        FRAG_VERT_ONLY("struct", (yyvsp[(1) - (1)].interm.type).line);
+        (yyval.interm.type) = (yyvsp[(1) - (1)].interm.type);
+        (yyval.interm.type).qualifier = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
+    }
+    break;
+
+  case 135:
+
+    {
+        //
+        // This is for user defined type names.  The lexical phase looked up the
+        // type.
+        //
+        TType& structure = static_cast<TVariable*>((yyvsp[(1) - (1)].lex).symbol)->getType();
+        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
+        (yyval.interm.type).setBasic(EbtStruct, qual, (yyvsp[(1) - (1)].lex).line);
+        (yyval.interm.type).userDef = &structure;
+    }
+    break;
+
+  case 136:
+
+    { if (context->enterStructDeclaration((yyvsp[(2) - (3)].lex).line, *(yyvsp[(2) - (3)].lex).string)) context->recover(); }
+    break;
+
+  case 137:
+
+    {
+        if (context->reservedErrorCheck((yyvsp[(2) - (6)].lex).line, *(yyvsp[(2) - (6)].lex).string))
+            context->recover();
+
+        TType* structure = new TType((yyvsp[(5) - (6)].interm.typeList), *(yyvsp[(2) - (6)].lex).string);
+        TVariable* userTypeDef = new TVariable((yyvsp[(2) - (6)].lex).string, *structure, true);
+        if (! context->symbolTable.insert(*userTypeDef)) {
+            context->error((yyvsp[(2) - (6)].lex).line, "redefinition", (yyvsp[(2) - (6)].lex).string->c_str(), "struct");
+            context->recover();
+        }
+        (yyval.interm.type).setBasic(EbtStruct, EvqTemporary, (yyvsp[(1) - (6)].lex).line);
+        (yyval.interm.type).userDef = structure;
+        context->exitStructDeclaration();
+    }
+    break;
+
+  case 138:
+
+    { if (context->enterStructDeclaration((yyvsp[(2) - (2)].lex).line, *(yyvsp[(2) - (2)].lex).string)) context->recover(); }
+    break;
+
+  case 139:
+
+    {
+        TType* structure = new TType((yyvsp[(4) - (5)].interm.typeList), TString(""));
+        (yyval.interm.type).setBasic(EbtStruct, EvqTemporary, (yyvsp[(1) - (5)].lex).line);
+        (yyval.interm.type).userDef = structure;
+        context->exitStructDeclaration();
+    }
+    break;
+
+  case 140:
+
+    {
+        (yyval.interm.typeList) = (yyvsp[(1) - (1)].interm.typeList);
+    }
+    break;
+
+  case 141:
+
+    {
+        (yyval.interm.typeList) = (yyvsp[(1) - (2)].interm.typeList);
+        for (unsigned int i = 0; i < (yyvsp[(2) - (2)].interm.typeList)->size(); ++i) {
+            for (unsigned int j = 0; j < (yyval.interm.typeList)->size(); ++j) {
+                if ((*(yyval.interm.typeList))[j].type->getFieldName() == (*(yyvsp[(2) - (2)].interm.typeList))[i].type->getFieldName()) {
+                    context->error((*(yyvsp[(2) - (2)].interm.typeList))[i].line, "duplicate field name in structure:", "struct", (*(yyvsp[(2) - (2)].interm.typeList))[i].type->getFieldName().c_str());
+                    context->recover();
+                }
+            }
+            (yyval.interm.typeList)->push_back((*(yyvsp[(2) - (2)].interm.typeList))[i]);
+        }
+    }
+    break;
+
+  case 142:
+
+    {
+        (yyval.interm.typeList) = (yyvsp[(2) - (3)].interm.typeList);
+
+        if (context->voidErrorCheck((yyvsp[(1) - (3)].interm.type).line, (*(yyvsp[(2) - (3)].interm.typeList))[0].type->getFieldName(), (yyvsp[(1) - (3)].interm.type))) {
+            context->recover();
+        }
+        for (unsigned int i = 0; i < (yyval.interm.typeList)->size(); ++i) {
+            //
+            // Careful not to replace already known aspects of type, like array-ness
+            //
+            TType* type = (*(yyval.interm.typeList))[i].type;
+            type->setBasicType((yyvsp[(1) - (3)].interm.type).type);
+            type->setNominalSize((yyvsp[(1) - (3)].interm.type).size);
+            type->setMatrix((yyvsp[(1) - (3)].interm.type).matrix);
+            type->setPrecision((yyvsp[(1) - (3)].interm.type).precision);
+
+            // don't allow arrays of arrays
+            if (type->isArray()) {
+                if (context->arrayTypeErrorCheck((yyvsp[(1) - (3)].interm.type).line, (yyvsp[(1) - (3)].interm.type)))
+                    context->recover();
+            }
+            if ((yyvsp[(1) - (3)].interm.type).array)
+                type->setArraySize((yyvsp[(1) - (3)].interm.type).arraySize);
+            if ((yyvsp[(1) - (3)].interm.type).userDef) {
+                type->setStruct((yyvsp[(1) - (3)].interm.type).userDef->getStruct());
+                type->setTypeName((yyvsp[(1) - (3)].interm.type).userDef->getTypeName());
+            }
+
+            if (context->structNestingErrorCheck((yyvsp[(1) - (3)].interm.type).line, *type)) {
+                context->recover();
+            }
+        }
+    }
+    break;
+
+  case 143:
+
+    {
+        (yyval.interm.typeList) = NewPoolTTypeList();
+        (yyval.interm.typeList)->push_back((yyvsp[(1) - (1)].interm.typeLine));
+    }
+    break;
+
+  case 144:
+
+    {
+        (yyval.interm.typeList)->push_back((yyvsp[(3) - (3)].interm.typeLine));
+    }
+    break;
+
+  case 145:
+
+    {
+        if (context->reservedErrorCheck((yyvsp[(1) - (1)].lex).line, *(yyvsp[(1) - (1)].lex).string))
+            context->recover();
+
+        (yyval.interm.typeLine).type = new TType(EbtVoid, EbpUndefined);
+        (yyval.interm.typeLine).line = (yyvsp[(1) - (1)].lex).line;
+        (yyval.interm.typeLine).type->setFieldName(*(yyvsp[(1) - (1)].lex).string);
+    }
+    break;
+
+  case 146:
+
+    {
+        if (context->reservedErrorCheck((yyvsp[(1) - (4)].lex).line, *(yyvsp[(1) - (4)].lex).string))
+            context->recover();
+
+        (yyval.interm.typeLine).type = new TType(EbtVoid, EbpUndefined);
+        (yyval.interm.typeLine).line = (yyvsp[(1) - (4)].lex).line;
+        (yyval.interm.typeLine).type->setFieldName(*(yyvsp[(1) - (4)].lex).string);
+
+        int size;
+        if (context->arraySizeErrorCheck((yyvsp[(2) - (4)].lex).line, (yyvsp[(3) - (4)].interm.intermTypedNode), size))
+            context->recover();
+        (yyval.interm.typeLine).type->setArraySize(size);
+    }
+    break;
+
+  case 147:
+
+    { (yyval.interm.intermTypedNode) = (yyvsp[(1) - (1)].interm.intermTypedNode); }
+    break;
+
+  case 148:
+
+    { (yyval.interm.intermNode) = (yyvsp[(1) - (1)].interm.intermNode); }
+    break;
+
+  case 149:
+
+    { (yyval.interm.intermNode) = (yyvsp[(1) - (1)].interm.intermAggregate); }
+    break;
+
+  case 150:
+
+    { (yyval.interm.intermNode) = (yyvsp[(1) - (1)].interm.intermNode); }
+    break;
+
+  case 151:
+
+    { (yyval.interm.intermNode) = (yyvsp[(1) - (1)].interm.intermNode); }
+    break;
+
+  case 152:
+
+    { (yyval.interm.intermNode) = (yyvsp[(1) - (1)].interm.intermNode); }
+    break;
+
+  case 153:
+
+    { (yyval.interm.intermNode) = (yyvsp[(1) - (1)].interm.intermNode); }
+    break;
+
+  case 154:
+
+    { (yyval.interm.intermNode) = (yyvsp[(1) - (1)].interm.intermNode); }
+    break;
+
+  case 155:
+
+    { (yyval.interm.intermNode) = (yyvsp[(1) - (1)].interm.intermNode); }
+    break;
+
+  case 156:
+
+    { (yyval.interm.intermAggregate) = 0; }
+    break;
+
+  case 157:
+
+    { context->symbolTable.push(); }
+    break;
+
+  case 158:
+
+    { context->symbolTable.pop(); }
+    break;
+
+  case 159:
+
+    {
+        if ((yyvsp[(3) - (5)].interm.intermAggregate) != 0) {
+            (yyvsp[(3) - (5)].interm.intermAggregate)->setOp(EOpSequence);
+            (yyvsp[(3) - (5)].interm.intermAggregate)->setEndLine((yyvsp[(5) - (5)].lex).line);
+        }
+        (yyval.interm.intermAggregate) = (yyvsp[(3) - (5)].interm.intermAggregate);
+    }
+    break;
+
+  case 160:
+
+    { (yyval.interm.intermNode) = (yyvsp[(1) - (1)].interm.intermNode); }
+    break;
+
+  case 161:
+
+    { (yyval.interm.intermNode) = (yyvsp[(1) - (1)].interm.intermNode); }
+    break;
+
+  case 162:
+
+    { context->symbolTable.push(); }
+    break;
+
+  case 163:
+
+    { context->symbolTable.pop(); (yyval.interm.intermNode) = (yyvsp[(2) - (2)].interm.intermNode); }
+    break;
+
+  case 164:
+
+    { context->symbolTable.push(); }
+    break;
+
+  case 165:
+
+    { context->symbolTable.pop(); (yyval.interm.intermNode) = (yyvsp[(2) - (2)].interm.intermNode); }
+    break;
+
+  case 166:
+
+    {
+        (yyval.interm.intermNode) = 0;
+    }
+    break;
+
+  case 167:
+
+    {
+        if ((yyvsp[(2) - (3)].interm.intermAggregate)) {
+            (yyvsp[(2) - (3)].interm.intermAggregate)->setOp(EOpSequence);
+            (yyvsp[(2) - (3)].interm.intermAggregate)->setEndLine((yyvsp[(3) - (3)].lex).line);
+        }
+        (yyval.interm.intermNode) = (yyvsp[(2) - (3)].interm.intermAggregate);
+    }
+    break;
+
+  case 168:
+
+    {
+        (yyval.interm.intermAggregate) = context->intermediate.makeAggregate((yyvsp[(1) - (1)].interm.intermNode), 0);
+    }
+    break;
+
+  case 169:
+
+    {
+        (yyval.interm.intermAggregate) = context->intermediate.growAggregate((yyvsp[(1) - (2)].interm.intermAggregate), (yyvsp[(2) - (2)].interm.intermNode), 0);
+    }
+    break;
+
+  case 170:
+
+    { (yyval.interm.intermNode) = 0; }
+    break;
+
+  case 171:
+
+    { (yyval.interm.intermNode) = static_cast<TIntermNode*>((yyvsp[(1) - (2)].interm.intermTypedNode)); }
+    break;
+
+  case 172:
+
+    {
+        if (context->boolErrorCheck((yyvsp[(1) - (5)].lex).line, (yyvsp[(3) - (5)].interm.intermTypedNode)))
+            context->recover();
+        (yyval.interm.intermNode) = context->intermediate.addSelection((yyvsp[(3) - (5)].interm.intermTypedNode), (yyvsp[(5) - (5)].interm.nodePair), (yyvsp[(1) - (5)].lex).line);
+    }
+    break;
+
+  case 173:
+
+    {
+        (yyval.interm.nodePair).node1 = (yyvsp[(1) - (3)].interm.intermNode);
+        (yyval.interm.nodePair).node2 = (yyvsp[(3) - (3)].interm.intermNode);
+    }
+    break;
+
+  case 174:
+
+    {
+        (yyval.interm.nodePair).node1 = (yyvsp[(1) - (1)].interm.intermNode);
+        (yyval.interm.nodePair).node2 = 0;
+    }
+    break;
+
+  case 175:
+
+    {
+        (yyval.interm.intermTypedNode) = (yyvsp[(1) - (1)].interm.intermTypedNode);
+        if (context->boolErrorCheck((yyvsp[(1) - (1)].interm.intermTypedNode)->getLine(), (yyvsp[(1) - (1)].interm.intermTypedNode)))
+            context->recover();
+    }
+    break;
+
+  case 176:
+
+    {
+        TIntermNode* intermNode;
+        if (context->structQualifierErrorCheck((yyvsp[(2) - (4)].lex).line, (yyvsp[(1) - (4)].interm.type)))
+            context->recover();
+        if (context->boolErrorCheck((yyvsp[(2) - (4)].lex).line, (yyvsp[(1) - (4)].interm.type)))
+            context->recover();
+
+        if (!context->executeInitializer((yyvsp[(2) - (4)].lex).line, *(yyvsp[(2) - (4)].lex).string, (yyvsp[(1) - (4)].interm.type), (yyvsp[(4) - (4)].interm.intermTypedNode), intermNode))
+            (yyval.interm.intermTypedNode) = (yyvsp[(4) - (4)].interm.intermTypedNode);
+        else {
+            context->recover();
+            (yyval.interm.intermTypedNode) = 0;
+        }
+    }
+    break;
+
+  case 177:
+
+    { context->symbolTable.push(); ++context->loopNestingLevel; }
+    break;
+
+  case 178:
+
+    {
+        context->symbolTable.pop();
+        (yyval.interm.intermNode) = context->intermediate.addLoop(ELoopWhile, 0, (yyvsp[(4) - (6)].interm.intermTypedNode), 0, (yyvsp[(6) - (6)].interm.intermNode), (yyvsp[(1) - (6)].lex).line);
+        --context->loopNestingLevel;
+    }
+    break;
+
+  case 179:
+
+    { ++context->loopNestingLevel; }
+    break;
+
+  case 180:
+
+    {
+        if (context->boolErrorCheck((yyvsp[(8) - (8)].lex).line, (yyvsp[(6) - (8)].interm.intermTypedNode)))
+            context->recover();
+
+        (yyval.interm.intermNode) = context->intermediate.addLoop(ELoopDoWhile, 0, (yyvsp[(6) - (8)].interm.intermTypedNode), 0, (yyvsp[(3) - (8)].interm.intermNode), (yyvsp[(4) - (8)].lex).line);
+        --context->loopNestingLevel;
+    }
+    break;
+
+  case 181:
+
+    { context->symbolTable.push(); ++context->loopNestingLevel; }
+    break;
+
+  case 182:
+
+    {
+        context->symbolTable.pop();
+        (yyval.interm.intermNode) = context->intermediate.addLoop(ELoopFor, (yyvsp[(4) - (7)].interm.intermNode), reinterpret_cast<TIntermTyped*>((yyvsp[(5) - (7)].interm.nodePair).node1), reinterpret_cast<TIntermTyped*>((yyvsp[(5) - (7)].interm.nodePair).node2), (yyvsp[(7) - (7)].interm.intermNode), (yyvsp[(1) - (7)].lex).line);
+        --context->loopNestingLevel;
+    }
+    break;
+
+  case 183:
+
+    {
+        (yyval.interm.intermNode) = (yyvsp[(1) - (1)].interm.intermNode);
+    }
+    break;
+
+  case 184:
+
+    {
+        (yyval.interm.intermNode) = (yyvsp[(1) - (1)].interm.intermNode);
+    }
+    break;
+
+  case 185:
+
+    {
+        (yyval.interm.intermTypedNode) = (yyvsp[(1) - (1)].interm.intermTypedNode);
+    }
+    break;
+
+  case 186:
+
+    {
+        (yyval.interm.intermTypedNode) = 0;
+    }
+    break;
+
+  case 187:
+
+    {
+        (yyval.interm.nodePair).node1 = (yyvsp[(1) - (2)].interm.intermTypedNode);
+        (yyval.interm.nodePair).node2 = 0;
+    }
+    break;
+
+  case 188:
+
+    {
+        (yyval.interm.nodePair).node1 = (yyvsp[(1) - (3)].interm.intermTypedNode);
+        (yyval.interm.nodePair).node2 = (yyvsp[(3) - (3)].interm.intermTypedNode);
+    }
+    break;
+
+  case 189:
+
+    {
+        if (context->loopNestingLevel <= 0) {
+            context->error((yyvsp[(1) - (2)].lex).line, "continue statement only allowed in loops", "");
+            context->recover();
+        }
+        (yyval.interm.intermNode) = context->intermediate.addBranch(EOpContinue, (yyvsp[(1) - (2)].lex).line);
+    }
+    break;
+
+  case 190:
+
+    {
+        if (context->loopNestingLevel <= 0) {
+            context->error((yyvsp[(1) - (2)].lex).line, "break statement only allowed in loops", "");
+            context->recover();
+        }
+        (yyval.interm.intermNode) = context->intermediate.addBranch(EOpBreak, (yyvsp[(1) - (2)].lex).line);
+    }
+    break;
+
+  case 191:
+
+    {
+        (yyval.interm.intermNode) = context->intermediate.addBranch(EOpReturn, (yyvsp[(1) - (2)].lex).line);
+        if (context->currentFunctionType->getBasicType() != EbtVoid) {
+            context->error((yyvsp[(1) - (2)].lex).line, "non-void function must return a value", "return");
+            context->recover();
+        }
+    }
+    break;
+
+  case 192:
+
+    {
+        (yyval.interm.intermNode) = context->intermediate.addBranch(EOpReturn, (yyvsp[(2) - (3)].interm.intermTypedNode), (yyvsp[(1) - (3)].lex).line);
+        context->functionReturnsValue = true;
+        if (context->currentFunctionType->getBasicType() == EbtVoid) {
+            context->error((yyvsp[(1) - (3)].lex).line, "void function cannot return a value", "return");
+            context->recover();
+        } else if (*(context->currentFunctionType) != (yyvsp[(2) - (3)].interm.intermTypedNode)->getType()) {
+            context->error((yyvsp[(1) - (3)].lex).line, "function return is not matching type:", "return");
+            context->recover();
+        }
+    }
+    break;
+
+  case 193:
+
+    {
+        FRAG_ONLY("discard", (yyvsp[(1) - (2)].lex).line);
+        (yyval.interm.intermNode) = context->intermediate.addBranch(EOpKill, (yyvsp[(1) - (2)].lex).line);
+    }
+    break;
+
+  case 194:
+
+    {
+        (yyval.interm.intermNode) = (yyvsp[(1) - (1)].interm.intermNode);
+        context->treeRoot = (yyval.interm.intermNode);
+    }
+    break;
+
+  case 195:
+
+    {
+        (yyval.interm.intermNode) = context->intermediate.growAggregate((yyvsp[(1) - (2)].interm.intermNode), (yyvsp[(2) - (2)].interm.intermNode), 0);
+        context->treeRoot = (yyval.interm.intermNode);
+    }
+    break;
+
+  case 196:
+
+    {
+        (yyval.interm.intermNode) = (yyvsp[(1) - (1)].interm.intermNode);
+    }
+    break;
+
+  case 197:
+
+    {
+        (yyval.interm.intermNode) = (yyvsp[(1) - (1)].interm.intermNode);
+    }
+    break;
+
+  case 198:
+
+    {
+        TFunction* function = (yyvsp[(1) - (1)].interm).function;
+        
+        const TSymbol *builtIn = context->symbolTable.findBuiltIn(function->getMangledName());
+        
+        if (builtIn)
+        {
+            context->error((yyvsp[(1) - (1)].interm).line, "built-in functions cannot be redefined", function->getName().c_str());
+            context->recover();
+        }
+        
+        TFunction* prevDec = static_cast<TFunction*>(context->symbolTable.find(function->getMangledName()));
+        //
+        // Note:  'prevDec' could be 'function' if this is the first time we've seen function
+        // as it would have just been put in the symbol table.  Otherwise, we're looking up
+        // an earlier occurance.
+        //
+        if (prevDec->isDefined()) {
+            //
+            // Then this function already has a body.
+            //
+            context->error((yyvsp[(1) - (1)].interm).line, "function already has a body", function->getName().c_str());
+            context->recover();
+        }
+        prevDec->setDefined();
+
+        //
+        // Raise error message if main function takes any parameters or return anything other than void
+        //
+        if (function->getName() == "main") {
+            if (function->getParamCount() > 0) {
+                context->error((yyvsp[(1) - (1)].interm).line, "function cannot take any parameter(s)", function->getName().c_str());
+                context->recover();
+            }
+            if (function->getReturnType().getBasicType() != EbtVoid) {
+                context->error((yyvsp[(1) - (1)].interm).line, "", function->getReturnType().getBasicString(), "main function cannot return a value");
+                context->recover();
+            }
+        }
+
+        //
+        // Remember the return type for later checking for RETURN statements.
+        //
+        context->currentFunctionType = &(prevDec->getReturnType());
+        context->functionReturnsValue = false;
+
+        //
+        // Insert parameters into the symbol table.
+        // If the parameter has no name, it's not an error, just don't insert it
+        // (could be used for unused args).
+        //
+        // Also, accumulate the list of parameters into the HIL, so lower level code
+        // knows where to find parameters.
+        //
+        TIntermAggregate* paramNodes = new TIntermAggregate;
+        for (int i = 0; i < function->getParamCount(); i++) {
+            const TParameter& param = function->getParam(i);
+            if (param.name != 0) {
+                TVariable *variable = new TVariable(param.name, *param.type);
+                //
+                // Insert the parameters with name in the symbol table.
+                //
+                if (! context->symbolTable.insert(*variable)) {
+                    context->error((yyvsp[(1) - (1)].interm).line, "redefinition", variable->getName().c_str());
+                    context->recover();
+                    delete variable;
+                }
+
+                //
+                // Add the parameter to the HIL
+                //
+                paramNodes = context->intermediate.growAggregate(
+                                               paramNodes,
+                                               context->intermediate.addSymbol(variable->getUniqueId(),
+                                                                       variable->getName(),
+                                                                       variable->getType(), (yyvsp[(1) - (1)].interm).line),
+                                               (yyvsp[(1) - (1)].interm).line);
+            } else {
+                paramNodes = context->intermediate.growAggregate(paramNodes, context->intermediate.addSymbol(0, "", *param.type, (yyvsp[(1) - (1)].interm).line), (yyvsp[(1) - (1)].interm).line);
+            }
+        }
+        context->intermediate.setAggregateOperator(paramNodes, EOpParameters, (yyvsp[(1) - (1)].interm).line);
+        (yyvsp[(1) - (1)].interm).intermAggregate = paramNodes;
+        context->loopNestingLevel = 0;
+    }
+    break;
+
+  case 199:
+
+    {
+        //?? Check that all paths return a value if return type != void ?
+        //   May be best done as post process phase on intermediate code
+        if (context->currentFunctionType->getBasicType() != EbtVoid && ! context->functionReturnsValue) {
+            context->error((yyvsp[(1) - (3)].interm).line, "function does not return a value:", "", (yyvsp[(1) - (3)].interm).function->getName().c_str());
+            context->recover();
+        }
+        
+        (yyval.interm.intermNode) = context->intermediate.growAggregate((yyvsp[(1) - (3)].interm).intermAggregate, (yyvsp[(3) - (3)].interm.intermNode), 0);
+        context->intermediate.setAggregateOperator((yyval.interm.intermNode), EOpFunction, (yyvsp[(1) - (3)].interm).line);
+        (yyval.interm.intermNode)->getAsAggregate()->setName((yyvsp[(1) - (3)].interm).function->getMangledName().c_str());
+        (yyval.interm.intermNode)->getAsAggregate()->setType((yyvsp[(1) - (3)].interm).function->getReturnType());
+
+        // store the pragma information for debug and optimize and other vendor specific
+        // information. This information can be queried from the parse tree
+        (yyval.interm.intermNode)->getAsAggregate()->setOptimize(context->pragma().optimize);
+        (yyval.interm.intermNode)->getAsAggregate()->setDebug(context->pragma().debug);
+
+        if ((yyvsp[(3) - (3)].interm.intermNode) && (yyvsp[(3) - (3)].interm.intermNode)->getAsAggregate())
+            (yyval.interm.intermNode)->getAsAggregate()->setEndLine((yyvsp[(3) - (3)].interm.intermNode)->getAsAggregate()->getEndLine());
+
+        context->symbolTable.pop();
+    }
+    break;
+
+
+
+      default: break;
+    }
+  YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc);
+
+  YYPOPSTACK (yylen);
+  yylen = 0;
+  YY_STACK_PRINT (yyss, yyssp);
+
+  *++yyvsp = yyval;
+
+  /* Now `shift' the result of the reduction.  Determine what state
+     that goes to, based on the state we popped back to and the rule
+     number reduced by.  */
+
+  yyn = yyr1[yyn];
+
+  yystate = yypgoto[yyn - YYNTOKENS] + *yyssp;
+  if (0 <= yystate && yystate <= YYLAST && yycheck[yystate] == *yyssp)
+    yystate = yytable[yystate];
+  else
+    yystate = yydefgoto[yyn - YYNTOKENS];
+
+  goto yynewstate;
+
+
+/*------------------------------------.
+| yyerrlab -- here on detecting error |
+`------------------------------------*/
+yyerrlab:
+  /* If not already recovering from an error, report this error.  */
+  if (!yyerrstatus)
+    {
+      ++yynerrs;
+#if ! YYERROR_VERBOSE
+      yyerror (context, YY_("syntax error"));
+#else
+      {
+	YYSIZE_T yysize = yysyntax_error (0, yystate, yychar);
+	if (yymsg_alloc < yysize && yymsg_alloc < YYSTACK_ALLOC_MAXIMUM)
+	  {
+	    YYSIZE_T yyalloc = 2 * yysize;
+	    if (! (yysize <= yyalloc && yyalloc <= YYSTACK_ALLOC_MAXIMUM))
+	      yyalloc = YYSTACK_ALLOC_MAXIMUM;
+	    if (yymsg != yymsgbuf)
+	      YYSTACK_FREE (yymsg);
+	    yymsg = (char *) YYSTACK_ALLOC (yyalloc);
+	    if (yymsg)
+	      yymsg_alloc = yyalloc;
+	    else
+	      {
+		yymsg = yymsgbuf;
+		yymsg_alloc = sizeof yymsgbuf;
+	      }
+	  }
+
+	if (0 < yysize && yysize <= yymsg_alloc)
+	  {
+	    (void) yysyntax_error (yymsg, yystate, yychar);
+	    yyerror (context, yymsg);
+	  }
+	else
+	  {
+	    yyerror (context, YY_("syntax error"));
+	    if (yysize != 0)
+	      goto yyexhaustedlab;
+	  }
+      }
+#endif
+    }
+
+
+
+  if (yyerrstatus == 3)
+    {
+      /* If just tried and failed to reuse lookahead token after an
+	 error, discard it.  */
+
+      if (yychar <= YYEOF)
+	{
+	  /* Return failure if at end of input.  */
+	  if (yychar == YYEOF)
+	    YYABORT;
+	}
+      else
+	{
+	  yydestruct ("Error: discarding",
+		      yytoken, &yylval, context);
+	  yychar = YYEMPTY;
+	}
+    }
+
+  /* Else will try to reuse lookahead token after shifting the error
+     token.  */
+  goto yyerrlab1;
+
+
+/*---------------------------------------------------.
+| yyerrorlab -- error raised explicitly by YYERROR.  |
+`---------------------------------------------------*/
+yyerrorlab:
+
+  /* Pacify compilers like GCC when the user code never invokes
+     YYERROR and the label yyerrorlab therefore never appears in user
+     code.  */
+  if (/*CONSTCOND*/ 0)
+     goto yyerrorlab;
+
+  /* Do not reclaim the symbols of the rule which action triggered
+     this YYERROR.  */
+  YYPOPSTACK (yylen);
+  yylen = 0;
+  YY_STACK_PRINT (yyss, yyssp);
+  yystate = *yyssp;
+  goto yyerrlab1;
+
+
+/*-------------------------------------------------------------.
+| yyerrlab1 -- common code for both syntax error and YYERROR.  |
+`-------------------------------------------------------------*/
+yyerrlab1:
+  yyerrstatus = 3;	/* Each real token shifted decrements this.  */
+
+  for (;;)
+    {
+      yyn = yypact[yystate];
+      if (yyn != YYPACT_NINF)
+	{
+	  yyn += YYTERROR;
+	  if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR)
+	    {
+	      yyn = yytable[yyn];
+	      if (0 < yyn)
+		break;
+	    }
+	}
+
+      /* Pop the current state because it cannot handle the error token.  */
+      if (yyssp == yyss)
+	YYABORT;
+
+
+      yydestruct ("Error: popping",
+		  yystos[yystate], yyvsp, context);
+      YYPOPSTACK (1);
+      yystate = *yyssp;
+      YY_STACK_PRINT (yyss, yyssp);
+    }
+
+  *++yyvsp = yylval;
+
+
+  /* Shift the error token.  */
+  YY_SYMBOL_PRINT ("Shifting", yystos[yyn], yyvsp, yylsp);
+
+  yystate = yyn;
+  goto yynewstate;
+
+
+/*-------------------------------------.
+| yyacceptlab -- YYACCEPT comes here.  |
+`-------------------------------------*/
+yyacceptlab:
+  yyresult = 0;
+  goto yyreturn;
+
+/*-----------------------------------.
+| yyabortlab -- YYABORT comes here.  |
+`-----------------------------------*/
+yyabortlab:
+  yyresult = 1;
+  goto yyreturn;
+
+#if !defined(yyoverflow) || YYERROR_VERBOSE
+/*-------------------------------------------------.
+| yyexhaustedlab -- memory exhaustion comes here.  |
+`-------------------------------------------------*/
+yyexhaustedlab:
+  yyerror (context, YY_("memory exhausted"));
+  yyresult = 2;
+  /* Fall through.  */
+#endif
+
+yyreturn:
+  if (yychar != YYEMPTY)
+     yydestruct ("Cleanup: discarding lookahead",
+		 yytoken, &yylval, context);
+  /* Do not reclaim the symbols of the rule which action triggered
+     this YYABORT or YYACCEPT.  */
+  YYPOPSTACK (yylen);
+  YY_STACK_PRINT (yyss, yyssp);
+  while (yyssp != yyss)
+    {
+      yydestruct ("Cleanup: popping",
+		  yystos[*yyssp], yyvsp, context);
+      YYPOPSTACK (1);
+    }
+#ifndef yyoverflow
+  if (yyss != yyssa)
+    YYSTACK_FREE (yyss);
+#endif
+#if YYERROR_VERBOSE
+  if (yymsg != yymsgbuf)
+    YYSTACK_FREE (yymsg);
+#endif
+  /* Make sure YYID is used.  */
+  return YYID (yyresult);
+}
+
+
+
+
+
+int glslang_parse(TParseContext* context) {
+    return yyparse(context);
+}
+
+
diff --git a/src/GLES2/compiler/glslang_tab.h b/src/GLES2/compiler/glslang_tab.h
new file mode 100644
index 0000000..5227361
--- /dev/null
+++ b/src/GLES2/compiler/glslang_tab.h
@@ -0,0 +1,182 @@
+/* A Bison parser, made by GNU Bison 2.4.2.  */
+
+/* Skeleton interface for Bison's Yacc-like parsers in C
+   
+      Copyright (C) 1984, 1989-1990, 2000-2006, 2009-2010 Free Software
+   Foundation, Inc.
+   
+   This program 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.
+   
+   This program 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 this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+/* As a special exception, you may create a larger work that contains
+   part or all of the Bison parser skeleton and distribute that work
+   under terms of your choice, so long as that work isn't itself a
+   parser generator using the skeleton or a modified version thereof
+   as a parser skeleton.  Alternatively, if you modify or redistribute
+   the parser skeleton itself, you may (at your option) remove this
+   special exception, which will cause the skeleton and the resulting
+   Bison output files to be licensed under the GNU General Public
+   License without this special exception.
+   
+   This special exception was added by the Free Software Foundation in
+   version 2.2 of Bison.  */
+
+
+/* Tokens.  */
+#ifndef YYTOKENTYPE
+# define YYTOKENTYPE
+   /* Put the tokens into the symbol table, so that GDB and other debuggers
+      know about them.  */
+   enum yytokentype {
+     INVARIANT = 258,
+     HIGH_PRECISION = 259,
+     MEDIUM_PRECISION = 260,
+     LOW_PRECISION = 261,
+     PRECISION = 262,
+     ATTRIBUTE = 263,
+     CONST_QUAL = 264,
+     BOOL_TYPE = 265,
+     FLOAT_TYPE = 266,
+     INT_TYPE = 267,
+     BREAK = 268,
+     CONTINUE = 269,
+     DO = 270,
+     ELSE = 271,
+     FOR = 272,
+     IF = 273,
+     DISCARD = 274,
+     RETURN = 275,
+     BVEC2 = 276,
+     BVEC3 = 277,
+     BVEC4 = 278,
+     IVEC2 = 279,
+     IVEC3 = 280,
+     IVEC4 = 281,
+     VEC2 = 282,
+     VEC3 = 283,
+     VEC4 = 284,
+     MATRIX2 = 285,
+     MATRIX3 = 286,
+     MATRIX4 = 287,
+     IN_QUAL = 288,
+     OUT_QUAL = 289,
+     INOUT_QUAL = 290,
+     UNIFORM = 291,
+     VARYING = 292,
+     STRUCT = 293,
+     VOID_TYPE = 294,
+     WHILE = 295,
+     SAMPLER2D = 296,
+     SAMPLERCUBE = 297,
+     IDENTIFIER = 298,
+     TYPE_NAME = 299,
+     FLOATCONSTANT = 300,
+     INTCONSTANT = 301,
+     BOOLCONSTANT = 302,
+     FIELD_SELECTION = 303,
+     LEFT_OP = 304,
+     RIGHT_OP = 305,
+     INC_OP = 306,
+     DEC_OP = 307,
+     LE_OP = 308,
+     GE_OP = 309,
+     EQ_OP = 310,
+     NE_OP = 311,
+     AND_OP = 312,
+     OR_OP = 313,
+     XOR_OP = 314,
+     MUL_ASSIGN = 315,
+     DIV_ASSIGN = 316,
+     ADD_ASSIGN = 317,
+     MOD_ASSIGN = 318,
+     LEFT_ASSIGN = 319,
+     RIGHT_ASSIGN = 320,
+     AND_ASSIGN = 321,
+     XOR_ASSIGN = 322,
+     OR_ASSIGN = 323,
+     SUB_ASSIGN = 324,
+     LEFT_PAREN = 325,
+     RIGHT_PAREN = 326,
+     LEFT_BRACKET = 327,
+     RIGHT_BRACKET = 328,
+     LEFT_BRACE = 329,
+     RIGHT_BRACE = 330,
+     DOT = 331,
+     COMMA = 332,
+     COLON = 333,
+     EQUAL = 334,
+     SEMICOLON = 335,
+     BANG = 336,
+     DASH = 337,
+     TILDE = 338,
+     PLUS = 339,
+     STAR = 340,
+     SLASH = 341,
+     PERCENT = 342,
+     LEFT_ANGLE = 343,
+     RIGHT_ANGLE = 344,
+     VERTICAL_BAR = 345,
+     CARET = 346,
+     AMPERSAND = 347,
+     QUESTION = 348
+   };
+#endif
+
+
+
+#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
+typedef union YYSTYPE
+{
+
+
+    struct {
+        TSourceLoc line;
+        union {
+            TString *string;
+            float f;
+            int i;
+            bool b;
+        };
+        TSymbol* symbol;
+    } lex;
+    struct {
+        TSourceLoc line;
+        TOperator op;
+        union {
+            TIntermNode* intermNode;
+            TIntermNodePair nodePair;
+            TIntermTyped* intermTypedNode;
+            TIntermAggregate* intermAggregate;
+        };
+        union {
+            TPublicType type;
+            TPrecision precision;
+            TQualifier qualifier;
+            TFunction* function;
+            TParameter param;
+            TTypeLine typeLine;
+            TTypeList* typeList;
+        };
+    } interm;
+
+
+
+} YYSTYPE;
+# define YYSTYPE_IS_TRIVIAL 1
+# define yystype YYSTYPE /* obsolescent; will be withdrawn */
+# define YYSTYPE_IS_DECLARED 1
+#endif
+
+
+
+
diff --git a/src/GLES2/compiler/intermOut.cpp b/src/GLES2/compiler/intermOut.cpp
new file mode 100644
index 0000000..798a69a
--- /dev/null
+++ b/src/GLES2/compiler/intermOut.cpp
@@ -0,0 +1,417 @@
+//
+// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "compiler/localintermediate.h"
+
+//
+// Two purposes:
+// 1.  Show an example of how to iterate tree.  Functions can
+//     also directly call Traverse() on children themselves to
+//     have finer grained control over the process than shown here.
+//     See the last function for how to get started.
+// 2.  Print out a text based description of the tree.
+//
+
+//
+// Use this class to carry along data from node to node in
+// the traversal
+//
+class TOutputTraverser : public TIntermTraverser {
+public:
+    TOutputTraverser(TInfoSinkBase& i) : sink(i) { }
+    TInfoSinkBase& sink;
+
+protected:
+    void visitSymbol(TIntermSymbol*);
+    void visitConstantUnion(TIntermConstantUnion*);
+    bool visitBinary(Visit visit, TIntermBinary*);
+    bool visitUnary(Visit visit, TIntermUnary*);
+    bool visitSelection(Visit visit, TIntermSelection*);
+    bool visitAggregate(Visit visit, TIntermAggregate*);
+    bool visitLoop(Visit visit, TIntermLoop*);
+    bool visitBranch(Visit visit, TIntermBranch*);
+};
+
+TString TType::getCompleteString() const
+{
+    TStringStream stream;
+
+    if (qualifier != EvqTemporary && qualifier != EvqGlobal)
+        stream << getQualifierString() << " " << getPrecisionString() << " ";
+    if (array)
+        stream << "array of ";
+    if (matrix)
+        stream << size << "X" << size << " matrix of ";
+    else if (size > 1)
+        stream << size << "-component vector of ";
+
+    stream << getBasicString();
+    return stream.str();
+}
+
+//
+// Helper functions for printing, not part of traversing.
+//
+
+void OutputTreeText(TInfoSinkBase& sink, TIntermNode* node, const int depth)
+{
+    int i;
+
+    sink.location(node->getLine());
+
+    for (i = 0; i < depth; ++i)
+        sink << "  ";
+}
+
+//
+// The rest of the file are the traversal functions.  The last one
+// is the one that starts the traversal.
+//
+// Return true from interior nodes to have the external traversal
+// continue on to children.  If you process children yourself,
+// return false.
+//
+
+void TOutputTraverser::visitSymbol(TIntermSymbol* node)
+{
+    OutputTreeText(sink, node, depth);
+
+    sink << "'" << node->getSymbol() << "' ";
+    sink << "(" << node->getCompleteString() << ")\n";
+}
+
+bool TOutputTraverser::visitBinary(Visit visit, TIntermBinary* node)
+{
+    TInfoSinkBase& out = sink;
+
+    OutputTreeText(out, node, depth);
+
+    switch (node->getOp()) {
+        case EOpAssign:                   out << "move second child to first child";           break;
+        case EOpInitialize:               out << "initialize first child with second child";   break;
+        case EOpAddAssign:                out << "add second child into first child";          break;
+        case EOpSubAssign:                out << "subtract second child into first child";     break;
+        case EOpMulAssign:                out << "multiply second child into first child";     break;
+        case EOpVectorTimesMatrixAssign:  out << "matrix mult second child into first child";  break;
+        case EOpVectorTimesScalarAssign:  out << "vector scale second child into first child"; break;
+        case EOpMatrixTimesScalarAssign:  out << "matrix scale second child into first child"; break;
+        case EOpMatrixTimesMatrixAssign:  out << "matrix mult second child into first child"; break;
+        case EOpDivAssign:                out << "divide second child into first child";       break;
+        case EOpIndexDirect:   out << "direct index";   break;
+        case EOpIndexIndirect: out << "indirect index"; break;
+        case EOpIndexDirectStruct:   out << "direct index for structure";   break;
+        case EOpVectorSwizzle: out << "vector swizzle"; break;
+
+        case EOpAdd:    out << "add";                     break;
+        case EOpSub:    out << "subtract";                break;
+        case EOpMul:    out << "component-wise multiply"; break;
+        case EOpDiv:    out << "divide";                  break;
+        case EOpEqual:            out << "Compare Equal";                 break;
+        case EOpNotEqual:         out << "Compare Not Equal";             break;
+        case EOpLessThan:         out << "Compare Less Than";             break;
+        case EOpGreaterThan:      out << "Compare Greater Than";          break;
+        case EOpLessThanEqual:    out << "Compare Less Than or Equal";    break;
+        case EOpGreaterThanEqual: out << "Compare Greater Than or Equal"; break;
+
+        case EOpVectorTimesScalar: out << "vector-scale";          break;
+        case EOpVectorTimesMatrix: out << "vector-times-matrix";   break;
+        case EOpMatrixTimesVector: out << "matrix-times-vector";   break;
+        case EOpMatrixTimesScalar: out << "matrix-scale";          break;
+        case EOpMatrixTimesMatrix: out << "matrix-multiply";       break;
+
+        case EOpLogicalOr:  out << "logical-or";   break;
+        case EOpLogicalXor: out << "logical-xor"; break;
+        case EOpLogicalAnd: out << "logical-and"; break;
+        default: out << "<unknown op>";
+    }
+
+    out << " (" << node->getCompleteString() << ")";
+
+    out << "\n";
+
+    return true;
+}
+
+bool TOutputTraverser::visitUnary(Visit visit, TIntermUnary* node)
+{
+    TInfoSinkBase& out = sink;
+
+    OutputTreeText(out, node, depth);
+
+    switch (node->getOp()) {
+        case EOpNegative:       out << "Negate value";         break;
+        case EOpVectorLogicalNot:
+        case EOpLogicalNot:     out << "Negate conditional";   break;
+
+        case EOpPostIncrement:  out << "Post-Increment";       break;
+        case EOpPostDecrement:  out << "Post-Decrement";       break;
+        case EOpPreIncrement:   out << "Pre-Increment";        break;
+        case EOpPreDecrement:   out << "Pre-Decrement";        break;
+
+        case EOpConvIntToBool:  out << "Convert int to bool";  break;
+        case EOpConvFloatToBool:out << "Convert float to bool";break;
+        case EOpConvBoolToFloat:out << "Convert bool to float";break;
+        case EOpConvIntToFloat: out << "Convert int to float"; break;
+        case EOpConvFloatToInt: out << "Convert float to int"; break;
+        case EOpConvBoolToInt:  out << "Convert bool to int";  break;
+
+        case EOpRadians:        out << "radians";              break;
+        case EOpDegrees:        out << "degrees";              break;
+        case EOpSin:            out << "sine";                 break;
+        case EOpCos:            out << "cosine";               break;
+        case EOpTan:            out << "tangent";              break;
+        case EOpAsin:           out << "arc sine";             break;
+        case EOpAcos:           out << "arc cosine";           break;
+        case EOpAtan:           out << "arc tangent";          break;
+
+        case EOpExp:            out << "exp";                  break;
+        case EOpLog:            out << "log";                  break;
+        case EOpExp2:           out << "exp2";                 break;
+        case EOpLog2:           out << "log2";                 break;
+        case EOpSqrt:           out << "sqrt";                 break;
+        case EOpInverseSqrt:    out << "inverse sqrt";         break;
+
+        case EOpAbs:            out << "Absolute value";       break;
+        case EOpSign:           out << "Sign";                 break;
+        case EOpFloor:          out << "Floor";                break;
+        case EOpCeil:           out << "Ceiling";              break;
+        case EOpFract:          out << "Fraction";             break;
+
+        case EOpLength:         out << "length";               break;
+        case EOpNormalize:      out << "normalize";            break;
+            //	case EOpDPdx:           out << "dPdx";                 break;               
+            //	case EOpDPdy:           out << "dPdy";                 break;   
+            //	case EOpFwidth:         out << "fwidth";               break;                   
+
+        case EOpAny:            out << "any";                  break;
+        case EOpAll:            out << "all";                  break;
+
+        default: out.message(EPrefixError, "Bad unary op");
+    }
+
+    out << " (" << node->getCompleteString() << ")";
+
+    out << "\n";
+
+    return true;
+}
+
+bool TOutputTraverser::visitAggregate(Visit visit, TIntermAggregate* node)
+{
+    TInfoSinkBase& out = sink;
+
+    if (node->getOp() == EOpNull) {
+        out.message(EPrefixError, "node is still EOpNull!");
+        return true;
+    }
+
+    OutputTreeText(out, node, depth);
+
+    switch (node->getOp()) {
+        case EOpSequence:      out << "Sequence\n"; return true;
+        case EOpComma:         out << "Comma\n"; return true;
+        case EOpFunction:      out << "Function Definition: " << node->getName(); break;
+        case EOpFunctionCall:  out << "Function Call: " << node->getName(); break;
+        case EOpParameters:    out << "Function Parameters: ";              break;
+
+        case EOpConstructFloat: out << "Construct float"; break;
+        case EOpConstructVec2:  out << "Construct vec2";  break;
+        case EOpConstructVec3:  out << "Construct vec3";  break;
+        case EOpConstructVec4:  out << "Construct vec4";  break;
+        case EOpConstructBool:  out << "Construct bool";  break;
+        case EOpConstructBVec2: out << "Construct bvec2"; break;
+        case EOpConstructBVec3: out << "Construct bvec3"; break;
+        case EOpConstructBVec4: out << "Construct bvec4"; break;
+        case EOpConstructInt:   out << "Construct int";   break;
+        case EOpConstructIVec2: out << "Construct ivec2"; break;
+        case EOpConstructIVec3: out << "Construct ivec3"; break;
+        case EOpConstructIVec4: out << "Construct ivec4"; break;
+        case EOpConstructMat2:  out << "Construct mat2";  break;
+        case EOpConstructMat3:  out << "Construct mat3";  break;
+        case EOpConstructMat4:  out << "Construct mat4";  break;
+        case EOpConstructStruct:  out << "Construct structure";  break;
+
+        case EOpLessThan:         out << "Compare Less Than";             break;
+        case EOpGreaterThan:      out << "Compare Greater Than";          break;
+        case EOpLessThanEqual:    out << "Compare Less Than or Equal";    break;
+        case EOpGreaterThanEqual: out << "Compare Greater Than or Equal"; break;
+        case EOpVectorEqual:      out << "Equal";                         break;
+        case EOpVectorNotEqual:   out << "NotEqual";                      break;
+
+        case EOpMod:           out << "mod";         break;
+        case EOpPow:           out << "pow";         break;
+
+        case EOpAtan:          out << "arc tangent"; break;
+
+        case EOpMin:           out << "min";         break;
+        case EOpMax:           out << "max";         break;
+        case EOpClamp:         out << "clamp";       break;
+        case EOpMix:           out << "mix";         break;
+        case EOpStep:          out << "step";        break;
+        case EOpSmoothStep:    out << "smoothstep";  break;
+
+        case EOpDistance:      out << "distance";                break;
+        case EOpDot:           out << "dot-product";             break;
+        case EOpCross:         out << "cross-product";           break;
+        case EOpFaceForward:   out << "face-forward";            break;
+        case EOpReflect:       out << "reflect";                 break;
+        case EOpRefract:       out << "refract";                 break;
+        case EOpMul:           out << "component-wise multiply"; break;
+
+        default: out.message(EPrefixError, "Bad aggregation op");
+    }
+
+    if (node->getOp() != EOpSequence && node->getOp() != EOpParameters)
+        out << " (" << node->getCompleteString() << ")";
+
+    out << "\n";
+
+    return true;
+}
+
+bool TOutputTraverser::visitSelection(Visit visit, TIntermSelection* node)
+{
+    TInfoSinkBase& out = sink;
+
+    OutputTreeText(out, node, depth);
+
+    out << "Test condition and select";
+    out << " (" << node->getCompleteString() << ")\n";
+
+    ++depth;
+
+    OutputTreeText(sink, node, depth);
+    out << "Condition\n";
+    node->getCondition()->traverse(this);
+
+    OutputTreeText(sink, node, depth);
+    if (node->getTrueBlock()) {
+        out << "true case\n";
+        node->getTrueBlock()->traverse(this);
+    } else
+        out << "true case is null\n";
+
+    if (node->getFalseBlock()) {
+        OutputTreeText(sink, node, depth);
+        out << "false case\n";
+        node->getFalseBlock()->traverse(this);
+    }
+
+    --depth;
+
+    return false;
+}
+
+void TOutputTraverser::visitConstantUnion(TIntermConstantUnion* node)
+{
+    TInfoSinkBase& out = sink;
+
+    int size = node->getType().getObjectSize();
+
+    for (int i = 0; i < size; i++) {
+        OutputTreeText(out, node, depth);
+        switch (node->getUnionArrayPointer()[i].getType()) {
+            case EbtBool:
+                if (node->getUnionArrayPointer()[i].getBConst())
+                    out << "true";
+                else
+                    out << "false";
+
+                out << " (" << "const bool" << ")";
+                out << "\n";
+                break;
+            case EbtFloat:
+                out << node->getUnionArrayPointer()[i].getFConst();
+                out << " (const float)\n";
+                break;
+            case EbtInt:
+                out << node->getUnionArrayPointer()[i].getIConst();
+                out << " (const int)\n";
+                break;
+            default:
+                out.message(EPrefixInternalError, "Unknown constant", node->getLine());
+                break;
+        }
+    }
+}
+
+bool TOutputTraverser::visitLoop(Visit visit, TIntermLoop* node)
+{
+    TInfoSinkBase& out = sink;
+
+    OutputTreeText(out, node, depth);
+
+    out << "Loop with condition ";
+    if (node->getType() == ELoopDoWhile)
+        out << "not ";
+    out << "tested first\n";
+
+    ++depth;
+
+    OutputTreeText(sink, node, depth);
+    if (node->getCondition()) {
+        out << "Loop Condition\n";
+        node->getCondition()->traverse(this);
+    } else
+        out << "No loop condition\n";
+
+    OutputTreeText(sink, node, depth);
+    if (node->getBody()) {
+        out << "Loop Body\n";
+        node->getBody()->traverse(this);
+    } else
+        out << "No loop body\n";
+
+    if (node->getExpression()) {
+        OutputTreeText(sink, node, depth);
+        out << "Loop Terminal Expression\n";
+        node->getExpression()->traverse(this);
+    }
+
+    --depth;
+
+    return false;
+}
+
+bool TOutputTraverser::visitBranch(Visit visit, TIntermBranch* node)
+{
+    TInfoSinkBase& out = sink;
+
+    OutputTreeText(out, node, depth);
+
+    switch (node->getFlowOp()) {
+        case EOpKill:      out << "Branch: Kill";           break;
+        case EOpBreak:     out << "Branch: Break";          break;
+        case EOpContinue:  out << "Branch: Continue";       break;
+        case EOpReturn:    out << "Branch: Return";         break;
+        default:           out << "Branch: Unknown Branch"; break;
+    }
+
+    if (node->getExpression()) {
+        out << " with expression\n";
+        ++depth;
+        node->getExpression()->traverse(this);
+        --depth;
+    } else
+        out << "\n";
+
+    return false;
+}
+
+//
+// This function is the one to call externally to start the traversal.
+// Individual functions can be initialized to 0 to skip processing of that
+// type of node.  It's children will still be processed.
+//
+void TIntermediate::outputTree(TIntermNode* root)
+{
+    if (root == 0)
+        return;
+
+    TOutputTraverser it(infoSink.info);
+
+    root->traverse(&it);
+}
diff --git a/src/GLES2/compiler/intermediate.h b/src/GLES2/compiler/intermediate.h
new file mode 100644
index 0000000..5ed5f54
--- /dev/null
+++ b/src/GLES2/compiler/intermediate.h
@@ -0,0 +1,551 @@
+//
+// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+//
+// Definition of the in-memory high-level intermediate representation
+// of shaders.  This is a tree that parser creates.
+//
+// Nodes in the tree are defined as a hierarchy of classes derived from 
+// TIntermNode. Each is a node in a tree.  There is no preset branching factor;
+// each node can have it's own type of list of children.
+//
+
+#ifndef __INTERMEDIATE_H
+#define __INTERMEDIATE_H
+
+#include "compiler/Common.h"
+#include "compiler/Types.h"
+#include "compiler/ConstantUnion.h"
+
+//
+// Operators used by the high-level (parse tree) representation.
+//
+enum TOperator {
+    EOpNull,            // if in a node, should only mean a node is still being built
+    EOpSequence,        // denotes a list of statements, or parameters, etc.
+    EOpFunctionCall,    
+    EOpFunction,        // For function definition
+    EOpParameters,      // an aggregate listing the parameters to a function
+
+    EOpDeclaration,
+    EOpPrototype,
+
+    //
+    // Unary operators
+    //
+
+    EOpNegative,
+    EOpLogicalNot,
+    EOpVectorLogicalNot,
+
+    EOpPostIncrement,
+    EOpPostDecrement,
+    EOpPreIncrement,
+    EOpPreDecrement,
+
+    EOpConvIntToBool,
+    EOpConvFloatToBool,
+    EOpConvBoolToFloat,
+    EOpConvIntToFloat,
+    EOpConvFloatToInt,
+    EOpConvBoolToInt,
+
+    //
+    // binary operations
+    //
+
+    EOpAdd,
+    EOpSub,
+    EOpMul,
+    EOpDiv,
+    EOpEqual,
+    EOpNotEqual,
+    EOpVectorEqual,
+    EOpVectorNotEqual,
+    EOpLessThan,
+    EOpGreaterThan,
+    EOpLessThanEqual,
+    EOpGreaterThanEqual,
+    EOpComma,
+
+    EOpVectorTimesScalar,
+    EOpVectorTimesMatrix,
+    EOpMatrixTimesVector,
+    EOpMatrixTimesScalar,
+
+    EOpLogicalOr,
+    EOpLogicalXor,
+    EOpLogicalAnd,
+
+    EOpIndexDirect,
+    EOpIndexIndirect,
+    EOpIndexDirectStruct,
+
+    EOpVectorSwizzle,
+
+    //
+    // Built-in functions potentially mapped to operators
+    //
+
+    EOpRadians,
+    EOpDegrees,
+    EOpSin,
+    EOpCos,
+    EOpTan,
+    EOpAsin,
+    EOpAcos,
+    EOpAtan,
+
+    EOpPow,
+    EOpExp,
+    EOpLog,
+    EOpExp2,
+    EOpLog2,
+    EOpSqrt,
+    EOpInverseSqrt,
+
+    EOpAbs,
+    EOpSign,
+    EOpFloor,
+    EOpCeil,
+    EOpFract,
+    EOpMod,
+    EOpMin,
+    EOpMax,
+    EOpClamp,
+    EOpMix,
+    EOpStep,
+    EOpSmoothStep,
+
+    EOpLength,
+    EOpDistance,
+    EOpDot,
+    EOpCross,
+    EOpNormalize,
+    EOpFaceForward,
+    EOpReflect,
+    EOpRefract,
+
+    EOpDFdx,            // Fragment only, OES_standard_derivatives extension
+    EOpDFdy,            // Fragment only, OES_standard_derivatives extension
+    EOpFwidth,          // Fragment only, OES_standard_derivatives extension
+
+    EOpMatrixTimesMatrix,
+
+    EOpAny,
+    EOpAll,
+
+    //
+    // Branch
+    //
+
+    EOpKill,            // Fragment only
+    EOpReturn,
+    EOpBreak,
+    EOpContinue,
+
+    //
+    // Constructors
+    //
+
+    EOpConstructInt,
+    EOpConstructBool,
+    EOpConstructFloat,
+    EOpConstructVec2,
+    EOpConstructVec3,
+    EOpConstructVec4,
+    EOpConstructBVec2,
+    EOpConstructBVec3,
+    EOpConstructBVec4,
+    EOpConstructIVec2,
+    EOpConstructIVec3,
+    EOpConstructIVec4,
+    EOpConstructMat2,
+    EOpConstructMat3,
+    EOpConstructMat4,
+    EOpConstructStruct,
+
+    //
+    // moves
+    //
+
+    EOpAssign,
+    EOpInitialize,
+    EOpAddAssign,
+    EOpSubAssign,
+    EOpMulAssign,
+    EOpVectorTimesMatrixAssign,
+    EOpVectorTimesScalarAssign,
+    EOpMatrixTimesScalarAssign,
+    EOpMatrixTimesMatrixAssign,
+    EOpDivAssign,
+};
+
+extern const char* getOperatorString(TOperator op);
+
+class TIntermTraverser;
+class TIntermAggregate;
+class TIntermBinary;
+class TIntermUnary;
+class TIntermConstantUnion;
+class TIntermSelection;
+class TIntermTyped;
+class TIntermSymbol;
+class TIntermLoop;
+class TIntermBranch;
+class TInfoSink;
+
+//
+// Base class for the tree nodes
+//
+class TIntermNode {
+public:
+    POOL_ALLOCATOR_NEW_DELETE(GlobalPoolAllocator)
+
+    TIntermNode() : line(0) {}
+
+    TSourceLoc getLine() const { return line; }
+    void setLine(TSourceLoc l) { line = l; }
+
+    virtual void traverse(TIntermTraverser*) = 0;
+    virtual TIntermTyped* getAsTyped() { return 0; }
+    virtual TIntermConstantUnion* getAsConstantUnion() { return 0; }
+    virtual TIntermAggregate* getAsAggregate() { return 0; }
+    virtual TIntermBinary* getAsBinaryNode() { return 0; }
+    virtual TIntermUnary* getAsUnaryNode() { return 0; }
+    virtual TIntermSelection* getAsSelectionNode() { return 0; }
+    virtual TIntermSymbol* getAsSymbolNode() { return 0; }
+    virtual TIntermLoop* getAsLoopNode() { return 0; }
+	virtual TIntermBranch* getAsBranchNode() { return 0; }
+    virtual ~TIntermNode() { }
+
+protected:
+    TSourceLoc line;
+};
+
+//
+// This is just to help yacc.
+//
+struct TIntermNodePair {
+    TIntermNode* node1;
+    TIntermNode* node2;
+};
+
+//
+// Intermediate class for nodes that have a type.
+//
+class TIntermTyped : public TIntermNode {
+public:
+    TIntermTyped(const TType& t) : type(t)  { }
+    virtual TIntermTyped* getAsTyped() { return this; }
+
+    void setType(const TType& t) { type = t; }
+    const TType& getType() const { return type; }
+    TType* getTypePointer() { return &type; }
+
+    TBasicType getBasicType() const { return type.getBasicType(); }
+    TQualifier getQualifier() const { return type.getQualifier(); }
+    TPrecision getPrecision() const { return type.getPrecision(); }
+    int getNominalSize() const { return type.getNominalSize(); }
+    
+    bool isMatrix() const { return type.isMatrix(); }
+    bool isArray()  const { return type.isArray(); }
+    bool isVector() const { return type.isVector(); }
+    bool isScalar() const { return type.isScalar(); }
+	bool isRegister() const { return type.isRegister(); }   // Fits in a 4-element register
+	bool isStruct() const { return type.isStruct(); }
+    const char* getBasicString() const { return type.getBasicString(); }
+    const char* getQualifierString() const { return type.getQualifierString(); }
+    TString getCompleteString() const { return type.getCompleteString(); }
+
+	int totalRegisterCount() const { return type.totalRegisterCount(); }
+	int elementRegisterCount() const { return type.elementRegisterCount(); }
+	int getArraySize() const { return type.getArraySize(); }
+
+protected:
+    TType type;
+};
+
+//
+// Handle for, do-while, and while loops.
+//
+enum TLoopType {
+    ELoopFor,
+    ELoopWhile,
+    ELoopDoWhile,
+};
+
+class TIntermLoop : public TIntermNode {
+public:
+    TIntermLoop(TLoopType aType,
+                TIntermNode *aInit, TIntermTyped* aCond, TIntermTyped* aExpr,
+                TIntermNode* aBody) :
+            type(aType),
+            init(aInit),
+            cond(aCond),
+            expr(aExpr),
+            body(aBody),
+            unrollFlag(false) { }
+
+    virtual TIntermLoop* getAsLoopNode() { return this; }
+    virtual void traverse(TIntermTraverser*);
+
+    TLoopType getType() const { return type; }
+    TIntermNode* getInit() { return init; }
+    TIntermTyped* getCondition() { return cond; }
+    TIntermTyped* getExpression() { return expr; }
+    TIntermNode* getBody() { return body; }
+
+    void setUnrollFlag(bool flag) { unrollFlag = flag; }
+    bool getUnrollFlag() { return unrollFlag; }
+
+protected:
+    TLoopType type;
+    TIntermNode* init;  // for-loop initialization
+    TIntermTyped* cond; // loop exit condition
+    TIntermTyped* expr; // for-loop expression
+    TIntermNode* body;  // loop body
+
+    bool unrollFlag; // Whether the loop should be unrolled or not.
+};
+
+//
+// Handle break, continue, return, and kill.
+//
+class TIntermBranch : public TIntermNode {
+public:
+    TIntermBranch(TOperator op, TIntermTyped* e) :
+            flowOp(op),
+            expression(e) { }
+
+	virtual TIntermBranch* getAsBranchNode() { return this; }
+    virtual void traverse(TIntermTraverser*);
+
+    TOperator getFlowOp() { return flowOp; }
+    TIntermTyped* getExpression() { return expression; }
+
+protected:
+    TOperator flowOp;
+    TIntermTyped* expression;  // non-zero except for "return exp;" statements
+};
+
+//
+// Nodes that correspond to symbols or constants in the source code.
+//
+class TIntermSymbol : public TIntermTyped {
+public:
+    // if symbol is initialized as symbol(sym), the memory comes from the poolallocator of sym. If sym comes from
+    // per process globalpoolallocator, then it causes increased memory usage per compile
+    // it is essential to use "symbol = sym" to assign to symbol
+    TIntermSymbol(int i, const TString& sym, const TType& t) : 
+            TIntermTyped(t), id(i)  { symbol = sym; } 
+
+    int getId() const { return id; }
+    const TString& getSymbol() const { return symbol; }
+
+    void setId(int newId) { id = newId; }
+    
+    virtual void traverse(TIntermTraverser*);
+    virtual TIntermSymbol* getAsSymbolNode() { return this; }
+
+protected:
+    int id;
+    TString symbol;
+};
+
+class TIntermConstantUnion : public TIntermTyped {
+public:
+    TIntermConstantUnion(ConstantUnion *unionPointer, const TType& t) : TIntermTyped(t), unionArrayPointer(unionPointer) { }
+
+    ConstantUnion* getUnionArrayPointer() const { return unionArrayPointer; }
+    void setUnionArrayPointer(ConstantUnion *c) { unionArrayPointer = c; }
+
+    virtual TIntermConstantUnion* getAsConstantUnion()  { return this; }
+    virtual void traverse(TIntermTraverser*);
+
+    TIntermTyped* fold(TOperator, TIntermTyped*, TInfoSink&);
+
+protected:
+    ConstantUnion *unionArrayPointer;
+};
+
+//
+// Intermediate class for node types that hold operators.
+//
+class TIntermOperator : public TIntermTyped {
+public:
+    TOperator getOp() const { return op; }
+    void setOp(TOperator o) { op = o; }
+
+    bool modifiesState() const;
+    bool isConstructor() const;
+
+protected:
+    TIntermOperator(TOperator o) : TIntermTyped(TType(EbtFloat, EbpUndefined)), op(o) {}
+    TIntermOperator(TOperator o, TType& t) : TIntermTyped(t), op(o) {}   
+    TOperator op;
+};
+
+//
+// Nodes for all the basic binary math operators.
+//
+class TIntermBinary : public TIntermOperator {
+public:
+    TIntermBinary(TOperator o) : TIntermOperator(o) {}
+
+    virtual TIntermBinary* getAsBinaryNode() { return this; }
+    virtual void traverse(TIntermTraverser*);
+
+    void setLeft(TIntermTyped* n) { left = n; }
+    void setRight(TIntermTyped* n) { right = n; }
+    TIntermTyped* getLeft() const { return left; }
+    TIntermTyped* getRight() const { return right; }
+    bool promote(TInfoSink&);
+
+protected:
+    TIntermTyped* left;
+    TIntermTyped* right;
+};
+
+//
+// Nodes for unary math operators.
+//
+class TIntermUnary : public TIntermOperator {
+public:
+    TIntermUnary(TOperator o, TType& t) : TIntermOperator(o, t), operand(0) {}
+    TIntermUnary(TOperator o) : TIntermOperator(o), operand(0) {}
+
+    virtual void traverse(TIntermTraverser*);
+    virtual TIntermUnary* getAsUnaryNode() { return this; }
+
+    void setOperand(TIntermTyped* o) { operand = o; }
+    TIntermTyped* getOperand() { return operand; }    
+    bool promote(TInfoSink&);
+
+protected:
+    TIntermTyped* operand;
+};
+
+typedef TVector<TIntermNode*> TIntermSequence;
+typedef TVector<int> TQualifierList;
+
+//
+// Nodes that operate on an arbitrary sized set of children.
+//
+class TIntermAggregate : public TIntermOperator {
+public:
+    TIntermAggregate() : TIntermOperator(EOpNull), userDefined(false), endLine(0) { }
+    TIntermAggregate(TOperator o) : TIntermOperator(o) { }
+    ~TIntermAggregate() { }
+
+    virtual TIntermAggregate* getAsAggregate() { return this; }
+    virtual void traverse(TIntermTraverser*);
+
+    TIntermSequence& getSequence() { return sequence; }
+
+    void setName(const TString& n) { name = n; }
+    const TString& getName() const { return name; }
+
+    void setUserDefined() { userDefined = true; }
+    bool isUserDefined() const { return userDefined; }
+
+    void setOptimize(bool o) { optimize = o; }
+    bool getOptimize() { return optimize; }
+    void setDebug(bool d) { debug = d; }
+    bool getDebug() { return debug; }
+
+    void setEndLine(TSourceLoc line) { endLine = line; }
+    TSourceLoc getEndLine() const { return endLine; }
+
+protected:
+    TIntermAggregate(const TIntermAggregate&); // disallow copy constructor
+    TIntermAggregate& operator=(const TIntermAggregate&); // disallow assignment operator
+    TIntermSequence sequence;
+    TString name;
+    bool userDefined; // used for user defined function names
+
+    bool optimize;
+    bool debug;
+    TSourceLoc endLine;
+};
+
+//
+// For if tests.  Simplified since there is no switch statement.
+//
+class TIntermSelection : public TIntermTyped {
+public:
+    TIntermSelection(TIntermTyped* cond, TIntermNode* trueB, TIntermNode* falseB) :
+            TIntermTyped(TType(EbtVoid, EbpUndefined)), condition(cond), trueBlock(trueB), falseBlock(falseB) {}
+    TIntermSelection(TIntermTyped* cond, TIntermNode* trueB, TIntermNode* falseB, const TType& type) :
+            TIntermTyped(type), condition(cond), trueBlock(trueB), falseBlock(falseB)
+	{
+		this->type.setQualifier(EvqTemporary);
+	}
+
+    virtual void traverse(TIntermTraverser*);
+
+    bool usesTernaryOperator() const { return getBasicType() != EbtVoid; }
+    TIntermTyped* getCondition() const { return condition; }
+    TIntermNode* getTrueBlock() const { return trueBlock; }
+    TIntermNode* getFalseBlock() const { return falseBlock; }
+    TIntermSelection* getAsSelectionNode() { return this; }
+
+protected:
+    TIntermTyped* condition;
+    TIntermNode* trueBlock;
+    TIntermNode* falseBlock;
+};
+
+enum Visit
+{
+    PreVisit,
+    InVisit,
+    PostVisit
+};
+
+//
+// For traversing the tree.  User should derive from this, 
+// put their traversal specific data in it, and then pass
+// it to a Traverse method.
+//
+// When using this, just fill in the methods for nodes you want visited.
+// Return false from a pre-visit to skip visiting that node's subtree.
+//
+class TIntermTraverser
+{
+public:
+    POOL_ALLOCATOR_NEW_DELETE(GlobalPoolAllocator)
+
+    TIntermTraverser(bool preVisit = true, bool inVisit = false, bool postVisit = false, bool rightToLeft = false) : 
+            preVisit(preVisit),
+            inVisit(inVisit),
+            postVisit(postVisit),
+            rightToLeft(rightToLeft),
+            depth(0) {}
+    virtual ~TIntermTraverser() {};
+
+    virtual void visitSymbol(TIntermSymbol*) {}
+    virtual void visitConstantUnion(TIntermConstantUnion*) {}
+    virtual bool visitBinary(Visit visit, TIntermBinary*) {return true;}
+    virtual bool visitUnary(Visit visit, TIntermUnary*) {return true;}
+    virtual bool visitSelection(Visit visit, TIntermSelection*) {return true;}
+    virtual bool visitAggregate(Visit visit, TIntermAggregate*) {return true;}
+    virtual bool visitLoop(Visit visit, TIntermLoop*) {return true;}
+    virtual bool visitBranch(Visit visit, TIntermBranch*) {return true;}
+
+    void incrementDepth() {depth++;}
+    void decrementDepth() {depth--;}
+
+    const bool preVisit;
+    const bool inVisit;
+    const bool postVisit;
+    const bool rightToLeft;
+
+protected:
+    int depth;
+};
+
+#endif // __INTERMEDIATE_H
diff --git a/src/GLES2/compiler/localintermediate.h b/src/GLES2/compiler/localintermediate.h
new file mode 100644
index 0000000..56890bd
--- /dev/null
+++ b/src/GLES2/compiler/localintermediate.h
@@ -0,0 +1,58 @@
+//
+// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#ifndef _LOCAL_INTERMEDIATE_INCLUDED_
+#define _LOCAL_INTERMEDIATE_INCLUDED_
+
+#include "GLSLANG/ShaderLang.h"
+#include "compiler/intermediate.h"
+#include "compiler/SymbolTable.h"
+
+struct TVectorFields {
+    int offsets[4];
+    int num;
+};
+
+//
+// Set of helper functions to help parse and build the tree.
+//
+class TInfoSink;
+class TIntermediate {
+public:    
+    POOL_ALLOCATOR_NEW_DELETE(GlobalPoolAllocator)
+
+    TIntermediate(TInfoSink& i) : infoSink(i) { }
+    TIntermSymbol* addSymbol(int Id, const TString&, const TType&, TSourceLoc);
+    TIntermTyped* addConversion(TOperator, const TType&, TIntermTyped*);
+    TIntermTyped* addBinaryMath(TOperator op, TIntermTyped* left, TIntermTyped* right, TSourceLoc, TSymbolTable&);
+    TIntermTyped* addAssign(TOperator op, TIntermTyped* left, TIntermTyped* right, TSourceLoc);
+    TIntermTyped* addIndex(TOperator op, TIntermTyped* base, TIntermTyped* index, TSourceLoc);
+    TIntermTyped* addUnaryMath(TOperator op, TIntermNode* child, TSourceLoc, TSymbolTable&);
+    TIntermAggregate* growAggregate(TIntermNode* left, TIntermNode* right, TSourceLoc);
+    TIntermAggregate* makeAggregate(TIntermNode* node, TSourceLoc);
+    TIntermAggregate* setAggregateOperator(TIntermNode*, TOperator, TSourceLoc);
+    TIntermNode*  addSelection(TIntermTyped* cond, TIntermNodePair code, TSourceLoc);
+    TIntermTyped* addSelection(TIntermTyped* cond, TIntermTyped* trueBlock, TIntermTyped* falseBlock, TSourceLoc);
+    TIntermTyped* addComma(TIntermTyped* left, TIntermTyped* right, TSourceLoc);
+    TIntermConstantUnion* addConstantUnion(ConstantUnion*, const TType&, TSourceLoc);
+    TIntermTyped* promoteConstantUnion(TBasicType, TIntermConstantUnion*) ;
+    bool parseConstTree(TSourceLoc, TIntermNode*, ConstantUnion*, TOperator, TSymbolTable&, TType, bool singleConstantParam = false);        
+    TIntermNode* addLoop(TLoopType, TIntermNode*, TIntermTyped*, TIntermTyped*, TIntermNode*, TSourceLoc);
+    TIntermBranch* addBranch(TOperator, TSourceLoc);
+    TIntermBranch* addBranch(TOperator, TIntermTyped*, TSourceLoc);
+    TIntermTyped* addSwizzle(TVectorFields&, TSourceLoc);
+    bool postProcess(TIntermNode*);
+	void remove(TIntermNode*);
+    void outputTree(TIntermNode*);
+    
+protected:
+    TInfoSink& infoSink;
+
+private:
+    void operator=(TIntermediate&); // prevent assignments
+};
+
+#endif // _LOCAL_INTERMEDIATE_INCLUDED_
diff --git a/src/GLES2/compiler/osinclude.h b/src/GLES2/compiler/osinclude.h
new file mode 100644
index 0000000..42379f0
--- /dev/null
+++ b/src/GLES2/compiler/osinclude.h
@@ -0,0 +1,65 @@
+//
+// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#ifndef __OSINCLUDE_H
+#define __OSINCLUDE_H
+
+//
+// This file contains contains os-specific datatypes and
+// declares any os-specific functions.
+//
+
+#if defined(_WIN32) || defined(_WIN64)
+#define ANGLE_OS_WIN
+#elif defined(__APPLE__) || defined(__linux__) || \
+      defined(__FreeBSD__) || defined(__OpenBSD__) || \
+      defined(__sun) || defined(ANDROID) || \
+      defined(__GLIBC__) || defined(__GNU__) || \
+      defined(__QNX__)
+#define ANGLE_OS_POSIX
+#else
+#error Unsupported platform.
+#endif
+
+#if defined(ANGLE_OS_WIN)
+#define STRICT
+#define VC_EXTRALEAN 1
+#include <windows.h>
+#elif defined(ANGLE_OS_POSIX)
+#include <pthread.h>
+#include <semaphore.h>
+#include <errno.h>
+#endif
+
+
+#include "compiler/debug.h"
+
+//
+// Thread Local Storage Operations
+//
+#if defined(ANGLE_OS_WIN)
+typedef DWORD OS_TLSIndex;
+#define OS_INVALID_TLS_INDEX (TLS_OUT_OF_INDEXES)
+#elif defined(ANGLE_OS_POSIX)
+typedef unsigned int OS_TLSIndex;
+#define OS_INVALID_TLS_INDEX 0xFFFFFFFF
+#endif
+
+OS_TLSIndex OS_AllocTLSIndex();
+bool OS_SetTLSValue(OS_TLSIndex nIndex, void *lpvValue);
+bool OS_FreeTLSIndex(OS_TLSIndex nIndex);
+
+inline void* OS_GetTLSValue(OS_TLSIndex nIndex)
+{
+    ASSERT(nIndex != OS_INVALID_TLS_INDEX);
+#if defined(ANGLE_OS_WIN)
+    return TlsGetValue(nIndex);
+#elif defined(ANGLE_OS_POSIX)
+    return pthread_getspecific(nIndex);
+#endif  // ANGLE_OS_WIN
+}
+
+#endif // __OSINCLUDE_H
diff --git a/src/GLES2/compiler/ossource_posix.cpp b/src/GLES2/compiler/ossource_posix.cpp
new file mode 100644
index 0000000..1e1e699
--- /dev/null
+++ b/src/GLES2/compiler/ossource_posix.cpp
@@ -0,0 +1,64 @@
+//
+// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+//
+// This file contains the posix specific functions
+//
+#include "compiler/osinclude.h"
+
+#if !defined(ANGLE_OS_POSIX)
+#error Trying to build a posix specific file in a non-posix build.
+#endif
+
+//
+// Thread Local Storage Operations
+//
+OS_TLSIndex OS_AllocTLSIndex()
+{
+    pthread_key_t pPoolIndex;
+
+    //
+    // Create global pool key.
+    //
+    if ((pthread_key_create(&pPoolIndex, NULL)) != 0) {
+        assert(0 && "OS_AllocTLSIndex(): Unable to allocate Thread Local Storage");
+        return false;
+    }
+    else {
+        return pPoolIndex;
+    }
+}
+
+
+bool OS_SetTLSValue(OS_TLSIndex nIndex, void *lpvValue)
+{
+    if (nIndex == OS_INVALID_TLS_INDEX) {
+        assert(0 && "OS_SetTLSValue(): Invalid TLS Index");
+        return false;
+    }
+
+    if (pthread_setspecific(nIndex, lpvValue) == 0)
+        return true;
+    else
+        return false;
+}
+
+
+bool OS_FreeTLSIndex(OS_TLSIndex nIndex)
+{
+    if (nIndex == OS_INVALID_TLS_INDEX) {
+        assert(0 && "OS_SetTLSValue(): Invalid TLS Index");
+        return false;
+    }
+
+    //
+    // Delete the global pool key.
+    //
+    if (pthread_key_delete(nIndex) == 0)
+        return true;
+    else
+        return false;
+}
diff --git a/src/GLES2/compiler/ossource_win.cpp b/src/GLES2/compiler/ossource_win.cpp
new file mode 100644
index 0000000..89922fe
--- /dev/null
+++ b/src/GLES2/compiler/ossource_win.cpp
@@ -0,0 +1,57 @@
+//
+// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "compiler/osinclude.h"
+//
+// This file contains contains the window's specific functions
+//
+
+#if !defined(ANGLE_OS_WIN)
+#error Trying to build a windows specific file in a non windows build.
+#endif
+
+
+//
+// Thread Local Storage Operations
+//
+OS_TLSIndex OS_AllocTLSIndex()
+{
+	DWORD dwIndex = TlsAlloc();
+	if (dwIndex == TLS_OUT_OF_INDEXES) {
+		assert(0 && "OS_AllocTLSIndex(): Unable to allocate Thread Local Storage");
+		return OS_INVALID_TLS_INDEX;
+	}
+
+	return dwIndex;
+}
+
+
+bool OS_SetTLSValue(OS_TLSIndex nIndex, void *lpvValue)
+{
+	if (nIndex == OS_INVALID_TLS_INDEX) {
+		assert(0 && "OS_SetTLSValue(): Invalid TLS Index");
+		return false;
+	}
+
+	if (TlsSetValue(nIndex, lpvValue))
+		return true;
+	else
+		return false;
+}
+
+
+bool OS_FreeTLSIndex(OS_TLSIndex nIndex)
+{
+	if (nIndex == OS_INVALID_TLS_INDEX) {
+		assert(0 && "OS_SetTLSValue(): Invalid TLS Index");
+		return false;
+	}
+
+	if (TlsFree(nIndex))
+		return true;
+	else
+		return false;
+}
diff --git a/src/GLES2/compiler/parseConst.cpp b/src/GLES2/compiler/parseConst.cpp
new file mode 100644
index 0000000..9a8a50c
--- /dev/null
+++ b/src/GLES2/compiler/parseConst.cpp
@@ -0,0 +1,238 @@
+//
+// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "compiler/ParseHelper.h"
+
+//
+// Use this class to carry along data from node to node in 
+// the traversal
+//
+class TConstTraverser : public TIntermTraverser {
+public:
+    TConstTraverser(ConstantUnion* cUnion, bool singleConstParam, TOperator constructType, TInfoSink& sink, TSymbolTable& symTable, TType& t)
+        : error(false),
+          index(0),
+          unionArray(cUnion),
+          type(t),
+          constructorType(constructType),
+          singleConstantParam(singleConstParam),
+          infoSink(sink),
+          symbolTable(symTable),
+          size(0),
+          isMatrix(false),
+          matrixSize(0) {
+    }
+
+    bool error;
+
+protected:
+    void visitSymbol(TIntermSymbol*);
+    void visitConstantUnion(TIntermConstantUnion*);
+    bool visitBinary(Visit visit, TIntermBinary*);
+    bool visitUnary(Visit visit, TIntermUnary*);
+    bool visitSelection(Visit visit, TIntermSelection*);
+    bool visitAggregate(Visit visit, TIntermAggregate*);
+    bool visitLoop(Visit visit, TIntermLoop*);
+    bool visitBranch(Visit visit, TIntermBranch*);
+
+    int index;
+    ConstantUnion *unionArray;
+    TType type;
+    TOperator constructorType;
+    bool singleConstantParam;
+    TInfoSink& infoSink;
+    TSymbolTable& symbolTable;
+    int size; // size of the constructor ( 4 for vec4)
+    bool isMatrix;
+    int matrixSize; // dimension of the matrix (nominal size and not the instance size)
+};
+
+//
+// The rest of the file are the traversal functions.  The last one
+// is the one that starts the traversal.
+//
+// Return true from interior nodes to have the external traversal
+// continue on to children.  If you process children yourself,
+// return false.
+//
+
+void TConstTraverser::visitSymbol(TIntermSymbol* node)
+{
+    infoSink.info.message(EPrefixInternalError, "Symbol Node found in constant constructor", node->getLine());
+    return;
+
+}
+
+bool TConstTraverser::visitBinary(Visit visit, TIntermBinary* node)
+{
+    TQualifier qualifier = node->getType().getQualifier();
+    
+    if (qualifier != EvqConst) {
+        TString buf;
+        buf.append("'constructor' : assigning non-constant to ");
+        buf.append(type.getCompleteString());
+        infoSink.info.message(EPrefixError, buf.c_str(), node->getLine());
+        error = true;
+        return false;  
+    }
+
+   infoSink.info.message(EPrefixInternalError, "Binary Node found in constant constructor", node->getLine());
+    
+    return false;
+}
+
+bool TConstTraverser::visitUnary(Visit visit, TIntermUnary* node)
+{
+    TString buf;
+    buf.append("'constructor' : assigning non-constant to ");
+    buf.append(type.getCompleteString());
+    infoSink.info.message(EPrefixError, buf.c_str(), node->getLine());
+    error = true;
+    return false;  
+}
+
+bool TConstTraverser::visitAggregate(Visit visit, TIntermAggregate* node)
+{
+    if (!node->isConstructor() && node->getOp() != EOpComma) {
+        TString buf;
+        buf.append("'constructor' : assigning non-constant to ");
+        buf.append(type.getCompleteString());
+        infoSink.info.message(EPrefixError, buf.c_str(), node->getLine());
+        error = true;
+        return false;  
+    }
+
+    if (node->getSequence().size() == 0) {
+        error = true;
+        return false;
+    }
+
+    bool flag = node->getSequence().size() == 1 && node->getSequence()[0]->getAsTyped()->getAsConstantUnion();
+    if (flag) 
+    {
+        singleConstantParam = true; 
+        constructorType = node->getOp();
+        size = node->getType().getObjectSize();
+
+        if (node->getType().isMatrix()) {
+            isMatrix = true;
+            matrixSize = node->getType().getNominalSize();
+        }
+    }       
+
+    for (TIntermSequence::iterator p = node->getSequence().begin(); 
+                                   p != node->getSequence().end(); p++) {
+
+        if (node->getOp() == EOpComma)
+            index = 0;           
+
+        (*p)->traverse(this);
+    }   
+    if (flag) 
+    {
+        singleConstantParam = false;   
+        constructorType = EOpNull;
+        size = 0;
+        isMatrix = false;
+        matrixSize = 0;
+    }
+    return false;
+}
+
+bool TConstTraverser::visitSelection(Visit visit, TIntermSelection* node)
+{
+    infoSink.info.message(EPrefixInternalError, "Selection Node found in constant constructor", node->getLine());
+    error = true;
+    return false;
+}
+
+void TConstTraverser::visitConstantUnion(TIntermConstantUnion* node)
+{
+    ConstantUnion* leftUnionArray = unionArray;
+    int instanceSize = type.getObjectSize();
+
+    if (index >= instanceSize)
+        return;
+
+    if (!singleConstantParam) {
+        int size = node->getType().getObjectSize();
+    
+        ConstantUnion *rightUnionArray = node->getUnionArrayPointer();
+        for (int i=0; i < size; i++) {
+            if (index >= instanceSize)
+                return;
+            leftUnionArray[index] = rightUnionArray[i];
+
+            (index)++;
+        }
+    } else {
+        int totalSize = index + size;
+        ConstantUnion *rightUnionArray = node->getUnionArrayPointer();
+        if (!isMatrix) {
+            int count = 0;
+            for (int i = index; i < totalSize; i++) {
+                if (i >= instanceSize)
+                    return;
+
+                leftUnionArray[i] = rightUnionArray[count];
+
+                (index)++;
+                
+                if (node->getType().getObjectSize() > 1)
+                    count++;
+            }
+        } else {  // for matrix constructors
+            int count = 0;
+            int element = index;
+            for (int i = index; i < totalSize; i++) {
+                if (i >= instanceSize)
+                    return;
+                if (element - i == 0 || (i - element) % (matrixSize + 1) == 0 )
+                    leftUnionArray[i] = rightUnionArray[count];
+                else 
+                    leftUnionArray[i].setFConst(0.0f);
+
+                (index)++;
+
+                if (node->getType().getObjectSize() > 1)
+                    count++;                
+            }
+        }
+    }
+}
+
+bool TConstTraverser::visitLoop(Visit visit, TIntermLoop* node)
+{
+    infoSink.info.message(EPrefixInternalError, "Loop Node found in constant constructor", node->getLine());
+    error = true;
+    return false;
+}
+
+bool TConstTraverser::visitBranch(Visit visit, TIntermBranch* node)
+{
+    infoSink.info.message(EPrefixInternalError, "Branch Node found in constant constructor", node->getLine());
+    error = true;
+    return false;
+}
+
+//
+// This function is the one to call externally to start the traversal.
+// Individual functions can be initialized to 0 to skip processing of that
+// type of node.  It's children will still be processed.
+//
+bool TIntermediate::parseConstTree(TSourceLoc line, TIntermNode* root, ConstantUnion* unionArray, TOperator constructorType, TSymbolTable& symbolTable, TType t, bool singleConstantParam)
+{
+    if (root == 0)
+        return false;
+
+    TConstTraverser it(unionArray, singleConstantParam, constructorType, infoSink, symbolTable, t);
+
+    root->traverse(&it);
+    if (it.error)
+        return true;
+    else
+        return false;
+}
diff --git a/src/GLES2/compiler/preprocessor/Diagnostics.cpp b/src/GLES2/compiler/preprocessor/Diagnostics.cpp
new file mode 100644
index 0000000..06d1d80
--- /dev/null
+++ b/src/GLES2/compiler/preprocessor/Diagnostics.cpp
@@ -0,0 +1,127 @@
+//

+// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.

+// Use of this source code is governed by a BSD-style license that can be

+// found in the LICENSE file.

+//

+

+#include "Diagnostics.h"

+

+#include <cassert>

+

+namespace pp

+{

+

+Diagnostics::~Diagnostics()

+{

+}

+

+void Diagnostics::report(ID id,

+                         const SourceLocation& loc,

+                         const std::string& text)

+{

+    // TODO(alokp): Keep a count of errors and warnings.

+    print(id, loc, text);

+}

+

+Diagnostics::Severity Diagnostics::severity(ID id)

+{

+    if ((id > ERROR_BEGIN) && (id < ERROR_END))

+        return PP_ERROR;

+

+    if ((id > WARNING_BEGIN) && (id < WARNING_END))

+        return PP_WARNING;

+

+    assert(false);

+    return PP_ERROR;

+}

+

+std::string Diagnostics::message(ID id)

+{

+    switch (id)

+    {

+      // Errors begin.

+      case INTERNAL_ERROR:

+          return "internal error";

+      case OUT_OF_MEMORY:

+          return "out of memory";

+      case INVALID_CHARACTER:

+          return "invalid character";

+      case INVALID_NUMBER:

+          return "invalid number";

+      case INTEGER_OVERFLOW:

+          return "integer overflow";

+      case FLOAT_OVERFLOW:

+          return "float overflow";

+      case TOKEN_TOO_LONG:

+          return "token too long";

+      case INVALID_EXPRESSION:

+          return "invalid expression";

+      case DIVISION_BY_ZERO:

+          return "division by zero";

+      case EOF_IN_COMMENT:

+          return "unexpected end of file found in comment";

+      case UNEXPECTED_TOKEN:

+          return "unexpected token";

+      case DIRECTIVE_INVALID_NAME:

+          return "invalid directive name";

+      case MACRO_NAME_RESERVED:

+          return "macro name is reserved";

+      case MACRO_REDEFINED:

+          return "macro redefined";

+      case MACRO_PREDEFINED_REDEFINED:

+          return "predefined macro redefined";

+      case MACRO_PREDEFINED_UNDEFINED:

+          return "predefined macro undefined";

+      case MACRO_UNTERMINATED_INVOCATION:

+          return "unterminated macro invocation";

+      case MACRO_TOO_FEW_ARGS:

+          return "Not enough arguments for macro";

+      case MACRO_TOO_MANY_ARGS:

+          return "Too many arguments for macro";

+      case CONDITIONAL_ENDIF_WITHOUT_IF:

+          return "unexpected #endif found without a matching #if";

+      case CONDITIONAL_ELSE_WITHOUT_IF:

+          return "unexpected #else found without a matching #if";

+      case CONDITIONAL_ELSE_AFTER_ELSE:

+          return "unexpected #else found after another #else";

+      case CONDITIONAL_ELIF_WITHOUT_IF:

+          return "unexpected #elif found without a matching #if";

+      case CONDITIONAL_ELIF_AFTER_ELSE:

+          return "unexpected #elif found after #else";

+      case CONDITIONAL_UNTERMINATED:

+          return "unexpected end of file found in conditional block";

+      case INVALID_EXTENSION_NAME:

+          return "invalid extension name";

+      case INVALID_EXTENSION_BEHAVIOR:

+          return "invalid extension behavior";

+      case INVALID_EXTENSION_DIRECTIVE:

+          return "invalid extension directive";

+      case INVALID_VERSION_NUMBER:

+          return "invalid version number";

+      case INVALID_VERSION_DIRECTIVE:

+          return "invalid version directive";

+      case VERSION_NOT_FIRST_STATEMENT:

+        return "#version directive must occur before anything else, "

+               "except for comments and white space";

+      case INVALID_LINE_NUMBER:

+          return "invalid line number";

+      case INVALID_FILE_NUMBER:

+          return "invalid file number";

+      case INVALID_LINE_DIRECTIVE:

+          return "invalid line directive";

+      // Errors end.

+      // Warnings begin.

+      case EOF_IN_DIRECTIVE:

+          return "unexpected end of file found in directive";

+      case CONDITIONAL_UNEXPECTED_TOKEN:

+          return "unexpected token after conditional expression";

+      case UNRECOGNIZED_PRAGMA:

+          return "unrecognized pragma";

+      // Warnings end.

+      default:

+          assert(false);

+          return "";

+    }

+}

+

+}  // namespace pp

diff --git a/src/GLES2/compiler/preprocessor/Diagnostics.h b/src/GLES2/compiler/preprocessor/Diagnostics.h
new file mode 100644
index 0000000..4db9c30
--- /dev/null
+++ b/src/GLES2/compiler/preprocessor/Diagnostics.h
@@ -0,0 +1,87 @@
+//

+// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.

+// Use of this source code is governed by a BSD-style license that can be

+// found in the LICENSE file.

+//

+

+#ifndef COMPILER_PREPROCESSOR_DIAGNOSTICS_H_

+#define COMPILER_PREPROCESSOR_DIAGNOSTICS_H_

+

+#include <string>

+

+namespace pp

+{

+

+struct SourceLocation;

+

+// Base class for reporting diagnostic messages.

+// Derived classes are responsible for formatting and printing the messages.

+class Diagnostics

+{

+  public:

+    enum Severity

+    {

+        PP_ERROR,

+        PP_WARNING

+    };

+    enum ID

+    {

+        ERROR_BEGIN,

+        INTERNAL_ERROR,

+        OUT_OF_MEMORY,

+        INVALID_CHARACTER,

+        INVALID_NUMBER,

+        INTEGER_OVERFLOW,

+        FLOAT_OVERFLOW,

+        TOKEN_TOO_LONG,

+        INVALID_EXPRESSION,

+        DIVISION_BY_ZERO,

+        EOF_IN_COMMENT,

+        UNEXPECTED_TOKEN,

+        DIRECTIVE_INVALID_NAME,

+        MACRO_NAME_RESERVED,

+        MACRO_REDEFINED,

+        MACRO_PREDEFINED_REDEFINED,

+        MACRO_PREDEFINED_UNDEFINED,

+        MACRO_UNTERMINATED_INVOCATION,

+        MACRO_TOO_FEW_ARGS,

+        MACRO_TOO_MANY_ARGS,

+        CONDITIONAL_ENDIF_WITHOUT_IF,

+        CONDITIONAL_ELSE_WITHOUT_IF,

+        CONDITIONAL_ELSE_AFTER_ELSE,

+        CONDITIONAL_ELIF_WITHOUT_IF,

+        CONDITIONAL_ELIF_AFTER_ELSE,

+        CONDITIONAL_UNTERMINATED,

+        INVALID_EXTENSION_NAME,

+        INVALID_EXTENSION_BEHAVIOR,

+        INVALID_EXTENSION_DIRECTIVE,

+        INVALID_VERSION_NUMBER,

+        INVALID_VERSION_DIRECTIVE,

+        VERSION_NOT_FIRST_STATEMENT,

+        INVALID_LINE_NUMBER,

+        INVALID_FILE_NUMBER,

+        INVALID_LINE_DIRECTIVE,

+        ERROR_END,

+

+        WARNING_BEGIN,

+        EOF_IN_DIRECTIVE,

+        CONDITIONAL_UNEXPECTED_TOKEN,

+        UNRECOGNIZED_PRAGMA,

+        WARNING_END

+    };

+

+    virtual ~Diagnostics();

+

+    void report(ID id, const SourceLocation& loc, const std::string& text);

+

+  protected:

+    Severity severity(ID id);

+    std::string message(ID id);

+

+    virtual void print(ID id,

+                       const SourceLocation& loc,

+                       const std::string& text) = 0;

+};

+

+}  // namespace pp

+#endif  // COMPILER_PREPROCESSOR_DIAGNOSTICS_H_

diff --git a/src/GLES2/compiler/preprocessor/DirectiveHandler.cpp b/src/GLES2/compiler/preprocessor/DirectiveHandler.cpp
new file mode 100644
index 0000000..d67bee3
--- /dev/null
+++ b/src/GLES2/compiler/preprocessor/DirectiveHandler.cpp
@@ -0,0 +1,16 @@
+//

+// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.

+// Use of this source code is governed by a BSD-style license that can be

+// found in the LICENSE file.

+//

+

+#include "DirectiveHandler.h"

+

+namespace pp

+{

+

+DirectiveHandler::~DirectiveHandler()

+{

+}

+

+}  // namespace pp

diff --git a/src/GLES2/compiler/preprocessor/DirectiveHandler.h b/src/GLES2/compiler/preprocessor/DirectiveHandler.h
new file mode 100644
index 0000000..572b897
--- /dev/null
+++ b/src/GLES2/compiler/preprocessor/DirectiveHandler.h
@@ -0,0 +1,43 @@
+//

+// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.

+// Use of this source code is governed by a BSD-style license that can be

+// found in the LICENSE file.

+//

+

+#ifndef COMPILER_PREPROCESSOR_DIRECTIVE_HANDLER_H_

+#define COMPILER_PREPROCESSOR_DIRECTIVE_HANDLER_H_

+

+#include <string>

+

+namespace pp

+{

+

+struct SourceLocation;

+

+// Base class for handling directives.

+// Preprocessor uses this class to notify the clients about certain

+// preprocessor directives. Derived classes are responsible for

+// handling them in an appropriate manner.

+class DirectiveHandler

+{

+  public:

+    virtual ~DirectiveHandler();

+

+    virtual void handleError(const SourceLocation& loc,

+                             const std::string& msg) = 0;

+

+    // Handle pragma of form: #pragma name[(value)]

+    virtual void handlePragma(const SourceLocation& loc,

+                              const std::string& name,

+                              const std::string& value) = 0;

+

+    virtual void handleExtension(const SourceLocation& loc,

+                                 const std::string& name,

+                                 const std::string& behavior) = 0;

+

+    virtual void handleVersion(const SourceLocation& loc,

+                               int version) = 0;

+};

+

+}  // namespace pp

+#endif  // COMPILER_PREPROCESSOR_DIRECTIVE_HANDLER_H_

diff --git a/src/GLES2/compiler/preprocessor/DirectiveParser.cpp b/src/GLES2/compiler/preprocessor/DirectiveParser.cpp
new file mode 100644
index 0000000..0038469
--- /dev/null
+++ b/src/GLES2/compiler/preprocessor/DirectiveParser.cpp
@@ -0,0 +1,932 @@
+//

+// Copyright (c) 2011 The ANGLE Project Authors. All rights reserved.

+// Use of this source code is governed by a BSD-style license that can be

+// found in the LICENSE file.

+//

+

+#include "DirectiveParser.h"

+

+#include <cassert>

+#include <cstdlib>

+#include <sstream>

+

+#include "Diagnostics.h"

+#include "DirectiveHandler.h"

+#include "ExpressionParser.h"

+#include "MacroExpander.h"

+#include "Token.h"

+#include "Tokenizer.h"

+

+namespace {

+enum DirectiveType

+{

+    DIRECTIVE_NONE,

+    DIRECTIVE_DEFINE,

+    DIRECTIVE_UNDEF,

+    DIRECTIVE_IF,

+    DIRECTIVE_IFDEF,

+    DIRECTIVE_IFNDEF,

+    DIRECTIVE_ELSE,

+    DIRECTIVE_ELIF,

+    DIRECTIVE_ENDIF,

+    DIRECTIVE_ERROR,

+    DIRECTIVE_PRAGMA,

+    DIRECTIVE_EXTENSION,

+    DIRECTIVE_VERSION,

+    DIRECTIVE_LINE

+};

+}  // namespace

+

+static DirectiveType getDirective(const pp::Token* token)

+{

+    static const std::string kDirectiveDefine("define");

+    static const std::string kDirectiveUndef("undef");

+    static const std::string kDirectiveIf("if");

+    static const std::string kDirectiveIfdef("ifdef");

+    static const std::string kDirectiveIfndef("ifndef");

+    static const std::string kDirectiveElse("else");

+    static const std::string kDirectiveElif("elif");

+    static const std::string kDirectiveEndif("endif");

+    static const std::string kDirectiveError("error");

+    static const std::string kDirectivePragma("pragma");

+    static const std::string kDirectiveExtension("extension");

+    static const std::string kDirectiveVersion("version");

+    static const std::string kDirectiveLine("line");

+

+    if (token->type != pp::Token::IDENTIFIER)

+        return DIRECTIVE_NONE;

+

+    if (token->text == kDirectiveDefine)

+        return DIRECTIVE_DEFINE;

+    else if (token->text == kDirectiveUndef)

+        return DIRECTIVE_UNDEF;

+    else if (token->text == kDirectiveIf)

+        return DIRECTIVE_IF;

+    else if (token->text == kDirectiveIfdef)

+        return DIRECTIVE_IFDEF;

+    else if (token->text == kDirectiveIfndef)

+        return DIRECTIVE_IFNDEF;

+    else if (token->text == kDirectiveElse)

+        return DIRECTIVE_ELSE;

+    else if (token->text == kDirectiveElif)

+        return DIRECTIVE_ELIF;

+    else if (token->text == kDirectiveEndif)

+        return DIRECTIVE_ENDIF;

+    else if (token->text == kDirectiveError)

+        return DIRECTIVE_ERROR;

+    else if (token->text == kDirectivePragma)

+        return DIRECTIVE_PRAGMA;

+    else if (token->text == kDirectiveExtension)

+        return DIRECTIVE_EXTENSION;

+    else if (token->text == kDirectiveVersion)

+        return DIRECTIVE_VERSION;

+    else if (token->text == kDirectiveLine)

+        return DIRECTIVE_LINE;

+

+    return DIRECTIVE_NONE;

+}

+

+static bool isConditionalDirective(DirectiveType directive)

+{

+    switch (directive)

+    {

+      case DIRECTIVE_IF:

+      case DIRECTIVE_IFDEF:

+      case DIRECTIVE_IFNDEF:

+      case DIRECTIVE_ELSE:

+      case DIRECTIVE_ELIF:

+      case DIRECTIVE_ENDIF:

+        return true;

+      default:

+        return false;

+    }

+}

+

+// Returns true if the token represents End Of Directive.

+static bool isEOD(const pp::Token* token)

+{

+    return (token->type == '\n') || (token->type == pp::Token::LAST);

+}

+

+static void skipUntilEOD(pp::Lexer* lexer, pp::Token* token)

+{

+    while(!isEOD(token))

+    {

+        lexer->lex(token);

+    }

+}

+

+static bool isMacroNameReserved(const std::string& name)

+{

+    // Names prefixed with "GL_" are reserved.

+    if (name.substr(0, 3) == "GL_")

+        return true;

+

+    // Names containing two consecutive underscores are reserved.

+    if (name.find("__") != std::string::npos)

+        return true;

+

+    return false;

+}

+

+static bool isMacroPredefined(const std::string& name,

+                              const pp::MacroSet& macroSet)

+{

+    pp::MacroSet::const_iterator iter = macroSet.find(name);

+    return iter != macroSet.end() ? iter->second.predefined : false;

+}

+

+namespace pp

+{

+

+class DefinedParser : public Lexer

+{

+  public:

+    DefinedParser(Lexer* lexer,

+                  const MacroSet* macroSet,

+                  Diagnostics* diagnostics) :

+        mLexer(lexer),

+        mMacroSet(macroSet),

+        mDiagnostics(diagnostics)

+    {

+    }

+

+  protected:

+    virtual void lex(Token* token)

+    {

+        static const std::string kDefined("defined");

+

+        mLexer->lex(token);

+        if (token->type != Token::IDENTIFIER)

+            return;

+        if (token->text != kDefined)

+            return;

+

+        bool paren = false;

+        mLexer->lex(token);

+        if (token->type == '(')

+        {

+            paren = true;

+            mLexer->lex(token);

+        }

+

+        if (token->type != Token::IDENTIFIER)

+        {

+            mDiagnostics->report(Diagnostics::UNEXPECTED_TOKEN,

+                                 token->location, token->text);

+            skipUntilEOD(mLexer, token);

+            return;

+        }

+        MacroSet::const_iterator iter = mMacroSet->find(token->text);

+        std::string expression = iter != mMacroSet->end() ? "1" : "0";

+

+        if (paren)

+        {

+            mLexer->lex(token);

+            if (token->type != ')')

+            {

+                mDiagnostics->report(Diagnostics::UNEXPECTED_TOKEN,

+                                     token->location, token->text);

+                skipUntilEOD(mLexer, token);

+                return;

+            }

+        }

+

+        // We have a valid defined operator.

+        // Convert the current token into a CONST_INT token.

+        token->type = Token::CONST_INT;

+        token->text = expression;

+    }

+

+  private:

+    Lexer* mLexer;

+    const MacroSet* mMacroSet;

+    Diagnostics* mDiagnostics;

+};

+

+DirectiveParser::DirectiveParser(Tokenizer* tokenizer,

+                                 MacroSet* macroSet,

+                                 Diagnostics* diagnostics,

+                                 DirectiveHandler* directiveHandler) :

+    mPastFirstStatement(false),

+    mTokenizer(tokenizer),

+    mMacroSet(macroSet),

+    mDiagnostics(diagnostics),

+    mDirectiveHandler(directiveHandler)

+{

+}

+

+void DirectiveParser::lex(Token* token)

+{

+    do

+    {

+        mTokenizer->lex(token);

+

+        if (token->type == Token::PP_HASH)

+        {

+            parseDirective(token);

+            mPastFirstStatement = true;

+        }

+

+        if (token->type == Token::LAST)

+        {

+            if (!mConditionalStack.empty())

+            {

+                const ConditionalBlock& block = mConditionalStack.back();

+                mDiagnostics->report(Diagnostics::CONDITIONAL_UNTERMINATED,

+                                     block.location, block.type);

+            }

+            break;

+        }

+

+    } while (skipping() || (token->type == '\n'));

+

+    mPastFirstStatement = true;

+}

+

+void DirectiveParser::parseDirective(Token* token)

+{

+    assert(token->type == Token::PP_HASH);

+

+    mTokenizer->lex(token);

+    if (isEOD(token))

+    {

+        // Empty Directive.

+        return;

+    }

+

+    DirectiveType directive = getDirective(token);

+

+    // While in an excluded conditional block/group,

+    // we only parse conditional directives.

+    if (skipping() && !isConditionalDirective(directive))

+    {

+        skipUntilEOD(mTokenizer, token);

+        return;

+    }

+

+    switch(directive)

+    {

+      case DIRECTIVE_NONE:

+        mDiagnostics->report(Diagnostics::DIRECTIVE_INVALID_NAME,

+                             token->location, token->text);

+        skipUntilEOD(mTokenizer, token);

+        break;

+      case DIRECTIVE_DEFINE:

+        parseDefine(token);

+        break;

+      case DIRECTIVE_UNDEF:

+        parseUndef(token);

+        break;

+      case DIRECTIVE_IF:

+        parseIf(token);

+        break;

+      case DIRECTIVE_IFDEF:

+        parseIfdef(token);

+        break;

+      case DIRECTIVE_IFNDEF:

+        parseIfndef(token);

+        break;

+      case DIRECTIVE_ELSE:

+        parseElse(token);

+        break;

+      case DIRECTIVE_ELIF:

+        parseElif(token);

+        break;

+      case DIRECTIVE_ENDIF:

+        parseEndif(token);

+        break;

+      case DIRECTIVE_ERROR:

+        parseError(token);

+        break;

+      case DIRECTIVE_PRAGMA:

+        parsePragma(token);

+        break;

+      case DIRECTIVE_EXTENSION:

+        parseExtension(token);

+        break;

+      case DIRECTIVE_VERSION:

+        parseVersion(token);

+        break;

+      case DIRECTIVE_LINE:

+        parseLine(token);

+        break;

+      default:

+        assert(false);

+        break;

+    }

+

+    skipUntilEOD(mTokenizer, token);

+    if (token->type == Token::LAST)

+    {

+        mDiagnostics->report(Diagnostics::EOF_IN_DIRECTIVE,

+                             token->location, token->text);

+    }

+}

+

+void DirectiveParser::parseDefine(Token* token)

+{

+    assert(getDirective(token) == DIRECTIVE_DEFINE);

+

+    mTokenizer->lex(token);

+    if (token->type != Token::IDENTIFIER)

+    {

+        mDiagnostics->report(Diagnostics::UNEXPECTED_TOKEN,

+                             token->location, token->text);

+        return;

+    }

+    if (isMacroPredefined(token->text, *mMacroSet))

+    {

+        mDiagnostics->report(Diagnostics::MACRO_PREDEFINED_REDEFINED,

+                             token->location, token->text);

+        return;

+    }

+    if (isMacroNameReserved(token->text))

+    {

+        mDiagnostics->report(Diagnostics::MACRO_NAME_RESERVED,

+                             token->location, token->text);

+        return;

+    }

+

+    Macro macro;

+    macro.type = Macro::kTypeObj;

+    macro.name = token->text;

+

+    mTokenizer->lex(token);

+    if (token->type == '(' && !token->hasLeadingSpace())

+    {

+        // Function-like macro. Collect arguments.

+        macro.type = Macro::kTypeFunc;

+        do {

+            mTokenizer->lex(token);

+            if (token->type != Token::IDENTIFIER)

+                break;

+            macro.parameters.push_back(token->text);

+

+            mTokenizer->lex(token);  // Get ','.

+        } while (token->type == ',');

+

+        if (token->type != ')')

+        {

+            mDiagnostics->report(Diagnostics::UNEXPECTED_TOKEN,

+                                 token->location,

+                                 token->text);

+            return;

+        }

+        mTokenizer->lex(token);  // Get ')'.

+    }

+

+    while ((token->type != '\n') && (token->type != Token::LAST))

+    {

+        // Reset the token location because it is unnecessary in replacement

+        // list. Resetting it also allows us to reuse Token::equals() to

+        // compare macros.

+        token->location = SourceLocation();

+        macro.replacements.push_back(*token);

+        mTokenizer->lex(token);

+    }

+    if (!macro.replacements.empty())

+    {

+        // Whitespace preceding the replacement list is not considered part of

+        // the replacement list for either form of macro.

+        macro.replacements.front().setHasLeadingSpace(false);

+    }

+

+    // Check for macro redefinition.

+    MacroSet::const_iterator iter = mMacroSet->find(macro.name);

+    if (iter != mMacroSet->end() && !macro.equals(iter->second))

+    {

+        mDiagnostics->report(Diagnostics::MACRO_REDEFINED,

+                             token->location,

+                             macro.name);

+        return;

+    }

+    mMacroSet->insert(std::make_pair(macro.name, macro));

+}

+

+void DirectiveParser::parseUndef(Token* token)

+{

+    assert(getDirective(token) == DIRECTIVE_UNDEF);

+

+    mTokenizer->lex(token);

+    if (token->type != Token::IDENTIFIER)

+    {

+        mDiagnostics->report(Diagnostics::UNEXPECTED_TOKEN,

+                             token->location, token->text);

+        return;

+    }

+

+    MacroSet::iterator iter = mMacroSet->find(token->text);

+    if (iter != mMacroSet->end())

+    {

+        if (iter->second.predefined)

+        {

+            mDiagnostics->report(Diagnostics::MACRO_PREDEFINED_UNDEFINED,

+                                 token->location, token->text);

+        }

+        else

+        {

+            mMacroSet->erase(iter);

+        }

+    }

+

+    mTokenizer->lex(token);

+}

+

+void DirectiveParser::parseIf(Token* token)

+{

+    assert(getDirective(token) == DIRECTIVE_IF);

+    parseConditionalIf(token);

+}

+

+void DirectiveParser::parseIfdef(Token* token)

+{

+    assert(getDirective(token) == DIRECTIVE_IFDEF);

+    parseConditionalIf(token);

+}

+

+void DirectiveParser::parseIfndef(Token* token)

+{

+    assert(getDirective(token) == DIRECTIVE_IFNDEF);

+    parseConditionalIf(token);

+}

+

+void DirectiveParser::parseElse(Token* token)

+{

+    assert(getDirective(token) == DIRECTIVE_ELSE);

+

+    if (mConditionalStack.empty())

+    {

+        mDiagnostics->report(Diagnostics::CONDITIONAL_ELSE_WITHOUT_IF,

+                             token->location, token->text);

+        skipUntilEOD(mTokenizer, token);

+        return;

+    }

+

+    ConditionalBlock& block = mConditionalStack.back();

+    if (block.skipBlock)

+    {

+        // No diagnostics. Just skip the whole line.

+        skipUntilEOD(mTokenizer, token);

+        return;

+    }

+    if (block.foundElseGroup)

+    {

+        mDiagnostics->report(Diagnostics::CONDITIONAL_ELSE_AFTER_ELSE,

+                             token->location, token->text);

+        skipUntilEOD(mTokenizer, token);

+        return;

+    }

+

+    block.foundElseGroup = true;

+    block.skipGroup = block.foundValidGroup;

+    block.foundValidGroup = true;

+

+    // Warn if there are extra tokens after #else.

+    mTokenizer->lex(token);

+    if (!isEOD(token))

+    {

+        mDiagnostics->report(Diagnostics::CONDITIONAL_UNEXPECTED_TOKEN,

+                             token->location, token->text);

+        skipUntilEOD(mTokenizer, token);

+    }

+}

+

+void DirectiveParser::parseElif(Token* token)

+{

+    assert(getDirective(token) == DIRECTIVE_ELIF);

+

+    if (mConditionalStack.empty())

+    {

+        mDiagnostics->report(Diagnostics::CONDITIONAL_ELIF_WITHOUT_IF,

+                             token->location, token->text);

+        skipUntilEOD(mTokenizer, token);

+        return;

+    }

+

+    ConditionalBlock& block = mConditionalStack.back();

+    if (block.skipBlock)

+    {

+        // No diagnostics. Just skip the whole line.

+        skipUntilEOD(mTokenizer, token);

+        return;

+    }

+    if (block.foundElseGroup)

+    {

+        mDiagnostics->report(Diagnostics::CONDITIONAL_ELIF_AFTER_ELSE,

+                             token->location, token->text);

+        skipUntilEOD(mTokenizer, token);

+        return;

+    }

+    if (block.foundValidGroup)

+    {

+        // Do not parse the expression.

+        // Also be careful not to emit a diagnostic.

+        block.skipGroup = true;

+        skipUntilEOD(mTokenizer, token);

+        return;

+    }

+

+    int expression = parseExpressionIf(token);

+    block.skipGroup = expression == 0;

+    block.foundValidGroup = expression != 0;

+}

+

+void DirectiveParser::parseEndif(Token* token)

+{

+    assert(getDirective(token) == DIRECTIVE_ENDIF);

+

+    if (mConditionalStack.empty())

+    {

+        mDiagnostics->report(Diagnostics::CONDITIONAL_ENDIF_WITHOUT_IF,

+                             token->location, token->text);

+        skipUntilEOD(mTokenizer, token);

+        return;

+    }

+

+    mConditionalStack.pop_back();

+

+    // Warn if there are tokens after #endif.

+    mTokenizer->lex(token);

+    if (!isEOD(token))

+    {

+        mDiagnostics->report(Diagnostics::CONDITIONAL_UNEXPECTED_TOKEN,

+                             token->location, token->text);

+        skipUntilEOD(mTokenizer, token);

+    }

+}

+

+void DirectiveParser::parseError(Token* token)

+{

+    assert(getDirective(token) == DIRECTIVE_ERROR);

+

+    std::ostringstream stream;

+    mTokenizer->lex(token);

+    while ((token->type != '\n') && (token->type != Token::LAST))

+    {

+        stream << *token;

+        mTokenizer->lex(token);

+    }

+    mDirectiveHandler->handleError(token->location, stream.str());

+}

+

+// Parses pragma of form: #pragma name[(value)].

+void DirectiveParser::parsePragma(Token* token)

+{

+    assert(getDirective(token) == DIRECTIVE_PRAGMA);

+

+    enum State

+    {

+        PRAGMA_NAME,

+        LEFT_PAREN,

+        PRAGMA_VALUE,

+        RIGHT_PAREN

+    };

+

+    bool valid = true;

+    std::string name, value;

+    int state = PRAGMA_NAME;

+

+    mTokenizer->lex(token);

+    while ((token->type != '\n') && (token->type != Token::LAST))

+    {

+        switch(state++)

+        {

+          case PRAGMA_NAME:

+            name = token->text;

+            valid = valid && (token->type == Token::IDENTIFIER);

+            break;

+          case LEFT_PAREN:

+            valid = valid && (token->type == '(');

+            break;

+          case PRAGMA_VALUE:

+            value = token->text;

+            valid = valid && (token->type == Token::IDENTIFIER);

+            break;

+          case RIGHT_PAREN:

+            valid = valid && (token->type == ')');

+            break;

+          default:

+            valid = false;

+            break;

+        }

+        mTokenizer->lex(token);

+    }

+

+    valid = valid && ((state == PRAGMA_NAME) ||     // Empty pragma.

+                      (state == LEFT_PAREN) ||      // Without value.

+                      (state == RIGHT_PAREN + 1));  // With value.

+    if (!valid)

+    {

+        mDiagnostics->report(Diagnostics::UNRECOGNIZED_PRAGMA,

+                             token->location, name);

+    }

+    else if (state > PRAGMA_NAME)  // Do not notify for empty pragma.

+    {

+        mDirectiveHandler->handlePragma(token->location, name, value);

+    }

+}

+

+void DirectiveParser::parseExtension(Token* token)

+{

+    assert(getDirective(token) == DIRECTIVE_EXTENSION);

+

+    enum State

+    {

+        EXT_NAME,

+        COLON,

+        EXT_BEHAVIOR

+    };

+

+    bool valid = true;

+    std::string name, behavior;

+    int state = EXT_NAME;

+

+    mTokenizer->lex(token);

+    while ((token->type != '\n') && (token->type != Token::LAST))

+    {

+        switch (state++)

+        {

+          case EXT_NAME:

+            if (valid && (token->type != Token::IDENTIFIER))

+            {

+                mDiagnostics->report(Diagnostics::INVALID_EXTENSION_NAME,

+                                     token->location, token->text);

+                valid = false;

+            }

+            if (valid) name = token->text;

+            break;

+          case COLON:

+            if (valid && (token->type != ':'))

+            {

+                mDiagnostics->report(Diagnostics::UNEXPECTED_TOKEN,

+                                     token->location, token->text);

+                valid = false;

+            }

+            break;

+          case EXT_BEHAVIOR:

+            if (valid && (token->type != Token::IDENTIFIER))

+            {

+                mDiagnostics->report(Diagnostics::INVALID_EXTENSION_BEHAVIOR,

+                                     token->location, token->text);

+                valid = false;

+            }

+            if (valid) behavior = token->text;

+            break;

+          default:

+            if (valid)

+            {

+                mDiagnostics->report(Diagnostics::UNEXPECTED_TOKEN,

+                                     token->location, token->text);

+                valid = false;

+            }

+            break;

+        }

+        mTokenizer->lex(token);

+    }

+    if (valid && (state != EXT_BEHAVIOR + 1))

+    {

+        mDiagnostics->report(Diagnostics::INVALID_EXTENSION_DIRECTIVE,

+                             token->location, token->text);

+        valid = false;

+    }

+    if (valid)

+        mDirectiveHandler->handleExtension(token->location, name, behavior);

+}

+

+void DirectiveParser::parseVersion(Token* token)

+{

+    assert(getDirective(token) == DIRECTIVE_VERSION);

+

+    if (mPastFirstStatement)

+    {

+        mDiagnostics->report(Diagnostics::VERSION_NOT_FIRST_STATEMENT,

+                             token->location, token->text);

+        skipUntilEOD(mTokenizer, token);

+        return;

+    }

+

+    enum State

+    {

+        VERSION_NUMBER

+    };

+

+    bool valid = true;

+    int version = 0;

+    int state = VERSION_NUMBER;

+

+    mTokenizer->lex(token);

+    while ((token->type != '\n') && (token->type != Token::LAST))

+    {

+        switch (state++)

+        {

+          case VERSION_NUMBER:

+            if (valid && (token->type != Token::CONST_INT))

+            {

+                mDiagnostics->report(Diagnostics::INVALID_VERSION_NUMBER,

+                                     token->location, token->text);

+                valid = false;

+            }

+            if (valid && !token->iValue(&version))

+            {

+                mDiagnostics->report(Diagnostics::INTEGER_OVERFLOW,

+                                     token->location, token->text);

+                valid = false;

+            }

+            break;

+          default:

+            if (valid)

+            {

+                mDiagnostics->report(Diagnostics::UNEXPECTED_TOKEN,

+                                     token->location, token->text);

+                valid = false;

+            }

+            break;

+        }

+        mTokenizer->lex(token);

+    }

+    if (valid && (state != VERSION_NUMBER + 1))

+    {

+        mDiagnostics->report(Diagnostics::INVALID_VERSION_DIRECTIVE,

+                             token->location, token->text);

+        valid = false;

+    }

+    if (valid)

+        mDirectiveHandler->handleVersion(token->location, version);

+}

+

+void DirectiveParser::parseLine(Token* token)

+{

+    assert(getDirective(token) == DIRECTIVE_LINE);

+

+    enum State

+    {

+        LINE_NUMBER,

+        FILE_NUMBER

+    };

+

+    bool valid = true;

+    int line = 0, file = 0;

+    int state = LINE_NUMBER;

+

+    MacroExpander macroExpander(mTokenizer, mMacroSet, mDiagnostics);

+    macroExpander.lex(token);

+    while ((token->type != '\n') && (token->type != Token::LAST))

+    {

+        switch (state++)

+        {

+          case LINE_NUMBER:

+            if (valid && (token->type != Token::CONST_INT))

+            {

+                mDiagnostics->report(Diagnostics::INVALID_LINE_NUMBER,

+                                     token->location, token->text);

+                valid = false;

+            }

+            if (valid && !token->iValue(&line))

+            {

+                mDiagnostics->report(Diagnostics::INTEGER_OVERFLOW,

+                                     token->location, token->text);

+                valid = false;

+            }

+            break;

+          case FILE_NUMBER:

+            if (valid && (token->type != Token::CONST_INT))

+            {

+                mDiagnostics->report(Diagnostics::INVALID_FILE_NUMBER,

+                                     token->location, token->text);

+                valid = false;

+            }

+            if (valid && !token->iValue(&file))

+            {

+                mDiagnostics->report(Diagnostics::INTEGER_OVERFLOW,

+                                     token->location, token->text);

+                valid = false;

+            }

+            break;

+          default:

+            if (valid)

+            {

+                mDiagnostics->report(Diagnostics::UNEXPECTED_TOKEN,

+                                     token->location, token->text);

+                valid = false;

+            }

+            break;

+        }

+        macroExpander.lex(token);

+    }

+

+    if (valid && (state != FILE_NUMBER) && (state != FILE_NUMBER + 1))

+    {

+        mDiagnostics->report(Diagnostics::INVALID_LINE_DIRECTIVE,

+                             token->location, token->text);

+        valid = false;

+    }

+    if (valid)

+    {

+        mTokenizer->setLineNumber(line);

+        if (state == FILE_NUMBER + 1) mTokenizer->setFileNumber(file);

+    }

+}

+

+bool DirectiveParser::skipping() const

+{

+    if (mConditionalStack.empty()) return false;

+

+    const ConditionalBlock& block = mConditionalStack.back();

+    return block.skipBlock || block.skipGroup;

+}

+

+void DirectiveParser::parseConditionalIf(Token* token)

+{

+    ConditionalBlock block;

+    block.type = token->text;

+    block.location = token->location;

+

+    if (skipping())

+    {

+        // This conditional block is inside another conditional group

+        // which is skipped. As a consequence this whole block is skipped.

+        // Be careful not to parse the conditional expression that might

+        // emit a diagnostic.

+        skipUntilEOD(mTokenizer, token);

+        block.skipBlock = true;

+    }

+    else

+    {

+        DirectiveType directive = getDirective(token);

+

+        int expression = 0;

+        switch (directive)

+        {

+          case DIRECTIVE_IF:

+            expression = parseExpressionIf(token);

+            break;

+          case DIRECTIVE_IFDEF:

+            expression = parseExpressionIfdef(token);

+            break;

+          case DIRECTIVE_IFNDEF:

+            expression = parseExpressionIfdef(token) == 0 ? 1 : 0;

+            break;

+          default:

+            assert(false);

+            break;

+        }

+        block.skipGroup = expression == 0;

+        block.foundValidGroup = expression != 0;

+    }

+    mConditionalStack.push_back(block);

+}

+

+int DirectiveParser::parseExpressionIf(Token* token)

+{

+    assert((getDirective(token) == DIRECTIVE_IF) ||

+           (getDirective(token) == DIRECTIVE_ELIF));

+

+    DefinedParser definedParser(mTokenizer, mMacroSet, mDiagnostics);

+    MacroExpander macroExpander(&definedParser, mMacroSet, mDiagnostics);

+    ExpressionParser expressionParser(&macroExpander, mDiagnostics);

+

+    int expression = 0;

+    macroExpander.lex(token);

+    expressionParser.parse(token, &expression);

+

+    // Warn if there are tokens after #if expression.

+    if (!isEOD(token))

+    {

+        mDiagnostics->report(Diagnostics::CONDITIONAL_UNEXPECTED_TOKEN,

+                             token->location, token->text);

+        skipUntilEOD(mTokenizer, token);

+    }

+

+    return expression;

+}

+

+int DirectiveParser::parseExpressionIfdef(Token* token)

+{

+    assert((getDirective(token) == DIRECTIVE_IFDEF) ||

+           (getDirective(token) == DIRECTIVE_IFNDEF));

+

+    mTokenizer->lex(token);

+    if (token->type != Token::IDENTIFIER)

+    {

+        mDiagnostics->report(Diagnostics::UNEXPECTED_TOKEN,

+                             token->location, token->text);

+        skipUntilEOD(mTokenizer, token);

+        return 0;

+    }

+

+    MacroSet::const_iterator iter = mMacroSet->find(token->text);

+    int expression = iter != mMacroSet->end() ? 1 : 0;

+

+    // Warn if there are tokens after #ifdef expression.

+    mTokenizer->lex(token);

+    if (!isEOD(token))

+    {

+        mDiagnostics->report(Diagnostics::CONDITIONAL_UNEXPECTED_TOKEN,

+                             token->location, token->text);

+        skipUntilEOD(mTokenizer, token);

+    }

+    return expression;

+}

+

+}  // namespace pp

diff --git a/src/GLES2/compiler/preprocessor/DirectiveParser.h b/src/GLES2/compiler/preprocessor/DirectiveParser.h
new file mode 100644
index 0000000..7b07392
--- /dev/null
+++ b/src/GLES2/compiler/preprocessor/DirectiveParser.h
@@ -0,0 +1,82 @@
+//

+// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.

+// Use of this source code is governed by a BSD-style license that can be

+// found in the LICENSE file.

+//

+

+#ifndef COMPILER_PREPROCESSOR_DIRECTIVE_PARSER_H_

+#define COMPILER_PREPROCESSOR_DIRECTIVE_PARSER_H_

+

+#include "Lexer.h"

+#include "Macro.h"

+#include "pp_utils.h"

+#include "SourceLocation.h"

+

+namespace pp

+{

+

+class Diagnostics;

+class DirectiveHandler;

+class Tokenizer;

+

+class DirectiveParser : public Lexer

+{

+  public:

+    DirectiveParser(Tokenizer* tokenizer,

+                    MacroSet* macroSet,

+                    Diagnostics* diagnostics,

+                    DirectiveHandler* directiveHandler);

+

+    virtual void lex(Token* token);

+

+  private:

+    PP_DISALLOW_COPY_AND_ASSIGN(DirectiveParser);

+

+    void parseDirective(Token* token);

+    void parseDefine(Token* token);

+    void parseUndef(Token* token);

+    void parseIf(Token* token);

+    void parseIfdef(Token* token);

+    void parseIfndef(Token* token);

+    void parseElse(Token* token);

+    void parseElif(Token* token);

+    void parseEndif(Token* token);

+    void parseError(Token* token);

+    void parsePragma(Token* token);

+    void parseExtension(Token* token);

+    void parseVersion(Token* token);

+    void parseLine(Token* token);

+

+    bool skipping() const;

+    void parseConditionalIf(Token* token);

+    int parseExpressionIf(Token* token);

+    int parseExpressionIfdef(Token* token);

+

+    struct ConditionalBlock

+    {

+        std::string type;

+        SourceLocation location;

+        bool skipBlock;

+        bool skipGroup;

+        bool foundValidGroup;

+        bool foundElseGroup;

+

+        ConditionalBlock() :

+            skipBlock(false),

+            skipGroup(false),

+            foundValidGroup(false),

+            foundElseGroup(false)

+        {

+        }

+    };

+    bool mPastFirstStatement;

+    std::vector<ConditionalBlock> mConditionalStack;

+    Tokenizer* mTokenizer;

+    MacroSet* mMacroSet;

+    Diagnostics* mDiagnostics;

+    DirectiveHandler* mDirectiveHandler;

+};

+

+}  // namespace pp

+#endif  // COMPILER_PREPROCESSOR_DIRECTIVE_PARSER_H_

+

diff --git a/src/GLES2/compiler/preprocessor/ExpressionParser.cpp b/src/GLES2/compiler/preprocessor/ExpressionParser.cpp
new file mode 100644
index 0000000..6bcae27
--- /dev/null
+++ b/src/GLES2/compiler/preprocessor/ExpressionParser.cpp
@@ -0,0 +1,1926 @@
+

+/* A Bison parser, made by GNU Bison 2.4.1.  */

+

+/* Skeleton implementation for Bison's Yacc-like parsers in C

+   

+      Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006

+   Free Software Foundation, Inc.

+   

+   This program 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.

+   

+   This program 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 this program.  If not, see <http://www.gnu.org/licenses/>.  */

+

+/* As a special exception, you may create a larger work that contains

+   part or all of the Bison parser skeleton and distribute that work

+   under terms of your choice, so long as that work isn't itself a

+   parser generator using the skeleton or a modified version thereof

+   as a parser skeleton.  Alternatively, if you modify or redistribute

+   the parser skeleton itself, you may (at your option) remove this

+   special exception, which will cause the skeleton and the resulting

+   Bison output files to be licensed under the GNU General Public

+   License without this special exception.

+   

+   This special exception was added by the Free Software Foundation in

+   version 2.2 of Bison.  */

+

+/* C LALR(1) parser skeleton written by Richard Stallman, by

+   simplifying the original so-called "semantic" parser.  */

+

+/* All symbols defined below should begin with yy or YY, to avoid

+   infringing on user name space.  This should be done even for local

+   variables, as they might otherwise be expanded by user macros.

+   There are some unavoidable exceptions within include files to

+   define necessary library symbols; they are noted "INFRINGES ON

+   USER NAME SPACE" below.  */

+

+/* Identify Bison output.  */

+#define YYBISON 1

+

+/* Bison version.  */

+#define YYBISON_VERSION "2.4.1"

+

+/* Skeleton name.  */

+#define YYSKELETON_NAME "yacc.c"

+

+/* Pure parsers.  */

+#define YYPURE 1

+

+/* Push parsers.  */

+#define YYPUSH 0

+

+/* Pull parsers.  */

+#define YYPULL 1

+

+/* Using locations.  */

+#define YYLSP_NEEDED 0

+

+/* Substitute the variable and function names.  */

+#define yyparse         ppparse

+#define yylex           pplex

+#define yyerror         pperror

+#define yylval          pplval

+#define yychar          ppchar

+#define yydebug         ppdebug

+#define yynerrs         ppnerrs

+

+

+/* Copy the first part of user declarations.  */

+

+

+//

+// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.

+// Use of this source code is governed by a BSD-style license that can be

+// found in the LICENSE file.

+//

+

+// This file is auto-generated by generate_parser.sh. DO NOT EDIT!

+

+#if defined(__GNUC__)

+// Triggered by the auto-generated pplval variable.

+#pragma GCC diagnostic ignored "-Wuninitialized"

+#elif defined(_MSC_VER)

+#pragma warning(disable: 4065 4701)

+#endif

+

+#include "ExpressionParser.h"

+

+#include <cassert>

+#include <sstream>

+

+#include "Diagnostics.h"

+#include "Lexer.h"

+#include "Token.h"

+

+#if defined(_MSC_VER)

+typedef __int64 YYSTYPE;

+#else

+#include <stdint.h>

+typedef intmax_t YYSTYPE;

+#endif  // _MSC_VER

+#define YYSTYPE_IS_TRIVIAL 1

+#define YYSTYPE_IS_DECLARED 1

+

+namespace {

+struct Context

+{

+    pp::Diagnostics* diagnostics;

+    pp::Lexer* lexer;

+    pp::Token* token;

+    int* result;

+};

+}  // namespace

+

+

+static int yylex(YYSTYPE* lvalp, Context* context);

+static void yyerror(Context* context, const char* reason);

+

+

+

+/* Enabling traces.  */

+#ifndef YYDEBUG

+# define YYDEBUG 0

+#endif

+

+/* Enabling verbose error messages.  */

+#ifdef YYERROR_VERBOSE

+# undef YYERROR_VERBOSE

+# define YYERROR_VERBOSE 1

+#else

+# define YYERROR_VERBOSE 0

+#endif

+

+/* Enabling the token table.  */

+#ifndef YYTOKEN_TABLE

+# define YYTOKEN_TABLE 0

+#endif

+

+

+/* Tokens.  */

+#ifndef YYTOKENTYPE

+# define YYTOKENTYPE

+   /* Put the tokens into the symbol table, so that GDB and other debuggers

+      know about them.  */

+   enum yytokentype {

+     TOK_CONST_INT = 258,

+     TOK_OP_OR = 259,

+     TOK_OP_AND = 260,

+     TOK_OP_NE = 261,

+     TOK_OP_EQ = 262,

+     TOK_OP_GE = 263,

+     TOK_OP_LE = 264,

+     TOK_OP_RIGHT = 265,

+     TOK_OP_LEFT = 266,

+     TOK_UNARY = 267

+   };

+#endif

+

+

+

+#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED

+typedef int YYSTYPE;

+# define YYSTYPE_IS_TRIVIAL 1

+# define yystype YYSTYPE /* obsolescent; will be withdrawn */

+# define YYSTYPE_IS_DECLARED 1

+#endif

+

+

+/* Copy the second part of user declarations.  */

+

+

+

+#ifdef short

+# undef short

+#endif

+

+#ifdef YYTYPE_UINT8

+typedef YYTYPE_UINT8 yytype_uint8;

+#else

+typedef unsigned char yytype_uint8;

+#endif

+

+#ifdef YYTYPE_INT8

+typedef YYTYPE_INT8 yytype_int8;

+#elif (defined __STDC__ || defined __C99__FUNC__ \

+     || defined __cplusplus || defined _MSC_VER)

+typedef signed char yytype_int8;

+#else

+typedef short int yytype_int8;

+#endif

+

+#ifdef YYTYPE_UINT16

+typedef YYTYPE_UINT16 yytype_uint16;

+#else

+typedef unsigned short int yytype_uint16;

+#endif

+

+#ifdef YYTYPE_INT16

+typedef YYTYPE_INT16 yytype_int16;

+#else

+typedef short int yytype_int16;

+#endif

+

+#ifndef YYSIZE_T

+# ifdef __SIZE_TYPE__

+#  define YYSIZE_T __SIZE_TYPE__

+# elif defined size_t

+#  define YYSIZE_T size_t

+# elif ! defined YYSIZE_T && (defined __STDC__ || defined __C99__FUNC__ \

+     || defined __cplusplus || defined _MSC_VER)

+#  include <stddef.h> /* INFRINGES ON USER NAME SPACE */

+#  define YYSIZE_T size_t

+# else

+#  define YYSIZE_T unsigned int

+# endif

+#endif

+

+#define YYSIZE_MAXIMUM ((YYSIZE_T) -1)

+

+#ifndef YY_

+# if YYENABLE_NLS

+#  if ENABLE_NLS

+#   include <libintl.h> /* INFRINGES ON USER NAME SPACE */

+#   define YY_(msgid) dgettext ("bison-runtime", msgid)

+#  endif

+# endif

+# ifndef YY_

+#  define YY_(msgid) msgid

+# endif

+#endif

+

+/* Suppress unused-variable warnings by "using" E.  */

+#if ! defined lint || defined __GNUC__

+# define YYUSE(e) ((void) (e))

+#else

+# define YYUSE(e) /* empty */

+#endif

+

+/* Identity function, used to suppress warnings about constant conditions.  */

+#ifndef lint

+# define YYID(n) (n)

+#else

+#if (defined __STDC__ || defined __C99__FUNC__ \

+     || defined __cplusplus || defined _MSC_VER)

+static int

+YYID (int yyi)

+#else

+static int

+YYID (yyi)

+    int yyi;

+#endif

+{

+  return yyi;

+}

+#endif

+

+#if ! defined yyoverflow || YYERROR_VERBOSE

+

+/* The parser invokes alloca or malloc; define the necessary symbols.  */

+

+# ifdef YYSTACK_USE_ALLOCA

+#  if YYSTACK_USE_ALLOCA

+#   ifdef __GNUC__

+#    define YYSTACK_ALLOC __builtin_alloca

+#   elif defined __BUILTIN_VA_ARG_INCR

+#    include <alloca.h> /* INFRINGES ON USER NAME SPACE */

+#   elif defined _AIX

+#    define YYSTACK_ALLOC __alloca

+#   elif defined _MSC_VER

+#    include <malloc.h> /* INFRINGES ON USER NAME SPACE */

+#    define alloca _alloca

+#   else

+#    define YYSTACK_ALLOC alloca

+#    if ! defined _ALLOCA_H && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \

+     || defined __cplusplus || defined _MSC_VER)

+#     include <stdlib.h> /* INFRINGES ON USER NAME SPACE */

+#     ifndef _STDLIB_H

+#      define _STDLIB_H 1

+#     endif

+#    endif

+#   endif

+#  endif

+# endif

+

+# ifdef YYSTACK_ALLOC

+   /* Pacify GCC's `empty if-body' warning.  */

+#  define YYSTACK_FREE(Ptr) do { /* empty */; } while (YYID (0))

+#  ifndef YYSTACK_ALLOC_MAXIMUM

+    /* The OS might guarantee only one guard page at the bottom of the stack,

+       and a page size can be as small as 4096 bytes.  So we cannot safely

+       invoke alloca (N) if N exceeds 4096.  Use a slightly smaller number

+       to allow for a few compiler-allocated temporary stack slots.  */

+#   define YYSTACK_ALLOC_MAXIMUM 4032 /* reasonable circa 2006 */

+#  endif

+# else

+#  define YYSTACK_ALLOC YYMALLOC

+#  define YYSTACK_FREE YYFREE

+#  ifndef YYSTACK_ALLOC_MAXIMUM

+#   define YYSTACK_ALLOC_MAXIMUM YYSIZE_MAXIMUM

+#  endif

+#  if (defined __cplusplus && ! defined _STDLIB_H \

+       && ! ((defined YYMALLOC || defined malloc) \

+	     && (defined YYFREE || defined free)))

+#   include <stdlib.h> /* INFRINGES ON USER NAME SPACE */

+#   ifndef _STDLIB_H

+#    define _STDLIB_H 1

+#   endif

+#  endif

+#  ifndef YYMALLOC

+#   define YYMALLOC malloc

+#   if ! defined malloc && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \

+     || defined __cplusplus || defined _MSC_VER)

+void *malloc (YYSIZE_T); /* INFRINGES ON USER NAME SPACE */

+#   endif

+#  endif

+#  ifndef YYFREE

+#   define YYFREE free

+#   if ! defined free && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \

+     || defined __cplusplus || defined _MSC_VER)

+void free (void *); /* INFRINGES ON USER NAME SPACE */

+#   endif

+#  endif

+# endif

+#endif /* ! defined yyoverflow || YYERROR_VERBOSE */

+

+

+#if (! defined yyoverflow \

+     && (! defined __cplusplus \

+	 || (defined YYSTYPE_IS_TRIVIAL && YYSTYPE_IS_TRIVIAL)))

+

+/* A type that is properly aligned for any stack member.  */

+union yyalloc

+{

+  yytype_int16 yyss_alloc;

+  YYSTYPE yyvs_alloc;

+};

+

+/* The size of the maximum gap between one aligned stack and the next.  */

+# define YYSTACK_GAP_MAXIMUM (sizeof (union yyalloc) - 1)

+

+/* The size of an array large to enough to hold all stacks, each with

+   N elements.  */

+# define YYSTACK_BYTES(N) \

+     ((N) * (sizeof (yytype_int16) + sizeof (YYSTYPE)) \

+      + YYSTACK_GAP_MAXIMUM)

+

+/* Copy COUNT objects from FROM to TO.  The source and destination do

+   not overlap.  */

+# ifndef YYCOPY

+#  if defined __GNUC__ && 1 < __GNUC__

+#   define YYCOPY(To, From, Count) \

+      __builtin_memcpy (To, From, (Count) * sizeof (*(From)))

+#  else

+#   define YYCOPY(To, From, Count)		\

+      do					\

+	{					\

+	  YYSIZE_T yyi;				\

+	  for (yyi = 0; yyi < (Count); yyi++)	\

+	    (To)[yyi] = (From)[yyi];		\

+	}					\

+      while (YYID (0))

+#  endif

+# endif

+

+/* Relocate STACK from its old location to the new one.  The

+   local variables YYSIZE and YYSTACKSIZE give the old and new number of

+   elements in the stack, and YYPTR gives the new location of the

+   stack.  Advance YYPTR to a properly aligned location for the next

+   stack.  */

+# define YYSTACK_RELOCATE(Stack_alloc, Stack)				\

+    do									\

+      {									\

+	YYSIZE_T yynewbytes;						\

+	YYCOPY (&yyptr->Stack_alloc, Stack, yysize);			\

+	Stack = &yyptr->Stack_alloc;					\

+	yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \

+	yyptr += yynewbytes / sizeof (*yyptr);				\

+      }									\

+    while (YYID (0))

+

+#endif

+

+/* YYFINAL -- State number of the termination state.  */

+#define YYFINAL  14

+/* YYLAST -- Last index in YYTABLE.  */

+#define YYLAST   175

+

+/* YYNTOKENS -- Number of terminals.  */

+#define YYNTOKENS  27

+/* YYNNTS -- Number of nonterminals.  */

+#define YYNNTS  3

+/* YYNRULES -- Number of rules.  */

+#define YYNRULES  26

+/* YYNRULES -- Number of states.  */

+#define YYNSTATES  52

+

+/* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX.  */

+#define YYUNDEFTOK  2

+#define YYMAXUTOK   267

+

+#define YYTRANSLATE(YYX)						\

+  ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK)

+

+/* YYTRANSLATE[YYLEX] -- Bison symbol number corresponding to YYLEX.  */

+static const yytype_uint8 yytranslate[] =

+{

+       0,     2,     2,     2,     2,     2,     2,     2,     2,     2,

+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,

+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,

+       2,     2,     2,    23,     2,     2,     2,    21,     8,     2,

+      25,    26,    19,    17,     2,    18,     2,    20,     2,     2,

+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,

+      11,     2,    12,     2,     2,     2,     2,     2,     2,     2,

+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,

+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,

+       2,     2,     2,     2,     7,     2,     2,     2,     2,     2,

+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,

+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,

+       2,     2,     2,     2,     6,     2,    24,     2,     2,     2,

+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,

+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,

+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,

+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,

+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,

+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,

+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,

+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,

+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,

+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,

+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,

+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,

+       2,     2,     2,     2,     2,     2,     1,     2,     3,     4,

+       5,     9,    10,    13,    14,    15,    16,    22

+};

+

+#if YYDEBUG

+/* YYPRHS[YYN] -- Index of the first RHS symbol of rule number YYN in

+   YYRHS.  */

+static const yytype_uint8 yyprhs[] =

+{

+       0,     0,     3,     5,     7,    11,    15,    19,    23,    27,

+      31,    35,    39,    43,    47,    51,    55,    59,    63,    67,

+      71,    75,    79,    82,    85,    88,    91

+};

+

+/* YYRHS -- A `-1'-separated list of the rules' RHS.  */

+static const yytype_int8 yyrhs[] =

+{

+      28,     0,    -1,    29,    -1,     3,    -1,    29,     4,    29,

+      -1,    29,     5,    29,    -1,    29,     6,    29,    -1,    29,

+       7,    29,    -1,    29,     8,    29,    -1,    29,     9,    29,

+      -1,    29,    10,    29,    -1,    29,    13,    29,    -1,    29,

+      14,    29,    -1,    29,    12,    29,    -1,    29,    11,    29,

+      -1,    29,    15,    29,    -1,    29,    16,    29,    -1,    29,

+      18,    29,    -1,    29,    17,    29,    -1,    29,    21,    29,

+      -1,    29,    20,    29,    -1,    29,    19,    29,    -1,    23,

+      29,    -1,    24,    29,    -1,    18,    29,    -1,    17,    29,

+      -1,    25,    29,    26,    -1

+};

+

+/* YYRLINE[YYN] -- source line where rule number YYN was defined.  */

+static const yytype_uint8 yyrline[] =

+{

+       0,    85,    85,    92,    93,    96,    99,   102,   105,   108,

+     111,   114,   117,   120,   123,   126,   129,   132,   135,   138,

+     151,   164,   167,   170,   173,   176,   179

+};

+#endif

+

+#if YYDEBUG || YYERROR_VERBOSE || YYTOKEN_TABLE

+/* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM.

+   First, the terminals, then, starting at YYNTOKENS, nonterminals.  */

+static const char *const yytname[] =

+{

+  "$end", "error", "$undefined", "TOK_CONST_INT", "TOK_OP_OR",

+  "TOK_OP_AND", "'|'", "'^'", "'&'", "TOK_OP_NE", "TOK_OP_EQ", "'<'",

+  "'>'", "TOK_OP_GE", "TOK_OP_LE", "TOK_OP_RIGHT", "TOK_OP_LEFT", "'+'",

+  "'-'", "'*'", "'/'", "'%'", "TOK_UNARY", "'!'", "'~'", "'('", "')'",

+  "$accept", "input", "expression", 0

+};

+#endif

+

+# ifdef YYPRINT

+/* YYTOKNUM[YYLEX-NUM] -- Internal token number corresponding to

+   token YYLEX-NUM.  */

+static const yytype_uint16 yytoknum[] =

+{

+       0,   256,   257,   258,   259,   260,   124,    94,    38,   261,

+     262,    60,    62,   263,   264,   265,   266,    43,    45,    42,

+      47,    37,   267,    33,   126,    40,    41

+};

+# endif

+

+/* YYR1[YYN] -- Symbol number of symbol that rule YYN derives.  */

+static const yytype_uint8 yyr1[] =

+{

+       0,    27,    28,    29,    29,    29,    29,    29,    29,    29,

+      29,    29,    29,    29,    29,    29,    29,    29,    29,    29,

+      29,    29,    29,    29,    29,    29,    29

+};

+

+/* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN.  */

+static const yytype_uint8 yyr2[] =

+{

+       0,     2,     1,     1,     3,     3,     3,     3,     3,     3,

+       3,     3,     3,     3,     3,     3,     3,     3,     3,     3,

+       3,     3,     2,     2,     2,     2,     3

+};

+

+/* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state

+   STATE-NUM when YYTABLE doesn't specify something else to do.  Zero

+   means the default is an error.  */

+static const yytype_uint8 yydefact[] =

+{

+       0,     3,     0,     0,     0,     0,     0,     0,     2,    25,

+      24,    22,    23,     0,     1,     0,     0,     0,     0,     0,

+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,

+       0,     0,     0,    26,     4,     5,     6,     7,     8,     9,

+      10,    14,    13,    11,    12,    15,    16,    18,    17,    21,

+      20,    19

+};

+

+/* YYDEFGOTO[NTERM-NUM].  */

+static const yytype_int8 yydefgoto[] =

+{

+      -1,     7,     8

+};

+

+/* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing

+   STATE-NUM.  */

+#define YYPACT_NINF -11

+static const yytype_int16 yypact[] =

+{

+      46,   -11,    46,    46,    46,    46,    46,    12,    68,   -11,

+     -11,   -11,   -11,    27,   -11,    46,    46,    46,    46,    46,

+      46,    46,    46,    46,    46,    46,    46,    46,    46,    46,

+      46,    46,    46,   -11,    85,   101,   116,   130,   143,   154,

+     154,   -10,   -10,   -10,   -10,    37,    37,    31,    31,   -11,

+     -11,   -11

+};

+

+/* YYPGOTO[NTERM-NUM].  */

+static const yytype_int8 yypgoto[] =

+{

+     -11,   -11,    -2

+};

+

+/* YYTABLE[YYPACT[STATE-NUM]].  What to do in state STATE-NUM.  If

+   positive, shift that token.  If negative, reduce the rule which

+   number is the opposite.  If zero, do what YYDEFACT says.

+   If YYTABLE_NINF, syntax error.  */

+#define YYTABLE_NINF -1

+static const yytype_uint8 yytable[] =

+{

+       9,    10,    11,    12,    13,    26,    27,    28,    29,    30,

+      31,    32,    14,    34,    35,    36,    37,    38,    39,    40,

+      41,    42,    43,    44,    45,    46,    47,    48,    49,    50,

+      51,    15,    16,    17,    18,    19,    20,    21,    22,    23,

+      24,    25,    26,    27,    28,    29,    30,    31,    32,     1,

+      30,    31,    32,    33,    28,    29,    30,    31,    32,     0,

+       0,     0,     0,     2,     3,     0,     0,     0,     0,     4,

+       5,     6,    15,    16,    17,    18,    19,    20,    21,    22,

+      23,    24,    25,    26,    27,    28,    29,    30,    31,    32,

+      16,    17,    18,    19,    20,    21,    22,    23,    24,    25,

+      26,    27,    28,    29,    30,    31,    32,    17,    18,    19,

+      20,    21,    22,    23,    24,    25,    26,    27,    28,    29,

+      30,    31,    32,    18,    19,    20,    21,    22,    23,    24,

+      25,    26,    27,    28,    29,    30,    31,    32,    19,    20,

+      21,    22,    23,    24,    25,    26,    27,    28,    29,    30,

+      31,    32,    20,    21,    22,    23,    24,    25,    26,    27,

+      28,    29,    30,    31,    32,    22,    23,    24,    25,    26,

+      27,    28,    29,    30,    31,    32

+};

+

+static const yytype_int8 yycheck[] =

+{

+       2,     3,     4,     5,     6,    15,    16,    17,    18,    19,

+      20,    21,     0,    15,    16,    17,    18,    19,    20,    21,

+      22,    23,    24,    25,    26,    27,    28,    29,    30,    31,

+      32,     4,     5,     6,     7,     8,     9,    10,    11,    12,

+      13,    14,    15,    16,    17,    18,    19,    20,    21,     3,

+      19,    20,    21,    26,    17,    18,    19,    20,    21,    -1,

+      -1,    -1,    -1,    17,    18,    -1,    -1,    -1,    -1,    23,

+      24,    25,     4,     5,     6,     7,     8,     9,    10,    11,

+      12,    13,    14,    15,    16,    17,    18,    19,    20,    21,

+       5,     6,     7,     8,     9,    10,    11,    12,    13,    14,

+      15,    16,    17,    18,    19,    20,    21,     6,     7,     8,

+       9,    10,    11,    12,    13,    14,    15,    16,    17,    18,

+      19,    20,    21,     7,     8,     9,    10,    11,    12,    13,

+      14,    15,    16,    17,    18,    19,    20,    21,     8,     9,

+      10,    11,    12,    13,    14,    15,    16,    17,    18,    19,

+      20,    21,     9,    10,    11,    12,    13,    14,    15,    16,

+      17,    18,    19,    20,    21,    11,    12,    13,    14,    15,

+      16,    17,    18,    19,    20,    21

+};

+

+/* YYSTOS[STATE-NUM] -- The (internal number of the) accessing

+   symbol of state STATE-NUM.  */

+static const yytype_uint8 yystos[] =

+{

+       0,     3,    17,    18,    23,    24,    25,    28,    29,    29,

+      29,    29,    29,    29,     0,     4,     5,     6,     7,     8,

+       9,    10,    11,    12,    13,    14,    15,    16,    17,    18,

+      19,    20,    21,    26,    29,    29,    29,    29,    29,    29,

+      29,    29,    29,    29,    29,    29,    29,    29,    29,    29,

+      29,    29

+};

+

+#define yyerrok		(yyerrstatus = 0)

+#define yyclearin	(yychar = YYEMPTY)

+#define YYEMPTY		(-2)

+#define YYEOF		0

+

+#define YYACCEPT	goto yyacceptlab

+#define YYABORT		goto yyabortlab

+#define YYERROR		goto yyerrorlab

+

+

+/* Like YYERROR except do call yyerror.  This remains here temporarily

+   to ease the transition to the new meaning of YYERROR, for GCC.

+   Once GCC version 2 has supplanted version 1, this can go.  */

+

+#define YYFAIL		goto yyerrlab

+

+#define YYRECOVERING()  (!!yyerrstatus)

+

+#define YYBACKUP(Token, Value)					\

+do								\

+  if (yychar == YYEMPTY && yylen == 1)				\

+    {								\

+      yychar = (Token);						\

+      yylval = (Value);						\

+      yytoken = YYTRANSLATE (yychar);				\

+      YYPOPSTACK (1);						\

+      goto yybackup;						\

+    }								\

+  else								\

+    {								\

+      yyerror (context, YY_("syntax error: cannot back up")); \

+      YYERROR;							\

+    }								\

+while (YYID (0))

+

+

+#define YYTERROR	1

+#define YYERRCODE	256

+

+

+/* YYLLOC_DEFAULT -- Set CURRENT to span from RHS[1] to RHS[N].

+   If N is 0, then set CURRENT to the empty location which ends

+   the previous symbol: RHS[0] (always defined).  */

+

+#define YYRHSLOC(Rhs, K) ((Rhs)[K])

+#ifndef YYLLOC_DEFAULT

+# define YYLLOC_DEFAULT(Current, Rhs, N)				\

+    do									\

+      if (YYID (N))                                                    \

+	{								\

+	  (Current).first_line   = YYRHSLOC (Rhs, 1).first_line;	\

+	  (Current).first_column = YYRHSLOC (Rhs, 1).first_column;	\

+	  (Current).last_line    = YYRHSLOC (Rhs, N).last_line;		\

+	  (Current).last_column  = YYRHSLOC (Rhs, N).last_column;	\

+	}								\

+      else								\

+	{								\

+	  (Current).first_line   = (Current).last_line   =		\

+	    YYRHSLOC (Rhs, 0).last_line;				\

+	  (Current).first_column = (Current).last_column =		\

+	    YYRHSLOC (Rhs, 0).last_column;				\

+	}								\

+    while (YYID (0))

+#endif

+

+

+/* YY_LOCATION_PRINT -- Print the location on the stream.

+   This macro was not mandated originally: define only if we know

+   we won't break user code: when these are the locations we know.  */

+

+#ifndef YY_LOCATION_PRINT

+# if YYLTYPE_IS_TRIVIAL

+#  define YY_LOCATION_PRINT(File, Loc)			\

+     fprintf (File, "%d.%d-%d.%d",			\

+	      (Loc).first_line, (Loc).first_column,	\

+	      (Loc).last_line,  (Loc).last_column)

+# else

+#  define YY_LOCATION_PRINT(File, Loc) ((void) 0)

+# endif

+#endif

+

+

+/* YYLEX -- calling `yylex' with the right arguments.  */

+

+#ifdef YYLEX_PARAM

+# define YYLEX yylex (&yylval, YYLEX_PARAM)

+#else

+# define YYLEX yylex (&yylval, context)

+#endif

+

+/* Enable debugging if requested.  */

+#if YYDEBUG

+

+# ifndef YYFPRINTF

+#  include <stdio.h> /* INFRINGES ON USER NAME SPACE */

+#  define YYFPRINTF fprintf

+# endif

+

+# define YYDPRINTF(Args)			\

+do {						\

+  if (yydebug)					\

+    YYFPRINTF Args;				\

+} while (YYID (0))

+

+# define YY_SYMBOL_PRINT(Title, Type, Value, Location)			  \

+do {									  \

+  if (yydebug)								  \

+    {									  \

+      YYFPRINTF (stderr, "%s ", Title);					  \

+      yy_symbol_print (stderr,						  \

+		  Type, Value, context); \

+      YYFPRINTF (stderr, "\n");						  \

+    }									  \

+} while (YYID (0))

+

+

+/*--------------------------------.

+| Print this symbol on YYOUTPUT.  |

+`--------------------------------*/

+

+/*ARGSUSED*/

+#if (defined __STDC__ || defined __C99__FUNC__ \

+     || defined __cplusplus || defined _MSC_VER)

+static void

+yy_symbol_value_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep, Context *context)

+#else

+static void

+yy_symbol_value_print (yyoutput, yytype, yyvaluep, context)

+    FILE *yyoutput;

+    int yytype;

+    YYSTYPE const * const yyvaluep;

+    Context *context;

+#endif

+{

+  if (!yyvaluep)

+    return;

+  YYUSE (context);

+# ifdef YYPRINT

+  if (yytype < YYNTOKENS)

+    YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep);

+# else

+  YYUSE (yyoutput);

+# endif

+  switch (yytype)

+    {

+      default:

+	break;

+    }

+}

+

+

+/*--------------------------------.

+| Print this symbol on YYOUTPUT.  |

+`--------------------------------*/

+

+#if (defined __STDC__ || defined __C99__FUNC__ \

+     || defined __cplusplus || defined _MSC_VER)

+static void

+yy_symbol_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep, Context *context)

+#else

+static void

+yy_symbol_print (yyoutput, yytype, yyvaluep, context)

+    FILE *yyoutput;

+    int yytype;

+    YYSTYPE const * const yyvaluep;

+    Context *context;

+#endif

+{

+  if (yytype < YYNTOKENS)

+    YYFPRINTF (yyoutput, "token %s (", yytname[yytype]);

+  else

+    YYFPRINTF (yyoutput, "nterm %s (", yytname[yytype]);

+

+  yy_symbol_value_print (yyoutput, yytype, yyvaluep, context);

+  YYFPRINTF (yyoutput, ")");

+}

+

+/*------------------------------------------------------------------.

+| yy_stack_print -- Print the state stack from its BOTTOM up to its |

+| TOP (included).                                                   |

+`------------------------------------------------------------------*/

+

+#if (defined __STDC__ || defined __C99__FUNC__ \

+     || defined __cplusplus || defined _MSC_VER)

+static void

+yy_stack_print (yytype_int16 *yybottom, yytype_int16 *yytop)

+#else

+static void

+yy_stack_print (yybottom, yytop)

+    yytype_int16 *yybottom;

+    yytype_int16 *yytop;

+#endif

+{

+  YYFPRINTF (stderr, "Stack now");

+  for (; yybottom <= yytop; yybottom++)

+    {

+      int yybot = *yybottom;

+      YYFPRINTF (stderr, " %d", yybot);

+    }

+  YYFPRINTF (stderr, "\n");

+}

+

+# define YY_STACK_PRINT(Bottom, Top)				\

+do {								\

+  if (yydebug)							\

+    yy_stack_print ((Bottom), (Top));				\

+} while (YYID (0))

+

+

+/*------------------------------------------------.

+| Report that the YYRULE is going to be reduced.  |

+`------------------------------------------------*/

+

+#if (defined __STDC__ || defined __C99__FUNC__ \

+     || defined __cplusplus || defined _MSC_VER)

+static void

+yy_reduce_print (YYSTYPE *yyvsp, int yyrule, Context *context)

+#else

+static void

+yy_reduce_print (yyvsp, yyrule, context)

+    YYSTYPE *yyvsp;

+    int yyrule;

+    Context *context;

+#endif

+{

+  int yynrhs = yyr2[yyrule];

+  int yyi;

+  unsigned long int yylno = yyrline[yyrule];

+  YYFPRINTF (stderr, "Reducing stack by rule %d (line %lu):\n",

+	     yyrule - 1, yylno);

+  /* The symbols being reduced.  */

+  for (yyi = 0; yyi < yynrhs; yyi++)

+    {

+      YYFPRINTF (stderr, "   $%d = ", yyi + 1);

+      yy_symbol_print (stderr, yyrhs[yyprhs[yyrule] + yyi],

+		       &(yyvsp[(yyi + 1) - (yynrhs)])

+		       		       , context);

+      YYFPRINTF (stderr, "\n");

+    }

+}

+

+# define YY_REDUCE_PRINT(Rule)		\

+do {					\

+  if (yydebug)				\

+    yy_reduce_print (yyvsp, Rule, context); \

+} while (YYID (0))

+

+/* Nonzero means print parse trace.  It is left uninitialized so that

+   multiple parsers can coexist.  */

+int yydebug;

+#else /* !YYDEBUG */

+# define YYDPRINTF(Args)

+# define YY_SYMBOL_PRINT(Title, Type, Value, Location)

+# define YY_STACK_PRINT(Bottom, Top)

+# define YY_REDUCE_PRINT(Rule)

+#endif /* !YYDEBUG */

+

+

+/* YYINITDEPTH -- initial size of the parser's stacks.  */

+#ifndef	YYINITDEPTH

+# define YYINITDEPTH 200

+#endif

+

+/* YYMAXDEPTH -- maximum size the stacks can grow to (effective only

+   if the built-in stack extension method is used).

+

+   Do not make this value too large; the results are undefined if

+   YYSTACK_ALLOC_MAXIMUM < YYSTACK_BYTES (YYMAXDEPTH)

+   evaluated with infinite-precision integer arithmetic.  */

+

+#ifndef YYMAXDEPTH

+# define YYMAXDEPTH 10000

+#endif

+

+

+

+#if YYERROR_VERBOSE

+

+# ifndef yystrlen

+#  if defined __GLIBC__ && defined _STRING_H

+#   define yystrlen strlen

+#  else

+/* Return the length of YYSTR.  */

+#if (defined __STDC__ || defined __C99__FUNC__ \

+     || defined __cplusplus || defined _MSC_VER)

+static YYSIZE_T

+yystrlen (const char *yystr)

+#else

+static YYSIZE_T

+yystrlen (yystr)

+    const char *yystr;

+#endif

+{

+  YYSIZE_T yylen;

+  for (yylen = 0; yystr[yylen]; yylen++)

+    continue;

+  return yylen;

+}

+#  endif

+# endif

+

+# ifndef yystpcpy

+#  if defined __GLIBC__ && defined _STRING_H && defined _GNU_SOURCE

+#   define yystpcpy stpcpy

+#  else

+/* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in

+   YYDEST.  */

+#if (defined __STDC__ || defined __C99__FUNC__ \

+     || defined __cplusplus || defined _MSC_VER)

+static char *

+yystpcpy (char *yydest, const char *yysrc)

+#else

+static char *

+yystpcpy (yydest, yysrc)

+    char *yydest;

+    const char *yysrc;

+#endif

+{

+  char *yyd = yydest;

+  const char *yys = yysrc;

+

+  while ((*yyd++ = *yys++) != '\0')

+    continue;

+

+  return yyd - 1;

+}

+#  endif

+# endif

+

+# ifndef yytnamerr

+/* Copy to YYRES the contents of YYSTR after stripping away unnecessary

+   quotes and backslashes, so that it's suitable for yyerror.  The

+   heuristic is that double-quoting is unnecessary unless the string

+   contains an apostrophe, a comma, or backslash (other than

+   backslash-backslash).  YYSTR is taken from yytname.  If YYRES is

+   null, do not copy; instead, return the length of what the result

+   would have been.  */

+static YYSIZE_T

+yytnamerr (char *yyres, const char *yystr)

+{

+  if (*yystr == '"')

+    {

+      YYSIZE_T yyn = 0;

+      char const *yyp = yystr;

+

+      for (;;)

+	switch (*++yyp)

+	  {

+	  case '\'':

+	  case ',':

+	    goto do_not_strip_quotes;

+

+	  case '\\':

+	    if (*++yyp != '\\')

+	      goto do_not_strip_quotes;

+	    /* Fall through.  */

+	  default:

+	    if (yyres)

+	      yyres[yyn] = *yyp;

+	    yyn++;

+	    break;

+

+	  case '"':

+	    if (yyres)

+	      yyres[yyn] = '\0';

+	    return yyn;

+	  }

+    do_not_strip_quotes: ;

+    }

+

+  if (! yyres)

+    return yystrlen (yystr);

+

+  return yystpcpy (yyres, yystr) - yyres;

+}

+# endif

+

+/* Copy into YYRESULT an error message about the unexpected token

+   YYCHAR while in state YYSTATE.  Return the number of bytes copied,

+   including the terminating null byte.  If YYRESULT is null, do not

+   copy anything; just return the number of bytes that would be

+   copied.  As a special case, return 0 if an ordinary "syntax error"

+   message will do.  Return YYSIZE_MAXIMUM if overflow occurs during

+   size calculation.  */

+static YYSIZE_T

+yysyntax_error (char *yyresult, int yystate, int yychar)

+{

+  int yyn = yypact[yystate];

+

+  if (! (YYPACT_NINF < yyn && yyn <= YYLAST))

+    return 0;

+  else

+    {

+      int yytype = YYTRANSLATE (yychar);

+      YYSIZE_T yysize0 = yytnamerr (0, yytname[yytype]);

+      YYSIZE_T yysize = yysize0;

+      YYSIZE_T yysize1;

+      int yysize_overflow = 0;

+      enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 };

+      char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM];

+      int yyx;

+

+# if 0

+      /* This is so xgettext sees the translatable formats that are

+	 constructed on the fly.  */

+      YY_("syntax error, unexpected %s");

+      YY_("syntax error, unexpected %s, expecting %s");

+      YY_("syntax error, unexpected %s, expecting %s or %s");

+      YY_("syntax error, unexpected %s, expecting %s or %s or %s");

+      YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s");

+# endif

+      char *yyfmt;

+      char const *yyf;

+      static char const yyunexpected[] = "syntax error, unexpected %s";

+      static char const yyexpecting[] = ", expecting %s";

+      static char const yyor[] = " or %s";

+      char yyformat[sizeof yyunexpected

+		    + sizeof yyexpecting - 1

+		    + ((YYERROR_VERBOSE_ARGS_MAXIMUM - 2)

+		       * (sizeof yyor - 1))];

+      char const *yyprefix = yyexpecting;

+

+      /* Start YYX at -YYN if negative to avoid negative indexes in

+	 YYCHECK.  */

+      int yyxbegin = yyn < 0 ? -yyn : 0;

+

+      /* Stay within bounds of both yycheck and yytname.  */

+      int yychecklim = YYLAST - yyn + 1;

+      int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS;

+      int yycount = 1;

+

+      yyarg[0] = yytname[yytype];

+      yyfmt = yystpcpy (yyformat, yyunexpected);

+

+      for (yyx = yyxbegin; yyx < yyxend; ++yyx)

+	if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR)

+	  {

+	    if (yycount == YYERROR_VERBOSE_ARGS_MAXIMUM)

+	      {

+		yycount = 1;

+		yysize = yysize0;

+		yyformat[sizeof yyunexpected - 1] = '\0';

+		break;

+	      }

+	    yyarg[yycount++] = yytname[yyx];

+	    yysize1 = yysize + yytnamerr (0, yytname[yyx]);

+	    yysize_overflow |= (yysize1 < yysize);

+	    yysize = yysize1;

+	    yyfmt = yystpcpy (yyfmt, yyprefix);

+	    yyprefix = yyor;

+	  }

+

+      yyf = YY_(yyformat);

+      yysize1 = yysize + yystrlen (yyf);

+      yysize_overflow |= (yysize1 < yysize);

+      yysize = yysize1;

+

+      if (yysize_overflow)

+	return YYSIZE_MAXIMUM;

+

+      if (yyresult)

+	{

+	  /* Avoid sprintf, as that infringes on the user's name space.

+	     Don't have undefined behavior even if the translation

+	     produced a string with the wrong number of "%s"s.  */

+	  char *yyp = yyresult;

+	  int yyi = 0;

+	  while ((*yyp = *yyf) != '\0')

+	    {

+	      if (*yyp == '%' && yyf[1] == 's' && yyi < yycount)

+		{

+		  yyp += yytnamerr (yyp, yyarg[yyi++]);

+		  yyf += 2;

+		}

+	      else

+		{

+		  yyp++;

+		  yyf++;

+		}

+	    }

+	}

+      return yysize;

+    }

+}

+#endif /* YYERROR_VERBOSE */

+

+

+/*-----------------------------------------------.

+| Release the memory associated to this symbol.  |

+`-----------------------------------------------*/

+

+/*ARGSUSED*/

+#if (defined __STDC__ || defined __C99__FUNC__ \

+     || defined __cplusplus || defined _MSC_VER)

+static void

+yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep, Context *context)

+#else

+static void

+yydestruct (yymsg, yytype, yyvaluep, context)

+    const char *yymsg;

+    int yytype;

+    YYSTYPE *yyvaluep;

+    Context *context;

+#endif

+{

+  YYUSE (yyvaluep);

+  YYUSE (context);

+

+  if (!yymsg)

+    yymsg = "Deleting";

+  YY_SYMBOL_PRINT (yymsg, yytype, yyvaluep, yylocationp);

+

+  switch (yytype)

+    {

+

+      default:

+	break;

+    }

+}

+

+/* Prevent warnings from -Wmissing-prototypes.  */

+#ifdef YYPARSE_PARAM

+#if defined __STDC__ || defined __cplusplus

+int yyparse (void *YYPARSE_PARAM);

+#else

+int yyparse ();

+#endif

+#else /* ! YYPARSE_PARAM */

+#if defined __STDC__ || defined __cplusplus

+int yyparse (Context *context);

+#else

+int yyparse ();

+#endif

+#endif /* ! YYPARSE_PARAM */

+

+

+

+

+

+/*-------------------------.

+| yyparse or yypush_parse.  |

+`-------------------------*/

+

+#ifdef YYPARSE_PARAM

+#if (defined __STDC__ || defined __C99__FUNC__ \

+     || defined __cplusplus || defined _MSC_VER)

+int

+yyparse (void *YYPARSE_PARAM)

+#else

+int

+yyparse (YYPARSE_PARAM)

+    void *YYPARSE_PARAM;

+#endif

+#else /* ! YYPARSE_PARAM */

+#if (defined __STDC__ || defined __C99__FUNC__ \

+     || defined __cplusplus || defined _MSC_VER)

+int

+yyparse (Context *context)

+#else

+int

+yyparse (context)

+    Context *context;

+#endif

+#endif

+{

+/* The lookahead symbol.  */

+int yychar;

+

+/* The semantic value of the lookahead symbol.  */

+YYSTYPE yylval;

+

+    /* Number of syntax errors so far.  */

+    int yynerrs;

+

+    int yystate;

+    /* Number of tokens to shift before error messages enabled.  */

+    int yyerrstatus;

+

+    /* The stacks and their tools:

+       `yyss': related to states.

+       `yyvs': related to semantic values.

+

+       Refer to the stacks thru separate pointers, to allow yyoverflow

+       to reallocate them elsewhere.  */

+

+    /* The state stack.  */

+    yytype_int16 yyssa[YYINITDEPTH];

+    yytype_int16 *yyss;

+    yytype_int16 *yyssp;

+

+    /* The semantic value stack.  */

+    YYSTYPE yyvsa[YYINITDEPTH];

+    YYSTYPE *yyvs;

+    YYSTYPE *yyvsp;

+

+    YYSIZE_T yystacksize;

+

+  int yyn;

+  int yyresult;

+  /* Lookahead token as an internal (translated) token number.  */

+  int yytoken;

+  /* The variables used to return semantic value and location from the

+     action routines.  */

+  YYSTYPE yyval;

+

+#if YYERROR_VERBOSE

+  /* Buffer for error messages, and its allocated size.  */

+  char yymsgbuf[128];

+  char *yymsg = yymsgbuf;

+  YYSIZE_T yymsg_alloc = sizeof yymsgbuf;

+#endif

+

+#define YYPOPSTACK(N)   (yyvsp -= (N), yyssp -= (N))

+

+  /* The number of symbols on the RHS of the reduced rule.

+     Keep to zero when no symbol should be popped.  */

+  int yylen = 0;

+

+  yytoken = 0;

+  yyss = yyssa;

+  yyvs = yyvsa;

+  yystacksize = YYINITDEPTH;

+

+  YYDPRINTF ((stderr, "Starting parse\n"));

+

+  yystate = 0;

+  yyerrstatus = 0;

+  yynerrs = 0;

+  yychar = YYEMPTY; /* Cause a token to be read.  */

+

+  /* Initialize stack pointers.

+     Waste one element of value and location stack

+     so that they stay on the same level as the state stack.

+     The wasted elements are never initialized.  */

+  yyssp = yyss;

+  yyvsp = yyvs;

+

+  goto yysetstate;

+

+/*------------------------------------------------------------.

+| yynewstate -- Push a new state, which is found in yystate.  |

+`------------------------------------------------------------*/

+ yynewstate:

+  /* In all cases, when you get here, the value and location stacks

+     have just been pushed.  So pushing a state here evens the stacks.  */

+  yyssp++;

+

+ yysetstate:

+  *yyssp = yystate;

+

+  if (yyss + yystacksize - 1 <= yyssp)

+    {

+      /* Get the current used size of the three stacks, in elements.  */

+      YYSIZE_T yysize = yyssp - yyss + 1;

+

+#ifdef yyoverflow

+      {

+	/* Give user a chance to reallocate the stack.  Use copies of

+	   these so that the &'s don't force the real ones into

+	   memory.  */

+	YYSTYPE *yyvs1 = yyvs;

+	yytype_int16 *yyss1 = yyss;

+

+	/* Each stack pointer address is followed by the size of the

+	   data in use in that stack, in bytes.  This used to be a

+	   conditional around just the two extra args, but that might

+	   be undefined if yyoverflow is a macro.  */

+	yyoverflow (YY_("memory exhausted"),

+		    &yyss1, yysize * sizeof (*yyssp),

+		    &yyvs1, yysize * sizeof (*yyvsp),

+		    &yystacksize);

+

+	yyss = yyss1;

+	yyvs = yyvs1;

+      }

+#else /* no yyoverflow */

+# ifndef YYSTACK_RELOCATE

+      goto yyexhaustedlab;

+# else

+      /* Extend the stack our own way.  */

+      if (YYMAXDEPTH <= yystacksize)

+	goto yyexhaustedlab;

+      yystacksize *= 2;

+      if (YYMAXDEPTH < yystacksize)

+	yystacksize = YYMAXDEPTH;

+

+      {

+	yytype_int16 *yyss1 = yyss;

+	union yyalloc *yyptr =

+	  (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize));

+	if (! yyptr)

+	  goto yyexhaustedlab;

+	YYSTACK_RELOCATE (yyss_alloc, yyss);

+	YYSTACK_RELOCATE (yyvs_alloc, yyvs);

+#  undef YYSTACK_RELOCATE

+	if (yyss1 != yyssa)

+	  YYSTACK_FREE (yyss1);

+      }

+# endif

+#endif /* no yyoverflow */

+

+      yyssp = yyss + yysize - 1;

+      yyvsp = yyvs + yysize - 1;

+

+      YYDPRINTF ((stderr, "Stack size increased to %lu\n",

+		  (unsigned long int) yystacksize));

+

+      if (yyss + yystacksize - 1 <= yyssp)

+	YYABORT;

+    }

+

+  YYDPRINTF ((stderr, "Entering state %d\n", yystate));

+

+  if (yystate == YYFINAL)

+    YYACCEPT;

+

+  goto yybackup;

+

+/*-----------.

+| yybackup.  |

+`-----------*/

+yybackup:

+

+  /* Do appropriate processing given the current state.  Read a

+     lookahead token if we need one and don't already have one.  */

+

+  /* First try to decide what to do without reference to lookahead token.  */

+  yyn = yypact[yystate];

+  if (yyn == YYPACT_NINF)

+    goto yydefault;

+

+  /* Not known => get a lookahead token if don't already have one.  */

+

+  /* YYCHAR is either YYEMPTY or YYEOF or a valid lookahead symbol.  */

+  if (yychar == YYEMPTY)

+    {

+      YYDPRINTF ((stderr, "Reading a token: "));

+      yychar = YYLEX;

+    }

+

+  if (yychar <= YYEOF)

+    {

+      yychar = yytoken = YYEOF;

+      YYDPRINTF ((stderr, "Now at end of input.\n"));

+    }

+  else

+    {

+      yytoken = YYTRANSLATE (yychar);

+      YY_SYMBOL_PRINT ("Next token is", yytoken, &yylval, &yylloc);

+    }

+

+  /* If the proper action on seeing token YYTOKEN is to reduce or to

+     detect an error, take that action.  */

+  yyn += yytoken;

+  if (yyn < 0 || YYLAST < yyn || yycheck[yyn] != yytoken)

+    goto yydefault;

+  yyn = yytable[yyn];

+  if (yyn <= 0)

+    {

+      if (yyn == 0 || yyn == YYTABLE_NINF)

+	goto yyerrlab;

+      yyn = -yyn;

+      goto yyreduce;

+    }

+

+  /* Count tokens shifted since error; after three, turn off error

+     status.  */

+  if (yyerrstatus)

+    yyerrstatus--;

+

+  /* Shift the lookahead token.  */

+  YY_SYMBOL_PRINT ("Shifting", yytoken, &yylval, &yylloc);

+

+  /* Discard the shifted token.  */

+  yychar = YYEMPTY;

+

+  yystate = yyn;

+  *++yyvsp = yylval;

+

+  goto yynewstate;

+

+

+/*-----------------------------------------------------------.

+| yydefault -- do the default action for the current state.  |

+`-----------------------------------------------------------*/

+yydefault:

+  yyn = yydefact[yystate];

+  if (yyn == 0)

+    goto yyerrlab;

+  goto yyreduce;

+

+

+/*-----------------------------.

+| yyreduce -- Do a reduction.  |

+`-----------------------------*/

+yyreduce:

+  /* yyn is the number of a rule to reduce with.  */

+  yylen = yyr2[yyn];

+

+  /* If YYLEN is nonzero, implement the default value of the action:

+     `$$ = $1'.

+

+     Otherwise, the following line sets YYVAL to garbage.

+     This behavior is undocumented and Bison

+     users should not rely upon it.  Assigning to YYVAL

+     unconditionally makes the parser a bit smaller, and it avoids a

+     GCC warning that YYVAL may be used uninitialized.  */

+  yyval = yyvsp[1-yylen];

+

+

+  YY_REDUCE_PRINT (yyn);

+  switch (yyn)

+    {

+        case 2:

+

+    {

+        *(context->result) = static_cast<int>((yyvsp[(1) - (1)]));

+        YYACCEPT;

+    }

+    break;

+

+  case 4:

+

+    {

+        (yyval) = (yyvsp[(1) - (3)]) || (yyvsp[(3) - (3)]);

+    }

+    break;

+

+  case 5:

+

+    {

+        (yyval) = (yyvsp[(1) - (3)]) && (yyvsp[(3) - (3)]);

+    }

+    break;

+

+  case 6:

+

+    {

+        (yyval) = (yyvsp[(1) - (3)]) | (yyvsp[(3) - (3)]);

+    }

+    break;

+

+  case 7:

+

+    {

+        (yyval) = (yyvsp[(1) - (3)]) ^ (yyvsp[(3) - (3)]);

+    }

+    break;

+

+  case 8:

+

+    {

+        (yyval) = (yyvsp[(1) - (3)]) & (yyvsp[(3) - (3)]);

+    }

+    break;

+

+  case 9:

+

+    {

+        (yyval) = (yyvsp[(1) - (3)]) != (yyvsp[(3) - (3)]);

+    }

+    break;

+

+  case 10:

+

+    {

+        (yyval) = (yyvsp[(1) - (3)]) == (yyvsp[(3) - (3)]);

+    }

+    break;

+

+  case 11:

+

+    {

+        (yyval) = (yyvsp[(1) - (3)]) >= (yyvsp[(3) - (3)]);

+    }

+    break;

+

+  case 12:

+

+    {

+        (yyval) = (yyvsp[(1) - (3)]) <= (yyvsp[(3) - (3)]);

+    }

+    break;

+

+  case 13:

+

+    {

+        (yyval) = (yyvsp[(1) - (3)]) > (yyvsp[(3) - (3)]);

+    }

+    break;

+

+  case 14:

+

+    {

+        (yyval) = (yyvsp[(1) - (3)]) < (yyvsp[(3) - (3)]);

+    }

+    break;

+

+  case 15:

+

+    {

+        (yyval) = (yyvsp[(1) - (3)]) >> (yyvsp[(3) - (3)]);

+    }

+    break;

+

+  case 16:

+

+    {

+        (yyval) = (yyvsp[(1) - (3)]) << (yyvsp[(3) - (3)]);

+    }

+    break;

+

+  case 17:

+

+    {

+        (yyval) = (yyvsp[(1) - (3)]) - (yyvsp[(3) - (3)]);

+    }

+    break;

+

+  case 18:

+

+    {

+        (yyval) = (yyvsp[(1) - (3)]) + (yyvsp[(3) - (3)]);

+    }

+    break;

+

+  case 19:

+

+    {

+        if ((yyvsp[(3) - (3)]) == 0) {

+            std::ostringstream stream;

+            stream << (yyvsp[(1) - (3)]) << " % " << (yyvsp[(3) - (3)]);

+            std::string text = stream.str();

+            context->diagnostics->report(pp::Diagnostics::DIVISION_BY_ZERO,

+                                         context->token->location,

+                                         text.c_str());

+            YYABORT;

+        } else {

+            (yyval) = (yyvsp[(1) - (3)]) % (yyvsp[(3) - (3)]);

+        }

+    }

+    break;

+

+  case 20:

+

+    {

+        if ((yyvsp[(3) - (3)]) == 0) {

+            std::ostringstream stream;

+            stream << (yyvsp[(1) - (3)]) << " / " << (yyvsp[(3) - (3)]);

+            std::string text = stream.str();

+            context->diagnostics->report(pp::Diagnostics::DIVISION_BY_ZERO,

+                                         context->token->location,

+                                         text.c_str());

+            YYABORT;

+        } else {

+            (yyval) = (yyvsp[(1) - (3)]) / (yyvsp[(3) - (3)]);

+        }

+    }

+    break;

+

+  case 21:

+

+    {

+        (yyval) = (yyvsp[(1) - (3)]) * (yyvsp[(3) - (3)]);

+    }

+    break;

+

+  case 22:

+

+    {

+        (yyval) = ! (yyvsp[(2) - (2)]);

+    }

+    break;

+

+  case 23:

+

+    {

+        (yyval) = ~ (yyvsp[(2) - (2)]);

+    }

+    break;

+

+  case 24:

+

+    {

+        (yyval) = - (yyvsp[(2) - (2)]);

+    }

+    break;

+

+  case 25:

+

+    {

+        (yyval) = + (yyvsp[(2) - (2)]);

+    }

+    break;

+

+  case 26:

+

+    {

+        (yyval) = (yyvsp[(2) - (3)]);

+    }

+    break;

+

+

+

+      default: break;

+    }

+  YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc);

+

+  YYPOPSTACK (yylen);

+  yylen = 0;

+  YY_STACK_PRINT (yyss, yyssp);

+

+  *++yyvsp = yyval;

+

+  /* Now `shift' the result of the reduction.  Determine what state

+     that goes to, based on the state we popped back to and the rule

+     number reduced by.  */

+

+  yyn = yyr1[yyn];

+

+  yystate = yypgoto[yyn - YYNTOKENS] + *yyssp;

+  if (0 <= yystate && yystate <= YYLAST && yycheck[yystate] == *yyssp)

+    yystate = yytable[yystate];

+  else

+    yystate = yydefgoto[yyn - YYNTOKENS];

+

+  goto yynewstate;

+

+

+/*------------------------------------.

+| yyerrlab -- here on detecting error |

+`------------------------------------*/

+yyerrlab:

+  /* If not already recovering from an error, report this error.  */

+  if (!yyerrstatus)

+    {

+      ++yynerrs;

+#if ! YYERROR_VERBOSE

+      yyerror (context, YY_("syntax error"));

+#else

+      {

+	YYSIZE_T yysize = yysyntax_error (0, yystate, yychar);

+	if (yymsg_alloc < yysize && yymsg_alloc < YYSTACK_ALLOC_MAXIMUM)

+	  {

+	    YYSIZE_T yyalloc = 2 * yysize;

+	    if (! (yysize <= yyalloc && yyalloc <= YYSTACK_ALLOC_MAXIMUM))

+	      yyalloc = YYSTACK_ALLOC_MAXIMUM;

+	    if (yymsg != yymsgbuf)

+	      YYSTACK_FREE (yymsg);

+	    yymsg = (char *) YYSTACK_ALLOC (yyalloc);

+	    if (yymsg)

+	      yymsg_alloc = yyalloc;

+	    else

+	      {

+		yymsg = yymsgbuf;

+		yymsg_alloc = sizeof yymsgbuf;

+	      }

+	  }

+

+	if (0 < yysize && yysize <= yymsg_alloc)

+	  {

+	    (void) yysyntax_error (yymsg, yystate, yychar);

+	    yyerror (context, yymsg);

+	  }

+	else

+	  {

+	    yyerror (context, YY_("syntax error"));

+	    if (yysize != 0)

+	      goto yyexhaustedlab;

+	  }

+      }

+#endif

+    }

+

+

+

+  if (yyerrstatus == 3)

+    {

+      /* If just tried and failed to reuse lookahead token after an

+	 error, discard it.  */

+

+      if (yychar <= YYEOF)

+	{

+	  /* Return failure if at end of input.  */

+	  if (yychar == YYEOF)

+	    YYABORT;

+	}

+      else

+	{

+	  yydestruct ("Error: discarding",

+		      yytoken, &yylval, context);

+	  yychar = YYEMPTY;

+	}

+    }

+

+  /* Else will try to reuse lookahead token after shifting the error

+     token.  */

+  goto yyerrlab1;

+

+

+/*---------------------------------------------------.

+| yyerrorlab -- error raised explicitly by YYERROR.  |

+`---------------------------------------------------*/

+yyerrorlab:

+

+  /* Pacify compilers like GCC when the user code never invokes

+     YYERROR and the label yyerrorlab therefore never appears in user

+     code.  */

+  if (/*CONSTCOND*/ 0)

+     goto yyerrorlab;

+

+  /* Do not reclaim the symbols of the rule which action triggered

+     this YYERROR.  */

+  YYPOPSTACK (yylen);

+  yylen = 0;

+  YY_STACK_PRINT (yyss, yyssp);

+  yystate = *yyssp;

+  goto yyerrlab1;

+

+

+/*-------------------------------------------------------------.

+| yyerrlab1 -- common code for both syntax error and YYERROR.  |

+`-------------------------------------------------------------*/

+yyerrlab1:

+  yyerrstatus = 3;	/* Each real token shifted decrements this.  */

+

+  for (;;)

+    {

+      yyn = yypact[yystate];

+      if (yyn != YYPACT_NINF)

+	{

+	  yyn += YYTERROR;

+	  if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR)

+	    {

+	      yyn = yytable[yyn];

+	      if (0 < yyn)

+		break;

+	    }

+	}

+

+      /* Pop the current state because it cannot handle the error token.  */

+      if (yyssp == yyss)

+	YYABORT;

+

+

+      yydestruct ("Error: popping",

+		  yystos[yystate], yyvsp, context);

+      YYPOPSTACK (1);

+      yystate = *yyssp;

+      YY_STACK_PRINT (yyss, yyssp);

+    }

+

+  *++yyvsp = yylval;

+

+

+  /* Shift the error token.  */

+  YY_SYMBOL_PRINT ("Shifting", yystos[yyn], yyvsp, yylsp);

+

+  yystate = yyn;

+  goto yynewstate;

+

+

+/*-------------------------------------.

+| yyacceptlab -- YYACCEPT comes here.  |

+`-------------------------------------*/

+yyacceptlab:

+  yyresult = 0;

+  goto yyreturn;

+

+/*-----------------------------------.

+| yyabortlab -- YYABORT comes here.  |

+`-----------------------------------*/

+yyabortlab:

+  yyresult = 1;

+  goto yyreturn;

+

+#if !defined(yyoverflow) || YYERROR_VERBOSE

+/*-------------------------------------------------.

+| yyexhaustedlab -- memory exhaustion comes here.  |

+`-------------------------------------------------*/

+yyexhaustedlab:

+  yyerror (context, YY_("memory exhausted"));

+  yyresult = 2;

+  /* Fall through.  */

+#endif

+

+yyreturn:

+  if (yychar != YYEMPTY)

+     yydestruct ("Cleanup: discarding lookahead",

+		 yytoken, &yylval, context);

+  /* Do not reclaim the symbols of the rule which action triggered

+     this YYABORT or YYACCEPT.  */

+  YYPOPSTACK (yylen);

+  YY_STACK_PRINT (yyss, yyssp);

+  while (yyssp != yyss)

+    {

+      yydestruct ("Cleanup: popping",

+		  yystos[*yyssp], yyvsp, context);

+      YYPOPSTACK (1);

+    }

+#ifndef yyoverflow

+  if (yyss != yyssa)

+    YYSTACK_FREE (yyss);

+#endif

+#if YYERROR_VERBOSE

+  if (yymsg != yymsgbuf)

+    YYSTACK_FREE (yymsg);

+#endif

+  /* Make sure YYID is used.  */

+  return YYID (yyresult);

+}

+

+

+

+

+

+int yylex(YYSTYPE* lvalp, Context* context)

+{

+    int type = 0;

+

+    pp::Token* token = context->token;

+    switch (token->type)

+    {

+      case pp::Token::CONST_INT:

+      {

+        unsigned int val = 0;

+        if (!token->uValue(&val))

+        {

+            context->diagnostics->report(pp::Diagnostics::INTEGER_OVERFLOW,

+                                         token->location, token->text);

+        }

+        *lvalp = static_cast<YYSTYPE>(val);

+        type = TOK_CONST_INT;

+        break;

+      }

+      case pp::Token::OP_OR: type = TOK_OP_OR; break;

+      case pp::Token::OP_AND: type = TOK_OP_AND; break;

+      case pp::Token::OP_NE: type = TOK_OP_NE; break;

+      case pp::Token::OP_EQ: type = TOK_OP_EQ; break;

+      case pp::Token::OP_GE: type = TOK_OP_GE; break;

+      case pp::Token::OP_LE: type = TOK_OP_LE; break;

+      case pp::Token::OP_RIGHT: type = TOK_OP_RIGHT; break;

+      case pp::Token::OP_LEFT: type = TOK_OP_LEFT; break;

+      case '|': type = '|'; break;

+      case '^': type = '^'; break;

+      case '&': type = '&'; break;

+      case '>': type = '>'; break;

+      case '<': type = '<'; break;

+      case '-': type = '-'; break;

+      case '+': type = '+'; break;

+      case '%': type = '%'; break;

+      case '/': type = '/'; break;

+      case '*': type = '*'; break;

+      case '!': type = '!'; break;

+      case '~': type = '~'; break;

+      case '(': type = '('; break;

+      case ')': type = ')'; break;

+

+      default: break;

+    }

+

+    // Advance to the next token if the current one is valid.

+    if (type != 0) context->lexer->lex(token);

+

+    return type;

+}

+

+void yyerror(Context* context, const char* reason)

+{

+    context->diagnostics->report(pp::Diagnostics::INVALID_EXPRESSION,

+                                 context->token->location,

+                                 reason);

+}

+

+namespace pp {

+

+ExpressionParser::ExpressionParser(Lexer* lexer, Diagnostics* diagnostics) :

+    mLexer(lexer),

+    mDiagnostics(diagnostics)

+{

+}

+

+bool ExpressionParser::parse(Token* token, int* result)

+{

+    Context context;

+    context.diagnostics = mDiagnostics;

+    context.lexer = mLexer;

+    context.token = token;

+    context.result = result;

+    int ret = yyparse(&context);

+    switch (ret)

+    {

+      case 0:

+      case 1:

+        break;

+

+      case 2:

+        mDiagnostics->report(Diagnostics::OUT_OF_MEMORY, token->location, "");

+        break;

+

+      default:

+        assert(false);

+        mDiagnostics->report(Diagnostics::INTERNAL_ERROR, token->location, "");

+        break;

+    }

+

+    return ret == 0;

+}

+

+}  // namespace pp

+

diff --git a/src/GLES2/compiler/preprocessor/ExpressionParser.h b/src/GLES2/compiler/preprocessor/ExpressionParser.h
new file mode 100644
index 0000000..3ee5b7a
--- /dev/null
+++ b/src/GLES2/compiler/preprocessor/ExpressionParser.h
@@ -0,0 +1,34 @@
+//

+// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.

+// Use of this source code is governed by a BSD-style license that can be

+// found in the LICENSE file.

+//

+

+#ifndef COMPILER_PREPROCESSOR_EXPRESSION_PARSER_H_

+#define COMPILER_PREPROCESSOR_EXPRESSION_PARSER_H_

+

+#include "pp_utils.h"

+

+namespace pp

+{

+

+class Diagnostics;

+class Lexer;

+struct Token;

+

+class ExpressionParser

+{

+  public:

+    ExpressionParser(Lexer* lexer, Diagnostics* diagnostics);

+

+    bool parse(Token* token, int* result);

+

+  private:

+    PP_DISALLOW_COPY_AND_ASSIGN(ExpressionParser);

+

+    Lexer* mLexer;

+    Diagnostics* mDiagnostics;

+};

+

+}  // namespace pp

+#endif  // COMPILER_PREPROCESSOR_EXPRESSION_PARSER_H_

diff --git a/src/GLES2/compiler/preprocessor/ExpressionParser.y b/src/GLES2/compiler/preprocessor/ExpressionParser.y
new file mode 100644
index 0000000..2104d77
--- /dev/null
+++ b/src/GLES2/compiler/preprocessor/ExpressionParser.y
@@ -0,0 +1,279 @@
+/*

+//

+// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.

+// Use of this source code is governed by a BSD-style license that can be

+// found in the LICENSE file.

+//

+

+This file contains the Yacc grammar for GLSL ES preprocessor expression.

+

+IF YOU MODIFY THIS FILE YOU ALSO NEED TO RUN generate_parser.sh,

+WHICH GENERATES THE GLSL ES preprocessor expression parser.

+*/

+

+%{

+//

+// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.

+// Use of this source code is governed by a BSD-style license that can be

+// found in the LICENSE file.

+//

+

+// This file is auto-generated by generate_parser.sh. DO NOT EDIT!

+

+#if defined(__GNUC__)

+// Triggered by the auto-generated pplval variable.

+#pragma GCC diagnostic ignored "-Wuninitialized"

+#elif defined(_MSC_VER)

+#pragma warning(disable: 4065 4701)

+#endif

+

+#include "ExpressionParser.h"

+

+#include <cassert>

+#include <sstream>

+

+#include "Diagnostics.h"

+#include "Lexer.h"

+#include "Token.h"

+

+#if defined(_MSC_VER)

+typedef __int64 YYSTYPE;

+#else

+#include <stdint.h>

+typedef intmax_t YYSTYPE;

+#endif  // _MSC_VER

+#define YYSTYPE_IS_TRIVIAL 1

+#define YYSTYPE_IS_DECLARED 1

+

+namespace {

+struct Context

+{

+    pp::Diagnostics* diagnostics;

+    pp::Lexer* lexer;

+    pp::Token* token;

+    int* result;

+};

+}  // namespace

+%}

+

+%pure-parser

+%name-prefix="pp"

+%parse-param {Context *context}

+%lex-param {Context *context}

+

+%{

+static int yylex(YYSTYPE* lvalp, Context* context);

+static void yyerror(Context* context, const char* reason);

+%}

+

+%token TOK_CONST_INT

+%left TOK_OP_OR

+%left TOK_OP_AND

+%left '|'

+%left '^'

+%left '&'

+%left TOK_OP_EQ TOK_OP_NE

+%left '<' '>' TOK_OP_LE TOK_OP_GE

+%left TOK_OP_LEFT TOK_OP_RIGHT

+%left '+' '-'

+%left '*' '/' '%'

+%right TOK_UNARY

+

+%%

+

+input

+    : expression {

+        *(context->result) = static_cast<int>($1);

+        YYACCEPT;

+    }

+;

+

+expression

+    : TOK_CONST_INT

+    | expression TOK_OP_OR expression {

+        $$ = $1 || $3;

+    }

+    | expression TOK_OP_AND expression {

+        $$ = $1 && $3;

+    }

+    | expression '|' expression {

+        $$ = $1 | $3;

+    }

+    | expression '^' expression {

+        $$ = $1 ^ $3;

+    }

+    | expression '&' expression {

+        $$ = $1 & $3;

+    }

+    | expression TOK_OP_NE expression {

+        $$ = $1 != $3;

+    }

+    | expression TOK_OP_EQ expression {

+        $$ = $1 == $3;

+    }

+    | expression TOK_OP_GE expression {

+        $$ = $1 >= $3;

+    }

+    | expression TOK_OP_LE expression {

+        $$ = $1 <= $3;

+    }

+    | expression '>' expression {

+        $$ = $1 > $3;

+    }

+    | expression '<' expression {

+        $$ = $1 < $3;

+    }

+    | expression TOK_OP_RIGHT expression {

+        $$ = $1 >> $3;

+    }

+    | expression TOK_OP_LEFT expression {

+        $$ = $1 << $3;

+    }

+    | expression '-' expression {

+        $$ = $1 - $3;

+    }

+    | expression '+' expression {

+        $$ = $1 + $3;

+    }

+    | expression '%' expression {

+        if ($3 == 0) {

+            std::ostringstream stream;

+            stream << $1 << " % " << $3;

+            std::string text = stream.str();

+            context->diagnostics->report(pp::Diagnostics::DIVISION_BY_ZERO,

+                                         context->token->location,

+                                         text.c_str());

+            YYABORT;

+        } else {

+            $$ = $1 % $3;

+        }

+    }

+    | expression '/' expression {

+        if ($3 == 0) {

+            std::ostringstream stream;

+            stream << $1 << " / " << $3;

+            std::string text = stream.str();

+            context->diagnostics->report(pp::Diagnostics::DIVISION_BY_ZERO,

+                                         context->token->location,

+                                         text.c_str());

+            YYABORT;

+        } else {

+            $$ = $1 / $3;

+        }

+    }

+    | expression '*' expression {

+        $$ = $1 * $3;

+    }

+    | '!' expression %prec TOK_UNARY {

+        $$ = ! $2;

+    }

+    | '~' expression %prec TOK_UNARY {

+        $$ = ~ $2;

+    }

+    | '-' expression %prec TOK_UNARY {

+        $$ = - $2;

+    }

+    | '+' expression %prec TOK_UNARY {

+        $$ = + $2;

+    }

+    | '(' expression ')' {

+        $$ = $2;

+    }

+;

+

+%%

+

+int yylex(YYSTYPE* lvalp, Context* context)

+{

+    int type = 0;

+

+    pp::Token* token = context->token;

+    switch (token->type)

+    {

+      case pp::Token::CONST_INT:

+      {

+        unsigned int val = 0;

+        if (!token->uValue(&val))

+        {

+            context->diagnostics->report(pp::Diagnostics::INTEGER_OVERFLOW,

+                                         token->location, token->text);

+        }

+        *lvalp = static_cast<YYSTYPE>(val);

+        type = TOK_CONST_INT;

+        break;

+      }

+      case pp::Token::OP_OR: type = TOK_OP_OR; break;

+      case pp::Token::OP_AND: type = TOK_OP_AND; break;

+      case pp::Token::OP_NE: type = TOK_OP_NE; break;

+      case pp::Token::OP_EQ: type = TOK_OP_EQ; break;

+      case pp::Token::OP_GE: type = TOK_OP_GE; break;

+      case pp::Token::OP_LE: type = TOK_OP_LE; break;

+      case pp::Token::OP_RIGHT: type = TOK_OP_RIGHT; break;

+      case pp::Token::OP_LEFT: type = TOK_OP_LEFT; break;

+      case '|': type = '|'; break;

+      case '^': type = '^'; break;

+      case '&': type = '&'; break;

+      case '>': type = '>'; break;

+      case '<': type = '<'; break;

+      case '-': type = '-'; break;

+      case '+': type = '+'; break;

+      case '%': type = '%'; break;

+      case '/': type = '/'; break;

+      case '*': type = '*'; break;

+      case '!': type = '!'; break;

+      case '~': type = '~'; break;

+      case '(': type = '('; break;

+      case ')': type = ')'; break;

+

+      default: break;

+    }

+

+    // Advance to the next token if the current one is valid.

+    if (type != 0) context->lexer->lex(token);

+

+    return type;

+}

+

+void yyerror(Context* context, const char* reason)

+{

+    context->diagnostics->report(pp::Diagnostics::INVALID_EXPRESSION,

+                                 context->token->location,

+                                 reason);

+}

+

+namespace pp {

+

+ExpressionParser::ExpressionParser(Lexer* lexer, Diagnostics* diagnostics) :

+    mLexer(lexer),

+    mDiagnostics(diagnostics)

+{

+}

+

+bool ExpressionParser::parse(Token* token, int* result)

+{

+    Context context;

+    context.diagnostics = mDiagnostics;

+    context.lexer = mLexer;

+    context.token = token;

+    context.result = result;

+    int ret = yyparse(&context);

+    switch (ret)

+    {

+      case 0:

+      case 1:

+        break;

+

+      case 2:

+        mDiagnostics->report(Diagnostics::OUT_OF_MEMORY, token->location, "");

+        break;

+

+      default:

+        assert(false);

+        mDiagnostics->report(Diagnostics::INTERNAL_ERROR, token->location, "");

+        break;

+    }

+

+    return ret == 0;

+}

+

+}  // namespace pp

diff --git a/src/GLES2/compiler/preprocessor/Input.cpp b/src/GLES2/compiler/preprocessor/Input.cpp
new file mode 100644
index 0000000..5cbf138
--- /dev/null
+++ b/src/GLES2/compiler/preprocessor/Input.cpp
@@ -0,0 +1,55 @@
+//

+// Copyright (c) 2011 The ANGLE Project Authors. All rights reserved.

+// Use of this source code is governed by a BSD-style license that can be

+// found in the LICENSE file.

+//

+

+#include "Input.h"

+

+#include <algorithm>

+#include <cassert>

+#include <cstring>

+

+namespace pp

+{

+

+Input::Input() : mCount(0), mString(0)

+{

+}

+

+Input::Input(int count, const char* const string[], const int length[]) :

+    mCount(count),

+    mString(string)

+{

+    assert(mCount >= 0);

+    mLength.reserve(mCount);

+    for (int i = 0; i < mCount; ++i)

+    {

+        int len = length ? length[i] : -1;

+        mLength.push_back(len < 0 ? strlen(mString[i]) : len);

+    }

+}

+

+int Input::read(char* buf, int maxSize)

+{

+    int nRead = 0;

+    while ((nRead < maxSize) && (mReadLoc.sIndex < mCount))

+    {

+        int size = mLength[mReadLoc.sIndex] - mReadLoc.cIndex;

+        size = std::min(size, maxSize);

+        memcpy(buf + nRead, mString[mReadLoc.sIndex] + mReadLoc.cIndex, size);

+        nRead += size;

+        mReadLoc.cIndex += size;

+

+        // Advance string if we reached the end of current string.

+        if (mReadLoc.cIndex == mLength[mReadLoc.sIndex])

+        {

+            ++mReadLoc.sIndex;

+            mReadLoc.cIndex = 0;

+        }

+    }

+    return nRead;

+}

+

+}  // namespace pp

+

diff --git a/src/GLES2/compiler/preprocessor/Input.h b/src/GLES2/compiler/preprocessor/Input.h
new file mode 100644
index 0000000..8e5b1e9
--- /dev/null
+++ b/src/GLES2/compiler/preprocessor/Input.h
@@ -0,0 +1,48 @@
+//

+// Copyright (c) 2011 The ANGLE Project Authors. All rights reserved.

+// Use of this source code is governed by a BSD-style license that can be

+// found in the LICENSE file.

+//

+

+#ifndef COMPILER_PREPROCESSOR_INPUT_H_

+#define COMPILER_PREPROCESSOR_INPUT_H_

+

+#include <vector>

+

+namespace pp

+{

+

+// Holds and reads input for Lexer.

+class Input

+{

+  public:

+    Input();

+    Input(int count, const char* const string[], const int length[]);

+

+    int count() const { return mCount; }

+    const char* string(int index) const { return mString[index]; }

+    int length(int index) const { return mLength[index]; }

+

+    int read(char* buf, int maxSize);

+

+    struct Location

+    {

+        int sIndex;  // String index;

+        int cIndex;  // Char index.

+

+        Location() : sIndex(0), cIndex(0) { }

+    };

+    const Location& readLoc() const { return mReadLoc; }

+

+  private:

+    // Input.

+    int mCount;

+    const char* const* mString;

+    std::vector<int> mLength;

+

+    Location mReadLoc;

+};

+

+}  // namespace pp

+#endif  // COMPILER_PREPROCESSOR_INPUT_H_

+

diff --git a/src/GLES2/compiler/preprocessor/Lexer.cpp b/src/GLES2/compiler/preprocessor/Lexer.cpp
new file mode 100644
index 0000000..231a906
--- /dev/null
+++ b/src/GLES2/compiler/preprocessor/Lexer.cpp
@@ -0,0 +1,16 @@
+//

+// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.

+// Use of this source code is governed by a BSD-style license that can be

+// found in the LICENSE file.

+//

+

+#include "Lexer.h"

+

+namespace pp

+{

+

+Lexer::~Lexer()

+{

+}

+

+}  // namespace pp

diff --git a/src/GLES2/compiler/preprocessor/Lexer.h b/src/GLES2/compiler/preprocessor/Lexer.h
new file mode 100644
index 0000000..cb29a10
--- /dev/null
+++ b/src/GLES2/compiler/preprocessor/Lexer.h
@@ -0,0 +1,25 @@
+//

+// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.

+// Use of this source code is governed by a BSD-style license that can be

+// found in the LICENSE file.

+//

+

+#ifndef COMPILER_PREPROCESSOR_LEXER_H_

+#define COMPILER_PREPROCESSOR_LEXER_H_

+

+namespace pp

+{

+

+struct Token;

+

+class Lexer

+{

+  public:

+    virtual ~Lexer();

+

+    virtual void lex(Token* token) = 0;

+};

+

+}  // namespace pp

+#endif  // COMPILER_PREPROCESSOR_LEXER_H_

+

diff --git a/src/GLES2/compiler/preprocessor/Macro.cpp b/src/GLES2/compiler/preprocessor/Macro.cpp
new file mode 100644
index 0000000..3c57afe
--- /dev/null
+++ b/src/GLES2/compiler/preprocessor/Macro.cpp
@@ -0,0 +1,23 @@
+//

+// Copyright (c) 2011 The ANGLE Project Authors. All rights reserved.

+// Use of this source code is governed by a BSD-style license that can be

+// found in the LICENSE file.

+//

+

+#include "Macro.h"

+

+#include "Token.h"

+

+namespace pp

+{

+

+bool Macro::equals(const Macro& other) const

+{

+    return (type == other.type) &&

+           (name == other.name) &&

+           (parameters == other.parameters) &&

+           (replacements == other.replacements);

+}

+

+}  // namespace pp

+

diff --git a/src/GLES2/compiler/preprocessor/Macro.h b/src/GLES2/compiler/preprocessor/Macro.h
new file mode 100644
index 0000000..36faae9
--- /dev/null
+++ b/src/GLES2/compiler/preprocessor/Macro.h
@@ -0,0 +1,44 @@
+//

+// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.

+// Use of this source code is governed by a BSD-style license that can be

+// found in the LICENSE file.

+//

+

+#ifndef COMPILER_PREPROCESSOR_MACRO_H_

+#define COMPILER_PREPROCESSOR_MACRO_H_

+

+#include <map>

+#include <string>

+#include <vector>

+

+namespace pp

+{

+

+struct Token;

+

+struct Macro

+{

+    enum Type

+    {

+        kTypeObj,

+        kTypeFunc

+    };

+    typedef std::vector<std::string> Parameters;

+    typedef std::vector<Token> Replacements;

+

+    Macro() : predefined(false), disabled(false), type(kTypeObj) { }

+    bool equals(const Macro& other) const;

+

+    bool predefined;

+    mutable bool disabled;

+

+    Type type;

+    std::string name;

+    Parameters parameters;

+    Replacements replacements;

+};

+

+typedef std::map<std::string, Macro> MacroSet;

+

+}  // namespace pp

+#endif  // COMPILER_PREPROCESSOR_MACRO_H_

diff --git a/src/GLES2/compiler/preprocessor/MacroExpander.cpp b/src/GLES2/compiler/preprocessor/MacroExpander.cpp
new file mode 100644
index 0000000..d8bbe8b
--- /dev/null
+++ b/src/GLES2/compiler/preprocessor/MacroExpander.cpp
@@ -0,0 +1,370 @@
+//

+// Copyright (c) 2011 The ANGLE Project Authors. All rights reserved.

+// Use of this source code is governed by a BSD-style license that can be

+// found in the LICENSE file.

+//

+

+#include "MacroExpander.h"

+

+#include <algorithm>

+#include <sstream>

+

+#include "Diagnostics.h"

+#include "Token.h"

+

+namespace pp

+{

+

+class TokenLexer : public Lexer

+{

+ public:

+    typedef std::vector<Token> TokenVector;

+

+    TokenLexer(TokenVector* tokens)

+    {

+        tokens->swap(mTokens);

+        mIter = mTokens.begin();

+    }

+

+    virtual void lex(Token* token)

+    {

+        if (mIter == mTokens.end())

+        {

+            token->reset();

+            token->type = Token::LAST;

+        }

+        else

+        {

+            *token = *mIter++;

+        }

+    }

+

+ private:

+    PP_DISALLOW_COPY_AND_ASSIGN(TokenLexer);

+

+    TokenVector mTokens;

+    TokenVector::const_iterator mIter;

+};

+

+MacroExpander::MacroExpander(Lexer* lexer,

+                             MacroSet* macroSet,

+                             Diagnostics* diagnostics) :

+    mLexer(lexer),

+    mMacroSet(macroSet),

+    mDiagnostics(diagnostics)

+{

+}

+

+MacroExpander::~MacroExpander()

+{

+    for (size_t i = 0; i < mContextStack.size(); ++i)

+    {

+        delete mContextStack[i];

+    }

+}

+

+void MacroExpander::lex(Token* token)

+{

+    while (true)

+    {

+        getToken(token);

+

+        if (token->type != Token::IDENTIFIER)

+            break;

+

+        if (token->expansionDisabled())

+            break;

+

+        MacroSet::const_iterator iter = mMacroSet->find(token->text);

+        if (iter == mMacroSet->end())

+            break;

+

+        const Macro& macro = iter->second;

+        if (macro.disabled)

+        {

+            // If a particular token is not expanded, it is never expanded.

+            token->setExpansionDisabled(true);

+            break;

+        }

+        if ((macro.type == Macro::kTypeFunc) && !isNextTokenLeftParen())

+        {

+            // If the token immediately after the macro name is not a '(',

+            // this macro should not be expanded.

+            break;

+        }

+

+        pushMacro(macro, *token);

+    }

+}

+

+void MacroExpander::getToken(Token* token)

+{

+    if (mReserveToken.get())

+    {

+        *token = *mReserveToken;

+        mReserveToken.reset();

+        return;

+    }

+

+    // First pop all empty macro contexts.

+    while (!mContextStack.empty() && mContextStack.back()->empty())

+    {

+        popMacro();

+    }

+

+    if (!mContextStack.empty())

+    {

+        *token = mContextStack.back()->get();

+    }

+    else

+    {

+        mLexer->lex(token);

+    }

+}

+

+void MacroExpander::ungetToken(const Token& token)

+{

+    if (!mContextStack.empty())

+    {

+        MacroContext* context = mContextStack.back();

+        context->unget();

+        assert(context->replacements[context->index] == token);

+    }

+    else

+    {

+        assert(!mReserveToken.get());

+        mReserveToken.reset(new Token(token));

+    }

+}

+

+bool MacroExpander::isNextTokenLeftParen()

+{

+    Token token;

+    getToken(&token);

+

+    bool lparen = token.type == '(';

+    ungetToken(token);

+

+    return lparen;

+}

+

+bool MacroExpander::pushMacro(const Macro& macro, const Token& identifier)

+{

+    assert(!macro.disabled);

+    assert(!identifier.expansionDisabled());

+    assert(identifier.type == Token::IDENTIFIER);

+    assert(identifier.text == macro.name);

+

+    std::vector<Token> replacements;

+    if (!expandMacro(macro, identifier, &replacements))

+        return false;

+

+    // Macro is disabled for expansion until it is popped off the stack.

+    macro.disabled = true;

+

+    MacroContext* context = new MacroContext;

+    context->macro = &macro;

+    context->replacements.swap(replacements);

+    mContextStack.push_back(context);

+    return true;

+}

+

+void MacroExpander::popMacro()

+{

+    assert(!mContextStack.empty());

+

+    MacroContext* context = mContextStack.back();

+    mContextStack.pop_back();

+

+    assert(context->empty());

+    assert(context->macro->disabled);

+    context->macro->disabled = false;

+    delete context;

+}

+

+bool MacroExpander::expandMacro(const Macro& macro,

+                                const Token& identifier,

+                                std::vector<Token>* replacements)

+{

+    replacements->clear();

+    if (macro.type == Macro::kTypeObj)

+    {

+        replacements->assign(macro.replacements.begin(),

+                             macro.replacements.end());

+

+        if (macro.predefined)

+        {

+            static const std::string kLine = "__LINE__";

+            static const std::string kFile = "__FILE__";

+

+            assert(replacements->size() == 1);

+            Token& repl = replacements->front();

+            if (macro.name == kLine)

+            {

+                std::ostringstream stream;

+                stream << identifier.location.line;

+                repl.text = stream.str();

+            }

+            else if (macro.name == kFile)

+            {

+                std::ostringstream stream;

+                stream << identifier.location.file;

+                repl.text = stream.str();

+            }

+        }

+    }

+    else

+    {

+        assert(macro.type == Macro::kTypeFunc);

+        std::vector<MacroArg> args;

+        args.reserve(macro.parameters.size());

+        if (!collectMacroArgs(macro, identifier, &args))

+            return false;

+

+        replaceMacroParams(macro, args, replacements);

+    }

+

+    for (size_t i = 0; i < replacements->size(); ++i)

+    {

+        Token& repl = replacements->at(i);

+        if (i == 0)

+        {

+            // The first token in the replacement list inherits the padding

+            // properties of the identifier token.

+            repl.setAtStartOfLine(identifier.atStartOfLine());

+            repl.setHasLeadingSpace(identifier.hasLeadingSpace());

+        }

+        repl.location = identifier.location;

+    }

+    return true;

+}

+

+bool MacroExpander::collectMacroArgs(const Macro& macro,

+                                     const Token& identifier,

+                                     std::vector<MacroArg>* args)

+{

+    Token token;

+    getToken(&token);

+    assert(token.type == '(');

+

+    args->push_back(MacroArg());

+    for (int openParens = 1; openParens != 0; )

+    {

+        getToken(&token);

+

+        if (token.type == Token::LAST)

+        {

+            mDiagnostics->report(Diagnostics::MACRO_UNTERMINATED_INVOCATION,

+                                 identifier.location, identifier.text);

+            // Do not lose EOF token.

+            ungetToken(token);

+            return false;

+        }

+

+        bool isArg = false; // True if token is part of the current argument.

+        switch (token.type)

+        {

+          case '(':

+            ++openParens;

+            isArg = true;

+            break;

+          case ')':

+            --openParens;

+            isArg = openParens != 0;

+            break;

+          case ',':

+            // The individual arguments are separated by comma tokens, but

+            // the comma tokens between matching inner parentheses do not

+            // seperate arguments.

+            if (openParens == 1) args->push_back(MacroArg());

+            isArg = openParens != 1;

+            break;

+          default:

+            isArg = true;

+            break;

+        }

+        if (isArg)

+        {

+            MacroArg& arg = args->back();

+            // Initial whitespace is not part of the argument.

+            if (arg.empty()) token.setHasLeadingSpace(false);

+            arg.push_back(token);

+        }

+    }

+

+    const Macro::Parameters& params = macro.parameters;

+    // If there is only one empty argument, it is equivalent to no argument.

+    if (params.empty() && (args->size() == 1) && args->front().empty())

+    {

+        args->clear();

+    }

+    // Validate the number of arguments.

+    if (args->size() != params.size())

+    {

+        Diagnostics::ID id = args->size() < macro.parameters.size() ?

+            Diagnostics::MACRO_TOO_FEW_ARGS :

+            Diagnostics::MACRO_TOO_MANY_ARGS;

+        mDiagnostics->report(id, identifier.location, identifier.text);

+        return false;

+    }

+

+    // Pre-expand each argument before substitution.

+    // This step expands each argument individually before they are

+    // inserted into the macro body.

+    for (size_t i = 0; i < args->size(); ++i)

+    {

+        MacroArg& arg = args->at(i);

+        TokenLexer lexer(&arg);

+        MacroExpander expander(&lexer, mMacroSet, mDiagnostics);

+

+        arg.clear();

+        expander.lex(&token);

+        while (token.type != Token::LAST)

+        {

+            arg.push_back(token);

+            expander.lex(&token);

+        }

+    }

+    return true;

+}

+

+void MacroExpander::replaceMacroParams(const Macro& macro,

+                                       const std::vector<MacroArg>& args,

+                                       std::vector<Token>* replacements)

+{

+    for (size_t i = 0; i < macro.replacements.size(); ++i)

+    {

+        const Token& repl = macro.replacements[i];

+        if (repl.type != Token::IDENTIFIER)

+        {

+            replacements->push_back(repl);

+            continue;

+        }

+

+        // TODO(alokp): Optimize this.

+        // There is no need to search for macro params every time.

+        // The param index can be cached with the replacement token.

+        Macro::Parameters::const_iterator iter = std::find(

+            macro.parameters.begin(), macro.parameters.end(), repl.text);

+        if (iter == macro.parameters.end())

+        {

+            replacements->push_back(repl);

+            continue;

+        }

+

+        size_t iArg = std::distance(macro.parameters.begin(), iter);

+        const MacroArg& arg = args[iArg];

+        if (arg.empty())

+        {

+            continue;

+        }

+        size_t iRepl = replacements->size();

+        replacements->insert(replacements->end(), arg.begin(), arg.end());

+        // The replacement token inherits padding properties from

+        // macro replacement token.

+        replacements->at(iRepl).setHasLeadingSpace(repl.hasLeadingSpace());

+    }

+}

+

+}  // namespace pp

+

diff --git a/src/GLES2/compiler/preprocessor/MacroExpander.h b/src/GLES2/compiler/preprocessor/MacroExpander.h
new file mode 100644
index 0000000..b10b01f
--- /dev/null
+++ b/src/GLES2/compiler/preprocessor/MacroExpander.h
@@ -0,0 +1,75 @@
+//

+// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.

+// Use of this source code is governed by a BSD-style license that can be

+// found in the LICENSE file.

+//

+

+#ifndef COMPILER_PREPROCESSOR_MACRO_EXPANDER_H_

+#define COMPILER_PREPROCESSOR_MACRO_EXPANDER_H_

+

+#include <cassert>

+#include <memory>

+#include <vector>

+

+#include "Lexer.h"

+#include "Macro.h"

+#include "pp_utils.h"

+

+namespace pp

+{

+

+class Diagnostics;

+

+class MacroExpander : public Lexer

+{

+  public:

+    MacroExpander(Lexer* lexer, MacroSet* macroSet, Diagnostics* diagnostics);

+    virtual ~MacroExpander();

+

+    virtual void lex(Token* token);

+

+  private:

+    PP_DISALLOW_COPY_AND_ASSIGN(MacroExpander);

+

+    void getToken(Token* token);

+    void ungetToken(const Token& token);

+    bool isNextTokenLeftParen();

+

+    bool pushMacro(const Macro& macro, const Token& identifier);

+    void popMacro();

+

+    bool expandMacro(const Macro& macro,

+                     const Token& identifier,

+                     std::vector<Token>* replacements);

+

+    typedef std::vector<Token> MacroArg;

+    bool collectMacroArgs(const Macro& macro,

+                          const Token& identifier,

+                          std::vector<MacroArg>* args);

+    void replaceMacroParams(const Macro& macro,

+                            const std::vector<MacroArg>& args,

+                            std::vector<Token>* replacements);

+

+    struct MacroContext

+    {

+        const Macro* macro;

+        size_t index;

+        std::vector<Token> replacements;

+

+        MacroContext() : macro(0), index(0) { }

+        bool empty() const { return index == replacements.size(); }

+        const Token& get() { return replacements[index++]; }

+        void unget() { assert(index > 0); --index; }

+    };

+

+    Lexer* mLexer;

+    MacroSet* mMacroSet;

+    Diagnostics* mDiagnostics;

+

+    std::auto_ptr<Token> mReserveToken;

+    std::vector<MacroContext*> mContextStack;

+};

+

+}  // namespace pp

+#endif  // COMPILER_PREPROCESSOR_MACRO_EXPANDER_H_

+

diff --git a/src/GLES2/compiler/preprocessor/Preprocessor.cpp b/src/GLES2/compiler/preprocessor/Preprocessor.cpp
new file mode 100644
index 0000000..296c8aa
--- /dev/null
+++ b/src/GLES2/compiler/preprocessor/Preprocessor.cpp
@@ -0,0 +1,142 @@
+//

+// Copyright (c) 2011 The ANGLE Project Authors. All rights reserved.

+// Use of this source code is governed by a BSD-style license that can be

+// found in the LICENSE file.

+//

+

+#include "Preprocessor.h"

+

+#include <cassert>

+#include <sstream>

+

+#include "Diagnostics.h"

+#include "DirectiveParser.h"

+#include "Macro.h"

+#include "MacroExpander.h"

+#include "Token.h"

+#include "Tokenizer.h"

+

+namespace pp

+{

+

+struct PreprocessorImpl

+{

+    Diagnostics* diagnostics;

+    MacroSet macroSet;

+    Tokenizer tokenizer;

+    DirectiveParser directiveParser;

+    MacroExpander macroExpander;

+

+    PreprocessorImpl(Diagnostics* diag,

+                     DirectiveHandler* directiveHandler) :

+        diagnostics(diag),

+        tokenizer(diag),

+        directiveParser(&tokenizer, &macroSet, diag, directiveHandler),

+        macroExpander(&directiveParser, &macroSet, diag)

+    {

+    }

+};

+

+Preprocessor::Preprocessor(Diagnostics* diagnostics,

+                           DirectiveHandler* directiveHandler)

+{

+    mImpl = new PreprocessorImpl(diagnostics, directiveHandler);

+}

+

+Preprocessor::~Preprocessor()

+{

+    delete mImpl;

+}

+

+bool Preprocessor::init(int count,

+                        const char* const string[],

+                        const int length[])

+{

+    static const int kGLSLVersion = 100;

+

+    // Add standard pre-defined macros.

+    predefineMacro("__LINE__", 0);

+    predefineMacro("__FILE__", 0);

+    predefineMacro("__VERSION__", kGLSLVersion);

+    predefineMacro("GL_ES", 1);

+

+    return mImpl->tokenizer.init(count, string, length);

+}

+

+void Preprocessor::predefineMacro(const char* name, int value)

+{

+    std::ostringstream stream;

+    stream << value;

+

+    Token token;

+    token.type = Token::CONST_INT;

+    token.text = stream.str();

+

+    Macro macro;

+    macro.predefined = true;

+    macro.type = Macro::kTypeObj;

+    macro.name = name;

+    macro.replacements.push_back(token);

+

+    mImpl->macroSet[name] = macro;

+}

+

+void Preprocessor::lex(Token* token)

+{

+    bool validToken = false;

+    while (!validToken)

+    {

+        mImpl->macroExpander.lex(token);

+        switch (token->type)

+        {

+          // We should not be returning internal preprocessing tokens.

+          // Convert preprocessing tokens to compiler tokens or report

+          // diagnostics.

+          case Token::PP_HASH:

+            assert(false);

+            break;

+          case Token::CONST_INT:

+          {

+            int val = 0;

+            if (!token->iValue(&val))

+            {

+                // Do not mark the token as invalid.

+                // Just emit the diagnostic and reset value to 0.

+                mImpl->diagnostics->report(Diagnostics::INTEGER_OVERFLOW,

+                                           token->location, token->text);

+                token->text.assign("0");

+            }

+            validToken = true;

+            break;

+          }

+          case Token::CONST_FLOAT:

+          {

+            float val = 0;

+            if (!token->fValue(&val))

+            {

+                // Do not mark the token as invalid.

+                // Just emit the diagnostic and reset value to 0.0.

+                mImpl->diagnostics->report(Diagnostics::FLOAT_OVERFLOW,

+                                           token->location, token->text);

+                token->text.assign("0.0");

+            }

+            validToken = true;

+            break;

+          }

+          case Token::PP_NUMBER:

+            mImpl->diagnostics->report(Diagnostics::INVALID_NUMBER,

+                                       token->location, token->text);

+            break;

+          case Token::PP_OTHER:

+            mImpl->diagnostics->report(Diagnostics::INVALID_CHARACTER,

+                                       token->location, token->text);

+            break;

+          default:

+            validToken = true;

+            break;

+        }

+    }

+}

+

+}  // namespace pp

+

diff --git a/src/GLES2/compiler/preprocessor/Preprocessor.h b/src/GLES2/compiler/preprocessor/Preprocessor.h
new file mode 100644
index 0000000..7a54da0
--- /dev/null
+++ b/src/GLES2/compiler/preprocessor/Preprocessor.h
@@ -0,0 +1,49 @@
+//

+// Copyright (c) 2011 The ANGLE Project Authors. All rights reserved.

+// Use of this source code is governed by a BSD-style license that can be

+// found in the LICENSE file.

+//

+

+#ifndef COMPILER_PREPROCESSOR_PREPROCESSOR_H_

+#define COMPILER_PREPROCESSOR_PREPROCESSOR_H_

+

+#include "pp_utils.h"

+

+namespace pp

+{

+

+class Diagnostics;

+class DirectiveHandler;

+struct PreprocessorImpl;

+struct Token;

+

+class Preprocessor

+{

+  public:

+    Preprocessor(Diagnostics* diagnostics, DirectiveHandler* directiveHandler);

+    ~Preprocessor();

+

+    // count: specifies the number of elements in the string and length arrays.

+    // string: specifies an array of pointers to strings.

+    // length: specifies an array of string lengths.

+    // If length is NULL, each string is assumed to be null terminated.

+    // If length is a value other than NULL, it points to an array containing

+    // a string length for each of the corresponding elements of string.

+    // Each element in the length array may contain the length of the

+    // corresponding string or a value less than 0 to indicate that the string

+    // is null terminated.

+    bool init(int count, const char* const string[], const int length[]);

+    // Adds a pre-defined macro.

+    void predefineMacro(const char* name, int value);

+

+    void lex(Token* token);

+

+  private:

+    PP_DISALLOW_COPY_AND_ASSIGN(Preprocessor);

+

+    PreprocessorImpl* mImpl;

+};

+

+}  // namespace pp

+#endif  // COMPILER_PREPROCESSOR_PREPROCESSOR_H_

+

diff --git a/src/GLES2/compiler/preprocessor/SourceLocation.h b/src/GLES2/compiler/preprocessor/SourceLocation.h
new file mode 100644
index 0000000..9c0d1d3
--- /dev/null
+++ b/src/GLES2/compiler/preprocessor/SourceLocation.h
@@ -0,0 +1,38 @@
+//

+// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.

+// Use of this source code is governed by a BSD-style license that can be

+// found in the LICENSE file.

+//

+

+#ifndef COMPILER_PREPROCESSOR_SOURCE_LOCATION_H_

+#define COMPILER_PREPROCESSOR_SOURCE_LOCATION_H_

+

+namespace pp

+{

+

+struct SourceLocation

+{

+    SourceLocation() : file(0), line(0) { }

+    SourceLocation(int f, int l) : file(f), line(l) { }

+

+    bool equals(const SourceLocation& other) const

+    {

+        return (file == other.file) && (line == other.line);

+    }

+

+    int file;

+    int line;

+};

+

+inline bool operator==(const SourceLocation& lhs, const SourceLocation& rhs)

+{

+    return lhs.equals(rhs);

+}

+

+inline bool operator!=(const SourceLocation& lhs, const SourceLocation& rhs)

+{

+    return !lhs.equals(rhs);

+}

+

+}  // namespace pp

+#endif  // COMPILER_PREPROCESSOR_SOURCE_LOCATION_H_

diff --git a/src/GLES2/compiler/preprocessor/Token.cpp b/src/GLES2/compiler/preprocessor/Token.cpp
new file mode 100644
index 0000000..a465aa1
--- /dev/null
+++ b/src/GLES2/compiler/preprocessor/Token.cpp
@@ -0,0 +1,83 @@
+//

+// Copyright (c) 2011 The ANGLE Project Authors. All rights reserved.

+// Use of this source code is governed by a BSD-style license that can be

+// found in the LICENSE file.

+//

+

+#include "Token.h"

+

+#include <cassert>

+

+#include "numeric_lex.h"

+

+namespace pp

+{

+

+void Token::reset()

+{

+    type = 0;

+    flags = 0;

+    location = SourceLocation();

+    text.clear();

+}

+

+bool Token::equals(const Token& other) const

+{

+    return (type == other.type) &&

+           (flags == other.flags) &&

+           (location == other.location) &&

+           (text == other.text);

+}

+

+void Token::setAtStartOfLine(bool start)

+{

+    if (start)

+        flags |= AT_START_OF_LINE;

+    else

+        flags &= ~AT_START_OF_LINE;

+}

+

+void Token::setHasLeadingSpace(bool space)

+{

+    if (space)

+        flags |= HAS_LEADING_SPACE;

+    else

+        flags &= ~HAS_LEADING_SPACE;

+}

+

+void Token::setExpansionDisabled(bool disable)

+{

+    if (disable)

+        flags |= EXPANSION_DISABLED;

+    else

+        flags &= ~EXPANSION_DISABLED;

+}

+

+bool Token::iValue(int* value) const

+{

+    assert(type == CONST_INT);

+    return numeric_lex_int(text, value);

+}

+

+bool Token::uValue(unsigned int* value) const

+{

+    assert(type == CONST_INT);

+    return numeric_lex_int(text, value);

+}

+

+bool Token::fValue(float* value) const

+{

+    assert(type == CONST_FLOAT);

+    return numeric_lex_float(text, value);

+}

+

+std::ostream& operator<<(std::ostream& out, const Token& token)

+{

+    if (token.hasLeadingSpace())

+        out << " ";

+

+    out << token.text;

+    return out;

+}

+

+}  // namespace pp

diff --git a/src/GLES2/compiler/preprocessor/Token.h b/src/GLES2/compiler/preprocessor/Token.h
new file mode 100644
index 0000000..45b1129
--- /dev/null
+++ b/src/GLES2/compiler/preprocessor/Token.h
@@ -0,0 +1,106 @@
+//

+// Copyright (c) 2011 The ANGLE Project Authors. All rights reserved.

+// Use of this source code is governed by a BSD-style license that can be

+// found in the LICENSE file.

+//

+

+#ifndef COMPILER_PREPROCESSOR_TOKEN_H_

+#define COMPILER_PREPROCESSOR_TOKEN_H_

+

+#include <ostream>

+#include <string>

+

+#include "SourceLocation.h"

+

+namespace pp

+{

+

+struct Token

+{

+    enum Type

+    {

+        LAST = 0,  // EOF.

+

+        IDENTIFIER = 258,

+

+        CONST_INT,

+        CONST_FLOAT,

+

+        OP_INC,

+        OP_DEC,

+        OP_LEFT,

+        OP_RIGHT,

+        OP_LE,

+        OP_GE,

+        OP_EQ,

+        OP_NE,

+        OP_AND,

+        OP_XOR,

+        OP_OR,

+        OP_ADD_ASSIGN,

+        OP_SUB_ASSIGN,

+        OP_MUL_ASSIGN,

+        OP_DIV_ASSIGN,

+        OP_MOD_ASSIGN,

+        OP_LEFT_ASSIGN,

+        OP_RIGHT_ASSIGN,

+        OP_AND_ASSIGN,

+        OP_XOR_ASSIGN,

+        OP_OR_ASSIGN,

+

+        // Preprocessing token types.

+        // These types are used by the preprocessor internally.

+        // Preprocessor clients must not depend or check for them.

+        PP_HASH,

+        PP_NUMBER,

+        PP_OTHER

+    };

+    enum Flags

+    {

+        AT_START_OF_LINE   = 1 << 0,

+        HAS_LEADING_SPACE  = 1 << 1,

+        EXPANSION_DISABLED = 1 << 2

+    };

+

+    Token() : type(0), flags(0) { }

+

+    void reset();

+    bool equals(const Token& other) const;

+

+    // Returns true if this is the first token on line.

+    // It disregards any leading whitespace.

+    bool atStartOfLine() const { return (flags & AT_START_OF_LINE) != 0; }

+    void setAtStartOfLine(bool start);

+

+    bool hasLeadingSpace() const { return (flags & HAS_LEADING_SPACE) != 0; }

+    void setHasLeadingSpace(bool space);

+

+    bool expansionDisabled() const { return (flags & EXPANSION_DISABLED) != 0; }

+    void setExpansionDisabled(bool disable);

+

+    // Converts text into numeric value for CONST_INT and CONST_FLOAT token.

+    // Returns false if the parsed value cannot fit into an int or float.

+    bool iValue(int* value) const;

+    bool uValue(unsigned int* value) const;

+    bool fValue(float* value) const;

+

+    int type;

+    unsigned int flags;

+    SourceLocation location;

+    std::string text;

+};

+

+inline bool operator==(const Token& lhs, const Token& rhs)

+{

+    return lhs.equals(rhs);

+}

+

+inline bool operator!=(const Token& lhs, const Token& rhs)

+{

+    return !lhs.equals(rhs);

+}

+

+extern std::ostream& operator<<(std::ostream& out, const Token& token);

+

+}  // namepsace pp

+#endif  // COMPILER_PREPROCESSOR_TOKEN_H_

diff --git a/src/GLES2/compiler/preprocessor/Tokenizer.cpp b/src/GLES2/compiler/preprocessor/Tokenizer.cpp
new file mode 100644
index 0000000..aecc06c
--- /dev/null
+++ b/src/GLES2/compiler/preprocessor/Tokenizer.cpp
@@ -0,0 +1,2370 @@
+#line 16 "./Tokenizer.l"

+//

+// Copyright (c) 2011 The ANGLE Project Authors. All rights reserved.

+// Use of this source code is governed by a BSD-style license that can be

+// found in the LICENSE file.

+//

+

+// This file is auto-generated by generate_parser.sh. DO NOT EDIT!

+

+

+

+#line 13 "./Tokenizer.cpp"

+

+#define  YY_INT_ALIGNED short int

+

+/* A lexical scanner generated by flex */

+

+#define FLEX_SCANNER

+#define YY_FLEX_MAJOR_VERSION 2

+#define YY_FLEX_MINOR_VERSION 5

+#define YY_FLEX_SUBMINOR_VERSION 35

+#if YY_FLEX_SUBMINOR_VERSION > 0

+#define FLEX_BETA

+#endif

+

+/* First, we deal with  platform-specific or compiler-specific issues. */

+

+/* begin standard C headers. */

+#include <stdio.h>

+#include <string.h>

+#include <errno.h>

+#include <stdlib.h>

+

+/* end standard C headers. */

+

+/* flex integer type definitions */

+

+#ifndef FLEXINT_H

+#define FLEXINT_H

+

+/* C99 systems have <inttypes.h>. Non-C99 systems may or may not. */

+

+#if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L

+

+/* C99 says to define __STDC_LIMIT_MACROS before including stdint.h,

+ * if you want the limit (max/min) macros for int types. 

+ */

+#ifndef __STDC_LIMIT_MACROS

+#define __STDC_LIMIT_MACROS 1

+#endif

+

+#include <inttypes.h>

+typedef int8_t flex_int8_t;

+typedef uint8_t flex_uint8_t;

+typedef int16_t flex_int16_t;

+typedef uint16_t flex_uint16_t;

+typedef int32_t flex_int32_t;

+typedef uint32_t flex_uint32_t;

+#else

+typedef signed char flex_int8_t;

+typedef short int flex_int16_t;

+typedef int flex_int32_t;

+typedef unsigned char flex_uint8_t; 

+typedef unsigned short int flex_uint16_t;

+typedef unsigned int flex_uint32_t;

+

+/* Limits of integral types. */

+#ifndef INT8_MIN

+#define INT8_MIN               (-128)

+#endif

+#ifndef INT16_MIN

+#define INT16_MIN              (-32767-1)

+#endif

+#ifndef INT32_MIN

+#define INT32_MIN              (-2147483647-1)

+#endif

+#ifndef INT8_MAX

+#define INT8_MAX               (127)

+#endif

+#ifndef INT16_MAX

+#define INT16_MAX              (32767)

+#endif

+#ifndef INT32_MAX

+#define INT32_MAX              (2147483647)

+#endif

+#ifndef UINT8_MAX

+#define UINT8_MAX              (255U)

+#endif

+#ifndef UINT16_MAX

+#define UINT16_MAX             (65535U)

+#endif

+#ifndef UINT32_MAX

+#define UINT32_MAX             (4294967295U)

+#endif

+

+#endif /* ! C99 */

+

+#endif /* ! FLEXINT_H */

+

+#ifdef __cplusplus

+

+/* The "const" storage-class-modifier is valid. */

+#define YY_USE_CONST

+

+#else	/* ! __cplusplus */

+

+/* C99 requires __STDC__ to be defined as 1. */

+#if defined (__STDC__)

+

+#define YY_USE_CONST

+

+#endif	/* defined (__STDC__) */

+#endif	/* ! __cplusplus */

+

+#ifdef YY_USE_CONST

+#define yyconst const

+#else

+#define yyconst

+#endif

+

+/* Returned upon end-of-file. */

+#define YY_NULL 0

+

+/* Promotes a possibly negative, possibly signed char to an unsigned

+ * integer for use as an array index.  If the signed char is negative,

+ * we want to instead treat it as an 8-bit unsigned char, hence the

+ * double cast.

+ */

+#define YY_SC_TO_UI(c) ((unsigned int) (unsigned char) c)

+

+/* An opaque pointer. */

+#ifndef YY_TYPEDEF_YY_SCANNER_T

+#define YY_TYPEDEF_YY_SCANNER_T

+typedef void* yyscan_t;

+#endif

+

+/* For convenience, these vars (plus the bison vars far below)

+   are macros in the reentrant scanner. */

+#define yyin yyg->yyin_r

+#define yyout yyg->yyout_r

+#define yyextra yyg->yyextra_r

+#define yyleng yyg->yyleng_r

+#define yytext yyg->yytext_r

+#define yylineno (YY_CURRENT_BUFFER_LVALUE->yy_bs_lineno)

+#define yycolumn (YY_CURRENT_BUFFER_LVALUE->yy_bs_column)

+#define yy_flex_debug yyg->yy_flex_debug_r

+

+/* Enter a start condition.  This macro really ought to take a parameter,

+ * but we do it the disgusting crufty way forced on us by the ()-less

+ * definition of BEGIN.

+ */

+#define BEGIN yyg->yy_start = 1 + 2 *

+

+/* Translate the current start state into a value that can be later handed

+ * to BEGIN to return to the state.  The YYSTATE alias is for lex

+ * compatibility.

+ */

+#define YY_START ((yyg->yy_start - 1) / 2)

+#define YYSTATE YY_START

+

+/* Action number for EOF rule of a given start state. */

+#define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1)

+

+/* Special action meaning "start processing a new file". */

+#define YY_NEW_FILE pprestart(yyin ,yyscanner )

+

+#define YY_END_OF_BUFFER_CHAR 0

+

+/* Size of default input buffer. */

+#ifndef YY_BUF_SIZE

+#ifdef __ia64__

+/* On IA-64, the buffer size is 16k, not 8k.

+ * Moreover, YY_BUF_SIZE is 2*YY_READ_BUF_SIZE in the general case.

+ * Ditto for the __ia64__ case accordingly.

+ */

+#define YY_BUF_SIZE 32768

+#else

+#define YY_BUF_SIZE 16384

+#endif /* __ia64__ */

+#endif

+

+/* The state buf must be large enough to hold one state per character in the main buffer.

+ */

+#define YY_STATE_BUF_SIZE   ((YY_BUF_SIZE + 2) * sizeof(yy_state_type))

+

+#ifndef YY_TYPEDEF_YY_BUFFER_STATE

+#define YY_TYPEDEF_YY_BUFFER_STATE

+typedef struct yy_buffer_state *YY_BUFFER_STATE;

+#endif

+

+#define EOB_ACT_CONTINUE_SCAN 0

+#define EOB_ACT_END_OF_FILE 1

+#define EOB_ACT_LAST_MATCH 2

+

+    #define YY_LESS_LINENO(n)

+    

+/* Return all but the first "n" matched characters back to the input stream. */

+#define yyless(n) \

+	do \

+		{ \

+		/* Undo effects of setting up yytext. */ \

+        int yyless_macro_arg = (n); \

+        YY_LESS_LINENO(yyless_macro_arg);\

+		*yy_cp = yyg->yy_hold_char; \

+		YY_RESTORE_YY_MORE_OFFSET \

+		yyg->yy_c_buf_p = yy_cp = yy_bp + yyless_macro_arg - YY_MORE_ADJ; \

+		YY_DO_BEFORE_ACTION; /* set up yytext again */ \

+		} \

+	while ( 0 )

+

+#define unput(c) yyunput( c, yyg->yytext_ptr , yyscanner )

+

+#ifndef YY_TYPEDEF_YY_SIZE_T

+#define YY_TYPEDEF_YY_SIZE_T

+typedef size_t yy_size_t;

+#endif

+

+#ifndef YY_STRUCT_YY_BUFFER_STATE

+#define YY_STRUCT_YY_BUFFER_STATE

+struct yy_buffer_state

+	{

+	FILE *yy_input_file;

+

+	char *yy_ch_buf;		/* input buffer */

+	char *yy_buf_pos;		/* current position in input buffer */

+

+	/* Size of input buffer in bytes, not including room for EOB

+	 * characters.

+	 */

+	yy_size_t yy_buf_size;

+

+	/* Number of characters read into yy_ch_buf, not including EOB

+	 * characters.

+	 */

+	int yy_n_chars;

+

+	/* Whether we "own" the buffer - i.e., we know we created it,

+	 * and can realloc() it to grow it, and should free() it to

+	 * delete it.

+	 */

+	int yy_is_our_buffer;

+

+	/* Whether this is an "interactive" input source; if so, and

+	 * if we're using stdio for input, then we want to use getc()

+	 * instead of fread(), to make sure we stop fetching input after

+	 * each newline.

+	 */

+	int yy_is_interactive;

+

+	/* Whether we're considered to be at the beginning of a line.

+	 * If so, '^' rules will be active on the next match, otherwise

+	 * not.

+	 */

+	int yy_at_bol;

+

+    int yy_bs_lineno; /**< The line count. */

+    int yy_bs_column; /**< The column count. */

+    

+	/* Whether to try to fill the input buffer when we reach the

+	 * end of it.

+	 */

+	int yy_fill_buffer;

+

+	int yy_buffer_status;

+

+#define YY_BUFFER_NEW 0

+#define YY_BUFFER_NORMAL 1

+	/* When an EOF's been seen but there's still some text to process

+	 * then we mark the buffer as YY_EOF_PENDING, to indicate that we

+	 * shouldn't try reading from the input source any more.  We might

+	 * still have a bunch of tokens to match, though, because of

+	 * possible backing-up.

+	 *

+	 * When we actually see the EOF, we change the status to "new"

+	 * (via pprestart()), so that the user can continue scanning by

+	 * just pointing yyin at a new input file.

+	 */

+#define YY_BUFFER_EOF_PENDING 2

+

+	};

+#endif /* !YY_STRUCT_YY_BUFFER_STATE */

+

+/* We provide macros for accessing buffer states in case in the

+ * future we want to put the buffer states in a more general

+ * "scanner state".

+ *

+ * Returns the top of the stack, or NULL.

+ */

+#define YY_CURRENT_BUFFER ( yyg->yy_buffer_stack \

+                          ? yyg->yy_buffer_stack[yyg->yy_buffer_stack_top] \

+                          : NULL)

+

+/* Same as previous macro, but useful when we know that the buffer stack is not

+ * NULL or when we need an lvalue. For internal use only.

+ */

+#define YY_CURRENT_BUFFER_LVALUE yyg->yy_buffer_stack[yyg->yy_buffer_stack_top]

+

+void pprestart (FILE *input_file ,yyscan_t yyscanner );

+void pp_switch_to_buffer (YY_BUFFER_STATE new_buffer ,yyscan_t yyscanner );

+YY_BUFFER_STATE pp_create_buffer (FILE *file,int size ,yyscan_t yyscanner );

+void pp_delete_buffer (YY_BUFFER_STATE b ,yyscan_t yyscanner );

+void pp_flush_buffer (YY_BUFFER_STATE b ,yyscan_t yyscanner );

+void pppush_buffer_state (YY_BUFFER_STATE new_buffer ,yyscan_t yyscanner );

+void pppop_buffer_state (yyscan_t yyscanner );

+

+static void ppensure_buffer_stack (yyscan_t yyscanner );

+static void pp_load_buffer_state (yyscan_t yyscanner );

+static void pp_init_buffer (YY_BUFFER_STATE b,FILE *file ,yyscan_t yyscanner );

+

+#define YY_FLUSH_BUFFER pp_flush_buffer(YY_CURRENT_BUFFER ,yyscanner)

+

+YY_BUFFER_STATE pp_scan_buffer (char *base,yy_size_t size ,yyscan_t yyscanner );

+YY_BUFFER_STATE pp_scan_string (yyconst char *yy_str ,yyscan_t yyscanner );

+YY_BUFFER_STATE pp_scan_bytes (yyconst char *bytes,int len ,yyscan_t yyscanner );

+

+void *ppalloc (yy_size_t ,yyscan_t yyscanner );

+void *pprealloc (void *,yy_size_t ,yyscan_t yyscanner );

+void ppfree (void * ,yyscan_t yyscanner );

+

+#define yy_new_buffer pp_create_buffer

+

+#define yy_set_interactive(is_interactive) \

+	{ \

+	if ( ! YY_CURRENT_BUFFER ){ \

+        ppensure_buffer_stack (yyscanner); \

+		YY_CURRENT_BUFFER_LVALUE =    \

+            pp_create_buffer(yyin,YY_BUF_SIZE ,yyscanner); \

+	} \

+	YY_CURRENT_BUFFER_LVALUE->yy_is_interactive = is_interactive; \

+	}

+

+#define yy_set_bol(at_bol) \

+	{ \

+	if ( ! YY_CURRENT_BUFFER ){\

+        ppensure_buffer_stack (yyscanner); \

+		YY_CURRENT_BUFFER_LVALUE =    \

+            pp_create_buffer(yyin,YY_BUF_SIZE ,yyscanner); \

+	} \

+	YY_CURRENT_BUFFER_LVALUE->yy_at_bol = at_bol; \

+	}

+

+#define YY_AT_BOL() (YY_CURRENT_BUFFER_LVALUE->yy_at_bol)

+

+/* Begin user sect3 */

+

+#define ppwrap(n) 1

+#define YY_SKIP_YYWRAP

+

+typedef unsigned char YY_CHAR;

+

+typedef int yy_state_type;

+

+#define yytext_ptr yytext_r

+

+static yy_state_type yy_get_previous_state (yyscan_t yyscanner );

+static yy_state_type yy_try_NUL_trans (yy_state_type current_state  ,yyscan_t yyscanner);

+static int yy_get_next_buffer (yyscan_t yyscanner );

+static void yy_fatal_error (yyconst char msg[] ,yyscan_t yyscanner );

+

+/* Done after the current pattern has been matched and before the

+ * corresponding action - sets up yytext.

+ */

+#define YY_DO_BEFORE_ACTION \

+	yyg->yytext_ptr = yy_bp; \

+	yyleng = (size_t) (yy_cp - yy_bp); \

+	yyg->yy_hold_char = *yy_cp; \

+	*yy_cp = '\0'; \

+	yyg->yy_c_buf_p = yy_cp;

+

+#define YY_NUM_RULES 37

+#define YY_END_OF_BUFFER 38

+/* This struct is not used in this scanner,

+   but its presence is necessary. */

+struct yy_trans_info

+	{

+	flex_int32_t yy_verify;

+	flex_int32_t yy_nxt;

+	};

+static yyconst flex_int16_t yy_accept[84] =

+    {   0,

+        0,    0,    0,    0,   38,   36,   34,   35,   35,   33,

+        7,   33,   33,   33,   33,   33,   33,   33,   33,    9,

+        9,   33,   33,   33,    8,   33,   33,    3,    5,    5,

+        4,   34,   35,   19,   27,   20,   30,   25,   12,   23,

+       13,   24,   10,    2,    1,   26,   10,    9,   11,   11,

+       11,   11,    9,   14,   16,   18,   17,   15,    8,   31,

+       21,   32,   22,    3,    5,    6,   11,   10,   11,    1,

+       10,   11,    0,   10,    9,   28,   29,    0,   10,   10,

+       10,   10,    0

+    } ;

+

+static yyconst flex_int32_t yy_ec[256] =

+    {   0,

+        1,    1,    1,    1,    1,    1,    1,    1,    2,    3,

+        2,    2,    4,    1,    1,    1,    1,    1,    1,    1,

+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,

+        1,    2,    5,    1,    6,    1,    7,    8,    1,    9,

+        9,   10,   11,    9,   12,   13,   14,   15,   16,   16,

+       16,   16,   16,   16,   16,   17,   17,    9,    9,   18,

+       19,   20,    9,    1,   21,   21,   21,   21,   22,   21,

+       23,   23,   23,   23,   23,   23,   23,   23,   23,   23,

+       23,   23,   23,   23,   23,   23,   23,   24,   23,   23,

+        9,    1,    9,   25,   23,    1,   21,   21,   21,   21,

+

+       22,   21,   23,   23,   23,   23,   23,   23,   23,   23,

+       23,   23,   23,   23,   23,   23,   23,   23,   23,   24,

+       23,   23,    9,   26,    9,    9,    1,    1,    1,    1,

+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,

+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,

+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,

+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,

+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,

+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,

+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,

+

+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,

+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,

+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,

+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,

+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,

+        1,    1,    1,    1,    1

+    } ;

+

+static yyconst flex_int32_t yy_meta[27] =

+    {   0,

+        1,    1,    2,    2,    1,    1,    1,    1,    1,    3,

+        1,    1,    4,    1,    5,    5,    5,    1,    1,    1,

+        5,    5,    5,    5,    1,    1

+    } ;

+

+static yyconst flex_int16_t yy_base[89] =

+    {   0,

+        0,    0,   24,   26,  158,  159,  150,  159,  145,  128,

+      159,  112,   23,  159,  111,   21,   25,   30,   29,   36,

+       46,   36,  100,   45,    0,   16,   47,    0,  159,   84,

+       65,   73,  159,  159,  159,  159,  159,  159,  159,  159,

+      159,  159,   61,  159,    0,  159,   73,   32,   56,   83,

+       95,   68,    0,   31,  159,  159,  159,   19,    0,  159,

+      159,  159,  159,    0,  159,  159,   98,    0,  110,    0,

+        0,  117,   52,   90,   80,  159,  159,  101,   97,  112,

+      120,  123,  159,  140,   28,  145,  150,  152

+    } ;

+

+static yyconst flex_int16_t yy_def[89] =

+    {   0,

+       83,    1,   84,   84,   83,   83,   83,   83,   83,   83,

+       83,   83,   83,   83,   83,   83,   83,   83,   83,   83,

+       20,   83,   83,   83,   85,   83,   83,   86,   83,   83,

+       83,   83,   83,   83,   83,   83,   83,   83,   83,   83,

+       83,   83,   83,   83,   87,   83,   83,   20,   20,   47,

+       50,   88,   21,   83,   83,   83,   83,   83,   85,   83,

+       83,   83,   83,   86,   83,   83,   43,   43,   67,   87,

+       47,   50,   83,   51,   88,   83,   83,   83,   69,   72,

+       83,   83,    0,   83,   83,   83,   83,   83

+    } ;

+

+static yyconst flex_int16_t yy_nxt[186] =

+    {   0,

+        6,    7,    8,    9,   10,   11,   12,   13,   14,   15,

+       16,   17,   18,   19,   20,   21,   21,   22,   23,   24,

+       25,   25,   25,   25,   26,   27,   29,   30,   29,   30,

+       36,   39,   59,   31,   60,   31,   41,   77,   44,   40,

+       61,   37,   45,   42,   43,   43,   43,   46,   47,   76,

+       48,   48,   49,   54,   55,   50,   50,   51,   50,   52,

+       53,   53,   53,   57,   58,   62,   81,   81,   81,   50,

+       49,   49,   63,   67,   32,   68,   68,   68,   66,   50,

+       50,   67,   69,   67,   67,   50,   65,   71,   71,   71,

+       50,   50,   50,   50,   72,   50,   50,   50,   50,   50,

+

+       83,   83,   50,   50,   50,   73,   73,   83,   83,   74,

+       74,   74,   67,   67,   67,   82,   82,   82,   56,   67,

+       78,   78,   83,   83,   79,   79,   79,   78,   78,   38,

+       35,   80,   80,   80,   81,   81,   81,   82,   82,   82,

+       28,   28,   28,   28,   28,   64,   34,   33,   64,   64,

+       70,   32,   70,   70,   70,   75,   75,   83,    5,   83,

+       83,   83,   83,   83,   83,   83,   83,   83,   83,   83,

+       83,   83,   83,   83,   83,   83,   83,   83,   83,   83,

+       83,   83,   83,   83,   83

+    } ;

+

+static yyconst flex_int16_t yy_chk[186] =

+    {   0,

+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,

+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,

+        1,    1,    1,    1,    1,    1,    3,    3,    4,    4,

+       13,   16,   85,    3,   26,    4,   17,   58,   19,   16,

+       26,   13,   19,   17,   18,   18,   18,   19,   20,   54,

+       20,   20,   20,   22,   22,   48,   20,   20,   20,   20,

+       21,   21,   21,   24,   24,   27,   73,   73,   73,   21,

+       49,   49,   27,   43,   32,   43,   43,   43,   31,   49,

+       52,   43,   43,   43,   43,   47,   30,   47,   47,   47,

+       52,   52,   75,   47,   47,   47,   47,   50,   50,   50,

+

+       74,   74,   75,   75,   50,   51,   51,   79,   79,   51,

+       51,   51,   67,   67,   67,   78,   78,   78,   23,   67,

+       69,   69,   80,   80,   69,   69,   69,   72,   72,   15,

+       12,   72,   72,   72,   81,   81,   81,   82,   82,   82,

+       84,   84,   84,   84,   84,   86,   10,    9,   86,   86,

+       87,    7,   87,   87,   87,   88,   88,    5,   83,   83,

+       83,   83,   83,   83,   83,   83,   83,   83,   83,   83,

+       83,   83,   83,   83,   83,   83,   83,   83,   83,   83,

+       83,   83,   83,   83,   83

+    } ;

+

+/* The intent behind this definition is that it'll catch

+ * any uses of REJECT which flex missed.

+ */

+#define REJECT reject_used_but_not_detected

+#define yymore() yymore_used_but_not_detected

+#define YY_MORE_ADJ 0

+#define YY_RESTORE_YY_MORE_OFFSET

+/*

+//

+// Copyright (c) 2002-2011 The ANGLE Project Authors. All rights reserved.

+// Use of this source code is governed by a BSD-style license that can be

+// found in the LICENSE file.

+//

+

+This file contains the Lex specification for GLSL ES preprocessor.

+Based on Microsoft Visual Studio 2010 Preprocessor Grammar:

+http://msdn.microsoft.com/en-us/library/2scxys89.aspx

+

+IF YOU MODIFY THIS FILE YOU ALSO NEED TO RUN generate_parser.sh.

+*/

+

+#include "Tokenizer.h"

+

+#include "Diagnostics.h"

+#include "Token.h"

+

+#if defined(__GNUC__)

+// Triggered by the auto-generated yy_fatal_error function.

+#pragma GCC diagnostic ignored "-Wmissing-noreturn"

+#endif

+

+typedef std::string YYSTYPE;

+typedef pp::SourceLocation YYLTYPE;

+

+// Use the unused yycolumn variable to track file (string) number.

+#define yyfileno yycolumn

+

+#define YY_USER_INIT                   \

+    do {                               \

+        yyfileno = 0;                  \

+        yylineno = 1;                  \

+        yyextra->leadingSpace = false; \

+        yyextra->lineStart = true;     \

+    } while(0);

+

+#define YY_USER_ACTION                                              \

+    do                                                              \

+    {                                                               \

+        pp::Input* input = &yyextra->input;                         \

+        pp::Input::Location* scanLoc = &yyextra->scanLoc;           \

+        while ((scanLoc->sIndex < input->count()) &&                \

+               (scanLoc->cIndex >= input->length(scanLoc->sIndex))) \

+        {                                                           \

+            scanLoc->cIndex -= input->length(scanLoc->sIndex++);    \

+            ++yyfileno; yylineno = 1;                               \

+        }                                                           \

+        yylloc->file = yyfileno;                                    \

+        yylloc->line = yylineno;                                    \

+        scanLoc->cIndex += yyleng;                                  \

+    } while(0);

+

+#define YY_INPUT(buf, result, maxSize) \

+    result = yyextra->input.read(buf, maxSize);

+

+#define INITIAL 0

+#define COMMENT 1

+

+#define YY_EXTRA_TYPE pp::Tokenizer::Context*

+

+/* Holds the entire state of the reentrant scanner. */

+struct yyguts_t

+    {

+

+    /* User-defined. Not touched by flex. */

+    YY_EXTRA_TYPE yyextra_r;

+

+    /* The rest are the same as the globals declared in the non-reentrant scanner. */

+    FILE *yyin_r, *yyout_r;

+    size_t yy_buffer_stack_top; /**< index of top of stack. */

+    size_t yy_buffer_stack_max; /**< capacity of stack. */

+    YY_BUFFER_STATE * yy_buffer_stack; /**< Stack as an array. */

+    char yy_hold_char;

+    int yy_n_chars;

+    int yyleng_r;

+    char *yy_c_buf_p;

+    int yy_init;

+    int yy_start;

+    int yy_did_buffer_switch_on_eof;

+    int yy_start_stack_ptr;

+    int yy_start_stack_depth;

+    int *yy_start_stack;

+    yy_state_type yy_last_accepting_state;

+    char* yy_last_accepting_cpos;

+

+    int yylineno_r;

+    int yy_flex_debug_r;

+

+    char *yytext_r;

+    int yy_more_flag;

+    int yy_more_len;

+

+    YYSTYPE * yylval_r;

+

+    YYLTYPE * yylloc_r;

+

+    }; /* end struct yyguts_t */

+

+static int yy_init_globals (yyscan_t yyscanner );

+

+    /* This must go here because YYSTYPE and YYLTYPE are included

+     * from bison output in section 1.*/

+    #    define yylval yyg->yylval_r

+    

+    #    define yylloc yyg->yylloc_r

+    

+int pplex_init (yyscan_t* scanner);

+

+int pplex_init_extra (YY_EXTRA_TYPE user_defined,yyscan_t* scanner);

+

+/* Accessor methods to globals.

+   These are made visible to non-reentrant scanners for convenience. */

+

+int pplex_destroy (yyscan_t yyscanner );

+

+int ppget_debug (yyscan_t yyscanner );

+

+void ppset_debug (int debug_flag ,yyscan_t yyscanner );

+

+YY_EXTRA_TYPE ppget_extra (yyscan_t yyscanner );

+

+void ppset_extra (YY_EXTRA_TYPE user_defined ,yyscan_t yyscanner );

+

+FILE *ppget_in (yyscan_t yyscanner );

+

+void ppset_in  (FILE * in_str ,yyscan_t yyscanner );

+

+FILE *ppget_out (yyscan_t yyscanner );

+

+void ppset_out  (FILE * out_str ,yyscan_t yyscanner );

+

+int ppget_leng (yyscan_t yyscanner );

+

+char *ppget_text (yyscan_t yyscanner );

+

+int ppget_lineno (yyscan_t yyscanner );

+

+void ppset_lineno (int line_number ,yyscan_t yyscanner );

+

+YYSTYPE * ppget_lval (yyscan_t yyscanner );

+

+void ppset_lval (YYSTYPE * yylval_param ,yyscan_t yyscanner );

+

+       YYLTYPE *ppget_lloc (yyscan_t yyscanner );

+    

+        void ppset_lloc (YYLTYPE * yylloc_param ,yyscan_t yyscanner );

+    

+/* Macros after this point can all be overridden by user definitions in

+ * section 1.

+ */

+

+#ifndef YY_SKIP_YYWRAP

+#ifdef __cplusplus

+extern "C" int ppwrap (yyscan_t yyscanner );

+#else

+extern int ppwrap (yyscan_t yyscanner );

+#endif

+#endif

+

+#ifndef yytext_ptr

+static void yy_flex_strncpy (char *,yyconst char *,int ,yyscan_t yyscanner);

+#endif

+

+#ifdef YY_NEED_STRLEN

+static int yy_flex_strlen (yyconst char * ,yyscan_t yyscanner);

+#endif

+

+#ifndef YY_NO_INPUT

+

+#ifdef __cplusplus

+static int yyinput (yyscan_t yyscanner );

+#else

+static int input (yyscan_t yyscanner );

+#endif

+

+#endif

+

+/* Amount of stuff to slurp up with each read. */

+#ifndef YY_READ_BUF_SIZE

+#ifdef __ia64__

+/* On IA-64, the buffer size is 16k, not 8k */

+#define YY_READ_BUF_SIZE 16384

+#else

+#define YY_READ_BUF_SIZE 8192

+#endif /* __ia64__ */

+#endif

+

+/* Copy whatever the last rule matched to the standard output. */

+#ifndef ECHO

+/* This used to be an fputs(), but since the string might contain NUL's,

+ * we now use fwrite().

+ */

+#define ECHO do { if (fwrite( yytext, yyleng, 1, yyout )) {} } while (0)

+#endif

+

+/* Gets input and stuffs it into "buf".  number of characters read, or YY_NULL,

+ * is returned in "result".

+ */

+#ifndef YY_INPUT

+#define YY_INPUT(buf,result,max_size) \

+	if ( YY_CURRENT_BUFFER_LVALUE->yy_is_interactive ) \

+		{ \

+		int c = '*'; \

+		size_t n; \

+		for ( n = 0; n < max_size && \

+			     (c = getc( yyin )) != EOF && c != '\n'; ++n ) \

+			buf[n] = (char) c; \

+		if ( c == '\n' ) \

+			buf[n++] = (char) c; \

+		if ( c == EOF && ferror( yyin ) ) \

+			YY_FATAL_ERROR( "input in flex scanner failed" ); \

+		result = n; \

+		} \

+	else \

+		{ \

+		errno=0; \

+		while ( (result = fread(buf, 1, max_size, yyin))==0 && ferror(yyin)) \

+			{ \

+			if( errno != EINTR) \

+				{ \

+				YY_FATAL_ERROR( "input in flex scanner failed" ); \

+				break; \

+				} \

+			errno=0; \

+			clearerr(yyin); \

+			} \

+		}\

+\

+

+#endif

+

+/* No semi-colon after return; correct usage is to write "yyterminate();" -

+ * we don't want an extra ';' after the "return" because that will cause

+ * some compilers to complain about unreachable statements.

+ */

+#ifndef yyterminate

+#define yyterminate() return YY_NULL

+#endif

+

+/* Number of entries by which start-condition stack grows. */

+#ifndef YY_START_STACK_INCR

+#define YY_START_STACK_INCR 25

+#endif

+

+/* Report a fatal error. */

+#ifndef YY_FATAL_ERROR

+#define YY_FATAL_ERROR(msg) yy_fatal_error( msg , yyscanner)

+#endif

+

+/* end tables serialization structures and prototypes */

+

+/* Default declaration of generated scanner - a define so the user can

+ * easily add parameters.

+ */

+#ifndef YY_DECL

+#define YY_DECL_IS_OURS 1

+

+extern int pplex \

+               (YYSTYPE * yylval_param,YYLTYPE * yylloc_param ,yyscan_t yyscanner);

+

+#define YY_DECL int pplex \

+               (YYSTYPE * yylval_param, YYLTYPE * yylloc_param , yyscan_t yyscanner)

+#endif /* !YY_DECL */

+

+/* Code executed at the beginning of each rule, after yytext and yyleng

+ * have been set up.

+ */

+#ifndef YY_USER_ACTION

+#define YY_USER_ACTION

+#endif

+

+/* Code executed at the end of each rule. */

+#ifndef YY_BREAK

+#define YY_BREAK break;

+#endif

+

+#define YY_RULE_SETUP \

+	YY_USER_ACTION

+

+/** The main scanner function which does all the work.

+ */

+YY_DECL

+{

+	register yy_state_type yy_current_state;

+	register char *yy_cp, *yy_bp;

+	register int yy_act;

+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;

+

+    /* Line comment */

+

+    yylval = yylval_param;

+

+    yylloc = yylloc_param;

+

+	if ( !yyg->yy_init )

+		{

+		yyg->yy_init = 1;

+

+#ifdef YY_USER_INIT

+		YY_USER_INIT;

+#endif

+

+		if ( ! yyg->yy_start )

+			yyg->yy_start = 1;	/* first start state */

+

+		if ( ! yyin )

+			yyin = stdin;

+

+		if ( ! yyout )

+			yyout = stdout;

+

+		if ( ! YY_CURRENT_BUFFER ) {

+			ppensure_buffer_stack (yyscanner);

+			YY_CURRENT_BUFFER_LVALUE =

+				pp_create_buffer(yyin,YY_BUF_SIZE ,yyscanner);

+		}

+

+		pp_load_buffer_state(yyscanner );

+		}

+

+	while ( 1 )		/* loops until end-of-file is reached */

+		{

+		yy_cp = yyg->yy_c_buf_p;

+

+		/* Support of yytext. */

+		*yy_cp = yyg->yy_hold_char;

+

+		/* yy_bp points to the position in yy_ch_buf of the start of

+		 * the current run.

+		 */

+		yy_bp = yy_cp;

+

+		yy_current_state = yyg->yy_start;

+yy_match:

+		do

+			{

+			register YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)];

+			if ( yy_accept[yy_current_state] )

+				{

+				yyg->yy_last_accepting_state = yy_current_state;

+				yyg->yy_last_accepting_cpos = yy_cp;

+				}

+			while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )

+				{

+				yy_current_state = (int) yy_def[yy_current_state];

+				if ( yy_current_state >= 84 )

+					yy_c = yy_meta[(unsigned int) yy_c];

+				}

+			yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];

+			++yy_cp;

+			}

+		while ( yy_current_state != 83 );

+		yy_cp = yyg->yy_last_accepting_cpos;

+		yy_current_state = yyg->yy_last_accepting_state;

+

+yy_find_action:

+		yy_act = yy_accept[yy_current_state];

+

+		YY_DO_BEFORE_ACTION;

+

+do_action:	/* This label is used only to access EOF actions. */

+

+		switch ( yy_act )

+	{ /* beginning of action switch */

+			case 0: /* must back up */

+			/* undo the effects of YY_DO_BEFORE_ACTION */

+			*yy_cp = yyg->yy_hold_char;

+			yy_cp = yyg->yy_last_accepting_cpos;

+			yy_current_state = yyg->yy_last_accepting_state;

+			goto yy_find_action;

+

+case 1:

+YY_RULE_SETUP

+

+	YY_BREAK

+/* Block comment */

+/* Line breaks are just counted - not returned. */

+/* The comment is replaced by a single space. */ 

+case 2:

+YY_RULE_SETUP

+{ BEGIN(COMMENT); }

+	YY_BREAK

+case 3:

+YY_RULE_SETUP

+

+	YY_BREAK

+case 4:

+YY_RULE_SETUP

+

+	YY_BREAK

+case 5:

+/* rule 5 can match eol */

+YY_RULE_SETUP

+{ ++yylineno; }

+	YY_BREAK

+case 6:

+YY_RULE_SETUP

+{

+    yyextra->leadingSpace = true;

+    BEGIN(INITIAL);

+}

+	YY_BREAK

+case 7:

+YY_RULE_SETUP

+{

+    // # is only valid at start of line for preprocessor directives.

+    yylval->assign(1, yytext[0]);

+    return yyextra->lineStart ? pp::Token::PP_HASH : pp::Token::PP_OTHER;

+}

+	YY_BREAK

+case 8:

+YY_RULE_SETUP

+{

+    yylval->assign(yytext, yyleng);

+    return pp::Token::IDENTIFIER;

+}

+	YY_BREAK

+case 9:

+YY_RULE_SETUP

+{

+    yylval->assign(yytext, yyleng);

+    return pp::Token::CONST_INT;

+}

+	YY_BREAK

+case 10:

+YY_RULE_SETUP

+{

+    yylval->assign(yytext, yyleng);

+    return pp::Token::CONST_FLOAT;

+}

+	YY_BREAK

+/* Anything that starts with a {DIGIT} or .{DIGIT} must be a number. */

+/* Rule to catch all invalid integers and floats. */

+case 11:

+YY_RULE_SETUP

+{

+    yylval->assign(yytext, yyleng);

+    return pp::Token::PP_NUMBER;

+}

+	YY_BREAK

+case 12:

+YY_RULE_SETUP

+{

+    yylval->assign(yytext, yyleng);

+    return pp::Token::OP_INC;

+}

+	YY_BREAK

+case 13:

+YY_RULE_SETUP

+{

+    yylval->assign(yytext, yyleng);

+    return pp::Token::OP_DEC;

+}

+	YY_BREAK

+case 14:

+YY_RULE_SETUP

+{

+    yylval->assign(yytext, yyleng);

+    return pp::Token::OP_LEFT;

+}

+	YY_BREAK

+case 15:

+YY_RULE_SETUP

+{

+    yylval->assign(yytext, yyleng);

+    return pp::Token::OP_RIGHT;

+}

+	YY_BREAK

+case 16:

+YY_RULE_SETUP

+{

+    yylval->assign(yytext, yyleng);

+    return pp::Token::OP_LE;

+}

+	YY_BREAK

+case 17:

+YY_RULE_SETUP

+{

+    yylval->assign(yytext, yyleng);

+    return pp::Token::OP_GE;

+}

+	YY_BREAK

+case 18:

+YY_RULE_SETUP

+{

+    yylval->assign(yytext, yyleng);

+    return pp::Token::OP_EQ;

+}

+	YY_BREAK

+case 19:

+YY_RULE_SETUP

+{

+    yylval->assign(yytext, yyleng);

+    return pp::Token::OP_NE;

+}

+	YY_BREAK

+case 20:

+YY_RULE_SETUP

+{

+    yylval->assign(yytext, yyleng);

+    return pp::Token::OP_AND;

+}

+	YY_BREAK

+case 21:

+YY_RULE_SETUP

+{

+    yylval->assign(yytext, yyleng);

+    return pp::Token::OP_XOR;

+}

+	YY_BREAK

+case 22:

+YY_RULE_SETUP

+{

+    yylval->assign(yytext, yyleng);

+    return pp::Token::OP_OR;

+}

+	YY_BREAK

+case 23:

+YY_RULE_SETUP

+{

+    yylval->assign(yytext, yyleng);

+    return pp::Token::OP_ADD_ASSIGN;

+}

+	YY_BREAK

+case 24:

+YY_RULE_SETUP

+{

+    yylval->assign(yytext, yyleng);

+    return pp::Token::OP_SUB_ASSIGN;

+}

+	YY_BREAK

+case 25:

+YY_RULE_SETUP

+{

+    yylval->assign(yytext, yyleng);

+    return pp::Token::OP_MUL_ASSIGN;

+}

+	YY_BREAK

+case 26:

+YY_RULE_SETUP

+{

+    yylval->assign(yytext, yyleng);

+    return pp::Token::OP_DIV_ASSIGN;

+}

+	YY_BREAK

+case 27:

+YY_RULE_SETUP

+{

+    yylval->assign(yytext, yyleng);

+    return pp::Token::OP_MOD_ASSIGN;

+}

+	YY_BREAK

+case 28:

+YY_RULE_SETUP

+{

+    yylval->assign(yytext, yyleng);

+    return pp::Token::OP_LEFT_ASSIGN;

+}

+	YY_BREAK

+case 29:

+YY_RULE_SETUP

+{

+    yylval->assign(yytext, yyleng);

+    return pp::Token::OP_RIGHT_ASSIGN;

+}

+	YY_BREAK

+case 30:

+YY_RULE_SETUP

+{

+    yylval->assign(yytext, yyleng);

+    return pp::Token::OP_AND_ASSIGN;

+}

+	YY_BREAK

+case 31:

+YY_RULE_SETUP

+{

+    yylval->assign(yytext, yyleng);

+    return pp::Token::OP_XOR_ASSIGN;

+}

+	YY_BREAK

+case 32:

+YY_RULE_SETUP

+{

+    yylval->assign(yytext, yyleng);

+    return pp::Token::OP_OR_ASSIGN;

+}

+	YY_BREAK

+case 33:

+YY_RULE_SETUP

+{

+    yylval->assign(1, yytext[0]);

+    return yytext[0];

+}

+	YY_BREAK

+case 34:

+YY_RULE_SETUP

+{ yyextra->leadingSpace = true; }

+	YY_BREAK

+case 35:

+/* rule 35 can match eol */

+YY_RULE_SETUP

+{

+    ++yylineno;

+    yylval->assign(1, '\n');

+    return '\n';

+}

+	YY_BREAK

+case 36:

+YY_RULE_SETUP

+{

+    yylval->assign(1, yytext[0]);

+    return pp::Token::PP_OTHER;

+}

+	YY_BREAK

+case YY_STATE_EOF(INITIAL):

+case YY_STATE_EOF(COMMENT):

+{

+    // YY_USER_ACTION is not invoked for handling EOF.

+    // Set the location for EOF token manually.

+    pp::Input* input = &yyextra->input;

+    pp::Input::Location* scanLoc = &yyextra->scanLoc;

+    int sIndexMax = std::max(0, input->count() - 1);

+    if (scanLoc->sIndex != sIndexMax)

+    {

+        // We can only reach here if there are empty strings at the

+        // end of the input.

+        scanLoc->sIndex = sIndexMax; scanLoc->cIndex = 0;

+        yyfileno = sIndexMax; yylineno = 1;

+    }

+    yylloc->file = yyfileno;

+    yylloc->line = yylineno;

+    yylval->clear();

+

+    if (YY_START == COMMENT)

+    {

+        yyextra->diagnostics->report(pp::Diagnostics::EOF_IN_COMMENT,

+                                     pp::SourceLocation(yyfileno, yylineno),

+                                     "");

+    }

+    yyterminate();

+}

+	YY_BREAK

+case 37:

+YY_RULE_SETUP

+ECHO;

+	YY_BREAK

+

+	case YY_END_OF_BUFFER:

+		{

+		/* Amount of text matched not including the EOB char. */

+		int yy_amount_of_matched_text = (int) (yy_cp - yyg->yytext_ptr) - 1;

+

+		/* Undo the effects of YY_DO_BEFORE_ACTION. */

+		*yy_cp = yyg->yy_hold_char;

+		YY_RESTORE_YY_MORE_OFFSET

+

+		if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_NEW )

+			{

+			/* We're scanning a new file or input source.  It's

+			 * possible that this happened because the user

+			 * just pointed yyin at a new source and called

+			 * pplex().  If so, then we have to assure

+			 * consistency between YY_CURRENT_BUFFER and our

+			 * globals.  Here is the right place to do so, because

+			 * this is the first action (other than possibly a

+			 * back-up) that will match for the new input source.

+			 */

+			yyg->yy_n_chars = YY_CURRENT_BUFFER_LVALUE->yy_n_chars;

+			YY_CURRENT_BUFFER_LVALUE->yy_input_file = yyin;

+			YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = YY_BUFFER_NORMAL;

+			}

+

+		/* Note that here we test for yy_c_buf_p "<=" to the position

+		 * of the first EOB in the buffer, since yy_c_buf_p will

+		 * already have been incremented past the NUL character

+		 * (since all states make transitions on EOB to the

+		 * end-of-buffer state).  Contrast this with the test

+		 * in input().

+		 */

+		if ( yyg->yy_c_buf_p <= &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars] )

+			{ /* This was really a NUL. */

+			yy_state_type yy_next_state;

+

+			yyg->yy_c_buf_p = yyg->yytext_ptr + yy_amount_of_matched_text;

+

+			yy_current_state = yy_get_previous_state( yyscanner );

+

+			/* Okay, we're now positioned to make the NUL

+			 * transition.  We couldn't have

+			 * yy_get_previous_state() go ahead and do it

+			 * for us because it doesn't know how to deal

+			 * with the possibility of jamming (and we don't

+			 * want to build jamming into it because then it

+			 * will run more slowly).

+			 */

+

+			yy_next_state = yy_try_NUL_trans( yy_current_state , yyscanner);

+

+			yy_bp = yyg->yytext_ptr + YY_MORE_ADJ;

+

+			if ( yy_next_state )

+				{

+				/* Consume the NUL. */

+				yy_cp = ++yyg->yy_c_buf_p;

+				yy_current_state = yy_next_state;

+				goto yy_match;

+				}

+

+			else

+				{

+				yy_cp = yyg->yy_last_accepting_cpos;

+				yy_current_state = yyg->yy_last_accepting_state;

+				goto yy_find_action;

+				}

+			}

+

+		else switch ( yy_get_next_buffer( yyscanner ) )

+			{

+			case EOB_ACT_END_OF_FILE:

+				{

+				yyg->yy_did_buffer_switch_on_eof = 0;

+

+				if ( ppwrap(yyscanner ) )

+					{

+					/* Note: because we've taken care in

+					 * yy_get_next_buffer() to have set up

+					 * yytext, we can now set up

+					 * yy_c_buf_p so that if some total

+					 * hoser (like flex itself) wants to

+					 * call the scanner after we return the

+					 * YY_NULL, it'll still work - another

+					 * YY_NULL will get returned.

+					 */

+					yyg->yy_c_buf_p = yyg->yytext_ptr + YY_MORE_ADJ;

+

+					yy_act = YY_STATE_EOF(YY_START);

+					goto do_action;

+					}

+

+				else

+					{

+					if ( ! yyg->yy_did_buffer_switch_on_eof )

+						YY_NEW_FILE;

+					}

+				break;

+				}

+

+			case EOB_ACT_CONTINUE_SCAN:

+				yyg->yy_c_buf_p =

+					yyg->yytext_ptr + yy_amount_of_matched_text;

+

+				yy_current_state = yy_get_previous_state( yyscanner );

+

+				yy_cp = yyg->yy_c_buf_p;

+				yy_bp = yyg->yytext_ptr + YY_MORE_ADJ;

+				goto yy_match;

+

+			case EOB_ACT_LAST_MATCH:

+				yyg->yy_c_buf_p =

+				&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars];

+

+				yy_current_state = yy_get_previous_state( yyscanner );

+

+				yy_cp = yyg->yy_c_buf_p;

+				yy_bp = yyg->yytext_ptr + YY_MORE_ADJ;

+				goto yy_find_action;

+			}

+		break;

+		}

+

+	default:

+		YY_FATAL_ERROR(

+			"fatal flex scanner internal error--no action found" );

+	} /* end of action switch */

+		} /* end of scanning one token */

+} /* end of pplex */

+

+/* yy_get_next_buffer - try to read in a new buffer

+ *

+ * Returns a code representing an action:

+ *	EOB_ACT_LAST_MATCH -

+ *	EOB_ACT_CONTINUE_SCAN - continue scanning from current position

+ *	EOB_ACT_END_OF_FILE - end of file

+ */

+static int yy_get_next_buffer (yyscan_t yyscanner)

+{

+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;

+	register char *dest = YY_CURRENT_BUFFER_LVALUE->yy_ch_buf;

+	register char *source = yyg->yytext_ptr;

+	register int number_to_move, i;

+	int ret_val;

+

+	if ( yyg->yy_c_buf_p > &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars + 1] )

+		YY_FATAL_ERROR(

+		"fatal flex scanner internal error--end of buffer missed" );

+

+	if ( YY_CURRENT_BUFFER_LVALUE->yy_fill_buffer == 0 )

+		{ /* Don't try to fill the buffer, so this is an EOF. */

+		if ( yyg->yy_c_buf_p - yyg->yytext_ptr - YY_MORE_ADJ == 1 )

+			{

+			/* We matched a single character, the EOB, so

+			 * treat this as a final EOF.

+			 */

+			return EOB_ACT_END_OF_FILE;

+			}

+

+		else

+			{

+			/* We matched some text prior to the EOB, first

+			 * process it.

+			 */

+			return EOB_ACT_LAST_MATCH;

+			}

+		}

+

+	/* Try to read more data. */

+

+	/* First move last chars to start of buffer. */

+	number_to_move = (int) (yyg->yy_c_buf_p - yyg->yytext_ptr) - 1;

+

+	for ( i = 0; i < number_to_move; ++i )

+		*(dest++) = *(source++);

+

+	if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_EOF_PENDING )

+		/* don't do the read, it's not guaranteed to return an EOF,

+		 * just force an EOF

+		 */

+		YY_CURRENT_BUFFER_LVALUE->yy_n_chars = yyg->yy_n_chars = 0;

+

+	else

+		{

+			int num_to_read =

+			YY_CURRENT_BUFFER_LVALUE->yy_buf_size - number_to_move - 1;

+

+		while ( num_to_read <= 0 )

+			{ /* Not enough room in the buffer - grow it. */

+

+			/* just a shorter name for the current buffer */

+			YY_BUFFER_STATE b = YY_CURRENT_BUFFER;

+

+			int yy_c_buf_p_offset =

+				(int) (yyg->yy_c_buf_p - b->yy_ch_buf);

+

+			if ( b->yy_is_our_buffer )

+				{

+				int new_size = b->yy_buf_size * 2;

+

+				if ( new_size <= 0 )

+					b->yy_buf_size += b->yy_buf_size / 8;

+				else

+					b->yy_buf_size *= 2;

+

+				b->yy_ch_buf = (char *)

+					/* Include room in for 2 EOB chars. */

+					pprealloc((void *) b->yy_ch_buf,b->yy_buf_size + 2 ,yyscanner );

+				}

+			else

+				/* Can't grow it, we don't own it. */

+				b->yy_ch_buf = 0;

+

+			if ( ! b->yy_ch_buf )

+				YY_FATAL_ERROR(

+				"fatal error - scanner input buffer overflow" );

+

+			yyg->yy_c_buf_p = &b->yy_ch_buf[yy_c_buf_p_offset];

+

+			num_to_read = YY_CURRENT_BUFFER_LVALUE->yy_buf_size -

+						number_to_move - 1;

+

+			}

+

+		if ( num_to_read > YY_READ_BUF_SIZE )

+			num_to_read = YY_READ_BUF_SIZE;

+

+		/* Read in more data. */

+		YY_INPUT( (&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]),

+			yyg->yy_n_chars, (size_t) num_to_read );

+

+		YY_CURRENT_BUFFER_LVALUE->yy_n_chars = yyg->yy_n_chars;

+		}

+

+	if ( yyg->yy_n_chars == 0 )

+		{

+		if ( number_to_move == YY_MORE_ADJ )

+			{

+			ret_val = EOB_ACT_END_OF_FILE;

+			pprestart(yyin  ,yyscanner);

+			}

+

+		else

+			{

+			ret_val = EOB_ACT_LAST_MATCH;

+			YY_CURRENT_BUFFER_LVALUE->yy_buffer_status =

+				YY_BUFFER_EOF_PENDING;

+			}

+		}

+

+	else

+		ret_val = EOB_ACT_CONTINUE_SCAN;

+

+	if ((yy_size_t) (yyg->yy_n_chars + number_to_move) > YY_CURRENT_BUFFER_LVALUE->yy_buf_size) {

+		/* Extend the array by 50%, plus the number we really need. */

+		yy_size_t new_size = yyg->yy_n_chars + number_to_move + (yyg->yy_n_chars >> 1);

+		YY_CURRENT_BUFFER_LVALUE->yy_ch_buf = (char *) pprealloc((void *) YY_CURRENT_BUFFER_LVALUE->yy_ch_buf,new_size ,yyscanner );

+		if ( ! YY_CURRENT_BUFFER_LVALUE->yy_ch_buf )

+			YY_FATAL_ERROR( "out of dynamic memory in yy_get_next_buffer()" );

+	}

+

+	yyg->yy_n_chars += number_to_move;

+	YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars] = YY_END_OF_BUFFER_CHAR;

+	YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars + 1] = YY_END_OF_BUFFER_CHAR;

+

+	yyg->yytext_ptr = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[0];

+

+	return ret_val;

+}

+

+/* yy_get_previous_state - get the state just before the EOB char was reached */

+

+    static yy_state_type yy_get_previous_state (yyscan_t yyscanner)

+{

+	register yy_state_type yy_current_state;

+	register char *yy_cp;

+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;

+

+	yy_current_state = yyg->yy_start;

+

+	for ( yy_cp = yyg->yytext_ptr + YY_MORE_ADJ; yy_cp < yyg->yy_c_buf_p; ++yy_cp )

+		{

+		register YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1);

+		if ( yy_accept[yy_current_state] )

+			{

+			yyg->yy_last_accepting_state = yy_current_state;

+			yyg->yy_last_accepting_cpos = yy_cp;

+			}

+		while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )

+			{

+			yy_current_state = (int) yy_def[yy_current_state];

+			if ( yy_current_state >= 84 )

+				yy_c = yy_meta[(unsigned int) yy_c];

+			}

+		yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];

+		}

+

+	return yy_current_state;

+}

+

+/* yy_try_NUL_trans - try to make a transition on the NUL character

+ *

+ * synopsis

+ *	next_state = yy_try_NUL_trans( current_state );

+ */

+    static yy_state_type yy_try_NUL_trans  (yy_state_type yy_current_state , yyscan_t yyscanner)

+{

+	register int yy_is_jam;

+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; /* This var may be unused depending upon options. */

+	register char *yy_cp = yyg->yy_c_buf_p;

+

+	register YY_CHAR yy_c = 1;

+	if ( yy_accept[yy_current_state] )

+		{

+		yyg->yy_last_accepting_state = yy_current_state;

+		yyg->yy_last_accepting_cpos = yy_cp;

+		}

+	while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )

+		{

+		yy_current_state = (int) yy_def[yy_current_state];

+		if ( yy_current_state >= 84 )

+			yy_c = yy_meta[(unsigned int) yy_c];

+		}

+	yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];

+	yy_is_jam = (yy_current_state == 83);

+

+	return yy_is_jam ? 0 : yy_current_state;

+}

+

+#ifndef YY_NO_INPUT

+#ifdef __cplusplus

+    static int yyinput (yyscan_t yyscanner)

+#else

+    static int input  (yyscan_t yyscanner)

+#endif

+

+{

+	int c;

+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;

+

+	*yyg->yy_c_buf_p = yyg->yy_hold_char;

+

+	if ( *yyg->yy_c_buf_p == YY_END_OF_BUFFER_CHAR )

+		{

+		/* yy_c_buf_p now points to the character we want to return.

+		 * If this occurs *before* the EOB characters, then it's a

+		 * valid NUL; if not, then we've hit the end of the buffer.

+		 */

+		if ( yyg->yy_c_buf_p < &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars] )

+			/* This was really a NUL. */

+			*yyg->yy_c_buf_p = '\0';

+

+		else

+			{ /* need more input */

+			int offset = yyg->yy_c_buf_p - yyg->yytext_ptr;

+			++yyg->yy_c_buf_p;

+

+			switch ( yy_get_next_buffer( yyscanner ) )

+				{

+				case EOB_ACT_LAST_MATCH:

+					/* This happens because yy_g_n_b()

+					 * sees that we've accumulated a

+					 * token and flags that we need to

+					 * try matching the token before

+					 * proceeding.  But for input(),

+					 * there's no matching to consider.

+					 * So convert the EOB_ACT_LAST_MATCH

+					 * to EOB_ACT_END_OF_FILE.

+					 */

+

+					/* Reset buffer status. */

+					pprestart(yyin ,yyscanner);

+

+					/*FALLTHROUGH*/

+

+				case EOB_ACT_END_OF_FILE:

+					{

+					if ( ppwrap(yyscanner ) )

+						return EOF;

+

+					if ( ! yyg->yy_did_buffer_switch_on_eof )

+						YY_NEW_FILE;

+#ifdef __cplusplus

+					return yyinput(yyscanner);

+#else

+					return input(yyscanner);

+#endif

+					}

+

+				case EOB_ACT_CONTINUE_SCAN:

+					yyg->yy_c_buf_p = yyg->yytext_ptr + offset;

+					break;

+				}

+			}

+		}

+

+	c = *(unsigned char *) yyg->yy_c_buf_p;	/* cast for 8-bit char's */

+	*yyg->yy_c_buf_p = '\0';	/* preserve yytext */

+	yyg->yy_hold_char = *++yyg->yy_c_buf_p;

+

+	return c;

+}

+#endif	/* ifndef YY_NO_INPUT */

+

+/** Immediately switch to a different input stream.

+ * @param input_file A readable stream.

+ * @param yyscanner The scanner object.

+ * @note This function does not reset the start condition to @c INITIAL .

+ */

+    void pprestart  (FILE * input_file , yyscan_t yyscanner)

+{

+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;

+

+	if ( ! YY_CURRENT_BUFFER ){

+        ppensure_buffer_stack (yyscanner);

+		YY_CURRENT_BUFFER_LVALUE =

+            pp_create_buffer(yyin,YY_BUF_SIZE ,yyscanner);

+	}

+

+	pp_init_buffer(YY_CURRENT_BUFFER,input_file ,yyscanner);

+	pp_load_buffer_state(yyscanner );

+}

+

+/** Switch to a different input buffer.

+ * @param new_buffer The new input buffer.

+ * @param yyscanner The scanner object.

+ */

+    void pp_switch_to_buffer  (YY_BUFFER_STATE  new_buffer , yyscan_t yyscanner)

+{

+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;

+

+	/* TODO. We should be able to replace this entire function body

+	 * with

+	 *		pppop_buffer_state();

+	 *		pppush_buffer_state(new_buffer);

+     */

+	ppensure_buffer_stack (yyscanner);

+	if ( YY_CURRENT_BUFFER == new_buffer )

+		return;

+

+	if ( YY_CURRENT_BUFFER )

+		{

+		/* Flush out information for old buffer. */

+		*yyg->yy_c_buf_p = yyg->yy_hold_char;

+		YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = yyg->yy_c_buf_p;

+		YY_CURRENT_BUFFER_LVALUE->yy_n_chars = yyg->yy_n_chars;

+		}

+

+	YY_CURRENT_BUFFER_LVALUE = new_buffer;

+	pp_load_buffer_state(yyscanner );

+

+	/* We don't actually know whether we did this switch during

+	 * EOF (ppwrap()) processing, but the only time this flag

+	 * is looked at is after ppwrap() is called, so it's safe

+	 * to go ahead and always set it.

+	 */

+	yyg->yy_did_buffer_switch_on_eof = 1;

+}

+

+static void pp_load_buffer_state  (yyscan_t yyscanner)

+{

+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;

+	yyg->yy_n_chars = YY_CURRENT_BUFFER_LVALUE->yy_n_chars;

+	yyg->yytext_ptr = yyg->yy_c_buf_p = YY_CURRENT_BUFFER_LVALUE->yy_buf_pos;

+	yyin = YY_CURRENT_BUFFER_LVALUE->yy_input_file;

+	yyg->yy_hold_char = *yyg->yy_c_buf_p;

+}

+

+/** Allocate and initialize an input buffer state.

+ * @param file A readable stream.

+ * @param size The character buffer size in bytes. When in doubt, use @c YY_BUF_SIZE.

+ * @param yyscanner The scanner object.

+ * @return the allocated buffer state.

+ */

+    YY_BUFFER_STATE pp_create_buffer  (FILE * file, int  size , yyscan_t yyscanner)

+{

+	YY_BUFFER_STATE b;

+    

+	b = (YY_BUFFER_STATE) ppalloc(sizeof( struct yy_buffer_state ) ,yyscanner );

+	if ( ! b )

+		YY_FATAL_ERROR( "out of dynamic memory in pp_create_buffer()" );

+

+	b->yy_buf_size = size;

+

+	/* yy_ch_buf has to be 2 characters longer than the size given because

+	 * we need to put in 2 end-of-buffer characters.

+	 */

+	b->yy_ch_buf = (char *) ppalloc(b->yy_buf_size + 2 ,yyscanner );

+	if ( ! b->yy_ch_buf )

+		YY_FATAL_ERROR( "out of dynamic memory in pp_create_buffer()" );

+

+	b->yy_is_our_buffer = 1;

+

+	pp_init_buffer(b,file ,yyscanner);

+

+	return b;

+}

+

+/** Destroy the buffer.

+ * @param b a buffer created with pp_create_buffer()

+ * @param yyscanner The scanner object.

+ */

+    void pp_delete_buffer (YY_BUFFER_STATE  b , yyscan_t yyscanner)

+{

+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;

+

+	if ( ! b )

+		return;

+

+	if ( b == YY_CURRENT_BUFFER ) /* Not sure if we should pop here. */

+		YY_CURRENT_BUFFER_LVALUE = (YY_BUFFER_STATE) 0;

+

+	if ( b->yy_is_our_buffer )

+		ppfree((void *) b->yy_ch_buf ,yyscanner );

+

+	ppfree((void *) b ,yyscanner );

+}

+

+/* Initializes or reinitializes a buffer.

+ * This function is sometimes called more than once on the same buffer,

+ * such as during a pprestart() or at EOF.

+ */

+    static void pp_init_buffer  (YY_BUFFER_STATE  b, FILE * file , yyscan_t yyscanner)

+

+{

+	int oerrno = errno;

+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;

+

+	pp_flush_buffer(b ,yyscanner);

+

+	b->yy_input_file = file;

+	b->yy_fill_buffer = 1;

+

+    /* If b is the current buffer, then pp_init_buffer was _probably_

+     * called from pprestart() or through yy_get_next_buffer.

+     * In that case, we don't want to reset the lineno or column.

+     */

+    if (b != YY_CURRENT_BUFFER){

+        b->yy_bs_lineno = 1;

+        b->yy_bs_column = 0;

+    }

+

+        b->yy_is_interactive = 0;

+    

+	errno = oerrno;

+}

+

+/** Discard all buffered characters. On the next scan, YY_INPUT will be called.

+ * @param b the buffer state to be flushed, usually @c YY_CURRENT_BUFFER.

+ * @param yyscanner The scanner object.

+ */

+    void pp_flush_buffer (YY_BUFFER_STATE  b , yyscan_t yyscanner)

+{

+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;

+	if ( ! b )

+		return;

+

+	b->yy_n_chars = 0;

+

+	/* We always need two end-of-buffer characters.  The first causes

+	 * a transition to the end-of-buffer state.  The second causes

+	 * a jam in that state.

+	 */

+	b->yy_ch_buf[0] = YY_END_OF_BUFFER_CHAR;

+	b->yy_ch_buf[1] = YY_END_OF_BUFFER_CHAR;

+

+	b->yy_buf_pos = &b->yy_ch_buf[0];

+

+	b->yy_at_bol = 1;

+	b->yy_buffer_status = YY_BUFFER_NEW;

+

+	if ( b == YY_CURRENT_BUFFER )

+		pp_load_buffer_state(yyscanner );

+}

+

+/** Pushes the new state onto the stack. The new state becomes

+ *  the current state. This function will allocate the stack

+ *  if necessary.

+ *  @param new_buffer The new state.

+ *  @param yyscanner The scanner object.

+ */

+void pppush_buffer_state (YY_BUFFER_STATE new_buffer , yyscan_t yyscanner)

+{

+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;

+	if (new_buffer == NULL)

+		return;

+

+	ppensure_buffer_stack(yyscanner);

+

+	/* This block is copied from pp_switch_to_buffer. */

+	if ( YY_CURRENT_BUFFER )

+		{

+		/* Flush out information for old buffer. */

+		*yyg->yy_c_buf_p = yyg->yy_hold_char;

+		YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = yyg->yy_c_buf_p;

+		YY_CURRENT_BUFFER_LVALUE->yy_n_chars = yyg->yy_n_chars;

+		}

+

+	/* Only push if top exists. Otherwise, replace top. */

+	if (YY_CURRENT_BUFFER)

+		yyg->yy_buffer_stack_top++;

+	YY_CURRENT_BUFFER_LVALUE = new_buffer;

+

+	/* copied from pp_switch_to_buffer. */

+	pp_load_buffer_state(yyscanner );

+	yyg->yy_did_buffer_switch_on_eof = 1;

+}

+

+/** Removes and deletes the top of the stack, if present.

+ *  The next element becomes the new top.

+ *  @param yyscanner The scanner object.

+ */

+void pppop_buffer_state (yyscan_t yyscanner)

+{

+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;

+	if (!YY_CURRENT_BUFFER)

+		return;

+

+	pp_delete_buffer(YY_CURRENT_BUFFER ,yyscanner);

+	YY_CURRENT_BUFFER_LVALUE = NULL;

+	if (yyg->yy_buffer_stack_top > 0)

+		--yyg->yy_buffer_stack_top;

+

+	if (YY_CURRENT_BUFFER) {

+		pp_load_buffer_state(yyscanner );

+		yyg->yy_did_buffer_switch_on_eof = 1;

+	}

+}

+

+/* Allocates the stack if it does not exist.

+ *  Guarantees space for at least one push.

+ */

+static void ppensure_buffer_stack (yyscan_t yyscanner)

+{

+	int num_to_alloc;

+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;

+

+	if (!yyg->yy_buffer_stack) {

+

+		/* First allocation is just for 2 elements, since we don't know if this

+		 * scanner will even need a stack. We use 2 instead of 1 to avoid an

+		 * immediate realloc on the next call.

+         */

+		num_to_alloc = 1;

+		yyg->yy_buffer_stack = (struct yy_buffer_state**)ppalloc

+								(num_to_alloc * sizeof(struct yy_buffer_state*)

+								, yyscanner);

+		if ( ! yyg->yy_buffer_stack )

+			YY_FATAL_ERROR( "out of dynamic memory in ppensure_buffer_stack()" );

+								  

+		memset(yyg->yy_buffer_stack, 0, num_to_alloc * sizeof(struct yy_buffer_state*));

+				

+		yyg->yy_buffer_stack_max = num_to_alloc;

+		yyg->yy_buffer_stack_top = 0;

+		return;

+	}

+

+	if (yyg->yy_buffer_stack_top >= (yyg->yy_buffer_stack_max) - 1){

+

+		/* Increase the buffer to prepare for a possible push. */

+		int grow_size = 8 /* arbitrary grow size */;

+

+		num_to_alloc = yyg->yy_buffer_stack_max + grow_size;

+		yyg->yy_buffer_stack = (struct yy_buffer_state**)pprealloc

+								(yyg->yy_buffer_stack,

+								num_to_alloc * sizeof(struct yy_buffer_state*)

+								, yyscanner);

+		if ( ! yyg->yy_buffer_stack )

+			YY_FATAL_ERROR( "out of dynamic memory in ppensure_buffer_stack()" );

+

+		/* zero only the new slots.*/

+		memset(yyg->yy_buffer_stack + yyg->yy_buffer_stack_max, 0, grow_size * sizeof(struct yy_buffer_state*));

+		yyg->yy_buffer_stack_max = num_to_alloc;

+	}

+}

+

+/** Setup the input buffer state to scan directly from a user-specified character buffer.

+ * @param base the character buffer

+ * @param size the size in bytes of the character buffer

+ * @param yyscanner The scanner object.

+ * @return the newly allocated buffer state object. 

+ */

+YY_BUFFER_STATE pp_scan_buffer  (char * base, yy_size_t  size , yyscan_t yyscanner)

+{

+	YY_BUFFER_STATE b;

+    

+	if ( size < 2 ||

+	     base[size-2] != YY_END_OF_BUFFER_CHAR ||

+	     base[size-1] != YY_END_OF_BUFFER_CHAR )

+		/* They forgot to leave room for the EOB's. */

+		return 0;

+

+	b = (YY_BUFFER_STATE) ppalloc(sizeof( struct yy_buffer_state ) ,yyscanner );

+	if ( ! b )

+		YY_FATAL_ERROR( "out of dynamic memory in pp_scan_buffer()" );

+

+	b->yy_buf_size = size - 2;	/* "- 2" to take care of EOB's */

+	b->yy_buf_pos = b->yy_ch_buf = base;

+	b->yy_is_our_buffer = 0;

+	b->yy_input_file = 0;

+	b->yy_n_chars = b->yy_buf_size;

+	b->yy_is_interactive = 0;

+	b->yy_at_bol = 1;

+	b->yy_fill_buffer = 0;

+	b->yy_buffer_status = YY_BUFFER_NEW;

+

+	pp_switch_to_buffer(b ,yyscanner );

+

+	return b;

+}

+

+/** Setup the input buffer state to scan a string. The next call to pplex() will

+ * scan from a @e copy of @a str.

+ * @param yystr a NUL-terminated string to scan

+ * @param yyscanner The scanner object.

+ * @return the newly allocated buffer state object.

+ * @note If you want to scan bytes that may contain NUL values, then use

+ *       pp_scan_bytes() instead.

+ */

+YY_BUFFER_STATE pp_scan_string (yyconst char * yystr , yyscan_t yyscanner)

+{

+    

+	return pp_scan_bytes(yystr,strlen(yystr) ,yyscanner);

+}

+

+/** Setup the input buffer state to scan the given bytes. The next call to pplex() will

+ * scan from a @e copy of @a bytes.

+ * @param yybytes the byte buffer to scan

+ * @param _yybytes_len the number of bytes in the buffer pointed to by @a bytes.

+ * @param yyscanner The scanner object.

+ * @return the newly allocated buffer state object.

+ */

+YY_BUFFER_STATE pp_scan_bytes  (yyconst char * yybytes, int  _yybytes_len , yyscan_t yyscanner)

+{

+	YY_BUFFER_STATE b;

+	char *buf;

+	yy_size_t n;

+	int i;

+    

+	/* Get memory for full buffer, including space for trailing EOB's. */

+	n = _yybytes_len + 2;

+	buf = (char *) ppalloc(n ,yyscanner );

+	if ( ! buf )

+		YY_FATAL_ERROR( "out of dynamic memory in pp_scan_bytes()" );

+

+	for ( i = 0; i < _yybytes_len; ++i )

+		buf[i] = yybytes[i];

+

+	buf[_yybytes_len] = buf[_yybytes_len+1] = YY_END_OF_BUFFER_CHAR;

+

+	b = pp_scan_buffer(buf,n ,yyscanner);

+	if ( ! b )

+		YY_FATAL_ERROR( "bad buffer in pp_scan_bytes()" );

+

+	/* It's okay to grow etc. this buffer, and we should throw it

+	 * away when we're done.

+	 */

+	b->yy_is_our_buffer = 1;

+

+	return b;

+}

+

+#ifndef YY_EXIT_FAILURE

+#define YY_EXIT_FAILURE 2

+#endif

+

+static void yy_fatal_error (yyconst char* msg , yyscan_t yyscanner)

+{

+    	(void) fprintf( stderr, "%s\n", msg );

+	exit( YY_EXIT_FAILURE );

+}

+

+/* Redefine yyless() so it works in section 3 code. */

+

+#undef yyless

+#define yyless(n) \

+	do \

+		{ \

+		/* Undo effects of setting up yytext. */ \

+        int yyless_macro_arg = (n); \

+        YY_LESS_LINENO(yyless_macro_arg);\

+		yytext[yyleng] = yyg->yy_hold_char; \

+		yyg->yy_c_buf_p = yytext + yyless_macro_arg; \

+		yyg->yy_hold_char = *yyg->yy_c_buf_p; \

+		*yyg->yy_c_buf_p = '\0'; \

+		yyleng = yyless_macro_arg; \

+		} \

+	while ( 0 )

+

+/* Accessor  methods (get/set functions) to struct members. */

+

+/** Get the user-defined data for this scanner.

+ * @param yyscanner The scanner object.

+ */

+YY_EXTRA_TYPE ppget_extra  (yyscan_t yyscanner)

+{

+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;

+    return yyextra;

+}

+

+/** Get the current line number.

+ * @param yyscanner The scanner object.

+ */

+int ppget_lineno  (yyscan_t yyscanner)

+{

+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;

+    

+        if (! YY_CURRENT_BUFFER)

+            return 0;

+    

+    return yylineno;

+}

+

+/** Get the current column number.

+ * @param yyscanner The scanner object.

+ */

+int ppget_column  (yyscan_t yyscanner)

+{

+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;

+    

+        if (! YY_CURRENT_BUFFER)

+            return 0;

+    

+    return yycolumn;

+}

+

+/** Get the input stream.

+ * @param yyscanner The scanner object.

+ */

+FILE *ppget_in  (yyscan_t yyscanner)

+{

+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;

+    return yyin;

+}

+

+/** Get the output stream.

+ * @param yyscanner The scanner object.

+ */

+FILE *ppget_out  (yyscan_t yyscanner)

+{

+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;

+    return yyout;

+}

+

+/** Get the length of the current token.

+ * @param yyscanner The scanner object.

+ */

+int ppget_leng  (yyscan_t yyscanner)

+{

+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;

+    return yyleng;

+}

+

+/** Get the current token.

+ * @param yyscanner The scanner object.

+ */

+

+char *ppget_text  (yyscan_t yyscanner)

+{

+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;

+    return yytext;

+}

+

+/** Set the user-defined data. This data is never touched by the scanner.

+ * @param user_defined The data to be associated with this scanner.

+ * @param yyscanner The scanner object.

+ */

+void ppset_extra (YY_EXTRA_TYPE  user_defined , yyscan_t yyscanner)

+{

+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;

+    yyextra = user_defined ;

+}

+

+/** Set the current line number.

+ * @param line_number

+ * @param yyscanner The scanner object.

+ */

+void ppset_lineno (int  line_number , yyscan_t yyscanner)

+{

+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;

+

+        /* lineno is only valid if an input buffer exists. */

+        if (! YY_CURRENT_BUFFER )

+           yy_fatal_error( "ppset_lineno called with no buffer" , yyscanner); 

+    

+    yylineno = line_number;

+}

+

+/** Set the current column.

+ * @param line_number

+ * @param yyscanner The scanner object.

+ */

+void ppset_column (int  column_no , yyscan_t yyscanner)

+{

+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;

+

+        /* column is only valid if an input buffer exists. */

+        if (! YY_CURRENT_BUFFER )

+           yy_fatal_error( "ppset_column called with no buffer" , yyscanner); 

+    

+    yycolumn = column_no;

+}

+

+/** Set the input stream. This does not discard the current

+ * input buffer.

+ * @param in_str A readable stream.

+ * @param yyscanner The scanner object.

+ * @see pp_switch_to_buffer

+ */

+void ppset_in (FILE *  in_str , yyscan_t yyscanner)

+{

+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;

+    yyin = in_str ;

+}

+

+void ppset_out (FILE *  out_str , yyscan_t yyscanner)

+{

+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;

+    yyout = out_str ;

+}

+

+int ppget_debug  (yyscan_t yyscanner)

+{

+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;

+    return yy_flex_debug;

+}

+

+void ppset_debug (int  bdebug , yyscan_t yyscanner)

+{

+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;

+    yy_flex_debug = bdebug ;

+}

+

+/* Accessor methods for yylval and yylloc */

+

+YYSTYPE * ppget_lval  (yyscan_t yyscanner)

+{

+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;

+    return yylval;

+}

+

+void ppset_lval (YYSTYPE *  yylval_param , yyscan_t yyscanner)

+{

+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;

+    yylval = yylval_param;

+}

+

+YYLTYPE *ppget_lloc  (yyscan_t yyscanner)

+{

+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;

+    return yylloc;

+}

+    

+void ppset_lloc (YYLTYPE *  yylloc_param , yyscan_t yyscanner)

+{

+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;

+    yylloc = yylloc_param;

+}

+    

+/* User-visible API */

+

+/* pplex_init is special because it creates the scanner itself, so it is

+ * the ONLY reentrant function that doesn't take the scanner as the last argument.

+ * That's why we explicitly handle the declaration, instead of using our macros.

+ */

+

+int pplex_init(yyscan_t* ptr_yy_globals)

+

+{

+    if (ptr_yy_globals == NULL){

+        errno = EINVAL;

+        return 1;

+    }

+

+    *ptr_yy_globals = (yyscan_t) ppalloc ( sizeof( struct yyguts_t ), NULL );

+

+    if (*ptr_yy_globals == NULL){

+        errno = ENOMEM;

+        return 1;

+    }

+

+    /* By setting to 0xAA, we expose bugs in yy_init_globals. Leave at 0x00 for releases. */

+    memset(*ptr_yy_globals,0x00,sizeof(struct yyguts_t));

+

+    return yy_init_globals ( *ptr_yy_globals );

+}

+

+/* pplex_init_extra has the same functionality as pplex_init, but follows the

+ * convention of taking the scanner as the last argument. Note however, that

+ * this is a *pointer* to a scanner, as it will be allocated by this call (and

+ * is the reason, too, why this function also must handle its own declaration).

+ * The user defined value in the first argument will be available to ppalloc in

+ * the yyextra field.

+ */

+

+int pplex_init_extra(YY_EXTRA_TYPE yy_user_defined,yyscan_t* ptr_yy_globals )

+

+{

+    struct yyguts_t dummy_yyguts;

+

+    ppset_extra (yy_user_defined, &dummy_yyguts);

+

+    if (ptr_yy_globals == NULL){

+        errno = EINVAL;

+        return 1;

+    }

+	

+    *ptr_yy_globals = (yyscan_t) ppalloc ( sizeof( struct yyguts_t ), &dummy_yyguts );

+	

+    if (*ptr_yy_globals == NULL){

+        errno = ENOMEM;

+        return 1;

+    }

+    

+    /* By setting to 0xAA, we expose bugs in

+    yy_init_globals. Leave at 0x00 for releases. */

+    memset(*ptr_yy_globals,0x00,sizeof(struct yyguts_t));

+    

+    ppset_extra (yy_user_defined, *ptr_yy_globals);

+    

+    return yy_init_globals ( *ptr_yy_globals );

+}

+

+static int yy_init_globals (yyscan_t yyscanner)

+{

+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;

+    /* Initialization is the same as for the non-reentrant scanner.

+     * This function is called from pplex_destroy(), so don't allocate here.

+     */

+

+    yyg->yy_buffer_stack = 0;

+    yyg->yy_buffer_stack_top = 0;

+    yyg->yy_buffer_stack_max = 0;

+    yyg->yy_c_buf_p = (char *) 0;

+    yyg->yy_init = 0;

+    yyg->yy_start = 0;

+

+    yyg->yy_start_stack_ptr = 0;

+    yyg->yy_start_stack_depth = 0;

+    yyg->yy_start_stack =  NULL;

+

+/* Defined in main.c */

+#ifdef YY_STDINIT

+    yyin = stdin;

+    yyout = stdout;

+#else

+    yyin = (FILE *) 0;

+    yyout = (FILE *) 0;

+#endif

+

+    /* For future reference: Set errno on error, since we are called by

+     * pplex_init()

+     */

+    return 0;

+}

+

+/* pplex_destroy is for both reentrant and non-reentrant scanners. */

+int pplex_destroy  (yyscan_t yyscanner)

+{

+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;

+

+    /* Pop the buffer stack, destroying each element. */

+	while(YY_CURRENT_BUFFER){

+		pp_delete_buffer(YY_CURRENT_BUFFER ,yyscanner );

+		YY_CURRENT_BUFFER_LVALUE = NULL;

+		pppop_buffer_state(yyscanner);

+	}

+

+	/* Destroy the stack itself. */

+	ppfree(yyg->yy_buffer_stack ,yyscanner);

+	yyg->yy_buffer_stack = NULL;

+

+    /* Destroy the start condition stack. */

+        ppfree(yyg->yy_start_stack ,yyscanner );

+        yyg->yy_start_stack = NULL;

+

+    /* Reset the globals. This is important in a non-reentrant scanner so the next time

+     * pplex() is called, initialization will occur. */

+    yy_init_globals( yyscanner);

+

+    /* Destroy the main struct (reentrant only). */

+    ppfree ( yyscanner , yyscanner );

+    yyscanner = NULL;

+    return 0;

+}

+

+/*

+ * Internal utility routines.

+ */

+

+#ifndef yytext_ptr

+static void yy_flex_strncpy (char* s1, yyconst char * s2, int n , yyscan_t yyscanner)

+{

+	register int i;

+	for ( i = 0; i < n; ++i )

+		s1[i] = s2[i];

+}

+#endif

+

+#ifdef YY_NEED_STRLEN

+static int yy_flex_strlen (yyconst char * s , yyscan_t yyscanner)

+{

+	register int n;

+	for ( n = 0; s[n]; ++n )

+		;

+

+	return n;

+}

+#endif

+

+void *ppalloc (yy_size_t  size , yyscan_t yyscanner)

+{

+	return (void *) malloc( size );

+}

+

+void *pprealloc  (void * ptr, yy_size_t  size , yyscan_t yyscanner)

+{

+	/* The cast to (char *) in the following accommodates both

+	 * implementations that use char* generic pointers, and those

+	 * that use void* generic pointers.  It works with the latter

+	 * because both ANSI C and C++ allow castless assignment from

+	 * any pointer type to void*, and deal with argument conversions

+	 * as though doing an assignment.

+	 */

+	return (void *) realloc( (char *) ptr, size );

+}

+

+void ppfree (void * ptr , yyscan_t yyscanner)

+{

+	free( (char *) ptr );	/* see pprealloc() for (char *) cast */

+}

+

+#define YYTABLES_NAME "yytables"

+

+namespace pp {

+

+// TODO(alokp): Maximum token length should ideally be specified by

+// the preprocessor client, i.e., the compiler.

+const size_t Tokenizer::kMaxTokenLength = 256;

+

+Tokenizer::Tokenizer(Diagnostics* diagnostics) : mHandle(0)

+{

+    mContext.diagnostics = diagnostics;

+}

+

+Tokenizer::~Tokenizer()

+{

+    destroyScanner();

+}

+

+bool Tokenizer::init(int count, const char* const string[], const int length[])

+{

+    if (count < 0) return false;

+    if ((count > 0) && (string == 0)) return false;

+

+    mContext.input = Input(count, string, length);

+    return initScanner();

+}

+

+void Tokenizer::setFileNumber(int file)

+{

+    // We use column number as file number.

+    // See macro yyfileno.

+    ppset_column(file,mHandle);

+}

+

+void Tokenizer::setLineNumber(int line)

+{

+    ppset_lineno(line,mHandle);

+}

+

+void Tokenizer::lex(Token* token)

+{

+    token->type = pplex(&token->text,&token->location,mHandle);

+    if (token->text.size() > kMaxTokenLength)

+    {

+        mContext.diagnostics->report(Diagnostics::TOKEN_TOO_LONG,

+                                     token->location, token->text);

+        token->text.erase(kMaxTokenLength);

+    }

+

+    token->flags = 0;

+

+    token->setAtStartOfLine(mContext.lineStart);

+    mContext.lineStart = token->type == '\n';

+

+    token->setHasLeadingSpace(mContext.leadingSpace);

+    mContext.leadingSpace = false;

+}

+

+bool Tokenizer::initScanner()

+{

+    if ((mHandle == NULL) && pplex_init_extra(&mContext,&mHandle))

+        return false;

+

+    pprestart(0,mHandle);

+    return true;

+}

+

+void Tokenizer::destroyScanner()

+{

+    if (mHandle == NULL)

+        return;

+

+    pplex_destroy(mHandle);

+    mHandle = NULL;

+}

+

+}  // namespace pp

+

diff --git a/src/GLES2/compiler/preprocessor/Tokenizer.h b/src/GLES2/compiler/preprocessor/Tokenizer.h
new file mode 100644
index 0000000..4dbfff2
--- /dev/null
+++ b/src/GLES2/compiler/preprocessor/Tokenizer.h
@@ -0,0 +1,58 @@
+//

+// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.

+// Use of this source code is governed by a BSD-style license that can be

+// found in the LICENSE file.

+//

+

+#ifndef COMPILER_PREPROCESSOR_TOKENIZER_H_

+#define COMPILER_PREPROCESSOR_TOKENIZER_H_

+

+#include "Input.h"

+#include "Lexer.h"

+#include "pp_utils.h"

+

+namespace pp

+{

+

+class Diagnostics;

+

+class Tokenizer : public Lexer

+{

+  public:

+    struct Context

+    {

+        Diagnostics* diagnostics;

+

+        Input input;

+        // The location where yytext points to. Token location should track

+        // scanLoc instead of Input::mReadLoc because they may not be the same

+        // if text is buffered up in the scanner input buffer.

+        Input::Location scanLoc;

+

+        bool leadingSpace;

+        bool lineStart;

+    };

+    static const size_t kMaxTokenLength;

+

+    Tokenizer(Diagnostics* diagnostics);

+    ~Tokenizer();

+

+    bool init(int count, const char* const string[], const int length[]);

+

+    void setFileNumber(int file);

+    void setLineNumber(int line);

+

+    virtual void lex(Token* token);

+

+  private:

+    PP_DISALLOW_COPY_AND_ASSIGN(Tokenizer);

+    bool initScanner();

+    void destroyScanner();

+

+    void* mHandle;  // Scanner handle.

+    Context mContext;  // Scanner extra.

+};

+

+}  // namespace pp

+#endif  // COMPILER_PREPROCESSOR_TOKENIZER_H_

+

diff --git a/src/GLES2/compiler/preprocessor/Tokenizer.l b/src/GLES2/compiler/preprocessor/Tokenizer.l
new file mode 100644
index 0000000..a641707
--- /dev/null
+++ b/src/GLES2/compiler/preprocessor/Tokenizer.l
@@ -0,0 +1,340 @@
+/*

+//

+// Copyright (c) 2002-2011 The ANGLE Project Authors. All rights reserved.

+// Use of this source code is governed by a BSD-style license that can be

+// found in the LICENSE file.

+//

+

+This file contains the Lex specification for GLSL ES preprocessor.

+Based on Microsoft Visual Studio 2010 Preprocessor Grammar:

+http://msdn.microsoft.com/en-us/library/2scxys89.aspx

+

+IF YOU MODIFY THIS FILE YOU ALSO NEED TO RUN generate_parser.sh.

+*/

+

+%top{

+//

+// Copyright (c) 2011 The ANGLE Project Authors. All rights reserved.

+// Use of this source code is governed by a BSD-style license that can be

+// found in the LICENSE file.

+//

+

+// This file is auto-generated by generate_parser.sh. DO NOT EDIT!

+}

+

+%{

+#include "Tokenizer.h"

+

+#include "Diagnostics.h"

+#include "Token.h"

+

+#if defined(__GNUC__)

+// Triggered by the auto-generated yy_fatal_error function.

+#pragma GCC diagnostic ignored "-Wmissing-noreturn"

+#endif

+

+typedef std::string YYSTYPE;

+typedef pp::SourceLocation YYLTYPE;

+

+// Use the unused yycolumn variable to track file (string) number.

+#define yyfileno yycolumn

+

+#define YY_USER_INIT                   \

+    do {                               \

+        yyfileno = 0;                  \

+        yylineno = 1;                  \

+        yyextra->leadingSpace = false; \

+        yyextra->lineStart = true;     \

+    } while(0);

+

+#define YY_USER_ACTION                                              \

+    do                                                              \

+    {                                                               \

+        pp::Input* input = &yyextra->input;                         \

+        pp::Input::Location* scanLoc = &yyextra->scanLoc;           \

+        while ((scanLoc->sIndex < input->count()) &&                \

+               (scanLoc->cIndex >= input->length(scanLoc->sIndex))) \

+        {                                                           \

+            scanLoc->cIndex -= input->length(scanLoc->sIndex++);    \

+            ++yyfileno; yylineno = 1;                               \

+        }                                                           \

+        yylloc->file = yyfileno;                                    \

+        yylloc->line = yylineno;                                    \

+        scanLoc->cIndex += yyleng;                                  \

+    } while(0);

+

+#define YY_INPUT(buf, result, maxSize) \

+    result = yyextra->input.read(buf, maxSize);

+

+%}

+

+%option noyywrap nounput never-interactive

+%option reentrant bison-bridge bison-locations

+%option prefix="pp"

+%option extra-type="pp::Tokenizer::Context*"

+%x COMMENT

+

+NEWLINE     \n|\r|\r\n

+IDENTIFIER  [_a-zA-Z][_a-zA-Z0-9]*

+PUNCTUATOR  [][<>(){}.+-/*%^|&~=!:;,?]

+

+DECIMAL_CONSTANT      [1-9][0-9]*

+OCTAL_CONSTANT        0[0-7]*

+HEXADECIMAL_CONSTANT  0[xX][0-9a-fA-F]+

+

+DIGIT                [0-9]

+EXPONENT_PART        [eE][+-]?{DIGIT}+

+FRACTIONAL_CONSTANT  ({DIGIT}*"."{DIGIT}+)|({DIGIT}+".")

+

+%%

+

+    /* Line comment */

+"//"[^\r\n]*

+

+    /* Block comment */

+    /* Line breaks are just counted - not returned. */

+    /* The comment is replaced by a single space. */ 

+"/*" { BEGIN(COMMENT); }

+<COMMENT>[^*\r\n]+

+<COMMENT>"*"

+<COMMENT>{NEWLINE} { ++yylineno; }

+<COMMENT>"*/" {

+    yyextra->leadingSpace = true;

+    BEGIN(INITIAL);

+}

+

+# {

+    // # is only valid at start of line for preprocessor directives.

+    yylval->assign(1, yytext[0]);

+    return yyextra->lineStart ? pp::Token::PP_HASH : pp::Token::PP_OTHER;

+}

+

+{IDENTIFIER} {

+    yylval->assign(yytext, yyleng);

+    return pp::Token::IDENTIFIER;

+}

+

+{DECIMAL_CONSTANT}|{OCTAL_CONSTANT}|{HEXADECIMAL_CONSTANT} {

+    yylval->assign(yytext, yyleng);

+    return pp::Token::CONST_INT;

+}

+

+({DIGIT}+{EXPONENT_PART})|({FRACTIONAL_CONSTANT}{EXPONENT_PART}?) {

+    yylval->assign(yytext, yyleng);

+    return pp::Token::CONST_FLOAT;

+}

+

+    /* Anything that starts with a {DIGIT} or .{DIGIT} must be a number. */

+    /* Rule to catch all invalid integers and floats. */

+({DIGIT}+[_a-zA-Z0-9.]*)|("."{DIGIT}+[_a-zA-Z0-9.]*) {

+    yylval->assign(yytext, yyleng);

+    return pp::Token::PP_NUMBER;

+}

+

+"++" {

+    yylval->assign(yytext, yyleng);

+    return pp::Token::OP_INC;

+}

+"--" {

+    yylval->assign(yytext, yyleng);

+    return pp::Token::OP_DEC;

+}

+"<<" {

+    yylval->assign(yytext, yyleng);

+    return pp::Token::OP_LEFT;

+}

+">>" {

+    yylval->assign(yytext, yyleng);

+    return pp::Token::OP_RIGHT;

+}

+"<=" {

+    yylval->assign(yytext, yyleng);

+    return pp::Token::OP_LE;

+}

+">=" {

+    yylval->assign(yytext, yyleng);

+    return pp::Token::OP_GE;

+}

+"==" {

+    yylval->assign(yytext, yyleng);

+    return pp::Token::OP_EQ;

+}

+"!=" {

+    yylval->assign(yytext, yyleng);

+    return pp::Token::OP_NE;

+}

+"&&" {

+    yylval->assign(yytext, yyleng);

+    return pp::Token::OP_AND;

+}

+"^^" {

+    yylval->assign(yytext, yyleng);

+    return pp::Token::OP_XOR;

+}

+"||" {

+    yylval->assign(yytext, yyleng);

+    return pp::Token::OP_OR;

+}

+"+=" {

+    yylval->assign(yytext, yyleng);

+    return pp::Token::OP_ADD_ASSIGN;

+}

+"-=" {

+    yylval->assign(yytext, yyleng);

+    return pp::Token::OP_SUB_ASSIGN;

+}

+"*=" {

+    yylval->assign(yytext, yyleng);

+    return pp::Token::OP_MUL_ASSIGN;

+}

+"/=" {

+    yylval->assign(yytext, yyleng);

+    return pp::Token::OP_DIV_ASSIGN;

+}

+"%=" {

+    yylval->assign(yytext, yyleng);

+    return pp::Token::OP_MOD_ASSIGN;

+}

+"<<=" {

+    yylval->assign(yytext, yyleng);

+    return pp::Token::OP_LEFT_ASSIGN;

+}

+">>=" {

+    yylval->assign(yytext, yyleng);

+    return pp::Token::OP_RIGHT_ASSIGN;

+}

+"&=" {

+    yylval->assign(yytext, yyleng);

+    return pp::Token::OP_AND_ASSIGN;

+}

+"^=" {

+    yylval->assign(yytext, yyleng);

+    return pp::Token::OP_XOR_ASSIGN;

+}

+"|=" {

+    yylval->assign(yytext, yyleng);

+    return pp::Token::OP_OR_ASSIGN;

+}

+

+{PUNCTUATOR} {

+    yylval->assign(1, yytext[0]);

+    return yytext[0];

+}

+

+[ \t\v\f]+   { yyextra->leadingSpace = true; }

+

+{NEWLINE} {

+    ++yylineno;

+    yylval->assign(1, '\n');

+    return '\n';

+}

+

+. {

+    yylval->assign(1, yytext[0]);

+    return pp::Token::PP_OTHER;

+}

+

+<*><<EOF>> {

+    // YY_USER_ACTION is not invoked for handling EOF.

+    // Set the location for EOF token manually.

+    pp::Input* input = &yyextra->input;

+    pp::Input::Location* scanLoc = &yyextra->scanLoc;

+    int sIndexMax = std::max(0, input->count() - 1);

+    if (scanLoc->sIndex != sIndexMax)

+    {

+        // We can only reach here if there are empty strings at the

+        // end of the input.

+        scanLoc->sIndex = sIndexMax; scanLoc->cIndex = 0;

+        yyfileno = sIndexMax; yylineno = 1;

+    }

+    yylloc->file = yyfileno;

+    yylloc->line = yylineno;

+    yylval->clear();

+

+    if (YY_START == COMMENT)

+    {

+        yyextra->diagnostics->report(pp::Diagnostics::EOF_IN_COMMENT,

+                                     pp::SourceLocation(yyfileno, yylineno),

+                                     "");

+    }

+    yyterminate();

+}

+

+%%

+

+namespace pp {

+

+// TODO(alokp): Maximum token length should ideally be specified by

+// the preprocessor client, i.e., the compiler.

+const size_t Tokenizer::kMaxTokenLength = 256;

+

+Tokenizer::Tokenizer(Diagnostics* diagnostics) : mHandle(0)

+{

+    mContext.diagnostics = diagnostics;

+}

+

+Tokenizer::~Tokenizer()

+{

+    destroyScanner();

+}

+

+bool Tokenizer::init(int count, const char* const string[], const int length[])

+{

+    if (count < 0) return false;

+    if ((count > 0) && (string == 0)) return false;

+

+    mContext.input = Input(count, string, length);

+    return initScanner();

+}

+

+void Tokenizer::setFileNumber(int file)

+{

+    // We use column number as file number.

+    // See macro yyfileno.

+    yyset_column(file, mHandle);

+}

+

+void Tokenizer::setLineNumber(int line)

+{

+    yyset_lineno(line, mHandle);

+}

+

+void Tokenizer::lex(Token* token)

+{

+    token->type = yylex(&token->text, &token->location, mHandle);

+    if (token->text.size() > kMaxTokenLength)

+    {

+        mContext.diagnostics->report(Diagnostics::TOKEN_TOO_LONG,

+                                     token->location, token->text);

+        token->text.erase(kMaxTokenLength);

+    }

+

+    token->flags = 0;

+

+    token->setAtStartOfLine(mContext.lineStart);

+    mContext.lineStart = token->type == '\n';

+

+    token->setHasLeadingSpace(mContext.leadingSpace);

+    mContext.leadingSpace = false;

+}

+

+bool Tokenizer::initScanner()

+{

+    if ((mHandle == NULL) && yylex_init_extra(&mContext, &mHandle))

+        return false;

+

+    yyrestart(0, mHandle);

+    return true;

+}

+

+void Tokenizer::destroyScanner()

+{

+    if (mHandle == NULL)

+        return;

+

+    yylex_destroy(mHandle);

+    mHandle = NULL;

+}

+

+}  // namespace pp

+

diff --git a/src/GLES2/compiler/preprocessor/generate_parser.sh b/src/GLES2/compiler/preprocessor/generate_parser.sh
new file mode 100644
index 0000000..8ffe0e5
--- /dev/null
+++ b/src/GLES2/compiler/preprocessor/generate_parser.sh
@@ -0,0 +1,26 @@
+#!/bin/bash

+# Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.

+# Use of this source code is governed by a BSD-style license that can be

+# found in the LICENSE file.

+

+# Generates various components of GLSL ES preprocessor.

+

+run_flex()

+{

+input_file=$script_dir/$1

+output_source=$script_dir/$2

+flex --noline --nounistd --outfile=$output_source $input_file

+}

+

+run_bison()

+{

+input_file=$script_dir/$1

+output_source=$script_dir/$2

+bison --no-lines --skeleton=yacc.c --output=$output_source $input_file

+}

+

+script_dir=$(dirname $0)

+

+# Generate preprocessor

+run_flex Tokenizer.l Tokenizer.cpp

+run_bison ExpressionParser.y ExpressionParser.cpp

diff --git a/src/GLES2/compiler/preprocessor/length_limits.h b/src/GLES2/compiler/preprocessor/length_limits.h
new file mode 100644
index 0000000..889d468
--- /dev/null
+++ b/src/GLES2/compiler/preprocessor/length_limits.h
@@ -0,0 +1,21 @@
+//

+// Copyright (c) 2011 The ANGLE Project Authors. All rights reserved.

+// Use of this source code is governed by a BSD-style license that can be

+// found in the LICENSE file.

+//

+

+//

+// length_limits.h

+//

+

+#if !defined(__LENGTH_LIMITS_H)

+#define __LENGTH_LIMITS_H 1

+

+// These constants are factored out from the rest of the headers to

+// make it easier to reference them from the compiler sources.

+

+// These lengths do not include the NULL terminator.

+#define MAX_SYMBOL_NAME_LEN 256

+#define MAX_STRING_LEN 511

+

+#endif // !(defined(__LENGTH_LIMITS_H)

diff --git a/src/GLES2/compiler/preprocessor/numeric_lex.h b/src/GLES2/compiler/preprocessor/numeric_lex.h
new file mode 100644
index 0000000..3cdf71f
--- /dev/null
+++ b/src/GLES2/compiler/preprocessor/numeric_lex.h
@@ -0,0 +1,61 @@
+//

+// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.

+// Use of this source code is governed by a BSD-style license that can be

+// found in the LICENSE file.

+//

+

+// numeric_lex.h: Functions to extract numeric values from string.

+

+#ifndef COMPILER_PREPROCESSOR_NUMERIC_LEX_H_

+#define COMPILER_PREPROCESSOR_NUMERIC_LEX_H_

+

+#include <sstream>

+

+namespace pp {

+

+inline std::ios::fmtflags numeric_base_int(const std::string& str)

+{

+    if ((str.size() >= 2) &&

+        (str[0] == '0') &&

+        (str[1] == 'x' || str[1] == 'X'))

+    {

+        return std::ios::hex;

+    }

+    else if ((str.size() >= 1) && (str[0] == '0'))

+    {

+        return std::ios::oct;

+    }

+    return std::ios::dec;

+}

+

+// The following functions parse the given string to extract a numerical

+// value of the given type. These functions assume that the string is

+// of the correct form. They can only fail if the parsed value is too big,

+// in which case false is returned.

+

+template<typename IntType>

+bool numeric_lex_int(const std::string& str, IntType* value)

+{

+    std::istringstream stream(str);

+    // This should not be necessary, but MSVS has a buggy implementation.

+    // It returns incorrect results if the base is not specified.

+    stream.setf(numeric_base_int(str), std::ios::basefield);

+

+    stream >> (*value);

+    return !stream.fail();

+}

+

+template<typename FloatType>

+bool numeric_lex_float(const std::string& str, FloatType* value)

+{

+    std::istringstream stream(str);

+    // Force "C" locale so that decimal character is always '.', and

+    // not dependent on the current locale.

+    stream.imbue(std::locale::classic());

+

+    stream >> (*value);

+    return !stream.fail();

+}

+

+} // namespace pp.

+#endif // COMPILER_PREPROCESSOR_NUMERIC_LEX_H_

diff --git a/src/GLES2/compiler/preprocessor/pp_utils.h b/src/GLES2/compiler/preprocessor/pp_utils.h
new file mode 100644
index 0000000..9fed659
--- /dev/null
+++ b/src/GLES2/compiler/preprocessor/pp_utils.h
@@ -0,0 +1,18 @@
+//

+// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.

+// Use of this source code is governed by a BSD-style license that can be

+// found in the LICENSE file.

+//

+

+// pp_utils.h: Common preprocessor utilities

+

+#ifndef COMPILER_PREPROCESSOR_PPUTILS_H_

+#define COMPILER_PREPROCESSOR_PPUTILS_H_

+

+// A macro to disallow the copy constructor and operator= functions

+// This must be used in the private: declarations for a class.

+#define PP_DISALLOW_COPY_AND_ASSIGN(TypeName) \

+  TypeName(const TypeName&);               \

+  void operator=(const TypeName&)

+

+#endif // COMPILER_PREPROCESSOR_PPUTILS_H_

diff --git a/src/GLES2/compiler/preprocessor/preprocessor.vcxproj b/src/GLES2/compiler/preprocessor/preprocessor.vcxproj
new file mode 100644
index 0000000..2afb4fe
--- /dev/null
+++ b/src/GLES2/compiler/preprocessor/preprocessor.vcxproj
@@ -0,0 +1,101 @@
+<?xml version="1.0" encoding="utf-8"?>

+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

+  <ItemGroup Label="ProjectConfigurations">

+    <ProjectConfiguration Include="Debug|Win32">

+      <Configuration>Debug</Configuration>

+      <Platform>Win32</Platform>

+    </ProjectConfiguration>

+    <ProjectConfiguration Include="Release|Win32">

+      <Configuration>Release</Configuration>

+      <Platform>Win32</Platform>

+    </ProjectConfiguration>

+  </ItemGroup>

+  <PropertyGroup Label="Globals">

+    <ProjectGuid>{92940255-AB4B-42FB-A2C4-0FAB19C3C48A}</ProjectGuid>

+    <RootNamespace>preprocessor</RootNamespace>

+  </PropertyGroup>

+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">

+    <ConfigurationType>StaticLibrary</ConfigurationType>

+    <UseDebugLibraries>true</UseDebugLibraries>

+    <CharacterSet>NotSet</CharacterSet>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">

+    <ConfigurationType>StaticLibrary</ConfigurationType>

+    <UseDebugLibraries>false</UseDebugLibraries>

+    <WholeProgramOptimization>true</WholeProgramOptimization>

+    <CharacterSet>NotSet</CharacterSet>

+  </PropertyGroup>

+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />

+  <ImportGroup Label="ExtensionSettings">

+  </ImportGroup>

+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">

+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

+  </ImportGroup>

+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">

+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

+  </ImportGroup>

+  <PropertyGroup Label="UserMacros" />

+  <PropertyGroup />

+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">

+    <ClCompile>

+      <WarningLevel>Level3</WarningLevel>

+      <Optimization>Disabled</Optimization>

+      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>

+    </ClCompile>

+    <Link>

+      <GenerateDebugInformation>true</GenerateDebugInformation>

+    </Link>

+  </ItemDefinitionGroup>

+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">

+    <ClCompile>

+      <WarningLevel>Level3</WarningLevel>

+      <Optimization>MaxSpeed</Optimization>

+      <FunctionLevelLinking>true</FunctionLevelLinking>

+      <IntrinsicFunctions>true</IntrinsicFunctions>

+      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>

+    </ClCompile>

+    <Link>

+      <GenerateDebugInformation>true</GenerateDebugInformation>

+      <EnableCOMDATFolding>true</EnableCOMDATFolding>

+      <OptimizeReferences>true</OptimizeReferences>

+    </Link>

+  </ItemDefinitionGroup>

+  <ItemGroup>

+    <ClInclude Include="Diagnostics.h" />

+    <ClInclude Include="DirectiveHandler.h" />

+    <ClInclude Include="DirectiveParser.h" />

+    <ClInclude Include="ExpressionParser.h" />

+    <ClInclude Include="Input.h" />

+    <ClInclude Include="length_limits.h" />

+    <ClInclude Include="Lexer.h" />

+    <ClInclude Include="Macro.h" />

+    <ClInclude Include="MacroExpander.h" />

+    <ClInclude Include="numeric_lex.h" />

+    <ClInclude Include="pp_utils.h" />

+    <ClInclude Include="Preprocessor.h" />

+    <ClInclude Include="SourceLocation.h" />

+    <ClInclude Include="Token.h" />

+    <ClInclude Include="Tokenizer.h" />

+  </ItemGroup>

+  <ItemGroup>

+    <ClCompile Include="Diagnostics.cpp" />

+    <ClCompile Include="DirectiveHandler.cpp" />

+    <ClCompile Include="DirectiveParser.cpp" />

+    <ClCompile Include="ExpressionParser.cpp" />

+    <ClCompile Include="Input.cpp" />

+    <ClCompile Include="Lexer.cpp" />

+    <ClCompile Include="Macro.cpp" />

+    <ClCompile Include="MacroExpander.cpp" />

+    <ClCompile Include="Preprocessor.cpp" />

+    <ClCompile Include="Token.cpp" />

+    <ClCompile Include="Tokenizer.cpp" />

+  </ItemGroup>

+  <ItemGroup>

+    <None Include="ExpressionParser.y" />

+    <None Include="Tokenizer.l" />

+  </ItemGroup>

+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />

+  <ImportGroup Label="ExtensionTargets">

+  </ImportGroup>

+</Project>

diff --git a/src/GLES2/compiler/preprocessor/preprocessor.vcxproj.filters b/src/GLES2/compiler/preprocessor/preprocessor.vcxproj.filters
new file mode 100644
index 0000000..d68cbe2
--- /dev/null
+++ b/src/GLES2/compiler/preprocessor/preprocessor.vcxproj.filters
@@ -0,0 +1,103 @@
+<?xml version="1.0" encoding="utf-8"?>

+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

+  <ItemGroup>

+    <Filter Include="Source Files">

+      <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>

+      <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>

+    </Filter>

+    <Filter Include="Header Files">

+      <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>

+      <Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>

+    </Filter>

+    <Filter Include="Resource Files">

+      <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>

+      <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>

+    </Filter>

+  </ItemGroup>

+  <ItemGroup>

+    <ClInclude Include="Diagnostics.h">

+      <Filter>Header Files</Filter>

+    </ClInclude>

+    <ClInclude Include="DirectiveHandler.h">

+      <Filter>Header Files</Filter>

+    </ClInclude>

+    <ClInclude Include="DirectiveParser.h">

+      <Filter>Header Files</Filter>

+    </ClInclude>

+    <ClInclude Include="ExpressionParser.h">

+      <Filter>Header Files</Filter>

+    </ClInclude>

+    <ClInclude Include="Input.h">

+      <Filter>Header Files</Filter>

+    </ClInclude>

+    <ClInclude Include="length_limits.h">

+      <Filter>Header Files</Filter>

+    </ClInclude>

+    <ClInclude Include="Lexer.h">

+      <Filter>Header Files</Filter>

+    </ClInclude>

+    <ClInclude Include="Macro.h">

+      <Filter>Header Files</Filter>

+    </ClInclude>

+    <ClInclude Include="MacroExpander.h">

+      <Filter>Header Files</Filter>

+    </ClInclude>

+    <ClInclude Include="numeric_lex.h">

+      <Filter>Header Files</Filter>

+    </ClInclude>

+    <ClInclude Include="pp_utils.h">

+      <Filter>Header Files</Filter>

+    </ClInclude>

+    <ClInclude Include="Preprocessor.h">

+      <Filter>Header Files</Filter>

+    </ClInclude>

+    <ClInclude Include="SourceLocation.h">

+      <Filter>Header Files</Filter>

+    </ClInclude>

+    <ClInclude Include="Token.h">

+      <Filter>Header Files</Filter>

+    </ClInclude>

+    <ClInclude Include="Tokenizer.h">

+      <Filter>Header Files</Filter>

+    </ClInclude>

+  </ItemGroup>

+  <ItemGroup>

+    <ClCompile Include="Diagnostics.cpp">

+      <Filter>Source Files</Filter>

+    </ClCompile>

+    <ClCompile Include="DirectiveHandler.cpp">

+      <Filter>Source Files</Filter>

+    </ClCompile>

+    <ClCompile Include="DirectiveParser.cpp">

+      <Filter>Source Files</Filter>

+    </ClCompile>

+    <ClCompile Include="ExpressionParser.cpp">

+      <Filter>Source Files</Filter>

+    </ClCompile>

+    <ClCompile Include="Input.cpp">

+      <Filter>Source Files</Filter>

+    </ClCompile>

+    <ClCompile Include="Lexer.cpp">

+      <Filter>Source Files</Filter>

+    </ClCompile>

+    <ClCompile Include="Macro.cpp">

+      <Filter>Source Files</Filter>

+    </ClCompile>

+    <ClCompile Include="MacroExpander.cpp">

+      <Filter>Source Files</Filter>

+    </ClCompile>

+    <ClCompile Include="Preprocessor.cpp">

+      <Filter>Source Files</Filter>

+    </ClCompile>

+    <ClCompile Include="Token.cpp">

+      <Filter>Source Files</Filter>

+    </ClCompile>

+    <ClCompile Include="Tokenizer.cpp">

+      <Filter>Source Files</Filter>

+    </ClCompile>

+  </ItemGroup>

+  <ItemGroup>

+    <None Include="Tokenizer.l" />

+    <None Include="ExpressionParser.y" />

+  </ItemGroup>

+</Project>

diff --git a/src/GLES2/compiler/util.cpp b/src/GLES2/compiler/util.cpp
new file mode 100644
index 0000000..b46e4d0
--- /dev/null
+++ b/src/GLES2/compiler/util.cpp
@@ -0,0 +1,33 @@
+//
+// Copyright (c) 2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include <math.h>
+#include <stdlib.h>
+
+#include "util.h"
+
+#ifdef _MSC_VER
+    #include <locale.h>
+#else
+    #include <sstream>
+#endif
+
+double atof_dot(const char *str)
+{
+#ifdef _MSC_VER
+    _locale_t l = _create_locale(LC_NUMERIC, "C");
+    double result = _atof_l(str, l);
+    _free_locale(l);
+    return result;
+#else
+    double result;
+    std::istringstream s(str);
+    std::locale l("C");
+    s.imbue(l);
+    s >> result;
+    return result;
+#endif
+}
diff --git a/src/GLES2/compiler/util.h b/src/GLES2/compiler/util.h
new file mode 100644
index 0000000..35288b7
--- /dev/null
+++ b/src/GLES2/compiler/util.h
@@ -0,0 +1,21 @@
+//
+// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#ifndef COMPILER_UTIL_H
+#define COMPILER_UTIL_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// atof_dot is like atof but forcing C locale, i.e. forcing '.' as decimal point.
+double atof_dot(const char *str);
+
+#ifdef __cplusplus
+} // end extern "C"
+#endif
+
+#endif // COMPILER_UTIL_H
diff --git a/src/GLES2/include/EGL/egl.h b/src/GLES2/include/EGL/egl.h
new file mode 100644
index 0000000..99ea342
--- /dev/null
+++ b/src/GLES2/include/EGL/egl.h
@@ -0,0 +1,329 @@
+/* -*- mode: c; tab-width: 8; -*- */
+/* vi: set sw=4 ts=8: */
+/* Reference version of egl.h for EGL 1.4.
+ * $Revision: 9356 $ on $Date: 2009-10-21 02:52:25 -0700 (Wed, 21 Oct 2009) $
+ */
+
+/*
+** Copyright (c) 2007-2009 The Khronos Group Inc.
+**
+** Permission is hereby granted, free of charge, to any person obtaining a
+** copy of this software and/or associated documentation files (the
+** "Materials"), to deal in the Materials without restriction, including
+** without limitation the rights to use, copy, modify, merge, publish,
+** distribute, sublicense, and/or sell copies of the Materials, and to
+** permit persons to whom the Materials are furnished to do so, subject to
+** the following conditions:
+**
+** The above copyright notice and this permission notice shall be included
+** in all copies or substantial portions of the Materials.
+**
+** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+*/
+
+#ifndef __egl_h_
+#define __egl_h_
+
+/* All platform-dependent types and macro boilerplate (such as EGLAPI
+ * and EGLAPIENTRY) should go in eglplatform.h.
+ */
+#include <EGL/eglplatform.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* EGL Types */
+/* EGLint is defined in eglplatform.h */
+typedef unsigned int EGLBoolean;
+typedef unsigned int EGLenum;
+typedef void *EGLConfig;
+typedef void *EGLContext;
+typedef void *EGLDisplay;
+typedef void *EGLSurface;
+typedef void *EGLClientBuffer;
+
+/* EGL Versioning */
+#define EGL_VERSION_1_0			1
+#define EGL_VERSION_1_1			1
+#define EGL_VERSION_1_2			1
+#define EGL_VERSION_1_3			1
+#define EGL_VERSION_1_4			1
+
+/* EGL Enumerants. Bitmasks and other exceptional cases aside, most
+ * enums are assigned unique values starting at 0x3000.
+ */
+
+/* EGL aliases */
+#define EGL_FALSE			0
+#define EGL_TRUE			1
+
+/* Out-of-band handle values */
+#define EGL_DEFAULT_DISPLAY		((EGLNativeDisplayType)0)
+#define EGL_NO_CONTEXT			((EGLContext)0)
+#define EGL_NO_DISPLAY			((EGLDisplay)0)
+#define EGL_NO_SURFACE			((EGLSurface)0)
+
+/* Out-of-band attribute value */
+#define EGL_DONT_CARE			((EGLint)-1)
+
+/* Errors / GetError return values */
+#define EGL_SUCCESS			0x3000
+#define EGL_NOT_INITIALIZED		0x3001
+#define EGL_BAD_ACCESS			0x3002
+#define EGL_BAD_ALLOC			0x3003
+#define EGL_BAD_ATTRIBUTE		0x3004
+#define EGL_BAD_CONFIG			0x3005
+#define EGL_BAD_CONTEXT			0x3006
+#define EGL_BAD_CURRENT_SURFACE		0x3007
+#define EGL_BAD_DISPLAY			0x3008
+#define EGL_BAD_MATCH			0x3009
+#define EGL_BAD_NATIVE_PIXMAP		0x300A
+#define EGL_BAD_NATIVE_WINDOW		0x300B
+#define EGL_BAD_PARAMETER		0x300C
+#define EGL_BAD_SURFACE			0x300D
+#define EGL_CONTEXT_LOST		0x300E	/* EGL 1.1 - IMG_power_management */
+
+/* Reserved 0x300F-0x301F for additional errors */
+
+/* Config attributes */
+#define EGL_BUFFER_SIZE			0x3020
+#define EGL_ALPHA_SIZE			0x3021
+#define EGL_BLUE_SIZE			0x3022
+#define EGL_GREEN_SIZE			0x3023
+#define EGL_RED_SIZE			0x3024
+#define EGL_DEPTH_SIZE			0x3025
+#define EGL_STENCIL_SIZE		0x3026
+#define EGL_CONFIG_CAVEAT		0x3027
+#define EGL_CONFIG_ID			0x3028
+#define EGL_LEVEL			0x3029
+#define EGL_MAX_PBUFFER_HEIGHT		0x302A
+#define EGL_MAX_PBUFFER_PIXELS		0x302B
+#define EGL_MAX_PBUFFER_WIDTH		0x302C
+#define EGL_NATIVE_RENDERABLE		0x302D
+#define EGL_NATIVE_VISUAL_ID		0x302E
+#define EGL_NATIVE_VISUAL_TYPE		0x302F
+#define EGL_SAMPLES			0x3031
+#define EGL_SAMPLE_BUFFERS		0x3032
+#define EGL_SURFACE_TYPE		0x3033
+#define EGL_TRANSPARENT_TYPE		0x3034
+#define EGL_TRANSPARENT_BLUE_VALUE	0x3035
+#define EGL_TRANSPARENT_GREEN_VALUE	0x3036
+#define EGL_TRANSPARENT_RED_VALUE	0x3037
+#define EGL_NONE			0x3038	/* Attrib list terminator */
+#define EGL_BIND_TO_TEXTURE_RGB		0x3039
+#define EGL_BIND_TO_TEXTURE_RGBA	0x303A
+#define EGL_MIN_SWAP_INTERVAL		0x303B
+#define EGL_MAX_SWAP_INTERVAL		0x303C
+#define EGL_LUMINANCE_SIZE		0x303D
+#define EGL_ALPHA_MASK_SIZE		0x303E
+#define EGL_COLOR_BUFFER_TYPE		0x303F
+#define EGL_RENDERABLE_TYPE		0x3040
+#define EGL_MATCH_NATIVE_PIXMAP		0x3041	/* Pseudo-attribute (not queryable) */
+#define EGL_CONFORMANT			0x3042
+
+/* Reserved 0x3041-0x304F for additional config attributes */
+
+/* Config attribute values */
+#define EGL_SLOW_CONFIG			0x3050	/* EGL_CONFIG_CAVEAT value */
+#define EGL_NON_CONFORMANT_CONFIG	0x3051	/* EGL_CONFIG_CAVEAT value */
+#define EGL_TRANSPARENT_RGB		0x3052	/* EGL_TRANSPARENT_TYPE value */
+#define EGL_RGB_BUFFER			0x308E	/* EGL_COLOR_BUFFER_TYPE value */
+#define EGL_LUMINANCE_BUFFER		0x308F	/* EGL_COLOR_BUFFER_TYPE value */
+
+/* More config attribute values, for EGL_TEXTURE_FORMAT */
+#define EGL_NO_TEXTURE			0x305C
+#define EGL_TEXTURE_RGB			0x305D
+#define EGL_TEXTURE_RGBA		0x305E
+#define EGL_TEXTURE_2D			0x305F
+
+/* Config attribute mask bits */
+#define EGL_PBUFFER_BIT			0x0001	/* EGL_SURFACE_TYPE mask bits */
+#define EGL_PIXMAP_BIT			0x0002	/* EGL_SURFACE_TYPE mask bits */
+#define EGL_WINDOW_BIT			0x0004	/* EGL_SURFACE_TYPE mask bits */
+#define EGL_VG_COLORSPACE_LINEAR_BIT	0x0020	/* EGL_SURFACE_TYPE mask bits */
+#define EGL_VG_ALPHA_FORMAT_PRE_BIT	0x0040	/* EGL_SURFACE_TYPE mask bits */
+#define EGL_MULTISAMPLE_RESOLVE_BOX_BIT 0x0200	/* EGL_SURFACE_TYPE mask bits */
+#define EGL_SWAP_BEHAVIOR_PRESERVED_BIT 0x0400	/* EGL_SURFACE_TYPE mask bits */
+
+#define EGL_OPENGL_ES_BIT		0x0001	/* EGL_RENDERABLE_TYPE mask bits */
+#define EGL_OPENVG_BIT			0x0002	/* EGL_RENDERABLE_TYPE mask bits */
+#define EGL_OPENGL_ES2_BIT		0x0004	/* EGL_RENDERABLE_TYPE mask bits */
+#define EGL_OPENGL_BIT			0x0008	/* EGL_RENDERABLE_TYPE mask bits */
+
+/* QueryString targets */
+#define EGL_VENDOR			0x3053
+#define EGL_VERSION			0x3054
+#define EGL_EXTENSIONS			0x3055
+#define EGL_CLIENT_APIS			0x308D
+
+/* QuerySurface / SurfaceAttrib / CreatePbufferSurface targets */
+#define EGL_HEIGHT			0x3056
+#define EGL_WIDTH			0x3057
+#define EGL_LARGEST_PBUFFER		0x3058
+#define EGL_TEXTURE_FORMAT		0x3080
+#define EGL_TEXTURE_TARGET		0x3081
+#define EGL_MIPMAP_TEXTURE		0x3082
+#define EGL_MIPMAP_LEVEL		0x3083
+#define EGL_RENDER_BUFFER		0x3086
+#define EGL_VG_COLORSPACE		0x3087
+#define EGL_VG_ALPHA_FORMAT		0x3088
+#define EGL_HORIZONTAL_RESOLUTION	0x3090
+#define EGL_VERTICAL_RESOLUTION		0x3091
+#define EGL_PIXEL_ASPECT_RATIO		0x3092
+#define EGL_SWAP_BEHAVIOR		0x3093
+#define EGL_MULTISAMPLE_RESOLVE		0x3099
+
+/* EGL_RENDER_BUFFER values / BindTexImage / ReleaseTexImage buffer targets */
+#define EGL_BACK_BUFFER			0x3084
+#define EGL_SINGLE_BUFFER		0x3085
+
+/* OpenVG color spaces */
+#define EGL_VG_COLORSPACE_sRGB		0x3089	/* EGL_VG_COLORSPACE value */
+#define EGL_VG_COLORSPACE_LINEAR	0x308A	/* EGL_VG_COLORSPACE value */
+
+/* OpenVG alpha formats */
+#define EGL_VG_ALPHA_FORMAT_NONPRE	0x308B	/* EGL_ALPHA_FORMAT value */
+#define EGL_VG_ALPHA_FORMAT_PRE		0x308C	/* EGL_ALPHA_FORMAT value */
+
+/* Constant scale factor by which fractional display resolutions &
+ * aspect ratio are scaled when queried as integer values.
+ */
+#define EGL_DISPLAY_SCALING		10000
+
+/* Unknown display resolution/aspect ratio */
+#define EGL_UNKNOWN			((EGLint)-1)
+
+/* Back buffer swap behaviors */
+#define EGL_BUFFER_PRESERVED		0x3094	/* EGL_SWAP_BEHAVIOR value */
+#define EGL_BUFFER_DESTROYED		0x3095	/* EGL_SWAP_BEHAVIOR value */
+
+/* CreatePbufferFromClientBuffer buffer types */
+#define EGL_OPENVG_IMAGE		0x3096
+
+/* QueryContext targets */
+#define EGL_CONTEXT_CLIENT_TYPE		0x3097
+
+/* CreateContext attributes */
+#define EGL_CONTEXT_CLIENT_VERSION	0x3098
+
+/* Multisample resolution behaviors */
+#define EGL_MULTISAMPLE_RESOLVE_DEFAULT 0x309A	/* EGL_MULTISAMPLE_RESOLVE value */
+#define EGL_MULTISAMPLE_RESOLVE_BOX	0x309B	/* EGL_MULTISAMPLE_RESOLVE value */
+
+/* BindAPI/QueryAPI targets */
+#define EGL_OPENGL_ES_API		0x30A0
+#define EGL_OPENVG_API			0x30A1
+#define EGL_OPENGL_API			0x30A2
+
+/* GetCurrentSurface targets */
+#define EGL_DRAW			0x3059
+#define EGL_READ			0x305A
+
+/* WaitNative engines */
+#define EGL_CORE_NATIVE_ENGINE		0x305B
+
+/* EGL 1.2 tokens renamed for consistency in EGL 1.3 */
+#define EGL_COLORSPACE			EGL_VG_COLORSPACE
+#define EGL_ALPHA_FORMAT		EGL_VG_ALPHA_FORMAT
+#define EGL_COLORSPACE_sRGB		EGL_VG_COLORSPACE_sRGB
+#define EGL_COLORSPACE_LINEAR		EGL_VG_COLORSPACE_LINEAR
+#define EGL_ALPHA_FORMAT_NONPRE		EGL_VG_ALPHA_FORMAT_NONPRE
+#define EGL_ALPHA_FORMAT_PRE		EGL_VG_ALPHA_FORMAT_PRE
+
+/* EGL extensions must request enum blocks from the Khronos
+ * API Registrar, who maintains the enumerant registry. Submit
+ * a bug in Khronos Bugzilla against task "Registry".
+ */
+
+
+
+/* EGL Functions */
+
+EGLAPI EGLint EGLAPIENTRY eglGetError(void);
+
+EGLAPI EGLDisplay EGLAPIENTRY eglGetDisplay(EGLNativeDisplayType display_id);
+EGLAPI EGLBoolean EGLAPIENTRY eglInitialize(EGLDisplay dpy, EGLint *major, EGLint *minor);
+EGLAPI EGLBoolean EGLAPIENTRY eglTerminate(EGLDisplay dpy);
+
+EGLAPI const char * EGLAPIENTRY eglQueryString(EGLDisplay dpy, EGLint name);
+
+EGLAPI EGLBoolean EGLAPIENTRY eglGetConfigs(EGLDisplay dpy, EGLConfig *configs,
+			 EGLint config_size, EGLint *num_config);
+EGLAPI EGLBoolean EGLAPIENTRY eglChooseConfig(EGLDisplay dpy, const EGLint *attrib_list,
+			   EGLConfig *configs, EGLint config_size,
+			   EGLint *num_config);
+EGLAPI EGLBoolean EGLAPIENTRY eglGetConfigAttrib(EGLDisplay dpy, EGLConfig config,
+			      EGLint attribute, EGLint *value);
+
+EGLAPI EGLSurface EGLAPIENTRY eglCreateWindowSurface(EGLDisplay dpy, EGLConfig config,
+				  EGLNativeWindowType win,
+				  const EGLint *attrib_list);
+EGLAPI EGLSurface EGLAPIENTRY eglCreatePbufferSurface(EGLDisplay dpy, EGLConfig config,
+				   const EGLint *attrib_list);
+EGLAPI EGLSurface EGLAPIENTRY eglCreatePixmapSurface(EGLDisplay dpy, EGLConfig config,
+				  EGLNativePixmapType pixmap,
+				  const EGLint *attrib_list);
+EGLAPI EGLBoolean EGLAPIENTRY eglDestroySurface(EGLDisplay dpy, EGLSurface surface);
+EGLAPI EGLBoolean EGLAPIENTRY eglQuerySurface(EGLDisplay dpy, EGLSurface surface,
+			   EGLint attribute, EGLint *value);
+
+EGLAPI EGLBoolean EGLAPIENTRY eglBindAPI(EGLenum api);
+EGLAPI EGLenum EGLAPIENTRY eglQueryAPI(void);
+
+EGLAPI EGLBoolean EGLAPIENTRY eglWaitClient(void);
+
+EGLAPI EGLBoolean EGLAPIENTRY eglReleaseThread(void);
+
+EGLAPI EGLSurface EGLAPIENTRY eglCreatePbufferFromClientBuffer(
+	      EGLDisplay dpy, EGLenum buftype, EGLClientBuffer buffer,
+	      EGLConfig config, const EGLint *attrib_list);
+
+EGLAPI EGLBoolean EGLAPIENTRY eglSurfaceAttrib(EGLDisplay dpy, EGLSurface surface,
+			    EGLint attribute, EGLint value);
+EGLAPI EGLBoolean EGLAPIENTRY eglBindTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer);
+EGLAPI EGLBoolean EGLAPIENTRY eglReleaseTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer);
+
+
+EGLAPI EGLBoolean EGLAPIENTRY eglSwapInterval(EGLDisplay dpy, EGLint interval);
+
+
+EGLAPI EGLContext EGLAPIENTRY eglCreateContext(EGLDisplay dpy, EGLConfig config,
+			    EGLContext share_context,
+			    const EGLint *attrib_list);
+EGLAPI EGLBoolean EGLAPIENTRY eglDestroyContext(EGLDisplay dpy, EGLContext ctx);
+EGLAPI EGLBoolean EGLAPIENTRY eglMakeCurrent(EGLDisplay dpy, EGLSurface draw,
+			  EGLSurface read, EGLContext ctx);
+
+EGLAPI EGLContext EGLAPIENTRY eglGetCurrentContext(void);
+EGLAPI EGLSurface EGLAPIENTRY eglGetCurrentSurface(EGLint readdraw);
+EGLAPI EGLDisplay EGLAPIENTRY eglGetCurrentDisplay(void);
+EGLAPI EGLBoolean EGLAPIENTRY eglQueryContext(EGLDisplay dpy, EGLContext ctx,
+			   EGLint attribute, EGLint *value);
+
+EGLAPI EGLBoolean EGLAPIENTRY eglWaitGL(void);
+EGLAPI EGLBoolean EGLAPIENTRY eglWaitNative(EGLint engine);
+EGLAPI EGLBoolean EGLAPIENTRY eglSwapBuffers(EGLDisplay dpy, EGLSurface surface);
+EGLAPI EGLBoolean EGLAPIENTRY eglCopyBuffers(EGLDisplay dpy, EGLSurface surface,
+			  EGLNativePixmapType target);
+
+/* This is a generic function pointer type, whose name indicates it must
+ * be cast to the proper type *and calling convention* before use.
+ */
+typedef void (*__eglMustCastToProperFunctionPointerType)(void);
+
+/* Now, define eglGetProcAddress using the generic function ptr. type */
+EGLAPI __eglMustCastToProperFunctionPointerType EGLAPIENTRY
+       eglGetProcAddress(const char *procname);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __egl_h_ */
diff --git a/src/GLES2/include/EGL/eglext.h b/src/GLES2/include/EGL/eglext.h
new file mode 100644
index 0000000..b670840
--- /dev/null
+++ b/src/GLES2/include/EGL/eglext.h
@@ -0,0 +1,348 @@
+#ifndef __eglext_h_
+#define __eglext_h_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+** Copyright (c) 2007-2012 The Khronos Group Inc.
+**
+** Permission is hereby granted, free of charge, to any person obtaining a
+** copy of this software and/or associated documentation files (the
+** "Materials"), to deal in the Materials without restriction, including
+** without limitation the rights to use, copy, modify, merge, publish,
+** distribute, sublicense, and/or sell copies of the Materials, and to
+** permit persons to whom the Materials are furnished to do so, subject to
+** the following conditions:
+**
+** The above copyright notice and this permission notice shall be included
+** in all copies or substantial portions of the Materials.
+**
+** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+*/
+
+#include <EGL/eglplatform.h>
+
+/*************************************************************/
+
+/* Header file version number */
+/* Current version at http://www.khronos.org/registry/egl/ */
+/* $Revision: 16473 $ on $Date: 2012-01-04 02:20:48 -0800 (Wed, 04 Jan 2012) $ */
+#define EGL_EGLEXT_VERSION 11
+
+#ifndef EGL_KHR_config_attribs
+#define EGL_KHR_config_attribs 1
+#define EGL_CONFORMANT_KHR			0x3042	/* EGLConfig attribute */
+#define EGL_VG_COLORSPACE_LINEAR_BIT_KHR	0x0020	/* EGL_SURFACE_TYPE bitfield */
+#define EGL_VG_ALPHA_FORMAT_PRE_BIT_KHR		0x0040	/* EGL_SURFACE_TYPE bitfield */
+#endif
+
+#ifndef EGL_KHR_lock_surface
+#define EGL_KHR_lock_surface 1
+#define EGL_READ_SURFACE_BIT_KHR		0x0001	/* EGL_LOCK_USAGE_HINT_KHR bitfield */
+#define EGL_WRITE_SURFACE_BIT_KHR		0x0002	/* EGL_LOCK_USAGE_HINT_KHR bitfield */
+#define EGL_LOCK_SURFACE_BIT_KHR		0x0080	/* EGL_SURFACE_TYPE bitfield */
+#define EGL_OPTIMAL_FORMAT_BIT_KHR		0x0100	/* EGL_SURFACE_TYPE bitfield */
+#define EGL_MATCH_FORMAT_KHR			0x3043	/* EGLConfig attribute */
+#define EGL_FORMAT_RGB_565_EXACT_KHR		0x30C0	/* EGL_MATCH_FORMAT_KHR value */
+#define EGL_FORMAT_RGB_565_KHR			0x30C1	/* EGL_MATCH_FORMAT_KHR value */
+#define EGL_FORMAT_RGBA_8888_EXACT_KHR		0x30C2	/* EGL_MATCH_FORMAT_KHR value */
+#define EGL_FORMAT_RGBA_8888_KHR		0x30C3	/* EGL_MATCH_FORMAT_KHR value */
+#define EGL_MAP_PRESERVE_PIXELS_KHR		0x30C4	/* eglLockSurfaceKHR attribute */
+#define EGL_LOCK_USAGE_HINT_KHR			0x30C5	/* eglLockSurfaceKHR attribute */
+#define EGL_BITMAP_POINTER_KHR			0x30C6	/* eglQuerySurface attribute */
+#define EGL_BITMAP_PITCH_KHR			0x30C7	/* eglQuerySurface attribute */
+#define EGL_BITMAP_ORIGIN_KHR			0x30C8	/* eglQuerySurface attribute */
+#define EGL_BITMAP_PIXEL_RED_OFFSET_KHR		0x30C9	/* eglQuerySurface attribute */
+#define EGL_BITMAP_PIXEL_GREEN_OFFSET_KHR	0x30CA	/* eglQuerySurface attribute */
+#define EGL_BITMAP_PIXEL_BLUE_OFFSET_KHR	0x30CB	/* eglQuerySurface attribute */
+#define EGL_BITMAP_PIXEL_ALPHA_OFFSET_KHR	0x30CC	/* eglQuerySurface attribute */
+#define EGL_BITMAP_PIXEL_LUMINANCE_OFFSET_KHR	0x30CD	/* eglQuerySurface attribute */
+#define EGL_LOWER_LEFT_KHR			0x30CE	/* EGL_BITMAP_ORIGIN_KHR value */
+#define EGL_UPPER_LEFT_KHR			0x30CF	/* EGL_BITMAP_ORIGIN_KHR value */
+#ifdef EGL_EGLEXT_PROTOTYPES
+EGLAPI EGLBoolean EGLAPIENTRY eglLockSurfaceKHR (EGLDisplay display, EGLSurface surface, const EGLint *attrib_list);
+EGLAPI EGLBoolean EGLAPIENTRY eglUnlockSurfaceKHR (EGLDisplay display, EGLSurface surface);
+#endif /* EGL_EGLEXT_PROTOTYPES */
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLLOCKSURFACEKHRPROC) (EGLDisplay display, EGLSurface surface, const EGLint *attrib_list);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLUNLOCKSURFACEKHRPROC) (EGLDisplay display, EGLSurface surface);
+#endif
+
+#ifndef EGL_KHR_image
+#define EGL_KHR_image 1
+#define EGL_NATIVE_PIXMAP_KHR			0x30B0	/* eglCreateImageKHR target */
+typedef void *EGLImageKHR;
+#define EGL_NO_IMAGE_KHR			((EGLImageKHR)0)
+#ifdef EGL_EGLEXT_PROTOTYPES
+EGLAPI EGLImageKHR EGLAPIENTRY eglCreateImageKHR (EGLDisplay dpy, EGLContext ctx, EGLenum target, EGLClientBuffer buffer, const EGLint *attrib_list);
+EGLAPI EGLBoolean EGLAPIENTRY eglDestroyImageKHR (EGLDisplay dpy, EGLImageKHR image);
+#endif /* EGL_EGLEXT_PROTOTYPES */
+typedef EGLImageKHR (EGLAPIENTRYP PFNEGLCREATEIMAGEKHRPROC) (EGLDisplay dpy, EGLContext ctx, EGLenum target, EGLClientBuffer buffer, const EGLint *attrib_list);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLDESTROYIMAGEKHRPROC) (EGLDisplay dpy, EGLImageKHR image);
+#endif
+
+#ifndef EGL_KHR_vg_parent_image
+#define EGL_KHR_vg_parent_image 1
+#define EGL_VG_PARENT_IMAGE_KHR			0x30BA	/* eglCreateImageKHR target */
+#endif
+
+#ifndef EGL_KHR_gl_texture_2D_image
+#define EGL_KHR_gl_texture_2D_image 1
+#define EGL_GL_TEXTURE_2D_KHR			0x30B1	/* eglCreateImageKHR target */
+#define EGL_GL_TEXTURE_LEVEL_KHR		0x30BC	/* eglCreateImageKHR attribute */
+#endif
+
+#ifndef EGL_KHR_gl_texture_cubemap_image
+#define EGL_KHR_gl_texture_cubemap_image 1
+#define EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X_KHR	0x30B3	/* eglCreateImageKHR target */
+#define EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_X_KHR	0x30B4	/* eglCreateImageKHR target */
+#define EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Y_KHR	0x30B5	/* eglCreateImageKHR target */
+#define EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_KHR	0x30B6	/* eglCreateImageKHR target */
+#define EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Z_KHR	0x30B7	/* eglCreateImageKHR target */
+#define EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_KHR	0x30B8	/* eglCreateImageKHR target */
+#endif
+
+#ifndef EGL_KHR_gl_texture_3D_image
+#define EGL_KHR_gl_texture_3D_image 1
+#define EGL_GL_TEXTURE_3D_KHR			0x30B2	/* eglCreateImageKHR target */
+#define EGL_GL_TEXTURE_ZOFFSET_KHR		0x30BD	/* eglCreateImageKHR attribute */
+#endif
+
+#ifndef EGL_KHR_gl_renderbuffer_image
+#define EGL_KHR_gl_renderbuffer_image 1
+#define EGL_GL_RENDERBUFFER_KHR			0x30B9	/* eglCreateImageKHR target */
+#endif
+
+#if KHRONOS_SUPPORT_INT64   /* EGLTimeKHR requires 64-bit uint support */
+#ifndef EGL_KHR_reusable_sync
+#define EGL_KHR_reusable_sync 1
+
+typedef void* EGLSyncKHR;
+typedef khronos_utime_nanoseconds_t EGLTimeKHR;
+
+#define EGL_SYNC_STATUS_KHR			0x30F1
+#define EGL_SIGNALED_KHR			0x30F2
+#define EGL_UNSIGNALED_KHR			0x30F3
+#define EGL_TIMEOUT_EXPIRED_KHR			0x30F5
+#define EGL_CONDITION_SATISFIED_KHR		0x30F6
+#define EGL_SYNC_TYPE_KHR			0x30F7
+#define EGL_SYNC_REUSABLE_KHR			0x30FA
+#define EGL_SYNC_FLUSH_COMMANDS_BIT_KHR		0x0001	/* eglClientWaitSyncKHR <flags> bitfield */
+#define EGL_FOREVER_KHR				0xFFFFFFFFFFFFFFFFull
+#define EGL_NO_SYNC_KHR				((EGLSyncKHR)0)
+#ifdef EGL_EGLEXT_PROTOTYPES
+EGLAPI EGLSyncKHR EGLAPIENTRY eglCreateSyncKHR(EGLDisplay dpy, EGLenum type, const EGLint *attrib_list);
+EGLAPI EGLBoolean EGLAPIENTRY eglDestroySyncKHR(EGLDisplay dpy, EGLSyncKHR sync);
+EGLAPI EGLint EGLAPIENTRY eglClientWaitSyncKHR(EGLDisplay dpy, EGLSyncKHR sync, EGLint flags, EGLTimeKHR timeout);
+EGLAPI EGLBoolean EGLAPIENTRY eglSignalSyncKHR(EGLDisplay dpy, EGLSyncKHR sync, EGLenum mode);
+EGLAPI EGLBoolean EGLAPIENTRY eglGetSyncAttribKHR(EGLDisplay dpy, EGLSyncKHR sync, EGLint attribute, EGLint *value);
+#endif /* EGL_EGLEXT_PROTOTYPES */
+typedef EGLSyncKHR (EGLAPIENTRYP PFNEGLCREATESYNCKHRPROC) (EGLDisplay dpy, EGLenum type, const EGLint *attrib_list);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLDESTROYSYNCKHRPROC) (EGLDisplay dpy, EGLSyncKHR sync);
+typedef EGLint (EGLAPIENTRYP PFNEGLCLIENTWAITSYNCKHRPROC) (EGLDisplay dpy, EGLSyncKHR sync, EGLint flags, EGLTimeKHR timeout);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLSIGNALSYNCKHRPROC) (EGLDisplay dpy, EGLSyncKHR sync, EGLenum mode);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLGETSYNCATTRIBKHRPROC) (EGLDisplay dpy, EGLSyncKHR sync, EGLint attribute, EGLint *value);
+#endif
+#endif
+
+#ifndef EGL_KHR_image_base
+#define EGL_KHR_image_base 1
+/* Most interfaces defined by EGL_KHR_image_pixmap above */
+#define EGL_IMAGE_PRESERVED_KHR			0x30D2	/* eglCreateImageKHR attribute */
+#endif
+
+#ifndef EGL_KHR_image_pixmap
+#define EGL_KHR_image_pixmap 1
+/* Interfaces defined by EGL_KHR_image above */
+#endif
+
+#ifndef EGL_IMG_context_priority
+#define EGL_IMG_context_priority 1
+#define EGL_CONTEXT_PRIORITY_LEVEL_IMG		0x3100
+#define EGL_CONTEXT_PRIORITY_HIGH_IMG		0x3101
+#define EGL_CONTEXT_PRIORITY_MEDIUM_IMG		0x3102
+#define EGL_CONTEXT_PRIORITY_LOW_IMG		0x3103
+#endif
+
+#ifndef EGL_KHR_lock_surface2
+#define EGL_KHR_lock_surface2 1
+#define EGL_BITMAP_PIXEL_SIZE_KHR		0x3110
+#endif
+
+#ifndef EGL_NV_coverage_sample
+#define EGL_NV_coverage_sample 1
+#define EGL_COVERAGE_BUFFERS_NV			0x30E0
+#define EGL_COVERAGE_SAMPLES_NV			0x30E1
+#endif
+
+#ifndef EGL_NV_depth_nonlinear
+#define EGL_NV_depth_nonlinear 1
+#define EGL_DEPTH_ENCODING_NV			0x30E2
+#define EGL_DEPTH_ENCODING_NONE_NV 0
+#define EGL_DEPTH_ENCODING_NONLINEAR_NV		0x30E3
+#endif
+
+#if KHRONOS_SUPPORT_INT64   /* EGLTimeNV requires 64-bit uint support */
+#ifndef EGL_NV_sync
+#define EGL_NV_sync 1
+#define EGL_SYNC_PRIOR_COMMANDS_COMPLETE_NV	0x30E6
+#define EGL_SYNC_STATUS_NV			0x30E7
+#define EGL_SIGNALED_NV				0x30E8
+#define EGL_UNSIGNALED_NV			0x30E9
+#define EGL_SYNC_FLUSH_COMMANDS_BIT_NV		0x0001
+#define EGL_FOREVER_NV				0xFFFFFFFFFFFFFFFFull
+#define EGL_ALREADY_SIGNALED_NV			0x30EA
+#define EGL_TIMEOUT_EXPIRED_NV			0x30EB
+#define EGL_CONDITION_SATISFIED_NV		0x30EC
+#define EGL_SYNC_TYPE_NV			0x30ED
+#define EGL_SYNC_CONDITION_NV			0x30EE
+#define EGL_SYNC_FENCE_NV			0x30EF
+#define EGL_NO_SYNC_NV				((EGLSyncNV)0)
+typedef void* EGLSyncNV;
+typedef khronos_utime_nanoseconds_t EGLTimeNV;
+#ifdef EGL_EGLEXT_PROTOTYPES
+EGLSyncNV eglCreateFenceSyncNV (EGLDisplay dpy, EGLenum condition, const EGLint *attrib_list);
+EGLBoolean eglDestroySyncNV (EGLSyncNV sync);
+EGLBoolean eglFenceNV (EGLSyncNV sync);
+EGLint eglClientWaitSyncNV (EGLSyncNV sync, EGLint flags, EGLTimeNV timeout);
+EGLBoolean eglSignalSyncNV (EGLSyncNV sync, EGLenum mode);
+EGLBoolean eglGetSyncAttribNV (EGLSyncNV sync, EGLint attribute, EGLint *value);
+#endif /* EGL_EGLEXT_PROTOTYPES */
+typedef EGLSyncNV (EGLAPIENTRYP PFNEGLCREATEFENCESYNCNVPROC) (EGLDisplay dpy, EGLenum condition, const EGLint *attrib_list);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLDESTROYSYNCNVPROC) (EGLSyncNV sync);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLFENCENVPROC) (EGLSyncNV sync);
+typedef EGLint (EGLAPIENTRYP PFNEGLCLIENTWAITSYNCNVPROC) (EGLSyncNV sync, EGLint flags, EGLTimeNV timeout);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLSIGNALSYNCNVPROC) (EGLSyncNV sync, EGLenum mode);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLGETSYNCATTRIBNVPROC) (EGLSyncNV sync, EGLint attribute, EGLint *value);
+#endif
+#endif
+
+#if KHRONOS_SUPPORT_INT64   /* Dependent on EGL_KHR_reusable_sync which requires 64-bit uint support */
+#ifndef EGL_KHR_fence_sync
+#define EGL_KHR_fence_sync 1
+/* Reuses most tokens and entry points from EGL_KHR_reusable_sync */
+#define EGL_SYNC_PRIOR_COMMANDS_COMPLETE_KHR	0x30F0
+#define EGL_SYNC_CONDITION_KHR			0x30F8
+#define EGL_SYNC_FENCE_KHR			0x30F9
+#endif
+#endif
+
+#ifndef EGL_HI_clientpixmap
+#define EGL_HI_clientpixmap 1
+
+/* Surface Attribute */
+#define EGL_CLIENT_PIXMAP_POINTER_HI		0x8F74
+/*
+ * Structure representing a client pixmap
+ * (pixmap's data is in client-space memory).
+ */
+struct EGLClientPixmapHI
+{
+	void*		pData;
+	EGLint		iWidth;
+	EGLint		iHeight;
+	EGLint		iStride;
+};
+
+#ifdef EGL_EGLEXT_PROTOTYPES
+EGLAPI EGLSurface EGLAPIENTRY eglCreatePixmapSurfaceHI(EGLDisplay dpy, EGLConfig config, struct EGLClientPixmapHI* pixmap);
+#endif /* EGL_EGLEXT_PROTOTYPES */
+typedef EGLSurface (EGLAPIENTRYP PFNEGLCREATEPIXMAPSURFACEHIPROC) (EGLDisplay dpy, EGLConfig config, struct EGLClientPixmapHI* pixmap);
+#endif	/* EGL_HI_clientpixmap */
+
+#ifndef EGL_HI_colorformats
+#define EGL_HI_colorformats 1
+/* Config Attribute */
+#define EGL_COLOR_FORMAT_HI			0x8F70
+/* Color Formats */
+#define EGL_COLOR_RGB_HI			0x8F71
+#define EGL_COLOR_RGBA_HI			0x8F72
+#define EGL_COLOR_ARGB_HI			0x8F73
+#endif /* EGL_HI_colorformats */
+
+#ifndef EGL_MESA_drm_image
+#define EGL_MESA_drm_image 1
+#define EGL_DRM_BUFFER_FORMAT_MESA		0x31D0	    /* CreateDRMImageMESA attribute */
+#define EGL_DRM_BUFFER_USE_MESA			0x31D1	    /* CreateDRMImageMESA attribute */
+#define EGL_DRM_BUFFER_FORMAT_ARGB32_MESA	0x31D2	    /* EGL_IMAGE_FORMAT_MESA attribute value */
+#define EGL_DRM_BUFFER_MESA			0x31D3	    /* eglCreateImageKHR target */
+#define EGL_DRM_BUFFER_STRIDE_MESA		0x31D4
+#define EGL_DRM_BUFFER_USE_SCANOUT_MESA		0x00000001  /* EGL_DRM_BUFFER_USE_MESA bits */
+#define EGL_DRM_BUFFER_USE_SHARE_MESA		0x00000002  /* EGL_DRM_BUFFER_USE_MESA bits */
+#ifdef EGL_EGLEXT_PROTOTYPES
+EGLAPI EGLImageKHR EGLAPIENTRY eglCreateDRMImageMESA (EGLDisplay dpy, const EGLint *attrib_list);
+EGLAPI EGLBoolean EGLAPIENTRY eglExportDRMImageMESA (EGLDisplay dpy, EGLImageKHR image, EGLint *name, EGLint *handle, EGLint *stride);
+#endif /* EGL_EGLEXT_PROTOTYPES */
+typedef EGLImageKHR (EGLAPIENTRYP PFNEGLCREATEDRMIMAGEMESAPROC) (EGLDisplay dpy, const EGLint *attrib_list);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLEXPORTDRMIMAGEMESAPROC) (EGLDisplay dpy, EGLImageKHR image, EGLint *name, EGLint *handle, EGLint *stride);
+#endif
+
+#ifndef EGL_NV_post_sub_buffer
+#define EGL_NV_post_sub_buffer 1
+#define EGL_POST_SUB_BUFFER_SUPPORTED_NV	0x30BE
+#ifdef EGL_EGLEXT_PROTOTYPES
+EGLAPI EGLBoolean EGLAPIENTRY eglPostSubBufferNV (EGLDisplay dpy, EGLSurface surface, EGLint x, EGLint y, EGLint width, EGLint height);
+#endif /* EGL_EGLEXT_PROTOTYPES */
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLPOSTSUBBUFFERNVPROC) (EGLDisplay dpy, EGLSurface surface, EGLint x, EGLint y, EGLint width, EGLint height);
+#endif
+
+#ifndef EGL_ANGLE_query_surface_pointer
+#define EGL_ANGLE_query_surface_pointer 1
+#ifdef EGL_EGLEXT_PROTOTYPES
+EGLAPI EGLBoolean eglQuerySurfacePointerANGLE(EGLDisplay dpy, EGLSurface surface, EGLint attribute, void **value);
+#endif
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYSURFACEPOINTERANGLEPROC) (EGLDisplay dpy, EGLSurface surface, EGLint attribute, void **value);
+#endif
+
+#ifndef EGL_ANGLE_software_display
+#define EGL_ANGLE_software_display 1
+#define EGL_SOFTWARE_DISPLAY_ANGLE ((EGLNativeDisplayType)-1)
+#endif
+
+#ifndef EGL_ANGLE_surface_d3d_texture_2d_share_handle
+#define EGL_ANGLE_surface_d3d_texture_2d_share_handle 1
+#define EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE	0x3200
+#endif
+
+#ifndef EGL_NV_coverage_sample_resolve
+#define EGL_NV_coverage_sample_resolve 1
+#define EGL_COVERAGE_SAMPLE_RESOLVE_NV		0x3131
+#define EGL_COVERAGE_SAMPLE_RESOLVE_DEFAULT_NV	0x3132
+#define EGL_COVERAGE_SAMPLE_RESOLVE_NONE_NV	0x3133
+#endif
+
+#if KHRONOS_SUPPORT_INT64   /* EGLTimeKHR requires 64-bit uint support */
+#ifndef EGL_NV_system_time
+#define EGL_NV_system_time 1
+
+typedef khronos_utime_nanoseconds_t EGLuint64NV;
+
+#ifdef EGL_EGLEXT_PROTOTYPES
+EGLAPI EGLuint64NV EGLAPIENTRY eglGetSystemTimeFrequencyNV(void);
+EGLAPI EGLuint64NV EGLAPIENTRY eglGetSystemTimeNV(void);
+#endif /* EGL_EGLEXT_PROTOTYPES */
+typedef EGLuint64NV (EGLAPIENTRYP PFNEGLGETSYSTEMTIMEFREQUENCYNVPROC) (void);
+typedef EGLuint64NV (EGLAPIENTRYP PFNEGLGETSYSTEMTIMENVPROC) (void);
+#endif
+#endif
+
+#ifndef EGL_EXT_create_context_robustness
+#define EGL_EXT_create_context_robustness 1
+#define EGL_CONTEXT_OPENGL_ROBUST_ACCESS_EXT	0x30BF
+#define EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_EXT 0x3138
+#define EGL_NO_RESET_NOTIFICATION_EXT		0x31BE
+#define EGL_LOSE_CONTEXT_ON_RESET_EXT		0x31BF
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/GLES2/include/EGL/eglplatform.h b/src/GLES2/include/EGL/eglplatform.h
new file mode 100644
index 0000000..34283f2
--- /dev/null
+++ b/src/GLES2/include/EGL/eglplatform.h
@@ -0,0 +1,129 @@
+#ifndef __eglplatform_h_
+#define __eglplatform_h_
+
+/*
+** Copyright (c) 2007-2009 The Khronos Group Inc.
+**
+** Permission is hereby granted, free of charge, to any person obtaining a
+** copy of this software and/or associated documentation files (the
+** "Materials"), to deal in the Materials without restriction, including
+** without limitation the rights to use, copy, modify, merge, publish,
+** distribute, sublicense, and/or sell copies of the Materials, and to
+** permit persons to whom the Materials are furnished to do so, subject to
+** the following conditions:
+**
+** The above copyright notice and this permission notice shall be included
+** in all copies or substantial portions of the Materials.
+**
+** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+*/
+
+/* Platform-specific types and definitions for egl.h
+ * $Revision: 12306 $ on $Date: 2010-08-25 09:51:28 -0700 (Wed, 25 Aug 2010) $
+ *
+ * Adopters may modify khrplatform.h and this file to suit their platform.
+ * You are encouraged to submit all modifications to the Khronos group so that
+ * they can be included in future versions of this file.  Please submit changes
+ * by sending them to the public Khronos Bugzilla (http://khronos.org/bugzilla)
+ * by filing a bug against product "EGL" component "Registry".
+ */
+
+#include <KHR/khrplatform.h>
+
+/* Macros used in EGL function prototype declarations.
+ *
+ * EGL functions should be prototyped as:
+ *
+ * EGLAPI return-type EGLAPIENTRY eglFunction(arguments);
+ * typedef return-type (EXPAPIENTRYP PFNEGLFUNCTIONPROC) (arguments);
+ *
+ * KHRONOS_APICALL and KHRONOS_APIENTRY are defined in KHR/khrplatform.h
+ */
+
+#ifndef EGLAPI
+#define EGLAPI KHRONOS_APICALL
+#endif
+
+#ifndef EGLAPIENTRY
+#define EGLAPIENTRY  KHRONOS_APIENTRY
+#endif
+#define EGLAPIENTRYP EGLAPIENTRY*
+
+/* The types NativeDisplayType, NativeWindowType, and NativePixmapType
+ * are aliases of window-system-dependent types, such as X Display * or
+ * Windows Device Context. They must be defined in platform-specific
+ * code below. The EGL-prefixed versions of Native*Type are the same
+ * types, renamed in EGL 1.3 so all types in the API start with "EGL".
+ *
+ * Khronos STRONGLY RECOMMENDS that you use the default definitions
+ * provided below, since these changes affect both binary and source
+ * portability of applications using EGL running on different EGL
+ * implementations.
+ */
+
+#if defined(_WIN32) || defined(__VC32__) && !defined(__CYGWIN__) && !defined(__SCITECH_SNAP__) /* Win32 and WinCE */
+#ifndef WIN32_LEAN_AND_MEAN
+#define WIN32_LEAN_AND_MEAN 1
+#endif
+#include <windows.h>
+
+typedef HDC     EGLNativeDisplayType;
+typedef HBITMAP EGLNativePixmapType;
+typedef HWND    EGLNativeWindowType;
+
+#elif defined(__WINSCW__) || defined(__SYMBIAN32__)  /* Symbian */
+
+typedef int   EGLNativeDisplayType;
+typedef void *EGLNativeWindowType;
+typedef void *EGLNativePixmapType;
+
+#elif defined(WL_EGL_PLATFORM)
+
+typedef struct wl_display     *EGLNativeDisplayType;
+typedef struct wl_egl_pixmap  *EGLNativePixmapType;
+typedef struct wl_egl_window  *EGLNativeWindowType;
+
+#elif defined(__unix__) && !defined(ANDROID)
+
+/* X11 (tentative)  */
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+
+typedef Display *EGLNativeDisplayType;
+typedef Pixmap   EGLNativePixmapType;
+typedef Window   EGLNativeWindowType;
+
+#elif defined(ANDROID)
+
+struct egl_native_pixmap_t;
+
+typedef struct ANativeWindow*           EGLNativeWindowType;
+typedef struct egl_native_pixmap_t*     EGLNativePixmapType;
+typedef void*                           EGLNativeDisplayType;
+
+#else
+#error "Platform not recognized"
+#endif
+
+/* EGL 1.2 types, renamed for consistency in EGL 1.3 */
+typedef EGLNativeDisplayType NativeDisplayType;
+typedef EGLNativePixmapType  NativePixmapType;
+typedef EGLNativeWindowType  NativeWindowType;
+
+
+/* Define EGLint. This must be a signed integral type large enough to contain
+ * all legal attribute names and values passed into and out of EGL, whether
+ * their type is boolean, bitmask, enumerant (symbolic constant), integer,
+ * handle, or other.  While in general a 32-bit integer will suffice, if
+ * handles are 64 bit types, then EGLint should be defined as a signed 64-bit
+ * integer type.
+ */
+typedef khronos_int32_t EGLint;
+
+#endif /* __eglplatform_h */
diff --git a/src/GLES2/include/GLES2/gl2.h b/src/GLES2/include/GLES2/gl2.h
new file mode 100644
index 0000000..e1d3b87
--- /dev/null
+++ b/src/GLES2/include/GLES2/gl2.h
@@ -0,0 +1,621 @@
+#ifndef __gl2_h_
+#define __gl2_h_
+
+/* $Revision: 10602 $ on $Date:: 2010-03-04 22:35:34 -0800 #$ */
+
+#include <GLES2/gl2platform.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * This document is licensed under the SGI Free Software B License Version
+ * 2.0. For details, see http://oss.sgi.com/projects/FreeB/ .
+ */
+
+/*-------------------------------------------------------------------------
+ * Data type definitions
+ *-----------------------------------------------------------------------*/
+
+typedef void             GLvoid;
+typedef char             GLchar;
+typedef unsigned int     GLenum;
+typedef unsigned char    GLboolean;
+typedef unsigned int     GLbitfield;
+typedef khronos_int8_t   GLbyte;
+typedef short            GLshort;
+typedef int              GLint;
+typedef int              GLsizei;
+typedef khronos_uint8_t  GLubyte;
+typedef unsigned short   GLushort;
+typedef unsigned int     GLuint;
+typedef khronos_float_t  GLfloat;
+typedef khronos_float_t  GLclampf;
+typedef khronos_int32_t  GLfixed;
+
+/* GL types for handling large vertex buffer objects */
+typedef khronos_intptr_t GLintptr;
+typedef khronos_ssize_t  GLsizeiptr;
+
+/* OpenGL ES core versions */
+#define GL_ES_VERSION_2_0                 1
+
+/* ClearBufferMask */
+#define GL_DEPTH_BUFFER_BIT               0x00000100
+#define GL_STENCIL_BUFFER_BIT             0x00000400
+#define GL_COLOR_BUFFER_BIT               0x00004000
+
+/* Boolean */
+#define GL_FALSE                          0
+#define GL_TRUE                           1
+
+/* BeginMode */
+#define GL_POINTS                         0x0000
+#define GL_LINES                          0x0001
+#define GL_LINE_LOOP                      0x0002
+#define GL_LINE_STRIP                     0x0003
+#define GL_TRIANGLES                      0x0004
+#define GL_TRIANGLE_STRIP                 0x0005
+#define GL_TRIANGLE_FAN                   0x0006
+
+/* AlphaFunction (not supported in ES20) */
+/*      GL_NEVER */
+/*      GL_LESS */
+/*      GL_EQUAL */
+/*      GL_LEQUAL */
+/*      GL_GREATER */
+/*      GL_NOTEQUAL */
+/*      GL_GEQUAL */
+/*      GL_ALWAYS */
+
+/* BlendingFactorDest */
+#define GL_ZERO                           0
+#define GL_ONE                            1
+#define GL_SRC_COLOR                      0x0300
+#define GL_ONE_MINUS_SRC_COLOR            0x0301
+#define GL_SRC_ALPHA                      0x0302
+#define GL_ONE_MINUS_SRC_ALPHA            0x0303
+#define GL_DST_ALPHA                      0x0304
+#define GL_ONE_MINUS_DST_ALPHA            0x0305
+
+/* BlendingFactorSrc */
+/*      GL_ZERO */
+/*      GL_ONE */
+#define GL_DST_COLOR                      0x0306
+#define GL_ONE_MINUS_DST_COLOR            0x0307
+#define GL_SRC_ALPHA_SATURATE             0x0308
+/*      GL_SRC_ALPHA */
+/*      GL_ONE_MINUS_SRC_ALPHA */
+/*      GL_DST_ALPHA */
+/*      GL_ONE_MINUS_DST_ALPHA */
+
+/* BlendEquationSeparate */
+#define GL_FUNC_ADD                       0x8006
+#define GL_BLEND_EQUATION                 0x8009
+#define GL_BLEND_EQUATION_RGB             0x8009    /* same as BLEND_EQUATION */
+#define GL_BLEND_EQUATION_ALPHA           0x883D
+
+/* BlendSubtract */
+#define GL_FUNC_SUBTRACT                  0x800A
+#define GL_FUNC_REVERSE_SUBTRACT          0x800B
+
+/* Separate Blend Functions */
+#define GL_BLEND_DST_RGB                  0x80C8
+#define GL_BLEND_SRC_RGB                  0x80C9
+#define GL_BLEND_DST_ALPHA                0x80CA
+#define GL_BLEND_SRC_ALPHA                0x80CB
+#define GL_CONSTANT_COLOR                 0x8001
+#define GL_ONE_MINUS_CONSTANT_COLOR       0x8002
+#define GL_CONSTANT_ALPHA                 0x8003
+#define GL_ONE_MINUS_CONSTANT_ALPHA       0x8004
+#define GL_BLEND_COLOR                    0x8005
+
+/* Buffer Objects */
+#define GL_ARRAY_BUFFER                   0x8892
+#define GL_ELEMENT_ARRAY_BUFFER           0x8893
+#define GL_ARRAY_BUFFER_BINDING           0x8894
+#define GL_ELEMENT_ARRAY_BUFFER_BINDING   0x8895
+
+#define GL_STREAM_DRAW                    0x88E0
+#define GL_STATIC_DRAW                    0x88E4
+#define GL_DYNAMIC_DRAW                   0x88E8
+
+#define GL_BUFFER_SIZE                    0x8764
+#define GL_BUFFER_USAGE                   0x8765
+
+#define GL_CURRENT_VERTEX_ATTRIB          0x8626
+
+/* CullFaceMode */
+#define GL_FRONT                          0x0404
+#define GL_BACK                           0x0405
+#define GL_FRONT_AND_BACK                 0x0408
+
+/* DepthFunction */
+/*      GL_NEVER */
+/*      GL_LESS */
+/*      GL_EQUAL */
+/*      GL_LEQUAL */
+/*      GL_GREATER */
+/*      GL_NOTEQUAL */
+/*      GL_GEQUAL */
+/*      GL_ALWAYS */
+
+/* EnableCap */
+#define GL_TEXTURE_2D                     0x0DE1
+#define GL_CULL_FACE                      0x0B44
+#define GL_BLEND                          0x0BE2
+#define GL_DITHER                         0x0BD0
+#define GL_STENCIL_TEST                   0x0B90
+#define GL_DEPTH_TEST                     0x0B71
+#define GL_SCISSOR_TEST                   0x0C11
+#define GL_POLYGON_OFFSET_FILL            0x8037
+#define GL_SAMPLE_ALPHA_TO_COVERAGE       0x809E
+#define GL_SAMPLE_COVERAGE                0x80A0
+
+/* ErrorCode */
+#define GL_NO_ERROR                       0
+#define GL_INVALID_ENUM                   0x0500
+#define GL_INVALID_VALUE                  0x0501
+#define GL_INVALID_OPERATION              0x0502
+#define GL_OUT_OF_MEMORY                  0x0505
+
+/* FrontFaceDirection */
+#define GL_CW                             0x0900
+#define GL_CCW                            0x0901
+
+/* GetPName */
+#define GL_LINE_WIDTH                     0x0B21
+#define GL_ALIASED_POINT_SIZE_RANGE       0x846D
+#define GL_ALIASED_LINE_WIDTH_RANGE       0x846E
+#define GL_CULL_FACE_MODE                 0x0B45
+#define GL_FRONT_FACE                     0x0B46
+#define GL_DEPTH_RANGE                    0x0B70
+#define GL_DEPTH_WRITEMASK                0x0B72
+#define GL_DEPTH_CLEAR_VALUE              0x0B73
+#define GL_DEPTH_FUNC                     0x0B74
+#define GL_STENCIL_CLEAR_VALUE            0x0B91
+#define GL_STENCIL_FUNC                   0x0B92
+#define GL_STENCIL_FAIL                   0x0B94
+#define GL_STENCIL_PASS_DEPTH_FAIL        0x0B95
+#define GL_STENCIL_PASS_DEPTH_PASS        0x0B96
+#define GL_STENCIL_REF                    0x0B97
+#define GL_STENCIL_VALUE_MASK             0x0B93
+#define GL_STENCIL_WRITEMASK              0x0B98
+#define GL_STENCIL_BACK_FUNC              0x8800
+#define GL_STENCIL_BACK_FAIL              0x8801
+#define GL_STENCIL_BACK_PASS_DEPTH_FAIL   0x8802
+#define GL_STENCIL_BACK_PASS_DEPTH_PASS   0x8803
+#define GL_STENCIL_BACK_REF               0x8CA3
+#define GL_STENCIL_BACK_VALUE_MASK        0x8CA4
+#define GL_STENCIL_BACK_WRITEMASK         0x8CA5
+#define GL_VIEWPORT                       0x0BA2
+#define GL_SCISSOR_BOX                    0x0C10
+/*      GL_SCISSOR_TEST */
+#define GL_COLOR_CLEAR_VALUE              0x0C22
+#define GL_COLOR_WRITEMASK                0x0C23
+#define GL_UNPACK_ALIGNMENT               0x0CF5
+#define GL_PACK_ALIGNMENT                 0x0D05
+#define GL_MAX_TEXTURE_SIZE               0x0D33
+#define GL_MAX_VIEWPORT_DIMS              0x0D3A
+#define GL_SUBPIXEL_BITS                  0x0D50
+#define GL_RED_BITS                       0x0D52
+#define GL_GREEN_BITS                     0x0D53
+#define GL_BLUE_BITS                      0x0D54
+#define GL_ALPHA_BITS                     0x0D55
+#define GL_DEPTH_BITS                     0x0D56
+#define GL_STENCIL_BITS                   0x0D57
+#define GL_POLYGON_OFFSET_UNITS           0x2A00
+/*      GL_POLYGON_OFFSET_FILL */
+#define GL_POLYGON_OFFSET_FACTOR          0x8038
+#define GL_TEXTURE_BINDING_2D             0x8069
+#define GL_SAMPLE_BUFFERS                 0x80A8
+#define GL_SAMPLES                        0x80A9
+#define GL_SAMPLE_COVERAGE_VALUE          0x80AA
+#define GL_SAMPLE_COVERAGE_INVERT         0x80AB
+
+/* GetTextureParameter */
+/*      GL_TEXTURE_MAG_FILTER */
+/*      GL_TEXTURE_MIN_FILTER */
+/*      GL_TEXTURE_WRAP_S */
+/*      GL_TEXTURE_WRAP_T */
+
+#define GL_NUM_COMPRESSED_TEXTURE_FORMATS 0x86A2
+#define GL_COMPRESSED_TEXTURE_FORMATS     0x86A3
+
+/* HintMode */
+#define GL_DONT_CARE                      0x1100
+#define GL_FASTEST                        0x1101
+#define GL_NICEST                         0x1102
+
+/* HintTarget */
+#define GL_GENERATE_MIPMAP_HINT            0x8192
+
+/* DataType */
+#define GL_BYTE                           0x1400
+#define GL_UNSIGNED_BYTE                  0x1401
+#define GL_SHORT                          0x1402
+#define GL_UNSIGNED_SHORT                 0x1403
+#define GL_INT                            0x1404
+#define GL_UNSIGNED_INT                   0x1405
+#define GL_FLOAT                          0x1406
+#define GL_FIXED                          0x140C
+
+/* PixelFormat */
+#define GL_DEPTH_COMPONENT                0x1902
+#define GL_ALPHA                          0x1906
+#define GL_RGB                            0x1907
+#define GL_RGBA                           0x1908
+#define GL_LUMINANCE                      0x1909
+#define GL_LUMINANCE_ALPHA                0x190A
+
+/* PixelType */
+/*      GL_UNSIGNED_BYTE */
+#define GL_UNSIGNED_SHORT_4_4_4_4         0x8033
+#define GL_UNSIGNED_SHORT_5_5_5_1         0x8034
+#define GL_UNSIGNED_SHORT_5_6_5           0x8363
+
+/* Shaders */
+#define GL_FRAGMENT_SHADER                  0x8B30
+#define GL_VERTEX_SHADER                    0x8B31
+#define GL_MAX_VERTEX_ATTRIBS               0x8869
+#define GL_MAX_VERTEX_UNIFORM_VECTORS       0x8DFB
+#define GL_MAX_VARYING_VECTORS              0x8DFC
+#define GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS 0x8B4D
+#define GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS   0x8B4C
+#define GL_MAX_TEXTURE_IMAGE_UNITS          0x8872
+#define GL_MAX_FRAGMENT_UNIFORM_VECTORS     0x8DFD
+#define GL_SHADER_TYPE                      0x8B4F
+#define GL_DELETE_STATUS                    0x8B80
+#define GL_LINK_STATUS                      0x8B82
+#define GL_VALIDATE_STATUS                  0x8B83
+#define GL_ATTACHED_SHADERS                 0x8B85
+#define GL_ACTIVE_UNIFORMS                  0x8B86
+#define GL_ACTIVE_UNIFORM_MAX_LENGTH        0x8B87
+#define GL_ACTIVE_ATTRIBUTES                0x8B89
+#define GL_ACTIVE_ATTRIBUTE_MAX_LENGTH      0x8B8A
+#define GL_SHADING_LANGUAGE_VERSION         0x8B8C
+#define GL_CURRENT_PROGRAM                  0x8B8D
+
+/* StencilFunction */
+#define GL_NEVER                          0x0200
+#define GL_LESS                           0x0201
+#define GL_EQUAL                          0x0202
+#define GL_LEQUAL                         0x0203
+#define GL_GREATER                        0x0204
+#define GL_NOTEQUAL                       0x0205
+#define GL_GEQUAL                         0x0206
+#define GL_ALWAYS                         0x0207
+
+/* StencilOp */
+/*      GL_ZERO */
+#define GL_KEEP                           0x1E00
+#define GL_REPLACE                        0x1E01
+#define GL_INCR                           0x1E02
+#define GL_DECR                           0x1E03
+#define GL_INVERT                         0x150A
+#define GL_INCR_WRAP                      0x8507
+#define GL_DECR_WRAP                      0x8508
+
+/* StringName */
+#define GL_VENDOR                         0x1F00
+#define GL_RENDERER                       0x1F01
+#define GL_VERSION                        0x1F02
+#define GL_EXTENSIONS                     0x1F03
+
+/* TextureMagFilter */
+#define GL_NEAREST                        0x2600
+#define GL_LINEAR                         0x2601
+
+/* TextureMinFilter */
+/*      GL_NEAREST */
+/*      GL_LINEAR */
+#define GL_NEAREST_MIPMAP_NEAREST         0x2700
+#define GL_LINEAR_MIPMAP_NEAREST          0x2701
+#define GL_NEAREST_MIPMAP_LINEAR          0x2702
+#define GL_LINEAR_MIPMAP_LINEAR           0x2703
+
+/* TextureParameterName */
+#define GL_TEXTURE_MAG_FILTER             0x2800
+#define GL_TEXTURE_MIN_FILTER             0x2801
+#define GL_TEXTURE_WRAP_S                 0x2802
+#define GL_TEXTURE_WRAP_T                 0x2803
+
+/* TextureTarget */
+/*      GL_TEXTURE_2D */
+#define GL_TEXTURE                        0x1702
+
+#define GL_TEXTURE_CUBE_MAP               0x8513
+#define GL_TEXTURE_BINDING_CUBE_MAP       0x8514
+#define GL_TEXTURE_CUBE_MAP_POSITIVE_X    0x8515
+#define GL_TEXTURE_CUBE_MAP_NEGATIVE_X    0x8516
+#define GL_TEXTURE_CUBE_MAP_POSITIVE_Y    0x8517
+#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Y    0x8518
+#define GL_TEXTURE_CUBE_MAP_POSITIVE_Z    0x8519
+#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Z    0x851A
+#define GL_MAX_CUBE_MAP_TEXTURE_SIZE      0x851C
+
+/* TextureUnit */
+#define GL_TEXTURE0                       0x84C0
+#define GL_TEXTURE1                       0x84C1
+#define GL_TEXTURE2                       0x84C2
+#define GL_TEXTURE3                       0x84C3
+#define GL_TEXTURE4                       0x84C4
+#define GL_TEXTURE5                       0x84C5
+#define GL_TEXTURE6                       0x84C6
+#define GL_TEXTURE7                       0x84C7
+#define GL_TEXTURE8                       0x84C8
+#define GL_TEXTURE9                       0x84C9
+#define GL_TEXTURE10                      0x84CA
+#define GL_TEXTURE11                      0x84CB
+#define GL_TEXTURE12                      0x84CC
+#define GL_TEXTURE13                      0x84CD
+#define GL_TEXTURE14                      0x84CE
+#define GL_TEXTURE15                      0x84CF
+#define GL_TEXTURE16                      0x84D0
+#define GL_TEXTURE17                      0x84D1
+#define GL_TEXTURE18                      0x84D2
+#define GL_TEXTURE19                      0x84D3
+#define GL_TEXTURE20                      0x84D4
+#define GL_TEXTURE21                      0x84D5
+#define GL_TEXTURE22                      0x84D6
+#define GL_TEXTURE23                      0x84D7
+#define GL_TEXTURE24                      0x84D8
+#define GL_TEXTURE25                      0x84D9
+#define GL_TEXTURE26                      0x84DA
+#define GL_TEXTURE27                      0x84DB
+#define GL_TEXTURE28                      0x84DC
+#define GL_TEXTURE29                      0x84DD
+#define GL_TEXTURE30                      0x84DE
+#define GL_TEXTURE31                      0x84DF
+#define GL_ACTIVE_TEXTURE                 0x84E0
+
+/* TextureWrapMode */
+#define GL_REPEAT                         0x2901
+#define GL_CLAMP_TO_EDGE                  0x812F
+#define GL_MIRRORED_REPEAT                0x8370
+
+/* Uniform Types */
+#define GL_FLOAT_VEC2                     0x8B50
+#define GL_FLOAT_VEC3                     0x8B51
+#define GL_FLOAT_VEC4                     0x8B52
+#define GL_INT_VEC2                       0x8B53
+#define GL_INT_VEC3                       0x8B54
+#define GL_INT_VEC4                       0x8B55
+#define GL_BOOL                           0x8B56
+#define GL_BOOL_VEC2                      0x8B57
+#define GL_BOOL_VEC3                      0x8B58
+#define GL_BOOL_VEC4                      0x8B59
+#define GL_FLOAT_MAT2                     0x8B5A
+#define GL_FLOAT_MAT3                     0x8B5B
+#define GL_FLOAT_MAT4                     0x8B5C
+#define GL_SAMPLER_2D                     0x8B5E
+#define GL_SAMPLER_CUBE                   0x8B60
+
+/* Vertex Arrays */
+#define GL_VERTEX_ATTRIB_ARRAY_ENABLED        0x8622
+#define GL_VERTEX_ATTRIB_ARRAY_SIZE           0x8623
+#define GL_VERTEX_ATTRIB_ARRAY_STRIDE         0x8624
+#define GL_VERTEX_ATTRIB_ARRAY_TYPE           0x8625
+#define GL_VERTEX_ATTRIB_ARRAY_NORMALIZED     0x886A
+#define GL_VERTEX_ATTRIB_ARRAY_POINTER        0x8645
+#define GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING 0x889F
+
+/* Read Format */
+#define GL_IMPLEMENTATION_COLOR_READ_TYPE   0x8B9A
+#define GL_IMPLEMENTATION_COLOR_READ_FORMAT 0x8B9B
+
+/* Shader Source */
+#define GL_COMPILE_STATUS                 0x8B81
+#define GL_INFO_LOG_LENGTH                0x8B84
+#define GL_SHADER_SOURCE_LENGTH           0x8B88
+#define GL_SHADER_COMPILER                0x8DFA
+
+/* Shader Binary */
+#define GL_SHADER_BINARY_FORMATS          0x8DF8
+#define GL_NUM_SHADER_BINARY_FORMATS      0x8DF9
+
+/* Shader Precision-Specified Types */
+#define GL_LOW_FLOAT                      0x8DF0
+#define GL_MEDIUM_FLOAT                   0x8DF1
+#define GL_HIGH_FLOAT                     0x8DF2
+#define GL_LOW_INT                        0x8DF3
+#define GL_MEDIUM_INT                     0x8DF4
+#define GL_HIGH_INT                       0x8DF5
+
+/* Framebuffer Object. */
+#define GL_FRAMEBUFFER                    0x8D40
+#define GL_RENDERBUFFER                   0x8D41
+
+#define GL_RGBA4                          0x8056
+#define GL_RGB5_A1                        0x8057
+#define GL_RGB565                         0x8D62
+#define GL_DEPTH_COMPONENT16              0x81A5
+#define GL_STENCIL_INDEX                  0x1901
+#define GL_STENCIL_INDEX8                 0x8D48
+
+#define GL_RENDERBUFFER_WIDTH             0x8D42
+#define GL_RENDERBUFFER_HEIGHT            0x8D43
+#define GL_RENDERBUFFER_INTERNAL_FORMAT   0x8D44
+#define GL_RENDERBUFFER_RED_SIZE          0x8D50
+#define GL_RENDERBUFFER_GREEN_SIZE        0x8D51
+#define GL_RENDERBUFFER_BLUE_SIZE         0x8D52
+#define GL_RENDERBUFFER_ALPHA_SIZE        0x8D53
+#define GL_RENDERBUFFER_DEPTH_SIZE        0x8D54
+#define GL_RENDERBUFFER_STENCIL_SIZE      0x8D55
+
+#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE           0x8CD0
+#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME           0x8CD1
+#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL         0x8CD2
+#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE 0x8CD3
+
+#define GL_COLOR_ATTACHMENT0              0x8CE0
+#define GL_DEPTH_ATTACHMENT               0x8D00
+#define GL_STENCIL_ATTACHMENT             0x8D20
+
+#define GL_NONE                           0
+
+#define GL_FRAMEBUFFER_COMPLETE                      0x8CD5
+#define GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT         0x8CD6
+#define GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT 0x8CD7
+#define GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS         0x8CD9
+#define GL_FRAMEBUFFER_UNSUPPORTED                   0x8CDD
+
+#define GL_FRAMEBUFFER_BINDING            0x8CA6
+#define GL_RENDERBUFFER_BINDING           0x8CA7
+#define GL_MAX_RENDERBUFFER_SIZE          0x84E8
+
+#define GL_INVALID_FRAMEBUFFER_OPERATION  0x0506
+
+/*-------------------------------------------------------------------------
+ * GL core functions.
+ *-----------------------------------------------------------------------*/
+
+GL_APICALL void         GL_APIENTRY glActiveTexture (GLenum texture);
+GL_APICALL void         GL_APIENTRY glAttachShader (GLuint program, GLuint shader);
+GL_APICALL void         GL_APIENTRY glBindAttribLocation (GLuint program, GLuint index, const GLchar* name);
+GL_APICALL void         GL_APIENTRY glBindBuffer (GLenum target, GLuint buffer);
+GL_APICALL void         GL_APIENTRY glBindFramebuffer (GLenum target, GLuint framebuffer);
+GL_APICALL void         GL_APIENTRY glBindRenderbuffer (GLenum target, GLuint renderbuffer);
+GL_APICALL void         GL_APIENTRY glBindTexture (GLenum target, GLuint texture);
+GL_APICALL void         GL_APIENTRY glBlendColor (GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha);
+GL_APICALL void         GL_APIENTRY glBlendEquation ( GLenum mode );
+GL_APICALL void         GL_APIENTRY glBlendEquationSeparate (GLenum modeRGB, GLenum modeAlpha);
+GL_APICALL void         GL_APIENTRY glBlendFunc (GLenum sfactor, GLenum dfactor);
+GL_APICALL void         GL_APIENTRY glBlendFuncSeparate (GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha);
+GL_APICALL void         GL_APIENTRY glBufferData (GLenum target, GLsizeiptr size, const GLvoid* data, GLenum usage);
+GL_APICALL void         GL_APIENTRY glBufferSubData (GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid* data);
+GL_APICALL GLenum       GL_APIENTRY glCheckFramebufferStatus (GLenum target);
+GL_APICALL void         GL_APIENTRY glClear (GLbitfield mask);
+GL_APICALL void         GL_APIENTRY glClearColor (GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha);
+GL_APICALL void         GL_APIENTRY glClearDepthf (GLclampf depth);
+GL_APICALL void         GL_APIENTRY glClearStencil (GLint s);
+GL_APICALL void         GL_APIENTRY glColorMask (GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha);
+GL_APICALL void         GL_APIENTRY glCompileShader (GLuint shader);
+GL_APICALL void         GL_APIENTRY glCompressedTexImage2D (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid* data);
+GL_APICALL void         GL_APIENTRY glCompressedTexSubImage2D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const GLvoid* data);
+GL_APICALL void         GL_APIENTRY glCopyTexImage2D (GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border);
+GL_APICALL void         GL_APIENTRY glCopyTexSubImage2D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height);
+GL_APICALL GLuint       GL_APIENTRY glCreateProgram (void);
+GL_APICALL GLuint       GL_APIENTRY glCreateShader (GLenum type);
+GL_APICALL void         GL_APIENTRY glCullFace (GLenum mode);
+GL_APICALL void         GL_APIENTRY glDeleteBuffers (GLsizei n, const GLuint* buffers);
+GL_APICALL void         GL_APIENTRY glDeleteFramebuffers (GLsizei n, const GLuint* framebuffers);
+GL_APICALL void         GL_APIENTRY glDeleteProgram (GLuint program);
+GL_APICALL void         GL_APIENTRY glDeleteRenderbuffers (GLsizei n, const GLuint* renderbuffers);
+GL_APICALL void         GL_APIENTRY glDeleteShader (GLuint shader);
+GL_APICALL void         GL_APIENTRY glDeleteTextures (GLsizei n, const GLuint* textures);
+GL_APICALL void         GL_APIENTRY glDepthFunc (GLenum func);
+GL_APICALL void         GL_APIENTRY glDepthMask (GLboolean flag);
+GL_APICALL void         GL_APIENTRY glDepthRangef (GLclampf zNear, GLclampf zFar);
+GL_APICALL void         GL_APIENTRY glDetachShader (GLuint program, GLuint shader);
+GL_APICALL void         GL_APIENTRY glDisable (GLenum cap);
+GL_APICALL void         GL_APIENTRY glDisableVertexAttribArray (GLuint index);
+GL_APICALL void         GL_APIENTRY glDrawArrays (GLenum mode, GLint first, GLsizei count);
+GL_APICALL void         GL_APIENTRY glDrawElements (GLenum mode, GLsizei count, GLenum type, const GLvoid* indices);
+GL_APICALL void         GL_APIENTRY glEnable (GLenum cap);
+GL_APICALL void         GL_APIENTRY glEnableVertexAttribArray (GLuint index);
+GL_APICALL void         GL_APIENTRY glFinish (void);
+GL_APICALL void         GL_APIENTRY glFlush (void);
+GL_APICALL void         GL_APIENTRY glFramebufferRenderbuffer (GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer);
+GL_APICALL void         GL_APIENTRY glFramebufferTexture2D (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level);
+GL_APICALL void         GL_APIENTRY glFrontFace (GLenum mode);
+GL_APICALL void         GL_APIENTRY glGenBuffers (GLsizei n, GLuint* buffers);
+GL_APICALL void         GL_APIENTRY glGenerateMipmap (GLenum target);
+GL_APICALL void         GL_APIENTRY glGenFramebuffers (GLsizei n, GLuint* framebuffers);
+GL_APICALL void         GL_APIENTRY glGenRenderbuffers (GLsizei n, GLuint* renderbuffers);
+GL_APICALL void         GL_APIENTRY glGenTextures (GLsizei n, GLuint* textures);
+GL_APICALL void         GL_APIENTRY glGetActiveAttrib (GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, GLchar* name);
+GL_APICALL void         GL_APIENTRY glGetActiveUniform (GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, GLchar* name);
+GL_APICALL void         GL_APIENTRY glGetAttachedShaders (GLuint program, GLsizei maxcount, GLsizei* count, GLuint* shaders);
+GL_APICALL int          GL_APIENTRY glGetAttribLocation (GLuint program, const GLchar* name);
+GL_APICALL void         GL_APIENTRY glGetBooleanv (GLenum pname, GLboolean* params);
+GL_APICALL void         GL_APIENTRY glGetBufferParameteriv (GLenum target, GLenum pname, GLint* params);
+GL_APICALL GLenum       GL_APIENTRY glGetError (void);
+GL_APICALL void         GL_APIENTRY glGetFloatv (GLenum pname, GLfloat* params);
+GL_APICALL void         GL_APIENTRY glGetFramebufferAttachmentParameteriv (GLenum target, GLenum attachment, GLenum pname, GLint* params);
+GL_APICALL void         GL_APIENTRY glGetIntegerv (GLenum pname, GLint* params);
+GL_APICALL void         GL_APIENTRY glGetProgramiv (GLuint program, GLenum pname, GLint* params);
+GL_APICALL void         GL_APIENTRY glGetProgramInfoLog (GLuint program, GLsizei bufsize, GLsizei* length, GLchar* infolog);
+GL_APICALL void         GL_APIENTRY glGetRenderbufferParameteriv (GLenum target, GLenum pname, GLint* params);
+GL_APICALL void         GL_APIENTRY glGetShaderiv (GLuint shader, GLenum pname, GLint* params);
+GL_APICALL void         GL_APIENTRY glGetShaderInfoLog (GLuint shader, GLsizei bufsize, GLsizei* length, GLchar* infolog);
+GL_APICALL void         GL_APIENTRY glGetShaderPrecisionFormat (GLenum shadertype, GLenum precisiontype, GLint* range, GLint* precision);
+GL_APICALL void         GL_APIENTRY glGetShaderSource (GLuint shader, GLsizei bufsize, GLsizei* length, GLchar* source);
+GL_APICALL const GLubyte* GL_APIENTRY glGetString (GLenum name);
+GL_APICALL void         GL_APIENTRY glGetTexParameterfv (GLenum target, GLenum pname, GLfloat* params);
+GL_APICALL void         GL_APIENTRY glGetTexParameteriv (GLenum target, GLenum pname, GLint* params);
+GL_APICALL void         GL_APIENTRY glGetUniformfv (GLuint program, GLint location, GLfloat* params);
+GL_APICALL void         GL_APIENTRY glGetUniformiv (GLuint program, GLint location, GLint* params);
+GL_APICALL int          GL_APIENTRY glGetUniformLocation (GLuint program, const GLchar* name);
+GL_APICALL void         GL_APIENTRY glGetVertexAttribfv (GLuint index, GLenum pname, GLfloat* params);
+GL_APICALL void         GL_APIENTRY glGetVertexAttribiv (GLuint index, GLenum pname, GLint* params);
+GL_APICALL void         GL_APIENTRY glGetVertexAttribPointerv (GLuint index, GLenum pname, GLvoid** pointer);
+GL_APICALL void         GL_APIENTRY glHint (GLenum target, GLenum mode);
+GL_APICALL GLboolean    GL_APIENTRY glIsBuffer (GLuint buffer);
+GL_APICALL GLboolean    GL_APIENTRY glIsEnabled (GLenum cap);
+GL_APICALL GLboolean    GL_APIENTRY glIsFramebuffer (GLuint framebuffer);
+GL_APICALL GLboolean    GL_APIENTRY glIsProgram (GLuint program);
+GL_APICALL GLboolean    GL_APIENTRY glIsRenderbuffer (GLuint renderbuffer);
+GL_APICALL GLboolean    GL_APIENTRY glIsShader (GLuint shader);
+GL_APICALL GLboolean    GL_APIENTRY glIsTexture (GLuint texture);
+GL_APICALL void         GL_APIENTRY glLineWidth (GLfloat width);
+GL_APICALL void         GL_APIENTRY glLinkProgram (GLuint program);
+GL_APICALL void         GL_APIENTRY glPixelStorei (GLenum pname, GLint param);
+GL_APICALL void         GL_APIENTRY glPolygonOffset (GLfloat factor, GLfloat units);
+GL_APICALL void         GL_APIENTRY glReadPixels (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid* pixels);
+GL_APICALL void         GL_APIENTRY glReleaseShaderCompiler (void);
+GL_APICALL void         GL_APIENTRY glRenderbufferStorage (GLenum target, GLenum internalformat, GLsizei width, GLsizei height);
+GL_APICALL void         GL_APIENTRY glSampleCoverage (GLclampf value, GLboolean invert);
+GL_APICALL void         GL_APIENTRY glScissor (GLint x, GLint y, GLsizei width, GLsizei height);
+GL_APICALL void         GL_APIENTRY glShaderBinary (GLsizei n, const GLuint* shaders, GLenum binaryformat, const GLvoid* binary, GLsizei length);
+GL_APICALL void         GL_APIENTRY glShaderSource (GLuint shader, GLsizei count, const GLchar** string, const GLint* length);
+GL_APICALL void         GL_APIENTRY glStencilFunc (GLenum func, GLint ref, GLuint mask);
+GL_APICALL void         GL_APIENTRY glStencilFuncSeparate (GLenum face, GLenum func, GLint ref, GLuint mask);
+GL_APICALL void         GL_APIENTRY glStencilMask (GLuint mask);
+GL_APICALL void         GL_APIENTRY glStencilMaskSeparate (GLenum face, GLuint mask);
+GL_APICALL void         GL_APIENTRY glStencilOp (GLenum fail, GLenum zfail, GLenum zpass);
+GL_APICALL void         GL_APIENTRY glStencilOpSeparate (GLenum face, GLenum fail, GLenum zfail, GLenum zpass);
+GL_APICALL void         GL_APIENTRY glTexImage2D (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid* pixels);
+GL_APICALL void         GL_APIENTRY glTexParameterf (GLenum target, GLenum pname, GLfloat param);
+GL_APICALL void         GL_APIENTRY glTexParameterfv (GLenum target, GLenum pname, const GLfloat* params);
+GL_APICALL void         GL_APIENTRY glTexParameteri (GLenum target, GLenum pname, GLint param);
+GL_APICALL void         GL_APIENTRY glTexParameteriv (GLenum target, GLenum pname, const GLint* params);
+GL_APICALL void         GL_APIENTRY glTexSubImage2D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid* pixels);
+GL_APICALL void         GL_APIENTRY glUniform1f (GLint location, GLfloat x);
+GL_APICALL void         GL_APIENTRY glUniform1fv (GLint location, GLsizei count, const GLfloat* v);
+GL_APICALL void         GL_APIENTRY glUniform1i (GLint location, GLint x);
+GL_APICALL void         GL_APIENTRY glUniform1iv (GLint location, GLsizei count, const GLint* v);
+GL_APICALL void         GL_APIENTRY glUniform2f (GLint location, GLfloat x, GLfloat y);
+GL_APICALL void         GL_APIENTRY glUniform2fv (GLint location, GLsizei count, const GLfloat* v);
+GL_APICALL void         GL_APIENTRY glUniform2i (GLint location, GLint x, GLint y);
+GL_APICALL void         GL_APIENTRY glUniform2iv (GLint location, GLsizei count, const GLint* v);
+GL_APICALL void         GL_APIENTRY glUniform3f (GLint location, GLfloat x, GLfloat y, GLfloat z);
+GL_APICALL void         GL_APIENTRY glUniform3fv (GLint location, GLsizei count, const GLfloat* v);
+GL_APICALL void         GL_APIENTRY glUniform3i (GLint location, GLint x, GLint y, GLint z);
+GL_APICALL void         GL_APIENTRY glUniform3iv (GLint location, GLsizei count, const GLint* v);
+GL_APICALL void         GL_APIENTRY glUniform4f (GLint location, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+GL_APICALL void         GL_APIENTRY glUniform4fv (GLint location, GLsizei count, const GLfloat* v);
+GL_APICALL void         GL_APIENTRY glUniform4i (GLint location, GLint x, GLint y, GLint z, GLint w);
+GL_APICALL void         GL_APIENTRY glUniform4iv (GLint location, GLsizei count, const GLint* v);
+GL_APICALL void         GL_APIENTRY glUniformMatrix2fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
+GL_APICALL void         GL_APIENTRY glUniformMatrix3fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
+GL_APICALL void         GL_APIENTRY glUniformMatrix4fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
+GL_APICALL void         GL_APIENTRY glUseProgram (GLuint program);
+GL_APICALL void         GL_APIENTRY glValidateProgram (GLuint program);
+GL_APICALL void         GL_APIENTRY glVertexAttrib1f (GLuint indx, GLfloat x);
+GL_APICALL void         GL_APIENTRY glVertexAttrib1fv (GLuint indx, const GLfloat* values);
+GL_APICALL void         GL_APIENTRY glVertexAttrib2f (GLuint indx, GLfloat x, GLfloat y);
+GL_APICALL void         GL_APIENTRY glVertexAttrib2fv (GLuint indx, const GLfloat* values);
+GL_APICALL void         GL_APIENTRY glVertexAttrib3f (GLuint indx, GLfloat x, GLfloat y, GLfloat z);
+GL_APICALL void         GL_APIENTRY glVertexAttrib3fv (GLuint indx, const GLfloat* values);
+GL_APICALL void         GL_APIENTRY glVertexAttrib4f (GLuint indx, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+GL_APICALL void         GL_APIENTRY glVertexAttrib4fv (GLuint indx, const GLfloat* values);
+GL_APICALL void         GL_APIENTRY glVertexAttribPointer (GLuint indx, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid* ptr);
+GL_APICALL void         GL_APIENTRY glViewport (GLint x, GLint y, GLsizei width, GLsizei height);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __gl2_h_ */
diff --git a/src/GLES2/include/GLES2/gl2ext.h b/src/GLES2/include/GLES2/gl2ext.h
new file mode 100644
index 0000000..a124014
--- /dev/null
+++ b/src/GLES2/include/GLES2/gl2ext.h
@@ -0,0 +1,1494 @@
+#ifndef __gl2ext_h_
+#define __gl2ext_h_
+
+/* $Revision: 16482 $ on $Date:: 2012-01-04 13:44:55 -0500 #$ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * This document is licensed under the SGI Free Software B License Version
+ * 2.0. For details, see http://oss.sgi.com/projects/FreeB/ .
+ */
+
+#ifndef GL_APIENTRYP
+#   define GL_APIENTRYP GL_APIENTRY*
+#endif
+
+/*------------------------------------------------------------------------*
+ * OES extension tokens
+ *------------------------------------------------------------------------*/
+
+/* GL_OES_compressed_ETC1_RGB8_texture */
+#ifndef GL_OES_compressed_ETC1_RGB8_texture
+#define GL_ETC1_RGB8_OES                                        0x8D64
+#endif
+
+/* GL_OES_compressed_paletted_texture */
+#ifndef GL_OES_compressed_paletted_texture
+#define GL_PALETTE4_RGB8_OES                                    0x8B90
+#define GL_PALETTE4_RGBA8_OES                                   0x8B91
+#define GL_PALETTE4_R5_G6_B5_OES                                0x8B92
+#define GL_PALETTE4_RGBA4_OES                                   0x8B93
+#define GL_PALETTE4_RGB5_A1_OES                                 0x8B94
+#define GL_PALETTE8_RGB8_OES                                    0x8B95
+#define GL_PALETTE8_RGBA8_OES                                   0x8B96
+#define GL_PALETTE8_R5_G6_B5_OES                                0x8B97
+#define GL_PALETTE8_RGBA4_OES                                   0x8B98
+#define GL_PALETTE8_RGB5_A1_OES                                 0x8B99
+#endif
+
+/* GL_OES_depth24 */
+#ifndef GL_OES_depth24
+#define GL_DEPTH_COMPONENT24_OES                                0x81A6
+#endif
+
+/* GL_OES_depth32 */
+#ifndef GL_OES_depth32
+#define GL_DEPTH_COMPONENT32_OES                                0x81A7
+#endif
+
+/* GL_OES_depth_texture */
+/* No new tokens introduced by this extension. */
+
+/* GL_OES_EGL_image */
+#ifndef GL_OES_EGL_image
+typedef void* GLeglImageOES;
+#endif
+
+/* GL_OES_EGL_image_external */
+#ifndef GL_OES_EGL_image_external
+/* GLeglImageOES defined in GL_OES_EGL_image already. */
+#define GL_TEXTURE_EXTERNAL_OES                                 0x8D65
+#define GL_SAMPLER_EXTERNAL_OES                                 0x8D66
+#define GL_TEXTURE_BINDING_EXTERNAL_OES                         0x8D67
+#define GL_REQUIRED_TEXTURE_IMAGE_UNITS_OES                     0x8D68
+#endif
+
+/* GL_OES_element_index_uint */
+#ifndef GL_OES_element_index_uint
+#define GL_UNSIGNED_INT                                         0x1405
+#endif
+
+/* GL_OES_get_program_binary */
+#ifndef GL_OES_get_program_binary
+#define GL_PROGRAM_BINARY_LENGTH_OES                            0x8741
+#define GL_NUM_PROGRAM_BINARY_FORMATS_OES                       0x87FE
+#define GL_PROGRAM_BINARY_FORMATS_OES                           0x87FF
+#endif
+
+/* GL_OES_mapbuffer */
+#ifndef GL_OES_mapbuffer
+#define GL_WRITE_ONLY_OES                                       0x88B9
+#define GL_BUFFER_ACCESS_OES                                    0x88BB
+#define GL_BUFFER_MAPPED_OES                                    0x88BC
+#define GL_BUFFER_MAP_POINTER_OES                               0x88BD
+#endif
+
+/* GL_OES_packed_depth_stencil */
+#ifndef GL_OES_packed_depth_stencil
+#define GL_DEPTH_STENCIL_OES                                    0x84F9
+#define GL_UNSIGNED_INT_24_8_OES                                0x84FA
+#define GL_DEPTH24_STENCIL8_OES                                 0x88F0
+#endif
+
+/* GL_OES_rgb8_rgba8 */
+#ifndef GL_OES_rgb8_rgba8
+#define GL_RGB8_OES                                             0x8051
+#define GL_RGBA8_OES                                            0x8058
+#endif
+
+/* GL_OES_standard_derivatives */
+#ifndef GL_OES_standard_derivatives
+#define GL_FRAGMENT_SHADER_DERIVATIVE_HINT_OES                  0x8B8B
+#endif
+
+/* GL_OES_stencil1 */
+#ifndef GL_OES_stencil1
+#define GL_STENCIL_INDEX1_OES                                   0x8D46
+#endif
+
+/* GL_OES_stencil4 */
+#ifndef GL_OES_stencil4
+#define GL_STENCIL_INDEX4_OES                                   0x8D47
+#endif
+
+/* GL_OES_texture_3D */
+#ifndef GL_OES_texture_3D
+#define GL_TEXTURE_WRAP_R_OES                                   0x8072
+#define GL_TEXTURE_3D_OES                                       0x806F
+#define GL_TEXTURE_BINDING_3D_OES                               0x806A
+#define GL_MAX_3D_TEXTURE_SIZE_OES                              0x8073
+#define GL_SAMPLER_3D_OES                                       0x8B5F
+#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_3D_ZOFFSET_OES        0x8CD4
+#endif
+
+/* GL_OES_texture_float */
+/* No new tokens introduced by this extension. */
+
+/* GL_OES_texture_float_linear */
+/* No new tokens introduced by this extension. */
+
+/* GL_OES_texture_half_float */
+#ifndef GL_OES_texture_half_float
+#define GL_HALF_FLOAT_OES                                       0x8D61
+#endif
+
+/* GL_OES_texture_half_float_linear */
+/* No new tokens introduced by this extension. */
+
+/* GL_OES_texture_npot */
+/* No new tokens introduced by this extension. */
+
+/* GL_OES_vertex_array_object */
+#ifndef GL_OES_vertex_array_object
+#define GL_VERTEX_ARRAY_BINDING_OES                             0x85B5
+#endif
+
+/* GL_OES_vertex_half_float */
+/* GL_HALF_FLOAT_OES defined in GL_OES_texture_half_float already. */
+
+/* GL_OES_vertex_type_10_10_10_2 */
+#ifndef GL_OES_vertex_type_10_10_10_2
+#define GL_UNSIGNED_INT_10_10_10_2_OES                          0x8DF6
+#define GL_INT_10_10_10_2_OES                                   0x8DF7
+#endif
+
+/*------------------------------------------------------------------------*
+ * AMD extension tokens
+ *------------------------------------------------------------------------*/
+
+/* GL_AMD_compressed_3DC_texture */
+#ifndef GL_AMD_compressed_3DC_texture
+#define GL_3DC_X_AMD                                            0x87F9
+#define GL_3DC_XY_AMD                                           0x87FA
+#endif
+
+/* GL_AMD_compressed_ATC_texture */
+#ifndef GL_AMD_compressed_ATC_texture
+#define GL_ATC_RGB_AMD                                          0x8C92
+#define GL_ATC_RGBA_EXPLICIT_ALPHA_AMD                          0x8C93
+#define GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD                      0x87EE
+#endif
+
+/* GL_AMD_performance_monitor */
+#ifndef GL_AMD_performance_monitor
+#define GL_COUNTER_TYPE_AMD                                     0x8BC0
+#define GL_COUNTER_RANGE_AMD                                    0x8BC1
+#define GL_UNSIGNED_INT64_AMD                                   0x8BC2
+#define GL_PERCENTAGE_AMD                                       0x8BC3
+#define GL_PERFMON_RESULT_AVAILABLE_AMD                         0x8BC4
+#define GL_PERFMON_RESULT_SIZE_AMD                              0x8BC5
+#define GL_PERFMON_RESULT_AMD                                   0x8BC6
+#endif
+
+/* GL_AMD_program_binary_Z400 */
+#ifndef GL_AMD_program_binary_Z400
+#define GL_Z400_BINARY_AMD                                      0x8740
+#endif
+
+/*------------------------------------------------------------------------*
+ * ANGLE extension tokens
+ *------------------------------------------------------------------------*/
+
+/* GL_ANGLE_framebuffer_blit */
+#ifndef GL_ANGLE_framebuffer_blit
+#define GL_READ_FRAMEBUFFER_ANGLE                               0x8CA8
+#define GL_DRAW_FRAMEBUFFER_ANGLE                               0x8CA9
+#define GL_DRAW_FRAMEBUFFER_BINDING_ANGLE                       0x8CA6
+#define GL_READ_FRAMEBUFFER_BINDING_ANGLE                       0x8CAA
+#endif
+
+/* GL_ANGLE_framebuffer_multisample */
+#ifndef GL_ANGLE_framebuffer_multisample
+#define GL_RENDERBUFFER_SAMPLES_ANGLE                           0x8CAB
+#define GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_ANGLE             0x8D56
+#define GL_MAX_SAMPLES_ANGLE                                    0x8D57
+#endif
+
+/* GL_ANGLE_pack_reverse_row_order */
+#ifndef GL_ANGLE_pack_reverse_row_order
+#define GL_PACK_REVERSE_ROW_ORDER_ANGLE                         0x93A4
+#endif
+
+/* GL_ANGLE_texture_compression_dxt3 */
+#ifndef GL_ANGLE_texture_compression_dxt3
+#define GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE                      0x83F2
+#endif
+
+/* GL_ANGLE_texture_compression_dxt5 */
+#ifndef GL_ANGLE_texture_compression_dxt5
+#define GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE                      0x83F3
+#endif
+
+/* GL_ANGLE_translated_shader_source */
+#ifndef GL_ANGLE_translated_shader_source
+#define GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE                0x93A0
+#endif
+
+/* GL_ANGLE_texture_usage */
+#ifndef GL_ANGLE_texture_usage
+#define GL_TEXTURE_USAGE_ANGLE                                  0x93A2
+#define GL_FRAMEBUFFER_ATTACHMENT_ANGLE                         0x93A3
+#endif
+
+/* GL_ANGLE_instanced_arrays */
+#ifndef GL_ANGLE_instanced_arrays
+#define GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE                    0x88FE
+#endif
+
+/*------------------------------------------------------------------------*
+ * APPLE extension tokens
+ *------------------------------------------------------------------------*/
+
+/* GL_APPLE_rgb_422 */
+#ifndef GL_APPLE_rgb_422
+#define GL_RGB_422_APPLE                                        0x8A1F
+#define GL_UNSIGNED_SHORT_8_8_APPLE                             0x85BA
+#define GL_UNSIGNED_SHORT_8_8_REV_APPLE                         0x85BB
+#endif
+
+/* GL_APPLE_framebuffer_multisample */
+#ifndef GL_APPLE_framebuffer_multisample
+#define GL_RENDERBUFFER_SAMPLES_APPLE                           0x8CAB
+#define GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_APPLE             0x8D56
+#define GL_MAX_SAMPLES_APPLE                                    0x8D57
+#define GL_READ_FRAMEBUFFER_APPLE                               0x8CA8
+#define GL_DRAW_FRAMEBUFFER_APPLE                               0x8CA9
+#define GL_DRAW_FRAMEBUFFER_BINDING_APPLE                       0x8CA6
+#define GL_READ_FRAMEBUFFER_BINDING_APPLE                       0x8CAA
+#endif
+
+/* GL_APPLE_texture_format_BGRA8888 */
+#ifndef GL_APPLE_texture_format_BGRA8888
+#define GL_BGRA_EXT                                             0x80E1
+#endif
+
+/* GL_APPLE_texture_max_level */
+#ifndef GL_APPLE_texture_max_level
+#define GL_TEXTURE_MAX_LEVEL_APPLE                              0x813D
+#endif
+
+/*------------------------------------------------------------------------*
+ * ARM extension tokens
+ *------------------------------------------------------------------------*/
+
+/* GL_ARM_mali_shader_binary */
+#ifndef GL_ARM_mali_shader_binary
+#define GL_MALI_SHADER_BINARY_ARM                               0x8F60
+#endif
+
+/* GL_ARM_rgba8 */
+/* No new tokens introduced by this extension. */
+
+/*------------------------------------------------------------------------*
+ * EXT extension tokens
+ *------------------------------------------------------------------------*/
+
+/* GL_EXT_blend_minmax */
+#ifndef GL_EXT_blend_minmax
+#define GL_MIN_EXT                                              0x8007
+#define GL_MAX_EXT                                              0x8008
+#endif
+
+/* GL_EXT_color_buffer_half_float */
+#ifndef GL_EXT_color_buffer_half_float
+#define GL_RGBA16F_EXT                                          0x881A
+#define GL_RGB16F_EXT                                           0x881B
+#define GL_RG16F_EXT                                            0x822F
+#define GL_R16F_EXT                                             0x822D
+#define GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE_EXT            0x8211
+#define GL_UNSIGNED_NORMALIZED_EXT                              0x8C17
+#endif
+
+/* GL_EXT_debug_label */
+#ifndef GL_EXT_debug_label
+#define GL_PROGRAM_PIPELINE_OBJECT_EXT                          0x8A4F
+#define GL_PROGRAM_OBJECT_EXT                                   0x8B40
+#define GL_SHADER_OBJECT_EXT                                    0x8B48
+#define GL_BUFFER_OBJECT_EXT                                    0x9151
+#define GL_QUERY_OBJECT_EXT                                     0x9153
+#define GL_VERTEX_ARRAY_OBJECT_EXT                              0x9154
+#endif
+
+/* GL_EXT_debug_marker */
+/* No new tokens introduced by this extension. */
+
+/* GL_EXT_discard_framebuffer */
+#ifndef GL_EXT_discard_framebuffer
+#define GL_COLOR_EXT                                            0x1800
+#define GL_DEPTH_EXT                                            0x1801
+#define GL_STENCIL_EXT                                          0x1802
+#endif
+
+/* GL_EXT_multisampled_render_to_texture */
+#ifndef GL_EXT_multisampled_render_to_texture
+#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_SAMPLES_EXT           0x8D6C
+#define GL_RENDERBUFFER_SAMPLES_EXT                             0x9133
+#define GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_EXT               0x9134
+#define GL_MAX_SAMPLES_EXT                                      0x9135
+#endif
+
+/* GL_EXT_multi_draw_arrays */
+/* No new tokens introduced by this extension. */
+
+/* GL_EXT_occlusion_query_boolean */
+#ifndef GL_EXT_occlusion_query_boolean
+#define GL_ANY_SAMPLES_PASSED_EXT                               0x8C2F
+#define GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT                  0x8D6A
+#define GL_CURRENT_QUERY_EXT                                    0x8865
+#define GL_QUERY_RESULT_EXT                                     0x8866
+#define GL_QUERY_RESULT_AVAILABLE_EXT                           0x8867
+#endif
+
+/* GL_EXT_read_format_bgra */
+#ifndef GL_EXT_read_format_bgra
+#define GL_BGRA_EXT                                             0x80E1
+#define GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT                       0x8365
+#define GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT                       0x8366
+#endif
+
+/* GL_EXT_robustness */
+#ifndef GL_EXT_robustness
+/* reuse GL_NO_ERROR */
+#define GL_GUILTY_CONTEXT_RESET_EXT                             0x8253
+#define GL_INNOCENT_CONTEXT_RESET_EXT                           0x8254
+#define GL_UNKNOWN_CONTEXT_RESET_EXT                            0x8255
+#define GL_CONTEXT_ROBUST_ACCESS_EXT                            0x90F3
+#define GL_RESET_NOTIFICATION_STRATEGY_EXT                      0x8256
+#define GL_LOSE_CONTEXT_ON_RESET_EXT                            0x8252
+#define GL_NO_RESET_NOTIFICATION_EXT                            0x8261
+#endif
+
+/* GL_EXT_separate_shader_objects */
+#ifndef GL_EXT_separate_shader_objects
+#define GL_VERTEX_SHADER_BIT_EXT                                0x00000001
+#define GL_FRAGMENT_SHADER_BIT_EXT                              0x00000002
+#define GL_ALL_SHADER_BITS_EXT                                  0xFFFFFFFF
+#define GL_PROGRAM_SEPARABLE_EXT                                0x8258
+#define GL_ACTIVE_PROGRAM_EXT                                   0x8259
+#define GL_PROGRAM_PIPELINE_BINDING_EXT                         0x825A
+#endif
+
+/* GL_EXT_shader_texture_lod */
+/* No new tokens introduced by this extension. */
+
+/* GL_EXT_shadow_samplers */
+#ifndef GL_EXT_shadow_samplers
+#define GL_TEXTURE_COMPARE_MODE_EXT                             0x884C
+#define GL_TEXTURE_COMPARE_FUNC_EXT                             0x884D
+#define GL_COMPARE_REF_TO_TEXTURE_EXT                           0x884E
+#endif
+
+/* GL_EXT_sRGB */
+#ifndef GL_EXT_sRGB
+#define GL_SRGB_EXT                                             0x8C40
+#define GL_SRGB_ALPHA_EXT                                       0x8C42
+#define GL_SRGB8_ALPHA8_EXT                                     0x8C43
+#define GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING_EXT            0x8210
+#endif
+
+/* GL_EXT_texture_compression_dxt1 */
+#ifndef GL_EXT_texture_compression_dxt1
+#define GL_COMPRESSED_RGB_S3TC_DXT1_EXT                         0x83F0
+#define GL_COMPRESSED_RGBA_S3TC_DXT1_EXT                        0x83F1
+#endif
+
+/* GL_EXT_texture_filter_anisotropic */
+#ifndef GL_EXT_texture_filter_anisotropic
+#define GL_TEXTURE_MAX_ANISOTROPY_EXT                           0x84FE
+#define GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT                       0x84FF
+#endif
+
+/* GL_EXT_texture_format_BGRA8888 */
+#ifndef GL_EXT_texture_format_BGRA8888
+#define GL_BGRA_EXT                                             0x80E1
+#endif
+
+/* GL_EXT_texture_rg */
+#ifndef GL_EXT_texture_rg
+#define GL_RED_EXT                                              0x1903
+#define GL_RG_EXT                                               0x8227
+#define GL_R8_EXT                                               0x8229
+#define GL_RG8_EXT                                              0x822B
+#endif
+
+/* GL_EXT_texture_storage */
+#ifndef GL_EXT_texture_storage
+#define GL_TEXTURE_IMMUTABLE_FORMAT_EXT                         0x912F
+#define GL_ALPHA8_EXT                                           0x803C  
+#define GL_LUMINANCE8_EXT                                       0x8040
+#define GL_LUMINANCE8_ALPHA8_EXT                                0x8045
+#define GL_RGBA32F_EXT                                          0x8814  
+#define GL_RGB32F_EXT                                           0x8815
+#define GL_ALPHA32F_EXT                                         0x8816
+#define GL_LUMINANCE32F_EXT                                     0x8818
+#define GL_LUMINANCE_ALPHA32F_EXT                               0x8819
+/* reuse GL_RGBA16F_EXT */
+#define GL_RGB16F_EXT                                           0x881B
+#define GL_ALPHA16F_EXT                                         0x881C
+#define GL_LUMINANCE16F_EXT                                     0x881E
+#define GL_LUMINANCE_ALPHA16F_EXT                               0x881F
+#define GL_RGB10_A2_EXT                                         0x8059  
+#define GL_RGB10_EXT                                            0x8052
+#define GL_BGRA8_EXT                                            0x93A1
+#endif
+
+/* GL_EXT_texture_type_2_10_10_10_REV */
+#ifndef GL_EXT_texture_type_2_10_10_10_REV
+#define GL_UNSIGNED_INT_2_10_10_10_REV_EXT                      0x8368
+#endif
+
+/* GL_EXT_unpack_subimage */
+#ifndef GL_EXT_unpack_subimage
+#define GL_UNPACK_ROW_LENGTH                                    0x0CF2
+#define GL_UNPACK_SKIP_ROWS                                     0x0CF3
+#define GL_UNPACK_SKIP_PIXELS                                   0x0CF4
+#endif
+
+/*------------------------------------------------------------------------*
+ * DMP extension tokens
+ *------------------------------------------------------------------------*/
+
+/* GL_DMP_shader_binary */
+#ifndef GL_DMP_shader_binary
+#define GL_SHADER_BINARY_DMP                                    0x9250
+#endif
+
+/*------------------------------------------------------------------------*
+ * IMG extension tokens
+ *------------------------------------------------------------------------*/
+
+/* GL_IMG_program_binary */
+#ifndef GL_IMG_program_binary
+#define GL_SGX_PROGRAM_BINARY_IMG                               0x9130
+#endif
+
+/* GL_IMG_read_format */
+#ifndef GL_IMG_read_format
+#define GL_BGRA_IMG                                             0x80E1
+#define GL_UNSIGNED_SHORT_4_4_4_4_REV_IMG                       0x8365
+#endif
+
+/* GL_IMG_shader_binary */
+#ifndef GL_IMG_shader_binary
+#define GL_SGX_BINARY_IMG                                       0x8C0A
+#endif
+
+/* GL_IMG_texture_compression_pvrtc */
+#ifndef GL_IMG_texture_compression_pvrtc
+#define GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG                      0x8C00
+#define GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG                      0x8C01
+#define GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG                     0x8C02
+#define GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG                     0x8C03
+#endif
+
+/* GL_IMG_multisampled_render_to_texture */
+#ifndef GL_IMG_multisampled_render_to_texture
+#define GL_RENDERBUFFER_SAMPLES_IMG                             0x9133
+#define GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_IMG               0x9134
+#define GL_MAX_SAMPLES_IMG                                      0x9135
+#define GL_TEXTURE_SAMPLES_IMG                                  0x9136
+#endif
+
+/*------------------------------------------------------------------------*
+ * NV extension tokens
+ *------------------------------------------------------------------------*/
+
+/* GL_NV_coverage_sample */
+#ifndef GL_NV_coverage_sample
+#define GL_COVERAGE_COMPONENT_NV                                0x8ED0
+#define GL_COVERAGE_COMPONENT4_NV                               0x8ED1
+#define GL_COVERAGE_ATTACHMENT_NV                               0x8ED2
+#define GL_COVERAGE_BUFFERS_NV                                  0x8ED3
+#define GL_COVERAGE_SAMPLES_NV                                  0x8ED4
+#define GL_COVERAGE_ALL_FRAGMENTS_NV                            0x8ED5
+#define GL_COVERAGE_EDGE_FRAGMENTS_NV                           0x8ED6
+#define GL_COVERAGE_AUTOMATIC_NV                                0x8ED7
+#define GL_COVERAGE_BUFFER_BIT_NV                               0x8000
+#endif
+
+/* GL_NV_depth_nonlinear */
+#ifndef GL_NV_depth_nonlinear
+#define GL_DEPTH_COMPONENT16_NONLINEAR_NV                       0x8E2C
+#endif
+
+/* GL_NV_draw_buffers */
+#ifndef GL_NV_draw_buffers
+#define GL_MAX_DRAW_BUFFERS_NV                                  0x8824
+#define GL_DRAW_BUFFER0_NV                                      0x8825
+#define GL_DRAW_BUFFER1_NV                                      0x8826
+#define GL_DRAW_BUFFER2_NV                                      0x8827
+#define GL_DRAW_BUFFER3_NV                                      0x8828
+#define GL_DRAW_BUFFER4_NV                                      0x8829
+#define GL_DRAW_BUFFER5_NV                                      0x882A
+#define GL_DRAW_BUFFER6_NV                                      0x882B
+#define GL_DRAW_BUFFER7_NV                                      0x882C
+#define GL_DRAW_BUFFER8_NV                                      0x882D
+#define GL_DRAW_BUFFER9_NV                                      0x882E
+#define GL_DRAW_BUFFER10_NV                                     0x882F
+#define GL_DRAW_BUFFER11_NV                                     0x8830
+#define GL_DRAW_BUFFER12_NV                                     0x8831
+#define GL_DRAW_BUFFER13_NV                                     0x8832
+#define GL_DRAW_BUFFER14_NV                                     0x8833
+#define GL_DRAW_BUFFER15_NV                                     0x8834
+#define GL_COLOR_ATTACHMENT0_NV                                 0x8CE0
+#define GL_COLOR_ATTACHMENT1_NV                                 0x8CE1
+#define GL_COLOR_ATTACHMENT2_NV                                 0x8CE2
+#define GL_COLOR_ATTACHMENT3_NV                                 0x8CE3
+#define GL_COLOR_ATTACHMENT4_NV                                 0x8CE4
+#define GL_COLOR_ATTACHMENT5_NV                                 0x8CE5
+#define GL_COLOR_ATTACHMENT6_NV                                 0x8CE6
+#define GL_COLOR_ATTACHMENT7_NV                                 0x8CE7
+#define GL_COLOR_ATTACHMENT8_NV                                 0x8CE8
+#define GL_COLOR_ATTACHMENT9_NV                                 0x8CE9
+#define GL_COLOR_ATTACHMENT10_NV                                0x8CEA
+#define GL_COLOR_ATTACHMENT11_NV                                0x8CEB
+#define GL_COLOR_ATTACHMENT12_NV                                0x8CEC
+#define GL_COLOR_ATTACHMENT13_NV                                0x8CED
+#define GL_COLOR_ATTACHMENT14_NV                                0x8CEE
+#define GL_COLOR_ATTACHMENT15_NV                                0x8CEF
+#endif
+
+/* GL_NV_fbo_color_attachments */
+#ifndef GL_NV_fbo_color_attachments
+#define GL_MAX_COLOR_ATTACHMENTS_NV                             0x8CDF
+/* GL_COLOR_ATTACHMENT{0-15}_NV defined in GL_NV_draw_buffers already. */
+#endif
+
+/* GL_NV_fence */
+#ifndef GL_NV_fence
+#define GL_ALL_COMPLETED_NV                                     0x84F2
+#define GL_FENCE_STATUS_NV                                      0x84F3
+#define GL_FENCE_CONDITION_NV                                   0x84F4
+#endif
+
+/* GL_NV_read_buffer */
+#ifndef GL_NV_read_buffer
+#define GL_READ_BUFFER_NV                                       0x0C02
+#endif
+
+/* GL_NV_read_buffer_front */
+/* No new tokens introduced by this extension. */
+
+/* GL_NV_read_depth */
+/* No new tokens introduced by this extension. */
+
+/* GL_NV_read_depth_stencil */
+/* No new tokens introduced by this extension. */
+
+/* GL_NV_read_stencil */
+/* No new tokens introduced by this extension. */
+
+/* GL_NV_texture_compression_s3tc_update */
+/* No new tokens introduced by this extension. */
+
+/* GL_NV_texture_npot_2D_mipmap */
+/* No new tokens introduced by this extension. */
+
+/*------------------------------------------------------------------------*
+ * QCOM extension tokens
+ *------------------------------------------------------------------------*/
+
+/* GL_QCOM_alpha_test */
+#ifndef GL_QCOM_alpha_test
+#define GL_ALPHA_TEST_QCOM                                      0x0BC0
+#define GL_ALPHA_TEST_FUNC_QCOM                                 0x0BC1
+#define GL_ALPHA_TEST_REF_QCOM                                  0x0BC2
+#endif
+
+/* GL_QCOM_driver_control */
+/* No new tokens introduced by this extension. */
+
+/* GL_QCOM_extended_get */
+#ifndef GL_QCOM_extended_get
+#define GL_TEXTURE_WIDTH_QCOM                                   0x8BD2
+#define GL_TEXTURE_HEIGHT_QCOM                                  0x8BD3
+#define GL_TEXTURE_DEPTH_QCOM                                   0x8BD4
+#define GL_TEXTURE_INTERNAL_FORMAT_QCOM                         0x8BD5
+#define GL_TEXTURE_FORMAT_QCOM                                  0x8BD6
+#define GL_TEXTURE_TYPE_QCOM                                    0x8BD7
+#define GL_TEXTURE_IMAGE_VALID_QCOM                             0x8BD8
+#define GL_TEXTURE_NUM_LEVELS_QCOM                              0x8BD9
+#define GL_TEXTURE_TARGET_QCOM                                  0x8BDA
+#define GL_TEXTURE_OBJECT_VALID_QCOM                            0x8BDB
+#define GL_STATE_RESTORE                                        0x8BDC
+#endif
+
+/* GL_QCOM_extended_get2 */
+/* No new tokens introduced by this extension. */
+
+/* GL_QCOM_perfmon_global_mode */
+#ifndef GL_QCOM_perfmon_global_mode
+#define GL_PERFMON_GLOBAL_MODE_QCOM                             0x8FA0
+#endif
+
+/* GL_QCOM_writeonly_rendering */
+#ifndef GL_QCOM_writeonly_rendering
+#define GL_WRITEONLY_RENDERING_QCOM                             0x8823
+#endif
+
+/* GL_QCOM_tiled_rendering */
+#ifndef GL_QCOM_tiled_rendering
+#define GL_COLOR_BUFFER_BIT0_QCOM                               0x00000001
+#define GL_COLOR_BUFFER_BIT1_QCOM                               0x00000002
+#define GL_COLOR_BUFFER_BIT2_QCOM                               0x00000004
+#define GL_COLOR_BUFFER_BIT3_QCOM                               0x00000008
+#define GL_COLOR_BUFFER_BIT4_QCOM                               0x00000010
+#define GL_COLOR_BUFFER_BIT5_QCOM                               0x00000020
+#define GL_COLOR_BUFFER_BIT6_QCOM                               0x00000040
+#define GL_COLOR_BUFFER_BIT7_QCOM                               0x00000080
+#define GL_DEPTH_BUFFER_BIT0_QCOM                               0x00000100
+#define GL_DEPTH_BUFFER_BIT1_QCOM                               0x00000200
+#define GL_DEPTH_BUFFER_BIT2_QCOM                               0x00000400
+#define GL_DEPTH_BUFFER_BIT3_QCOM                               0x00000800
+#define GL_DEPTH_BUFFER_BIT4_QCOM                               0x00001000
+#define GL_DEPTH_BUFFER_BIT5_QCOM                               0x00002000
+#define GL_DEPTH_BUFFER_BIT6_QCOM                               0x00004000
+#define GL_DEPTH_BUFFER_BIT7_QCOM                               0x00008000
+#define GL_STENCIL_BUFFER_BIT0_QCOM                             0x00010000
+#define GL_STENCIL_BUFFER_BIT1_QCOM                             0x00020000
+#define GL_STENCIL_BUFFER_BIT2_QCOM                             0x00040000
+#define GL_STENCIL_BUFFER_BIT3_QCOM                             0x00080000
+#define GL_STENCIL_BUFFER_BIT4_QCOM                             0x00100000
+#define GL_STENCIL_BUFFER_BIT5_QCOM                             0x00200000
+#define GL_STENCIL_BUFFER_BIT6_QCOM                             0x00400000
+#define GL_STENCIL_BUFFER_BIT7_QCOM                             0x00800000
+#define GL_MULTISAMPLE_BUFFER_BIT0_QCOM                         0x01000000
+#define GL_MULTISAMPLE_BUFFER_BIT1_QCOM                         0x02000000
+#define GL_MULTISAMPLE_BUFFER_BIT2_QCOM                         0x04000000
+#define GL_MULTISAMPLE_BUFFER_BIT3_QCOM                         0x08000000
+#define GL_MULTISAMPLE_BUFFER_BIT4_QCOM                         0x10000000
+#define GL_MULTISAMPLE_BUFFER_BIT5_QCOM                         0x20000000
+#define GL_MULTISAMPLE_BUFFER_BIT6_QCOM                         0x40000000
+#define GL_MULTISAMPLE_BUFFER_BIT7_QCOM                         0x80000000
+#endif
+
+/*------------------------------------------------------------------------*
+ * VIV extension tokens
+ *------------------------------------------------------------------------*/
+
+/* GL_VIV_shader_binary */
+#ifndef GL_VIV_shader_binary
+#define GL_SHADER_BINARY_VIV                                    0x8FC4
+#endif
+
+/*------------------------------------------------------------------------*
+ * End of extension tokens, start of corresponding extension functions
+ *------------------------------------------------------------------------*/
+
+/*------------------------------------------------------------------------*
+ * OES extension functions
+ *------------------------------------------------------------------------*/
+
+/* GL_OES_compressed_ETC1_RGB8_texture */
+#ifndef GL_OES_compressed_ETC1_RGB8_texture
+#define GL_OES_compressed_ETC1_RGB8_texture 1
+#endif
+
+/* GL_OES_compressed_paletted_texture */
+#ifndef GL_OES_compressed_paletted_texture
+#define GL_OES_compressed_paletted_texture 1
+#endif
+
+/* GL_OES_depth24 */
+#ifndef GL_OES_depth24
+#define GL_OES_depth24 1
+#endif
+
+/* GL_OES_depth32 */
+#ifndef GL_OES_depth32
+#define GL_OES_depth32 1
+#endif
+
+/* GL_OES_depth_texture */
+#ifndef GL_OES_depth_texture
+#define GL_OES_depth_texture 1
+#endif
+
+/* GL_OES_EGL_image */
+#ifndef GL_OES_EGL_image
+#define GL_OES_EGL_image 1
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glEGLImageTargetTexture2DOES (GLenum target, GLeglImageOES image);
+GL_APICALL void GL_APIENTRY glEGLImageTargetRenderbufferStorageOES (GLenum target, GLeglImageOES image);
+#endif
+typedef void (GL_APIENTRYP PFNGLEGLIMAGETARGETTEXTURE2DOESPROC) (GLenum target, GLeglImageOES image);
+typedef void (GL_APIENTRYP PFNGLEGLIMAGETARGETRENDERBUFFERSTORAGEOESPROC) (GLenum target, GLeglImageOES image);
+#endif
+
+/* GL_OES_EGL_image_external */
+#ifndef GL_OES_EGL_image_external
+#define GL_OES_EGL_image_external 1
+/* glEGLImageTargetTexture2DOES defined in GL_OES_EGL_image already. */
+#endif
+
+/* GL_OES_element_index_uint */
+#ifndef GL_OES_element_index_uint
+#define GL_OES_element_index_uint 1
+#endif
+
+/* GL_OES_fbo_render_mipmap */
+#ifndef GL_OES_fbo_render_mipmap
+#define GL_OES_fbo_render_mipmap 1
+#endif
+
+/* GL_OES_fragment_precision_high */
+#ifndef GL_OES_fragment_precision_high
+#define GL_OES_fragment_precision_high 1
+#endif
+
+/* GL_OES_get_program_binary */
+#ifndef GL_OES_get_program_binary
+#define GL_OES_get_program_binary 1
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glGetProgramBinaryOES (GLuint program, GLsizei bufSize, GLsizei *length, GLenum *binaryFormat, GLvoid *binary);
+GL_APICALL void GL_APIENTRY glProgramBinaryOES (GLuint program, GLenum binaryFormat, const GLvoid *binary, GLint length);
+#endif
+typedef void (GL_APIENTRYP PFNGLGETPROGRAMBINARYOESPROC) (GLuint program, GLsizei bufSize, GLsizei *length, GLenum *binaryFormat, GLvoid *binary);
+typedef void (GL_APIENTRYP PFNGLPROGRAMBINARYOESPROC) (GLuint program, GLenum binaryFormat, const GLvoid *binary, GLint length);
+#endif
+
+/* GL_OES_mapbuffer */
+#ifndef GL_OES_mapbuffer
+#define GL_OES_mapbuffer 1
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void* GL_APIENTRY glMapBufferOES (GLenum target, GLenum access);
+GL_APICALL GLboolean GL_APIENTRY glUnmapBufferOES (GLenum target);
+GL_APICALL void GL_APIENTRY glGetBufferPointervOES (GLenum target, GLenum pname, GLvoid** params);
+#endif
+typedef void* (GL_APIENTRYP PFNGLMAPBUFFEROESPROC) (GLenum target, GLenum access);
+typedef GLboolean (GL_APIENTRYP PFNGLUNMAPBUFFEROESPROC) (GLenum target);
+typedef void (GL_APIENTRYP PFNGLGETBUFFERPOINTERVOESPROC) (GLenum target, GLenum pname, GLvoid** params);
+#endif
+
+/* GL_OES_packed_depth_stencil */
+#ifndef GL_OES_packed_depth_stencil
+#define GL_OES_packed_depth_stencil 1
+#endif
+
+/* GL_OES_rgb8_rgba8 */
+#ifndef GL_OES_rgb8_rgba8
+#define GL_OES_rgb8_rgba8 1
+#endif
+
+/* GL_OES_standard_derivatives */
+#ifndef GL_OES_standard_derivatives
+#define GL_OES_standard_derivatives 1
+#endif
+
+/* GL_OES_stencil1 */
+#ifndef GL_OES_stencil1
+#define GL_OES_stencil1 1
+#endif
+
+/* GL_OES_stencil4 */
+#ifndef GL_OES_stencil4
+#define GL_OES_stencil4 1
+#endif
+
+/* GL_OES_texture_3D */
+#ifndef GL_OES_texture_3D
+#define GL_OES_texture_3D 1
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glTexImage3DOES (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const GLvoid* pixels);
+GL_APICALL void GL_APIENTRY glTexSubImage3DOES (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const GLvoid* pixels);
+GL_APICALL void GL_APIENTRY glCopyTexSubImage3DOES (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height);
+GL_APICALL void GL_APIENTRY glCompressedTexImage3DOES (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const GLvoid* data);
+GL_APICALL void GL_APIENTRY glCompressedTexSubImage3DOES (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const GLvoid* data);
+GL_APICALL void GL_APIENTRY glFramebufferTexture3DOES (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLint zoffset);
+#endif
+typedef void (GL_APIENTRYP PFNGLTEXIMAGE3DOESPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const GLvoid* pixels);
+typedef void (GL_APIENTRYP PFNGLTEXSUBIMAGE3DOESPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const GLvoid* pixels);
+typedef void (GL_APIENTRYP PFNGLCOPYTEXSUBIMAGE3DOESPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height);
+typedef void (GL_APIENTRYP PFNGLCOMPRESSEDTEXIMAGE3DOESPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const GLvoid* data);
+typedef void (GL_APIENTRYP PFNGLCOMPRESSEDTEXSUBIMAGE3DOESPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const GLvoid* data);
+typedef void (GL_APIENTRYP PFNGLFRAMEBUFFERTEXTURE3DOES) (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLint zoffset);
+#endif
+
+/* GL_OES_texture_float */
+#ifndef GL_OES_texture_float
+#define GL_OES_texture_float 1
+#endif
+
+/* GL_OES_texture_float_linear */
+#ifndef GL_OES_texture_float_linear
+#define GL_OES_texture_float_linear 1
+#endif
+
+/* GL_OES_texture_half_float */
+#ifndef GL_OES_texture_half_float
+#define GL_OES_texture_half_float 1
+#endif
+
+/* GL_OES_texture_half_float_linear */
+#ifndef GL_OES_texture_half_float_linear
+#define GL_OES_texture_half_float_linear 1
+#endif
+
+/* GL_OES_texture_npot */
+#ifndef GL_OES_texture_npot
+#define GL_OES_texture_npot 1
+#endif
+
+/* GL_OES_vertex_array_object */
+#ifndef GL_OES_vertex_array_object
+#define GL_OES_vertex_array_object 1
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glBindVertexArrayOES (GLuint array);
+GL_APICALL void GL_APIENTRY glDeleteVertexArraysOES (GLsizei n, const GLuint *arrays);
+GL_APICALL void GL_APIENTRY glGenVertexArraysOES (GLsizei n, GLuint *arrays);
+GL_APICALL GLboolean GL_APIENTRY glIsVertexArrayOES (GLuint array);
+#endif
+typedef void (GL_APIENTRYP PFNGLBINDVERTEXARRAYOESPROC) (GLuint array);
+typedef void (GL_APIENTRYP PFNGLDELETEVERTEXARRAYSOESPROC) (GLsizei n, const GLuint *arrays);
+typedef void (GL_APIENTRYP PFNGLGENVERTEXARRAYSOESPROC) (GLsizei n, GLuint *arrays);
+typedef GLboolean (GL_APIENTRYP PFNGLISVERTEXARRAYOESPROC) (GLuint array);
+#endif
+
+/* GL_OES_vertex_half_float */
+#ifndef GL_OES_vertex_half_float
+#define GL_OES_vertex_half_float 1
+#endif
+
+/* GL_OES_vertex_type_10_10_10_2 */
+#ifndef GL_OES_vertex_type_10_10_10_2
+#define GL_OES_vertex_type_10_10_10_2 1
+#endif
+
+/*------------------------------------------------------------------------*
+ * AMD extension functions
+ *------------------------------------------------------------------------*/
+
+/* GL_AMD_compressed_3DC_texture */
+#ifndef GL_AMD_compressed_3DC_texture
+#define GL_AMD_compressed_3DC_texture 1
+#endif
+
+/* GL_AMD_compressed_ATC_texture */
+#ifndef GL_AMD_compressed_ATC_texture
+#define GL_AMD_compressed_ATC_texture 1
+#endif
+
+/* AMD_performance_monitor */
+#ifndef GL_AMD_performance_monitor
+#define GL_AMD_performance_monitor 1
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glGetPerfMonitorGroupsAMD (GLint *numGroups, GLsizei groupsSize, GLuint *groups);
+GL_APICALL void GL_APIENTRY glGetPerfMonitorCountersAMD (GLuint group, GLint *numCounters, GLint *maxActiveCounters, GLsizei counterSize, GLuint *counters);
+GL_APICALL void GL_APIENTRY glGetPerfMonitorGroupStringAMD (GLuint group, GLsizei bufSize, GLsizei *length, GLchar *groupString);
+GL_APICALL void GL_APIENTRY glGetPerfMonitorCounterStringAMD (GLuint group, GLuint counter, GLsizei bufSize, GLsizei *length, GLchar *counterString);
+GL_APICALL void GL_APIENTRY glGetPerfMonitorCounterInfoAMD (GLuint group, GLuint counter, GLenum pname, GLvoid *data);
+GL_APICALL void GL_APIENTRY glGenPerfMonitorsAMD (GLsizei n, GLuint *monitors);
+GL_APICALL void GL_APIENTRY glDeletePerfMonitorsAMD (GLsizei n, GLuint *monitors);
+GL_APICALL void GL_APIENTRY glSelectPerfMonitorCountersAMD (GLuint monitor, GLboolean enable, GLuint group, GLint numCounters, GLuint *countersList);
+GL_APICALL void GL_APIENTRY glBeginPerfMonitorAMD (GLuint monitor);
+GL_APICALL void GL_APIENTRY glEndPerfMonitorAMD (GLuint monitor);
+GL_APICALL void GL_APIENTRY glGetPerfMonitorCounterDataAMD (GLuint monitor, GLenum pname, GLsizei dataSize, GLuint *data, GLint *bytesWritten);
+#endif
+typedef void (GL_APIENTRYP PFNGLGETPERFMONITORGROUPSAMDPROC) (GLint *numGroups, GLsizei groupsSize, GLuint *groups);
+typedef void (GL_APIENTRYP PFNGLGETPERFMONITORCOUNTERSAMDPROC) (GLuint group, GLint *numCounters, GLint *maxActiveCounters, GLsizei counterSize, GLuint *counters);
+typedef void (GL_APIENTRYP PFNGLGETPERFMONITORGROUPSTRINGAMDPROC) (GLuint group, GLsizei bufSize, GLsizei *length, GLchar *groupString);
+typedef void (GL_APIENTRYP PFNGLGETPERFMONITORCOUNTERSTRINGAMDPROC) (GLuint group, GLuint counter, GLsizei bufSize, GLsizei *length, GLchar *counterString);
+typedef void (GL_APIENTRYP PFNGLGETPERFMONITORCOUNTERINFOAMDPROC) (GLuint group, GLuint counter, GLenum pname, GLvoid *data);
+typedef void (GL_APIENTRYP PFNGLGENPERFMONITORSAMDPROC) (GLsizei n, GLuint *monitors);
+typedef void (GL_APIENTRYP PFNGLDELETEPERFMONITORSAMDPROC) (GLsizei n, GLuint *monitors);
+typedef void (GL_APIENTRYP PFNGLSELECTPERFMONITORCOUNTERSAMDPROC) (GLuint monitor, GLboolean enable, GLuint group, GLint numCounters, GLuint *countersList);
+typedef void (GL_APIENTRYP PFNGLBEGINPERFMONITORAMDPROC) (GLuint monitor);
+typedef void (GL_APIENTRYP PFNGLENDPERFMONITORAMDPROC) (GLuint monitor);
+typedef void (GL_APIENTRYP PFNGLGETPERFMONITORCOUNTERDATAAMDPROC) (GLuint monitor, GLenum pname, GLsizei dataSize, GLuint *data, GLint *bytesWritten);
+#endif
+
+/* GL_AMD_program_binary_Z400 */
+#ifndef GL_AMD_program_binary_Z400
+#define GL_AMD_program_binary_Z400 1
+#endif
+
+/*------------------------------------------------------------------------*
+ * ANGLE extension functions
+ *------------------------------------------------------------------------*/
+
+/* GL_ANGLE_framebuffer_blit */
+#ifndef GL_ANGLE_framebuffer_blit
+#define GL_ANGLE_framebuffer_blit 1
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glBlitFramebufferANGLE (GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter);
+#endif
+typedef void (GL_APIENTRYP PFNGLBLITFRAMEBUFFERANGLEPROC) (GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter);
+#endif
+
+/* GL_ANGLE_framebuffer_multisample */
+#ifndef GL_ANGLE_framebuffer_multisample
+#define GL_ANGLE_framebuffer_multisample 1
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glRenderbufferStorageMultisampleANGLE (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height);
+#endif
+typedef void (GL_APIENTRYP PFNGLRENDERBUFFERSTORAGEMULTISAMPLEANGLEPROC) (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height);
+#endif
+
+/* GL_ANGLE_pack_reverse_row_order */
+#ifndef GL_ANGLE_pack_reverse_row_order
+#define GL_ANGLE_pack_reverse_row_order 1
+#endif
+
+/* GL_ANGLE_texture_compression_dxt3 */
+#ifndef GL_ANGLE_texture_compression_dxt3
+#define GL_ANGLE_texture_compression_dxt3 1
+#endif
+
+/* GL_ANGLE_texture_compression_dxt5 */
+#ifndef GL_ANGLE_texture_compression_dxt5
+#define GL_ANGLE_texture_compression_dxt5 1
+#endif
+
+/* GL_ANGLE_translated_shader_source */
+#ifndef GL_ANGLE_translated_shader_source
+#define GL_ANGLE_translated_shader_source 1
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glGetTranslatedShaderSourceANGLE (GLuint shader, GLsizei bufsize, GLsizei* length, GLchar* source);
+#endif
+typedef void (GL_APIENTRYP PFNGLGETTRANSLATEDSHADERSOURCEANGLEPROC) (GLuint shader, GLsizei bufsize, GLsizei* length, GLchar* source);
+#endif
+
+/* GL_ANGLE_texture_usage */
+#ifndef GL_ANGLE_texture_usage
+#define GL_ANGLE_texture_usage 1
+#endif
+
+/* GL_ANGLE_instanced_arrays */
+#ifndef GL_ANGLE_instanced_arrays
+#define GL_ANGLE_instanced_arrays 1
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glVertexAttribDivisorANGLE(GLuint index, GLuint divisor);
+GL_APICALL void GL_APIENTRY glDrawArraysInstancedANGLE(GLenum mode, GLint first, GLsizei count, GLsizei primcount);
+GL_APICALL void GL_APIENTRY glDrawElementsInstancedANGLE(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, GLsizei primcount);
+#endif
+typedef void (GL_APIENTRYP PFNGLVERTEXATTRIBDIVISORANGLEPROC) (GLuint index, GLuint divisor);
+typedef void (GL_APIENTRYP PFNGLDRAWARRAYSINSTANCEDANGLEPROC) (GLenum mode, GLint first, GLsizei count, GLsizei primcount);
+typedef void (GL_APIENTRYP PFNGLDRAWELEMENTSINSTANCEDANGLEPROC) (GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, GLsizei primcount);
+#endif
+
+/*------------------------------------------------------------------------*
+ * APPLE extension functions
+ *------------------------------------------------------------------------*/
+
+/* GL_APPLE_rgb_422 */
+#ifndef GL_APPLE_rgb_422
+#define GL_APPLE_rgb_422 1
+#endif
+
+/* GL_APPLE_framebuffer_multisample */
+#ifndef GL_APPLE_framebuffer_multisample
+#define GL_APPLE_framebuffer_multisample 1
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glRenderbufferStorageMultisampleAPPLE (GLenum, GLsizei, GLenum, GLsizei, GLsizei);
+GL_APICALL void GL_APIENTRY glResolveMultisampleFramebufferAPPLE (void);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (GL_APIENTRYP PFNGLRENDERBUFFERSTORAGEMULTISAMPLEAPPLEPROC) (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height);
+typedef void (GL_APIENTRYP PFNGLRESOLVEMULTISAMPLEFRAMEBUFFERAPPLEPROC) (void);
+#endif
+
+/* GL_APPLE_texture_format_BGRA8888 */
+#ifndef GL_APPLE_texture_format_BGRA8888
+#define GL_APPLE_texture_format_BGRA8888 1
+#endif
+
+/* GL_APPLE_texture_max_level */
+#ifndef GL_APPLE_texture_max_level
+#define GL_APPLE_texture_max_level 1
+#endif
+
+/*------------------------------------------------------------------------*
+ * ARM extension functions
+ *------------------------------------------------------------------------*/
+
+/* GL_ARM_mali_shader_binary */
+#ifndef GL_ARM_mali_shader_binary
+#define GL_ARM_mali_shader_binary 1
+#endif
+
+/* GL_ARM_rgba8 */
+#ifndef GL_ARM_rgba8
+#define GL_ARM_rgba8 1
+#endif
+
+/*------------------------------------------------------------------------*
+ * EXT extension functions
+ *------------------------------------------------------------------------*/
+
+/* GL_EXT_blend_minmax */
+#ifndef GL_EXT_blend_minmax
+#define GL_EXT_blend_minmax 1
+#endif
+
+/* GL_EXT_color_buffer_half_float */
+#ifndef GL_EXT_color_buffer_half_float
+#define GL_EXT_color_buffer_half_float 1
+#endif
+
+/* GL_EXT_debug_label */
+#ifndef GL_EXT_debug_label
+#define GL_EXT_debug_label 1
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glLabelObjectEXT (GLenum type, GLuint object, GLsizei length, const GLchar *label);
+GL_APICALL void GL_APIENTRY glGetObjectLabelEXT (GLenum type, GLuint object, GLsizei bufSize, GLsizei *length, GLchar *label);
+#endif
+typedef void (GL_APIENTRYP PFNGLLABELOBJECTEXTPROC) (GLenum type, GLuint object, GLsizei length, const GLchar *label);
+typedef void (GL_APIENTRYP PFNGLGETOBJECTLABELEXTPROC) (GLenum type, GLuint object, GLsizei bufSize, GLsizei *length, GLchar *label);
+#endif
+
+/* GL_EXT_debug_marker */
+#ifndef GL_EXT_debug_marker
+#define GL_EXT_debug_marker 1
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glInsertEventMarkerEXT (GLsizei length, const GLchar *marker);
+GL_APICALL void GL_APIENTRY glPushGroupMarkerEXT (GLsizei length, const GLchar *marker);
+GL_APICALL void GL_APIENTRY glPopGroupMarkerEXT (void);
+#endif
+typedef void (GL_APIENTRYP PFNGLINSERTEVENTMARKEREXTPROC) (GLsizei length, const GLchar *marker);
+typedef void (GL_APIENTRYP PFNGLPUSHGROUPMARKEREXTPROC) (GLsizei length, const GLchar *marker);
+typedef void (GL_APIENTRYP PFNGLPOPGROUPMARKEREXTPROC) (void);
+#endif
+
+/* GL_EXT_discard_framebuffer */
+#ifndef GL_EXT_discard_framebuffer
+#define GL_EXT_discard_framebuffer 1
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glDiscardFramebufferEXT (GLenum target, GLsizei numAttachments, const GLenum *attachments);
+#endif
+typedef void (GL_APIENTRYP PFNGLDISCARDFRAMEBUFFEREXTPROC) (GLenum target, GLsizei numAttachments, const GLenum *attachments);
+#endif
+
+/* GL_EXT_multisampled_render_to_texture */
+#ifndef GL_EXT_multisampled_render_to_texture
+#define GL_EXT_multisampled_render_to_texture 1
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glRenderbufferStorageMultisampleEXT (GLenum, GLsizei, GLenum, GLsizei, GLsizei);
+GL_APICALL void GL_APIENTRY glFramebufferTexture2DMultisampleEXT (GLenum, GLenum, GLenum, GLuint, GLint, GLsizei);
+#endif
+typedef void (GL_APIENTRYP PFNGLRENDERBUFFERSTORAGEMULTISAMPLEEXTPROC) (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height);
+typedef void (GL_APIENTRYP PFNGLFRAMEBUFFERTEXTURE2DMULTISAMPLEEXTPROC) (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLsizei samples);
+#endif
+
+#ifndef GL_EXT_multi_draw_arrays
+#define GL_EXT_multi_draw_arrays 1
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glMultiDrawArraysEXT (GLenum, GLint *, GLsizei *, GLsizei);
+GL_APICALL void GL_APIENTRY glMultiDrawElementsEXT (GLenum, const GLsizei *, GLenum, const GLvoid* *, GLsizei);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (GL_APIENTRYP PFNGLMULTIDRAWARRAYSEXTPROC) (GLenum mode, GLint *first, GLsizei *count, GLsizei primcount);
+typedef void (GL_APIENTRYP PFNGLMULTIDRAWELEMENTSEXTPROC) (GLenum mode, const GLsizei *count, GLenum type, const GLvoid* *indices, GLsizei primcount);
+#endif
+
+/* GL_EXT_occlusion_query_boolean */
+#ifndef GL_EXT_occlusion_query_boolean
+#define GL_EXT_occlusion_query_boolean 1
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glGenQueriesEXT (GLsizei n, GLuint *ids);
+GL_APICALL void GL_APIENTRY glDeleteQueriesEXT (GLsizei n, const GLuint *ids);
+GL_APICALL GLboolean GL_APIENTRY glIsQueryEXT (GLuint id);
+GL_APICALL void GL_APIENTRY glBeginQueryEXT (GLenum target, GLuint id);
+GL_APICALL void GL_APIENTRY glEndQueryEXT (GLenum target);
+GL_APICALL void GL_APIENTRY glGetQueryivEXT (GLenum target, GLenum pname, GLint *params);
+GL_APICALL void GL_APIENTRY glGetQueryObjectuivEXT (GLuint id, GLenum pname, GLuint *params);
+#endif
+typedef void (GL_APIENTRYP PFNGLGENQUERIESEXTPROC) (GLsizei n, GLuint *ids);
+typedef void (GL_APIENTRYP PFNGLDELETEQUERIESEXTPROC) (GLsizei n, const GLuint *ids);
+typedef GLboolean (GL_APIENTRYP PFNGLISQUERYEXTPROC) (GLuint id);
+typedef void (GL_APIENTRYP PFNGLBEGINQUERYEXTPROC) (GLenum target, GLuint id);
+typedef void (GL_APIENTRYP PFNGLENDQUERYEXTPROC) (GLenum target);
+typedef void (GL_APIENTRYP PFNGLGETQUERYIVEXTPROC) (GLenum target, GLenum pname, GLint *params);
+typedef void (GL_APIENTRYP PFNGLGETQUERYOBJECTUIVEXTPROC) (GLuint id, GLenum pname, GLuint *params);
+#endif
+
+/* GL_EXT_read_format_bgra */
+#ifndef GL_EXT_read_format_bgra
+#define GL_EXT_read_format_bgra 1
+#endif
+
+/* GL_EXT_robustness */
+#ifndef GL_EXT_robustness
+#define GL_EXT_robustness 1
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL GLenum GL_APIENTRY glGetGraphicsResetStatusEXT (void);
+GL_APICALL void GL_APIENTRY glReadnPixelsEXT (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLsizei bufSize, void *data);
+GL_APICALL void GL_APIENTRY glGetnUniformfvEXT (GLuint program, GLint location, GLsizei bufSize, float *params);
+GL_APICALL void GL_APIENTRY glGetnUniformivEXT (GLuint program, GLint location, GLsizei bufSize, GLint *params);
+#endif
+typedef GLenum (GL_APIENTRYP PFNGLGETGRAPHICSRESETSTATUSEXTPROC) (void);
+typedef void (GL_APIENTRYP PFNGLREADNPIXELSEXTPROC) (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLsizei bufSize, void *data);
+typedef void (GL_APIENTRYP PFNGLGETNUNIFORMFVEXTPROC) (GLuint program, GLint location, GLsizei bufSize, float *params);
+typedef void (GL_APIENTRYP PFNGLGETNUNIFORMIVEXTPROC) (GLuint program, GLint location, GLsizei bufSize, GLint *params);
+#endif
+
+/* GL_EXT_separate_shader_objects */
+#ifndef GL_EXT_separate_shader_objects
+#define GL_EXT_separate_shader_objects 1
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glUseProgramStagesEXT (GLuint pipeline, GLbitfield stages, GLuint program);
+GL_APICALL void GL_APIENTRY glActiveShaderProgramEXT (GLuint pipeline, GLuint program);
+GL_APICALL GLuint GL_APIENTRY glCreateShaderProgramvEXT (GLenum type, GLsizei count, const GLchar **strings);
+GL_APICALL void GL_APIENTRY glBindProgramPipelineEXT (GLuint pipeline);
+GL_APICALL void GL_APIENTRY glDeleteProgramPipelinesEXT (GLsizei n, const GLuint *pipelines);
+GL_APICALL void GL_APIENTRY glGenProgramPipelinesEXT (GLsizei n, GLuint *pipelines);
+GL_APICALL GLboolean GL_APIENTRY glIsProgramPipelineEXT (GLuint pipeline);
+GL_APICALL void GL_APIENTRY glProgramParameteriEXT (GLuint program, GLenum pname, GLint value);
+GL_APICALL void GL_APIENTRY glGetProgramPipelineivEXT (GLuint pipeline, GLenum pname, GLint *params);
+GL_APICALL void GL_APIENTRY glProgramUniform1iEXT (GLuint program, GLint location, GLint x);
+GL_APICALL void GL_APIENTRY glProgramUniform2iEXT (GLuint program, GLint location, GLint x, GLint y);
+GL_APICALL void GL_APIENTRY glProgramUniform3iEXT (GLuint program, GLint location, GLint x, GLint y, GLint z);
+GL_APICALL void GL_APIENTRY glProgramUniform4iEXT (GLuint program, GLint location, GLint x, GLint y, GLint z, GLint w);
+GL_APICALL void GL_APIENTRY glProgramUniform1fEXT (GLuint program, GLint location, GLfloat x);
+GL_APICALL void GL_APIENTRY glProgramUniform2fEXT (GLuint program, GLint location, GLfloat x, GLfloat y);
+GL_APICALL void GL_APIENTRY glProgramUniform3fEXT (GLuint program, GLint location, GLfloat x, GLfloat y, GLfloat z);
+GL_APICALL void GL_APIENTRY glProgramUniform4fEXT (GLuint program, GLint location, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+GL_APICALL void GL_APIENTRY glProgramUniform1ivEXT (GLuint program, GLint location, GLsizei count, const GLint *value);
+GL_APICALL void GL_APIENTRY glProgramUniform2ivEXT (GLuint program, GLint location, GLsizei count, const GLint *value);
+GL_APICALL void GL_APIENTRY glProgramUniform3ivEXT (GLuint program, GLint location, GLsizei count, const GLint *value);
+GL_APICALL void GL_APIENTRY glProgramUniform4ivEXT (GLuint program, GLint location, GLsizei count, const GLint *value);
+GL_APICALL void GL_APIENTRY glProgramUniform1fvEXT (GLuint program, GLint location, GLsizei count, const GLfloat *value);
+GL_APICALL void GL_APIENTRY glProgramUniform2fvEXT (GLuint program, GLint location, GLsizei count, const GLfloat *value);
+GL_APICALL void GL_APIENTRY glProgramUniform3fvEXT (GLuint program, GLint location, GLsizei count, const GLfloat *value);
+GL_APICALL void GL_APIENTRY glProgramUniform4fvEXT (GLuint program, GLint location, GLsizei count, const GLfloat *value);
+GL_APICALL void GL_APIENTRY glProgramUniformMatrix2fvEXT (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GL_APICALL void GL_APIENTRY glProgramUniformMatrix3fvEXT (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GL_APICALL void GL_APIENTRY glProgramUniformMatrix4fvEXT (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GL_APICALL void GL_APIENTRY glValidateProgramPipelineEXT (GLuint pipeline);
+GL_APICALL void GL_APIENTRY glGetProgramPipelineInfoLogEXT (GLuint pipeline, GLsizei bufSize, GLsizei *length, GLchar *infoLog);
+#endif
+typedef void (GL_APIENTRYP PFNGLUSEPROGRAMSTAGESEXTPROC) (GLuint pipeline, GLbitfield stages, GLuint program);
+typedef void (GL_APIENTRYP PFNGLACTIVESHADERPROGRAMEXTPROC) (GLuint pipeline, GLuint program);
+typedef GLuint (GL_APIENTRYP PFNGLCREATESHADERPROGRAMVEXTPROC) (GLenum type, GLsizei count, const GLchar **strings);
+typedef void (GL_APIENTRYP PFNGLBINDPROGRAMPIPELINEEXTPROC) (GLuint pipeline);
+typedef void (GL_APIENTRYP PFNGLDELETEPROGRAMPIPELINESEXTPROC) (GLsizei n, const GLuint *pipelines);
+typedef void (GL_APIENTRYP PFNGLGENPROGRAMPIPELINESEXTPROC) (GLsizei n, GLuint *pipelines);
+typedef GLboolean (GL_APIENTRYP PFNGLISPROGRAMPIPELINEEXTPROC) (GLuint pipeline);
+typedef void (GL_APIENTRYP PFNGLPROGRAMPARAMETERIEXTPROC) (GLuint program, GLenum pname, GLint value);
+typedef void (GL_APIENTRYP PFNGLGETPROGRAMPIPELINEIVEXTPROC) (GLuint pipeline, GLenum pname, GLint *params);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM1IEXTPROC) (GLuint program, GLint location, GLint x);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM2IEXTPROC) (GLuint program, GLint location, GLint x, GLint y);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM3IEXTPROC) (GLuint program, GLint location, GLint x, GLint y, GLint z);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM4IEXTPROC) (GLuint program, GLint location, GLint x, GLint y, GLint z, GLint w);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM1FEXTPROC) (GLuint program, GLint location, GLfloat x);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM2FEXTPROC) (GLuint program, GLint location, GLfloat x, GLfloat y);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM3FEXTPROC) (GLuint program, GLint location, GLfloat x, GLfloat y, GLfloat z);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM4FEXTPROC) (GLuint program, GLint location, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM1IVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLint *value);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM2IVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLint *value);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM3IVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLint *value);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM4IVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLint *value);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM1FVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM2FVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM3FVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM4FVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORMMATRIX2FVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORMMATRIX3FVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORMMATRIX4FVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLVALIDATEPROGRAMPIPELINEEXTPROC) (GLuint pipeline);
+typedef void (GL_APIENTRYP PFNGLGETPROGRAMPIPELINEINFOLOGEXTPROC) (GLuint pipeline, GLsizei bufSize, GLsizei *length, GLchar *infoLog);
+#endif
+
+/* GL_EXT_shader_texture_lod */
+#ifndef GL_EXT_shader_texture_lod
+#define GL_EXT_shader_texture_lod 1
+#endif
+
+/* GL_EXT_shadow_samplers */
+#ifndef GL_EXT_shadow_samplers
+#define GL_EXT_shadow_samplers 1
+#endif
+
+/* GL_EXT_sRGB */
+#ifndef GL_EXT_sRGB
+#define GL_EXT_sRGB 1
+#endif
+
+/* GL_EXT_texture_compression_dxt1 */
+#ifndef GL_EXT_texture_compression_dxt1
+#define GL_EXT_texture_compression_dxt1 1
+#endif
+
+/* GL_EXT_texture_filter_anisotropic */
+#ifndef GL_EXT_texture_filter_anisotropic
+#define GL_EXT_texture_filter_anisotropic 1
+#endif
+
+/* GL_EXT_texture_format_BGRA8888 */
+#ifndef GL_EXT_texture_format_BGRA8888
+#define GL_EXT_texture_format_BGRA8888 1
+#endif
+
+/* GL_EXT_texture_rg */
+#ifndef GL_EXT_texture_rg
+#define GL_EXT_texture_rg 1
+#endif
+
+/* GL_EXT_texture_storage */
+#ifndef GL_EXT_texture_storage
+#define GL_EXT_texture_storage 1
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glTexStorage1DEXT (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width);
+GL_APICALL void GL_APIENTRY glTexStorage2DEXT (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height);
+GL_APICALL void GL_APIENTRY glTexStorage3DEXT (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth);
+GL_APICALL void GL_APIENTRY glTextureStorage1DEXT (GLuint texture, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width);
+GL_APICALL void GL_APIENTRY glTextureStorage2DEXT (GLuint texture, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height);
+GL_APICALL void GL_APIENTRY glTextureStorage3DEXT (GLuint texture, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth);
+#endif
+typedef void (GL_APIENTRYP PFNGLTEXSTORAGE1DEXTPROC) (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width);
+typedef void (GL_APIENTRYP PFNGLTEXSTORAGE2DEXTPROC) (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height);
+typedef void (GL_APIENTRYP PFNGLTEXSTORAGE3DEXTPROC) (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth);
+typedef void (GL_APIENTRYP PFNGLTEXTURESTORAGE1DEXTPROC) (GLuint texture, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width);
+typedef void (GL_APIENTRYP PFNGLTEXTURESTORAGE2DEXTPROC) (GLuint texture, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height);
+typedef void (GL_APIENTRYP PFNGLTEXTURESTORAGE3DEXTPROC) (GLuint texture, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth);
+#endif
+
+/* GL_EXT_texture_type_2_10_10_10_REV */
+#ifndef GL_EXT_texture_type_2_10_10_10_REV
+#define GL_EXT_texture_type_2_10_10_10_REV 1
+#endif
+
+/* GL_EXT_unpack_subimage */
+#ifndef GL_EXT_unpack_subimage
+#define GL_EXT_unpack_subimage 1
+#endif
+
+/*------------------------------------------------------------------------*
+ * DMP extension functions
+ *------------------------------------------------------------------------*/
+
+/* GL_DMP_shader_binary */
+#ifndef GL_DMP_shader_binary
+#define GL_DMP_shader_binary 1
+#endif
+
+/*------------------------------------------------------------------------*
+ * IMG extension functions
+ *------------------------------------------------------------------------*/
+
+/* GL_IMG_program_binary */
+#ifndef GL_IMG_program_binary
+#define GL_IMG_program_binary 1
+#endif
+
+/* GL_IMG_read_format */
+#ifndef GL_IMG_read_format
+#define GL_IMG_read_format 1
+#endif
+
+/* GL_IMG_shader_binary */
+#ifndef GL_IMG_shader_binary
+#define GL_IMG_shader_binary 1
+#endif
+
+/* GL_IMG_texture_compression_pvrtc */
+#ifndef GL_IMG_texture_compression_pvrtc
+#define GL_IMG_texture_compression_pvrtc 1
+#endif
+
+/* GL_IMG_multisampled_render_to_texture */
+#ifndef GL_IMG_multisampled_render_to_texture
+#define GL_IMG_multisampled_render_to_texture 1
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glRenderbufferStorageMultisampleIMG (GLenum, GLsizei, GLenum, GLsizei, GLsizei);
+GL_APICALL void GL_APIENTRY glFramebufferTexture2DMultisampleIMG (GLenum, GLenum, GLenum, GLuint, GLint, GLsizei);
+#endif
+typedef void (GL_APIENTRYP PFNGLRENDERBUFFERSTORAGEMULTISAMPLEIMG) (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height);
+typedef void (GL_APIENTRYP PFNGLFRAMEBUFFERTEXTURE2DMULTISAMPLEIMG) (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLsizei samples);
+#endif
+
+/*------------------------------------------------------------------------*
+ * NV extension functions
+ *------------------------------------------------------------------------*/
+
+/* GL_NV_coverage_sample */
+#ifndef GL_NV_coverage_sample
+#define GL_NV_coverage_sample 1
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glCoverageMaskNV (GLboolean mask);
+GL_APICALL void GL_APIENTRY glCoverageOperationNV (GLenum operation);
+#endif
+typedef void (GL_APIENTRYP PFNGLCOVERAGEMASKNVPROC) (GLboolean mask);
+typedef void (GL_APIENTRYP PFNGLCOVERAGEOPERATIONNVPROC) (GLenum operation);
+#endif
+
+/* GL_NV_depth_nonlinear */
+#ifndef GL_NV_depth_nonlinear
+#define GL_NV_depth_nonlinear 1
+#endif
+
+/* GL_NV_draw_buffers */
+#ifndef GL_NV_draw_buffers
+#define GL_NV_draw_buffers 1
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glDrawBuffersNV (GLsizei n, const GLenum *bufs);
+#endif
+typedef void (GL_APIENTRYP PFNGLDRAWBUFFERSNVPROC) (GLsizei n, const GLenum *bufs);
+#endif
+
+/* GL_NV_fbo_color_attachments */
+#ifndef GL_NV_fbo_color_attachments
+#define GL_NV_fbo_color_attachments 1
+#endif
+
+/* GL_NV_fence */
+#ifndef GL_NV_fence
+#define GL_NV_fence 1
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glDeleteFencesNV (GLsizei, const GLuint *);
+GL_APICALL void GL_APIENTRY glGenFencesNV (GLsizei, GLuint *);
+GL_APICALL GLboolean GL_APIENTRY glIsFenceNV (GLuint);
+GL_APICALL GLboolean GL_APIENTRY glTestFenceNV (GLuint);
+GL_APICALL void GL_APIENTRY glGetFenceivNV (GLuint, GLenum, GLint *);
+GL_APICALL void GL_APIENTRY glFinishFenceNV (GLuint);
+GL_APICALL void GL_APIENTRY glSetFenceNV (GLuint, GLenum);
+#endif
+typedef void (GL_APIENTRYP PFNGLDELETEFENCESNVPROC) (GLsizei n, const GLuint *fences);
+typedef void (GL_APIENTRYP PFNGLGENFENCESNVPROC) (GLsizei n, GLuint *fences);
+typedef GLboolean (GL_APIENTRYP PFNGLISFENCENVPROC) (GLuint fence);
+typedef GLboolean (GL_APIENTRYP PFNGLTESTFENCENVPROC) (GLuint fence);
+typedef void (GL_APIENTRYP PFNGLGETFENCEIVNVPROC) (GLuint fence, GLenum pname, GLint *params);
+typedef void (GL_APIENTRYP PFNGLFINISHFENCENVPROC) (GLuint fence);
+typedef void (GL_APIENTRYP PFNGLSETFENCENVPROC) (GLuint fence, GLenum condition);
+#endif
+
+/* GL_NV_read_buffer */
+#ifndef GL_NV_read_buffer
+#define GL_NV_read_buffer 1
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glReadBufferNV (GLenum mode);
+#endif
+typedef void (GL_APIENTRYP PFNGLREADBUFFERNVPROC) (GLenum mode);
+#endif
+
+/* GL_NV_read_buffer_front */
+#ifndef GL_NV_read_buffer_front
+#define GL_NV_read_buffer_front 1
+#endif
+
+/* GL_NV_read_depth */
+#ifndef GL_NV_read_depth
+#define GL_NV_read_depth 1
+#endif
+
+/* GL_NV_read_depth_stencil */
+#ifndef GL_NV_read_depth_stencil
+#define GL_NV_read_depth_stencil 1
+#endif
+
+/* GL_NV_read_stencil */
+#ifndef GL_NV_read_stencil
+#define GL_NV_read_stencil 1
+#endif
+
+/* GL_NV_texture_compression_s3tc_update */
+#ifndef GL_NV_texture_compression_s3tc_update
+#define GL_NV_texture_compression_s3tc_update 1
+#endif
+
+/* GL_NV_texture_npot_2D_mipmap */
+#ifndef GL_NV_texture_npot_2D_mipmap
+#define GL_NV_texture_npot_2D_mipmap 1
+#endif
+
+/*------------------------------------------------------------------------*
+ * QCOM extension functions
+ *------------------------------------------------------------------------*/
+
+/* GL_QCOM_alpha_test */
+#ifndef GL_QCOM_alpha_test
+#define GL_QCOM_alpha_test 1
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glAlphaFuncQCOM (GLenum func, GLclampf ref);
+#endif
+typedef void (GL_APIENTRYP PFNGLALPHAFUNCQCOMPROC) (GLenum func, GLclampf ref);
+#endif
+
+/* GL_QCOM_driver_control */
+#ifndef GL_QCOM_driver_control
+#define GL_QCOM_driver_control 1
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glGetDriverControlsQCOM (GLint *num, GLsizei size, GLuint *driverControls);
+GL_APICALL void GL_APIENTRY glGetDriverControlStringQCOM (GLuint driverControl, GLsizei bufSize, GLsizei *length, GLchar *driverControlString);
+GL_APICALL void GL_APIENTRY glEnableDriverControlQCOM (GLuint driverControl);
+GL_APICALL void GL_APIENTRY glDisableDriverControlQCOM (GLuint driverControl);
+#endif
+typedef void (GL_APIENTRYP PFNGLGETDRIVERCONTROLSQCOMPROC) (GLint *num, GLsizei size, GLuint *driverControls);
+typedef void (GL_APIENTRYP PFNGLGETDRIVERCONTROLSTRINGQCOMPROC) (GLuint driverControl, GLsizei bufSize, GLsizei *length, GLchar *driverControlString);
+typedef void (GL_APIENTRYP PFNGLENABLEDRIVERCONTROLQCOMPROC) (GLuint driverControl);
+typedef void (GL_APIENTRYP PFNGLDISABLEDRIVERCONTROLQCOMPROC) (GLuint driverControl);
+#endif
+
+/* GL_QCOM_extended_get */
+#ifndef GL_QCOM_extended_get
+#define GL_QCOM_extended_get 1
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glExtGetTexturesQCOM (GLuint *textures, GLint maxTextures, GLint *numTextures);
+GL_APICALL void GL_APIENTRY glExtGetBuffersQCOM (GLuint *buffers, GLint maxBuffers, GLint *numBuffers);
+GL_APICALL void GL_APIENTRY glExtGetRenderbuffersQCOM (GLuint *renderbuffers, GLint maxRenderbuffers, GLint *numRenderbuffers);
+GL_APICALL void GL_APIENTRY glExtGetFramebuffersQCOM (GLuint *framebuffers, GLint maxFramebuffers, GLint *numFramebuffers);
+GL_APICALL void GL_APIENTRY glExtGetTexLevelParameterivQCOM (GLuint texture, GLenum face, GLint level, GLenum pname, GLint *params);
+GL_APICALL void GL_APIENTRY glExtTexObjectStateOverrideiQCOM (GLenum target, GLenum pname, GLint param);
+GL_APICALL void GL_APIENTRY glExtGetTexSubImageQCOM (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, GLvoid *texels);
+GL_APICALL void GL_APIENTRY glExtGetBufferPointervQCOM (GLenum target, GLvoid **params);
+#endif
+typedef void (GL_APIENTRYP PFNGLEXTGETTEXTURESQCOMPROC) (GLuint *textures, GLint maxTextures, GLint *numTextures);
+typedef void (GL_APIENTRYP PFNGLEXTGETBUFFERSQCOMPROC) (GLuint *buffers, GLint maxBuffers, GLint *numBuffers);
+typedef void (GL_APIENTRYP PFNGLEXTGETRENDERBUFFERSQCOMPROC) (GLuint *renderbuffers, GLint maxRenderbuffers, GLint *numRenderbuffers);
+typedef void (GL_APIENTRYP PFNGLEXTGETFRAMEBUFFERSQCOMPROC) (GLuint *framebuffers, GLint maxFramebuffers, GLint *numFramebuffers);
+typedef void (GL_APIENTRYP PFNGLEXTGETTEXLEVELPARAMETERIVQCOMPROC) (GLuint texture, GLenum face, GLint level, GLenum pname, GLint *params);
+typedef void (GL_APIENTRYP PFNGLEXTTEXOBJECTSTATEOVERRIDEIQCOMPROC) (GLenum target, GLenum pname, GLint param);
+typedef void (GL_APIENTRYP PFNGLEXTGETTEXSUBIMAGEQCOMPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, GLvoid *texels);
+typedef void (GL_APIENTRYP PFNGLEXTGETBUFFERPOINTERVQCOMPROC) (GLenum target, GLvoid **params);
+#endif
+
+/* GL_QCOM_extended_get2 */
+#ifndef GL_QCOM_extended_get2
+#define GL_QCOM_extended_get2 1
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glExtGetShadersQCOM (GLuint *shaders, GLint maxShaders, GLint *numShaders);
+GL_APICALL void GL_APIENTRY glExtGetProgramsQCOM (GLuint *programs, GLint maxPrograms, GLint *numPrograms);
+GL_APICALL GLboolean GL_APIENTRY glExtIsProgramBinaryQCOM (GLuint program);
+GL_APICALL void GL_APIENTRY glExtGetProgramBinarySourceQCOM (GLuint program, GLenum shadertype, GLchar *source, GLint *length);
+#endif
+typedef void (GL_APIENTRYP PFNGLEXTGETSHADERSQCOMPROC) (GLuint *shaders, GLint maxShaders, GLint *numShaders);
+typedef void (GL_APIENTRYP PFNGLEXTGETPROGRAMSQCOMPROC) (GLuint *programs, GLint maxPrograms, GLint *numPrograms);
+typedef GLboolean (GL_APIENTRYP PFNGLEXTISPROGRAMBINARYQCOMPROC) (GLuint program);
+typedef void (GL_APIENTRYP PFNGLEXTGETPROGRAMBINARYSOURCEQCOMPROC) (GLuint program, GLenum shadertype, GLchar *source, GLint *length);
+#endif
+
+/* GL_QCOM_perfmon_global_mode */
+#ifndef GL_QCOM_perfmon_global_mode
+#define GL_QCOM_perfmon_global_mode 1
+#endif
+
+/* GL_QCOM_writeonly_rendering */
+#ifndef GL_QCOM_writeonly_rendering
+#define GL_QCOM_writeonly_rendering 1
+#endif
+
+/* GL_QCOM_tiled_rendering */
+#ifndef GL_QCOM_tiled_rendering
+#define GL_QCOM_tiled_rendering 1
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glStartTilingQCOM (GLuint x, GLuint y, GLuint width, GLuint height, GLbitfield preserveMask);
+GL_APICALL void GL_APIENTRY glEndTilingQCOM (GLbitfield preserveMask);
+#endif
+typedef void (GL_APIENTRYP PFNGLSTARTTILINGQCOMPROC) (GLuint x, GLuint y, GLuint width, GLuint height, GLbitfield preserveMask);
+typedef void (GL_APIENTRYP PFNGLENDTILINGQCOMPROC) (GLbitfield preserveMask);
+#endif
+
+/*------------------------------------------------------------------------*
+ * VIV extension tokens
+ *------------------------------------------------------------------------*/
+
+/* GL_VIV_shader_binary */
+#ifndef GL_VIV_shader_binary
+#define GL_VIV_shader_binary 1
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __gl2ext_h_ */
diff --git a/src/GLES2/include/GLES2/gl2platform.h b/src/GLES2/include/GLES2/gl2platform.h
new file mode 100644
index 0000000..c9fa3c4
--- /dev/null
+++ b/src/GLES2/include/GLES2/gl2platform.h
@@ -0,0 +1,30 @@
+#ifndef __gl2platform_h_
+#define __gl2platform_h_
+
+/* $Revision: 10602 $ on $Date:: 2010-03-04 22:35:34 -0800 #$ */
+
+/*
+ * This document is licensed under the SGI Free Software B License Version
+ * 2.0. For details, see http://oss.sgi.com/projects/FreeB/ .
+ */
+
+/* Platform-specific types and definitions for OpenGL ES 2.X  gl2.h
+ *
+ * Adopters may modify khrplatform.h and this file to suit their platform.
+ * You are encouraged to submit all modifications to the Khronos group so that
+ * they can be included in future versions of this file.  Please submit changes
+ * by sending them to the public Khronos Bugzilla (http://khronos.org/bugzilla)
+ * by filing a bug against product "OpenGL-ES" component "Registry".
+ */
+
+#include <KHR/khrplatform.h>
+
+#ifndef GL_APICALL
+#define GL_APICALL  KHRONOS_APICALL
+#endif
+
+#ifndef GL_APIENTRY
+#define GL_APIENTRY KHRONOS_APIENTRY
+#endif
+
+#endif /* __gl2platform_h_ */
diff --git a/src/GLES2/include/GLSLANG/ShaderLang.h b/src/GLES2/include/GLSLANG/ShaderLang.h
new file mode 100644
index 0000000..0d78834
--- /dev/null
+++ b/src/GLES2/include/GLSLANG/ShaderLang.h
@@ -0,0 +1,272 @@
+//
+// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+#ifndef _COMPILER_INTERFACE_INCLUDED_
+#define _COMPILER_INTERFACE_INCLUDED_
+
+//
+// This is the platform independent interface between an OGL driver
+// and the shading language compiler.
+//
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// Version number for shader translation API.
+// It is incremented everytime the API changes.
+#define SH_VERSION 104
+
+//
+// The names of the following enums have been derived by replacing GL prefix
+// with SH. For example, SH_INFO_LOG_LENGTH is equivalent to GL_INFO_LOG_LENGTH.
+// The enum values are also equal to the values of their GL counterpart. This
+// is done to make it easier for applications to use the shader library.
+//
+typedef enum {
+  SH_FRAGMENT_SHADER = 0x8B30,
+  SH_VERTEX_SHADER   = 0x8B31
+} ShShaderType;
+
+typedef enum {
+  SH_GLES2_SPEC = 0x8B40,
+  SH_WEBGL_SPEC = 0x8B41
+} ShShaderSpec;
+
+typedef enum {
+  SH_NONE           = 0,
+  SH_INT            = 0x1404,
+  SH_FLOAT          = 0x1406,
+  SH_FLOAT_VEC2     = 0x8B50,
+  SH_FLOAT_VEC3     = 0x8B51,
+  SH_FLOAT_VEC4     = 0x8B52,
+  SH_INT_VEC2       = 0x8B53,
+  SH_INT_VEC3       = 0x8B54,
+  SH_INT_VEC4       = 0x8B55,
+  SH_BOOL           = 0x8B56,
+  SH_BOOL_VEC2      = 0x8B57,
+  SH_BOOL_VEC3      = 0x8B58,
+  SH_BOOL_VEC4      = 0x8B59,
+  SH_FLOAT_MAT2     = 0x8B5A,
+  SH_FLOAT_MAT3     = 0x8B5B,
+  SH_FLOAT_MAT4     = 0x8B5C,
+  SH_SAMPLER_2D     = 0x8B5E,
+  SH_SAMPLER_CUBE   = 0x8B60
+} ShDataType;
+
+typedef enum {
+  SH_INFO_LOG_LENGTH             =  0x8B84,
+  SH_OBJECT_CODE_LENGTH          =  0x8B88,  // GL_SHADER_SOURCE_LENGTH
+  SH_ACTIVE_UNIFORMS             =  0x8B86,
+  SH_ACTIVE_UNIFORM_MAX_LENGTH   =  0x8B87,
+  SH_ACTIVE_ATTRIBUTES           =  0x8B89,
+  SH_ACTIVE_ATTRIBUTE_MAX_LENGTH =  0x8B8A
+} ShShaderInfo;
+
+// Compile options.
+typedef enum {
+  SH_VALIDATE                = 0,
+  SH_VALIDATE_LOOP_INDEXING  = 0x0001,
+  SH_INTERMEDIATE_TREE       = 0x0002,
+  SH_OBJECT_CODE             = 0x0004,
+  SH_ATTRIBUTES_UNIFORMS     = 0x0008,
+  SH_LINE_DIRECTIVES         = 0x0010,
+  SH_SOURCE_PATH             = 0x0020
+} ShCompileOptions;
+
+//
+// Driver must call this first, once, before doing any other
+// compiler operations.
+// If the function succeeds, the return value is nonzero, else zero.
+//
+int ShInitialize();
+//
+// Driver should call this at shutdown.
+// If the function succeeds, the return value is nonzero, else zero.
+//
+int ShFinalize();
+
+//
+// Implementation dependent built-in resources (constants and extensions).
+// The names for these resources has been obtained by stripping gl_/GL_.
+//
+typedef struct
+{
+    // Constants.
+    int MaxVertexAttribs;
+    int MaxVertexUniformVectors;
+    int MaxVaryingVectors;
+    int MaxVertexTextureImageUnits;
+    int MaxCombinedTextureImageUnits;
+    int MaxTextureImageUnits;
+    int MaxFragmentUniformVectors;
+    int MaxDrawBuffers;
+
+    // Extensions.
+    // Set to 1 to enable the extension, else 0.
+    int OES_standard_derivatives;
+} ShBuiltInResources;
+
+//
+// Initialize built-in resources with minimum expected values.
+//
+void ShInitBuiltInResources(ShBuiltInResources* resources);
+
+//
+// ShHandle held by but opaque to the driver.  It is allocated,
+// managed, and de-allocated by the compiler. It's contents 
+// are defined by and used by the compiler.
+//
+// If handle creation fails, 0 will be returned.
+//
+typedef void* ShHandle;
+
+//
+// Driver calls these to create and destroy compiler objects.
+//
+// Returns the handle of constructed compiler.
+// Parameters:
+// type: Specifies the type of shader - SH_FRAGMENT_SHADER or SH_VERTEX_SHADER.
+// spec: Specifies the language spec the compiler must conform to -
+//       SH_GLES2_SPEC or SH_WEBGL_SPEC.
+// resources: Specifies the built-in resources.
+ShHandle ShConstructCompiler(ShShaderType type, ShShaderSpec spec,
+                             const ShBuiltInResources* resources);
+void ShDestruct(ShHandle handle);
+
+//
+// Compiles the given shader source.
+// If the function succeeds, the return value is nonzero, else zero.
+// Parameters:
+// handle: Specifies the handle of compiler to be used.
+// shaderStrings: Specifies an array of pointers to null-terminated strings
+//                containing the shader source code.
+// numStrings: Specifies the number of elements in shaderStrings array.
+// compileOptions: A mask containing the following parameters:
+// SH_VALIDATE: Validates shader to ensure that it conforms to the spec
+//              specified during compiler construction.
+// SH_VALIDATE_LOOP_INDEXING: Validates loop and indexing in the shader to
+//                            ensure that they do not exceed the minimum
+//                            functionality mandated in GLSL 1.0 spec,
+//                            Appendix A, Section 4 and 5.
+//                            There is no need to specify this parameter when
+//                            compiling for WebGL - it is implied.
+// SH_INTERMEDIATE_TREE: Writes intermediate tree to info log.
+//                       Can be queried by calling ShGetInfoLog().
+// SH_OBJECT_CODE: Translates intermediate tree to glsl or hlsl shader.
+//                 Can be queried by calling ShGetObjectCode().
+// SH_ATTRIBUTES_UNIFORMS: Extracts attributes and uniforms.
+//                         Can be queried by calling ShGetActiveAttrib() and
+//                         ShGetActiveUniform().
+//
+int ShCompile(
+    const ShHandle handle,
+    const char* const shaderStrings[],
+    const int numStrings,
+    int compileOptions
+    );
+
+// Returns a parameter from a compiled shader.
+// Parameters:
+// handle: Specifies the compiler
+// pname: Specifies the parameter to query.
+// The following parameters are defined:
+// SH_INFO_LOG_LENGTH: the number of characters in the information log
+//                     including the null termination character.
+// SH_OBJECT_CODE_LENGTH: the number of characters in the object code
+//                        including the null termination character.
+// SH_ACTIVE_ATTRIBUTES: the number of active attribute variables.
+// SH_ACTIVE_ATTRIBUTE_MAX_LENGTH: the length of the longest active attribute
+//                                 variable name including the null
+//                                 termination character.
+// SH_ACTIVE_UNIFORMS: the number of active uniform variables.
+// SH_ACTIVE_UNIFORM_MAX_LENGTH: the length of the longest active uniform
+//                               variable name including the null
+//                               termination character.
+// SH_MAPPED_NAME_MAX_LENGTH: the length of the mapped variable name including
+//                            the null termination character.
+// 
+// params: Requested parameter
+void ShGetInfo(const ShHandle handle, ShShaderInfo pname, int* params);
+
+// Returns nul-terminated information log for a compiled shader.
+// Parameters:
+// handle: Specifies the compiler
+// infoLog: Specifies an array of characters that is used to return
+//          the information log. It is assumed that infoLog has enough memory
+//          to accomodate the information log. The size of the buffer required
+//          to store the returned information log can be obtained by calling
+//          ShGetInfo with SH_INFO_LOG_LENGTH.
+void ShGetInfoLog(const ShHandle handle, char* infoLog);
+
+// Returns null-terminated object code for a compiled shader.
+// Parameters:
+// handle: Specifies the compiler
+// infoLog: Specifies an array of characters that is used to return
+//          the object code. It is assumed that infoLog has enough memory to
+//          accomodate the object code. The size of the buffer required to
+//          store the returned object code can be obtained by calling
+//          ShGetInfo with SH_OBJECT_CODE_LENGTH.
+void ShGetObjectCode(const ShHandle handle, char* objCode);
+
+// Returns information about an active attribute variable.
+// Parameters:
+// handle: Specifies the compiler
+// index: Specifies the index of the attribute variable to be queried.
+// length: Returns the number of characters actually written in the string
+//         indicated by name (excluding the null terminator) if a value other
+//         than NULL is passed.
+// size: Returns the size of the attribute variable.
+// type: Returns the data type of the attribute variable.
+// name: Returns a null terminated string containing the name of the
+//       attribute variable. It is assumed that name has enough memory to
+//       accomodate the attribute variable name. The size of the buffer
+//       required to store the attribute variable name can be obtained by
+//       calling ShGetInfo with SH_ACTIVE_ATTRIBUTE_MAX_LENGTH.
+// mappedName: Returns a null terminated string containing the mapped name of
+//             the attribute variable, It is assumed that mappedName has enough
+//             memory (SH_MAPPED_NAME_MAX_LENGTH), or NULL if don't care
+//             about the mapped name. If the name is not mapped, then name and
+//             mappedName are the same.
+void ShGetActiveAttrib(const ShHandle handle,
+                       int index,
+                       int* length,
+                       int* size,
+                       ShDataType* type,
+                       char* name,
+                       char* mappedName);
+
+// Returns information about an active uniform variable.
+// Parameters:
+// handle: Specifies the compiler
+// index: Specifies the index of the uniform variable to be queried.
+// length: Returns the number of characters actually written in the string
+//         indicated by name (excluding the null terminator) if a value
+//         other than NULL is passed.
+// size: Returns the size of the uniform variable.
+// type: Returns the data type of the uniform variable.
+// name: Returns a null terminated string containing the name of the
+//       uniform variable. It is assumed that name has enough memory to
+//       accomodate the uniform variable name. The size of the buffer required
+//       to store the uniform variable name can be obtained by calling
+//       ShGetInfo with SH_ACTIVE_UNIFORMS_MAX_LENGTH.
+// mappedName: Returns a null terminated string containing the mapped name of
+//             the uniform variable, It is assumed that mappedName has enough
+//             memory (SH_MAPPED_NAME_MAX_LENGTH), or NULL if don't care
+//             about the mapped name. If the name is not mapped, then name and
+//             mappedName are the same.
+void ShGetActiveUniform(const ShHandle handle,
+                        int index,
+                        int* length,
+                        int* size,
+                        ShDataType* type,
+                        char* name,
+                        char* mappedName);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // _COMPILER_INTERFACE_INCLUDED_
diff --git a/src/GLES2/include/KHR/khrplatform.h b/src/GLES2/include/KHR/khrplatform.h
new file mode 100644
index 0000000..8ec0d19
--- /dev/null
+++ b/src/GLES2/include/KHR/khrplatform.h
@@ -0,0 +1,269 @@
+#ifndef __khrplatform_h_
+#define __khrplatform_h_
+
+/*
+** Copyright (c) 2008-2009 The Khronos Group Inc.
+**
+** Permission is hereby granted, free of charge, to any person obtaining a
+** copy of this software and/or associated documentation files (the
+** "Materials"), to deal in the Materials without restriction, including
+** without limitation the rights to use, copy, modify, merge, publish,
+** distribute, sublicense, and/or sell copies of the Materials, and to
+** permit persons to whom the Materials are furnished to do so, subject to
+** the following conditions:
+**
+** The above copyright notice and this permission notice shall be included
+** in all copies or substantial portions of the Materials.
+**
+** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+*/
+
+/* Khronos platform-specific types and definitions.
+ *
+ * $Revision: 9356 $ on $Date: 2009-10-21 02:52:25 -0700 (Wed, 21 Oct 2009) $
+ *
+ * Adopters may modify this file to suit their platform. Adopters are
+ * encouraged to submit platform specific modifications to the Khronos
+ * group so that they can be included in future versions of this file.
+ * Please submit changes by sending them to the public Khronos Bugzilla
+ * (http://khronos.org/bugzilla) by filing a bug against product
+ * "Khronos (general)" component "Registry".
+ *
+ * A predefined template which fills in some of the bug fields can be
+ * reached using http://tinyurl.com/khrplatform-h-bugreport, but you
+ * must create a Bugzilla login first.
+ *
+ *
+ * See the Implementer's Guidelines for information about where this file
+ * should be located on your system and for more details of its use:
+ *    http://www.khronos.org/registry/implementers_guide.pdf
+ *
+ * This file should be included as
+ *        #include <KHR/khrplatform.h>
+ * by Khronos client API header files that use its types and defines.
+ *
+ * The types in khrplatform.h should only be used to define API-specific types.
+ *
+ * Types defined in khrplatform.h:
+ *    khronos_int8_t              signed   8  bit
+ *    khronos_uint8_t             unsigned 8  bit
+ *    khronos_int16_t             signed   16 bit
+ *    khronos_uint16_t            unsigned 16 bit
+ *    khronos_int32_t             signed   32 bit
+ *    khronos_uint32_t            unsigned 32 bit
+ *    khronos_int64_t             signed   64 bit
+ *    khronos_uint64_t            unsigned 64 bit
+ *    khronos_intptr_t            signed   same number of bits as a pointer
+ *    khronos_uintptr_t           unsigned same number of bits as a pointer
+ *    khronos_ssize_t             signed   size
+ *    khronos_usize_t             unsigned size
+ *    khronos_float_t             signed   32 bit floating point
+ *    khronos_time_ns_t           unsigned 64 bit time in nanoseconds
+ *    khronos_utime_nanoseconds_t unsigned time interval or absolute time in
+ *                                         nanoseconds
+ *    khronos_stime_nanoseconds_t signed time interval in nanoseconds
+ *    khronos_boolean_enum_t      enumerated boolean type. This should
+ *      only be used as a base type when a client API's boolean type is
+ *      an enum. Client APIs which use an integer or other type for
+ *      booleans cannot use this as the base type for their boolean.
+ *
+ * Tokens defined in khrplatform.h:
+ *
+ *    KHRONOS_FALSE, KHRONOS_TRUE Enumerated boolean false/true values.
+ *
+ *    KHRONOS_SUPPORT_INT64 is 1 if 64 bit integers are supported; otherwise 0.
+ *    KHRONOS_SUPPORT_FLOAT is 1 if floats are supported; otherwise 0.
+ *
+ * Calling convention macros defined in this file:
+ *    KHRONOS_APICALL
+ *    KHRONOS_APIENTRY
+ *    KHRONOS_APIATTRIBUTES
+ *
+ * These may be used in function prototypes as:
+ *
+ *      KHRONOS_APICALL void KHRONOS_APIENTRY funcname(
+ *                                  int arg1,
+ *                                  int arg2) KHRONOS_APIATTRIBUTES;
+ */
+
+/*-------------------------------------------------------------------------
+ * Definition of KHRONOS_APICALL
+ *-------------------------------------------------------------------------
+ * This precedes the return type of the function in the function prototype.
+ */
+#if defined(_WIN32) && !defined(__SCITECH_SNAP__)
+#   define KHRONOS_APICALL __declspec(dllimport)
+#elif defined (__SYMBIAN32__)
+#   define KHRONOS_APICALL IMPORT_C
+#else
+#   define KHRONOS_APICALL
+#endif
+
+/*-------------------------------------------------------------------------
+ * Definition of KHRONOS_APIENTRY
+ *-------------------------------------------------------------------------
+ * This follows the return type of the function  and precedes the function
+ * name in the function prototype.
+ */
+#if defined(_WIN32) && !defined(_WIN32_WCE) && !defined(__SCITECH_SNAP__)
+    /* Win32 but not WinCE */
+#   define KHRONOS_APIENTRY __stdcall
+#else
+#   define KHRONOS_APIENTRY
+#endif
+
+/*-------------------------------------------------------------------------
+ * Definition of KHRONOS_APIATTRIBUTES
+ *-------------------------------------------------------------------------
+ * This follows the closing parenthesis of the function prototype arguments.
+ */
+#if defined (__ARMCC_2__)
+#define KHRONOS_APIATTRIBUTES __softfp
+#else
+#define KHRONOS_APIATTRIBUTES
+#endif
+
+/*-------------------------------------------------------------------------
+ * basic type definitions
+ *-----------------------------------------------------------------------*/
+#if (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) || defined(__GNUC__) || defined(__SCO__) || defined(__USLC__)
+
+
+/*
+ * Using <stdint.h>
+ */
+#include <stdint.h>
+typedef int32_t                 khronos_int32_t;
+typedef uint32_t                khronos_uint32_t;
+typedef int64_t                 khronos_int64_t;
+typedef uint64_t                khronos_uint64_t;
+#define KHRONOS_SUPPORT_INT64   1
+#define KHRONOS_SUPPORT_FLOAT   1
+
+#elif defined(__VMS ) || defined(__sgi)
+
+/*
+ * Using <inttypes.h>
+ */
+#include <inttypes.h>
+typedef int32_t                 khronos_int32_t;
+typedef uint32_t                khronos_uint32_t;
+typedef int64_t                 khronos_int64_t;
+typedef uint64_t                khronos_uint64_t;
+#define KHRONOS_SUPPORT_INT64   1
+#define KHRONOS_SUPPORT_FLOAT   1
+
+#elif defined(_WIN32) && !defined(__SCITECH_SNAP__)
+
+/*
+ * Win32
+ */
+typedef __int32                 khronos_int32_t;
+typedef unsigned __int32        khronos_uint32_t;
+typedef __int64                 khronos_int64_t;
+typedef unsigned __int64        khronos_uint64_t;
+#define KHRONOS_SUPPORT_INT64   1
+#define KHRONOS_SUPPORT_FLOAT   1
+
+#elif defined(__sun__) || defined(__digital__)
+
+/*
+ * Sun or Digital
+ */
+typedef int                     khronos_int32_t;
+typedef unsigned int            khronos_uint32_t;
+#if defined(__arch64__) || defined(_LP64)
+typedef long int                khronos_int64_t;
+typedef unsigned long int       khronos_uint64_t;
+#else
+typedef long long int           khronos_int64_t;
+typedef unsigned long long int  khronos_uint64_t;
+#endif /* __arch64__ */
+#define KHRONOS_SUPPORT_INT64   1
+#define KHRONOS_SUPPORT_FLOAT   1
+
+#elif 0
+
+/*
+ * Hypothetical platform with no float or int64 support
+ */
+typedef int                     khronos_int32_t;
+typedef unsigned int            khronos_uint32_t;
+#define KHRONOS_SUPPORT_INT64   0
+#define KHRONOS_SUPPORT_FLOAT   0
+
+#else
+
+/*
+ * Generic fallback
+ */
+#include <stdint.h>
+typedef int32_t                 khronos_int32_t;
+typedef uint32_t                khronos_uint32_t;
+typedef int64_t                 khronos_int64_t;
+typedef uint64_t                khronos_uint64_t;
+#define KHRONOS_SUPPORT_INT64   1
+#define KHRONOS_SUPPORT_FLOAT   1
+
+#endif
+
+
+/*
+ * Types that are (so far) the same on all platforms
+ */
+typedef signed   char          khronos_int8_t;
+typedef unsigned char          khronos_uint8_t;
+typedef signed   short int     khronos_int16_t;
+typedef unsigned short int     khronos_uint16_t;
+typedef signed   long  int     khronos_intptr_t;
+typedef unsigned long  int     khronos_uintptr_t;
+typedef signed   long  int     khronos_ssize_t;
+typedef unsigned long  int     khronos_usize_t;
+
+#if KHRONOS_SUPPORT_FLOAT
+/*
+ * Float type
+ */
+typedef          float         khronos_float_t;
+#endif
+
+#if KHRONOS_SUPPORT_INT64
+/* Time types
+ *
+ * These types can be used to represent a time interval in nanoseconds or
+ * an absolute Unadjusted System Time.  Unadjusted System Time is the number
+ * of nanoseconds since some arbitrary system event (e.g. since the last
+ * time the system booted).  The Unadjusted System Time is an unsigned
+ * 64 bit value that wraps back to 0 every 584 years.  Time intervals
+ * may be either signed or unsigned.
+ */
+typedef khronos_uint64_t       khronos_utime_nanoseconds_t;
+typedef khronos_int64_t        khronos_stime_nanoseconds_t;
+#endif
+
+/*
+ * Dummy value used to pad enum types to 32 bits.
+ */
+#ifndef KHRONOS_MAX_ENUM
+#define KHRONOS_MAX_ENUM 0x7FFFFFFF
+#endif
+
+/*
+ * Enumerated boolean type
+ *
+ * Values other than zero should be considered to be true.  Therefore
+ * comparisons should not be made against KHRONOS_TRUE.
+ */
+typedef enum {
+    KHRONOS_FALSE = 0,
+    KHRONOS_TRUE  = 1,
+    KHRONOS_BOOLEAN_ENUM_FORCE_SIZE = KHRONOS_MAX_ENUM
+} khronos_boolean_enum_t;
+
+#endif /* __khrplatform_h_ */
diff --git a/src/GLES2/libEGL/Config.cpp b/src/GLES2/libEGL/Config.cpp
new file mode 100644
index 0000000..76bbdf0
--- /dev/null
+++ b/src/GLES2/libEGL/Config.cpp
@@ -0,0 +1,369 @@
+// SwiftShader Software Renderer
+//
+// Copyright(c) 2005-2012 TransGaming Inc.
+//
+// All rights reserved. No part of this software may be copied, distributed, transmitted,
+// transcribed, stored in a retrieval system, translated into any human or computer
+// language by any means, or disclosed to third parties without the explicit written
+// agreement of TransGaming Inc. Without such an agreement, no rights or licenses, express
+// or implied, including but not limited to any patent rights, are granted to you.
+//
+
+// Config.cpp: Implements the egl::Config class, describing the format, type
+// and size for an egl::Surface. Implements EGLConfig and related functionality.
+// [EGL 1.4] section 3.4 page 15.
+
+#include "Config.h"
+
+#include "common/debug.h"
+#include "libGLESv2/Image.hpp"
+
+#include <algorithm>
+#include <vector>
+
+using namespace std;
+
+namespace egl
+{
+Config::Config(DisplayMode displayMode, EGLint minInterval, EGLint maxInterval, sw::Format renderTargetFormat, sw::Format depthStencilFormat, EGLint multiSample)
+    : mDisplayMode(displayMode), mRenderTargetFormat(renderTargetFormat), mDepthStencilFormat(depthStencilFormat), mMultiSample(multiSample)
+{
+    set(displayMode, minInterval, maxInterval, renderTargetFormat, depthStencilFormat, multiSample);
+}
+
+void Config::set(DisplayMode displayMode, EGLint minInterval, EGLint maxInterval, sw::Format renderTargetFormat, sw::Format depthStencilFormat, EGLint multiSample)
+{
+    mBindToTextureRGB = EGL_FALSE;
+    mBindToTextureRGBA = EGL_FALSE;
+
+    switch (renderTargetFormat)
+    {
+      case sw::FORMAT_A1R5G5B5:
+        mBufferSize = 16;
+        mRedSize = 5;
+        mGreenSize = 5;
+        mBlueSize = 5;
+        mAlphaSize = 1;
+        break;
+      case sw::FORMAT_A2R10G10B10:
+        mBufferSize = 32;
+        mRedSize = 10;
+        mGreenSize = 10;
+        mBlueSize = 10;
+        mAlphaSize = 2;
+        break;
+      case sw::FORMAT_A8R8G8B8:
+        mBufferSize = 32;
+        mRedSize = 8;
+        mGreenSize = 8;
+        mBlueSize = 8;
+        mAlphaSize = 8;
+        mBindToTextureRGBA = true;
+        break;
+      case sw::FORMAT_R5G6B5:
+        mBufferSize = 16;
+        mRedSize = 5;
+        mGreenSize = 6;
+        mBlueSize = 5;
+        mAlphaSize = 0;
+        break;
+      case sw::FORMAT_X8R8G8B8:
+        mBufferSize = 32;
+        mRedSize = 8;
+        mGreenSize = 8;
+        mBlueSize = 8;
+        mAlphaSize = 0;
+        mBindToTextureRGB = true;
+        break;
+      default:
+        UNREACHABLE();   // Other formats should not be valid
+    }
+
+    mLuminanceSize = 0;
+    mAlphaMaskSize = 0;
+    mColorBufferType = EGL_RGB_BUFFER;
+    mConfigCaveat = (displayMode.format == renderTargetFormat) ? EGL_NONE : EGL_SLOW_CONFIG;
+    mConfigID = 0;
+    mConformant = EGL_OPENGL_ES2_BIT;
+
+	switch (depthStencilFormat)
+	{
+	case sw::FORMAT_NULL:
+		mDepthSize = 0;
+		mStencilSize = 0;
+		break;
+//  case sw::FORMAT_D16_LOCKABLE:
+//      mDepthSize = 16;
+//      mStencilSize = 0;
+//      break;
+	case sw::FORMAT_D32:
+		mDepthSize = 32;
+		mStencilSize = 0;
+		break;
+//	case sw::FORMAT_D15S1:
+//		mDepthSize = 15;
+//		mStencilSize = 1;
+//		break;
+	case sw::FORMAT_D24S8:
+		mDepthSize = 24;
+		mStencilSize = 8;
+		break;
+	case sw::FORMAT_D24X8:
+		mDepthSize = 24;
+		mStencilSize = 0;
+		break;
+//	case sw::FORMAT_D24X4S4:
+//		mDepthSize = 24;
+//		mStencilSize = 4;
+//		break;
+	case sw::FORMAT_D16:
+		mDepthSize = 16;
+		mStencilSize = 0;
+		break;
+//  case sw::FORMAT_D32F_LOCKABLE:
+//      mDepthSize = 32;
+//      mStencilSize = 0;
+//      break;
+//  case sw::FORMAT_D24FS8:
+//      mDepthSize = 24;
+//      mStencilSize = 8;
+//      break;
+	  default:
+		UNREACHABLE();
+	}
+
+    mLevel = 0;
+    mMatchNativePixmap = EGL_NONE;
+    mMaxPBufferWidth = 4096;
+    mMaxPBufferHeight = 4096;
+    mMaxPBufferPixels = mMaxPBufferWidth * mMaxPBufferHeight;
+    mMaxSwapInterval = maxInterval;
+    mMinSwapInterval = minInterval;
+    mNativeRenderable = EGL_FALSE;
+    mNativeVisualID = 0;
+    mNativeVisualType = 0;
+    mRenderableType = EGL_OPENGL_ES2_BIT;
+    mSampleBuffers = multiSample ? 1 : 0;
+    mSamples = multiSample;
+    mSurfaceType = EGL_PBUFFER_BIT | EGL_WINDOW_BIT | EGL_SWAP_BEHAVIOR_PRESERVED_BIT;
+    mTransparentType = EGL_NONE;
+    mTransparentRedValue = 0;
+    mTransparentGreenValue = 0;
+    mTransparentBlueValue = 0;
+}
+
+EGLConfig Config::getHandle() const
+{
+    return (EGLConfig)(size_t)mConfigID;
+}
+
+SortConfig::SortConfig(const EGLint *attribList)
+    : mWantRed(false), mWantGreen(false), mWantBlue(false), mWantAlpha(false), mWantLuminance(false)
+{
+    scanForWantedComponents(attribList);
+}
+
+void SortConfig::scanForWantedComponents(const EGLint *attribList)
+{
+    // [EGL] section 3.4.1 page 24
+    // Sorting rule #3: by larger total number of color bits, not considering
+    // components that are 0 or don't-care.
+    for(const EGLint *attr = attribList; attr[0] != EGL_NONE; attr += 2)
+    {
+        if(attr[1] != 0 && attr[1] != EGL_DONT_CARE)
+        {
+            switch (attr[0])
+            {
+              case EGL_RED_SIZE:       mWantRed = true; break;
+              case EGL_GREEN_SIZE:     mWantGreen = true; break;
+              case EGL_BLUE_SIZE:      mWantBlue = true; break;
+              case EGL_ALPHA_SIZE:     mWantAlpha = true; break;
+              case EGL_LUMINANCE_SIZE: mWantLuminance = true; break;
+            }
+        }
+    }
+}
+
+EGLint SortConfig::wantedComponentsSize(const Config &config) const
+{
+    EGLint total = 0;
+
+    if(mWantRed)       total += config.mRedSize;
+    if(mWantGreen)     total += config.mGreenSize;
+    if(mWantBlue)      total += config.mBlueSize;
+    if(mWantAlpha)     total += config.mAlphaSize;
+    if(mWantLuminance) total += config.mLuminanceSize;
+
+    return total;
+}
+
+bool SortConfig::operator()(const Config *x, const Config *y) const
+{
+    return (*this)(*x, *y);
+}
+
+bool SortConfig::operator()(const Config &x, const Config &y) const
+{
+    #define SORT(attribute)                        \
+        if(x.attribute != y.attribute)             \
+        {                                          \
+            return x.attribute < y.attribute;      \
+        }
+
+    META_ASSERT(EGL_NONE < EGL_SLOW_CONFIG && EGL_SLOW_CONFIG < EGL_NON_CONFORMANT_CONFIG);
+    SORT(mConfigCaveat);
+
+    META_ASSERT(EGL_RGB_BUFFER < EGL_LUMINANCE_BUFFER);
+    SORT(mColorBufferType);
+
+    // By larger total number of color bits, only considering those that are requested to be > 0.
+    EGLint xComponentsSize = wantedComponentsSize(x);
+    EGLint yComponentsSize = wantedComponentsSize(y);
+    if(xComponentsSize != yComponentsSize)
+    {
+        return xComponentsSize > yComponentsSize;
+    }
+
+    SORT(mBufferSize);
+    SORT(mSampleBuffers);
+    SORT(mSamples);
+    SORT(mDepthSize);
+    SORT(mStencilSize);
+    SORT(mAlphaMaskSize);
+    SORT(mNativeVisualType);
+    SORT(mConfigID);
+
+    #undef SORT
+
+    return false;
+}
+
+// We'd like to use SortConfig to also eliminate duplicate configs.
+// This works as long as we never have two configs with different per-RGB-component layouts,
+// but the same total.
+// 5551 and 565 are different because R+G+B is different.
+// 5551 and 555 are different because bufferSize is different.
+const EGLint ConfigSet::mSortAttribs[] =
+{
+    EGL_RED_SIZE, 1,
+    EGL_GREEN_SIZE, 1,
+    EGL_BLUE_SIZE, 1,
+    EGL_LUMINANCE_SIZE, 1,
+    // BUT NOT ALPHA
+    EGL_NONE
+};
+
+ConfigSet::ConfigSet()
+    : mSet(SortConfig(mSortAttribs))
+{
+}
+
+void ConfigSet::add(const DisplayMode &displayMode, EGLint minSwapInterval, EGLint maxSwapInterval, sw::Format renderTargetFormat, sw::Format depthStencilFormat, EGLint multiSample)
+{
+    Config config(displayMode, minSwapInterval, maxSwapInterval, renderTargetFormat, depthStencilFormat, multiSample);
+
+    mSet.insert(config);
+}
+
+size_t ConfigSet::size() const
+{
+    return mSet.size();
+}
+
+bool ConfigSet::getConfigs(EGLConfig *configs, const EGLint *attribList, EGLint configSize, EGLint *numConfig)
+{
+    vector<const Config*> passed;
+    passed.reserve(mSet.size());
+
+    for(Iterator config = mSet.begin(); config != mSet.end(); config++)
+    {
+        bool match = true;
+        const EGLint *attribute = attribList;
+
+        while(attribute[0] != EGL_NONE)
+        {
+            switch (attribute[0])
+            {
+              case EGL_BUFFER_SIZE:               match = config->mBufferSize >= attribute[1];                      break;
+              case EGL_ALPHA_SIZE:                match = config->mAlphaSize >= attribute[1];                       break;
+              case EGL_BLUE_SIZE:                 match = config->mBlueSize >= attribute[1];                        break;
+              case EGL_GREEN_SIZE:                match = config->mGreenSize >= attribute[1];                       break;
+              case EGL_RED_SIZE:                  match = config->mRedSize >= attribute[1];                         break;
+              case EGL_DEPTH_SIZE:                match = config->mDepthSize >= attribute[1];                       break;
+              case EGL_STENCIL_SIZE:              match = config->mStencilSize >= attribute[1];                     break;
+              case EGL_CONFIG_CAVEAT:             match = config->mConfigCaveat == attribute[1];                    break;
+              case EGL_CONFIG_ID:                 match = config->mConfigID == attribute[1];                        break;
+              case EGL_LEVEL:                     match = config->mLevel >= attribute[1];                           break;
+              case EGL_NATIVE_RENDERABLE:         match = config->mNativeRenderable == attribute[1];                break;
+              case EGL_NATIVE_VISUAL_TYPE:        match = config->mNativeVisualType == attribute[1];                break;
+              case EGL_SAMPLES:                   match = config->mSamples >= attribute[1];                         break;
+              case EGL_SAMPLE_BUFFERS:            match = config->mSampleBuffers >= attribute[1];                   break;
+              case EGL_SURFACE_TYPE:              match = (config->mSurfaceType & attribute[1]) == attribute[1];    break;
+              case EGL_TRANSPARENT_TYPE:          match = config->mTransparentType == attribute[1];                 break;
+              case EGL_TRANSPARENT_BLUE_VALUE:    match = config->mTransparentBlueValue == attribute[1];            break;
+              case EGL_TRANSPARENT_GREEN_VALUE:   match = config->mTransparentGreenValue == attribute[1];           break;
+              case EGL_TRANSPARENT_RED_VALUE:     match = config->mTransparentRedValue == attribute[1];             break;
+              case EGL_BIND_TO_TEXTURE_RGB:       match = config->mBindToTextureRGB == attribute[1];                break;
+              case EGL_BIND_TO_TEXTURE_RGBA:      match = config->mBindToTextureRGBA == attribute[1];               break;
+              case EGL_MIN_SWAP_INTERVAL:         match = config->mMinSwapInterval == attribute[1];                 break;
+              case EGL_MAX_SWAP_INTERVAL:         match = config->mMaxSwapInterval == attribute[1];                 break;
+              case EGL_LUMINANCE_SIZE:            match = config->mLuminanceSize >= attribute[1];                   break;
+              case EGL_ALPHA_MASK_SIZE:           match = config->mAlphaMaskSize >= attribute[1];                   break;
+              case EGL_COLOR_BUFFER_TYPE:         match = config->mColorBufferType == attribute[1];                 break;
+              case EGL_RENDERABLE_TYPE:           match = (config->mRenderableType & attribute[1]) == attribute[1]; break;
+              case EGL_MATCH_NATIVE_PIXMAP:       match = false; UNIMPLEMENTED();                                   break;
+              case EGL_CONFORMANT:                match = (config->mConformant & attribute[1]) == attribute[1];     break;
+              case EGL_MAX_PBUFFER_WIDTH:         match = config->mMaxPBufferWidth >= attribute[1];                 break;
+              case EGL_MAX_PBUFFER_HEIGHT:        match = config->mMaxPBufferHeight >= attribute[1];                break;
+              case EGL_MAX_PBUFFER_PIXELS:        match = config->mMaxPBufferPixels >= attribute[1];                break;
+              default:
+                return false;
+            }
+
+            if(!match)
+            {
+                break;
+            }
+
+            attribute += 2;
+        }
+
+        if(match)
+        {
+            passed.push_back(&*config);
+        }
+    }
+
+    if(configs)
+    {
+        sort(passed.begin(), passed.end(), SortConfig(attribList));
+
+        EGLint index;
+        for(index = 0; index < configSize && index < static_cast<EGLint>(passed.size()); index++)
+        {
+            configs[index] = passed[index]->getHandle();
+        }
+
+        *numConfig = index;
+    }
+    else
+    {
+        *numConfig = passed.size();
+    }
+
+    return true;
+}
+
+const egl::Config *ConfigSet::get(EGLConfig configHandle)
+{
+    for(Iterator config = mSet.begin(); config != mSet.end(); config++)
+    {
+        if(config->getHandle() == configHandle)
+        {
+            return &(*config);
+        }
+    }
+
+    return NULL;
+}
+}
diff --git a/src/GLES2/libEGL/Config.h b/src/GLES2/libEGL/Config.h
new file mode 100644
index 0000000..9af441f
--- /dev/null
+++ b/src/GLES2/libEGL/Config.h
@@ -0,0 +1,126 @@
+// SwiftShader Software Renderer

+//

+// Copyright(c) 2005-2012 TransGaming Inc.

+//

+// All rights reserved. No part of this software may be copied, distributed, transmitted,

+// transcribed, stored in a retrieval system, translated into any human or computer

+// language by any means, or disclosed to third parties without the explicit written

+// agreement of TransGaming Inc. Without such an agreement, no rights or licenses, express

+// or implied, including but not limited to any patent rights, are granted to you.

+//

+

+// Config.h: Defines the egl::Config class, describing the format, type

+// and size for an egl::Surface. Implements EGLConfig and related functionality.

+// [EGL 1.4] section 3.4 page 15.

+

+#ifndef INCLUDE_CONFIG_H_

+#define INCLUDE_CONFIG_H_

+

+#include "Renderer/Surface.hpp"

+

+#define EGLAPI

+#include <EGL/egl.h>

+

+#include <set>

+

+namespace egl

+{

+class Display;

+

+struct DisplayMode

+{

+	unsigned int width;

+	unsigned int height;

+	sw::Format format;

+};

+

+class Config

+{

+  public:

+    Config(DisplayMode displayMode, EGLint minSwapInterval, EGLint maxSwapInterval, sw::Format renderTargetFormat, sw::Format depthStencilFormat, EGLint multiSample);

+

+    void set(DisplayMode displayMode, EGLint minSwapInterval, EGLint maxSwapInterval, sw::Format renderTargetFormat, sw::Format depthStencilFormat, EGLint multiSample);

+    EGLConfig getHandle() const;

+

+    const DisplayMode mDisplayMode;

+    const sw::Format mRenderTargetFormat;

+    const sw::Format mDepthStencilFormat;

+    const EGLint mMultiSample;

+

+    EGLint mBufferSize;              // Depth of the color buffer

+    EGLint mRedSize;                 // Bits of Red in the color buffer

+    EGLint mGreenSize;               // Bits of Green in the color buffer

+    EGLint mBlueSize;                // Bits of Blue in the color buffer

+    EGLint mLuminanceSize;           // Bits of Luminance in the color buffer

+    EGLint mAlphaSize;               // Bits of Alpha in the color buffer

+    EGLint mAlphaMaskSize;           // Bits of Alpha Mask in the mask buffer

+    EGLBoolean mBindToTextureRGB;    // True if bindable to RGB textures.

+    EGLBoolean mBindToTextureRGBA;   // True if bindable to RGBA textures.

+    EGLenum mColorBufferType;        // Color buffer type

+    EGLenum mConfigCaveat;           // Any caveats for the configuration

+    EGLint mConfigID;                // Unique EGLConfig identifier

+    EGLint mConformant;              // Whether contexts created with this config are conformant

+    EGLint mDepthSize;               // Bits of Z in the depth buffer

+    EGLint mLevel;                   // Frame buffer level

+    EGLBoolean mMatchNativePixmap;   // Match the native pixmap format

+    EGLint mMaxPBufferWidth;         // Maximum width of pbuffer

+    EGLint mMaxPBufferHeight;        // Maximum height of pbuffer

+    EGLint mMaxPBufferPixels;        // Maximum size of pbuffer

+    EGLint mMaxSwapInterval;         // Maximum swap interval

+    EGLint mMinSwapInterval;         // Minimum swap interval

+    EGLBoolean mNativeRenderable;    // EGL_TRUE if native rendering APIs can render to surface

+    EGLint mNativeVisualID;          // Handle of corresponding native visual

+    EGLint mNativeVisualType;        // Native visual type of the associated visual

+    EGLint mRenderableType;          // Which client rendering APIs are supported.

+    EGLint mSampleBuffers;           // Number of multisample buffers

+    EGLint mSamples;                 // Number of samples per pixel

+    EGLint mStencilSize;             // Bits of Stencil in the stencil buffer

+    EGLint mSurfaceType;             // Which types of EGL surfaces are supported.

+    EGLenum mTransparentType;        // Type of transparency supported

+    EGLint mTransparentRedValue;     // Transparent red value

+    EGLint mTransparentGreenValue;   // Transparent green value

+    EGLint mTransparentBlueValue;    // Transparent blue value

+};

+

+// Function object used by STL sorting routines for ordering Configs according to [EGL] section 3.4.1 page 24.

+class SortConfig

+{

+  public:

+    explicit SortConfig(const EGLint *attribList);

+

+    bool operator()(const Config *x, const Config *y) const;

+    bool operator()(const Config &x, const Config &y) const;

+

+  private:

+    void scanForWantedComponents(const EGLint *attribList);

+    EGLint wantedComponentsSize(const Config &config) const;

+

+    bool mWantRed;

+    bool mWantGreen;

+    bool mWantBlue;

+    bool mWantAlpha;

+    bool mWantLuminance;

+};

+

+class ConfigSet

+{

+    friend class Display;

+

+  public:

+    ConfigSet();

+

+    void add(const DisplayMode &displayMode, EGLint minSwapInterval, EGLint maxSwapInterval, sw::Format renderTargetFormat, sw::Format depthStencilFormat, EGLint multiSample);

+    size_t size() const;

+    bool getConfigs(EGLConfig *configs, const EGLint *attribList, EGLint configSize, EGLint *numConfig);

+    const egl::Config *get(EGLConfig configHandle);

+

+  private:

+    typedef std::set<Config, SortConfig> Set;

+    typedef Set::iterator Iterator;

+    Set mSet;

+

+    static const EGLint mSortAttribs[];

+};

+}

+

+#endif   // INCLUDE_CONFIG_H_

diff --git a/src/GLES2/libEGL/Display.cpp b/src/GLES2/libEGL/Display.cpp
new file mode 100644
index 0000000..623ba0c
--- /dev/null
+++ b/src/GLES2/libEGL/Display.cpp
@@ -0,0 +1,566 @@
+// SwiftShader Software Renderer

+//

+// Copyright(c) 2005-2012 TransGaming Inc.

+//

+// All rights reserved. No part of this software may be copied, distributed, transmitted,

+// transcribed, stored in a retrieval system, translated into any human or computer

+// language by any means, or disclosed to third parties without the explicit written

+// agreement of TransGaming Inc. Without such an agreement, no rights or licenses, express

+// or implied, including but not limited to any patent rights, are granted to you.

+//

+

+// Display.cpp: Implements the egl::Display class, representing the abstract

+// display on which graphics are drawn. Implements EGLDisplay.

+// [EGL 1.4] section 2.1.2 page 3.

+

+#include "Display.h"

+

+#include "main.h"

+#include "libGLESv2/mathutil.h"

+#include "libGLESv2/Device.hpp"

+#include "common/debug.h"

+

+#include <algorithm>

+#include <vector>

+#include <map>

+

+namespace egl

+{

+typedef std::map<EGLNativeDisplayType, Display*> DisplayMap; 

+DisplayMap displays;

+

+egl::Display *Display::getDisplay(EGLNativeDisplayType displayId)

+{

+    if(displays.find(displayId) != displays.end())

+    {

+        return displays[displayId];

+    }

+

+    egl::Display *display = NULL;

+

+    if(displayId == EGL_DEFAULT_DISPLAY)

+    {

+        display = new egl::Display(displayId);

+    }

+    else

+    {

+        // FIXME: Check if displayId is a valid display device context

+

+        display = new egl::Display(displayId);

+    }

+

+    displays[displayId] = display;

+    return display;

+}

+

+Display::Display(EGLNativeDisplayType displayId) : displayId(displayId)

+{

+    mDevice = NULL;

+

+    mMinSwapInterval = 1;

+    mMaxSwapInterval = 1;

+}

+

+Display::~Display()

+{

+    terminate();

+

+	displays.erase(displayId);

+}

+

+static void cpuid(int registers[4], int info)

+{

+	#if defined(_WIN32)

+        __cpuid(registers, info);

+    #else

+        __asm volatile("cpuid": "=a" (registers[0]), "=b" (registers[1]), "=c" (registers[2]), "=d" (registers[3]): "a" (info));

+    #endif

+}

+

+static bool detectSSE()

+{

+	#if defined(__APPLE__)

+		int SSE = false;

+		size_t length = sizeof(SSE);

+		sysctlbyname("hw.optional.sse", &SSE, &length, 0, 0);

+		return SSE;

+	#else

+		int registers[4];

+		cpuid(registers, 1);

+		return (registers[3] & 0x02000000) != 0;

+	#endif

+}

+

+bool Display::initialize()

+{

+    if(isInitialized())

+    {

+        return true;

+    }

+

+	if(!detectSSE())

+	{

+		 return false;

+	}

+		

+    mMinSwapInterval = 0;

+    mMaxSwapInterval = 4;

+

+    const sw::Format renderTargetFormats[] =

+    {

+        sw::FORMAT_A1R5G5B5,

+    //  sw::FORMAT_A2R10G10B10,   // The color_ramp conformance test uses ReadPixels with UNSIGNED_BYTE causing it to think that rendering skipped a colour value.

+        sw::FORMAT_A8R8G8B8,

+        sw::FORMAT_R5G6B5,

+    //  sw::FORMAT_X1R5G5B5,      // Has no compatible OpenGL ES renderbuffer format

+        sw::FORMAT_X8R8G8B8

+    };

+

+    const sw::Format depthStencilFormats[] =

+    {

+        sw::FORMAT_NULL,

+    //  sw::FORMAT_D16_LOCKABLE,

+        sw::FORMAT_D32,

+    //  sw::FORMAT_D15S1,

+        sw::FORMAT_D24S8,

+        sw::FORMAT_D24X8,

+    //  sw::FORMAT_D24X4S4,

+        sw::FORMAT_D16,

+    //  sw::FORMAT_D32F_LOCKABLE,

+    //  sw::FORMAT_D24FS8

+    };

+

+	DisplayMode currentDisplayMode = getDisplayMode();

+    ConfigSet configSet;

+

+    for(int formatIndex = 0; formatIndex < sizeof(renderTargetFormats) / sizeof(sw::Format); formatIndex++)

+    {

+        sw::Format renderTargetFormat = renderTargetFormats[formatIndex];

+

+        for(int depthStencilIndex = 0; depthStencilIndex < sizeof(depthStencilFormats) / sizeof(sw::Format); depthStencilIndex++)

+        {

+            sw::Format depthStencilFormat = depthStencilFormats[depthStencilIndex];

+             

+            // FIXME: enumerate multi-sampling

+

+            configSet.add(currentDisplayMode, mMinSwapInterval, mMaxSwapInterval, renderTargetFormat, depthStencilFormat, 0);

+        }

+    }

+

+    // Give the sorted configs a unique ID and store them internally

+    EGLint index = 1;

+    for(ConfigSet::Iterator config = configSet.mSet.begin(); config != configSet.mSet.end(); config++)

+    {

+        Config configuration = *config;

+        configuration.mConfigID = index;

+        index++;

+

+        mConfigSet.mSet.insert(configuration);

+    }

+

+    if(!isInitialized())

+    {

+        terminate();

+

+        return false;

+    }

+

+    initExtensionString();

+

+    return true;

+}

+

+void Display::terminate()

+{

+    while(!mSurfaceSet.empty())

+    {

+        destroySurface(*mSurfaceSet.begin());

+    }

+

+    while(!mContextSet.empty())

+    {

+        destroyContext(*mContextSet.begin());

+    }

+

+    delete mDevice;

+    mDevice = NULL;

+}

+

+bool Display::getConfigs(EGLConfig *configs, const EGLint *attribList, EGLint configSize, EGLint *numConfig)

+{

+    return mConfigSet.getConfigs(configs, attribList, configSize, numConfig);

+}

+

+bool Display::getConfigAttrib(EGLConfig config, EGLint attribute, EGLint *value)

+{

+    const egl::Config *configuration = mConfigSet.get(config);

+

+    switch (attribute)

+    {

+      case EGL_BUFFER_SIZE:               *value = configuration->mBufferSize;             break;

+      case EGL_ALPHA_SIZE:                *value = configuration->mAlphaSize;              break;

+      case EGL_BLUE_SIZE:                 *value = configuration->mBlueSize;               break;

+      case EGL_GREEN_SIZE:                *value = configuration->mGreenSize;              break;

+      case EGL_RED_SIZE:                  *value = configuration->mRedSize;                break;

+      case EGL_DEPTH_SIZE:                *value = configuration->mDepthSize;              break;

+      case EGL_STENCIL_SIZE:              *value = configuration->mStencilSize;            break;

+      case EGL_CONFIG_CAVEAT:             *value = configuration->mConfigCaveat;           break;

+      case EGL_CONFIG_ID:                 *value = configuration->mConfigID;               break;

+      case EGL_LEVEL:                     *value = configuration->mLevel;                  break;

+      case EGL_NATIVE_RENDERABLE:         *value = configuration->mNativeRenderable;       break;

+      case EGL_NATIVE_VISUAL_TYPE:        *value = configuration->mNativeVisualType;       break;

+      case EGL_SAMPLES:                   *value = configuration->mSamples;                break;

+      case EGL_SAMPLE_BUFFERS:            *value = configuration->mSampleBuffers;          break;

+      case EGL_SURFACE_TYPE:              *value = configuration->mSurfaceType;            break;

+      case EGL_TRANSPARENT_TYPE:          *value = configuration->mTransparentType;        break;

+      case EGL_TRANSPARENT_BLUE_VALUE:    *value = configuration->mTransparentBlueValue;   break;

+      case EGL_TRANSPARENT_GREEN_VALUE:   *value = configuration->mTransparentGreenValue;  break;

+      case EGL_TRANSPARENT_RED_VALUE:     *value = configuration->mTransparentRedValue;    break;

+      case EGL_BIND_TO_TEXTURE_RGB:       *value = configuration->mBindToTextureRGB;       break;

+      case EGL_BIND_TO_TEXTURE_RGBA:      *value = configuration->mBindToTextureRGBA;      break;

+      case EGL_MIN_SWAP_INTERVAL:         *value = configuration->mMinSwapInterval;        break;

+      case EGL_MAX_SWAP_INTERVAL:         *value = configuration->mMaxSwapInterval;        break;

+      case EGL_LUMINANCE_SIZE:            *value = configuration->mLuminanceSize;          break;

+      case EGL_ALPHA_MASK_SIZE:           *value = configuration->mAlphaMaskSize;          break;

+      case EGL_COLOR_BUFFER_TYPE:         *value = configuration->mColorBufferType;        break;

+      case EGL_RENDERABLE_TYPE:           *value = configuration->mRenderableType;         break;

+      case EGL_MATCH_NATIVE_PIXMAP:       *value = false; UNIMPLEMENTED();                 break;

+      case EGL_CONFORMANT:                *value = configuration->mConformant;             break;

+      case EGL_MAX_PBUFFER_WIDTH:         *value = configuration->mMaxPBufferWidth;        break;

+      case EGL_MAX_PBUFFER_HEIGHT:        *value = configuration->mMaxPBufferHeight;       break;

+      case EGL_MAX_PBUFFER_PIXELS:        *value = configuration->mMaxPBufferPixels;       break;

+      default:

+        return false;

+    }

+

+    return true;

+}

+

+bool Display::createDevice()

+{

+    mDevice = gl::createDevice();

+

+    if(!mDevice)

+    {

+        return error(EGL_BAD_ALLOC, false);

+    }

+

+    // Permanent non-default states

+	mDevice->setPointSpriteEnable(true);

+

+    return true;

+}

+

+EGLSurface Display::createWindowSurface(EGLNativeWindowType window, EGLConfig config, const EGLint *attribList)

+{

+    const Config *configuration = mConfigSet.get(config);

+

+    if(attribList)

+    {

+        while(*attribList != EGL_NONE)

+        {

+            switch (attribList[0])

+            {

+              case EGL_RENDER_BUFFER:

+                switch (attribList[1])

+                {

+                  case EGL_BACK_BUFFER:

+                    break;

+                  case EGL_SINGLE_BUFFER:

+                    return error(EGL_BAD_MATCH, EGL_NO_SURFACE);   // Rendering directly to front buffer not supported

+                  default:

+                    return error(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE);

+                }

+                break;

+              case EGL_VG_COLORSPACE:

+                return error(EGL_BAD_MATCH, EGL_NO_SURFACE);

+              case EGL_VG_ALPHA_FORMAT:

+                return error(EGL_BAD_MATCH, EGL_NO_SURFACE);

+              default:

+                return error(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE);

+            }

+

+            attribList += 2;

+        }

+    }

+

+    if(hasExistingWindowSurface(window))

+    {

+        return error(EGL_BAD_ALLOC, EGL_NO_SURFACE);

+    }

+

+    Surface *surface = new Surface(this, configuration, window);

+

+    if(!surface->initialize())

+    {

+        delete surface;

+        return EGL_NO_SURFACE;

+    }

+

+    mSurfaceSet.insert(surface);

+

+    return success(surface);

+}

+

+EGLSurface Display::createOffscreenSurface(EGLConfig config, const EGLint *attribList)

+{

+    EGLint width = 0, height = 0;

+    EGLenum textureFormat = EGL_NO_TEXTURE;

+    EGLenum textureTarget = EGL_NO_TEXTURE;

+    const Config *configuration = mConfigSet.get(config);

+

+    if(attribList)

+    {

+        while(*attribList != EGL_NONE)

+        {

+            switch (attribList[0])

+            {

+              case EGL_WIDTH:

+                width = attribList[1];

+                break;

+              case EGL_HEIGHT:

+                height = attribList[1];

+                break;

+              case EGL_LARGEST_PBUFFER:

+                if(attribList[1] != EGL_FALSE)

+                  UNIMPLEMENTED(); // FIXME

+                break;

+              case EGL_TEXTURE_FORMAT:

+                switch (attribList[1])

+                {

+                  case EGL_NO_TEXTURE:

+                  case EGL_TEXTURE_RGB:

+                  case EGL_TEXTURE_RGBA:

+                    textureFormat = attribList[1];

+                    break;

+                  default:

+                    return error(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE);

+                }

+                break;

+              case EGL_TEXTURE_TARGET:

+                switch (attribList[1])

+                {

+                  case EGL_NO_TEXTURE:

+                  case EGL_TEXTURE_2D:

+                    textureTarget = attribList[1];

+                    break;

+                  default:

+                    return error(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE);

+                }

+                break;

+              case EGL_MIPMAP_TEXTURE:

+                if(attribList[1] != EGL_FALSE)

+                  return error(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE);

+                break;

+              case EGL_VG_COLORSPACE:

+                return error(EGL_BAD_MATCH, EGL_NO_SURFACE);

+              case EGL_VG_ALPHA_FORMAT:

+                return error(EGL_BAD_MATCH, EGL_NO_SURFACE);

+              default:

+                return error(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE);

+            }

+

+            attribList += 2;

+        }

+    }

+

+    if(width < 0 || height < 0)

+    {

+        return error(EGL_BAD_PARAMETER, EGL_NO_SURFACE);

+    }

+

+    if(width == 0 || height == 0)

+    {

+        return error(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE);

+    }

+

+    if((textureFormat != EGL_NO_TEXTURE && textureTarget == EGL_NO_TEXTURE) ||

+       (textureFormat == EGL_NO_TEXTURE && textureTarget != EGL_NO_TEXTURE))

+    {

+        return error(EGL_BAD_MATCH, EGL_NO_SURFACE);

+    }

+

+    if(!(configuration->mSurfaceType & EGL_PBUFFER_BIT))

+    {

+        return error(EGL_BAD_MATCH, EGL_NO_SURFACE);

+    }

+

+    if((textureFormat == EGL_TEXTURE_RGB && configuration->mBindToTextureRGB != EGL_TRUE) ||

+       (textureFormat == EGL_TEXTURE_RGBA && configuration->mBindToTextureRGBA != EGL_TRUE))

+    {

+        return error(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE);

+    }

+

+    Surface *surface = new Surface(this, configuration, width, height, textureFormat, textureTarget);

+

+    if(!surface->initialize())

+    {

+        delete surface;

+        return EGL_NO_SURFACE;

+    }

+

+    mSurfaceSet.insert(surface);

+

+    return success(surface);

+}

+

+EGLContext Display::createContext(EGLConfig configHandle, const gl::Context *shareContext)

+{

+    if(!mDevice)

+    {

+        if(!createDevice())

+        {

+            return NULL;

+        }

+    }

+

+    const egl::Config *config = mConfigSet.get(configHandle);

+

+    gl::Context *context = gl::createContext(config, shareContext);

+    mContextSet.insert(context);

+

+    return context;

+}

+

+void Display::destroySurface(egl::Surface *surface)

+{

+    delete surface;

+    mSurfaceSet.erase(surface);

+}

+

+void Display::destroyContext(gl::Context *context)

+{

+    gl::destroyContext(context);

+    mContextSet.erase(context);

+}

+

+bool Display::isInitialized() const

+{

+    return mConfigSet.size() > 0;

+}

+

+bool Display::isValidConfig(EGLConfig config)

+{

+    return mConfigSet.get(config) != NULL;

+}

+

+bool Display::isValidContext(gl::Context *context)

+{

+    return mContextSet.find(context) != mContextSet.end();

+}

+

+bool Display::isValidSurface(egl::Surface *surface)

+{

+    return mSurfaceSet.find(surface) != mSurfaceSet.end();

+}

+

+bool Display::isValidWindow(EGLNativeWindowType window)

+{

+	#if defined(_WIN32)

+		return IsWindow(window) == TRUE;

+	#else

+		XWindowAttributes windowAttributes;

+		Status status = XGetWindowAttributes(displayId, window, &windowAttributes);

+			

+		return status == True;

+	#endif

+}

+

+bool Display::hasExistingWindowSurface(EGLNativeWindowType window)

+{

+    for(SurfaceSet::iterator surface = mSurfaceSet.begin(); surface != mSurfaceSet.end(); surface++)

+    {

+        if((*surface)->getWindowHandle() == window)

+        {

+            return true;

+        }

+    }

+

+    return false;

+}

+

+EGLint Display::getMinSwapInterval()

+{

+    return mMinSwapInterval;

+}

+

+EGLint Display::getMaxSwapInterval()

+{

+    return mMaxSwapInterval;

+}

+

+gl::Device *Display::getDevice()

+{

+    if(!mDevice)

+    {

+        if(!createDevice())

+        {

+            return NULL;

+        }

+    }

+

+    return mDevice;

+}

+

+void Display::initExtensionString()

+{

+    mExtensionString += "EGL_ANGLE_query_surface_pointer ";

+

+    std::string::size_type end = mExtensionString.find_last_not_of(' ');

+    if(end != std::string::npos)

+    {

+        mExtensionString.resize(end + 1);

+    }

+}

+

+const char *Display::getExtensionString() const

+{

+    return mExtensionString.c_str();

+}

+

+EGLNativeDisplayType Display::getNativeDisplay() const

+{

+	return displayId;

+}

+

+DisplayMode Display::getDisplayMode() const

+{

+	DisplayMode displayMode = {0};

+

+	#if defined(_WIN32)

+		HDC deviceContext = GetDC(0);

+	

+		displayMode.width = ::GetDeviceCaps(deviceContext, HORZRES);

+		displayMode.height = ::GetDeviceCaps(deviceContext, VERTRES);

+		unsigned int bpp = ::GetDeviceCaps(deviceContext, BITSPIXEL);

+	

+		switch(bpp)

+		{

+		case 32: displayMode.format = sw::FORMAT_X8R8G8B8; break;

+		case 24: displayMode.format = sw::FORMAT_R8G8B8;   break;

+		case 16: displayMode.format = sw::FORMAT_R5G6B5;   break;

+		default:

+			ASSERT(false);   // Unexpected display mode color depth

+		}

+	

+		ReleaseDC(0, deviceContext);

+	#else

+		Screen *screen = XDefaultScreenOfDisplay(displayId);

+		displayMode.width = XWidthOfScreen(screen);

+		displayMode.height = XHeightOfScreen(screen);

+		unsigned int bpp = XPlanesOfScreen(screen);

+

+		switch(bpp)

+		{

+		case 32: displayMode.format = sw::FORMAT_X8R8G8B8; break;

+		case 24: displayMode.format = sw::FORMAT_R8G8B8;   break;

+		case 16: displayMode.format = sw::FORMAT_R5G6B5;   break;

+		default:

+			ASSERT(false);   // Unexpected display mode color depth

+		}

+	#endif

+

+	return displayMode;

+}

+

+}

diff --git a/src/GLES2/libEGL/Display.h b/src/GLES2/libEGL/Display.h
new file mode 100644
index 0000000..094fe7f
--- /dev/null
+++ b/src/GLES2/libEGL/Display.h
@@ -0,0 +1,89 @@
+// SwiftShader Software Renderer

+//

+// Copyright(c) 2005-2012 TransGaming Inc.

+//

+// All rights reserved. No part of this software may be copied, distributed, transmitted,

+// transcribed, stored in a retrieval system, translated into any human or computer

+// language by any means, or disclosed to third parties without the explicit written

+// agreement of TransGaming Inc. Without such an agreement, no rights or licenses, express

+// or implied, including but not limited to any patent rights, are granted to you.

+//

+

+// Display.h: Defines the egl::Display class, representing the abstract

+// display on which graphics are drawn. Implements EGLDisplay.

+// [EGL 1.4] section 2.1.2 page 3.

+

+#ifndef INCLUDE_DISPLAY_H_

+#define INCLUDE_DISPLAY_H_

+

+#include "Config.h"

+#include "Surface.h"

+#include "libGLESv2/Context.h"

+#include "libGLESv2/Device.hpp"

+

+#include <set>

+

+namespace egl

+{

+	class Display

+	{

+	public:

+		~Display();

+

+		static egl::Display *getDisplay(EGLNativeDisplayType displayId);

+

+		bool initialize();

+		void terminate();

+

+		bool getConfigs(EGLConfig *configs, const EGLint *attribList, EGLint configSize, EGLint *numConfig);

+		bool getConfigAttrib(EGLConfig config, EGLint attribute, EGLint *value);

+

+		EGLSurface createWindowSurface(EGLNativeWindowType window, EGLConfig config, const EGLint *attribList);

+		EGLSurface createOffscreenSurface(EGLConfig config, const EGLint *attribList);

+		EGLContext createContext(EGLConfig configHandle, const gl::Context *shareContext);

+

+		void destroySurface(egl::Surface *surface);

+		void destroyContext(gl::Context *context);

+

+		bool isInitialized() const;

+		bool isValidConfig(EGLConfig config);

+		bool isValidContext(gl::Context *context);

+		bool isValidSurface(egl::Surface *surface);

+		bool isValidWindow(EGLNativeWindowType window);

+		bool hasExistingWindowSurface(EGLNativeWindowType window);

+

+		EGLint getMinSwapInterval();

+		EGLint getMaxSwapInterval();

+

+		virtual gl::Device *getDevice();

+

+		EGLNativeDisplayType getNativeDisplay() const;

+		const char *getExtensionString() const;

+

+	private:

+		Display(EGLNativeDisplayType displayId);

+

+		DisplayMode getDisplayMode() const;

+

+		const EGLNativeDisplayType displayId;

+		gl::Device *mDevice;

+

+		EGLint mMaxSwapInterval;

+		EGLint mMinSwapInterval;

+    

+		typedef std::set<Surface*> SurfaceSet;

+		SurfaceSet mSurfaceSet;

+

+		ConfigSet mConfigSet;

+

+		typedef std::set<gl::Context*> ContextSet;

+		ContextSet mContextSet;

+

+		bool createDevice();

+

+		void initExtensionString();

+		std::string mExtensionString;

+	};

+}

+

+#endif   // INCLUDE_DISPLAY_H_

diff --git a/src/GLES2/libEGL/Surface.cpp b/src/GLES2/libEGL/Surface.cpp
new file mode 100644
index 0000000..dc2abb8
--- /dev/null
+++ b/src/GLES2/libEGL/Surface.cpp
@@ -0,0 +1,419 @@
+// SwiftShader Software Renderer

+//

+// Copyright(c) 2005-2012 TransGaming Inc.

+//

+// All rights reserved. No part of this software may be copied, distributed, transmitted,

+// transcribed, stored in a retrieval system, translated into any human or computer

+// language by any means, or disclosed to third parties without the explicit written

+// agreement of TransGaming Inc. Without such an agreement, no rights or licenses, express

+// or implied, including but not limited to any patent rights, are granted to you.

+//

+

+// Surface.cpp: Implements the egl::Surface class, representing a drawing surface

+// such as the client area of a window, including any back buffers.

+// Implements EGLSurface and related functionality. [EGL 1.4] section 2.2 page 3.

+

+#include "Surface.h"

+

+#include "main.h"

+#include "Display.h"

+#include "libGLESv2/Texture.h"

+#include "libGLESv2/Device.hpp"

+#include "common/debug.h"

+#include "Main/FrameBuffer.hpp"

+

+#if defined(_WIN32)

+#include <dwmapi.h>

+#include <tchar.h>

+#endif

+

+namespace egl

+{

+

+Surface::Surface(Display *display, const Config *config, EGLNativeWindowType window) 

+    : mDisplay(display), mConfig(config), mWindow(window)

+{

+    frameBuffer = 0;

+	backBuffer = 0;

+

+    mDepthStencil = NULL;

+    mTexture = NULL;

+    mTextureFormat = EGL_NO_TEXTURE;

+    mTextureTarget = EGL_NO_TEXTURE;

+

+    mPixelAspectRatio = (EGLint)(1.0 * EGL_DISPLAY_SCALING);   // FIXME: Determine actual pixel aspect ratio

+    mRenderBuffer = EGL_BACK_BUFFER;

+    mSwapBehavior = EGL_BUFFER_PRESERVED;

+    mSwapInterval = -1;

+    setSwapInterval(1);

+

+	#if defined(_WIN32)

+		subclassWindow();

+    #endif

+}

+

+Surface::Surface(Display *display, const Config *config, EGLint width, EGLint height, EGLenum textureFormat, EGLenum textureType)

+    : mDisplay(display), mWindow(NULL), mConfig(config), mWidth(width), mHeight(height)

+{

+	frameBuffer = 0;

+	backBuffer = 0;

+

+    mDepthStencil = NULL;

+    mWindowSubclassed = false;

+    mTexture = NULL;

+    mTextureFormat = textureFormat;

+    mTextureTarget = textureType;

+

+    mPixelAspectRatio = (EGLint)(1.0 * EGL_DISPLAY_SCALING);   // FIXME: Determine actual pixel aspect ratio

+    mRenderBuffer = EGL_BACK_BUFFER;

+    mSwapBehavior = EGL_BUFFER_PRESERVED;

+    mSwapInterval = -1;

+    setSwapInterval(1);

+}

+

+Surface::~Surface()

+{

+	#if defined(_WIN32)

+		unsubclassWindow();

+    #endif

+    

+    release();

+}

+

+bool Surface::initialize()

+{

+    ASSERT(!frameBuffer && !backBuffer && !mDepthStencil);

+

+    if(!reset())

+	{

+		return false;

+	}

+

+	#if defined(_WIN32)

+		// Modify present parameters for this window, if we are composited,

+		// to minimize the amount of queuing done by DWM between our calls to

+		// present and the actual screen.

+		if(mWindow && LOBYTE(GetVersion()) >= 6)

+		{

+			BOOL isComposited;

+			HRESULT result = DwmIsCompositionEnabled(&isComposited);

+

+			if(SUCCEEDED(result) && isComposited)

+			{

+				DWM_PRESENT_PARAMETERS presentParams = {0};

+				presentParams.cbSize = sizeof(DWM_PRESENT_PARAMETERS);

+				presentParams.cBuffer = 2;

+

+				result = DwmSetPresentParameters(mWindow, &presentParams);

+				

+				if(FAILED(result))

+				{

+					ERR("Unable to set present parameters: %081X", result);

+				}

+			}

+		}

+    #endif

+

+    return true;

+}

+

+void Surface::release()

+{	

+    if(mDepthStencil)

+    {

+        mDepthStencil->release();

+        mDepthStencil = NULL;

+    }

+

+    if(mTexture)

+    {

+        mTexture->releaseTexImage();

+        mTexture = NULL;

+    }

+

+	if(backBuffer)

+	{

+		backBuffer->release();

+		backBuffer = 0;

+	}

+

+	delete frameBuffer;

+	frameBuffer = 0;

+}

+

+bool Surface::reset()

+{

+    if(!mWindow)

+    {

+        return reset(mWidth, mHeight);

+    }

+

+	// FIXME: Wrap into an abstract Window class

+	#if defined(_WIN32)

+		RECT windowRect;

+		GetClientRect(mWindow, &windowRect);

+

+		return reset(windowRect.right - windowRect.left, windowRect.bottom - windowRect.top);

+	#else

+		XWindowAttributes windowAttributes;

+		XGetWindowAttributes(mDisplay->getNativeDisplay(), mWindow, &windowAttributes);

+		

+		return reset(windowAttributes.width, windowAttributes.height);

+	#endif

+}

+

+bool Surface::reset(int backBufferWidth, int backBufferHeight)

+{

+    gl::Device *device = mDisplay->getDevice();

+

+    if(device == NULL)

+    {

+        return false;

+    }

+

+    release();

+

+    if(mWindow)

+    {

+		frameBuffer = gl::createFrameBuffer(mWindow, backBufferWidth, backBufferHeight);

+

+		if(!frameBuffer)

+		{

+			ERR("Could not create frame buffer");

+			release();

+			return error(EGL_BAD_ALLOC, false);

+		}

+

+		#if defined(_WIN32)

+			InvalidateRect(mWindow, NULL, FALSE);

+		#endif

+    }

+

+	backBuffer = gl::createBackBuffer(backBufferWidth, backBufferHeight, mConfig);

+

+	if(backBuffer)

+	{

+		backBuffer->addRef();

+	}

+

+    if(!backBuffer)

+    {

+        ERR("Could not create back buffer");

+        release();

+        return error(EGL_BAD_ALLOC, false);

+    }

+

+    if(mConfig->mDepthStencilFormat != sw::FORMAT_NULL)

+    {

+        mDepthStencil = device->createDepthStencilSurface(backBufferWidth, backBufferHeight, mConfig->mDepthStencilFormat, 1, false);

+

+		if(!mDepthStencil)

+		{

+			ERR("Could not create depth/stencil buffer for surface");

+			release();

+			return error(EGL_BAD_ALLOC, false);

+		}

+    }

+

+    mWidth = backBufferWidth;

+    mHeight = backBufferHeight;

+

+    return true;

+}

+

+EGLNativeWindowType Surface::getWindowHandle()

+{

+    return mWindow;

+}

+

+void Surface::swap()

+{

+    #if PERF_PROFILE

+		profiler.nextFrame();

+	#endif

+

+	if(backBuffer)

+    {

+		bool HDR = backBuffer->getInternalFormat() == sw::FORMAT_A16B16G16R16;

+		void *source = backBuffer->lockInternal(0, 0, 0, sw::LOCK_READONLY, sw::PUBLIC);

+		frameBuffer->flip(source, HDR);

+		backBuffer->unlockInternal();

+	

+		#if defined(_WIN32)

+			checkForResize();

+		#endif

+	}

+}

+

+EGLint Surface::getWidth() const

+{

+    return mWidth;

+}

+

+EGLint Surface::getHeight() const

+{

+    return mHeight;

+}

+

+gl::Image *Surface::getRenderTarget()

+{

+    if(backBuffer)

+    {

+        backBuffer->addRef();

+    }

+

+    return backBuffer;

+}

+

+gl::Image *Surface::getDepthStencil()

+{

+    if(mDepthStencil)

+    {

+        mDepthStencil->addRef();

+    }

+

+    return mDepthStencil;

+}

+

+void Surface::setSwapInterval(EGLint interval)

+{

+    if(mSwapInterval == interval)

+    {

+        return;

+    }

+    

+    mSwapInterval = interval;

+    mSwapInterval = std::max(mSwapInterval, mDisplay->getMinSwapInterval());

+    mSwapInterval = std::min(mSwapInterval, mDisplay->getMaxSwapInterval());

+}

+

+EGLenum Surface::getTextureFormat() const

+{

+    return mTextureFormat;

+}

+

+EGLenum Surface::getTextureTarget() const

+{

+    return mTextureTarget;

+}

+

+void Surface::setBoundTexture(gl::Texture2D *texture)

+{

+    mTexture = texture;

+}

+

+gl::Texture2D *Surface::getBoundTexture() const

+{

+    return mTexture;

+}

+

+sw::Format Surface::getInternalFormat() const

+{

+    return mConfig->mRenderTargetFormat;

+}

+

+#if defined(WIN32)

+#define kSurfaceProperty _TEXT("Egl::SurfaceOwner")

+#define kParentWndProc _TEXT("Egl::SurfaceParentWndProc")

+

+static LRESULT CALLBACK SurfaceWindowProc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)

+{

+	if(message == WM_SIZE)

+	{

+		Surface *surface = reinterpret_cast<Surface*>(GetProp(hwnd, kSurfaceProperty));

+		

+		if(surface)

+		{

+			surface->checkForResize();

+		}

+	}

+

+	WNDPROC prevWndFunc = reinterpret_cast<WNDPROC>(GetProp(hwnd, kParentWndProc));

+

+	return CallWindowProc(prevWndFunc, hwnd, message, wparam, lparam);

+}

+

+void Surface::subclassWindow()

+{

+	if(!mWindow)

+	{

+		return;

+	}

+

+	DWORD processId;

+	DWORD threadId = GetWindowThreadProcessId(mWindow, &processId);

+	if (processId != GetCurrentProcessId() || threadId != GetCurrentThreadId())

+	{

+		return;

+	}

+

+	SetLastError(0);

+	LONG oldWndProc = SetWindowLong(mWindow, GWL_WNDPROC, reinterpret_cast<LONG>(SurfaceWindowProc));

+

+	if(oldWndProc == 0 && GetLastError() != ERROR_SUCCESS)

+	{

+		mWindowSubclassed = false;

+		return;

+	}

+

+	SetProp(mWindow, kSurfaceProperty, reinterpret_cast<HANDLE>(this));

+	SetProp(mWindow, kParentWndProc, reinterpret_cast<HANDLE>(oldWndProc));

+	mWindowSubclassed = true;

+}

+

+void Surface::unsubclassWindow()

+{

+	if(!mWindowSubclassed)

+	{

+		return;

+	}

+

+	// un-subclass

+	LONG parentWndFunc = reinterpret_cast<LONG>(GetProp(mWindow, kParentWndProc));

+

+	// Check the windowproc is still SurfaceWindowProc.

+	// If this assert fails, then it is likely the application has subclassed the

+	// hwnd as well and did not unsubclass before destroying its EGL context. The

+	// application should be modified to either subclass before initializing the

+	// EGL context, or to unsubclass before destroying the EGL context.

+	if(parentWndFunc)

+	{

+		LONG prevWndFunc = SetWindowLong(mWindow, GWL_WNDPROC, parentWndFunc);

+		ASSERT(prevWndFunc == reinterpret_cast<LONG>(SurfaceWindowProc));

+	}

+

+	RemoveProp(mWindow, kSurfaceProperty);

+	RemoveProp(mWindow, kParentWndProc);

+	mWindowSubclassed = false;

+}

+

+bool Surface::checkForResize()

+{

+    RECT client;

+    if(!GetClientRect(mWindow, &client))

+    {

+        ASSERT(false);

+        return false;

+    }

+

+    // Grow the buffer now, if the window has grown. We need to grow now to avoid losing information.

+    int clientWidth = client.right - client.left;

+    int clientHeight = client.bottom - client.top;

+    bool sizeDirty = clientWidth != getWidth() || clientHeight != getHeight();

+

+    if(sizeDirty)

+    {

+        reset(clientWidth, clientHeight);

+

+        if(static_cast<egl::Surface*>(getCurrentDrawSurface()) == this)

+        {

+            gl::makeCurrent(gl::getCurrentContext(), static_cast<egl::Display*>(getCurrentDisplay()), this);

+        }

+

+        return true;

+    }

+

+    return false;

+}

+#endif

+}

diff --git a/src/GLES2/libEGL/Surface.h b/src/GLES2/libEGL/Surface.h
new file mode 100644
index 0000000..610113a
--- /dev/null
+++ b/src/GLES2/libEGL/Surface.h
@@ -0,0 +1,107 @@
+// SwiftShader Software Renderer

+//

+// Copyright(c) 2005-2012 TransGaming Inc.

+//

+// All rights reserved. No part of this software may be copied, distributed, transmitted,

+// transcribed, stored in a retrieval system, translated into any human or computer

+// language by any means, or disclosed to third parties without the explicit written

+// agreement of TransGaming Inc. Without such an agreement, no rights or licenses, express

+// or implied, including but not limited to any patent rights, are granted to you.

+//

+

+// Surface.h: Defines the egl::Surface class, representing a drawing surface

+// such as the client area of a window, including any back buffers.

+// Implements EGLSurface and related functionality. [EGL 1.4] section 2.2 page 3.

+

+#ifndef INCLUDE_SURFACE_H_

+#define INCLUDE_SURFACE_H_

+

+#include "libGLESv2/Image.hpp"

+#include "libGLESv2/Texture.h"

+#include "Main/FrameBuffer.hpp"

+

+#define EGLAPI

+#include <EGL/egl.h>

+

+namespace gl

+{

+class Image;

+class Texture2D;

+}

+

+namespace egl

+{

+class Display;

+class Config;

+

+class Surface

+{

+public:

+    Surface(Display *display, const egl::Config *config, EGLNativeWindowType window);

+    Surface(Display *display, const egl::Config *config, EGLint width, EGLint height, EGLenum textureFormat, EGLenum textureTarget);

+

+    ~Surface();

+

+	bool initialize();

+    void swap();

+

+	EGLNativeWindowType getWindowHandle();

+    virtual EGLint getWidth() const;

+    virtual EGLint getHeight() const;

+

+    virtual gl::Image *getRenderTarget();

+    virtual gl::Image *getDepthStencil();

+

+    void setSwapInterval(EGLint interval);

+

+    virtual EGLenum getTextureFormat() const;

+    virtual EGLenum getTextureTarget() const;

+    virtual sw::Format getInternalFormat() const;

+

+    virtual void setBoundTexture(gl::Texture2D *texture);

+    virtual gl::Texture2D *getBoundTexture() const;

+

+	#if defined(_WIN32)

+	bool checkForResize();   // Returns true if surface changed due to resize or interval update

+	#endif

+

+private:

+    void release();

+    bool reset();

+

+    Display *const mDisplay;

+    gl::Image *mDepthStencil;

+	sw::FrameBuffer *frameBuffer;

+	gl::Image *backBuffer;

+

+	bool reset(int backbufferWidth, int backbufferHeight);

+

+	#if defined(_WIN32)

+    void subclassWindow();

+    void unsubclassWindow();

+    #endif

+

+    const EGLNativeWindowType mWindow;   // Window that the surface is created for.

+    bool mWindowSubclassed;              // Indicates whether we successfully subclassed mWindow for WM_RESIZE hooking

+    const egl::Config *mConfig;          // EGL config surface was created with

+    EGLint mHeight;                      // Height of surface

+    EGLint mWidth;                       // Width of surface

+//  EGLint horizontalResolution;         // Horizontal dot pitch

+//  EGLint verticalResolution;           // Vertical dot pitch

+//  EGLBoolean largestPBuffer;           // If true, create largest pbuffer possible

+//  EGLBoolean mipmapTexture;            // True if texture has mipmaps

+//  EGLint mipmapLevel;                  // Mipmap level to render to

+//  EGLenum multisampleResolve;          // Multisample resolve behavior

+    EGLint mPixelAspectRatio;            // Display aspect ratio

+    EGLenum mRenderBuffer;               // Render buffer

+    EGLenum mSwapBehavior;               // Buffer swap behavior

+    EGLenum mTextureFormat;              // Format of texture: RGB, RGBA, or no texture

+    EGLenum mTextureTarget;              // Type of texture: 2D or no texture

+//  EGLenum vgAlphaFormat;               // Alpha format for OpenVG

+//  EGLenum vgColorSpace;                // Color space for OpenVG

+    EGLint mSwapInterval;

+    gl::Texture2D *mTexture;

+};

+}

+

+#endif   // INCLUDE_SURFACE_H_

diff --git a/src/GLES2/libEGL/libEGL.cbp b/src/GLES2/libEGL/libEGL.cbp
new file mode 100644
index 0000000..5609d21
--- /dev/null
+++ b/src/GLES2/libEGL/libEGL.cbp
@@ -0,0 +1,104 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
+<CodeBlocks_project_file>
+	<FileVersion major="1" minor="6" />
+	<Project>
+		<Option title="libEGL" />
+		<Option pch_mode="2" />
+		<Option compiler="gcc" />
+		<Build>
+			<Target title="Debug x86">
+				<Option output="./../../bin/x86/Debug/libEGL.so" prefix_auto="0" extension_auto="0" />
+				<Option object_output="obj/x86/Debug/" />
+				<Option type="3" />
+				<Option compiler="gcc" />
+				<Option createDefFile="1" />
+				<Option createStaticLib="1" />
+				<Compiler>
+					<Add option="-g" />
+					<Add option="-m32" />
+				</Compiler>
+				<Linker>
+					<Add option="-m32" />
+				</Linker>
+			</Target>
+			<Target title="Release x86">
+				<Option output="./../../bin/x86/Release/libEGL.so" prefix_auto="0" extension_auto="0" />
+				<Option object_output="obj/x86/Release/" />
+				<Option type="3" />
+				<Option compiler="gcc" />
+				<Option createDefFile="1" />
+				<Option createStaticLib="1" />
+				<Compiler>
+					<Add option="-O2" />
+					<Add option="-m32" />
+					<Add option="-DNDEBUG" />
+					<Add option="-DANGLE_DISABLE_TRACE" />
+				</Compiler>
+				<Linker>
+					<Add option="-s" />
+					<Add option="-m32" />
+				</Linker>
+			</Target>
+			<Target title="Debug x64">
+				<Option output="./../../bin/x64/Debug/libEGL.so" prefix_auto="0" extension_auto="0" />
+				<Option object_output="obj/x64/Debug/" />
+				<Option type="3" />
+				<Option compiler="gcc" />
+				<Option createDefFile="1" />
+				<Option createStaticLib="1" />
+				<Compiler>
+					<Add option="-g" />
+					<Add option="-m64" />
+					<Add option="-fPIC" />
+				</Compiler>
+				<Linker>
+					<Add option="-m64" />
+				</Linker>
+			</Target>
+			<Target title="Release x64">
+				<Option output="./../../bin/x64/Release/libEGL.so" prefix_auto="0" extension_auto="0" />
+				<Option object_output="obj/x64/Release/" />
+				<Option type="3" />
+				<Option compiler="gcc" />
+				<Option createDefFile="1" />
+				<Option createStaticLib="1" />
+				<Compiler>
+					<Add option="-march=core2" />
+					<Add option="-O2" />
+					<Add option="-m64" />
+					<Add option="-fPIC" />
+					<Add option="-DNDEBUG" />
+					<Add option="-DANGLE_DISABLE_TRACE" />
+				</Compiler>
+				<Linker>
+					<Add option="-s" />
+					<Add option="-m64" />
+				</Linker>
+			</Target>
+		</Build>
+		<Compiler>
+			<Add option="-Wall" />
+			<Add option="-fexceptions" />
+			<Add directory="./../include/" />
+			<Add directory="./../" />
+			<Add directory="./../../" />
+		</Compiler>
+		<Linker>
+			<Add library="pthread" />
+		</Linker>
+		<Unit filename="../common/debug.cpp" />
+		<Unit filename="./Config.cpp" />
+		<Unit filename="./Config.h" />
+		<Unit filename="./Display.cpp" />
+		<Unit filename="./Display.h" />
+		<Unit filename="./Surface.cpp" />
+		<Unit filename="./Surface.h" />
+		<Unit filename="./libEGL.cpp" />
+		<Unit filename="./main.cpp" />
+		<Unit filename="./main.h" />
+		<Extensions>
+			<code_completion />
+			<debugger />
+		</Extensions>
+	</Project>
+</CodeBlocks_project_file>
diff --git a/src/GLES2/libEGL/libEGL.cpp b/src/GLES2/libEGL/libEGL.cpp
new file mode 100644
index 0000000..e4358a6
--- /dev/null
+++ b/src/GLES2/libEGL/libEGL.cpp
@@ -0,0 +1,1100 @@
+// SwiftShader Software Renderer

+//

+// Copyright(c) 2005-2012 TransGaming Inc.

+//

+// All rights reserved. No part of this software may be copied, distributed, transmitted,

+// transcribed, stored in a retrieval system, translated into any human or computer

+// language by any means, or disclosed to third parties without the explicit written

+// agreement of TransGaming Inc. Without such an agreement, no rights or licenses, express

+// or implied, including but not limited to any patent rights, are granted to you.

+//

+

+// libEGL.cpp: Implements the exported EGL functions.

+

+#include "main.h"

+#include "Display.h"

+#include "libGLESv2/Context.h"

+#include "libGLESv2/Texture.h"

+#include "common/debug.h"

+#include "Common/Version.h"

+

+#include <exception>

+

+static bool validateDisplay(egl::Display *display)

+{

+    if(display == EGL_NO_DISPLAY)

+    {

+        return error(EGL_BAD_DISPLAY, false);

+    }

+

+    if(!display->isInitialized())

+    {

+        return error(EGL_NOT_INITIALIZED, false);

+    }

+

+    return true;

+}

+

+static bool validateConfig(egl::Display *display, EGLConfig config)

+{

+    if(!validateDisplay(display))

+    {

+        return false;

+    }

+

+    if(!display->isValidConfig(config))

+    {

+        return error(EGL_BAD_CONFIG, false);

+    }

+

+    return true;

+}

+

+static bool validateContext(egl::Display *display, gl::Context *context)

+{

+    if(!validateDisplay(display))

+    {

+        return false;

+    }

+

+    if(!display->isValidContext(context))

+    {

+        return error(EGL_BAD_CONTEXT, false);

+    }

+

+    return true;

+}

+

+static bool validateSurface(egl::Display *display, egl::Surface *surface)

+{

+    if(!validateDisplay(display))

+    {

+        return false;

+    }

+

+    if(!display->isValidSurface(surface))

+    {

+        return error(EGL_BAD_SURFACE, false);

+    }

+

+    return true;

+}

+

+extern "C"

+{

+EGLint EGLAPIENTRY eglGetError(void)

+{

+    TRACE("()");

+

+    EGLint error = egl::getCurrentError();

+

+    if(error != EGL_SUCCESS)

+    {

+        egl::setCurrentError(EGL_SUCCESS);

+    }

+

+    return error;

+}

+

+EGLDisplay EGLAPIENTRY eglGetDisplay(EGLNativeDisplayType display_id)

+{

+    TRACE("(EGLNativeDisplayType display_id = 0x%0.8p)", display_id);

+

+    try

+    {

+        return egl::Display::getDisplay(display_id);

+    }

+    catch(std::bad_alloc&)

+    {

+        return error(EGL_BAD_ALLOC, EGL_NO_DISPLAY);

+    }

+

+    return EGL_NO_DISPLAY;

+}

+

+EGLBoolean EGLAPIENTRY eglInitialize(EGLDisplay dpy, EGLint *major, EGLint *minor)

+{

+    TRACE("(EGLDisplay dpy = 0x%0.8p, EGLint *major = 0x%0.8p, EGLint *minor = 0x%0.8p)",

+          dpy, major, minor);

+

+    try

+    {

+        if(dpy == EGL_NO_DISPLAY)

+        {

+            return error(EGL_BAD_DISPLAY, EGL_FALSE);

+        }

+

+        egl::Display *display = static_cast<egl::Display*>(dpy);

+

+        if(!display->initialize())

+        {

+            return error(EGL_NOT_INITIALIZED, EGL_FALSE);

+        }

+

+        if(major) *major = 1;

+        if(minor) *minor = 4;

+

+        return success(EGL_TRUE);

+    }

+    catch(std::bad_alloc&)

+    {

+        return error(EGL_BAD_ALLOC, EGL_FALSE);

+    }

+

+    return EGL_FALSE;

+}

+

+EGLBoolean EGLAPIENTRY eglTerminate(EGLDisplay dpy)

+{

+    TRACE("(EGLDisplay dpy = 0x%0.8p)", dpy);

+

+    try

+    {

+        if(dpy == EGL_NO_DISPLAY)

+        {

+            return error(EGL_BAD_DISPLAY, EGL_FALSE);

+        }

+

+        egl::Display *display = static_cast<egl::Display*>(dpy);

+

+        display->terminate();

+

+        return success(EGL_TRUE);

+    }

+    catch(std::bad_alloc&)

+    {

+        return error(EGL_BAD_ALLOC, EGL_FALSE);

+    }

+

+    return EGL_FALSE;

+}

+

+const char *EGLAPIENTRY eglQueryString(EGLDisplay dpy, EGLint name)

+{

+    TRACE("(EGLDisplay dpy = 0x%0.8p, EGLint name = %d)", dpy, name);

+

+    try

+    {

+        egl::Display *display = static_cast<egl::Display*>(dpy);

+

+        if(!validateDisplay(display))

+        {

+            return NULL;

+        }

+

+        switch (name)

+        {

+          case EGL_CLIENT_APIS:

+            return success("OpenGL_ES");

+          case EGL_EXTENSIONS:

+            return display->getExtensionString();

+          case EGL_VENDOR:

+            return success("TransGaming Inc.");

+          case EGL_VERSION:

+            return success("1.4 SwiftShader "VERSION_STRING);

+        }

+

+        return error(EGL_BAD_PARAMETER, (const char*)NULL);

+    }

+    catch(std::bad_alloc&)

+    {

+        return error(EGL_BAD_ALLOC, (const char*)NULL);

+    }

+

+    return NULL;

+}

+

+EGLBoolean EGLAPIENTRY eglGetConfigs(EGLDisplay dpy, EGLConfig *configs, EGLint config_size, EGLint *num_config)

+{

+    TRACE("(EGLDisplay dpy = 0x%0.8p, EGLConfig *configs = 0x%0.8p, "

+          "EGLint config_size = %d, EGLint *num_config = 0x%0.8p)",

+          dpy, configs, config_size, num_config);

+

+    try

+    {

+        egl::Display *display = static_cast<egl::Display*>(dpy);

+

+        if(!validateDisplay(display))

+        {

+            return EGL_FALSE;

+        }

+

+        if(!num_config)

+        {

+            return error(EGL_BAD_PARAMETER, EGL_FALSE);

+        }

+

+        const EGLint attribList[] =    {EGL_NONE};

+

+        if(!display->getConfigs(configs, attribList, config_size, num_config))

+        {

+            return error(EGL_BAD_ATTRIBUTE, EGL_FALSE);

+        }

+

+        return success(EGL_TRUE);

+    }

+    catch(std::bad_alloc&)

+    {

+        return error(EGL_BAD_ALLOC, EGL_FALSE);

+    }

+

+    return EGL_FALSE;

+}

+

+EGLBoolean EGLAPIENTRY eglChooseConfig(EGLDisplay dpy, const EGLint *attrib_list, EGLConfig *configs, EGLint config_size, EGLint *num_config)

+{

+    TRACE("(EGLDisplay dpy = 0x%0.8p, const EGLint *attrib_list = 0x%0.8p, "

+          "EGLConfig *configs = 0x%0.8p, EGLint config_size = %d, EGLint *num_config = 0x%0.8p)",

+          dpy, attrib_list, configs, config_size, num_config);

+

+    try

+    {

+        egl::Display *display = static_cast<egl::Display*>(dpy);

+

+        if(!validateDisplay(display))

+        {

+            return EGL_FALSE;

+        }

+

+        if(!num_config)

+        {

+            return error(EGL_BAD_PARAMETER, EGL_FALSE);

+        }

+

+        const EGLint attribList[] =    {EGL_NONE};

+

+        if(!attrib_list)

+        {

+            attrib_list = attribList;

+        }

+

+        display->getConfigs(configs, attrib_list, config_size, num_config);

+

+        return success(EGL_TRUE);

+    }

+    catch(std::bad_alloc&)

+    {

+        return error(EGL_BAD_ALLOC, EGL_FALSE);

+    }

+

+    return EGL_FALSE;

+}

+

+EGLBoolean EGLAPIENTRY eglGetConfigAttrib(EGLDisplay dpy, EGLConfig config, EGLint attribute, EGLint *value)

+{

+    TRACE("(EGLDisplay dpy = 0x%0.8p, EGLConfig config = 0x%0.8p, EGLint attribute = %d, EGLint *value = 0x%0.8p)",

+          dpy, config, attribute, value);

+

+    try

+    {

+        egl::Display *display = static_cast<egl::Display*>(dpy);

+

+        if(!validateConfig(display, config))

+        {

+            return EGL_FALSE;

+        }

+

+        if(!display->getConfigAttrib(config, attribute, value))

+        {

+            return error(EGL_BAD_ATTRIBUTE, EGL_FALSE);

+        }

+

+        return success(EGL_TRUE);

+    }

+    catch(std::bad_alloc&)

+    {

+        return error(EGL_BAD_ALLOC, EGL_FALSE);

+    }

+

+    return EGL_FALSE;

+}

+

+EGLSurface EGLAPIENTRY eglCreateWindowSurface(EGLDisplay dpy, EGLConfig config, EGLNativeWindowType window, const EGLint *attrib_list)

+{

+    TRACE("(EGLDisplay dpy = 0x%0.8p, EGLConfig config = 0x%0.8p, EGLNativeWindowType win = 0x%0.8p, "

+          "const EGLint *attrib_list = 0x%0.8p)", dpy, config, window, attrib_list);

+

+    try

+    {

+        egl::Display *display = static_cast<egl::Display*>(dpy);

+

+        if(!validateConfig(display, config))

+        {

+            return EGL_NO_SURFACE;

+        }

+

+		if(!display->isValidWindow(window))

+		{

+			return error(EGL_BAD_NATIVE_WINDOW, EGL_NO_SURFACE);

+		}

+

+        return display->createWindowSurface(window, config, attrib_list);

+    }

+    catch(std::bad_alloc&)

+    {

+        return error(EGL_BAD_ALLOC, EGL_NO_SURFACE);

+    }

+

+    return EGL_NO_SURFACE;

+}

+

+EGLSurface EGLAPIENTRY eglCreatePbufferSurface(EGLDisplay dpy, EGLConfig config, const EGLint *attrib_list)

+{

+    TRACE("(EGLDisplay dpy = 0x%0.8p, EGLConfig config = 0x%0.8p, const EGLint *attrib_list = 0x%0.8p)",

+          dpy, config, attrib_list);

+

+    try

+    {

+        egl::Display *display = static_cast<egl::Display*>(dpy);

+

+        if(!validateConfig(display, config))

+        {

+            return EGL_NO_SURFACE;

+        }

+

+        return display->createOffscreenSurface(config, attrib_list);

+    }

+    catch(std::bad_alloc&)

+    {

+        return error(EGL_BAD_ALLOC, EGL_NO_SURFACE);

+    }

+

+    return EGL_NO_SURFACE;

+}

+

+EGLSurface EGLAPIENTRY eglCreatePixmapSurface(EGLDisplay dpy, EGLConfig config, EGLNativePixmapType pixmap, const EGLint *attrib_list)

+{

+    TRACE("(EGLDisplay dpy = 0x%0.8p, EGLConfig config = 0x%0.8p, EGLNativePixmapType pixmap = 0x%0.8p, "

+          "const EGLint *attrib_list = 0x%0.8p)", dpy, config, pixmap, attrib_list);

+

+    try

+    {

+        egl::Display *display = static_cast<egl::Display*>(dpy);

+

+        if(!validateConfig(display, config))

+        {

+            return EGL_NO_SURFACE;

+        }

+

+        UNIMPLEMENTED();   // FIXME

+

+        return success(EGL_NO_SURFACE);

+    }

+    catch(std::bad_alloc&)

+    {

+        return error(EGL_BAD_ALLOC, EGL_NO_SURFACE);

+    }

+

+    return EGL_NO_SURFACE;

+}

+

+EGLBoolean EGLAPIENTRY eglDestroySurface(EGLDisplay dpy, EGLSurface surface)

+{

+    TRACE("(EGLDisplay dpy = 0x%0.8p, EGLSurface surface = 0x%0.8p)", dpy, surface);

+

+    try

+    {

+        egl::Display *display = static_cast<egl::Display*>(dpy);

+        egl::Surface *eglSurface = static_cast<egl::Surface*>(surface);

+

+        if(!validateSurface(display, eglSurface))

+        {

+            return EGL_FALSE;

+        }

+

+        if(surface == EGL_NO_SURFACE)

+        {

+            return error(EGL_BAD_SURFACE, EGL_FALSE);

+        }

+

+        display->destroySurface((egl::Surface*)surface);

+

+        return success(EGL_TRUE);

+    }

+    catch(std::bad_alloc&)

+    {

+        return error(EGL_BAD_ALLOC, EGL_FALSE);

+    }

+

+    return EGL_FALSE;

+}

+

+EGLBoolean EGLAPIENTRY eglQuerySurface(EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint *value)

+{

+    TRACE("(EGLDisplay dpy = 0x%0.8p, EGLSurface surface = 0x%0.8p, EGLint attribute = %d, EGLint *value = 0x%0.8p)",

+          dpy, surface, attribute, value);

+

+    try

+    {

+        egl::Display *display = static_cast<egl::Display*>(dpy);

+        egl::Surface *eglSurface = (egl::Surface*)surface;

+

+        if(!validateSurface(display, eglSurface))

+        {

+            return EGL_FALSE;

+        }

+

+        if(surface == EGL_NO_SURFACE)

+        {

+            return error(EGL_BAD_SURFACE, EGL_FALSE);

+        }

+

+        switch(attribute)

+        {

+          case EGL_VG_ALPHA_FORMAT:

+            UNIMPLEMENTED();   // FIXME

+            break;

+          case EGL_VG_COLORSPACE:

+            UNIMPLEMENTED();   // FIXME

+            break;

+          case EGL_CONFIG_ID:

+            UNIMPLEMENTED();   // FIXME

+            break;

+          case EGL_HEIGHT:

+            *value = eglSurface->getHeight();

+            break;

+          case EGL_HORIZONTAL_RESOLUTION:

+            UNIMPLEMENTED();   // FIXME

+            break;

+          case EGL_LARGEST_PBUFFER:

+            UNIMPLEMENTED();   // FIXME

+            break;

+          case EGL_MIPMAP_TEXTURE:

+            UNIMPLEMENTED();   // FIXME

+            break;

+          case EGL_MIPMAP_LEVEL:

+            UNIMPLEMENTED();   // FIXME

+            break;

+          case EGL_MULTISAMPLE_RESOLVE:

+            UNIMPLEMENTED();   // FIXME

+            break;

+          case EGL_PIXEL_ASPECT_RATIO:

+            UNIMPLEMENTED();   // FIXME

+            break;

+          case EGL_RENDER_BUFFER:

+            UNIMPLEMENTED();   // FIXME

+            break;

+          case EGL_SWAP_BEHAVIOR:

+            UNIMPLEMENTED();   // FIXME

+            break;

+          case EGL_TEXTURE_FORMAT:

+            UNIMPLEMENTED();   // FIXME

+            break;

+          case EGL_TEXTURE_TARGET:

+            UNIMPLEMENTED();   // FIXME

+            break;

+          case EGL_VERTICAL_RESOLUTION:

+            UNIMPLEMENTED();   // FIXME

+            break;

+          case EGL_WIDTH:

+            *value = eglSurface->getWidth();

+            break;

+          default:

+            return error(EGL_BAD_ATTRIBUTE, EGL_FALSE);

+        }

+

+        return success(EGL_TRUE);

+    }

+    catch(std::bad_alloc&)

+    {

+        return error(EGL_BAD_ALLOC, EGL_FALSE);

+    }

+

+    return EGL_FALSE;

+}

+

+EGLBoolean EGLAPIENTRY eglBindAPI(EGLenum api)

+{

+    TRACE("(EGLenum api = 0x%X)", api);

+

+    try

+    {

+        switch (api)

+        {

+          case EGL_OPENGL_API:

+          case EGL_OPENVG_API:

+            return error(EGL_BAD_PARAMETER, EGL_FALSE);   // Not supported by this implementation

+          case EGL_OPENGL_ES_API:

+            break;

+          default:

+            return error(EGL_BAD_PARAMETER, EGL_FALSE);

+        }

+

+        egl::setCurrentAPI(api);

+

+        return success(EGL_TRUE);

+    }

+    catch(std::bad_alloc&)

+    {

+        return error(EGL_BAD_ALLOC, EGL_FALSE);

+    }

+

+    return EGL_FALSE;

+}

+

+EGLenum EGLAPIENTRY eglQueryAPI(void)

+{

+    TRACE("()");

+

+    try

+    {

+        EGLenum API = egl::getCurrentAPI();

+

+        return success(API);

+    }

+    catch(std::bad_alloc&)

+    {

+        return error(EGL_BAD_ALLOC, EGL_FALSE);

+    }

+

+    return EGL_FALSE;

+}

+

+EGLBoolean EGLAPIENTRY eglWaitClient(void)

+{

+    TRACE("()");

+

+    try

+    {

+        UNIMPLEMENTED();   // FIXME

+

+        return success(0);

+    }

+    catch(std::bad_alloc&)

+    {

+        return error(EGL_BAD_ALLOC, EGL_FALSE);

+    }

+

+    return EGL_FALSE;

+}

+

+EGLBoolean EGLAPIENTRY eglReleaseThread(void)

+{

+    TRACE("()");

+

+    try

+    {

+        eglMakeCurrent(EGL_NO_DISPLAY, EGL_NO_CONTEXT, EGL_NO_SURFACE, EGL_NO_SURFACE);

+

+        return success(EGL_TRUE);

+    }

+    catch(std::bad_alloc&)

+    {

+        return error(EGL_BAD_ALLOC, EGL_FALSE);

+    }

+

+    return EGL_FALSE;

+}

+

+EGLSurface EGLAPIENTRY eglCreatePbufferFromClientBuffer(EGLDisplay dpy, EGLenum buftype, EGLClientBuffer buffer, EGLConfig config, const EGLint *attrib_list)

+{

+    TRACE("(EGLDisplay dpy = 0x%0.8p, EGLenum buftype = 0x%X, EGLClientBuffer buffer = 0x%0.8p, "

+          "EGLConfig config = 0x%0.8p, const EGLint *attrib_list = 0x%0.8p)",

+          dpy, buftype, buffer, config, attrib_list);

+

+	UNIMPLEMENTED();

+

+    return error(EGL_BAD_PARAMETER, EGL_NO_SURFACE);

+}

+

+EGLBoolean EGLAPIENTRY eglSurfaceAttrib(EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint value)

+{

+    TRACE("(EGLDisplay dpy = 0x%0.8p, EGLSurface surface = 0x%0.8p, EGLint attribute = %d, EGLint value = %d)",

+          dpy, surface, attribute, value);

+

+    try

+    {

+        egl::Display *display = static_cast<egl::Display*>(dpy);

+        egl::Surface *eglSurface = static_cast<egl::Surface*>(surface);

+

+        if(!validateSurface(display, eglSurface))

+        {

+            return EGL_FALSE;

+        }

+

+        UNIMPLEMENTED();   // FIXME

+

+        return success(EGL_TRUE);

+    }

+    catch(std::bad_alloc&)

+    {

+        return error(EGL_BAD_ALLOC, EGL_FALSE);

+    }

+

+    return EGL_FALSE;

+}

+

+EGLBoolean EGLAPIENTRY eglBindTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer)

+{

+    TRACE("(EGLDisplay dpy = 0x%0.8p, EGLSurface surface = 0x%0.8p, EGLint buffer = %d)", dpy, surface, buffer);

+

+    try

+    {

+        egl::Display *display = static_cast<egl::Display*>(dpy);

+        egl::Surface *eglSurface = static_cast<egl::Surface*>(surface);

+

+        if(!validateSurface(display, eglSurface))

+        {

+            return EGL_FALSE;

+        }

+

+        if(buffer != EGL_BACK_BUFFER)

+        {

+            return error(EGL_BAD_PARAMETER, EGL_FALSE);

+        }

+

+        if(surface == EGL_NO_SURFACE || eglSurface->getWindowHandle())

+        {

+            return error(EGL_BAD_SURFACE, EGL_FALSE);

+        }

+

+        if(eglSurface->getBoundTexture())

+        {

+            return error(EGL_BAD_ACCESS, EGL_FALSE);

+        }

+

+        if(eglSurface->getTextureFormat() == EGL_NO_TEXTURE)

+        {

+            return error(EGL_BAD_MATCH, EGL_FALSE);

+        }

+

+        gl::bindTexImage(eglSurface);

+

+        return success(EGL_TRUE);

+    }

+    catch(std::bad_alloc&)

+    {

+        return error(EGL_BAD_ALLOC, EGL_FALSE);

+    }

+

+    return EGL_FALSE;

+}

+

+EGLBoolean EGLAPIENTRY eglReleaseTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer)

+{

+    TRACE("(EGLDisplay dpy = 0x%0.8p, EGLSurface surface = 0x%0.8p, EGLint buffer = %d)", dpy, surface, buffer);

+

+    try

+    {

+        egl::Display *display = static_cast<egl::Display*>(dpy);

+        egl::Surface *eglSurface = static_cast<egl::Surface*>(surface);

+

+        if(!validateSurface(display, eglSurface))

+        {

+            return EGL_FALSE;

+        }

+

+        if(buffer != EGL_BACK_BUFFER)

+        {

+            return error(EGL_BAD_PARAMETER, EGL_FALSE);

+        }

+

+        if(surface == EGL_NO_SURFACE || eglSurface->getWindowHandle())

+        {

+            return error(EGL_BAD_SURFACE, EGL_FALSE);

+        }

+

+        if(eglSurface->getTextureFormat() == EGL_NO_TEXTURE)

+        {

+            return error(EGL_BAD_MATCH, EGL_FALSE);

+        }

+

+        gl::Texture2D *texture = eglSurface->getBoundTexture();

+

+        if(texture)

+        {

+            texture->releaseTexImage();

+        }

+

+        return success(EGL_TRUE);

+    }

+    catch(std::bad_alloc&)

+    {

+        return error(EGL_BAD_ALLOC, EGL_FALSE);

+    }

+

+    return EGL_FALSE;

+}

+

+EGLBoolean EGLAPIENTRY eglSwapInterval(EGLDisplay dpy, EGLint interval)

+{

+    TRACE("(EGLDisplay dpy = 0x%0.8p, EGLint interval = %d)", dpy, interval);

+

+    try

+    {

+        egl::Display *display = static_cast<egl::Display*>(dpy);

+

+        if(!validateDisplay(display))

+        {

+            return EGL_FALSE;

+        }

+

+        egl::Surface *draw_surface = static_cast<egl::Surface*>(egl::getCurrentDrawSurface());

+

+        if(draw_surface == NULL)

+        {

+            return error(EGL_BAD_SURFACE, EGL_FALSE);

+        }

+        

+        draw_surface->setSwapInterval(interval);

+

+        return success(EGL_TRUE);

+    }

+    catch(std::bad_alloc&)

+    {

+        return error(EGL_BAD_ALLOC, EGL_FALSE);

+    }

+

+    return EGL_FALSE;

+}

+

+EGLContext EGLAPIENTRY eglCreateContext(EGLDisplay dpy, EGLConfig config, EGLContext share_context, const EGLint *attrib_list)

+{

+    TRACE("(EGLDisplay dpy = 0x%0.8p, EGLConfig config = 0x%0.8p, EGLContext share_context = 0x%0.8p, "

+          "const EGLint *attrib_list = 0x%0.8p)", dpy, config, share_context, attrib_list);

+

+    try

+    {

+        // Get the requested client version (default is 1) and check it is two.

+        EGLint client_version = 1;

+        if(attrib_list)

+        {

+            for(const EGLint* attribute = attrib_list; attribute[0] != EGL_NONE; attribute += 2)

+            {

+                if(attribute[0] == EGL_CONTEXT_CLIENT_VERSION)

+                {

+                    client_version = attribute[1];

+                }

+                else

+                {

+                    return error(EGL_BAD_ATTRIBUTE, EGL_NO_CONTEXT);

+                }

+            }

+        }

+

+        if(client_version != 2)

+        {

+            return error(EGL_BAD_CONFIG, EGL_NO_CONTEXT);

+        }

+

+        egl::Display *display = static_cast<egl::Display*>(dpy);

+

+        if(!validateConfig(display, config))

+        {

+            return EGL_NO_CONTEXT;

+        }

+

+        EGLContext context = display->createContext(config, static_cast<gl::Context*>(share_context));

+

+        return success(context);

+    }

+    catch(std::bad_alloc&)

+    {

+        return error(EGL_BAD_ALLOC, EGL_NO_CONTEXT);

+    }

+

+    return EGL_NO_CONTEXT;

+}

+

+EGLBoolean EGLAPIENTRY eglDestroyContext(EGLDisplay dpy, EGLContext ctx)

+{

+    TRACE("(EGLDisplay dpy = 0x%0.8p, EGLContext ctx = 0x%0.8p)", dpy, ctx);

+

+    try

+    {

+        egl::Display *display = static_cast<egl::Display*>(dpy);

+        gl::Context *context = static_cast<gl::Context*>(ctx);

+

+        if(!validateContext(display, context))

+        {

+            return EGL_FALSE;

+        }

+

+        if(ctx == EGL_NO_CONTEXT)

+        {

+            return error(EGL_BAD_CONTEXT, EGL_FALSE);

+        }

+

+        display->destroyContext(context);

+

+        return success(EGL_TRUE);

+    }

+    catch(std::bad_alloc&)

+    {

+        return error(EGL_BAD_ALLOC, EGL_FALSE);

+    }

+

+    return EGL_FALSE;

+}

+

+EGLBoolean EGLAPIENTRY eglMakeCurrent(EGLDisplay dpy, EGLSurface draw, EGLSurface read, EGLContext ctx)

+{

+    TRACE("(EGLDisplay dpy = 0x%0.8p, EGLSurface draw = 0x%0.8p, EGLSurface read = 0x%0.8p, EGLContext ctx = 0x%0.8p)",

+          dpy, draw, read, ctx);

+

+    try

+    {

+        egl::Display *display = static_cast<egl::Display*>(dpy);

+        gl::Context *context = static_cast<gl::Context*>(ctx);

+        gl::Device *device = display->getDevice();

+

+        if(!device)

+        {

+            return error(EGL_CONTEXT_LOST, EGL_FALSE);

+        }

+

+        if(ctx != EGL_NO_CONTEXT && !validateContext(display, context))

+        {

+            return EGL_FALSE;

+        }

+

+        if((draw != EGL_NO_SURFACE && !validateSurface(display, static_cast<egl::Surface*>(draw))) ||

+           (read != EGL_NO_SURFACE && !validateSurface(display, static_cast<egl::Surface*>(read))))

+        {

+            return EGL_FALSE;

+        }

+

+        if(draw != read)

+        {

+            UNIMPLEMENTED();   // FIXME

+        }

+

+        egl::Surface* previousDraw = static_cast<egl::Surface*>(egl::getCurrentDrawSurface());

+        egl::Surface* previousRead = static_cast<egl::Surface*>(egl::getCurrentReadSurface());

+

+        egl::setCurrentDisplay(dpy);

+        egl::setCurrentDrawSurface(draw);

+        egl::setCurrentReadSurface(read);

+

+        gl::makeCurrent(context, display, static_cast<egl::Surface*>(draw));

+

+        return success(EGL_TRUE);

+    }

+    catch(std::bad_alloc&)

+    {

+        return error(EGL_BAD_ALLOC, EGL_FALSE);

+    }

+

+    return EGL_FALSE;

+}

+

+EGLContext EGLAPIENTRY eglGetCurrentContext(void)

+{

+    TRACE("()");

+

+    try

+    {

+		EGLContext context = gl::getCurrentContext();

+

+		return success(context);

+    }

+    catch(std::bad_alloc&)

+    {

+        return error(EGL_BAD_ALLOC, EGL_NO_CONTEXT);

+    }

+

+    return EGL_NO_CONTEXT;

+}

+

+EGLSurface EGLAPIENTRY eglGetCurrentSurface(EGLint readdraw)

+{

+    TRACE("(EGLint readdraw = %d)", readdraw);

+

+    try

+    {

+        if(readdraw == EGL_READ)

+        {

+            EGLSurface read = egl::getCurrentReadSurface();

+            return success(read);

+        }

+        else if(readdraw == EGL_DRAW)

+        {

+            EGLSurface draw = egl::getCurrentDrawSurface();

+            return success(draw);

+        }

+        else

+        {

+            return error(EGL_BAD_PARAMETER, EGL_NO_SURFACE);

+        }

+    }

+    catch(std::bad_alloc&)

+    {

+        return error(EGL_BAD_ALLOC, EGL_NO_SURFACE);

+    }

+

+    return EGL_NO_SURFACE;

+}

+

+EGLDisplay EGLAPIENTRY eglGetCurrentDisplay(void)

+{

+    TRACE("()");

+

+    try

+    {

+        EGLDisplay dpy = egl::getCurrentDisplay();

+

+        return success(dpy);

+    }

+    catch(std::bad_alloc&)

+    {

+        return error(EGL_BAD_ALLOC, EGL_NO_DISPLAY);

+    }

+

+    return EGL_NO_DISPLAY;

+}

+

+EGLBoolean EGLAPIENTRY eglQueryContext(EGLDisplay dpy, EGLContext ctx, EGLint attribute, EGLint *value)

+{

+    TRACE("(EGLDisplay dpy = 0x%0.8p, EGLContext ctx = 0x%0.8p, EGLint attribute = %d, EGLint *value = 0x%0.8p)",

+          dpy, ctx, attribute, value);

+

+    try

+    {

+        egl::Display *display = static_cast<egl::Display*>(dpy);

+        gl::Context *context = static_cast<gl::Context*>(ctx);

+

+        if(!validateContext(display, context))

+        {

+            return EGL_FALSE;

+        }

+

+        UNIMPLEMENTED();   // FIXME

+

+        return success(0);

+    }

+    catch(std::bad_alloc&)

+    {

+        return error(EGL_BAD_ALLOC, EGL_FALSE);

+    }

+

+    return EGL_FALSE;

+}

+

+EGLBoolean EGLAPIENTRY eglWaitGL(void)

+{

+    TRACE("()");

+

+    try

+    {

+        UNIMPLEMENTED();   // FIXME

+

+        return success(0);

+    }

+    catch(std::bad_alloc&)

+    {

+        return error(EGL_BAD_ALLOC, EGL_FALSE);

+    }

+

+    return EGL_FALSE;

+}

+

+EGLBoolean EGLAPIENTRY eglWaitNative(EGLint engine)

+{

+    TRACE("(EGLint engine = %d)", engine);

+

+    try

+    {

+        UNIMPLEMENTED();   // FIXME

+

+        return success(0);

+    }

+    catch(std::bad_alloc&)

+    {

+        return error(EGL_BAD_ALLOC, EGL_FALSE);

+    }

+

+    return EGL_FALSE;

+}

+

+EGLBoolean EGLAPIENTRY eglSwapBuffers(EGLDisplay dpy, EGLSurface surface)

+{

+    TRACE("(EGLDisplay dpy = 0x%0.8p, EGLSurface surface = 0x%0.8p)", dpy, surface);

+

+    try

+    {

+        egl::Display *display = static_cast<egl::Display*>(dpy);

+        egl::Surface *eglSurface = (egl::Surface*)surface;

+

+        if(!validateSurface(display, eglSurface))

+        {

+            return EGL_FALSE;

+        }

+

+        if(surface == EGL_NO_SURFACE)

+        {

+            return error(EGL_BAD_SURFACE, EGL_FALSE);

+        }

+

+        eglSurface->swap();

+        

+        return success(EGL_TRUE);

+    }

+    catch(std::bad_alloc&)

+    {

+        return error(EGL_BAD_ALLOC, EGL_FALSE);

+    }

+

+    return EGL_FALSE;

+}

+

+EGLBoolean EGLAPIENTRY eglCopyBuffers(EGLDisplay dpy, EGLSurface surface, EGLNativePixmapType target)

+{

+    TRACE("(EGLDisplay dpy = 0x%0.8p, EGLSurface surface = 0x%0.8p, EGLNativePixmapType target = 0x%0.8p)", dpy, surface, target);

+

+    try

+    {

+        egl::Display *display = static_cast<egl::Display*>(dpy);

+        egl::Surface *eglSurface = static_cast<egl::Surface*>(surface);

+

+        if(!validateSurface(display, eglSurface))

+        {

+            return EGL_FALSE;

+        }

+

+        UNIMPLEMENTED();   // FIXME

+

+        return success(0);

+    }

+    catch(std::bad_alloc&)

+    {

+        return error(EGL_BAD_ALLOC, EGL_FALSE);

+    }

+

+    return EGL_FALSE;

+}

+

+__eglMustCastToProperFunctionPointerType EGLAPIENTRY eglGetProcAddress(const char *procname)

+{

+    TRACE("(const char *procname = \"%s\")", procname);

+

+    try

+    {

+        struct Extension

+        {

+            const char *name;

+            __eglMustCastToProperFunctionPointerType address;

+        };

+

+        static const Extension eglExtensions[] =

+        {

+            {"", NULL},

+        };

+

+        for(int ext = 0; ext < sizeof(eglExtensions) / sizeof(Extension); ext++)

+        {

+            if(strcmp(procname, eglExtensions[ext].name) == 0)

+            {

+                return (__eglMustCastToProperFunctionPointerType)eglExtensions[ext].address;

+            }

+        }

+

+		return gl::getProcAddress(procname);

+    }

+    catch(std::bad_alloc&)

+    {

+        return error(EGL_BAD_ALLOC, (__eglMustCastToProperFunctionPointerType)NULL);

+    }

+

+    return NULL;

+}

+}

diff --git a/src/GLES2/libEGL/libEGL.def b/src/GLES2/libEGL/libEGL.def
new file mode 100644
index 0000000..71a5e67
--- /dev/null
+++ b/src/GLES2/libEGL/libEGL.def
@@ -0,0 +1,36 @@
+LIBRARY	libEGL
+EXPORTS
+	eglBindAPI                      @14
+	eglBindTexImage                 @20
+	eglChooseConfig                 @7
+	eglCopyBuffers                  @33
+	eglCreateContext                @23
+	eglCreatePbufferFromClientBuffer        @18
+	eglCreatePbufferSurface         @10
+	eglCreatePixmapSurface          @11
+	eglCreateWindowSurface          @9
+	eglDestroyContext               @24
+	eglDestroySurface               @12
+	eglGetConfigAttrib              @8
+	eglGetConfigs                   @6
+	eglGetCurrentContext            @26
+	eglGetCurrentDisplay            @28
+	eglGetCurrentSurface            @27
+	eglGetDisplay                   @2
+	eglGetError                     @1
+	eglGetProcAddress               @34
+	eglInitialize                   @3
+	eglMakeCurrent                  @25
+	eglQueryAPI                     @15
+	eglQueryContext                 @29
+	eglQueryString                  @5
+	eglQuerySurface                 @13
+	eglReleaseTexImage              @21
+	eglReleaseThread                @17
+	eglSurfaceAttrib                @19
+	eglSwapBuffers                  @32
+	eglSwapInterval                 @22
+	eglTerminate                    @4
+	eglWaitClient                   @16
+	eglWaitGL                       @30
+	eglWaitNative                   @31
\ No newline at end of file
diff --git a/src/GLES2/libEGL/libEGL.rc b/src/GLES2/libEGL/libEGL.rc
new file mode 100644
index 0000000..d426063
--- /dev/null
+++ b/src/GLES2/libEGL/libEGL.rc
@@ -0,0 +1,102 @@
+// Microsoft Visual C++ generated resource script.
+//
+#include "resource.h"
+
+#define APSTUDIO_READONLY_SYMBOLS
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 2 resource.
+//
+#include <windows.h>
+#include "../../common/Version.h"
+
+/////////////////////////////////////////////////////////////////////////////
+#undef APSTUDIO_READONLY_SYMBOLS
+
+/////////////////////////////////////////////////////////////////////////////
+// English (U.S.) resources
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
+#ifdef _WIN32
+LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
+#pragma code_page(1252)
+#endif //_WIN32
+
+#ifdef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// TEXTINCLUDE
+//
+
+1 TEXTINCLUDE 
+BEGIN
+    "resource.h\0"
+END
+
+2 TEXTINCLUDE 
+BEGIN
+    "#include ""afxres.h""\r\n"
+    "#include ""../common/version.h""\0"
+END
+
+3 TEXTINCLUDE 
+BEGIN
+    "\r\n"
+    "\0"
+END
+
+#endif    // APSTUDIO_INVOKED
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Version
+//
+
+VS_VERSION_INFO VERSIONINFO
+ FILEVERSION MAJOR_VERSION,MINOR_VERSION,BUILD_VERSION,BUILD_REVISION
+ PRODUCTVERSION MAJOR_VERSION,MINOR_VERSION,BUILD_VERSION,BUILD_REVISION
+ FILEFLAGSMASK 0x17L
+#ifdef _DEBUG
+ FILEFLAGS 0x1L
+#else
+ FILEFLAGS 0x0L
+#endif
+ FILEOS 0x4L
+ FILETYPE 0x2L
+ FILESUBTYPE 0x0L
+BEGIN
+    BLOCK "StringFileInfo"
+    BEGIN
+        BLOCK "040904b0"
+        BEGIN
+            VALUE "FileDescription", "SwiftShader libEGL Dynamic Link Library"
+            VALUE "FileVersion", VERSION_STRING
+            VALUE "InternalName", "libEGL"
+            VALUE "LegalCopyright", "Copyright (C) 2012 TransGaming Inc."
+            VALUE "OriginalFilename", "libEGL.dll"
+            VALUE "PrivateBuild", VERSION_STRING
+            VALUE "ProductName", "SwiftShader libEGL Dynamic Link Library"
+            VALUE "ProductVersion", VERSION_STRING
+        END
+    END
+    BLOCK "VarFileInfo"
+    BEGIN
+        VALUE "Translation", 0x409, 1200
+    END
+END
+
+#endif    // English (U.S.) resources
+/////////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 3 resource.
+//
+
+
+/////////////////////////////////////////////////////////////////////////////
+#endif    // not APSTUDIO_INVOKED
diff --git a/src/GLES2/libEGL/libEGL.vcxproj b/src/GLES2/libEGL/libEGL.vcxproj
new file mode 100644
index 0000000..7eeff3f
--- /dev/null
+++ b/src/GLES2/libEGL/libEGL.vcxproj
@@ -0,0 +1,187 @@
+<?xml version="1.0" encoding="utf-8"?>

+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

+  <ItemGroup Label="ProjectConfigurations">

+    <ProjectConfiguration Include="Debug|Win32">

+      <Configuration>Debug</Configuration>

+      <Platform>Win32</Platform>

+    </ProjectConfiguration>

+    <ProjectConfiguration Include="Profile|Win32">

+      <Configuration>Profile</Configuration>

+      <Platform>Win32</Platform>

+    </ProjectConfiguration>

+    <ProjectConfiguration Include="Release|Win32">

+      <Configuration>Release</Configuration>

+      <Platform>Win32</Platform>

+    </ProjectConfiguration>

+  </ItemGroup>

+  <PropertyGroup Label="Globals">

+    <ProjectGuid>{E746FCA9-64C3-433E-85E8-9A5A67AB7ED6}</ProjectGuid>

+    <RootNamespace>libEGL</RootNamespace>

+    <Keyword>Win32Proj</Keyword>

+  </PropertyGroup>

+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">

+    <ConfigurationType>DynamicLibrary</ConfigurationType>

+    <CharacterSet>NotSet</CharacterSet>

+    <WholeProgramOptimization>true</WholeProgramOptimization>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Profile|Win32'" Label="Configuration">

+    <ConfigurationType>DynamicLibrary</ConfigurationType>

+    <CharacterSet>NotSet</CharacterSet>

+    <WholeProgramOptimization>true</WholeProgramOptimization>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">

+    <ConfigurationType>DynamicLibrary</ConfigurationType>

+    <CharacterSet>NotSet</CharacterSet>

+  </PropertyGroup>

+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />

+  <ImportGroup Label="ExtensionSettings">

+  </ImportGroup>

+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">

+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

+  </ImportGroup>

+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Profile|Win32'" Label="PropertySheets">

+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

+  </ImportGroup>

+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">

+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

+  </ImportGroup>

+  <PropertyGroup Label="UserMacros" />

+  <PropertyGroup>

+    <_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion>

+    <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(Platform)\$(Configuration)\</OutDir>

+    <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(Platform)\$(Configuration)\</IntDir>

+    <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</LinkIncremental>

+    <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(Platform)\$(Configuration)\</OutDir>

+    <OutDir Condition="'$(Configuration)|$(Platform)'=='Profile|Win32'">$(Platform)\$(Configuration)\</OutDir>

+    <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(Platform)\$(Configuration)\</IntDir>

+    <IntDir Condition="'$(Configuration)|$(Platform)'=='Profile|Win32'">$(Platform)\$(Configuration)\</IntDir>

+    <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</LinkIncremental>

+    <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Profile|Win32'">false</LinkIncremental>

+    <IncludePath Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">..\include;$(DXSDK_DIR)\Include;$(VCInstallDir)PlatformSDK\include;$(IncludePath)</IncludePath>

+    <IncludePath Condition="'$(Configuration)|$(Platform)'=='Profile|Win32'">..\include;$(DXSDK_DIR)\Include;$(VCInstallDir)PlatformSDK\include;$(IncludePath)</IncludePath>

+    <IncludePath Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">..\include;$(DXSDK_DIR)\Include;$(VCInstallDir)PlatformSDK\include;$(IncludePath)</IncludePath>

+  </PropertyGroup>

+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">

+    <ClCompile>

+      <Optimization>Disabled</Optimization>

+      <AdditionalIncludeDirectories>$(ProjectDir)/..;$(ProjectDir)/../..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>

+      <PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;LIBEGL_EXPORTS;_CRT_SECURE_NO_DEPRECATE;NOMINMAX;%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <MinimalRebuild>true</MinimalRebuild>

+      <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>

+      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>

+      <PrecompiledHeader>

+      </PrecompiledHeader>

+      <WarningLevel>Level3</WarningLevel>

+      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>

+      <BrowseInformation>true</BrowseInformation>

+    </ClCompile>

+    <Link>

+      <AdditionalDependencies>dwmapi.lib;%(AdditionalDependencies)</AdditionalDependencies>

+      <ModuleDefinitionFile>libEGL.def</ModuleDefinitionFile>

+      <DelayLoadDLLs>dwmapi.dll;%(DelayLoadDLLs)</DelayLoadDLLs>

+      <GenerateDebugInformation>true</GenerateDebugInformation>

+      <SubSystem>Windows</SubSystem>

+      <RandomizedBaseAddress>false</RandomizedBaseAddress>

+      <DataExecutionPrevention>

+      </DataExecutionPrevention>

+      <TargetMachine>MachineX86</TargetMachine>

+    </Link>

+    <PostBuildEvent>

+      <Command>mkdir "$(ProjectDir)..\..\lib\$(Configuration)\"

+copy "$(OutDir)libEGL.dll" "$(ProjectDir)..\..\lib\$(Configuration)\"

+copy "$(OutDir)libEGL.lib" "$(ProjectDir)..\..\lib\$(Configuration)\"</Command>

+    </PostBuildEvent>

+  </ItemDefinitionGroup>

+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">

+    <ClCompile>

+      <Optimization>MaxSpeed</Optimization>

+      <InlineFunctionExpansion>AnySuitable</InlineFunctionExpansion>

+      <AdditionalIncludeDirectories>$(ProjectDir)/..;$(ProjectDir)/../..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>

+      <PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;LIBEGL_EXPORTS;_CRT_SECURE_NO_DEPRECATE;NOMINMAX;_SECURE_SCL=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>

+      <PrecompiledHeader>

+      </PrecompiledHeader>

+      <WarningLevel>Level3</WarningLevel>

+      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>

+    </ClCompile>

+    <Link>

+      <AdditionalDependencies>dwmapi.lib;%(AdditionalDependencies)</AdditionalDependencies>

+      <ModuleDefinitionFile>libEGL.def</ModuleDefinitionFile>

+      <DelayLoadDLLs>dwmapi.dll;%(DelayLoadDLLs)</DelayLoadDLLs>

+      <GenerateDebugInformation>true</GenerateDebugInformation>

+      <SubSystem>Windows</SubSystem>

+      <OptimizeReferences>true</OptimizeReferences>

+      <EnableCOMDATFolding>true</EnableCOMDATFolding>

+      <RandomizedBaseAddress>false</RandomizedBaseAddress>

+      <DataExecutionPrevention>

+      </DataExecutionPrevention>

+      <TargetMachine>MachineX86</TargetMachine>

+    </Link>

+    <PostBuildEvent>

+      <Command>mkdir "$(ProjectDir)..\..\lib\$(Configuration)\"

+copy "$(OutDir)libEGL.dll" "$(ProjectDir)..\..\lib\$(Configuration)\"

+copy "$(OutDir)libEGL.lib" "$(ProjectDir)..\..\lib\$(Configuration)\"</Command>

+    </PostBuildEvent>

+  </ItemDefinitionGroup>

+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Profile|Win32'">

+    <ClCompile>

+      <Optimization>MaxSpeed</Optimization>

+      <InlineFunctionExpansion>AnySuitable</InlineFunctionExpansion>

+      <AdditionalIncludeDirectories>$(ProjectDir)/..;$(ProjectDir)/../..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>

+      <PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;LIBEGL_EXPORTS;_CRT_SECURE_NO_DEPRECATE;NOMINMAX;_SECURE_SCL=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>

+      <PrecompiledHeader>

+      </PrecompiledHeader>

+      <WarningLevel>Level3</WarningLevel>

+      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>

+      <OmitFramePointers>false</OmitFramePointers>

+    </ClCompile>

+    <Link>

+      <AdditionalDependencies>dwmapi.lib;%(AdditionalDependencies)</AdditionalDependencies>

+      <ModuleDefinitionFile>libEGL.def</ModuleDefinitionFile>

+      <DelayLoadDLLs>dwmapi.dll;%(DelayLoadDLLs)</DelayLoadDLLs>

+      <GenerateDebugInformation>true</GenerateDebugInformation>

+      <SubSystem>Windows</SubSystem>

+      <OptimizeReferences>true</OptimizeReferences>

+      <EnableCOMDATFolding>true</EnableCOMDATFolding>

+      <RandomizedBaseAddress>false</RandomizedBaseAddress>

+      <DataExecutionPrevention>

+      </DataExecutionPrevention>

+      <TargetMachine>MachineX86</TargetMachine>

+    </Link>

+    <PostBuildEvent>

+      <Command>mkdir "$(ProjectDir)..\..\lib\$(Configuration)\"

+copy "$(OutDir)libEGL.dll" "$(ProjectDir)..\..\lib\$(Configuration)\"

+copy "$(OutDir)libEGL.lib" "$(ProjectDir)..\..\lib\$(Configuration)\"</Command>

+    </PostBuildEvent>

+  </ItemDefinitionGroup>

+  <ItemGroup>

+    <ClCompile Include="Config.cpp" />

+    <ClCompile Include="..\Common\debug.cpp" />

+    <ClCompile Include="Display.cpp" />

+    <ClCompile Include="libEGL.cpp" />

+    <ClCompile Include="main.cpp" />

+    <ClCompile Include="Surface.cpp" />

+  </ItemGroup>

+  <ItemGroup>

+    <ClInclude Include="..\common\debug.h" />

+    <ClInclude Include="..\include\EGL\egl.h" />

+    <ClInclude Include="..\include\EGL\eglext.h" />

+    <ClInclude Include="..\include\EGL\eglplatform.h" />

+    <ClInclude Include="Config.h" />

+    <ClInclude Include="Display.h" />

+    <ClInclude Include="main.h" />

+    <ClInclude Include="resource.h" />

+    <ClInclude Include="Surface.h" />

+  </ItemGroup>

+  <ItemGroup>

+    <None Include="libEGL.def" />

+  </ItemGroup>

+  <ItemGroup>

+    <ResourceCompile Include="libEGL.rc" />

+  </ItemGroup>

+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />

+  <ImportGroup Label="ExtensionTargets">

+  </ImportGroup>

+</Project>
\ No newline at end of file
diff --git a/src/GLES2/libEGL/libEGL.vcxproj.filters b/src/GLES2/libEGL/libEGL.vcxproj.filters
new file mode 100644
index 0000000..44a6a98
--- /dev/null
+++ b/src/GLES2/libEGL/libEGL.vcxproj.filters
@@ -0,0 +1,68 @@
+<?xml version="1.0" encoding="utf-8"?>

+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

+  <ItemGroup>

+    <Filter Include="Source Files">

+      <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>

+      <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>

+    </Filter>

+    <Filter Include="Header Files">

+      <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>

+      <Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>

+    </Filter>

+  </ItemGroup>

+  <ItemGroup>

+    <ClCompile Include="Config.cpp">

+      <Filter>Source Files</Filter>

+    </ClCompile>

+    <ClCompile Include="..\Common\debug.cpp">

+      <Filter>Source Files</Filter>

+    </ClCompile>

+    <ClCompile Include="Display.cpp">

+      <Filter>Source Files</Filter>

+    </ClCompile>

+    <ClCompile Include="libEGL.cpp">

+      <Filter>Source Files</Filter>

+    </ClCompile>

+    <ClCompile Include="main.cpp">

+      <Filter>Source Files</Filter>

+    </ClCompile>

+    <ClCompile Include="Surface.cpp">

+      <Filter>Source Files</Filter>

+    </ClCompile>

+  </ItemGroup>

+  <ItemGroup>

+    <ClInclude Include="Config.h">

+      <Filter>Header Files</Filter>

+    </ClInclude>

+    <ClInclude Include="Display.h">

+      <Filter>Header Files</Filter>

+    </ClInclude>

+    <ClInclude Include="main.h">

+      <Filter>Header Files</Filter>

+    </ClInclude>

+    <ClInclude Include="resource.h">

+      <Filter>Header Files</Filter>

+    </ClInclude>

+    <ClInclude Include="Surface.h">

+      <Filter>Header Files</Filter>

+    </ClInclude>

+    <ClInclude Include="..\include\EGL\egl.h">

+      <Filter>Header Files</Filter>

+    </ClInclude>

+    <ClInclude Include="..\include\EGL\eglext.h">

+      <Filter>Header Files</Filter>

+    </ClInclude>

+    <ClInclude Include="..\include\EGL\eglplatform.h">

+      <Filter>Header Files</Filter>

+    </ClInclude>

+    <ClInclude Include="..\common\debug.h">

+      <Filter>Header Files</Filter>

+    </ClInclude>

+  </ItemGroup>

+  <ItemGroup>

+    <ResourceCompile Include="libEGL.rc" />

+  </ItemGroup>

+  <ItemGroup>

+    <None Include="libEGL.def" />

+  </ItemGroup>

+</Project>
\ No newline at end of file
diff --git a/src/GLES2/libEGL/main.cpp b/src/GLES2/libEGL/main.cpp
new file mode 100644
index 0000000..aeef1ec
--- /dev/null
+++ b/src/GLES2/libEGL/main.cpp
@@ -0,0 +1,248 @@
+// SwiftShader Software Renderer

+//

+// Copyright(c) 2005-2012 TransGaming Inc.

+//

+// All rights reserved. No part of this software may be copied, distributed, transmitted,

+// transcribed, stored in a retrieval system, translated into any human or computer

+// language by any means, or disclosed to third parties without the explicit written

+// agreement of TransGaming Inc. Without such an agreement, no rights or licenses, express

+// or implied, including but not limited to any patent rights, are granted to you.

+//

+

+// main.cpp: DLL entry point and management of thread-local data.

+

+#include "main.h"

+

+#include "Common/Thread.hpp"

+#include "Common/SharedLibrary.hpp"

+#include "common/debug.h"

+

+static sw::Thread::LocalStorageKey currentTLS = TLS_OUT_OF_INDEXES;

+

+#if !defined(_MSC_VER)

+#define CONSTRUCTOR __attribute__((constructor))

+#define DESTRUCTOR __attribute__((destructor))

+#else

+#define CONSTRUCTOR

+#define DESTRUCTOR

+#endif

+

+static void eglAttachThread()

+{

+    TRACE("()");

+

+    egl::Current *current = new egl::Current;

+

+    if(current)

+    {

+        sw::Thread::setLocalStorage(currentTLS, current);

+

+        current->error = EGL_SUCCESS;

+        current->API = EGL_OPENGL_ES_API;

+        current->display = EGL_NO_DISPLAY;

+        current->drawSurface = EGL_NO_SURFACE;

+        current->readSurface = EGL_NO_SURFACE;

+	}

+}

+

+static void eglDetachThread()

+{

+    TRACE("()");

+

+	egl::Current *current = (egl::Current*)sw::Thread::getLocalStorage(currentTLS);

+

+	if(current)

+	{

+        delete current;

+	}

+}

+

+CONSTRUCTOR static bool eglAttachProcess()

+{

+    TRACE("()");

+

+	#if !defined(ANGLE_DISABLE_TRACE)

+        FILE *debug = fopen(TRACE_OUTPUT_FILE, "rt");

+

+        if(debug)

+        {

+            fclose(debug);

+            debug = fopen(TRACE_OUTPUT_FILE, "wt");   // Erase

+            fclose(debug);

+        }

+	#endif

+

+    currentTLS = sw::Thread::allocateLocalStorageKey();

+

+    if(currentTLS == TLS_OUT_OF_INDEXES)

+    {

+        return false;

+    }

+

+	eglAttachThread();

+

+	#if defined(_WIN32)

+	const char *libGLESv2_lib = "libGLESv2.dll";

+	#else

+	const char *libGLESv2_lib = "libGLESv2.so";

+	#endif

+	

+    libGLESv2 = loadLibrary(libGLESv2_lib);

+    gl::createDevice = (gl::Device*(*)())getProcAddress(libGLESv2, "createDevice");

+    gl::createContext = (gl::Context *(*)(const egl::Config*, const gl::Context*))getProcAddress(libGLESv2, "glCreateContext");

+    gl::destroyContext = (void (*)(gl::Context*))getProcAddress(libGLESv2, "glDestroyContext");

+    gl::makeCurrent = (void (*)(gl::Context*, egl::Display*, egl::Surface*))getProcAddress(libGLESv2, "glMakeCurrent");

+    gl::getCurrentContext = (gl::Context *(*)())getProcAddress(libGLESv2, "glGetCurrentContext");

+    gl::getProcAddress = (__eglMustCastToProperFunctionPointerType (*)(const char*))getProcAddress(libGLESv2, "glGetProcAddress");

+    gl::createBackBuffer = (gl::Image *(*)(int, int, const egl::Config*))getProcAddress(libGLESv2, "createBackBuffer");

+    gl::createFrameBuffer = (sw::FrameBuffer *(*)(EGLNativeWindowType, int, int))getProcAddress(libGLESv2, "createFrameBuffer");

+

+	return libGLESv2 != 0;

+}

+

+DESTRUCTOR static void eglDetachProcess()

+{

+    TRACE("()");

+

+	eglDetachThread();

+	sw::Thread::freeLocalStorageKey(currentTLS);

+	freeLibrary(libGLESv2);

+}

+

+#if defined(_WIN32)

+extern "C" BOOL WINAPI DllMain(HINSTANCE instance, DWORD reason, LPVOID reserved)

+{

+    switch(reason)

+    {

+    case DLL_PROCESS_ATTACH:

+        return eglAttachProcess();

+        break;

+    case DLL_THREAD_ATTACH:

+        eglAttachThread();

+        break;

+    case DLL_THREAD_DETACH:

+        eglDetachThread();

+        break;

+    case DLL_PROCESS_DETACH:

+        eglDetachProcess();

+        break;

+    default:

+        break;

+    }

+

+    return TRUE;

+}

+#endif

+

+namespace egl

+{

+void setCurrentError(EGLint error)

+{

+    Current *current = (Current*)sw::Thread::getLocalStorage(currentTLS);

+

+    current->error = error;

+}

+

+EGLint getCurrentError()

+{

+    Current *current = (Current*)sw::Thread::getLocalStorage(currentTLS);

+

+    return current->error;

+}

+

+void setCurrentAPI(EGLenum API)

+{

+    Current *current = (Current*)sw::Thread::getLocalStorage(currentTLS);

+

+    current->API = API;

+}

+

+EGLenum getCurrentAPI()

+{

+    Current *current = (Current*)sw::Thread::getLocalStorage(currentTLS);

+

+    return current->API;

+}

+

+void setCurrentDisplay(EGLDisplay dpy)

+{

+    Current *current = (Current*)sw::Thread::getLocalStorage(currentTLS);

+

+    current->display = dpy;

+}

+

+EGLDisplay getCurrentDisplay()

+{

+    Current *current = (Current*)sw::Thread::getLocalStorage(currentTLS);

+

+    return current->display;

+}

+

+void setCurrentDrawSurface(EGLSurface surface)

+{

+    Current *current = (Current*)sw::Thread::getLocalStorage(currentTLS);

+

+    current->drawSurface = surface;

+}

+

+EGLSurface getCurrentDrawSurface()

+{

+    Current *current = (Current*)sw::Thread::getLocalStorage(currentTLS);

+

+    return current->drawSurface;

+}

+

+void setCurrentReadSurface(EGLSurface surface)

+{

+    Current *current = (Current*)sw::Thread::getLocalStorage(currentTLS);

+

+    current->readSurface = surface;

+}

+

+EGLSurface getCurrentReadSurface()

+{

+    Current *current = (Current*)sw::Thread::getLocalStorage(currentTLS);

+

+    return current->readSurface;

+}

+}

+

+void error(EGLint errorCode)

+{

+    egl::setCurrentError(errorCode);

+

+    switch(errorCode)

+    {

+    case EGL_SUCCESS:                                                                  break;

+    case EGL_NOT_INITIALIZED:     TRACE("\t! Error generated: not initialized\n");     break;

+    case EGL_BAD_ACCESS:          TRACE("\t! Error generated: bad access\n");          break;

+    case EGL_BAD_ALLOC:           TRACE("\t! Error generated: bad alloc\n");           break;

+    case EGL_BAD_ATTRIBUTE:       TRACE("\t! Error generated: bad attribute\n");       break;

+    case EGL_BAD_CONFIG:          TRACE("\t! Error generated: bad config\n");          break;

+    case EGL_BAD_CONTEXT:         TRACE("\t! Error generated: bad context\n");         break;

+    case EGL_BAD_CURRENT_SURFACE: TRACE("\t! Error generated: bad current surface\n"); break;

+    case EGL_BAD_DISPLAY:         TRACE("\t! Error generated: bad display\n");         break;

+    case EGL_BAD_MATCH:           TRACE("\t! Error generated: bad match\n");           break;

+    case EGL_BAD_NATIVE_PIXMAP:   TRACE("\t! Error generated: bad native pixmap\n");   break;

+    case EGL_BAD_NATIVE_WINDOW:   TRACE("\t! Error generated: bad native window\n");   break;

+    case EGL_BAD_PARAMETER:       TRACE("\t! Error generated: bad parameter\n");       break;

+    case EGL_BAD_SURFACE:         TRACE("\t! Error generated: bad surface\n");         break;

+    case EGL_CONTEXT_LOST:        TRACE("\t! Error generated: context lost\n");        break;

+    default:                      TRACE("\t! Error generated: <0x%X>\n", errorCode);   break;

+    }

+}

+

+namespace gl

+{

+	Device *(*createDevice)() = 0;

+	Context *(*createContext)(const egl::Config *config, const Context *shareContext) = 0;

+	void (*destroyContext)(Context *context) = 0;

+	void (*bindTexImage)(egl::Surface *surface) = 0;

+	void (*makeCurrent)(Context *context, egl::Display *display, egl::Surface *surface) = 0;

+	Context *(*getCurrentContext)() = 0;

+	__eglMustCastToProperFunctionPointerType (*getProcAddress)(const char *procname) = 0;

+	Image *(*createBackBuffer)(int width, int height, const egl::Config *config) = 0;

+	sw::FrameBuffer *(*createFrameBuffer)(EGLNativeWindowType window, int width, int height) = 0;

+}

+

+void *libGLESv2 = 0;   // Handle to the libGLESv2 module
\ No newline at end of file
diff --git a/src/GLES2/libEGL/main.h b/src/GLES2/libEGL/main.h
new file mode 100644
index 0000000..b8995db
--- /dev/null
+++ b/src/GLES2/libEGL/main.h
@@ -0,0 +1,98 @@
+// SwiftShader Software Renderer
+//
+// Copyright(c) 2005-2012 TransGaming Inc.
+//
+// All rights reserved. No part of this software may be copied, distributed, transmitted,
+// transcribed, stored in a retrieval system, translated into any human or computer
+// language by any means, or disclosed to third parties without the explicit written
+// agreement of TransGaming Inc. Without such an agreement, no rights or licenses, express
+// or implied, including but not limited to any patent rights, are granted to you.
+//
+
+// main.h: Management of thread-local data.
+
+#ifndef LIBEGL_MAIN_H_
+#define LIBEGL_MAIN_H_
+
+#define EGLAPI
+#include <EGL/egl.h>
+#include <EGL/eglext.h>
+
+namespace egl
+{
+	struct Current
+	{
+		EGLint error;
+		EGLenum API;
+		EGLDisplay display;
+		EGLSurface drawSurface;
+		EGLSurface readSurface;
+	};
+
+	void setCurrentError(EGLint error);
+	EGLint getCurrentError();
+
+	void setCurrentAPI(EGLenum API);
+	EGLenum getCurrentAPI();
+
+	void setCurrentDisplay(EGLDisplay dpy);
+	EGLDisplay getCurrentDisplay();
+
+	void setCurrentDrawSurface(EGLSurface surface);
+	EGLSurface getCurrentDrawSurface();
+
+	void setCurrentReadSurface(EGLSurface surface);
+	EGLSurface getCurrentReadSurface();
+}
+
+void error(EGLint errorCode);
+
+template<class T>
+const T &error(EGLint errorCode, const T &returnValue)
+{
+    error(errorCode);
+
+    return returnValue;
+}
+
+template<class T>
+const T &success(const T &returnValue)
+{
+    egl::setCurrentError(EGL_SUCCESS);
+
+    return returnValue;
+}
+
+namespace egl
+{
+	class Config;
+	class Surface;
+	class Display;
+}
+
+namespace sw
+{
+	class FrameBuffer;
+}
+
+// libGLESv2 dependencies
+namespace gl
+{
+	class Device;
+	class Context;
+	class Image;
+
+	extern Device *(*createDevice)();
+	extern Context *(*createContext)(const egl::Config *config, const Context *shareContext);
+	extern void (*destroyContext)(Context *context);
+	extern void (*bindTexImage)(egl::Surface *surface);
+	extern void (*makeCurrent)(Context *context, egl::Display *display, egl::Surface *surface);
+	extern Context *(*getCurrentContext)();
+	extern __eglMustCastToProperFunctionPointerType (*getProcAddress)(const char *procname);
+	extern Image *(*createBackBuffer)(int width, int height, const egl::Config *config);
+	extern sw::FrameBuffer *(*createFrameBuffer)(EGLNativeWindowType window, int width, int height);
+}
+
+extern void *libGLESv2;   // Handle to the libGLESv2 module
+
+#endif  // LIBEGL_MAIN_H_
diff --git a/src/GLES2/libEGL/resource.h b/src/GLES2/libEGL/resource.h
new file mode 100644
index 0000000..3921f4c
--- /dev/null
+++ b/src/GLES2/libEGL/resource.h
@@ -0,0 +1,14 @@
+//{{NO_DEPENDENCIES}}
+// Microsoft Visual C++ generated include file.
+// Used by libEGL.rc
+
+// Next default values for new objects
+// 
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NEXT_RESOURCE_VALUE        101
+#define _APS_NEXT_COMMAND_VALUE         40001
+#define _APS_NEXT_CONTROL_VALUE         1001
+#define _APS_NEXT_SYMED_VALUE           101
+#endif
+#endif
diff --git a/src/GLES2/libGLESv2/Buffer.cpp b/src/GLES2/libGLESv2/Buffer.cpp
new file mode 100644
index 0000000..e98d8eb
--- /dev/null
+++ b/src/GLES2/libGLESv2/Buffer.cpp
@@ -0,0 +1,88 @@
+// SwiftShader Software Renderer
+//
+// Copyright(c) 2005-2013 TransGaming Inc.
+//
+// All rights reserved. No part of this software may be copied, distributed, transmitted,
+// transcribed, stored in a retrieval system, translated into any human or computer
+// language by any means, or disclosed to third parties without the explicit written
+// agreement of TransGaming Inc. Without such an agreement, no rights or licenses, express
+// or implied, including but not limited to any patent rights, are granted to you.
+//
+
+// Buffer.cpp: Implements the Buffer class, representing storage of vertex and/or
+// index data. Implements GL buffer objects and related functionality.
+// [OpenGL ES 2.0.24] section 2.9 page 21.
+
+#include "Buffer.h"
+
+#include "main.h"
+#include "VertexDataManager.h"
+#include "IndexDataManager.h"
+
+namespace gl
+{
+
+Buffer::Buffer(GLuint id) : RefCountObject(id)
+{
+    mContents = 0;
+    mSize = 0;
+    mUsage = GL_DYNAMIC_DRAW;
+}
+
+Buffer::~Buffer()
+{
+    if(mContents)
+	{
+		mContents->destruct();
+	}
+}
+
+void Buffer::bufferData(const void *data, GLsizeiptr size, GLenum usage)
+{
+	if(mContents)
+	{
+		mContents->destruct();
+		mContents = 0;
+	}
+
+	mSize = size;
+	mUsage = usage;
+
+	if(size > 0)
+	{
+		const int padding = 1024;   // For SIMD processing of vertices
+		mContents = new sw::Resource(size + padding);
+
+		if(!mContents)
+		{
+			return error(GL_OUT_OF_MEMORY);
+		}
+
+		if(data)
+		{
+			memcpy((void*)mContents->getBuffer(), data, size);
+			memset((char*)mContents->getBuffer() + size, 0, padding);
+		}
+		else
+		{
+			memset((void*)mContents->getBuffer(), 0, size + padding);
+		}
+	}
+}
+
+void Buffer::bufferSubData(const void *data, GLsizeiptr size, GLintptr offset)
+{
+	if(mContents)
+	{
+		char *buffer = (char*)mContents->lock(sw::PUBLIC);
+		memcpy(buffer + offset, data, size);
+		mContents->unlock();
+	}
+}
+
+sw::Resource *Buffer::getResource()
+{
+	return mContents;
+}
+
+}
diff --git a/src/GLES2/libGLESv2/Buffer.h b/src/GLES2/libGLESv2/Buffer.h
new file mode 100644
index 0000000..91580e6
--- /dev/null
+++ b/src/GLES2/libGLESv2/Buffer.h
@@ -0,0 +1,54 @@
+// SwiftShader Software Renderer

+//

+// Copyright(c) 2005-2012 TransGaming Inc.

+//

+// All rights reserved. No part of this software may be copied, distributed, transmitted,

+// transcribed, stored in a retrieval system, translated into any human or computer

+// language by any means, or disclosed to third parties without the explicit written

+// agreement of TransGaming Inc. Without such an agreement, no rights or licenses, express

+// or implied, including but not limited to any patent rights, are granted to you.

+//

+

+// Buffer.h: Defines the Buffer class, representing storage of vertex and/or

+// index data. Implements GL buffer objects and related functionality.

+// [OpenGL ES 2.0.24] section 2.9 page 21.

+

+#ifndef LIBGLESV2_BUFFER_H_

+#define LIBGLESV2_BUFFER_H_

+

+#include "RefCountObject.h"

+#include "Common/Resource.hpp"

+

+#define GL_APICALL

+#include <GLES2/gl2.h>

+

+#include <cstddef>

+#include <vector>

+

+namespace gl

+{

+class Buffer : public RefCountObject

+{

+  public:

+    explicit Buffer(GLuint id);

+

+    virtual ~Buffer();

+

+    void bufferData(const void *data, GLsizeiptr size, GLenum usage);

+    void bufferSubData(const void *data, GLsizeiptr size, GLintptr offset);

+

+	const void *data() { return mContents ? mContents->getBuffer() : 0; }

+    size_t size() const { return mSize; }

+    GLenum usage() const { return mUsage; }

+

+	sw::Resource *getResource();

+

+  private:

+    sw::Resource *mContents;

+    size_t mSize;

+    GLenum mUsage;

+};

+

+}

+

+#endif   // LIBGLESV2_BUFFER_H_

diff --git a/src/GLES2/libGLESv2/Context.cpp b/src/GLES2/libGLESv2/Context.cpp
new file mode 100644
index 0000000..445962c
--- /dev/null
+++ b/src/GLES2/libGLESv2/Context.cpp
@@ -0,0 +1,3075 @@
+// SwiftShader Software Renderer

+//

+// Copyright(c) 2005-2013 TransGaming Inc.

+//

+// All rights reserved. No part of this software may be copied, distributed, transmitted,

+// transcribed, stored in a retrieval system, translated into any human or computer

+// language by any means, or disclosed to third parties without the explicit written

+// agreement of TransGaming Inc. Without such an agreement, no rights or licenses, express

+// or implied, including but not limited to any patent rights, are granted to you.

+//

+

+// Context.cpp: Implements the gl::Context class, managing all GL state and performing

+// rendering operations. It is the GLES2 specific implementation of EGLContext.

+

+#include "Context.h"

+

+#include "main.h"

+#include "mathutil.h"

+#include "utilities.h"

+#include "ResourceManager.h"

+#include "Buffer.h"

+#include "Fence.h"

+#include "Framebuffer.h"

+#include "Program.h"

+#include "Query.h"

+#include "Renderbuffer.h"

+#include "Shader.h"

+#include "Texture.h"

+#include "VertexDataManager.h"

+#include "IndexDataManager.h"

+#include "libEGL/Display.h"

+#include "Common/Half.hpp"

+

+#undef near

+#undef far

+

+namespace gl

+{

+Context::Context(const egl::Config *config, const Context *shareContext) : mConfig(config)

+{

+    mFenceHandleAllocator.setBaseHandle(0);

+

+    setClearColor(0.0f, 0.0f, 0.0f, 0.0f);

+

+    mState.depthClearValue = 1.0f;

+    mState.stencilClearValue = 0;

+

+    mState.cullFace = false;

+    mState.cullMode = GL_BACK;

+    mState.frontFace = GL_CCW;

+    mState.depthTest = false;

+    mState.depthFunc = GL_LESS;

+    mState.blend = false;

+    mState.sourceBlendRGB = GL_ONE;

+    mState.sourceBlendAlpha = GL_ONE;

+    mState.destBlendRGB = GL_ZERO;

+    mState.destBlendAlpha = GL_ZERO;

+    mState.blendEquationRGB = GL_FUNC_ADD;

+    mState.blendEquationAlpha = GL_FUNC_ADD;

+    mState.blendColor.red = 0;

+    mState.blendColor.green = 0;

+    mState.blendColor.blue = 0;

+    mState.blendColor.alpha = 0;

+    mState.stencilTest = false;

+    mState.stencilFunc = GL_ALWAYS;

+    mState.stencilRef = 0;

+    mState.stencilMask = -1;

+    mState.stencilWritemask = -1;

+    mState.stencilBackFunc = GL_ALWAYS;

+    mState.stencilBackRef = 0;

+    mState.stencilBackMask = - 1;

+    mState.stencilBackWritemask = -1;

+    mState.stencilFail = GL_KEEP;

+    mState.stencilPassDepthFail = GL_KEEP;

+    mState.stencilPassDepthPass = GL_KEEP;

+    mState.stencilBackFail = GL_KEEP;

+    mState.stencilBackPassDepthFail = GL_KEEP;

+    mState.stencilBackPassDepthPass = GL_KEEP;

+    mState.polygonOffsetFill = false;

+    mState.polygonOffsetFactor = 0.0f;

+    mState.polygonOffsetUnits = 0.0f;

+    mState.sampleAlphaToCoverage = false;

+    mState.sampleCoverage = false;

+    mState.sampleCoverageValue = 1.0f;

+    mState.sampleCoverageInvert = false;

+    mState.scissorTest = false;

+    mState.dither = true;

+    mState.generateMipmapHint = GL_DONT_CARE;

+    mState.fragmentShaderDerivativeHint = GL_DONT_CARE;

+

+    mState.lineWidth = 1.0f;

+

+    mState.viewportX = 0;

+    mState.viewportY = 0;

+    mState.viewportWidth = config->mDisplayMode.width;

+    mState.viewportHeight = config->mDisplayMode.height;

+    mState.zNear = 0.0f;

+    mState.zFar = 1.0f;

+

+    mState.scissorX = 0;

+    mState.scissorY = 0;

+    mState.scissorWidth = config->mDisplayMode.width;

+    mState.scissorHeight = config->mDisplayMode.height;

+

+    mState.colorMaskRed = true;

+    mState.colorMaskGreen = true;

+    mState.colorMaskBlue = true;

+    mState.colorMaskAlpha = true;

+    mState.depthMask = true;

+

+    if(shareContext != NULL)

+    {

+        mResourceManager = shareContext->mResourceManager;

+        mResourceManager->addRef();

+    }

+    else

+    {

+        mResourceManager = new ResourceManager();

+    }

+

+    // [OpenGL ES 2.0.24] section 3.7 page 83:

+    // In the initial state, TEXTURE_2D and TEXTURE_CUBE_MAP have twodimensional

+    // and cube map texture state vectors respectively associated with them.

+    // In order that access to these initial textures not be lost, they are treated as texture

+    // objects all of whose names are 0.

+

+    mTexture2DZero.set(new Texture2D(0));

+    mTextureCubeMapZero.set(new TextureCubeMap(0));

+

+    mState.activeSampler = 0;

+    bindArrayBuffer(0);

+    bindElementArrayBuffer(0);

+    bindTextureCubeMap(0);

+    bindTexture2D(0);

+    bindReadFramebuffer(0);

+    bindDrawFramebuffer(0);

+    bindRenderbuffer(0);

+

+    mState.currentProgram = 0;

+

+    mState.packAlignment = 4;

+    mState.unpackAlignment = 4;

+

+    mVertexDataManager = NULL;

+    mIndexDataManager = NULL;

+

+    mInvalidEnum = false;

+    mInvalidValue = false;

+    mInvalidOperation = false;

+    mOutOfMemory = false;

+    mInvalidFramebufferOperation = false;

+

+    mHasBeenCurrent = false;

+

+    markAllStateDirty();

+}

+

+Context::~Context()

+{

+    if(mState.currentProgram != 0)

+    {

+        Program *programObject = mResourceManager->getProgram(mState.currentProgram);

+        if(programObject)

+        {

+            programObject->release();

+        }

+        mState.currentProgram = 0;

+    }

+

+    while(!mFramebufferMap.empty())

+    {

+        deleteFramebuffer(mFramebufferMap.begin()->first);

+    }

+

+    while(!mFenceMap.empty())

+    {

+        deleteFence(mFenceMap.begin()->first);

+    }

+

+	while(!mQueryMap.empty())

+    {

+        deleteQuery(mQueryMap.begin()->first);

+    }

+

+    for(int type = 0; type < TEXTURE_TYPE_COUNT; type++)

+    {

+        for(int sampler = 0; sampler < MAX_COMBINED_TEXTURE_IMAGE_UNITS; sampler++)

+        {

+            mState.samplerTexture[type][sampler].set(NULL);

+        }

+    }

+

+    for(int i = 0; i < MAX_VERTEX_ATTRIBS; i++)

+    {

+        mState.vertexAttribute[i].mBoundBuffer.set(NULL);

+    }

+

+	for(int i = 0; i < QUERY_TYPE_COUNT; i++)

+    {

+        mState.activeQuery[i].set(NULL);

+    }

+

+    mState.arrayBuffer.set(NULL);

+    mState.elementArrayBuffer.set(NULL);

+    mState.renderbuffer.set(NULL);

+

+    mTexture2DZero.set(NULL);

+    mTextureCubeMapZero.set(NULL);

+

+    delete mVertexDataManager;

+    delete mIndexDataManager;

+

+    mResourceManager->release();

+}

+

+void Context::makeCurrent(egl::Display *display, egl::Surface *surface)

+{

+    Device *device = display->getDevice();

+

+    if(!mHasBeenCurrent)

+    {

+        mVertexDataManager = new VertexDataManager(this);

+        mIndexDataManager = new IndexDataManager();

+

+        const sw::Format renderBufferFormats[] =

+        {

+            sw::FORMAT_A8R8G8B8,

+            sw::FORMAT_X8R8G8B8,

+            sw::FORMAT_R5G6B5,

+            sw::FORMAT_D24S8

+        };

+

+        initExtensionString();

+

+        mState.viewportX = 0;

+        mState.viewportY = 0;

+        mState.viewportWidth = surface->getWidth();

+        mState.viewportHeight = surface->getHeight();

+

+        mState.scissorX = 0;

+        mState.scissorY = 0;

+        mState.scissorWidth = surface->getWidth();

+        mState.scissorHeight = surface->getHeight();

+

+        mHasBeenCurrent = true;

+    }

+

+    // Wrap the existing resources into GL objects and assign them to the '0' names

+    Image *defaultRenderTarget = surface->getRenderTarget();

+    Image *depthStencil = surface->getDepthStencil();

+

+    Colorbuffer *colorbufferZero = new Colorbuffer(defaultRenderTarget);

+    DepthStencilbuffer *depthStencilbufferZero = new DepthStencilbuffer(depthStencil);

+    Framebuffer *framebufferZero = new DefaultFramebuffer(colorbufferZero, depthStencilbufferZero);

+

+    setFramebufferZero(framebufferZero);

+

+    if(defaultRenderTarget)

+    {

+        defaultRenderTarget->release();

+    }

+

+    if(depthStencil)

+    {

+        depthStencil->release();

+    }

+    

+    markAllStateDirty();

+}

+

+// This function will set all of the state-related dirty flags, so that all state is set during next pre-draw.

+void Context::markAllStateDirty()

+{

+    mAppliedProgramSerial = 0;

+

+    mDepthStateDirty = true;

+    mMaskStateDirty = true;

+    mBlendStateDirty = true;

+    mStencilStateDirty = true;

+    mPolygonOffsetStateDirty = true;

+    mSampleStateDirty = true;

+    mDitherStateDirty = true;

+    mFrontFaceDirty = true;

+}

+

+void Context::setClearColor(float red, float green, float blue, float alpha)

+{

+    mState.colorClearValue.red = red;

+    mState.colorClearValue.green = green;

+    mState.colorClearValue.blue = blue;

+    mState.colorClearValue.alpha = alpha;

+}

+

+void Context::setClearDepth(float depth)

+{

+    mState.depthClearValue = depth;

+}

+

+void Context::setClearStencil(int stencil)

+{

+    mState.stencilClearValue = stencil;

+}

+

+void Context::setCullFace(bool enabled)

+{

+    mState.cullFace = enabled;

+}

+

+bool Context::isCullFaceEnabled() const

+{

+    return mState.cullFace;

+}

+

+void Context::setCullMode(GLenum mode)

+{

+   mState.cullMode = mode;

+}

+

+void Context::setFrontFace(GLenum front)

+{

+    if(mState.frontFace != front)

+    {

+        mState.frontFace = front;

+        mFrontFaceDirty = true;

+    }

+}

+

+void Context::setDepthTest(bool enabled)

+{

+    if(mState.depthTest != enabled)

+    {

+        mState.depthTest = enabled;

+        mDepthStateDirty = true;

+    }

+}

+

+bool Context::isDepthTestEnabled() const

+{

+    return mState.depthTest;

+}

+

+void Context::setDepthFunc(GLenum depthFunc)

+{

+    if(mState.depthFunc != depthFunc)

+    {

+        mState.depthFunc = depthFunc;

+        mDepthStateDirty = true;

+    }

+}

+

+void Context::setDepthRange(float zNear, float zFar)

+{

+    mState.zNear = zNear;

+    mState.zFar = zFar;

+}

+

+void Context::setBlend(bool enabled)

+{

+    if(mState.blend != enabled)

+    {

+        mState.blend = enabled;

+        mBlendStateDirty = true;

+    }

+}

+

+bool Context::isBlendEnabled() const

+{

+    return mState.blend;

+}

+

+void Context::setBlendFactors(GLenum sourceRGB, GLenum destRGB, GLenum sourceAlpha, GLenum destAlpha)

+{

+    if(mState.sourceBlendRGB != sourceRGB ||

+       mState.sourceBlendAlpha != sourceAlpha ||

+       mState.destBlendRGB != destRGB ||

+       mState.destBlendAlpha != destAlpha)

+    {

+        mState.sourceBlendRGB = sourceRGB;

+        mState.destBlendRGB = destRGB;

+        mState.sourceBlendAlpha = sourceAlpha;

+        mState.destBlendAlpha = destAlpha;

+        mBlendStateDirty = true;

+    }

+}

+

+void Context::setBlendColor(float red, float green, float blue, float alpha)

+{

+    if(mState.blendColor.red != red ||

+       mState.blendColor.green != green ||

+       mState.blendColor.blue != blue ||

+       mState.blendColor.alpha != alpha)

+    {

+        mState.blendColor.red = red;

+        mState.blendColor.green = green;

+        mState.blendColor.blue = blue;

+        mState.blendColor.alpha = alpha;

+        mBlendStateDirty = true;

+    }

+}

+

+void Context::setBlendEquation(GLenum rgbEquation, GLenum alphaEquation)

+{

+    if(mState.blendEquationRGB != rgbEquation ||

+       mState.blendEquationAlpha != alphaEquation)

+    {

+        mState.blendEquationRGB = rgbEquation;

+        mState.blendEquationAlpha = alphaEquation;

+        mBlendStateDirty = true;

+    }

+}

+

+void Context::setStencilTest(bool enabled)

+{

+    if(mState.stencilTest != enabled)

+    {

+        mState.stencilTest = enabled;

+        mStencilStateDirty = true;

+    }

+}

+

+bool Context::isStencilTestEnabled() const

+{

+    return mState.stencilTest;

+}

+

+void Context::setStencilParams(GLenum stencilFunc, GLint stencilRef, GLuint stencilMask)

+{

+    if(mState.stencilFunc != stencilFunc ||

+        mState.stencilRef != stencilRef ||

+        mState.stencilMask != stencilMask)

+    {

+        mState.stencilFunc = stencilFunc;

+        mState.stencilRef = (stencilRef > 0) ? stencilRef : 0;

+        mState.stencilMask = stencilMask;

+        mStencilStateDirty = true;

+    }

+}

+

+void Context::setStencilBackParams(GLenum stencilBackFunc, GLint stencilBackRef, GLuint stencilBackMask)

+{

+    if(mState.stencilBackFunc != stencilBackFunc ||

+        mState.stencilBackRef != stencilBackRef ||

+        mState.stencilBackMask != stencilBackMask)

+    {

+        mState.stencilBackFunc = stencilBackFunc;

+        mState.stencilBackRef = (stencilBackRef > 0) ? stencilBackRef : 0;

+        mState.stencilBackMask = stencilBackMask;

+        mStencilStateDirty = true;

+    }

+}

+

+void Context::setStencilWritemask(GLuint stencilWritemask)

+{

+    if(mState.stencilWritemask != stencilWritemask)

+    {

+        mState.stencilWritemask = stencilWritemask;

+        mStencilStateDirty = true;

+    }

+}

+

+void Context::setStencilBackWritemask(GLuint stencilBackWritemask)

+{

+    if(mState.stencilBackWritemask != stencilBackWritemask)

+    {

+        mState.stencilBackWritemask = stencilBackWritemask;

+        mStencilStateDirty = true;

+    }

+}

+

+void Context::setStencilOperations(GLenum stencilFail, GLenum stencilPassDepthFail, GLenum stencilPassDepthPass)

+{

+    if(mState.stencilFail != stencilFail ||

+        mState.stencilPassDepthFail != stencilPassDepthFail ||

+        mState.stencilPassDepthPass != stencilPassDepthPass)

+    {

+        mState.stencilFail = stencilFail;

+        mState.stencilPassDepthFail = stencilPassDepthFail;

+        mState.stencilPassDepthPass = stencilPassDepthPass;

+        mStencilStateDirty = true;

+    }

+}

+

+void Context::setStencilBackOperations(GLenum stencilBackFail, GLenum stencilBackPassDepthFail, GLenum stencilBackPassDepthPass)

+{

+    if(mState.stencilBackFail != stencilBackFail ||

+        mState.stencilBackPassDepthFail != stencilBackPassDepthFail ||

+        mState.stencilBackPassDepthPass != stencilBackPassDepthPass)

+    {

+        mState.stencilBackFail = stencilBackFail;

+        mState.stencilBackPassDepthFail = stencilBackPassDepthFail;

+        mState.stencilBackPassDepthPass = stencilBackPassDepthPass;

+        mStencilStateDirty = true;

+    }

+}

+

+void Context::setPolygonOffsetFill(bool enabled)

+{

+    if(mState.polygonOffsetFill != enabled)

+    {

+        mState.polygonOffsetFill = enabled;

+        mPolygonOffsetStateDirty = true;

+    }

+}

+

+bool Context::isPolygonOffsetFillEnabled() const

+{

+    return mState.polygonOffsetFill;

+

+}

+

+void Context::setPolygonOffsetParams(GLfloat factor, GLfloat units)

+{

+    if(mState.polygonOffsetFactor != factor ||

+        mState.polygonOffsetUnits != units)

+    {

+        mState.polygonOffsetFactor = factor;

+        mState.polygonOffsetUnits = units;

+        mPolygonOffsetStateDirty = true;

+    }

+}

+

+void Context::setSampleAlphaToCoverage(bool enabled)

+{

+    if(mState.sampleAlphaToCoverage != enabled)

+    {

+        mState.sampleAlphaToCoverage = enabled;

+        mSampleStateDirty = true;

+    }

+}

+

+bool Context::isSampleAlphaToCoverageEnabled() const

+{

+    return mState.sampleAlphaToCoverage;

+}

+

+void Context::setSampleCoverage(bool enabled)

+{

+    if(mState.sampleCoverage != enabled)

+    {

+        mState.sampleCoverage = enabled;

+        mSampleStateDirty = true;

+    }

+}

+

+bool Context::isSampleCoverageEnabled() const

+{

+    return mState.sampleCoverage;

+}

+

+void Context::setSampleCoverageParams(GLclampf value, bool invert)

+{

+    if(mState.sampleCoverageValue != value ||

+        mState.sampleCoverageInvert != invert)

+    {

+        mState.sampleCoverageValue = value;

+        mState.sampleCoverageInvert = invert;

+        mSampleStateDirty = true;

+    }

+}

+

+void Context::setScissorTest(bool enabled)

+{

+    mState.scissorTest = enabled;

+}

+

+bool Context::isScissorTestEnabled() const

+{

+    return mState.scissorTest;

+}

+

+void Context::setDither(bool enabled)

+{

+    if(mState.dither != enabled)

+    {

+        mState.dither = enabled;

+        mDitherStateDirty = true;

+    }

+}

+

+bool Context::isDitherEnabled() const

+{

+    return mState.dither;

+}

+

+void Context::setLineWidth(GLfloat width)

+{

+    mState.lineWidth = width;

+}

+

+void Context::setGenerateMipmapHint(GLenum hint)

+{

+    mState.generateMipmapHint = hint;

+}

+

+void Context::setFragmentShaderDerivativeHint(GLenum hint)

+{

+    mState.fragmentShaderDerivativeHint = hint;

+    // TODO: Propagate the hint to shader translator so we can write

+    // ddx, ddx_coarse, or ddx_fine depending on the hint.

+    // Ignore for now. It is valid for implementations to ignore hint.

+}

+

+void Context::setViewportParams(GLint x, GLint y, GLsizei width, GLsizei height)

+{

+    mState.viewportX = x;

+    mState.viewportY = y;

+    mState.viewportWidth = width;

+    mState.viewportHeight = height;

+}

+

+void Context::setScissorParams(GLint x, GLint y, GLsizei width, GLsizei height)

+{

+    mState.scissorX = x;

+    mState.scissorY = y;

+    mState.scissorWidth = width;

+    mState.scissorHeight = height;

+}

+

+void Context::setColorMask(bool red, bool green, bool blue, bool alpha)

+{

+    if(mState.colorMaskRed != red || mState.colorMaskGreen != green ||

+       mState.colorMaskBlue != blue || mState.colorMaskAlpha != alpha)

+    {

+        mState.colorMaskRed = red;

+        mState.colorMaskGreen = green;

+        mState.colorMaskBlue = blue;

+        mState.colorMaskAlpha = alpha;

+        mMaskStateDirty = true;

+    }

+}

+

+void Context::setDepthMask(bool mask)

+{

+    if(mState.depthMask != mask)

+    {

+        mState.depthMask = mask;

+        mMaskStateDirty = true;

+    }

+}

+

+void Context::setActiveSampler(unsigned int active)

+{

+    mState.activeSampler = active;

+}

+

+GLuint Context::getReadFramebufferHandle() const

+{

+    return mState.readFramebuffer;

+}

+

+GLuint Context::getDrawFramebufferHandle() const

+{

+    return mState.drawFramebuffer;

+}

+

+GLuint Context::getRenderbufferHandle() const

+{

+    return mState.renderbuffer.id();

+}

+

+GLuint Context::getArrayBufferHandle() const

+{

+    return mState.arrayBuffer.id();

+}

+

+GLuint Context::getActiveQuery(GLenum target) const

+{

+    Query *queryObject = NULL;

+    

+    switch(target)

+    {

+    case GL_ANY_SAMPLES_PASSED_EXT:

+        queryObject = mState.activeQuery[QUERY_ANY_SAMPLES_PASSED].get();

+        break;

+    case GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT:

+        queryObject = mState.activeQuery[QUERY_ANY_SAMPLES_PASSED_CONSERVATIVE].get();

+        break;

+    default:

+        ASSERT(false);

+    }

+

+    if(queryObject)

+    {

+        return queryObject->id();

+    }

+    

+	return 0;

+}

+

+void Context::setEnableVertexAttribArray(unsigned int attribNum, bool enabled)

+{

+    mState.vertexAttribute[attribNum].mArrayEnabled = enabled;

+}

+

+const VertexAttribute &Context::getVertexAttribState(unsigned int attribNum)

+{

+    return mState.vertexAttribute[attribNum];

+}

+

+void Context::setVertexAttribState(unsigned int attribNum, Buffer *boundBuffer, GLint size, GLenum type, bool normalized,

+                                   GLsizei stride, const void *pointer)

+{

+    mState.vertexAttribute[attribNum].mBoundBuffer.set(boundBuffer);

+    mState.vertexAttribute[attribNum].mSize = size;

+    mState.vertexAttribute[attribNum].mType = type;

+    mState.vertexAttribute[attribNum].mNormalized = normalized;

+    mState.vertexAttribute[attribNum].mStride = stride;

+    mState.vertexAttribute[attribNum].mPointer = pointer;

+}

+

+const void *Context::getVertexAttribPointer(unsigned int attribNum) const

+{

+    return mState.vertexAttribute[attribNum].mPointer;

+}

+

+const VertexAttributeArray &Context::getVertexAttributes()

+{

+    return mState.vertexAttribute;

+}

+

+void Context::setPackAlignment(GLint alignment)

+{

+    mState.packAlignment = alignment;

+}

+

+GLint Context::getPackAlignment() const

+{

+    return mState.packAlignment;

+}

+

+void Context::setUnpackAlignment(GLint alignment)

+{

+    mState.unpackAlignment = alignment;

+}

+

+GLint Context::getUnpackAlignment() const

+{

+    return mState.unpackAlignment;

+}

+

+GLuint Context::createBuffer()

+{

+    return mResourceManager->createBuffer();

+}

+

+GLuint Context::createProgram()

+{

+    return mResourceManager->createProgram();

+}

+

+GLuint Context::createShader(GLenum type)

+{

+    return mResourceManager->createShader(type);

+}

+

+GLuint Context::createTexture()

+{

+    return mResourceManager->createTexture();

+}

+

+GLuint Context::createRenderbuffer()

+{

+    return mResourceManager->createRenderbuffer();

+}

+

+// Returns an unused framebuffer name

+GLuint Context::createFramebuffer()

+{

+    GLuint handle = mFramebufferHandleAllocator.allocate();

+

+    mFramebufferMap[handle] = NULL;

+

+    return handle;

+}

+

+GLuint Context::createFence()

+{

+    GLuint handle = mFenceHandleAllocator.allocate();

+

+    mFenceMap[handle] = new Fence;

+

+    return handle;

+}

+

+// Returns an unused query name

+GLuint Context::createQuery()

+{

+    GLuint handle = mQueryHandleAllocator.allocate();

+

+    mQueryMap[handle] = NULL;

+

+    return handle;

+}

+

+void Context::deleteBuffer(GLuint buffer)

+{

+    if(mResourceManager->getBuffer(buffer))

+    {

+        detachBuffer(buffer);

+    }

+    

+    mResourceManager->deleteBuffer(buffer);

+}

+

+void Context::deleteShader(GLuint shader)

+{

+    mResourceManager->deleteShader(shader);

+}

+

+void Context::deleteProgram(GLuint program)

+{

+    mResourceManager->deleteProgram(program);

+}

+

+void Context::deleteTexture(GLuint texture)

+{

+    if(mResourceManager->getTexture(texture))

+    {

+        detachTexture(texture);

+    }

+

+    mResourceManager->deleteTexture(texture);

+}

+

+void Context::deleteRenderbuffer(GLuint renderbuffer)

+{

+    if(mResourceManager->getRenderbuffer(renderbuffer))

+    {

+        detachRenderbuffer(renderbuffer);

+    }

+    

+    mResourceManager->deleteRenderbuffer(renderbuffer);

+}

+

+void Context::deleteFramebuffer(GLuint framebuffer)

+{

+    FramebufferMap::iterator framebufferObject = mFramebufferMap.find(framebuffer);

+

+    if(framebufferObject != mFramebufferMap.end())

+    {

+        detachFramebuffer(framebuffer);

+

+        mFramebufferHandleAllocator.release(framebufferObject->first);

+        delete framebufferObject->second;

+        mFramebufferMap.erase(framebufferObject);

+    }

+}

+

+void Context::deleteFence(GLuint fence)

+{

+    FenceMap::iterator fenceObject = mFenceMap.find(fence);

+

+    if(fenceObject != mFenceMap.end())

+    {

+        mFenceHandleAllocator.release(fenceObject->first);

+        delete fenceObject->second;

+        mFenceMap.erase(fenceObject);

+    }

+}

+

+void Context::deleteQuery(GLuint query)

+{

+    QueryMap::iterator queryObject = mQueryMap.find(query);

+    

+	if(queryObject != mQueryMap.end())

+    {

+        mQueryHandleAllocator.release(queryObject->first);

+        

+		if(queryObject->second)

+        {

+            queryObject->second->release();

+        }

+        

+		mQueryMap.erase(queryObject);

+    }

+}

+

+Buffer *Context::getBuffer(GLuint handle)

+{

+    return mResourceManager->getBuffer(handle);

+}

+

+Shader *Context::getShader(GLuint handle)

+{

+    return mResourceManager->getShader(handle);

+}

+

+Program *Context::getProgram(GLuint handle)

+{

+    return mResourceManager->getProgram(handle);

+}

+

+Texture *Context::getTexture(GLuint handle)

+{

+    return mResourceManager->getTexture(handle);

+}

+

+Renderbuffer *Context::getRenderbuffer(GLuint handle)

+{

+    return mResourceManager->getRenderbuffer(handle);

+}

+

+Framebuffer *Context::getReadFramebuffer()

+{

+    return getFramebuffer(mState.readFramebuffer);

+}

+

+Framebuffer *Context::getDrawFramebuffer()

+{

+    return getFramebuffer(mState.drawFramebuffer);

+}

+

+void Context::bindArrayBuffer(unsigned int buffer)

+{

+    mResourceManager->checkBufferAllocation(buffer);

+

+    mState.arrayBuffer.set(getBuffer(buffer));

+}

+

+void Context::bindElementArrayBuffer(unsigned int buffer)

+{

+    mResourceManager->checkBufferAllocation(buffer);

+

+    mState.elementArrayBuffer.set(getBuffer(buffer));

+}

+

+void Context::bindTexture2D(GLuint texture)

+{

+    mResourceManager->checkTextureAllocation(texture, TEXTURE_2D);

+

+    mState.samplerTexture[TEXTURE_2D][mState.activeSampler].set(getTexture(texture));

+}

+

+void Context::bindTextureCubeMap(GLuint texture)

+{

+    mResourceManager->checkTextureAllocation(texture, TEXTURE_CUBE);

+

+    mState.samplerTexture[TEXTURE_CUBE][mState.activeSampler].set(getTexture(texture));

+}

+

+void Context::bindReadFramebuffer(GLuint framebuffer)

+{

+    if(!getFramebuffer(framebuffer))

+    {

+        mFramebufferMap[framebuffer] = new Framebuffer();

+    }

+

+    mState.readFramebuffer = framebuffer;

+}

+

+void Context::bindDrawFramebuffer(GLuint framebuffer)

+{

+    if(!getFramebuffer(framebuffer))

+    {

+        mFramebufferMap[framebuffer] = new Framebuffer();

+    }

+

+    mState.drawFramebuffer = framebuffer;

+}

+

+void Context::bindRenderbuffer(GLuint renderbuffer)

+{

+    mResourceManager->checkRenderbufferAllocation(renderbuffer);

+

+    mState.renderbuffer.set(getRenderbuffer(renderbuffer));

+}

+

+void Context::useProgram(GLuint program)

+{

+    GLuint priorProgram = mState.currentProgram;

+    mState.currentProgram = program;               // Must switch before trying to delete, otherwise it only gets flagged.

+

+    if(priorProgram != program)

+    {

+        Program *newProgram = mResourceManager->getProgram(program);

+        Program *oldProgram = mResourceManager->getProgram(priorProgram);

+

+        if(newProgram)

+        {

+            newProgram->addRef();

+        }

+        

+        if(oldProgram)

+        {

+            oldProgram->release();

+        }

+    }

+}

+

+void Context::beginQuery(GLenum target, GLuint query)

+{

+    // From EXT_occlusion_query_boolean: If BeginQueryEXT is called with an <id>  

+    // of zero, if the active query object name for <target> is non-zero (for the  

+    // targets ANY_SAMPLES_PASSED_EXT and ANY_SAMPLES_PASSED_CONSERVATIVE_EXT, if  

+    // the active query for either target is non-zero), if <id> is the name of an 

+    // existing query object whose type does not match <target>, or if <id> is the

+    // active query object name for any query type, the error INVALID_OPERATION is

+    // generated.

+

+    // Ensure no other queries are active

+    // NOTE: If other queries than occlusion are supported, we will need to check

+    // separately that:

+    //    a) The query ID passed is not the current active query for any target/type

+    //    b) There are no active queries for the requested target (and in the case

+    //       of GL_ANY_SAMPLES_PASSED_EXT and GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT,

+    //       no query may be active for either if glBeginQuery targets either.

+    for(int i = 0; i < QUERY_TYPE_COUNT; i++)

+    {

+        if(mState.activeQuery[i].get() != NULL)

+        {

+            return error(GL_INVALID_OPERATION);

+        }

+    }

+

+    QueryType qType;

+    switch(target)

+    {

+    case GL_ANY_SAMPLES_PASSED_EXT: 

+        qType = QUERY_ANY_SAMPLES_PASSED; 

+        break;

+    case GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT: 

+        qType = QUERY_ANY_SAMPLES_PASSED_CONSERVATIVE; 

+        break;

+    default: 

+        ASSERT(false);

+    }

+

+    Query *queryObject = getQuery(query, true, target);

+

+    // Check that name was obtained with glGenQueries

+    if(!queryObject)

+    {

+        return error(GL_INVALID_OPERATION);

+    }

+

+    // Check for type mismatch

+    if(queryObject->getType() != target)

+    {

+        return error(GL_INVALID_OPERATION);

+    }

+

+    // Set query as active for specified target

+    mState.activeQuery[qType].set(queryObject);

+

+    // Begin query

+    queryObject->begin();

+}

+

+void Context::endQuery(GLenum target)

+{

+    QueryType qType;

+

+    switch(target)

+    {

+    case GL_ANY_SAMPLES_PASSED_EXT: 

+        qType = QUERY_ANY_SAMPLES_PASSED; 

+        break;

+    case GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT: 

+        qType = QUERY_ANY_SAMPLES_PASSED_CONSERVATIVE; 

+        break;

+    default: 

+        ASSERT(false);

+    }

+

+    Query *queryObject = mState.activeQuery[qType].get();

+

+    if(queryObject == NULL)

+    {

+        return error(GL_INVALID_OPERATION);

+    }

+

+    queryObject->end();

+

+    mState.activeQuery[qType].set(NULL);

+}

+

+void Context::setFramebufferZero(Framebuffer *buffer)

+{

+    delete mFramebufferMap[0];

+    mFramebufferMap[0] = buffer;

+}

+

+void Context::setRenderbufferStorage(RenderbufferStorage *renderbuffer)

+{

+    Renderbuffer *renderbufferObject = mState.renderbuffer.get();

+    renderbufferObject->setStorage(renderbuffer);

+}

+

+Framebuffer *Context::getFramebuffer(unsigned int handle)

+{

+    FramebufferMap::iterator framebuffer = mFramebufferMap.find(handle);

+

+    if(framebuffer == mFramebufferMap.end())

+    {

+        return NULL;

+    }

+    else

+    {

+        return framebuffer->second;

+    }

+}

+

+Fence *Context::getFence(unsigned int handle)

+{

+    FenceMap::iterator fence = mFenceMap.find(handle);

+

+    if(fence == mFenceMap.end())

+    {

+        return NULL;

+    }

+    else

+    {

+        return fence->second;

+    }

+}

+

+Query *Context::getQuery(unsigned int handle, bool create, GLenum type)

+{

+    QueryMap::iterator query = mQueryMap.find(handle);

+

+    if(query == mQueryMap.end())

+    {

+        return NULL;

+    }

+    else

+    {

+        if(!query->second && create)

+        {

+            query->second = new Query(handle, type);

+            query->second->addRef();

+        }

+

+        return query->second;

+    }

+}

+

+Buffer *Context::getArrayBuffer()

+{

+    return mState.arrayBuffer.get();

+}

+

+Buffer *Context::getElementArrayBuffer()

+{

+    return mState.elementArrayBuffer.get();

+}

+

+Program *Context::getCurrentProgram()

+{

+    return mResourceManager->getProgram(mState.currentProgram);

+}

+

+Texture2D *Context::getTexture2D()

+{

+    return static_cast<Texture2D*>(getSamplerTexture(mState.activeSampler, TEXTURE_2D));

+}

+

+TextureCubeMap *Context::getTextureCubeMap()

+{

+    return static_cast<TextureCubeMap*>(getSamplerTexture(mState.activeSampler, TEXTURE_CUBE));

+}

+

+Texture *Context::getSamplerTexture(unsigned int sampler, TextureType type)

+{

+    GLuint texid = mState.samplerTexture[type][sampler].id();

+

+    if(texid == 0)   // Special case: 0 refers to different initial textures based on the target

+    {

+        switch (type)

+        {

+          default: UNREACHABLE();

+          case TEXTURE_2D: return mTexture2DZero.get();

+          case TEXTURE_CUBE: return mTextureCubeMapZero.get();

+        }

+    }

+

+    return mState.samplerTexture[type][sampler].get();

+}

+

+bool Context::getBooleanv(GLenum pname, GLboolean *params)

+{

+    switch (pname)

+    {

+      case GL_SHADER_COMPILER:          *params = GL_TRUE;                          break;

+      case GL_SAMPLE_COVERAGE_INVERT:   *params = mState.sampleCoverageInvert;      break;

+      case GL_DEPTH_WRITEMASK:          *params = mState.depthMask;                 break;

+      case GL_COLOR_WRITEMASK:

+        params[0] = mState.colorMaskRed;

+        params[1] = mState.colorMaskGreen;

+        params[2] = mState.colorMaskBlue;

+        params[3] = mState.colorMaskAlpha;

+        break;

+      case GL_CULL_FACE:                *params = mState.cullFace;                  break;

+      case GL_POLYGON_OFFSET_FILL:      *params = mState.polygonOffsetFill;         break;

+      case GL_SAMPLE_ALPHA_TO_COVERAGE: *params = mState.sampleAlphaToCoverage;     break;

+      case GL_SAMPLE_COVERAGE:          *params = mState.sampleCoverage;            break;

+      case GL_SCISSOR_TEST:             *params = mState.scissorTest;               break;

+      case GL_STENCIL_TEST:             *params = mState.stencilTest;               break;

+      case GL_DEPTH_TEST:               *params = mState.depthTest;                 break;

+      case GL_BLEND:                    *params = mState.blend;                     break;

+      case GL_DITHER:                   *params = mState.dither;                    break;

+      default:

+        return false;

+    }

+

+    return true;

+}

+

+bool Context::getFloatv(GLenum pname, GLfloat *params)

+{

+    // Please note: DEPTH_CLEAR_VALUE is included in our internal getFloatv implementation

+    // because it is stored as a float, despite the fact that the GL ES 2.0 spec names

+    // GetIntegerv as its native query function. As it would require conversion in any

+    // case, this should make no difference to the calling application.

+    switch (pname)

+    {

+      case GL_LINE_WIDTH:               *params = mState.lineWidth;            break;

+      case GL_SAMPLE_COVERAGE_VALUE:    *params = mState.sampleCoverageValue;  break;

+      case GL_DEPTH_CLEAR_VALUE:        *params = mState.depthClearValue;      break;

+      case GL_POLYGON_OFFSET_FACTOR:    *params = mState.polygonOffsetFactor;  break;

+      case GL_POLYGON_OFFSET_UNITS:     *params = mState.polygonOffsetUnits;   break;

+      case GL_ALIASED_LINE_WIDTH_RANGE:

+        params[0] = ALIASED_LINE_WIDTH_RANGE_MIN;

+        params[1] = ALIASED_LINE_WIDTH_RANGE_MAX;

+        break;

+      case GL_ALIASED_POINT_SIZE_RANGE:

+        params[0] = ALIASED_POINT_SIZE_RANGE_MIN;

+        params[1] = ALIASED_POINT_SIZE_RANGE_MAX;

+        break;

+      case GL_DEPTH_RANGE:

+        params[0] = mState.zNear;

+        params[1] = mState.zFar;

+        break;

+      case GL_COLOR_CLEAR_VALUE:

+        params[0] = mState.colorClearValue.red;

+        params[1] = mState.colorClearValue.green;

+        params[2] = mState.colorClearValue.blue;

+        params[3] = mState.colorClearValue.alpha;

+        break;

+      case GL_BLEND_COLOR:

+        params[0] = mState.blendColor.red;

+        params[1] = mState.blendColor.green;

+        params[2] = mState.blendColor.blue;

+        params[3] = mState.blendColor.alpha;

+        break;

+	  case GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT:

+        *params = MAX_TEXTURE_MAX_ANISOTROPY;

+		break;

+      default:

+        return false;

+    }

+

+    return true;

+}

+

+bool Context::getIntegerv(GLenum pname, GLint *params)

+{

+    // Please note: DEPTH_CLEAR_VALUE is not included in our internal getIntegerv implementation

+    // because it is stored as a float, despite the fact that the GL ES 2.0 spec names

+    // GetIntegerv as its native query function. As it would require conversion in any

+    // case, this should make no difference to the calling application. You may find it in 

+    // Context::getFloatv.

+    switch (pname)

+    {

+    case GL_MAX_VERTEX_ATTRIBS:               *params = MAX_VERTEX_ATTRIBS;               break;

+    case GL_MAX_VERTEX_UNIFORM_VECTORS:       *params = MAX_VERTEX_UNIFORM_VECTORS;       break;

+    case GL_MAX_VARYING_VECTORS:              *params = MAX_VARYING_VECTORS;              break;

+    case GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS: *params = MAX_COMBINED_TEXTURE_IMAGE_UNITS; break;

+    case GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS:   *params = MAX_VERTEX_TEXTURE_IMAGE_UNITS;   break;

+    case GL_MAX_TEXTURE_IMAGE_UNITS:          *params = MAX_TEXTURE_IMAGE_UNITS;          break;

+	case GL_MAX_FRAGMENT_UNIFORM_VECTORS:     *params = MAX_FRAGMENT_UNIFORM_VECTORS;     break;

+	case GL_MAX_RENDERBUFFER_SIZE:            *params = IMPLEMENTATION_MAX_RENDERBUFFER_SIZE; break;

+    case GL_NUM_SHADER_BINARY_FORMATS:        *params = 0;                                    break;

+    case GL_SHADER_BINARY_FORMATS:      /* no shader binary formats are supported */          break;

+    case GL_ARRAY_BUFFER_BINDING:             *params = mState.arrayBuffer.id();              break;

+    case GL_ELEMENT_ARRAY_BUFFER_BINDING:     *params = mState.elementArrayBuffer.id();       break;

+//	case GL_FRAMEBUFFER_BINDING:            // now equivalent to GL_DRAW_FRAMEBUFFER_BINDING_ANGLE

+    case GL_DRAW_FRAMEBUFFER_BINDING_ANGLE:   *params = mState.drawFramebuffer;               break;

+    case GL_READ_FRAMEBUFFER_BINDING_ANGLE:   *params = mState.readFramebuffer;               break;

+    case GL_RENDERBUFFER_BINDING:             *params = mState.renderbuffer.id();             break;

+    case GL_CURRENT_PROGRAM:                  *params = mState.currentProgram;                break;

+    case GL_PACK_ALIGNMENT:                   *params = mState.packAlignment;                 break;

+    case GL_UNPACK_ALIGNMENT:                 *params = mState.unpackAlignment;               break;

+    case GL_GENERATE_MIPMAP_HINT:             *params = mState.generateMipmapHint;            break;

+    case GL_FRAGMENT_SHADER_DERIVATIVE_HINT_OES: *params = mState.fragmentShaderDerivativeHint; break;

+    case GL_ACTIVE_TEXTURE:                   *params = (mState.activeSampler + GL_TEXTURE0); break;

+    case GL_STENCIL_FUNC:                     *params = mState.stencilFunc;                   break;

+    case GL_STENCIL_REF:                      *params = mState.stencilRef;                    break;

+    case GL_STENCIL_VALUE_MASK:               *params = mState.stencilMask;                   break;

+    case GL_STENCIL_BACK_FUNC:                *params = mState.stencilBackFunc;               break;

+    case GL_STENCIL_BACK_REF:                 *params = mState.stencilBackRef;                break;

+    case GL_STENCIL_BACK_VALUE_MASK:          *params = mState.stencilBackMask;               break;

+    case GL_STENCIL_FAIL:                     *params = mState.stencilFail;                   break;

+    case GL_STENCIL_PASS_DEPTH_FAIL:          *params = mState.stencilPassDepthFail;          break;

+    case GL_STENCIL_PASS_DEPTH_PASS:          *params = mState.stencilPassDepthPass;          break;

+    case GL_STENCIL_BACK_FAIL:                *params = mState.stencilBackFail;               break;

+    case GL_STENCIL_BACK_PASS_DEPTH_FAIL:     *params = mState.stencilBackPassDepthFail;      break;

+    case GL_STENCIL_BACK_PASS_DEPTH_PASS:     *params = mState.stencilBackPassDepthPass;      break;

+    case GL_DEPTH_FUNC:                       *params = mState.depthFunc;                     break;

+    case GL_BLEND_SRC_RGB:                    *params = mState.sourceBlendRGB;                break;

+    case GL_BLEND_SRC_ALPHA:                  *params = mState.sourceBlendAlpha;              break;

+    case GL_BLEND_DST_RGB:                    *params = mState.destBlendRGB;                  break;

+    case GL_BLEND_DST_ALPHA:                  *params = mState.destBlendAlpha;                break;

+    case GL_BLEND_EQUATION_RGB:               *params = mState.blendEquationRGB;              break;

+    case GL_BLEND_EQUATION_ALPHA:             *params = mState.blendEquationAlpha;            break;

+    case GL_STENCIL_WRITEMASK:                *params = mState.stencilWritemask;              break;

+    case GL_STENCIL_BACK_WRITEMASK:           *params = mState.stencilBackWritemask;          break;

+    case GL_STENCIL_CLEAR_VALUE:              *params = mState.stencilClearValue;             break;

+    case GL_SUBPIXEL_BITS:                    *params = 4;                                    break;

+	case GL_MAX_TEXTURE_SIZE:                 *params = IMPLEMENTATION_MAX_TEXTURE_SIZE;  break;

+	case GL_MAX_CUBE_MAP_TEXTURE_SIZE:        *params = IMPLEMENTATION_MAX_CUBE_MAP_TEXTURE_SIZE; break;

+    case GL_NUM_COMPRESSED_TEXTURE_FORMATS:   

+        {

+            if(S3TC_SUPPORT)

+            {

+                // GL_COMPRESSED_RGB_S3TC_DXT1_EXT

+                // GL_COMPRESSED_RGBA_S3TC_DXT1_EXT

+				// GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE

+				// GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE

+                *params = 4;

+            }

+            else

+            {

+                *params = 0;

+            }

+        }

+        break;

+	case GL_MAX_SAMPLES_ANGLE:                *params = IMPLEMENTATION_MAX_SAMPLES; break;

+    case GL_SAMPLE_BUFFERS:                   

+    case GL_SAMPLES:

+        {

+            Framebuffer *framebuffer = getDrawFramebuffer();

+			int width, height, samples;

+

+            if(framebuffer->completeness(width, height, samples) == GL_FRAMEBUFFER_COMPLETE)

+            {

+                switch(pname)

+                {

+                case GL_SAMPLE_BUFFERS:

+                    if(samples != 0)

+                    {

+                        *params = 1;

+                    }

+                    else

+                    {

+                        *params = 0;

+                    }

+                    break;

+                case GL_SAMPLES:

+                    *params = samples;

+                    break;

+                }

+            }

+            else 

+            {

+                *params = 0;

+            }

+        }

+        break;

+    case GL_IMPLEMENTATION_COLOR_READ_TYPE:   *params = IMPLEMENTATION_COLOR_READ_TYPE;   break;

+    case GL_IMPLEMENTATION_COLOR_READ_FORMAT: *params = IMPLEMENTATION_COLOR_READ_FORMAT; break;

+    case GL_MAX_VIEWPORT_DIMS:

+        {

+			int maxDimension = IMPLEMENTATION_MAX_RENDERBUFFER_SIZE;

+            params[0] = maxDimension;

+            params[1] = maxDimension;

+        }

+        break;

+    case GL_COMPRESSED_TEXTURE_FORMATS:

+        {

+            if(S3TC_SUPPORT)

+            {

+                params[0] = GL_COMPRESSED_RGB_S3TC_DXT1_EXT;

+                params[1] = GL_COMPRESSED_RGBA_S3TC_DXT1_EXT;

+				params[2] = GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE;

+                params[3] = GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE;

+            }

+        }

+        break;

+    case GL_VIEWPORT:

+        params[0] = mState.viewportX;

+        params[1] = mState.viewportY;

+        params[2] = mState.viewportWidth;

+        params[3] = mState.viewportHeight;

+        break;

+    case GL_SCISSOR_BOX:

+        params[0] = mState.scissorX;

+        params[1] = mState.scissorY;

+        params[2] = mState.scissorWidth;

+        params[3] = mState.scissorHeight;

+        break;

+    case GL_CULL_FACE_MODE:                   *params = mState.cullMode;                 break;

+    case GL_FRONT_FACE:                       *params = mState.frontFace;                break;

+    case GL_RED_BITS:

+    case GL_GREEN_BITS:

+    case GL_BLUE_BITS:

+    case GL_ALPHA_BITS:

+        {

+            Framebuffer *framebuffer = getDrawFramebuffer();

+            Renderbuffer *colorbuffer = framebuffer->getColorbuffer();

+

+            if(colorbuffer)

+            {

+                switch (pname)

+                {

+                  case GL_RED_BITS:   *params = colorbuffer->getRedSize();   break;

+                  case GL_GREEN_BITS: *params = colorbuffer->getGreenSize(); break;

+                  case GL_BLUE_BITS:  *params = colorbuffer->getBlueSize();  break;

+                  case GL_ALPHA_BITS: *params = colorbuffer->getAlphaSize(); break;

+                }

+            }

+            else

+            {

+                *params = 0;

+            }

+        }

+        break;

+    case GL_DEPTH_BITS:

+        {

+            Framebuffer *framebuffer = getDrawFramebuffer();

+            Renderbuffer *depthbuffer = framebuffer->getDepthbuffer();

+

+            if(depthbuffer)

+            {

+                *params = depthbuffer->getDepthSize();

+            }

+            else

+            {

+                *params = 0;

+            }

+        }

+        break;

+    case GL_STENCIL_BITS:

+        {

+            Framebuffer *framebuffer = getDrawFramebuffer();

+            Renderbuffer *stencilbuffer = framebuffer->getStencilbuffer();

+

+            if(stencilbuffer)

+            {

+                *params = stencilbuffer->getStencilSize();

+            }

+            else

+            {

+                *params = 0;

+            }

+        }

+        break;

+    case GL_TEXTURE_BINDING_2D:

+        {

+            if(mState.activeSampler < 0 || mState.activeSampler > MAX_COMBINED_TEXTURE_IMAGE_UNITS - 1)

+            {

+                error(GL_INVALID_OPERATION);

+                return false;

+            }

+

+            *params = mState.samplerTexture[TEXTURE_2D][mState.activeSampler].id();

+        }

+        break;

+    case GL_TEXTURE_BINDING_CUBE_MAP:

+        {

+            if(mState.activeSampler < 0 || mState.activeSampler > MAX_COMBINED_TEXTURE_IMAGE_UNITS - 1)

+            {

+                error(GL_INVALID_OPERATION);

+                return false;

+            }

+

+            *params = mState.samplerTexture[TEXTURE_CUBE][mState.activeSampler].id();

+        }

+        break;

+    default:

+        return false;

+    }

+

+    return true;

+}

+

+bool Context::getQueryParameterInfo(GLenum pname, GLenum *type, unsigned int *numParams)

+{

+    // Please note: the query type returned for DEPTH_CLEAR_VALUE in this implementation

+    // is FLOAT rather than INT, as would be suggested by the GL ES 2.0 spec. This is due

+    // to the fact that it is stored internally as a float, and so would require conversion

+    // if returned from Context::getIntegerv. Since this conversion is already implemented 

+    // in the case that one calls glGetIntegerv to retrieve a float-typed state variable, we

+    // place DEPTH_CLEAR_VALUE with the floats. This should make no difference to the calling

+    // application.

+    switch (pname)

+    {

+      case GL_COMPRESSED_TEXTURE_FORMATS:

+		{

+            *type = GL_INT;

+            *numParams = S3TC_SUPPORT ? 4 : 0;

+        }

+		break;

+      case GL_SHADER_BINARY_FORMATS:

+        {

+            *type = GL_INT;

+            *numParams = 0;

+        }

+        break;

+      case GL_MAX_VERTEX_ATTRIBS:

+      case GL_MAX_VERTEX_UNIFORM_VECTORS:

+      case GL_MAX_VARYING_VECTORS:

+      case GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS:

+      case GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS:

+      case GL_MAX_TEXTURE_IMAGE_UNITS:

+      case GL_MAX_FRAGMENT_UNIFORM_VECTORS:

+      case GL_MAX_RENDERBUFFER_SIZE:

+      case GL_NUM_SHADER_BINARY_FORMATS:

+      case GL_NUM_COMPRESSED_TEXTURE_FORMATS:

+      case GL_ARRAY_BUFFER_BINDING:

+      case GL_FRAMEBUFFER_BINDING:

+      case GL_RENDERBUFFER_BINDING:

+      case GL_CURRENT_PROGRAM:

+      case GL_PACK_ALIGNMENT:

+      case GL_UNPACK_ALIGNMENT:

+      case GL_GENERATE_MIPMAP_HINT:

+      case GL_FRAGMENT_SHADER_DERIVATIVE_HINT_OES:

+      case GL_RED_BITS:

+      case GL_GREEN_BITS:

+      case GL_BLUE_BITS:

+      case GL_ALPHA_BITS:

+      case GL_DEPTH_BITS:

+      case GL_STENCIL_BITS:

+      case GL_ELEMENT_ARRAY_BUFFER_BINDING:

+      case GL_CULL_FACE_MODE:

+      case GL_FRONT_FACE:

+      case GL_ACTIVE_TEXTURE:

+      case GL_STENCIL_FUNC:

+      case GL_STENCIL_VALUE_MASK:

+      case GL_STENCIL_REF:

+      case GL_STENCIL_FAIL:

+      case GL_STENCIL_PASS_DEPTH_FAIL:

+      case GL_STENCIL_PASS_DEPTH_PASS:

+      case GL_STENCIL_BACK_FUNC:

+      case GL_STENCIL_BACK_VALUE_MASK:

+      case GL_STENCIL_BACK_REF:

+      case GL_STENCIL_BACK_FAIL:

+      case GL_STENCIL_BACK_PASS_DEPTH_FAIL:

+      case GL_STENCIL_BACK_PASS_DEPTH_PASS:

+      case GL_DEPTH_FUNC:

+      case GL_BLEND_SRC_RGB:

+      case GL_BLEND_SRC_ALPHA:

+      case GL_BLEND_DST_RGB:

+      case GL_BLEND_DST_ALPHA:

+      case GL_BLEND_EQUATION_RGB:

+      case GL_BLEND_EQUATION_ALPHA:

+      case GL_STENCIL_WRITEMASK:

+      case GL_STENCIL_BACK_WRITEMASK:

+      case GL_STENCIL_CLEAR_VALUE:

+      case GL_SUBPIXEL_BITS:

+      case GL_MAX_TEXTURE_SIZE:

+      case GL_MAX_CUBE_MAP_TEXTURE_SIZE:

+      case GL_SAMPLE_BUFFERS:

+      case GL_SAMPLES:

+      case GL_IMPLEMENTATION_COLOR_READ_TYPE:

+      case GL_IMPLEMENTATION_COLOR_READ_FORMAT:

+      case GL_TEXTURE_BINDING_2D:

+      case GL_TEXTURE_BINDING_CUBE_MAP:

+        {

+            *type = GL_INT;

+            *numParams = 1;

+        }

+        break;

+      case GL_MAX_SAMPLES_ANGLE:

+        {

+            *type = GL_INT;

+            *numParams = 1;

+        }

+        break;

+      case GL_MAX_VIEWPORT_DIMS:

+        {

+            *type = GL_INT;

+            *numParams = 2;

+        }

+        break;

+      case GL_VIEWPORT:

+      case GL_SCISSOR_BOX:

+        {

+            *type = GL_INT;

+            *numParams = 4;

+        }

+        break;

+      case GL_SHADER_COMPILER:

+      case GL_SAMPLE_COVERAGE_INVERT:

+      case GL_DEPTH_WRITEMASK:

+      case GL_CULL_FACE:                // CULL_FACE through DITHER are natural to IsEnabled,

+      case GL_POLYGON_OFFSET_FILL:      // but can be retrieved through the Get{Type}v queries.

+      case GL_SAMPLE_ALPHA_TO_COVERAGE: // For this purpose, they are treated here as bool-natural

+      case GL_SAMPLE_COVERAGE:

+      case GL_SCISSOR_TEST:

+      case GL_STENCIL_TEST:

+      case GL_DEPTH_TEST:

+      case GL_BLEND:

+      case GL_DITHER:

+        {

+            *type = GL_BOOL;

+            *numParams = 1;

+        }

+        break;

+      case GL_COLOR_WRITEMASK:

+        {

+            *type = GL_BOOL;

+            *numParams = 4;

+        }

+        break;

+      case GL_POLYGON_OFFSET_FACTOR:

+      case GL_POLYGON_OFFSET_UNITS:

+      case GL_SAMPLE_COVERAGE_VALUE:

+      case GL_DEPTH_CLEAR_VALUE:

+      case GL_LINE_WIDTH:

+        {

+            *type = GL_FLOAT;

+            *numParams = 1;

+        }

+        break;

+      case GL_ALIASED_LINE_WIDTH_RANGE:

+      case GL_ALIASED_POINT_SIZE_RANGE:

+      case GL_DEPTH_RANGE:

+        {

+            *type = GL_FLOAT;

+            *numParams = 2;

+        }

+        break;

+      case GL_COLOR_CLEAR_VALUE:

+      case GL_BLEND_COLOR:

+        {

+            *type = GL_FLOAT;

+            *numParams = 4;

+        }

+        break;

+	  case GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT:

+        *type = GL_FLOAT;

+        *numParams = 1;

+        break;

+      default:

+        return false;

+    }

+

+    return true;

+}

+

+// Applies the render target surface, depth stencil surface, viewport rectangle and scissor rectangle

+bool Context::applyRenderTarget()

+{

+    Device *device = getDevice();

+    Framebuffer *framebuffer = getDrawFramebuffer();

+	int width, height, samples;

+

+    if(!framebuffer || framebuffer->completeness(width, height, samples) != GL_FRAMEBUFFER_COMPLETE)

+    {

+        return error(GL_INVALID_FRAMEBUFFER_OPERATION, false);

+    }

+

+    Image *renderTarget = framebuffer->getRenderTarget();

+	device->setRenderTarget(renderTarget);

+	if(renderTarget) renderTarget->release();

+

+    Image *depthStencil = framebuffer->getDepthStencil();

+    device->setDepthStencilSurface(depthStencil);

+	if(depthStencil) depthStencil->release();

+

+    Viewport viewport;

+    float zNear = clamp01(mState.zNear);

+    float zFar = clamp01(mState.zFar);

+

+    viewport.x0 = mState.viewportX;

+    viewport.y0 = mState.viewportY;

+    viewport.width = mState.viewportWidth;

+    viewport.height = mState.viewportHeight;

+    viewport.minZ = zNear;

+    viewport.maxZ = zFar;

+

+    device->setViewport(viewport);

+

+    if(mState.scissorTest)

+    {

+		sw::Rect scissor = {mState.scissorX, mState.scissorY, mState.scissorX + mState.scissorWidth, mState.scissorY + mState.scissorHeight};

+		scissor.clip(0, 0, width, height);

+        

+		device->setScissorRect(scissor);

+        device->setScissorEnable(true);

+    }

+    else

+    {

+        device->setScissorEnable(false);

+    }

+

+	Program *program = getCurrentProgram();

+

+	if(program)

+	{

+		GLfloat nearFarDiff[3] = {zNear, zFar, zFar - zNear};

+        program->setUniform1fv(program->getUniformLocation("gl_DepthRange.near"), 1, &nearFarDiff[0]);

+		program->setUniform1fv(program->getUniformLocation("gl_DepthRange.far"), 1, &nearFarDiff[1]);

+		program->setUniform1fv(program->getUniformLocation("gl_DepthRange.diff"), 1, &nearFarDiff[2]);

+    }

+

+    return true;

+}

+

+// Applies the fixed-function state (culling, depth test, alpha blending, stenciling, etc)

+void Context::applyState(GLenum drawMode)

+{

+    Device *device = getDevice();

+    Framebuffer *framebuffer = getDrawFramebuffer();

+

+    if(mState.cullFace)

+    {

+        device->setCullMode(es2sw::ConvertCullMode(mState.cullMode, mState.frontFace));

+    }

+    else

+    {

+		device->setCullMode(sw::Context::CULL_NONE);

+    }

+

+    if(mDepthStateDirty)

+    {

+        if(mState.depthTest)

+        {

+			device->setDepthBufferEnable(true);

+			device->setDepthCompare(es2sw::ConvertDepthComparison(mState.depthFunc));

+        }

+        else

+        {

+            device->setDepthBufferEnable(false);

+        }

+

+        mDepthStateDirty = false;

+    }

+

+    if(mBlendStateDirty)

+    {

+        if(mState.blend)

+        {

+			device->setAlphaBlendEnable(true);

+			device->setSeparateAlphaBlendEnable(true);

+

+            device->setBlendConstant(es2sw::ConvertColor(mState.blendColor));

+

+			device->setSourceBlendFactor(es2sw::ConvertBlendFunc(mState.sourceBlendRGB));

+			device->setDestBlendFactor(es2sw::ConvertBlendFunc(mState.destBlendRGB));

+			device->setBlendOperation(es2sw::ConvertBlendOp(mState.blendEquationRGB));

+

+            device->setSourceBlendFactorAlpha(es2sw::ConvertBlendFunc(mState.sourceBlendAlpha));

+			device->setDestBlendFactorAlpha(es2sw::ConvertBlendFunc(mState.destBlendAlpha));

+			device->setBlendOperationAlpha(es2sw::ConvertBlendOp(mState.blendEquationAlpha));

+        }

+        else

+        {

+			device->setAlphaBlendEnable(false);

+        }

+

+        mBlendStateDirty = false;

+    }

+

+    if(mStencilStateDirty || mFrontFaceDirty)

+    {

+        if(mState.stencilTest && framebuffer->hasStencil())

+        {

+			device->setStencilEnable(true);

+			device->setTwoSidedStencil(true);

+

+            if(mState.stencilWritemask != mState.stencilBackWritemask || 

+               mState.stencilRef != mState.stencilBackRef || 

+               mState.stencilMask != mState.stencilBackMask)

+            {

+				ERR("Separate front/back stencil writemasks, reference values, or stencil mask values are invalid under WebGL.");

+                return error(GL_INVALID_OPERATION);

+            }

+

+            // get the maximum size of the stencil ref

+            Renderbuffer *stencilbuffer = framebuffer->getStencilbuffer();

+            GLuint maxStencil = (1 << stencilbuffer->getStencilSize()) - 1;

+

+			if(mState.frontFace == GL_CCW)

+			{

+				device->setStencilWriteMask(mState.stencilWritemask);

+				device->setStencilCompare(es2sw::ConvertStencilComparison(mState.stencilFunc));

+

+				device->setStencilReference((mState.stencilRef < (GLint)maxStencil) ? mState.stencilRef : maxStencil);

+				device->setStencilMask(mState.stencilMask);

+

+				device->setStencilFailOperation(es2sw::ConvertStencilOp(mState.stencilFail));

+				device->setStencilZFailOperation(es2sw::ConvertStencilOp(mState.stencilPassDepthFail));

+				device->setStencilPassOperation(es2sw::ConvertStencilOp(mState.stencilPassDepthPass));

+

+				device->setStencilWriteMaskCCW(mState.stencilBackWritemask);

+				device->setStencilCompareCCW(es2sw::ConvertStencilComparison(mState.stencilBackFunc));

+

+				device->setStencilReferenceCCW((mState.stencilBackRef < (GLint)maxStencil) ? mState.stencilBackRef : maxStencil);

+				device->setStencilMaskCCW(mState.stencilBackMask);

+

+				device->setStencilFailOperationCCW(es2sw::ConvertStencilOp(mState.stencilBackFail));

+				device->setStencilZFailOperationCCW(es2sw::ConvertStencilOp(mState.stencilBackPassDepthFail));

+				device->setStencilPassOperationCCW(es2sw::ConvertStencilOp(mState.stencilBackPassDepthPass));

+			}

+			else

+			{

+				device->setStencilWriteMaskCCW(mState.stencilWritemask);

+				device->setStencilCompareCCW(es2sw::ConvertStencilComparison(mState.stencilFunc));

+

+				device->setStencilReferenceCCW((mState.stencilRef < (GLint)maxStencil) ? mState.stencilRef : maxStencil);

+				device->setStencilMaskCCW(mState.stencilMask);

+

+				device->setStencilFailOperationCCW(es2sw::ConvertStencilOp(mState.stencilFail));

+				device->setStencilZFailOperationCCW(es2sw::ConvertStencilOp(mState.stencilPassDepthFail));

+				device->setStencilPassOperationCCW(es2sw::ConvertStencilOp(mState.stencilPassDepthPass));

+

+				device->setStencilWriteMask(mState.stencilBackWritemask);

+				device->setStencilCompare(es2sw::ConvertStencilComparison(mState.stencilBackFunc));

+

+				device->setStencilReference((mState.stencilBackRef < (GLint)maxStencil) ? mState.stencilBackRef : maxStencil);

+				device->setStencilMask(mState.stencilBackMask);

+

+				device->setStencilFailOperation(es2sw::ConvertStencilOp(mState.stencilBackFail));

+				device->setStencilZFailOperation(es2sw::ConvertStencilOp(mState.stencilBackPassDepthFail));

+				device->setStencilPassOperation(es2sw::ConvertStencilOp(mState.stencilBackPassDepthPass));

+			}

+        }

+        else

+        {

+			device->setStencilEnable(false);

+        }

+

+        mStencilStateDirty = false;

+        mFrontFaceDirty = false;

+    }

+

+    if(mMaskStateDirty)

+    {

+		device->setColorWriteMask(0, es2sw::ConvertColorMask(mState.colorMaskRed, mState.colorMaskGreen, mState.colorMaskBlue, mState.colorMaskAlpha));

+		device->setDepthWriteEnable(mState.depthMask);

+

+        mMaskStateDirty = false;

+    }

+

+    if(mPolygonOffsetStateDirty)

+    {

+        if(mState.polygonOffsetFill)

+        {

+            Renderbuffer *depthbuffer = framebuffer->getDepthbuffer();

+            if(depthbuffer)

+            {

+				device->setSlopeDepthBias(mState.polygonOffsetFactor);

+                float depthBias = ldexp(mState.polygonOffsetUnits, -(int)(depthbuffer->getDepthSize()));

+				device->setDepthBias(depthBias);

+            }

+        }

+        else

+        {

+            device->setSlopeDepthBias(0);

+            device->setDepthBias(0);

+        }

+

+        mPolygonOffsetStateDirty = false;

+    }

+

+    if(mSampleStateDirty)

+    {

+        if(mState.sampleAlphaToCoverage)

+        {

+            device->setTransparencyAntialiasing(sw::Context::TRANSPARENCY_ALPHA_TO_COVERAGE);

+        }

+		else

+		{

+			device->setTransparencyAntialiasing(sw::Context::TRANSPARENCY_NONE);

+		}

+

+        if(mState.sampleCoverage)

+        {

+            unsigned int mask = 0;

+            if(mState.sampleCoverageValue != 0)

+            {

+				int width, height, samples;

+				framebuffer->completeness(width, height, samples);

+

+                float threshold = 0.5f;

+

+                for(int i = 0; i < samples; i++)

+                {

+                    mask <<= 1;

+

+                    if((i + 1) * mState.sampleCoverageValue >= threshold)

+                    {

+                        threshold += 1.0f;

+                        mask |= 1;

+                    }

+                }

+            }

+            

+            if(mState.sampleCoverageInvert)

+            {

+                mask = ~mask;

+            }

+

+			device->setMultiSampleMask(mask);

+        }

+        else

+        {

+			device->setMultiSampleMask(0xFFFFFFFF);

+        }

+

+        mSampleStateDirty = false;

+    }

+

+    if(mDitherStateDirty)

+    {

+    //	UNIMPLEMENTED();   // FIXME

+

+        mDitherStateDirty = false;

+    }

+}

+

+GLenum Context::applyVertexBuffer(GLint base, GLint first, GLsizei count)

+{

+    TranslatedAttribute attributes[MAX_VERTEX_ATTRIBS];

+

+    GLenum err = mVertexDataManager->prepareVertexData(first, count, attributes);

+    if(err != GL_NO_ERROR)

+    {

+        return err;

+    }

+

+    Device *device = getDevice();

+	Program *program = getCurrentProgram();

+

+	device->resetInputStreams(false);

+

+    for(int i = 0; i < MAX_VERTEX_ATTRIBS; i++)

+	{

+		if(program->getAttributeStream(i) == -1)

+		{

+			continue;

+		}

+

+		sw::Resource *resource = attributes[i].vertexBuffer;

+		const void *buffer = (char*)resource->getBuffer() + attributes[i].offset;

+			

+		int stride = attributes[i].stride;

+

+		buffer = (char*)buffer + stride * base;

+

+		sw::Stream attribute(resource, buffer, stride);

+

+		attribute.type = attributes[i].type;

+		attribute.count = attributes[i].count;

+		attribute.normalized = attributes[i].normalized;

+

+		int stream = program->getAttributeStream(i);

+		device->setInputStream(stream, attribute);

+	}

+

+	return GL_NO_ERROR;

+}

+

+// Applies the indices and element array bindings

+GLenum Context::applyIndexBuffer(const void *indices, GLsizei count, GLenum mode, GLenum type, TranslatedIndexData *indexInfo)

+{

+    Device *device = getDevice();

+    GLenum err = mIndexDataManager->prepareIndexData(type, count, mState.elementArrayBuffer.get(), indices, indexInfo);

+

+    if(err == GL_NO_ERROR)

+    {

+        device->setIndexBuffer(indexInfo->indexBuffer);

+    }

+

+    return err;

+}

+

+// Applies the shaders and shader constants

+void Context::applyShaders()

+{

+    Device *device = getDevice();

+    Program *programObject = getCurrentProgram();

+    sw::VertexShader *vertexShader = programObject->getVertexShader();

+	sw::PixelShader *pixelShader = programObject->getPixelShader();

+

+    device->setVertexShader(vertexShader);

+    device->setPixelShader(pixelShader);

+

+    if(programObject->getSerial() != mAppliedProgramSerial)

+    {

+        programObject->dirtyAllUniforms();

+        mAppliedProgramSerial = programObject->getSerial();

+    }

+

+    programObject->applyUniforms();

+}

+

+void Context::applyTextures()

+{

+    applyTextures(sw::SAMPLER_PIXEL);

+	applyTextures(sw::SAMPLER_VERTEX);

+}

+

+void Context::applyTextures(sw::SamplerType samplerType)

+{

+    Device *device = getDevice();

+    Program *programObject = getCurrentProgram();

+

+    int samplerCount = (samplerType == sw::SAMPLER_PIXEL) ? MAX_TEXTURE_IMAGE_UNITS : MAX_VERTEX_TEXTURE_IMAGE_UNITS;   // Range of samplers of given sampler type

+

+    for(int samplerIndex = 0; samplerIndex < samplerCount; samplerIndex++)

+    {

+        int textureUnit = programObject->getSamplerMapping(samplerType, samplerIndex);   // OpenGL texture image unit index

+

+        if(textureUnit != -1)

+        {

+            TextureType textureType = programObject->getSamplerTextureType(samplerType, samplerIndex);

+

+            Texture *texture = getSamplerTexture(textureUnit, textureType);

+

+			if(texture->isSamplerComplete())

+            {

+                GLenum wrapS = texture->getWrapS();

+                GLenum wrapT = texture->getWrapT();

+                GLenum texFilter = texture->getMinFilter();

+                GLenum magFilter = texture->getMagFilter();

+				GLenum maxAnisotropy = texture->getMaxAnisotropy();

+

+				device->setAddressingModeU(samplerType, samplerIndex, es2sw::ConvertTextureWrap(wrapS));

+                device->setAddressingModeV(samplerType, samplerIndex, es2sw::ConvertTextureWrap(wrapT));

+

+				sw::FilterType minFilter;

+				sw::MipmapType mipFilter;

+                es2sw::ConvertMinFilter(texFilter, &minFilter, &mipFilter, maxAnisotropy);

+			//	ASSERT(minFilter == es2sw::ConvertMagFilter(magFilter));

+

+				device->setTextureFilter(samplerType, samplerIndex, minFilter);

+			//	device->setTextureFilter(samplerType, samplerIndex, es2sw::ConvertMagFilter(magFilter));

+				device->setMipmapFilter(samplerType, samplerIndex, mipFilter);

+				device->setMaxAnisotropy(samplerType, samplerIndex, maxAnisotropy);                

+

+				applyTexture(samplerType, samplerIndex, texture);

+            }

+            else

+            {

+                applyTexture(samplerType, samplerIndex, 0);

+            }

+        }

+        else

+        {

+            applyTexture(samplerType, samplerIndex, NULL);

+        }

+    }

+}

+

+void Context::applyTexture(sw::SamplerType type, int index, Texture *baseTexture)

+{

+	Device *device = getDevice();

+	Program *program = getCurrentProgram();

+	int sampler = (type == sw::SAMPLER_PIXEL) ? index : 16 + index;

+	bool textureUsed = false;

+

+	if(type == sw::SAMPLER_PIXEL)

+	{

+		textureUsed = program->getPixelShader()->usesSampler(index);

+	}

+	else if(type == sw::SAMPLER_VERTEX)

+	{

+		textureUsed = program->getVertexShader()->usesSampler(index);

+	}

+	else UNREACHABLE();

+

+	sw::Resource *resource = 0;

+

+	if(baseTexture && textureUsed)

+	{

+		resource = baseTexture->getResource();

+	}

+

+	device->setTextureResource(sampler, resource);

+			

+	if(baseTexture && textureUsed)

+	{

+		int levelCount = baseTexture->getLevelCount();

+

+		if(baseTexture->isTexture2D())

+		{

+			Texture2D *texture = static_cast<Texture2D*>(baseTexture);

+

+			for(int mipmapLevel = 0; mipmapLevel < MIPMAP_LEVELS; mipmapLevel++)

+			{

+				int surfaceLevel = mipmapLevel;

+

+				if(surfaceLevel < 0)

+				{

+					surfaceLevel = 0;

+				}

+				else if(surfaceLevel >= levelCount)

+				{

+					surfaceLevel = levelCount - 1;

+				}

+

+				Image *surface = texture->getImage(surfaceLevel);

+				device->setTextureLevel(sampler, 0, mipmapLevel, surface, sw::TEXTURE_2D);

+			}

+		}

+		else if(baseTexture->isTextureCubeMap())

+		{

+			for(int face = 0; face < 6; face++)

+			{

+				TextureCubeMap *cubeTexture = static_cast<TextureCubeMap*>(baseTexture);

+

+				for(int mipmapLevel = 0; mipmapLevel < MIPMAP_LEVELS; mipmapLevel++)

+				{

+					int surfaceLevel = mipmapLevel;

+

+					if(surfaceLevel < 0)

+					{

+						surfaceLevel = 0;

+					}

+					else if(surfaceLevel >= levelCount)

+					{

+						surfaceLevel = levelCount - 1;

+					}

+

+					Image *surface = cubeTexture->getImage(face, surfaceLevel);

+					device->setTextureLevel(sampler, face, mipmapLevel, surface, sw::TEXTURE_CUBE);

+				}

+			}

+		}

+		else UNIMPLEMENTED();

+	}

+	else

+	{

+		device->setTextureLevel(sampler, 0, 0, 0, sw::TEXTURE_NULL);

+	}

+}

+

+void Context::readPixels(GLint x, GLint y, GLsizei width, GLsizei height,

+                         GLenum format, GLenum type, GLsizei *bufSize, void* pixels)

+{

+    Framebuffer *framebuffer = getReadFramebuffer();

+	int framebufferWidth, framebufferHeight, framebufferSamples;

+

+    if(framebuffer->completeness(framebufferWidth, framebufferHeight, framebufferSamples) != GL_FRAMEBUFFER_COMPLETE)

+    {

+        return error(GL_INVALID_FRAMEBUFFER_OPERATION);

+    }

+

+    if(getReadFramebufferHandle() != 0 && framebufferSamples != 0)

+    {

+        return error(GL_INVALID_OPERATION);

+    }

+

+	GLsizei outputPitch = ComputePitch(width, format, type, mState.packAlignment);

+    

+	// Sized query sanity check

+    if(bufSize)

+    {

+        int requiredSize = outputPitch * height;

+        if(requiredSize > *bufSize)

+        {

+            return error(GL_INVALID_OPERATION);

+        }

+    }

+

+    Image *renderTarget = framebuffer->getRenderTarget();

+

+    if(!renderTarget)

+    {

+        return error(GL_OUT_OF_MEMORY);

+    }

+

+	sw::Rect rect = {x, y, x + width, y + height};

+	rect.clip(0, 0, renderTarget->getWidth(), renderTarget->getHeight());

+

+    unsigned char *source = (unsigned char*)renderTarget->lock(rect.x0, rect.y0, sw::LOCK_READONLY);

+    unsigned char *dest = (unsigned char*)pixels;

+    unsigned short *dest16 = (unsigned short*)pixels;

+    int inputPitch = (int)renderTarget->getPitch();

+

+    for(int j = 0; j < rect.y1 - rect.y0; j++)

+    {

+        if(renderTarget->getInternalFormat() == sw::FORMAT_A8R8G8B8 &&

+           format == GL_BGRA_EXT && type == GL_UNSIGNED_BYTE)

+        {

+            // Fast path for EXT_read_format_bgra, given an RGBA source buffer

+			// Note that buffers with no alpha go through the slow path below

+            memcpy(dest + j * outputPitch, source + j * inputPitch, (rect.x1 - rect.x0) * 4);

+        }

+		else

+		{

+			for(int i = 0; i < rect.x1 - rect.x0; i++)

+			{

+				float r;

+				float g;

+				float b;

+				float a;

+

+				switch(renderTarget->getInternalFormat())

+				{

+				case sw::FORMAT_R5G6B5:

+					{

+						unsigned short rgb = *(unsigned short*)(source + 2 * i + j * inputPitch);

+

+						a = 1.0f;

+						b = (rgb & 0x001F) * (1.0f / 0x001F);

+						g = (rgb & 0x07E0) * (1.0f / 0x07E0);

+						r = (rgb & 0xF800) * (1.0f / 0xF800);

+					}

+					break;

+				case sw::FORMAT_A1R5G5B5:

+					{

+						unsigned short argb = *(unsigned short*)(source + 2 * i + j * inputPitch);

+

+						a = (argb & 0x8000) ? 1.0f : 0.0f;

+						b = (argb & 0x001F) * (1.0f / 0x001F);

+						g = (argb & 0x03E0) * (1.0f / 0x03E0);

+						r = (argb & 0x7C00) * (1.0f / 0x7C00);

+					}

+					break;

+				case sw::FORMAT_A8R8G8B8:

+					{

+						unsigned int argb = *(unsigned int*)(source + 4 * i + j * inputPitch);

+

+						a = (argb & 0xFF000000) * (1.0f / 0xFF000000);

+						b = (argb & 0x000000FF) * (1.0f / 0x000000FF);

+						g = (argb & 0x0000FF00) * (1.0f / 0x0000FF00);

+						r = (argb & 0x00FF0000) * (1.0f / 0x00FF0000);

+					}

+					break;

+				case sw::FORMAT_X8R8G8B8:

+					{

+						unsigned int xrgb = *(unsigned int*)(source + 4 * i + j * inputPitch);

+

+						a = 1.0f;

+						b = (xrgb & 0x000000FF) * (1.0f / 0x000000FF);

+						g = (xrgb & 0x0000FF00) * (1.0f / 0x0000FF00);

+						r = (xrgb & 0x00FF0000) * (1.0f / 0x00FF0000);

+					}

+					break;

+				case sw::FORMAT_A2R10G10B10:

+					{

+						unsigned int argb = *(unsigned int*)(source + 4 * i + j * inputPitch);

+

+						a = (argb & 0xC0000000) * (1.0f / 0xC0000000);

+						b = (argb & 0x000003FF) * (1.0f / 0x000003FF);

+						g = (argb & 0x000FFC00) * (1.0f / 0x000FFC00);

+						r = (argb & 0x3FF00000) * (1.0f / 0x3FF00000);

+					}

+					break;

+				case sw::FORMAT_A32B32G32R32F:

+					{

+						r = *((float*)(source + 16 * i + j * inputPitch) + 0);

+						g = *((float*)(source + 16 * i + j * inputPitch) + 1);

+						b = *((float*)(source + 16 * i + j * inputPitch) + 2);

+						a = *((float*)(source + 16 * i + j * inputPitch) + 3);

+					}

+					break;

+				case sw::FORMAT_A16B16G16R16F:

+					{

+						r = (float)*((sw::half*)(source + 8 * i + j * inputPitch) + 0);

+						g = (float)*((sw::half*)(source + 8 * i + j * inputPitch) + 1);

+						b = (float)*((sw::half*)(source + 8 * i + j * inputPitch) + 2);

+						a = (float)*((sw::half*)(source + 8 * i + j * inputPitch) + 3);

+					}

+					break;

+				default:

+					UNIMPLEMENTED();   // FIXME

+					UNREACHABLE();

+				}

+

+				switch(format)

+				{

+				case GL_RGBA:

+					switch(type)

+					{

+					case GL_UNSIGNED_BYTE:

+						dest[4 * i + j * outputPitch + 0] = (unsigned char)(255 * r + 0.5f);

+						dest[4 * i + j * outputPitch + 1] = (unsigned char)(255 * g + 0.5f);

+						dest[4 * i + j * outputPitch + 2] = (unsigned char)(255 * b + 0.5f);

+						dest[4 * i + j * outputPitch + 3] = (unsigned char)(255 * a + 0.5f);

+						break;

+					default: UNREACHABLE();

+					}

+					break;

+				case GL_BGRA_EXT:

+					switch(type)

+					{

+					case GL_UNSIGNED_BYTE:

+						dest[4 * i + j * outputPitch + 0] = (unsigned char)(255 * b + 0.5f);

+						dest[4 * i + j * outputPitch + 1] = (unsigned char)(255 * g + 0.5f);

+						dest[4 * i + j * outputPitch + 2] = (unsigned char)(255 * r + 0.5f);

+						dest[4 * i + j * outputPitch + 3] = (unsigned char)(255 * a + 0.5f);

+						break;

+					case GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT:

+						// According to the desktop GL spec in the "Transfer of Pixel Rectangles" section

+						// this type is packed as follows:

+						//   15   14   13   12   11   10    9    8    7    6    5    4    3    2    1    0

+						//  --------------------------------------------------------------------------------

+						// |       4th         |        3rd         |        2nd        |   1st component   |

+						//  --------------------------------------------------------------------------------

+						// in the case of BGRA_EXT, B is the first component, G the second, and so forth.

+						dest16[i + j * outputPitch / sizeof(unsigned short)] =

+							((unsigned short)(15 * a + 0.5f) << 12)|

+							((unsigned short)(15 * r + 0.5f) << 8) |

+							((unsigned short)(15 * g + 0.5f) << 4) |

+							((unsigned short)(15 * b + 0.5f) << 0);

+						break;

+					case GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT:

+						// According to the desktop GL spec in the "Transfer of Pixel Rectangles" section

+						// this type is packed as follows:

+						//   15   14   13   12   11   10    9    8    7    6    5    4    3    2    1    0

+						//  --------------------------------------------------------------------------------

+						// | 4th |          3rd           |           2nd          |      1st component     |

+						//  --------------------------------------------------------------------------------

+						// in the case of BGRA_EXT, B is the first component, G the second, and so forth.

+						dest16[i + j * outputPitch / sizeof(unsigned short)] =

+							((unsigned short)(     a + 0.5f) << 15) |

+							((unsigned short)(31 * r + 0.5f) << 10) |

+							((unsigned short)(31 * g + 0.5f) << 5) |

+							((unsigned short)(31 * b + 0.5f) << 0);

+						break;

+					default: UNREACHABLE();

+					}

+					break;

+				case GL_RGB:   // IMPLEMENTATION_COLOR_READ_FORMAT

+					switch(type)

+					{

+					case GL_UNSIGNED_SHORT_5_6_5:   // IMPLEMENTATION_COLOR_READ_TYPE

+						dest16[i + j * outputPitch / sizeof(unsigned short)] = 

+							((unsigned short)(31 * b + 0.5f) << 0) |

+							((unsigned short)(63 * g + 0.5f) << 5) |

+							((unsigned short)(31 * r + 0.5f) << 11);

+						break;

+					default: UNREACHABLE();

+					}

+					break;

+				default: UNREACHABLE();

+				}

+			}

+        }

+    }

+

+	renderTarget->unlock();

+	renderTarget->release();

+}

+

+void Context::clear(GLbitfield mask)

+{

+    Framebuffer *framebuffer = getDrawFramebuffer();

+

+    if(!framebuffer || framebuffer->completeness() != GL_FRAMEBUFFER_COMPLETE)

+    {

+        return error(GL_INVALID_FRAMEBUFFER_OPERATION);

+    }

+

+    if(!applyRenderTarget())

+    {

+        return;

+    }

+

+	Device *device = getDevice();

+

+	unsigned int color = (unorm<8>(mState.colorClearValue.alpha) << 24) |

+                         (unorm<8>(mState.colorClearValue.red) << 16) |

+                         (unorm<8>(mState.colorClearValue.green) << 8) | 

+                         (unorm<8>(mState.colorClearValue.blue) << 0);

+    float depth = clamp01(mState.depthClearValue);

+    int stencil = mState.stencilClearValue & 0x000000FF;

+

+	if(mask & GL_COLOR_BUFFER_BIT)

+	{

+		unsigned int rgbaMask = (mState.colorMaskRed ? 0x1 : 0) |

+		                        (mState.colorMaskGreen ? 0x2 : 0) | 

+		                        (mState.colorMaskBlue ? 0x4 : 0) |

+		                        (mState.colorMaskAlpha ? 0x8 : 0);

+		device->clearColor(color, rgbaMask);

+	}

+

+	if(mask & GL_DEPTH_BUFFER_BIT)

+	{

+		if(mState.depthMask)

+		{

+			device->clearDepth(depth);

+		}

+	}

+

+	if(mask & GL_STENCIL_BUFFER_BIT)

+	{

+		device->clearStencil(stencil, mState.stencilWritemask);

+	}

+}

+

+void Context::drawArrays(GLenum mode, GLint first, GLsizei count)

+{

+    if(!mState.currentProgram)

+    {

+        return error(GL_INVALID_OPERATION);

+    }

+

+    Device *device = getDevice();

+    PrimitiveType primitiveType;

+    int primitiveCount;

+

+    if(!es2sw::ConvertPrimitiveType(mode, count, primitiveType, primitiveCount))

+        return error(GL_INVALID_ENUM);

+

+    if(primitiveCount <= 0)

+    {

+        return;

+    }

+

+    if(!applyRenderTarget())

+    {

+        return;

+    }

+

+    applyState(mode);

+

+    GLenum err = applyVertexBuffer(0, first, count);

+    if(err != GL_NO_ERROR)

+    {

+        return error(err);

+    }

+

+    applyShaders();

+    applyTextures();

+

+    if(!getCurrentProgram()->validateSamplers(false))

+    {

+        return error(GL_INVALID_OPERATION);

+    }

+

+    if(!cullSkipsDraw(mode))

+    {

+        device->drawPrimitive(primitiveType, primitiveCount);

+    }

+}

+

+void Context::drawElements(GLenum mode, GLsizei count, GLenum type, const void *indices)

+{

+    if(!mState.currentProgram)

+    {

+        return error(GL_INVALID_OPERATION);

+    }

+

+    if(!indices && !mState.elementArrayBuffer)

+    {

+        return error(GL_INVALID_OPERATION);

+    }

+

+    Device *device = getDevice();

+    PrimitiveType primitiveType;

+    int primitiveCount;

+

+    if(!es2sw::ConvertPrimitiveType(mode, count, primitiveType, primitiveCount))

+        return error(GL_INVALID_ENUM);

+

+    if(primitiveCount <= 0)

+    {

+        return;

+    }

+

+    if(!applyRenderTarget())

+    {

+        return;

+    }

+

+    applyState(mode);

+

+    TranslatedIndexData indexInfo;

+    GLenum err = applyIndexBuffer(indices, count, mode, type, &indexInfo);

+    if(err != GL_NO_ERROR)

+    {

+        return error(err);

+    }

+

+    GLsizei vertexCount = indexInfo.maxIndex - indexInfo.minIndex + 1;

+    err = applyVertexBuffer(-(int)indexInfo.minIndex, indexInfo.minIndex, vertexCount);

+    if(err != GL_NO_ERROR)

+    {

+        return error(err);

+    }

+

+    applyShaders();

+    applyTextures();

+

+    if(!getCurrentProgram()->validateSamplers(false))

+    {

+        return error(GL_INVALID_OPERATION);

+    }

+

+    if(!cullSkipsDraw(mode))

+    {

+		device->drawIndexedPrimitive(primitiveType, indexInfo.indexOffset, primitiveCount, IndexDataManager::typeSize(type));

+    }

+}

+

+void Context::finish()

+{

+	Device *device = getDevice();

+

+	device->finish();

+}

+

+void Context::flush()

+{

+    // We don't queue anything without processing it as fast as possible

+}

+

+void Context::recordInvalidEnum()

+{

+    mInvalidEnum = true;

+}

+

+void Context::recordInvalidValue()

+{

+    mInvalidValue = true;

+}

+

+void Context::recordInvalidOperation()

+{

+    mInvalidOperation = true;

+}

+

+void Context::recordOutOfMemory()

+{

+    mOutOfMemory = true;

+}

+

+void Context::recordInvalidFramebufferOperation()

+{

+    mInvalidFramebufferOperation = true;

+}

+

+// Get one of the recorded errors and clear its flag, if any.

+// [OpenGL ES 2.0.24] section 2.5 page 13.

+GLenum Context::getError()

+{

+    if(mInvalidEnum)

+    {

+        mInvalidEnum = false;

+

+        return GL_INVALID_ENUM;

+    }

+

+    if(mInvalidValue)

+    {

+        mInvalidValue = false;

+

+        return GL_INVALID_VALUE;

+    }

+

+    if(mInvalidOperation)

+    {

+        mInvalidOperation = false;

+

+        return GL_INVALID_OPERATION;

+    }

+

+    if(mOutOfMemory)

+    {

+        mOutOfMemory = false;

+

+        return GL_OUT_OF_MEMORY;

+    }

+

+    if(mInvalidFramebufferOperation)

+    {

+        mInvalidFramebufferOperation = false;

+

+        return GL_INVALID_FRAMEBUFFER_OPERATION;

+    }

+

+    return GL_NO_ERROR;

+}

+

+int Context::getNearestSupportedSamples(sw::Format format, int requested) const

+{

+    if(requested <= 1)

+    {

+        return requested;

+    }

+	

+	if(requested <= 2)

+	{

+		return 2;

+	}

+	

+	return 4;

+}

+

+void Context::detachBuffer(GLuint buffer)

+{

+    // [OpenGL ES 2.0.24] section 2.9 page 22:

+    // If a buffer object is deleted while it is bound, all bindings to that object in the current context

+    // (i.e. in the thread that called Delete-Buffers) are reset to zero.

+

+    if(mState.arrayBuffer.id() == buffer)

+    {

+        mState.arrayBuffer.set(NULL);

+    }

+

+    if(mState.elementArrayBuffer.id() == buffer)

+    {

+        mState.elementArrayBuffer.set(NULL);

+    }

+

+    for(int attribute = 0; attribute < MAX_VERTEX_ATTRIBS; attribute++)

+    {

+        if(mState.vertexAttribute[attribute].mBoundBuffer.id() == buffer)

+        {

+            mState.vertexAttribute[attribute].mBoundBuffer.set(NULL);

+        }

+    }

+}

+

+void Context::detachTexture(GLuint texture)

+{

+    // [OpenGL ES 2.0.24] section 3.8 page 84:

+    // If a texture object is deleted, it is as if all texture units which are bound to that texture object are

+    // rebound to texture object zero

+

+    for(int type = 0; type < TEXTURE_TYPE_COUNT; type++)

+    {

+        for(int sampler = 0; sampler < MAX_COMBINED_TEXTURE_IMAGE_UNITS; sampler++)

+        {

+            if(mState.samplerTexture[type][sampler].id() == texture)

+            {

+                mState.samplerTexture[type][sampler].set(NULL);

+            }

+        }

+    }

+

+    // [OpenGL ES 2.0.24] section 4.4 page 112:

+    // If a texture object is deleted while its image is attached to the currently bound framebuffer, then it is

+    // as if FramebufferTexture2D had been called, with a texture of 0, for each attachment point to which this

+    // image was attached in the currently bound framebuffer.

+

+    Framebuffer *readFramebuffer = getReadFramebuffer();

+    Framebuffer *drawFramebuffer = getDrawFramebuffer();

+

+    if(readFramebuffer)

+    {

+        readFramebuffer->detachTexture(texture);

+    }

+

+    if(drawFramebuffer && drawFramebuffer != readFramebuffer)

+    {

+        drawFramebuffer->detachTexture(texture);

+    }

+}

+

+void Context::detachFramebuffer(GLuint framebuffer)

+{

+    // [OpenGL ES 2.0.24] section 4.4 page 107:

+    // If a framebuffer that is currently bound to the target FRAMEBUFFER is deleted, it is as though

+    // BindFramebuffer had been executed with the target of FRAMEBUFFER and framebuffer of zero.

+

+    if(mState.readFramebuffer == framebuffer)

+    {

+        bindReadFramebuffer(0);

+    }

+

+    if(mState.drawFramebuffer == framebuffer)

+    {

+        bindDrawFramebuffer(0);

+    }

+}

+

+void Context::detachRenderbuffer(GLuint renderbuffer)

+{

+    // [OpenGL ES 2.0.24] section 4.4 page 109:

+    // If a renderbuffer that is currently bound to RENDERBUFFER is deleted, it is as though BindRenderbuffer

+    // had been executed with the target RENDERBUFFER and name of zero.

+

+    if(mState.renderbuffer.id() == renderbuffer)

+    {

+        bindRenderbuffer(0);

+    }

+

+    // [OpenGL ES 2.0.24] section 4.4 page 111:

+    // If a renderbuffer object is deleted while its image is attached to the currently bound framebuffer,

+    // then it is as if FramebufferRenderbuffer had been called, with a renderbuffer of 0, for each attachment

+    // point to which this image was attached in the currently bound framebuffer.

+

+    Framebuffer *readFramebuffer = getReadFramebuffer();

+    Framebuffer *drawFramebuffer = getDrawFramebuffer();

+

+    if(readFramebuffer)

+    {

+        readFramebuffer->detachRenderbuffer(renderbuffer);

+    }

+

+    if(drawFramebuffer && drawFramebuffer != readFramebuffer)

+    {

+        drawFramebuffer->detachRenderbuffer(renderbuffer);

+    }

+}

+

+bool Context::cullSkipsDraw(GLenum drawMode)

+{

+    return mState.cullFace && mState.cullMode == GL_FRONT_AND_BACK && isTriangleMode(drawMode);

+}

+

+bool Context::isTriangleMode(GLenum drawMode)

+{

+    switch (drawMode)

+    {

+      case GL_TRIANGLES:

+      case GL_TRIANGLE_FAN:

+      case GL_TRIANGLE_STRIP:

+        return true;

+      case GL_POINTS:

+      case GL_LINES:

+      case GL_LINE_LOOP:

+      case GL_LINE_STRIP:

+        return false;

+      default: UNREACHABLE();

+    }

+

+    return false;

+}

+

+void Context::setVertexAttrib(GLuint index, const GLfloat *values)

+{

+    ASSERT(index < MAX_VERTEX_ATTRIBS);

+

+    mState.vertexAttribute[index].mCurrentValue[0] = values[0];

+    mState.vertexAttribute[index].mCurrentValue[1] = values[1];

+    mState.vertexAttribute[index].mCurrentValue[2] = values[2];

+    mState.vertexAttribute[index].mCurrentValue[3] = values[3];

+

+    mVertexDataManager->dirtyCurrentValue(index);

+}

+

+void Context::initExtensionString()

+{

+	// Keep list sorted in following order:

+	// OES extensions

+	// EXT extensions

+	// Vendor extensions

+

+	mExtensionString += "GL_OES_depth_texture ";

+	mExtensionString += "GL_OES_depth_texture_cube_map ";

+	mExtensionString += "GL_OES_element_index_uint ";

+	mExtensionString += "GL_OES_packed_depth_stencil ";

+	mExtensionString += "GL_OES_rgb8_rgba8 ";

+	mExtensionString += "GL_OES_standard_derivatives ";

+	mExtensionString += "GL_OES_texture_float ";

+	mExtensionString += "GL_OES_texture_float_linear ";

+	mExtensionString += "GL_OES_texture_half_float ";

+	mExtensionString += "GL_OES_texture_half_float_linear ";

+	mExtensionString += "GL_OES_texture_npot ";

+	mExtensionString += "GL_EXT_occlusion_query_boolean ";

+	mExtensionString += "GL_EXT_read_format_bgra ";

+	

+	if(S3TC_SUPPORT)

+	{

+		mExtensionString += "GL_EXT_texture_compression_dxt1 ";

+		mExtensionString += "GL_ANGLE_texture_compression_dxt3 ";

+		mExtensionString += "GL_ANGLE_texture_compression_dxt5 ";

+	}

+

+	mExtensionString += "GL_EXT_texture_filter_anisotropic ";

+	mExtensionString += "GL_EXT_texture_format_BGRA8888 ";

+	mExtensionString += "GL_ANGLE_framebuffer_blit ";

+	mExtensionString += "GL_ANGLE_framebuffer_multisample ";

+	mExtensionString += "GL_NV_fence ";

+

+	std::string::size_type end = mExtensionString.find_last_not_of(' ');

+	if(end != std::string::npos)

+	{

+		mExtensionString.resize(end + 1);

+	}

+}

+

+const char *Context::getExtensionString() const

+{

+    return mExtensionString.c_str();

+}

+

+void Context::blitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, 

+                              GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,

+                              GLbitfield mask)

+{

+    Device *device = getDevice();

+

+    Framebuffer *readFramebuffer = getReadFramebuffer();

+    Framebuffer *drawFramebuffer = getDrawFramebuffer();

+

+	int readBufferWidth, readBufferHeight, readBufferSamples;

+    int drawBufferWidth, drawBufferHeight, drawBufferSamples;

+

+    if(!readFramebuffer || readFramebuffer->completeness(readBufferWidth, readBufferHeight, readBufferSamples) != GL_FRAMEBUFFER_COMPLETE ||

+       !drawFramebuffer || drawFramebuffer->completeness(drawBufferWidth, drawBufferHeight, drawBufferSamples) != GL_FRAMEBUFFER_COMPLETE)

+    {

+        return error(GL_INVALID_FRAMEBUFFER_OPERATION);

+    }

+

+    if(drawBufferSamples != 0)

+    {

+        return error(GL_INVALID_OPERATION);

+    }

+

+    sw::Rect sourceRect;

+    sw::Rect destRect;

+

+    if(srcX0 < srcX1)

+    {

+        sourceRect.x0 = srcX0;

+        sourceRect.x1 = srcX1;

+        destRect.x0 = dstX0;

+        destRect.x1 = dstX1;

+    }

+    else

+    {

+        sourceRect.x0 = srcX1;

+        destRect.x0 = dstX1;

+        sourceRect.x1 = srcX0;

+        destRect.x1 = dstX0;

+    }

+

+    if(srcY0 < srcY1)

+    {

+        sourceRect.y0 = srcY0;

+        destRect.y0 = dstY0;

+        sourceRect.y1 = srcY1;

+        destRect.y1 = dstY1;

+    }

+    else

+    {

+        sourceRect.y0 = srcY1;

+        destRect.y0 = dstY1;

+        sourceRect.y1 = srcY0;

+        destRect.y1 = dstY0;

+    }

+

+    sw::Rect sourceScissoredRect = sourceRect;

+    sw::Rect destScissoredRect = destRect;

+

+    if(mState.scissorTest)   // Only write to parts of the destination framebuffer which pass the scissor test

+    {

+        if(destRect.x0 < mState.scissorX)

+        {

+            int xDiff = mState.scissorX - destRect.x0;

+            destScissoredRect.x0 = mState.scissorX;

+            sourceScissoredRect.x0 += xDiff;

+        }

+

+        if(destRect.x1 > mState.scissorX + mState.scissorWidth)

+        {

+            int xDiff = destRect.x1 - (mState.scissorX + mState.scissorWidth);

+            destScissoredRect.x1 = mState.scissorX + mState.scissorWidth;

+            sourceScissoredRect.x1 -= xDiff;

+        }

+

+        if(destRect.y0 < mState.scissorY)

+        {

+            int yDiff = mState.scissorY - destRect.y0;

+            destScissoredRect.y0 = mState.scissorY;

+            sourceScissoredRect.y0 += yDiff;

+        }

+

+        if(destRect.y1 > mState.scissorY + mState.scissorHeight)

+        {

+            int yDiff = destRect.y1 - (mState.scissorY + mState.scissorHeight);

+            destScissoredRect.y1 = mState.scissorY + mState.scissorHeight;

+            sourceScissoredRect.y1 -= yDiff;

+        }

+    }

+

+    sw::Rect sourceTrimmedRect = sourceScissoredRect;

+    sw::Rect destTrimmedRect = destScissoredRect;

+

+    // The source & destination rectangles also may need to be trimmed if they fall out of the bounds of 

+    // the actual draw and read surfaces.

+    if(sourceTrimmedRect.x0 < 0)

+    {

+        int xDiff = 0 - sourceTrimmedRect.x0;

+        sourceTrimmedRect.x0 = 0;

+        destTrimmedRect.x0 += xDiff;

+    }

+

+    if(sourceTrimmedRect.x1 > readBufferWidth)

+    {

+        int xDiff = sourceTrimmedRect.x1 - readBufferWidth;

+        sourceTrimmedRect.x1 = readBufferWidth;

+        destTrimmedRect.x1 -= xDiff;

+    }

+

+    if(sourceTrimmedRect.y0 < 0)

+    {

+        int yDiff = 0 - sourceTrimmedRect.y0;

+        sourceTrimmedRect.y0 = 0;

+        destTrimmedRect.y0 += yDiff;

+    }

+

+    if(sourceTrimmedRect.y1 > readBufferHeight)

+    {

+        int yDiff = sourceTrimmedRect.y1 - readBufferHeight;

+        sourceTrimmedRect.y1 = readBufferHeight;

+        destTrimmedRect.y1 -= yDiff;

+    }

+

+    if(destTrimmedRect.x0 < 0)

+    {

+        int xDiff = 0 - destTrimmedRect.x0;

+        destTrimmedRect.x0 = 0;

+        sourceTrimmedRect.x0 += xDiff;

+    }

+

+    if(destTrimmedRect.x1 > drawBufferWidth)

+    {

+        int xDiff = destTrimmedRect.x1 - drawBufferWidth;

+        destTrimmedRect.x1 = drawBufferWidth;

+        sourceTrimmedRect.x1 -= xDiff;

+    }

+

+    if(destTrimmedRect.y0 < 0)

+    {

+        int yDiff = 0 - destTrimmedRect.y0;

+        destTrimmedRect.y0 = 0;

+        sourceTrimmedRect.y0 += yDiff;

+    }

+

+    if(destTrimmedRect.y1 > drawBufferHeight)

+    {

+        int yDiff = destTrimmedRect.y1 - drawBufferHeight;

+        destTrimmedRect.y1 = drawBufferHeight;

+        sourceTrimmedRect.y1 -= yDiff;

+    }

+

+    bool partialBufferCopy = false;

+

+    if(sourceTrimmedRect.y1 - sourceTrimmedRect.y0 < readBufferHeight ||

+       sourceTrimmedRect.x1 - sourceTrimmedRect.x0 < readBufferWidth || 

+       destTrimmedRect.y1 - destTrimmedRect.y0 < drawBufferHeight ||

+       destTrimmedRect.x1 - destTrimmedRect.x0 < drawBufferWidth ||

+       sourceTrimmedRect.y0 != 0 || destTrimmedRect.y0 != 0 || sourceTrimmedRect.x0 != 0 || destTrimmedRect.x0 != 0)

+    {

+        partialBufferCopy = true;

+    }

+

+	bool blitRenderTarget = false;

+    bool blitDepthStencil = false;

+

+    if(mask & GL_COLOR_BUFFER_BIT)

+    {

+        const bool validReadType = readFramebuffer->getColorbufferType() == GL_TEXTURE_2D ||

+                                   readFramebuffer->getColorbufferType() == GL_RENDERBUFFER;

+        const bool validDrawType = drawFramebuffer->getColorbufferType() == GL_TEXTURE_2D ||

+                                   drawFramebuffer->getColorbufferType() == GL_RENDERBUFFER;

+        if(!validReadType || !validDrawType ||

+           readFramebuffer->getColorbuffer()->getInternalFormat() != drawFramebuffer->getColorbuffer()->getInternalFormat())

+        {

+            ERR("Color buffer format conversion in BlitFramebufferANGLE not supported by this implementation");

+            return error(GL_INVALID_OPERATION);

+        }

+        

+        if(partialBufferCopy && readBufferSamples != 0)

+        {

+            return error(GL_INVALID_OPERATION);

+        }

+

+        blitRenderTarget = true;

+    }

+

+    if(mask & (GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT))

+    {

+        Renderbuffer *readDSBuffer = NULL;

+        Renderbuffer *drawDSBuffer = NULL;

+

+        // We support OES_packed_depth_stencil, and do not support a separately attached depth and stencil buffer, so if we have

+        // both a depth and stencil buffer, it will be the same buffer.

+

+        if(mask & GL_DEPTH_BUFFER_BIT)

+        {

+            if(readFramebuffer->getDepthbuffer() && drawFramebuffer->getDepthbuffer())

+            {

+                if(readFramebuffer->getDepthbufferType() != drawFramebuffer->getDepthbufferType() ||

+                   readFramebuffer->getDepthbuffer()->getInternalFormat() != drawFramebuffer->getDepthbuffer()->getInternalFormat())

+                {

+                    return error(GL_INVALID_OPERATION);

+                }

+

+                blitDepthStencil = true;

+                readDSBuffer = readFramebuffer->getDepthbuffer();

+                drawDSBuffer = drawFramebuffer->getDepthbuffer();

+            }

+        }

+

+        if(mask & GL_STENCIL_BUFFER_BIT)

+        {

+            if(readFramebuffer->getStencilbuffer() && drawFramebuffer->getStencilbuffer())

+            {

+                if(readFramebuffer->getStencilbufferType() != drawFramebuffer->getStencilbufferType() ||

+                   readFramebuffer->getStencilbuffer()->getInternalFormat() != drawFramebuffer->getStencilbuffer()->getInternalFormat())

+                {

+                    return error(GL_INVALID_OPERATION);

+                }

+

+                blitDepthStencil = true;

+                readDSBuffer = readFramebuffer->getStencilbuffer();

+                drawDSBuffer = drawFramebuffer->getStencilbuffer();

+            }

+        }

+

+        if(partialBufferCopy)

+        {

+            ERR("Only whole-buffer depth and stencil blits are supported by this implementation.");

+            return error(GL_INVALID_OPERATION);   // Only whole-buffer copies are permitted

+        }

+

+        if((drawDSBuffer && drawDSBuffer->getSamples() != 0) || 

+           (readDSBuffer && readDSBuffer->getSamples() != 0))

+        {

+            return error(GL_INVALID_OPERATION);

+        }

+    }

+

+    if(blitRenderTarget || blitDepthStencil)

+    {

+        if(blitRenderTarget)

+        {

+            Image *readRenderTarget = readFramebuffer->getRenderTarget();

+            Image *drawRenderTarget = drawFramebuffer->getRenderTarget();

+ 

+            bool success = device->stretchRect(readRenderTarget, &sourceRect, drawRenderTarget, &destRect, false);

+

+            readRenderTarget->release();

+            drawRenderTarget->release();

+

+            if(!success)

+            {

+                ERR("BlitFramebufferANGLE failed.");

+                return;

+            }

+        }

+

+        if(blitDepthStencil)

+        {

+            bool success = device->stretchRect(readFramebuffer->getDepthStencil(), NULL, drawFramebuffer->getDepthStencil(), NULL, false);

+

+            if(!success)

+            {

+                ERR("BlitFramebufferANGLE failed.");

+                return;

+            }

+        }

+    }

+}

+

+}

+

+// Exported functions for use by EGL

+extern "C"

+{

+	gl::Context *glCreateContext(const egl::Config *config, const gl::Context *shareContext)

+	{

+		return new gl::Context(config, shareContext);

+	}

+

+	void glDestroyContext(gl::Context *context)

+	{

+		delete context;

+

+		if(context == gl::getContext())

+		{

+			gl::makeCurrent(NULL, NULL, NULL);

+		}

+	}

+

+	void glMakeCurrent(gl::Context *context, egl::Display *display, egl::Surface *surface)

+	{

+		gl::makeCurrent(context, display, surface);

+	}

+

+	gl::Context *glGetCurrentContext()

+	{

+		return gl::getContext();

+	}

+}

diff --git a/src/GLES2/libGLESv2/Context.h b/src/GLES2/libGLESv2/Context.h
new file mode 100644
index 0000000..1ca0d55
--- /dev/null
+++ b/src/GLES2/libGLESv2/Context.h
@@ -0,0 +1,488 @@
+// SwiftShader Software Renderer

+//

+// Copyright(c) 2005-2013 TransGaming Inc.

+//

+// All rights reserved. No part of this software may be copied, distributed, transmitted,

+// transcribed, stored in a retrieval system, translated into any human or computer

+// language by any means, or disclosed to third parties without the explicit written

+// agreement of TransGaming Inc. Without such an agreement, no rights or licenses, express

+// or implied, including but not limited to any patent rights, are granted to you.

+//

+

+// Context.h: Defines the Context class, managing all GL state and performing

+// rendering operations. It is the GLES2 specific implementation of EGLContext.

+

+#ifndef LIBGLESV2_CONTEXT_H_

+#define LIBGLESV2_CONTEXT_H_

+

+#include "ResourceManager.h"

+#include "HandleAllocator.h"

+#include "RefCountObject.h"

+#include "Image.hpp"

+#include "Renderer/Sampler.hpp"

+

+#define GL_APICALL

+#include <GLES2/gl2.h>

+#include <GLES2/gl2ext.h>

+#define EGLAPI

+#include <EGL/egl.h>

+

+#include <map>

+#include <string>

+

+namespace egl

+{

+class Display;

+class Surface;

+class Config;

+}

+

+namespace gl

+{

+struct TranslatedAttribute;

+struct TranslatedIndexData;

+

+class Buffer;

+class Shader;

+class Program;

+class Texture;

+class Texture2D;

+class TextureCubeMap;

+class Framebuffer;

+class Renderbuffer;

+class RenderbufferStorage;

+class Colorbuffer;

+class Depthbuffer;

+class StreamingIndexBuffer;

+class Stencilbuffer;

+class DepthStencilbuffer;

+class VertexDataManager;

+class IndexDataManager;

+class Fence;

+class Query;

+

+enum

+{

+    MAX_VERTEX_ATTRIBS = 16,

+	MAX_UNIFORM_VECTORS = 256,   // Device limit

+    MAX_VERTEX_UNIFORM_VECTORS = 256 - 3,   // Reserve space for gl_DepthRange

+    MAX_VARYING_VECTORS = 10,

+    MAX_TEXTURE_IMAGE_UNITS = 16,

+    MAX_VERTEX_TEXTURE_IMAGE_UNITS = 4,

+    MAX_COMBINED_TEXTURE_IMAGE_UNITS = MAX_TEXTURE_IMAGE_UNITS + MAX_VERTEX_TEXTURE_IMAGE_UNITS,

+    MAX_FRAGMENT_UNIFORM_VECTORS = 224 - 3,    // Reserve space for gl_DepthRange

+    MAX_DRAW_BUFFERS = 1,

+

+    IMPLEMENTATION_COLOR_READ_FORMAT = GL_RGB,

+    IMPLEMENTATION_COLOR_READ_TYPE = GL_UNSIGNED_SHORT_5_6_5

+};

+

+enum QueryType

+{

+    QUERY_ANY_SAMPLES_PASSED,

+    QUERY_ANY_SAMPLES_PASSED_CONSERVATIVE,

+

+    QUERY_TYPE_COUNT

+};

+

+const float ALIASED_LINE_WIDTH_RANGE_MIN = 1.0f;

+const float ALIASED_LINE_WIDTH_RANGE_MAX = 1.0f;

+const float ALIASED_POINT_SIZE_RANGE_MIN = 0.125f;

+const float ALIASED_POINT_SIZE_RANGE_MAX = 8192.0f;

+const float MAX_TEXTURE_MAX_ANISOTROPY = 16.0f;

+

+struct Color

+{

+    float red;

+    float green;

+    float blue;

+    float alpha;

+};

+

+// Helper structure describing a single vertex attribute

+class VertexAttribute

+{

+  public:

+    VertexAttribute() : mType(GL_FLOAT), mSize(0), mNormalized(false), mStride(0), mPointer(NULL), mArrayEnabled(false)

+    {

+        mCurrentValue[0] = 0.0f;

+        mCurrentValue[1] = 0.0f;

+        mCurrentValue[2] = 0.0f;

+        mCurrentValue[3] = 1.0f;

+    }

+

+    int typeSize() const

+    {

+        switch (mType)

+        {

+        case GL_BYTE:           return mSize * sizeof(GLbyte);

+        case GL_UNSIGNED_BYTE:  return mSize * sizeof(GLubyte);

+        case GL_SHORT:          return mSize * sizeof(GLshort);

+        case GL_UNSIGNED_SHORT: return mSize * sizeof(GLushort);

+        case GL_FIXED:          return mSize * sizeof(GLfixed);

+        case GL_FLOAT:          return mSize * sizeof(GLfloat);

+        default: UNREACHABLE(); return mSize * sizeof(GLfloat);

+        }

+    }

+

+    GLsizei stride() const

+    {

+        return mStride ? mStride : typeSize();

+    }

+

+    // From glVertexAttribPointer

+    GLenum mType;

+    GLint mSize;

+    bool mNormalized;

+    GLsizei mStride;   // 0 means natural stride

+

+    union

+    {

+        const void *mPointer;

+        intptr_t mOffset;

+    };

+

+    BindingPointer<Buffer> mBoundBuffer;   // Captured when glVertexAttribPointer is called.

+

+    bool mArrayEnabled;   // From glEnable/DisableVertexAttribArray

+    float mCurrentValue[4];   // From glVertexAttrib

+};

+

+typedef VertexAttribute VertexAttributeArray[MAX_VERTEX_ATTRIBS];

+

+// Helper structure to store all raw state

+struct State

+{

+    Color colorClearValue;

+    GLclampf depthClearValue;

+    int stencilClearValue;

+

+    bool cullFace;

+    GLenum cullMode;

+    GLenum frontFace;

+    bool depthTest;

+    GLenum depthFunc;

+    bool blend;

+    GLenum sourceBlendRGB;

+    GLenum destBlendRGB;

+    GLenum sourceBlendAlpha;

+    GLenum destBlendAlpha;

+    GLenum blendEquationRGB;

+    GLenum blendEquationAlpha;

+    Color blendColor;

+    bool stencilTest;

+    GLenum stencilFunc;

+    GLint stencilRef;

+    GLuint stencilMask;

+    GLenum stencilFail;

+    GLenum stencilPassDepthFail;

+    GLenum stencilPassDepthPass;

+    GLuint stencilWritemask;

+    GLenum stencilBackFunc;

+    GLint stencilBackRef;

+    GLuint stencilBackMask;

+    GLenum stencilBackFail;

+    GLenum stencilBackPassDepthFail;

+    GLenum stencilBackPassDepthPass;

+    GLuint stencilBackWritemask;

+    bool polygonOffsetFill;

+    GLfloat polygonOffsetFactor;

+    GLfloat polygonOffsetUnits;

+    bool sampleAlphaToCoverage;

+    bool sampleCoverage;

+    GLclampf sampleCoverageValue;

+    bool sampleCoverageInvert;

+    bool scissorTest;

+    bool dither;

+

+    GLfloat lineWidth;

+

+    GLenum generateMipmapHint;

+    GLenum fragmentShaderDerivativeHint;

+

+    GLint viewportX;

+    GLint viewportY;

+    GLsizei viewportWidth;

+    GLsizei viewportHeight;

+    float zNear;

+    float zFar;

+

+    GLint scissorX;

+    GLint scissorY;

+    GLsizei scissorWidth;

+    GLsizei scissorHeight;

+

+    bool colorMaskRed;

+    bool colorMaskGreen;

+    bool colorMaskBlue;

+    bool colorMaskAlpha;

+    bool depthMask;

+

+    unsigned int activeSampler;   // Active texture unit selector - GL_TEXTURE0

+    BindingPointer<Buffer> arrayBuffer;

+    BindingPointer<Buffer> elementArrayBuffer;

+    GLuint readFramebuffer;

+    GLuint drawFramebuffer;

+    BindingPointer<Renderbuffer> renderbuffer;

+    GLuint currentProgram;

+

+    VertexAttribute vertexAttribute[MAX_VERTEX_ATTRIBS];

+    BindingPointer<Texture> samplerTexture[TEXTURE_TYPE_COUNT][MAX_COMBINED_TEXTURE_IMAGE_UNITS];

+	BindingPointer<Query> activeQuery[QUERY_TYPE_COUNT];

+

+    GLint unpackAlignment;

+    GLint packAlignment;

+};

+

+class Context

+{

+  public:

+    Context(const egl::Config *config, const Context *shareContext);

+

+    ~Context();

+

+    void makeCurrent(egl::Display *display, egl::Surface *surface);

+

+    void markAllStateDirty();

+

+    // State manipulation

+    void setClearColor(float red, float green, float blue, float alpha);

+    void setClearDepth(float depth);

+    void setClearStencil(int stencil);

+

+    void setCullFace(bool enabled);

+    bool isCullFaceEnabled() const;

+    void setCullMode(GLenum mode);

+    void setFrontFace(GLenum front);

+

+    void setDepthTest(bool enabled);

+    bool isDepthTestEnabled() const;

+    void setDepthFunc(GLenum depthFunc);

+    void setDepthRange(float zNear, float zFar);

+    

+    void setBlend(bool enabled);

+    bool isBlendEnabled() const;

+    void setBlendFactors(GLenum sourceRGB, GLenum destRGB, GLenum sourceAlpha, GLenum destAlpha);

+    void setBlendColor(float red, float green, float blue, float alpha);

+    void setBlendEquation(GLenum rgbEquation, GLenum alphaEquation);

+

+    void setStencilTest(bool enabled);

+    bool isStencilTestEnabled() const;

+    void setStencilParams(GLenum stencilFunc, GLint stencilRef, GLuint stencilMask);

+    void setStencilBackParams(GLenum stencilBackFunc, GLint stencilBackRef, GLuint stencilBackMask);

+    void setStencilWritemask(GLuint stencilWritemask);

+    void setStencilBackWritemask(GLuint stencilBackWritemask);

+    void setStencilOperations(GLenum stencilFail, GLenum stencilPassDepthFail, GLenum stencilPassDepthPass);

+    void setStencilBackOperations(GLenum stencilBackFail, GLenum stencilBackPassDepthFail, GLenum stencilBackPassDepthPass);

+

+    void setPolygonOffsetFill(bool enabled);

+    bool isPolygonOffsetFillEnabled() const;

+    void setPolygonOffsetParams(GLfloat factor, GLfloat units);

+

+    void setSampleAlphaToCoverage(bool enabled);

+    bool isSampleAlphaToCoverageEnabled() const;

+    void setSampleCoverage(bool enabled);

+    bool isSampleCoverageEnabled() const;

+    void setSampleCoverageParams(GLclampf value, bool invert);

+

+    void setDither(bool enabled);

+    bool isDitherEnabled() const;

+

+    void setLineWidth(GLfloat width);

+

+    void setGenerateMipmapHint(GLenum hint);

+    void setFragmentShaderDerivativeHint(GLenum hint);

+

+    void setViewportParams(GLint x, GLint y, GLsizei width, GLsizei height);

+

+	void setScissorTest(bool enabled);

+    bool isScissorTestEnabled() const;

+    void setScissorParams(GLint x, GLint y, GLsizei width, GLsizei height);

+

+    void setColorMask(bool red, bool green, bool blue, bool alpha);

+    void setDepthMask(bool mask);

+

+    void setActiveSampler(unsigned int active);

+

+    GLuint getReadFramebufferHandle() const;

+    GLuint getDrawFramebufferHandle() const;

+    GLuint getRenderbufferHandle() const;

+

+	GLuint getActiveQuery(GLenum target) const;

+

+    GLuint getArrayBufferHandle() const;

+

+    void setEnableVertexAttribArray(unsigned int attribNum, bool enabled);

+    const VertexAttribute &getVertexAttribState(unsigned int attribNum);

+    void setVertexAttribState(unsigned int attribNum, Buffer *boundBuffer, GLint size, GLenum type,

+                              bool normalized, GLsizei stride, const void *pointer);

+    const void *getVertexAttribPointer(unsigned int attribNum) const;

+

+    const VertexAttributeArray &getVertexAttributes();

+

+    void setUnpackAlignment(GLint alignment);

+    GLint getUnpackAlignment() const;

+

+    void setPackAlignment(GLint alignment);

+    GLint getPackAlignment() const;

+

+    // These create  and destroy methods are merely pass-throughs to 

+    // ResourceManager, which owns these object types

+    GLuint createBuffer();

+    GLuint createShader(GLenum type);

+    GLuint createProgram();

+    GLuint createTexture();

+    GLuint createRenderbuffer();

+

+    void deleteBuffer(GLuint buffer);

+    void deleteShader(GLuint shader);

+    void deleteProgram(GLuint program);

+    void deleteTexture(GLuint texture);

+    void deleteRenderbuffer(GLuint renderbuffer);

+

+    // Framebuffers are owned by the Context, so these methods do not pass through

+    GLuint createFramebuffer();

+    void deleteFramebuffer(GLuint framebuffer);

+

+    // Fences are owned by the Context

+    GLuint createFence();

+    void deleteFence(GLuint fence);

+

+	// Queries are owned by the Context

+    GLuint createQuery();

+    void deleteQuery(GLuint query);

+

+    void bindArrayBuffer(GLuint buffer);

+    void bindElementArrayBuffer(GLuint buffer);

+    void bindTexture2D(GLuint texture);

+    void bindTextureCubeMap(GLuint texture);

+    void bindReadFramebuffer(GLuint framebuffer);

+    void bindDrawFramebuffer(GLuint framebuffer);

+    void bindRenderbuffer(GLuint renderbuffer);

+    void useProgram(GLuint program);

+

+	void beginQuery(GLenum target, GLuint query);

+    void endQuery(GLenum target);

+

+    void setFramebufferZero(Framebuffer *framebuffer);

+

+    void setRenderbufferStorage(RenderbufferStorage *renderbuffer);

+

+    void setVertexAttrib(GLuint index, const GLfloat *values);

+

+    Buffer *getBuffer(GLuint handle);

+    Fence *getFence(GLuint handle);

+    Shader *getShader(GLuint handle);

+    Program *getProgram(GLuint handle);

+    Texture *getTexture(GLuint handle);

+    Framebuffer *getFramebuffer(GLuint handle);

+    Renderbuffer *getRenderbuffer(GLuint handle);

+	Query *getQuery(GLuint handle, bool create, GLenum type);

+

+    Buffer *getArrayBuffer();

+    Buffer *getElementArrayBuffer();

+    Program *getCurrentProgram();

+    Texture2D *getTexture2D();

+    TextureCubeMap *getTextureCubeMap();

+    Texture *getSamplerTexture(unsigned int sampler, TextureType type);

+    Framebuffer *getReadFramebuffer();

+    Framebuffer *getDrawFramebuffer();

+

+    bool getFloatv(GLenum pname, GLfloat *params);

+    bool getIntegerv(GLenum pname, GLint *params);

+    bool getBooleanv(GLenum pname, GLboolean *params);

+

+    bool getQueryParameterInfo(GLenum pname, GLenum *type, unsigned int *numParams);

+

+    void readPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLsizei *bufSize, void* pixels);

+    void clear(GLbitfield mask);

+    void drawArrays(GLenum mode, GLint first, GLsizei count);

+    void drawElements(GLenum mode, GLsizei count, GLenum type, const void *indices);

+    void finish();

+    void flush();

+

+    void recordInvalidEnum();

+    void recordInvalidValue();

+    void recordInvalidOperation();

+    void recordOutOfMemory();

+    void recordInvalidFramebufferOperation();

+

+    GLenum getError();

+

+    int getNearestSupportedSamples(sw::Format format, int requested) const;

+    const char *getExtensionString() const;

+    

+    void blitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, 

+                         GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,

+                         GLbitfield mask);

+

+  private:

+    bool applyRenderTarget();

+    void applyState(GLenum drawMode);

+    GLenum applyVertexBuffer(GLint base, GLint first, GLsizei count);

+    GLenum applyIndexBuffer(const void *indices, GLsizei count, GLenum mode, GLenum type, TranslatedIndexData *indexInfo);

+    void applyShaders();

+    void applyTextures();

+    void applyTextures(sw::SamplerType type);

+	void applyTexture(sw::SamplerType type, int sampler, Texture *texture);

+

+    void detachBuffer(GLuint buffer);

+    void detachTexture(GLuint texture);

+    void detachFramebuffer(GLuint framebuffer);

+    void detachRenderbuffer(GLuint renderbuffer);

+

+    bool cullSkipsDraw(GLenum drawMode);

+    bool isTriangleMode(GLenum drawMode);

+

+    const egl::Config *const mConfig;

+

+    State mState;

+

+    BindingPointer<Texture2D> mTexture2DZero;

+    BindingPointer<TextureCubeMap> mTextureCubeMapZero;

+

+    typedef std::map<GLint, Framebuffer*> FramebufferMap;

+    FramebufferMap mFramebufferMap;

+    HandleAllocator mFramebufferHandleAllocator;

+

+    typedef std::map<GLint, Fence*> FenceMap;

+    FenceMap mFenceMap;

+    HandleAllocator mFenceHandleAllocator;

+

+	typedef std::map<GLint, Query*> QueryMap;

+    QueryMap mQueryMap;

+    HandleAllocator mQueryHandleAllocator;

+

+    void initExtensionString();

+    std::string mExtensionString;

+

+    VertexDataManager *mVertexDataManager;

+    IndexDataManager *mIndexDataManager;

+

+    // Recorded errors

+    bool mInvalidEnum;

+    bool mInvalidValue;

+    bool mInvalidOperation;

+    bool mOutOfMemory;

+    bool mInvalidFramebufferOperation;

+

+    bool mHasBeenCurrent;

+

+    unsigned int mAppliedProgramSerial;

+    

+    // state caching flags

+    bool mDepthStateDirty;

+    bool mMaskStateDirty;

+    bool mPixelPackingStateDirty;

+    bool mBlendStateDirty;

+    bool mStencilStateDirty;

+    bool mPolygonOffsetStateDirty;

+    bool mSampleStateDirty;

+    bool mFrontFaceDirty;

+    bool mDitherStateDirty;

+

+    ResourceManager *mResourceManager;

+};

+}

+

+#endif   // INCLUDE_CONTEXT_H_

diff --git a/src/GLES2/libGLESv2/Device.cpp b/src/GLES2/libGLESv2/Device.cpp
new file mode 100644
index 0000000..64b888d
--- /dev/null
+++ b/src/GLES2/libGLESv2/Device.cpp
@@ -0,0 +1,805 @@
+// SwiftShader Software Renderer

+//

+// Copyright(c) 2005-2013 TransGaming Inc.

+//

+// All rights reserved. No part of this software may be copied, distributed, transmitted,

+// transcribed, stored in a retrieval system, translated into any human or computer

+// language by any means, or disclosed to third parties without the explicit written

+// agreement of TransGaming Inc. Without such an agreement, no rights or licenses, express

+// or implied, including but not limited to any patent rights, are granted to you.

+//

+

+#include "Device.hpp"

+

+#include "Image.hpp"

+#include "Texture.h"

+

+#include "Renderer/Renderer.hpp"

+#include "Renderer/Clipper.hpp"

+#include "Shader/PixelShader.hpp"

+#include "Shader/VertexShader.hpp"

+#include "Main/Config.hpp"

+#include "Main/FrameBuffer.hpp"

+#include "Common/Math.hpp"

+#include "Common/Configurator.hpp"

+#include "Common/Timer.hpp"

+#include "../common/debug.h"

+

+bool localShaderConstants = false;

+

+namespace gl

+{

+	using namespace sw;

+

+	Device::Device(Context *context) : Renderer(context, true, true, true, true, true), context(context)

+	{

+		depthStencil = 0;

+		renderTarget = 0;

+

+		setDepthBufferEnable(true);

+		setFillMode(Context::FILL_SOLID);

+		setShadingMode(Context::SHADING_GOURAUD);

+		setDepthWriteEnable(true);

+		setAlphaTestEnable(false);

+		setSourceBlendFactor(Context::BLEND_ONE);

+		setDestBlendFactor(Context::BLEND_ZERO);

+		setCullMode(Context::CULL_COUNTERCLOCKWISE);

+		setDepthCompare(Context::DEPTH_LESSEQUAL);

+		setAlphaReference(0);

+		setAlphaCompare(Context::ALPHA_ALWAYS);

+		setAlphaBlendEnable(false);

+		setFogEnable(false);

+		setSpecularEnable(false);

+		setFogColor(0);

+		setPixelFogMode(Context::FOG_NONE);

+		setFogStart(0.0f);

+		setFogEnd(1.0f);

+		setFogDensity(1.0f);

+		setRangeFogEnable(false);

+		setStencilEnable(false);

+		setStencilFailOperation(Context::OPERATION_KEEP);

+		setStencilZFailOperation(Context::OPERATION_KEEP);

+		setStencilPassOperation(Context::OPERATION_KEEP);

+		setStencilCompare(Context::STENCIL_ALWAYS);

+		setStencilReference(0);

+		setStencilMask(0xFFFFFFFF);

+		setStencilWriteMask(0xFFFFFFFF);

+		setVertexFogMode(Context::FOG_NONE);

+		setClipFlags(0);

+		setPointSize(1.0f);

+		setPointSizeMin(0.125f);

+		setPointSpriteEnable(false);

+        setPointSizeMax(8192.0f);

+		setColorWriteMask(0, 0x0000000F);

+		setBlendOperation(Context::BLENDOP_ADD);

+		scissorEnable = false;

+		setSlopeDepthBias(0.0f);

+		setTwoSidedStencil(false);

+		setStencilFailOperationCCW(Context::OPERATION_KEEP);

+		setStencilZFailOperationCCW(Context::OPERATION_KEEP);

+		setStencilPassOperationCCW(Context::OPERATION_KEEP);

+		setStencilCompareCCW(Context::STENCIL_ALWAYS);

+		setColorWriteMask(1, 0x0000000F);

+		setColorWriteMask(2, 0x0000000F);

+		setColorWriteMask(3, 0x0000000F);

+		setBlendConstant(0xFFFFFFFF);

+		setWriteSRGB(false);

+		setDepthBias(0.0f);

+		setSeparateAlphaBlendEnable(false);

+		setSourceBlendFactorAlpha(Context::BLEND_ONE);

+		setDestBlendFactorAlpha(Context::BLEND_ZERO);

+		setBlendOperationAlpha(Context::BLENDOP_ADD);

+

+		for(int i = 0; i < 16; i++)

+		{

+			setAddressingModeU(sw::SAMPLER_PIXEL, i, ADDRESSING_WRAP);

+			setAddressingModeV(sw::SAMPLER_PIXEL, i, ADDRESSING_WRAP);

+			setAddressingModeW(sw::SAMPLER_PIXEL, i, ADDRESSING_WRAP);

+			setBorderColor(sw::SAMPLER_PIXEL, i, 0x00000000);

+			setTextureFilter(sw::SAMPLER_PIXEL, i, FILTER_POINT);

+			setMipmapFilter(sw::SAMPLER_PIXEL, i, MIPMAP_NONE);

+			setMipmapLOD(sw::SAMPLER_PIXEL, i, 0.0f);

+		}

+

+		for(int i = 0; i < 4; i++)

+		{

+			setAddressingModeU(sw::SAMPLER_VERTEX, i, ADDRESSING_WRAP);

+			setAddressingModeV(sw::SAMPLER_VERTEX, i, ADDRESSING_WRAP);

+			setAddressingModeW(sw::SAMPLER_VERTEX, i, ADDRESSING_WRAP);

+			setBorderColor(sw::SAMPLER_VERTEX, i, 0x00000000);

+			setTextureFilter(sw::SAMPLER_VERTEX, i, FILTER_POINT);

+			setMipmapFilter(sw::SAMPLER_VERTEX, i, MIPMAP_NONE);

+			setMipmapLOD(sw::SAMPLER_VERTEX, i, 0.0f);

+		}

+

+		for(int i = 0; i < 6; i++)

+		{

+			float plane[4] = {0, 0, 0, 0};

+

+			setClipPlane(i, plane);

+		}

+

+		pixelShader = 0;

+		vertexShader = 0;

+

+		pixelShaderDirty = true;

+		pixelShaderConstantsFDirty = 0;

+		vertexShaderDirty = true;

+		vertexShaderConstantsFDirty = 0;

+

+		for(int i = 0; i < 224; i++)

+		{

+			float zero[4] = {0, 0, 0, 0};

+

+			setPixelShaderConstantF(i, zero, 1);

+		}

+

+		for(int i = 0; i < 256; i++)

+		{

+			float zero[4] = {0, 0, 0, 0};

+

+			setVertexShaderConstantF(i, zero, 1);

+		}

+	}

+

+	Device::~Device()

+	{		

+		if(depthStencil)

+		{

+			depthStencil->release();

+			depthStencil = 0;

+		}

+		

+		if(renderTarget)

+		{

+			renderTarget->release();

+			renderTarget = 0;

+		}

+

+		delete context;

+	}

+

+	void Device::clearColor(unsigned int color, unsigned int rgbaMask)

+	{

+		TRACE("unsigned long color = 0x%0.8X", color);

+

+		if(!renderTarget)

+		{

+			return;

+		}

+

+		int x0 = 0;

+		int y0 = 0;

+		int width = renderTarget->getExternalWidth();

+		int height = renderTarget->getExternalHeight();

+

+		if(scissorEnable)   // Clamp against scissor rectangle

+		{

+			if(x0 < scissorRect.x0) x0 = scissorRect.x0;

+			if(y0 < scissorRect.y0) y0 = scissorRect.y0;

+			if(width > scissorRect.x1 - scissorRect.x0) width = scissorRect.x1 - scissorRect.x0;

+			if(height > scissorRect.y1 - scissorRect.y0) height = scissorRect.y1 - scissorRect.y0;

+		}

+

+		renderTarget->clearColorBuffer(color, rgbaMask, x0, y0, width, height);

+	}

+

+	void Device::clearDepth(float z)

+	{

+		TRACE("float z = %f", z);

+

+		if(!depthStencil)

+		{

+			return;

+		}

+

+		if(z > 1) z = 1;

+		if(z < 0) z = 0;

+

+		int x0 = 0;

+		int y0 = 0;

+		int width = depthStencil->getExternalWidth();

+		int height = depthStencil->getExternalHeight();

+

+		if(scissorEnable)   // Clamp against scissor rectangle

+		{

+			if(x0 < scissorRect.x0) x0 = scissorRect.x0;

+			if(y0 < scissorRect.y0) y0 = scissorRect.y0;

+			if(width > scissorRect.x1 - scissorRect.x0) width = scissorRect.x1 - scissorRect.x0;

+			if(height > scissorRect.y1 - scissorRect.y0) height = scissorRect.y1 - scissorRect.y0;

+		}

+			

+		depthStencil->clearDepthBuffer(z, x0, y0, width, height);

+	}

+

+	void Device::clearStencil(unsigned int stencil, unsigned int mask)

+	{

+		TRACE("unsigned long stencil = %d", stencil);

+

+		if(!depthStencil)

+		{

+			return;

+		}

+

+		int x0 = 0;

+		int y0 = 0;

+		int width = depthStencil->getExternalWidth();

+		int height = depthStencil->getExternalHeight();

+

+		if(scissorEnable)   // Clamp against scissor rectangle

+		{

+			if(x0 < scissorRect.x0) x0 = scissorRect.x0;

+			if(y0 < scissorRect.y0) y0 = scissorRect.y0;

+			if(width > scissorRect.x1 - scissorRect.x0) width = scissorRect.x1 - scissorRect.x0;

+			if(height > scissorRect.y1 - scissorRect.y0) height = scissorRect.y1 - scissorRect.y0;

+		}

+

+		depthStencil->clearStencilBuffer(stencil, mask, x0, y0, width, height);

+	}

+

+	Image *Device::createDepthStencilSurface(unsigned int width, unsigned int height, sw::Format format, int multiSampleDepth, bool discard)

+	{

+		TRACE("unsigned int width = %d, unsigned int height = %d, sw::Format format = %d, int multiSampleDepth = %d, bool discard = %d", width, height, format, multiSampleDepth, discard);

+

+		if(width == 0 || height == 0 || height > OUTLINE_RESOLUTION)

+		{

+			ERR("Invalid parameters");

+			return 0;

+		}

+		

+		bool lockable = true;

+

+		switch(format)

+		{

+	//	case FORMAT_D15S1:

+		case FORMAT_D24S8:

+		case FORMAT_D24X8:

+	//	case FORMAT_D24X4S4:

+		case FORMAT_D24FS8:

+		case FORMAT_D32:

+		case FORMAT_D16:

+			lockable = false;

+			break;

+	//	case FORMAT_S8_LOCKABLE:

+	//	case FORMAT_D16_LOCKABLE:

+		case FORMAT_D32F_LOCKABLE:

+	//	case FORMAT_D32_LOCKABLE:

+		case FORMAT_DF24S8:

+		case FORMAT_DF16S8:

+			lockable = true;

+			break;

+		default:

+			UNREACHABLE();

+		}

+

+		Image *surface = new Image(0, width, height, format, GL_NONE, GL_NONE, multiSampleDepth, lockable, true);

+

+		if(!surface)

+		{

+			ERR("Out of memory");

+			return 0;

+		}

+

+		surface->addRef();

+

+		return surface;

+	}

+

+	Image *Device::createRenderTarget(unsigned int width, unsigned int height, sw::Format format, int multiSampleDepth, bool lockable)

+	{

+		TRACE("unsigned int width = %d, unsigned int height = %d, sw::Format format = %d, int multiSampleDepth = %d, bool lockable = %d", width, height, format, multiSampleDepth, lockable);

+

+		if(height > OUTLINE_RESOLUTION)

+		{

+			ERR("Invalid parameters");

+			return 0;

+		}

+

+		Image *surface = new Image(0, width, height, format, GL_NONE, GL_NONE, multiSampleDepth, lockable, true);

+

+		if(!surface)

+		{

+			ERR("Out of memory");

+			return 0;

+		}

+

+		surface->addRef();

+		

+		return surface;

+	}

+

+	void Device::drawIndexedPrimitive(PrimitiveType type, unsigned int indexOffset, unsigned int primitiveCount, int indexSize)

+	{

+		TRACE("");

+

+		if(!bindResources() || !primitiveCount)

+		{

+			return;

+		}

+

+		Context::DrawType drawType;

+

+		if(indexSize == 4)

+		{

+			switch(type)

+			{

+			case DRAW_POINTLIST:     drawType = Context::DRAW_INDEXEDPOINTLIST32;     break;

+			case DRAW_LINELIST:      drawType = Context::DRAW_INDEXEDLINELIST32;      break;

+			case DRAW_LINESTRIP:     drawType = Context::DRAW_INDEXEDLINESTRIP32;     break;

+			case DRAW_LINELOOP:      drawType = Context::DRAW_INDEXEDLINELOOP32;      break;

+			case DRAW_TRIANGLELIST:  drawType = Context::DRAW_INDEXEDTRIANGLELIST32;  break;

+			case DRAW_TRIANGLESTRIP: drawType = Context::DRAW_INDEXEDTRIANGLESTRIP32; break;

+			case DRAW_TRIANGLEFAN:   drawType = Context::DRAW_INDEXEDTRIANGLEFAN32;	  break;

+			default: UNREACHABLE();

+			}

+		}

+		else if(indexSize == 2)

+		{

+			switch(type)

+			{

+			case DRAW_POINTLIST:     drawType = Context::DRAW_INDEXEDPOINTLIST16;     break;

+			case DRAW_LINELIST:      drawType = Context::DRAW_INDEXEDLINELIST16;      break;

+			case DRAW_LINESTRIP:     drawType = Context::DRAW_INDEXEDLINESTRIP16;     break;

+			case DRAW_LINELOOP:      drawType = Context::DRAW_INDEXEDLINELOOP16;      break;

+			case DRAW_TRIANGLELIST:  drawType = Context::DRAW_INDEXEDTRIANGLELIST16;  break;

+			case DRAW_TRIANGLESTRIP: drawType = Context::DRAW_INDEXEDTRIANGLESTRIP16; break;

+			case DRAW_TRIANGLEFAN:   drawType = Context::DRAW_INDEXEDTRIANGLEFAN16;   break;

+			default: UNREACHABLE();

+			}

+		}

+		else if(indexSize == 1)

+		{

+			switch(type)

+			{

+			case DRAW_POINTLIST:     drawType = Context::DRAW_INDEXEDPOINTLIST8;     break;

+			case DRAW_LINELIST:      drawType = Context::DRAW_INDEXEDLINELIST8;      break;

+			case DRAW_LINESTRIP:     drawType = Context::DRAW_INDEXEDLINESTRIP8;     break;

+			case DRAW_LINELOOP:      drawType = Context::DRAW_INDEXEDLINELOOP8;      break;

+			case DRAW_TRIANGLELIST:  drawType = Context::DRAW_INDEXEDTRIANGLELIST8;  break;

+			case DRAW_TRIANGLESTRIP: drawType = Context::DRAW_INDEXEDTRIANGLESTRIP8; break;

+			case DRAW_TRIANGLEFAN:   drawType = Context::DRAW_INDEXEDTRIANGLEFAN8;   break;

+			default: UNREACHABLE();

+			}

+		}

+		else UNREACHABLE();

+

+		draw(drawType, indexOffset, primitiveCount);

+	}

+

+	void Device::drawPrimitive(PrimitiveType primitiveType, unsigned int primitiveCount)

+	{

+		TRACE("");

+

+		if(!bindResources() || !primitiveCount)

+		{

+			return;

+		}

+

+		setIndexBuffer(0);

+		

+		Context::DrawType drawType;

+

+		switch(primitiveType)

+		{

+		case DRAW_POINTLIST:     drawType = Context::DRAW_POINTLIST;     break;

+		case DRAW_LINELIST:      drawType = Context::DRAW_LINELIST;      break;

+		case DRAW_LINESTRIP:     drawType = Context::DRAW_LINESTRIP;     break;

+		case DRAW_LINELOOP:      drawType = Context::DRAW_LINELOOP;      break;

+		case DRAW_TRIANGLELIST:  drawType = Context::DRAW_TRIANGLELIST;  break;

+		case DRAW_TRIANGLESTRIP: drawType = Context::DRAW_TRIANGLESTRIP; break;

+		case DRAW_TRIANGLEFAN:   drawType = Context::DRAW_TRIANGLEFAN;   break;

+		default: UNREACHABLE();

+		}

+

+		draw(drawType, 0, primitiveCount);

+	}

+

+	void Device::setDepthStencilSurface(Image *depthStencil)

+	{

+		TRACE("Image *newDepthStencil = 0x%0.8p", depthStencil);

+

+		if(this->depthStencil == depthStencil)

+		{

+			return;

+		}

+

+		if(depthStencil)

+		{

+			depthStencil->addRef();

+		}

+

+		if(this->depthStencil)

+		{

+			this->depthStencil->release();

+		}

+

+		this->depthStencil = depthStencil;

+

+		setDepthStencil(depthStencil);

+	}

+

+	void Device::setPixelShader(PixelShader *pixelShader)

+	{

+		TRACE("PixelShader *shader = 0x%0.8p", pixelShader);

+

+		this->pixelShader = pixelShader;

+		pixelShaderDirty = true;

+	}

+

+	void Device::setPixelShaderConstantF(unsigned int startRegister, const float *constantData, unsigned int count)

+	{

+		TRACE("unsigned int startRegister = %d, const int *constantData = 0x%0.8p, unsigned int count = %d", startRegister, constantData, count);

+

+		for(unsigned int i = 0; i < count && startRegister + i < 224; i++)

+		{

+			pixelShaderConstantF[startRegister + i][0] = constantData[i * 4 + 0];

+			pixelShaderConstantF[startRegister + i][1] = constantData[i * 4 + 1];

+			pixelShaderConstantF[startRegister + i][2] = constantData[i * 4 + 2];

+			pixelShaderConstantF[startRegister + i][3] = constantData[i * 4 + 3];

+		}

+

+		pixelShaderConstantsFDirty = max(startRegister + count, pixelShaderConstantsFDirty);

+		pixelShaderDirty = true;   // Reload DEF constants

+	}

+

+	void Device::setScissorEnable(bool enable)

+	{

+		scissorEnable = enable;

+	}

+

+	void Device::setRenderTarget(Image *renderTarget)

+	{

+		TRACE("Image *newRenderTarget = 0x%0.8p", renderTarget);

+

+		if(renderTarget)

+		{

+			renderTarget->addRef();

+		}

+

+		if(this->renderTarget)

+		{

+			this->renderTarget->release();

+		}

+

+		this->renderTarget = renderTarget;

+

+		Renderer::setRenderTarget(0, renderTarget);

+	}

+

+	void Device::setScissorRect(const sw::Rect &rect)

+	{

+		TRACE("const sw::Rect *rect = 0x%0.8p", rect);

+

+		scissorRect = rect;

+	}

+

+	void Device::setVertexShader(VertexShader *vertexShader)

+	{

+		TRACE("VertexShader *shader = 0x%0.8p", vertexShader);

+

+		this->vertexShader = vertexShader;

+		vertexShaderDirty = true;

+	}

+

+	void Device::setVertexShaderConstantF(unsigned int startRegister, const float *constantData, unsigned int count)

+	{

+		TRACE("unsigned int startRegister = %d, const int *constantData = 0x%0.8p, unsigned int count = %d", startRegister, constantData, count);

+

+		for(unsigned int i = 0; i < count && startRegister + i < 256; i++)

+		{

+			vertexShaderConstantF[startRegister + i][0] = constantData[i * 4 + 0];

+			vertexShaderConstantF[startRegister + i][1] = constantData[i * 4 + 1];

+			vertexShaderConstantF[startRegister + i][2] = constantData[i * 4 + 2];

+			vertexShaderConstantF[startRegister + i][3] = constantData[i * 4 + 3];

+		}

+			

+		vertexShaderConstantsFDirty = max(startRegister + count, vertexShaderConstantsFDirty);

+		vertexShaderDirty = true;   // Reload DEF constants

+	}

+

+	void Device::setViewport(const Viewport &viewport)

+	{

+		TRACE("const Viewport *viewport = 0x%0.8p", viewport);

+

+		this->viewport = viewport;

+	}

+

+	bool Device::stretchRect(Image *source, const sw::Rect *sourceRect, Image *dest, const sw::Rect *destRect, bool filter)

+	{

+		TRACE("Image *sourceSurface = 0x%0.8p, const sw::Rect *sourceRect = 0x%0.8p, Image *destSurface = 0x%0.8p, const sw::Rect *destRect = 0x%0.8p, bool filter = %d", source, sourceRect, dest, destRect, filter);

+

+		if(!source || !dest || !validRectangle(sourceRect, source) || !validRectangle(destRect, dest))

+		{

+			ERR("Invalid parameters");

+			return false;

+		}

+		

+		int sWidth = source->getExternalWidth();

+		int sHeight = source->getExternalHeight();

+		int dWidth = dest->getExternalWidth();

+		int dHeight = dest->getExternalHeight();

+

+		Rect sRect;

+		Rect dRect;

+

+		if(sourceRect)

+		{

+			sRect = *sourceRect;

+		}

+		else

+		{

+			sRect.y0 = 0;

+			sRect.x0 = 0;

+			sRect.y1 = sHeight;

+			sRect.x1 = sWidth;

+		}

+

+		if(destRect)

+		{

+			dRect = *destRect;

+		}

+		else

+		{

+			dRect.y0 = 0;

+			dRect.x0 = 0;

+			dRect.y1 = dHeight;

+			dRect.x1 = dWidth;

+		}

+

+		bool scaling = (sRect.x1 - sRect.x0 != dRect.x1 - dRect.x0) || (sRect.y1 - sRect.y0 != dRect.y1 - dRect.y0);

+		bool equalFormats = source->getInternalFormat() == dest->getInternalFormat();

+		bool depthStencil = Image::isDepth(source->getInternalFormat()) || Image::isStencil(source->getInternalFormat());

+		bool alpha0xFF = false;

+

+		if((source->getInternalFormat() == FORMAT_A8R8G8B8 && dest->getInternalFormat() == FORMAT_X8R8G8B8) ||

+		   (source->getInternalFormat() == FORMAT_X8R8G8B8 && dest->getInternalFormat() == FORMAT_A8R8G8B8))

+		{

+			equalFormats = true;

+			alpha0xFF = true;

+		}

+

+		if(depthStencil)   // Copy entirely, internally   // FIXME: Check

+		{

+			if(source->hasDepth())

+			{

+				sw::byte *sourceBuffer = (sw::byte*)source->lockInternal(0, 0, 0, LOCK_READONLY, PUBLIC);

+				sw::byte *destBuffer = (sw::byte*)dest->lockInternal(0, 0, 0, LOCK_DISCARD, PUBLIC);

+

+				unsigned int width = source->getInternalWidth();

+				unsigned int height = source->getInternalHeight();

+				unsigned int pitch = source->getInternalPitchB();

+

+				for(unsigned int y = 0; y < height; y++)

+				{

+					memcpy(destBuffer, sourceBuffer, pitch);   // FIXME: Only copy width * bytes

+

+					sourceBuffer += pitch;

+					destBuffer += pitch;

+				}

+

+				source->unlockInternal();

+				dest->unlockInternal();

+			}

+

+			if(source->hasStencil())

+			{

+				sw::byte *sourceBuffer = (sw::byte*)source->lockStencil(0, PUBLIC);

+				sw::byte *destBuffer = (sw::byte*)dest->lockStencil(0, PUBLIC);

+

+				unsigned int width = source->getInternalWidth();

+				unsigned int height = source->getInternalHeight();

+				unsigned int pitch = source->getStencilPitchB();

+

+				for(unsigned int y = 0; y < height; y++)

+				{

+					memcpy(destBuffer, sourceBuffer, pitch);   // FIXME: Only copy width * bytes

+

+					sourceBuffer += pitch;

+					destBuffer += pitch;

+				}

+

+				source->unlockStencil();

+				dest->unlockStencil();

+			}

+		}

+		else if(!scaling && equalFormats)

+		{

+			unsigned char *sourceBytes = (unsigned char*)source->lockInternal(sRect.x0, sRect.y0, 0, LOCK_READONLY, PUBLIC);

+			unsigned char *destBytes = (unsigned char*)dest->lockInternal(dRect.x0, dRect.y0, 0, LOCK_READWRITE, PUBLIC);

+			unsigned int sourcePitch = source->getInternalPitchB();

+			unsigned int destPitch = dest->getInternalPitchB();

+

+			unsigned int width = dRect.x1 - dRect.x0;

+			unsigned int height = dRect.y1 - dRect.y0;

+			unsigned int bytes = width * Image::bytes(source->getInternalFormat());

+

+			for(unsigned int y = 0; y < height; y++)

+			{

+				memcpy(destBytes, sourceBytes, bytes);

+

+				if(alpha0xFF)

+				{

+					for(unsigned int x = 0; x < width; x++)

+					{

+						destBytes[4 * x + 3] = 0xFF;

+					}

+				}

+				

+				sourceBytes += sourcePitch;

+				destBytes += destPitch;

+			}

+

+			source->unlockInternal();

+			dest->unlockInternal();

+		}

+		else

+		{

+			blit(source, sRect, dest, dRect, scaling && filter);

+		}

+

+		return true;

+	}

+

+	bool Device::bindResources()

+	{

+		if(!bindViewport())

+		{

+			return false;   // Zero-area target region

+		}

+

+		bindShaderConstants();

+

+		return true;

+	}

+

+	void Device::bindShaderConstants()

+	{

+		if(pixelShaderDirty)

+		{

+			if(pixelShader)

+			{

+				if(pixelShaderConstantsFDirty)

+				{

+					Renderer::setPixelShaderConstantF(0, pixelShaderConstantF[0], pixelShaderConstantsFDirty);

+				}

+

+				Renderer::setPixelShader(pixelShader);   // Loads shader constants set with DEF

+				pixelShaderConstantsFDirty = pixelShader->dirtyConstantsF;   // Shader DEF'ed constants are dirty

+			}

+			else

+			{

+				setPixelShader(0);

+			}

+

+			pixelShaderDirty = false;

+		}

+

+		if(vertexShaderDirty)

+		{

+			if(vertexShader)

+			{

+				if(vertexShaderConstantsFDirty)

+				{

+					Renderer::setVertexShaderConstantF(0, vertexShaderConstantF[0], vertexShaderConstantsFDirty);

+				}

+		

+				Renderer::setVertexShader(vertexShader);   // Loads shader constants set with DEF

+				vertexShaderConstantsFDirty = vertexShader->dirtyConstantsF;   // Shader DEF'ed constants are dirty

+			}

+			else

+			{

+				setVertexShader(0);

+			}

+

+			vertexShaderDirty = false;

+		}

+	}

+	

+	bool Device::bindViewport()

+	{

+		if(viewport.width <= 0 || viewport.height <= 0)

+		{

+			return false;

+		}

+

+		if(scissorEnable)

+		{

+			if(scissorRect.x0 >= scissorRect.x1 || scissorRect.y0 >= scissorRect.y1)

+			{

+				return false;

+			}

+

+			sw::Rect scissor;

+			scissor.x0 = scissorRect.x0;

+			scissor.x1 = scissorRect.x1;

+			scissor.y0 = scissorRect.y0;

+			scissor.y1 = scissorRect.y1;

+			

+			setScissor(scissor);

+		}

+		else

+		{

+			sw::Rect scissor;

+			scissor.x0 = viewport.x0;

+			scissor.x1 = viewport.x0 + viewport.width;

+			scissor.y0 = viewport.y0;

+			scissor.y1 = viewport.y0 + viewport.height;

+			

+			if(renderTarget)

+			{

+				scissor.x0 = max(scissor.x0, 0);

+				scissor.x1 = min(scissor.x1, renderTarget->getExternalWidth());

+				scissor.y0 = max(scissor.y0, 0);

+				scissor.y1 = min(scissor.y1, renderTarget->getExternalHeight());

+			}

+

+			if(depthStencil)

+			{

+				scissor.x0 = max(scissor.x0, 0);

+				scissor.x1 = min(scissor.x1, depthStencil->getExternalWidth());

+				scissor.y0 = max(scissor.y0, 0);

+				scissor.y1 = min(scissor.y1, depthStencil->getExternalHeight());

+			}

+

+			setScissor(scissor);

+		}

+

+		sw::Viewport view;

+		view.x0 = (float)viewport.x0;

+		view.y0 = (float)viewport.y0;

+		view.width = (float)viewport.width;

+		view.height = (float)viewport.height;

+		view.minZ = viewport.minZ;

+		view.maxZ = viewport.maxZ;

+		

+		Renderer::setViewport(view);

+

+		return true;

+	}

+

+	bool Device::validRectangle(const sw::Rect *rect, Image *surface)

+	{

+		if(!rect)

+		{

+			return true;

+		}

+

+		if(rect->x1 <= rect->x0 || rect->y1 <= rect->y0)

+		{

+			return false;

+		}

+

+		if(rect->x0 < 0 || rect->y0 < 0)

+		{

+			return false;

+		}

+

+		if(rect->x1 > (int)surface->getWidth() || rect->y1 > (int)surface->getHeight())

+		{

+			return false;

+		}

+

+		return true;

+	}

+

+	void Device::finish()

+	{

+		synchronize();

+	}

+}

+

+// Exported functions for use by EGL

+extern "C"

+{

+	gl::Device *createDevice()

+	{

+		sw::Context *context = new sw::Context();

+

+		if(context)

+		{

+			return new gl::Device(context);

+		}

+

+		return 0;

+	}

+}
\ No newline at end of file
diff --git a/src/GLES2/libGLESv2/Device.hpp b/src/GLES2/libGLESv2/Device.hpp
new file mode 100644
index 0000000..dcee30f
--- /dev/null
+++ b/src/GLES2/libGLESv2/Device.hpp
@@ -0,0 +1,103 @@
+// SwiftShader Software Renderer

+//

+// Copyright(c) 2005-2012 TransGaming Inc.

+//

+// All rights reserved. No part of this software may be copied, distributed, transmitted,

+// transcribed, stored in a retrieval system, translated into any human or computer

+// language by any means, or disclosed to third parties without the explicit written

+// agreement of TransGaming Inc. Without such an agreement, no rights or licenses, express

+// or implied, including but not limited to any patent rights, are granted to you.

+//

+

+#ifndef gl_Device_hpp

+#define gl_Device_hpp

+

+#include "Renderer/Renderer.hpp"

+

+namespace gl

+{

+	class Texture;

+}

+

+namespace gl

+{

+	class Image;

+

+	enum PrimitiveType

+	{

+		DRAW_POINTLIST,

+		DRAW_LINELIST,

+		DRAW_LINESTRIP,

+		DRAW_LINELOOP,

+		DRAW_TRIANGLELIST,

+		DRAW_TRIANGLESTRIP,

+		DRAW_TRIANGLEFAN

+	};

+

+	struct Viewport

+	{

+		int x0;

+		int y0;

+		unsigned int width;

+		unsigned int height;

+		float minZ;

+		float maxZ;

+	};

+

+	class Device : public sw::Renderer

+	{

+	public:

+		explicit Device(sw::Context *context);

+

+		virtual ~Device();

+

+		virtual void clearColor(unsigned int color, unsigned int rgbaMask);

+		virtual void clearDepth(float z);

+		virtual void clearStencil(unsigned int stencil, unsigned int mask);

+		virtual Image *createDepthStencilSurface(unsigned int width, unsigned int height, sw::Format format, int multiSampleDepth, bool discard);

+		virtual Image *createRenderTarget(unsigned int width, unsigned int height, sw::Format format, int multiSampleDepth, bool lockable);

+		virtual void drawIndexedPrimitive(PrimitiveType type, unsigned int indexOffset, unsigned int primitiveCount, int indexSize);

+		virtual void drawPrimitive(PrimitiveType primitiveType, unsigned int primiveCount);

+		virtual void setDepthStencilSurface(Image *newDepthStencil);

+		virtual void setPixelShader(sw::PixelShader *shader);

+		virtual void setPixelShaderConstantF(unsigned int startRegister, const float *constantData, unsigned int count);

+		virtual void setScissorEnable(bool enable);

+		virtual void setRenderTarget(Image *renderTarget);

+		virtual void setScissorRect(const sw::Rect &rect);

+		virtual void setVertexShader(sw::VertexShader *shader);

+		virtual void setVertexShaderConstantF(unsigned int startRegister, const float *constantData, unsigned int count);

+		virtual void setViewport(const Viewport &viewport);

+

+		virtual bool stretchRect(Image *sourceSurface, const sw::Rect *sourceRect, Image *destSurface, const sw::Rect *destRect, bool filter);

+		virtual void finish();

+

+	private:

+		sw::Context *const context;

+

+		bool bindResources();

+		void bindShaderConstants();

+		bool bindViewport();   // Also adjusts for scissoring

+

+		bool validRectangle(const sw::Rect *rect, Image *surface);

+

+		Viewport viewport;

+		sw::Rect scissorRect;

+		bool scissorEnable;

+

+		sw::PixelShader *pixelShader;

+		sw::VertexShader *vertexShader;

+

+		bool pixelShaderDirty;

+		int pixelShaderConstantsFDirty;

+		bool vertexShaderDirty;

+		int vertexShaderConstantsFDirty;

+

+		float pixelShaderConstantF[224][4];

+		float vertexShaderConstantF[256][4];

+

+		Image *renderTarget;

+		Image *depthStencil;

+	};

+}

+

+#endif   // gl_Device_hpp

diff --git a/src/GLES2/libGLESv2/Fence.cpp b/src/GLES2/libGLESv2/Fence.cpp
new file mode 100644
index 0000000..8221075
--- /dev/null
+++ b/src/GLES2/libGLESv2/Fence.cpp
@@ -0,0 +1,108 @@
+// SwiftShader Software Renderer

+//

+// Copyright(c) 2005-2012 TransGaming Inc.

+//

+// All rights reserved. No part of this software may be copied, distributed, transmitted,

+// transcribed, stored in a retrieval system, translated into any human or computer

+// language by any means, or disclosed to third parties without the explicit written

+// agreement of TransGaming Inc. Without such an agreement, no rights or licenses, express

+// or implied, including but not limited to any patent rights, are granted to you.

+//

+

+// Fence.cpp: Implements the Fence class, which supports the GL_NV_fence extension.

+

+#include "Fence.h"

+

+#include "main.h"

+#include "Common/Thread.hpp"

+

+namespace gl

+{

+

+Fence::Fence()

+{ 

+    mQuery = false;

+    mCondition = GL_NONE;

+    mStatus = GL_FALSE;

+}

+

+Fence::~Fence()

+{

+    mQuery = false;

+}

+

+GLboolean Fence::isFence()

+{

+    // GL_NV_fence spec:

+    // A name returned by GenFencesNV, but not yet set via SetFenceNV, is not the name of an existing fence.

+    return mQuery;

+}

+

+void Fence::setFence(GLenum condition)

+{

+    mQuery = true;

+    mCondition = condition;

+    mStatus = GL_FALSE;

+}

+

+GLboolean Fence::testFence()

+{

+    if(!mQuery)

+    {

+        return error(GL_INVALID_OPERATION, GL_TRUE);

+    }

+

+	UNIMPLEMENTED();

+    mStatus = GL_TRUE;

+

+    return mStatus;

+}

+

+void Fence::finishFence()

+{

+    if(!mQuery)

+    {

+        return error(GL_INVALID_OPERATION);

+    }

+

+    while(!testFence())

+    {

+        sw::Thread::yield();

+    }

+}

+

+void Fence::getFenceiv(GLenum pname, GLint *params)

+{

+    if(!mQuery)

+    {

+        return error(GL_INVALID_OPERATION);

+    }

+

+    switch (pname)

+    {

+    case GL_FENCE_STATUS_NV:

+		{

+			// GL_NV_fence spec:

+			// Once the status of a fence has been finished (via FinishFenceNV) or tested and the returned status is TRUE (via either TestFenceNV

+			// or GetFenceivNV querying the FENCE_STATUS_NV), the status remains TRUE until the next SetFenceNV of the fence.

+			if(mStatus)

+			{

+				params[0] = GL_TRUE;

+				return;

+			}

+            

+			mStatus = testFence();

+

+			params[0] = mStatus;            

+			break;

+		}

+    case GL_FENCE_CONDITION_NV:

+        params[0] = mCondition;

+        break;

+    default:

+        return error(GL_INVALID_ENUM);

+        break;

+    }

+}

+

+}

diff --git a/src/GLES2/libGLESv2/Fence.h b/src/GLES2/libGLESv2/Fence.h
new file mode 100644
index 0000000..bd6d9ac
--- /dev/null
+++ b/src/GLES2/libGLESv2/Fence.h
@@ -0,0 +1,43 @@
+// SwiftShader Software Renderer

+//

+// Copyright(c) 2005-2012 TransGaming Inc.

+//

+// All rights reserved. No part of this software may be copied, distributed, transmitted,

+// transcribed, stored in a retrieval system, translated into any human or computer

+// language by any means, or disclosed to third parties without the explicit written

+// agreement of TransGaming Inc. Without such an agreement, no rights or licenses, express

+// or implied, including but not limited to any patent rights, are granted to you.

+//

+

+// Fence.h: Defines the Fence class, which supports the GL_NV_fence extension.

+

+#ifndef LIBGLESV2_FENCE_H_

+#define LIBGLESV2_FENCE_H_

+

+#define GL_APICALL

+#include <GLES2/gl2.h>

+

+namespace gl

+{

+

+class Fence

+{

+  public:

+    Fence();

+    virtual ~Fence();

+

+    GLboolean isFence();

+    void setFence(GLenum condition);

+    GLboolean testFence();

+    void finishFence();

+    void getFenceiv(GLenum pname, GLint *params);

+

+  private:

+    bool mQuery;

+    GLenum mCondition;

+    GLboolean mStatus;

+};

+

+}

+

+#endif   // LIBGLESV2_FENCE_H_

diff --git a/src/GLES2/libGLESv2/Framebuffer.cpp b/src/GLES2/libGLESv2/Framebuffer.cpp
new file mode 100644
index 0000000..8ba7d9e
--- /dev/null
+++ b/src/GLES2/libGLESv2/Framebuffer.cpp
@@ -0,0 +1,423 @@
+// SwiftShader Software Renderer
+//
+// Copyright(c) 2005-2013 TransGaming Inc.
+//
+// All rights reserved. No part of this software may be copied, distributed, transmitted,
+// transcribed, stored in a retrieval system, translated into any human or computer
+// language by any means, or disclosed to third parties without the explicit written
+// agreement of TransGaming Inc. Without such an agreement, no rights or licenses, express
+// or implied, including but not limited to any patent rights, are granted to you.
+//
+
+// Framebuffer.cpp: Implements the Framebuffer class. Implements GL framebuffer
+// objects and related functionality. [OpenGL ES 2.0.24] section 4.4 page 105.
+
+#include "Framebuffer.h"
+
+#include "main.h"
+#include "Renderbuffer.h"
+#include "Texture.h"
+#include "utilities.h"
+
+namespace gl
+{
+
+Framebuffer::Framebuffer()
+{
+	mColorbufferType = GL_NONE;
+	mDepthbufferType = GL_NONE;
+	mStencilbufferType = GL_NONE;
+}
+
+Framebuffer::~Framebuffer()
+{
+	mColorbufferPointer.set(NULL);
+	mDepthbufferPointer.set(NULL);
+	mStencilbufferPointer.set(NULL);
+}
+
+Renderbuffer *Framebuffer::lookupRenderbuffer(GLenum type, GLuint handle) const
+{
+	Context *context = getContext();
+	Renderbuffer *buffer = NULL;
+
+	if(type == GL_NONE)
+	{
+		buffer = NULL;
+	}
+	else if(type == GL_RENDERBUFFER)
+	{
+		buffer = context->getRenderbuffer(handle);
+	}
+	else if(IsTextureTarget(type))
+	{
+		buffer = context->getTexture(handle)->getRenderbuffer(type);
+	}
+	else
+	{
+		UNREACHABLE();
+	}
+
+	return buffer;
+}
+
+void Framebuffer::setColorbuffer(GLenum type, GLuint colorbuffer)
+{
+	mColorbufferType = (colorbuffer != 0) ? type : GL_NONE;
+	mColorbufferPointer.set(lookupRenderbuffer(type, colorbuffer));
+}
+
+void Framebuffer::setDepthbuffer(GLenum type, GLuint depthbuffer)
+{
+	mDepthbufferType = (depthbuffer != 0) ? type : GL_NONE;
+	mDepthbufferPointer.set(lookupRenderbuffer(type, depthbuffer));
+}
+
+void Framebuffer::setStencilbuffer(GLenum type, GLuint stencilbuffer)
+{
+	mStencilbufferType = (stencilbuffer != 0) ? type : GL_NONE;
+	mStencilbufferPointer.set(lookupRenderbuffer(type, stencilbuffer));
+}
+
+void Framebuffer::detachTexture(GLuint texture)
+{
+	if(mColorbufferPointer.id() == texture && IsTextureTarget(mColorbufferType))
+	{
+		mColorbufferType = GL_NONE;
+		mColorbufferPointer.set(NULL);
+	}
+
+	if(mDepthbufferPointer.id() == texture && IsTextureTarget(mDepthbufferType))
+	{
+		mDepthbufferType = GL_NONE;
+		mDepthbufferPointer.set(NULL);
+	}
+
+	if(mStencilbufferPointer.id() == texture && IsTextureTarget(mStencilbufferType))
+	{
+		mStencilbufferType = GL_NONE;
+		mStencilbufferPointer.set(NULL);
+	}
+}
+
+void Framebuffer::detachRenderbuffer(GLuint renderbuffer)
+{
+	if(mColorbufferPointer.id() == renderbuffer && mColorbufferType == GL_RENDERBUFFER)
+	{
+		mColorbufferType = GL_NONE;
+		mColorbufferPointer.set(NULL);
+	}
+
+	if(mDepthbufferPointer.id() == renderbuffer && mDepthbufferType == GL_RENDERBUFFER)
+	{
+		mDepthbufferType = GL_NONE;
+		mDepthbufferPointer.set(NULL);
+	}
+
+	if(mStencilbufferPointer.id() == renderbuffer && mStencilbufferType == GL_RENDERBUFFER)
+	{
+		mStencilbufferType = GL_NONE;
+		mStencilbufferPointer.set(NULL);
+	}
+}
+
+// Increments refcount on surface.
+// caller must Release() the returned surface
+Image *Framebuffer::getRenderTarget()
+{
+	Renderbuffer *colorbuffer = mColorbufferPointer.get();
+
+	if(colorbuffer)
+	{
+		return colorbuffer->getRenderTarget();
+	}
+
+	return NULL;
+}
+
+// Increments refcount on surface.
+// caller must Release() the returned surface
+Image *Framebuffer::getDepthStencil()
+{
+	Renderbuffer *depthstencilbuffer = mDepthbufferPointer.get();
+	
+	if(!depthstencilbuffer)
+	{
+		depthstencilbuffer = mStencilbufferPointer.get();
+	}
+
+	if(depthstencilbuffer)
+	{
+		return depthstencilbuffer->getRenderTarget();
+	}
+
+	return NULL;
+}
+
+Renderbuffer *Framebuffer::getColorbuffer()
+{
+	return mColorbufferPointer.get();
+}
+
+Renderbuffer *Framebuffer::getDepthbuffer()
+{
+	return mDepthbufferPointer.get();
+}
+
+Renderbuffer *Framebuffer::getStencilbuffer()
+{
+	return mStencilbufferPointer.get();
+}
+
+GLenum Framebuffer::getColorbufferType()
+{
+	return mColorbufferType;
+}
+
+GLenum Framebuffer::getDepthbufferType()
+{
+	return mDepthbufferType;
+}
+
+GLenum Framebuffer::getStencilbufferType()
+{
+	return mStencilbufferType;
+}
+
+GLuint Framebuffer::getColorbufferHandle()
+{
+	return mColorbufferPointer.id();
+}
+
+GLuint Framebuffer::getDepthbufferHandle()
+{
+	return mDepthbufferPointer.id();
+}
+
+GLuint Framebuffer::getStencilbufferHandle()
+{
+	return mStencilbufferPointer.id();
+}
+
+bool Framebuffer::hasStencil()
+{
+	if(mStencilbufferType != GL_NONE)
+	{
+		Renderbuffer *stencilbufferObject = getStencilbuffer();
+
+		if(stencilbufferObject)
+		{
+			return stencilbufferObject->getStencilSize() > 0;
+		}
+	}
+
+	return false;
+}
+
+GLenum Framebuffer::completeness()
+{
+	int width;
+	int height;
+	int samples;
+
+	return completeness(width, height, samples);
+}
+
+GLenum Framebuffer::completeness(int &width, int &height, int &samples)
+{
+	width = -1;
+	height = -1;
+	samples = -1;
+
+	if(mColorbufferType != GL_NONE)
+	{
+		Renderbuffer *colorbuffer = getColorbuffer();
+
+		if(!colorbuffer)
+		{
+			return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
+		}
+
+		if(colorbuffer->getWidth() == 0 || colorbuffer->getHeight() == 0)
+		{
+			return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
+		}
+
+		if(mColorbufferType == GL_RENDERBUFFER)
+		{
+			if(!gl::IsColorRenderable(colorbuffer->getFormat()))
+			{
+				return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
+			}
+		}
+		else if(IsTextureTarget(mColorbufferType))
+		{
+			GLenum format = colorbuffer->getFormat();
+
+			if(IsCompressed(format) ||
+			   format == GL_ALPHA ||
+			   format == GL_LUMINANCE ||
+			   format == GL_LUMINANCE_ALPHA)
+			{
+				return GL_FRAMEBUFFER_UNSUPPORTED;
+			}
+
+			if(gl::IsDepthTexture(format) || gl::IsStencilTexture(format))
+			{
+				return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
+			}
+		}
+		else
+		{
+			UNREACHABLE();
+			return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
+		}
+
+		width = colorbuffer->getWidth();
+		height = colorbuffer->getHeight();
+		samples = colorbuffer->getSamples();
+	}
+
+	Renderbuffer *depthbuffer = NULL;
+	Renderbuffer *stencilbuffer = NULL;
+
+	if(mDepthbufferType != GL_NONE)
+	{
+		depthbuffer = getDepthbuffer();
+
+		if(!depthbuffer)
+		{
+			return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
+		}
+
+		if(depthbuffer->getWidth() == 0 || depthbuffer->getHeight() == 0)
+		{
+			return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
+		}
+
+		if(mDepthbufferType == GL_RENDERBUFFER)
+		{
+			if(!gl::IsDepthRenderable(depthbuffer->getFormat()))
+			{
+				return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
+			}
+		}
+		else if(IsTextureTarget(mDepthbufferType))
+		{
+			if(!gl::IsDepthTexture(depthbuffer->getFormat()))
+			{
+				return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
+			}
+		}
+		else
+		{
+			UNREACHABLE();
+			return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
+		}
+
+		if(width == -1 || height == -1)
+		{
+			width = depthbuffer->getWidth();
+			height = depthbuffer->getHeight();
+			samples = depthbuffer->getSamples();
+		}
+		else if(width != depthbuffer->getWidth() || height != depthbuffer->getHeight())
+		{
+			return GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS;
+		}
+		else if(samples != depthbuffer->getSamples())
+		{
+			return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_ANGLE;
+		}
+	}
+
+	if(mStencilbufferType != GL_NONE)
+	{
+		stencilbuffer = getStencilbuffer();
+
+		if(!stencilbuffer)
+		{
+			return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
+		}
+
+		if(stencilbuffer->getWidth() == 0 || stencilbuffer->getHeight() == 0)
+		{
+			return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
+		}
+
+		if(mStencilbufferType == GL_RENDERBUFFER)
+		{
+			if(!gl::IsStencilRenderable(stencilbuffer->getFormat()))
+			{
+				return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
+			}
+		}
+		else if(IsTextureTarget(mStencilbufferType))
+		{
+			GLenum internalformat = stencilbuffer->getFormat();
+
+			if(!gl::IsStencilTexture(internalformat))
+			{
+				return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
+			}
+		}
+		else
+		{
+			UNREACHABLE();
+			return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
+		}
+
+		if(width == -1 || height == -1)
+		{
+			width = stencilbuffer->getWidth();
+			height = stencilbuffer->getHeight();
+			samples = stencilbuffer->getSamples();
+		}
+		else if(width != stencilbuffer->getWidth() || height != stencilbuffer->getHeight())
+		{
+			return GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS;
+		}
+		else if(samples != stencilbuffer->getSamples())
+		{
+			return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_ANGLE;
+		}
+	}
+
+	// If we have both a depth and stencil buffer, they must refer to the same object
+	// since we only support packed_depth_stencil and not separate depth and stencil
+	if(depthbuffer && stencilbuffer && (depthbuffer != stencilbuffer))
+	{
+		return GL_FRAMEBUFFER_UNSUPPORTED;
+	}
+
+	// We need to have at least one attachment to be complete
+	if(width == -1 || height == -1)
+	{
+		return GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT;
+	}
+
+	return GL_FRAMEBUFFER_COMPLETE;
+}
+
+DefaultFramebuffer::DefaultFramebuffer(Colorbuffer *colorbuffer, DepthStencilbuffer *depthStencil)
+{
+	mColorbufferPointer.set(new Renderbuffer(0, colorbuffer));
+
+	Renderbuffer *depthStencilRenderbuffer = new Renderbuffer(0, depthStencil);
+	mDepthbufferPointer.set(depthStencilRenderbuffer);
+	mStencilbufferPointer.set(depthStencilRenderbuffer);
+
+	mColorbufferType = GL_RENDERBUFFER;
+	mDepthbufferType = (depthStencilRenderbuffer->getDepthSize() != 0) ? GL_RENDERBUFFER : GL_NONE;
+	mStencilbufferType = (depthStencilRenderbuffer->getStencilSize() != 0) ? GL_RENDERBUFFER : GL_NONE;
+}
+
+GLenum DefaultFramebuffer::completeness()
+{
+	// The default framebuffer should always be complete
+	ASSERT(Framebuffer::completeness() == GL_FRAMEBUFFER_COMPLETE);
+
+	return GL_FRAMEBUFFER_COMPLETE;
+}
+
+}
diff --git a/src/GLES2/libGLESv2/Framebuffer.h b/src/GLES2/libGLESv2/Framebuffer.h
new file mode 100644
index 0000000..c3e0f0b
--- /dev/null
+++ b/src/GLES2/libGLESv2/Framebuffer.h
@@ -0,0 +1,90 @@
+// SwiftShader Software Renderer

+//

+// Copyright(c) 2005-2013 TransGaming Inc.

+//

+// All rights reserved. No part of this software may be copied, distributed, transmitted,

+// transcribed, stored in a retrieval system, translated into any human or computer

+// language by any means, or disclosed to third parties without the explicit written

+// agreement of TransGaming Inc. Without such an agreement, no rights or licenses, express

+// or implied, including but not limited to any patent rights, are granted to you.

+//

+

+// Framebuffer.h: Defines the Framebuffer class. Implements GL framebuffer

+// objects and related functionality. [OpenGL ES 2.0.24] section 4.4 page 105.

+

+#ifndef LIBGLESV2_FRAMEBUFFER_H_

+#define LIBGLESV2_FRAMEBUFFER_H_

+

+#include "RefCountObject.h"

+#include "Image.hpp"

+

+#define GL_APICALL

+#include <GLES2/gl2.h>

+

+namespace gl

+{

+class Renderbuffer;

+class Colorbuffer;

+class Depthbuffer;

+class Stencilbuffer;

+class DepthStencilbuffer;

+

+class Framebuffer

+{

+public:

+    Framebuffer();

+

+    virtual ~Framebuffer();

+

+    void setColorbuffer(GLenum type, GLuint colorbuffer);

+    void setDepthbuffer(GLenum type, GLuint depthbuffer);

+    void setStencilbuffer(GLenum type, GLuint stencilbuffer);

+

+    void detachTexture(GLuint texture);

+    void detachRenderbuffer(GLuint renderbuffer);

+

+    Image *getRenderTarget();

+    Image *getDepthStencil();

+

+    Renderbuffer *getColorbuffer();

+    Renderbuffer *getDepthbuffer();

+    Renderbuffer *getStencilbuffer();

+

+    GLenum getColorbufferType();

+    GLenum getDepthbufferType();

+    GLenum getStencilbufferType();

+

+    GLuint getColorbufferHandle();

+    GLuint getDepthbufferHandle();

+    GLuint getStencilbufferHandle();

+

+    bool hasStencil();

+

+	virtual GLenum completeness();

+	GLenum completeness(int &width, int &height, int &samples);

+

+protected:

+    GLenum mColorbufferType;

+    BindingPointer<Renderbuffer> mColorbufferPointer;

+

+    GLenum mDepthbufferType;

+    BindingPointer<Renderbuffer> mDepthbufferPointer;

+

+    GLenum mStencilbufferType;

+    BindingPointer<Renderbuffer> mStencilbufferPointer;

+

+private:

+    Renderbuffer *lookupRenderbuffer(GLenum type, GLuint handle) const;

+};

+

+class DefaultFramebuffer : public Framebuffer

+{

+public:

+    DefaultFramebuffer(Colorbuffer *colorbuffer, DepthStencilbuffer *depthStencil);

+

+    virtual GLenum completeness();

+};

+

+}

+

+#endif   // LIBGLESV2_FRAMEBUFFER_H_

diff --git a/src/GLES2/libGLESv2/HandleAllocator.cpp b/src/GLES2/libGLESv2/HandleAllocator.cpp
new file mode 100644
index 0000000..7db672a
--- /dev/null
+++ b/src/GLES2/libGLESv2/HandleAllocator.cpp
@@ -0,0 +1,68 @@
+// SwiftShader Software Renderer
+//
+// Copyright(c) 2005-2012 TransGaming Inc.
+//
+// All rights reserved. No part of this software may be copied, distributed, transmitted,
+// transcribed, stored in a retrieval system, translated into any human or computer
+// language by any means, or disclosed to third parties without the explicit written
+// agreement of TransGaming Inc. Without such an agreement, no rights or licenses, express
+// or implied, including but not limited to any patent rights, are granted to you.
+//
+
+// HandleAllocator.cpp: Implements the HandleAllocator class, which is used
+// to allocate GL handles.
+
+#include "HandleAllocator.h"
+
+#include "main.h"
+
+namespace gl
+{
+
+HandleAllocator::HandleAllocator() : mBaseValue(1), mNextValue(1)
+{
+}
+
+HandleAllocator::~HandleAllocator()
+{
+}
+
+void HandleAllocator::setBaseHandle(GLuint value)
+{
+    ASSERT(mBaseValue == mNextValue);
+    mBaseValue = value;
+    mNextValue = value;
+}
+
+GLuint HandleAllocator::allocate()
+{
+    if(mFreeValues.size())
+    {
+        GLuint handle = mFreeValues.back();
+        mFreeValues.pop_back();
+        return handle;
+    }
+    return mNextValue++;
+}
+
+void HandleAllocator::release(GLuint handle)
+{
+    if(handle == mNextValue - 1)
+    {
+        // Don't drop below base value
+        if(mNextValue > mBaseValue)
+        {
+            mNextValue--;
+        }
+    }
+    else
+    {
+        // Only free handles that we own - don't drop below the base value
+        if(handle >= mBaseValue)
+        {
+            mFreeValues.push_back(handle);
+        }
+    }
+}
+
+}
diff --git a/src/GLES2/libGLESv2/HandleAllocator.h b/src/GLES2/libGLESv2/HandleAllocator.h
new file mode 100644
index 0000000..3dc5a34
--- /dev/null
+++ b/src/GLES2/libGLESv2/HandleAllocator.h
@@ -0,0 +1,46 @@
+// SwiftShader Software Renderer

+//

+// Copyright(c) 2005-2012 TransGaming Inc.

+//

+// All rights reserved. No part of this software may be copied, distributed, transmitted,

+// transcribed, stored in a retrieval system, translated into any human or computer

+// language by any means, or disclosed to third parties without the explicit written

+// agreement of TransGaming Inc. Without such an agreement, no rights or licenses, express

+// or implied, including but not limited to any patent rights, are granted to you.

+//

+

+// HandleAllocator.h: Defines the HandleAllocator class, which is used to

+// allocate GL handles.

+

+#ifndef LIBGLESV2_HANDLEALLOCATOR_H_

+#define LIBGLESV2_HANDLEALLOCATOR_H_

+

+#define GL_APICALL

+#include <GLES2/gl2.h>

+

+#include <vector>

+

+namespace gl

+{

+

+class HandleAllocator

+{

+  public:

+    HandleAllocator();

+    virtual ~HandleAllocator();

+

+    void setBaseHandle(GLuint value);

+

+    GLuint allocate();

+    void release(GLuint handle);

+

+  private:

+    GLuint mBaseValue;

+    GLuint mNextValue;

+    typedef std::vector<GLuint> HandleList;

+    HandleList mFreeValues;

+};

+

+}

+

+#endif   // LIBGLESV2_HANDLEALLOCATOR_H_

diff --git a/src/GLES2/libGLESv2/Image.cpp b/src/GLES2/libGLESv2/Image.cpp
new file mode 100644
index 0000000..0b8220e
--- /dev/null
+++ b/src/GLES2/libGLESv2/Image.cpp
@@ -0,0 +1,660 @@
+// SwiftShader Software Renderer
+//
+// Copyright(c) 2005-2013 TransGaming Inc.
+//
+// All rights reserved. No part of this software may be copied, distributed, transmitted,
+// transcribed, stored in a retrieval system, translated into any human or computer
+// language by any means, or disclosed to third parties without the explicit written
+// agreement of TransGaming Inc. Without such an agreement, no rights or licenses, express
+// or implied, including but not limited to any patent rights, are granted to you.
+//
+
+#include "Image.hpp"
+
+#include "utilities.h"
+#include "../common/debug.h"
+#include "Common/Thread.hpp"
+
+#include <GLES2/gl2ext.h>
+
+namespace gl
+{
+	Image::Image(sw::Resource *parentTexture, GLsizei width, GLsizei height, GLenum format, GLenum type) : sw::Surface(parentTexture, width, height, 1, selectInternalFormat(format, type), true, true), width(width), height(height), internalFormat(selectInternalFormat(format, type)), format(format), type(type), multiSampleDepth(1)
+	{
+		referenceCount = 0;
+	}
+
+	Image::Image(sw::Resource *parentTexture, GLsizei width, GLsizei height, sw::Format internalFormat, GLenum format, GLenum type, int multiSampleDepth, bool lockable, bool renderTarget) : sw::Surface(parentTexture, width, height, multiSampleDepth, internalFormat, lockable, renderTarget), width(width), height(height), internalFormat(internalFormat), format(format), type(type), multiSampleDepth(multiSampleDepth)
+	{
+		referenceCount = 0;
+	}
+
+	Image::~Image()
+	{
+		ASSERT(referenceCount == 0);
+	}
+
+	void *Image::lock(unsigned int left, unsigned int top, sw::Lock lock)
+	{
+		return lockExternal(left, top, 0, lock, sw::PUBLIC);
+	}
+
+	unsigned int Image::getPitch() const
+	{
+		return getExternalPitchB();
+	}
+
+	void Image::unlock()
+	{
+		unlockExternal();
+	}
+
+	int Image::getWidth()
+	{
+		return width;
+	}
+	
+	int Image::getHeight()
+	{
+		return height;
+	}
+
+	GLenum Image::getFormat()
+	{
+		return format;
+	}
+	
+	GLenum Image::getType()
+	{
+		return type;
+	}
+	
+	sw::Format Image::getInternalFormat()
+	{
+		return internalFormat;
+	}
+	
+	int Image::getMultiSampleDepth()
+	{
+		return multiSampleDepth;
+	}
+
+	void Image::addRef()
+	{
+		sw::atomicIncrement(&referenceCount);
+	}
+
+	void Image::release()
+	{
+		if(referenceCount > 0)
+		{
+			sw::atomicDecrement(&referenceCount);
+		}
+
+		if(referenceCount == 0)
+		{
+			delete this;
+		}
+	}
+
+	sw::Format Image::selectInternalFormat(GLenum format, GLenum type)
+	{
+		#if S3TC_SUPPORT
+		if(format == GL_COMPRESSED_RGB_S3TC_DXT1_EXT ||
+		   format == GL_COMPRESSED_RGBA_S3TC_DXT1_EXT)
+		{
+			return sw::FORMAT_DXT1;
+		}
+		else if(format == GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE)
+		{
+			return sw::FORMAT_DXT3;
+		}
+		else if(format == GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE)
+		{
+			return sw::FORMAT_DXT5;
+		}
+		else
+		#endif
+		if(type == GL_FLOAT)
+		{
+			return sw::FORMAT_A32B32G32R32F;
+		}
+		else if(type == GL_HALF_FLOAT_OES)
+		{
+			return sw::FORMAT_A16B16G16R16F;
+		}
+		else if(type == GL_UNSIGNED_BYTE)
+		{
+			if(format == GL_LUMINANCE)
+			{
+				return sw::FORMAT_L8;
+			}
+			else if(format == GL_LUMINANCE_ALPHA)
+			{
+				return sw::FORMAT_A8L8;
+			}
+			else if(format == GL_RGBA || format == GL_BGRA_EXT)
+			{
+				return sw::FORMAT_A8R8G8B8;
+			}
+			else if(format == GL_RGB)
+			{
+				return sw::FORMAT_X8R8G8B8;
+			}
+			else if(format == GL_ALPHA)
+			{
+				return sw::FORMAT_A8;
+			}
+			else UNREACHABLE();
+		}
+		else if(type == GL_UNSIGNED_SHORT || type == GL_UNSIGNED_INT)
+		{
+			if(format == GL_DEPTH_COMPONENT)
+			{
+				return sw::FORMAT_D32FS8_TEXTURE;
+			}
+			else UNREACHABLE();
+		}
+		else if(type == GL_UNSIGNED_INT_24_8_OES)
+		{
+			if(format == GL_DEPTH_STENCIL_OES)
+			{
+				return sw::FORMAT_D32FS8_TEXTURE;
+			}
+			else UNREACHABLE();
+		}
+		else UNREACHABLE();
+
+		return sw::FORMAT_A8R8G8B8;
+	}
+
+	int Image::bytes(sw::Format format)
+	{
+		return sw::Surface::bytes(format);
+	}
+
+	void Image::loadImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *input)
+	{
+		GLsizei inputPitch = ComputePitch(width, format, type, unpackAlignment);
+		void *buffer = lock(0, 0, sw::LOCK_WRITEONLY);
+		
+		if(buffer)
+		{
+			switch(type)
+			{
+			case GL_UNSIGNED_BYTE:
+				switch(format)
+				{
+				case GL_ALPHA:
+					loadAlphaImageData(xoffset, yoffset, width, height, inputPitch, input, buffer);
+					break;
+				case GL_LUMINANCE:
+					loadLuminanceImageData(xoffset, yoffset, width, height, inputPitch, input, buffer);
+					break;
+				case GL_LUMINANCE_ALPHA:
+					loadLuminanceAlphaImageData(xoffset, yoffset, width, height, inputPitch, input, buffer);
+					break;
+				case GL_RGB:
+					loadRGBUByteImageData(xoffset, yoffset, width, height, inputPitch, input, buffer);
+					break;
+				case GL_RGBA:
+					loadRGBAUByteImageData(xoffset, yoffset, width, height, inputPitch, input, buffer);
+					break;
+				case GL_BGRA_EXT:
+					loadBGRAImageData(xoffset, yoffset, width, height, inputPitch, input, buffer);
+					break;
+				default: UNREACHABLE();
+				}
+				break;
+			case GL_UNSIGNED_SHORT_5_6_5:
+				switch(format)
+				{
+				case GL_RGB:
+					loadRGB565ImageData(xoffset, yoffset, width, height, inputPitch, input, buffer);
+					break;
+				default: UNREACHABLE();
+				}
+				break;
+			case GL_UNSIGNED_SHORT_4_4_4_4:
+				switch(format)
+				{
+				case GL_RGBA:
+					loadRGBA4444ImageData(xoffset, yoffset, width, height, inputPitch, input, buffer);
+					break;
+				default: UNREACHABLE();
+				}
+				break;
+			case GL_UNSIGNED_SHORT_5_5_5_1:
+				switch(format)
+				{
+				case GL_RGBA:
+					loadRGBA5551ImageData(xoffset, yoffset, width, height, inputPitch, input, buffer);
+					break;
+				default: UNREACHABLE();
+				}
+				break;
+			case GL_FLOAT:
+				switch(format)
+				{
+				// float textures are converted to RGBA, not BGRA
+				case GL_ALPHA:
+					loadAlphaFloatImageData(xoffset, yoffset, width, height, inputPitch, input, buffer);
+					break;
+				case GL_LUMINANCE:
+					loadLuminanceFloatImageData(xoffset, yoffset, width, height, inputPitch, input, buffer);
+					break;
+				case GL_LUMINANCE_ALPHA:
+					loadLuminanceAlphaFloatImageData(xoffset, yoffset, width, height, inputPitch, input, buffer);
+					break;
+				case GL_RGB:
+					loadRGBFloatImageData(xoffset, yoffset, width, height, inputPitch, input, buffer);
+					break;
+				case GL_RGBA:
+					loadRGBAFloatImageData(xoffset, yoffset, width, height, inputPitch, input, buffer);
+					break;
+				default: UNREACHABLE();
+				}
+				break;
+			  case GL_HALF_FLOAT_OES:
+				switch(format)
+				{
+				// float textures are converted to RGBA, not BGRA
+				case GL_ALPHA:
+					loadAlphaHalfFloatImageData(xoffset, yoffset, width, height, inputPitch, input, buffer);
+					break;
+				case GL_LUMINANCE:
+					loadLuminanceHalfFloatImageData(xoffset, yoffset, width, height, inputPitch, input, buffer);
+					break;
+				case GL_LUMINANCE_ALPHA:
+					loadLuminanceAlphaHalfFloatImageData(xoffset, yoffset, width, height, inputPitch, input, buffer);
+					break;
+				case GL_RGB:
+					loadRGBHalfFloatImageData(xoffset, yoffset, width, height, inputPitch, input, buffer);
+					break;
+				case GL_RGBA:
+					loadRGBAHalfFloatImageData(xoffset, yoffset, width, height, inputPitch, input, buffer);
+					break;
+				default: UNREACHABLE();
+				}
+				break;
+			case GL_UNSIGNED_SHORT:
+				loadD16ImageData(xoffset, yoffset, width, height, inputPitch, input, buffer);
+				break;
+			case GL_UNSIGNED_INT:
+				loadD32ImageData(xoffset, yoffset, width, height, inputPitch, input, buffer);
+				break;
+			case GL_UNSIGNED_INT_24_8_OES:
+				loadD24S8ImageData(xoffset, yoffset, width, height, inputPitch, input, buffer);
+				break;
+			default: UNREACHABLE();
+			}
+
+			unlock();
+		}
+	}
+
+	void Image::loadAlphaImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, int inputPitch, const void *input, void *buffer) const
+	{
+		for(int y = 0; y < height; y++)
+		{
+			const unsigned char *source = static_cast<const unsigned char*>(input) + y * inputPitch;
+			unsigned char *dest = static_cast<unsigned char*>(buffer) + (y + yoffset) * getPitch() + xoffset;
+
+			memcpy(dest, source, width);
+		}
+	}
+
+	void Image::loadAlphaFloatImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, int inputPitch, const void *input, void *buffer) const
+	{
+		for(int y = 0; y < height; y++)
+		{
+			const float *source = reinterpret_cast<const float*>(static_cast<const unsigned char*>(input) + y * inputPitch);
+			float *dest = reinterpret_cast<float*>(static_cast<unsigned char*>(buffer) + (y + yoffset) * getPitch() + xoffset * 16);
+			
+			for(int x = 0; x < width; x++)
+			{
+				dest[4 * x + 0] = 0;
+				dest[4 * x + 1] = 0;
+				dest[4 * x + 2] = 0;
+				dest[4 * x + 3] = source[x];
+			}
+		}
+	}
+
+	void Image::loadAlphaHalfFloatImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, int inputPitch, const void *input, void *buffer) const
+	{
+		for(int y = 0; y < height; y++)
+		{
+			const unsigned short *source = reinterpret_cast<const unsigned short*>(static_cast<const unsigned char*>(input) + y * inputPitch);
+			unsigned short *dest = reinterpret_cast<unsigned short*>(static_cast<unsigned char*>(buffer) + (y + yoffset) * getPitch() + xoffset * 8);
+			
+			for(int x = 0; x < width; x++)
+			{
+				dest[4 * x + 0] = 0;
+				dest[4 * x + 1] = 0;
+				dest[4 * x + 2] = 0;
+				dest[4 * x + 3] = source[x];
+			}
+		}
+	}
+
+	void Image::loadLuminanceImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, int inputPitch, const void *input, void *buffer) const
+	{
+		for(int y = 0; y < height; y++)
+		{
+			const unsigned char *source = static_cast<const unsigned char*>(input) + y * inputPitch;
+			unsigned char *dest = static_cast<unsigned char*>(buffer) + (y + yoffset) * getPitch() + xoffset;
+
+			memcpy(dest, source, width);
+		}
+	}
+
+	void Image::loadLuminanceFloatImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, int inputPitch, const void *input, void *buffer) const
+	{
+		for(int y = 0; y < height; y++)
+		{
+			const float *source = reinterpret_cast<const float*>(static_cast<const unsigned char*>(input) + y * inputPitch);
+			float *dest = reinterpret_cast<float*>(static_cast<unsigned char*>(buffer) + (y + yoffset) * getPitch() + xoffset * 16);
+			
+			for(int x = 0; x < width; x++)
+			{
+				dest[4 * x + 0] = source[x];
+				dest[4 * x + 1] = source[x];
+				dest[4 * x + 2] = source[x];
+				dest[4 * x + 3] = 1.0f;
+			}
+		}
+	}
+
+	void Image::loadLuminanceHalfFloatImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, int inputPitch, const void *input, void *buffer) const
+	{
+		for(int y = 0; y < height; y++)
+		{
+			const unsigned short *source = reinterpret_cast<const unsigned short*>(static_cast<const unsigned char*>(input) + y * inputPitch);
+			unsigned short *dest = reinterpret_cast<unsigned short*>(static_cast<unsigned char*>(buffer) + (y + yoffset) * getPitch() + xoffset * 8);
+			
+			for(int x = 0; x < width; x++)
+			{
+				dest[4 * x + 0] = source[x];
+				dest[4 * x + 1] = source[x];
+				dest[4 * x + 2] = source[x];
+				dest[4 * x + 3] = 0x3C00; // SEEEEEMMMMMMMMMM, S = 0, E = 15, M = 0: 16bit flpt representation of 1
+			}
+		}
+	}
+
+	void Image::loadLuminanceAlphaImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, int inputPitch, const void *input, void *buffer) const
+	{
+		for(int y = 0; y < height; y++)
+		{
+			const unsigned char *source = static_cast<const unsigned char*>(input) + y * inputPitch;
+			unsigned char *dest = static_cast<unsigned char*>(buffer) + (y + yoffset) * getPitch() + xoffset * 2;
+        
+			memcpy(dest, source, width * 2);
+		}
+	}
+
+	void Image::loadLuminanceAlphaFloatImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, int inputPitch, const void *input, void *buffer) const
+	{
+		for(int y = 0; y < height; y++)
+		{
+			const float *source = reinterpret_cast<const float*>(static_cast<const unsigned char*>(input) + y * inputPitch);
+			float *dest = reinterpret_cast<float*>(static_cast<unsigned char*>(buffer) + (y + yoffset) * getPitch() + xoffset * 16);
+			
+			for(int x = 0; x < width; x++)
+			{
+				dest[4 * x + 0] = source[2*x+0];
+				dest[4 * x + 1] = source[2*x+0];
+				dest[4 * x + 2] = source[2*x+0];
+				dest[4 * x + 3] = source[2*x+1];
+			}
+		}
+	}
+
+	void Image::loadLuminanceAlphaHalfFloatImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, int inputPitch, const void *input, void *buffer) const
+	{
+		for(int y = 0; y < height; y++)
+		{
+			const unsigned short *source = reinterpret_cast<const unsigned short*>(static_cast<const unsigned char*>(input) + y * inputPitch);
+			unsigned short *dest = reinterpret_cast<unsigned short*>(static_cast<unsigned char*>(buffer) + (y + yoffset) * getPitch() + xoffset * 8);
+			
+			for(int x = 0; x < width; x++)
+			{
+				dest[4 * x + 0] = source[2*x+0];
+				dest[4 * x + 1] = source[2*x+0];
+				dest[4 * x + 2] = source[2*x+0];
+				dest[4 * x + 3] = source[2*x+1];
+			}
+		}
+	}
+
+	void Image::loadRGBUByteImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, int inputPitch, const void *input, void *buffer) const
+	{
+		for(int y = 0; y < height; y++)
+		{
+			const unsigned char *source = static_cast<const unsigned char*>(input) + y * inputPitch;
+			unsigned char *dest = static_cast<unsigned char*>(buffer) + (y + yoffset) * getPitch() + xoffset * 4;
+			
+			for(int x = 0; x < width; x++)
+			{
+				dest[4 * x + 0] = source[x * 3 + 2];
+				dest[4 * x + 1] = source[x * 3 + 1];
+				dest[4 * x + 2] = source[x * 3 + 0];
+				dest[4 * x + 3] = 0xFF;
+			}
+		}
+	}
+
+	void Image::loadRGB565ImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, int inputPitch, const void *input, void *buffer) const
+	{
+		for(int y = 0; y < height; y++)
+		{
+			const unsigned short *source = reinterpret_cast<const unsigned short*>(static_cast<const unsigned char*>(input) + y * inputPitch);
+			unsigned char *dest = static_cast<unsigned char*>(buffer) + (y + yoffset) * getPitch() + xoffset * 4;
+			
+			for(int x = 0; x < width; x++)
+			{
+				unsigned short rgba = source[x];
+				dest[4 * x + 0] = ((rgba & 0x001F) << 3) | ((rgba & 0x001F) >> 2);
+				dest[4 * x + 1] = ((rgba & 0x07E0) >> 3) | ((rgba & 0x07E0) >> 9);
+				dest[4 * x + 2] = ((rgba & 0xF800) >> 8) | ((rgba & 0xF800) >> 13);
+				dest[4 * x + 3] = 0xFF;
+			}
+		}
+	}
+
+	void Image::loadRGBFloatImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, int inputPitch, const void *input, void *buffer) const
+	{
+		for(int y = 0; y < height; y++)
+		{
+			const float *source = reinterpret_cast<const float*>(static_cast<const unsigned char*>(input) + y * inputPitch);
+			float *dest = reinterpret_cast<float*>(static_cast<unsigned char*>(buffer) + (y + yoffset) * getPitch() + xoffset * 16);
+			
+			for(int x = 0; x < width; x++)
+			{
+				dest[4 * x + 0] = source[x * 3 + 0];
+				dest[4 * x + 1] = source[x * 3 + 1];
+				dest[4 * x + 2] = source[x * 3 + 2];
+				dest[4 * x + 3] = 1.0f;
+			}
+		}
+	}
+
+	void Image::loadRGBHalfFloatImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, int inputPitch, const void *input, void *buffer) const
+	{
+		for(int y = 0; y < height; y++)
+		{
+			const unsigned short *source = reinterpret_cast<const unsigned short*>(static_cast<const unsigned char*>(input) + y * inputPitch);
+			unsigned short *dest = reinterpret_cast<unsigned short*>(static_cast<unsigned char*>(buffer) + (y + yoffset) * getPitch() + xoffset * 8);
+			
+			for(int x = 0; x < width; x++)
+			{
+				dest[4 * x + 0] = source[x * 3 + 0];
+				dest[4 * x + 1] = source[x * 3 + 1];
+				dest[4 * x + 2] = source[x * 3 + 2];
+				dest[4 * x + 3] = 0x3C00; // SEEEEEMMMMMMMMMM, S = 0, E = 15, M = 0: 16bit flpt representation of 1
+			}
+		}
+	}
+
+	void Image::loadRGBAUByteImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, int inputPitch, const void *input, void *buffer) const
+	{
+		for(int y = 0; y < height; y++)
+		{
+			const unsigned int *source = reinterpret_cast<const unsigned int*>(static_cast<const unsigned char*>(input) + y * inputPitch);
+			unsigned int *dest = reinterpret_cast<unsigned int*>(static_cast<unsigned char*>(buffer) + (y + yoffset) * getPitch() + xoffset * 4);
+
+			for(int x = 0; x < width; x++)
+			{
+				unsigned int rgba = source[x];
+				dest[x] = (rgba & 0xFF00FF00) | ((rgba << 16) & 0x00FF0000) | ((rgba >> 16) & 0x000000FF);
+			}
+		}
+	}
+
+	void Image::loadRGBA4444ImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, int inputPitch, const void *input, void *buffer) const
+	{
+		for(int y = 0; y < height; y++)
+		{
+			const unsigned short *source = reinterpret_cast<const unsigned short*>(static_cast<const unsigned char*>(input) + y * inputPitch);
+			unsigned char *dest = static_cast<unsigned char*>(buffer) + (y + yoffset) * getPitch() + xoffset * 4;
+			
+			for(int x = 0; x < width; x++)
+			{
+				unsigned short rgba = source[x];
+				dest[4 * x + 0] = ((rgba & 0x00F0) << 0) | ((rgba & 0x00F0) >> 4);
+				dest[4 * x + 1] = ((rgba & 0x0F00) >> 4) | ((rgba & 0x0F00) >> 8);
+				dest[4 * x + 2] = ((rgba & 0xF000) >> 8) | ((rgba & 0xF000) >> 12);
+				dest[4 * x + 3] = ((rgba & 0x000F) << 4) | ((rgba & 0x000F) >> 0);
+			}
+		}
+	}
+
+	void Image::loadRGBA5551ImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, int inputPitch, const void *input, void *buffer) const
+	{
+		for(int y = 0; y < height; y++)
+		{
+			const unsigned short *source = reinterpret_cast<const unsigned short*>(static_cast<const unsigned char*>(input) + y * inputPitch);
+			unsigned char *dest = static_cast<unsigned char*>(buffer) + (y + yoffset) * getPitch() + xoffset * 4;
+			
+			for(int x = 0; x < width; x++)
+			{
+				unsigned short rgba = source[x];
+				dest[4 * x + 0] = ((rgba & 0x003E) << 2) | ((rgba & 0x003E) >> 3);
+				dest[4 * x + 1] = ((rgba & 0x07C0) >> 3) | ((rgba & 0x07C0) >> 8);
+				dest[4 * x + 2] = ((rgba & 0xF800) >> 8) | ((rgba & 0xF800) >> 13);
+				dest[4 * x + 3] = (rgba & 0x0001) ? 0xFF : 0;
+			}
+		}
+	}
+
+	void Image::loadRGBAFloatImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, int inputPitch, const void *input, void *buffer) const
+	{
+		for(int y = 0; y < height; y++)
+		{
+			const float *source = reinterpret_cast<const float*>(static_cast<const unsigned char*>(input) + y * inputPitch);
+			float *dest = reinterpret_cast<float*>(static_cast<unsigned char*>(buffer) + (y + yoffset) * getPitch() + xoffset * 16);
+			
+			memcpy(dest, source, width * 16);
+		}
+	}
+
+	void Image::loadRGBAHalfFloatImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, int inputPitch, const void *input, void *buffer) const
+	{
+		for(int y = 0; y < height; y++)
+		{
+			const unsigned char *source = static_cast<const unsigned char*>(input) + y * inputPitch;
+			unsigned char *dest = static_cast<unsigned char*>(buffer) + (y + yoffset) * getPitch() + xoffset * 8;
+			
+			memcpy(dest, source, width * 8);
+		}
+	}
+
+	void Image::loadBGRAImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, int inputPitch, const void *input, void *buffer) const
+	{
+		for(int y = 0; y < height; y++)
+		{
+			const unsigned char *source = static_cast<const unsigned char*>(input) + y * inputPitch;
+			unsigned char *dest = static_cast<unsigned char*>(buffer) + (y + yoffset) * getPitch() + xoffset * 4;
+			
+			memcpy(dest, source, width*4);
+		}
+	}
+
+	void Image::loadD16ImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, int inputPitch, const void *input, void *buffer) const
+	{
+		for(int y = 0; y < height; y++)
+		{
+			const unsigned short *source = reinterpret_cast<const unsigned short*>(static_cast<const unsigned char*>(input) + y * inputPitch);
+			float *dest = reinterpret_cast<float*>(static_cast<unsigned char*>(buffer) + (y + yoffset) * getPitch() + xoffset * 4);
+
+			for(int x = 0; x < width; x++)
+			{
+				dest[x] = (float)source[x] / 0xFFFF;
+			}
+		}
+	}
+
+	void Image::loadD32ImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, int inputPitch, const void *input, void *buffer) const
+	{
+		for(int y = 0; y < height; y++)
+		{
+			const unsigned int *source = reinterpret_cast<const unsigned int*>(static_cast<const unsigned char*>(input) + y * inputPitch);
+			float *dest = reinterpret_cast<float*>(static_cast<unsigned char*>(buffer) + (y + yoffset) * getPitch() + xoffset * 4);
+
+			for(int x = 0; x < width; x++)
+			{
+				dest[x] = (float)source[x] / 0xFFFFFFFF;
+			}
+		}
+	}
+
+	void Image::loadD24S8ImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, int inputPitch, const void *input, void *buffer)
+	{
+		for(int y = 0; y < height; y++)
+		{
+			const unsigned int *source = reinterpret_cast<const unsigned int*>(static_cast<const unsigned char*>(input) + y * inputPitch);
+			float *dest = reinterpret_cast<float*>(static_cast<unsigned char*>(buffer) + (y + yoffset) * getPitch() + xoffset * 4);
+
+			for(int x = 0; x < width; x++)
+			{
+				dest[x] = (float)(source[x] & 0xFFFFFF00) / 0xFFFFFF00;
+			}
+		}
+
+		unsigned char *stencil = reinterpret_cast<unsigned char*>(lockStencil(0, sw::PUBLIC));
+
+		if(stencil)
+		{
+			for(int y = 0; y < height; y++)
+			{
+				const unsigned int *source = reinterpret_cast<const unsigned int*>(static_cast<const unsigned char*>(input) + y * inputPitch);
+				unsigned char *dest = static_cast<unsigned char*>(stencil) + (y + yoffset) * getStencilPitchB() + xoffset;
+
+				for(int x = 0; x < width; x++)
+				{
+					dest[x] = static_cast<unsigned char>(source[x] & 0x000000FF);   // FIXME: Quad layout
+				}
+			}
+
+			unlockStencil();
+		}
+	}
+
+	void Image::loadCompressedData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLsizei imageSize, const void *pixels)
+	{
+		int inputPitch = ComputeCompressedPitch(width, format);
+		int rows = imageSize / inputPitch;
+		void *buffer = lock(xoffset, yoffset, sw::LOCK_WRITEONLY);
+
+        if(buffer)
+        {
+			for(int i = 0; i < rows; i++)
+			{
+				memcpy((void*)((GLbyte*)buffer + i * getPitch()), (void*)((GLbyte*)pixels + i * inputPitch), inputPitch);
+			}
+
+            unlock();
+        }
+	}
+}
\ No newline at end of file
diff --git a/src/GLES2/libGLESv2/Image.hpp b/src/GLES2/libGLESv2/Image.hpp
new file mode 100644
index 0000000..baf963d
--- /dev/null
+++ b/src/GLES2/libGLESv2/Image.hpp
@@ -0,0 +1,85 @@
+// SwiftShader Software Renderer
+//
+// Copyright(c) 2005-2013 TransGaming Inc.
+//
+// All rights reserved. No part of this software may be copied, distributed, transmitted,
+// transcribed, stored in a retrieval system, translated into any human or computer
+// language by any means, or disclosed to third parties without the explicit written
+// agreement of TransGaming Inc. Without such an agreement, no rights or licenses, express
+// or implied, including but not limited to any patent rights, are granted to you.
+//
+
+#ifndef gl_Image_hpp
+#define gl_Image_hpp
+
+#include "Renderer/Surface.hpp"
+
+#define GL_APICALL
+#include <GLES2/gl2.h>
+
+namespace gl
+{
+	class Image : public sw::Surface
+	{
+	public:
+		Image(sw::Resource *parentTexture, GLsizei width, GLsizei height, GLenum format, GLenum type);
+		Image(sw::Resource *parentTexture, GLsizei width, GLsizei height, sw::Format internalFormat, GLenum format, GLenum type, int multiSampleDepth, bool lockable, bool renderTarget);
+
+		void loadImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *input);
+		void loadCompressedData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLsizei imageSize, const void *pixels);
+
+		void *lock(unsigned int left, unsigned int top, sw::Lock lock);
+		unsigned int getPitch() const;
+		void unlock();
+		
+		int getWidth();
+		int getHeight();
+		GLenum getFormat();
+		GLenum getType();
+		virtual sw::Format getInternalFormat();
+		int getMultiSampleDepth();
+
+		virtual void addRef();
+		virtual void release();
+
+		static sw::Format selectInternalFormat(GLenum format, GLenum type);
+		static int bytes(sw::Format format);
+
+	private:
+		virtual ~Image();
+
+		void loadAlphaImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, int inputPitch, const void *input, void *buffer) const;
+		void loadAlphaFloatImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, int inputPitch, const void *input, void *buffer) const;
+		void loadAlphaHalfFloatImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, int inputPitch, const void *input, void *buffer) const;
+		void loadLuminanceImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, int inputPitch, const void *input, void *buffer) const;
+		void loadLuminanceFloatImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, int inputPitch, const void *input, void *buffer) const;
+		void loadLuminanceHalfFloatImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, int inputPitch, const void *input, void *buffer) const;
+		void loadLuminanceAlphaImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, int inputPitch, const void *input, void *buffer) const;
+		void loadLuminanceAlphaFloatImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, int inputPitch, const void *input, void *buffer) const;
+		void loadLuminanceAlphaHalfFloatImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, int inputPitch, const void *input, void *buffer) const;
+		void loadRGBUByteImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, int inputPitch, const void *input, void *buffer) const;
+		void loadRGB565ImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, int inputPitch, const void *input, void *buffer) const;
+		void loadRGBFloatImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, int inputPitch, const void *input, void *buffer) const;
+		void loadRGBHalfFloatImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, int inputPitch, const void *input, void *buffer) const;
+		void loadRGBAUByteImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, int inputPitch, const void *input, void *buffer) const;
+		void loadRGBA4444ImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, int inputPitch, const void *input, void *buffer) const;
+		void loadRGBA5551ImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, int inputPitch, const void *input, void *buffer) const;
+		void loadRGBAFloatImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, int inputPitch, const void *input, void *buffer) const;
+		void loadRGBAHalfFloatImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, int inputPitch, const void *input, void *buffer) const;
+		void loadBGRAImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, int inputPitch, const void *input, void *buffer) const;
+		void loadD16ImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, int inputPitch, const void *input, void *buffer) const;
+		void loadD32ImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, int inputPitch, const void *input, void *buffer) const;
+		void loadD24S8ImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, int inputPitch, const void *input, void *buffer);
+
+		const GLsizei width;
+		const GLsizei height;
+		const GLenum format;
+		const GLenum type;
+		const sw::Format internalFormat;
+		const int multiSampleDepth;
+
+		volatile int referenceCount;
+	};
+}
+
+#endif   // gl_Image_hpp
diff --git a/src/GLES2/libGLESv2/IndexDataManager.cpp b/src/GLES2/libGLESv2/IndexDataManager.cpp
new file mode 100644
index 0000000..ab445b3
--- /dev/null
+++ b/src/GLES2/libGLESv2/IndexDataManager.cpp
@@ -0,0 +1,258 @@
+// SwiftShader Software Renderer

+//

+// Copyright(c) 2005-2012 TransGaming Inc.

+//

+// All rights reserved. No part of this software may be copied, distributed, transmitted,

+// transcribed, stored in a retrieval system, translated into any human or computer

+// language by any means, or disclosed to third parties without the explicit written

+// agreement of TransGaming Inc. Without such an agreement, no rights or licenses, express

+// or implied, including but not limited to any patent rights, are granted to you.

+//

+

+// IndexDataManager.cpp: Defines the IndexDataManager, a class that

+// runs the Buffer translation process for index buffers.

+

+#include "IndexDataManager.h"

+

+#include "Buffer.h"

+#include "common/debug.h"

+

+#include <string.h>

+

+namespace

+{

+    enum { INITIAL_INDEX_BUFFER_SIZE = 4096 * sizeof(GLuint) };

+}

+

+namespace gl

+{

+

+IndexDataManager::IndexDataManager()

+{

+    mStreamingBuffer = new StreamingIndexBuffer(INITIAL_INDEX_BUFFER_SIZE);

+

+    if(!mStreamingBuffer)

+    {

+        ERR("Failed to allocate the streaming index buffer.");

+    }

+}

+

+IndexDataManager::~IndexDataManager()

+{

+    delete mStreamingBuffer;

+}

+

+void copyIndices(GLenum type, const void *input, GLsizei count, void *output)

+{

+    if(type == GL_UNSIGNED_BYTE)

+    {

+        memcpy(output, input, count * sizeof(GLubyte));

+    }

+    else if(type == GL_UNSIGNED_INT)

+    {

+        memcpy(output, input, count * sizeof(GLuint));

+    }

+    else if(type == GL_UNSIGNED_SHORT)

+    {

+        memcpy(output, input, count * sizeof(GLushort));

+    }

+    else UNREACHABLE();

+}

+

+template<class IndexType>

+void computeRange(const IndexType *indices, GLsizei count, GLuint *minIndex, GLuint *maxIndex)

+{

+    *minIndex = indices[0];

+    *maxIndex = indices[0];

+

+    for(GLsizei i = 0; i < count; i++)

+    {

+        if(*minIndex > indices[i]) *minIndex = indices[i];

+        if(*maxIndex < indices[i]) *maxIndex = indices[i];

+    }

+}

+

+void computeRange(GLenum type, const void *indices, GLsizei count, GLuint *minIndex, GLuint *maxIndex)

+{

+    if(type == GL_UNSIGNED_BYTE)

+    {

+        computeRange(static_cast<const GLubyte*>(indices), count, minIndex, maxIndex);

+    }

+    else if(type == GL_UNSIGNED_INT)

+    {

+        computeRange(static_cast<const GLuint*>(indices), count, minIndex, maxIndex);

+    }

+    else if(type == GL_UNSIGNED_SHORT)

+    {

+        computeRange(static_cast<const GLushort*>(indices), count, minIndex, maxIndex);

+    }

+    else UNREACHABLE();

+}

+

+GLenum IndexDataManager::prepareIndexData(GLenum type, GLsizei count, Buffer *buffer, const void *indices, TranslatedIndexData *translated)

+{

+    if(!mStreamingBuffer)

+    {

+        return GL_OUT_OF_MEMORY;

+    }

+

+    intptr_t offset = reinterpret_cast<intptr_t>(indices);

+    bool alignedOffset = false;

+

+    if(buffer != NULL)

+    {

+        switch(type)

+        {

+          case GL_UNSIGNED_BYTE:  alignedOffset = (offset % sizeof(GLubyte) == 0);  break;

+          case GL_UNSIGNED_SHORT: alignedOffset = (offset % sizeof(GLushort) == 0); break;

+          case GL_UNSIGNED_INT:   alignedOffset = (offset % sizeof(GLuint) == 0);   break;

+          default: UNREACHABLE(); alignedOffset = false;

+        }

+

+        if(typeSize(type) * count + offset > static_cast<std::size_t>(buffer->size()))

+        {

+            return GL_INVALID_OPERATION;

+        }

+

+        indices = static_cast<const GLubyte*>(buffer->data()) + offset;

+    }

+

+    StreamingIndexBuffer *streamingBuffer = mStreamingBuffer;

+

+	sw::Resource *staticBuffer = buffer ? buffer->getResource() : NULL;

+

+    if(staticBuffer)

+    {

+        computeRange(type, indices, count, &translated->minIndex, &translated->maxIndex);

+

+		translated->indexBuffer = staticBuffer;

+		translated->indexOffset = offset;

+    }

+    else

+    {

+		unsigned int streamOffset = 0;

+        int convertCount = count;

+

+        streamingBuffer->reserveSpace(convertCount * typeSize(type), type);

+        void *output = streamingBuffer->map(typeSize(type) * convertCount, &streamOffset);

+        

+        if(output == NULL)

+        {

+            ERR("Failed to map index buffer.");

+            return GL_OUT_OF_MEMORY;

+        }

+

+        copyIndices(type, staticBuffer ? buffer->data() : indices, convertCount, output);

+        streamingBuffer->unmap();

+

+        computeRange(type, indices, count, &translated->minIndex, &translated->maxIndex);

+

+		translated->indexBuffer = streamingBuffer->getResource();

+		translated->indexOffset = streamOffset;

+    }

+

+    return GL_NO_ERROR;

+}

+

+std::size_t IndexDataManager::typeSize(GLenum type)

+{

+    switch(type)

+    {

+    case GL_UNSIGNED_INT:   return sizeof(GLuint);

+    case GL_UNSIGNED_SHORT: return sizeof(GLushort);

+    case GL_UNSIGNED_BYTE:  return sizeof(GLubyte);

+    default: UNREACHABLE(); return sizeof(GLushort);

+    }

+}

+

+StreamingIndexBuffer::StreamingIndexBuffer(unsigned int initialSize) : mBufferSize(initialSize), mIndexBuffer(NULL)

+{

+	if(initialSize > 0)

+    {

+		mIndexBuffer = new sw::Resource(initialSize + 16);

+

+        if(!mIndexBuffer)

+        {

+            ERR("Out of memory allocating an index buffer of size %lu.", initialSize);

+        }

+    }

+

+    mWritePosition = 0;

+}

+

+StreamingIndexBuffer::~StreamingIndexBuffer()

+{

+	if(mIndexBuffer)

+    {

+        mIndexBuffer->destruct();

+    }

+}

+

+void *StreamingIndexBuffer::map(unsigned int requiredSpace, unsigned int *offset)

+{

+    void *mapPtr = NULL;

+

+    if(mIndexBuffer)

+    {

+        mapPtr = (char*)mIndexBuffer->lock(sw::PUBLIC) + mWritePosition;

+     

+        if(!mapPtr)

+        {

+            ERR(" Lock failed");

+            return NULL;

+        }

+

+        *offset = mWritePosition;

+        mWritePosition += requiredSpace;

+    }

+

+    return mapPtr;

+}

+

+void StreamingIndexBuffer::unmap()

+{

+    if(mIndexBuffer)

+    {

+        mIndexBuffer->unlock();

+    }

+}

+

+void StreamingIndexBuffer::reserveSpace(unsigned int requiredSpace, GLenum type)

+{

+    if(requiredSpace > mBufferSize)

+    {

+        if(mIndexBuffer)

+        {

+            mIndexBuffer->destruct();

+            mIndexBuffer = 0;

+        }

+

+        mBufferSize = std::max(requiredSpace, 2 * mBufferSize);

+

+		mIndexBuffer = new sw::Resource(mBufferSize + 16);

+    

+        if(!mIndexBuffer)

+        {

+            ERR("Out of memory allocating an index buffer of size %lu.", mBufferSize);

+        }

+

+        mWritePosition = 0;

+    }

+    else if(mWritePosition + requiredSpace > mBufferSize)   // Recycle

+    {

+		if(mIndexBuffer)

+		{

+			mIndexBuffer->destruct();

+			mIndexBuffer = new sw::Resource(mBufferSize + 16);

+		}

+

+        mWritePosition = 0;

+    }

+}

+

+sw::Resource *StreamingIndexBuffer::getResource() const

+{

+    return mIndexBuffer;

+}

+

+}

diff --git a/src/GLES2/libGLESv2/IndexDataManager.h b/src/GLES2/libGLESv2/IndexDataManager.h
new file mode 100644
index 0000000..059e9fc
--- /dev/null
+++ b/src/GLES2/libGLESv2/IndexDataManager.h
@@ -0,0 +1,69 @@
+// SwiftShader Software Renderer

+//

+// Copyright(c) 2005-2012 TransGaming Inc.

+//

+// All rights reserved. No part of this software may be copied, distributed, transmitted,

+// transcribed, stored in a retrieval system, translated into any human or computer

+// language by any means, or disclosed to third parties without the explicit written

+// agreement of TransGaming Inc. Without such an agreement, no rights or licenses, express

+// or implied, including but not limited to any patent rights, are granted to you.

+//

+

+// IndexDataManager.h: Defines the IndexDataManager, a class that

+// runs the Buffer translation process for index buffers.

+

+#ifndef LIBGLESV2_INDEXDATAMANAGER_H_

+#define LIBGLESV2_INDEXDATAMANAGER_H_

+

+#include "Context.h"

+

+#define GL_APICALL

+#include <GLES2/gl2.h>

+

+namespace gl

+{

+

+struct TranslatedIndexData

+{

+    unsigned int minIndex;

+    unsigned int maxIndex;

+    unsigned int indexOffset;

+

+    sw::Resource *indexBuffer;

+};

+

+class StreamingIndexBuffer

+{

+  public:

+    StreamingIndexBuffer(unsigned int initialSize);

+    virtual ~StreamingIndexBuffer();

+

+    void *map(unsigned int requiredSpace, unsigned int *offset);

+	void unmap();

+    void reserveSpace(unsigned int requiredSpace, GLenum type);

+

+	sw::Resource *getResource() const;

+

+  private:

+    sw::Resource *mIndexBuffer;

+    unsigned int mBufferSize;

+    unsigned int mWritePosition;

+};

+

+class IndexDataManager

+{

+  public:

+    IndexDataManager();

+    virtual ~IndexDataManager();

+

+    GLenum prepareIndexData(GLenum type, GLsizei count, Buffer *arrayElementBuffer, const void *indices, TranslatedIndexData *translated);

+

+	static std::size_t typeSize(GLenum type);

+

+  private:

+    StreamingIndexBuffer *mStreamingBuffer;

+};

+

+}

+

+#endif   // LIBGLESV2_INDEXDATAMANAGER_H_

diff --git a/src/GLES2/libGLESv2/Program.cpp b/src/GLES2/libGLESv2/Program.cpp
new file mode 100644
index 0000000..a1ad45e
--- /dev/null
+++ b/src/GLES2/libGLESv2/Program.cpp
@@ -0,0 +1,2285 @@
+// SwiftShader Software Renderer

+//

+// Copyright(c) 2005-2013 TransGaming Inc.

+//

+// All rights reserved. No part of this software may be copied, distributed, transmitted,

+// transcribed, stored in a retrieval system, translated into any human or computer

+// language by any means, or disclosed to third parties without the explicit written

+// agreement of TransGaming Inc. Without such an agreement, no rights or licenses, express

+// or implied, including but not limited to any patent rights, are granted to you.

+//

+

+// Program.cpp: Implements the Program class. Implements GL program objects

+// and related functionality. [OpenGL ES 2.0.24] section 2.10.3 page 28.

+

+#include "Program.h"

+

+#include "main.h"

+#include "Shader.h"

+#include "utilities.h"

+#include "common/debug.h"

+#include "Shader/PixelShader.hpp"

+#include "Shader/VertexShader.hpp"

+

+#include <string>

+#include <stdlib.h>

+

+namespace gl

+{

+	unsigned int Program::currentSerial = 1;

+

+	std::string str(int i)

+	{

+		char buffer[20];

+		sprintf(buffer, "%d", i);

+		return buffer;

+	}

+

+	Uniform::Uniform(GLenum type, const std::string &name, unsigned int arraySize) : type(type), name(name), arraySize(arraySize)

+	{

+		int bytes = UniformTypeSize(type) * size();

+		data = new unsigned char[bytes];

+		memset(data, 0, bytes);

+		dirty = true;

+

+		psRegisterIndex = -1;

+		vsRegisterIndex = -1;

+	}

+

+	Uniform::~Uniform()

+	{

+		delete[] data;

+	}

+

+	bool Uniform::isArray() const

+	{

+		return arraySize >= 1;

+	}

+

+	int Uniform::size() const

+	{

+		return arraySize > 0 ? arraySize : 1;

+	}

+

+	int Uniform::registerCount() const

+	{

+		return size() * VariableRowCount(type);

+	}

+

+	UniformLocation::UniformLocation(const std::string &name, unsigned int element, unsigned int index) : name(name), element(element), index(index)

+	{

+	}

+

+	Program::Program(ResourceManager *manager, GLuint handle) : resourceManager(manager), handle(handle), serial(issueSerial())

+	{

+		device = getDevice();

+

+		fragmentShader = 0;

+		vertexShader = 0;

+		pixelBinary = 0;

+		vertexBinary = 0;

+

+		infoLog = 0;

+		validated = false;

+

+		unlink();

+

+		orphaned = false;

+		referenceCount = 0;

+	}

+

+	Program::~Program()

+	{

+		unlink();

+

+		if(vertexShader)

+		{

+			vertexShader->release();

+		}

+

+		if(fragmentShader)

+		{

+			fragmentShader->release();

+		}

+	}

+

+	bool Program::attachShader(Shader *shader)

+	{

+		if(shader->getType() == GL_VERTEX_SHADER)

+		{

+			if(vertexShader)

+			{

+				return false;

+			}

+

+			vertexShader = (VertexShader*)shader;

+			vertexShader->addRef();

+		}

+		else if(shader->getType() == GL_FRAGMENT_SHADER)

+		{

+			if(fragmentShader)

+			{

+				return false;

+			}

+

+			fragmentShader = (FragmentShader*)shader;

+			fragmentShader->addRef();

+		}

+		else UNREACHABLE();

+

+		return true;

+	}

+

+	bool Program::detachShader(Shader *shader)

+	{

+		if(shader->getType() == GL_VERTEX_SHADER)

+		{

+			if(vertexShader != shader)

+			{

+				return false;

+			}

+

+			vertexShader->release();

+			vertexShader = 0;

+		}

+		else if(shader->getType() == GL_FRAGMENT_SHADER)

+		{

+			if(fragmentShader != shader)

+			{

+				return false;

+			}

+

+			fragmentShader->release();

+			fragmentShader = 0;

+		}

+		else UNREACHABLE();

+

+		return true;

+	}

+

+	int Program::getAttachedShadersCount() const

+	{

+		return (vertexShader ? 1 : 0) + (fragmentShader ? 1 : 0);

+	}

+

+	sw::PixelShader *Program::getPixelShader()

+	{

+		return pixelBinary;

+	}

+

+	sw::VertexShader *Program::getVertexShader()

+	{

+		return vertexBinary;

+	}

+

+	void Program::bindAttributeLocation(GLuint index, const char *name)

+	{

+		if(index < MAX_VERTEX_ATTRIBS)

+		{

+			for(int i = 0; i < MAX_VERTEX_ATTRIBS; i++)

+			{

+				attributeBinding[i].erase(name);

+			}

+

+			attributeBinding[index].insert(name);

+		}

+	}

+

+	GLuint Program::getAttributeLocation(const char *name)

+	{

+		if(name)

+		{

+			for(int index = 0; index < MAX_VERTEX_ATTRIBS; index++)

+			{

+				if(linkedAttribute[index].name == std::string(name))

+				{

+					return index;

+				}

+			}

+		}

+

+		return -1;

+	}

+

+	int Program::getAttributeStream(int attributeIndex)

+	{

+		ASSERT(attributeIndex >= 0 && attributeIndex < MAX_VERTEX_ATTRIBS);

+    

+		return attributeStream[attributeIndex];

+	}

+

+	// Returns the index of the texture image unit (0-19) corresponding to a sampler index (0-15 for the pixel shader and 0-3 for the vertex shader)

+	GLint Program::getSamplerMapping(sw::SamplerType type, unsigned int samplerIndex)

+	{

+		GLuint logicalTextureUnit = -1;

+

+		switch(type)

+		{

+		case sw::SAMPLER_PIXEL:

+			ASSERT(samplerIndex < sizeof(samplersPS) / sizeof(samplersPS[0]));

+

+			if(samplersPS[samplerIndex].active)

+			{

+				logicalTextureUnit = samplersPS[samplerIndex].logicalTextureUnit;

+			}

+			break;

+		case sw::SAMPLER_VERTEX:

+			ASSERT(samplerIndex < sizeof(samplersVS) / sizeof(samplersVS[0]));

+

+			if(samplersVS[samplerIndex].active)

+			{

+				logicalTextureUnit = samplersVS[samplerIndex].logicalTextureUnit;

+			}

+			break;

+		default: UNREACHABLE();

+		}

+

+		if(logicalTextureUnit >= 0 && logicalTextureUnit < MAX_COMBINED_TEXTURE_IMAGE_UNITS)

+		{

+			return logicalTextureUnit;

+		}

+

+		return -1;

+	}

+

+	// Returns the texture type for a given sampler type and index (0-15 for the pixel shader and 0-3 for the vertex shader)

+	TextureType Program::getSamplerTextureType(sw::SamplerType type, unsigned int samplerIndex)

+	{

+		switch(type)

+		{

+		case sw::SAMPLER_PIXEL:

+			ASSERT(samplerIndex < sizeof(samplersPS)/sizeof(samplersPS[0]));

+			ASSERT(samplersPS[samplerIndex].active);

+			return samplersPS[samplerIndex].textureType;

+		case sw::SAMPLER_VERTEX:

+			ASSERT(samplerIndex < sizeof(samplersVS)/sizeof(samplersVS[0]));

+			ASSERT(samplersVS[samplerIndex].active);

+			return samplersVS[samplerIndex].textureType;

+		default: UNREACHABLE();

+		}

+

+		return TEXTURE_2D;

+	}

+

+	GLint Program::getUniformLocation(std::string name)

+	{

+		int subscript = 0;

+

+		// Strip any trailing array operator and retrieve the subscript

+		size_t open = name.find_last_of('[');

+		size_t close = name.find_last_of(']');

+		if(open != std::string::npos && close == name.length() - 1)

+		{

+			subscript = atoi(name.substr(open + 1).c_str());

+			name.erase(open);

+		}

+

+		unsigned int numUniforms = uniformIndex.size();

+		for(unsigned int location = 0; location < numUniforms; location++)

+		{

+			if(uniformIndex[location].name == name &&

+			   uniformIndex[location].element == subscript)

+			{

+				return location;

+			}

+		}

+

+		return -1;

+	}

+

+	bool Program::setUniform1fv(GLint location, GLsizei count, const GLfloat* v)

+	{

+		if(location < 0 || location >= (int)uniformIndex.size())

+		{

+			return false;

+		}

+

+		Uniform *targetUniform = uniforms[uniformIndex[location].index];

+		targetUniform->dirty = true;

+

+		int size = targetUniform->size();

+

+		if(size == 1 && count > 1)

+		{

+			return false;   // Attempting to write an array to a non-array uniform is an INVALID_OPERATION

+		}

+	

+		count = std::min(size - (int)uniformIndex[location].element, count);

+

+		if(targetUniform->type == GL_FLOAT)

+		{

+			memcpy(targetUniform->data + uniformIndex[location].element * sizeof(GLfloat),

+				   v, sizeof(GLfloat) * count);

+		}

+		else if(targetUniform->type == GL_BOOL)

+		{

+			GLboolean *boolParams = (GLboolean*)targetUniform->data + uniformIndex[location].element;

+

+			for(int i = 0; i < count; i++)

+			{

+				if(v[i] == 0.0f)

+				{

+					boolParams[i] = GL_FALSE;

+				}

+				else

+				{

+					boolParams[i] = GL_TRUE;

+				}

+			}

+		}

+		else

+		{

+			return false;

+		}

+

+		return true;

+	}

+

+	bool Program::setUniform2fv(GLint location, GLsizei count, const GLfloat *v)

+	{

+		if(location < 0 || location >= (int)uniformIndex.size())

+		{

+			return false;

+		}

+

+		Uniform *targetUniform = uniforms[uniformIndex[location].index];

+		targetUniform->dirty = true;

+

+		int size = targetUniform->size();

+

+		if(size == 1 && count > 1)

+		{

+			return false;   // Attempting to write an array to a non-array uniform is an INVALID_OPERATION

+		}

+	

+		count = std::min(size - (int)uniformIndex[location].element, count);

+

+		if(targetUniform->type == GL_FLOAT_VEC2)

+		{

+			memcpy(targetUniform->data + uniformIndex[location].element * sizeof(GLfloat) * 2,

+				   v, 2 * sizeof(GLfloat) * count);

+		}

+		else if(targetUniform->type == GL_BOOL_VEC2)

+		{

+			GLboolean *boolParams = (GLboolean*)targetUniform->data + uniformIndex[location].element * 2;

+

+			for(int i = 0; i < count * 2; i++)

+			{

+				if(v[i] == 0.0f)

+				{

+					boolParams[i] = GL_FALSE;

+				}

+				else

+				{

+					boolParams[i] = GL_TRUE;

+				}

+			}

+		}

+		else 

+		{

+			return false;

+		}

+

+		return true;

+	}

+

+	bool Program::setUniform3fv(GLint location, GLsizei count, const GLfloat *v)

+	{

+		if(location < 0 || location >= (int)uniformIndex.size())

+		{

+			return false;

+		}

+

+		Uniform *targetUniform = uniforms[uniformIndex[location].index];

+		targetUniform->dirty = true;

+

+		int size = targetUniform->size();

+

+		if(size == 1 && count > 1)

+		{

+			return false;   // Attempting to write an array to a non-array uniform is an INVALID_OPERATION

+		}

+	

+		count = std::min(size - (int)uniformIndex[location].element, count);

+

+		if(targetUniform->type == GL_FLOAT_VEC3)

+		{

+			memcpy(targetUniform->data + uniformIndex[location].element * sizeof(GLfloat) * 3,

+				   v, 3 * sizeof(GLfloat) * count);

+		}

+		else if(targetUniform->type == GL_BOOL_VEC3)

+		{

+			GLboolean *boolParams = (GLboolean*)targetUniform->data + uniformIndex[location].element * 3;

+

+			for(int i = 0; i < count * 3; i++)

+			{

+				if(v[i] == 0.0f)

+				{

+					boolParams[i] = GL_FALSE;

+				}

+				else

+				{

+					boolParams[i] = GL_TRUE;

+				}

+			}

+		}

+		else 

+		{

+			return false;

+		}

+

+		return true;

+	}

+

+	bool Program::setUniform4fv(GLint location, GLsizei count, const GLfloat *v)

+	{

+		if(location < 0 || location >= (int)uniformIndex.size())

+		{

+			return false;

+		}

+

+		Uniform *targetUniform = uniforms[uniformIndex[location].index];

+		targetUniform->dirty = true;

+

+		int size = targetUniform->size();

+

+		if(size == 1 && count > 1)

+		{

+			return false;   // Attempting to write an array to a non-array uniform is an INVALID_OPERATION

+		}

+	

+		count = std::min(size - (int)uniformIndex[location].element, count);

+

+		if(targetUniform->type == GL_FLOAT_VEC4)

+		{

+			memcpy(targetUniform->data + uniformIndex[location].element * sizeof(GLfloat) * 4,

+				   v, 4 * sizeof(GLfloat) * count);

+		}

+		else if(targetUniform->type == GL_BOOL_VEC4)

+		{

+			GLboolean *boolParams = (GLboolean*)targetUniform->data + uniformIndex[location].element * 4;

+

+			for(int i = 0; i < count * 4; i++)

+			{

+				if(v[i] == 0.0f)

+				{

+					boolParams[i] = GL_FALSE;

+				}

+				else

+				{

+					boolParams[i] = GL_TRUE;

+				}

+			}

+		}

+		else 

+		{

+			return false;

+		}

+

+		return true;

+	}

+

+	bool Program::setUniformMatrix2fv(GLint location, GLsizei count, const GLfloat *value)

+	{

+		if(location < 0 || location >= (int)uniformIndex.size())

+		{

+			return false;

+		}

+

+		Uniform *targetUniform = uniforms[uniformIndex[location].index];

+		targetUniform->dirty = true;

+

+		if(targetUniform->type != GL_FLOAT_MAT2)

+		{

+			return false;

+		}

+

+		int size = targetUniform->size();

+

+		if(size == 1 && count > 1)

+		{

+			return false;   // Attempting to write an array to a non-array uniform is an INVALID_OPERATION

+		}

+

+		count = std::min(size - (int)uniformIndex[location].element, count);

+

+		memcpy(targetUniform->data + uniformIndex[location].element * sizeof(GLfloat) * 4,

+			   value, 4 * sizeof(GLfloat) * count);

+

+		return true;

+	}

+

+	bool Program::setUniformMatrix3fv(GLint location, GLsizei count, const GLfloat *value)

+	{

+		if(location < 0 || location >= (int)uniformIndex.size())

+		{

+			return false;

+		}

+

+		Uniform *targetUniform = uniforms[uniformIndex[location].index];

+		targetUniform->dirty = true;

+

+		if(targetUniform->type != GL_FLOAT_MAT3)

+		{

+			return false;

+		}

+

+		int size = targetUniform->size();

+

+		if(size == 1 && count > 1)

+		{

+			return false;   // Attempting to write an array to a non-array uniform is an INVALID_OPERATION

+		}

+

+		count = std::min(size - (int)uniformIndex[location].element, count);

+

+		memcpy(targetUniform->data + uniformIndex[location].element * sizeof(GLfloat) * 9,

+			   value, 9 * sizeof(GLfloat) * count);

+

+		return true;

+	}

+

+	bool Program::setUniformMatrix4fv(GLint location, GLsizei count, const GLfloat *value)

+	{

+		if(location < 0 || location >= (int)uniformIndex.size())

+		{

+			return false;

+		}

+

+		Uniform *targetUniform = uniforms[uniformIndex[location].index];

+		targetUniform->dirty = true;

+

+		if(targetUniform->type != GL_FLOAT_MAT4)

+		{

+			return false;

+		}

+

+		int size = targetUniform->size();

+

+		if(size == 1 && count > 1)

+		{

+			return false;   // Attempting to write an array to a non-array uniform is an INVALID_OPERATION

+		}

+

+		count = std::min(size - (int)uniformIndex[location].element, count);

+

+		memcpy(targetUniform->data + uniformIndex[location].element * sizeof(GLfloat) * 16,

+			   value, 16 * sizeof(GLfloat) * count);

+

+		return true;

+	}

+

+	bool Program::setUniform1iv(GLint location, GLsizei count, const GLint *v)

+	{

+		if(location < 0 || location >= (int)uniformIndex.size())

+		{

+			return false;

+		}

+

+		Uniform *targetUniform = uniforms[uniformIndex[location].index];

+		targetUniform->dirty = true;

+

+		int size = targetUniform->size();

+

+		if(size == 1 && count > 1)

+		{

+			return false;   // Attempting to write an array to a non-array uniform is an INVALID_OPERATION

+		}

+	

+		count = std::min(size - (int)uniformIndex[location].element, count);

+

+		if(targetUniform->type == GL_INT ||

+		   targetUniform->type == GL_SAMPLER_2D ||

+		   targetUniform->type == GL_SAMPLER_CUBE)

+		{

+			memcpy(targetUniform->data + uniformIndex[location].element * sizeof(GLint),

+				   v, sizeof(GLint) * count);

+		}

+		else if(targetUniform->type == GL_BOOL)

+		{

+			GLboolean *boolParams = new GLboolean[count];

+

+			for(int i = 0; i < count; i++)

+			{

+				if(v[i] == 0)

+				{

+					boolParams[i] = GL_FALSE;

+				}

+				else

+				{

+					boolParams[i] = GL_TRUE;

+				}

+			}

+

+			memcpy(targetUniform->data + uniformIndex[location].element * sizeof(GLboolean),

+				   boolParams, sizeof(GLboolean) * count);

+

+			delete[] boolParams;

+		}

+		else

+		{

+			return false;

+		}

+

+		return true;

+	}

+

+	bool Program::setUniform2iv(GLint location, GLsizei count, const GLint *v)

+	{

+		if(location < 0 || location >= (int)uniformIndex.size())

+		{

+			return false;

+		}

+

+		Uniform *targetUniform = uniforms[uniformIndex[location].index];

+		targetUniform->dirty = true;

+

+		int size = targetUniform->size();

+

+		if(size == 1 && count > 1)

+		{

+			return false;   // Attempting to write an array to a non-array uniform is an INVALID_OPERATION

+		}

+	

+		count = std::min(size - (int)uniformIndex[location].element, count);

+

+		if(targetUniform->type == GL_INT_VEC2)

+		{

+			memcpy(targetUniform->data + uniformIndex[location].element * sizeof(GLint) * 2,

+				   v, 2 * sizeof(GLint) * count);

+		}

+		else if(targetUniform->type == GL_BOOL_VEC2)

+		{

+			GLboolean *boolParams = new GLboolean[count * 2];

+

+			for(int i = 0; i < count * 2; i++)

+			{

+				if(v[i] == 0)

+				{

+					boolParams[i] = GL_FALSE;

+				}

+				else

+				{

+					boolParams[i] = GL_TRUE;

+				}

+			}

+

+			memcpy(targetUniform->data + uniformIndex[location].element * sizeof(GLboolean) * 2,

+				   boolParams, 2 * sizeof(GLboolean) * count);

+

+			delete[] boolParams;

+		}

+		else

+		{

+			return false;

+		}

+

+		return true;

+	}

+

+	bool Program::setUniform3iv(GLint location, GLsizei count, const GLint *v)

+	{

+		if(location < 0 || location >= (int)uniformIndex.size())

+		{

+			return false;

+		}

+

+		Uniform *targetUniform = uniforms[uniformIndex[location].index];

+		targetUniform->dirty = true;

+

+		int size = targetUniform->size();

+

+		if(size == 1 && count > 1)

+		{

+			return false;   // Attempting to write an array to a non-array uniform is an INVALID_OPERATION

+		}

+	

+		count = std::min(size - (int)uniformIndex[location].element, count);

+

+		if(targetUniform->type == GL_INT_VEC3)

+		{

+			memcpy(targetUniform->data + uniformIndex[location].element * sizeof(GLint) * 3,

+				   v, 3 * sizeof(GLint) * count);

+		}

+		else if(targetUniform->type == GL_BOOL_VEC3)

+		{

+			GLboolean *boolParams = new GLboolean[count * 3];

+

+			for(int i = 0; i < count * 3; i++)

+			{

+				if(v[i] == 0)

+				{

+					boolParams[i] = GL_FALSE;

+				}

+				else

+				{

+					boolParams[i] = GL_TRUE;

+				}

+			}

+

+			memcpy(targetUniform->data + uniformIndex[location].element * sizeof(GLboolean) * 3,

+				   boolParams, 3 * sizeof(GLboolean) * count);

+

+			delete[] boolParams;

+		}

+		else

+		{

+			return false;

+		}

+

+		return true;

+	}

+

+	bool Program::setUniform4iv(GLint location, GLsizei count, const GLint *v)

+	{

+		if(location < 0 || location >= (int)uniformIndex.size())

+		{

+			return false;

+		}

+

+		Uniform *targetUniform = uniforms[uniformIndex[location].index];

+		targetUniform->dirty = true;

+

+		int size = targetUniform->size();

+

+		if(size == 1 && count > 1)

+		{

+			return false;   // Attempting to write an array to a non-array uniform is an INVALID_OPERATION

+		}

+	

+		count = std::min(size - (int)uniformIndex[location].element, count);

+

+		if(targetUniform->type == GL_INT_VEC4)

+		{

+			memcpy(targetUniform->data + uniformIndex[location].element * sizeof(GLint) * 4,

+				   v, 4 * sizeof(GLint) * count);

+		}

+		else if(targetUniform->type == GL_BOOL_VEC4)

+		{

+			GLboolean *boolParams = new GLboolean[count * 4];

+

+			for(int i = 0; i < count * 4; i++)

+			{

+				if(v[i] == 0)

+				{

+					boolParams[i] = GL_FALSE;

+				}

+				else

+				{

+					boolParams[i] = GL_TRUE;

+				}

+			}

+

+			memcpy(targetUniform->data + uniformIndex[location].element * sizeof(GLboolean) * 4,

+				   boolParams, 4 * sizeof(GLboolean) * count);

+

+			delete[] boolParams;

+		}

+		else

+		{

+			return false;

+		}

+

+		return true;

+	}

+

+	bool Program::getUniformfv(GLint location, GLsizei *bufSize, GLfloat *params)

+	{

+		if(location < 0 || location >= (int)uniformIndex.size())

+		{

+			return false;

+		}

+

+		Uniform *targetUniform = uniforms[uniformIndex[location].index];

+		unsigned int count = UniformComponentCount(targetUniform->type);

+

+		// Sized query - ensure the provided buffer is large enough

+		if(bufSize && *bufSize < count * sizeof(GLfloat))

+		{

+			return false;

+		}

+

+		switch (UniformComponentType(targetUniform->type))

+		{

+		  case GL_BOOL:

+			{

+				GLboolean *boolParams = (GLboolean*)targetUniform->data + uniformIndex[location].element * count;

+

+				for(unsigned int i = 0; i < count; i++)

+				{

+					params[i] = (boolParams[i] == GL_FALSE) ? 0.0f : 1.0f;

+				}

+			}

+			break;

+		  case GL_FLOAT:

+			memcpy(params, targetUniform->data + uniformIndex[location].element * count * sizeof(GLfloat),

+				   count * sizeof(GLfloat));

+			break;

+		  case GL_INT:

+			{

+				GLint *intParams = (GLint*)targetUniform->data + uniformIndex[location].element * count;

+

+				for(unsigned int i = 0; i < count; i++)

+				{

+					params[i] = (float)intParams[i];

+				}

+			}

+			break;

+		  default: UNREACHABLE();

+		}

+

+		return true;

+	}

+

+	bool Program::getUniformiv(GLint location, GLsizei *bufSize, GLint *params)

+	{

+		if(location < 0 || location >= (int)uniformIndex.size())

+		{

+			return false;

+		}

+

+		Uniform *targetUniform = uniforms[uniformIndex[location].index];

+		unsigned int count = UniformComponentCount(targetUniform->type);

+

+		// Sized query - ensure the provided buffer is large enough

+		if(bufSize && *bufSize < count * sizeof(GLint))

+		{

+			return false;

+		}

+

+		switch (UniformComponentType(targetUniform->type))

+		{

+		  case GL_BOOL:

+			{

+				GLboolean *boolParams = targetUniform->data + uniformIndex[location].element * count;

+

+				for(unsigned int i = 0; i < count; i++)

+				{

+					params[i] = (GLint)boolParams[i];

+				}

+			}

+			break;

+		  case GL_FLOAT:

+			{

+				GLfloat *floatParams = (GLfloat*)targetUniform->data + uniformIndex[location].element * count;

+

+				for(unsigned int i = 0; i < count; i++)

+				{

+					params[i] = (GLint)floatParams[i];

+				}

+			}

+			break;

+		  case GL_INT:

+			memcpy(params, targetUniform->data + uniformIndex[location].element * count * sizeof(GLint),

+				   count * sizeof(GLint));

+			break;

+		  default: UNREACHABLE();

+		}

+

+		return true;

+	}

+

+	void Program::dirtyAllUniforms()

+	{

+		unsigned int numUniforms = uniforms.size();

+		for(unsigned int index = 0; index < numUniforms; index++)

+		{

+			uniforms[index]->dirty = true;

+		}

+	}

+

+	// Applies all the uniforms set for this program object to the device

+	void Program::applyUniforms()

+	{

+		unsigned int numUniforms = uniformIndex.size();

+		for(unsigned int location = 0; location < numUniforms; location++)

+		{

+			if(uniformIndex[location].element != 0)

+			{

+				continue;

+			}

+

+			Uniform *targetUniform = uniforms[uniformIndex[location].index];

+

+			if(targetUniform->dirty)

+			{

+				int size = targetUniform->size();

+				GLfloat *f = (GLfloat*)targetUniform->data;

+				GLint *i = (GLint*)targetUniform->data;

+				GLboolean *b = (GLboolean*)targetUniform->data;

+

+				switch(targetUniform->type)

+				{

+				  case GL_BOOL:       applyUniform1bv(location, size, b);       break;

+				  case GL_BOOL_VEC2:  applyUniform2bv(location, size, b);       break;

+				  case GL_BOOL_VEC3:  applyUniform3bv(location, size, b);       break;

+				  case GL_BOOL_VEC4:  applyUniform4bv(location, size, b);       break;

+				  case GL_FLOAT:      applyUniform1fv(location, size, f);       break;

+				  case GL_FLOAT_VEC2: applyUniform2fv(location, size, f);       break;

+				  case GL_FLOAT_VEC3: applyUniform3fv(location, size, f);       break;

+				  case GL_FLOAT_VEC4: applyUniform4fv(location, size, f);       break;

+				  case GL_FLOAT_MAT2: applyUniformMatrix2fv(location, size, f); break;

+				  case GL_FLOAT_MAT3: applyUniformMatrix3fv(location, size, f); break;

+				  case GL_FLOAT_MAT4: applyUniformMatrix4fv(location, size, f); break;

+				  case GL_SAMPLER_2D:

+				  case GL_SAMPLER_CUBE:

+				  case GL_INT:        applyUniform1iv(location, size, i);       break;

+				  case GL_INT_VEC2:   applyUniform2iv(location, size, i);       break;

+				  case GL_INT_VEC3:   applyUniform3iv(location, size, i);       break;

+				  case GL_INT_VEC4:   applyUniform4iv(location, size, i);       break;

+				  default:

+					UNREACHABLE();

+				}

+

+				targetUniform->dirty = false;

+			}

+		}

+	}

+

+	// Packs varyings into generic varying registers, using the algorithm from [OpenGL ES Shading Language 1.00 rev. 17] appendix A section 7 page 111

+	// Returns the number of used varying registers, or -1 if unsuccesful

+	int Program::packVaryings(const Varying *packing[][4])

+	{

+		for(VaryingList::iterator varying = fragmentShader->varyings.begin(); varying != fragmentShader->varyings.end(); varying++)

+		{

+			int n = VariableRowCount(varying->type) * varying->size();

+			int m = VariableColumnCount(varying->type);

+			bool success = false;

+

+			if(m == 2 || m == 3 || m == 4)

+			{

+				for(int r = 0; r <= MAX_VARYING_VECTORS - n && !success; r++)

+				{

+					bool available = true;

+

+					for(int y = 0; y < n && available; y++)

+					{

+						for(int x = 0; x < m && available; x++)

+						{

+							if(packing[r + y][x])

+							{

+								available = false;

+							}

+						}

+					}

+

+					if(available)

+					{

+						varying->reg = r;

+						varying->col = 0;

+

+						for(int y = 0; y < n; y++)

+						{

+							for(int x = 0; x < m; x++)

+							{

+								packing[r + y][x] = &*varying;

+							}

+						}

+

+						success = true;

+					}

+				}

+

+				if(!success && m == 2)

+				{

+					for(int r = MAX_VARYING_VECTORS - n; r >= 0 && !success; r--)

+					{

+						bool available = true;

+

+						for(int y = 0; y < n && available; y++)

+						{

+							for(int x = 2; x < 4 && available; x++)

+							{

+								if(packing[r + y][x])

+								{

+									available = false;

+								}

+							}

+						}

+

+						if(available)

+						{

+							varying->reg = r;

+							varying->col = 2;

+

+							for(int y = 0; y < n; y++)

+							{

+								for(int x = 2; x < 4; x++)

+								{

+									packing[r + y][x] = &*varying;

+								}

+							}

+

+							success = true;

+						}

+					}

+				}

+			}

+			else if(m == 1)

+			{

+				int space[4] = {0};

+

+				for(int y = 0; y < MAX_VARYING_VECTORS; y++)

+				{

+					for(int x = 0; x < 4; x++)

+					{

+						space[x] += packing[y][x] ? 0 : 1;

+					}

+				}

+

+				int column = 0;

+

+				for(int x = 0; x < 4; x++)

+				{

+					if(space[x] >= n && space[x] < space[column])

+					{

+						column = x;

+					}

+				}

+

+				if(space[column] >= n)

+				{

+					for(int r = 0; r < MAX_VARYING_VECTORS; r++)

+					{

+						if(!packing[r][column])

+						{

+							varying->reg = r;

+

+							for(int y = r; y < r + n; y++)

+							{

+								packing[y][column] = &*varying;

+							}

+

+							break;

+						}

+					}

+

+					varying->col = column;

+

+					success = true;

+				}

+			}

+			else UNREACHABLE();

+

+			if(!success)

+			{

+				appendToInfoLog("Could not pack varying %s", varying->name.c_str());

+

+				return -1;

+			}

+		}

+

+		// Return the number of used registers

+		int registers = 0;

+

+		for(int r = 0; r < MAX_VARYING_VECTORS; r++)

+		{

+			if(packing[r][0] || packing[r][1] || packing[r][2] || packing[r][3])

+			{

+				registers++;

+			}

+		}

+

+		return registers;

+	}

+

+	bool Program::linkVaryings()

+	{

+		for(VaryingList::iterator input = fragmentShader->varyings.begin(); input != fragmentShader->varyings.end(); input++)

+		{

+			bool matched = false;

+

+			for(VaryingList::iterator output = vertexShader->varyings.begin(); output != vertexShader->varyings.end(); output++)

+			{

+				if(output->name == input->name)

+				{

+					if(output->type != input->type || output->size() != input->size())

+					{

+						appendToInfoLog("Type of vertex varying %s does not match that of the fragment varying", output->name.c_str());

+

+						return false;

+					}

+

+					matched = true;

+					break;

+				}

+			}

+

+			if(!matched)

+			{

+				appendToInfoLog("Fragment varying %s does not match any vertex varying", input->name.c_str());

+

+				return false;

+			}

+		}

+

+		VaryingList &psVaryings = fragmentShader->varyings;

+		VaryingList &vsVaryings = vertexShader->varyings;

+

+		for(VaryingList::iterator output = vsVaryings.begin(); output != vsVaryings.end(); output++)

+		{

+			for(VaryingList::iterator input = psVaryings.begin(); input != psVaryings.end(); input++)

+			{

+				if(output->name == input->name)

+				{

+					int in = input->reg;

+					int out = output->reg;

+					int components = VariableColumnCount(output->type);

+					int registers = VariableRowCount(output->type) * output->size();

+

+					ASSERT(in >= 0);

+

+					if(in + registers > MAX_VARYING_VECTORS)

+					{

+						appendToInfoLog("Too many varyings");

+

+						return false;

+					}

+

+					if(out >= 0)

+					{

+						if(out + registers > MAX_VARYING_VECTORS)

+						{

+							appendToInfoLog("Too many varyings");

+

+							return false;

+						}

+

+						for(int i = 0; i < registers; i++)

+						{

+							if(components >= 1) vertexBinary->output[out + i][0] = sw::Shader::Semantic(sw::Shader::USAGE_COLOR, in + i);

+							if(components >= 2) vertexBinary->output[out + i][1] = sw::Shader::Semantic(sw::Shader::USAGE_COLOR, in + i);

+							if(components >= 3) vertexBinary->output[out + i][2] = sw::Shader::Semantic(sw::Shader::USAGE_COLOR, in + i);

+							if(components >= 4) vertexBinary->output[out + i][3] = sw::Shader::Semantic(sw::Shader::USAGE_COLOR, in + i);

+						}

+					}

+					else   // Vertex varying is declared but not written to

+					{

+						for(int i = 0; i < registers; i++)

+						{

+							if(components >= 1) pixelBinary->semantic[in + i][0] = sw::Shader::Semantic();

+							if(components >= 2) pixelBinary->semantic[in + i][1] = sw::Shader::Semantic();

+							if(components >= 3) pixelBinary->semantic[in + i][2] = sw::Shader::Semantic();

+							if(components >= 4) pixelBinary->semantic[in + i][3] = sw::Shader::Semantic();					

+						}

+					}

+

+					break;

+				}

+			}

+		}

+

+		return true;

+	}

+

+	// Links the code of the vertex and pixel shader by matching up their varyings,

+	// compiling them into binaries, determining the attribute mappings, and collecting

+	// a list of uniforms

+	void Program::link()

+	{

+		unlink();

+

+		if(!fragmentShader || !fragmentShader->isCompiled())

+		{

+			return;

+		}

+

+		if(!vertexShader || !vertexShader->isCompiled())

+		{

+			return;

+		}

+

+		vertexBinary = new sw::VertexShader(vertexShader->getVertexShader());

+		pixelBinary = new sw::PixelShader(fragmentShader->getPixelShader());

+			

+		if(!linkVaryings())

+		{

+			return;

+		}

+

+		if(!linkAttributes())

+		{

+			return;

+		}

+

+		if(!linkUniforms(fragmentShader))

+		{

+			return;

+		}

+

+		if(!linkUniforms(vertexShader))

+		{

+			return;

+		}

+

+		linked = true;   // Success

+	}

+

+	// Determines the mapping between GL attributes and vertex stream usage indices

+	bool Program::linkAttributes()

+	{

+		unsigned int usedLocations = 0;

+

+		// Link attributes that have a binding location

+		for(sh::ActiveAttributes::iterator attribute = vertexShader->activeAttributes.begin(); attribute != vertexShader->activeAttributes.end(); attribute++)

+		{

+			int location = getAttributeBinding(attribute->name);

+

+			if(location != -1)   // Set by glBindAttribLocation

+			{

+				if(!linkedAttribute[location].name.empty())

+				{

+					// Multiple active attributes bound to the same location; not an error

+				}

+

+				linkedAttribute[location] = *attribute;

+

+				int rows = VariableRowCount(attribute->type);

+

+				if(rows + location > MAX_VERTEX_ATTRIBS)

+				{

+					appendToInfoLog("Active attribute (%s) at location %d is too big to fit", attribute->name.c_str(), location);

+

+					return false;

+				}

+

+				for(int i = 0; i < rows; i++)

+				{

+					usedLocations |= 1 << (location + i);

+				}

+			}

+		}

+

+		// Link attributes that don't have a binding location

+		for(sh::ActiveAttributes::iterator attribute = vertexShader->activeAttributes.begin(); attribute != vertexShader->activeAttributes.end(); attribute++)

+		{

+			int location = getAttributeBinding(attribute->name);

+

+			if(location == -1)   // Not set by glBindAttribLocation

+			{

+				int rows = VariableRowCount(attribute->type);

+				int availableIndex = AllocateFirstFreeBits(&usedLocations, rows, MAX_VERTEX_ATTRIBS);

+

+				if(availableIndex == -1 || availableIndex + rows > MAX_VERTEX_ATTRIBS)

+				{

+					appendToInfoLog("Too many active attributes (%s)", attribute->name.c_str());

+

+					return false;   // Fail to link

+				}

+

+				linkedAttribute[availableIndex] = *attribute;

+			}

+		}

+

+		for(int attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; )

+		{

+			int index = vertexShader->getSemanticIndex(linkedAttribute[attributeIndex].name);

+			int rows = std::max(VariableRowCount(linkedAttribute[attributeIndex].type), 1);

+

+			for(int r = 0; r < rows; r++)

+			{

+				attributeStream[attributeIndex++] = index++;

+			}

+		}

+

+		return true;

+	}

+

+	int Program::getAttributeBinding(const std::string &name)

+	{

+		for(int location = 0; location < MAX_VERTEX_ATTRIBS; location++)

+		{

+			if(attributeBinding[location].find(name) != attributeBinding[location].end())

+			{

+				return location;

+			}

+		}

+

+		return -1;

+	}

+

+	bool Program::linkUniforms(Shader *shader)

+	{

+		const sh::ActiveUniforms &activeUniforms = shader->activeUniforms;

+

+		for(unsigned int uniformIndex = 0; uniformIndex < activeUniforms.size(); uniformIndex++)

+		{

+			const sh::Uniform &uniform = activeUniforms[uniformIndex];

+

+			if(!defineUniform(shader->getType(), uniform.type, uniform.name, uniform.arraySize, uniform.registerIndex))

+			{

+				return false;

+			}

+		}

+

+		return true;

+	}

+

+	bool Program::defineUniform(GLenum shader, GLenum type, const std::string &name, unsigned int arraySize, int registerIndex)

+	{

+		if(type == GL_SAMPLER_2D || type == GL_SAMPLER_CUBE)

+	    {

+			int index = registerIndex;

+			

+			do

+			{

+				if(shader == GL_VERTEX_SHADER)

+				{

+					if(index < MAX_VERTEX_TEXTURE_IMAGE_UNITS)

+					{

+						samplersVS[index].active = true;

+						samplersVS[index].textureType = (type == GL_SAMPLER_CUBE) ? TEXTURE_CUBE : TEXTURE_2D;

+						samplersVS[index].logicalTextureUnit = 0;

+					}

+					else

+					{

+					   appendToInfoLog("Vertex shader sampler count exceeds MAX_VERTEX_TEXTURE_IMAGE_UNITS (%d).", MAX_VERTEX_TEXTURE_IMAGE_UNITS);

+					   return false;

+					}

+				}

+				else if(shader == GL_FRAGMENT_SHADER)

+				{

+					if(index < MAX_TEXTURE_IMAGE_UNITS)

+					{

+						samplersPS[index].active = true;

+						samplersPS[index].textureType = (type == GL_SAMPLER_CUBE) ? TEXTURE_CUBE : TEXTURE_2D;

+						samplersPS[index].logicalTextureUnit = 0;

+					}

+					else

+					{

+						appendToInfoLog("Pixel shader sampler count exceeds MAX_TEXTURE_IMAGE_UNITS (%d).", MAX_TEXTURE_IMAGE_UNITS);

+						return false;

+					}

+				}

+				else UNREACHABLE();

+

+				index++;

+			}

+			while(index < registerIndex + arraySize);

+	    }

+

+		Uniform *uniform = 0;

+		GLint location = getUniformLocation(name);

+

+		if(location >= 0)   // Previously defined, types must match

+		{

+			uniform = uniforms[uniformIndex[location].index];

+

+			if(uniform->type != type)

+			{

+				return false;

+			}

+		}

+		else

+		{

+			uniform = new Uniform(type, name, arraySize);

+		}

+

+		if(!uniform)

+		{

+			return false;

+		}

+

+		if(shader == GL_VERTEX_SHADER)

+		{

+			uniform->vsRegisterIndex = registerIndex;

+		}

+		else if(shader == GL_FRAGMENT_SHADER)

+		{

+			uniform->psRegisterIndex = registerIndex;

+		}

+		else UNREACHABLE();

+

+		if(location == -1)   // Not previously defined

+		{

+			uniforms.push_back(uniform);

+			unsigned int index = uniforms.size() - 1;

+

+			for(unsigned int i = 0; i < uniform->size(); i++)

+			{

+				uniformIndex.push_back(UniformLocation(name, i, index));

+			}

+		}

+

+		if(shader == GL_VERTEX_SHADER)

+		{

+			if(registerIndex + uniform->registerCount() > MAX_VERTEX_UNIFORM_VECTORS)

+			{

+				appendToInfoLog("Vertex shader active uniforms exceed GL_MAX_VERTEX_UNIFORM_VECTORS (%d)", MAX_VERTEX_UNIFORM_VECTORS);

+				return false;

+			}

+		}

+		else if(shader == GL_FRAGMENT_SHADER)

+		{

+			if(registerIndex + uniform->registerCount() > MAX_FRAGMENT_UNIFORM_VECTORS)

+			{

+				appendToInfoLog("Fragment shader active uniforms exceed GL_MAX_FRAGMENT_UNIFORM_VECTORS (%d)", MAX_FRAGMENT_UNIFORM_VECTORS);

+				return false;

+			}

+		}

+		else UNREACHABLE();

+

+		return true;

+	}

+

+	bool Program::applyUniform1bv(GLint location, GLsizei count, const GLboolean *v)

+	{

+		int vector[MAX_UNIFORM_VECTORS][4];

+

+		for(int i = 0; i < count; i++)

+		{

+			vector[i][0] = (v[0] == GL_FALSE ? 0x00000000 : 0xFFFFFFFF);

+			vector[i][1] = 0;

+			vector[i][2] = 0;

+			vector[i][3] = 0;

+

+			v += 1;

+		}

+

+		Uniform *targetUniform = uniforms[uniformIndex[location].index];

+

+		if(targetUniform->psRegisterIndex != -1)

+		{

+			device->setPixelShaderConstantF(targetUniform->psRegisterIndex, (float*)vector, targetUniform->registerCount());

+		}

+

+		if(targetUniform->vsRegisterIndex != -1)

+		{

+			device->setVertexShaderConstantF(targetUniform->vsRegisterIndex, (float*)vector, targetUniform->registerCount());

+		}

+

+		return true;

+	}

+

+	bool Program::applyUniform2bv(GLint location, GLsizei count, const GLboolean *v)

+	{

+		int vector[MAX_UNIFORM_VECTORS][4];

+

+		for(int i = 0; i < count; i++)

+		{

+			vector[i][0] = (v[0] == GL_FALSE ? 0x00000000 : 0xFFFFFFFF);

+			vector[i][1] = (v[1] == GL_FALSE ? 0x00000000 : 0xFFFFFFFF);

+			vector[i][2] = 0;

+			vector[i][3] = 0;

+

+			v += 2;

+		}

+

+		Uniform *targetUniform = uniforms[uniformIndex[location].index];

+

+		if(targetUniform->psRegisterIndex != -1)

+		{

+			device->setPixelShaderConstantF(targetUniform->psRegisterIndex, (float*)vector, targetUniform->registerCount());

+		}

+

+		if(targetUniform->vsRegisterIndex != -1)

+		{

+			device->setVertexShaderConstantF(targetUniform->vsRegisterIndex, (float*)vector, targetUniform->registerCount());

+		}

+

+		return true;

+	}

+

+	bool Program::applyUniform3bv(GLint location, GLsizei count, const GLboolean *v)

+	{

+		int vector[MAX_UNIFORM_VECTORS][4];

+

+		for(int i = 0; i < count; i++)

+		{

+			vector[i][0] = (v[0] == GL_FALSE ? 0x00000000 : 0xFFFFFFFF);

+			vector[i][1] = (v[1] == GL_FALSE ? 0x00000000 : 0xFFFFFFFF);

+			vector[i][2] = (v[2] == GL_FALSE ? 0x00000000 : 0xFFFFFFFF);

+			vector[i][3] = 0;

+

+			v += 3;

+		}

+

+		Uniform *targetUniform = uniforms[uniformIndex[location].index];

+

+		if(targetUniform->psRegisterIndex != -1)

+		{

+			device->setPixelShaderConstantF(targetUniform->psRegisterIndex, (float*)vector, targetUniform->registerCount());

+		}

+

+		if(targetUniform->vsRegisterIndex != -1)

+		{

+			device->setVertexShaderConstantF(targetUniform->vsRegisterIndex, (float*)vector, targetUniform->registerCount());

+		}

+

+		return true;

+	}

+

+	bool Program::applyUniform4bv(GLint location, GLsizei count, const GLboolean *v)

+	{

+		int vector[MAX_UNIFORM_VECTORS][4];

+

+		for(int i = 0; i < count; i++)

+		{

+			vector[i][0] = (v[0] == GL_FALSE ? 0x00000000 : 0xFFFFFFFF);

+			vector[i][1] = (v[1] == GL_FALSE ? 0x00000000 : 0xFFFFFFFF);

+			vector[i][2] = (v[2] == GL_FALSE ? 0x00000000 : 0xFFFFFFFF);

+			vector[i][3] = (v[3] == GL_FALSE ? 0x00000000 : 0xFFFFFFFF);

+

+			v += 4;

+		}

+

+		Uniform *targetUniform = uniforms[uniformIndex[location].index];

+

+		if(targetUniform->psRegisterIndex != -1)

+		{

+			device->setPixelShaderConstantF(targetUniform->psRegisterIndex, (float*)vector, targetUniform->registerCount());

+		}

+

+		if(targetUniform->vsRegisterIndex != -1)

+		{

+			device->setVertexShaderConstantF(targetUniform->vsRegisterIndex, (float*)vector, targetUniform->registerCount());

+		}

+

+		return true;

+	}

+

+	bool Program::applyUniform1fv(GLint location, GLsizei count, const GLfloat *v)

+	{

+		float vector[MAX_UNIFORM_VECTORS][4];

+

+		for(int i = 0; i < count; i++)

+		{

+			vector[i][0] = v[0];

+			vector[i][1] = 0;

+			vector[i][2] = 0;

+			vector[i][3] = 0;

+

+			v += 1;

+		}

+

+		Uniform *targetUniform = uniforms[uniformIndex[location].index];

+

+		if(targetUniform->psRegisterIndex != -1)

+		{

+			device->setPixelShaderConstantF(targetUniform->psRegisterIndex, (float*)vector, targetUniform->registerCount());

+		}

+

+		if(targetUniform->vsRegisterIndex != -1)

+		{

+			device->setVertexShaderConstantF(targetUniform->vsRegisterIndex, (float*)vector, targetUniform->registerCount());

+		}

+

+		return true;

+	}

+

+	bool Program::applyUniform2fv(GLint location, GLsizei count, const GLfloat *v)

+	{

+		float vector[MAX_UNIFORM_VECTORS][4];

+

+		for(int i = 0; i < count; i++)

+		{

+			vector[i][0] = v[0];

+			vector[i][1] = v[1];

+			vector[i][2] = 0;

+			vector[i][3] = 0;

+

+			v += 2;

+		}

+

+		Uniform *targetUniform = uniforms[uniformIndex[location].index];

+

+		if(targetUniform->psRegisterIndex != -1)

+		{

+			device->setPixelShaderConstantF(targetUniform->psRegisterIndex, (float*)vector, targetUniform->registerCount());

+		}

+

+		if(targetUniform->vsRegisterIndex != -1)

+		{

+			device->setVertexShaderConstantF(targetUniform->vsRegisterIndex, (float*)vector, targetUniform->registerCount());

+		}

+

+		return true;

+	}

+

+	bool Program::applyUniform3fv(GLint location, GLsizei count, const GLfloat *v)

+	{

+		float vector[MAX_UNIFORM_VECTORS][4];

+

+		for(int i = 0; i < count; i++)

+		{

+			vector[i][0] = v[0];

+			vector[i][1] = v[1];

+			vector[i][2] = v[2];

+			vector[i][3] = 0;

+

+			v += 3;

+		}

+

+		Uniform *targetUniform = uniforms[uniformIndex[location].index];

+

+		if(targetUniform->psRegisterIndex != -1)

+		{

+			device->setPixelShaderConstantF(targetUniform->psRegisterIndex, (float*)vector, targetUniform->registerCount());

+		}

+

+		if(targetUniform->vsRegisterIndex != -1)

+		{

+			device->setVertexShaderConstantF(targetUniform->vsRegisterIndex, (float*)vector, targetUniform->registerCount());

+		}

+

+		return true;

+	}

+

+	bool Program::applyUniform4fv(GLint location, GLsizei count, const GLfloat *v)

+	{

+		Uniform *targetUniform = uniforms[uniformIndex[location].index];

+

+		if(targetUniform->psRegisterIndex != -1)

+		{

+			device->setPixelShaderConstantF(targetUniform->psRegisterIndex, (float*)v, targetUniform->registerCount());

+		}

+

+		if(targetUniform->vsRegisterIndex != -1)

+		{

+			device->setVertexShaderConstantF(targetUniform->vsRegisterIndex, (float*)v, targetUniform->registerCount());

+		}

+

+		return true;

+	}

+

+	bool Program::applyUniformMatrix2fv(GLint location, GLsizei count, const GLfloat *value)

+	{

+		float matrix[(MAX_UNIFORM_VECTORS + 1) / 2][2][4];

+

+		for(int i = 0; i < count; i++)

+		{

+			matrix[i][0][0] = value[0];	matrix[i][0][1] = value[1];	matrix[i][0][2] = 0; matrix[i][0][3] = 0;

+			matrix[i][1][0] = value[2];	matrix[i][1][1] = value[3];	matrix[i][1][2] = 0; matrix[i][1][3] = 0;

+

+			value += 4;

+		}

+

+		Uniform *targetUniform = uniforms[uniformIndex[location].index];

+

+		if(targetUniform->psRegisterIndex != -1)

+		{

+			device->setPixelShaderConstantF(targetUniform->psRegisterIndex, (float*)matrix, targetUniform->registerCount());

+		}

+

+		if(targetUniform->vsRegisterIndex != -1)

+		{

+			device->setVertexShaderConstantF(targetUniform->vsRegisterIndex, (float*)matrix, targetUniform->registerCount());

+		}

+

+		return true;

+	}

+

+	bool Program::applyUniformMatrix3fv(GLint location, GLsizei count, const GLfloat *value)

+	{

+		float matrix[(MAX_UNIFORM_VECTORS + 2) / 3][3][4];

+

+		for(int i = 0; i < count; i++)

+		{

+			matrix[i][0][0] = value[0];	matrix[i][0][1] = value[1];	matrix[i][0][2] = value[2];	matrix[i][0][3] = 0;

+			matrix[i][1][0] = value[3];	matrix[i][1][1] = value[4];	matrix[i][1][2] = value[5];	matrix[i][1][3] = 0;

+			matrix[i][2][0] = value[6];	matrix[i][2][1] = value[7];	matrix[i][2][2] = value[8];	matrix[i][2][3] = 0;

+

+			value += 9;

+		}

+

+		Uniform *targetUniform = uniforms[uniformIndex[location].index];

+

+		if(targetUniform->psRegisterIndex != -1)

+		{

+			device->setPixelShaderConstantF(targetUniform->psRegisterIndex, (float*)matrix, targetUniform->registerCount());

+		}

+

+		if(targetUniform->vsRegisterIndex != -1)

+		{	

+			device->setVertexShaderConstantF(targetUniform->vsRegisterIndex, (float*)matrix, targetUniform->registerCount());

+		}

+

+		return true;

+	}

+

+	bool Program::applyUniformMatrix4fv(GLint location, GLsizei count, const GLfloat *value)

+	{

+		Uniform *targetUniform = uniforms[uniformIndex[location].index];

+	

+		if(targetUniform->psRegisterIndex != -1)

+		{

+			device->setPixelShaderConstantF(targetUniform->psRegisterIndex, (float*)value, targetUniform->registerCount());

+		}

+

+		if(targetUniform->vsRegisterIndex != -1)

+		{

+			device->setVertexShaderConstantF(targetUniform->vsRegisterIndex, (float*)value, targetUniform->registerCount());

+		}

+

+		return true;

+	}

+

+	bool Program::applyUniform1iv(GLint location, GLsizei count, const GLint *v)

+	{

+		float vector[MAX_UNIFORM_VECTORS][4];

+

+		for(int i = 0; i < count; i++)

+		{

+			vector[i][0] = (float)v[i];

+			vector[i][1] = 0;

+			vector[i][2] = 0;

+			vector[i][3] = 0;

+		}

+

+		Uniform *targetUniform = uniforms[uniformIndex[location].index];

+

+		if(targetUniform->psRegisterIndex != -1)

+		{

+			if(targetUniform->type == GL_SAMPLER_2D ||

+			   targetUniform->type == GL_SAMPLER_CUBE)

+			{

+				for(int i = 0; i < count; i++)

+				{

+					unsigned int samplerIndex = targetUniform->psRegisterIndex + i;

+

+					if(samplerIndex < MAX_TEXTURE_IMAGE_UNITS)

+					{

+						ASSERT(samplersPS[samplerIndex].active);

+						samplersPS[samplerIndex].logicalTextureUnit = v[i];

+					}

+				}

+			}

+			else

+			{

+				device->setPixelShaderConstantF(targetUniform->psRegisterIndex, (float*)vector, targetUniform->registerCount());

+			}

+		}

+

+		if(targetUniform->vsRegisterIndex != -1)

+		{

+			if(targetUniform->type == GL_SAMPLER_2D ||

+			   targetUniform->type == GL_SAMPLER_CUBE)

+			{

+				for(int i = 0; i < count; i++)

+				{

+					unsigned int samplerIndex = targetUniform->vsRegisterIndex + i;

+

+					if(samplerIndex < MAX_VERTEX_TEXTURE_IMAGE_UNITS)

+					{

+						ASSERT(samplersVS[samplerIndex].active);

+						samplersVS[samplerIndex].logicalTextureUnit = v[i];

+					}

+				}

+			}

+			else

+			{

+				device->setVertexShaderConstantF(targetUniform->vsRegisterIndex, (float*)vector, targetUniform->registerCount());

+			}

+		}

+

+		return true;

+	}

+

+	bool Program::applyUniform2iv(GLint location, GLsizei count, const GLint *v)

+	{

+		float vector[MAX_UNIFORM_VECTORS][4];

+

+		for(int i = 0; i < count; i++)

+		{

+			vector[i][0] = (float)v[0];

+			vector[i][1] = (float)v[1];

+			vector[i][2] = 0;

+			vector[i][3] = 0;

+

+			v += 2;

+		}

+

+		Uniform *targetUniform = uniforms[uniformIndex[location].index];

+

+		if(targetUniform->psRegisterIndex != -1)

+		{

+			device->setPixelShaderConstantF(targetUniform->psRegisterIndex, (float*)vector, targetUniform->registerCount());

+		}

+

+		if(targetUniform->vsRegisterIndex != -1)

+		{

+			device->setVertexShaderConstantF(targetUniform->vsRegisterIndex, (float*)vector, targetUniform->registerCount());

+		}

+

+		return true;

+	}

+

+	bool Program::applyUniform3iv(GLint location, GLsizei count, const GLint *v)

+	{

+		float vector[MAX_UNIFORM_VECTORS][4];

+

+		for(int i = 0; i < count; i++)

+		{

+			vector[i][0] = (float)v[0];

+			vector[i][1] = (float)v[1];

+			vector[i][2] = (float)v[2];

+			vector[i][3] = 0;

+

+			v += 3;

+		}

+

+		Uniform *targetUniform = uniforms[uniformIndex[location].index];

+

+		if(targetUniform->psRegisterIndex != -1)

+		{

+			device->setPixelShaderConstantF(targetUniform->psRegisterIndex, (float*)vector, targetUniform->registerCount());

+		}

+

+		if(targetUniform->vsRegisterIndex != -1)

+		{

+			device->setVertexShaderConstantF(targetUniform->vsRegisterIndex, (float*)vector, targetUniform->registerCount());

+		}

+

+		return true;

+	}

+

+	bool Program::applyUniform4iv(GLint location, GLsizei count, const GLint *v)

+	{

+		float vector[MAX_UNIFORM_VECTORS][4];

+

+		for(int i = 0; i < count; i++)

+		{

+			vector[i][0] = (float)v[0];

+			vector[i][1] = (float)v[1];

+			vector[i][2] = (float)v[2];

+			vector[i][3] = (float)v[3];

+

+			v += 4;

+		}

+

+		Uniform *targetUniform = uniforms[uniformIndex[location].index];

+

+		if(targetUniform->psRegisterIndex != -1)

+		{

+			device->setPixelShaderConstantF(targetUniform->psRegisterIndex, (float*)vector, targetUniform->registerCount());

+		}

+

+		if(targetUniform->vsRegisterIndex != -1)

+		{

+			device->setVertexShaderConstantF(targetUniform->vsRegisterIndex, (float*)vector, targetUniform->registerCount());

+		}

+

+		return true;

+	}

+

+	void Program::appendToInfoLog(const char *format, ...)

+	{

+		if(!format)

+		{

+			return;

+		}

+

+		char info[1024];

+

+		va_list vararg;

+		va_start(vararg, format);

+		vsnprintf(info, sizeof(info), format, vararg);

+		va_end(vararg);

+

+		size_t infoLength = strlen(info);

+

+		if(!infoLog)

+		{

+			infoLog = new char[infoLength + 1];

+			strcpy(infoLog, info);

+		}

+		else

+		{

+			size_t logLength = strlen(infoLog);

+			char *newLog = new char[logLength + infoLength + 1];

+			strcpy(newLog, infoLog);

+			strcpy(newLog + logLength, info);

+

+			delete[] infoLog;

+			infoLog = newLog;

+		}

+	}

+

+	void Program::resetInfoLog()

+	{

+		if(infoLog)

+		{

+			delete[] infoLog;

+			infoLog = 0;

+		}

+	}

+

+	// Returns the program object to an unlinked state, before re-linking, or at destruction

+	void Program::unlink()

+	{

+		delete vertexBinary;

+		vertexBinary = 0;

+		delete pixelBinary;

+		pixelBinary = 0;

+

+		for(int index = 0; index < MAX_VERTEX_ATTRIBS; index++)

+		{

+			linkedAttribute[index].name.clear();

+			attributeStream[index] = -1;

+		}

+

+		for(int index = 0; index < MAX_TEXTURE_IMAGE_UNITS; index++)

+		{

+			samplersPS[index].active = false;

+		}

+

+		for(int index = 0; index < MAX_VERTEX_TEXTURE_IMAGE_UNITS; index++)

+		{

+			samplersVS[index].active = false;

+		}

+

+		while(!uniforms.empty())

+		{

+			delete uniforms.back();

+			uniforms.pop_back();

+		}

+

+		uniformIndex.clear();

+

+		delete[] infoLog;

+		infoLog = 0;

+

+		linked = false;

+	}

+

+	bool Program::isLinked()

+	{

+		return linked;

+	}

+

+	bool Program::isValidated() const 

+	{

+		return validated;

+	}

+

+	void Program::release()

+	{

+		referenceCount--;

+

+		if(referenceCount == 0 && orphaned)

+		{

+			resourceManager->deleteProgram(handle);

+		}

+	}

+

+	void Program::addRef()

+	{

+		referenceCount++;

+	}

+

+	unsigned int Program::getRefCount() const

+	{

+		return referenceCount;

+	}

+

+	unsigned int Program::getSerial() const

+	{

+		return serial;

+	}

+

+	unsigned int Program::issueSerial()

+	{

+		return currentSerial++;

+	}

+

+	int Program::getInfoLogLength() const

+	{

+		if(!infoLog)

+		{

+			return 0;

+		}

+		else

+		{

+		   return strlen(infoLog) + 1;

+		}

+	}

+

+	void Program::getInfoLog(GLsizei bufSize, GLsizei *length, char *buffer)

+	{

+		int index = 0;

+

+		if(bufSize > 0)

+		{

+			if(infoLog)

+			{

+				index = std::min(bufSize - 1, (int)strlen(infoLog));

+				memcpy(buffer, infoLog, index);

+			}

+

+			buffer[index] = '\0';

+		}

+

+		if(length)

+		{

+			*length = index;

+		}

+	}

+

+	void Program::getAttachedShaders(GLsizei maxCount, GLsizei *count, GLuint *shaders)

+	{

+		int total = 0;

+

+		if(vertexShader)

+		{

+			if(total < maxCount)

+			{

+				shaders[total] = vertexShader->getHandle();

+			}

+

+			total++;

+		}

+

+		if(fragmentShader)

+		{

+			if(total < maxCount)

+			{

+				shaders[total] = fragmentShader->getHandle();

+			}

+

+			total++;

+		}

+

+		if(count)

+		{

+			*count = total;

+		}

+	}

+

+	void Program::getActiveAttribute(GLuint index, GLsizei bufsize, GLsizei *length, GLint *size, GLenum *type, GLchar *name)

+	{

+		// Skip over inactive attributes

+		unsigned int activeAttribute = 0;

+		unsigned int attribute;

+		for(attribute = 0; attribute < MAX_VERTEX_ATTRIBS; attribute++)

+		{

+			if(linkedAttribute[attribute].name.empty())

+			{

+				continue;

+			}

+

+			if(activeAttribute == index)

+			{

+				break;

+			}

+

+			activeAttribute++;

+		}

+

+		if(bufsize > 0)

+		{

+			const char *string = linkedAttribute[attribute].name.c_str();

+

+			strncpy(name, string, bufsize);

+			name[bufsize - 1] = '\0';

+

+			if(length)

+			{

+				*length = strlen(name);

+			}

+		}

+

+		*size = 1;   // Always a single 'type' instance

+

+		*type = linkedAttribute[attribute].type;

+	}

+

+	GLint Program::getActiveAttributeCount()

+	{

+		int count = 0;

+

+		for(int attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; attributeIndex++)

+		{

+			if(!linkedAttribute[attributeIndex].name.empty())

+			{

+				count++;

+			}

+		}

+

+		return count;

+	}

+

+	GLint Program::getActiveAttributeMaxLength()

+	{

+		int maxLength = 0;

+

+		for(int attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; attributeIndex++)

+		{

+			if(!linkedAttribute[attributeIndex].name.empty())

+			{

+				maxLength = std::max((int)(linkedAttribute[attributeIndex].name.length() + 1), maxLength);

+			}

+		}

+

+		return maxLength;

+	}

+

+	void Program::getActiveUniform(GLuint index, GLsizei bufsize, GLsizei *length, GLint *size, GLenum *type, GLchar *name)

+	{

+		if(bufsize > 0)

+		{

+			std::string string = uniforms[index]->name;

+

+			if(uniforms[index]->isArray())

+			{

+				string += "[0]";

+			}

+

+			strncpy(name, string.c_str(), bufsize);

+			name[bufsize - 1] = '\0';

+

+			if(length)

+			{

+				*length = strlen(name);

+			}

+		}

+

+		*size = uniforms[index]->size();

+

+		*type = uniforms[index]->type;

+	}

+

+	GLint Program::getActiveUniformCount()

+	{

+		return uniforms.size();

+	}

+

+	GLint Program::getActiveUniformMaxLength()

+	{

+		int maxLength = 0;

+

+		unsigned int numUniforms = uniforms.size();

+		for(unsigned int uniformIndex = 0; uniformIndex < numUniforms; uniformIndex++)

+		{

+			if(!uniforms[uniformIndex]->name.empty())

+			{

+				int length = (int)(uniforms[uniformIndex]->name.length() + 1);

+				if(uniforms[uniformIndex]->isArray())

+				{

+					length += 3;  // Counting in "[0]".

+				}

+				maxLength = std::max(length, maxLength);

+			}

+		}

+

+		return maxLength;

+	}

+

+	void Program::flagForDeletion()

+	{

+		orphaned = true;

+	}

+

+	bool Program::isFlaggedForDeletion() const

+	{

+		return orphaned;

+	}

+

+	void Program::validate()

+	{

+		resetInfoLog();

+

+		if(!isLinked()) 

+		{

+			appendToInfoLog("Program has not been successfully linked.");

+			validated = false;

+		}

+		else

+		{

+			applyUniforms();

+			if(!validateSamplers(true))

+			{

+				validated = false;

+			}

+			else

+			{

+				validated = true;

+			}

+		}

+	}

+

+	bool Program::validateSamplers(bool logErrors)

+	{

+		// if any two active samplers in a program are of different types, but refer to the same

+		// texture image unit, and this is the current program, then ValidateProgram will fail, and

+		// DrawArrays and DrawElements will issue the INVALID_OPERATION error.

+

+		TextureType textureUnitType[MAX_COMBINED_TEXTURE_IMAGE_UNITS];

+

+		for(unsigned int i = 0; i < MAX_COMBINED_TEXTURE_IMAGE_UNITS; i++)

+		{

+			textureUnitType[i] = TEXTURE_UNKNOWN;

+		}

+

+		for(unsigned int i = 0; i < MAX_TEXTURE_IMAGE_UNITS; i++)

+		{

+			if(samplersPS[i].active)

+			{

+				unsigned int unit = samplersPS[i].logicalTextureUnit;

+            

+				if(unit >= MAX_COMBINED_TEXTURE_IMAGE_UNITS)

+				{

+					if(logErrors)

+					{

+						appendToInfoLog("Sampler uniform (%d) exceeds MAX_COMBINED_TEXTURE_IMAGE_UNITS (%d)", unit, MAX_COMBINED_TEXTURE_IMAGE_UNITS);

+					}

+

+					return false;

+				}

+

+				if(textureUnitType[unit] != TEXTURE_UNKNOWN)

+				{

+					if(samplersPS[i].textureType != textureUnitType[unit])

+					{

+						if(logErrors)

+						{

+							appendToInfoLog("Samplers of conflicting types refer to the same texture image unit (%d).", unit);

+						}

+

+						return false;

+					}

+				}

+				else

+				{

+					textureUnitType[unit] = samplersPS[i].textureType;

+				}

+			}

+		}

+

+		for(unsigned int i = 0; i < MAX_VERTEX_TEXTURE_IMAGE_UNITS; i++)

+		{

+			if(samplersVS[i].active)

+			{

+				unsigned int unit = samplersVS[i].logicalTextureUnit;

+            

+				if(unit >= MAX_COMBINED_TEXTURE_IMAGE_UNITS)

+				{

+					if(logErrors)

+					{

+						appendToInfoLog("Sampler uniform (%d) exceeds MAX_COMBINED_TEXTURE_IMAGE_UNITS (%d)", unit, MAX_COMBINED_TEXTURE_IMAGE_UNITS);

+					}

+

+					return false;

+				}

+

+				if(textureUnitType[unit] != TEXTURE_UNKNOWN)

+				{

+					if(samplersVS[i].textureType != textureUnitType[unit])

+					{

+						if(logErrors)

+						{

+							appendToInfoLog("Samplers of conflicting types refer to the same texture image unit (%d).", unit);

+						}

+

+						return false;

+					}

+				}

+				else

+				{

+					textureUnitType[unit] = samplersVS[i].textureType;

+				}

+			}

+		}

+

+		return true;

+	}

+}

diff --git a/src/GLES2/libGLESv2/Program.h b/src/GLES2/libGLESv2/Program.h
new file mode 100644
index 0000000..404a208
--- /dev/null
+++ b/src/GLES2/libGLESv2/Program.h
@@ -0,0 +1,206 @@
+// SwiftShader Software Renderer

+//

+// Copyright(c) 2005-2012 TransGaming Inc.

+//

+// All rights reserved. No part of this software may be copied, distributed, transmitted,

+// transcribed, stored in a retrieval system, translated into any human or computer

+// language by any means, or disclosed to third parties without the explicit written

+// agreement of TransGaming Inc. Without such an agreement, no rights or licenses, express

+// or implied, including but not limited to any patent rights, are granted to you.

+//

+

+// Program.h: Defines the Program class. Implements GL program objects

+// and related functionality. [OpenGL ES 2.0.24] section 2.10.3 page 28.

+

+#ifndef LIBGLESV2_PROGRAM_H_

+#define LIBGLESV2_PROGRAM_H_

+

+#include "Shader.h"

+#include "Context.h"

+#include "Shader/PixelShader.hpp"

+#include "Shader/VertexShader.hpp"

+

+#include <string>

+#include <vector>

+#include <set>

+

+namespace gl

+{

+	class Device;

+	class ResourceManager;

+	class FragmentShader;

+	class VertexShader;

+

+	// Helper struct representing a single shader uniform

+	struct Uniform

+	{

+		Uniform(GLenum type, const std::string &name, unsigned int arraySize);

+

+		~Uniform();

+

+		bool isArray() const;

+		int size() const;

+		int registerCount() const;

+

+		const GLenum type;

+		const std::string name;

+		const unsigned int arraySize;

+

+		unsigned char *data;

+		bool dirty;

+

+		short psRegisterIndex;

+		short vsRegisterIndex;

+	};

+

+	// Struct used for correlating uniforms/elements of uniform arrays to handles

+	struct UniformLocation

+	{

+		UniformLocation(const std::string &name, unsigned int element, unsigned int index);

+

+		std::string name;

+		unsigned int element;

+		unsigned int index;

+	};

+

+	class Program

+	{

+	public:

+		Program(ResourceManager *manager, GLuint handle);

+

+		~Program();

+

+		bool attachShader(Shader *shader);

+		bool detachShader(Shader *shader);

+		int getAttachedShadersCount() const;

+

+		sw::PixelShader *getPixelShader();

+		sw::VertexShader *getVertexShader();

+

+		void bindAttributeLocation(GLuint index, const char *name);

+		GLuint getAttributeLocation(const char *name);

+		int getAttributeStream(int attributeIndex);

+

+		GLint getSamplerMapping(sw::SamplerType type, unsigned int samplerIndex);

+		TextureType getSamplerTextureType(sw::SamplerType type, unsigned int samplerIndex);

+

+		GLint getUniformLocation(std::string name);

+		bool setUniform1fv(GLint location, GLsizei count, const GLfloat *v);

+		bool setUniform2fv(GLint location, GLsizei count, const GLfloat *v);

+		bool setUniform3fv(GLint location, GLsizei count, const GLfloat *v);

+		bool setUniform4fv(GLint location, GLsizei count, const GLfloat *v);

+		bool setUniformMatrix2fv(GLint location, GLsizei count, const GLfloat *value);

+		bool setUniformMatrix3fv(GLint location, GLsizei count, const GLfloat *value);

+		bool setUniformMatrix4fv(GLint location, GLsizei count, const GLfloat *value);

+		bool setUniform1iv(GLint location, GLsizei count, const GLint *v);

+		bool setUniform2iv(GLint location, GLsizei count, const GLint *v);

+		bool setUniform3iv(GLint location, GLsizei count, const GLint *v);

+		bool setUniform4iv(GLint location, GLsizei count, const GLint *v);

+

+		bool getUniformfv(GLint location, GLsizei *bufSize, GLfloat *params);

+		bool getUniformiv(GLint location, GLsizei *bufSize, GLint *params);

+

+		void dirtyAllUniforms();

+		void applyUniforms();

+

+		void link();

+		bool isLinked();

+		int getInfoLogLength() const;

+		void getInfoLog(GLsizei bufSize, GLsizei *length, char *infoLog);

+		void getAttachedShaders(GLsizei maxCount, GLsizei *count, GLuint *shaders);

+

+		void getActiveAttribute(GLuint index, GLsizei bufsize, GLsizei *length, GLint *size, GLenum *type, GLchar *name);

+		GLint getActiveAttributeCount();

+		GLint getActiveAttributeMaxLength();

+

+		void getActiveUniform(GLuint index, GLsizei bufsize, GLsizei *length, GLint *size, GLenum *type, GLchar *name);

+		GLint getActiveUniformCount();

+		GLint getActiveUniformMaxLength();

+

+		void addRef();

+		void release();

+		unsigned int getRefCount() const;

+		void flagForDeletion();

+		bool isFlaggedForDeletion() const;

+

+		void validate();

+		bool validateSamplers(bool logErrors);

+		bool isValidated() const;

+

+		unsigned int getSerial() const;

+

+	private:

+		void unlink();

+

+		int packVaryings(const Varying *packing[][4]);

+		bool linkVaryings();

+

+		bool linkAttributes();

+		int getAttributeBinding(const std::string &name);

+

+		bool linkUniforms(Shader *shader);

+		bool defineUniform(GLenum shader, GLenum type, const std::string &_name, unsigned int arraySize, int registerIndex);

+		bool applyUniform1bv(GLint location, GLsizei count, const GLboolean *v);

+		bool applyUniform2bv(GLint location, GLsizei count, const GLboolean *v);

+		bool applyUniform3bv(GLint location, GLsizei count, const GLboolean *v);

+		bool applyUniform4bv(GLint location, GLsizei count, const GLboolean *v);

+		bool applyUniform1fv(GLint location, GLsizei count, const GLfloat *v);

+		bool applyUniform2fv(GLint location, GLsizei count, const GLfloat *v);

+		bool applyUniform3fv(GLint location, GLsizei count, const GLfloat *v);

+		bool applyUniform4fv(GLint location, GLsizei count, const GLfloat *v);

+		bool applyUniformMatrix2fv(GLint location, GLsizei count, const GLfloat *value);

+		bool applyUniformMatrix3fv(GLint location, GLsizei count, const GLfloat *value);

+		bool applyUniformMatrix4fv(GLint location, GLsizei count, const GLfloat *value);

+		bool applyUniform1iv(GLint location, GLsizei count, const GLint *v);

+		bool applyUniform2iv(GLint location, GLsizei count, const GLint *v);

+		bool applyUniform3iv(GLint location, GLsizei count, const GLint *v);

+		bool applyUniform4iv(GLint location, GLsizei count, const GLint *v);    

+

+		void appendToInfoLog(const char *info, ...);

+		void resetInfoLog();

+

+		static unsigned int issueSerial();

+

+	private:

+		gl::Device *device;

+		FragmentShader *fragmentShader;

+		VertexShader *vertexShader;

+

+		sw::PixelShader *pixelBinary;

+		sw::VertexShader *vertexBinary;

+    

+		std::set<std::string> attributeBinding[MAX_VERTEX_ATTRIBS];

+		sh::Attribute linkedAttribute[MAX_VERTEX_ATTRIBS];

+		int attributeStream[MAX_VERTEX_ATTRIBS];

+

+		struct Sampler

+		{

+			bool active;

+			GLint logicalTextureUnit;

+			TextureType textureType;

+		};

+

+		Sampler samplersPS[MAX_TEXTURE_IMAGE_UNITS];

+		Sampler samplersVS[MAX_VERTEX_TEXTURE_IMAGE_UNITS];

+

+		typedef std::vector<Uniform*> UniformArray;

+		UniformArray uniforms;

+		typedef std::vector<UniformLocation> UniformIndex;

+		UniformIndex uniformIndex;

+

+		bool linked;

+		bool orphaned;   // Flag to indicate that the program can be deleted when no longer in use

+		char *infoLog;

+		bool validated;

+

+		unsigned int referenceCount;

+		const unsigned int serial;

+

+		static unsigned int currentSerial;

+

+		ResourceManager *resourceManager;

+		const GLuint handle;

+	};

+}

+

+#endif   // LIBGLESV2_PROGRAM_H_

diff --git a/src/GLES2/libGLESv2/Query.cpp b/src/GLES2/libGLESv2/Query.cpp
new file mode 100644
index 0000000..8e69d70
--- /dev/null
+++ b/src/GLES2/libGLESv2/Query.cpp
@@ -0,0 +1,127 @@
+// SwiftShader Software Renderer

+//

+// Copyright(c) 2005-2012 TransGaming Inc.

+//

+// All rights reserved. No part of this software may be copied, distributed, transmitted,

+// transcribed, stored in a retrieval system, translated into any human or computer

+// language by any means, or disclosed to third parties without the explicit written

+// agreement of TransGaming Inc. Without such an agreement, no rights or licenses, express

+// or implied, including but not limited to any patent rights, are granted to you.

+//

+

+// Query.cpp: Implements the gl::Query class

+

+#include "Query.h"

+

+#include "main.h"

+#include "Common/Thread.hpp"

+

+namespace gl

+{

+

+Query::Query(GLuint id, GLenum type) : RefCountObject(id)

+{ 

+    mQuery = NULL;

+    mStatus = GL_FALSE;

+    mResult = GL_FALSE;

+    mType = type;

+}

+

+Query::~Query()

+{

+    if(mQuery != NULL)

+    {

+        delete mQuery;

+    }

+}

+

+void Query::begin()

+{

+    if(mQuery == NULL)

+    {

+		mQuery = new sw::Query();

+        

+		if(!mQuery)

+        {

+            return error(GL_OUT_OF_MEMORY);

+        }

+    }

+

+	Device *device = getDevice();

+

+	mQuery->begin();

+	device->addQuery(mQuery);

+	device->setOcclusionEnabled(true);

+}

+

+void Query::end()

+{

+    if(mQuery == NULL)

+    {

+        return error(GL_INVALID_OPERATION);

+	}

+

+	Device *device = getDevice();

+

+    mQuery->end();

+	device->removeQuery(mQuery);

+	device->setOcclusionEnabled(false);

+    

+    mStatus = GL_FALSE;

+    mResult = GL_FALSE;

+}

+

+GLuint Query::getResult()

+{

+    if(mQuery != NULL)

+    {

+        while(!testQuery())

+        {

+            sw::Thread::yield();

+        }

+    }

+

+    return (GLuint)mResult;

+}

+

+GLboolean Query::isResultAvailable()

+{

+    if(mQuery != NULL)

+    {

+        testQuery();

+    }

+    

+    return mStatus;

+}

+

+GLenum Query::getType() const

+{

+    return mType;

+}

+

+GLboolean Query::testQuery()

+{

+    if(mQuery != NULL && mStatus != GL_TRUE)

+    {

+        if(!mQuery->building && mQuery->reference == 0)

+        {

+			unsigned int numPixels = mQuery->data;

+            mStatus = GL_TRUE;

+

+            switch(mType)

+            {

+            case GL_ANY_SAMPLES_PASSED_EXT:

+            case GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT:

+                mResult = (numPixels > 0) ? GL_TRUE : GL_FALSE;

+                break;

+            default:

+                ASSERT(false);

+            }

+        }

+        

+        return mStatus;

+    }

+

+    return GL_TRUE;   // Prevent blocking when query is null

+}

+}

diff --git a/src/GLES2/libGLESv2/Query.h b/src/GLES2/libGLESv2/Query.h
new file mode 100644
index 0000000..a80456e
--- /dev/null
+++ b/src/GLES2/libGLESv2/Query.h
@@ -0,0 +1,50 @@
+// SwiftShader Software Renderer

+//

+// Copyright(c) 2005-2012 TransGaming Inc.

+//

+// All rights reserved. No part of this software may be copied, distributed, transmitted,

+// transcribed, stored in a retrieval system, translated into any human or computer

+// language by any means, or disclosed to third parties without the explicit written

+// agreement of TransGaming Inc. Without such an agreement, no rights or licenses, express

+// or implied, including but not limited to any patent rights, are granted to you.

+//

+

+// Query.h: Defines the gl::Query class

+

+#ifndef LIBGLESV2_QUERY_H_

+#define LIBGLESV2_QUERY_H_

+

+#include "RefCountObject.h"

+#include "Renderer/Renderer.hpp"

+

+#define GL_APICALL

+#include <GLES2/gl2.h>

+

+namespace gl

+{

+

+class Query : public RefCountObject

+{

+  public:

+    Query(GLuint id, GLenum type);

+    virtual ~Query();

+

+    void begin();

+    void end();

+    GLuint getResult();

+    GLboolean isResultAvailable();

+

+    GLenum getType() const;

+

+  private:

+    GLboolean testQuery();

+

+    sw::Query* mQuery;

+    GLenum mType;

+    GLboolean mStatus;

+    GLint mResult;

+};

+

+}

+

+#endif   // LIBGLESV2_QUERY_H_

diff --git a/src/GLES2/libGLESv2/RefCountObject.cpp b/src/GLES2/libGLESv2/RefCountObject.cpp
new file mode 100644
index 0000000..b470ab2
--- /dev/null
+++ b/src/GLES2/libGLESv2/RefCountObject.cpp
@@ -0,0 +1,65 @@
+// SwiftShader Software Renderer
+//
+// Copyright(c) 2005-2012 TransGaming Inc.
+//
+// All rights reserved. No part of this software may be copied, distributed, transmitted,
+// transcribed, stored in a retrieval system, translated into any human or computer
+// language by any means, or disclosed to third parties without the explicit written
+// agreement of TransGaming Inc. Without such an agreement, no rights or licenses, express
+// or implied, including but not limited to any patent rights, are granted to you.
+//
+
+// RefCountObject.cpp: Defines the RefCountObject base class that provides
+// lifecycle support for GL objects using the traditional BindObject scheme, but
+// that need to be reference counted for correct cross-context deletion.
+// (Concretely, textures, buffers and renderbuffers.)
+
+#include "RefCountObject.h"
+
+#include "Common/Thread.hpp"
+
+namespace gl
+{
+
+RefCountObject::RefCountObject(GLuint id)
+{
+    mId = id;
+    
+	referenceCount = 0;
+}
+
+RefCountObject::~RefCountObject()
+{
+    ASSERT(referenceCount == 0);
+}
+
+void RefCountObject::addRef()
+{
+	sw::atomicIncrement(&referenceCount);
+}
+
+void RefCountObject::release()
+{
+    ASSERT(referenceCount > 0);
+
+    if(referenceCount > 0)
+	{
+		sw::atomicDecrement(&referenceCount);
+	}
+
+	if(referenceCount == 0)
+	{
+		delete this;
+	}
+}
+
+void RefCountObjectBindingPointer::set(RefCountObject *newObject)
+{
+    // addRef first in case newObject == mObject and this is the last reference to it.
+    if(newObject != NULL) newObject->addRef();
+    if(mObject != NULL) mObject->release();
+
+    mObject = newObject;
+}
+
+}
diff --git a/src/GLES2/libGLESv2/RefCountObject.h b/src/GLES2/libGLESv2/RefCountObject.h
new file mode 100644
index 0000000..a9a11e0
--- /dev/null
+++ b/src/GLES2/libGLESv2/RefCountObject.h
@@ -0,0 +1,75 @@
+// SwiftShader Software Renderer
+//
+// Copyright(c) 2005-2012 TransGaming Inc.
+//
+// All rights reserved. No part of this software may be copied, distributed, transmitted,
+// transcribed, stored in a retrieval system, translated into any human or computer
+// language by any means, or disclosed to third parties without the explicit written
+// agreement of TransGaming Inc. Without such an agreement, no rights or licenses, express
+// or implied, including but not limited to any patent rights, are granted to you.
+//
+
+// RefCountObject.h: Defines the RefCountObject base class that provides
+// lifecycle support for GL objects using the traditional BindObject scheme, but
+// that need to be reference counted for correct cross-context deletion.
+// (Concretely, textures, buffers and renderbuffers.)
+
+#ifndef LIBGLESV2_REFCOUNTOBJECT_H_
+#define LIBGLESV2_REFCOUNTOBJECT_H_
+
+#include "common/debug.h"
+
+#define GL_APICALL
+#include <GLES2/gl2.h>
+
+#include <cstddef>
+
+namespace gl
+{
+
+class RefCountObject
+{
+  public:
+    explicit RefCountObject(GLuint id);
+    virtual ~RefCountObject();
+
+    virtual void addRef();
+	virtual void release();
+
+    GLuint id() const {return mId;}
+    
+  private:
+    GLuint mId;
+
+    volatile int referenceCount;
+};
+
+class RefCountObjectBindingPointer
+{
+  protected:
+    RefCountObjectBindingPointer() : mObject(NULL) { }
+    ~RefCountObjectBindingPointer() { ASSERT(mObject == NULL); } // Objects have to be released before the resource manager is destroyed, so they must be explicitly cleaned up.
+
+    void set(RefCountObject *newObject);
+    RefCountObject *get() const { return mObject; }
+
+  public:
+    GLuint id() const { return (mObject != NULL) ? mObject->id() : 0; }
+    bool operator ! () const { return (get() == NULL); }
+
+  private:
+    RefCountObject *mObject;
+};
+
+template<class ObjectType>
+class BindingPointer : public RefCountObjectBindingPointer
+{
+  public:
+    void set(ObjectType *newObject) { RefCountObjectBindingPointer::set(newObject); }
+    ObjectType *get() const { return static_cast<ObjectType*>(RefCountObjectBindingPointer::get()); }
+    ObjectType *operator -> () const { return get(); }
+};
+
+}
+
+#endif   // LIBGLESV2_REFCOUNTOBJECT_H_
diff --git a/src/GLES2/libGLESv2/Renderbuffer.cpp b/src/GLES2/libGLESv2/Renderbuffer.cpp
new file mode 100644
index 0000000..133b592
--- /dev/null
+++ b/src/GLES2/libGLESv2/Renderbuffer.cpp
@@ -0,0 +1,506 @@
+// SwiftShader Software Renderer
+//
+// Copyright(c) 2005-2013 TransGaming Inc.
+//
+// All rights reserved. No part of this software may be copied, distributed, transmitted,
+// transcribed, stored in a retrieval system, translated into any human or computer
+// language by any means, or disclosed to third parties without the explicit written
+// agreement of TransGaming Inc. Without such an agreement, no rights or licenses, express
+// or implied, including but not limited to any patent rights, are granted to you.
+//
+
+// Renderbuffer.cpp: the Renderbuffer class and its derived classes
+// Colorbuffer, Depthbuffer and Stencilbuffer. Implements GL renderbuffer
+// objects and related functionality. [OpenGL ES 2.0.24] section 4.4.3 page 108.
+
+#include "Renderbuffer.h"
+
+#include "main.h"
+#include "Texture.h"
+#include "utilities.h"
+
+namespace gl
+{
+RenderbufferInterface::RenderbufferInterface()
+{
+}
+
+// The default case for classes inherited from RenderbufferInterface is not to
+// need to do anything upon the reference count to the parent Renderbuffer incrementing
+// or decrementing. 
+void RenderbufferInterface::addProxyRef(const Renderbuffer *proxy)
+{
+}
+
+void RenderbufferInterface::releaseProxy(const Renderbuffer *proxy)
+{
+}
+
+GLuint RenderbufferInterface::getRedSize() const
+{
+	return sw2es::GetRedSize(getInternalFormat());
+}
+
+GLuint RenderbufferInterface::getGreenSize() const
+{
+	return sw2es::GetGreenSize(getInternalFormat());
+}
+
+GLuint RenderbufferInterface::getBlueSize() const
+{
+	return sw2es::GetBlueSize(getInternalFormat());
+}
+
+GLuint RenderbufferInterface::getAlphaSize() const
+{
+	return sw2es::GetAlphaSize(getInternalFormat());
+}
+
+GLuint RenderbufferInterface::getDepthSize() const
+{
+	return sw2es::GetDepthSize(getInternalFormat());
+}
+
+GLuint RenderbufferInterface::getStencilSize() const
+{
+	return sw2es::GetStencilSize(getInternalFormat());
+}
+
+///// RenderbufferTexture2D Implementation ////////
+
+RenderbufferTexture2D::RenderbufferTexture2D(Texture2D *texture)
+{
+	mTexture2D.set(texture);
+}
+
+RenderbufferTexture2D::~RenderbufferTexture2D()
+{
+	mTexture2D.set(NULL);
+}
+
+// Textures need to maintain their own reference count for references via
+// Renderbuffers acting as proxies. Here, we notify the texture of a reference.
+void RenderbufferTexture2D::addProxyRef(const Renderbuffer *proxy)
+{
+    mTexture2D->addProxyRef(proxy);
+}
+
+void RenderbufferTexture2D::releaseProxy(const Renderbuffer *proxy)
+{
+    mTexture2D->releaseProxy(proxy);
+}
+
+// Increments refcount on surface.
+// caller must release() the returned surface
+Image *RenderbufferTexture2D::getRenderTarget()
+{
+	return mTexture2D->getRenderTarget(GL_TEXTURE_2D);
+}
+
+GLsizei RenderbufferTexture2D::getWidth() const
+{
+	return mTexture2D->getWidth(GL_TEXTURE_2D, 0);
+}
+
+GLsizei RenderbufferTexture2D::getHeight() const
+{
+	return mTexture2D->getHeight(GL_TEXTURE_2D, 0);
+}
+
+GLenum RenderbufferTexture2D::getFormat() const
+{
+	return mTexture2D->getFormat(GL_TEXTURE_2D, 0);
+}
+
+sw::Format RenderbufferTexture2D::getInternalFormat() const
+{
+	return mTexture2D->getInternalFormat(GL_TEXTURE_2D, 0);
+}
+
+GLsizei RenderbufferTexture2D::getSamples() const
+{
+	return 0;
+}
+
+///// RenderbufferTextureCubeMap Implementation ////////
+
+RenderbufferTextureCubeMap::RenderbufferTextureCubeMap(TextureCubeMap *texture, GLenum target) : mTarget(target)
+{
+	mTextureCubeMap.set(texture);
+}
+
+RenderbufferTextureCubeMap::~RenderbufferTextureCubeMap()
+{
+	mTextureCubeMap.set(NULL);
+}
+
+// Textures need to maintain their own reference count for references via
+// Renderbuffers acting as proxies. Here, we notify the texture of a reference.
+void RenderbufferTextureCubeMap::addProxyRef(const Renderbuffer *proxy)
+{
+    mTextureCubeMap->addProxyRef(proxy);
+}
+
+void RenderbufferTextureCubeMap::releaseProxy(const Renderbuffer *proxy)
+{
+    mTextureCubeMap->releaseProxy(proxy);
+}
+
+// Increments refcount on surface.
+// caller must release() the returned surface
+Image *RenderbufferTextureCubeMap::getRenderTarget()
+{
+	return mTextureCubeMap->getRenderTarget(mTarget);
+}
+
+GLsizei RenderbufferTextureCubeMap::getWidth() const
+{
+	return mTextureCubeMap->getWidth(mTarget, 0);
+}
+
+GLsizei RenderbufferTextureCubeMap::getHeight() const
+{
+	return mTextureCubeMap->getHeight(mTarget, 0);
+}
+
+GLenum RenderbufferTextureCubeMap::getFormat() const
+{
+	return mTextureCubeMap->getFormat(mTarget, 0);
+}
+
+sw::Format RenderbufferTextureCubeMap::getInternalFormat() const
+{
+	return mTextureCubeMap->getInternalFormat(mTarget, 0);
+}
+
+GLsizei RenderbufferTextureCubeMap::getSamples() const
+{
+	return 0;
+}
+
+////// Renderbuffer Implementation //////
+
+Renderbuffer::Renderbuffer(GLuint id, RenderbufferInterface *instance) : RefCountObject(id)
+{
+	ASSERT(instance != NULL);
+	mInstance = instance;
+}
+
+Renderbuffer::~Renderbuffer()
+{
+	delete mInstance;
+}
+
+// The RenderbufferInterface contained in this Renderbuffer may need to maintain
+// its own reference count, so we pass it on here.
+void Renderbuffer::addRef()
+{
+    mInstance->addProxyRef(this);
+
+    RefCountObject::addRef();
+}
+
+void Renderbuffer::release()
+{
+    mInstance->releaseProxy(this);
+
+    RefCountObject::release();
+}
+
+// Increments refcount on surface.
+// caller must Release() the returned surface
+Image *Renderbuffer::getRenderTarget()
+{
+	return mInstance->getRenderTarget();
+}
+
+GLsizei Renderbuffer::getWidth() const
+{
+	return mInstance->getWidth();
+}
+
+GLsizei Renderbuffer::getHeight() const
+{
+	return mInstance->getHeight();
+}
+
+GLenum Renderbuffer::getFormat() const
+{
+	return mInstance->getFormat();
+}
+
+sw::Format Renderbuffer::getInternalFormat() const
+{
+	return mInstance->getInternalFormat();
+}
+
+GLuint Renderbuffer::getRedSize() const
+{
+	return mInstance->getRedSize();
+}
+
+GLuint Renderbuffer::getGreenSize() const
+{
+	return mInstance->getGreenSize();
+}
+
+GLuint Renderbuffer::getBlueSize() const
+{
+	return mInstance->getBlueSize();
+}
+
+GLuint Renderbuffer::getAlphaSize() const
+{
+	return mInstance->getAlphaSize();
+}
+
+GLuint Renderbuffer::getDepthSize() const
+{
+	return mInstance->getDepthSize();
+}
+
+GLuint Renderbuffer::getStencilSize() const
+{
+	return mInstance->getStencilSize();
+}
+
+GLsizei Renderbuffer::getSamples() const
+{
+	return mInstance->getSamples();
+}
+
+void Renderbuffer::setStorage(RenderbufferStorage *newStorage)
+{
+	ASSERT(newStorage != NULL);
+
+	delete mInstance;
+	mInstance = newStorage;
+}
+
+RenderbufferStorage::RenderbufferStorage()
+{
+	mWidth = 0;
+	mHeight = 0;
+	format = GL_RGBA4;
+	internalFormat = sw::FORMAT_A8R8G8B8;
+	mSamples = 0;
+}
+
+RenderbufferStorage::~RenderbufferStorage()
+{
+}
+
+// Increments refcount on surface.
+// caller must Release() the returned surface
+Image *RenderbufferStorage::getRenderTarget()
+{
+	return NULL;
+}
+
+GLsizei RenderbufferStorage::getWidth() const
+{
+	return mWidth;
+}
+
+GLsizei RenderbufferStorage::getHeight() const
+{
+	return mHeight;
+}
+
+GLenum RenderbufferStorage::getFormat() const
+{
+	return format;
+}
+
+sw::Format RenderbufferStorage::getInternalFormat() const
+{
+	return internalFormat;
+}
+
+GLsizei RenderbufferStorage::getSamples() const
+{
+	return mSamples;
+}
+
+Colorbuffer::Colorbuffer(Image *renderTarget) : mRenderTarget(renderTarget)
+{
+	if(renderTarget)
+	{
+		renderTarget->addRef();
+		
+		mWidth = renderTarget->getWidth();
+		mHeight = renderTarget->getHeight();
+		internalFormat = renderTarget->getInternalFormat();
+		format = sw2es::ConvertBackBufferFormat(internalFormat);
+		mSamples = renderTarget->getMultiSampleDepth();
+	}
+}
+
+Colorbuffer::Colorbuffer(int width, int height, GLenum format, GLsizei samples) : mRenderTarget(NULL)
+{
+	Device *device = getDevice();
+
+	sw::Format requestedFormat = es2sw::ConvertRenderbufferFormat(format);
+	int supportedSamples = getContext()->getNearestSupportedSamples(requestedFormat, samples);
+
+	if(supportedSamples == -1)
+	{
+		error(GL_OUT_OF_MEMORY);
+
+		return;
+	}
+
+	if(width > 0 && height > 0)
+	{
+		mRenderTarget = device->createRenderTarget(width, height, requestedFormat, supportedSamples, false);
+
+		if(!mRenderTarget)
+		{
+			error(GL_OUT_OF_MEMORY);
+			return;
+		}
+	}
+
+	mWidth = width;
+	mHeight = height;
+	this->format = format;
+	internalFormat = requestedFormat;
+	mSamples = supportedSamples;
+}
+
+Colorbuffer::~Colorbuffer()
+{
+	if(mRenderTarget)
+	{
+		mRenderTarget->release();
+	}
+}
+
+// Increments refcount on surface.
+// caller must release() the returned surface
+Image *Colorbuffer::getRenderTarget()
+{
+	if(mRenderTarget)
+	{
+		mRenderTarget->addRef();
+	}
+
+	return mRenderTarget;
+}
+
+DepthStencilbuffer::DepthStencilbuffer(Image *depthStencil) : mDepthStencil(depthStencil)
+{
+	if(depthStencil)
+	{
+		depthStencil->addRef();
+
+		mWidth = depthStencil->getWidth();
+		mHeight = depthStencil->getHeight();
+		internalFormat = depthStencil->getInternalFormat();
+		format = sw2es::ConvertDepthStencilFormat(internalFormat);
+		mSamples = depthStencil->getMultiSampleDepth();
+	}
+}
+
+DepthStencilbuffer::DepthStencilbuffer(int width, int height, GLsizei samples)
+{
+	Device *device = getDevice();
+
+	mDepthStencil = NULL;
+	
+	int supportedSamples = getContext()->getNearestSupportedSamples(sw::FORMAT_D24S8, samples);
+
+	if(supportedSamples == -1)
+	{
+		error(GL_OUT_OF_MEMORY);
+
+		return;
+	}
+
+	if(width > 0 && height > 0)
+	{
+		mDepthStencil = device->createDepthStencilSurface(width, height, sw::FORMAT_D24S8, supportedSamples, false);
+
+		if(!mDepthStencil)
+		{
+			error(GL_OUT_OF_MEMORY);
+			return;
+		}
+	}
+
+	mWidth = width;
+	mHeight = height;
+	format = GL_DEPTH24_STENCIL8_OES;
+	internalFormat = sw::FORMAT_D24S8;
+	mSamples = supportedSamples;
+}
+
+DepthStencilbuffer::~DepthStencilbuffer()
+{
+	if(mDepthStencil)
+	{
+		mDepthStencil->release();
+	}
+}
+
+// Increments refcount on surface.
+// caller must release() the returned surface
+Image *DepthStencilbuffer::getRenderTarget()
+{
+	if(mDepthStencil)
+	{
+		mDepthStencil->addRef();
+	}
+
+	return mDepthStencil;
+}
+
+Depthbuffer::Depthbuffer(Image *depthStencil) : DepthStencilbuffer(depthStencil)
+{
+	if(depthStencil)
+	{
+		format = GL_DEPTH_COMPONENT16;   // If the renderbuffer parameters are queried, the calling function
+		                                 // will expect one of the valid renderbuffer formats for use in 
+		                                 // glRenderbufferStorage
+	}
+}
+
+Depthbuffer::Depthbuffer(int width, int height, GLsizei samples) : DepthStencilbuffer(width, height, samples)
+{
+	if(mDepthStencil)
+	{
+		format = GL_DEPTH_COMPONENT16;   // If the renderbuffer parameters are queried, the calling function
+		                                 // will expect one of the valid renderbuffer formats for use in 
+		                                 // glRenderbufferStorage
+	}
+}
+
+Depthbuffer::~Depthbuffer()
+{
+}
+
+Stencilbuffer::Stencilbuffer(Image *depthStencil) : DepthStencilbuffer(depthStencil)
+{
+	if(depthStencil)
+	{
+		format = GL_STENCIL_INDEX8;   // If the renderbuffer parameters are queried, the calling function
+		                              // will expect one of the valid renderbuffer formats for use in 
+		                              // glRenderbufferStorage
+	}
+}
+
+Stencilbuffer::Stencilbuffer(int width, int height, GLsizei samples) : DepthStencilbuffer(width, height, samples)
+{
+	if(mDepthStencil)
+	{
+		format = GL_STENCIL_INDEX8;   // If the renderbuffer parameters are queried, the calling function
+		                              // will expect one of the valid renderbuffer formats for use in 
+		                              // glRenderbufferStorage
+	}
+}
+
+Stencilbuffer::~Stencilbuffer()
+{
+}
+
+}
diff --git a/src/GLES2/libGLESv2/Renderbuffer.h b/src/GLES2/libGLESv2/Renderbuffer.h
new file mode 100644
index 0000000..f5e1704
--- /dev/null
+++ b/src/GLES2/libGLESv2/Renderbuffer.h
@@ -0,0 +1,215 @@
+// SwiftShader Software Renderer

+//

+// Copyright(c) 2005-2013 TransGaming Inc.

+//

+// All rights reserved. No part of this software may be copied, distributed, transmitted,

+// transcribed, stored in a retrieval system, translated into any human or computer

+// language by any means, or disclosed to third parties without the explicit written

+// agreement of TransGaming Inc. Without such an agreement, no rights or licenses, express

+// or implied, including but not limited to any patent rights, are granted to you.

+//

+

+// Renderbuffer.h: Defines the wrapper class Renderbuffer, as well as the

+// class hierarchy used to store its contents: RenderbufferStorage, Colorbuffer,

+// DepthStencilbuffer, Depthbuffer and Stencilbuffer. Implements GL renderbuffer

+// objects and related functionality. [OpenGL ES 2.0.24] section 4.4.3 page 108.

+

+#ifndef LIBGLESV2_RENDERBUFFER_H_

+#define LIBGLESV2_RENDERBUFFER_H_

+

+#include "RefCountObject.h"

+#include "Image.hpp"

+

+#define GL_APICALL

+#include <GLES2/gl2.h>

+

+namespace gl

+{

+class Texture2D;

+class TextureCubeMap;

+class Renderbuffer;

+class Colorbuffer;

+class DepthStencilbuffer;

+

+class RenderbufferInterface

+{

+public:

+	RenderbufferInterface();

+

+	virtual ~RenderbufferInterface() {};

+

+	virtual void addProxyRef(const Renderbuffer *proxy);

+    virtual void releaseProxy(const Renderbuffer *proxy);

+

+	virtual Image *getRenderTarget() = 0;

+

+	virtual GLsizei getWidth() const = 0;

+	virtual GLsizei getHeight() const = 0;

+	virtual GLenum getFormat() const = 0;

+	virtual sw::Format getInternalFormat() const = 0;

+	virtual GLsizei getSamples() const = 0;

+

+	GLuint getRedSize() const;

+	GLuint getGreenSize() const;

+	GLuint getBlueSize() const;

+	GLuint getAlphaSize() const;

+	GLuint getDepthSize() const;

+	GLuint getStencilSize() const;

+};

+

+class RenderbufferTexture2D : public RenderbufferInterface

+{

+public:

+	RenderbufferTexture2D(Texture2D *texture);

+

+	virtual ~RenderbufferTexture2D();

+

+	virtual void addProxyRef(const Renderbuffer *proxy);

+    virtual void releaseProxy(const Renderbuffer *proxy);

+

+	Image *getRenderTarget();

+

+	virtual GLsizei getWidth() const;

+	virtual GLsizei getHeight() const;

+	virtual GLenum getFormat() const;

+	virtual sw::Format getInternalFormat() const;

+	virtual GLsizei getSamples() const;

+

+private:

+	BindingPointer<Texture2D> mTexture2D;

+};

+

+class RenderbufferTextureCubeMap : public RenderbufferInterface

+{

+public:

+	RenderbufferTextureCubeMap(TextureCubeMap *texture, GLenum target);

+

+	virtual ~RenderbufferTextureCubeMap();

+

+	virtual void addProxyRef(const Renderbuffer *proxy);

+    virtual void releaseProxy(const Renderbuffer *proxy);

+

+	Image *getRenderTarget();

+

+	virtual GLsizei getWidth() const;

+	virtual GLsizei getHeight() const;

+	virtual GLenum getFormat() const;

+	virtual sw::Format getInternalFormat() const;

+	virtual GLsizei getSamples() const;

+

+private:

+	BindingPointer<TextureCubeMap> mTextureCubeMap;

+	GLenum mTarget;

+};

+

+// A class derived from RenderbufferStorage is created whenever glRenderbufferStorage

+// is called. The specific concrete type depends on whether the internal format is

+// colour depth, stencil or packed depth/stencil.

+class RenderbufferStorage : public RenderbufferInterface

+{

+public:

+	RenderbufferStorage();

+

+	virtual ~RenderbufferStorage() = 0;

+

+	virtual Image *getRenderTarget();

+

+	virtual GLsizei getWidth() const;

+	virtual GLsizei getHeight() const;

+	virtual GLenum getFormat() const;

+	virtual sw::Format getInternalFormat() const;

+	virtual GLsizei getSamples() const;

+

+protected:

+	GLsizei mWidth;

+	GLsizei mHeight;

+	GLenum format;

+	sw::Format internalFormat;

+	GLsizei mSamples;

+};

+

+// Renderbuffer implements the GL renderbuffer object.

+// It's only a proxy for a RenderbufferInterface instance; the internal object

+// can change whenever glRenderbufferStorage is called.

+class Renderbuffer : public RefCountObject

+{

+public:

+	Renderbuffer(GLuint id, RenderbufferInterface *storage);

+

+	virtual ~Renderbuffer();

+

+	// These functions from RefCountObject are overloaded here because

+    // Textures need to maintain their own count of references to them via

+    // Renderbuffers/RenderbufferTextures. These functions invoke those

+    // reference counting functions on the RenderbufferInterface.

+    virtual void addRef();

+    virtual void release();

+

+	Image *getRenderTarget();

+

+	GLsizei getWidth() const;

+	GLsizei getHeight() const;

+	GLenum getFormat() const;

+	sw::Format getInternalFormat() const;

+	GLuint getRedSize() const;

+	GLuint getGreenSize() const;

+	GLuint getBlueSize() const;

+	GLuint getAlphaSize() const;

+	GLuint getDepthSize() const;

+	GLuint getStencilSize() const;

+	GLsizei getSamples() const;

+

+	void setStorage(RenderbufferStorage *newStorage);

+

+private:

+	RenderbufferInterface *mInstance;

+};

+

+class Colorbuffer : public RenderbufferStorage

+{

+public:

+	explicit Colorbuffer(Image *renderTarget);

+	Colorbuffer(GLsizei width, GLsizei height, GLenum format, GLsizei samples);

+

+	virtual ~Colorbuffer();

+

+	virtual Image *getRenderTarget();

+

+private:

+	Image *mRenderTarget;

+};

+

+class DepthStencilbuffer : public RenderbufferStorage

+{

+public:

+	explicit DepthStencilbuffer(Image *depthStencil);

+	DepthStencilbuffer(GLsizei width, GLsizei height, GLsizei samples);

+

+	~DepthStencilbuffer();

+

+	virtual Image *getRenderTarget();

+

+protected:

+	Image *mDepthStencil;

+};

+

+class Depthbuffer : public DepthStencilbuffer

+{

+public:

+	explicit Depthbuffer(Image *depthStencil);

+	Depthbuffer(GLsizei width, GLsizei height, GLsizei samples);

+

+	virtual ~Depthbuffer();

+};

+

+class Stencilbuffer : public DepthStencilbuffer

+{

+public:

+	explicit Stencilbuffer(Image *depthStencil);

+	Stencilbuffer(GLsizei width, GLsizei height, GLsizei samples);

+

+	virtual ~Stencilbuffer();

+};

+}

+

+#endif   // LIBGLESV2_RENDERBUFFER_H_

diff --git a/src/GLES2/libGLESv2/ResourceManager.cpp b/src/GLES2/libGLESv2/ResourceManager.cpp
new file mode 100644
index 0000000..522257f
--- /dev/null
+++ b/src/GLES2/libGLESv2/ResourceManager.cpp
@@ -0,0 +1,325 @@
+// SwiftShader Software Renderer
+//
+// Copyright(c) 2005-2012 TransGaming Inc.
+//
+// All rights reserved. No part of this software may be copied, distributed, transmitted,
+// transcribed, stored in a retrieval system, translated into any human or computer
+// language by any means, or disclosed to third parties without the explicit written
+// agreement of TransGaming Inc. Without such an agreement, no rights or licenses, express
+// or implied, including but not limited to any patent rights, are granted to you.
+//
+
+// ResourceManager.cpp: Implements the ResourceManager class, which tracks and 
+// retrieves objects which may be shared by multiple Contexts.
+
+#include "ResourceManager.h"
+
+#include "Buffer.h"
+#include "Program.h"
+#include "Renderbuffer.h"
+#include "Shader.h"
+#include "Texture.h"
+
+namespace gl
+{
+ResourceManager::ResourceManager()
+{
+    mRefCount = 1;
+}
+
+ResourceManager::~ResourceManager()
+{
+    while(!mBufferMap.empty())
+    {
+        deleteBuffer(mBufferMap.begin()->first);
+    }
+
+    while(!mProgramMap.empty())
+    {
+        deleteProgram(mProgramMap.begin()->first);
+    }
+
+    while(!mShaderMap.empty())
+    {
+        deleteShader(mShaderMap.begin()->first);
+    }
+
+    while(!mRenderbufferMap.empty())
+    {
+        deleteRenderbuffer(mRenderbufferMap.begin()->first);
+    }
+
+    while(!mTextureMap.empty())
+    {
+        deleteTexture(mTextureMap.begin()->first);
+    }
+}
+
+void ResourceManager::addRef()
+{
+    mRefCount++;
+}
+
+void ResourceManager::release()
+{
+    if(--mRefCount == 0)
+    {
+        delete this;
+    }
+}
+
+// Returns an unused buffer name
+GLuint ResourceManager::createBuffer()
+{
+    GLuint handle = mBufferHandleAllocator.allocate();
+
+    mBufferMap[handle] = NULL;
+
+    return handle;
+}
+
+// Returns an unused shader/program name
+GLuint ResourceManager::createShader(GLenum type)
+{
+    GLuint handle = mProgramShaderHandleAllocator.allocate();
+
+    if(type == GL_VERTEX_SHADER)
+    {
+        mShaderMap[handle] = new VertexShader(this, handle);
+    }
+    else if(type == GL_FRAGMENT_SHADER)
+    {
+        mShaderMap[handle] = new FragmentShader(this, handle);
+    }
+    else UNREACHABLE();
+
+    return handle;
+}
+
+// Returns an unused program/shader name
+GLuint ResourceManager::createProgram()
+{
+    GLuint handle = mProgramShaderHandleAllocator.allocate();
+
+    mProgramMap[handle] = new Program(this, handle);
+
+    return handle;
+}
+
+// Returns an unused texture name
+GLuint ResourceManager::createTexture()
+{
+    GLuint handle = mTextureHandleAllocator.allocate();
+
+    mTextureMap[handle] = NULL;
+
+    return handle;
+}
+
+// Returns an unused renderbuffer name
+GLuint ResourceManager::createRenderbuffer()
+{
+    GLuint handle = mRenderbufferHandleAllocator.allocate();
+
+    mRenderbufferMap[handle] = NULL;
+
+    return handle;
+}
+
+void ResourceManager::deleteBuffer(GLuint buffer)
+{
+    BufferMap::iterator bufferObject = mBufferMap.find(buffer);
+
+    if(bufferObject != mBufferMap.end())
+    {
+        mBufferHandleAllocator.release(bufferObject->first);
+        if(bufferObject->second) bufferObject->second->release();
+        mBufferMap.erase(bufferObject);
+    }
+}
+
+void ResourceManager::deleteShader(GLuint shader)
+{
+    ShaderMap::iterator shaderObject = mShaderMap.find(shader);
+
+    if(shaderObject != mShaderMap.end())
+    {
+        if(shaderObject->second->getRefCount() == 0)
+        {
+            mProgramShaderHandleAllocator.release(shaderObject->first);
+            delete shaderObject->second;
+            mShaderMap.erase(shaderObject);
+        }
+        else
+        {
+            shaderObject->second->flagForDeletion();
+        }
+    }
+}
+
+void ResourceManager::deleteProgram(GLuint program)
+{
+    ProgramMap::iterator programObject = mProgramMap.find(program);
+
+    if(programObject != mProgramMap.end())
+    {
+        if(programObject->second->getRefCount() == 0)
+        {
+            mProgramShaderHandleAllocator.release(programObject->first);
+            delete programObject->second;
+            mProgramMap.erase(programObject);
+        }
+        else
+        { 
+            programObject->second->flagForDeletion();
+        }
+    }
+}
+
+void ResourceManager::deleteTexture(GLuint texture)
+{
+    TextureMap::iterator textureObject = mTextureMap.find(texture);
+
+    if(textureObject != mTextureMap.end())
+    {
+        mTextureHandleAllocator.release(textureObject->first);
+        if(textureObject->second) textureObject->second->release();
+        mTextureMap.erase(textureObject);
+    }
+}
+
+void ResourceManager::deleteRenderbuffer(GLuint renderbuffer)
+{
+    RenderbufferMap::iterator renderbufferObject = mRenderbufferMap.find(renderbuffer);
+
+    if(renderbufferObject != mRenderbufferMap.end())
+    {
+        mRenderbufferHandleAllocator.release(renderbufferObject->first);
+        if(renderbufferObject->second) renderbufferObject->second->release();
+        mRenderbufferMap.erase(renderbufferObject);
+    }
+}
+
+Buffer *ResourceManager::getBuffer(unsigned int handle)
+{
+    BufferMap::iterator buffer = mBufferMap.find(handle);
+
+    if(buffer == mBufferMap.end())
+    {
+        return NULL;
+    }
+    else
+    {
+        return buffer->second;
+    }
+}
+
+Shader *ResourceManager::getShader(unsigned int handle)
+{
+    ShaderMap::iterator shader = mShaderMap.find(handle);
+
+    if(shader == mShaderMap.end())
+    {
+        return NULL;
+    }
+    else
+    {
+        return shader->second;
+    }
+}
+
+Texture *ResourceManager::getTexture(unsigned int handle)
+{
+    if(handle == 0) return NULL;
+
+    TextureMap::iterator texture = mTextureMap.find(handle);
+
+    if(texture == mTextureMap.end())
+    {
+        return NULL;
+    }
+    else
+    {
+        return texture->second;
+    }
+}
+
+Program *ResourceManager::getProgram(unsigned int handle)
+{
+    ProgramMap::iterator program = mProgramMap.find(handle);
+
+    if(program == mProgramMap.end())
+    {
+        return NULL;
+    }
+    else
+    {
+        return program->second;
+    }
+}
+
+Renderbuffer *ResourceManager::getRenderbuffer(unsigned int handle)
+{
+    RenderbufferMap::iterator renderbuffer = mRenderbufferMap.find(handle);
+
+    if(renderbuffer == mRenderbufferMap.end())
+    {
+        return NULL;
+    }
+    else
+    {
+        return renderbuffer->second;
+    }
+}
+
+void ResourceManager::setRenderbuffer(GLuint handle, Renderbuffer *buffer)
+{
+    mRenderbufferMap[handle] = buffer;
+}
+
+void ResourceManager::checkBufferAllocation(unsigned int buffer)
+{
+    if(buffer != 0 && !getBuffer(buffer))
+    {
+        Buffer *bufferObject = new Buffer(buffer);
+        mBufferMap[buffer] = bufferObject;
+        bufferObject->addRef();
+    }
+}
+
+void ResourceManager::checkTextureAllocation(GLuint texture, TextureType type)
+{
+    if(!getTexture(texture) && texture != 0)
+    {
+        Texture *textureObject;
+
+        if(type == TEXTURE_2D)
+        {
+            textureObject = new Texture2D(texture);
+        }
+        else if(type == TEXTURE_CUBE)
+        {
+            textureObject = new TextureCubeMap(texture);
+        }
+        else
+        {
+            UNREACHABLE();
+            return;
+        }
+
+        mTextureMap[texture] = textureObject;
+        textureObject->addRef();
+    }
+}
+
+void ResourceManager::checkRenderbufferAllocation(GLuint renderbuffer)
+{
+    if(renderbuffer != 0 && !getRenderbuffer(renderbuffer))
+    {
+        Renderbuffer *renderbufferObject = new Renderbuffer(renderbuffer, new Colorbuffer(0, 0, GL_RGBA4, 0));
+        mRenderbufferMap[renderbuffer] = renderbufferObject;
+        renderbufferObject->addRef();
+    }
+}
+
+}
diff --git a/src/GLES2/libGLESv2/ResourceManager.h b/src/GLES2/libGLESv2/ResourceManager.h
new file mode 100644
index 0000000..6c6031b
--- /dev/null
+++ b/src/GLES2/libGLESv2/ResourceManager.h
@@ -0,0 +1,100 @@
+// SwiftShader Software Renderer

+//

+// Copyright(c) 2005-2012 TransGaming Inc.

+//

+// All rights reserved. No part of this software may be copied, distributed, transmitted,

+// transcribed, stored in a retrieval system, translated into any human or computer

+// language by any means, or disclosed to third parties without the explicit written

+// agreement of TransGaming Inc. Without such an agreement, no rights or licenses, express

+// or implied, including but not limited to any patent rights, are granted to you.

+//

+

+// ResourceManager.h : Defines the ResourceManager class, which tracks objects

+// shared by multiple GL contexts.

+

+#ifndef LIBGLESV2_RESOURCEMANAGER_H_

+#define LIBGLESV2_RESOURCEMANAGER_H_

+

+#include "HandleAllocator.h"

+

+#define GL_APICALL

+#include <GLES2/gl2.h>

+

+#include <map>

+

+namespace gl

+{

+class Buffer;

+class Shader;

+class Program;

+class Texture;

+class Renderbuffer;

+

+enum TextureType

+{

+    TEXTURE_2D,

+    TEXTURE_CUBE,

+

+    TEXTURE_TYPE_COUNT,

+    TEXTURE_UNKNOWN

+};

+

+class ResourceManager

+{

+  public:

+    ResourceManager();

+    ~ResourceManager();

+

+    void addRef();

+    void release();

+

+    GLuint createBuffer();

+    GLuint createShader(GLenum type);

+    GLuint createProgram();

+    GLuint createTexture();

+    GLuint createRenderbuffer();

+

+    void deleteBuffer(GLuint buffer);

+    void deleteShader(GLuint shader);

+    void deleteProgram(GLuint program);

+    void deleteTexture(GLuint texture);

+    void deleteRenderbuffer(GLuint renderbuffer);

+

+    Buffer *getBuffer(GLuint handle);

+    Shader *getShader(GLuint handle);

+    Program *getProgram(GLuint handle);

+    Texture *getTexture(GLuint handle);

+    Renderbuffer *getRenderbuffer(GLuint handle);

+    

+    void setRenderbuffer(GLuint handle, Renderbuffer *renderbuffer);

+

+    void checkBufferAllocation(unsigned int buffer);

+    void checkTextureAllocation(GLuint texture, TextureType type);

+    void checkRenderbufferAllocation(GLuint renderbuffer);

+

+  private:

+    std::size_t mRefCount;

+

+    typedef std::map<GLint, Buffer*> BufferMap;

+    BufferMap mBufferMap;

+    HandleAllocator mBufferHandleAllocator;

+

+    typedef std::map<GLint, Shader*> ShaderMap;

+    ShaderMap mShaderMap;

+

+    typedef std::map<GLint, Program*> ProgramMap;

+    ProgramMap mProgramMap;

+    HandleAllocator mProgramShaderHandleAllocator;

+

+    typedef std::map<GLint, Texture*> TextureMap;

+    TextureMap mTextureMap;

+    HandleAllocator mTextureHandleAllocator;

+

+    typedef std::map<GLint, Renderbuffer*> RenderbufferMap;

+    RenderbufferMap mRenderbufferMap;

+    HandleAllocator mRenderbufferHandleAllocator;

+};

+

+}

+

+#endif // LIBGLESV2_RESOURCEMANAGER_H_

diff --git a/src/GLES2/libGLESv2/Shader.cpp b/src/GLES2/libGLESv2/Shader.cpp
new file mode 100644
index 0000000..f144a24
--- /dev/null
+++ b/src/GLES2/libGLESv2/Shader.cpp
@@ -0,0 +1,554 @@
+// SwiftShader Software Renderer
+//
+// Copyright(c) 2005-2012 TransGaming Inc.
+//
+// All rights reserved. No part of this software may be copied, distributed, transmitted,
+// transcribed, stored in a retrieval system, translated into any human or computer
+// language by any means, or disclosed to third parties without the explicit written
+// agreement of TransGaming Inc. Without such an agreement, no rights or licenses, express
+// or implied, including but not limited to any patent rights, are granted to you.
+//
+
+// Shader.cpp: Implements the Shader class and its  derived classes
+// VertexShader and FragmentShader. Implements GL shader objects and related
+// functionality. [OpenGL ES 2.0.24] section 2.10 page 24 and section 3.8 page 84.
+
+#include "Shader.h"
+
+#include "main.h"
+#include "utilities.h"
+
+#include "GLSLANG/ShaderLang.h"
+
+#include <string>
+
+namespace gl
+{
+void *Shader::mFragmentCompiler = NULL;
+void *Shader::mVertexCompiler = NULL;
+
+Shader::Shader(ResourceManager *manager, GLuint handle) : mHandle(handle), mResourceManager(manager)
+{
+    mSource = NULL;
+    mInfoLog = NULL;
+
+	clear();
+	initializeCompiler();
+
+    mRefCount = 0;
+    mDeleteStatus = false;
+}
+
+Shader::~Shader()
+{
+    delete[] mSource;
+    delete[] mInfoLog;
+}
+
+GLuint Shader::getHandle() const
+{
+    return mHandle;
+}
+
+void Shader::setSource(GLsizei count, const char **string, const GLint *length)
+{
+    delete[] mSource;
+    int totalLength = 0;
+
+    for(int i = 0; i < count; i++)
+    {
+        if(length && length[i] >= 0)
+        {
+            totalLength += length[i];
+        }
+        else
+        {
+            totalLength += (int)strlen(string[i]);
+        }
+    }
+
+    mSource = new char[totalLength + 1];
+    char *code = mSource;
+
+    for(int i = 0; i < count; i++)
+    {
+        int stringLength;
+
+        if(length && length[i] >= 0)
+        {
+            stringLength = length[i];
+        }
+        else
+        {
+            stringLength = (int)strlen(string[i]);
+        }
+
+        strncpy(code, string[i], stringLength);
+        code += stringLength;
+    }
+
+    mSource[totalLength] = '\0';
+}
+
+int Shader::getInfoLogLength() const
+{
+    if(!mInfoLog)
+    {
+        return 0;
+    }
+    else
+    {
+       return strlen(mInfoLog) + 1;
+    }
+}
+
+void Shader::getInfoLog(GLsizei bufSize, GLsizei *length, char *infoLog)
+{
+    int index = 0;
+
+	if(bufSize > 0)
+	{
+		if(mInfoLog)
+		{
+			index = std::min(bufSize - 1, (int)strlen(mInfoLog));
+			memcpy(infoLog, mInfoLog, index);
+		}
+
+        infoLog[index] = '\0';
+    }
+
+    if(length)
+    {
+        *length = index;
+    }
+}
+
+int Shader::getSourceLength() const
+{
+    if(!mSource)
+    {
+        return 0;
+    }
+    else
+    {
+       return strlen(mSource) + 1;
+    }
+}
+
+void Shader::getSource(GLsizei bufSize, GLsizei *length, char *source)
+{
+    int index = 0;
+
+	if(bufSize > 0)
+	{
+		if(mSource)
+		{
+			index = std::min(bufSize - 1, (int)strlen(mSource));
+			memcpy(source, mSource, index);
+		}
+
+        source[index] = '\0';
+    }
+
+    if(length)
+    {
+        *length = index;
+    }
+}
+
+void Shader::clear()
+{
+    delete[] mInfoLog;
+    mInfoLog = NULL;
+
+    varyings.clear();
+	activeAttributes.clear();
+}
+
+bool Shader::isCompiled()
+{
+    return getShader() != 0;
+}
+
+sw::PixelShader *Shader::getPixelShader() const
+{
+	return 0;
+}
+
+sw::VertexShader *Shader::getVertexShader() const
+{
+	return 0;
+}
+
+void Shader::addRef()
+{
+    mRefCount++;
+}
+
+void Shader::release()
+{
+    mRefCount--;
+
+    if(mRefCount == 0 && mDeleteStatus)
+    {
+        mResourceManager->deleteShader(mHandle);
+    }
+}
+
+unsigned int Shader::getRefCount() const
+{
+    return mRefCount;
+}
+
+bool Shader::isFlaggedForDeletion() const
+{
+    return mDeleteStatus;
+}
+
+void Shader::flagForDeletion()
+{
+    mDeleteStatus = true;
+}
+
+// Perform a one-time initialization of the shader compiler (or after being destructed by releaseCompiler)
+void Shader::initializeCompiler()
+{
+    if(!mFragmentCompiler)
+    {
+        int result = ShInitialize();
+
+        if(result)
+        {
+            ShBuiltInResources resources;
+            ShInitBuiltInResources(&resources);
+            Context *context = getContext();            
+
+            resources.MaxVertexAttribs = MAX_VERTEX_ATTRIBS;
+            resources.MaxVertexUniformVectors = MAX_VERTEX_UNIFORM_VECTORS;
+            resources.MaxVaryingVectors = MAX_VARYING_VECTORS;
+            resources.MaxVertexTextureImageUnits = MAX_VERTEX_TEXTURE_IMAGE_UNITS;
+            resources.MaxCombinedTextureImageUnits = MAX_COMBINED_TEXTURE_IMAGE_UNITS;
+            resources.MaxTextureImageUnits = MAX_TEXTURE_IMAGE_UNITS;
+            resources.MaxFragmentUniformVectors = MAX_FRAGMENT_UNIFORM_VECTORS;
+            resources.MaxDrawBuffers = MAX_DRAW_BUFFERS;
+            resources.OES_standard_derivatives = 1;
+
+            mFragmentCompiler = ShConstructCompiler(SH_FRAGMENT_SHADER, SH_GLES2_SPEC, &resources);
+            mVertexCompiler = ShConstructCompiler(SH_VERTEX_SHADER, SH_GLES2_SPEC, &resources);
+        }
+    }
+}
+
+void Shader::releaseCompiler()
+{
+    ShDestruct(mFragmentCompiler);
+    ShDestruct(mVertexCompiler);
+
+    mFragmentCompiler = NULL;
+    mVertexCompiler = NULL;
+
+    ShFinalize();
+}
+
+GLenum Shader::parseType(const std::string &type)
+{
+    if(type == "float")
+    {
+        return GL_FLOAT;
+    }
+    else if(type == "float2")
+    {
+        return GL_FLOAT_VEC2;
+    }
+    else if(type == "float3")
+    {
+        return GL_FLOAT_VEC3;
+    }
+    else if(type == "float4")
+    {
+        return GL_FLOAT_VEC4;
+    }
+    else if(type == "float2x2")
+    {
+        return GL_FLOAT_MAT2;
+    }
+    else if(type == "float3x3")
+    {
+        return GL_FLOAT_MAT3;
+    }
+    else if(type == "float4x4")
+    {
+        return GL_FLOAT_MAT4;
+    }
+    else UNREACHABLE();
+
+    return GL_NONE;
+}
+
+// true if varying x has a higher priority in packing than y
+bool Shader::compareVarying(const Varying &x, const Varying &y)
+{
+    if(x.type == y.type)
+    {
+        return x.size() > y.size();
+    }
+
+    switch (x.type)
+    {
+      case GL_FLOAT_MAT4: return true;
+      case GL_FLOAT_MAT2:
+        switch(y.type)
+        {
+          case GL_FLOAT_MAT4: return false;
+          case GL_FLOAT_MAT2: return true;
+          case GL_FLOAT_VEC4: return true;
+          case GL_FLOAT_MAT3: return true;
+          case GL_FLOAT_VEC3: return true;
+          case GL_FLOAT_VEC2: return true;
+          case GL_FLOAT:      return true;
+          default: UNREACHABLE();
+        }
+        break;
+      case GL_FLOAT_VEC4:
+        switch(y.type)
+        {
+          case GL_FLOAT_MAT4: return false;
+          case GL_FLOAT_MAT2: return false;
+          case GL_FLOAT_VEC4: return true;
+          case GL_FLOAT_MAT3: return true;
+          case GL_FLOAT_VEC3: return true;
+          case GL_FLOAT_VEC2: return true;
+          case GL_FLOAT:      return true;
+          default: UNREACHABLE();
+        }
+        break;
+      case GL_FLOAT_MAT3:
+        switch(y.type)
+        {
+          case GL_FLOAT_MAT4: return false;
+          case GL_FLOAT_MAT2: return false;
+          case GL_FLOAT_VEC4: return false;
+          case GL_FLOAT_MAT3: return true;
+          case GL_FLOAT_VEC3: return true;
+          case GL_FLOAT_VEC2: return true;
+          case GL_FLOAT:      return true;
+          default: UNREACHABLE();
+        }
+        break;
+      case GL_FLOAT_VEC3:
+        switch(y.type)
+        {
+          case GL_FLOAT_MAT4: return false;
+          case GL_FLOAT_MAT2: return false;
+          case GL_FLOAT_VEC4: return false;
+          case GL_FLOAT_MAT3: return false;
+          case GL_FLOAT_VEC3: return true;
+          case GL_FLOAT_VEC2: return true;
+          case GL_FLOAT:      return true;
+          default: UNREACHABLE();
+        }
+        break;
+      case GL_FLOAT_VEC2:
+        switch(y.type)
+        {
+          case GL_FLOAT_MAT4: return false;
+          case GL_FLOAT_MAT2: return false;
+          case GL_FLOAT_VEC4: return false;
+          case GL_FLOAT_MAT3: return false;
+          case GL_FLOAT_VEC3: return false;
+          case GL_FLOAT_VEC2: return true;
+          case GL_FLOAT:      return true;
+          default: UNREACHABLE();
+        }
+        break;
+      case GL_FLOAT: return false;
+      default: UNREACHABLE();
+    }
+
+    return false;
+}
+
+VertexShader::VertexShader(ResourceManager *manager, GLuint handle) : Shader(manager, handle)
+{
+	vertexShader = 0;
+}
+
+VertexShader::~VertexShader()
+{
+	delete vertexShader;
+}
+
+GLenum VertexShader::getType()
+{
+    return GL_VERTEX_SHADER;
+}
+
+void VertexShader::compile()
+{
+	clear();
+	initializeCompiler();
+
+	delete vertexShader;
+	vertexShader = new sw::VertexShader();
+
+	TranslatorASM *assembler = new TranslatorASM(this, SH_VERTEX_SHADER, SH_GLES2_SPEC);
+
+	ShBuiltInResources resources;
+	ShInitBuiltInResources(&resources);     
+	resources.MaxVertexAttribs = MAX_VERTEX_ATTRIBS;
+	resources.MaxVertexUniformVectors = MAX_VERTEX_UNIFORM_VECTORS;
+	resources.MaxVaryingVectors = MAX_VARYING_VECTORS;
+	resources.MaxVertexTextureImageUnits = MAX_VERTEX_TEXTURE_IMAGE_UNITS;
+	resources.MaxCombinedTextureImageUnits = MAX_COMBINED_TEXTURE_IMAGE_UNITS;
+	resources.MaxTextureImageUnits = MAX_TEXTURE_IMAGE_UNITS;
+	resources.MaxFragmentUniformVectors = MAX_FRAGMENT_UNIFORM_VECTORS;
+	resources.MaxDrawBuffers = MAX_DRAW_BUFFERS;
+	resources.OES_standard_derivatives = 1;
+	assembler->Init(resources);
+
+	// Ensure we don't pass a NULL source to the compiler
+    char *source = "\0";
+	if(mSource)
+    {
+        source = mSource;
+    }
+
+	int success = ShCompile(assembler, &source, 1, SH_OBJECT_CODE);
+
+	if(false)
+	{
+		static int serial = 1;
+		char buffer[256];
+		sprintf(buffer, "vertex-input-%d-%d.txt", getHandle(), serial);
+		FILE *file = fopen(buffer, "wt");
+		fprintf(file, mSource);
+		fclose(file);
+		vertexShader->print("vertex-output-%d-%d.txt", getHandle(), serial);
+		serial++;
+	}
+
+	if(!success)
+	{
+		delete vertexShader;
+		vertexShader = 0;
+
+		int infoLogLen = 0;
+        ShGetInfo(assembler, SH_INFO_LOG_LENGTH, &infoLogLen);
+        mInfoLog = new char[infoLogLen];
+        ShGetInfoLog(assembler, mInfoLog);
+        TRACE("\n%s", mInfoLog);
+	}
+
+	delete assembler;
+}
+
+int VertexShader::getSemanticIndex(const std::string &attributeName)
+{
+    if(!attributeName.empty())
+    {
+		for(sh::ActiveAttributes::iterator attribute = activeAttributes.begin(); attribute != activeAttributes.end(); attribute++)
+        {
+            if(attribute->name == attributeName)
+            {
+				return attribute->registerIndex;
+            }
+        }
+    }
+
+    return -1;
+}
+
+sw::Shader *VertexShader::getShader() const
+{
+	return vertexShader;
+}
+
+sw::VertexShader *VertexShader::getVertexShader() const
+{
+	return vertexShader;
+}
+
+FragmentShader::FragmentShader(ResourceManager *manager, GLuint handle) : Shader(manager, handle)
+{
+	pixelShader = 0;
+}
+
+FragmentShader::~FragmentShader()
+{
+	delete pixelShader;
+}
+
+GLenum FragmentShader::getType()
+{
+    return GL_FRAGMENT_SHADER;
+}
+
+void FragmentShader::compile()
+{
+	clear();
+	initializeCompiler();
+
+	delete pixelShader;
+	pixelShader = new sw::PixelShader();
+
+	TranslatorASM *assembler = new TranslatorASM(this, SH_FRAGMENT_SHADER, SH_GLES2_SPEC);
+
+	ShBuiltInResources resources;
+	ShInitBuiltInResources(&resources);     
+	resources.MaxVertexAttribs = MAX_VERTEX_ATTRIBS;
+	resources.MaxVertexUniformVectors = MAX_VERTEX_UNIFORM_VECTORS;
+	resources.MaxVaryingVectors = MAX_VARYING_VECTORS;
+	resources.MaxVertexTextureImageUnits = MAX_VERTEX_TEXTURE_IMAGE_UNITS;
+	resources.MaxCombinedTextureImageUnits = MAX_COMBINED_TEXTURE_IMAGE_UNITS;
+	resources.MaxTextureImageUnits = MAX_TEXTURE_IMAGE_UNITS;
+	resources.MaxFragmentUniformVectors = MAX_FRAGMENT_UNIFORM_VECTORS;
+	resources.MaxDrawBuffers = MAX_DRAW_BUFFERS;
+	resources.OES_standard_derivatives = 1;
+	assembler->Init(resources);
+
+	// Ensure we don't pass a NULL source to the compiler
+    char *source = "\0";
+	if(mSource)
+    {
+        source = mSource;
+    }
+
+	int success = ShCompile(assembler, &source, 1, SH_OBJECT_CODE);
+	
+	if(false)
+	{
+		static int serial = 1;
+		char buffer[256];
+		sprintf(buffer, "pixel-input-%d-%d.txt", getHandle(), serial);
+		FILE *file = fopen(buffer, "wt");
+		fprintf(file, mSource);
+		fclose(file);
+		pixelShader->print("pixel-output-%d-%d.txt", getHandle(), serial);
+		serial++;
+	}
+
+	if(!success)
+	{
+		delete pixelShader;
+		pixelShader = 0;
+
+		int infoLogLen = 0;
+        ShGetInfo(assembler, SH_INFO_LOG_LENGTH, &infoLogLen);
+        mInfoLog = new char[infoLogLen];
+        ShGetInfoLog(assembler, mInfoLog);
+        TRACE("\n%s", mInfoLog);
+	}
+
+	delete assembler;
+}
+
+sw::Shader *FragmentShader::getShader() const
+{
+	return pixelShader;
+}
+
+sw::PixelShader *FragmentShader::getPixelShader() const
+{
+	return pixelShader;
+}
+}
diff --git a/src/GLES2/libGLESv2/Shader.h b/src/GLES2/libGLESv2/Shader.h
new file mode 100644
index 0000000..6629c39
--- /dev/null
+++ b/src/GLES2/libGLESv2/Shader.h
@@ -0,0 +1,162 @@
+// SwiftShader Software Renderer

+//

+// Copyright(c) 2005-2012 TransGaming Inc.

+//

+// All rights reserved. No part of this software may be copied, distributed, transmitted,

+// transcribed, stored in a retrieval system, translated into any human or computer

+// language by any means, or disclosed to third parties without the explicit written

+// agreement of TransGaming Inc. Without such an agreement, no rights or licenses, express

+// or implied, including but not limited to any patent rights, are granted to you.

+//

+

+// Shader.h: Defines the abstract Shader class and its concrete derived

+// classes VertexShader and FragmentShader. Implements GL shader objects and

+// related functionality. [OpenGL ES 2.0.24] section 2.10 page 24 and section

+// 3.8 page 84.

+

+#ifndef LIBGLESV2_SHADER_H_

+#define LIBGLESV2_SHADER_H_

+

+#include "ResourceManager.h"

+

+#include "compiler/TranslatorASM.h"

+

+#define GL_APICALL

+#include <GLES2/gl2.h>

+

+#include <list>

+#include <vector>

+

+namespace sh

+{

+	class OutputASM;

+}

+

+namespace gl

+{

+struct Varying

+{

+    Varying(GLenum type, const std::string &name, int arraySize, int reg = -1, int col = -1)

+        : type(type), name(name), arraySize(arraySize), reg(reg), col(col)

+    {

+    }

+

+	bool isArray() const

+	{

+		return arraySize >= 1;

+	}

+

+	int size() const   // Unify with gl::Uniform?

+	{

+		return arraySize > 0 ? arraySize : 1;

+	}

+

+    GLenum type;

+    std::string name;

+    int arraySize;

+

+    int reg;    // First varying register, assigned during link

+    int col;    // First register element, assigned during link

+};

+

+typedef std::list<Varying> VaryingList;

+

+class Shader

+{

+    friend class Program;

+	friend class sh::OutputASM;

+

+public:

+    Shader(ResourceManager *manager, GLuint handle);

+

+    virtual ~Shader();

+

+    virtual GLenum getType() = 0;

+    GLuint getHandle() const;

+

+    void deleteSource();

+    void setSource(GLsizei count, const char **string, const GLint *length);

+    int getInfoLogLength() const;

+    void getInfoLog(GLsizei bufSize, GLsizei *length, char *infoLog);

+    int getSourceLength() const;

+    void getSource(GLsizei bufSize, GLsizei *length, char *source);

+

+    virtual void compile() = 0;

+    bool isCompiled();

+    

+	virtual sw::Shader *getShader() const = 0;

+	virtual sw::PixelShader *getPixelShader() const;

+	virtual sw::VertexShader *getVertexShader() const;

+

+    void addRef();

+    void release();

+    unsigned int getRefCount() const;

+    bool isFlaggedForDeletion() const;

+    void flagForDeletion();

+

+    static void releaseCompiler();

+

+protected:

+	void clear();

+	void initializeCompiler();

+

+    static GLenum parseType(const std::string &type);

+    static bool compareVarying(const Varying &x, const Varying &y);

+

+	char *mSource;

+	char *mInfoLog;

+

+    VaryingList varyings;

+	sh::ActiveUniforms activeUniforms;

+	sh::ActiveAttributes activeAttributes;

+

+private:

+	const GLuint mHandle;

+    unsigned int mRefCount;     // Number of program objects this shader is attached to

+    bool mDeleteStatus;         // Flag to indicate that the shader can be deleted when no longer in use

+

+	ResourceManager *mResourceManager;

+

+	static void *mFragmentCompiler;

+	static void *mVertexCompiler;

+};

+

+class VertexShader : public Shader

+{

+    friend class Program;

+

+public:

+    VertexShader(ResourceManager *manager, GLuint handle);

+

+    ~VertexShader();

+

+    virtual GLenum getType();

+    virtual void compile();

+    int getSemanticIndex(const std::string &attributeName);

+

+	virtual sw::Shader *getShader() const;

+	virtual sw::VertexShader *getVertexShader() const;

+

+private:

+	sw::VertexShader *vertexShader;

+};

+

+class FragmentShader : public Shader

+{

+public:

+    FragmentShader(ResourceManager *manager, GLuint handle);

+

+    ~FragmentShader();

+

+    virtual GLenum getType();

+    virtual void compile();

+

+	virtual sw::Shader *getShader() const;

+	virtual sw::PixelShader *getPixelShader() const;

+

+private:

+	sw::PixelShader *pixelShader;

+};

+}

+

+#endif   // LIBGLESV2_SHADER_H_

diff --git a/src/GLES2/libGLESv2/Texture.cpp b/src/GLES2/libGLESv2/Texture.cpp
new file mode 100644
index 0000000..dedc7cb
--- /dev/null
+++ b/src/GLES2/libGLESv2/Texture.cpp
@@ -0,0 +1,1113 @@
+// SwiftShader Software Renderer

+//

+// Copyright(c) 2005-2013 TransGaming Inc.

+//

+// All rights reserved. No part of this software may be copied, distributed, transmitted,

+// transcribed, stored in a retrieval system, translated into any human or computer

+// language by any means, or disclosed to third parties without the explicit written

+// agreement of TransGaming Inc. Without such an agreement, no rights or licenses, express

+// or implied, including but not limited to any patent rights, are granted to you.

+//

+

+// Texture.cpp: Implements the Texture class and its derived classes

+// Texture2D and TextureCubeMap. Implements GL texture objects and related

+// functionality. [OpenGL ES 2.0.24] section 3.7 page 63.

+

+#include "Texture.h"

+

+#include "main.h"

+#include "mathutil.h"

+#include "Framebuffer.h"

+#include "Device.hpp"

+#include "libEGL/Display.h"

+#include "common/debug.h"

+

+#include <algorithm>

+

+namespace gl

+{

+

+Texture::Texture(GLuint id) : RefCountObject(id)

+{

+    mMinFilter = GL_NEAREST_MIPMAP_LINEAR;

+    mMagFilter = GL_LINEAR;

+    mWrapS = GL_REPEAT;

+    mWrapT = GL_REPEAT;

+	mMaxAnisotropy = 1.0f;

+

+	resource = new sw::Resource(0);

+}

+

+Texture::~Texture()

+{

+	resource->destruct();

+}

+

+sw::Resource *Texture::getResource() const

+{

+	return resource;

+}

+

+bool Texture::isTexture2D()

+{

+	return false;

+}

+

+bool Texture::isTextureCubeMap()

+{

+	return false;

+}

+

+// Returns true on successful filter state update (valid enum parameter)

+bool Texture::setMinFilter(GLenum filter)

+{

+    switch(filter)

+    {

+    case GL_NEAREST:

+    case GL_LINEAR:

+    case GL_NEAREST_MIPMAP_NEAREST:

+    case GL_LINEAR_MIPMAP_NEAREST:

+    case GL_NEAREST_MIPMAP_LINEAR:

+    case GL_LINEAR_MIPMAP_LINEAR:

+        mMinFilter = filter;

+        return true;

+    default:

+        return false;

+    }

+}

+

+// Returns true on successful filter state update (valid enum parameter)

+bool Texture::setMagFilter(GLenum filter)

+{

+    switch(filter)

+    {

+    case GL_NEAREST:

+    case GL_LINEAR:

+        mMagFilter = filter;

+        return true;

+    default:

+        return false;

+    }

+}

+

+// Returns true on successful wrap state update (valid enum parameter)

+bool Texture::setWrapS(GLenum wrap)

+{

+    switch(wrap)

+    {

+    case GL_REPEAT:

+    case GL_CLAMP_TO_EDGE:

+    case GL_MIRRORED_REPEAT:

+        mWrapS = wrap;

+        return true;

+    default:

+        return false;

+    }

+}

+

+// Returns true on successful wrap state update (valid enum parameter)

+bool Texture::setWrapT(GLenum wrap)

+{

+    switch(wrap)

+    {

+    case GL_REPEAT:

+    case GL_CLAMP_TO_EDGE:

+    case GL_MIRRORED_REPEAT:

+         mWrapT = wrap;

+         return true;

+    default:

+        return false;

+    }

+}

+

+// Returns true on successful max anisotropy update (valid anisotropy value)

+bool Texture::setMaxAnisotropy(float textureMaxAnisotropy)

+{

+    textureMaxAnisotropy = std::min(textureMaxAnisotropy, MAX_TEXTURE_MAX_ANISOTROPY);

+

+    if(textureMaxAnisotropy < 1.0f)

+    {

+        return false;

+    }

+    

+	if(mMaxAnisotropy != textureMaxAnisotropy)

+    {

+        mMaxAnisotropy = textureMaxAnisotropy;

+    }

+

+    return true;

+}

+

+GLenum Texture::getMinFilter() const

+{

+    return mMinFilter;

+}

+

+GLenum Texture::getMagFilter() const

+{

+    return mMagFilter;

+}

+

+GLenum Texture::getWrapS() const

+{

+    return mWrapS;

+}

+

+GLenum Texture::getWrapT() const

+{

+    return mWrapT;

+}

+

+GLfloat Texture::getMaxAnisotropy() const

+{

+    return mMaxAnisotropy;

+}

+

+void Texture::setImage(GLenum format, GLenum type, GLint unpackAlignment, const void *pixels, Image *image)

+{

+    if(pixels && image)

+    {

+		image->loadImageData(0, 0, image->getWidth(), image->getHeight(), format, type, unpackAlignment, pixels);

+    }

+}

+

+void Texture::setCompressedImage(GLsizei imageSize, const void *pixels, Image *image)

+{

+    if(pixels && image)

+    {

+		image->loadCompressedData(0, 0, image->getWidth(), image->getHeight(), imageSize, pixels);

+    }

+}

+

+void Texture::subImage(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels, Image *image)

+{

+	if(!image)

+	{

+		return error(GL_INVALID_OPERATION);

+	}

+

+    if(width + xoffset > image->getWidth() || height + yoffset > image->getHeight())

+    {

+        return error(GL_INVALID_VALUE);

+    }

+

+    if(IsCompressed(image->getFormat()))

+    {

+        return error(GL_INVALID_OPERATION);

+    }

+

+    if(format != image->getFormat())

+    {

+        return error(GL_INVALID_OPERATION);

+    }

+

+    if(pixels)

+    {

+        image->loadImageData(xoffset, yoffset, width, height, format, type, unpackAlignment, pixels);

+    }

+}

+

+void Texture::subImageCompressed(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *pixels, Image *image)

+{

+	if(!image)

+	{

+		return error(GL_INVALID_OPERATION);

+	}

+

+    if(width + xoffset > image->getWidth() || height + yoffset > image->getHeight())

+    {

+        return error(GL_INVALID_VALUE);

+    }

+

+    if(format != image->getFormat())

+    {

+        return error(GL_INVALID_OPERATION);

+    }

+

+    if(pixels)

+    {

+		image->loadCompressedData(xoffset, yoffset, width, height, imageSize, pixels);

+    }

+}

+

+bool Texture::copy(Image *source, const sw::Rect &sourceRect, GLenum destFormat, GLint xoffset, GLint yoffset, Image *dest)

+{

+    Device *device = getDevice();

+	

+    sw::Rect destRect = {xoffset, yoffset, xoffset + (sourceRect.x1 - sourceRect.x0), yoffset + (sourceRect.y1 - sourceRect.y0)};

+    bool success = device->stretchRect(source, &sourceRect, dest, &destRect, false);

+

+    if(!success)

+    {

+        return error(GL_OUT_OF_MEMORY, false);

+    }

+

+    return true;

+}

+

+bool Texture::isMipmapFiltered() const

+{

+	switch(mMinFilter)

+    {

+    case GL_NEAREST:

+    case GL_LINEAR:

+        return false;

+    case GL_NEAREST_MIPMAP_NEAREST:

+    case GL_LINEAR_MIPMAP_NEAREST:

+    case GL_NEAREST_MIPMAP_LINEAR:

+    case GL_LINEAR_MIPMAP_LINEAR:

+        return true;

+    default: UNREACHABLE();

+    }

+

+	return false;

+}

+

+Texture2D::Texture2D(GLuint id) : Texture(id)

+{

+	for(int i = 0; i < MIPMAP_LEVELS; i++)

+	{

+		image[i] = 0;

+	}

+

+    mSurface = NULL;

+

+	mColorbufferProxy = NULL;

+	mProxyRefs = 0;

+}

+

+Texture2D::~Texture2D()

+{

+	resource->lock(sw::DESTRUCT);

+

+	for(int i = 0; i < MIPMAP_LEVELS; i++)

+	{

+		if(image[i])

+		{

+			image[i]->release();

+			image[i] = 0;

+		}

+	}

+

+	resource->unlock();

+

+    if(mSurface)

+    {

+        mSurface->setBoundTexture(NULL);

+        mSurface = NULL;

+    }

+

+	mColorbufferProxy = NULL;

+}

+

+bool Texture2D::isTexture2D()

+{

+	return true;

+}

+

+// We need to maintain a count of references to renderbuffers acting as 

+// proxies for this texture, so that we do not attempt to use a pointer 

+// to a renderbuffer proxy which has been deleted.

+void Texture2D::addProxyRef(const Renderbuffer *proxy)

+{

+    mProxyRefs++;

+}

+

+void Texture2D::releaseProxy(const Renderbuffer *proxy)

+{

+    if(mProxyRefs > 0)

+	{

+        mProxyRefs--;

+	}

+

+    if(mProxyRefs == 0)

+	{

+		mColorbufferProxy = NULL;

+	}

+}

+

+GLenum Texture2D::getTarget() const

+{

+    return GL_TEXTURE_2D;

+}

+

+GLsizei Texture2D::getWidth(GLenum target, GLint level) const

+{

+	ASSERT(target == GL_TEXTURE_2D);

+    return image[level] ? image[level]->getWidth() : 0;

+}

+

+GLsizei Texture2D::getHeight(GLenum target, GLint level) const

+{

+	ASSERT(target == GL_TEXTURE_2D);

+    return image[level] ? image[level]->getHeight() : 0;

+}

+

+GLenum Texture2D::getFormat(GLenum target, GLint level) const

+{

+	ASSERT(target == GL_TEXTURE_2D);

+    return image[level] ? image[level]->getFormat() : 0;

+}

+

+GLenum Texture2D::getType(GLenum target, GLint level) const

+{

+	ASSERT(target == GL_TEXTURE_2D);

+    return image[level] ? image[level]->getType() : 0;

+}

+

+sw::Format Texture2D::getInternalFormat(GLenum target, GLint level) const

+{

+	ASSERT(target == GL_TEXTURE_2D);

+	return image[level] ? image[level]->getInternalFormat() : sw::FORMAT_NULL;

+}

+

+int Texture2D::getLevelCount() const

+{

+	ASSERT(isSamplerComplete());

+	int levels = 0;

+

+	while(levels < MIPMAP_LEVELS && image[levels])

+	{

+		levels++;

+	}

+

+	return levels;

+}

+

+void Texture2D::setImage(GLint level, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels)

+{

+	if(image[level])

+	{

+		image[level]->release();

+	}

+

+	image[level] = new Image(resource, width, height, format, type);

+

+	if(!image[level])

+	{

+		return error(GL_OUT_OF_MEMORY);

+	}

+

+	image[level]->addRef();

+

+    Texture::setImage(format, type, unpackAlignment, pixels, image[level]);

+}

+

+void Texture2D::bindTexImage(egl::Surface *surface)

+{

+    GLenum format;

+

+    switch(surface->getInternalFormat())

+    {

+    case sw::FORMAT_A8R8G8B8:

+        format = GL_RGBA;

+        break;

+    case sw::FORMAT_X8R8G8B8:

+        format = GL_RGB;

+        break;

+    default:

+        UNIMPLEMENTED();

+        return;

+    }

+

+	for(int level = 0; level < MIPMAP_LEVELS; level++)

+	{

+		if(image[level])

+		{

+			image[level]->release();

+			image[level] = 0;

+		}

+	}

+

+	image[0] = surface->getRenderTarget();

+

+    mSurface = surface;

+    mSurface->setBoundTexture(this);

+}

+

+void Texture2D::releaseTexImage()

+{

+    for(int level = 0; level < MIPMAP_LEVELS; level++)

+	{

+		if(image[level])

+		{

+			image[level]->release();

+			image[level] = 0;

+		}

+	}

+}

+

+void Texture2D::setCompressedImage(GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei imageSize, const void *pixels)

+{

+	if(image[level])

+	{

+		image[level]->release();

+	}

+

+	image[level] = new Image(resource, width, height, format, GL_UNSIGNED_BYTE);

+

+	if(!image[level])

+	{

+		return error(GL_OUT_OF_MEMORY);

+	}

+

+	image[level]->addRef();

+

+    Texture::setCompressedImage(imageSize, pixels, image[level]);

+}

+

+void Texture2D::subImage(GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels)

+{

+	Texture::subImage(xoffset, yoffset, width, height, format, type, unpackAlignment, pixels, image[level]);

+}

+

+void Texture2D::subImageCompressed(GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *pixels)

+{

+    Texture::subImageCompressed(xoffset, yoffset, width, height, format, imageSize, pixels, image[level]);

+}

+

+void Texture2D::copyImage(GLint level, GLenum format, GLint x, GLint y, GLsizei width, GLsizei height, Framebuffer *source)

+{

+    Image *renderTarget = source->getRenderTarget();

+

+    if(!renderTarget)

+    {

+        ERR("Failed to retrieve the render target.");

+        return error(GL_OUT_OF_MEMORY);

+    }

+

+	if(image[level])

+	{

+		image[level]->release();

+	}

+

+	image[level] = new Image(resource, width, height, format, GL_UNSIGNED_BYTE);

+

+	if(!image[level])

+	{

+		return error(GL_OUT_OF_MEMORY);

+	}

+

+	image[level]->addRef();

+

+    if(width != 0 && height != 0)

+    {

+		sw::Rect sourceRect = {x, y, x + width, y + height};

+		sourceRect.clip(0, 0, source->getColorbuffer()->getWidth(), source->getColorbuffer()->getHeight());

+

+        copy(renderTarget, sourceRect, format, 0, 0, image[level]);

+    }

+

+	renderTarget->release();

+}

+

+void Texture2D::copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height, Framebuffer *source)

+{

+	if(!image[level])

+	{

+		return error(GL_INVALID_OPERATION);

+	}

+

+    if(xoffset + width > image[level]->getWidth() || yoffset + height > image[level]->getHeight())

+    {

+        return error(GL_INVALID_VALUE);

+    }

+

+    Image *renderTarget = source->getRenderTarget();

+

+    if(!renderTarget)

+    {

+        ERR("Failed to retrieve the render target.");

+        return error(GL_OUT_OF_MEMORY);

+    }

+

+	sw::Rect sourceRect = {x, y, x + width, y + height};

+	sourceRect.clip(0, 0, source->getColorbuffer()->getWidth(), source->getColorbuffer()->getHeight());

+

+	copy(renderTarget, sourceRect, image[level]->getFormat(), xoffset, yoffset, image[level]);

+

+	renderTarget->release();

+}

+

+// Tests for 2D texture sampling completeness. [OpenGL ES 2.0.24] section 3.8.2 page 85.

+bool Texture2D::isSamplerComplete() const

+{

+	if(!image[0])

+	{

+		return false;

+	}

+

+    GLsizei width = image[0]->getWidth();

+    GLsizei height = image[0]->getHeight();

+

+    if(width <= 0 || height <= 0)

+    {

+        return false;

+    }

+

+    if(isMipmapFiltered())

+    {

+        if(!isMipmapComplete())

+        {

+            return false;

+        }

+    }

+

+    return true;

+}

+

+// Tests for 2D texture (mipmap) completeness. [OpenGL ES 2.0.24] section 3.7.10 page 81.

+bool Texture2D::isMipmapComplete() const

+{

+    GLsizei width = image[0]->getWidth();

+    GLsizei height = image[0]->getHeight();

+

+    int q = log2(std::max(width, height));

+

+    for(int level = 1; level <= q; level++)

+    {

+		if(!image[level])

+		{

+			return false;

+		}

+

+        if(image[level]->getFormat() != image[0]->getFormat())

+        {

+            return false;

+        }

+

+        if(image[level]->getType() != image[0]->getType())

+        {

+            return false;

+        }

+

+        if(image[level]->getWidth() != std::max(1, width >> level))

+        {

+            return false;

+        }

+

+        if(image[level]->getHeight() != std::max(1, height >> level))

+        {

+            return false;

+        }

+    }

+

+    return true;

+}

+

+bool Texture2D::isCompressed(GLenum target, GLint level) const

+{

+    return IsCompressed(getFormat(target, level));

+}

+

+bool Texture2D::isDepth(GLenum target, GLint level) const

+{

+    return IsDepthTexture(getFormat(target, level));

+}

+

+void Texture2D::generateMipmaps()

+{

+	if(!image[0])

+	{

+		return;   // FIXME: error?

+	}

+

+    unsigned int q = log2(std::max(image[0]->getWidth(), image[0]->getHeight()));

+    

+	for(unsigned int i = 1; i <= q; i++)

+    {

+		if(image[i])

+		{

+			image[i]->release();

+		}

+

+		image[i] = new Image(resource, std::max(image[0]->getWidth() >> i, 1), std::max(image[0]->getHeight() >> i, 1), image[0]->getFormat(), image[0]->getType());

+

+		if(!image[i])

+		{

+			return error(GL_OUT_OF_MEMORY);

+		}

+

+		image[i]->addRef();

+

+		getDevice()->stretchRect(image[i - 1], 0, image[i], 0, true);

+    }

+}

+

+Image *Texture2D::getImage(unsigned int level)

+{

+	return image[level];

+}

+

+Renderbuffer *Texture2D::getRenderbuffer(GLenum target)

+{

+    if(target != GL_TEXTURE_2D)

+    {

+        return error(GL_INVALID_OPERATION, (Renderbuffer *)NULL);

+    }

+

+    if(mColorbufferProxy == NULL)

+    {

+        mColorbufferProxy = new Renderbuffer(id(), new RenderbufferTexture2D(this));

+    }

+

+    return mColorbufferProxy;

+}

+

+Image *Texture2D::getRenderTarget(GLenum target)

+{

+    ASSERT(target == GL_TEXTURE_2D);

+

+	if(image[0])

+	{

+		image[0]->addRef();

+	}

+

+	return image[0];

+}

+

+TextureCubeMap::TextureCubeMap(GLuint id) : Texture(id)

+{

+	for(int f = 0; f < 6; f++)

+	{

+		for(int i = 0; i < MIPMAP_LEVELS; i++)

+		{

+			image[f][i] = 0;

+		}

+	}

+

+	for(int f = 0; f < 6; f++)

+    {

+        mFaceProxies[f] = NULL;

+        mFaceProxyRefs[f] = 0;

+	}

+}

+

+TextureCubeMap::~TextureCubeMap()

+{

+	resource->lock(sw::DESTRUCT);

+

+	for(int f = 0; f < 6; f++)

+	{

+		for(int i = 0; i < MIPMAP_LEVELS; i++)

+		{

+			if(image[f][i])

+			{

+				image[f][i]->release();

+				image[f][i] = 0;

+			}

+		}

+	}

+

+	resource->unlock();

+

+    for(int i = 0; i < 6; i++)

+    {

+        mFaceProxies[i] = NULL;

+    }

+}

+

+bool TextureCubeMap::isTextureCubeMap()

+{

+	return true;

+}

+

+// We need to maintain a count of references to renderbuffers acting as 

+// proxies for this texture, so that the texture is not deleted while 

+// proxy references still exist. If the reference count drops to zero,

+// we set our proxy pointer NULL, so that a new attempt at referencing

+// will cause recreation.

+void TextureCubeMap::addProxyRef(const Renderbuffer *proxy)

+{

+    for(int f = 0; f < 6; f++)

+    {

+        if(mFaceProxies[f] == proxy)

+        {

+			mFaceProxyRefs[f]++;

+		}

+	}

+}

+

+void TextureCubeMap::releaseProxy(const Renderbuffer *proxy)

+{

+    for(int f = 0; f < 6; f++)

+    {

+        if(mFaceProxies[f] == proxy)

+        {

+            if(mFaceProxyRefs[f] > 0)

+			{

+				mFaceProxyRefs[f]--;

+			}

+

+            if(mFaceProxyRefs[f] == 0)

+			{

+				mFaceProxies[f] = NULL;

+			}

+		}

+    }

+}

+

+GLenum TextureCubeMap::getTarget() const

+{

+    return GL_TEXTURE_CUBE_MAP;

+}

+

+GLsizei TextureCubeMap::getWidth(GLenum target, GLint level) const

+{

+	int face = CubeFaceIndex(target);

+    return image[face][level] ? image[face][level]->getWidth() : 0;

+}

+

+GLsizei TextureCubeMap::getHeight(GLenum target, GLint level) const

+{

+	int face = CubeFaceIndex(target);

+    return image[face][level] ? image[face][level]->getHeight() : 0;

+}

+

+GLenum TextureCubeMap::getFormat(GLenum target, GLint level) const

+{

+	int face = CubeFaceIndex(target);

+    return image[face][level] ? image[face][level]->getFormat() : 0;

+}

+

+GLenum TextureCubeMap::getType(GLenum target, GLint level) const

+{

+	int face = CubeFaceIndex(target);

+    return image[face][level] ? image[face][level]->getType() : 0;

+}

+

+sw::Format TextureCubeMap::getInternalFormat(GLenum target, GLint level) const

+{

+	int face = CubeFaceIndex(target);

+    return image[face][level] ? image[face][level]->getInternalFormat() : sw::FORMAT_NULL;

+}

+

+int TextureCubeMap::getLevelCount() const

+{

+	ASSERT(isSamplerComplete());

+	int levels = 0;

+

+	while(levels < MIPMAP_LEVELS && image[0][levels])

+	{

+		levels++;

+	}

+

+	return levels;

+}

+

+void TextureCubeMap::setCompressedImage(GLenum target, GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei imageSize, const void *pixels)

+{

+	int face = CubeFaceIndex(target);

+

+	if(image[face][level])

+	{

+		image[face][level]->release();

+	}

+

+	image[face][level] = new Image(resource, width, height, format, GL_UNSIGNED_BYTE);

+

+	if(!image[face][level])

+	{

+		return error(GL_OUT_OF_MEMORY);

+	}

+

+	image[face][level]->addRef();

+

+    Texture::setCompressedImage(imageSize, pixels, image[face][level]);

+}

+

+void TextureCubeMap::subImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels)

+{

+    Texture::subImage(xoffset, yoffset, width, height, format, type, unpackAlignment, pixels, image[CubeFaceIndex(target)][level]);

+}

+

+void TextureCubeMap::subImageCompressed(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *pixels)

+{

+    Texture::subImageCompressed(xoffset, yoffset, width, height, format, imageSize, pixels, image[CubeFaceIndex(target)][level]);

+}

+

+// Tests for cube map sampling completeness. [OpenGL ES 2.0.24] section 3.8.2 page 86.

+bool TextureCubeMap::isSamplerComplete() const

+{

+	for(int face = 0; face < 6; face++)

+    {

+		if(!image[face][0])

+		{

+			return false;

+		}

+	}

+

+    int size = image[0][0]->getWidth();

+

+    if(size <= 0)

+    {

+        return false;

+    }

+

+    if(!isMipmapFiltered())

+    {

+        if(!isCubeComplete())

+        {

+            return false;

+        }

+    }

+    else

+    {

+        if(!isMipmapCubeComplete())   // Also tests for isCubeComplete()

+        {

+            return false;

+        }

+    }

+

+    return true;

+}

+

+// Tests for cube texture completeness. [OpenGL ES 2.0.24] section 3.7.10 page 81.

+bool TextureCubeMap::isCubeComplete() const

+{

+    if(image[0][0]->getWidth() <= 0 || image[0][0]->getHeight() != image[0][0]->getWidth())

+    {

+        return false;

+    }

+

+    for(unsigned int face = 1; face < 6; face++)

+    {

+        if(image[face][0]->getWidth()  != image[0][0]->getWidth() ||

+           image[face][0]->getWidth()  != image[0][0]->getHeight() ||

+           image[face][0]->getFormat() != image[0][0]->getFormat() ||

+           image[face][0]->getType()   != image[0][0]->getType())

+        {

+            return false;

+        }

+    }

+

+    return true;

+}

+

+bool TextureCubeMap::isMipmapCubeComplete() const

+{

+    if(!isCubeComplete())

+    {

+        return false;

+    }

+

+    GLsizei size = image[0][0]->getWidth();

+    int q = log2(size);

+

+    for(int face = 0; face < 6; face++)

+    {

+        for(int level = 1; level <= q; level++)

+        {

+			if(!image[face][level])

+			{

+				return false;

+			}

+

+            if(image[face][level]->getFormat() != image[0][0]->getFormat())

+            {

+                return false;

+            }

+

+            if(image[face][level]->getType() != image[0][0]->getType())

+            {

+                return false;

+            }

+

+            if(image[face][level]->getWidth() != std::max(1, size >> level))

+            {

+                return false;

+            }

+        }

+    }

+

+    return true;

+}

+

+bool TextureCubeMap::isCompressed(GLenum target, GLint level) const

+{

+    return IsCompressed(getFormat(target, level));

+}

+

+bool TextureCubeMap::isDepth(GLenum target, GLint level) const

+{

+    return IsDepthTexture(getFormat(target, level));

+}

+

+void TextureCubeMap::setImage(GLenum target, GLint level, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels)

+{

+	int face = CubeFaceIndex(target);

+

+	if(image[face][level])

+	{

+		image[face][level]->release();

+	}

+

+	image[face][level] = new Image(resource, width, height, format, GL_UNSIGNED_BYTE);

+

+	if(!image[face][level])

+	{

+		return error(GL_OUT_OF_MEMORY);

+	}

+

+	image[face][level]->addRef();

+

+    Texture::setImage(format, type, unpackAlignment, pixels, image[face][level]);

+}

+

+void TextureCubeMap::copyImage(GLenum target, GLint level, GLenum format, GLint x, GLint y, GLsizei width, GLsizei height, Framebuffer *source)

+{

+	Image *renderTarget = source->getRenderTarget();

+

+    if(!renderTarget)

+    {

+        ERR("Failed to retrieve the render target.");

+        return error(GL_OUT_OF_MEMORY);

+    }

+

+	int face = CubeFaceIndex(target);

+

+	if(image[face][level])

+	{

+		image[face][level]->release();

+	}

+

+	image[face][level] = new Image(resource, width, height, format, GL_UNSIGNED_BYTE);

+

+	if(!image[face][level])

+	{

+		return error(GL_OUT_OF_MEMORY);

+	}

+

+	image[face][level]->addRef();

+

+    if(width != 0 && height != 0)

+    {

+		sw::Rect sourceRect = {x, y, x + width, y + height};

+		sourceRect.clip(0, 0, source->getColorbuffer()->getWidth(), source->getColorbuffer()->getHeight());

+        

+        copy(renderTarget, sourceRect, format, 0, 0, image[face][level]);

+    }

+

+	renderTarget->release();

+}

+

+Image *TextureCubeMap::getImage(int face, unsigned int level)

+{

+	return image[face][level];

+}

+

+Image *TextureCubeMap::getImage(GLenum face, unsigned int level)

+{

+    return image[CubeFaceIndex(face)][level];

+}

+

+void TextureCubeMap::copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height, Framebuffer *source)

+{

+	int face = CubeFaceIndex(target);

+

+	if(!image[face][level])

+	{

+		return error(GL_INVALID_OPERATION);

+	}

+

+    GLsizei size = image[face][level]->getWidth();

+

+    if(xoffset + width > size || yoffset + height > size)

+    {

+        return error(GL_INVALID_VALUE);

+    }

+

+    Image *renderTarget = source->getRenderTarget();

+

+    if(!renderTarget)

+    {

+        ERR("Failed to retrieve the render target.");

+        return error(GL_OUT_OF_MEMORY);

+    }

+

+	sw::Rect sourceRect = {x, y, x + width, y + height};

+	sourceRect.clip(0, 0, source->getColorbuffer()->getWidth(), source->getColorbuffer()->getHeight());

+

+	copy(renderTarget, sourceRect, image[face][level]->getFormat(), xoffset, yoffset, image[face][level]);

+

+	renderTarget->release();

+}

+

+void TextureCubeMap::generateMipmaps()

+{

+    if(!isCubeComplete())

+    {

+        return error(GL_INVALID_OPERATION);

+    }

+

+    unsigned int q = log2(image[0][0]->getWidth());

+

+	for(unsigned int f = 0; f < 6; f++)

+    {

+		for(unsigned int i = 1; i <= q; i++)

+		{

+			if(image[f][i])

+			{

+				image[f][i]->release();

+			}

+

+			image[f][i] = new Image(resource, std::max(image[0][0]->getWidth() >> i, 1), std::max(image[0][0]->getHeight() >> i, 1), image[0][0]->getFormat(), image[0][0]->getType());

+

+			if(!image[f][i])

+			{

+				return error(GL_OUT_OF_MEMORY);

+			}

+

+			image[f][i]->addRef();

+

+			getDevice()->stretchRect(image[f][i - 1], 0, image[f][i], 0, true);

+		}

+	}

+}

+

+Renderbuffer *TextureCubeMap::getRenderbuffer(GLenum target)

+{

+    if(!IsCubemapTextureTarget(target))

+    {

+        return error(GL_INVALID_OPERATION, (Renderbuffer *)NULL);

+    }

+

+    int face = CubeFaceIndex(target);

+

+    if(mFaceProxies[face] == NULL)

+    {

+        mFaceProxies[face] = new Renderbuffer(id(), new RenderbufferTextureCubeMap(this, target));

+    }

+

+    return mFaceProxies[face];

+}

+

+Image *TextureCubeMap::getRenderTarget(GLenum target)

+{

+    ASSERT(IsCubemapTextureTarget(target));

+    

+	int face = CubeFaceIndex(target);

+

+	if(image[face][0])

+	{

+		image[face][0]->addRef();

+	}

+

+	return image[face][0];

+}

+

+}

+

+// Exported functions for use by EGL

+extern "C"

+{

+	gl::Image *createBackBuffer(int width, int height, const egl::Config *config)

+	{

+		if(config)

+		{

+			return new gl::Image(0, width, height, config->mAlphaSize ? GL_RGBA : GL_RGB, GL_UNSIGNED_BYTE);

+		}

+

+		return 0;

+	}

+}
\ No newline at end of file
diff --git a/src/GLES2/libGLESv2/Texture.h b/src/GLES2/libGLESv2/Texture.h
new file mode 100644
index 0000000..d62a537
--- /dev/null
+++ b/src/GLES2/libGLESv2/Texture.h
@@ -0,0 +1,229 @@
+// SwiftShader Software Renderer

+//

+// Copyright(c) 2005-2013 TransGaming Inc.

+//

+// All rights reserved. No part of this software may be copied, distributed, transmitted,

+// transcribed, stored in a retrieval system, translated into any human or computer

+// language by any means, or disclosed to third parties without the explicit written

+// agreement of TransGaming Inc. Without such an agreement, no rights or licenses, express

+// or implied, including but not limited to any patent rights, are granted to you.

+//

+

+// Texture.h: Defines the abstract Texture class and its concrete derived

+// classes Texture2D and TextureCubeMap. Implements GL texture objects and

+// related functionality. [OpenGL ES 2.0.24] section 3.7 page 63.

+

+#ifndef LIBGLESV2_TEXTURE_H_

+#define LIBGLESV2_TEXTURE_H_

+

+#include "Renderbuffer.h"

+#include "RefCountObject.h"

+#include "utilities.h"

+#include "common/debug.h"

+

+#define GL_APICALL

+#include <GLES2/gl2.h>

+

+#include <vector>

+

+namespace egl

+{

+class Surface;

+class Config;

+}

+

+namespace gl

+{

+class Framebuffer;

+

+enum

+{

+	IMPLEMENTATION_MAX_TEXTURE_LEVELS = MIPMAP_LEVELS,

+    IMPLEMENTATION_MAX_TEXTURE_SIZE = 1 << (MIPMAP_LEVELS - 1),

+    IMPLEMENTATION_MAX_CUBE_MAP_TEXTURE_SIZE = 1 << (MIPMAP_LEVELS - 1),

+	IMPLEMENTATION_MAX_RENDERBUFFER_SIZE = OUTLINE_RESOLUTION,

+	IMPLEMENTATION_MAX_SAMPLES = 4

+};

+

+class Texture : public RefCountObject

+{

+public:

+    explicit Texture(GLuint id);

+

+    virtual ~Texture();

+

+	sw::Resource *getResource() const;

+	virtual bool isTexture2D();

+	virtual bool isTextureCubeMap();

+

+	virtual void addProxyRef(const Renderbuffer *proxy) = 0;

+    virtual void releaseProxy(const Renderbuffer *proxy) = 0;

+

+    virtual GLenum getTarget() const = 0;

+

+    bool setMinFilter(GLenum filter);

+    bool setMagFilter(GLenum filter);

+    bool setWrapS(GLenum wrap);

+    bool setWrapT(GLenum wrap);

+	bool setMaxAnisotropy(GLfloat textureMaxAnisotropy);

+

+    GLenum getMinFilter() const;

+    GLenum getMagFilter() const;

+    GLenum getWrapS() const;

+    GLenum getWrapT() const;

+	GLfloat getMaxAnisotropy() const;

+

+    virtual GLsizei getWidth(GLenum target, GLint level) const = 0;

+    virtual GLsizei getHeight(GLenum target, GLint level) const = 0;

+    virtual GLenum getFormat(GLenum target, GLint level) const = 0;

+    virtual GLenum getType(GLenum target, GLint level) const = 0;

+    virtual sw::Format getInternalFormat(GLenum target, GLint level) const = 0;

+	virtual int getLevelCount() const = 0;

+

+    virtual bool isSamplerComplete() const = 0;

+    virtual bool isCompressed(GLenum target, GLint level) const = 0;

+	virtual bool isDepth(GLenum target, GLint level) const = 0;

+

+    virtual Renderbuffer *getRenderbuffer(GLenum target) = 0;

+	virtual Image *getRenderTarget(GLenum target) = 0;

+

+    virtual void generateMipmaps() = 0;

+    virtual void copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height, Framebuffer *source) = 0;

+

+    static const GLuint INCOMPLETE_TEXTURE_ID = static_cast<GLuint>(-1);   // Every texture takes an id at creation time. The value is arbitrary because it is never registered with the resource manager.

+

+protected:

+    void setImage(GLenum format, GLenum type, GLint unpackAlignment, const void *pixels, Image *image);

+    void subImage(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels, Image *image);

+    void setCompressedImage(GLsizei imageSize, const void *pixels, Image *image);

+    void subImageCompressed(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *pixels, Image *image);

+

+	bool copy(Image *source, const sw::Rect &sourceRect, GLenum destFormat, GLint xoffset, GLint yoffset, Image *dest);

+

+	bool isMipmapFiltered() const;

+

+    GLenum mMinFilter;

+    GLenum mMagFilter;

+    GLenum mWrapS;

+    GLenum mWrapT;

+	GLfloat mMaxAnisotropy;

+

+	sw::Resource *resource;

+};

+

+class Texture2D : public Texture

+{

+public:

+    explicit Texture2D(GLuint id);

+

+    ~Texture2D();

+

+	virtual bool isTexture2D();

+

+	void addProxyRef(const Renderbuffer *proxy);

+    void releaseProxy(const Renderbuffer *proxy);

+

+    virtual GLenum getTarget() const;

+

+    virtual GLsizei getWidth(GLenum target, GLint level) const;

+    virtual GLsizei getHeight(GLenum target, GLint level) const;

+    virtual GLenum getFormat(GLenum target, GLint level) const;

+    virtual GLenum getType(GLenum target, GLint level) const;

+    virtual sw::Format getInternalFormat(GLenum target, GLint level) const;

+	virtual int getLevelCount() const;

+

+    void setImage(GLint level, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels);

+    void setCompressedImage(GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei imageSize, const void *pixels);

+    void subImage(GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels);

+    void subImageCompressed(GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *pixels);

+    void copyImage(GLint level, GLenum format, GLint x, GLint y, GLsizei width, GLsizei height, Framebuffer *source);

+    void copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height, Framebuffer *source);

+

+    virtual bool isSamplerComplete() const;

+    virtual bool isCompressed(GLenum target, GLint level) const;

+	virtual bool isDepth(GLenum target, GLint level) const;

+    virtual void bindTexImage(egl::Surface *surface);

+    virtual void releaseTexImage();

+

+    virtual void generateMipmaps();

+

+	virtual Image *getImage(unsigned int level);

+    virtual Renderbuffer *getRenderbuffer(GLenum target);

+	Image *getRenderTarget(GLenum target);

+

+private:

+	bool isMipmapComplete() const;

+

+	Image *image[IMPLEMENTATION_MAX_TEXTURE_LEVELS];

+    

+    egl::Surface *mSurface;

+    

+	// A specific internal reference count is kept for colorbuffer proxy references,

+    // because, as the renderbuffer acting as proxy will maintain a binding pointer

+    // back to this texture, there would be a circular reference if we used a binding

+    // pointer here. This reference count will cause the pointer to be set to NULL if

+    // the count drops to zero, but will not cause deletion of the Renderbuffer.

+    Renderbuffer *mColorbufferProxy;

+    unsigned int mProxyRefs;

+};

+

+class TextureCubeMap : public Texture

+{

+public:

+    explicit TextureCubeMap(GLuint id);

+

+    ~TextureCubeMap();

+

+	virtual bool isTextureCubeMap();

+

+	void addProxyRef(const Renderbuffer *proxy);

+    void releaseProxy(const Renderbuffer *proxy);

+

+    virtual GLenum getTarget() const;

+    

+    virtual GLsizei getWidth(GLenum target, GLint level) const;

+    virtual GLsizei getHeight(GLenum target, GLint level) const;

+    virtual GLenum getFormat(GLenum target, GLint level) const;

+    virtual GLenum getType(GLenum target, GLint level) const;

+    virtual sw::Format getInternalFormat(GLenum target, GLint level) const;

+	virtual int getLevelCount() const;

+

+	void setImage(GLenum target, GLint level, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels);

+    void setCompressedImage(GLenum target, GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei imageSize, const void *pixels);

+

+    void subImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels);

+    void subImageCompressed(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *pixels);

+    void copyImage(GLenum target, GLint level, GLenum format, GLint x, GLint y, GLsizei width, GLsizei height, Framebuffer *source);

+    virtual void copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height, Framebuffer *source);

+

+    virtual bool isSamplerComplete() const;

+    virtual bool isCompressed(GLenum target, GLint level) const;

+	virtual bool isDepth(GLenum target, GLint level) const;

+

+    virtual void generateMipmaps();

+

+    virtual Renderbuffer *getRenderbuffer(GLenum target);

+	virtual Image *getRenderTarget(GLenum target);

+

+	Image *getImage(int face, unsigned int level);

+

+private:

+	bool isCubeComplete() const;

+	bool isMipmapCubeComplete() const;

+

+    // face is one of the GL_TEXTURE_CUBE_MAP_* enumerants. Returns NULL on failure.

+    Image *getImage(GLenum face, unsigned int level);

+

+    Image *image[6][IMPLEMENTATION_MAX_TEXTURE_LEVELS];

+	

+	// A specific internal reference count is kept for colorbuffer proxy references,

+    // because, as the renderbuffer acting as proxy will maintain a binding pointer

+    // back to this texture, there would be a circular reference if we used a binding

+    // pointer here. This reference count will cause the pointer to be set to NULL if

+    // the count drops to zero, but will not cause deletion of the Renderbuffer.

+    Renderbuffer *mFaceProxies[6];

+	unsigned int mFaceProxyRefs[6];

+};

+}

+

+#endif   // LIBGLESV2_TEXTURE_H_

diff --git a/src/GLES2/libGLESv2/VertexDataManager.cpp b/src/GLES2/libGLESv2/VertexDataManager.cpp
new file mode 100644
index 0000000..ff88a6d
--- /dev/null
+++ b/src/GLES2/libGLESv2/VertexDataManager.cpp
@@ -0,0 +1,334 @@
+// SwiftShader Software Renderer

+//

+// Copyright(c) 2005-2012 TransGaming Inc.

+//

+// All rights reserved. No part of this software may be copied, distributed, transmitted,

+// transcribed, stored in a retrieval system, translated into any human or computer

+// language by any means, or disclosed to third parties without the explicit written

+// agreement of TransGaming Inc. Without such an agreement, no rights or licenses, express

+// or implied, including but not limited to any patent rights, are granted to you.

+//

+

+// VertexDataManager.h: Defines the VertexDataManager, a class that

+// runs the Buffer translation process.

+

+#include "VertexDataManager.h"

+

+#include "Buffer.h"

+#include "Program.h"

+#include "IndexDataManager.h"

+#include "common/debug.h"

+

+namespace

+{

+    enum {INITIAL_STREAM_BUFFER_SIZE = 1024 * 1024};

+}

+

+namespace gl

+{

+

+VertexDataManager::VertexDataManager(Context *context) : mContext(context)

+{

+    for(int i = 0; i < MAX_VERTEX_ATTRIBS; i++)

+    {

+        mDirtyCurrentValue[i] = true;

+        mCurrentValueBuffer[i] = NULL;

+    }

+

+    mStreamingBuffer = new StreamingVertexBuffer(INITIAL_STREAM_BUFFER_SIZE);

+

+    if(!mStreamingBuffer)

+    {

+        ERR("Failed to allocate the streaming vertex buffer.");

+    }

+}

+

+VertexDataManager::~VertexDataManager()

+{

+    delete mStreamingBuffer;

+

+    for(int i = 0; i < MAX_VERTEX_ATTRIBS; i++)

+    {

+        delete mCurrentValueBuffer[i];

+    }

+}

+

+unsigned int VertexDataManager::writeAttributeData(StreamingVertexBuffer *vertexBuffer, GLint start, GLsizei count, const VertexAttribute &attribute)

+{

+    Buffer *buffer = attribute.mBoundBuffer.get();

+

+    int inputStride = attribute.stride();

+    int elementSize = attribute.typeSize();

+    unsigned int streamOffset = 0;

+

+    char *output = NULL;

+    

+    if(vertexBuffer)

+    {

+        output = (char*)vertexBuffer->map(attribute, attribute.typeSize() * count, &streamOffset);

+    }

+

+    if(output == NULL)

+    {

+        ERR("Failed to map vertex buffer.");

+        return -1;

+    }

+

+    const char *input = NULL;

+

+    if(buffer)

+    {

+        int offset = attribute.mOffset;

+

+        input = static_cast<const char*>(buffer->data()) + offset;

+    }

+    else

+    {

+        input = static_cast<const char*>(attribute.mPointer);

+    }

+

+    input += inputStride * start;

+

+    if(inputStride == elementSize)

+    {

+        memcpy(output, input, count * inputStride);

+    }

+    else

+    {

+		for(int i = 0; i < count; i++)

+		{

+			memcpy(output, input, elementSize);

+			output += elementSize;

+			input += inputStride;

+		}

+    }

+

+    vertexBuffer->unmap();

+

+    return streamOffset;

+}

+

+GLenum VertexDataManager::prepareVertexData(GLint start, GLsizei count, TranslatedAttribute *translated)

+{

+    if(!mStreamingBuffer)

+    {

+        return GL_OUT_OF_MEMORY;

+    }

+

+    const VertexAttributeArray &attribs = mContext->getVertexAttributes();

+    Program *program = mContext->getCurrentProgram();

+

+    // Determine the required storage size per used buffer

+    for(int i = 0; i < MAX_VERTEX_ATTRIBS; i++)

+    {

+        if(program->getAttributeStream(i) != -1 && attribs[i].mArrayEnabled)

+        {

+            if(!attribs[i].mBoundBuffer)

+            {

+                mStreamingBuffer->addRequiredSpace(attribs[i].typeSize() * count);

+            }

+        }

+    }

+

+    mStreamingBuffer->reserveRequiredSpace();

+    

+    // Perform the vertex data translations

+    for(int i = 0; i < MAX_VERTEX_ATTRIBS; i++)

+    {

+        if(program->getAttributeStream(i) != -1)

+        {

+            if(attribs[i].mArrayEnabled)

+            {

+                Buffer *buffer = attribs[i].mBoundBuffer.get();

+

+                if(!buffer && attribs[i].mPointer == NULL)

+                {

+                    // This is an application error that would normally result in a crash, but we catch it and return an error

+                    ERR("An enabled vertex array has no buffer and no pointer.");

+                    return GL_INVALID_OPERATION;

+                }

+

+                sw::Resource *staticBuffer = buffer ? buffer->getResource() : NULL;

+

+                if(staticBuffer)

+                {

+					translated[i].vertexBuffer = staticBuffer;

+					translated[i].offset = start * attribs[i].stride() + attribs[i].mOffset;

+					translated[i].stride = attribs[i].stride();

+                }

+                else

+                {

+                    unsigned int streamOffset = writeAttributeData(mStreamingBuffer, start, count, attribs[i]);

+

+					if(streamOffset == -1)

+					{

+						return GL_OUT_OF_MEMORY;

+					}

+

+					translated[i].vertexBuffer = mStreamingBuffer->getResource();

+					translated[i].offset = streamOffset;

+					translated[i].stride = attribs[i].typeSize();

+                }

+

+				switch(attribs[i].mType)

+				{

+				case GL_BYTE:           translated[i].type = sw::STREAMTYPE_SBYTE;  break;

+				case GL_UNSIGNED_BYTE:  translated[i].type = sw::STREAMTYPE_BYTE;   break;

+				case GL_SHORT:          translated[i].type = sw::STREAMTYPE_SHORT;  break;

+				case GL_UNSIGNED_SHORT: translated[i].type = sw::STREAMTYPE_USHORT; break;

+				case GL_FIXED:          translated[i].type = sw::STREAMTYPE_FIXED;  break;

+				case GL_FLOAT:          translated[i].type = sw::STREAMTYPE_FLOAT;  break;

+				default: UNREACHABLE(); translated[i].type = sw::STREAMTYPE_FLOAT;  break;

+				}

+

+				translated[i].count = attribs[i].mSize;

+				translated[i].normalized = attribs[i].mNormalized;

+            }

+            else

+            {

+                if(mDirtyCurrentValue[i])

+                {

+                    delete mCurrentValueBuffer[i];

+                    mCurrentValueBuffer[i] = new ConstantVertexBuffer(attribs[i].mCurrentValue[0], attribs[i].mCurrentValue[1], attribs[i].mCurrentValue[2], attribs[i].mCurrentValue[3]);

+                    mDirtyCurrentValue[i] = false;

+                }

+

+                translated[i].vertexBuffer = mCurrentValueBuffer[i]->getResource();

+

+                translated[i].type = sw::STREAMTYPE_FLOAT;

+				translated[i].count = 4;

+                translated[i].stride = 0;

+                translated[i].offset = 0;

+            }

+        }

+    }

+

+    return GL_NO_ERROR;

+}

+

+VertexBuffer::VertexBuffer(unsigned int size) : mVertexBuffer(NULL)

+{

+    if(size > 0)

+    {

+        mVertexBuffer = new sw::Resource(size + 1024);

+        

+        if(!mVertexBuffer)

+        {

+            ERR("Out of memory allocating a vertex buffer of size %lu.", size);

+        }

+    }

+}

+

+VertexBuffer::~VertexBuffer()

+{

+    if(mVertexBuffer)

+    {

+        mVertexBuffer->destruct();

+    }

+}

+

+void VertexBuffer::unmap()

+{

+    if(mVertexBuffer)

+    {

+		mVertexBuffer->unlock();

+    }

+}

+

+sw::Resource *VertexBuffer::getResource() const

+{

+    return mVertexBuffer;

+}

+

+ConstantVertexBuffer::ConstantVertexBuffer(float x, float y, float z, float w) : VertexBuffer(4 * sizeof(float))

+{

+    if(mVertexBuffer)

+    {

+		float *vector = (float*)mVertexBuffer->lock(sw::PUBLIC);

+     

+        vector[0] = x;

+        vector[1] = y;

+        vector[2] = z;

+        vector[3] = w;

+

+        mVertexBuffer->unlock();

+    }

+}

+

+ConstantVertexBuffer::~ConstantVertexBuffer()

+{

+}

+

+StreamingVertexBuffer::StreamingVertexBuffer(unsigned int size) : VertexBuffer(size)

+{

+    mBufferSize = size;

+    mWritePosition = 0;

+    mRequiredSpace = 0;

+}

+

+StreamingVertexBuffer::~StreamingVertexBuffer()

+{

+}

+

+void StreamingVertexBuffer::addRequiredSpace(unsigned int requiredSpace)

+{

+    mRequiredSpace += requiredSpace;

+}

+

+void *StreamingVertexBuffer::map(const VertexAttribute &attribute, unsigned int requiredSpace, unsigned int *offset)

+{

+    void *mapPtr = NULL;

+

+    if(mVertexBuffer)

+    {

+		mapPtr = (char*)mVertexBuffer->lock(sw::PUBLIC) + mWritePosition;

+        

+        if(!mapPtr)

+        {

+            ERR("Lock failed");

+            return NULL;

+        }

+

+        *offset = mWritePosition;

+        mWritePosition += requiredSpace;

+    }

+

+    return mapPtr;

+}

+

+void StreamingVertexBuffer::reserveRequiredSpace()

+{

+    if(mRequiredSpace > mBufferSize)

+    {

+        if(mVertexBuffer)

+        {

+            mVertexBuffer->destruct();

+            mVertexBuffer = 0;

+        }

+

+        mBufferSize = std::max(mRequiredSpace, 3 * mBufferSize / 2);   // 1.5 x mBufferSize is arbitrary and should be checked to see we don't have too many reallocations.

+

+		mVertexBuffer = new sw::Resource(mBufferSize);

+    

+        if(!mVertexBuffer)

+        {

+            ERR("Out of memory allocating a vertex buffer of size %lu.", mBufferSize);

+        }

+

+        mWritePosition = 0;

+    }

+    else if(mWritePosition + mRequiredSpace > mBufferSize)   // Recycle

+    {

+        if(mVertexBuffer)

+        {

+            mVertexBuffer->destruct();

+			mVertexBuffer = new sw::Resource(mBufferSize);

+        }

+

+        mWritePosition = 0;

+    }

+

+    mRequiredSpace = 0;

+}

+

+}

diff --git a/src/GLES2/libGLESv2/VertexDataManager.h b/src/GLES2/libGLESv2/VertexDataManager.h
new file mode 100644
index 0000000..8800219
--- /dev/null
+++ b/src/GLES2/libGLESv2/VertexDataManager.h
@@ -0,0 +1,99 @@
+// SwiftShader Software Renderer

+//

+// Copyright(c) 2005-2012 TransGaming Inc.

+//

+// All rights reserved. No part of this software may be copied, distributed, transmitted,

+// transcribed, stored in a retrieval system, translated into any human or computer

+// language by any means, or disclosed to third parties without the explicit written

+// agreement of TransGaming Inc. Without such an agreement, no rights or licenses, express

+// or implied, including but not limited to any patent rights, are granted to you.

+//

+

+// VertexDataManager.h: Defines the VertexDataManager, a class that

+// runs the Buffer translation process.

+

+#ifndef LIBGLESV2_VERTEXDATAMANAGER_H_

+#define LIBGLESV2_VERTEXDATAMANAGER_H_

+

+#include "Context.h"

+#include "Device.hpp"

+

+#define GL_APICALL

+#include <GLES2/gl2.h>

+

+namespace gl

+{

+

+struct TranslatedAttribute

+{

+    sw::StreamType type;

+	int count;

+	bool normalized;

+

+    unsigned int offset;

+    unsigned int stride;   // 0 means not to advance the read pointer at all

+

+    sw::Resource *vertexBuffer;

+};

+

+class VertexBuffer

+{

+  public:

+    VertexBuffer(unsigned int size);

+    virtual ~VertexBuffer();

+

+    void unmap();

+

+    sw::Resource *getResource() const;

+

+  protected:

+    sw::Resource *mVertexBuffer;

+};

+

+class ConstantVertexBuffer : public VertexBuffer

+{

+  public:

+    ConstantVertexBuffer(float x, float y, float z, float w);

+    ~ConstantVertexBuffer();

+};

+

+class StreamingVertexBuffer : public VertexBuffer

+{

+  public:

+    StreamingVertexBuffer(unsigned int size);

+    ~StreamingVertexBuffer();

+

+    void *map(const VertexAttribute &attribute, unsigned int requiredSpace, unsigned int *streamOffset);

+    void reserveRequiredSpace();

+    void addRequiredSpace(unsigned int requiredSpace);

+

+  protected:

+    unsigned int mBufferSize;

+    unsigned int mWritePosition;

+    unsigned int mRequiredSpace;

+};

+

+class VertexDataManager

+{

+  public:

+    VertexDataManager(Context *context);

+    virtual ~VertexDataManager();

+

+    void dirtyCurrentValue(int index) { mDirtyCurrentValue[index] = true; }

+

+    GLenum prepareVertexData(GLint start, GLsizei count, TranslatedAttribute *outAttribs);

+

+  private:

+    unsigned int writeAttributeData(StreamingVertexBuffer *vertexBuffer, GLint start, GLsizei count, const VertexAttribute &attribute);

+

+    Context *const mContext;

+

+    StreamingVertexBuffer *mStreamingBuffer;

+

+    bool mDirtyCurrentValue[MAX_VERTEX_ATTRIBS];

+    ConstantVertexBuffer *mCurrentValueBuffer[MAX_VERTEX_ATTRIBS];

+};

+

+}

+

+#endif   // LIBGLESV2_VERTEXDATAMANAGER_H_

diff --git a/src/GLES2/libGLESv2/exports.map b/src/GLES2/libGLESv2/exports.map
new file mode 100644
index 0000000..7d08ed0
--- /dev/null
+++ b/src/GLES2/libGLESv2/exports.map
@@ -0,0 +1,186 @@
+{
+global:
+    glActiveTexture;
+    glAttachShader;
+    glBindAttribLocation;
+    glBindBuffer;
+    glBindFramebuffer;
+    glBindRenderbuffer;
+    glBindTexture;
+    glBlendColor;
+    glBlendEquation;
+    glBlendEquationSeparate;
+    glBlendFunc;
+    glBlendFuncSeparate;
+    glBufferData;
+    glBufferSubData;
+    glCheckFramebufferStatus;
+    glClear;
+    glClearColor;
+    glClearDepthf;
+    glClearStencil;
+    glColorMask;
+    glCompileShader;
+    glCompressedTexImage2D;
+    glCompressedTexSubImage2D;
+    glCopyTexImage2D;
+    glCopyTexSubImage2D;
+    glCreateProgram;
+    glCreateShader;
+    glCullFace;
+    glDeleteBuffers;
+    glDeleteFramebuffers;
+    glDeleteProgram;
+    glDeleteRenderbuffers;
+    glDeleteShader;
+    glDeleteTextures;
+    glDepthFunc;
+    glDepthMask;
+    glDepthRangef;
+    glDetachShader;
+    glDisable;
+    glDisableVertexAttribArray;
+    glDrawArrays;
+    glDrawElements;
+    glEnable;
+    glEnableVertexAttribArray;
+    glFinish;
+    glFlush;
+    glFramebufferRenderbuffer;
+    glFramebufferTexture2D;
+    glFrontFace;
+    glGenBuffers;
+    glGenFramebuffers;
+    glGenRenderbuffers;
+    glGenTextures;
+    glGenerateMipmap;
+    glGetActiveAttrib;
+    glGetActiveUniform;
+    glGetAttachedShaders;
+    glGetAttribLocation;
+    glGetBooleanv;
+    glGetBufferParameteriv;
+    glGetError;
+    glGetFloatv;
+    glGetFramebufferAttachmentParameteriv;
+    glGetIntegerv;
+    glGetProgramInfoLog;
+    glGetProgramiv;
+    glGetRenderbufferParameteriv;
+    glGetShaderInfoLog;
+    glGetShaderPrecisionFormat;
+    glGetShaderSource;
+    glGetShaderiv;
+    glGetString;
+    glGetTexParameterfv;
+    glGetTexParameteriv;
+    glGetUniformLocation;
+    glGetUniformfv;
+    glGetUniformiv;
+    glGetVertexAttribPointerv;
+    glGetVertexAttribfv;
+    glGetVertexAttribiv;
+    glHint;
+    glIsBuffer;
+    glIsEnabled;
+    glIsFramebuffer;
+    glIsProgram;
+    glIsRenderbuffer;
+    glIsShader;
+    glIsTexture;
+    glLineWidth;
+    glLinkProgram;
+    glPixelStorei;
+    glPolygonOffset;
+    glReadPixels;
+    glReleaseShaderCompiler;
+    glRenderbufferStorage;
+    glSampleCoverage;
+    glScissor;
+    glShaderBinary;
+    glShaderSource;
+    glStencilFunc;
+    glStencilFuncSeparate;
+    glStencilMask;
+    glStencilMaskSeparate;
+    glStencilOp;
+    glStencilOpSeparate;
+    glTexImage2D;
+    glTexParameterf;
+    glTexParameterfv;
+    glTexParameteri;
+    glTexParameteriv;
+    glTexSubImage2D;
+    glUniform1f;
+    glUniform1fv;
+    glUniform1i;
+    glUniform1iv;
+    glUniform2f;
+    glUniform2fv;
+    glUniform2i;
+    glUniform2iv;
+    glUniform3f;
+    glUniform3fv;
+    glUniform3i;
+    glUniform3iv;
+    glUniform4f;
+    glUniform4fv;
+    glUniform4i;
+    glUniform4iv;
+    glUniformMatrix2fv;
+    glUniformMatrix3fv;
+    glUniformMatrix4fv;
+    glUseProgram;
+    glValidateProgram;
+    glVertexAttrib1f;
+    glVertexAttrib1fv;
+    glVertexAttrib2f;
+    glVertexAttrib2fv;
+    glVertexAttrib3f;
+    glVertexAttrib3fv;
+    glVertexAttrib4f;
+    glVertexAttrib4fv;
+    glVertexAttribPointer;
+    glViewport;
+
+    # Extensions
+    glTexImage3DOES;
+    glBlitFramebufferANGLE;
+    glRenderbufferStorageMultisampleANGLE;
+    glDeleteFencesNV;
+    glFinishFenceNV;
+    glGenFencesNV;
+    glGetFenceivNV;
+    glIsFenceNV;
+    glSetFenceNV;
+    glTestFenceNV;
+    glGetGraphicsResetStatusEXT;
+    glReadnPixelsEXT;
+    glGetnUniformfvEXT;
+    glGetnUniformivEXT;
+    glGenQueriesEXT;
+    glDeleteQueriesEXT;
+    glIsQueryEXT;
+    glBeginQueryEXT;
+    glEndQueryEXT;
+    glGetQueryivEXT;
+    glGetQueryObjectuivEXT;
+
+    # EGL dependencies
+    glCreateContext;
+    glDestroyContext;
+    glMakeCurrent;
+    glGetCurrentContext;
+    glGetProcAddress;
+    glBindTexImage;
+
+    createFrameBuffer;
+    createBackBuffer;
+    createDevice;
+
+    Register;
+
+local:
+    *;
+};
+
diff --git a/src/GLES2/libGLESv2/libGLESv2.cbp b/src/GLES2/libGLESv2/libGLESv2.cbp
new file mode 100644
index 0000000..8f5d976
--- /dev/null
+++ b/src/GLES2/libGLESv2/libGLESv2.cbp
@@ -0,0 +1,369 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
+<CodeBlocks_project_file>
+	<FileVersion major="1" minor="6" />
+	<Project>
+		<Option title="libGLESv2" />
+		<Option pch_mode="2" />
+		<Option compiler="gcc" />
+		<Build>
+			<Target title="Debug x86">
+				<Option output="./../../bin/x86/Debug/libGLESv2.so" prefix_auto="0" extension_auto="0" />
+				<Option object_output="obj/x86/Debug/" />
+				<Option type="3" />
+				<Option compiler="gcc" />
+				<Option createDefFile="1" />
+				<Option createStaticLib="1" />
+				<Compiler>
+					<Add option="-g" />
+					<Add option="-m32" />
+				</Compiler>
+				<Linker>
+					<Add option="-m32" />
+					<Add library="./../../LLVM/bin/x86/Debug/libLLVM.a" />
+				</Linker>
+			</Target>
+			<Target title="Release x86">
+				<Option output="./../../bin/x86/Release/libGLESv2.so" prefix_auto="0" extension_auto="0" />
+				<Option object_output="obj/x86/Release/" />
+				<Option type="3" />
+				<Option compiler="gcc" />
+				<Option createDefFile="1" />
+				<Option createStaticLib="1" />
+				<Compiler>
+					<Add option="-march=i686" />
+					<Add option="-fomit-frame-pointer" />
+					<Add option="-O2" />
+					<Add option="-m32" />
+					<Add option="-ffunction-sections" />
+					<Add option="-fdata-sections" />
+					<Add option="-DNDEBUG" />
+					<Add option="-DANGLE_DISABLE_TRACE" />
+				</Compiler>
+				<Linker>
+					<Add option="-s" />
+					<Add option="-m32" />
+					<Add option="-Wl,--gc-sections" />
+					<Add library="./../../LLVM/bin/x86/Release/libLLVM.a" />
+				</Linker>
+			</Target>
+			<Target title="Debug x64">
+				<Option output="./../../bin/x64/Debug/libGLESv2.so" prefix_auto="0" extension_auto="0" />
+				<Option object_output="obj/x64/Debug/" />
+				<Option type="3" />
+				<Option compiler="gcc" />
+				<Option createDefFile="1" />
+				<Option createStaticLib="1" />
+				<Compiler>
+					<Add option="-g" />
+					<Add option="-m64" />
+					<Add option="-fPIC" />
+				</Compiler>
+				<Linker>
+					<Add option="-m64" />
+					<Add library="./../../LLVM/bin/x64/Debug/libLLVM.a" />
+				</Linker>
+			</Target>
+			<Target title="Release x64">
+				<Option output="./../../bin/x64/Release/libGLESv2.so" prefix_auto="0" extension_auto="0" />
+				<Option object_output="obj/x64/Release/" />
+				<Option type="3" />
+				<Option compiler="gcc" />
+				<Option createDefFile="1" />
+				<Option createStaticLib="1" />
+				<Compiler>
+					<Add option="-march=core2" />
+					<Add option="-fomit-frame-pointer" />
+					<Add option="-O2" />
+					<Add option="-m64" />
+					<Add option="-fPIC" />
+					<Add option="-ffunction-sections" />
+					<Add option="-fdata-sections" />
+					<Add option="-DNDEBUG" />
+					<Add option="-DANGLE_DISABLE_TRACE" />
+				</Compiler>
+				<Linker>
+					<Add option="-s" />
+					<Add option="-m64" />
+					<Add option="-Wl,--gc-sections" />
+					<Add library="./../../LLVM/bin/x64/Release/libLLVM.a" />
+				</Linker>
+			</Target>
+		</Build>
+		<Compiler>
+			<Add option="-Wall" />
+			<Add option="-fexceptions" />
+			<Add option="-fno-operator-names" />
+			<Add option="-ffriend-injection" />
+			<Add option="-msse2" />
+			<Add option="-D__STDC_LIMIT_MACROS" />
+			<Add option="-D__STDC_CONSTANT_MACROS" />
+			<Add directory="./../" />
+			<Add directory="./../include/" />
+			<Add directory="./../../" />
+			<Add directory="./../../LLVM/include-linux/" />
+			<Add directory="./../../LLVM/include/" />
+			<Add directory="./../../LLVM/lib/Target/X86" />
+			<Add directory="./../../Renderer/" />
+			<Add directory="./../../Common/" />
+			<Add directory="./../../Shader/" />
+			<Add directory="./../../Main/" />
+		</Compiler>
+		<Linker>
+			<Add option="-Wl,--version-script=./exports.map" />
+			<Add library="pthread" />
+			<Add library="X11" />
+			<Add library="Xext" />
+		</Linker>
+		<Unit filename="./../../Common/CPUID.cpp" />
+		<Unit filename="./../../Common/CPUID.hpp" />
+		<Unit filename="./../../Common/Configurator.cpp" />
+		<Unit filename="./../../Common/Configurator.hpp" />
+		<Unit filename="./../../Common/Debug.cpp" />
+		<Unit filename="./../../Common/Debug.hpp" />
+		<Unit filename="./../../Common/ExceptionHandling.hpp" />
+		<Unit filename="./../../Common/Half.cpp" />
+		<Unit filename="./../../Common/Half.hpp" />
+		<Unit filename="./../../Common/Math.cpp" />
+		<Unit filename="./../../Common/Math.hpp" />
+		<Unit filename="./../../Common/Memory.cpp" />
+		<Unit filename="./../../Common/Memory.hpp" />
+		<Unit filename="./../../Common/MetaMacro.hpp" />
+		<Unit filename="./../../Common/MutexLock.hpp" />
+		<Unit filename="./../../Common/Resource.cpp" />
+		<Unit filename="./../../Common/Resource.hpp" />
+		<Unit filename="./../../Common/Socket.cpp" />
+		<Unit filename="./../../Common/Socket.hpp" />
+		<Unit filename="./../../Common/Thread.cpp" />
+		<Unit filename="./../../Common/Thread.hpp" />
+		<Unit filename="./../../Common/Timer.cpp" />
+		<Unit filename="./../../Common/Timer.hpp" />
+		<Unit filename="./../../Common/Types.hpp" />
+		<Unit filename="./../../Common/Version.h" />
+		<Unit filename="./../common/debug.cpp" />
+		<Unit filename="./../common/debug.h" />
+		<Unit filename="../compiler/BaseTypes.h" />
+		<Unit filename="../compiler/Common.h" />
+		<Unit filename="../compiler/Compiler.cpp" />
+		<Unit filename="../compiler/ConstantUnion.h" />
+		<Unit filename="../compiler/DetectRecursion.cpp" />
+		<Unit filename="../compiler/DetectRecursion.h" />
+		<Unit filename="../compiler/Diagnostics.cpp" />
+		<Unit filename="../compiler/Diagnostics.h" />
+		<Unit filename="../compiler/DirectiveHandler.cpp" />
+		<Unit filename="../compiler/DirectiveHandler.h" />
+		<Unit filename="../compiler/ExtensionBehavior.h" />
+		<Unit filename="../compiler/InfoSink.cpp" />
+		<Unit filename="../compiler/InfoSink.h" />
+		<Unit filename="../compiler/Initialize.cpp" />
+		<Unit filename="../compiler/Initialize.h" />
+		<Unit filename="../compiler/InitializeDll.cpp" />
+		<Unit filename="../compiler/InitializeDll.h" />
+		<Unit filename="../compiler/InitializeGlobals.h" />
+		<Unit filename="../compiler/InitializeParseContext.cpp" />
+		<Unit filename="../compiler/InitializeParseContext.h" />
+		<Unit filename="../compiler/IntermTraverse.cpp" />
+		<Unit filename="../compiler/Intermediate.cpp" />
+		<Unit filename="../compiler/MMap.h" />
+		<Unit filename="../compiler/OutputASM.cpp" />
+		<Unit filename="../compiler/OutputASM.h" />
+		<Unit filename="../compiler/ParseHelper.cpp" />
+		<Unit filename="../compiler/ParseHelper.h" />
+		<Unit filename="../compiler/PoolAlloc.cpp" />
+		<Unit filename="../compiler/PoolAlloc.h" />
+		<Unit filename="../compiler/Pragma.h" />
+		<Unit filename="../compiler/QualifierAlive.cpp" />
+		<Unit filename="../compiler/QualifierAlive.h" />
+		<Unit filename="../compiler/RemoveTree.cpp" />
+		<Unit filename="../compiler/RemoveTree.h" />
+		<Unit filename="../compiler/ShHandle.h" />
+		<Unit filename="../compiler/ShaderLang.cpp" />
+		<Unit filename="../compiler/SymbolTable.cpp" />
+		<Unit filename="../compiler/SymbolTable.h" />
+		<Unit filename="../compiler/TranslatorASM.cpp" />
+		<Unit filename="../compiler/TranslatorASM.h" />
+		<Unit filename="../compiler/Types.h" />
+		<Unit filename="../compiler/ValidateLimitations.cpp" />
+		<Unit filename="../compiler/ValidateLimitations.h" />
+		<Unit filename="../compiler/VariableInfo.cpp" />
+		<Unit filename="../compiler/VariableInfo.h" />
+		<Unit filename="../compiler/debug.cpp" />
+		<Unit filename="../compiler/debug.h" />
+		<Unit filename="../compiler/glslang.h" />
+		<Unit filename="../compiler/glslang_lex.cpp" />
+		<Unit filename="../compiler/glslang_tab.cpp" />
+		<Unit filename="../compiler/glslang_tab.h" />
+		<Unit filename="../compiler/intermOut.cpp" />
+		<Unit filename="../compiler/intermediate.h" />
+		<Unit filename="../compiler/localintermediate.h" />
+		<Unit filename="../compiler/osinclude.h" />
+		<Unit filename="../compiler/ossource_posix.cpp" />
+		<Unit filename="../compiler/parseConst.cpp" />
+		<Unit filename="../compiler/preprocessor/Diagnostics.cpp" />
+		<Unit filename="../compiler/preprocessor/Diagnostics.h" />
+		<Unit filename="../compiler/preprocessor/DirectiveHandler.cpp" />
+		<Unit filename="../compiler/preprocessor/DirectiveHandler.h" />
+		<Unit filename="../compiler/preprocessor/DirectiveParser.cpp" />
+		<Unit filename="../compiler/preprocessor/DirectiveParser.h" />
+		<Unit filename="../compiler/preprocessor/ExpressionParser.cpp" />
+		<Unit filename="../compiler/preprocessor/ExpressionParser.h" />
+		<Unit filename="../compiler/preprocessor/Input.cpp" />
+		<Unit filename="../compiler/preprocessor/Input.h" />
+		<Unit filename="../compiler/preprocessor/Lexer.cpp" />
+		<Unit filename="../compiler/preprocessor/Lexer.h" />
+		<Unit filename="../compiler/preprocessor/Macro.cpp" />
+		<Unit filename="../compiler/preprocessor/Macro.h" />
+		<Unit filename="../compiler/preprocessor/MacroExpander.cpp" />
+		<Unit filename="../compiler/preprocessor/MacroExpander.h" />
+		<Unit filename="../compiler/preprocessor/Preprocessor.cpp" />
+		<Unit filename="../compiler/preprocessor/Preprocessor.h" />
+		<Unit filename="../compiler/preprocessor/SourceLocation.h" />
+		<Unit filename="../compiler/preprocessor/Token.cpp" />
+		<Unit filename="../compiler/preprocessor/Token.h" />
+		<Unit filename="../compiler/preprocessor/Tokenizer.cpp" />
+		<Unit filename="../compiler/preprocessor/Tokenizer.h" />
+		<Unit filename="../compiler/preprocessor/length_limits.h" />
+		<Unit filename="../compiler/preprocessor/numeric_lex.h" />
+		<Unit filename="../compiler/preprocessor/pp_utils.h" />
+		<Unit filename="../compiler/util.cpp" />
+		<Unit filename="../compiler/util.h" />
+		<Unit filename="./../include/EGL/egl.h" />
+		<Unit filename="./../include/EGL/eglext.h" />
+		<Unit filename="./../include/EGL/eglplatform.h" />
+		<Unit filename="./../include/GLES2/gl2.h" />
+		<Unit filename="./../include/GLES2/gl2ext.h" />
+		<Unit filename="./../include/GLES2/gl2platform.h" />
+		<Unit filename="./../include/GLSLANG/ShaderLang.h" />
+		<Unit filename="./../include/KHR/khrplatform.h" />
+		<Unit filename="./../libGLESv2/Buffer.cpp" />
+		<Unit filename="./../libGLESv2/Buffer.h" />
+		<Unit filename="./../libGLESv2/Context.cpp" />
+		<Unit filename="./../libGLESv2/Context.h" />
+		<Unit filename="./../libGLESv2/Device.cpp" />
+		<Unit filename="./../libGLESv2/Device.hpp" />
+		<Unit filename="./../libGLESv2/Fence.cpp" />
+		<Unit filename="./../libGLESv2/Fence.h" />
+		<Unit filename="./../libGLESv2/Framebuffer.cpp" />
+		<Unit filename="./../libGLESv2/Framebuffer.h" />
+		<Unit filename="./../libGLESv2/HandleAllocator.cpp" />
+		<Unit filename="./../libGLESv2/HandleAllocator.h" />
+		<Unit filename="./../libGLESv2/Image.cpp" />
+		<Unit filename="./../libGLESv2/Image.hpp" />
+		<Unit filename="./../libGLESv2/IndexDataManager.cpp" />
+		<Unit filename="./../libGLESv2/IndexDataManager.h" />
+		<Unit filename="./../libGLESv2/Program.cpp" />
+		<Unit filename="./../libGLESv2/Program.h" />
+		<Unit filename="./../libGLESv2/Query.cpp" />
+		<Unit filename="./../libGLESv2/Query.h" />
+		<Unit filename="./../libGLESv2/RefCountObject.cpp" />
+		<Unit filename="./../libGLESv2/RefCountObject.h" />
+		<Unit filename="./../libGLESv2/Renderbuffer.cpp" />
+		<Unit filename="./../libGLESv2/Renderbuffer.h" />
+		<Unit filename="./../libGLESv2/ResourceManager.cpp" />
+		<Unit filename="./../libGLESv2/ResourceManager.h" />
+		<Unit filename="./../libGLESv2/Shader.cpp" />
+		<Unit filename="./../libGLESv2/Shader.h" />
+		<Unit filename="./../libGLESv2/Texture.cpp" />
+		<Unit filename="./../libGLESv2/Texture.h" />
+		<Unit filename="./../libGLESv2/Unknown.hpp" />
+		<Unit filename="./../libGLESv2/VertexDataManager.cpp" />
+		<Unit filename="./../libGLESv2/VertexDataManager.h" />
+		<Unit filename="./../libGLESv2/libGLESv2.cpp" />
+		<Unit filename="./../libGLESv2/main.cpp" />
+		<Unit filename="./../libGLESv2/main.h" />
+		<Unit filename="./../libGLESv2/mathutil.h" />
+		<Unit filename="./../libGLESv2/resource.h" />
+		<Unit filename="./../libGLESv2/utilities.cpp" />
+		<Unit filename="./../libGLESv2/utilities.h" />
+		<Unit filename="./../libGLESv2/vertexconversion.h" />
+		<Unit filename="./../../Main/Config.cpp" />
+		<Unit filename="./../../Main/Config.hpp" />
+		<Unit filename="./../../Main/FrameBuffer.cpp" />
+		<Unit filename="./../../Main/FrameBuffer.hpp" />
+		<Unit filename="./../../Main/FrameBufferX11.cpp" />
+		<Unit filename="./../../Main/FrameBufferX11.hpp" />
+		<Unit filename="./../../Main/Logo.cpp" />
+		<Unit filename="./../../Main/Register.cpp" />
+		<Unit filename="./../../Main/Register.hpp" />
+		<Unit filename="./../../Main/SwiftConfig.cpp" />
+		<Unit filename="./../../Main/SwiftConfig.hpp" />
+		<Unit filename="./../../Main/crc.c">
+			<Option compilerVar="CC" />
+		</Unit>
+		<Unit filename="./../../Main/crc.h" />
+		<Unit filename="./../../Main/serialcommon.h" />
+		<Unit filename="./../../Main/serialvalid.cpp" />
+		<Unit filename="./../../Main/serialvalid.h" />
+		<Unit filename="./../../Reactor/MemoryManager.cpp" />
+		<Unit filename="./../../Reactor/MemoryManager.hpp" />
+		<Unit filename="./../../Reactor/Nucleus.cpp" />
+		<Unit filename="./../../Reactor/Nucleus.hpp" />
+		<Unit filename="./../../Reactor/Reactor.hpp" />
+		<Unit filename="./../../Reactor/x86.hpp" />
+		<Unit filename="./../../Renderer/Blitter.cpp" />
+		<Unit filename="./../../Renderer/Blitter.hpp" />
+		<Unit filename="./../../Renderer/Clipper.cpp" />
+		<Unit filename="./../../Renderer/Clipper.hpp" />
+		<Unit filename="./../../Renderer/Color.cpp" />
+		<Unit filename="./../../Renderer/Color.hpp" />
+		<Unit filename="./../../Renderer/Context.cpp" />
+		<Unit filename="./../../Renderer/Context.hpp" />
+		<Unit filename="./../../Renderer/LRUCache.hpp" />
+		<Unit filename="./../../Renderer/Matrix.cpp" />
+		<Unit filename="./../../Renderer/Matrix.hpp" />
+		<Unit filename="./../../Renderer/PixelProcessor.cpp" />
+		<Unit filename="./../../Renderer/PixelProcessor.hpp" />
+		<Unit filename="./../../Renderer/Plane.cpp" />
+		<Unit filename="./../../Renderer/Plane.hpp" />
+		<Unit filename="./../../Renderer/Point.cpp" />
+		<Unit filename="./../../Renderer/Point.hpp" />
+		<Unit filename="./../../Renderer/Polygon.hpp" />
+		<Unit filename="./../../Renderer/Primitive.hpp" />
+		<Unit filename="./../../Renderer/QuadRasterizer.cpp" />
+		<Unit filename="./../../Renderer/QuadRasterizer.hpp" />
+		<Unit filename="./../../Renderer/Rasterizer.cpp" />
+		<Unit filename="./../../Renderer/Rasterizer.hpp" />
+		<Unit filename="./../../Renderer/Renderer.cpp" />
+		<Unit filename="./../../Renderer/Renderer.hpp" />
+		<Unit filename="./../../Renderer/Sampler.cpp" />
+		<Unit filename="./../../Renderer/Sampler.hpp" />
+		<Unit filename="./../../Renderer/SetupProcessor.cpp" />
+		<Unit filename="./../../Renderer/SetupProcessor.hpp" />
+		<Unit filename="./../../Renderer/Stream.hpp" />
+		<Unit filename="./../../Renderer/Surface.cpp" />
+		<Unit filename="./../../Renderer/Surface.hpp" />
+		<Unit filename="./../../Renderer/TextureStage.cpp" />
+		<Unit filename="./../../Renderer/TextureStage.hpp" />
+		<Unit filename="./../../Renderer/Triangle.hpp" />
+		<Unit filename="./../../Renderer/Vector.cpp" />
+		<Unit filename="./../../Renderer/Vector.hpp" />
+		<Unit filename="./../../Renderer/Vertex.hpp" />
+		<Unit filename="./../../Renderer/VertexProcessor.cpp" />
+		<Unit filename="./../../Renderer/VertexProcessor.hpp" />
+		<Unit filename="./../../Shader/Constants.cpp" />
+		<Unit filename="./../../Shader/Constants.hpp" />
+		<Unit filename="./../../Shader/PixelRoutine.cpp" />
+		<Unit filename="./../../Shader/PixelRoutine.hpp" />
+		<Unit filename="./../../Shader/PixelShader.cpp" />
+		<Unit filename="./../../Shader/PixelShader.hpp" />
+		<Unit filename="./../../Shader/SamplerCore.cpp" />
+		<Unit filename="./../../Shader/SamplerCore.hpp" />
+		<Unit filename="./../../Shader/SetupRoutine.cpp" />
+		<Unit filename="./../../Shader/SetupRoutine.hpp" />
+		<Unit filename="./../../Shader/Shader.cpp" />
+		<Unit filename="./../../Shader/Shader.hpp" />
+		<Unit filename="./../../Shader/ShaderCore.cpp" />
+		<Unit filename="./../../Shader/ShaderCore.hpp" />
+		<Unit filename="./../../Shader/VertexPipeline.cpp" />
+		<Unit filename="./../../Shader/VertexPipeline.hpp" />
+		<Unit filename="./../../Shader/VertexProgram.cpp" />
+		<Unit filename="./../../Shader/VertexProgram.hpp" />
+		<Unit filename="./../../Shader/VertexRoutine.cpp" />
+		<Unit filename="./../../Shader/VertexRoutine.hpp" />
+		<Unit filename="./../../Shader/VertexShader.cpp" />
+		<Unit filename="./../../Shader/VertexShader.hpp" />
+		<Extensions>
+			<code_completion />
+			<debugger />
+		</Extensions>
+	</Project>
+</CodeBlocks_project_file>
diff --git a/src/GLES2/libGLESv2/libGLESv2.cpp b/src/GLES2/libGLESv2/libGLESv2.cpp
new file mode 100644
index 0000000..0448330
--- /dev/null
+++ b/src/GLES2/libGLESv2/libGLESv2.cpp
@@ -0,0 +1,6121 @@
+// SwiftShader Software Renderer

+//

+// Copyright(c) 2005-2013 TransGaming Inc.

+//

+// All rights reserved. No part of this software may be copied, distributed, transmitted,

+// transcribed, stored in a retrieval system, translated into any human or computer

+// language by any means, or disclosed to third parties without the explicit written

+// agreement of TransGaming Inc. Without such an agreement, no rights or licenses, express

+// or implied, including but not limited to any patent rights, are granted to you.

+//

+// libGLESv2.cpp: Implements the exported OpenGL ES 2.0 functions.

+

+#include "main.h"

+#include "mathutil.h"

+#include "utilities.h"

+#include "Buffer.h"

+#include "Context.h"

+#include "Fence.h"

+#include "Framebuffer.h"

+#include "Program.h"

+#include "Renderbuffer.h"

+#include "Shader.h"

+#include "Texture.h"

+#include "Query.h"

+#include "common/debug.h"

+#include "Common/Version.h"

+

+#define GL_APICALL

+#include <GLES2/gl2.h>

+#include <GLES2/gl2ext.h>

+

+#include <exception>

+#include <limits>

+

+static bool validImageSize(GLint level, GLsizei width, GLsizei height)

+{

+    if(level < 0 || level >= gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS || width < 0 || height < 0)

+    {

+        return false;

+    }

+

+    return true;

+}

+

+static bool validateSubImageParams(bool compressed, GLsizei width, GLsizei height, GLint xoffset, GLint yoffset, GLenum target, GLint level, GLenum format, gl::Texture *texture)

+{

+    if(!texture)

+    {

+        return error(GL_INVALID_OPERATION, false);

+    }

+

+    if(compressed != texture->isCompressed(target, level))

+    {

+        return error(GL_INVALID_OPERATION, false);

+    }

+

+    if(format != GL_NONE && format != texture->getFormat(target, level))

+    {

+        return error(GL_INVALID_OPERATION, false);

+    }

+

+    if(compressed)

+    {

+        if((width % 4 != 0 && width != texture->getWidth(target, 0)) || 

+           (height % 4 != 0 && height != texture->getHeight(target, 0)))

+        {

+            return error(GL_INVALID_OPERATION, false);

+        }

+    }

+

+    if(xoffset + width > texture->getWidth(target, level) ||

+       yoffset + height > texture->getHeight(target, level))

+    {

+        return error(GL_INVALID_VALUE, false);

+    }

+

+    return true;

+}

+

+// Check for combinations of format and type that are valid for ReadPixels

+static bool validReadFormatType(GLenum format, GLenum type)

+{

+    switch(format)

+    {

+    case GL_RGBA:

+        switch (type)

+        {

+        case GL_UNSIGNED_BYTE:

+            break;

+        default:

+            return false;

+        }

+        break;

+    case GL_BGRA_EXT:

+        switch (type)

+        {

+        case GL_UNSIGNED_BYTE:

+        case GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT:

+        case GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT:

+            break;

+        default:

+            return false;

+        }

+        break;

+    case gl::IMPLEMENTATION_COLOR_READ_FORMAT:

+        switch (type)

+        {

+        case gl::IMPLEMENTATION_COLOR_READ_TYPE:

+            break;

+        default:

+            return false;

+        }

+        break;

+    default:

+        return false;

+    }

+

+    return true;

+}

+

+extern "C"

+{

+

+void GL_APIENTRY glActiveTexture(GLenum texture)

+{

+    TRACE("(GLenum texture = 0x%X)", texture);

+

+    try

+    {

+        gl::Context *context = gl::getContext();

+

+        if(context)

+        {

+            if(texture < GL_TEXTURE0 || texture > GL_TEXTURE0 + gl::MAX_COMBINED_TEXTURE_IMAGE_UNITS - 1)

+            {

+                return error(GL_INVALID_ENUM);

+            }

+

+            context->setActiveSampler(texture - GL_TEXTURE0);

+        }

+    }

+    catch(std::bad_alloc&)

+    {

+        return error(GL_OUT_OF_MEMORY);

+    }

+}

+

+void GL_APIENTRY glAttachShader(GLuint program, GLuint shader)

+{

+    TRACE("(GLuint program = %d, GLuint shader = %d)", program, shader);

+

+    try

+    {

+        gl::Context *context = gl::getContext();

+

+        if(context)

+        {

+            gl::Program *programObject = context->getProgram(program);

+            gl::Shader *shaderObject = context->getShader(shader);

+

+            if(!programObject)

+            {

+                if(context->getShader(program))

+                {

+                    return error(GL_INVALID_OPERATION);

+                }

+                else

+                {

+                    return error(GL_INVALID_VALUE);

+                }

+            }

+

+            if(!shaderObject)

+            {

+                if(context->getProgram(shader))

+                {

+                    return error(GL_INVALID_OPERATION);

+                }

+                else

+                {

+                    return error(GL_INVALID_VALUE);

+                }

+            }

+

+            if(!programObject->attachShader(shaderObject))

+            {

+                return error(GL_INVALID_OPERATION);

+            }

+        }

+    }

+    catch(std::bad_alloc&)

+    {

+        return error(GL_OUT_OF_MEMORY);

+    }

+}

+

+void GL_APIENTRY glBeginQueryEXT(GLenum target, GLuint id)

+{

+    TRACE("(GLenum target = 0x%X, GLuint %d)", target, id);

+

+    try

+    {

+        switch(target)

+        {

+        case GL_ANY_SAMPLES_PASSED_EXT: 

+        case GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT:

+            break;

+        default: 

+            return error(GL_INVALID_ENUM);

+        }

+

+        if(id == 0)

+        {

+            return error(GL_INVALID_OPERATION);

+        }

+

+        gl::Context *context = gl::getContext();

+

+        if(context)

+        {

+            context->beginQuery(target, id);

+        }

+    }

+    catch(std::bad_alloc&)

+    {

+        return error(GL_OUT_OF_MEMORY);

+    }

+}

+

+void GL_APIENTRY glBindAttribLocation(GLuint program, GLuint index, const GLchar* name)

+{

+    TRACE("(GLuint program = %d, GLuint index = %d, const GLchar* name = 0x%0.8p)", program, index, name);

+

+    try

+    {

+        if(index >= gl::MAX_VERTEX_ATTRIBS)

+        {

+            return error(GL_INVALID_VALUE);

+        }

+

+        gl::Context *context = gl::getContext();

+

+        if(context)

+        {

+            gl::Program *programObject = context->getProgram(program);

+

+            if(!programObject)

+            {

+                if(context->getShader(program))

+                {

+                    return error(GL_INVALID_OPERATION);

+                }

+                else

+                {

+                    return error(GL_INVALID_VALUE);

+                }

+            }

+

+            if(strncmp(name, "gl_", 3) == 0)

+            {

+                return error(GL_INVALID_OPERATION);

+            }

+

+            programObject->bindAttributeLocation(index, name);

+        }

+    }

+    catch(std::bad_alloc&)

+    {

+        return error(GL_OUT_OF_MEMORY);

+    }

+}

+

+void GL_APIENTRY glBindBuffer(GLenum target, GLuint buffer)

+{

+    TRACE("(GLenum target = 0x%X, GLuint buffer = %d)", target, buffer);

+

+    try

+    {

+        gl::Context *context = gl::getContext();

+

+        if(context)

+        {

+            switch(target)

+            {

+              case GL_ARRAY_BUFFER:

+                context->bindArrayBuffer(buffer);

+                return;

+              case GL_ELEMENT_ARRAY_BUFFER:

+                context->bindElementArrayBuffer(buffer);

+                return;

+              default:

+                return error(GL_INVALID_ENUM);

+            }

+        }

+    }

+    catch(std::bad_alloc&)

+    {

+        return error(GL_OUT_OF_MEMORY);

+    }

+}

+

+void GL_APIENTRY glBindFramebuffer(GLenum target, GLuint framebuffer)

+{

+    TRACE("(GLenum target = 0x%X, GLuint framebuffer = %d)", target, framebuffer);

+

+    try

+    {

+        if(target != GL_FRAMEBUFFER && target != GL_DRAW_FRAMEBUFFER_ANGLE && target != GL_READ_FRAMEBUFFER_ANGLE)

+        {

+            return error(GL_INVALID_ENUM);

+        }

+

+        gl::Context *context = gl::getContext();

+

+        if(context)

+        {

+            if(target == GL_READ_FRAMEBUFFER_ANGLE || target == GL_FRAMEBUFFER)

+            {

+                context->bindReadFramebuffer(framebuffer);

+            }

+            

+            if(target == GL_DRAW_FRAMEBUFFER_ANGLE || target == GL_FRAMEBUFFER)

+            {

+                context->bindDrawFramebuffer(framebuffer);

+            }

+        }

+    }

+    catch(std::bad_alloc&)

+    {

+        return error(GL_OUT_OF_MEMORY);

+    }

+}

+

+void GL_APIENTRY glBindRenderbuffer(GLenum target, GLuint renderbuffer)

+{

+    TRACE("(GLenum target = 0x%X, GLuint renderbuffer = %d)", target, renderbuffer);

+

+    try

+    {

+        if(target != GL_RENDERBUFFER)

+        {

+            return error(GL_INVALID_ENUM);

+        }

+

+        gl::Context *context = gl::getContext();

+

+        if(context)

+        {

+            context->bindRenderbuffer(renderbuffer);

+        }

+    }

+    catch(std::bad_alloc&)

+    {

+        return error(GL_OUT_OF_MEMORY);

+    }

+}

+

+void GL_APIENTRY glBindTexture(GLenum target, GLuint texture)

+{

+    TRACE("(GLenum target = 0x%X, GLuint texture = %d)", target, texture);

+

+    try

+    {

+        gl::Context *context = gl::getContext();

+

+        if(context)

+        {

+            gl::Texture *textureObject = context->getTexture(texture);

+

+            if(textureObject && textureObject->getTarget() != target && texture != 0)

+            {

+                return error(GL_INVALID_OPERATION);

+            }

+

+            switch(target)

+            {

+              case GL_TEXTURE_2D:

+                context->bindTexture2D(texture);

+                return;

+              case GL_TEXTURE_CUBE_MAP:

+                context->bindTextureCubeMap(texture);

+                return;

+              default:

+                return error(GL_INVALID_ENUM);

+            }

+        }

+    }

+    catch(std::bad_alloc&)

+    {

+        return error(GL_OUT_OF_MEMORY);

+    }

+}

+

+void GL_APIENTRY glBlendColor(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha)

+{

+    TRACE("(GLclampf red = %f, GLclampf green = %f, GLclampf blue = %f, GLclampf alpha = %f)",

+          red, green, blue, alpha);

+

+    try

+    {

+        gl::Context* context = gl::getContext();

+

+        if(context)

+        {

+            context->setBlendColor(gl::clamp01(red), gl::clamp01(green), gl::clamp01(blue), gl::clamp01(alpha));

+        }

+    }

+    catch(std::bad_alloc&)

+    {

+        return error(GL_OUT_OF_MEMORY);

+    }

+}

+

+void GL_APIENTRY glBlendEquation(GLenum mode)

+{

+    glBlendEquationSeparate(mode, mode);

+}

+

+void GL_APIENTRY glBlendEquationSeparate(GLenum modeRGB, GLenum modeAlpha)

+{

+    TRACE("(GLenum modeRGB = 0x%X, GLenum modeAlpha = 0x%X)", modeRGB, modeAlpha);

+

+    try

+    {

+        switch(modeRGB)

+        {

+          case GL_FUNC_ADD:

+          case GL_FUNC_SUBTRACT:

+          case GL_FUNC_REVERSE_SUBTRACT:

+            break;

+          default:

+            return error(GL_INVALID_ENUM);

+        }

+

+        switch(modeAlpha)

+        {

+          case GL_FUNC_ADD:

+          case GL_FUNC_SUBTRACT:

+          case GL_FUNC_REVERSE_SUBTRACT:

+            break;

+          default:

+            return error(GL_INVALID_ENUM);

+        }

+

+        gl::Context *context = gl::getContext();

+

+        if(context)

+        {

+            context->setBlendEquation(modeRGB, modeAlpha);

+        }

+    }

+    catch(std::bad_alloc&)

+    {

+        return error(GL_OUT_OF_MEMORY);

+    }

+}

+

+void GL_APIENTRY glBlendFunc(GLenum sfactor, GLenum dfactor)

+{

+    glBlendFuncSeparate(sfactor, dfactor, sfactor, dfactor);

+}

+

+void GL_APIENTRY glBlendFuncSeparate(GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha)

+{

+    TRACE("(GLenum srcRGB = 0x%X, GLenum dstRGB = 0x%X, GLenum srcAlpha = 0x%X, GLenum dstAlpha = 0x%X)",

+          srcRGB, dstRGB, srcAlpha, dstAlpha);

+

+    try

+    {

+        switch(srcRGB)

+        {

+          case GL_ZERO:

+          case GL_ONE:

+          case GL_SRC_COLOR:

+          case GL_ONE_MINUS_SRC_COLOR:

+          case GL_DST_COLOR:

+          case GL_ONE_MINUS_DST_COLOR:

+          case GL_SRC_ALPHA:

+          case GL_ONE_MINUS_SRC_ALPHA:

+          case GL_DST_ALPHA:

+          case GL_ONE_MINUS_DST_ALPHA:

+          case GL_CONSTANT_COLOR:

+          case GL_ONE_MINUS_CONSTANT_COLOR:

+          case GL_CONSTANT_ALPHA:

+          case GL_ONE_MINUS_CONSTANT_ALPHA:

+          case GL_SRC_ALPHA_SATURATE:

+            break;

+          default:

+            return error(GL_INVALID_ENUM);

+        }

+

+        switch(dstRGB)

+        {

+          case GL_ZERO:

+          case GL_ONE:

+          case GL_SRC_COLOR:

+          case GL_ONE_MINUS_SRC_COLOR:

+          case GL_DST_COLOR:

+          case GL_ONE_MINUS_DST_COLOR:

+          case GL_SRC_ALPHA:

+          case GL_ONE_MINUS_SRC_ALPHA:

+          case GL_DST_ALPHA:

+          case GL_ONE_MINUS_DST_ALPHA:

+          case GL_CONSTANT_COLOR:

+          case GL_ONE_MINUS_CONSTANT_COLOR:

+          case GL_CONSTANT_ALPHA:

+          case GL_ONE_MINUS_CONSTANT_ALPHA:

+            break;

+          default:

+            return error(GL_INVALID_ENUM);

+        }

+

+        switch(srcAlpha)

+        {

+          case GL_ZERO:

+          case GL_ONE:

+          case GL_SRC_COLOR:

+          case GL_ONE_MINUS_SRC_COLOR:

+          case GL_DST_COLOR:

+          case GL_ONE_MINUS_DST_COLOR:

+          case GL_SRC_ALPHA:

+          case GL_ONE_MINUS_SRC_ALPHA:

+          case GL_DST_ALPHA:

+          case GL_ONE_MINUS_DST_ALPHA:

+          case GL_CONSTANT_COLOR:

+          case GL_ONE_MINUS_CONSTANT_COLOR:

+          case GL_CONSTANT_ALPHA:

+          case GL_ONE_MINUS_CONSTANT_ALPHA:

+          case GL_SRC_ALPHA_SATURATE:

+            break;

+          default:

+            return error(GL_INVALID_ENUM);

+        }

+

+        switch(dstAlpha)

+        {

+          case GL_ZERO:

+          case GL_ONE:

+          case GL_SRC_COLOR:

+          case GL_ONE_MINUS_SRC_COLOR:

+          case GL_DST_COLOR:

+          case GL_ONE_MINUS_DST_COLOR:

+          case GL_SRC_ALPHA:

+          case GL_ONE_MINUS_SRC_ALPHA:

+          case GL_DST_ALPHA:

+          case GL_ONE_MINUS_DST_ALPHA:

+          case GL_CONSTANT_COLOR:

+          case GL_ONE_MINUS_CONSTANT_COLOR:

+          case GL_CONSTANT_ALPHA:

+          case GL_ONE_MINUS_CONSTANT_ALPHA:

+            break;

+          default:

+            return error(GL_INVALID_ENUM);

+        }

+

+        gl::Context *context = gl::getContext();

+

+        if(context)

+        {

+            context->setBlendFactors(srcRGB, dstRGB, srcAlpha, dstAlpha);

+        }

+    }

+    catch(std::bad_alloc&)

+    {

+        return error(GL_OUT_OF_MEMORY);

+    }

+}

+

+void GL_APIENTRY glBufferData(GLenum target, GLsizeiptr size, const GLvoid* data, GLenum usage)

+{

+    TRACE("(GLenum target = 0x%X, GLsizeiptr size = %d, const GLvoid* data = 0x%0.8p, GLenum usage = %d)",

+          target, size, data, usage);

+

+    try

+    {

+        if(size < 0)

+        {

+            return error(GL_INVALID_VALUE);

+        }

+

+        switch(usage)

+        {

+          case GL_STREAM_DRAW:

+          case GL_STATIC_DRAW:

+          case GL_DYNAMIC_DRAW:

+            break;

+          default:

+            return error(GL_INVALID_ENUM);

+        }

+

+        gl::Context *context = gl::getContext();

+

+        if(context)

+        {

+            gl::Buffer *buffer;

+

+            switch(target)

+            {

+              case GL_ARRAY_BUFFER:

+                buffer = context->getArrayBuffer();

+                break;

+              case GL_ELEMENT_ARRAY_BUFFER:

+                buffer = context->getElementArrayBuffer();

+                break;

+              default:

+                return error(GL_INVALID_ENUM);

+            }

+

+            if(!buffer)

+            {

+                return error(GL_INVALID_OPERATION);

+            }

+

+            buffer->bufferData(data, size, usage);

+        }

+    }

+    catch(std::bad_alloc&)

+    {

+        return error(GL_OUT_OF_MEMORY);

+    }

+}

+

+void GL_APIENTRY glBufferSubData(GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid* data)

+{

+    TRACE("(GLenum target = 0x%X, GLintptr offset = %d, GLsizeiptr size = %d, const GLvoid* data = 0x%0.8p)",

+          target, offset, size, data);

+

+    try

+    {

+        if(size < 0 || offset < 0)

+        {

+            return error(GL_INVALID_VALUE);

+        }

+

+        if(data == NULL)

+        {

+            return;

+        }

+

+        gl::Context *context = gl::getContext();

+

+        if(context)

+        {

+            gl::Buffer *buffer;

+

+            switch(target)

+            {

+              case GL_ARRAY_BUFFER:

+                buffer = context->getArrayBuffer();

+                break;

+              case GL_ELEMENT_ARRAY_BUFFER:

+                buffer = context->getElementArrayBuffer();

+                break;

+              default:

+                return error(GL_INVALID_ENUM);

+            }

+

+            if(!buffer)

+            {

+                return error(GL_INVALID_OPERATION);

+            }

+

+            if((size_t)size + offset > buffer->size())

+            {

+                return error(GL_INVALID_VALUE);

+            }

+

+            buffer->bufferSubData(data, size, offset);

+        }

+    }

+    catch(std::bad_alloc&)

+    {

+        return error(GL_OUT_OF_MEMORY);

+    }

+}

+

+GLenum GL_APIENTRY glCheckFramebufferStatus(GLenum target)

+{

+    TRACE("(GLenum target = 0x%X)", target);

+

+    try

+    {

+        if(target != GL_FRAMEBUFFER && target != GL_DRAW_FRAMEBUFFER_ANGLE && target != GL_READ_FRAMEBUFFER_ANGLE)

+        {

+            return error(GL_INVALID_ENUM, 0);

+        }

+

+        gl::Context *context = gl::getContext();

+

+        if(context)

+        {

+            gl::Framebuffer *framebuffer = NULL;

+            if(target == GL_READ_FRAMEBUFFER_ANGLE)

+            {

+                framebuffer = context->getReadFramebuffer();

+            }

+            else

+            {

+                framebuffer = context->getDrawFramebuffer();

+            }

+

+            return framebuffer->completeness();

+        }

+    }

+    catch(std::bad_alloc&)

+    {

+        return error(GL_OUT_OF_MEMORY, 0);

+    }

+

+    return 0;

+}

+

+void GL_APIENTRY glClear(GLbitfield mask)

+{

+    TRACE("(GLbitfield mask = %X)", mask);

+

+    try

+    {

+		if((mask & ~(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT)) != 0)

+		{

+			return error(GL_INVALID_VALUE);

+		}

+

+        gl::Context *context = gl::getContext();

+

+        if(context)

+        {

+            context->clear(mask);

+        }

+    }

+    catch(std::bad_alloc&)

+    {

+        return error(GL_OUT_OF_MEMORY);

+    }

+}

+

+void GL_APIENTRY glClearColor(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha)

+{

+    TRACE("(GLclampf red = %f, GLclampf green = %f, GLclampf blue = %f, GLclampf alpha = %f)",

+          red, green, blue, alpha);

+

+    try

+    {

+        gl::Context *context = gl::getContext();

+

+        if(context)

+        {

+            context->setClearColor(red, green, blue, alpha);

+        }

+    }

+    catch(std::bad_alloc&)

+    {

+        return error(GL_OUT_OF_MEMORY);

+    }

+}

+

+void GL_APIENTRY glClearDepthf(GLclampf depth)

+{

+    TRACE("(GLclampf depth = %f)", depth);

+

+    try

+    {

+        gl::Context *context = gl::getContext();

+

+        if(context)

+        {

+            context->setClearDepth(depth);

+        }

+    }

+    catch(std::bad_alloc&)

+    {

+        return error(GL_OUT_OF_MEMORY);

+    }

+}

+

+void GL_APIENTRY glClearStencil(GLint s)

+{

+    TRACE("(GLint s = %d)", s);

+

+    try

+    {

+        gl::Context *context = gl::getContext();

+

+        if(context)

+        {

+            context->setClearStencil(s);

+        }

+    }

+    catch(std::bad_alloc&)

+    {

+        return error(GL_OUT_OF_MEMORY);

+    }

+}

+

+void GL_APIENTRY glColorMask(GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha)

+{

+    TRACE("(GLboolean red = %d, GLboolean green = %d, GLboolean blue = %d, GLboolean alpha = %d)",

+          red, green, blue, alpha);

+

+    try

+    {

+        gl::Context *context = gl::getContext();

+

+        if(context)

+        {

+            context->setColorMask(red == GL_TRUE, green == GL_TRUE, blue == GL_TRUE, alpha == GL_TRUE);

+        }

+    }

+    catch(std::bad_alloc&)

+    {

+        return error(GL_OUT_OF_MEMORY);

+    }

+}

+

+void GL_APIENTRY glCompileShader(GLuint shader)

+{

+    TRACE("(GLuint shader = %d)", shader);

+

+    try

+    {

+        gl::Context *context = gl::getContext();

+

+        if(context)

+        {

+            gl::Shader *shaderObject = context->getShader(shader);

+

+            if(!shaderObject)

+            {

+                if(context->getProgram(shader))

+                {

+                    return error(GL_INVALID_OPERATION);

+                }

+                else

+                {

+                    return error(GL_INVALID_VALUE);

+                }

+            }

+

+            shaderObject->compile();

+        }

+    }

+    catch(std::bad_alloc&)

+    {

+        return error(GL_OUT_OF_MEMORY);

+    }

+}

+

+void GL_APIENTRY glCompressedTexImage2D(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, 

+                                        GLint border, GLsizei imageSize, const GLvoid* data)

+{

+    TRACE("(GLenum target = 0x%X, GLint level = %d, GLenum internalformat = 0x%X, GLsizei width = %d, " 

+          "GLsizei height = %d, GLint border = %d, GLsizei imageSize = %d, const GLvoid* data = 0x%0.8p)",

+          target, level, internalformat, width, height, border, imageSize, data);

+

+    try

+    {

+        if(!validImageSize(level, width, height) || border != 0 || imageSize < 0)

+        {

+            return error(GL_INVALID_VALUE);

+        }

+

+        switch(internalformat)

+        {

+        case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:

+        case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:

+		case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:

+		case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:

+			if(!S3TC_SUPPORT)

+            {

+                return error(GL_INVALID_ENUM);

+            }

+            break;

+		case GL_DEPTH_COMPONENT:

+		case GL_DEPTH_COMPONENT16:

+		case GL_DEPTH_COMPONENT32_OES:

+		case GL_DEPTH_STENCIL_OES:

+		case GL_DEPTH24_STENCIL8_OES:

+			return error(GL_INVALID_OPERATION);

+        default:

+            return error(GL_INVALID_ENUM);

+        }

+

+        if(border != 0)

+        {

+            return error(GL_INVALID_VALUE);

+        }

+

+        gl::Context *context = gl::getContext();

+

+        if(context)

+        {

+			if(level > gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS)

+            {

+                return error(GL_INVALID_VALUE);

+            }

+

+            switch(target)

+            {

+              case GL_TEXTURE_2D:

+                if(width > (gl::IMPLEMENTATION_MAX_TEXTURE_SIZE >> level) ||

+                    height > (gl::IMPLEMENTATION_MAX_TEXTURE_SIZE >> level))

+                {

+                    return error(GL_INVALID_VALUE);

+                }

+                break;

+              case GL_TEXTURE_CUBE_MAP_POSITIVE_X:

+              case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:

+              case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:

+              case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:

+              case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:

+              case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:

+                if(width != height)

+                {

+                    return error(GL_INVALID_VALUE);

+                }

+

+                if(width > (gl::IMPLEMENTATION_MAX_CUBE_MAP_TEXTURE_SIZE >> level) ||

+                   height > (gl::IMPLEMENTATION_MAX_CUBE_MAP_TEXTURE_SIZE >> level))

+                {

+                    return error(GL_INVALID_VALUE);

+                }

+                break;

+              default:

+                return error(GL_INVALID_ENUM);

+            }

+

+            if(imageSize != gl::ComputeCompressedSize(width, height, internalformat))

+            {

+                return error(GL_INVALID_VALUE);

+            }

+

+            if(target == GL_TEXTURE_2D)

+            {

+                gl::Texture2D *texture = context->getTexture2D();

+

+                if(!texture)

+                {

+                    return error(GL_INVALID_OPERATION);

+                }

+

+                texture->setCompressedImage(level, internalformat, width, height, imageSize, data);

+            }

+            else

+            {

+                gl::TextureCubeMap *texture = context->getTextureCubeMap();

+

+                if(!texture)

+                {

+                    return error(GL_INVALID_OPERATION);

+                }

+

+                switch(target)

+                {

+                  case GL_TEXTURE_CUBE_MAP_POSITIVE_X:

+                  case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:

+                  case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:

+                  case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:

+                  case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:

+                  case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:

+                    texture->setCompressedImage(target, level, internalformat, width, height, imageSize, data);

+                    break;

+                  default: UNREACHABLE();

+                }

+            }

+        }

+    }

+    catch(std::bad_alloc&)

+    {

+        return error(GL_OUT_OF_MEMORY);

+    }

+}

+

+void GL_APIENTRY glCompressedTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,

+                                         GLenum format, GLsizei imageSize, const GLvoid* data)

+{

+    TRACE("(GLenum target = 0x%X, GLint level = %d, GLint xoffset = %d, GLint yoffset = %d, "

+          "GLsizei width = %d, GLsizei height = %d, GLenum format = 0x%X, "

+          "GLsizei imageSize = %d, const GLvoid* data = 0x%0.8p)",

+          target, level, xoffset, yoffset, width, height, format, imageSize, data);

+

+    try

+    {

+        if(!gl::IsTextureTarget(target))

+        {

+            return error(GL_INVALID_ENUM);

+        }

+

+        if(xoffset < 0 || yoffset < 0 || !validImageSize(level, width, height) || imageSize < 0)

+        {

+            return error(GL_INVALID_VALUE);

+        }

+

+        switch(format)

+        {

+        case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:

+        case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:

+		case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:

+		case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:

+			if(!S3TC_SUPPORT)

+            {

+                return error(GL_INVALID_ENUM);

+            }

+            break;

+        default:

+            return error(GL_INVALID_ENUM);

+        }

+

+        if(width == 0 || height == 0 || data == NULL)

+        {

+            return;

+        }

+

+        gl::Context *context = gl::getContext();

+

+        if(context)

+        {

+            if(level > gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS)

+            {

+                return error(GL_INVALID_VALUE);

+            }

+

+            if(imageSize != gl::ComputeCompressedSize(width, height, format))

+            {

+                return error(GL_INVALID_VALUE);

+            }

+

+            if(xoffset % 4 != 0 || yoffset % 4 != 0)

+            {

+				// We wait to check the offsets until this point, because the multiple-of-four restriction does not exist unless DXT1 textures are supported

+                return error(GL_INVALID_OPERATION);

+            }

+

+            if(target == GL_TEXTURE_2D)

+            {

+                gl::Texture2D *texture = context->getTexture2D();

+

+                if(validateSubImageParams(true, width, height, xoffset, yoffset, target, level, format, texture))

+				{

+					texture->subImageCompressed(level, xoffset, yoffset, width, height, format, imageSize, data);

+				}

+            }

+            else if(gl::IsCubemapTextureTarget(target))

+            {

+                gl::TextureCubeMap *texture = context->getTextureCubeMap();

+

+                if(validateSubImageParams(true, width, height, xoffset, yoffset, target, level, format, texture))

+				{

+					texture->subImageCompressed(target, level, xoffset, yoffset, width, height, format, imageSize, data);

+				}

+            }

+            else

+            {

+                UNREACHABLE();

+            }

+        }

+    }

+    catch(std::bad_alloc&)

+    {

+        return error(GL_OUT_OF_MEMORY);

+    }

+}

+

+void GL_APIENTRY glCopyTexImage2D(GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border)

+{

+    TRACE("(GLenum target = 0x%X, GLint level = %d, GLenum internalformat = 0x%X, "

+          "GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d, GLint border = %d)",

+          target, level, internalformat, x, y, width, height, border);

+

+    try

+    {

+        if(!validImageSize(level, width, height))

+        {

+            return error(GL_INVALID_VALUE);

+        }

+

+        if(border != 0)

+        {

+            return error(GL_INVALID_VALUE);

+        }

+

+        gl::Context *context = gl::getContext();

+

+        if(context)

+        {

+            switch(target)

+            {

+              case GL_TEXTURE_2D:

+                if(width > (gl::IMPLEMENTATION_MAX_TEXTURE_SIZE >> level) ||

+                   height > (gl::IMPLEMENTATION_MAX_TEXTURE_SIZE >> level))

+                {

+                    return error(GL_INVALID_VALUE);

+                }

+                break;

+              case GL_TEXTURE_CUBE_MAP_POSITIVE_X:

+              case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:

+              case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:

+              case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:

+              case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:

+              case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:

+                if(width != height)

+                {

+                    return error(GL_INVALID_VALUE);

+                }

+

+                if(width > (gl::IMPLEMENTATION_MAX_CUBE_MAP_TEXTURE_SIZE >> level) ||

+                   height > (gl::IMPLEMENTATION_MAX_CUBE_MAP_TEXTURE_SIZE >> level))

+                {

+                    return error(GL_INVALID_VALUE);

+                }

+                break;

+              default:

+                return error(GL_INVALID_ENUM);

+            }

+

+            gl::Framebuffer *framebuffer = context->getReadFramebuffer();

+

+            if(framebuffer->completeness() != GL_FRAMEBUFFER_COMPLETE)

+            {

+                return error(GL_INVALID_FRAMEBUFFER_OPERATION);

+            }

+

+            if(context->getReadFramebufferHandle() != 0 && framebuffer->getColorbuffer()->getSamples() != 0)

+            {

+                return error(GL_INVALID_OPERATION);

+            }

+

+            gl::Renderbuffer *source = framebuffer->getColorbuffer();

+            GLenum colorbufferFormat = source->getFormat();

+

+            // [OpenGL ES 2.0.24] table 3.9

+            switch(internalformat)

+            {

+            case GL_ALPHA:

+                if(colorbufferFormat != GL_ALPHA &&

+                   colorbufferFormat != GL_RGBA &&

+                   colorbufferFormat != GL_RGBA4 &&

+                   colorbufferFormat != GL_RGB5_A1 &&

+                   colorbufferFormat != GL_RGBA8_OES)

+                {

+                    return error(GL_INVALID_OPERATION);

+                }

+                break;

+            case GL_LUMINANCE:

+            case GL_RGB:

+                if(colorbufferFormat != GL_RGB &&

+                   colorbufferFormat != GL_RGB565 &&

+                   colorbufferFormat != GL_RGB8_OES &&

+                   colorbufferFormat != GL_RGBA &&

+                   colorbufferFormat != GL_RGBA4 &&

+                   colorbufferFormat != GL_RGB5_A1 &&

+                   colorbufferFormat != GL_RGBA8_OES)

+                {

+                    return error(GL_INVALID_OPERATION);

+                }

+                break;

+            case GL_LUMINANCE_ALPHA:

+            case GL_RGBA:

+                if(colorbufferFormat != GL_RGBA &&

+                   colorbufferFormat != GL_RGBA4 &&

+                   colorbufferFormat != GL_RGB5_A1 &&

+                   colorbufferFormat != GL_RGBA8_OES)

+                 {

+                     return error(GL_INVALID_OPERATION);

+                 }

+                 break;

+            case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:

+            case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:

+			case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:

+			case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:

+                if(S3TC_SUPPORT)

+                {

+                    return error(GL_INVALID_OPERATION);

+                }

+                else

+                {

+                    return error(GL_INVALID_ENUM);

+                }

+                break;

+            default:

+                return error(GL_INVALID_ENUM);

+            }

+

+            if(target == GL_TEXTURE_2D)

+            {

+                gl::Texture2D *texture = context->getTexture2D();

+

+                if(!texture)

+                {

+                    return error(GL_INVALID_OPERATION);

+                }

+

+                texture->copyImage(level, internalformat, x, y, width, height, framebuffer);

+            }

+            else if(gl::IsCubemapTextureTarget(target))

+            {

+                gl::TextureCubeMap *texture = context->getTextureCubeMap();

+

+                if(!texture)

+                {

+                    return error(GL_INVALID_OPERATION);

+                }

+

+                texture->copyImage(target, level, internalformat, x, y, width, height, framebuffer);

+            }

+            else UNREACHABLE();

+        }

+    }

+    catch(std::bad_alloc&)

+    {

+        return error(GL_OUT_OF_MEMORY);

+    }

+}

+

+void GL_APIENTRY glCopyTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height)

+{

+    TRACE("(GLenum target = 0x%X, GLint level = %d, GLint xoffset = %d, GLint yoffset = %d, "

+          "GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d)",

+          target, level, xoffset, yoffset, x, y, width, height);

+

+    try

+    {

+        if(!gl::IsTextureTarget(target))

+        {

+            return error(GL_INVALID_ENUM);

+        }

+

+        if(level < 0 || xoffset < 0 || yoffset < 0 || width < 0 || height < 0)

+        {

+            return error(GL_INVALID_VALUE);

+        }

+

+        if(std::numeric_limits<GLsizei>::max() - xoffset < width || std::numeric_limits<GLsizei>::max() - yoffset < height)

+        {

+            return error(GL_INVALID_VALUE);

+        }

+

+        if(width == 0 || height == 0)

+        {

+            return;

+        }

+

+        gl::Context *context = gl::getContext();

+

+        if(context)

+        {

+            if(level > gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS)

+            {

+                return error(GL_INVALID_VALUE);

+            }

+

+            gl::Framebuffer *framebuffer = context->getReadFramebuffer();

+

+            if(framebuffer->completeness() != GL_FRAMEBUFFER_COMPLETE)

+            {

+                return error(GL_INVALID_FRAMEBUFFER_OPERATION);

+            }

+

+            if(context->getReadFramebufferHandle() != 0 && framebuffer->getColorbuffer()->getSamples() != 0)

+            {

+                return error(GL_INVALID_OPERATION);

+            }

+

+            gl::Renderbuffer *source = framebuffer->getColorbuffer();

+            GLenum colorbufferFormat = source->getFormat();

+            gl::Texture *texture = NULL;

+

+            if(target == GL_TEXTURE_2D)

+            {

+                texture = context->getTexture2D();

+            }

+            else if(gl::IsCubemapTextureTarget(target))

+            {

+                texture = context->getTextureCubeMap();

+            }

+            else UNREACHABLE();

+

+            if(!validateSubImageParams(false, width, height, xoffset, yoffset, target, level, GL_NONE, texture))

+			{

+				return;

+			}

+

+            GLenum textureFormat = texture->getFormat(target, level);

+

+            // [OpenGL ES 2.0.24] table 3.9

+            switch(textureFormat)

+            {

+            case GL_ALPHA:

+                if(colorbufferFormat != GL_ALPHA &&

+                   colorbufferFormat != GL_RGBA &&

+                   colorbufferFormat != GL_RGBA4 &&

+                   colorbufferFormat != GL_RGB5_A1 &&

+                   colorbufferFormat != GL_RGBA8_OES)

+                {

+                    return error(GL_INVALID_OPERATION);

+                }

+                break;

+            case GL_LUMINANCE:

+            case GL_RGB:

+                if(colorbufferFormat != GL_RGB &&

+                   colorbufferFormat != GL_RGB565 &&

+                   colorbufferFormat != GL_RGB8_OES &&

+                   colorbufferFormat != GL_RGBA &&

+                   colorbufferFormat != GL_RGBA4 &&

+                   colorbufferFormat != GL_RGB5_A1 &&

+                   colorbufferFormat != GL_RGBA8_OES)

+                {

+                    return error(GL_INVALID_OPERATION);

+                }

+                break;

+            case GL_LUMINANCE_ALPHA:

+            case GL_RGBA:

+                if(colorbufferFormat != GL_RGBA &&

+                   colorbufferFormat != GL_RGBA4 &&

+                   colorbufferFormat != GL_RGB5_A1 &&

+                   colorbufferFormat != GL_RGBA8_OES)

+                {

+                    return error(GL_INVALID_OPERATION);

+                }

+                break;

+            case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:

+            case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:

+			case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:

+			case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:

+                return error(GL_INVALID_OPERATION);

+			case GL_DEPTH_COMPONENT:

+			case GL_DEPTH_STENCIL_OES:

+				return error(GL_INVALID_OPERATION);

+            default:

+                return error(GL_INVALID_OPERATION);

+            }

+

+            texture->copySubImage(target, level, xoffset, yoffset, x, y, width, height, framebuffer);

+        }

+    }

+

+    catch(std::bad_alloc&)

+    {

+        return error(GL_OUT_OF_MEMORY);

+    }

+}

+

+GLuint GL_APIENTRY glCreateProgram(void)

+{

+    TRACE("()");

+

+    try

+    {

+        gl::Context *context = gl::getContext();

+

+        if(context)

+        {

+            return context->createProgram();

+        }

+    }

+    catch(std::bad_alloc&)

+    {

+        return error(GL_OUT_OF_MEMORY, 0);

+    }

+

+    return 0;

+}

+

+GLuint GL_APIENTRY glCreateShader(GLenum type)

+{

+    TRACE("(GLenum type = 0x%X)", type);

+

+    try

+    {

+        gl::Context *context = gl::getContext();

+

+        if(context)

+        {

+            switch(type)

+            {

+              case GL_FRAGMENT_SHADER:

+              case GL_VERTEX_SHADER:

+                return context->createShader(type);

+              default:

+                return error(GL_INVALID_ENUM, 0);

+            }

+        }

+    }

+    catch(std::bad_alloc&)

+    {

+        return error(GL_OUT_OF_MEMORY, 0);

+    }

+

+    return 0;

+}

+

+void GL_APIENTRY glCullFace(GLenum mode)

+{

+    TRACE("(GLenum mode = 0x%X)", mode);

+

+    try

+    {

+        switch(mode)

+        {

+          case GL_FRONT:

+          case GL_BACK:

+          case GL_FRONT_AND_BACK:

+            {

+                gl::Context *context = gl::getContext();

+

+                if(context)

+                {

+                    context->setCullMode(mode);

+                }

+            }

+            break;

+          default:

+            return error(GL_INVALID_ENUM);

+        }

+    }

+    catch(std::bad_alloc&)

+    {

+        return error(GL_OUT_OF_MEMORY);

+    }

+}

+

+void GL_APIENTRY glDeleteBuffers(GLsizei n, const GLuint* buffers)

+{

+    TRACE("(GLsizei n = %d, const GLuint* buffers = 0x%0.8p)", n, buffers);

+

+    try

+    {

+        if(n < 0)

+        {

+            return error(GL_INVALID_VALUE);

+        }

+

+        gl::Context *context = gl::getContext();

+

+        if(context)

+        {

+            for(int i = 0; i < n; i++)

+            {

+                context->deleteBuffer(buffers[i]);

+            }

+        }

+    }

+    catch(std::bad_alloc&)

+    {

+        return error(GL_OUT_OF_MEMORY);

+    }

+}

+

+void GL_APIENTRY glDeleteFencesNV(GLsizei n, const GLuint* fences)

+{

+    TRACE("(GLsizei n = %d, const GLuint* fences = 0x%0.8p)", n, fences);

+

+    try

+    {

+        if(n < 0)

+        {

+            return error(GL_INVALID_VALUE);

+        }

+

+        gl::Context *context = gl::getContext();

+

+        if(context)

+        {

+            for(int i = 0; i < n; i++)

+            {

+                context->deleteFence(fences[i]);

+            }

+        }

+    }

+    catch(std::bad_alloc&)

+    {

+        return error(GL_OUT_OF_MEMORY);

+    }

+}

+

+void GL_APIENTRY glDeleteFramebuffers(GLsizei n, const GLuint* framebuffers)

+{

+    TRACE("(GLsizei n = %d, const GLuint* framebuffers = 0x%0.8p)", n, framebuffers);

+

+    try

+    {

+        if(n < 0)

+        {

+            return error(GL_INVALID_VALUE);

+        }

+

+        gl::Context *context = gl::getContext();

+

+        if(context)

+        {

+            for(int i = 0; i < n; i++)

+            {

+                if(framebuffers[i] != 0)

+                {

+                    context->deleteFramebuffer(framebuffers[i]);

+                }

+            }

+        }

+    }

+    catch(std::bad_alloc&)

+    {

+        return error(GL_OUT_OF_MEMORY);

+    }

+}

+

+void GL_APIENTRY glDeleteProgram(GLuint program)

+{

+    TRACE("(GLuint program = %d)", program);

+

+    try

+    {

+        if(program == 0)

+        {

+            return;

+        }

+

+        gl::Context *context = gl::getContext();

+

+        if(context)

+        {

+            if(!context->getProgram(program))

+            {

+                if(context->getShader(program))

+                {

+                    return error(GL_INVALID_OPERATION);

+                }

+                else

+                {

+                    return error(GL_INVALID_VALUE);

+                }

+            }

+

+            context->deleteProgram(program);

+        }

+    }

+    catch(std::bad_alloc&)

+    {

+        return error(GL_OUT_OF_MEMORY);

+    }

+}

+

+void GL_APIENTRY glDeleteQueriesEXT(GLsizei n, const GLuint *ids)

+{

+    TRACE("(GLsizei n = %d, const GLuint *ids = 0x%0.8p)", n, ids);

+

+    try

+    {

+        if(n < 0)

+        {

+            return error(GL_INVALID_VALUE);

+        }

+

+        gl::Context *context = gl::getContext();

+

+        if(context)

+        {

+            for(int i = 0; i < n; i++)

+            {

+                context->deleteQuery(ids[i]);

+            }

+        }

+    }

+    catch(std::bad_alloc&)

+    {

+        return error(GL_OUT_OF_MEMORY);

+    }

+}

+

+void GL_APIENTRY glDeleteRenderbuffers(GLsizei n, const GLuint* renderbuffers)

+{

+    TRACE("(GLsizei n = %d, const GLuint* renderbuffers = 0x%0.8p)", n, renderbuffers);

+

+    try

+    {

+        if(n < 0)

+        {

+            return error(GL_INVALID_VALUE);

+        }

+

+        gl::Context *context = gl::getContext();

+

+        if(context)

+        {

+            for(int i = 0; i < n; i++)

+            {

+                context->deleteRenderbuffer(renderbuffers[i]);

+            }

+        }

+    }

+    catch(std::bad_alloc&)

+    {

+        return error(GL_OUT_OF_MEMORY);

+    }

+}

+

+void GL_APIENTRY glDeleteShader(GLuint shader)

+{

+    TRACE("(GLuint shader = %d)", shader);

+

+    try

+    {

+        if(shader == 0)

+        {

+            return;

+        }

+

+        gl::Context *context = gl::getContext();

+

+        if(context)

+        {

+            if(!context->getShader(shader))

+            {

+                if(context->getProgram(shader))

+                {

+                    return error(GL_INVALID_OPERATION);

+                }

+                else

+                {

+                    return error(GL_INVALID_VALUE);

+                }

+            }

+

+            context->deleteShader(shader);

+        }

+    }

+    catch(std::bad_alloc&)

+    {

+        return error(GL_OUT_OF_MEMORY);

+    }

+}

+

+void GL_APIENTRY glDeleteTextures(GLsizei n, const GLuint* textures)

+{

+    TRACE("(GLsizei n = %d, const GLuint* textures = 0x%0.8p)", n, textures);

+

+    try

+    {

+        if(n < 0)

+        {

+            return error(GL_INVALID_VALUE);

+        }

+

+        gl::Context *context = gl::getContext();

+

+        if(context)

+        {

+            for(int i = 0; i < n; i++)

+            {

+                if(textures[i] != 0)

+                {

+                    context->deleteTexture(textures[i]);

+                }

+            }

+        }

+    }

+    catch(std::bad_alloc&)

+    {

+        return error(GL_OUT_OF_MEMORY);

+    }

+}

+

+void GL_APIENTRY glDepthFunc(GLenum func)

+{

+    TRACE("(GLenum func = 0x%X)", func);

+

+    try

+    {

+        switch(func)

+        {

+          case GL_NEVER:

+          case GL_ALWAYS:

+          case GL_LESS:

+          case GL_LEQUAL:

+          case GL_EQUAL:

+          case GL_GREATER:

+          case GL_GEQUAL:

+          case GL_NOTEQUAL:

+            break;

+          default:

+            return error(GL_INVALID_ENUM);

+        }

+

+        gl::Context *context = gl::getContext();

+

+        if(context)

+        {

+            context->setDepthFunc(func);

+        }

+    }

+    catch(std::bad_alloc&)

+    {

+        return error(GL_OUT_OF_MEMORY);

+    }

+}

+

+void GL_APIENTRY glDepthMask(GLboolean flag)

+{

+    TRACE("(GLboolean flag = %d)", flag);

+

+    try

+    {

+        gl::Context *context = gl::getContext();

+

+        if(context)

+        {

+            context->setDepthMask(flag != GL_FALSE);

+        }

+    }

+    catch(std::bad_alloc&)

+    {

+        return error(GL_OUT_OF_MEMORY);

+    }

+}

+

+void GL_APIENTRY glDepthRangef(GLclampf zNear, GLclampf zFar)

+{

+    TRACE("(GLclampf zNear = %f, GLclampf zFar = %f)", zNear, zFar);

+

+    try

+    {

+        gl::Context *context = gl::getContext();

+

+        if(context)

+        {

+            context->setDepthRange(zNear, zFar);

+        }

+    }

+    catch(std::bad_alloc&)

+    {

+        return error(GL_OUT_OF_MEMORY);

+    }

+}

+

+void GL_APIENTRY glDetachShader(GLuint program, GLuint shader)

+{

+    TRACE("(GLuint program = %d, GLuint shader = %d)", program, shader);

+

+    try

+    {

+        gl::Context *context = gl::getContext();

+

+        if(context)

+        {

+

+            gl::Program *programObject = context->getProgram(program);

+            gl::Shader *shaderObject = context->getShader(shader);

+            

+            if(!programObject)

+            {

+                gl::Shader *shaderByProgramHandle;

+                shaderByProgramHandle = context->getShader(program);

+                if(!shaderByProgramHandle)

+                {

+                    return error(GL_INVALID_VALUE);

+                }

+                else

+                {

+                    return error(GL_INVALID_OPERATION);

+                }

+            }

+

+            if(!shaderObject)

+            {

+                gl::Program *programByShaderHandle = context->getProgram(shader);

+                if(!programByShaderHandle)

+                {

+                    return error(GL_INVALID_VALUE);

+                }

+                else

+                {

+                    return error(GL_INVALID_OPERATION);

+                }

+            }

+

+            if(!programObject->detachShader(shaderObject))

+            {

+                return error(GL_INVALID_OPERATION);

+            }

+        }

+    }

+    catch(std::bad_alloc&)

+    {

+        return error(GL_OUT_OF_MEMORY);

+    }

+}

+

+void GL_APIENTRY glDisable(GLenum cap)

+{

+    TRACE("(GLenum cap = 0x%X)", cap);

+

+    try

+    {

+        gl::Context *context = gl::getContext();

+

+        if(context)

+        {

+            switch(cap)

+            {

+              case GL_CULL_FACE:                context->setCullFace(false);              break;

+              case GL_POLYGON_OFFSET_FILL:      context->setPolygonOffsetFill(false);     break;

+              case GL_SAMPLE_ALPHA_TO_COVERAGE: context->setSampleAlphaToCoverage(false); break;

+              case GL_SAMPLE_COVERAGE:          context->setSampleCoverage(false);        break;

+              case GL_SCISSOR_TEST:             context->setScissorTest(false);           break;

+              case GL_STENCIL_TEST:             context->setStencilTest(false);           break;

+              case GL_DEPTH_TEST:               context->setDepthTest(false);             break;

+              case GL_BLEND:                    context->setBlend(false);                 break;

+              case GL_DITHER:                   context->setDither(false);                break;

+              default:

+                return error(GL_INVALID_ENUM);

+            }

+        }

+    }

+    catch(std::bad_alloc&)

+    {

+        return error(GL_OUT_OF_MEMORY);

+    }

+}

+

+void GL_APIENTRY glDisableVertexAttribArray(GLuint index)

+{

+    TRACE("(GLuint index = %d)", index);

+

+    try

+    {

+        if(index >= gl::MAX_VERTEX_ATTRIBS)

+        {

+            return error(GL_INVALID_VALUE);

+        }

+

+        gl::Context *context = gl::getContext();

+

+        if(context)

+        {

+            context->setEnableVertexAttribArray(index, false);

+        }

+    }

+    catch(std::bad_alloc&)

+    {

+        return error(GL_OUT_OF_MEMORY);

+    }

+}

+

+void GL_APIENTRY glDrawArrays(GLenum mode, GLint first, GLsizei count)

+{

+    TRACE("(GLenum mode = 0x%X, GLint first = %d, GLsizei count = %d)", mode, first, count);

+

+    try

+    {

+        if(count < 0 || first < 0)

+        {

+            return error(GL_INVALID_VALUE);

+        }

+

+        gl::Context *context = gl::getContext();

+

+        if(context)

+        {

+            context->drawArrays(mode, first, count);

+        }

+    }

+    catch(std::bad_alloc&)

+    {

+        return error(GL_OUT_OF_MEMORY);

+    }

+}

+

+void GL_APIENTRY glDrawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid* indices)

+{

+    TRACE("(GLenum mode = 0x%X, GLsizei count = %d, GLenum type = 0x%X, const GLvoid* indices = 0x%0.8p)",

+          mode, count, type, indices);

+

+    try

+    {

+        if(count < 0)

+        {

+            return error(GL_INVALID_VALUE);

+        }

+

+        gl::Context *context = gl::getContext();

+

+        if(context)

+        {

+            switch(type)

+            {

+              case GL_UNSIGNED_BYTE:

+              case GL_UNSIGNED_SHORT:

+              case GL_UNSIGNED_INT:

+                break;

+              default:

+                return error(GL_INVALID_ENUM);

+            }

+        

+            context->drawElements(mode, count, type, indices);

+        }

+    }

+    catch(std::bad_alloc&)

+    {

+        return error(GL_OUT_OF_MEMORY);

+    }

+}

+

+void GL_APIENTRY glEnable(GLenum cap)

+{

+    TRACE("(GLenum cap = 0x%X)", cap);

+

+    try

+    {

+        gl::Context *context = gl::getContext();

+

+        if(context)

+        {

+            switch(cap)

+            {

+              case GL_CULL_FACE:                context->setCullFace(true);              break;

+              case GL_POLYGON_OFFSET_FILL:      context->setPolygonOffsetFill(true);     break;

+              case GL_SAMPLE_ALPHA_TO_COVERAGE: context->setSampleAlphaToCoverage(true); break;

+              case GL_SAMPLE_COVERAGE:          context->setSampleCoverage(true);        break;

+              case GL_SCISSOR_TEST:             context->setScissorTest(true);           break;

+              case GL_STENCIL_TEST:             context->setStencilTest(true);           break;

+              case GL_DEPTH_TEST:               context->setDepthTest(true);             break;

+              case GL_BLEND:                    context->setBlend(true);                 break;

+              case GL_DITHER:                   context->setDither(true);                break;

+              default:

+                return error(GL_INVALID_ENUM);

+            }

+        }

+    }

+    catch(std::bad_alloc&)

+    {

+        return error(GL_OUT_OF_MEMORY);

+    }

+}

+

+void GL_APIENTRY glEnableVertexAttribArray(GLuint index)

+{

+    TRACE("(GLuint index = %d)", index);

+

+    try

+    {

+        if(index >= gl::MAX_VERTEX_ATTRIBS)

+        {

+            return error(GL_INVALID_VALUE);

+        }

+

+        gl::Context *context = gl::getContext();

+

+        if(context)

+        {

+            context->setEnableVertexAttribArray(index, true);

+        }

+    }

+    catch(std::bad_alloc&)

+    {

+        return error(GL_OUT_OF_MEMORY);

+    }

+}

+

+void GL_APIENTRY glEndQueryEXT(GLenum target)

+{

+    TRACE("GLenum target = 0x%X)", target);

+

+    try

+    {

+        switch(target)

+        {

+        case GL_ANY_SAMPLES_PASSED_EXT: 

+        case GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT:

+            break;

+        default: 

+            return error(GL_INVALID_ENUM);

+        }

+

+        gl::Context *context = gl::getContext();

+

+        if(context)

+        {

+            context->endQuery(target);

+        }

+    }

+    catch(std::bad_alloc&)

+    {

+        return error(GL_OUT_OF_MEMORY);

+    }

+}

+

+void GL_APIENTRY glFinishFenceNV(GLuint fence)

+{

+    TRACE("(GLuint fence = %d)", fence);

+

+    try

+    {

+        gl::Context *context = gl::getContext();

+

+        if(context)

+        {

+            gl::Fence* fenceObject = context->getFence(fence);

+

+            if(fenceObject == NULL)

+            {

+                return error(GL_INVALID_OPERATION);

+            }

+

+            fenceObject->finishFence();

+        }

+    }

+    catch(std::bad_alloc&)

+    {

+        return error(GL_OUT_OF_MEMORY);

+    }

+}

+

+void GL_APIENTRY glFinish(void)

+{

+    TRACE("()");

+

+    try

+    {

+        gl::Context *context = gl::getContext();

+

+        if(context)

+        {

+            context->finish();

+        }

+    }

+    catch(std::bad_alloc&)

+    {

+        return error(GL_OUT_OF_MEMORY);

+    }

+}

+

+void GL_APIENTRY glFlush(void)

+{

+    TRACE("()");

+

+    try

+    {

+        gl::Context *context = gl::getContext();

+

+        if(context)

+        {

+            context->flush();

+        }

+    }

+    catch(std::bad_alloc&)

+    {

+        return error(GL_OUT_OF_MEMORY);

+    }

+}

+

+void GL_APIENTRY glFramebufferRenderbuffer(GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer)

+{

+    TRACE("(GLenum target = 0x%X, GLenum attachment = 0x%X, GLenum renderbuffertarget = 0x%X, "

+          "GLuint renderbuffer = %d)", target, attachment, renderbuffertarget, renderbuffer);

+

+    try

+    {

+        if((target != GL_FRAMEBUFFER && target != GL_DRAW_FRAMEBUFFER_ANGLE && target != GL_READ_FRAMEBUFFER_ANGLE)

+            || (renderbuffertarget != GL_RENDERBUFFER && renderbuffer != 0))

+        {

+            return error(GL_INVALID_ENUM);

+        }

+

+        gl::Context *context = gl::getContext();

+

+        if(context)

+        {

+            gl::Framebuffer *framebuffer = NULL;

+            GLuint framebufferHandle = 0;

+            if(target == GL_READ_FRAMEBUFFER_ANGLE)

+            {

+                framebuffer = context->getReadFramebuffer();

+                framebufferHandle = context->getReadFramebufferHandle();

+            }

+            else

+            {

+                framebuffer = context->getDrawFramebuffer();

+                framebufferHandle = context->getDrawFramebufferHandle();

+            }

+

+            if(!framebuffer || (framebufferHandle == 0 && renderbuffer != 0))

+            {

+                return error(GL_INVALID_OPERATION);

+            }

+

+            switch(attachment)

+            {

+              case GL_COLOR_ATTACHMENT0:

+                framebuffer->setColorbuffer(GL_RENDERBUFFER, renderbuffer);

+                break;

+              case GL_DEPTH_ATTACHMENT:

+                framebuffer->setDepthbuffer(GL_RENDERBUFFER, renderbuffer);

+                break;

+              case GL_STENCIL_ATTACHMENT:

+                framebuffer->setStencilbuffer(GL_RENDERBUFFER, renderbuffer);

+                break;

+              default:

+                return error(GL_INVALID_ENUM);

+            }

+        }

+    }

+    catch(std::bad_alloc&)

+    {

+        return error(GL_OUT_OF_MEMORY);

+    }

+}

+

+void GL_APIENTRY glFramebufferTexture2D(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level)

+{

+    TRACE("(GLenum target = 0x%X, GLenum attachment = 0x%X, GLenum textarget = 0x%X, "

+          "GLuint texture = %d, GLint level = %d)", target, attachment, textarget, texture, level);

+

+    try

+    {

+        if(target != GL_FRAMEBUFFER && target != GL_DRAW_FRAMEBUFFER_ANGLE && target != GL_READ_FRAMEBUFFER_ANGLE)

+        {

+            return error(GL_INVALID_ENUM);

+        }

+

+        switch(attachment)

+        {

+          case GL_COLOR_ATTACHMENT0:

+          case GL_DEPTH_ATTACHMENT:

+          case GL_STENCIL_ATTACHMENT:

+            break;

+          default:

+            return error(GL_INVALID_ENUM);

+        }

+

+        gl::Context *context = gl::getContext();

+

+        if(context)

+        {

+            if(texture == 0)

+            {

+                textarget = GL_NONE;

+            }

+            else

+            {

+                gl::Texture *tex = context->getTexture(texture);

+

+                if(tex == NULL)

+                {

+                    return error(GL_INVALID_OPERATION);

+                }

+

+                if(tex->isCompressed(textarget, level))

+                {

+                    return error(GL_INVALID_OPERATION);

+                }

+

+                switch(textarget)

+                {

+                  case GL_TEXTURE_2D:

+                    if(tex->getTarget() != GL_TEXTURE_2D)

+                    {

+                        return error(GL_INVALID_OPERATION);

+                    }

+                    break;

+

+                  case GL_TEXTURE_CUBE_MAP_POSITIVE_X:

+                  case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:

+                  case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:

+                  case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:

+                  case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:

+                  case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:

+                    if(tex->getTarget() != GL_TEXTURE_CUBE_MAP)

+                    {

+                        return error(GL_INVALID_OPERATION);

+                    }

+                    break;

+

+                  default:

+                    return error(GL_INVALID_ENUM);

+                }

+

+                if(level != 0)

+                {

+                    return error(GL_INVALID_VALUE);

+                }

+            }

+

+            gl::Framebuffer *framebuffer = NULL;

+            GLuint framebufferHandle = 0;

+            if(target == GL_READ_FRAMEBUFFER_ANGLE)

+            {

+                framebuffer = context->getReadFramebuffer();

+                framebufferHandle = context->getReadFramebufferHandle();

+            }

+            else

+            {

+                framebuffer = context->getDrawFramebuffer();

+                framebufferHandle = context->getDrawFramebufferHandle();

+            }

+

+            if(framebufferHandle == 0 || !framebuffer)

+            {

+                return error(GL_INVALID_OPERATION);

+            }

+

+            switch(attachment)

+            {

+              case GL_COLOR_ATTACHMENT0:  framebuffer->setColorbuffer(textarget, texture);   break;

+              case GL_DEPTH_ATTACHMENT:   framebuffer->setDepthbuffer(textarget, texture);   break;

+              case GL_STENCIL_ATTACHMENT: framebuffer->setStencilbuffer(textarget, texture); break;

+            }

+        }

+    }

+    catch(std::bad_alloc&)

+    {

+        return error(GL_OUT_OF_MEMORY);

+    }

+}

+

+void GL_APIENTRY glFrontFace(GLenum mode)

+{

+    TRACE("(GLenum mode = 0x%X)", mode);

+

+    try

+    {

+        switch(mode)

+        {

+          case GL_CW:

+          case GL_CCW:

+            {

+                gl::Context *context = gl::getContext();

+

+                if(context)

+                {

+                    context->setFrontFace(mode);

+                }

+            }

+            break;

+          default:

+            return error(GL_INVALID_ENUM);

+        }

+    }

+    catch(std::bad_alloc&)

+    {

+        return error(GL_OUT_OF_MEMORY);

+    }

+}

+

+void GL_APIENTRY glGenBuffers(GLsizei n, GLuint* buffers)

+{

+    TRACE("(GLsizei n = %d, GLuint* buffers = 0x%0.8p)", n, buffers);

+

+    try

+    {

+        if(n < 0)

+        {

+            return error(GL_INVALID_VALUE);

+        }

+

+        gl::Context *context = gl::getContext();

+

+        if(context)

+        {

+            for(int i = 0; i < n; i++)

+            {

+                buffers[i] = context->createBuffer();

+            }

+        }

+    }

+    catch(std::bad_alloc&)

+    {

+        return error(GL_OUT_OF_MEMORY);

+    }

+}

+

+void GL_APIENTRY glGenerateMipmap(GLenum target)

+{

+    TRACE("(GLenum target = 0x%X)", target);

+

+    try

+    {

+        gl::Context *context = gl::getContext();

+

+        if(context)

+        {

+            gl::Texture *texture;

+

+            switch(target)

+            {

+              case GL_TEXTURE_2D:

+                texture = context->getTexture2D();

+                break;

+              case GL_TEXTURE_CUBE_MAP:

+                texture = context->getTextureCubeMap();

+                break;

+              default:

+                return error(GL_INVALID_ENUM);

+            }

+

+            if(texture->isCompressed(target, 0) || texture->isDepth(target, 0))

+            {

+                return error(GL_INVALID_OPERATION);

+            }

+

+            texture->generateMipmaps();

+        }

+    }

+    catch(std::bad_alloc&)

+    {

+        return error(GL_OUT_OF_MEMORY);

+    }

+}

+

+void GL_APIENTRY glGenFencesNV(GLsizei n, GLuint* fences)

+{

+    TRACE("(GLsizei n = %d, GLuint* fences = 0x%0.8p)", n, fences);

+

+    try

+    {

+        if(n < 0)

+        {

+            return error(GL_INVALID_VALUE);

+        }

+

+        gl::Context *context = gl::getContext();

+

+        if(context)

+        {

+            for(int i = 0; i < n; i++)

+            {

+                fences[i] = context->createFence();

+            }

+        }

+    }

+    catch(std::bad_alloc&)

+    {

+        return error(GL_OUT_OF_MEMORY);

+    }

+}

+

+void GL_APIENTRY glGenFramebuffers(GLsizei n, GLuint* framebuffers)

+{

+    TRACE("(GLsizei n = %d, GLuint* framebuffers = 0x%0.8p)", n, framebuffers);

+

+    try

+    {

+        if(n < 0)

+        {

+            return error(GL_INVALID_VALUE);

+        }

+

+        gl::Context *context = gl::getContext();

+

+        if(context)

+        {

+            for(int i = 0; i < n; i++)

+            {

+                framebuffers[i] = context->createFramebuffer();

+            }

+        }

+    }

+    catch(std::bad_alloc&)

+    {

+        return error(GL_OUT_OF_MEMORY);

+    }

+}

+

+void GL_APIENTRY glGenQueriesEXT(GLsizei n, GLuint* ids)

+{

+    TRACE("(GLsizei n = %d, GLuint* ids = 0x%0.8p)", n, ids);

+

+    try

+    {

+        if(n < 0)

+        {

+            return error(GL_INVALID_VALUE);

+        }

+

+        gl::Context *context = gl::getContext();

+

+        if(context)

+        {

+            for(int i = 0; i < n; i++)

+            {

+                ids[i] = context->createQuery();

+            }

+        }

+    }

+    catch(std::bad_alloc&)

+    {

+        return error(GL_OUT_OF_MEMORY);

+    }

+}

+

+void GL_APIENTRY glGenRenderbuffers(GLsizei n, GLuint* renderbuffers)

+{

+    TRACE("(GLsizei n = %d, GLuint* renderbuffers = 0x%0.8p)", n, renderbuffers);

+

+    try

+    {

+        if(n < 0)

+        {

+            return error(GL_INVALID_VALUE);

+        }

+

+        gl::Context *context = gl::getContext();

+

+        if(context)

+        {

+            for(int i = 0; i < n; i++)

+            {

+                renderbuffers[i] = context->createRenderbuffer();

+            }

+        }

+    }

+    catch(std::bad_alloc&)

+    {

+        return error(GL_OUT_OF_MEMORY);

+    }

+}

+

+void GL_APIENTRY glGenTextures(GLsizei n, GLuint* textures)

+{

+    TRACE("(GLsizei n = %d, GLuint* textures =  0x%0.8p)", n, textures);

+

+    try

+    {

+        if(n < 0)

+        {

+            return error(GL_INVALID_VALUE);

+        }

+

+        gl::Context *context = gl::getContext();

+

+        if(context)

+        {

+            for(int i = 0; i < n; i++)

+            {

+                textures[i] = context->createTexture();

+            }

+        }

+    }

+    catch(std::bad_alloc&)

+    {

+        return error(GL_OUT_OF_MEMORY);

+    }

+}

+

+void GL_APIENTRY glGetActiveAttrib(GLuint program, GLuint index, GLsizei bufsize, GLsizei *length, GLint *size, GLenum *type, GLchar *name)

+{

+    TRACE("(GLuint program = %d, GLuint index = %d, GLsizei bufsize = %d, GLsizei *length = 0x%0.8p, "

+          "GLint *size = 0x%0.8p, GLenum *type = %0.8p, GLchar *name = %0.8p)",

+          program, index, bufsize, length, size, type, name);

+

+    try

+    {

+        if(bufsize < 0)

+        {

+            return error(GL_INVALID_VALUE);

+        }

+

+        gl::Context *context = gl::getContext();

+

+        if(context)

+        {

+            gl::Program *programObject = context->getProgram(program);

+

+            if(!programObject)

+            {

+                if(context->getShader(program))

+                {

+                    return error(GL_INVALID_OPERATION);

+                }

+                else

+                {

+                    return error(GL_INVALID_VALUE);

+                }

+            }

+

+            if(index >= (GLuint)programObject->getActiveAttributeCount())

+            {

+                return error(GL_INVALID_VALUE);

+            }

+

+            programObject->getActiveAttribute(index, bufsize, length, size, type, name);

+        }

+    }

+    catch(std::bad_alloc&)

+    {

+        return error(GL_OUT_OF_MEMORY);

+    }

+}

+

+void GL_APIENTRY glGetActiveUniform(GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, GLchar* name)

+{

+    TRACE("(GLuint program = %d, GLuint index = %d, GLsizei bufsize = %d, "

+          "GLsizei* length = 0x%0.8p, GLint* size = 0x%0.8p, GLenum* type = 0x%0.8p, GLchar* name = 0x%0.8p)",

+          program, index, bufsize, length, size, type, name);

+

+    try

+    {

+        if(bufsize < 0)

+        {

+            return error(GL_INVALID_VALUE);

+        }

+

+        gl::Context *context = gl::getContext();

+

+        if(context)

+        {

+            gl::Program *programObject = context->getProgram(program);

+

+            if(!programObject)

+            {

+                if(context->getShader(program))

+                {

+                    return error(GL_INVALID_OPERATION);

+                }

+                else

+                {

+                    return error(GL_INVALID_VALUE);

+                }

+            }

+

+            if(index >= (GLuint)programObject->getActiveUniformCount())

+            {

+                return error(GL_INVALID_VALUE);

+            }

+

+            programObject->getActiveUniform(index, bufsize, length, size, type, name);

+        }

+    }

+    catch(std::bad_alloc&)

+    {

+        return error(GL_OUT_OF_MEMORY);

+    }

+}

+

+void GL_APIENTRY glGetAttachedShaders(GLuint program, GLsizei maxcount, GLsizei* count, GLuint* shaders)

+{

+    TRACE("(GLuint program = %d, GLsizei maxcount = %d, GLsizei* count = 0x%0.8p, GLuint* shaders = 0x%0.8p)",

+          program, maxcount, count, shaders);

+

+    try

+    {

+        if(maxcount < 0)

+        {

+            return error(GL_INVALID_VALUE);

+        }

+

+        gl::Context *context = gl::getContext();

+

+        if(context)

+        {

+            gl::Program *programObject = context->getProgram(program);

+

+            if(!programObject)

+            {

+                if(context->getShader(program))

+                {

+                    return error(GL_INVALID_OPERATION);

+                }

+                else

+                {

+                    return error(GL_INVALID_VALUE);

+                }

+            }

+

+            return programObject->getAttachedShaders(maxcount, count, shaders);

+        }

+    }

+    catch(std::bad_alloc&)

+    {

+        return error(GL_OUT_OF_MEMORY);

+    }

+}

+

+int GL_APIENTRY glGetAttribLocation(GLuint program, const GLchar* name)

+{

+    TRACE("(GLuint program = %d, const GLchar* name = %s)", program, name);

+

+    try

+    {

+        gl::Context *context = gl::getContext();

+

+        if(context)

+        {

+

+            gl::Program *programObject = context->getProgram(program);

+

+            if(!programObject)

+            {

+                if(context->getShader(program))

+                {

+                    return error(GL_INVALID_OPERATION, -1);

+                }

+                else

+                {

+                    return error(GL_INVALID_VALUE, -1);

+                }

+            }

+

+            if(!programObject->isLinked())

+            {

+                return error(GL_INVALID_OPERATION, -1);

+            }

+

+            return programObject->getAttributeLocation(name);

+        }

+    }

+    catch(std::bad_alloc&)

+    {

+        return error(GL_OUT_OF_MEMORY, -1);

+    }

+

+    return -1;

+}

+

+void GL_APIENTRY glGetBooleanv(GLenum pname, GLboolean* params)

+{

+    TRACE("(GLenum pname = 0x%X, GLboolean* params = 0x%0.8p)",  pname, params);

+

+    try

+    {

+        gl::Context *context = gl::getContext();

+

+        if(context)

+        {

+            if(!(context->getBooleanv(pname, params)))

+            {

+                GLenum nativeType;

+                unsigned int numParams = 0;

+                if(!context->getQueryParameterInfo(pname, &nativeType, &numParams))

+                    return error(GL_INVALID_ENUM);

+

+                if(numParams == 0)

+                    return; // it is known that the pname is valid, but there are no parameters to return

+

+                if(nativeType == GL_FLOAT)

+                {

+                    GLfloat *floatParams = NULL;

+                    floatParams = new GLfloat[numParams];

+

+                    context->getFloatv(pname, floatParams);

+

+                    for(unsigned int i = 0; i < numParams; ++i)

+                    {

+                        if(floatParams[i] == 0.0f)

+                            params[i] = GL_FALSE;

+                        else

+                            params[i] = GL_TRUE;

+                    }

+

+                    delete [] floatParams;

+                }

+                else if(nativeType == GL_INT)

+                {

+                    GLint *intParams = NULL;

+                    intParams = new GLint[numParams];

+

+                    context->getIntegerv(pname, intParams);

+

+                    for(unsigned int i = 0; i < numParams; ++i)

+                    {

+                        if(intParams[i] == 0)

+                            params[i] = GL_FALSE;

+                        else

+                            params[i] = GL_TRUE;

+                    }

+

+                    delete [] intParams;

+                }

+            }

+        }

+    }

+    catch(std::bad_alloc&)

+    {

+        return error(GL_OUT_OF_MEMORY);

+    }

+}

+

+void GL_APIENTRY glGetBufferParameteriv(GLenum target, GLenum pname, GLint* params)

+{

+    TRACE("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint* params = 0x%0.8p)", target, pname, params);

+

+    try

+    {

+        gl::Context *context = gl::getContext();

+

+        if(context)

+        {

+            gl::Buffer *buffer;

+

+            switch(target)

+            {

+              case GL_ARRAY_BUFFER:

+                buffer = context->getArrayBuffer();

+                break;

+              case GL_ELEMENT_ARRAY_BUFFER:

+                buffer = context->getElementArrayBuffer();

+                break;

+              default: return error(GL_INVALID_ENUM);

+            }

+

+            if(!buffer)

+            {

+                // A null buffer means that "0" is bound to the requested buffer target

+                return error(GL_INVALID_OPERATION);

+            }

+

+            switch(pname)

+            {

+              case GL_BUFFER_USAGE:

+                *params = buffer->usage();

+                break;

+              case GL_BUFFER_SIZE:

+                *params = buffer->size();

+                break;

+              default: return error(GL_INVALID_ENUM);

+            }

+        }

+    }

+    catch(std::bad_alloc&)

+    {

+        return error(GL_OUT_OF_MEMORY);

+    }

+}

+

+GLenum GL_APIENTRY glGetError(void)

+{

+    TRACE("()");

+

+    gl::Context *context = gl::getContext();

+

+    if(context)

+    {

+        return context->getError();

+    }

+

+    return GL_NO_ERROR;

+}

+

+void GL_APIENTRY glGetFenceivNV(GLuint fence, GLenum pname, GLint *params)

+{

+    TRACE("(GLuint fence = %d, GLenum pname = 0x%X, GLint *params = 0x%0.8p)", fence, pname, params);

+

+    try

+    {

+        gl::Context *context = gl::getContext();

+

+        if(context)

+        {

+            gl::Fence *fenceObject = context->getFence(fence);

+

+            if(fenceObject == NULL)

+            {

+                return error(GL_INVALID_OPERATION);

+            }

+

+            fenceObject->getFenceiv(pname, params);

+        }

+    }

+    catch(std::bad_alloc&)

+    {

+        return error(GL_OUT_OF_MEMORY);

+    }

+}

+

+void GL_APIENTRY glGetFloatv(GLenum pname, GLfloat* params)

+{

+    TRACE("(GLenum pname = 0x%X, GLfloat* params = 0x%0.8p)", pname, params);

+

+    try

+    {

+        gl::Context *context = gl::getContext();

+

+        if(context)

+        {

+            if(!(context->getFloatv(pname, params)))

+            {

+                GLenum nativeType;

+                unsigned int numParams = 0;

+                if(!context->getQueryParameterInfo(pname, &nativeType, &numParams))

+                    return error(GL_INVALID_ENUM);

+

+                if(numParams == 0)

+                    return; // it is known that the pname is valid, but that there are no parameters to return.

+

+                if(nativeType == GL_BOOL)

+                {

+                    GLboolean *boolParams = NULL;

+                    boolParams = new GLboolean[numParams];

+

+                    context->getBooleanv(pname, boolParams);

+

+                    for(unsigned int i = 0; i < numParams; ++i)

+                    {

+                        if(boolParams[i] == GL_FALSE)

+                            params[i] = 0.0f;

+                        else

+                            params[i] = 1.0f;

+                    }

+

+                    delete [] boolParams;

+                }

+                else if(nativeType == GL_INT)

+                {

+                    GLint *intParams = NULL;

+                    intParams = new GLint[numParams];

+

+                    context->getIntegerv(pname, intParams);

+

+                    for(unsigned int i = 0; i < numParams; ++i)

+                    {

+                        params[i] = (GLfloat)intParams[i];

+                    }

+

+                    delete [] intParams;

+                }

+            }

+        }

+    }

+    catch(std::bad_alloc&)

+    {

+        return error(GL_OUT_OF_MEMORY);

+    }

+}

+

+void GL_APIENTRY glGetFramebufferAttachmentParameteriv(GLenum target, GLenum attachment, GLenum pname, GLint* params)

+{

+    TRACE("(GLenum target = 0x%X, GLenum attachment = 0x%X, GLenum pname = 0x%X, GLint* params = 0x%0.8p)",

+          target, attachment, pname, params);

+

+    try

+    {

+        gl::Context *context = gl::getContext();

+

+        if(context)

+        {

+            if(target != GL_FRAMEBUFFER && target != GL_DRAW_FRAMEBUFFER_ANGLE && target != GL_READ_FRAMEBUFFER_ANGLE)

+            {

+                return error(GL_INVALID_ENUM);

+            }

+

+            gl::Framebuffer *framebuffer = NULL;

+            if(target == GL_READ_FRAMEBUFFER_ANGLE)

+            {

+                if(context->getReadFramebufferHandle() == 0)

+                {

+                    return error(GL_INVALID_OPERATION);

+                }

+

+                framebuffer = context->getReadFramebuffer();

+            }

+            else 

+            {

+                if(context->getDrawFramebufferHandle() == 0)

+                {

+                    return error(GL_INVALID_OPERATION);

+                }

+

+                framebuffer = context->getDrawFramebuffer();

+            }

+

+            GLenum attachmentType;

+            GLuint attachmentHandle;

+            switch(attachment)

+            {

+              case GL_COLOR_ATTACHMENT0:    

+                attachmentType = framebuffer->getColorbufferType();

+                attachmentHandle = framebuffer->getColorbufferHandle(); 

+                break;

+              case GL_DEPTH_ATTACHMENT:     

+                attachmentType = framebuffer->getDepthbufferType();

+                attachmentHandle = framebuffer->getDepthbufferHandle();

+                break;

+              case GL_STENCIL_ATTACHMENT:   

+                attachmentType = framebuffer->getStencilbufferType();

+                attachmentHandle = framebuffer->getStencilbufferHandle();

+                break;

+              default: return error(GL_INVALID_ENUM);

+            }

+

+            GLenum attachmentObjectType;   // Type category

+            if(attachmentType == GL_NONE || attachmentType == GL_RENDERBUFFER)

+            {

+                attachmentObjectType = attachmentType;

+            }

+            else if(gl::IsTextureTarget(attachmentType))

+            {

+                attachmentObjectType = GL_TEXTURE;

+            }

+            else UNREACHABLE();

+

+            switch(pname)

+            {

+              case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:

+                *params = attachmentObjectType;

+                break;

+              case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:

+                if(attachmentObjectType == GL_RENDERBUFFER || attachmentObjectType == GL_TEXTURE)

+                {

+                    *params = attachmentHandle;

+                }

+                else

+                {

+                    return error(GL_INVALID_ENUM);

+                }

+                break;

+              case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:

+                if(attachmentObjectType == GL_TEXTURE)

+                {

+                    *params = 0; // FramebufferTexture2D will not allow level to be set to anything else in GL ES 2.0

+                }

+                else

+                {

+                    return error(GL_INVALID_ENUM);

+                }

+                break;

+              case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:

+                if(attachmentObjectType == GL_TEXTURE)

+                {

+                    if(gl::IsCubemapTextureTarget(attachmentType))

+                    {

+                        *params = attachmentType;

+                    }

+                    else

+                    {

+                        *params = 0;

+                    }

+                }

+                else

+                {

+                    return error(GL_INVALID_ENUM);

+                }

+                break;

+              default:

+                return error(GL_INVALID_ENUM);

+            }

+        }

+    }

+    catch(std::bad_alloc&)

+    {

+        return error(GL_OUT_OF_MEMORY);

+    }

+}

+

+GLenum GL_APIENTRY glGetGraphicsResetStatusEXT(void)

+{

+    TRACE("()");

+

+    return GL_NO_ERROR;

+}

+

+void GL_APIENTRY glGetIntegerv(GLenum pname, GLint* params)

+{

+    TRACE("(GLenum pname = 0x%X, GLint* params = 0x%0.8p)", pname, params);

+

+    try

+    {

+        gl::Context *context = gl::getContext();

+

+        if(context)

+        {

+            if(!(context->getIntegerv(pname, params)))

+            {

+                GLenum nativeType;

+                unsigned int numParams = 0;

+                if(!context->getQueryParameterInfo(pname, &nativeType, &numParams))

+                    return error(GL_INVALID_ENUM);

+

+                if(numParams == 0)

+                    return; // it is known that pname is valid, but there are no parameters to return

+

+                if(nativeType == GL_BOOL)

+                {

+                    GLboolean *boolParams = NULL;

+                    boolParams = new GLboolean[numParams];

+

+                    context->getBooleanv(pname, boolParams);

+

+                    for(unsigned int i = 0; i < numParams; ++i)

+                    {

+                        if(boolParams[i] == GL_FALSE)

+                            params[i] = 0;

+                        else

+                            params[i] = 1;

+                    }

+

+                    delete [] boolParams;

+                }

+                else if(nativeType == GL_FLOAT)

+                {

+                    GLfloat *floatParams = NULL;

+                    floatParams = new GLfloat[numParams];

+

+                    context->getFloatv(pname, floatParams);

+

+                    for(unsigned int i = 0; i < numParams; ++i)

+                    {

+                        if(pname == GL_DEPTH_RANGE || pname == GL_COLOR_CLEAR_VALUE || pname == GL_DEPTH_CLEAR_VALUE || pname == GL_BLEND_COLOR)

+                        {

+                            params[i] = (GLint)(((GLfloat)(0xFFFFFFFF) * floatParams[i] - 1.0f) / 2.0f);

+                        }

+                        else

+                            params[i] = (GLint)(floatParams[i] > 0.0f ? floor(floatParams[i] + 0.5) : ceil(floatParams[i] - 0.5));

+                    }

+

+                    delete [] floatParams;

+                }

+            }

+        }

+    }

+    catch(std::bad_alloc&)

+    {

+        return error(GL_OUT_OF_MEMORY);

+    }

+}

+

+void GL_APIENTRY glGetProgramiv(GLuint program, GLenum pname, GLint* params)

+{

+    TRACE("(GLuint program = %d, GLenum pname = %d, GLint* params = 0x%0.8p)", program, pname, params);

+

+    try

+    {

+        gl::Context *context = gl::getContext();

+

+        if(context)

+        {

+            gl::Program *programObject = context->getProgram(program);

+

+            if(!programObject)

+            {

+                return error(GL_INVALID_VALUE);

+            }

+

+            switch(pname)

+            {

+              case GL_DELETE_STATUS:

+                *params = programObject->isFlaggedForDeletion();

+                return;

+              case GL_LINK_STATUS:

+                *params = programObject->isLinked();

+                return;

+              case GL_VALIDATE_STATUS:

+                *params = programObject->isValidated();

+                return;

+              case GL_INFO_LOG_LENGTH:

+                *params = programObject->getInfoLogLength();

+                return;

+              case GL_ATTACHED_SHADERS:

+                *params = programObject->getAttachedShadersCount();

+                return;

+              case GL_ACTIVE_ATTRIBUTES:

+                *params = programObject->getActiveAttributeCount();

+                return;

+              case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH:

+                *params = programObject->getActiveAttributeMaxLength();

+                return;

+              case GL_ACTIVE_UNIFORMS:

+                *params = programObject->getActiveUniformCount();

+                return;

+              case GL_ACTIVE_UNIFORM_MAX_LENGTH:

+                *params = programObject->getActiveUniformMaxLength();

+                return;

+              default:

+                return error(GL_INVALID_ENUM);

+            }

+        }

+    }

+    catch(std::bad_alloc&)

+    {

+        return error(GL_OUT_OF_MEMORY);

+    }

+}

+

+void GL_APIENTRY glGetProgramInfoLog(GLuint program, GLsizei bufsize, GLsizei* length, GLchar* infolog)

+{

+    TRACE("(GLuint program = %d, GLsizei bufsize = %d, GLsizei* length = 0x%0.8p, GLchar* infolog = 0x%0.8p)",

+          program, bufsize, length, infolog);

+

+    try

+    {

+        if(bufsize < 0)

+        {

+            return error(GL_INVALID_VALUE);

+        }

+

+        gl::Context *context = gl::getContext();

+

+        if(context)

+        {

+            gl::Program *programObject = context->getProgram(program);

+

+            if(!programObject)

+            {

+                return error(GL_INVALID_VALUE);

+            }

+

+            programObject->getInfoLog(bufsize, length, infolog);

+        }

+    }

+    catch(std::bad_alloc&)

+    {

+        return error(GL_OUT_OF_MEMORY);

+    }

+}

+

+void GL_APIENTRY glGetQueryivEXT(GLenum target, GLenum pname, GLint *params)

+{

+    TRACE("GLenum target = 0x%X, GLenum pname = 0x%X, GLint *params = 0x%0.8p)", target, pname, params);

+

+    try

+    {

+        switch(pname)

+        {

+        case GL_CURRENT_QUERY_EXT:

+            break;

+        default:

+            return error(GL_INVALID_ENUM);

+        }

+

+        gl::Context *context = gl::getContext();

+

+        if(context)

+        {

+            params[0] = context->getActiveQuery(target);

+        }

+    }

+    catch(std::bad_alloc&)

+    {

+        return error(GL_OUT_OF_MEMORY);

+    }

+}

+

+void GL_APIENTRY glGetQueryObjectuivEXT(GLuint id, GLenum pname, GLuint *params)

+{

+    TRACE("(GLuint id = %d, GLenum pname = 0x%X, GLuint *params = 0x%0.8p)", id, pname, params);

+

+    try

+    {

+        switch(pname)

+        {

+        case GL_QUERY_RESULT_EXT:

+        case GL_QUERY_RESULT_AVAILABLE_EXT:

+            break;

+        default:

+            return error(GL_INVALID_ENUM);

+        }

+

+        gl::Context *context = gl::getContext();

+

+        if(context)

+        {

+            gl::Query *queryObject = context->getQuery(id, false, GL_NONE);

+

+            if(!queryObject)

+            {

+                return error(GL_INVALID_OPERATION);

+            }

+

+            if(context->getActiveQuery(queryObject->getType()) == id)

+            {

+                return error(GL_INVALID_OPERATION);

+            }

+

+            switch(pname)

+            {

+            case GL_QUERY_RESULT_EXT:

+                params[0] = queryObject->getResult();

+                break;

+            case GL_QUERY_RESULT_AVAILABLE_EXT:

+                params[0] = queryObject->isResultAvailable();

+                break;

+            default:

+                ASSERT(false);

+            }

+        }

+    }

+    catch(std::bad_alloc&)

+    {

+        return error(GL_OUT_OF_MEMORY);

+    }

+}

+

+void GL_APIENTRY glGetRenderbufferParameteriv(GLenum target, GLenum pname, GLint* params)

+{

+    TRACE("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint* params = 0x%0.8p)", target, pname, params);

+

+    try

+    {

+        gl::Context *context = gl::getContext();

+

+        if(context)

+        {

+            if(target != GL_RENDERBUFFER)

+            {

+                return error(GL_INVALID_ENUM);

+            }

+

+            if(context->getRenderbufferHandle() == 0)

+            {

+                return error(GL_INVALID_OPERATION);

+            }

+

+            gl::Renderbuffer *renderbuffer = context->getRenderbuffer(context->getRenderbufferHandle());

+

+            switch(pname)

+            {

+              case GL_RENDERBUFFER_WIDTH:           *params = renderbuffer->getWidth();       break;

+              case GL_RENDERBUFFER_HEIGHT:          *params = renderbuffer->getHeight();      break;

+              case GL_RENDERBUFFER_INTERNAL_FORMAT: *params = renderbuffer->getFormat();      break;

+              case GL_RENDERBUFFER_RED_SIZE:        *params = renderbuffer->getRedSize();     break;

+              case GL_RENDERBUFFER_GREEN_SIZE:      *params = renderbuffer->getGreenSize();   break;

+              case GL_RENDERBUFFER_BLUE_SIZE:       *params = renderbuffer->getBlueSize();    break;

+              case GL_RENDERBUFFER_ALPHA_SIZE:      *params = renderbuffer->getAlphaSize();   break;

+              case GL_RENDERBUFFER_DEPTH_SIZE:      *params = renderbuffer->getDepthSize();   break;

+              case GL_RENDERBUFFER_STENCIL_SIZE:    *params = renderbuffer->getStencilSize(); break;

+              case GL_RENDERBUFFER_SAMPLES_ANGLE:

+                if(gl::IMPLEMENTATION_MAX_SAMPLES != 0)

+                {

+                    *params = renderbuffer->getSamples();

+                }

+                else

+                {

+                    return error(GL_INVALID_ENUM);

+                }

+                break;

+              default:

+                return error(GL_INVALID_ENUM);

+            }

+        }

+    }

+    catch(std::bad_alloc&)

+    {

+        return error(GL_OUT_OF_MEMORY);

+    }

+}

+

+void GL_APIENTRY glGetShaderiv(GLuint shader, GLenum pname, GLint* params)

+{

+    TRACE("(GLuint shader = %d, GLenum pname = %d, GLint* params = 0x%0.8p)", shader, pname, params);

+

+    try

+    {

+        gl::Context *context = gl::getContext();

+

+        if(context)

+        {

+            gl::Shader *shaderObject = context->getShader(shader);

+

+            if(!shaderObject)

+            {

+                return error(GL_INVALID_VALUE);

+            }

+

+            switch(pname)

+            {

+              case GL_SHADER_TYPE:

+                *params = shaderObject->getType();

+                return;

+              case GL_DELETE_STATUS:

+                *params = shaderObject->isFlaggedForDeletion();

+                return;

+              case GL_COMPILE_STATUS:

+                *params = shaderObject->isCompiled() ? GL_TRUE : GL_FALSE;

+                return;

+              case GL_INFO_LOG_LENGTH:

+                *params = shaderObject->getInfoLogLength();

+                return;

+              case GL_SHADER_SOURCE_LENGTH:

+                *params = shaderObject->getSourceLength();

+                return;

+              default:

+                return error(GL_INVALID_ENUM);

+            }

+        }

+    }

+    catch(std::bad_alloc&)

+    {

+        return error(GL_OUT_OF_MEMORY);

+    }

+}

+

+void GL_APIENTRY glGetShaderInfoLog(GLuint shader, GLsizei bufsize, GLsizei* length, GLchar* infolog)

+{

+    TRACE("(GLuint shader = %d, GLsizei bufsize = %d, GLsizei* length = 0x%0.8p, GLchar* infolog = 0x%0.8p)",

+          shader, bufsize, length, infolog);

+

+    try

+    {

+        if(bufsize < 0)

+        {

+            return error(GL_INVALID_VALUE);

+        }

+

+        gl::Context *context = gl::getContext();

+

+        if(context)

+        {

+            gl::Shader *shaderObject = context->getShader(shader);

+

+            if(!shaderObject)

+            {

+                return error(GL_INVALID_VALUE);

+            }

+

+            shaderObject->getInfoLog(bufsize, length, infolog);

+        }

+    }

+    catch(std::bad_alloc&)

+    {

+        return error(GL_OUT_OF_MEMORY);

+    }

+}

+

+void GL_APIENTRY glGetShaderPrecisionFormat(GLenum shadertype, GLenum precisiontype, GLint* range, GLint* precision)

+{

+    TRACE("(GLenum shadertype = 0x%X, GLenum precisiontype = 0x%X, GLint* range = 0x%0.8p, GLint* precision = 0x%0.8p)",

+          shadertype, precisiontype, range, precision);

+

+    try

+    {

+        switch(shadertype)

+        {

+          case GL_VERTEX_SHADER:

+          case GL_FRAGMENT_SHADER:

+            break;

+          default:

+            return error(GL_INVALID_ENUM);

+        }

+

+        switch(precisiontype)

+        {

+          case GL_LOW_FLOAT:

+          case GL_MEDIUM_FLOAT:

+          case GL_HIGH_FLOAT:

+            // IEEE 754 single-precision

+            range[0] = 127;

+            range[1] = 127;

+            *precision = 23;

+            break;

+          case GL_LOW_INT:

+          case GL_MEDIUM_INT:

+          case GL_HIGH_INT:

+            // Single-precision floating-point numbers can accurately represent integers up to +/-16777216

+            range[0] = 24;

+            range[1] = 24;

+            *precision = 0;

+            break;

+          default:

+            return error(GL_INVALID_ENUM);

+        }

+    }

+    catch(std::bad_alloc&)

+    {

+        return error(GL_OUT_OF_MEMORY);

+    }

+}

+

+void GL_APIENTRY glGetShaderSource(GLuint shader, GLsizei bufsize, GLsizei* length, GLchar* source)

+{

+    TRACE("(GLuint shader = %d, GLsizei bufsize = %d, GLsizei* length = 0x%0.8p, GLchar* source = 0x%0.8p)",

+          shader, bufsize, length, source);

+

+    try

+    {

+        if(bufsize < 0)

+        {

+            return error(GL_INVALID_VALUE);

+        }

+

+        gl::Context *context = gl::getContext();

+

+        if(context)

+        {

+            gl::Shader *shaderObject = context->getShader(shader);

+

+            if(!shaderObject)

+            {

+                return error(GL_INVALID_OPERATION);

+            }

+

+            shaderObject->getSource(bufsize, length, source);

+        }

+    }

+    catch(std::bad_alloc&)

+    {

+        return error(GL_OUT_OF_MEMORY);

+    }

+}

+

+const GLubyte* GL_APIENTRY glGetString(GLenum name)

+{

+    TRACE("(GLenum name = 0x%X)", name);

+

+    try

+    {

+        gl::Context *context = gl::getContext();

+

+        switch(name)

+        {

+          case GL_VENDOR:

+            return (GLubyte*)"TransGaming Inc.";

+          case GL_RENDERER:

+            return (GLubyte*)"SwiftShader";

+          case GL_VERSION:

+            return (GLubyte*)"OpenGL ES 2.0 SwiftShader "VERSION_STRING;

+          case GL_SHADING_LANGUAGE_VERSION:

+            return (GLubyte*)"OpenGL ES GLSL ES 1.00 SwiftShader "VERSION_STRING;

+          case GL_EXTENSIONS:

+            return (GLubyte*)((context != NULL) ? context->getExtensionString() : "");

+          default:

+            return error(GL_INVALID_ENUM, (GLubyte*)NULL);

+        }

+    }

+    catch(std::bad_alloc&)

+    {

+        return error(GL_OUT_OF_MEMORY, (GLubyte*)NULL);

+    }

+

+    return NULL;

+}

+

+void GL_APIENTRY glGetTexParameterfv(GLenum target, GLenum pname, GLfloat* params)

+{

+    TRACE("(GLenum target = 0x%X, GLenum pname = 0x%X, GLfloat* params = 0x%0.8p)", target, pname, params);

+

+    try

+    {

+        gl::Context *context = gl::getContext();

+

+        if(context)

+        {

+            gl::Texture *texture;

+

+            switch(target)

+            {

+              case GL_TEXTURE_2D:

+                texture = context->getTexture2D();

+                break;

+              case GL_TEXTURE_CUBE_MAP:

+                texture = context->getTextureCubeMap();

+                break;

+              default:

+                return error(GL_INVALID_ENUM);

+            }

+

+            switch(pname)

+            {

+              case GL_TEXTURE_MAG_FILTER:

+                *params = (GLfloat)texture->getMagFilter();

+                break;

+              case GL_TEXTURE_MIN_FILTER:

+                *params = (GLfloat)texture->getMinFilter();

+                break;

+              case GL_TEXTURE_WRAP_S:

+                *params = (GLfloat)texture->getWrapS();

+                break;

+              case GL_TEXTURE_WRAP_T:

+                *params = (GLfloat)texture->getWrapT();

+                break;

+			  case GL_TEXTURE_MAX_ANISOTROPY_EXT:

+                *params = texture->getMaxAnisotropy();

+                break;

+              default:

+                return error(GL_INVALID_ENUM);

+            }

+        }

+    }

+    catch(std::bad_alloc&)

+    {

+        return error(GL_OUT_OF_MEMORY);

+    }

+}

+

+void GL_APIENTRY glGetTexParameteriv(GLenum target, GLenum pname, GLint* params)

+{

+    TRACE("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint* params = 0x%0.8p)", target, pname, params);

+

+    try

+    {

+        gl::Context *context = gl::getContext();

+

+        if(context)

+        {

+            gl::Texture *texture;

+

+            switch(target)

+            {

+              case GL_TEXTURE_2D:

+                texture = context->getTexture2D();

+                break;

+              case GL_TEXTURE_CUBE_MAP:

+                texture = context->getTextureCubeMap();

+                break;

+              default:

+                return error(GL_INVALID_ENUM);

+            }

+

+            switch(pname)

+            {

+              case GL_TEXTURE_MAG_FILTER:

+                *params = texture->getMagFilter();

+                break;

+              case GL_TEXTURE_MIN_FILTER:

+                *params = texture->getMinFilter();

+                break;

+              case GL_TEXTURE_WRAP_S:

+                *params = texture->getWrapS();

+                break;

+              case GL_TEXTURE_WRAP_T:

+                *params = texture->getWrapT();

+                break;

+			  case GL_TEXTURE_MAX_ANISOTROPY_EXT:

+                *params = (GLint)texture->getMaxAnisotropy();

+                break;

+              default:

+                return error(GL_INVALID_ENUM);

+            }

+        }

+    }

+    catch(std::bad_alloc&)

+    {

+        return error(GL_OUT_OF_MEMORY);

+    }

+}

+

+void GL_APIENTRY glGetnUniformfvEXT(GLuint program, GLint location, GLsizei bufSize, GLfloat* params)

+{

+    TRACE("(GLuint program = %d, GLint location = %d, GLsizei bufSize = %d, GLfloat* params = 0x%0.8p)",

+          program, location, bufSize, params);

+

+    try

+    {

+        if(bufSize < 0)

+        {

+            return error(GL_INVALID_VALUE);

+        }

+

+        gl::Context *context = gl::getContext();

+

+        if(context)

+        {

+            if(program == 0)

+            {

+                return error(GL_INVALID_VALUE);

+            }

+

+            gl::Program *programObject = context->getProgram(program);

+

+            if(!programObject || !programObject->isLinked())

+            {

+                return error(GL_INVALID_OPERATION);

+            }

+

+            if(!programObject->getUniformfv(location, &bufSize, params))

+            {

+                return error(GL_INVALID_OPERATION);

+            }

+        }

+    }

+    catch(std::bad_alloc&)

+    {

+        return error(GL_OUT_OF_MEMORY);

+    }

+}

+

+void GL_APIENTRY glGetUniformfv(GLuint program, GLint location, GLfloat* params)

+{

+    TRACE("(GLuint program = %d, GLint location = %d, GLfloat* params = 0x%0.8p)", program, location, params);

+

+    try

+    {

+        gl::Context *context = gl::getContext();

+

+        if(context)

+        {

+            if(program == 0)

+            {

+                return error(GL_INVALID_VALUE);

+            }

+

+            gl::Program *programObject = context->getProgram(program);

+

+            if(!programObject || !programObject->isLinked())

+            {

+                return error(GL_INVALID_OPERATION);

+            }

+

+            if(!programObject->getUniformfv(location, NULL, params))

+            {

+                return error(GL_INVALID_OPERATION);

+            }

+        }

+    }

+    catch(std::bad_alloc&)

+    {

+        return error(GL_OUT_OF_MEMORY);

+    }

+}

+

+void GL_APIENTRY glGetnUniformivEXT(GLuint program, GLint location, GLsizei bufSize, GLint* params)

+{

+    TRACE("(GLuint program = %d, GLint location = %d, GLsizei bufSize = %d, GLint* params = 0x%0.8p)", 

+          program, location, bufSize, params);

+

+    try

+    {

+        if(bufSize < 0)

+        {

+            return error(GL_INVALID_VALUE);

+        }

+

+        gl::Context *context = gl::getContext();

+

+        if(context)

+        {

+            if(program == 0)

+            {

+                return error(GL_INVALID_VALUE);

+            }

+

+            gl::Program *programObject = context->getProgram(program);

+

+            if(!programObject || !programObject->isLinked())

+            {

+                return error(GL_INVALID_OPERATION);

+            }

+

+            if(!programObject)

+            {

+                return error(GL_INVALID_OPERATION);

+            }

+

+            if(!programObject->getUniformiv(location, &bufSize, params))

+            {

+                return error(GL_INVALID_OPERATION);

+            }

+        }

+    }

+    catch(std::bad_alloc&)

+    {

+        return error(GL_OUT_OF_MEMORY);

+    }

+}

+

+void GL_APIENTRY glGetUniformiv(GLuint program, GLint location, GLint* params)

+{

+    TRACE("(GLuint program = %d, GLint location = %d, GLint* params = 0x%0.8p)", program, location, params);

+

+    try

+    {

+        gl::Context *context = gl::getContext();

+

+        if(context)

+        {

+            if(program == 0)

+            {

+                return error(GL_INVALID_VALUE);

+            }

+

+            gl::Program *programObject = context->getProgram(program);

+

+            if(!programObject || !programObject->isLinked())

+            {

+                return error(GL_INVALID_OPERATION);

+            }

+

+            if(!programObject)

+            {

+                return error(GL_INVALID_OPERATION);

+            }

+

+            if(!programObject->getUniformiv(location, NULL, params))

+            {

+                return error(GL_INVALID_OPERATION);

+            }

+        }

+    }

+    catch(std::bad_alloc&)

+    {

+        return error(GL_OUT_OF_MEMORY);

+    }

+}

+

+int GL_APIENTRY glGetUniformLocation(GLuint program, const GLchar* name)

+{

+    TRACE("(GLuint program = %d, const GLchar* name = 0x%0.8p)", program, name);

+

+    try

+    {

+        gl::Context *context = gl::getContext();

+

+        if(strstr(name, "gl_") == name)

+        {

+            return -1;

+        }

+

+        if(context)

+        {

+            gl::Program *programObject = context->getProgram(program);

+

+            if(!programObject)

+            {

+                if(context->getShader(program))

+                {

+                    return error(GL_INVALID_OPERATION, -1);

+                }

+                else

+                {

+                    return error(GL_INVALID_VALUE, -1);

+                }

+            }

+

+            if(!programObject->isLinked())

+            {

+                return error(GL_INVALID_OPERATION, -1);

+            }

+

+            return programObject->getUniformLocation(name);

+        }

+    }

+    catch(std::bad_alloc&)

+    {

+        return error(GL_OUT_OF_MEMORY, -1);

+    }

+

+    return -1;

+}

+

+void GL_APIENTRY glGetVertexAttribfv(GLuint index, GLenum pname, GLfloat* params)

+{

+    TRACE("(GLuint index = %d, GLenum pname = 0x%X, GLfloat* params = 0x%0.8p)", index, pname, params);

+

+    try

+    {

+        gl::Context *context = gl::getContext();

+

+        if(context)

+        {

+            if(index >= gl::MAX_VERTEX_ATTRIBS)

+            {

+                return error(GL_INVALID_VALUE);

+            }

+

+            const gl::VertexAttribute &attribState = context->getVertexAttribState(index);

+

+            switch(pname)

+            {

+              case GL_VERTEX_ATTRIB_ARRAY_ENABLED:

+                *params = (GLfloat)(attribState.mArrayEnabled ? GL_TRUE : GL_FALSE);

+                break;

+              case GL_VERTEX_ATTRIB_ARRAY_SIZE:

+                *params = (GLfloat)attribState.mSize;

+                break;

+              case GL_VERTEX_ATTRIB_ARRAY_STRIDE:

+                *params = (GLfloat)attribState.mStride;

+                break;

+              case GL_VERTEX_ATTRIB_ARRAY_TYPE:

+                *params = (GLfloat)attribState.mType;

+                break;

+              case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:

+                *params = (GLfloat)(attribState.mNormalized ? GL_TRUE : GL_FALSE);

+                break;

+              case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING:

+                *params = (GLfloat)attribState.mBoundBuffer.id();

+                break;

+              case GL_CURRENT_VERTEX_ATTRIB:

+                for(int i = 0; i < 4; ++i)

+                {

+                    params[i] = attribState.mCurrentValue[i];

+                }

+                break;

+              default: return error(GL_INVALID_ENUM);

+            }

+        }

+    }

+    catch(std::bad_alloc&)

+    {

+        return error(GL_OUT_OF_MEMORY);

+    }

+}

+

+void GL_APIENTRY glGetVertexAttribiv(GLuint index, GLenum pname, GLint* params)

+{

+    TRACE("(GLuint index = %d, GLenum pname = 0x%X, GLint* params = 0x%0.8p)", index, pname, params);

+

+    try

+    {

+        gl::Context *context = gl::getContext();

+

+        if(context)

+        {

+            if(index >= gl::MAX_VERTEX_ATTRIBS)

+            {

+                return error(GL_INVALID_VALUE);

+            }

+

+            const gl::VertexAttribute &attribState = context->getVertexAttribState(index);

+

+            switch(pname)

+            {

+              case GL_VERTEX_ATTRIB_ARRAY_ENABLED:

+                *params = (attribState.mArrayEnabled ? GL_TRUE : GL_FALSE);

+                break;

+              case GL_VERTEX_ATTRIB_ARRAY_SIZE:

+                *params = attribState.mSize;

+                break;

+              case GL_VERTEX_ATTRIB_ARRAY_STRIDE:

+                *params = attribState.mStride;

+                break;

+              case GL_VERTEX_ATTRIB_ARRAY_TYPE:

+                *params = attribState.mType;

+                break;

+              case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:

+                *params = (attribState.mNormalized ? GL_TRUE : GL_FALSE);

+                break;

+              case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING:

+                *params = attribState.mBoundBuffer.id();

+                break;

+              case GL_CURRENT_VERTEX_ATTRIB:

+                for(int i = 0; i < 4; ++i)

+                {

+                    float currentValue = attribState.mCurrentValue[i];

+                    params[i] = (GLint)(currentValue > 0.0f ? floor(currentValue + 0.5f) : ceil(currentValue - 0.5f));

+                }

+                break;

+              default: return error(GL_INVALID_ENUM);

+            }

+        }

+    }

+    catch(std::bad_alloc&)

+    {

+        return error(GL_OUT_OF_MEMORY);

+    }

+}

+

+void GL_APIENTRY glGetVertexAttribPointerv(GLuint index, GLenum pname, GLvoid** pointer)

+{

+    TRACE("(GLuint index = %d, GLenum pname = 0x%X, GLvoid** pointer = 0x%0.8p)", index, pname, pointer);

+

+    try

+    {

+        gl::Context *context = gl::getContext();

+

+        if(context)

+        {

+            if(index >= gl::MAX_VERTEX_ATTRIBS)

+            {

+                return error(GL_INVALID_VALUE);

+            }

+

+            if(pname != GL_VERTEX_ATTRIB_ARRAY_POINTER)

+            {

+                return error(GL_INVALID_ENUM);

+            }

+

+            *pointer = const_cast<GLvoid*>(context->getVertexAttribPointer(index));

+        }

+    }

+    catch(std::bad_alloc&)

+    {

+        return error(GL_OUT_OF_MEMORY);

+    }

+}

+

+void GL_APIENTRY glHint(GLenum target, GLenum mode)

+{

+    TRACE("(GLenum target = 0x%X, GLenum mode = 0x%X)", target, mode);

+

+    try

+    {

+        switch(mode)

+        {

+          case GL_FASTEST:

+          case GL_NICEST:

+          case GL_DONT_CARE:

+            break;

+          default:

+            return error(GL_INVALID_ENUM); 

+        }

+

+        gl::Context *context = gl::getContext();

+        switch(target)

+        {

+          case GL_GENERATE_MIPMAP_HINT:

+            if(context) context->setGenerateMipmapHint(mode);

+            break;

+          case GL_FRAGMENT_SHADER_DERIVATIVE_HINT_OES:

+            if(context) context->setFragmentShaderDerivativeHint(mode);

+            break;

+          default:

+            return error(GL_INVALID_ENUM);

+        }

+    }

+    catch(std::bad_alloc&)

+    {

+        return error(GL_OUT_OF_MEMORY);

+    }

+}

+

+GLboolean GL_APIENTRY glIsBuffer(GLuint buffer)

+{

+    TRACE("(GLuint buffer = %d)", buffer);

+

+    try

+    {

+        gl::Context *context = gl::getContext();

+

+        if(context && buffer)

+        {

+            gl::Buffer *bufferObject = context->getBuffer(buffer);

+

+            if(bufferObject)

+            {

+                return GL_TRUE;

+            }

+        }

+    }

+    catch(std::bad_alloc&)

+    {

+        return error(GL_OUT_OF_MEMORY, GL_FALSE);

+    }

+

+    return GL_FALSE;

+}

+

+GLboolean GL_APIENTRY glIsEnabled(GLenum cap)

+{

+    TRACE("(GLenum cap = 0x%X)", cap);

+

+    try

+    {

+        gl::Context *context = gl::getContext();

+

+        if(context)

+        {

+            switch(cap)

+            {

+              case GL_CULL_FACE:                return context->isCullFaceEnabled();

+              case GL_POLYGON_OFFSET_FILL:      return context->isPolygonOffsetFillEnabled();

+              case GL_SAMPLE_ALPHA_TO_COVERAGE: return context->isSampleAlphaToCoverageEnabled();

+              case GL_SAMPLE_COVERAGE:          return context->isSampleCoverageEnabled();

+              case GL_SCISSOR_TEST:             return context->isScissorTestEnabled();

+              case GL_STENCIL_TEST:             return context->isStencilTestEnabled();

+              case GL_DEPTH_TEST:               return context->isDepthTestEnabled();

+              case GL_BLEND:                    return context->isBlendEnabled();

+              case GL_DITHER:                   return context->isDitherEnabled();

+              default:

+                return error(GL_INVALID_ENUM, false);

+            }

+        }

+    }

+    catch(std::bad_alloc&)

+    {

+        return error(GL_OUT_OF_MEMORY, false);

+    }

+

+    return false;

+}

+

+GLboolean GL_APIENTRY glIsFenceNV(GLuint fence)

+{

+    TRACE("(GLuint fence = %d)", fence);

+

+    try

+    {

+        gl::Context *context = gl::getContext();

+

+        if(context)

+        {

+            gl::Fence *fenceObject = context->getFence(fence);

+

+            if(fenceObject == NULL)

+            {

+                return GL_FALSE;

+            }

+

+            return fenceObject->isFence();

+        }

+    }

+    catch(std::bad_alloc&)

+    {

+        return error(GL_OUT_OF_MEMORY, GL_FALSE);

+    }

+

+    return GL_FALSE;

+}

+

+GLboolean GL_APIENTRY glIsFramebuffer(GLuint framebuffer)

+{

+    TRACE("(GLuint framebuffer = %d)", framebuffer);

+

+    try

+    {

+        gl::Context *context = gl::getContext();

+

+        if(context && framebuffer)

+        {

+            gl::Framebuffer *framebufferObject = context->getFramebuffer(framebuffer);

+

+            if(framebufferObject)

+            {

+                return GL_TRUE;

+            }

+        }

+    }

+    catch(std::bad_alloc&)

+    {

+        return error(GL_OUT_OF_MEMORY, GL_FALSE);

+    }

+

+    return GL_FALSE;

+}

+

+GLboolean GL_APIENTRY glIsProgram(GLuint program)

+{

+    TRACE("(GLuint program = %d)", program);

+

+    try

+    {

+        gl::Context *context = gl::getContext();

+

+        if(context && program)

+        {

+            gl::Program *programObject = context->getProgram(program);

+

+            if(programObject)

+            {

+                return GL_TRUE;

+            }

+        }

+    }

+    catch(std::bad_alloc&)

+    {

+        return error(GL_OUT_OF_MEMORY, GL_FALSE);

+    }

+

+    return GL_FALSE;

+}

+

+GLboolean GL_APIENTRY glIsQueryEXT(GLuint id)

+{

+    TRACE("(GLuint id = %d)", id);

+

+    try

+    {

+        if(id == 0)

+        {

+            return GL_FALSE;

+        }

+

+        gl::Context *context = gl::getContext();

+

+        if(context)

+        {

+            gl::Query *queryObject = context->getQuery(id, false, GL_NONE);

+

+            if(queryObject)

+            {

+                return GL_TRUE;

+            }

+        }

+    }

+    catch(std::bad_alloc&)

+    {

+        return error(GL_OUT_OF_MEMORY, GL_FALSE);

+    }

+

+    return GL_FALSE;

+}

+

+GLboolean GL_APIENTRY glIsRenderbuffer(GLuint renderbuffer)

+{

+    TRACE("(GLuint renderbuffer = %d)", renderbuffer);

+

+    try

+    {

+        gl::Context *context = gl::getContext();

+

+        if(context && renderbuffer)

+        {

+            gl::Renderbuffer *renderbufferObject = context->getRenderbuffer(renderbuffer);

+

+            if(renderbufferObject)

+            {

+                return GL_TRUE;

+            }

+        }

+    }

+    catch(std::bad_alloc&)

+    {

+        return error(GL_OUT_OF_MEMORY, GL_FALSE);

+    }

+

+    return GL_FALSE;

+}

+

+GLboolean GL_APIENTRY glIsShader(GLuint shader)

+{

+    TRACE("(GLuint shader = %d)", shader);

+

+    try

+    {

+        gl::Context *context = gl::getContext();

+

+        if(context && shader)

+        {

+            gl::Shader *shaderObject = context->getShader(shader);

+

+            if(shaderObject)

+            {

+                return GL_TRUE;

+            }

+        }

+    }

+    catch(std::bad_alloc&)

+    {

+        return error(GL_OUT_OF_MEMORY, GL_FALSE);

+    }

+

+    return GL_FALSE;

+}

+

+GLboolean GL_APIENTRY glIsTexture(GLuint texture)

+{

+    TRACE("(GLuint texture = %d)", texture);

+

+    try

+    {

+        gl::Context *context = gl::getContext();

+

+        if(context && texture)

+        {

+            gl::Texture *textureObject = context->getTexture(texture);

+

+            if(textureObject)

+            {

+                return GL_TRUE;

+            }

+        }

+    }

+    catch(std::bad_alloc&)

+    {

+        return error(GL_OUT_OF_MEMORY, GL_FALSE);

+    }

+

+    return GL_FALSE;

+}

+

+void GL_APIENTRY glLineWidth(GLfloat width)

+{

+    TRACE("(GLfloat width = %f)", width);

+

+    try

+    {

+        if(width <= 0.0f)

+        {

+            return error(GL_INVALID_VALUE);

+        }

+

+        gl::Context *context = gl::getContext();

+

+        if(context)

+        {

+            context->setLineWidth(width);

+        }

+    }

+    catch(std::bad_alloc&)

+    {

+        return error(GL_OUT_OF_MEMORY);

+    }

+}

+

+void GL_APIENTRY glLinkProgram(GLuint program)

+{

+    TRACE("(GLuint program = %d)", program);

+

+    try

+    {

+        gl::Context *context = gl::getContext();

+

+        if(context)

+        {

+            gl::Program *programObject = context->getProgram(program);

+

+            if(!programObject)

+            {

+                if(context->getShader(program))

+                {

+                    return error(GL_INVALID_OPERATION);

+                }

+                else

+                {

+                    return error(GL_INVALID_VALUE);

+                }

+            }

+

+            programObject->link();

+        }

+    }

+    catch(std::bad_alloc&)

+    {

+        return error(GL_OUT_OF_MEMORY);

+    }

+}

+

+void GL_APIENTRY glPixelStorei(GLenum pname, GLint param)

+{

+    TRACE("(GLenum pname = 0x%X, GLint param = %d)", pname, param);

+

+    try

+    {

+        gl::Context *context = gl::getContext();

+

+        if(context)

+        {

+            switch(pname)

+            {

+              case GL_UNPACK_ALIGNMENT:

+                if(param != 1 && param != 2 && param != 4 && param != 8)

+                {

+                    return error(GL_INVALID_VALUE);

+                }

+

+                context->setUnpackAlignment(param);

+                break;

+

+              case GL_PACK_ALIGNMENT:

+                if(param != 1 && param != 2 && param != 4 && param != 8)

+                {

+                    return error(GL_INVALID_VALUE);

+                }

+

+                context->setPackAlignment(param);

+                break;

+

+              default:

+                return error(GL_INVALID_ENUM);

+            }

+        }

+    }

+    catch(std::bad_alloc&)

+    {

+        return error(GL_OUT_OF_MEMORY);

+    }

+}

+

+void GL_APIENTRY glPolygonOffset(GLfloat factor, GLfloat units)

+{

+    TRACE("(GLfloat factor = %f, GLfloat units = %f)", factor, units);

+

+    try

+    {

+        gl::Context *context = gl::getContext();

+

+        if(context)

+        {

+            context->setPolygonOffsetParams(factor, units);

+        }

+    }

+    catch(std::bad_alloc&)

+    {

+        return error(GL_OUT_OF_MEMORY);

+    }

+}

+

+void GL_APIENTRY glReadnPixelsEXT(GLint x, GLint y, GLsizei width, GLsizei height,

+                                GLenum format, GLenum type, GLsizei bufSize,

+                                GLvoid *data)

+{

+    TRACE("(GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d, "

+          "GLenum format = 0x%X, GLenum type = 0x%X, GLsizei bufSize = 0x%d, GLvoid *data = 0x%0.8p)",

+          x, y, width, height, format, type, bufSize, data);

+

+    try

+    {

+        if(width < 0 || height < 0 || bufSize < 0)

+        {

+            return error(GL_INVALID_VALUE);

+        }

+

+        if(!validReadFormatType(format, type))

+        {

+            return error(GL_INVALID_OPERATION);

+        }

+

+        gl::Context *context = gl::getContext();

+

+        if(context)

+        {

+            context->readPixels(x, y, width, height, format, type, &bufSize, data);

+        }

+    }

+    catch(std::bad_alloc&)

+    {

+        return error(GL_OUT_OF_MEMORY);

+    }

+}

+

+void GL_APIENTRY glReadPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid* pixels)

+{

+    TRACE("(GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d, "

+          "GLenum format = 0x%X, GLenum type = 0x%X, GLvoid* pixels = 0x%0.8p)",

+          x, y, width, height, format, type,  pixels);

+

+    try

+    {

+        if(width < 0 || height < 0)

+        {

+            return error(GL_INVALID_VALUE);

+        }

+

+        if(!validReadFormatType(format, type))

+        {

+            return error(GL_INVALID_OPERATION);

+        }

+

+        gl::Context *context = gl::getContext();

+

+        if(context)

+        {

+            context->readPixels(x, y, width, height, format, type, NULL, pixels);

+        }

+    }

+    catch(std::bad_alloc&)

+    {

+        return error(GL_OUT_OF_MEMORY);

+    }

+}

+

+void GL_APIENTRY glReleaseShaderCompiler(void)

+{

+    TRACE("()");

+

+    try

+    {

+        gl::Shader::releaseCompiler();

+    }

+    catch(std::bad_alloc&)

+    {

+        return error(GL_OUT_OF_MEMORY);

+    }

+}

+

+void GL_APIENTRY glRenderbufferStorageMultisampleANGLE(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height)

+{

+    TRACE("(GLenum target = 0x%X, GLsizei samples = %d, GLenum internalformat = 0x%X, GLsizei width = %d, GLsizei height = %d)",

+          target, samples, internalformat, width, height);

+

+    try

+    {

+        switch(target)

+        {

+          case GL_RENDERBUFFER:

+            break;

+          default:

+            return error(GL_INVALID_ENUM);

+        }

+

+        if(!gl::IsColorRenderable(internalformat) && !gl::IsDepthRenderable(internalformat) && !gl::IsStencilRenderable(internalformat))

+        {

+            return error(GL_INVALID_ENUM);

+        }

+

+        if(width < 0 || height < 0 || samples < 0)

+        {

+            return error(GL_INVALID_VALUE);

+        }

+

+        gl::Context *context = gl::getContext();

+

+        if(context)

+        {

+            if(width > gl::IMPLEMENTATION_MAX_RENDERBUFFER_SIZE || 

+               height > gl::IMPLEMENTATION_MAX_RENDERBUFFER_SIZE ||

+               samples > gl::IMPLEMENTATION_MAX_SAMPLES)

+            {

+                return error(GL_INVALID_VALUE);

+            }

+

+            GLuint handle = context->getRenderbufferHandle();

+            if(handle == 0)

+            {

+                return error(GL_INVALID_OPERATION);

+            }

+

+            switch(internalformat)

+            {

+              case GL_DEPTH_COMPONENT16:

+                context->setRenderbufferStorage(new gl::Depthbuffer(width, height, samples));

+                break;

+              case GL_RGBA4:

+              case GL_RGB5_A1:

+              case GL_RGB565:

+              case GL_RGB8_OES:

+              case GL_RGBA8_OES:

+                context->setRenderbufferStorage(new gl::Colorbuffer(width, height, internalformat, samples));

+                break;

+              case GL_STENCIL_INDEX8:

+                context->setRenderbufferStorage(new gl::Stencilbuffer(width, height, samples));

+                break;

+              case GL_DEPTH24_STENCIL8_OES:

+                context->setRenderbufferStorage(new gl::DepthStencilbuffer(width, height, samples));

+                break;

+              default:

+                return error(GL_INVALID_ENUM);

+            }

+        }

+    }

+    catch(std::bad_alloc&)

+    {

+        return error(GL_OUT_OF_MEMORY);

+    }

+}

+

+void GL_APIENTRY glRenderbufferStorage(GLenum target, GLenum internalformat, GLsizei width, GLsizei height)

+{

+    glRenderbufferStorageMultisampleANGLE(target, 0, internalformat, width, height);

+}

+

+void GL_APIENTRY glSampleCoverage(GLclampf value, GLboolean invert)

+{

+    TRACE("(GLclampf value = %f, GLboolean invert = %d)", value, invert);

+

+    try

+    {

+        gl::Context* context = gl::getContext();

+

+        if(context)

+        {

+            context->setSampleCoverageParams(gl::clamp01(value), invert == GL_TRUE);

+        }

+    }

+    catch(std::bad_alloc&)

+    {

+        return error(GL_OUT_OF_MEMORY);

+    }

+}

+

+void GL_APIENTRY glSetFenceNV(GLuint fence, GLenum condition)

+{

+    TRACE("(GLuint fence = %d, GLenum condition = 0x%X)", fence, condition);

+

+    try

+    {

+        if(condition != GL_ALL_COMPLETED_NV)

+        {

+            return error(GL_INVALID_ENUM);

+        }

+

+        gl::Context *context = gl::getContext();

+

+        if(context)

+        {

+            gl::Fence *fenceObject = context->getFence(fence);

+

+            if(fenceObject == NULL)

+            {

+                return error(GL_INVALID_OPERATION);

+            }

+

+            fenceObject->setFence(condition);    

+        }

+    }

+    catch(std::bad_alloc&)

+    {

+        return error(GL_OUT_OF_MEMORY);

+    }

+}

+

+void GL_APIENTRY glScissor(GLint x, GLint y, GLsizei width, GLsizei height)

+{

+    TRACE("(GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d)", x, y, width, height);

+

+    try

+    {

+        if(width < 0 || height < 0)

+        {

+            return error(GL_INVALID_VALUE);

+        }

+

+        gl::Context* context = gl::getContext();

+

+        if(context)

+        {

+            context->setScissorParams(x, y, width, height);

+        }

+    }

+    catch(std::bad_alloc&)

+    {

+        return error(GL_OUT_OF_MEMORY);

+    }

+}

+

+void GL_APIENTRY glShaderBinary(GLsizei n, const GLuint* shaders, GLenum binaryformat, const GLvoid* binary, GLsizei length)

+{

+    TRACE("(GLsizei n = %d, const GLuint* shaders = 0x%0.8p, GLenum binaryformat = 0x%X, "

+          "const GLvoid* binary = 0x%0.8p, GLsizei length = %d)",

+          n, shaders, binaryformat, binary, length);

+

+    try

+    {

+        // No binary shader formats are supported.

+        return error(GL_INVALID_ENUM);

+    }

+    catch(std::bad_alloc&)

+    {

+        return error(GL_OUT_OF_MEMORY);

+    }

+}

+

+void GL_APIENTRY glShaderSource(GLuint shader, GLsizei count, const GLchar** string, const GLint* length)

+{

+    TRACE("(GLuint shader = %d, GLsizei count = %d, const GLchar** string = 0x%0.8p, const GLint* length = 0x%0.8p)",

+          shader, count, string, length);

+

+    try

+    {

+        if(count < 0)

+        {

+            return error(GL_INVALID_VALUE);

+        }

+

+        gl::Context *context = gl::getContext();

+

+        if(context)

+        {

+            gl::Shader *shaderObject = context->getShader(shader);

+

+            if(!shaderObject)

+            {

+                if(context->getProgram(shader))

+                {

+                    return error(GL_INVALID_OPERATION);

+                }

+                else

+                {

+                    return error(GL_INVALID_VALUE);

+                }

+            }

+

+            shaderObject->setSource(count, string, length);

+        }

+    }

+    catch(std::bad_alloc&)

+    {

+        return error(GL_OUT_OF_MEMORY);

+    }

+}

+

+void GL_APIENTRY glStencilFunc(GLenum func, GLint ref, GLuint mask)

+{

+    glStencilFuncSeparate(GL_FRONT_AND_BACK, func, ref, mask);

+}

+

+void GL_APIENTRY glStencilFuncSeparate(GLenum face, GLenum func, GLint ref, GLuint mask)

+{

+    TRACE("(GLenum face = 0x%X, GLenum func = 0x%X, GLint ref = %d, GLuint mask = %d)", face, func, ref, mask);

+

+    try

+    {

+        switch(face)

+        {

+          case GL_FRONT:

+          case GL_BACK:

+          case GL_FRONT_AND_BACK:

+            break;

+          default:

+            return error(GL_INVALID_ENUM);

+        }

+

+        switch(func)

+        {

+          case GL_NEVER:

+          case GL_ALWAYS:

+          case GL_LESS:

+          case GL_LEQUAL:

+          case GL_EQUAL:

+          case GL_GEQUAL:

+          case GL_GREATER:

+          case GL_NOTEQUAL:

+            break;

+          default:

+            return error(GL_INVALID_ENUM);

+        }

+

+        gl::Context *context = gl::getContext();

+

+        if(context)

+        {

+            if(face == GL_FRONT || face == GL_FRONT_AND_BACK)

+            {

+                context->setStencilParams(func, ref, mask);

+            }

+

+            if(face == GL_BACK || face == GL_FRONT_AND_BACK)

+            {

+                context->setStencilBackParams(func, ref, mask);

+            }

+        }

+    }

+    catch(std::bad_alloc&)

+    {

+        return error(GL_OUT_OF_MEMORY);

+    }

+}

+

+void GL_APIENTRY glStencilMask(GLuint mask)

+{

+    glStencilMaskSeparate(GL_FRONT_AND_BACK, mask);

+}

+

+void GL_APIENTRY glStencilMaskSeparate(GLenum face, GLuint mask)

+{

+    TRACE("(GLenum face = 0x%X, GLuint mask = %d)", face, mask);

+

+    try

+    {

+        switch(face)

+        {

+          case GL_FRONT:

+          case GL_BACK:

+          case GL_FRONT_AND_BACK:

+            break;

+          default:

+            return error(GL_INVALID_ENUM);

+        }

+

+        gl::Context *context = gl::getContext();

+

+        if(context)

+        {

+            if(face == GL_FRONT || face == GL_FRONT_AND_BACK)

+            {

+                context->setStencilWritemask(mask);

+            }

+

+            if(face == GL_BACK || face == GL_FRONT_AND_BACK)

+            {

+                context->setStencilBackWritemask(mask);

+            }

+        }

+    }

+    catch(std::bad_alloc&)

+    {

+        return error(GL_OUT_OF_MEMORY);

+    }

+}

+

+void GL_APIENTRY glStencilOp(GLenum fail, GLenum zfail, GLenum zpass)

+{

+    glStencilOpSeparate(GL_FRONT_AND_BACK, fail, zfail, zpass);

+}

+

+void GL_APIENTRY glStencilOpSeparate(GLenum face, GLenum fail, GLenum zfail, GLenum zpass)

+{

+    TRACE("(GLenum face = 0x%X, GLenum fail = 0x%X, GLenum zfail = 0x%X, GLenum zpas = 0x%Xs)",

+          face, fail, zfail, zpass);

+

+    try

+    {

+        switch(face)

+        {

+          case GL_FRONT:

+          case GL_BACK:

+          case GL_FRONT_AND_BACK:

+            break;

+          default:

+            return error(GL_INVALID_ENUM);

+        }

+

+        switch(fail)

+        {

+          case GL_ZERO:

+          case GL_KEEP:

+          case GL_REPLACE:

+          case GL_INCR:

+          case GL_DECR:

+          case GL_INVERT:

+          case GL_INCR_WRAP:

+          case GL_DECR_WRAP:

+            break;

+          default:

+            return error(GL_INVALID_ENUM);

+        }

+

+        switch(zfail)

+        {

+          case GL_ZERO:

+          case GL_KEEP:

+          case GL_REPLACE:

+          case GL_INCR:

+          case GL_DECR:

+          case GL_INVERT:

+          case GL_INCR_WRAP:

+          case GL_DECR_WRAP:

+            break;

+          default:

+            return error(GL_INVALID_ENUM);

+        }

+

+        switch(zpass)

+        {

+          case GL_ZERO:

+          case GL_KEEP:

+          case GL_REPLACE:

+          case GL_INCR:

+          case GL_DECR:

+          case GL_INVERT:

+          case GL_INCR_WRAP:

+          case GL_DECR_WRAP:

+            break;

+          default:

+            return error(GL_INVALID_ENUM);

+        }

+

+        gl::Context *context = gl::getContext();

+

+        if(context)

+        {

+            if(face == GL_FRONT || face == GL_FRONT_AND_BACK)

+            {

+                context->setStencilOperations(fail, zfail, zpass);

+            }

+

+            if(face == GL_BACK || face == GL_FRONT_AND_BACK)

+            {

+                context->setStencilBackOperations(fail, zfail, zpass);

+            }

+        }

+    }

+    catch(std::bad_alloc&)

+    {

+        return error(GL_OUT_OF_MEMORY);

+    }

+}

+

+GLboolean GL_APIENTRY glTestFenceNV(GLuint fence)

+{

+    TRACE("(GLuint fence = %d)", fence);

+

+    try

+    {

+        gl::Context *context = gl::getContext();

+

+        if(context)

+        {

+            gl::Fence *fenceObject = context->getFence(fence);

+

+            if(fenceObject == NULL)

+            {

+                return error(GL_INVALID_OPERATION, GL_TRUE);

+            }

+

+            return fenceObject->testFence();

+        }

+    }

+    catch(std::bad_alloc&)

+    {

+        error(GL_OUT_OF_MEMORY);

+    }

+    

+    return GL_TRUE;

+}

+

+void GL_APIENTRY glTexImage2D(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height,

+                              GLint border, GLenum format, GLenum type, const GLvoid* pixels)

+{

+    TRACE("(GLenum target = 0x%X, GLint level = %d, GLint internalformat = %d, GLsizei width = %d, GLsizei height = %d, "

+          "GLint border = %d, GLenum format = 0x%X, GLenum type = 0x%X, const GLvoid* pixels =  0x%0.8p)",

+          target, level, internalformat, width, height, border, format, type, pixels);

+

+    try

+    {

+        if(!validImageSize(level, width, height))

+        {

+            return error(GL_INVALID_VALUE);

+        }

+

+        if(internalformat != format)

+        {

+            return error(GL_INVALID_OPERATION);

+        }

+

+        switch(format)

+        {

+        case GL_ALPHA:

+        case GL_LUMINANCE:

+        case GL_LUMINANCE_ALPHA:

+            switch(type)

+            {

+            case GL_UNSIGNED_BYTE:

+            case GL_FLOAT:

+            case GL_HALF_FLOAT_OES:

+                break;

+            default:

+                return error(GL_INVALID_ENUM);

+            }

+            break;

+        case GL_RGB:

+            switch(type)

+            {

+            case GL_UNSIGNED_BYTE:

+            case GL_UNSIGNED_SHORT_5_6_5:

+            case GL_FLOAT:

+            case GL_HALF_FLOAT_OES:

+                break;

+            default:

+                return error(GL_INVALID_ENUM);

+            }

+            break;

+        case GL_RGBA:

+            switch(type)

+            {

+            case GL_UNSIGNED_BYTE:

+            case GL_UNSIGNED_SHORT_4_4_4_4:

+            case GL_UNSIGNED_SHORT_5_5_5_1:

+            case GL_FLOAT:

+            case GL_HALF_FLOAT_OES:

+                break;

+            default:

+                return error(GL_INVALID_ENUM);

+            }

+            break;

+        case GL_BGRA_EXT:

+            switch(type)

+            {

+            case GL_UNSIGNED_BYTE:

+                break;

+            default:

+                return error(GL_INVALID_ENUM);

+            }

+            break;

+        case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:  // error cases for compressed textures are handled below

+        case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:

+		case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:

+		case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:

+            break;

+		case GL_DEPTH_COMPONENT:

+			switch(type)

+			{

+			case GL_UNSIGNED_SHORT:

+			case GL_UNSIGNED_INT:

+				break;

+			default:

+				return error(GL_INVALID_ENUM);

+			}

+			break;

+		case GL_DEPTH_STENCIL_OES:

+			switch(type)

+			{

+			case GL_UNSIGNED_INT_24_8_OES:

+				break;

+			default:

+				return error(GL_INVALID_ENUM);

+			}

+			break;

+        default:

+            return error(GL_INVALID_VALUE);

+        }

+

+        if(border != 0)

+        {

+            return error(GL_INVALID_VALUE);

+        }

+

+        gl::Context *context = gl::getContext();

+

+        if(context)

+        {

+            switch(target)

+            {

+              case GL_TEXTURE_2D:

+                if(width > (gl::IMPLEMENTATION_MAX_TEXTURE_SIZE >> level) ||

+                   height > (gl::IMPLEMENTATION_MAX_TEXTURE_SIZE >> level))

+                {

+                    return error(GL_INVALID_VALUE);

+                }

+                break;

+              case GL_TEXTURE_CUBE_MAP_POSITIVE_X:

+              case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:

+              case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:

+              case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:

+              case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:

+              case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:

+                if(width != height)

+                {

+                    return error(GL_INVALID_VALUE);

+                }

+

+                if(width > (gl::IMPLEMENTATION_MAX_CUBE_MAP_TEXTURE_SIZE >> level) ||

+                   height > (gl::IMPLEMENTATION_MAX_CUBE_MAP_TEXTURE_SIZE >> level))

+                {

+                    return error(GL_INVALID_VALUE);

+                }

+                break;

+              default:

+                return error(GL_INVALID_ENUM);

+            }

+

+            if(format == GL_COMPRESSED_RGB_S3TC_DXT1_EXT ||

+               format == GL_COMPRESSED_RGBA_S3TC_DXT1_EXT ||

+			   format == GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE ||

+			   format == GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE)

+            {

+                if(S3TC_SUPPORT)

+                {

+                    return error(GL_INVALID_OPERATION);

+                }

+                else

+                {

+                    return error(GL_INVALID_ENUM);

+                }

+            }

+			

+            if(target == GL_TEXTURE_2D)

+            {

+                gl::Texture2D *texture = context->getTexture2D();

+

+                if(!texture)

+                {

+                    return error(GL_INVALID_OPERATION);

+                }

+

+                texture->setImage(level, width, height, format, type, context->getUnpackAlignment(), pixels);

+            }

+            else

+            {

+                gl::TextureCubeMap *texture = context->getTextureCubeMap();

+

+                if(!texture)

+                {

+                    return error(GL_INVALID_OPERATION);

+                }

+

+				texture->setImage(target, level, width, height, format, type, context->getUnpackAlignment(), pixels);

+            }

+        }

+    }

+    catch(std::bad_alloc&)

+    {

+        return error(GL_OUT_OF_MEMORY);

+    }

+}

+

+void GL_APIENTRY glTexParameterf(GLenum target, GLenum pname, GLfloat param)

+{

+    TRACE("(GLenum target = 0x%X, GLenum pname = 0x%X, GLfloat param = %f)", target, pname, param);

+

+    try

+    {

+        gl::Context *context = gl::getContext();

+

+        if(context)

+        {

+            gl::Texture *texture;

+

+            switch(target)

+            {

+            case GL_TEXTURE_2D:

+                texture = context->getTexture2D();

+                break;

+            case GL_TEXTURE_CUBE_MAP:

+                texture = context->getTextureCubeMap();

+                break;

+            default:

+                return error(GL_INVALID_ENUM);

+            }

+

+            switch(pname)

+            {

+            case GL_TEXTURE_WRAP_S:

+                if(!texture->setWrapS((GLenum)param))

+                {

+                    return error(GL_INVALID_ENUM);

+                }

+                break;

+            case GL_TEXTURE_WRAP_T:

+                if(!texture->setWrapT((GLenum)param))

+                {

+                    return error(GL_INVALID_ENUM);

+                }

+                break;

+            case GL_TEXTURE_MIN_FILTER:

+                if(!texture->setMinFilter((GLenum)param))

+                {

+                    return error(GL_INVALID_ENUM);

+                }

+                break;

+            case GL_TEXTURE_MAG_FILTER:

+                if(!texture->setMagFilter((GLenum)param))

+                {

+                    return error(GL_INVALID_ENUM);

+                }

+                break;

+            case GL_TEXTURE_MAX_ANISOTROPY_EXT:

+                if(!texture->setMaxAnisotropy(param))

+                {

+                    return error(GL_INVALID_VALUE);

+                }

+                break;

+            default:

+                return error(GL_INVALID_ENUM);

+            }

+        }

+    }

+    catch(std::bad_alloc&)

+    {

+        return error(GL_OUT_OF_MEMORY);

+    }

+}

+

+void GL_APIENTRY glTexParameterfv(GLenum target, GLenum pname, const GLfloat* params)

+{

+    glTexParameterf(target, pname, *params);

+}

+

+void GL_APIENTRY glTexParameteri(GLenum target, GLenum pname, GLint param)

+{

+    TRACE("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint param = %d)", target, pname, param);

+

+    try

+    {

+        gl::Context *context = gl::getContext();

+

+        if(context)

+        {

+            gl::Texture *texture;

+

+            switch(target)

+            {

+              case GL_TEXTURE_2D:

+                texture = context->getTexture2D();

+                break;

+              case GL_TEXTURE_CUBE_MAP:

+                texture = context->getTextureCubeMap();

+                break;

+              default:

+                return error(GL_INVALID_ENUM);

+            }

+

+            switch(pname)

+            {

+              case GL_TEXTURE_WRAP_S:

+                if(!texture->setWrapS((GLenum)param))

+                {

+                    return error(GL_INVALID_ENUM);

+                }

+                break;

+              case GL_TEXTURE_WRAP_T:

+                if(!texture->setWrapT((GLenum)param))

+                {

+                    return error(GL_INVALID_ENUM);

+                }

+                break;

+              case GL_TEXTURE_MIN_FILTER:

+                if(!texture->setMinFilter((GLenum)param))

+                {

+                    return error(GL_INVALID_ENUM);

+                }

+                break;

+              case GL_TEXTURE_MAG_FILTER:

+                if(!texture->setMagFilter((GLenum)param))

+                {

+                    return error(GL_INVALID_ENUM);

+                }

+                break;

+			  case GL_TEXTURE_MAX_ANISOTROPY_EXT:

+                if(!texture->setMaxAnisotropy((GLfloat)param))

+                {

+                    return error(GL_INVALID_VALUE);

+                }

+                break;

+              default:

+                return error(GL_INVALID_ENUM);

+            }

+        }

+    }

+    catch(std::bad_alloc&)

+    {

+        return error(GL_OUT_OF_MEMORY);

+    }

+}

+

+void GL_APIENTRY glTexParameteriv(GLenum target, GLenum pname, const GLint* params)

+{

+    glTexParameteri(target, pname, *params);

+}

+

+void GL_APIENTRY glTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,

+                               GLenum format, GLenum type, const GLvoid* pixels)

+{

+    TRACE("(GLenum target = 0x%X, GLint level = %d, GLint xoffset = %d, GLint yoffset = %d, "

+          "GLsizei width = %d, GLsizei height = %d, GLenum format = 0x%X, GLenum type = 0x%X, "

+          "const GLvoid* pixels = 0x%0.8p)",

+           target, level, xoffset, yoffset, width, height, format, type, pixels);

+

+    try

+    {

+        if(!gl::IsTextureTarget(target))

+        {

+            return error(GL_INVALID_ENUM);

+        }

+

+        if(level < 0 || xoffset < 0 || yoffset < 0 || width < 0 || height < 0)

+        {

+            return error(GL_INVALID_VALUE);

+        }

+

+        if(std::numeric_limits<GLsizei>::max() - xoffset < width || std::numeric_limits<GLsizei>::max() - yoffset < height)

+        {

+            return error(GL_INVALID_VALUE);

+        }

+

+        if(!gl::CheckTextureFormatType(format, type))

+        {

+            return error(GL_INVALID_ENUM);

+        }

+

+        if(width == 0 || height == 0 || pixels == NULL)

+        {

+            return;

+        }

+

+        gl::Context *context = gl::getContext();

+

+        if(context)

+        {

+            if(level > gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS)

+            {

+                return error(GL_INVALID_VALUE);

+            }

+

+            if(target == GL_TEXTURE_2D)

+            {

+                gl::Texture2D *texture = context->getTexture2D();

+

+                if(validateSubImageParams(false, width, height, xoffset, yoffset, target, level, format, texture))

+				{

+					texture->subImage(level, xoffset, yoffset, width, height, format, type, context->getUnpackAlignment(), pixels);

+				}

+            }

+            else if(gl::IsCubemapTextureTarget(target))

+            {

+                gl::TextureCubeMap *texture = context->getTextureCubeMap();

+				

+				if(validateSubImageParams(false, width, height, xoffset, yoffset, target, level, format, texture))

+				{

+					texture->subImage(target, level, xoffset, yoffset, width, height, format, type, context->getUnpackAlignment(), pixels);

+				}

+            }

+            else

+            {

+                UNREACHABLE();

+            }

+        }

+    }

+    catch(std::bad_alloc&)

+    {

+        return error(GL_OUT_OF_MEMORY);

+    }

+}

+

+void GL_APIENTRY glUniform1f(GLint location, GLfloat x)

+{

+    glUniform1fv(location, 1, &x);

+}

+

+void GL_APIENTRY glUniform1fv(GLint location, GLsizei count, const GLfloat* v)

+{

+    TRACE("(GLint location = %d, GLsizei count = %d, const GLfloat* v = 0x%0.8p)", location, count, v);

+

+    try

+    {

+        if(count < 0)

+        {

+            return error(GL_INVALID_VALUE);

+        }

+

+        if(location == -1)

+        {

+            return;

+        }

+

+        gl::Context *context = gl::getContext();

+

+        if(context)

+        {

+            gl::Program *program = context->getCurrentProgram();

+

+            if(!program)

+            {

+                return error(GL_INVALID_OPERATION);

+            }

+

+            if(!program->setUniform1fv(location, count, v))

+            {

+                return error(GL_INVALID_OPERATION);

+            }

+        }

+    }

+    catch(std::bad_alloc&)

+    {

+        return error(GL_OUT_OF_MEMORY);

+    }

+}

+

+void GL_APIENTRY glUniform1i(GLint location, GLint x)

+{

+    glUniform1iv(location, 1, &x);

+}

+

+void GL_APIENTRY glUniform1iv(GLint location, GLsizei count, const GLint* v)

+{

+    TRACE("(GLint location = %d, GLsizei count = %d, const GLint* v = 0x%0.8p)", location, count, v);

+

+    try

+    {

+        if(count < 0)

+        {

+            return error(GL_INVALID_VALUE);

+        }

+

+        if(location == -1)

+        {

+            return;

+        }

+

+        gl::Context *context = gl::getContext();

+

+        if(context)

+        {

+            gl::Program *program = context->getCurrentProgram();

+

+            if(!program)

+            {

+                return error(GL_INVALID_OPERATION);

+            }

+

+            if(!program->setUniform1iv(location, count, v))

+            {

+                return error(GL_INVALID_OPERATION);

+            }

+        }

+    }

+    catch(std::bad_alloc&)

+    {

+        return error(GL_OUT_OF_MEMORY);

+    }

+}

+

+void GL_APIENTRY glUniform2f(GLint location, GLfloat x, GLfloat y)

+{

+    GLfloat xy[2] = {x, y};

+

+    glUniform2fv(location, 1, (GLfloat*)&xy);

+}

+

+void GL_APIENTRY glUniform2fv(GLint location, GLsizei count, const GLfloat* v)

+{

+    TRACE("(GLint location = %d, GLsizei count = %d, const GLfloat* v = 0x%0.8p)", location, count, v);

+

+    try

+    {

+        if(count < 0)

+        {

+            return error(GL_INVALID_VALUE);

+        }

+        

+        if(location == -1)

+        {

+            return;

+        }

+

+        gl::Context *context = gl::getContext();

+

+        if(context)

+        {

+            gl::Program *program = context->getCurrentProgram();

+

+            if(!program)

+            {

+                return error(GL_INVALID_OPERATION);

+            }

+

+            if(!program->setUniform2fv(location, count, v))

+            {

+                return error(GL_INVALID_OPERATION);

+            }

+        }

+    }

+    catch(std::bad_alloc&)

+    {

+        return error(GL_OUT_OF_MEMORY);

+    }

+}

+

+void GL_APIENTRY glUniform2i(GLint location, GLint x, GLint y)

+{

+    GLint xy[4] = {x, y};

+

+    glUniform2iv(location, 1, (GLint*)&xy);

+}

+

+void GL_APIENTRY glUniform2iv(GLint location, GLsizei count, const GLint* v)

+{

+    TRACE("(GLint location = %d, GLsizei count = %d, const GLint* v = 0x%0.8p)", location, count, v);

+

+    try

+    {

+        if(count < 0)

+        {

+            return error(GL_INVALID_VALUE);

+        }

+

+        if(location == -1)

+        {

+            return;

+        }

+

+        gl::Context *context = gl::getContext();

+

+        if(context)

+        {

+            gl::Program *program = context->getCurrentProgram();

+

+            if(!program)

+            {

+                return error(GL_INVALID_OPERATION);

+            }

+

+            if(!program->setUniform2iv(location, count, v))

+            {

+                return error(GL_INVALID_OPERATION);

+            }

+        }

+    }

+    catch(std::bad_alloc&)

+    {

+        return error(GL_OUT_OF_MEMORY);

+    }

+}

+

+void GL_APIENTRY glUniform3f(GLint location, GLfloat x, GLfloat y, GLfloat z)

+{

+    GLfloat xyz[3] = {x, y, z};

+

+    glUniform3fv(location, 1, (GLfloat*)&xyz);

+}

+

+void GL_APIENTRY glUniform3fv(GLint location, GLsizei count, const GLfloat* v)

+{

+    TRACE("(GLint location = %d, GLsizei count = %d, const GLfloat* v = 0x%0.8p)", location, count, v);

+

+    try

+    {

+        if(count < 0)

+        {

+            return error(GL_INVALID_VALUE);

+        }

+

+        if(location == -1)

+        {

+            return;

+        }

+

+        gl::Context *context = gl::getContext();

+

+        if(context)

+        {

+            gl::Program *program = context->getCurrentProgram();

+

+            if(!program)

+            {

+                return error(GL_INVALID_OPERATION);

+            }

+

+            if(!program->setUniform3fv(location, count, v))

+            {

+                return error(GL_INVALID_OPERATION);

+            }

+        }

+    }

+    catch(std::bad_alloc&)

+    {

+        return error(GL_OUT_OF_MEMORY);

+    }

+}

+

+void GL_APIENTRY glUniform3i(GLint location, GLint x, GLint y, GLint z)

+{

+    GLint xyz[3] = {x, y, z};

+

+    glUniform3iv(location, 1, (GLint*)&xyz);

+}

+

+void GL_APIENTRY glUniform3iv(GLint location, GLsizei count, const GLint* v)

+{

+    TRACE("(GLint location = %d, GLsizei count = %d, const GLint* v = 0x%0.8p)", location, count, v);

+

+    try

+    {

+        if(count < 0)

+        {

+            return error(GL_INVALID_VALUE);

+        }

+

+        if(location == -1)

+        {

+            return;

+        }

+

+        gl::Context *context = gl::getContext();

+

+        if(context)

+        {

+            gl::Program *program = context->getCurrentProgram();

+

+            if(!program)

+            {

+                return error(GL_INVALID_OPERATION);

+            }

+

+            if(!program->setUniform3iv(location, count, v))

+            {

+                return error(GL_INVALID_OPERATION);

+            }

+        }

+    }

+    catch(std::bad_alloc&)

+    {

+        return error(GL_OUT_OF_MEMORY);

+    }

+}

+

+void GL_APIENTRY glUniform4f(GLint location, GLfloat x, GLfloat y, GLfloat z, GLfloat w)

+{

+    GLfloat xyzw[4] = {x, y, z, w};

+

+    glUniform4fv(location, 1, (GLfloat*)&xyzw);

+}

+

+void GL_APIENTRY glUniform4fv(GLint location, GLsizei count, const GLfloat* v)

+{

+    TRACE("(GLint location = %d, GLsizei count = %d, const GLfloat* v = 0x%0.8p)", location, count, v);

+

+    try

+    {

+        if(count < 0)

+        {

+            return error(GL_INVALID_VALUE);

+        }

+

+        if(location == -1)

+        {

+            return;

+        }

+

+        gl::Context *context = gl::getContext();

+

+        if(context)

+        {

+            gl::Program *program = context->getCurrentProgram();

+

+            if(!program)

+            {

+                return error(GL_INVALID_OPERATION);

+            }

+

+            if(!program->setUniform4fv(location, count, v))

+            {

+                return error(GL_INVALID_OPERATION);

+            }

+        }

+    }

+    catch(std::bad_alloc&)

+    {

+        return error(GL_OUT_OF_MEMORY);

+    }

+}

+

+void GL_APIENTRY glUniform4i(GLint location, GLint x, GLint y, GLint z, GLint w)

+{

+    GLint xyzw[4] = {x, y, z, w};

+

+    glUniform4iv(location, 1, (GLint*)&xyzw);

+}

+

+void GL_APIENTRY glUniform4iv(GLint location, GLsizei count, const GLint* v)

+{

+    TRACE("(GLint location = %d, GLsizei count = %d, const GLint* v = 0x%0.8p)", location, count, v);

+

+    try

+    {

+        if(count < 0)

+        {

+            return error(GL_INVALID_VALUE);

+        }

+

+        if(location == -1)

+        {

+            return;

+        }

+

+        gl::Context *context = gl::getContext();

+

+        if(context)

+        {

+            gl::Program *program = context->getCurrentProgram();

+

+            if(!program)

+            {

+                return error(GL_INVALID_OPERATION);

+            }

+

+            if(!program->setUniform4iv(location, count, v))

+            {

+                return error(GL_INVALID_OPERATION);

+            }

+        }

+    }

+    catch(std::bad_alloc&)

+    {

+        return error(GL_OUT_OF_MEMORY);

+    }

+}

+

+void GL_APIENTRY glUniformMatrix2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)

+{

+    TRACE("(GLint location = %d, GLsizei count = %d, GLboolean transpose = %d, const GLfloat* value = 0x%0.8p)",

+          location, count, transpose, value);

+

+    try

+    {

+        if(count < 0 || transpose != GL_FALSE)

+        {

+            return error(GL_INVALID_VALUE);

+        }

+

+        if(location == -1)

+        {

+            return;

+        }

+

+        gl::Context *context = gl::getContext();

+

+        if(context)

+        {

+            gl::Program *program = context->getCurrentProgram();

+

+            if(!program)

+            {

+                return error(GL_INVALID_OPERATION);

+            }

+

+            if(!program->setUniformMatrix2fv(location, count, value))

+            {

+                return error(GL_INVALID_OPERATION);

+            }

+        }

+    }

+    catch(std::bad_alloc&)

+    {

+        return error(GL_OUT_OF_MEMORY);

+    }

+}

+

+void GL_APIENTRY glUniformMatrix3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)

+{

+    TRACE("(GLint location = %d, GLsizei count = %d, GLboolean transpose = %d, const GLfloat* value = 0x%0.8p)",

+          location, count, transpose, value);

+

+    try

+    {

+        if(count < 0 || transpose != GL_FALSE)

+        {

+            return error(GL_INVALID_VALUE);

+        }

+

+        if(location == -1)

+        {

+            return;

+        }

+

+        gl::Context *context = gl::getContext();

+

+        if(context)

+        {

+            gl::Program *program = context->getCurrentProgram();

+

+            if(!program)

+            {

+                return error(GL_INVALID_OPERATION);

+            }

+

+            if(!program->setUniformMatrix3fv(location, count, value))

+            {

+                return error(GL_INVALID_OPERATION);

+            }

+        }

+    }

+    catch(std::bad_alloc&)

+    {

+        return error(GL_OUT_OF_MEMORY);

+    }

+}

+

+void GL_APIENTRY glUniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)

+{

+    TRACE("(GLint location = %d, GLsizei count = %d, GLboolean transpose = %d, const GLfloat* value = 0x%0.8p)",

+          location, count, transpose, value);

+

+    try

+    {

+        if(count < 0 || transpose != GL_FALSE)

+        {

+            return error(GL_INVALID_VALUE);

+        }

+

+        if(location == -1)

+        {

+            return;

+        }

+

+        gl::Context *context = gl::getContext();

+

+        if(context)

+        {

+            gl::Program *program = context->getCurrentProgram();

+

+            if(!program)

+            {

+                return error(GL_INVALID_OPERATION);

+            }

+

+            if(!program->setUniformMatrix4fv(location, count, value))

+            {

+                return error(GL_INVALID_OPERATION);

+            }

+        }

+    }

+    catch(std::bad_alloc&)

+    {

+        return error(GL_OUT_OF_MEMORY);

+    }

+}

+

+void GL_APIENTRY glUseProgram(GLuint program)

+{

+    TRACE("(GLuint program = %d)", program);

+

+    try

+    {

+        gl::Context *context = gl::getContext();

+

+        if(context)

+        {

+            gl::Program *programObject = context->getProgram(program);

+

+            if(!programObject && program != 0)

+            {

+                if(context->getShader(program))

+                {

+                    return error(GL_INVALID_OPERATION);

+                }

+                else

+                {

+                    return error(GL_INVALID_VALUE);

+                }

+            }

+

+            if(program != 0 && !programObject->isLinked())

+            {

+                return error(GL_INVALID_OPERATION);

+            }

+

+            context->useProgram(program);

+        }

+    }

+    catch(std::bad_alloc&)

+    {

+        return error(GL_OUT_OF_MEMORY);

+    }

+}

+

+void GL_APIENTRY glValidateProgram(GLuint program)

+{

+    TRACE("(GLuint program = %d)", program);

+

+    try

+    {

+        gl::Context *context = gl::getContext();

+

+        if(context)

+        {

+            gl::Program *programObject = context->getProgram(program);

+

+            if(!programObject)

+            {

+                if(context->getShader(program))

+                {

+                    return error(GL_INVALID_OPERATION);

+                }

+                else

+                {

+                    return error(GL_INVALID_VALUE);

+                }

+            }

+

+            programObject->validate();

+        }

+    }

+    catch(std::bad_alloc&)

+    {

+        return error(GL_OUT_OF_MEMORY);

+    }

+}

+

+void GL_APIENTRY glVertexAttrib1f(GLuint index, GLfloat x)

+{

+    TRACE("(GLuint index = %d, GLfloat x = %f)", index, x);

+

+    try

+    {

+        if(index >= gl::MAX_VERTEX_ATTRIBS)

+        {

+            return error(GL_INVALID_VALUE);

+        }

+

+        gl::Context *context = gl::getContext();

+

+        if(context)

+        {

+            GLfloat vals[4] = { x, 0, 0, 1 };

+            context->setVertexAttrib(index, vals);

+        }

+    }

+    catch(std::bad_alloc&)

+    {

+        return error(GL_OUT_OF_MEMORY);

+    }

+}

+

+void GL_APIENTRY glVertexAttrib1fv(GLuint index, const GLfloat* values)

+{

+    TRACE("(GLuint index = %d, const GLfloat* values = 0x%0.8p)", index, values);

+

+    try

+    {

+        if(index >= gl::MAX_VERTEX_ATTRIBS)

+        {

+            return error(GL_INVALID_VALUE);

+        }

+

+        gl::Context *context = gl::getContext();

+

+        if(context)

+        {

+            GLfloat vals[4] = { values[0], 0, 0, 1 };

+            context->setVertexAttrib(index, vals);

+        }

+    }

+    catch(std::bad_alloc&)

+    {

+        return error(GL_OUT_OF_MEMORY);

+    }

+}

+

+void GL_APIENTRY glVertexAttrib2f(GLuint index, GLfloat x, GLfloat y)

+{

+    TRACE("(GLuint index = %d, GLfloat x = %f, GLfloat y = %f)", index, x, y);

+

+    try

+    {

+        if(index >= gl::MAX_VERTEX_ATTRIBS)

+        {

+            return error(GL_INVALID_VALUE);

+        }

+

+        gl::Context *context = gl::getContext();

+

+        if(context)

+        {

+            GLfloat vals[4] = { x, y, 0, 1 };

+            context->setVertexAttrib(index, vals);

+        }

+    }

+    catch(std::bad_alloc&)

+    {

+        return error(GL_OUT_OF_MEMORY);

+    }

+}

+

+void GL_APIENTRY glVertexAttrib2fv(GLuint index, const GLfloat* values)

+{

+    TRACE("(GLuint index = %d, const GLfloat* values = 0x%0.8p)", index, values);

+

+    try

+    {

+        if(index >= gl::MAX_VERTEX_ATTRIBS)

+        {

+            return error(GL_INVALID_VALUE);

+        }

+

+        gl::Context *context = gl::getContext();

+

+        if(context)

+        {

+            GLfloat vals[4] = { values[0], values[1], 0, 1 };

+            context->setVertexAttrib(index, vals);

+        }

+    }

+    catch(std::bad_alloc&)

+    {

+        return error(GL_OUT_OF_MEMORY);

+    }

+}

+

+void GL_APIENTRY glVertexAttrib3f(GLuint index, GLfloat x, GLfloat y, GLfloat z)

+{

+    TRACE("(GLuint index = %d, GLfloat x = %f, GLfloat y = %f, GLfloat z = %f)", index, x, y, z);

+

+    try

+    {

+        if(index >= gl::MAX_VERTEX_ATTRIBS)

+        {

+            return error(GL_INVALID_VALUE);

+        }

+

+        gl::Context *context = gl::getContext();

+

+        if(context)

+        {

+            GLfloat vals[4] = { x, y, z, 1 };

+            context->setVertexAttrib(index, vals);

+        }

+    }

+    catch(std::bad_alloc&)

+    {

+        return error(GL_OUT_OF_MEMORY);

+    }

+}

+

+void GL_APIENTRY glVertexAttrib3fv(GLuint index, const GLfloat* values)

+{

+    TRACE("(GLuint index = %d, const GLfloat* values = 0x%0.8p)", index, values);

+

+    try

+    {

+        if(index >= gl::MAX_VERTEX_ATTRIBS)

+        {

+            return error(GL_INVALID_VALUE);

+        }

+

+        gl::Context *context = gl::getContext();

+

+        if(context)

+        {

+            GLfloat vals[4] = { values[0], values[1], values[2], 1 };

+            context->setVertexAttrib(index, vals);

+        }

+    }

+    catch(std::bad_alloc&)

+    {

+        return error(GL_OUT_OF_MEMORY);

+    }

+}

+

+void GL_APIENTRY glVertexAttrib4f(GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w)

+{

+    TRACE("(GLuint index = %d, GLfloat x = %f, GLfloat y = %f, GLfloat z = %f, GLfloat w = %f)", index, x, y, z, w);

+

+    try

+    {

+        if(index >= gl::MAX_VERTEX_ATTRIBS)

+        {

+            return error(GL_INVALID_VALUE);

+        }

+

+        gl::Context *context = gl::getContext();

+

+        if(context)

+        {

+            GLfloat vals[4] = { x, y, z, w };

+            context->setVertexAttrib(index, vals);

+        }

+    }

+    catch(std::bad_alloc&)

+    {

+        return error(GL_OUT_OF_MEMORY);

+    }

+}

+

+void GL_APIENTRY glVertexAttrib4fv(GLuint index, const GLfloat* values)

+{

+    TRACE("(GLuint index = %d, const GLfloat* values = 0x%0.8p)", index, values);

+

+    try

+    {

+        if(index >= gl::MAX_VERTEX_ATTRIBS)

+        {

+            return error(GL_INVALID_VALUE);

+        }

+

+        gl::Context *context = gl::getContext();

+

+        if(context)

+        {

+            context->setVertexAttrib(index, values);

+        }

+    }

+    catch(std::bad_alloc&)

+    {

+        return error(GL_OUT_OF_MEMORY);

+    }

+}

+

+void GL_APIENTRY glVertexAttribPointer(GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid* ptr)

+{

+    TRACE("(GLuint index = %d, GLint size = %d, GLenum type = 0x%X, "

+          "GLboolean normalized = %d, GLsizei stride = %d, const GLvoid* ptr = 0x%0.8p)",

+          index, size, type, normalized, stride, ptr);

+

+    try

+    {

+        if(index >= gl::MAX_VERTEX_ATTRIBS)

+        {

+            return error(GL_INVALID_VALUE);

+        }

+

+        if(size < 1 || size > 4)

+        {

+            return error(GL_INVALID_VALUE);

+        }

+

+        switch(type)

+        {

+          case GL_BYTE:

+          case GL_UNSIGNED_BYTE:

+          case GL_SHORT:

+          case GL_UNSIGNED_SHORT:

+          case GL_FIXED:

+          case GL_FLOAT:

+            break;

+          default:

+            return error(GL_INVALID_ENUM);

+        }

+

+        if(stride < 0)

+        {

+            return error(GL_INVALID_VALUE);

+        }

+

+        gl::Context *context = gl::getContext();

+

+        if(context)

+        {

+            context->setVertexAttribState(index, context->getArrayBuffer(), size, type, (normalized == GL_TRUE), stride, ptr);

+        }

+    }

+    catch(std::bad_alloc&)

+    {

+        return error(GL_OUT_OF_MEMORY);

+    }

+}

+

+void GL_APIENTRY glViewport(GLint x, GLint y, GLsizei width, GLsizei height)

+{

+    TRACE("(GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d)", x, y, width, height);

+

+    try

+    {

+        if(width < 0 || height < 0)

+        {

+            return error(GL_INVALID_VALUE);

+        }

+

+        gl::Context *context = gl::getContext();

+

+        if(context)

+        {

+            context->setViewportParams(x, y, width, height);

+        }

+    }

+    catch(std::bad_alloc&)

+    {

+        return error(GL_OUT_OF_MEMORY);

+    }

+}

+

+void GL_APIENTRY glBlitFramebufferANGLE(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,

+                                      GLbitfield mask, GLenum filter)

+{

+    TRACE("(GLint srcX0 = %d, GLint srcY0 = %d, GLint srcX1 = %d, GLint srcY1 = %d, "

+          "GLint dstX0 = %d, GLint dstY0 = %d, GLint dstX1 = %d, GLint dstY1 = %d, "

+          "GLbitfield mask = 0x%X, GLenum filter = 0x%X)",

+          srcX0, srcY0, srcX1, srcX1, dstX0, dstY0, dstX1, dstY1, mask, filter);

+

+    try

+    {

+        switch(filter)

+        {

+          case GL_NEAREST:

+            break;

+          default:

+            return error(GL_INVALID_ENUM);

+        }

+

+        if((mask & ~(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)) != 0)

+        {

+            return error(GL_INVALID_VALUE);

+        }

+

+        if(srcX1 - srcX0 != dstX1 - dstX0 || srcY1 - srcY0 != dstY1 - dstY0)

+        {

+            ERR("Scaling and flipping in BlitFramebufferANGLE not supported by this implementation");

+            return error(GL_INVALID_OPERATION);

+        }

+

+        gl::Context *context = gl::getContext();

+

+        if(context)

+        {

+            if(context->getReadFramebufferHandle() == context->getDrawFramebufferHandle())

+            {

+                ERR("Blits with the same source and destination framebuffer are not supported by this implementation.");

+                return error(GL_INVALID_OPERATION);

+            }

+

+            context->blitFramebuffer(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask);

+        }

+    }

+    catch(std::bad_alloc&)

+    {

+        return error(GL_OUT_OF_MEMORY);

+    }

+}

+

+void GL_APIENTRY glTexImage3DOES(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth,

+                               GLint border, GLenum format, GLenum type, const GLvoid* pixels)

+{

+    TRACE("(GLenum target = 0x%X, GLint level = %d, GLenum internalformat = 0x%X, "

+          "GLsizei width = %d, GLsizei height = %d, GLsizei depth = %d, GLint border = %d, "

+          "GLenum format = 0x%X, GLenum type = 0x%x, const GLvoid* pixels = 0x%0.8p)",

+          target, level, internalformat, width, height, depth, border, format, type, pixels);

+

+    try

+    {

+        UNIMPLEMENTED();   // FIXME

+    }

+    catch(std::bad_alloc&)

+    {

+        return error(GL_OUT_OF_MEMORY);

+    }

+}

+

+__eglMustCastToProperFunctionPointerType glGetProcAddress(const char *procname)

+{

+    struct Extension

+    {

+        const char *name;

+        __eglMustCastToProperFunctionPointerType address;

+    };

+

+    static const Extension glExtensions[] =

+    {

+        {"glTexImage3DOES", (__eglMustCastToProperFunctionPointerType)glTexImage3DOES},

+        {"glBlitFramebufferANGLE", (__eglMustCastToProperFunctionPointerType)glBlitFramebufferANGLE},

+        {"glRenderbufferStorageMultisampleANGLE", (__eglMustCastToProperFunctionPointerType)glRenderbufferStorageMultisampleANGLE},

+        {"glDeleteFencesNV", (__eglMustCastToProperFunctionPointerType)glDeleteFencesNV},

+        {"glGenFencesNV", (__eglMustCastToProperFunctionPointerType)glGenFencesNV},

+        {"glIsFenceNV", (__eglMustCastToProperFunctionPointerType)glIsFenceNV},

+        {"glTestFenceNV", (__eglMustCastToProperFunctionPointerType)glTestFenceNV},

+        {"glGetFenceivNV", (__eglMustCastToProperFunctionPointerType)glGetFenceivNV},

+        {"glFinishFenceNV", (__eglMustCastToProperFunctionPointerType)glFinishFenceNV},

+        {"glSetFenceNV", (__eglMustCastToProperFunctionPointerType)glSetFenceNV},

+		{"glGetGraphicsResetStatusEXT", (__eglMustCastToProperFunctionPointerType)glGetGraphicsResetStatusEXT},

+        {"glReadnPixelsEXT", (__eglMustCastToProperFunctionPointerType)glReadnPixelsEXT},

+        {"glGetnUniformfvEXT", (__eglMustCastToProperFunctionPointerType)glGetnUniformfvEXT},

+        {"glGetnUniformivEXT", (__eglMustCastToProperFunctionPointerType)glGetnUniformivEXT},

+		{"glGenQueriesEXT", (__eglMustCastToProperFunctionPointerType)glGenQueriesEXT},

+        {"glDeleteQueriesEXT", (__eglMustCastToProperFunctionPointerType)glDeleteQueriesEXT},

+        {"glIsQueryEXT", (__eglMustCastToProperFunctionPointerType)glIsQueryEXT},

+        {"glBeginQueryEXT", (__eglMustCastToProperFunctionPointerType)glBeginQueryEXT},

+        {"glEndQueryEXT", (__eglMustCastToProperFunctionPointerType)glEndQueryEXT},

+        {"glGetQueryivEXT", (__eglMustCastToProperFunctionPointerType)glGetQueryivEXT},

+        {"glGetQueryObjectuivEXT", (__eglMustCastToProperFunctionPointerType)glGetQueryObjectuivEXT},

+    };

+

+    for(int ext = 0; ext < sizeof(glExtensions) / sizeof(Extension); ext++)

+    {

+        if(strcmp(procname, glExtensions[ext].name) == 0)

+        {

+            return (__eglMustCastToProperFunctionPointerType)glExtensions[ext].address;

+        }

+    }

+

+    return NULL;

+}

+

+void glBindTexImage(egl::Surface *surface)

+{

+    TRACE("(egl::Surface* surface = 0x%0.8p)",

+          surface);

+

+    try

+    {

+        gl::Context *context = gl::getContext();

+

+        if(context)

+        {

+            gl::Texture2D *textureObject = context->getTexture2D();

+

+            if(textureObject)

+            {

+                textureObject->bindTexImage(surface);

+            }

+        }

+    }

+    catch(std::bad_alloc&)

+    {

+        return error(GL_OUT_OF_MEMORY);

+    }

+}

+

+}

diff --git a/src/GLES2/libGLESv2/libGLESv2.def b/src/GLES2/libGLESv2/libGLESv2.def
new file mode 100644
index 0000000..bd087d3
--- /dev/null
+++ b/src/GLES2/libGLESv2/libGLESv2.def
@@ -0,0 +1,183 @@
+LIBRARY libGLESv2
+EXPORTS
+    glActiveTexture                 @1
+    glAttachShader                  @2
+    glBindAttribLocation            @3
+    glBindBuffer                    @4
+    glBindFramebuffer               @5
+    glBindRenderbuffer              @6
+    glBindTexture                   @7
+    glBlendColor                    @8
+    glBlendEquation                 @9
+    glBlendEquationSeparate         @10
+    glBlendFunc                     @11
+    glBlendFuncSeparate             @12
+    glBufferData                    @13
+    glBufferSubData                 @14
+    glCheckFramebufferStatus        @15
+    glClear                         @16
+    glClearColor                    @17
+    glClearDepthf                   @18
+    glClearStencil                  @19
+    glColorMask                     @20
+    glCompileShader                 @21
+    glCompressedTexImage2D          @22
+    glCompressedTexSubImage2D       @23
+    glCopyTexImage2D                @24
+    glCopyTexSubImage2D             @25
+    glCreateProgram                 @26
+    glCreateShader                  @27
+    glCullFace                      @28
+    glDeleteBuffers                 @29
+    glDeleteFramebuffers            @30
+    glDeleteProgram                 @32
+    glDeleteRenderbuffers           @33
+    glDeleteShader                  @34
+    glDeleteTextures                @31
+    glDepthFunc                     @36
+    glDepthMask                     @37
+    glDepthRangef                   @38
+    glDetachShader                  @35
+    glDisable                       @39
+    glDisableVertexAttribArray      @40
+    glDrawArrays                    @41
+    glDrawElements                  @42
+    glEnable                        @43
+    glEnableVertexAttribArray       @44
+    glFinish                        @45
+    glFlush                         @46
+    glFramebufferRenderbuffer       @47
+    glFramebufferTexture2D          @48
+    glFrontFace                     @49
+    glGenBuffers                    @50
+    glGenFramebuffers               @52
+    glGenRenderbuffers              @53
+    glGenTextures                   @54
+    glGenerateMipmap                @51
+    glGetActiveAttrib               @55
+    glGetActiveUniform              @56
+    glGetAttachedShaders            @57
+    glGetAttribLocation             @58
+    glGetBooleanv                   @59
+    glGetBufferParameteriv          @60
+    glGetError                      @61
+    glGetFloatv                     @62
+    glGetFramebufferAttachmentParameteriv   @63
+    glGetIntegerv                   @64
+    glGetProgramInfoLog             @66
+    glGetProgramiv                  @65
+    glGetRenderbufferParameteriv    @67
+    glGetShaderInfoLog              @69
+    glGetShaderPrecisionFormat      @70
+    glGetShaderSource               @71
+    glGetShaderiv                   @68
+    glGetString                     @72
+    glGetTexParameterfv             @73
+    glGetTexParameteriv             @74
+    glGetUniformLocation            @77
+    glGetUniformfv                  @75
+    glGetUniformiv                  @76
+    glGetVertexAttribPointerv       @80
+    glGetVertexAttribfv             @78
+    glGetVertexAttribiv             @79
+    glHint                          @81
+    glIsBuffer                      @82
+    glIsEnabled                     @83
+    glIsFramebuffer                 @84
+    glIsProgram                     @85
+    glIsRenderbuffer                @86
+    glIsShader                      @87
+    glIsTexture                     @88
+    glLineWidth                     @89
+    glLinkProgram                   @90
+    glPixelStorei                   @91
+    glPolygonOffset                 @92
+    glReadPixels                    @93
+    glReleaseShaderCompiler         @94
+    glRenderbufferStorage           @95
+    glSampleCoverage                @96
+    glScissor                       @97
+    glShaderBinary                  @98
+    glShaderSource                  @99
+    glStencilFunc                   @100
+    glStencilFuncSeparate           @101
+    glStencilMask                   @102
+    glStencilMaskSeparate           @103
+    glStencilOp                     @104
+    glStencilOpSeparate             @105
+    glTexImage2D                    @106
+    glTexParameterf                 @107
+    glTexParameterfv                @108
+    glTexParameteri                 @109
+    glTexParameteriv                @110
+    glTexSubImage2D                 @111
+    glUniform1f                     @112
+    glUniform1fv                    @113
+    glUniform1i                     @114
+    glUniform1iv                    @115
+    glUniform2f                     @116
+    glUniform2fv                    @117
+    glUniform2i                     @118
+    glUniform2iv                    @119
+    glUniform3f                     @120
+    glUniform3fv                    @121
+    glUniform3i                     @122
+    glUniform3iv                    @123
+    glUniform4f                     @124
+    glUniform4fv                    @125
+    glUniform4i                     @126
+    glUniform4iv                    @127
+    glUniformMatrix2fv              @128
+    glUniformMatrix3fv              @129
+    glUniformMatrix4fv              @130
+    glUseProgram                    @131
+    glValidateProgram               @132
+    glVertexAttrib1f                @133
+    glVertexAttrib1fv               @134
+    glVertexAttrib2f                @135
+    glVertexAttrib2fv               @136
+    glVertexAttrib3f                @137
+    glVertexAttrib3fv               @138
+    glVertexAttrib4f                @139
+    glVertexAttrib4fv               @140
+    glVertexAttribPointer           @141
+    glViewport                      @142
+
+    ; Extensions
+    glTexImage3DOES                 @143
+    glBlitFramebufferANGLE          @149
+    glRenderbufferStorageMultisampleANGLE @150
+    glDeleteFencesNV                @151
+    glFinishFenceNV                 @152
+    glGenFencesNV                   @153
+    glGetFenceivNV                  @154
+    glIsFenceNV                     @155
+    glSetFenceNV                    @156
+    glTestFenceNV                   @157
+    ;glGetTranslatedShaderSourceANGLE @159
+    ;glTexStorage2DEXT               @160
+    glGetGraphicsResetStatusEXT     @161
+    glReadnPixelsEXT                @162
+    glGetnUniformfvEXT              @163
+    glGetnUniformivEXT              @164
+	glGenQueriesEXT                 @165
+    glDeleteQueriesEXT              @166
+    glIsQueryEXT                    @167
+    glBeginQueryEXT                 @168
+    glEndQueryEXT                   @169
+    glGetQueryivEXT                 @170
+    glGetQueryObjectuivEXT          @171
+
+    ; EGL dependencies
+    glCreateContext                 @144
+    glDestroyContext                @145
+    glMakeCurrent                   @146
+    glGetCurrentContext             @147
+    glGetProcAddress                @148
+    glBindTexImage                  @158
+
+	createFrameBuffer               @172
+	createBackBuffer                @173
+	createDevice                    @174
+
+	Register
\ No newline at end of file
diff --git a/src/GLES2/libGLESv2/libGLESv2.rc b/src/GLES2/libGLESv2/libGLESv2.rc
new file mode 100644
index 0000000..919c7ed
--- /dev/null
+++ b/src/GLES2/libGLESv2/libGLESv2.rc
@@ -0,0 +1,102 @@
+// Microsoft Visual C++ generated resource script.
+//
+#include "resource.h"
+
+#define APSTUDIO_READONLY_SYMBOLS
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 2 resource.
+//
+#include <windows.h>
+#include "../../common/Version.h"
+
+/////////////////////////////////////////////////////////////////////////////
+#undef APSTUDIO_READONLY_SYMBOLS
+
+/////////////////////////////////////////////////////////////////////////////
+// English (U.S.) resources
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
+#ifdef _WIN32
+LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
+#pragma code_page(1252)
+#endif //_WIN32
+
+#ifdef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// TEXTINCLUDE
+//
+
+1 TEXTINCLUDE 
+BEGIN
+    "resource.h\0"
+END
+
+2 TEXTINCLUDE 
+BEGIN
+    "#include ""afxres.h""\r\n"
+    "#include ""../common/version.h""\0"
+END
+
+3 TEXTINCLUDE 
+BEGIN
+    "\r\n"
+    "\0"
+END
+
+#endif    // APSTUDIO_INVOKED
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Version
+//
+
+VS_VERSION_INFO VERSIONINFO
+ FILEVERSION MAJOR_VERSION,MINOR_VERSION,BUILD_VERSION,BUILD_REVISION
+ PRODUCTVERSION MAJOR_VERSION,MINOR_VERSION,BUILD_VERSION,BUILD_REVISION
+ FILEFLAGSMASK 0x17L
+#ifdef _DEBUG
+ FILEFLAGS 0x1L
+#else
+ FILEFLAGS 0x0L
+#endif
+ FILEOS 0x4L
+ FILETYPE 0x2L
+ FILESUBTYPE 0x0L
+BEGIN
+    BLOCK "StringFileInfo"
+    BEGIN
+        BLOCK "040904b0"
+        BEGIN
+            VALUE "FileDescription", "SwiftShader libGLESv2 Dynamic Link Library"
+            VALUE "FileVersion", VERSION_STRING
+            VALUE "InternalName", "libGLESv2"
+            VALUE "LegalCopyright", "Copyright (C) 2012 TransGaming Inc."
+            VALUE "OriginalFilename", "libGLESv2.dll"
+            VALUE "PrivateBuild", VERSION_STRING
+            VALUE "ProductName", "SwiftShader libGLESv2 Dynamic Link Library"
+            VALUE "ProductVersion", VERSION_STRING
+        END
+    END
+    BLOCK "VarFileInfo"
+    BEGIN
+        VALUE "Translation", 0x409, 1200
+    END
+END
+
+#endif    // English (U.S.) resources
+/////////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 3 resource.
+//
+
+
+/////////////////////////////////////////////////////////////////////////////
+#endif    // not APSTUDIO_INVOKED
diff --git a/src/GLES2/libGLESv2/libGLESv2.vcxproj b/src/GLES2/libGLESv2/libGLESv2.vcxproj
new file mode 100644
index 0000000..20cf4f8
--- /dev/null
+++ b/src/GLES2/libGLESv2/libGLESv2.vcxproj
@@ -0,0 +1,241 @@
+<?xml version="1.0" encoding="utf-8"?>

+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

+  <ItemGroup Label="ProjectConfigurations">

+    <ProjectConfiguration Include="Debug|Win32">

+      <Configuration>Debug</Configuration>

+      <Platform>Win32</Platform>

+    </ProjectConfiguration>

+    <ProjectConfiguration Include="Profile|Win32">

+      <Configuration>Profile</Configuration>

+      <Platform>Win32</Platform>

+    </ProjectConfiguration>

+    <ProjectConfiguration Include="Release|Win32">

+      <Configuration>Release</Configuration>

+      <Platform>Win32</Platform>

+    </ProjectConfiguration>

+  </ItemGroup>

+  <PropertyGroup Label="Globals">

+    <ProjectGuid>{B5871A7A-968C-42E3-A33B-981E6F448E78}</ProjectGuid>

+    <RootNamespace>libGLESv2</RootNamespace>

+    <Keyword>Win32Proj</Keyword>

+  </PropertyGroup>

+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">

+    <ConfigurationType>DynamicLibrary</ConfigurationType>

+    <CharacterSet>NotSet</CharacterSet>

+    <WholeProgramOptimization>true</WholeProgramOptimization>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Profile|Win32'" Label="Configuration">

+    <ConfigurationType>DynamicLibrary</ConfigurationType>

+    <CharacterSet>NotSet</CharacterSet>

+    <WholeProgramOptimization>true</WholeProgramOptimization>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">

+    <ConfigurationType>DynamicLibrary</ConfigurationType>

+    <CharacterSet>NotSet</CharacterSet>

+  </PropertyGroup>

+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />

+  <ImportGroup Label="ExtensionSettings">

+  </ImportGroup>

+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">

+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

+  </ImportGroup>

+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Profile|Win32'" Label="PropertySheets">

+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

+  </ImportGroup>

+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">

+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

+  </ImportGroup>

+  <PropertyGroup Label="UserMacros" />

+  <PropertyGroup>

+    <_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion>

+    <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(Platform)\$(Configuration)\</OutDir>

+    <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(Platform)\$(Configuration)\</IntDir>

+    <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</LinkIncremental>

+    <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(Platform)\$(Configuration)\</OutDir>

+    <OutDir Condition="'$(Configuration)|$(Platform)'=='Profile|Win32'">$(Platform)\$(Configuration)\</OutDir>

+    <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(Platform)\$(Configuration)\</IntDir>

+    <IntDir Condition="'$(Configuration)|$(Platform)'=='Profile|Win32'">$(Platform)\$(Configuration)\</IntDir>

+    <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</LinkIncremental>

+    <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Profile|Win32'">false</LinkIncremental>

+    <IncludePath Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(DXSDK_DIR)\Include;..\include;$(IncludePath)</IncludePath>

+    <IncludePath Condition="'$(Configuration)|$(Platform)'=='Profile|Win32'">$(DXSDK_DIR)\Include;..\include;$(IncludePath)</IncludePath>

+    <IncludePath Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(DXSDK_DIR)\Include;..\include;$(DXSDK_DIR)\Include;$(VCInstallDir)PlatformSDK\include;$(IncludePath)</IncludePath>

+    <LibraryPath Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(DXSDK_DIR)\Lib\x86;$(VCInstallDir)PlatformSDK\lib;$(LibraryPath)</LibraryPath>

+    <LibraryPath Condition="'$(Configuration)|$(Platform)'=='Profile|Win32'">$(DXSDK_DIR)\Lib\x86;$(VCInstallDir)lib;$(VCInstallDir)atlmfc\lib;$(WindowsSdkDir)lib;$(FrameworkSDKDir)\lib</LibraryPath>

+    <LibraryPath Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(DXSDK_DIR)\Lib\x86;$(VCInstallDir)lib;$(VCInstallDir)atlmfc\lib;$(WindowsSdkDir)lib;$(FrameworkSDKDir)\lib</LibraryPath>

+  </PropertyGroup>

+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">

+    <ClCompile>

+      <Optimization>Disabled</Optimization>

+      <AdditionalIncludeDirectories>$(SolutionDir);$(ProjectDir)/..;$(ProjectDir)/../..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>

+      <PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;LIBGLESV2_EXPORTS;_CRT_SECURE_NO_DEPRECATE;NOMINMAX;%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <MinimalRebuild>true</MinimalRebuild>

+      <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>

+      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>

+      <PrecompiledHeader>

+      </PrecompiledHeader>

+      <WarningLevel>Level3</WarningLevel>

+      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>

+      <BrowseInformation>true</BrowseInformation>

+    </ClCompile>

+    <Link>

+      <AdditionalDependencies>dxguid.lib;dwmapi.lib;WS2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>

+      <ModuleDefinitionFile>libGLESv2.def</ModuleDefinitionFile>

+      <GenerateDebugInformation>true</GenerateDebugInformation>

+      <SubSystem>Windows</SubSystem>

+      <RandomizedBaseAddress>false</RandomizedBaseAddress>

+      <DataExecutionPrevention>

+      </DataExecutionPrevention>

+      <TargetMachine>MachineX86</TargetMachine>

+    </Link>

+    <PostBuildEvent>

+      <Command>mkdir "$(ProjectDir)..\..\lib\$(Configuration)\"

+copy "$(OutDir)libGLESv2.dll" "$(ProjectDir)..\..\lib\$(Configuration)\"

+copy "$(OutDir)libGLESv2.lib" "$(ProjectDir)..\..\lib\$(Configuration)\"</Command>

+    </PostBuildEvent>

+  </ItemDefinitionGroup>

+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">

+    <ClCompile>

+      <Optimization>Full</Optimization>

+      <InlineFunctionExpansion>AnySuitable</InlineFunctionExpansion>

+      <AdditionalIncludeDirectories>$(ProjectDir)/..;$(ProjectDir)/../..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>

+      <PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;LIBGLESV2_EXPORTS;_CRT_SECURE_NO_DEPRECATE;NOMINMAX;_SECURE_SCL=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>

+      <PrecompiledHeader>

+      </PrecompiledHeader>

+      <WarningLevel>Level3</WarningLevel>

+      <DebugInformationFormat>

+      </DebugInformationFormat>

+      <FavorSizeOrSpeed>Size</FavorSizeOrSpeed>

+      <OmitFramePointers>true</OmitFramePointers>

+      <EnableFiberSafeOptimizations>true</EnableFiberSafeOptimizations>

+      <WholeProgramOptimization>true</WholeProgramOptimization>

+      <IntrinsicFunctions>false</IntrinsicFunctions>

+    </ClCompile>

+    <Link>

+      <AdditionalDependencies>dxguid.lib;dwmapi.lib;WS2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>

+      <IgnoreAllDefaultLibraries>false</IgnoreAllDefaultLibraries>

+      <ModuleDefinitionFile>libGLESv2.def</ModuleDefinitionFile>

+      <GenerateDebugInformation>true</GenerateDebugInformation>

+      <SubSystem>Windows</SubSystem>

+      <OptimizeReferences>true</OptimizeReferences>

+      <EnableCOMDATFolding>true</EnableCOMDATFolding>

+      <RandomizedBaseAddress>false</RandomizedBaseAddress>

+      <DataExecutionPrevention>

+      </DataExecutionPrevention>

+      <TargetMachine>MachineX86</TargetMachine>

+    </Link>

+    <PostBuildEvent>

+      <Command>mkdir "$(ProjectDir)..\..\lib\$(Configuration)\"

+copy "$(OutDir)libGLESv2.dll" "$(ProjectDir)..\..\lib\$(Configuration)\"

+copy "$(OutDir)libGLESv2.lib" "$(ProjectDir)..\..\lib\$(Configuration)\"</Command>

+    </PostBuildEvent>

+  </ItemDefinitionGroup>

+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Profile|Win32'">

+    <ClCompile>

+      <Optimization>Full</Optimization>

+      <InlineFunctionExpansion>AnySuitable</InlineFunctionExpansion>

+      <AdditionalIncludeDirectories>$(ProjectDir)/..; $(ProjectDir)/../..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>

+      <PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;LIBGLESV2_EXPORTS;_CRT_SECURE_NO_DEPRECATE;NOMINMAX;_SECURE_SCL=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>

+      <PrecompiledHeader>

+      </PrecompiledHeader>

+      <WarningLevel>Level3</WarningLevel>

+      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>

+      <FavorSizeOrSpeed>Size</FavorSizeOrSpeed>

+      <OmitFramePointers>false</OmitFramePointers>

+      <EnableFiberSafeOptimizations>true</EnableFiberSafeOptimizations>

+      <WholeProgramOptimization>true</WholeProgramOptimization>

+      <IntrinsicFunctions>false</IntrinsicFunctions>

+    </ClCompile>

+    <Link>

+      <AdditionalDependencies>dxguid.lib;dwmapi.lib;WS2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>

+      <IgnoreAllDefaultLibraries>false</IgnoreAllDefaultLibraries>

+      <ModuleDefinitionFile>libGLESv2.def</ModuleDefinitionFile>

+      <GenerateDebugInformation>true</GenerateDebugInformation>

+      <SubSystem>Windows</SubSystem>

+      <OptimizeReferences>true</OptimizeReferences>

+      <EnableCOMDATFolding>true</EnableCOMDATFolding>

+      <RandomizedBaseAddress>false</RandomizedBaseAddress>

+      <DataExecutionPrevention>

+      </DataExecutionPrevention>

+      <TargetMachine>MachineX86</TargetMachine>

+    </Link>

+    <PostBuildEvent>

+      <Command>mkdir "$(ProjectDir)..\..\lib\$(Configuration)\"

+copy "$(OutDir)libGLESv2.dll" "$(ProjectDir)..\..\lib\$(Configuration)\"

+copy "$(OutDir)libGLESv2.lib" "$(ProjectDir)..\..\lib\$(Configuration)\"</Command>

+    </PostBuildEvent>

+  </ItemDefinitionGroup>

+  <ItemGroup>

+    <ClCompile Include="Buffer.cpp" />

+    <ClCompile Include="Context.cpp" />

+    <ClCompile Include="..\common\debug.cpp" />

+    <ClCompile Include="Device.cpp" />

+    <ClCompile Include="Fence.cpp" />

+    <ClCompile Include="Framebuffer.cpp" />

+    <ClCompile Include="HandleAllocator.cpp" />

+    <ClCompile Include="Image.cpp" />

+    <ClCompile Include="IndexDataManager.cpp" />

+    <ClCompile Include="libGLESv2.cpp" />

+    <ClCompile Include="main.cpp" />

+    <ClCompile Include="Program.cpp" />

+    <ClCompile Include="Query.cpp" />

+    <ClCompile Include="RefCountObject.cpp" />

+    <ClCompile Include="Renderbuffer.cpp" />

+    <ClCompile Include="ResourceManager.cpp" />

+    <ClCompile Include="Shader.cpp" />

+    <ClCompile Include="Texture.cpp" />

+    <ClCompile Include="utilities.cpp" />

+    <ClCompile Include="VertexDataManager.cpp" />

+  </ItemGroup>

+  <ItemGroup>

+    <ClInclude Include="..\common\debug.h" />

+    <ClInclude Include="..\include\GLES2\gl2.h" />

+    <ClInclude Include="..\include\GLES2\gl2ext.h" />

+    <ClInclude Include="..\include\GLES2\gl2platform.h" />

+    <ClInclude Include="Buffer.h" />

+    <ClInclude Include="Context.h" />

+    <ClInclude Include="Device.hpp" />

+    <ClInclude Include="Fence.h" />

+    <ClInclude Include="Framebuffer.h" />

+    <ClInclude Include="HandleAllocator.h" />

+    <ClInclude Include="Image.hpp" />

+    <ClInclude Include="IndexDataManager.h" />

+    <ClInclude Include="main.h" />

+    <ClInclude Include="mathutil.h" />

+    <ClInclude Include="Program.h" />

+    <ClInclude Include="Query.h" />

+    <ClInclude Include="RefCountObject.h" />

+    <ClInclude Include="Renderbuffer.h" />

+    <ClInclude Include="resource.h" />

+    <ClInclude Include="ResourceManager.h" />

+    <ClInclude Include="Shader.h" />

+    <ClInclude Include="Texture.h" />

+    <ClInclude Include="utilities.h" />

+    <ClInclude Include="VertexDataManager.h" />

+  </ItemGroup>

+  <ItemGroup>

+    <None Include="libGLESv2.def" />

+  </ItemGroup>

+  <ItemGroup>

+    <ResourceCompile Include="libGLESv2.rc" />

+  </ItemGroup>

+  <ItemGroup>

+    <ProjectReference Include="..\..\SwiftShader\SwiftShader.vcxproj">

+      <Project>{7b02cb19-4cdf-4f79-bc9b-7f3f6164a003}</Project>

+      <Private>true</Private>

+      <ReferenceOutputAssembly>true</ReferenceOutputAssembly>

+      <CopyLocalSatelliteAssemblies>false</CopyLocalSatelliteAssemblies>

+      <LinkLibraryDependencies>true</LinkLibraryDependencies>

+      <UseLibraryDependencyInputs>true</UseLibraryDependencyInputs>

+    </ProjectReference>

+    <ProjectReference Include="..\compiler\Compiler.vcxproj">

+      <Project>{5b3a6db8-1e7e-40d7-92b9-da8aae619fad}</Project>

+    </ProjectReference>

+  </ItemGroup>

+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />

+  <ImportGroup Label="ExtensionTargets">

+  </ImportGroup>

+</Project>
\ No newline at end of file
diff --git a/src/GLES2/libGLESv2/libGLESv2.vcxproj.filters b/src/GLES2/libGLESv2/libGLESv2.vcxproj.filters
new file mode 100644
index 0000000..91125de
--- /dev/null
+++ b/src/GLES2/libGLESv2/libGLESv2.vcxproj.filters
@@ -0,0 +1,155 @@
+<?xml version="1.0" encoding="utf-8"?>

+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

+  <ItemGroup>

+    <Filter Include="Source Files">

+      <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>

+      <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>

+    </Filter>

+    <Filter Include="Header Files">

+      <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>

+      <Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>

+    </Filter>

+  </ItemGroup>

+  <ItemGroup>

+    <ClCompile Include="Buffer.cpp">

+      <Filter>Source Files</Filter>

+    </ClCompile>

+    <ClCompile Include="Context.cpp">

+      <Filter>Source Files</Filter>

+    </ClCompile>

+    <ClCompile Include="..\common\debug.cpp">

+      <Filter>Source Files</Filter>

+    </ClCompile>

+    <ClCompile Include="Fence.cpp">

+      <Filter>Source Files</Filter>

+    </ClCompile>

+    <ClCompile Include="Framebuffer.cpp">

+      <Filter>Source Files</Filter>

+    </ClCompile>

+    <ClCompile Include="HandleAllocator.cpp">

+      <Filter>Source Files</Filter>

+    </ClCompile>

+    <ClCompile Include="IndexDataManager.cpp">

+      <Filter>Source Files</Filter>

+    </ClCompile>

+    <ClCompile Include="libGLESv2.cpp">

+      <Filter>Source Files</Filter>

+    </ClCompile>

+    <ClCompile Include="main.cpp">

+      <Filter>Source Files</Filter>

+    </ClCompile>

+    <ClCompile Include="Program.cpp">

+      <Filter>Source Files</Filter>

+    </ClCompile>

+    <ClCompile Include="RefCountObject.cpp">

+      <Filter>Source Files</Filter>

+    </ClCompile>

+    <ClCompile Include="Renderbuffer.cpp">

+      <Filter>Source Files</Filter>

+    </ClCompile>

+    <ClCompile Include="ResourceManager.cpp">

+      <Filter>Source Files</Filter>

+    </ClCompile>

+    <ClCompile Include="Shader.cpp">

+      <Filter>Source Files</Filter>

+    </ClCompile>

+    <ClCompile Include="Texture.cpp">

+      <Filter>Source Files</Filter>

+    </ClCompile>

+    <ClCompile Include="utilities.cpp">

+      <Filter>Source Files</Filter>

+    </ClCompile>

+    <ClCompile Include="VertexDataManager.cpp">

+      <Filter>Source Files</Filter>

+    </ClCompile>

+    <ClCompile Include="Device.cpp">

+      <Filter>Source Files</Filter>

+    </ClCompile>

+    <ClCompile Include="Image.cpp">

+      <Filter>Source Files</Filter>

+    </ClCompile>

+    <ClCompile Include="Query.cpp">

+      <Filter>Source Files</Filter>

+    </ClCompile>

+  </ItemGroup>

+  <ItemGroup>

+    <ClInclude Include="Buffer.h">

+      <Filter>Header Files</Filter>

+    </ClInclude>

+    <ClInclude Include="Context.h">

+      <Filter>Header Files</Filter>

+    </ClInclude>

+    <ClInclude Include="Fence.h">

+      <Filter>Header Files</Filter>

+    </ClInclude>

+    <ClInclude Include="Framebuffer.h">

+      <Filter>Header Files</Filter>

+    </ClInclude>

+    <ClInclude Include="HandleAllocator.h">

+      <Filter>Header Files</Filter>

+    </ClInclude>

+    <ClInclude Include="IndexDataManager.h">

+      <Filter>Header Files</Filter>

+    </ClInclude>

+    <ClInclude Include="main.h">

+      <Filter>Header Files</Filter>

+    </ClInclude>

+    <ClInclude Include="mathutil.h">

+      <Filter>Header Files</Filter>

+    </ClInclude>

+    <ClInclude Include="Program.h">

+      <Filter>Header Files</Filter>

+    </ClInclude>

+    <ClInclude Include="RefCountObject.h">

+      <Filter>Header Files</Filter>

+    </ClInclude>

+    <ClInclude Include="Renderbuffer.h">

+      <Filter>Header Files</Filter>

+    </ClInclude>

+    <ClInclude Include="resource.h">

+      <Filter>Header Files</Filter>

+    </ClInclude>

+    <ClInclude Include="ResourceManager.h">

+      <Filter>Header Files</Filter>

+    </ClInclude>

+    <ClInclude Include="Shader.h">

+      <Filter>Header Files</Filter>

+    </ClInclude>

+    <ClInclude Include="Texture.h">

+      <Filter>Header Files</Filter>

+    </ClInclude>

+    <ClInclude Include="utilities.h">

+      <Filter>Header Files</Filter>

+    </ClInclude>

+    <ClInclude Include="VertexDataManager.h">

+      <Filter>Header Files</Filter>

+    </ClInclude>

+    <ClInclude Include="Device.hpp">

+      <Filter>Header Files</Filter>

+    </ClInclude>

+    <ClInclude Include="Image.hpp">

+      <Filter>Header Files</Filter>

+    </ClInclude>

+    <ClInclude Include="..\include\GLES2\gl2.h">

+      <Filter>Header Files</Filter>

+    </ClInclude>

+    <ClInclude Include="..\include\GLES2\gl2ext.h">

+      <Filter>Header Files</Filter>

+    </ClInclude>

+    <ClInclude Include="..\include\GLES2\gl2platform.h">

+      <Filter>Header Files</Filter>

+    </ClInclude>

+    <ClInclude Include="Query.h">

+      <Filter>Header Files</Filter>

+    </ClInclude>

+    <ClInclude Include="..\common\debug.h">

+      <Filter>Header Files</Filter>

+    </ClInclude>

+  </ItemGroup>

+  <ItemGroup>

+    <ResourceCompile Include="libGLESv2.rc" />

+  </ItemGroup>

+  <ItemGroup>

+    <None Include="libGLESv2.def" />

+  </ItemGroup>

+</Project>
\ No newline at end of file
diff --git a/src/GLES2/libGLESv2/main.cpp b/src/GLES2/libGLESv2/main.cpp
new file mode 100644
index 0000000..4393ae7
--- /dev/null
+++ b/src/GLES2/libGLESv2/main.cpp
@@ -0,0 +1,177 @@
+// SwiftShader Software Renderer

+//

+// Copyright(c) 2005-2012 TransGaming Inc.

+//

+// All rights reserved. No part of this software may be copied, distributed, transmitted,

+// transcribed, stored in a retrieval system, translated into any human or computer

+// language by any means, or disclosed to third parties without the explicit written

+// agreement of TransGaming Inc. Without such an agreement, no rights or licenses, express

+// or implied, including but not limited to any patent rights, are granted to you.

+//

+

+// main.cpp: DLL entry point and management of thread-local data.

+

+#include "main.h"

+

+#include "Framebuffer.h"

+#include "libEGL/Surface.h"

+#include "Common/Thread.hpp"

+#include "common/debug.h"

+

+static sw::Thread::LocalStorageKey currentTLS = TLS_OUT_OF_INDEXES;

+

+#if !defined(_MSC_VER)

+#define CONSTRUCTOR __attribute__((constructor))

+#define DESTRUCTOR __attribute__((destructor))

+#else

+#define CONSTRUCTOR

+#define DESTRUCTOR

+#endif

+

+static void glAttachThread()

+{

+    TRACE("()");

+

+	gl::Current *current = new gl::Current;

+

+    if(current)

+    {

+		sw::Thread::setLocalStorage(currentTLS, current);

+

+        current->context = NULL;

+        current->display = NULL;

+    }

+}

+

+static void glDetachThread()

+{

+    TRACE("()");

+

+	gl::Current *current = (gl::Current*)sw::Thread::getLocalStorage(currentTLS);

+

+    if(current)

+    {

+        delete current;

+    }

+}

+

+CONSTRUCTOR static bool glAttachProcess()

+{

+    TRACE("()");

+

+	currentTLS = sw::Thread::allocateLocalStorageKey();

+

+    if(currentTLS == TLS_OUT_OF_INDEXES)

+    {

+        return false;

+    }

+

+    glAttachThread();

+

+    return true;

+}

+

+DESTRUCTOR static void glDetachProcess()

+{

+    TRACE("()");

+

+	glDetachThread();

+

+    sw::Thread::freeLocalStorageKey(currentTLS);

+}

+

+#if defined(_WIN32)

+extern "C" BOOL WINAPI DllMain(HINSTANCE instance, DWORD reason, LPVOID reserved)

+{

+    switch(reason)

+    {

+    case DLL_PROCESS_ATTACH:

+        return glAttachProcess();

+        break;

+    case DLL_THREAD_ATTACH:

+        glAttachThread();

+        break;

+    case DLL_THREAD_DETACH:

+        glDetachThread();

+        break;

+    case DLL_PROCESS_DETACH:

+        glDetachProcess();

+        break;

+    default:

+        break;

+    }

+

+    return TRUE;

+}

+#endif

+

+namespace gl

+{

+void makeCurrent(Context *context, egl::Display *display, egl::Surface *surface)

+{

+    Current *current = (Current*)sw::Thread::getLocalStorage(currentTLS);

+

+    current->context = context;

+    current->display = display;

+

+    if(context && display && surface)

+    {

+        context->makeCurrent(display, surface);

+    }

+}

+

+Context *getContext()

+{

+    Current *current = (Current*)sw::Thread::getLocalStorage(currentTLS);

+

+    return current->context;

+}

+

+egl::Display *getDisplay()

+{

+    Current *current = (Current*)sw::Thread::getLocalStorage(currentTLS);

+

+    return current->display;

+}

+

+Device *getDevice()

+{

+    egl::Display *display = getDisplay();

+

+    return display->getDevice();

+}

+}

+

+// Records an error code

+void error(GLenum errorCode)

+{

+    gl::Context *context = gl::getContext();

+

+    if(context)

+    {

+        switch(errorCode)

+        {

+        case GL_INVALID_ENUM:

+            context->recordInvalidEnum();

+            TRACE("\t! Error generated: invalid enum\n");

+            break;

+        case GL_INVALID_VALUE:

+            context->recordInvalidValue();

+            TRACE("\t! Error generated: invalid value\n");

+            break;

+        case GL_INVALID_OPERATION:

+            context->recordInvalidOperation();

+            TRACE("\t! Error generated: invalid operation\n");

+            break;

+        case GL_OUT_OF_MEMORY:

+            context->recordOutOfMemory();

+            TRACE("\t! Error generated: out of memory\n");

+            break;

+        case GL_INVALID_FRAMEBUFFER_OPERATION:

+            context->recordInvalidFramebufferOperation();

+            TRACE("\t! Error generated: invalid framebuffer operation\n");

+            break;

+        default: UNREACHABLE();

+        }

+    }

+}

diff --git a/src/GLES2/libGLESv2/main.h b/src/GLES2/libGLESv2/main.h
new file mode 100644
index 0000000..fdb0dc0
--- /dev/null
+++ b/src/GLES2/libGLESv2/main.h
@@ -0,0 +1,52 @@
+// SwiftShader Software Renderer
+//
+// Copyright(c) 2005-2012 TransGaming Inc.
+//
+// All rights reserved. No part of this software may be copied, distributed, transmitted,
+// transcribed, stored in a retrieval system, translated into any human or computer
+// language by any means, or disclosed to third parties without the explicit written
+// agreement of TransGaming Inc. Without such an agreement, no rights or licenses, express
+// or implied, including but not limited to any patent rights, are granted to you.
+//
+
+// main.h: Management of thread-local data.
+
+#ifndef LIBGLESV2_MAIN_H_
+#define LIBGLESV2_MAIN_H_
+
+#include "Context.h"
+#include "Device.hpp"
+#include "common/debug.h"
+#include "libEGL/Display.h"
+
+#define GL_APICALL
+#include <GLES2/gl2.h>
+#include <GLES2/gl2ext.h>
+
+namespace gl
+{
+	struct Current
+	{
+		Context *context;
+		egl::Display *display;
+	};
+
+	void makeCurrent(Context *context, egl::Display *display, egl::Surface *surface);
+
+	Context *getContext();
+	egl::Display *getDisplay();
+
+	Device *getDevice();
+}
+
+void error(GLenum errorCode);
+
+template<class T>
+const T &error(GLenum errorCode, const T &returnValue)
+{
+    error(errorCode);
+
+    return returnValue;
+}
+
+#endif   // LIBGLESV2_MAIN_H_
diff --git a/src/GLES2/libGLESv2/mathutil.h b/src/GLES2/libGLESv2/mathutil.h
new file mode 100644
index 0000000..9955fb2
--- /dev/null
+++ b/src/GLES2/libGLESv2/mathutil.h
@@ -0,0 +1,79 @@
+// SwiftShader Software Renderer
+//
+// Copyright(c) 2005-2012 TransGaming Inc.
+//
+// All rights reserved. No part of this software may be copied, distributed, transmitted,
+// transcribed, stored in a retrieval system, translated into any human or computer
+// language by any means, or disclosed to third parties without the explicit written
+// agreement of TransGaming Inc. Without such an agreement, no rights or licenses, express
+// or implied, including but not limited to any patent rights, are granted to you.
+//
+
+// mathutil.h: Math and bit manipulation functions.
+
+#ifndef LIBGLESV2_MATHUTIL_H_
+#define LIBGLESV2_MATHUTIL_H_
+
+#include "common/debug.h"
+
+#include <math.h>
+
+namespace gl
+{
+inline bool isPow2(int x)
+{
+    return (x & (x - 1)) == 0 && (x != 0);
+}
+
+inline int log2(int x)
+{
+    int r = 0;
+    while((x >> r) > 1) r++;
+    return r;
+}
+
+inline unsigned int ceilPow2(unsigned int x)
+{
+    if(x != 0) x--;
+    x |= x >> 1;
+    x |= x >> 2;
+    x |= x >> 4;
+    x |= x >> 8;
+    x |= x >> 16;
+    x++;
+
+    return x;
+}
+
+template<typename T, typename MIN, typename MAX>
+inline T clamp(T x, MIN min, MAX max)
+{
+    return x < min ? min : (x > max ? max : x);
+}
+
+inline float clamp01(float x)
+{
+    return clamp(x, 0.0f, 1.0f);
+}
+
+template<const int n>
+inline unsigned int unorm(float x)
+{
+    const unsigned int max = 0xFFFFFFFF >> (32 - n);
+
+    if(x > 1)
+    {
+        return max;
+    }
+    else if(x < 0)
+    {
+        return 0;
+    }
+    else
+    {
+        return (unsigned int)(max * x + 0.5f);
+    }
+}
+}
+
+#endif   // LIBGLESV2_MATHUTIL_H_
diff --git a/src/GLES2/libGLESv2/resource.h b/src/GLES2/libGLESv2/resource.h
new file mode 100644
index 0000000..39adaad
--- /dev/null
+++ b/src/GLES2/libGLESv2/resource.h
@@ -0,0 +1,14 @@
+//{{NO_DEPENDENCIES}}
+// Microsoft Visual C++ generated include file.
+// Used by libGLESv2.rc
+
+// Next default values for new objects
+// 
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NEXT_RESOURCE_VALUE        101
+#define _APS_NEXT_COMMAND_VALUE         40001
+#define _APS_NEXT_CONTROL_VALUE         1001
+#define _APS_NEXT_SYMED_VALUE           101
+#endif
+#endif
diff --git a/src/GLES2/libGLESv2/utilities.cpp b/src/GLES2/libGLESv2/utilities.cpp
new file mode 100644
index 0000000..954d937
--- /dev/null
+++ b/src/GLES2/libGLESv2/utilities.cpp
@@ -0,0 +1,849 @@
+// SwiftShader Software Renderer

+//

+// Copyright(c) 2005-2013 TransGaming Inc.

+//

+// All rights reserved. No part of this software may be copied, distributed, transmitted,

+// transcribed, stored in a retrieval system, translated into any human or computer

+// language by any means, or disclosed to third parties without the explicit written

+// agreement of TransGaming Inc. Without such an agreement, no rights or licenses, express

+// or implied, including but not limited to any patent rights, are granted to you.

+//

+

+// utilities.cpp: Conversion functions and other utility routines.

+

+#include "utilities.h"

+

+#include "mathutil.h"

+#include "Context.h"

+#include "common/debug.h"

+

+#include <limits>

+#include <stdio.h>

+

+namespace gl

+{

+	int UniformComponentCount(GLenum type)

+	{

+		switch(type)

+		{

+		case GL_BOOL:

+		case GL_FLOAT:

+		case GL_INT:

+		case GL_SAMPLER_2D:

+		case GL_SAMPLER_CUBE:

+			return 1;

+		case GL_BOOL_VEC2:

+		case GL_FLOAT_VEC2:

+		case GL_INT_VEC2:

+			return 2;

+		case GL_INT_VEC3:

+		case GL_FLOAT_VEC3:

+		case GL_BOOL_VEC3:

+			return 3;

+		case GL_BOOL_VEC4:

+		case GL_FLOAT_VEC4:

+		case GL_INT_VEC4:

+		case GL_FLOAT_MAT2:

+			return 4;

+		case GL_FLOAT_MAT3:

+			return 9;

+		case GL_FLOAT_MAT4:

+			return 16;

+		default:

+			UNREACHABLE();

+		}

+

+		return 0;

+	}

+

+	GLenum UniformComponentType(GLenum type)

+	{

+		switch(type)

+		{

+		case GL_BOOL:

+		case GL_BOOL_VEC2:

+		case GL_BOOL_VEC3:

+		case GL_BOOL_VEC4:

+			return GL_BOOL;

+		case GL_FLOAT:

+		case GL_FLOAT_VEC2:

+		case GL_FLOAT_VEC3:

+		case GL_FLOAT_VEC4:

+		case GL_FLOAT_MAT2:

+		case GL_FLOAT_MAT3:

+		case GL_FLOAT_MAT4:

+			return GL_FLOAT;

+		case GL_INT:

+		case GL_SAMPLER_2D:

+		case GL_SAMPLER_CUBE:

+		case GL_INT_VEC2:

+		case GL_INT_VEC3:

+		case GL_INT_VEC4:

+			return GL_INT;

+		default:

+			UNREACHABLE();

+		}

+

+		return GL_NONE;

+	}

+

+	size_t UniformTypeSize(GLenum type)

+	{

+		switch(type)

+		{

+		case GL_BOOL:  return sizeof(GLboolean);

+		case GL_FLOAT: return sizeof(GLfloat);

+		case GL_INT:   return sizeof(GLint);

+		}

+

+		return UniformTypeSize(UniformComponentType(type)) * UniformComponentCount(type);

+	}

+

+	int VariableRowCount(GLenum type)

+	{

+		switch(type)

+		{

+		case GL_NONE:

+			return 0;

+		case GL_BOOL:

+		case GL_FLOAT:

+		case GL_INT:

+		case GL_BOOL_VEC2:

+		case GL_FLOAT_VEC2:

+		case GL_INT_VEC2:

+		case GL_INT_VEC3:

+		case GL_FLOAT_VEC3:

+		case GL_BOOL_VEC3:

+		case GL_BOOL_VEC4:

+		case GL_FLOAT_VEC4:

+		case GL_INT_VEC4:

+		case GL_SAMPLER_2D:

+		case GL_SAMPLER_CUBE:

+			return 1;

+		case GL_FLOAT_MAT2:

+			return 2;

+		case GL_FLOAT_MAT3:

+			return 3;

+		case GL_FLOAT_MAT4:

+			return 4;

+		default:

+			UNREACHABLE();

+		}

+

+		return 0;

+	}

+

+	int VariableColumnCount(GLenum type)

+	{

+		switch(type)

+		{

+		case GL_NONE:

+			return 0;

+		case GL_BOOL:

+		case GL_FLOAT:

+		case GL_INT:

+			return 1;

+		case GL_BOOL_VEC2:

+		case GL_FLOAT_VEC2:

+		case GL_INT_VEC2:

+		case GL_FLOAT_MAT2:

+			return 2;

+		case GL_INT_VEC3:

+		case GL_FLOAT_VEC3:

+		case GL_BOOL_VEC3:

+		case GL_FLOAT_MAT3:

+			return 3;

+		case GL_BOOL_VEC4:

+		case GL_FLOAT_VEC4:

+		case GL_INT_VEC4:

+		case GL_FLOAT_MAT4:

+			return 4;

+		default:

+			UNREACHABLE();

+		}

+

+		return 0;

+	}

+

+	int AllocateFirstFreeBits(unsigned int *bits, unsigned int allocationSize, unsigned int bitsSize)

+	{

+		ASSERT(allocationSize <= bitsSize);

+

+		unsigned int mask = std::numeric_limits<unsigned int>::max() >> (std::numeric_limits<unsigned int>::digits - allocationSize);

+

+		for(unsigned int i = 0; i < bitsSize - allocationSize + 1; i++)

+		{

+			if((*bits & mask) == 0)

+			{

+				*bits |= mask;

+				return i;

+			}

+

+			mask <<= 1;

+		}

+

+		return -1;

+	}

+

+	GLsizei ComputePitch(GLsizei width, GLenum format, GLenum type, GLint alignment)

+	{

+		ASSERT(alignment > 0 && isPow2(alignment));

+

+		GLsizei rawPitch = ComputePixelSize(format, type) * width;

+		return (rawPitch + alignment - 1) & ~(alignment - 1);

+	}

+

+	GLsizei ComputeCompressedPitch(GLsizei width, GLenum format)

+	{

+		return ComputeCompressedSize(width, 1, format);

+	}

+

+	GLsizei ComputeCompressedSize(GLsizei width, GLsizei height, GLenum format)

+	{

+		switch(format)

+		{

+		case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:

+		case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:

+			return 8 * (GLsizei)ceil((float)width / 4.0f) * (GLsizei)ceil((float)height / 4.0f);

+		case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:

+		case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:

+			return 16 * (GLsizei)ceil((float)width / 4.0f) * (GLsizei)ceil((float)height / 4.0f);

+		default:

+			return 0;

+		}

+	}

+

+	bool IsCompressed(GLenum format)

+	{

+		if(format == GL_COMPRESSED_RGB_S3TC_DXT1_EXT ||

+		   format == GL_COMPRESSED_RGBA_S3TC_DXT1_EXT ||

+		   format == GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE ||

+		   format == GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE)

+		{

+			return true;

+		}

+		else

+		{

+			return false;

+		}

+	}

+

+	bool IsDepthTexture(GLenum format)

+	{

+		if(format == GL_DEPTH_COMPONENT ||

+		   format == GL_DEPTH_STENCIL_OES)

+		{

+			return true;

+		}

+

+		return false;

+	}

+

+	bool IsStencilTexture(GLenum format)

+	{

+		if(format == GL_STENCIL_INDEX ||

+		   format == GL_DEPTH_STENCIL_OES)

+		{

+			return true;

+		}

+

+		return false;

+	}

+

+	// Returns the size, in bytes, of a single texel in an Image

+	int ComputePixelSize(GLenum format, GLenum type)

+	{

+		switch(type)

+		{

+		case GL_UNSIGNED_BYTE:

+			switch(format)

+			{

+			case GL_ALPHA:           return sizeof(unsigned char);

+			case GL_LUMINANCE:       return sizeof(unsigned char);

+			case GL_LUMINANCE_ALPHA: return sizeof(unsigned char) * 2;

+			case GL_RGB:             return sizeof(unsigned char) * 3;

+			case GL_RGBA:            return sizeof(unsigned char) * 4;

+			case GL_BGRA_EXT:        return sizeof(unsigned char) * 4;

+			default: UNREACHABLE();

+			}

+			break;

+		case GL_UNSIGNED_SHORT_4_4_4_4:

+		case GL_UNSIGNED_SHORT_5_5_5_1:

+		case GL_UNSIGNED_SHORT_5_6_5:

+		case GL_UNSIGNED_SHORT:

+			return sizeof(unsigned short);

+		case GL_UNSIGNED_INT:

+		case GL_UNSIGNED_INT_24_8_OES:

+			return sizeof(unsigned int);

+		case GL_FLOAT:

+			switch(format)

+			{

+			case GL_ALPHA:           return sizeof(float);

+			case GL_LUMINANCE:       return sizeof(float);

+			case GL_LUMINANCE_ALPHA: return sizeof(float) * 2;

+			case GL_RGB:             return sizeof(float) * 3;

+			case GL_RGBA:            return sizeof(float) * 4;

+			default: UNREACHABLE();

+			}

+			break;

+		case GL_HALF_FLOAT_OES:

+			switch(format)

+			{

+			case GL_ALPHA:           return sizeof(unsigned short);

+			case GL_LUMINANCE:       return sizeof(unsigned short);

+			case GL_LUMINANCE_ALPHA: return sizeof(unsigned short) * 2;

+			case GL_RGB:             return sizeof(unsigned short) * 3;

+			case GL_RGBA:            return sizeof(unsigned short) * 4;

+			default: UNREACHABLE();

+			}

+			break;

+		default: UNREACHABLE();

+		}

+

+		return 0;

+	}

+

+	bool IsCubemapTextureTarget(GLenum target)

+	{

+		return (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X && target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z);

+	}

+

+	int CubeFaceIndex(GLenum cubeFace)

+	{

+		switch(cubeFace)

+		{

+		case GL_TEXTURE_CUBE_MAP:

+		case GL_TEXTURE_CUBE_MAP_POSITIVE_X: return 0;

+		case GL_TEXTURE_CUBE_MAP_NEGATIVE_X: return 1;

+		case GL_TEXTURE_CUBE_MAP_POSITIVE_Y: return 2;

+		case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: return 3;

+		case GL_TEXTURE_CUBE_MAP_POSITIVE_Z: return 4;

+		case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: return 5;

+		default: UNREACHABLE(); return 0;

+		}

+	}

+

+	bool IsTextureTarget(GLenum target)

+	{

+		return target == GL_TEXTURE_2D || IsCubemapTextureTarget(target);

+	}

+

+	// Verify that format/type are one of the combinations from table 3.4.

+	bool CheckTextureFormatType(GLenum format, GLenum type)

+	{

+		switch(type)

+		{

+		case GL_UNSIGNED_BYTE:

+			switch(format)

+			{

+			case GL_RGBA:

+			case GL_BGRA_EXT:

+			case GL_RGB:

+			case GL_ALPHA:

+			case GL_LUMINANCE:

+			case GL_LUMINANCE_ALPHA:

+				return true;

+			default:

+				return false;

+			}

+		case GL_FLOAT:

+		case GL_HALF_FLOAT_OES:

+			switch(format)

+			{

+			case GL_RGBA:

+			case GL_RGB:

+			case GL_ALPHA:

+			case GL_LUMINANCE:

+			case GL_LUMINANCE_ALPHA:

+				return true;

+			default:

+				return false;

+			}

+		case GL_UNSIGNED_SHORT_4_4_4_4:

+		case GL_UNSIGNED_SHORT_5_5_5_1:

+			return (format == GL_RGBA);

+		case GL_UNSIGNED_SHORT_5_6_5:

+			return (format == GL_RGB);

+		case GL_UNSIGNED_INT:

+			return (format == GL_DEPTH_COMPONENT);

+		case GL_UNSIGNED_INT_24_8_OES:

+			return (format == GL_DEPTH_STENCIL_OES);

+		default:

+			return false;

+		}

+	}

+

+	bool IsColorRenderable(GLenum internalformat)

+	{

+		switch(internalformat)

+		{

+		case GL_RGBA4:

+		case GL_RGB5_A1:

+		case GL_RGB565:

+		case GL_RGB8_OES:

+		case GL_RGBA8_OES:

+			return true;

+		case GL_DEPTH_COMPONENT16:

+		case GL_STENCIL_INDEX8:

+		case GL_DEPTH24_STENCIL8_OES:

+			return false;

+		default:

+			UNIMPLEMENTED();

+		}

+

+		return false;

+	}

+

+	bool IsDepthRenderable(GLenum internalformat)

+	{

+		switch(internalformat)

+		{

+		case GL_DEPTH_COMPONENT16:

+		case GL_DEPTH24_STENCIL8_OES:

+			return true;

+		case GL_STENCIL_INDEX8:

+		case GL_RGBA4:

+		case GL_RGB5_A1:

+		case GL_RGB565:

+		case GL_RGB8_OES:

+		case GL_RGBA8_OES:

+			return false;

+		default:

+			UNIMPLEMENTED();

+		}

+

+		return false;

+	}

+

+	bool IsStencilRenderable(GLenum internalformat)

+	{

+		switch(internalformat)

+		{

+		case GL_STENCIL_INDEX8:

+		case GL_DEPTH24_STENCIL8_OES:

+			return true;

+		case GL_RGBA4:

+		case GL_RGB5_A1:

+		case GL_RGB565:

+		case GL_RGB8_OES:

+		case GL_RGBA8_OES:

+		case GL_DEPTH_COMPONENT16:

+			return false;

+		default:

+			UNIMPLEMENTED();

+		}

+

+		return false;

+	}

+}

+

+namespace es2sw

+{

+	sw::Context::DepthCompareMode ConvertDepthComparison(GLenum comparison)

+	{

+		switch(comparison)

+		{

+		case GL_NEVER:    return sw::Context::DEPTH_NEVER;

+		case GL_ALWAYS:   return sw::Context::DEPTH_ALWAYS;

+		case GL_LESS:     return sw::Context::DEPTH_LESS;

+		case GL_LEQUAL:   return sw::Context::DEPTH_LESSEQUAL;

+		case GL_EQUAL:    return sw::Context::DEPTH_EQUAL;

+		case GL_GREATER:  return sw::Context::DEPTH_GREATER;

+		case GL_GEQUAL:   return sw::Context::DEPTH_GREATEREQUAL;

+		case GL_NOTEQUAL: return sw::Context::DEPTH_NOTEQUAL;

+		default: UNREACHABLE();

+		}

+

+		return sw::Context::DEPTH_ALWAYS;

+	}

+

+	sw::Context::StencilCompareMode ConvertStencilComparison(GLenum comparison)

+	{

+		switch(comparison)

+		{

+		case GL_NEVER:    return sw::Context::STENCIL_NEVER;

+		case GL_ALWAYS:   return sw::Context::STENCIL_ALWAYS;

+		case GL_LESS:     return sw::Context::STENCIL_LESS;

+		case GL_LEQUAL:   return sw::Context::STENCIL_LESSEQUAL;

+		case GL_EQUAL:    return sw::Context::STENCIL_EQUAL;

+		case GL_GREATER:  return sw::Context::STENCIL_GREATER;

+		case GL_GEQUAL:   return sw::Context::STENCIL_GREATEREQUAL;

+		case GL_NOTEQUAL: return sw::Context::STENCIL_NOTEQUAL;

+		default: UNREACHABLE();

+		}

+

+		return sw::Context::STENCIL_ALWAYS;

+	}

+

+	sw::Color<float> ConvertColor(gl::Color color)

+	{

+		return sw::Color<float>(color.red, color.green, color.blue, color.alpha);

+	}

+

+	sw::Context::BlendFactor ConvertBlendFunc(GLenum blend)

+	{

+		switch(blend)

+		{

+		case GL_ZERO:                     return sw::Context::BLEND_ZERO;

+		case GL_ONE:                      return sw::Context::BLEND_ONE;

+		case GL_SRC_COLOR:                return sw::Context::BLEND_SOURCE;

+		case GL_ONE_MINUS_SRC_COLOR:      return sw::Context::BLEND_INVSOURCE;

+		case GL_DST_COLOR:                return sw::Context::BLEND_DEST;

+		case GL_ONE_MINUS_DST_COLOR:      return sw::Context::BLEND_INVDEST;

+		case GL_SRC_ALPHA:                return sw::Context::BLEND_SOURCEALPHA;

+		case GL_ONE_MINUS_SRC_ALPHA:      return sw::Context::BLEND_INVSOURCEALPHA;

+		case GL_DST_ALPHA:                return sw::Context::BLEND_DESTALPHA;

+		case GL_ONE_MINUS_DST_ALPHA:      return sw::Context::BLEND_INVDESTALPHA;

+		case GL_CONSTANT_COLOR:           return sw::Context::BLEND_CONSTANT;

+		case GL_ONE_MINUS_CONSTANT_COLOR: return sw::Context::BLEND_INVCONSTANT;

+		case GL_CONSTANT_ALPHA:           return sw::Context::BLEND_CONSTANTALPHA;

+		case GL_ONE_MINUS_CONSTANT_ALPHA: return sw::Context::BLEND_INVCONSTANTALPHA;

+		case GL_SRC_ALPHA_SATURATE:       return sw::Context::BLEND_SRCALPHASAT;

+		default: UNREACHABLE();

+		}

+

+		return sw::Context::BLEND_ZERO;

+	}

+

+	sw::Context::BlendOperation ConvertBlendOp(GLenum blendOp)

+	{

+		switch(blendOp)

+		{

+		case GL_FUNC_ADD:              return sw::Context::BLENDOP_ADD;

+		case GL_FUNC_SUBTRACT:         return sw::Context::BLENDOP_SUB;

+		case GL_FUNC_REVERSE_SUBTRACT: return sw::Context::BLENDOP_INVSUB;

+		default: UNREACHABLE();

+		}

+

+		return sw::Context::BLENDOP_ADD;

+	}

+

+	sw::Context::StencilOperation ConvertStencilOp(GLenum stencilOp)

+	{

+		switch(stencilOp)

+		{

+		case GL_ZERO:      return sw::Context::OPERATION_ZERO;

+		case GL_KEEP:      return sw::Context::OPERATION_KEEP;

+		case GL_REPLACE:   return sw::Context::OPERATION_REPLACE;

+		case GL_INCR:      return sw::Context::OPERATION_INCRSAT;

+		case GL_DECR:      return sw::Context::OPERATION_DECRSAT;

+		case GL_INVERT:    return sw::Context::OPERATION_INVERT;

+		case GL_INCR_WRAP: return sw::Context::OPERATION_INCR;

+		case GL_DECR_WRAP: return sw::Context::OPERATION_DECR;

+		default: UNREACHABLE();

+		}

+

+		return sw::Context::OPERATION_KEEP;

+	}

+

+	sw::AddressingMode ConvertTextureWrap(GLenum wrap)

+	{

+		switch(wrap)

+		{

+		case GL_REPEAT:            return sw::ADDRESSING_WRAP;

+		case GL_CLAMP_TO_EDGE:     return sw::ADDRESSING_CLAMP;

+		case GL_MIRRORED_REPEAT:   return sw::ADDRESSING_MIRROR;

+		default: UNREACHABLE();

+		}

+

+		return sw::ADDRESSING_WRAP;

+	}

+

+	sw::Context::CullMode ConvertCullMode(GLenum cullFace, GLenum frontFace)

+	{

+		switch(cullFace)

+		{

+		case GL_FRONT:

+			return (frontFace == GL_CCW ? sw::Context::CULL_CLOCKWISE : sw::Context::CULL_COUNTERCLOCKWISE);

+		case GL_BACK:

+			return (frontFace == GL_CCW ? sw::Context::CULL_COUNTERCLOCKWISE : sw::Context::CULL_CLOCKWISE);

+		case GL_FRONT_AND_BACK:

+			return sw::Context::CULL_NONE;   // culling will be handled during draw

+		default: UNREACHABLE();

+		}

+

+		return sw::Context::CULL_COUNTERCLOCKWISE;

+	}

+

+	unsigned int ConvertColorMask(bool red, bool green, bool blue, bool alpha)

+	{

+		return (red   ? 0x00000001 : 0) |

+			   (green ? 0x00000002 : 0) |

+			   (blue  ? 0x00000004 : 0) |

+			   (alpha ? 0x00000008 : 0);

+	}

+

+	sw::FilterType ConvertMagFilter(GLenum magFilter)

+	{

+		switch(magFilter)

+		{

+		case GL_NEAREST: return sw::FILTER_POINT;

+		case GL_LINEAR:  return sw::FILTER_LINEAR;

+		default: UNREACHABLE();

+		}

+

+		return sw::FILTER_POINT;

+	}

+

+	void ConvertMinFilter(GLenum texFilter, sw::FilterType *minFilter, sw::MipmapType *mipFilter, float maxAnisotropy)

+	{

+		switch(texFilter)

+		{

+		case GL_NEAREST:

+			*minFilter = sw::FILTER_POINT;

+			*mipFilter = sw::MIPMAP_NONE;

+			break;

+		case GL_LINEAR:

+			*minFilter = sw::FILTER_LINEAR;

+			*mipFilter = sw::MIPMAP_NONE;

+			break;

+		case GL_NEAREST_MIPMAP_NEAREST:

+			*minFilter = sw::FILTER_POINT;

+			*mipFilter = sw::MIPMAP_POINT;

+			break;

+		case GL_LINEAR_MIPMAP_NEAREST:

+			*minFilter = sw::FILTER_LINEAR;

+			*mipFilter = sw::MIPMAP_POINT;

+			break;

+		case GL_NEAREST_MIPMAP_LINEAR:

+			*minFilter = sw::FILTER_POINT;

+			*mipFilter = sw::MIPMAP_LINEAR;

+			break;

+		case GL_LINEAR_MIPMAP_LINEAR:

+			*minFilter = sw::FILTER_LINEAR;

+			*mipFilter = sw::MIPMAP_LINEAR;

+			break;

+		default:

+			*minFilter = sw::FILTER_POINT;

+			*mipFilter = sw::MIPMAP_NONE;

+			UNREACHABLE();

+		}

+

+		if(maxAnisotropy > 1.0f)

+		{

+			*minFilter = sw::FILTER_ANISOTROPIC;

+		}

+	}

+

+	bool ConvertPrimitiveType(GLenum primitiveType, GLsizei elementCount,  gl::PrimitiveType &swPrimitiveType, int &primitiveCount)

+	{

+		switch(primitiveType)

+		{

+		case GL_POINTS:

+			swPrimitiveType = gl::DRAW_POINTLIST;

+			primitiveCount = elementCount;

+			break;

+		case GL_LINES:

+			swPrimitiveType = gl::DRAW_LINELIST;

+			primitiveCount = elementCount / 2;

+			break;

+		case GL_LINE_LOOP:

+			swPrimitiveType = gl::DRAW_LINELOOP;

+			primitiveCount = elementCount;

+			break;

+		case GL_LINE_STRIP:

+			swPrimitiveType = gl::DRAW_LINESTRIP;

+			primitiveCount = elementCount - 1;

+			break;

+		case GL_TRIANGLES:

+			swPrimitiveType = gl::DRAW_TRIANGLELIST;

+			primitiveCount = elementCount / 3;

+			break;

+		case GL_TRIANGLE_STRIP:

+			swPrimitiveType = gl::DRAW_TRIANGLESTRIP;

+			primitiveCount = elementCount - 2;

+			break;

+		case GL_TRIANGLE_FAN:

+			swPrimitiveType = gl::DRAW_TRIANGLEFAN;

+			primitiveCount = elementCount - 2;

+			break;

+		default:

+			return false;

+		}

+

+		return true;

+	}

+

+	sw::Format ConvertRenderbufferFormat(GLenum format)

+	{

+		switch(format)

+		{

+		case GL_RGBA4:

+		case GL_RGB5_A1:

+		case GL_RGBA8_OES:            return sw::FORMAT_A8R8G8B8;

+		case GL_RGB565:               return sw::FORMAT_R5G6B5;

+		case GL_RGB8_OES:             return sw::FORMAT_X8R8G8B8;

+		case GL_DEPTH_COMPONENT16:

+		case GL_STENCIL_INDEX8:       

+		case GL_DEPTH24_STENCIL8_OES: return sw::FORMAT_D24S8;

+		default: UNREACHABLE();       return sw::FORMAT_A8R8G8B8;

+		}

+	}

+}

+

+namespace sw2es

+{

+	unsigned int GetStencilSize(sw::Format stencilFormat)

+	{

+		switch(stencilFormat)

+		{

+		case sw::FORMAT_D24FS8:

+		case sw::FORMAT_D24S8:

+		case sw::FORMAT_D32FS8_TEXTURE:

+			return 8;

+	//	case sw::FORMAT_D24X4S4:

+	//		return 4;

+	//	case sw::FORMAT_D15S1:

+	//		return 1;

+	//	case sw::FORMAT_D16_LOCKABLE:

+		case sw::FORMAT_D32:

+		case sw::FORMAT_D24X8:

+		case sw::FORMAT_D32F_LOCKABLE:

+		case sw::FORMAT_D16:

+			return 0;

+	//	case sw::FORMAT_D32_LOCKABLE:  return 0;

+	//	case sw::FORMAT_S8_LOCKABLE:   return 8;

+		default:

+			return 0;

+		}

+	}

+

+	unsigned int GetAlphaSize(sw::Format colorFormat)

+	{

+		switch(colorFormat)

+		{

+		case sw::FORMAT_A16B16G16R16F:

+			return 16;

+		case sw::FORMAT_A32B32G32R32F:

+			return 32;

+		case sw::FORMAT_A2R10G10B10:

+			return 2;

+		case sw::FORMAT_A8R8G8B8:

+			return 8;

+		case sw::FORMAT_A1R5G5B5:

+			return 1;

+		case sw::FORMAT_X8R8G8B8:

+		case sw::FORMAT_R5G6B5:

+			return 0;

+		default:

+			return 0;

+		}

+	}

+

+	unsigned int GetRedSize(sw::Format colorFormat)

+	{

+		switch(colorFormat)

+		{

+		case sw::FORMAT_A16B16G16R16F:

+			return 16;

+		case sw::FORMAT_A32B32G32R32F:

+			return 32;

+		case sw::FORMAT_A2R10G10B10:

+			return 10;

+		case sw::FORMAT_A8R8G8B8:

+		case sw::FORMAT_X8R8G8B8:

+			return 8;

+		case sw::FORMAT_A1R5G5B5:

+		case sw::FORMAT_R5G6B5:

+			return 5;

+		default:

+			return 0;

+		}

+	}

+

+	unsigned int GetGreenSize(sw::Format colorFormat)

+	{

+		switch(colorFormat)

+		{

+		case sw::FORMAT_A16B16G16R16F:

+			return 16;

+		case sw::FORMAT_A32B32G32R32F:

+			return 32;

+		case sw::FORMAT_A2R10G10B10:

+			return 10;

+		case sw::FORMAT_A8R8G8B8:

+		case sw::FORMAT_X8R8G8B8:

+			return 8;

+		case sw::FORMAT_A1R5G5B5:

+			return 5;

+		case sw::FORMAT_R5G6B5:

+			return 6;

+		default:

+			return 0;

+		}

+	}

+

+	unsigned int GetBlueSize(sw::Format colorFormat)

+	{

+		switch(colorFormat)

+		{

+		case sw::FORMAT_A16B16G16R16F:

+			return 16;

+		case sw::FORMAT_A32B32G32R32F:

+			return 32;

+		case sw::FORMAT_A2R10G10B10:

+			return 10;

+		case sw::FORMAT_A8R8G8B8:

+		case sw::FORMAT_X8R8G8B8:

+			return 8;

+		case sw::FORMAT_A1R5G5B5:

+		case sw::FORMAT_R5G6B5:

+			return 5;

+		default:

+			return 0;

+		}

+	}

+

+	unsigned int GetDepthSize(sw::Format depthFormat)

+	{

+		switch(depthFormat)

+		{

+	//	case sw::FORMAT_D16_LOCKABLE:   return 16;

+		case sw::FORMAT_D32:            return 32;

+	//	case sw::FORMAT_D15S1:          return 15;

+		case sw::FORMAT_D24S8:          return 24;

+		case sw::FORMAT_D24X8:          return 24;

+	//	case sw::FORMAT_D24X4S4:        return 24;

+		case sw::FORMAT_D16:            return 16;

+		case sw::FORMAT_D32F_LOCKABLE:  return 32;

+		case sw::FORMAT_D24FS8:         return 24;

+	//	case sw::FORMAT_D32_LOCKABLE:   return 32;

+	//	case sw::FORMAT_S8_LOCKABLE:    return 0;

+		case sw::FORMAT_D32FS8_TEXTURE: return 32;

+		default:                        return 0;

+		}

+	}

+

+	GLenum ConvertBackBufferFormat(sw::Format format)

+	{

+		switch(format)

+		{

+		case sw::FORMAT_A4R4G4B4: return GL_RGBA4;

+		case sw::FORMAT_A8R8G8B8: return GL_RGBA8_OES;

+		case sw::FORMAT_A1R5G5B5: return GL_RGB5_A1;

+		case sw::FORMAT_R5G6B5:   return GL_RGB565;

+		case sw::FORMAT_X8R8G8B8: return GL_RGB8_OES;

+		default:

+			UNREACHABLE();

+		}

+

+		return GL_RGBA4;

+	}

+

+	GLenum ConvertDepthStencilFormat(sw::Format format)

+	{

+		switch(format)

+		{

+		case sw::FORMAT_D16:

+		case sw::FORMAT_D24X8:

+		case sw::FORMAT_D32:

+			return GL_DEPTH_COMPONENT16;

+		case sw::FORMAT_D24S8:

+			return GL_DEPTH24_STENCIL8_OES;

+		default:

+			UNREACHABLE();

+		}

+

+		return GL_DEPTH24_STENCIL8_OES;

+	}

+}

diff --git a/src/GLES2/libGLESv2/utilities.h b/src/GLES2/libGLESv2/utilities.h
new file mode 100644
index 0000000..94d89052
--- /dev/null
+++ b/src/GLES2/libGLESv2/utilities.h
@@ -0,0 +1,86 @@
+// SwiftShader Software Renderer

+//

+// Copyright(c) 2005-2013 TransGaming Inc.

+//

+// All rights reserved. No part of this software may be copied, distributed, transmitted,

+// transcribed, stored in a retrieval system, translated into any human or computer

+// language by any means, or disclosed to third parties without the explicit written

+// agreement of TransGaming Inc. Without such an agreement, no rights or licenses, express

+// or implied, including but not limited to any patent rights, are granted to you.

+//

+

+// utilities.h: Conversion functions and other utility routines.

+

+#ifndef LIBGLESV2_UTILITIES_H

+#define LIBGLESV2_UTILITIES_H

+

+#include "Device.hpp"

+#include "Image.hpp"

+#include "Texture.h"

+

+#define GL_APICALL

+#include <GLES2/gl2.h>

+#include <GLES2/gl2ext.h>

+

+#include <string>

+

+namespace gl

+{

+	struct Color;

+

+	int UniformComponentCount(GLenum type);

+	GLenum UniformComponentType(GLenum type);

+	size_t UniformTypeSize(GLenum type);

+	int VariableRowCount(GLenum type);

+	int VariableColumnCount(GLenum type);

+

+	int AllocateFirstFreeBits(unsigned int *bits, unsigned int allocationSize, unsigned int bitsSize);

+

+	int ComputePixelSize(GLenum format, GLenum type);

+	GLsizei ComputePitch(GLsizei width, GLenum format, GLenum type, GLint alignment);

+	GLsizei ComputeCompressedPitch(GLsizei width, GLenum format);

+	GLsizei ComputeCompressedSize(GLsizei width, GLsizei height, GLenum format);

+	bool IsCompressed(GLenum format);

+	bool IsDepthTexture(GLenum format);

+	bool IsStencilTexture(GLenum format);

+	bool IsCubemapTextureTarget(GLenum target);

+	int CubeFaceIndex(GLenum cubeTarget);

+	bool IsTextureTarget(GLenum target);

+	bool CheckTextureFormatType(GLenum format, GLenum type);

+

+	bool IsColorRenderable(GLenum internalformat);

+	bool IsDepthRenderable(GLenum internalformat);

+	bool IsStencilRenderable(GLenum internalformat);

+}

+

+namespace es2sw

+{

+	sw::Context::DepthCompareMode ConvertDepthComparison(GLenum comparison);

+	sw::Context::StencilCompareMode ConvertStencilComparison(GLenum comparison);

+	sw::Color<float> ConvertColor(gl::Color color);

+	sw::Context::BlendFactor ConvertBlendFunc(GLenum blend);

+	sw::Context::BlendOperation ConvertBlendOp(GLenum blendOp);

+	sw::Context::StencilOperation ConvertStencilOp(GLenum stencilOp);

+	sw::AddressingMode ConvertTextureWrap(GLenum wrap);

+	sw::Context::CullMode ConvertCullMode(GLenum cullFace, GLenum frontFace);

+	unsigned int ConvertColorMask(bool red, bool green, bool blue, bool alpha);

+	sw::FilterType ConvertMagFilter(GLenum magFilter);

+	void ConvertMinFilter(GLenum texFilter, sw::FilterType *minFilter, sw::MipmapType *mipFilter, float maxAnisotropy);

+	bool ConvertPrimitiveType(GLenum primitiveType, GLsizei elementCount,  gl::PrimitiveType &swPrimitiveType, int &primitiveCount);

+	sw::Format ConvertRenderbufferFormat(GLenum format);

+}

+

+namespace sw2es

+{

+	GLuint GetAlphaSize(sw::Format colorFormat);

+	GLuint GetRedSize(sw::Format colorFormat);

+	GLuint GetGreenSize(sw::Format colorFormat);

+	GLuint GetBlueSize(sw::Format colorFormat);

+	GLuint GetDepthSize(sw::Format depthFormat);

+	GLuint GetStencilSize(sw::Format stencilFormat);

+

+	GLenum ConvertBackBufferFormat(sw::Format format);

+	GLenum ConvertDepthStencilFormat(sw::Format format);

+}

+

+#endif  // LIBGLESV2_UTILITIES_H