Initial import from TransGaming

git-svn-id: https://angleproject.googlecode.com/svn/trunk@2 736b8ea6-26fd-11df-bfd4-992fa37f6226
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..37c8466
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,18 @@
+Debug
+Release
+ANGLE.ncb
+ANGLE.suo
+Compiler/Compiler.vcproj.*
+Compiler/Gen_glslang.cpp
+Compiler/Gen_glslang_tab.cpp
+Compiler/glslang.output
+Compiler/glslang_tab.h
+Compiler/Debug
+Compiler/Release
+libEGL/Debug
+libEGL/Release
+libEGL/libEGL.vcproj.*
+libGLESv2/Debug
+libGLESv2/Release
+libGLESv2/libGLESv2.vcproj.*
+
diff --git a/ANGLE.sln b/ANGLE.sln
new file mode 100644
index 0000000..ba98b73
--- /dev/null
+++ b/ANGLE.sln
@@ -0,0 +1,38 @@
+

+Microsoft Visual Studio Solution File, Format Version 10.00

+# Visual C++ Express 2008

+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libEGL", "libEGL\libEGL.vcproj", "{E746FCA9-64C3-433E-85E8-9A5A67AB7ED6}"

+	ProjectSection(ProjectDependencies) = postProject

+		{B5871A7A-968C-42E3-A33B-981E6F448E78} = {B5871A7A-968C-42E3-A33B-981E6F448E78}

+	EndProjectSection

+EndProject

+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libGLESv2", "libGLESv2\libGLESv2.vcproj", "{B5871A7A-968C-42E3-A33B-981E6F448E78}"

+	ProjectSection(ProjectDependencies) = postProject

+		{5B3A6DB8-1E7E-40D7-92B9-DA8AAE619FAD} = {5B3A6DB8-1E7E-40D7-92B9-DA8AAE619FAD}

+	EndProjectSection

+EndProject

+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Compiler", "Compiler\Compiler.vcproj", "{5B3A6DB8-1E7E-40D7-92B9-DA8AAE619FAD}"

+EndProject

+Global

+	GlobalSection(SolutionConfigurationPlatforms) = preSolution

+		Debug|Win32 = Debug|Win32

+		Release|Win32 = Release|Win32

+	EndGlobalSection

+	GlobalSection(ProjectConfigurationPlatforms) = postSolution

+		{E746FCA9-64C3-433E-85E8-9A5A67AB7ED6}.Debug|Win32.ActiveCfg = Debug|Win32

+		{E746FCA9-64C3-433E-85E8-9A5A67AB7ED6}.Debug|Win32.Build.0 = Debug|Win32

+		{E746FCA9-64C3-433E-85E8-9A5A67AB7ED6}.Release|Win32.ActiveCfg = Release|Win32

+		{E746FCA9-64C3-433E-85E8-9A5A67AB7ED6}.Release|Win32.Build.0 = Release|Win32

+		{B5871A7A-968C-42E3-A33B-981E6F448E78}.Debug|Win32.ActiveCfg = Debug|Win32

+		{B5871A7A-968C-42E3-A33B-981E6F448E78}.Debug|Win32.Build.0 = Debug|Win32

+		{B5871A7A-968C-42E3-A33B-981E6F448E78}.Release|Win32.ActiveCfg = Release|Win32

+		{B5871A7A-968C-42E3-A33B-981E6F448E78}.Release|Win32.Build.0 = Release|Win32

+		{5B3A6DB8-1E7E-40D7-92B9-DA8AAE619FAD}.Debug|Win32.ActiveCfg = Debug|Win32

+		{5B3A6DB8-1E7E-40D7-92B9-DA8AAE619FAD}.Debug|Win32.Build.0 = Debug|Win32

+		{5B3A6DB8-1E7E-40D7-92B9-DA8AAE619FAD}.Release|Win32.ActiveCfg = Release|Win32

+		{5B3A6DB8-1E7E-40D7-92B9-DA8AAE619FAD}.Release|Win32.Build.0 = Release|Win32

+	EndGlobalSection

+	GlobalSection(SolutionProperties) = preSolution

+		HideSolutionNode = FALSE

+	EndGlobalSection

+EndGlobal

diff --git a/AUTHORS b/AUTHORS
new file mode 100644
index 0000000..5bde284
--- /dev/null
+++ b/AUTHORS
@@ -0,0 +1,15 @@
+# This is the official list of The ANGLE Project Authors
+# for copyright purposes.
+# This file is distinct from the CONTRIBUTORS files.
+# See the latter for an explanation.
+
+# Names should be added to this file as
+#	Name or Organization <email address>
+# The email address is not required for organizations.
+
+TransGaming Inc.
+
+Google Inc.
+
+3DLabs Inc. Ltd.
+
diff --git a/CONTRIBUTORS b/CONTRIBUTORS
new file mode 100644
index 0000000..b5d7975
--- /dev/null
+++ b/CONTRIBUTORS
@@ -0,0 +1,18 @@
+# This is the official list of people who can contribute
+# (and who have contributed) code to the ANGLE project
+# repository.
+# The AUTHORS file lists the copyright holders; this file
+# lists people.  For example, Google employees are listed here
+# but not in AUTHORS, because Google holds the copyright.
+#
+
+TransGaming Inc.
+ Nicolas Capens
+ Daniel Koch
+ Andrew Lewycky
+ Gavriel State
+ Shannon Woods
+
+Google Inc.
+ Henry Bridge
+ Vangelis Kokkevis
diff --git a/Common/debug.cpp b/Common/debug.cpp
new file mode 100644
index 0000000..14c0d09
--- /dev/null
+++ b/Common/debug.cpp
@@ -0,0 +1,36 @@
+//
+// 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 "debug.h"
+
+#include <stdio.h>
+#include <stdarg.h>
+
+namespace gl
+{
+void trace(const char *format, ...)
+{
+    if (true)
+    {
+        if (format)
+        {
+            FILE *file = fopen("debug.txt", "a");
+
+            if (file)
+            {
+                va_list vararg;
+                va_start(vararg, format);
+                vfprintf(file, format, vararg);
+                va_end(vararg);
+
+                fclose(file);
+            }
+        }
+    }
+}
+}
diff --git a/Compiler/BaseTypes.h b/Compiler/BaseTypes.h
new file mode 100644
index 0000000..2265b96
--- /dev/null
+++ b/Compiler/BaseTypes.h
@@ -0,0 +1,130 @@
+//
+// 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
+{
+	EbpHigh,
+	EbpMedium,
+	EbpLow,
+};
+
+__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 "unknown precision";
+	}
+}
+
+//
+// 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??
+};
+
+__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/Compiler/CodeGen.cpp b/Compiler/CodeGen.cpp
new file mode 100644
index 0000000..fa54c7e
--- /dev/null
+++ b/Compiler/CodeGen.cpp
@@ -0,0 +1,47 @@
+//
+// 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 "Common.h"
+#include "ShHandle.h"
+
+//
+// Here is where real machine specific high-level data would be defined.
+//
+class TGenericCompiler : public TCompiler {
+public:
+    TGenericCompiler(EShLanguage l, int dOptions) : TCompiler(l, infoSink), debugOptions(dOptions) { }
+    virtual bool compile(TIntermNode* root);
+    TInfoSink infoSink;
+    int debugOptions;
+};
+
+//
+// This function must be provided to create the actual
+// compile object used by higher level code.  It returns
+// a subclass of TCompiler.
+//
+TCompiler* ConstructCompiler(EShLanguage language, int debugOptions)
+{
+    return new TGenericCompiler(language, debugOptions);
+}
+
+//
+// Delete the compiler made by ConstructCompiler
+//
+void DeleteCompiler(TCompiler* compiler)
+{
+    delete compiler;
+}
+
+//
+//  Generate code from the given parse tree
+//
+bool TGenericCompiler::compile(TIntermNode *root)
+{
+    haveValidObjectCode = true;
+
+    return haveValidObjectCode;
+}
diff --git a/Compiler/Common.h b/Compiler/Common.h
new file mode 100644
index 0000000..1ab2e91
--- /dev/null
+++ b/Compiler/Common.h
@@ -0,0 +1,164 @@
+//
+// 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_
+
+#ifdef _WIN32
+    #include <basetsd.h>
+#elif defined (solaris)
+    #include <sys/int_types.h>
+    #define UINT_PTR uintptr_t
+#else
+    #include <stdint.h>
+    #define UINT_PTR uintptr_t
+#endif
+
+/* windows only pragma */
+#ifdef _MSC_VER
+    #pragma warning(disable : 4786) // Don't warn about too long identifiers
+    #pragma warning(disable : 4514) // unused inline method
+    #pragma warning(disable : 4201) // nameless union
+#endif
+
+//
+// Doing the push and pop below for warnings does not leave the warning state
+// the way it was.  This seems like a defect in the compiler.  We would like
+// to do this, but since it does not work correctly right now, it is turned
+// off.
+//
+//??#pragma warning(push, 3)
+
+	#include <set>
+    #include <vector>
+    #include <map>
+    #include <list>
+    #include <string>
+    #include <stdio.h>
+
+//??#pragma warning(pop)
+
+typedef int TSourceLoc;
+
+	#include <assert.h>
+
+#include "PoolAlloc.h"
+
+//
+// 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 *) { }
+
+#define TBaseMap std::map
+#define TBaseList std::list
+#define TBaseSet std::set
+
+//
+// Pool version of string.
+//
+typedef pool_allocator<char> TStringAllocator;
+typedef std::basic_string <char, std::char_traits<char>, TStringAllocator > TString;
+inline TString* NewPoolTString(const char* s)
+{
+	void* memory = GlobalPoolAllocator.allocate(sizeof(TString));
+	return new(memory) TString(s);
+}
+
+//
+// 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 T> class TList   : public TBaseList  <T, pool_allocator<T> > {
+public:
+    typedef typename TBaseList<T, pool_allocator<T> >::size_type size_type;
+    TList() : TBaseList<T, pool_allocator<T> >() {}
+    TList(const pool_allocator<T>& a) : TBaseList<T, pool_allocator<T> >(a) {}
+    TList(size_type i): TBaseList<T, pool_allocator<T> >(i) {}
+};
+
+// This is called TStlSet, because TSet is taken by an existing compiler class.
+template <class T, class CMP> class TStlSet : public std::set<T, CMP, pool_allocator<T> > {
+    // No pool allocator versions of constructors in std::set.
+};
+
+
+template <class K, class D, class CMP = std::less<K> > 
+class TMap : public TBaseMap<K, D, CMP, pool_allocator<std::pair<K, D> > > {
+public:
+    typedef pool_allocator<std::pair <K, D> > tAllocator;
+
+    TMap() : TBaseMap<K, D, CMP, tAllocator >() {}
+    // use correct two-stage name lookup supported in gcc 3.4 and above
+    TMap(const tAllocator& a) : TBaseMap<K, D, CMP, tAllocator>(TBaseMap<K, D, CMP, tAllocator >::key_compare(), a) {}
+};
+
+//
+// Persistent string memory.  Should only be used for strings that survive
+// across compiles/links.
+//
+typedef std::basic_string<char> TPersistString;
+
+//
+// templatized min and max functions.
+//
+template <class T> T Min(const T a, const T b) { return a < b ? a : b; }
+template <class T> T Max(const T a, const T b) { return a > b ? a : b; }
+
+//
+// Create a TString object from an integer.
+//
+inline const TString String(const int i, const int base = 10)
+{
+    char text[16];     // 32 bit ints are at most 10 digits in base 10
+    
+    #ifdef _WIN32
+        _itoa(i, text, base);
+    #else
+        // we assume base 10 for all cases
+        sprintf(text, "%d", i);
+    #endif
+
+    return text;
+}
+
+const unsigned int SourceLocLineMask = 0xffff;
+const unsigned int SourceLocStringShift = 16;
+
+__inline TPersistString FormatSourceLoc(const TSourceLoc loc)
+{
+    char locText[64];
+
+    int string = loc >> SourceLocStringShift;
+    int line = loc & SourceLocLineMask;
+
+    if (line)
+        sprintf(locText, "%d:%d", string, line);
+    else
+        sprintf(locText, "%d:? ", string);
+
+    return TPersistString(locText);
+}
+
+
+typedef TMap<TString, TString> TPragmaTable;
+typedef TMap<TString, TString>::tAllocator TPragmaTableAllocator;
+
+#endif // _COMMON_INCLUDED_
diff --git a/Compiler/Compiler.vcproj b/Compiler/Compiler.vcproj
new file mode 100644
index 0000000..7c380e9
--- /dev/null
+++ b/Compiler/Compiler.vcproj
@@ -0,0 +1,474 @@
+<?xml version="1.0" encoding="Windows-1252"?>

+<VisualStudioProject

+	ProjectType="Visual C++"

+	Version="9.00"

+	Name="Compiler"

+	ProjectGUID="{5B3A6DB8-1E7E-40D7-92B9-DA8AAE619FAD}"

+	RootNamespace="Compiler"

+	Keyword="Win32Proj"

+	TargetFrameworkVersion="131072"

+	>

+	<Platforms>

+		<Platform

+			Name="Win32"

+		/>

+	</Platforms>

+	<ToolFiles>

+	</ToolFiles>

+	<Configurations>

+		<Configuration

+			Name="Debug|Win32"

+			OutputDirectory="$(SolutionDir)$(ConfigurationName)"

+			IntermediateDirectory="$(ConfigurationName)"

+			ConfigurationType="4"

+			CharacterSet="0"

+			>

+			<Tool

+				Name="VCPreBuildEventTool"

+			/>

+			<Tool

+				Name="VCCustomBuildTool"

+			/>

+			<Tool

+				Name="VCXMLDataGeneratorTool"

+			/>

+			<Tool

+				Name="VCWebServiceProxyGeneratorTool"

+			/>

+			<Tool

+				Name="VCMIDLTool"

+			/>

+			<Tool

+				Name="VCCLCompilerTool"

+				Optimization="0"

+				AdditionalIncludeDirectories="./; ../Include/"

+				PreprocessorDefinitions="WIN32;_DEBUG;_LIB;_CRT_SECURE_NO_DEPRECATE"

+				MinimalRebuild="true"

+				BasicRuntimeChecks="3"

+				RuntimeLibrary="1"

+				UsePrecompiledHeader="0"

+				WarningLevel="3"

+				Detect64BitPortabilityProblems="false"

+				DebugInformationFormat="4"

+			/>

+			<Tool

+				Name="VCManagedResourceCompilerTool"

+			/>

+			<Tool

+				Name="VCResourceCompilerTool"

+			/>

+			<Tool

+				Name="VCPreLinkEventTool"

+			/>

+			<Tool

+				Name="VCLibrarianTool"

+			/>

+			<Tool

+				Name="VCALinkTool"

+			/>

+			<Tool

+				Name="VCXDCMakeTool"

+			/>

+			<Tool

+				Name="VCBscMakeTool"

+			/>

+			<Tool

+				Name="VCFxCopTool"

+			/>

+			<Tool

+				Name="VCPostBuildEventTool"

+			/>

+		</Configuration>

+		<Configuration

+			Name="Release|Win32"

+			OutputDirectory="$(SolutionDir)$(ConfigurationName)"

+			IntermediateDirectory="$(ConfigurationName)"

+			ConfigurationType="4"

+			CharacterSet="0"

+			WholeProgramOptimization="1"

+			>

+			<Tool

+				Name="VCPreBuildEventTool"

+			/>

+			<Tool

+				Name="VCCustomBuildTool"

+			/>

+			<Tool

+				Name="VCXMLDataGeneratorTool"

+			/>

+			<Tool

+				Name="VCWebServiceProxyGeneratorTool"

+			/>

+			<Tool

+				Name="VCMIDLTool"

+			/>

+			<Tool

+				Name="VCCLCompilerTool"

+				AdditionalIncludeDirectories="./; ../Include/"

+				PreprocessorDefinitions="WIN32;NDEBUG;_LIB;_CRT_SECURE_NO_DEPRECATE"

+				RuntimeLibrary="0"

+				UsePrecompiledHeader="0"

+				WarningLevel="3"

+				Detect64BitPortabilityProblems="false"

+				DebugInformationFormat="3"

+			/>

+			<Tool

+				Name="VCManagedResourceCompilerTool"

+			/>

+			<Tool

+				Name="VCResourceCompilerTool"

+			/>

+			<Tool

+				Name="VCPreLinkEventTool"

+			/>

+			<Tool

+				Name="VCLibrarianTool"

+			/>

+			<Tool

+				Name="VCALinkTool"

+			/>

+			<Tool

+				Name="VCXDCMakeTool"

+			/>

+			<Tool

+				Name="VCBscMakeTool"

+			/>

+			<Tool

+				Name="VCFxCopTool"

+			/>

+			<Tool

+				Name="VCPostBuildEventTool"

+			/>

+		</Configuration>

+	</Configurations>

+	<References>

+	</References>

+	<Files>

+		<Filter

+			Name="Source Files"

+			Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"

+			UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"

+			>

+			<File

+				RelativePath=".\CodeGen.cpp"

+				>

+			</File>

+			<File

+				RelativePath=".\glslang.l"

+				>

+				<FileConfiguration

+					Name="Debug|Win32"

+					>

+					<Tool

+						Name="VCCustomBuildTool"

+						Description="Executing flex on $(InputPath)"

+						CommandLine="if EXIST $(InputDir)Gen_glslang.cpp del $(InputDir)Gen_glslang.cpp&#x0D;&#x0A;$(InputDir)Tools\flex.exe $(InputPath)&#x0D;&#x0A;"

+						AdditionalDependencies="glslang_tab.h"

+						Outputs="$(InputDir)Gen_glslang.cpp"

+					/>

+				</FileConfiguration>

+				<FileConfiguration

+					Name="Release|Win32"

+					>

+					<Tool

+						Name="VCCustomBuildTool"

+						Description="Executing flex on $(InputPath)"

+						CommandLine="if EXIST $(InputDir)Gen_glslang.cpp del $(InputDir)Gen_glslang.cpp&#x0D;&#x0A;$(InputDir)Tools\flex.exe $(InputPath)&#x0D;&#x0A;"

+						AdditionalDependencies="glslang_tab.h"

+						Outputs="$(InputDir)Gen_glslang.cpp"

+					/>

+				</FileConfiguration>

+			</File>

+			<File

+				RelativePath=".\glslang.y"

+				>

+				<FileConfiguration

+					Name="Debug|Win32"

+					>

+					<Tool

+						Name="VCCustomBuildTool"

+						Description="Executing Bison on $(InputPath)"

+						CommandLine="SET BISON_SIMPLE=$(InputDir)Tools\bison.simple&#x0D;&#x0A;SET BISON_HAIRY=$(InputDir)Tools\bison.simple&#x0D;&#x0A;if EXIST $(InputDir)Gen_$(InputName)_tab.cpp del $(InputDir)Gen_$(InputName)_tab.cpp&#x0D;&#x0A;$(InputDir)Tools\bison.exe -d -t -v $(InputName).y&#x0D;&#x0A;rename $(InputDir)$(InputName)_tab.c Gen_$(InputName)_tab.cpp&#x0D;&#x0A;"

+						Outputs="$(InputDir)Gen_$(InputName)_tab.cpp"

+					/>

+				</FileConfiguration>

+				<FileConfiguration

+					Name="Release|Win32"

+					>

+					<Tool

+						Name="VCCustomBuildTool"

+						Description="Executing Bison on $(InputPath)"

+						CommandLine="SET BISON_SIMPLE=$(InputDir)Tools\bison.simple&#x0D;&#x0A;SET BISON_HAIRY=$(InputDir)Tools\bison.simple&#x0D;&#x0A;if EXIST $(InputDir)Gen_$(InputName)_tab.cpp del $(InputDir)Gen_$(InputName)_tab.cpp&#x0D;&#x0A;$(InputDir)Tools\bison.exe -d -t -v $(InputName).y&#x0D;&#x0A;rename $(InputDir)$(InputName)_tab.c Gen_$(InputName)_tab.cpp&#x0D;&#x0A;"

+						Outputs="$(InputDir)Gen_$(InputName)_tab.cpp"

+					/>

+				</FileConfiguration>

+			</File>

+			<File

+				RelativePath=".\InfoSink.cpp"

+				>

+			</File>

+			<File

+				RelativePath=".\Initialize.cpp"

+				>

+			</File>

+			<File

+				RelativePath=".\InitializeDll.cpp"

+				>

+			</File>

+			<File

+				RelativePath=".\Intermediate.cpp"

+				>

+			</File>

+			<File

+				RelativePath=".\intermOut.cpp"

+				>

+			</File>

+			<File

+				RelativePath=".\IntermTraverse.cpp"

+				>

+			</File>

+			<File

+				RelativePath=".\Link.cpp"

+				>

+			</File>

+			<File

+				RelativePath=".\ossource.cpp"

+				>

+			</File>

+			<File

+				RelativePath=".\OutputHLSL.cpp"

+				>

+			</File>

+			<File

+				RelativePath=".\parseConst.cpp"

+				>

+			</File>

+			<File

+				RelativePath=".\ParseHelper.cpp"

+				>

+			</File>

+			<File

+				RelativePath=".\PoolAlloc.cpp"

+				>

+			</File>

+			<File

+				RelativePath=".\QualifierAlive.cpp"

+				>

+			</File>

+			<File

+				RelativePath=".\RemoveTree.cpp"

+				>

+			</File>

+			<File

+				RelativePath=".\ShaderLang.cpp"

+				>

+			</File>

+			<File

+				RelativePath=".\SymbolTable.cpp"

+				>

+			</File>

+			<Filter

+				Name="Preprocessor"

+				>

+				<File

+					RelativePath=".\Preprocessor\atom.c"

+					>

+				</File>

+				<File

+					RelativePath=".\Preprocessor\cpp.c"

+					>

+				</File>

+				<File

+					RelativePath=".\Preprocessor\cppstruct.c"

+					>

+				</File>

+				<File

+					RelativePath=".\Preprocessor\memory.c"

+					>

+				</File>

+				<File

+					RelativePath=".\Preprocessor\scanner.c"

+					>

+				</File>

+				<File

+					RelativePath=".\Preprocessor\symbols.c"

+					>

+				</File>

+				<File

+					RelativePath=".\Preprocessor\tokens.c"

+					>

+				</File>

+			</Filter>

+			<Filter

+				Name="Generated"

+				>

+				<File

+					RelativePath=".\Gen_glslang.cpp"

+					>

+				</File>

+				<File

+					RelativePath=".\Gen_glslang_tab.cpp"

+					>

+				</File>

+			</Filter>

+		</Filter>

+		<Filter

+			Name="Header Files"

+			Filter="h;hpp;hxx;hm;inl;inc;xsd"

+			UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"

+			>

+			<File

+				RelativePath=".\BaseTypes.h"

+				>

+			</File>

+			<File

+				RelativePath=".\Common.h"

+				>

+			</File>

+			<File

+				RelativePath=".\ConstantUnion.h"

+				>

+			</File>

+			<File

+				RelativePath=".\InfoSink.h"

+				>

+			</File>

+			<File

+				RelativePath=".\Initialize.h"

+				>

+			</File>

+			<File

+				RelativePath=".\InitializeDll.h"

+				>

+			</File>

+			<File

+				RelativePath=".\InitializeGlobals.h"

+				>

+			</File>

+			<File

+				RelativePath=".\InitializeParseContext.h"

+				>

+			</File>

+			<File

+				RelativePath=".\intermediate.h"

+				>

+			</File>

+			<File

+				RelativePath=".\localintermediate.h"

+				>

+			</File>

+			<File

+				RelativePath=".\MMap.h"

+				>

+			</File>

+			<File

+				RelativePath=".\osinclude.h"

+				>

+			</File>

+			<File

+				RelativePath=".\OutputHLSL.h"

+				>

+			</File>

+			<File

+				RelativePath=".\ParseHelper.h"

+				>

+			</File>

+			<File

+				RelativePath=".\PoolAlloc.h"

+				>

+			</File>

+			<File

+				RelativePath=".\QualifierAlive.h"

+				>

+			</File>

+			<File

+				RelativePath=".\RemoveTree.h"

+				>

+			</File>

+			<File

+				RelativePath=".\ResourceLimits.h"

+				>

+			</File>

+			<File

+				RelativePath=".\ShaderLang.h"

+				>

+			</File>

+			<File

+				RelativePath=".\ShHandle.h"

+				>

+			</File>

+			<File

+				RelativePath=".\SymbolTable.h"

+				>

+			</File>

+			<File

+				RelativePath=".\Types.h"

+				>

+			</File>

+			<File

+				RelativePath=".\unistd.h"

+				>

+			</File>

+			<Filter

+				Name="Preprocessor"

+				>

+				<File

+					RelativePath=".\Preprocessor\atom.h"

+					>

+				</File>

+				<File

+					RelativePath=".\Preprocessor\compile.h"

+					>

+				</File>

+				<File

+					RelativePath=".\Preprocessor\cpp.h"

+					>

+				</File>

+				<File

+					RelativePath=".\Preprocessor\memory.h"

+					>

+				</File>

+				<File

+					RelativePath=".\Preprocessor\parser.h"

+					>

+				</File>

+				<File

+					RelativePath=".\Preprocessor\preprocess.h"

+					>

+				</File>

+				<File

+					RelativePath=".\Preprocessor\scanner.h"

+					>

+				</File>

+				<File

+					RelativePath=".\Preprocessor\slglobals.h"

+					>

+				</File>

+				<File

+					RelativePath=".\Preprocessor\symbols.h"

+					>

+				</File>

+				<File

+					RelativePath=".\Preprocessor\tokens.h"

+					>

+				</File>

+			</Filter>

+			<Filter

+				Name="Generated"

+				>

+				<File

+					RelativePath=".\glslang_tab.h"

+					>

+				</File>

+			</Filter>

+		</Filter>

+		<Filter

+			Name="Resource Files"

+			Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav"

+			UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"

+			>

+		</Filter>

+	</Files>

+	<Globals>

+	</Globals>

+</VisualStudioProject>

diff --git a/Compiler/ConstantUnion.h b/Compiler/ConstantUnion.h
new file mode 100644
index 0000000..b0ab971
--- /dev/null
+++ b/Compiler/ConstantUnion.h
@@ -0,0 +1,287 @@
+//
+// 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 _CONSTANT_UNION_INCLUDED_
+#define _CONSTANT_UNION_INCLUDED_
+
+
+class constUnion {
+public:
+
+    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; }
+
+    bool operator==(const int i) const
+    {
+        if (i == iConst)
+            return true;
+
+        return false;
+    }
+
+    bool operator==(const float f) const
+    {
+        if (f == fConst)
+            return true;
+
+        return false;
+    }
+
+    bool operator==(const bool b) const
+    {
+        if (b == bConst)
+            return true;
+
+        return false;
+    }
+
+    bool operator==(const constUnion& constant) const
+    {
+        if (constant.type != type)
+            return false;
+
+        switch (type) {
+        case EbtInt:
+            if (constant.iConst == iConst)
+                return true;
+
+            break;
+        case EbtFloat:
+            if (constant.fConst == fConst)
+                return true;
+
+            break;
+        case EbtBool:
+            if (constant.bConst == bConst)
+                return true;
+
+            break;
+        }
+
+        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 constUnion& constant) const
+    {
+        return !operator==(constant);
+    }
+
+    bool operator>(const constUnion& constant) const
+    { 
+        assert(type == constant.type);
+        switch (type) {
+        case EbtInt:
+            if (iConst > constant.iConst)
+                return true;
+
+            return false;
+        case EbtFloat:
+            if (fConst > constant.fConst)
+                return true;
+
+            return false;
+        default:
+            assert(false && "Default missing");
+            return false;
+        }
+
+        return false;
+    }
+
+    bool operator<(const constUnion& constant) const
+    { 
+        assert(type == constant.type);
+        switch (type) {
+        case EbtInt:
+            if (iConst < constant.iConst)
+                return true;
+
+            return false;
+        case EbtFloat:
+            if (fConst < constant.fConst)
+                return true;
+
+            return false;
+        default:
+            assert(false && "Default missing");
+            return false;
+        }
+
+        return false;
+    }
+
+    constUnion operator+(const constUnion& constant) const
+    { 
+        constUnion 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;
+    }
+
+    constUnion operator-(const constUnion& constant) const
+    { 
+        constUnion 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;
+    }
+
+    constUnion operator*(const constUnion& constant) const
+    { 
+        constUnion 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;
+    }
+
+    constUnion operator%(const constUnion& constant) const
+    { 
+        constUnion returnValue;
+        assert(type == constant.type);
+        switch (type) {
+        case EbtInt: returnValue.setIConst(iConst % constant.iConst); break;
+        default:     assert(false && "Default missing");
+        }
+
+        return returnValue;
+    }
+
+    constUnion operator>>(const constUnion& constant) const
+    { 
+        constUnion returnValue;
+        assert(type == constant.type);
+        switch (type) {
+        case EbtInt: returnValue.setIConst(iConst >> constant.iConst); break;
+        default:     assert(false && "Default missing");
+        }
+
+        return returnValue;
+    }
+
+    constUnion operator<<(const constUnion& constant) const
+    { 
+        constUnion returnValue;
+        assert(type == constant.type);
+        switch (type) {
+        case EbtInt: returnValue.setIConst(iConst << constant.iConst); break;
+        default:     assert(false && "Default missing");
+        }
+
+        return returnValue;
+    }
+
+    constUnion operator&(const constUnion& constant) const
+    { 
+        constUnion returnValue;
+        assert(type == constant.type);
+        switch (type) {
+        case EbtInt:  returnValue.setIConst(iConst & constant.iConst); break;
+        default:     assert(false && "Default missing");
+        }
+
+        return returnValue;
+    }
+
+    constUnion operator|(const constUnion& constant) const
+    { 
+        constUnion returnValue;
+        assert(type == constant.type);
+        switch (type) {
+        case EbtInt:  returnValue.setIConst(iConst | constant.iConst); break;
+        default:     assert(false && "Default missing");
+        }
+
+        return returnValue;
+    }
+
+    constUnion operator^(const constUnion& constant) const
+    { 
+        constUnion returnValue;
+        assert(type == constant.type);
+        switch (type) {
+        case EbtInt:  returnValue.setIConst(iConst ^ constant.iConst); break;
+        default:     assert(false && "Default missing");
+        }
+
+        return returnValue;
+    }
+
+    constUnion operator&&(const constUnion& constant) const
+    { 
+        constUnion returnValue;
+        assert(type == constant.type);
+        switch (type) {
+        case EbtBool: returnValue.setBConst(bConst && constant.bConst); break;
+        default:     assert(false && "Default missing");
+        }
+
+        return returnValue;
+    }
+
+    constUnion operator||(const constUnion& constant) const
+    { 
+        constUnion returnValue;
+        assert(type == constant.type);
+        switch (type) {
+        case EbtBool: returnValue.setBConst(bConst || constant.bConst); break;
+        default:     assert(false && "Default missing");
+        }
+
+        return returnValue;
+    }
+
+    TBasicType getType() { 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/Compiler/InfoSink.cpp b/Compiler/InfoSink.cpp
new file mode 100644
index 0000000..9f2a188
--- /dev/null
+++ b/Compiler/InfoSink.cpp
@@ -0,0 +1,79 @@
+//
+// 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 "InfoSink.h"
+
+#ifdef _WIN32
+    #include <windows.h>
+#endif
+
+void TInfoSinkBase::append(const char *s)           
+{
+    if (outputStream & EString) {
+        checkMem(strlen(s)); 
+        sink.append(s); 
+    }
+
+#ifdef _WIN32
+    if (outputStream & EDebugger)
+        OutputDebugString(s);
+#endif
+
+    if (outputStream & EStdOut)
+        fprintf(stdout, "%s", s);
+}
+
+void TInfoSinkBase::append(int count, char c)       
+{ 
+    if (outputStream & EString) {
+        checkMem(count);         
+        sink.append(count, c); 
+    }
+
+#ifdef _WIN32
+    if (outputStream & EDebugger) {
+        char str[2];
+        str[0] = c;
+        str[1] = '\0';
+        OutputDebugString(str);
+    }
+#endif
+
+    if (outputStream & EStdOut)
+        fprintf(stdout, "%c", c);
+}
+
+void TInfoSinkBase::append(const TPersistString& t) 
+{ 
+    if (outputStream & EString) {
+        checkMem(t.size());  
+        sink.append(t); 
+    }
+
+#ifdef _WIN32
+    if (outputStream & EDebugger)
+        OutputDebugString(t.c_str());
+#endif
+
+    if (outputStream & EStdOut)
+        fprintf(stdout, "%s", t.c_str());
+}
+
+void TInfoSinkBase::append(const TString& t)
+{ 
+    if (outputStream & EString) {
+        checkMem(t.size());  
+        sink.append(t.c_str()); 
+    }
+
+#ifdef _WIN32
+    if (outputStream & EDebugger)
+        OutputDebugString(t.c_str());
+#endif
+
+    if (outputStream & EStdOut)
+        fprintf(stdout, "%s", t.c_str());
+}
diff --git a/Compiler/InfoSink.h b/Compiler/InfoSink.h
new file mode 100644
index 0000000..525a378
--- /dev/null
+++ b/Compiler/InfoSink.h
@@ -0,0 +1,109 @@
+//
+// 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 "Common.h"
+#include <math.h>
+
+//
+// TPrefixType is used to centralize how info log messages start.
+// See below.
+//
+enum TPrefixType {
+    EPrefixNone,
+    EPrefixWarning,
+    EPrefixError,
+    EPrefixInternalError,
+    EPrefixUnimplemented,
+    EPrefixNote
+};
+
+enum TOutputStream {
+    ENull = 0,
+    EDebugger = 0x01,
+    EStdOut = 0x02,
+    EString = 0x04,
+};
+//
+// 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() : outputStream(4) {}
+    void erase() { sink.erase(); }
+    TInfoSinkBase& operator<<(const TPersistString& t) { append(t); return *this; }
+    TInfoSinkBase& operator<<(char c)                  { append(1, c); return *this; }
+    TInfoSinkBase& operator<<(const char* s)           { append(s); return *this; }
+    TInfoSinkBase& operator<<(int n)                   { append(String(n)); return *this; }
+    TInfoSinkBase& operator<<(const unsigned int n)    { append(String(n)); return *this; }
+    TInfoSinkBase& operator<<(float n)                 { char buf[40]; 
+                                                     sprintf(buf, "%.8g", n);
+                                                     append(buf); 
+                                                     return *this; }
+    TInfoSinkBase& operator+(const TPersistString& t)  { append(t); return *this; }
+    TInfoSinkBase& operator+(const TString& t)         { append(t); return *this; }
+    TInfoSinkBase& operator<<(const TString& t)        { append(t); return *this; }
+    TInfoSinkBase& operator+(const char* s)            { append(s); return *this; }
+    const char* c_str() const { return sink.c_str(); }
+    void prefix(TPrefixType message) {
+        switch(message) {
+        case EPrefixNone:                                      break;
+        case EPrefixWarning:       append("WARNING: ");        break;
+        case EPrefixError:         append("ERROR: ");          break;
+        case EPrefixInternalError: append("INTERNAL ERROR: "); break;
+        case EPrefixUnimplemented: append("UNIMPLEMENTED: ");  break;
+        case EPrefixNote:          append("NOTE: ");           break;
+        default:                   append("UNKOWN ERROR: ");   break;
+        }
+    }
+    void location(TSourceLoc loc) {
+        append(FormatSourceLoc(loc).c_str());
+        append(": ");
+    }
+    void message(TPrefixType message, const char* s) {
+        prefix(message);
+        append(s);
+        append("\n");
+    }
+    void message(TPrefixType message, const char* s, TSourceLoc loc) {
+        prefix(message);
+        location(loc);
+        append(s);
+        append("\n");
+    }
+    
+    void setOutputStream(int output = 4)
+    {
+        outputStream = output;
+    }
+
+protected:
+    void append(const char *s); 
+
+    void append(int count, char c);
+    void append(const TPersistString& t);
+    void append(const TString& t);
+
+    void checkMem(size_t growth) { if (sink.capacity() < sink.size() + growth + 2)  
+                                       sink.reserve(sink.capacity() +  sink.capacity() / 2); }
+    void appendToStream(const char* s);
+    TPersistString sink;
+    int outputStream;
+};
+
+class TInfoSink {
+public:
+    TInfoSinkBase info;
+    TInfoSinkBase debug;
+    TInfoSinkBase obj;
+};
+
+#endif // _INFOSINK_INCLUDED_
diff --git a/Compiler/Initialize.cpp b/Compiler/Initialize.cpp
new file mode 100644
index 0000000..2b7ecff
--- /dev/null
+++ b/Compiler/Initialize.cpp
@@ -0,0 +1,616 @@
+//
+// 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 "intermediate.h"
+#include "Initialize.h"
+
+void TBuiltIns::initialize()
+{
+	//
+	// Initialize all the built-in strings for parsing.
+	//
+	TString BuiltInFunctions;
+	TString BuiltInFunctionsVertex;
+	TString BuiltInFunctionsFragment;
+	TString StandardUniforms;
+
+	{
+		//============================================================================
+		//
+		// Prototypes for built-in functions seen by both vertex and fragment shaders.
+		//
+		//============================================================================
+
+		TString& s = BuiltInFunctions;
+
+		//
+		// 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);"));
+
+		s.append(TString("\n"));
+	}
+	{
+		//============================================================================
+		//
+		// Prototypes for built-in functions seen by vertex shaders only.
+		//
+		//============================================================================
+
+		TString& s = BuiltInFunctionsVertex;
+
+		//
+		// 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);"));
+
+		s.append(TString("\n"));
+	}
+	{
+		//============================================================================
+		//
+		// Prototypes for built-in functions seen by fragment shaders only.
+		//
+		//============================================================================
+
+		TString& s = BuiltInFunctionsFragment;
+
+		//
+		// 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);"));
+
+	//	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);"));
+
+		s.append(TString("\n"));
+	}
+	{
+		//============================================================================
+		//
+		// Standard Uniforms
+		//
+		//============================================================================
+
+		TString& s = StandardUniforms;
+
+		//
+		// Depth range in window coordinates
+		//
+		s.append(TString("struct gl_DepthRangeParameters {"));
+		s.append(TString("    float near;"));        // n       // FIXME: highp
+		s.append(TString("    float far;"));         // f       // FIXME: highp
+		s.append(TString("    float diff;"));        // f - n   // FIXME: highp
+		s.append(TString("};"));
+		s.append(TString("uniform gl_DepthRangeParameters gl_DepthRange;"));
+
+		s.append(TString("\n"));
+	}
+
+	builtInStrings[EShLangFragment].push_back(BuiltInFunctions.c_str());
+	builtInStrings[EShLangFragment].push_back(BuiltInFunctionsFragment);
+	builtInStrings[EShLangFragment].push_back(StandardUniforms);
+
+	builtInStrings[EShLangVertex].push_back(BuiltInFunctions);
+	builtInStrings[EShLangVertex].push_back(BuiltInFunctionsVertex);
+	builtInStrings[EShLangVertex].push_back(StandardUniforms);
+}
+
+void TBuiltIns::initialize(const TBuiltInResource &resources)
+{
+	TString builtIns;
+
+	// Implementation dependent constants
+	char builtInConstant[80];
+
+	sprintf(builtInConstant, "const int  gl_MaxVertexAttribs = %d;", resources.maxVertexAttribs);
+	builtIns.append(TString(builtInConstant));
+
+	sprintf(builtInConstant, "const int  gl_MaxVertexUniformVectors = %d;", resources.maxVertexUniformVectors);
+	builtIns.append(TString(builtInConstant));       
+
+	sprintf(builtInConstant, "const int  gl_MaxVaryingVectors = %d;", resources.maxVaryingVectors);
+	builtIns.append(TString(builtInConstant));        
+
+	sprintf(builtInConstant, "const int  gl_MaxVertexTextureImageUnits = %d;", resources.maxVertexTextureImageUnits);
+	builtIns.append(TString(builtInConstant));        
+
+	sprintf(builtInConstant, "const int  gl_MaxCombinedTextureImageUnits = %d;", resources.maxCombinedTextureImageUnits);
+	builtIns.append(TString(builtInConstant));        
+
+	sprintf(builtInConstant, "const int  gl_MaxTextureImageUnits = %d;", resources.maxTextureImageUnits);
+	builtIns.append(TString(builtInConstant));
+
+	sprintf(builtInConstant, "const int  gl_MaxFragmentUniformVectors = %d;", resources.maxFragmentUniformVectors);
+	builtIns.append(TString(builtInConstant));
+
+	sprintf(builtInConstant, "const int  gl_MaxDrawBuffers = %d;", resources.maxDrawBuffers);
+	builtIns.append(TString(builtInConstant));
+
+	builtInStrings[EShLangFragment].push_back(builtIns);
+	builtInStrings[EShLangVertex].push_back(builtIns);
+}
+
+void IdentifyBuiltIns(EShLanguage language, TSymbolTable& symbolTable)
+{
+	//
+	// First, insert some special built-in variables that are not in 
+	// the built-in header files.
+	//
+	switch(language) {
+
+	case EShLangFragment: {
+			symbolTable.insert(*new TVariable(NewPoolTString("gl_FragCoord"),                   TType(EbtFloat, EvqFragCoord,   4)));   // FIXME: mediump
+			symbolTable.insert(*new TVariable(NewPoolTString("gl_FrontFacing"),                 TType(EbtBool,  EvqFrontFacing, 1)));
+			symbolTable.insert(*new TVariable(NewPoolTString("gl_FragColor"),                   TType(EbtFloat, EvqFragColor,   4)));   // FIXME: mediump
+			symbolTable.insert(*new TVariable(NewPoolTString("gl_FragData[gl_MaxDrawBuffers]"), TType(EbtFloat, EvqFragData,    4)));   // FIXME: mediump
+			symbolTable.insert(*new TVariable(NewPoolTString("gl_PointCoord"),                  TType(EbtFloat, EvqPointCoord,  2)));   // FIXME: mediump
+
+		}
+		break;
+
+	case EShLangVertex:
+		symbolTable.insert(*new TVariable(NewPoolTString("gl_Position"),    TType(EbtFloat, EvqPosition,    4)));   // FIXME: highp
+		symbolTable.insert(*new TVariable(NewPoolTString("gl_PointSize"),   TType(EbtFloat, EvqPointSize,   1)));   // FIXME: mediump
+		break;
+	default: break;
+	}
+
+	//
+	// 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("mod",              EOpMod);
+
+	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("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("forward",      EOpFaceForward);
+	symbolTable.relateToOperator("reflect",      EOpReflect);
+	symbolTable.relateToOperator("refract",      EOpRefract);
+	
+	symbolTable.relateToOperator("any",          EOpAny);
+	symbolTable.relateToOperator("all",          EOpAll);
+
+	switch(language)
+	{
+	case EShLangVertex:
+		break;
+	case EShLangFragment:
+	//	symbolTable.relateToOperator("dFdx",         EOpDPdx);             
+	//	symbolTable.relateToOperator("dFdy",         EOpDPdy);             
+	//	symbolTable.relateToOperator("fwidth",       EOpFwidth);
+		break;
+	case EShLangPack:
+	case EShLangUnpack:
+		symbolTable.relateToOperator("itof",         EOpItof);
+		symbolTable.relateToOperator("ftoi",         EOpFtoi);
+		symbolTable.relateToOperator("skipPixels",   EOpSkipPixels);
+		symbolTable.relateToOperator("readInput",    EOpReadInput);
+		symbolTable.relateToOperator("writePixel",   EOpWritePixel);
+		symbolTable.relateToOperator("bitmapLSB",    EOpBitmapLsb);
+		symbolTable.relateToOperator("bitmapMSB",    EOpBitmapMsb);
+		symbolTable.relateToOperator("writeOutput",  EOpWriteOutput);
+		symbolTable.relateToOperator("readPixel",    EOpReadPixel);
+		break;
+	default: assert(false && "Language not supported");
+	}
+}
+
+void IdentifyBuiltIns(EShLanguage language, TSymbolTable& symbolTable, const TBuiltInResource &resources)
+{
+	//
+	// First, insert some special built-in variables that are not in 
+	// the built-in header files.
+	//
+	switch(language) {
+
+	case EShLangFragment: {
+			// Set up gl_FragData.  The array size.
+			TType fragData(EbtFloat, EvqFragColor,   4, false, true);
+			fragData.setArraySize(resources.maxDrawBuffers);
+			symbolTable.insert(*new TVariable(NewPoolTString("gl_FragData"),    fragData));
+		}
+		break;
+
+	default: break;
+	}
+}
+
+const char* GetPreprocessorBuiltinString()
+{
+	static const char *PreprocessorBuiltinString = "";
+
+	return PreprocessorBuiltinString;
+}
diff --git a/Compiler/Initialize.h b/Compiler/Initialize.h
new file mode 100644
index 0000000..99b0dfc
--- /dev/null
+++ b/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 "ResourceLimits.h"
+#include "Common.h"
+#include "ShHandle.h"
+#include "SymbolTable.h"
+
+typedef TVector<TString> TBuiltInStrings;
+
+class TBuiltIns {
+public:
+	POOL_ALLOCATOR_NEW_DELETE(GlobalPoolAllocator)
+	void initialize();
+	void initialize(const TBuiltInResource& resources);
+	TBuiltInStrings* getBuiltInStrings() { return builtInStrings; }
+protected:
+	TBuiltInStrings builtInStrings[EShLangCount];
+};
+
+void IdentifyBuiltIns(EShLanguage, TSymbolTable&);
+void IdentifyBuiltIns(EShLanguage, TSymbolTable&, const TBuiltInResource &resources);
+bool GenerateBuiltInSymbolTable(const TBuiltInResource* resources, TInfoSink&, TSymbolTable*, EShLanguage language = EShLangCount);
+bool InitializeSymbolTable(TBuiltInStrings* BuiltInStrings, EShLanguage language, TInfoSink& infoSink, const TBuiltInResource *resources, TSymbolTable*);
+const char* GetPreprocessorBuiltinString();
+extern "C" int InitPreprocessor(void);
+extern "C" int FinalizePreprocessor(void);
+
+#endif // _INITIALIZE_INCLUDED_
diff --git a/Compiler/InitializeDll.cpp b/Compiler/InitializeDll.cpp
new file mode 100644
index 0000000..fd7c3ab
--- /dev/null
+++ b/Compiler/InitializeDll.cpp
@@ -0,0 +1,119 @@
+//
+// 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 "InitializeDll.h"
+#include "InitializeGlobals.h"
+#include "InitializeParseContext.h"
+
+#include "ShaderLang.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;
+	}
+
+	InitThread();
+    return true;
+}
+
+
+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;
+		}
+
+		FreeGlobalPools();
+
+		if (!FreeParseContext())
+            success = false;
+	}
+
+    return success;
+}
+
+bool DetachProcess()
+{
+    bool success = true;
+
+    if (ThreadInitializeIndex == OS_INVALID_TLS_INDEX)
+        return true;
+
+    ShFinalize();
+
+    success = DetachThread();
+
+	FreePoolIndex();
+
+	if (!FreeParseContextIndex())
+        success = false;
+
+    OS_FreeTLSIndex(ThreadInitializeIndex);
+    ThreadInitializeIndex = OS_INVALID_TLS_INDEX;
+
+    return success;
+}
diff --git a/Compiler/InitializeDll.h b/Compiler/InitializeDll.h
new file mode 100644
index 0000000..ec7b303
--- /dev/null
+++ b/Compiler/InitializeDll.h
@@ -0,0 +1,19 @@
+//
+// 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
+
+
+#include "osinclude.h"
+
+
+bool InitProcess();
+bool InitThread();
+bool DetachThread();
+bool DetachProcess();
+
+#endif // __INITIALIZEDLL_H
+
diff --git a/Compiler/InitializeGlobals.h b/Compiler/InitializeGlobals.h
new file mode 100644
index 0000000..842a452
--- /dev/null
+++ b/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/Compiler/InitializeParseContext.h b/Compiler/InitializeParseContext.h
new file mode 100644
index 0000000..45fc3f3
--- /dev/null
+++ b/Compiler/InitializeParseContext.h
@@ -0,0 +1,17 @@
+//
+// 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_PARSE_CONTEXT_INCLUDED_
+#define __INITIALIZE_PARSE_CONTEXT_INCLUDED_
+#include "osinclude.h"
+
+bool InitializeParseContextIndex();
+bool InitializeGlobalParseContext();
+bool FreeParseContext();
+bool FreeParseContextIndex();
+
+
+#endif // __INITIALIZE_PARSE_CONTEXT_INCLUDED_
diff --git a/Compiler/IntermTraverse.cpp b/Compiler/IntermTraverse.cpp
new file mode 100644
index 0000000..6a61884
--- /dev/null
+++ b/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 "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(terminal)
+			{
+				terminal->traverse(it);
+			}
+
+			if(body)
+			{
+				body->traverse(it);
+			}
+
+			if(test)
+			{
+				test->traverse(it);
+			}
+		}
+		else
+		{
+			if(test)
+			{
+				test->traverse(it);
+			}
+
+			if(body)
+			{
+				body->traverse(it);
+			}
+
+			if(terminal)
+			{
+				terminal->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/Compiler/Intermediate.cpp b/Compiler/Intermediate.cpp
new file mode 100644
index 0000000..54fa796
--- /dev/null
+++ b/Compiler/Intermediate.cpp
@@ -0,0 +1,1483 @@
+//
+// 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.
+//
+
+//
+// Build the intermediate representation.
+//
+
+#include "localintermediate.h"
+#include "QualifierAlive.h"
+#include "RemoveTree.h"
+#include <float.h>
+
+bool CompareStructure(const TType& leftNodeType, constUnion* rightUnionArray, constUnion* leftUnionArray);
+
+////////////////////////////////////////////////////////////////////////////
+//
+// 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 EOpLessThan:
+	case EOpGreaterThan:
+	case EOpLessThanEqual:
+	case EOpGreaterThanEqual:
+		if (left->getType().isMatrix() || left->getType().isArray() || left->getType().isVector() || left->getType().getBasicType() == EbtStruct) {
+			return 0;
+		}
+		break;
+	case EOpLogicalOr:
+	case EOpLogicalXor:
+	case EOpLogicalAnd:
+		if (left->getType().getBasicType() != EbtBool || left->getType().isMatrix() || left->getType().isArray() || left->getType().isVector()) {
+			return 0;
+		}
+		break;
+	case EOpAdd:
+	case EOpSub:
+	case EOpDiv:
+	case EOpMul:
+		if (left->getType().getBasicType() == EbtStruct || left->getType().getBasicType() == EbtBool)
+			return 0;
+	default: break;
+	}
+
+	//
+	// First try converting the children to compatible types.
+	//
+
+	if (!(left->getType().getStruct() && right->getType().getStruct())) {
+		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;
+		}
+	} else {
+		if (left->getType() != right->getType())
+			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;
+
+	TIntermConstantUnion *leftTempConstant = left->getAsConstantUnion();
+	TIntermConstantUnion *rightTempConstant = right->getAsConstantUnion();
+
+	if (leftTempConstant)
+		leftTempConstant = left->getAsConstantUnion();
+
+	if (rightTempConstant)
+		rightTempConstant = right->getAsConstantUnion();
+
+	//
+	// See if we can fold constants.
+	//
+
+	TIntermTyped* typedReturnNode = 0;
+	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, 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.
+//
+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->setOperator(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, 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())
+			return nodePair.node1;
+		else
+			return nodePair.node2;
+	}
+
+	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()->setOperator(EOpComma);
+		commaAggregate->setType(right->getType());
+		commaAggregate->getTypePointer()->changeQualifier(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->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(constUnion* 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();
+	constUnion* unionArray;
+
+	for (int i = 0; i < fields.num; i++) {
+		unionArray = new constUnion[1];
+		unionArray->setIConst(fields.offsets[i]);
+		constIntNode = addConstantUnion(unionArray, TType(EbtInt, EvqConst), line);
+		sequenceVector.push_back(constIntNode);
+	}
+
+	return node;
+}
+
+//
+// Create loop nodes.
+//
+TIntermNode* TIntermediate::addLoop(TIntermNode *init, TIntermNode* body, TIntermTyped* test, TIntermTyped* terminal, bool testFirst, TSourceLoc line)
+{
+	TIntermNode* node = new TIntermLoop(init, body, test, terminal, testFirst);
+	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, EShLanguage language)
+{
+	if (root == 0)
+		return true;
+
+	//
+	// First, finish off the top level sequence, if any
+	//
+	TIntermAggregate* aggRoot = root->getAsAggregate();
+	if (aggRoot && aggRoot->getOp() == EOpNull)
+		aggRoot->setOperator(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:
+	case EOpModAssign:
+	case EOpAndAssign:
+	case EOpInclusiveOrAssign:
+	case EOpExclusiveOrAssign:
+	case EOpLeftShiftAssign:
+	case EOpRightShiftAssign:
+		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 EOpBitwiseNot:
+		if (operand->getBasicType() != EbtInt)
+			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());
+
+	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)
+{
+	int size = left->getNominalSize();
+	if (right->getNominalSize() > size)
+		size = right->getNominalSize();
+
+	TBasicType type = left->getBasicType();
+
+	//
+	// Arrays have to be exact matches.
+	//
+	if ((left->isArray() || right->isArray()) && (left->getType() != right->getType()))
+		return false;
+
+	//
+	// Base assumption:  just make the type the same as the left
+	// operand.  Then only deviations from this need be coded.
+	//
+	setType(TType(type, EvqTemporary, left->getNominalSize(), left->isMatrix()));
+
+	//
+	// Array operations.
+	//
+	if (left->isArray()) {
+
+		switch (op) {
+
+		//
+		// Promote to conditional
+		//
+		case EOpEqual:
+		case EOpNotEqual:
+			setType(TType(EbtBool));
+			break;
+
+		//
+		// Set array information.
+		//
+		case EOpAssign:
+		case EOpInitialize:
+			getType().setArraySize(left->getType().getArraySize());
+			getType().setArrayInformationType(left->getType().getArrayInformationType());
+			break;
+
+		default:
+			return false;
+		}
+
+		return true;
+	}
+
+	//
+	// 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));
+			break;
+
+		//
+		// And and Or operate on conditionals
+		//
+		case EOpLogicalAnd:
+		case EOpLogicalOr:
+			if (left->getBasicType() != EbtBool || right->getBasicType() != EbtBool)
+				return false;
+			setType(TType(EbtBool));
+			break;
+
+		//
+		// Check for integer only operands.
+		//
+		case EOpMod:
+		case EOpRightShift:
+		case EOpLeftShift:
+		case EOpAnd:
+		case EOpInclusiveOr:
+		case EOpExclusiveOr:
+			if (left->getBasicType() != EbtInt || right->getBasicType() != EbtInt)
+				return false;
+			break;
+		case EOpModAssign:
+		case EOpAndAssign:
+		case EOpInclusiveOrAssign:
+		case EOpExclusiveOrAssign:
+		case EOpLeftShiftAssign:
+		case EOpRightShiftAssign:
+			if (left->getBasicType() != EbtInt || right->getBasicType() != EbtInt)
+				return false;
+			// fall through
+
+		//
+		// Everything else should have matching types
+		//
+		default:
+			if (left->getBasicType() != right->getBasicType() ||
+				left->isMatrix()     != right->isMatrix())
+				return false;
+		}
+
+		return true;
+	}
+
+	//
+	// Are the sizes compatible?
+	//
+	if ( left->getNominalSize() != size &&  left->getNominalSize() != 1 ||
+		right->getNominalSize() != size && right->getNominalSize() != 1)
+		return false;
+
+	//
+	// Can these two operands be combined?
+	//
+	switch (op) {
+	case EOpMul:
+		if (!left->isMatrix() && right->isMatrix()) {
+			if (left->isVector())
+				op = EOpVectorTimesMatrix;
+			else {
+				op = EOpMatrixTimesScalar;
+				setType(TType(type, EvqTemporary, size, true));
+			}
+		} else if (left->isMatrix() && !right->isMatrix()) {
+			if (right->isVector()) {
+				op = EOpMatrixTimesVector;
+				setType(TType(type, 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(type, 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(type, EvqTemporary, size, false));
+			}
+		} else {
+			infoSink.info.message(EPrefixInternalError, "Missing elses", getLine());
+			return false;
+		}
+		break;
+	case EOpAssign:
+	case EOpInitialize:
+		if (left->getNominalSize() != right->getNominalSize())
+			return false;
+		// fall through
+	case EOpAdd:
+	case EOpSub:
+	case EOpDiv:
+	case EOpMod:
+	case EOpAddAssign:
+	case EOpSubAssign:
+	case EOpDivAssign:
+	case EOpModAssign:
+		if (left->isMatrix() && right->isVector() ||
+			left->isVector() && right->isMatrix() ||
+			left->getBasicType() != right->getBasicType())
+			return false;
+		setType(TType(type, 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() ||
+			left->getBasicType() != right->getBasicType())
+			return false;
+		setType(TType(EbtBool));
+		break;
+
+default:
+		return false;
+	}
+
+	//
+	// One more check for assignment.  The Resulting type has to match the left operand.
+	//
+	switch (op) {
+	case EOpAssign:
+	case EOpInitialize:
+	case EOpAddAssign:
+	case EOpSubAssign:
+	case EOpMulAssign:
+	case EOpDivAssign:
+	case EOpModAssign:
+	case EOpAndAssign:
+	case EOpInclusiveOrAssign:
+	case EOpExclusiveOrAssign:
+	case EOpLeftShiftAssign:
+	case EOpRightShiftAssign:
+		if (getType() != left->getType())
+			return false;
+		break;
+	default:
+		break;
+	}
+
+	return true;
+}
+
+bool CompareStruct(const TType& leftNodeType, constUnion* rightUnionArray, constUnion* leftUnionArray)
+{
+	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, constUnion* rightUnionArray, constUnion* 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)
+{
+	constUnion *unionArray = getUnionArrayPointer();
+	int objectSize = getType().getObjectSize();
+
+	if (constantNode) {  // binary operations
+		TIntermConstantUnion *node = constantNode->getAsConstantUnion();
+		constUnion *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 constUnion[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 constUnion[constantNode->getType().getObjectSize()];
+			for (int i = 0; i < constantNode->getType().getObjectSize(); ++i)
+				unionArray[i] = *getUnionArrayPointer();
+			returnType = node->getType();
+			objectSize = constantNode->getType().getObjectSize();
+		}
+
+		constUnion* tempConstArray = 0;
+		TIntermConstantUnion *tempNode;
+
+		bool boolNodeFlag = false;
+		switch(op) {
+		case EOpAdd:
+			tempConstArray = new constUnion[objectSize];
+			{// support MSVC++6.0
+				for (int i = 0; i < objectSize; i++)
+					tempConstArray[i] = unionArray[i] + rightUnionArray[i];
+			}
+			break;
+		case EOpSub:
+			tempConstArray = new constUnion[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 constUnion[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 constUnion[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 constUnion[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 constUnion[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 constUnion[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 EOpMod:
+			tempConstArray = new constUnion[objectSize];
+			{// support MSVC++6.0
+				for (int i = 0; i < objectSize; i++)
+					tempConstArray[i] = unionArray[i] % rightUnionArray[i];
+			}
+			break;
+
+		case EOpRightShift:
+			tempConstArray = new constUnion[objectSize];
+			{// support MSVC++6.0
+				for (int i = 0; i < objectSize; i++)
+					tempConstArray[i] = unionArray[i] >> rightUnionArray[i];
+			}
+			break;
+
+		case EOpLeftShift:
+			tempConstArray = new constUnion[objectSize];
+			{// support MSVC++6.0
+				for (int i = 0; i < objectSize; i++)
+					tempConstArray[i] = unionArray[i] << rightUnionArray[i];
+			}
+			break;
+
+		case EOpAnd:
+			tempConstArray = new constUnion[objectSize];
+			{// support MSVC++6.0
+				for (int i = 0; i < objectSize; i++)
+					tempConstArray[i] = unionArray[i] & rightUnionArray[i];
+			}
+			break;
+		case EOpInclusiveOr:
+			tempConstArray = new constUnion[objectSize];
+			{// support MSVC++6.0
+				for (int i = 0; i < objectSize; i++)
+					tempConstArray[i] = unionArray[i] | rightUnionArray[i];
+			}
+			break;
+		case EOpExclusiveOr:
+			tempConstArray = new constUnion[objectSize];
+			{// support MSVC++6.0
+				for (int i = 0; i < objectSize; i++)
+					tempConstArray[i] = unionArray[i] ^ rightUnionArray[i];
+			}
+			break;
+
+		case EOpLogicalAnd: // this code is written for possible future use, will not get executed currently
+			tempConstArray = new constUnion[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 constUnion[objectSize];
+			{// support MSVC++6.0
+				for (int i = 0; i < objectSize; i++)
+					tempConstArray[i] = unionArray[i] || rightUnionArray[i];
+			}
+			break;
+
+		case EOpLogicalXor:
+			tempConstArray = new constUnion[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 constUnion[1];
+			tempConstArray->setBConst(*unionArray < *rightUnionArray);
+			returnType = TType(EbtBool, EvqConst);
+			break;
+		case EOpGreaterThan:
+			assert(objectSize == 1);
+			tempConstArray = new constUnion[1];
+			tempConstArray->setBConst(*unionArray > *rightUnionArray);
+			returnType = TType(EbtBool, EvqConst);
+			break;
+		case EOpLessThanEqual:
+		{
+			assert(objectSize == 1);
+			constUnion constant;
+			constant.setBConst(*unionArray > *rightUnionArray);
+			tempConstArray = new constUnion[1];
+			tempConstArray->setBConst(!constant.getBConst());
+			returnType = TType(EbtBool, EvqConst);
+			break;
+		}
+		case EOpGreaterThanEqual:
+		{
+			assert(objectSize == 1);
+			constUnion constant;
+			constant.setBConst(*unionArray < *rightUnionArray);
+			tempConstArray = new constUnion[1];
+			tempConstArray->setBConst(!constant.getBConst());
+			returnType = TType(EbtBool, 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 constUnion[1];
+			if (!boolNodeFlag) {
+				tempConstArray->setBConst(true);
+			}
+			else {
+				tempConstArray->setBConst(false);
+			}
+
+			tempNode = new TIntermConstantUnion(tempConstArray, TType(EbtBool, 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 constUnion[1];
+			if (!boolNodeFlag) {
+				tempConstArray->setBConst(true);
+			}
+			else {
+				tempConstArray->setBConst(false);
+			}
+
+			tempNode = new TIntermConstantUnion(tempConstArray, TType(EbtBool, 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;
+		constUnion* tempConstArray = new constUnion[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;
+	}
+
+	return this;
+}
+
+TIntermTyped* TIntermediate::promoteConstantUnion(TBasicType promoteTo, TIntermConstantUnion* node)
+{
+	constUnion *rightUnionArray = node->getUnionArrayPointer();
+	int size = node->getType().getObjectSize();
+
+	constUnion *leftUnionArray = new constUnion[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.getQualifier(), t.getNominalSize(), t.isMatrix(), t.isArray()), node->getLine());
+}
+
+void TIntermAggregate::addToPragmaTable(const TPragmaTable& pTable)
+{
+	assert(!pragmaTable);
+	pragmaTable = new TPragmaTable();
+	*pragmaTable = pTable;
+}
+
diff --git a/Compiler/Link.cpp b/Compiler/Link.cpp
new file mode 100644
index 0000000..9f5819b
--- /dev/null
+++ b/Compiler/Link.cpp
@@ -0,0 +1,63 @@
+//
+// 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.
+//
+
+//
+// The top level algorithms for linking multiple
+// shaders together.
+//
+#include "Common.h"
+#include "ShHandle.h"
+
+//
+// Actual link object, derived from the shader handle base classes.
+//
+class TGenericLinker : public TLinker {
+public:
+    TGenericLinker(EShExecutable e, int dOptions) : TLinker(e, infoSink), debugOptions(dOptions) { }
+    bool link(TCompilerList&, TUniformMap*) { return true; }
+	void getAttributeBindings(ShBindingTable const **t) const { }
+    TInfoSink infoSink;
+    int debugOptions;
+};
+
+//
+// The internal view of a uniform/float object exchanged with the driver.
+//
+class TUniformLinkedMap : public TUniformMap {
+public:
+    TUniformLinkedMap() { }
+    virtual int getLocation(const char* name) { return 0; }
+};
+
+TShHandleBase* ConstructLinker(EShExecutable executable, int debugOptions)
+{
+    return new TGenericLinker(executable, debugOptions);
+}
+
+void DeleteLinker(TShHandleBase* linker)
+{
+    delete linker;
+}
+
+TUniformMap* ConstructUniformMap()
+{
+    return new TUniformLinkedMap();
+}
+
+void DeleteUniformMap(TUniformMap* map)
+{
+    delete map;
+}
+
+TShHandleBase* ConstructBindings()
+{
+    return 0;
+}
+
+void DeleteBindingList(TShHandleBase* bindingList)
+{
+    delete bindingList;
+}
diff --git a/Compiler/MMap.h b/Compiler/MMap.h
new file mode 100644
index 0000000..a308671
--- /dev/null
+++ b/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/Compiler/OutputHLSL.cpp b/Compiler/OutputHLSL.cpp
new file mode 100644
index 0000000..eaa1589
--- /dev/null
+++ b/Compiler/OutputHLSL.cpp
@@ -0,0 +1,1184 @@
+//
+// 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 "OutputHLSL.h"
+
+#include "InfoSink.h"
+#include "debug.h"
+
+namespace sh
+{
+OutputHLSL::OutputHLSL(TParseContext &context) : TIntermTraverser(true, true, true), context(context)
+{
+}
+
+void OutputHLSL::header()
+{
+    EShLanguage language = context.language;
+    TInfoSinkBase &out = context.infoSink.obj;
+
+    if (language == EShLangFragment)
+    {
+        TString uniforms;
+        TString varyingInput;
+        TString varyingGlobals;
+
+        TSymbolTableLevel *symbols = context.symbolTable.getGlobalLevel();
+        int semanticIndex = 0;
+
+        for (TSymbolTableLevel::const_iterator namedSymbol = symbols->begin(); namedSymbol != symbols->end(); namedSymbol++)
+        {
+            const TSymbol *symbol = (*namedSymbol).second;
+            const TString &name = symbol->getName();
+
+            if (symbol->isVariable())
+            {
+                const TVariable *variable = static_cast<const TVariable*>(symbol);
+                const TType &type = variable->getType();
+                TQualifier qualifier = type.getQualifier();
+
+                if (qualifier == EvqUniform)
+                {
+                    uniforms += "uniform " + typeString(type) + " " + name + arrayString(type) + ";\n";
+                }
+                else if (qualifier == EvqVaryingIn || qualifier == EvqInvariantVaryingIn)
+                {
+                    char semantic[100];
+                    sprintf(semantic, " : TEXCOORD%d", semanticIndex);
+                    semanticIndex += type.isArray() ? type.getArraySize() : 1;
+
+                    varyingInput += "    " + typeString(type) + " " + name + arrayString(type) + semantic + ";\n";
+                    varyingGlobals += "static " + typeString(type) + " " + name + arrayString(type) + " = " + initializer(type) + ";\n";
+                }
+            }
+        }
+
+        out <<  uniforms;
+        out << "\n";
+        out << "struct PS_INPUT\n"   // FIXME: Prevent name clashes
+               "{\n";
+        out <<        varyingInput;
+        out << "};\n"
+               "\n";
+        out <<    varyingGlobals;
+        out << "\n"
+               "struct PS_OUTPUT\n"   // FIXME: Prevent name clashes
+               "{\n"
+               "    float4 gl_Color[1] : COLOR;\n"
+               "};\n"
+               "\n"
+               "static float4 gl_Color[1] = {float4(0, 0, 0, 0)};\n"
+               "\n"
+               "float4 gl_texture2D(sampler2D s, float2 t)\n"
+               "{\n"
+               "    return tex2D(s, t);\n"
+               "}\n"
+               "\n"
+               "float4 gl_texture2DProj(sampler2D s, float3 t)\n"
+               "{\n"
+               "    return tex2Dproj(s, float4(t.x, t.y, 0, t.z));\n"
+               "}\n"
+               "float4 gl_texture2DBias(sampler2D s, float2 t, float bias)\n"
+               "{\n"
+               "    return tex2Dbias(s, float4(t.x, t.y, 0, bias));\n"
+               "}\n"
+               "\n"
+               "float4 gl_textureCube(samplerCUBE s, float3 t)\n"
+               "{\n"
+               "    return texCUBE(s, t);\n"
+               "}\n"
+               "\n";
+    }
+    else
+    {
+        TString uniforms;
+        TString attributeInput;
+        TString attributeGlobals;
+        TString varyingOutput;
+        TString varyingGlobals;
+        TString globals;
+
+        TSymbolTableLevel *symbols = context.symbolTable.getGlobalLevel();
+        int semanticIndex = 0;
+
+        for (TSymbolTableLevel::const_iterator namedSymbol = symbols->begin(); namedSymbol != symbols->end(); namedSymbol++)
+        {
+            const TSymbol *symbol = (*namedSymbol).second;
+            const TString &name = symbol->getName();
+
+            if (symbol->isVariable())
+            {
+                const TVariable *variable = static_cast<const TVariable*>(symbol);
+                const TType &type = variable->getType();
+                TQualifier qualifier = type.getQualifier();
+
+                if (qualifier == EvqUniform)
+                {
+                    uniforms += "uniform " + typeString(type) + " " + name + arrayString(type) + ";\n";
+                }
+                else if (qualifier == EvqAttribute)
+                {
+                    char semantic[100];
+                    sprintf(semantic, " : TEXCOORD%d", semanticIndex);
+                    semanticIndex += type.isArray() ? type.getArraySize() : 1;
+
+                    attributeInput += "    " + typeString(type) + " " + name + arrayString(type) + semantic + ";\n";
+                    attributeGlobals += "static " + typeString(type) + " " + name + arrayString(type) + " = " + initializer(type) + ";\n";
+                }
+                else if (qualifier == EvqVaryingOut || qualifier == EvqInvariantVaryingOut)
+                {
+                    varyingOutput += "    " + typeString(type) + " " + name + arrayString(type) + " : TEXCOORD0;\n";   // Actual semantic index assigned during link
+                    varyingGlobals += "static " + typeString(type) + " " + name + arrayString(type) + " = " + initializer(type) + ";\n";
+                }
+                else if (qualifier == EvqGlobal)
+                {
+                    globals += typeString(type) + " " + name + arrayString(type) + ";\n";
+                }
+                else UNREACHABLE();
+            }
+        }
+
+        out << "uniform float2 gl_HalfPixelSize;\n";
+        out << "\n";
+        out <<  uniforms;
+        out << "\n";
+        out <<  globals;
+        out << "\n";
+        out << "struct VS_INPUT\n"   // FIXME: Prevent name clashes
+               "{\n";
+        out <<        attributeInput;
+        out << "};\n"
+               "\n";
+        out <<  attributeGlobals;
+        out << "\n"
+               "struct VS_OUTPUT\n"   // FIXME: Prevent name clashes
+               "{\n"
+               "    float4 gl_Position : POSITION;\n"
+               "    float gl_PointSize : PSIZE;\n";
+        out <<        varyingOutput;
+        out << "};\n"
+               "\n"
+               "static float4 gl_Position = float4(0, 0, 0, 0);\n"
+               "static float gl_PointSize = float(0);\n";
+        out <<  varyingGlobals;
+        out << "\n";
+    }
+
+    out << "float vec1(float x)\n"   // FIXME: Prevent name clashes
+           "{\n"
+           "    return x;\n"
+           "}\n"
+           "\n"
+           "float vec1(float2 xy)\n"   // FIXME: Prevent name clashes
+           "{\n"
+           "    return xy[0];\n"
+           "}\n"
+           "\n"
+           "float vec1(float3 xyz)\n"   // FIXME: Prevent name clashes
+           "{\n"
+           "    return xyz[0];\n"
+           "}\n"
+           "\n"
+           "float vec1(float4 xyzw)\n"   // FIXME: Prevent name clashes
+           "{\n"
+           "    return xyzw[0];\n"
+           "}\n"
+           "\n"
+           "float2 vec2(float x)\n"   // FIXME: Prevent name clashes
+           "{\n"
+           "    return float2(x, x);\n"
+           "}\n"
+           "\n"
+           "float2 vec2(float x, float y)\n"   // FIXME: Prevent name clashes
+           "{\n"
+           "    return float2(x, y);\n"
+           "}\n"
+           "\n"
+           "float2 vec2(float2 xy)\n"   // FIXME: Prevent name clashes
+           "{\n"
+           "    return xy;\n"
+           "}\n"
+           "\n"
+           "float2 vec2(float3 xyz)\n"   // FIXME: Prevent name clashes
+           "{\n"
+           "    return float2(xyz[0], xyz[1]);\n"
+           "}\n"
+           "\n"
+           "float2 vec2(float4 xyzw)\n"   // FIXME: Prevent name clashes
+           "{\n"
+           "    return float2(xyzw[0], xyzw[1]);\n"
+           "}\n"
+           "\n"
+           "float3 vec3(float x)\n"   // FIXME: Prevent name clashes
+           "{\n"
+           "    return float3(x, x, x);\n"
+           "}\n"
+           "\n"
+           "float3 vec3(float x, float y, float z)\n"   // FIXME: Prevent name clashes
+           "{\n"
+           "    return float3(x, y, z);\n"
+           "}\n"
+           "\n"
+           "float3 vec3(float2 xy, float z)\n"   // FIXME: Prevent name clashes
+           "{\n"
+           "    return float3(xy[0], xy[1], z);\n"
+           "}\n"
+           "\n"
+           "float3 vec3(float x, float2 yz)\n"   // FIXME: Prevent name clashes
+           "{\n"
+           "    return float3(x, yz[0], yz[1]);\n"
+           "}\n"
+           "\n"
+           "float3 vec3(float3 xyz)\n"   // FIXME: Prevent name clashes
+           "{\n"
+           "    return xyz;\n"
+           "}\n"
+           "\n"
+           "float3 vec3(float4 xyzw)\n"   // FIXME: Prevent name clashes
+           "{\n"
+           "    return float3(xyzw[0], xyzw[1], xyzw[2]);\n"
+           "}\n"
+           "\n"
+           "float4 vec4(float x)\n"   // FIXME: Prevent name clashes
+           "{\n"
+           "    return float4(x, x, x, x);\n"
+           "}\n"
+           "\n"
+           "float4 vec4(float x, float y, float z, float w)\n"   // FIXME: Prevent name clashes
+           "{\n"
+           "    return float4(x, y, z, w);\n"
+           "}\n"
+           "\n"
+           "float4 vec4(float2 xy, float z, float w)\n"   // FIXME: Prevent name clashes
+           "{\n"
+           "    return float4(xy[0], xy[1], z, w);\n"
+           "}\n"
+           "\n"
+           "float4 vec4(float x, float2 yz, float w)\n"   // FIXME: Prevent name clashes
+           "{\n"
+           "    return float4(x, yz[0], yz[1], w);\n"
+           "}\n"
+           "\n"
+           "float4 vec4(float x, float y, float2 zw)\n"   // FIXME: Prevent name clashes
+           "{\n"
+           "    return float4(x, y, zw[0], zw[1]);\n"
+           "}\n"
+           "\n"
+           "float4 vec4(float2 xy, float2 zw)\n"   // FIXME: Prevent name clashes
+           "{\n"
+           "    return float4(xy[0], xy[1], zw[0], zw[1]);\n"
+           "}\n"
+           "\n"
+           "float4 vec4(float3 xyz, float w)\n"   // FIXME: Prevent name clashes
+           "{\n"
+           "    return float4(xyz[0], xyz[1], xyz[2], w);\n"
+           "}\n"
+           "\n"
+           "float4 vec4(float x, float3 yzw)\n"   // FIXME: Prevent name clashes
+           "{\n"
+           "    return float4(x, yzw[0], yzw[1], yzw[2]);\n"
+           "}\n"
+           "\n"
+           "float4 vec4(float4 xyzw)\n"   // FIXME: Prevent name clashes
+           "{\n"
+           "    return xyzw;\n"
+           "}\n"
+           "\n"
+           "bool xor(bool p, bool q)\n"   // FIXME: Prevent name clashes
+           "{\n"
+           "    return (p || q) && !(p && q);\n"
+           "}\n"
+           "\n"
+           "float mod(float x, float y)\n"   // FIXME: Prevent name clashes
+           "{\n"
+           "    return x - y * floor(x / y);\n"
+           "}\n"
+           "float2 mod(float2 x, float y)\n"   // FIXME: Prevent name clashes
+           "{\n"
+           "    return x - y * floor(x / y);\n"
+           "}\n"
+           "float3 mod(float3 x, float y)\n"   // FIXME: Prevent name clashes
+           "{\n"
+           "    return x - y * floor(x / y);\n"
+           "}\n"
+           "float4 mod(float4 x, float y)\n"   // FIXME: Prevent name clashes
+           "{\n"
+           "    return x - y * floor(x / y);\n"
+           "}\n"
+           "\n";
+}
+
+void OutputHLSL::visitSymbol(TIntermSymbol *node)
+{
+    TInfoSinkBase &out = context.infoSink.obj;
+
+    TString name = node->getSymbol();
+
+    if (name == "gl_FragColor")
+    {
+        out << "gl_Color[0]";
+    }
+    else if (name == "gl_FragData")
+    {
+        out << "gl_Color";
+    }
+    else
+    {
+        out << name;
+    }
+}
+
+bool OutputHLSL::visitBinary(Visit visit, TIntermBinary *node)
+{
+    TInfoSinkBase &out = context.infoSink.obj;
+
+    switch (node->getOp())
+    {
+      case EOpAssign:                  outputTriplet(visit, "(", " = ", ")");       break;
+      case EOpInitialize:              outputTriplet(visit, NULL, " = ", NULL);     break;
+      case EOpAddAssign:               outputTriplet(visit, NULL, " += ", NULL);    break;
+      case EOpSubAssign:               outputTriplet(visit, NULL, " -= ", NULL);    break;
+      case EOpMulAssign:               outputTriplet(visit, NULL, " *= ", NULL);    break;
+      case EOpVectorTimesMatrixAssign: UNIMPLEMENTED(); /* FIXME */ out << "matrix mult second child into first child";  break;
+      case EOpVectorTimesScalarAssign: outputTriplet(visit, NULL, " *= ", NULL);    break;
+      case EOpMatrixTimesScalarAssign: UNIMPLEMENTED(); /* FIXME */ out << "matrix scale second child into first child"; break;
+      case EOpMatrixTimesMatrixAssign: UNIMPLEMENTED(); /* FIXME */ out << "matrix mult second child into first child"; break;
+      case EOpDivAssign:               outputTriplet(visit, NULL, " /= ", NULL);    break;
+      case EOpModAssign:               UNIMPLEMENTED(); /* FIXME */ out << "mod second child into first child";          break;
+      case EOpAndAssign:               UNIMPLEMENTED(); /* FIXME */ out << "and second child into first child";          break;
+      case EOpInclusiveOrAssign:       UNIMPLEMENTED(); /* FIXME */ out << "or second child into first child";           break;
+      case EOpExclusiveOrAssign:       UNIMPLEMENTED(); /* FIXME */ out << "exclusive or second child into first child"; break;
+      case EOpLeftShiftAssign:         UNIMPLEMENTED(); /* FIXME */ out << "left shift second child into first child";   break;
+      case EOpRightShiftAssign:        UNIMPLEMENTED(); /* FIXME */ out << "right shift second child into first child";  break;
+      case EOpIndexDirect:             outputTriplet(visit, NULL, "[", "]"); break;
+      case EOpIndexIndirect:           outputTriplet(visit, NULL, "[", "]"); break;
+      case EOpIndexDirectStruct:       UNIMPLEMENTED(); /* FIXME */ out << "direct index for structure";   break;
+      case EOpVectorSwizzle:
+        if (visit == InVisit)
+        {
+            out << ".";
+
+            TIntermAggregate *swizzle = node->getRight()->getAsAggregate();
+
+            if (swizzle)
+            {
+                TIntermSequence &sequence = swizzle->getSequence();
+
+                for (TIntermSequence::iterator sit = sequence.begin(); sit != sequence.end(); sit++)
+                {
+                    TIntermConstantUnion *element = (*sit)->getAsConstantUnion();
+
+                    if (element)
+                    {
+                        int i = element->getUnionArrayPointer()[0].getIConst();
+
+                        switch (i)
+                        {
+                        case 0: out << "x"; break;
+                        case 1: out << "y"; break;
+                        case 2: out << "z"; break;
+                        case 3: out << "w"; break;
+                        default: UNREACHABLE();
+                        }
+                    }
+                    else UNREACHABLE();
+                }
+            }
+            else UNREACHABLE();
+
+            return false;   // Fully processed
+        }
+        break;
+      case EOpAdd:               outputTriplet(visit, "(", " + ", ")"); break;
+      case EOpSub:               outputTriplet(visit, "(", " - ", ")"); break;
+      case EOpMul:               outputTriplet(visit, "(", " * ", ")"); break;
+      case EOpDiv:               outputTriplet(visit, "(", " / ", ")"); break;
+      case EOpMod:               UNIMPLEMENTED(); /* FIXME */ out << "mod";                     break;
+      case EOpRightShift:        UNIMPLEMENTED(); /* FIXME */ out << "right-shift";  break;
+      case EOpLeftShift:         UNIMPLEMENTED(); /* FIXME */ out << "left-shift";   break;
+      case EOpAnd:               UNIMPLEMENTED(); /* FIXME */ out << "bitwise and";  break;
+      case EOpInclusiveOr:       UNIMPLEMENTED(); /* FIXME */ out << "inclusive-or"; break;
+      case EOpExclusiveOr:       UNIMPLEMENTED(); /* FIXME */ out << "exclusive-or"; break;
+      case EOpEqual:             outputTriplet(visit, "(", " == ", ")");  break;
+      case EOpNotEqual:          outputTriplet(visit, "(", " != ", ")");  break;
+      case EOpLessThan:          outputTriplet(visit, "(", " < ", ")");   break;
+      case EOpGreaterThan:       outputTriplet(visit, "(", " > ", ")");   break;
+      case EOpLessThanEqual:     outputTriplet(visit, "(", " <= ", ")");  break;
+      case EOpGreaterThanEqual:  outputTriplet(visit, "(", " >= ", ")");  break;
+      case EOpVectorTimesScalar: outputTriplet(visit, "(", " * ", ")");   break;
+      case EOpVectorTimesMatrix: UNIMPLEMENTED(); /* FIXME */ out << "vector-times-matrix";   break;
+      case EOpMatrixTimesVector: outputTriplet(visit, "mul(", ", ", ")"); break;
+      case EOpMatrixTimesScalar: UNIMPLEMENTED(); /* FIXME */ out << "matrix-scale";          break;
+      case EOpMatrixTimesMatrix: UNIMPLEMENTED(); /* FIXME */ out << "matrix-multiply";       break;
+      case EOpLogicalOr:         outputTriplet(visit, "(", " || ", ")");  break;
+      case EOpLogicalXor:        outputTriplet(visit, "xor(", ", ", ")"); break;   // FIXME: Prevent name clashes
+      case EOpLogicalAnd:        outputTriplet(visit, "(", " && ", ")");  break;
+      default: UNREACHABLE();
+    }
+
+    return true;
+}
+
+bool OutputHLSL::visitUnary(Visit visit, TIntermUnary *node)
+{
+    TInfoSinkBase &out = context.infoSink.obj;
+
+    switch (node->getOp())
+    {
+      case EOpNegative:         outputTriplet(visit, "(-", NULL, ")");  break;
+      case EOpVectorLogicalNot: outputTriplet(visit, "(!", NULL, ")");  break;
+      case EOpLogicalNot:       outputTriplet(visit, "(!", NULL, ")");  break;
+      case EOpBitwiseNot:       outputTriplet(visit, "(~", NULL, ")");  break;
+      case EOpPostIncrement:    outputTriplet(visit, "(", NULL, "++)"); break;
+      case EOpPostDecrement:    outputTriplet(visit, "(", NULL, "--)"); break;
+      case EOpPreIncrement:     outputTriplet(visit, "(++", NULL, ")"); break;
+      case EOpPreDecrement:     outputTriplet(visit, "(--", NULL, ")"); break;
+      case EOpConvIntToBool:
+      case EOpConvFloatToBool:
+        switch (node->getOperand()->getType().getNominalSize())
+        {
+          case 1:    outputTriplet(visit, "bool(", NULL, ")");  break;
+          case 2:    outputTriplet(visit, "bool2(", NULL, ")"); break;
+          case 3:    outputTriplet(visit, "bool3(", NULL, ")"); break;
+          case 4:    outputTriplet(visit, "bool4(", NULL, ")"); break;
+          default: UNREACHABLE();
+        }
+        break;
+      case EOpConvBoolToFloat:
+      case EOpConvIntToFloat:
+        switch (node->getOperand()->getType().getNominalSize())
+        {
+          case 1:    outputTriplet(visit, "float(", NULL, ")");  break;
+          case 2:    outputTriplet(visit, "float2(", NULL, ")"); break;
+          case 3:    outputTriplet(visit, "float3(", NULL, ")"); break;
+          case 4:    outputTriplet(visit, "float4(", NULL, ")"); break;
+          default: UNREACHABLE();
+        }
+        break;
+      case EOpConvFloatToInt:
+      case EOpConvBoolToInt:
+        switch (node->getOperand()->getType().getNominalSize())
+        {
+          case 1:    outputTriplet(visit, "int(", NULL, ")");  break;
+          case 2:    outputTriplet(visit, "int2(", NULL, ")"); break;
+          case 3:    outputTriplet(visit, "int3(", NULL, ")"); break;
+          case 4:    outputTriplet(visit, "int4(", NULL, ")"); break;
+          default: UNREACHABLE();
+        }
+        break;
+      case EOpRadians:          outputTriplet(visit, "radians(", NULL, ")");   break;
+      case EOpDegrees:          outputTriplet(visit, "degrees(", NULL, ")");   break;
+      case EOpSin:              outputTriplet(visit, "sin(", NULL, ")");       break;
+      case EOpCos:              outputTriplet(visit, "cos(", NULL, ")");       break;
+      case EOpTan:              outputTriplet(visit, "tan(", NULL, ")");       break;
+      case EOpAsin:             outputTriplet(visit, "asin(", NULL, ")");      break;
+      case EOpAcos:             outputTriplet(visit, "acos(", NULL, ")");      break;
+      case EOpAtan:             outputTriplet(visit, "atan(", NULL, ")");      break;
+      case EOpExp:              outputTriplet(visit, "exp(", NULL, ")");       break;
+      case EOpLog:              outputTriplet(visit, "log(", NULL, ")");       break;
+      case EOpExp2:             outputTriplet(visit, "exp2(", NULL, ")");      break;
+      case EOpLog2:             outputTriplet(visit, "log2(", NULL, ")");      break;
+      case EOpSqrt:             outputTriplet(visit, "sqrt(", NULL, ")");      break;
+      case EOpInverseSqrt:      outputTriplet(visit, "rsqrt(", NULL, ")");     break;
+      case EOpAbs:              outputTriplet(visit, "abs(", NULL, ")");       break;
+      case EOpSign:             outputTriplet(visit, "sign(", NULL, ")");      break;
+      case EOpFloor:            outputTriplet(visit, "floor(", NULL, ")");     break;
+      case EOpCeil:             outputTriplet(visit, "ceil(", NULL, ")");      break;
+      case EOpFract:            outputTriplet(visit, "frac(", NULL, ")");      break;
+      case EOpLength:           outputTriplet(visit, "length(", NULL, ")");    break;
+      case EOpNormalize:        outputTriplet(visit, "normalize(", NULL, ")"); break;
+//      case EOpDPdx:             outputTriplet(visit, "ddx(", NULL, ")");       break;
+//      case EOpDPdy:             outputTriplet(visit, "ddy(", NULL, ")");       break;
+//      case EOpFwidth:           outputTriplet(visit, "fwidth(", NULL, ")");    break;        
+      case EOpAny:              outputTriplet(visit, "any(", NULL, ")");       break;
+      case EOpAll:              outputTriplet(visit, "all(", NULL, ")");       break;
+      default: UNREACHABLE();
+    }
+
+    return true;
+}
+
+bool OutputHLSL::visitAggregate(Visit visit, TIntermAggregate *node)
+{
+    EShLanguage language = context.language;
+    TInfoSinkBase &out = context.infoSink.obj;
+
+    if (node->getOp() == EOpNull)
+    {
+        out.message(EPrefixError, "node is still EOpNull!");
+        return true;
+    }
+
+    switch (node->getOp())
+    {
+      case EOpSequence: outputTriplet(visit, NULL, ";\n", ";\n"); break;
+      case EOpDeclaration:
+        if (visit == PreVisit)
+        {
+            TIntermSequence &sequence = node->getSequence();
+            TIntermTyped *variable = sequence[0]->getAsTyped();
+            bool visit = true;
+
+            if (variable && variable->getQualifier() == EvqTemporary)
+            {
+                out << typeString(variable->getType()) + " ";
+
+                for (TIntermSequence::iterator sit = sequence.begin(); sit != sequence.end(); sit++)
+                {
+                    TIntermSymbol *symbol = (*sit)->getAsSymbolNode();
+
+                    if (symbol)
+                    {
+                        symbol->traverse(this);
+
+                        out << arrayString(symbol->getType());
+                    }
+                    else
+                    {
+                        (*sit)->traverse(this);
+                    }
+
+                    if (visit && this->inVisit)
+                    {
+                        if (*sit != sequence.back())
+                        {
+                            visit = this->visitAggregate(InVisit, node);
+                        }
+                    }
+                }
+
+                if (visit && this->postVisit)
+                {
+                    this->visitAggregate(PostVisit, node);
+                }
+            }
+            
+            return false;
+        }
+        else if (visit == InVisit)
+        {
+            out << ", ";
+        }
+        break;
+      case EOpComma:         UNIMPLEMENTED(); /* FIXME */ out << "Comma\n"; return true;
+      case EOpFunction:
+        {
+            const TString &mangledName = node->getName();
+            TString name = TString(mangledName.c_str(), mangledName.find_first_of('('));
+
+            if (visit == PreVisit)
+            {
+                if (name == "main")
+                {
+                    TSymbolTableLevel *symbols = context.symbolTable.getGlobalLevel();
+
+                    if (language == EShLangFragment)
+                    {
+                        out << "PS_OUTPUT main(PS_INPUT input)\n"   // FIXME: Prevent name clashes
+                               "{\n";
+
+                        for (TSymbolTableLevel::const_iterator namedSymbol = symbols->begin(); namedSymbol != symbols->end(); namedSymbol++)
+                        {
+                            const TSymbol *symbol = (*namedSymbol).second;
+                            const TString &name = symbol->getName();
+
+                            if (symbol->isVariable())
+                            {
+                                const TVariable *variable = static_cast<const TVariable*>(symbol);
+                                const TType &type = variable->getType();
+                                TQualifier qualifier = type.getQualifier();
+
+                                if(qualifier == EvqVaryingIn)
+                                {
+                                    out << "    " + name + " = input." + name + ";\n";   // FIXME: Prevent name clashes
+                                }
+                            }
+                        }
+                    }
+                    else
+                    {
+                        out << "VS_OUTPUT main(VS_INPUT input)\n"   // FIXME: Prevent name clashes
+                               "{\n";
+
+                        for (TSymbolTableLevel::const_iterator namedSymbol = symbols->begin(); namedSymbol != symbols->end(); namedSymbol++)
+                        {
+                            const TSymbol *symbol = (*namedSymbol).second;
+                            const TString &name = symbol->getName();
+
+                            if (symbol->isVariable())
+                            {
+                                const TVariable *variable = static_cast<const TVariable*>(symbol);
+                                const TType &type = variable->getType();
+                                TQualifier qualifier = type.getQualifier();
+
+                                if (qualifier == EvqAttribute)
+                                {
+                                    out << "    " + name + " = input." + name + ";\n";   // FIXME: Prevent name clashes
+                                }
+                            }
+                        }
+                    }
+
+                    // Erase the (empty) argument list
+                    TIntermSequence &sequence = node->getSequence();
+                    sequence.erase(sequence.begin());
+                }
+                else
+                {
+                    out << typeString(node->getType()) << " " << name << "(";
+
+                    TIntermSequence &sequence = node->getSequence();
+                    TIntermSequence &arguments = sequence[0]->getAsAggregate()->getSequence();
+
+                    for (unsigned int i = 0; i < arguments.size(); i++)
+                    {
+                        TIntermSymbol *symbol = arguments[i]->getAsSymbolNode();
+
+                        if (symbol)
+                        {
+                            const TType &type = symbol->getType();
+                            const TString &name = symbol->getSymbol();
+
+                            out << typeString(type) + " " + name;
+
+                            if(i < arguments.size() - 1)
+                            {
+                                out << ", ";
+                            }
+                        }
+                        else UNREACHABLE();
+                    }
+
+                    sequence.erase(sequence.begin());
+
+                    out << ")\n"
+                           "{\n";
+                }
+            }
+            else if (visit == PostVisit)
+            {
+                if (name == "main")
+                {
+                    if (language == EShLangFragment)
+                    {
+                        out << "    PS_OUTPUT output;\n"                    // FIXME: Prevent name clashes
+                               "    output.gl_Color[0] = gl_Color[0];\n";   // FIXME: Prevent name clashes
+
+                        TSymbolTableLevel *symbols = context.symbolTable.getGlobalLevel();
+
+                        for (TSymbolTableLevel::const_iterator namedSymbol = symbols->begin(); namedSymbol != symbols->end(); namedSymbol++)
+                        {
+                            const TSymbol *symbol = (*namedSymbol).second;
+                            const TString &name = symbol->getName();
+                        }
+                    }
+                    else
+                    {
+                        out << "    VS_OUTPUT output;\n"   // FIXME: Prevent name clashes
+                               "    output.gl_Position.x = gl_Position.x - gl_HalfPixelSize.x * gl_Position.w;\n"
+                               "    output.gl_Position.y = -(gl_Position.y - gl_HalfPixelSize.y * gl_Position.w);\n"
+                               "    output.gl_Position.z = (gl_Position.z + gl_Position.w) * 0.5;\n"
+                               "    output.gl_Position.w = gl_Position.w;\n"
+                               "    output.gl_PointSize = gl_PointSize;\n";
+
+                        TSymbolTableLevel *symbols = context.symbolTable.getGlobalLevel();
+
+                        for (TSymbolTableLevel::const_iterator namedSymbol = symbols->begin(); namedSymbol != symbols->end(); namedSymbol++)
+                        {
+                            const TSymbol *symbol = (*namedSymbol).second;
+                            const TString &name = symbol->getName();
+
+                            if (symbol->isVariable())
+                            {
+                                const TVariable *variable = static_cast<const TVariable*>(symbol);
+                                TQualifier qualifier = variable->getType().getQualifier();
+
+                                if(qualifier == EvqVaryingOut || qualifier == EvqInvariantVaryingOut)
+                                {
+                                    out << "    output." + name + " = " + name + ";\n";   // FIXME: Prevent name clashes
+                                }
+                            }
+                        }
+                    }
+
+                    out << "    return output;\n"   // FIXME: Prevent name clashes
+                           "}\n";
+                }
+                else
+                {
+                    out << "}\n";
+                }
+            }
+        }
+        break;
+      case EOpFunctionCall:
+        {
+            if (visit == PreVisit)
+            {
+                const TString &mangledName = node->getName();
+                TString name = TString(mangledName.c_str(), mangledName.find_first_of('('));
+
+                if (node->isUserDefined())
+                {
+                    out << name << "(";
+                }
+                else
+                {
+                    if (name == "texture2D")
+                    {
+                        if (node->getSequence().size() == 2)
+                        {
+                            out << "gl_texture2D(";
+                        }
+                        else if (node->getSequence().size() == 3)
+                        {
+                            out << "gl_texture2DBias(";
+                        }
+                        else UNREACHABLE();
+                    }
+                    else if (name == "texture2DProj")
+                    {
+                        out << "gl_texture2DProj(";
+                    }
+                    else if (name == "texture2DLod")
+                    {
+                        out << "gl_texture2DLod(";
+                        UNIMPLEMENTED();   // FIXME: Move lod to last texture coordinate component
+                    }
+                    else if (name == "texture2DProjLod")
+                    {
+                        out << "gl_texture2DProjLod(";
+                        UNIMPLEMENTED();   // FIXME: Move lod to last texture coordinate component
+                    }
+                    else if (name == "textureCube")
+                    {
+                        out << "gl_textureCube(";   // FIXME: Incorrect sampling location
+                    }
+                    else
+                    {
+                        UNIMPLEMENTED();   // FIXME
+                    }
+                }
+            }
+            else if (visit == InVisit)
+            {
+                out << ", ";
+            }
+            else
+            {
+                out << ")";
+            }
+        }
+        break;
+      case EOpParameters:       outputTriplet(visit, "(", ", ", ")\n{\n");  break;
+      case EOpConstructFloat:   outputTriplet(visit, "vec1(", NULL, ")");   break;
+      case EOpConstructVec2:    outputTriplet(visit, "vec2(", ", ", ")");   break;
+      case EOpConstructVec3:    outputTriplet(visit, "vec3(", ", ", ")");   break;
+      case EOpConstructVec4:    outputTriplet(visit, "vec4(", ", ", ")");   break;
+      case EOpConstructBool:    UNIMPLEMENTED(); /* FIXME */ out << "Construct bool";  break;
+      case EOpConstructBVec2:   UNIMPLEMENTED(); /* FIXME */ out << "Construct bvec2"; break;
+      case EOpConstructBVec3:   UNIMPLEMENTED(); /* FIXME */ out << "Construct bvec3"; break;
+      case EOpConstructBVec4:   UNIMPLEMENTED(); /* FIXME */ out << "Construct bvec4"; break;
+      case EOpConstructInt:     UNIMPLEMENTED(); /* FIXME */ out << "Construct int";   break;
+      case EOpConstructIVec2:   UNIMPLEMENTED(); /* FIXME */ out << "Construct ivec2"; break;
+      case EOpConstructIVec3:   UNIMPLEMENTED(); /* FIXME */ out << "Construct ivec3"; break;
+      case EOpConstructIVec4:   UNIMPLEMENTED(); /* FIXME */ out << "Construct ivec4"; break;
+      case EOpConstructMat2:    outputTriplet(visit, "float2x2(", ", ", ")"); break;
+      case EOpConstructMat3:    outputTriplet(visit, "float3x3(", ", ", ")"); break;
+      case EOpConstructMat4:    UNIMPLEMENTED(); /* FIXME */ out << "Construct mat4";  break;
+      case EOpConstructStruct:  UNIMPLEMENTED(); /* FIXME */ out << "Construct structure";  break;
+      case EOpLessThan:         outputTriplet(visit, "(", " < ", ")");             break;
+      case EOpGreaterThan:      outputTriplet(visit, "(", " > ", ")");             break;
+      case EOpLessThanEqual:    outputTriplet(visit, "(", " <= ", ")");            break;
+      case EOpGreaterThanEqual: outputTriplet(visit, "(", " >= ", ")");            break;
+      case EOpVectorEqual:      outputTriplet(visit, "(", " == ", ")");            break;
+      case EOpVectorNotEqual:   outputTriplet(visit, "(", " != ", ")");            break;
+      case EOpMod:              outputTriplet(visit, "mod(", ", ", ")");           break;   // FIXME: Prevent name clashes
+      case EOpPow:              outputTriplet(visit, "pow(", ", ", ")");           break;
+      case EOpAtan:
+        if (node->getSequence().size() == 1)
+        {
+            outputTriplet(visit, "atan(", ", ", ")");
+        }
+        else if (node->getSequence().size() == 2)
+        {
+            outputTriplet(visit, "atan2(", ", ", ")");
+        }
+        else UNREACHABLE();
+        break;
+      case EOpMin:           outputTriplet(visit, "min(", ", ", ")");           break;
+      case EOpMax:           outputTriplet(visit, "max(", ", ", ")");           break;
+      case EOpClamp:         outputTriplet(visit, "clamp(", ", ", ")");         break;
+      case EOpMix:           outputTriplet(visit, "lerp(", ", ", ")");          break;
+      case EOpStep:          outputTriplet(visit, "step(", ", ", ")");          break;
+      case EOpSmoothStep:    outputTriplet(visit, "smoothstep(", ", ", ")");    break;
+      case EOpDistance:      outputTriplet(visit, "distance(", ", ", ")");      break;
+      case EOpDot:           outputTriplet(visit, "dot(", ", ", ")");           break;
+      case EOpCross:         outputTriplet(visit, "cross(", ", ", ")");         break;
+      case EOpFaceForward:   UNIMPLEMENTED(); /* FIXME */ out << "face-forward";            break;
+      case EOpReflect:       outputTriplet(visit, "reflect(", ", ", ")");       break;
+      case EOpRefract:       outputTriplet(visit, "refract(", ", ", ")");       break;
+      case EOpMul:           outputTriplet(visit, "(", " * ", ")");             break;
+      case EOpItof:          UNIMPLEMENTED(); /* FIXME */ out << "itof";        break;
+      case EOpFtoi:          UNIMPLEMENTED(); /* FIXME */ out << "ftoi";        break;
+      case EOpSkipPixels:    UNIMPLEMENTED(); /* FIXME */ out << "skipPixels";  break;
+      case EOpReadInput:     UNIMPLEMENTED(); /* FIXME */ out << "readInput";   break;
+      case EOpWritePixel:    UNIMPLEMENTED(); /* FIXME */ out << "writePixel";  break;
+      case EOpBitmapLsb:     UNIMPLEMENTED(); /* FIXME */ out << "bitmapLSB";   break;
+      case EOpBitmapMsb:     UNIMPLEMENTED(); /* FIXME */ out << "bitmapMSB";   break;
+      case EOpWriteOutput:   UNIMPLEMENTED(); /* FIXME */ out << "writeOutput"; break;
+      case EOpReadPixel:     UNIMPLEMENTED(); /* FIXME */ out << "readPixel";   break;
+      default: UNREACHABLE();
+    }
+
+    return true;
+}
+
+bool OutputHLSL::visitSelection(Visit visit, TIntermSelection *node)
+{
+    TInfoSinkBase &out = context.infoSink.obj;
+
+    out << "if(";
+
+    node->getCondition()->traverse(this);
+
+    out << ")\n"
+           "{\n";
+
+    node->getTrueBlock()->traverse(this);
+
+    out << ";}\n";
+
+    if (node->getFalseBlock())
+    {
+        out << "else\n"
+               "{\n";
+
+        node->getFalseBlock()->traverse(this);
+
+        out << ";}\n";
+    }
+
+    return false;
+}
+
+void OutputHLSL::visitConstantUnion(TIntermConstantUnion *node)
+{
+    TInfoSinkBase &out = context.infoSink.obj;
+    
+    int size = node->getType().getObjectSize();
+    bool matrix = node->getType().isMatrix();
+    TBasicType type = node->getUnionArrayPointer()[0].getType();
+
+    switch (type)
+    {
+      case EbtBool:
+        if (!matrix)
+        {
+            switch (size)
+            {
+              case 1: out << "bool(";  break;
+              case 2: out << "bool2("; break;
+              case 3: out << "bool3("; break;
+              case 4: out << "bool4("; break;
+              default: UNREACHABLE();
+            }
+        }
+        else
+        {
+            UNIMPLEMENTED();
+        }
+        break;
+      case EbtFloat:
+        if (!matrix)
+        {
+            switch (size)
+            {
+              case 1: out << "float(";  break;
+              case 2: out << "float2("; break;
+              case 3: out << "float3("; break;
+              case 4: out << "float4("; break;
+              default: UNREACHABLE();
+            }
+        }
+        else
+        {
+            switch (size)
+            {
+              case 4:  out << "float2x2("; break;
+              case 9:  out << "float3x3("; break;
+              case 16: out << "float4x4("; break;
+              default: UNREACHABLE();
+            }
+        }
+        break;
+      case EbtInt:
+        if (!matrix)
+        {
+            switch (size)
+            {
+              case 1: out << "int(";  break;
+              case 2: out << "int2("; break;
+              case 3: out << "int3("; break;
+              case 4: out << "int4("; break;
+              default: UNREACHABLE();
+            }
+        }
+        else
+        {
+            UNIMPLEMENTED();
+        }
+        break;
+      default:
+        UNIMPLEMENTED();   // FIXME
+    }
+
+    for (int i = 0; i < size; i++)
+    {
+        switch (type)
+        {
+          case EbtBool:
+            if (node->getUnionArrayPointer()[i].getBConst())
+            {
+                out << "true";
+            }
+            else
+            {
+                out << "false";
+            }
+            break;
+          case EbtFloat:
+            out << node->getUnionArrayPointer()[i].getFConst();           
+            break;
+          case EbtInt:
+            out << node->getUnionArrayPointer()[i].getIConst();
+            break;
+          default: 
+            UNIMPLEMENTED();   // FIXME
+        }
+
+        if (i != size - 1)
+        {
+            out << ", ";
+        }
+    }
+
+    out << ")";
+}
+
+bool OutputHLSL::visitLoop(Visit visit, TIntermLoop *node)
+{
+    TInfoSinkBase &out = context.infoSink.obj;
+
+    if (!node->testFirst())
+    {
+        out << "do\n"
+               "{\n";
+    }
+    else
+    {
+        out << "for(";
+        
+        if (node->getInit())
+        {
+            node->getInit()->traverse(this);
+        }
+
+        out << "; ";
+
+        if (node->getTest())
+        {
+            node->getTest()->traverse(this);
+        }
+
+        out << "; ";
+
+        if (node->getTerminal())
+        {
+            node->getTerminal()->traverse(this);
+        }
+
+        out << ")\n"
+               "{\n";
+    }
+
+    if (node->getBody())
+    {
+        node->getBody()->traverse(this);
+    }
+
+    out << "}\n";
+
+    if (!node->testFirst())
+    {
+        out << "while(\n";
+
+        node->getTest()->traverse(this);
+
+        out << ")";
+    }
+
+    out << ";\n";
+
+    return false;
+}
+
+bool OutputHLSL::visitBranch(Visit visit, TIntermBranch *node)
+{
+    TInfoSinkBase &out = context.infoSink.obj;
+
+    switch (node->getFlowOp())
+    {
+      case EOpKill:      outputTriplet(visit, "discard", NULL, NULL); break;
+      case EOpBreak:     UNIMPLEMENTED(); /* FIXME */          break;
+      case EOpContinue:  UNIMPLEMENTED(); /* FIXME */       break;
+      case EOpReturn:
+        if (visit == PreVisit)
+        {
+            if (node->getExpression())
+            {
+                out << "return ";
+            }
+            else
+            {
+                out << "return;\n";
+            }
+        }
+        else if (visit == PostVisit)
+        {
+            out << ";\n";
+        }
+        break;
+      default: UNREACHABLE();
+    }
+
+    return true;
+}
+
+void OutputHLSL::outputTriplet(Visit visit, const char *preString, const char *inString, const char *postString)
+{
+    TInfoSinkBase &out = context.infoSink.obj;
+
+    if (visit == PreVisit && preString)
+    {
+        out << preString;
+    }
+    else if (visit == InVisit && inString)
+    {
+        out << inString;
+    }
+    else if (visit == PostVisit && postString)
+    {
+        out << postString;
+    }
+}
+
+TString OutputHLSL::typeString(const TType &type)
+{
+    if (type.isMatrix())
+    {
+        switch (type.getNominalSize())
+        {
+          case 2: return "float2x2";
+          case 3: return "float3x3";
+          case 4: return "float4x4";
+        }
+    }
+    else
+    {
+        switch (type.getBasicType())
+        {
+          case EbtFloat:
+            switch (type.getNominalSize())
+            {
+              case 1: return "float";
+              case 2: return "float2";
+              case 3: return "float3";
+              case 4: return "float4";
+            }
+          case EbtInt:
+            switch (type.getNominalSize())
+            {
+              case 1: return "int";
+              case 2: return "int2";
+              case 3: return "int3";
+              case 4: return "int4";
+            }
+          case EbtBool:
+            switch (type.getNominalSize())
+            {
+              case 1: return "bool";
+              case 2: return "bool2";
+              case 3: return "bool3";
+              case 4: return "bool4";
+            }
+          case EbtVoid:
+            return "void";
+          case EbtSampler2D:
+            return "sampler2D";
+          case EbtSamplerCube:
+            return "samplerCUBE";
+        }
+    }
+
+    UNIMPLEMENTED();   // FIXME
+    return "<unknown type>";
+}
+
+TString OutputHLSL::arrayString(const TType &type)
+{
+    if (!type.isArray())
+    {
+        return "";
+    }
+
+    char buffer[100];
+    sprintf(buffer, "[%d]", type.getArraySize());
+
+    return buffer;
+}
+
+TString OutputHLSL::initializer(const TType &type)
+{
+    TString string;
+
+    int arraySize = type.isArray() ? type.getArraySize() : 1;
+
+    if (type.isArray())
+    {
+        string += "{";
+    }
+
+    for (int element = 0; element < arraySize; element++)
+    {
+        string += typeString(type) + "(";
+
+        for (int component = 0; component < type.getNominalSize(); component++)
+        {
+            string += "0";
+
+            if (component < type.getNominalSize() - 1)
+            {
+                string += ", ";
+            }
+        }
+
+        string += ")";
+
+        if (element < arraySize - 1)
+        {
+            string += ", ";
+        }
+    }
+
+    if (type.isArray())
+    {
+        string += "}";
+    }
+
+    return string;
+}
+}
diff --git a/Compiler/OutputHLSL.h b/Compiler/OutputHLSL.h
new file mode 100644
index 0000000..a54e006
--- /dev/null
+++ b/Compiler/OutputHLSL.h
@@ -0,0 +1,42 @@
+//
+// 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_OUTPUTHLSL_H_
+#define COMPILER_OUTPUTHLSL_H_
+
+#include "intermediate.h"
+#include "ParseHelper.h"
+
+namespace sh
+{
+class OutputHLSL : public TIntermTraverser
+{
+  public:
+    OutputHLSL(TParseContext &context);
+
+    void header();
+
+  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*);
+
+    void outputTriplet(Visit visit, const char *preString, const char *inString, const char *postString);
+
+    static TString typeString(const TType &type);
+    static TString arrayString(const TType &type);
+    static TString initializer(const TType &type);
+
+    TParseContext &context;
+};
+}
+
+#endif   // COMPILER_OUTPUTHLSL_H_
diff --git a/Compiler/ParseHelper.cpp b/Compiler/ParseHelper.cpp
new file mode 100644
index 0000000..4062a56
--- /dev/null
+++ b/Compiler/ParseHelper.cpp
@@ -0,0 +1,1436 @@
+//
+// 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 "ParseHelper.h"
+#include "InitializeParseContext.h"
+#include "osinclude.h"
+#include <stdarg.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()
+{
+	recoveredFromError = true;
+}
+
+//
+// Used by flex/bison to output all syntax and parsing errors.
+//
+void C_DECL TParseContext::error(TSourceLoc nLine, const char *szReason, const char *szToken, 
+								 const char *szExtraInfoFormat, ...)
+{
+	char szExtraInfo[400];
+	va_list marker;
+	
+	va_start(marker, szExtraInfoFormat);
+	
+	_vsnprintf(szExtraInfo, sizeof(szExtraInfo), szExtraInfoFormat, marker);
+	
+	/* VC++ format: file(linenum) : error #: 'token' : extrainfo */
+	infoSink.info.prefix(EPrefixError);
+	infoSink.info.location(nLine);
+	infoSink.info << "'" << szToken <<  "' : " << szReason << " " << szExtraInfo << "\n";
+	
+	va_end(marker);
+
+	++numErrors;
+}
+
+//
+// Same error message for all places assignments don't work.
+//
+void TParseContext::assignError(int line, const char* op, TString left, TString right)
+{
+	error(line, "", op, "cannot convert from '%s' to '%s'",
+		  right.c_str(), left.c_str());
+}
+
+//
+// Same error message for all places unary operations don't work.
+//
+void TParseContext::unaryOpError(int line, const char* op, TString operand)
+{
+   error(line, " wrong operand type", op, 
+		  "no operation '%s' exists that takes an operand of type %s (or there is no acceptable conversion)",
+		  op, operand.c_str());
+}
+
+//
+// Same error message for all binary operations don't work.
+//
+void TParseContext::binaryOpError(int line, const char* op, TString left, TString right)
+{
+	error(line, " wrong operand types ", op, 
+			"no operation '%s' exists that takes a left-hand operand of type '%s' and "
+			"a right operand of type '%s' (or there is no acceptable conversion)", 
+			op, left.c_str(), right.c_str());
+}
+
+//
+// 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)
+		error(line, " l-value required", op, "\"%s\" (%s)", symbol, message);
+	else
+		error(line, " l-value required", op, "(%s)", message);
+
+	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.
+//
+// Returns true if there was an error.
+//
+bool TParseContext::reservedErrorCheck(int line, const TString& identifier)
+{
+	if (!symbolTable.atBuiltInLevel()) {
+		if (identifier.substr(0, 3) == TString("gl_")) {
+			error(line, "reserved built-in name", "gl_", "");
+			return true;
+		}
+		if (identifier.find("__") != TString::npos) {
+			//error(line, "Two consecutive underscores are reserved for future use.", identifier.c_str(), "", "");
+			//return true;
+			infoSink.info.message(EPrefixWarning, "Two consecutive underscores are reserved for future use.", line);
+			return false;
+		}
+	}
+
+	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) {
+		size += function[i].type->getObjectSize();
+		
+		if (constructingMatrix && function[i].type->isMatrix())
+			matrixInMatrix = true;
+		if (full)
+			overFull = true;
+		if (op != EOpConstructStruct && !type->isArray() && size >= type->getObjectSize())
+			full = true;
+		if (function[i].type->getQualifier() != EvqConst)
+			constType = false;
+		if (function[i].type->isArray())
+			arrayArg = true;
+	}
+	
+	if (constType)
+		type->changeQualifier(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()) {
+		error(line, "constructing matrix from matrix", "constructor", "(reserved)");
+		return true;
+	}
+
+	if (overFull) {
+		error(line, "too many arguments", "constructor", "");
+		return true;
+	}
+	
+	if (op == EOpConstructStruct && !type->isArray() && type->getStruct()->size() != function.getParamCount()) {
+		error(line, "Number of constructor parameters does not match the number of structure fields", "constructor", "");
+		return true;
+	}
+
+	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->getAsTyped();
+	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, TType::getBasicString(pType.type), "(structure contains a sampler)");
+		
+			return true;
+		}
+		
+		return false;
+	} else if (IsSampler(pType.type)) {
+		error(line, reason, TType::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) {
+		error(line, "cannot declare arrays of this qualifier", TType(type).getCompleteString().c_str(), "");
+		return true;
+	}
+
+	if (type.qualifier == EvqConst && extensionErrorCheck(line, "GL_3DL_array_objects"))
+		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);
+		if (fragData == 0) {
+			infoSink.info.message(EPrefixInternalError, "gl_MaxDrawBuffers not defined", line);
+			return true;
+		}
+
+		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)
+{
+	//
+	// Make the qualifier make sense.
+	//
+	if (type.qualifier == EvqConst) {
+		type.qualifier = EvqTemporary;
+		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)
+{
+	if (reservedErrorCheck(line, identifier))
+		recover();
+
+	TVariable* variable = new TVariable(&identifier, TType(type));
+
+	if (! symbolTable.insert(*variable)) {
+		error(line, "redefinition", variable->getName().c_str(), "");
+		delete variable;
+		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->changeQualifier(EvqConstReadOnly);
+	else
+		type->changeQualifier(paramQualifier);
+
+	return false;
+}
+
+bool TParseContext::extensionErrorCheck(int line, const char* extension)
+{       
+	if (extensionBehavior[extension] == EBhWarn) {
+		infoSink.info.message(EPrefixWarning, ("extension " + TString(extension) + " is being used").c_str(), line);
+		return false;
+	}
+	if (extensionBehavior[extension] == EBhDisable) {
+		error(line, "extension", extension, "is disabled");
+		return true;
+	}
+
+	return false;
+}
+
+/////////////////////////////////////////////////////////////////////////////////
+//
+// 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)
+{
+	const TSymbol* 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;
+	}
+	
+	const TFunction* function = static_cast<const TFunction*>(symbol);
+	
+	return function;
+}
+
+//
+// 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()) {
+			error(line, " assigning non-constant to", "=", "'%s'", variable->getType().getCompleteString().c_str());
+			variable->getType().changeQualifier(EvqTemporary);
+			return true;
+		}
+		if (type != initializer->getType()) {
+			error(line, " non-matching types for const initializer ", 
+				variable->getType().getQualifierString(), "");
+			variable->getType().changeQualifier(EvqTemporary);
+			return true;
+		}
+		if (initializer->getAsConstantUnion()) { 
+			constUnion* 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);
+
+			constUnion* constArray = tVar->getConstPointer();
+			variable->shareConstPointer(constArray);
+		} else {
+			error(line, " cannot assign to", "=", "'%s'", variable->getType().getCompleteString().c_str());
+			variable->getType().changeQualifier(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)
+{
+	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
+	if (aggrNode) {
+		TIntermSequence &childSequenceVector = aggrNode->getSequence() ;
+		for (TIntermSequence::iterator p = childSequenceVector.begin(); 
+									p != childSequenceVector.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::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;
+		constUnion* unionArray = new constUnion[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 {
+		error(line, "", "constructor", "cannot convert parameter %d from '%s' to '%s'", paramCount,
+				node->getAsTyped()->getType().getBasicString(), type->getBasicString());
+		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();
+
+	constUnion *unionArray;
+	if (tempConstantNode) {
+		unionArray = tempConstantNode->getUnionArrayPointer();
+
+		if (!unionArray) {  // this error message should never be raised
+			infoSink.info.message(EPrefixInternalError, "constUnion not initialized in addConstVectorNode function", line);
+			recover();
+
+			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;
+	}
+
+	constUnion* constArray = new constUnion[fields.num];
+
+	for (int i = 0; i < fields.num; i++) {
+		if (fields.offsets[i] >= node->getType().getObjectSize()) {
+			error(line, "", "[", "vector field selection out of range '%d'", fields.offsets[i]);
+			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()) {
+		error(line, "", "[", "matrix field selection out of range '%d'", index);
+		recover();
+		index = 0;
+	}
+
+	if (tempConstantNode) {
+		 constUnion* 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()) {
+		error(line, "", "[", "array field selection out of range '%d'", index);
+		recover();
+		index = 0;
+	}
+
+	int arrayElementSize = arrayElementType.getObjectSize();
+
+	if (tempConstantNode) {
+		 constUnion* 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)
+{
+	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) {
+		 constUnion* 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;
+}
+
+//
+// Initialize all supported extensions to disable
+//
+void TParseContext::initializeExtensionBehavior()
+{
+	//
+	// example code: extensionBehavior["test"] = EBhDisable; // where "test" is the name of 
+	// supported extension
+	//
+	extensionBehavior["GL_ARB_texture_rectangle"] = EBhRequire;
+	extensionBehavior["GL_3DL_array_objects"] = EBhDisable;
+}
+
+OS_TLSIndex GlobalParseContextIndex = OS_INVALID_TLS_INDEX;
+
+bool InitializeParseContextIndex()
+{
+	if (GlobalParseContextIndex != OS_INVALID_TLS_INDEX) {
+		assert(0 && "InitializeParseContextIndex(): Parse Context already initalised");
+		return false;
+	}
+
+	//
+	// Allocate a TLS index.
+	//
+	GlobalParseContextIndex = OS_AllocTLSIndex();
+	
+	if (GlobalParseContextIndex == OS_INVALID_TLS_INDEX) {
+		assert(0 && "InitializeParseContextIndex(): Parse Context already initalised");
+		return false;
+	}
+
+	return true;
+}
+
+bool InitializeGlobalParseContext()
+{
+	if (GlobalParseContextIndex == OS_INVALID_TLS_INDEX) {
+		assert(0 && "InitializeGlobalParseContext(): Parse Context index not initalised");
+		return false;
+	}
+
+	TThreadParseContext *lpParseContext = static_cast<TThreadParseContext *>(OS_GetTLSValue(GlobalParseContextIndex));
+	if (lpParseContext != 0) {
+		assert(0 && "InitializeParseContextIndex(): Parse Context already initalised");
+		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;
+}
+
+TParseContextPointer& GetGlobalParseContext()
+{
+	//
+	// Minimal error checking for speed
+	//
+
+	TThreadParseContext *lpParseContext = static_cast<TThreadParseContext *>(OS_GetTLSValue(GlobalParseContextIndex));
+
+	return lpParseContext->lpGlobalParseContext;
+}
+
+bool FreeParseContext()
+{
+	if (GlobalParseContextIndex == OS_INVALID_TLS_INDEX) {
+		assert(0 && "FreeParseContext(): Parse Context index not initalised");
+		return false;
+	}
+
+	TThreadParseContext *lpParseContext = static_cast<TThreadParseContext *>(OS_GetTLSValue(GlobalParseContextIndex));
+	if (lpParseContext)
+		delete lpParseContext;
+
+	return true;
+}
+
+bool FreeParseContextIndex()
+{
+	OS_TLSIndex tlsiIndex = GlobalParseContextIndex;
+
+	if (GlobalParseContextIndex == OS_INVALID_TLS_INDEX) {
+		assert(0 && "FreeParseContextIndex(): Parse Context index not initalised");
+		return false;
+	}
+
+	GlobalParseContextIndex = OS_INVALID_TLS_INDEX;
+
+	return OS_FreeTLSIndex(tlsiIndex);
+}
diff --git a/Compiler/ParseHelper.h b/Compiler/ParseHelper.h
new file mode 100644
index 0000000..bb61220
--- /dev/null
+++ b/Compiler/ParseHelper.h
@@ -0,0 +1,121 @@
+//
+// 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 _PARSER_HELPER_INCLUDED_
+#define _PARSER_HELPER_INCLUDED_
+
+#include "ShHandle.h"
+#include "SymbolTable.h"
+#include "localintermediate.h"
+
+struct TMatrixFields {
+	bool wholeRow;
+	bool wholeCol;
+	int row;
+	int col;
+};
+
+typedef enum {
+	EBhRequire,
+	EBhEnable,
+	EBhWarn,
+	EBhDisable
+} TBehavior;
+
+struct TPragma {
+	TPragma(bool o, bool d) : optimize(o), debug(d) { }
+	bool optimize;
+	bool debug;
+	TPragmaTable pragmaTable;
+};
+
+//
+// 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, TIntermediate& interm, EShLanguage L, TInfoSink& is) :
+			intermediate(interm), symbolTable(symt), infoSink(is), language(L), treeRoot(0),
+			recoveredFromError(false), numErrors(0), lexAfterType(false), loopNestingLevel(0),
+			inTypeParen(false), contextPragma(true, false) {  }
+	TIntermediate& intermediate; // to hold and build a parse tree
+	TSymbolTable& symbolTable;   // symbol table that goes with the language currently being parsed
+	TInfoSink& infoSink;
+	EShLanguage language;        // vertex or fragment language (future: pack or unpack)
+	TIntermNode* treeRoot;       // root of parse tree being created
+	bool recoveredFromError;     // true if a parse error has occurred, but we continue to parse
+	int numErrors;
+	bool lexAfterType;           // true if we've recognized a type, so can only be looking for an identifier
+	int loopNestingLevel;        // 0 if outside all loops
+	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
+	TMap<TString, TBehavior> extensionBehavior;
+	void initializeExtensionBehavior();
+
+	void C_DECL error(TSourceLoc, const char *szReason, const char *szToken,
+					  const char *szExtraInfoFormat, ...);
+	bool reservedErrorCheck(int line, const TString& identifier);
+	void recover();
+
+	bool parseVectorFields(const TString&, int vecSize, TVectorFields&, int line);
+	bool parseMatrixFields(const TString&, int matSize, TMatrixFields&, int line);
+	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 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 containsSampler(TType& type);
+	bool nonInitConstErrorCheck(int line, TString& identifier, TPublicType& type);
+	bool nonInitErrorCheck(int line, TString& identifier, TPublicType& type);
+	bool paramErrorCheck(int line, TQualifier qualifier, TQualifier paramQualifier, TType* type);
+	bool extensionErrorCheck(int line, const char*);
+	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 areAllChildConst(TIntermAggregate* aggrNode);
+	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);
+	bool arraySetMaxSize(TIntermSymbol*, TType*, int, bool, TSourceLoc);
+	struct TPragma contextPragma;
+	TString HashErrMsg;
+	bool AfterEOF;
+};
+
+int PaParseStrings(char* argv[], int strLen[], int argc, TParseContext&);
+void PaReservedWord();
+int PaIdentOrType(TString& id, TParseContext&, TSymbol*&);
+int PaParseComment(int &lineno, TParseContext&);
+void setInitialState();
+
+typedef TParseContext* TParseContextPointer;
+extern TParseContextPointer& GetGlobalParseContext();
+#define GlobalParseContext GetGlobalParseContext()
+
+typedef struct TThreadParseContextRec
+{
+	TParseContext *lpGlobalParseContext;
+} TThreadParseContext;
+
+#endif // _PARSER_HELPER_INCLUDED_
diff --git a/Compiler/PoolAlloc.cpp b/Compiler/PoolAlloc.cpp
new file mode 100644
index 0000000..013e752
--- /dev/null
+++ b/Compiler/PoolAlloc.cpp
@@ -0,0 +1,314 @@
+//
+// 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 "PoolAlloc.h"
+#include "Common.h"
+
+#include "InitializeGlobals.h"
+#include "osinclude.h"
+
+OS_TLSIndex PoolIndex = TLS_OUT_OF_INDEXES;
+
+void InitializeGlobalPools()
+{
+	TThreadGlobalPools* globalPools= static_cast<TThreadGlobalPools*>(OS_GetTLSValue(PoolIndex));    
+	if (globalPools)
+		return;
+
+	TPoolAllocator *globalPoolAllocator = new TPoolAllocator(true);
+
+	TThreadGlobalPools* threadData = new TThreadGlobalPools();
+	
+	threadData->globalPoolAllocator = globalPoolAllocator;
+		
+	OS_SetTLSValue(PoolIndex, threadData);     
+	globalPoolAllocator->push();
+}
+
+void FreeGlobalPools()
+{
+	// Release the allocated memory for this thread.
+	TThreadGlobalPools* globalPools= static_cast<TThreadGlobalPools*>(OS_GetTLSValue(PoolIndex));    
+	if (!globalPools)
+		return;
+	
+	GlobalPoolAllocator.popAll();
+	delete &GlobalPoolAllocator;       
+	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 SetGlobalPoolAllocatorPtr(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(bool g, int growthIncrement, int allocationAlignment) : 
+	global(g),
+	pageSize(growthIncrement),
+	alignment(allocationAlignment),
+	freeList(0),
+	inUseList(0),
+	numCalls(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()
+{
+	if (!global) {
+		//
+		// Then we know that this object is not being 
+		// allocated after other, globally scoped objects
+		// that depend on it.  So we can delete the "in use" memory.
+		//
+		while (inUseList) {
+			tHeader* next = inUseList->nextPage;
+			inUseList->~tHeader();
+			delete [] reinterpret_cast<char*>(inUseList);
+			inUseList = next;
+		}
+	}
+
+	//
+	// Always delete the free list memory - it can't be being
+	// (correctly) referenced, whether the pool allocator was
+	// global or not.  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
+{
+	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.
+			sprintf(assertMsg, "PoolAlloc: Damage %s %lu byte allocation at 0x%p\n",
+					locText, size, data());
+			assert(0 && "PoolAlloc: Damage in guard block");
+		}
+	}
+}
+
+
+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<UINT_PTR>(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/Compiler/PoolAlloc.h b/Compiler/PoolAlloc.h
new file mode 100644
index 0000000..bd417b7
--- /dev/null
+++ b/Compiler/PoolAlloc.h
@@ -0,0 +1,321 @@
+//
+// 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 <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(bool global = false, 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) :
+#ifdef GUARD_BLOCKS
+		lastAllocation(0),
+#endif
+		nextPage(nextPage), pageCount(pageCount) { }
+
+		~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);
+	}
+
+	bool global;            // should be true if this object is globally scoped
+	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.
+//
+typedef TPoolAllocator* PoolAllocatorPointer;
+extern TPoolAllocator& GetGlobalPoolAllocator();
+#define GlobalPoolAllocator GetGlobalPoolAllocator()
+
+
+struct TThreadGlobalPools
+{
+		TPoolAllocator* globalPoolAllocator;
+};
+
+void SetGlobalPoolAllocatorPtr(TPoolAllocator* poolAllocator);
+
+//
+// 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; }
+
+#ifdef USING_SGI_STL
+	pool_allocator()  { }
+#else
+	pool_allocator() : allocator(GlobalPoolAllocator) { }
+	pool_allocator(TPoolAllocator& a) : allocator(a) { }
+	pool_allocator(const pool_allocator<T>& p) : allocator(p.allocator) { }
+#endif
+
+#if defined(_MSC_VER) && _MSC_VER >= 1300
+	template<class Other>
+#ifdef USING_SGI_STL
+		pool_allocator(const pool_allocator<Other>& p) /*: allocator(p.getAllocator())*/ { }
+#else
+		pool_allocator(const pool_allocator<Other>& p) : allocator(p.getAllocator()) { }
+#endif
+#endif
+
+#ifndef _WIN32
+		template<class Other>
+			pool_allocator(const pool_allocator<Other>& p) : allocator(p.getAllocator()) { }
+#endif
+
+#ifdef USING_SGI_STL
+	static pointer allocate(size_type n) { 
+		return reinterpret_cast<pointer>(getAllocator().allocate(n)); }
+	pointer allocate(size_type n, const void*) { 
+		return reinterpret_cast<pointer>(getAllocator().allocate(n)); }
+
+	static void deallocate(void*, size_type) { }
+	static void deallocate(pointer, 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(void*, size_type) { }
+	void deallocate(pointer, size_type) { }
+#endif
+
+	pointer _Charalloc(size_t n) {
+		return reinterpret_cast<pointer>(getAllocator().allocate(n)); }
+
+	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; }
+
+#ifdef USING_SGI_STL
+	//void setAllocator(TPoolAllocator* a) { allocator = a; }
+	static  TPoolAllocator& getAllocator() { return GlobalPoolAllocator; }
+#else
+	void setAllocator(TPoolAllocator* a) { allocator = *a; }
+	TPoolAllocator& getAllocator() const { return allocator; }
+
+protected:
+	TPoolAllocator& allocator;
+#endif
+};
+
+#endif // _POOLALLOC_INCLUDED_
diff --git a/Compiler/Preprocessor/atom.c b/Compiler/Preprocessor/atom.c
new file mode 100644
index 0000000..204fb0d
--- /dev/null
+++ b/Compiler/Preprocessor/atom.c
@@ -0,0 +1,740 @@
+//
+// 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.
+//
+/****************************************************************************\
+Copyright (c) 2002, NVIDIA Corporation.
+
+NVIDIA Corporation("NVIDIA") supplies this software to you in
+consideration of your agreement to the following terms, and your use,
+installation, modification or redistribution of this NVIDIA software
+constitutes acceptance of these terms.  If you do not agree with these
+terms, please do not use, install, modify or redistribute this NVIDIA
+software.
+
+In consideration of your agreement to abide by the following terms, and
+subject to these terms, NVIDIA grants you a personal, non-exclusive
+license, under NVIDIA's copyrights in this original NVIDIA software (the
+"NVIDIA Software"), to use, reproduce, modify and redistribute the
+NVIDIA Software, with or without modifications, in source and/or binary
+forms; provided that if you redistribute the NVIDIA Software, you must
+retain the copyright notice of NVIDIA, this notice and the following
+text and disclaimers in all such redistributions of the NVIDIA Software.
+Neither the name, trademarks, service marks nor logos of NVIDIA
+Corporation may be used to endorse or promote products derived from the
+NVIDIA Software without specific prior written permission from NVIDIA.
+Except as expressly stated in this notice, no other rights or licenses
+express or implied, are granted by NVIDIA herein, including but not
+limited to any patent rights that may be infringed by your derivative
+works or by other works in which the NVIDIA Software may be
+incorporated. No hardware is licensed hereunder. 
+
+THE NVIDIA SOFTWARE IS BEING PROVIDED ON AN "AS IS" BASIS, WITHOUT
+WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED,
+INCLUDING WITHOUT LIMITATION, WARRANTIES OR CONDITIONS OF TITLE,
+NON-INFRINGEMENT, MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR
+ITS USE AND OPERATION EITHER ALONE OR IN COMBINATION WITH OTHER
+PRODUCTS.
+
+IN NO EVENT SHALL NVIDIA BE LIABLE FOR ANY SPECIAL, INDIRECT,
+INCIDENTAL, EXEMPLARY, CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+TO, LOST PROFITS; PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) OR ARISING IN ANY WAY
+OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE
+NVIDIA SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT,
+TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF
+NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+\****************************************************************************/
+
+//
+// atom.c
+//
+
+#include <assert.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "slglobals.h"
+
+#undef malloc
+#undef realloc
+#undef free
+
+///////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////// String table: //////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////////////////////
+
+static const struct {
+    int val;
+    const char *str;
+} tokens[] = {
+    { CPP_AND_OP,         "&&" },
+    { CPP_AND_ASSIGN,     "&=" },
+    { CPP_SUB_ASSIGN,     "-=" },
+    { CPP_MOD_ASSIGN,     "%=" },
+    { CPP_ADD_ASSIGN,     "+=" },
+    { CPP_DIV_ASSIGN,     "/=" },
+    { CPP_MUL_ASSIGN,     "*=" },
+    { CPP_RIGHT_BRACKET,  ":>" },
+    { CPP_EQ_OP,          "==" },
+    { CPP_XOR_OP,         "^^" }, 
+    { CPP_XOR_ASSIGN,     "^=" }, 
+    { CPP_FLOATCONSTANT,  "<float-const>" },
+    { CPP_GE_OP,          ">=" },
+    { CPP_RIGHT_OP,       ">>" },
+    { CPP_RIGHT_ASSIGN,   ">>=" }, 
+    { CPP_IDENTIFIER,     "<ident>" },
+    { CPP_INTCONSTANT,    "<int-const>" },
+    { CPP_LE_OP,          "<=" },
+    { CPP_LEFT_OP,        "<<" },
+    { CPP_LEFT_ASSIGN,    "<<=" },
+    { CPP_LEFT_BRACKET,   "<:" },
+    { CPP_LEFT_BRACE,     "<%" }, 
+    { CPP_DEC_OP,         "--" },
+    { CPP_RIGHT_BRACE,    "%>" }, 
+    { CPP_NE_OP,          "!=" },
+    { CPP_OR_OP,          "||" },
+    { CPP_OR_ASSIGN,      "|=" }, 
+    { CPP_INC_OP,         "++" },
+    { CPP_STRCONSTANT,    "<string-const>" },
+    { CPP_TYPEIDENTIFIER, "<type-ident>" },
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////// String table: //////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////////////////////
+
+#define INIT_STRING_TABLE_SIZE 16384
+
+typedef struct StringTable_Rec {
+    char *strings;
+    int nextFree;
+    int size;
+} StringTable;
+
+/*
+ * InitStringTable() - Initialize the string table.
+ *
+ */
+
+static int InitStringTable(StringTable *stable)
+{
+    stable->strings = (char *) malloc(INIT_STRING_TABLE_SIZE);
+    if (!stable->strings)
+        return 0;
+    // Zero-th offset means "empty" so don't use it.
+    stable->nextFree = 1;
+    stable->size = INIT_STRING_TABLE_SIZE;
+    return 1;
+} // InitStringTable
+
+/*
+ * FreeStringTable() - Free the string table.
+ *
+ */
+
+static void FreeStringTable(StringTable *stable)
+{
+    if (stable->strings)
+        free(stable->strings);
+    stable->strings = NULL;
+    stable->nextFree = 0;
+    stable->size = 0;
+} // FreeStringTable
+
+/*
+ * HashString() - Hash a string with the base hash function.
+ *
+ */
+
+static int HashString(const char *s)
+{
+    int hval = 0;
+
+    while (*s) {
+        hval = (hval*13507 + *s*197) ^ (hval >> 2);
+        s++;
+    }
+    return hval & 0x7fffffff;
+} // HashString
+
+/*
+ * HashString2() - Hash a string with the incrimenting hash function.
+ *
+ */
+
+static int HashString2(const char *s)
+{
+    int hval = 0;
+
+    while (*s) {
+        hval = (hval*729 + *s*37) ^ (hval >> 1);
+        s++;
+    }
+    return hval;
+} // HashString2
+
+/*
+ * AddString() - Add a string to a string table.  Return it's offset.
+ *
+ */
+
+static int AddString(StringTable *stable, const char *s)
+{
+    int len, loc;
+    char *str;
+
+    len = (int) strlen(s);
+    if (stable->nextFree + len + 1 >= stable->size) {
+        assert(stable->size < 1000000);
+        str = (char *) malloc(stable->size*2);
+        memcpy(str, stable->strings, stable->size);
+        free(stable->strings);
+        stable->strings = str;
+    }
+    loc = stable->nextFree;
+    strcpy(&stable->strings[loc], s);
+    stable->nextFree += len + 1;
+    return loc;
+} // AddString
+
+///////////////////////////////////////////////////////////////////////////////////////////////
+/////////////////////////////////////////// Hash table: ///////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////////////////////
+
+#define INIT_HASH_TABLE_SIZE 2047
+#define HASH_TABLE_MAX_COLLISIONS 3
+
+typedef struct HashEntry_Rec {
+    int index;      // String table offset of string representation
+    int value;      // Atom (symbol) value
+} HashEntry;
+
+typedef struct HashTable_Rec {
+    HashEntry *entry;
+    int size;
+    int entries;
+    int counts[HASH_TABLE_MAX_COLLISIONS + 1];
+} HashTable;
+
+/*
+ * InitHashTable() - Initialize the hash table.
+ *
+ */
+
+static int InitHashTable(HashTable *htable, int fsize)
+{
+    int ii;
+
+    htable->entry = (HashEntry *) malloc(sizeof(HashEntry)*fsize);
+    if (!htable->entry)
+        return 0;
+    htable->size = fsize;
+    for (ii = 0; ii < fsize; ii++) {
+        htable->entry[ii].index = 0;
+        htable->entry[ii].value = 0;
+    }
+    htable->entries = 0;
+    for (ii = 0; ii <= HASH_TABLE_MAX_COLLISIONS; ii++)
+        htable->counts[ii] = 0;
+    return 1;
+} // InitHashTable
+
+/*
+ * FreeHashTable() - Free the hash table.
+ *
+ */
+
+static void FreeHashTable(HashTable *htable)
+{
+    if (htable->entry)
+        free(htable->entry);
+    htable->entry = NULL;
+    htable->size = 0;
+    htable->entries = 0;
+} // FreeHashTable
+
+/*
+ * Empty() - See if a hash table entry is empty.
+ *
+ */
+
+static int Empty(HashTable *htable, int hashloc)
+{
+    assert(hashloc >= 0 && hashloc < htable->size);
+    if (htable->entry[hashloc].index == 0) {
+        return 1;
+    } else {
+        return 0;
+    }
+} // Empty
+
+/*
+ * Match() - See if a hash table entry is matches a string.
+ *
+ */
+
+static int Match(HashTable *htable, StringTable *stable, const char *s, int hashloc)
+{
+    int strloc;
+
+    strloc = htable->entry[hashloc].index;
+    if (!strcmp(s, &stable->strings[strloc])) {
+        return 1;
+    } else {
+        return 0;
+    }
+} // Match
+
+///////////////////////////////////////////////////////////////////////////////////////////////
+/////////////////////////////////////////// Atom table: ///////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////////////////////
+
+#define INIT_ATOM_TABLE_SIZE 1024
+
+
+struct AtomTable_Rec {
+    StringTable stable; // String table.
+    HashTable htable;   // Hashes string to atom number and token value.  Multiple strings can
+                        // have the same token value but each unique string is a unique atom.
+    int *amap;          // Maps atom value to offset in string table.  Atoms all map to unique
+                        // strings except for some undefined values in the lower, fixed part
+                        // of the atom table that map to "<undefined>".  The lowest 256 atoms
+                        // correspond to single character ASCII values except for alphanumeric
+                        // characters and '_', which can be other tokens.  Next come the
+                        // language tokens with their atom values equal to the token value.
+                        // Then come predefined atoms, followed by user specified identifiers.
+    int *arev;          // Reversed atom for symbol table use.
+    int nextFree;
+    int size;
+};
+
+static AtomTable latable = { { 0 } };
+AtomTable *atable = &latable;
+
+static int AddAtomFixed(AtomTable *atable, const char *s, int atom);
+
+/*
+ * GrowAtomTable() - Grow the atom table to at least "size" if it's smaller.
+ *
+ */
+
+static int GrowAtomTable(AtomTable *atable, int size)
+{
+    int *newmap, *newrev;
+
+    if (atable->size < size) {
+        if (atable->amap) {
+            newmap = realloc(atable->amap, sizeof(int)*size);
+            newrev = realloc(atable->arev, sizeof(int)*size);
+        } else {
+            newmap = malloc(sizeof(int)*size);
+            newrev = malloc(sizeof(int)*size);
+            atable->size = 0;
+        }
+        if (!newmap || !newrev) {
+            /* failed to grow -- error */
+            if (newmap)
+                atable->amap = newmap;
+            if (newrev)
+                atable->amap = newrev;
+            return -1;
+        }
+        memset(&newmap[atable->size], 0, (size - atable->size) * sizeof(int));
+        memset(&newrev[atable->size], 0, (size - atable->size) * sizeof(int));
+        atable->amap = newmap;
+        atable->arev = newrev;
+        atable->size = size;
+    }
+    return 0;
+} // GrowAtomTable
+
+/*
+ * lReverse() - Reverse the bottom 20 bits of a 32 bit int.
+ *
+ */
+
+static int lReverse(int fval)
+{
+    unsigned int in = fval;
+    int result = 0, cnt = 0;
+
+    while(in) {
+        result <<= 1;
+        result |= in&1;
+        in >>= 1;
+        cnt++;
+    }
+
+    // Don't use all 31 bits.  One million atoms is plenty and sometimes the
+    // upper bits are used for other things.
+
+    if (cnt < 20)
+        result <<= 20 - cnt;
+    return result;
+} // lReverse
+
+/*
+ * AllocateAtom() - Allocate a new atom.  Associated with the "undefined" value of -1.
+ *
+ */
+
+static int AllocateAtom(AtomTable *atable)
+{
+    if (atable->nextFree >= atable->size)
+        GrowAtomTable(atable, atable->nextFree*2);
+    atable->amap[atable->nextFree] = -1;
+    atable->arev[atable->nextFree] = lReverse(atable->nextFree);
+    atable->nextFree++;
+    return atable->nextFree - 1;
+} // AllocateAtom
+
+/*
+ * SetAtomValue() - Allocate a new atom associated with "hashindex".
+ *
+ */
+
+static void SetAtomValue(AtomTable *atable, int atomnumber, int hashindex)
+{
+    atable->amap[atomnumber] = atable->htable.entry[hashindex].index;
+    atable->htable.entry[hashindex].value = atomnumber;
+} // SetAtomValue
+
+/*
+ * FindHashLoc() - Find the hash location for this string.  Return -1 it hash table is full.
+ *
+ */
+
+static int FindHashLoc(AtomTable *atable, const char *s)
+{
+    int hashloc, hashdelta, count;
+    int FoundEmptySlot = 0;
+    int collision[HASH_TABLE_MAX_COLLISIONS + 1];
+
+    hashloc = HashString(s) % atable->htable.size;
+    if (!Empty(&atable->htable, hashloc)) {
+        if (Match(&atable->htable, &atable->stable, s, hashloc))
+            return hashloc;
+        collision[0] = hashloc;
+        hashdelta = HashString2(s);
+        count = 0;
+        while (count < HASH_TABLE_MAX_COLLISIONS) {
+            hashloc = ((hashloc + hashdelta) & 0x7fffffff) % atable->htable.size;
+            if (!Empty(&atable->htable, hashloc)) {
+                if (Match(&atable->htable, &atable->stable, s, hashloc)) {
+                    return hashloc;
+                }
+            } else {
+                FoundEmptySlot = 1;
+                break;
+            }
+            count++;
+            collision[count] = hashloc;
+        }
+
+        if (!FoundEmptySlot) {
+            if (cpp->options.DumpAtomTable) {
+                int ii;
+                char str[200];
+                sprintf(str, "*** Hash failed with more than %d collisions. Must increase hash table size. ***",
+                       HASH_TABLE_MAX_COLLISIONS);
+                CPPShInfoLogMsg(str);
+
+                sprintf(str, "*** New string \"%s\", hash=%04x, delta=%04x", s, collision[0], hashdelta);
+                CPPShInfoLogMsg(str);
+                for (ii = 0; ii <= HASH_TABLE_MAX_COLLISIONS; ii++) {
+                    sprintf(str, "*** Collides on try %d at hash entry %04x with \"%s\"",
+                           ii + 1, collision[ii], GetAtomString(atable, atable->htable.entry[collision[ii]].value));
+                    CPPShInfoLogMsg(str);
+                }
+            }
+            return -1;
+        } else {
+            atable->htable.counts[count]++;
+        }
+    }
+    return hashloc;
+} // FindHashLoc
+
+/*
+ * IncreaseHashTableSize()
+ *
+ */
+
+static int IncreaseHashTableSize(AtomTable *atable)
+{
+    int ii, strloc, oldhashloc, value, size;
+    AtomTable oldtable;
+    char *s;
+
+    // Save the old atom table and create a new one:
+
+    oldtable = *atable;
+    size = oldtable.htable.size*2 + 1;
+    if (!InitAtomTable(atable, size))
+        return 0;
+
+    // Add all the existing values to the new atom table preserving their atom values:
+
+    for (ii = atable->nextFree; ii < oldtable.nextFree; ii++) {
+        strloc = oldtable.amap[ii];
+        s = &oldtable.stable.strings[strloc];
+        oldhashloc = FindHashLoc(&oldtable, s);
+        assert(oldhashloc >= 0);
+        value = oldtable.htable.entry[oldhashloc].value;
+        AddAtomFixed(atable, s, value);
+    }
+    FreeAtomTable(&oldtable);
+    return 1;
+} // IncreaseHashTableSize
+
+/*
+ * LookUpAddStringHash() - Lookup a string in the hash table.  If it's not there, add it and
+ *        initialize the atom value in the hash table to 0.  Return the hash table index.
+ */
+
+static int LookUpAddStringHash(AtomTable *atable, const char *s)
+{
+    int hashloc, strloc;
+
+    while(1) {
+        hashloc = FindHashLoc(atable, s);
+        if (hashloc >= 0)
+            break;
+        IncreaseHashTableSize(atable);
+    }
+
+    if (Empty(&atable->htable, hashloc)) {
+        atable->htable.entries++;
+        strloc = AddString(&atable->stable, s);
+        atable->htable.entry[hashloc].index = strloc;
+        atable->htable.entry[hashloc].value = 0;
+    }
+    return hashloc;
+} // LookUpAddStringHash
+
+/*
+ * LookUpAddString() - Lookup a string in the hash table.  If it's not there, add it and
+ *        initialize the atom value in the hash table to the next atom number.
+ *        Return the atom value of string.
+ */
+
+int LookUpAddString(AtomTable *atable, const char *s)
+{
+    int hashindex, atom;
+
+    hashindex = LookUpAddStringHash(atable, s);
+    atom = atable->htable.entry[hashindex].value;
+    if (atom == 0) {
+        atom = AllocateAtom(atable);
+        SetAtomValue(atable, atom, hashindex);
+    }
+    return atom;
+} // LookUpAddString
+
+/*
+ * GetAtomString()
+ *
+ */
+
+const  char *GetAtomString(AtomTable *atable, int atom)
+{
+    int soffset;
+
+    if (atom > 0 && atom < atable->nextFree) {
+        soffset = atable->amap[atom];
+        if (soffset > 0 && soffset < atable->stable.nextFree) {
+            return &atable->stable.strings[soffset];
+        } else {
+            return "<internal error: bad soffset>";
+        }
+    } else {
+        if (atom == 0) {
+            return "<null atom>";
+        } else {
+            if (atom == EOF) {
+                return "<EOF>";
+            } else {
+                return "<invalid atom>";
+            }
+        }
+    }
+} // GetAtomString
+
+/*
+ * GetReversedAtom()
+ *
+ */
+
+int GetReversedAtom(AtomTable *atable, int atom)
+{
+    if (atom > 0 && atom < atable->nextFree) {
+        return atable->arev[atom];
+    } else {
+        return 0;
+    }
+} // GetReversedAtom
+
+/*
+ * AddAtom() - Add a string to the atom, hash and string tables if it isn't already there.
+ *         Return it's atom index.
+ */
+
+int AddAtom(AtomTable *atable, const char *s)
+{
+    int atom;
+
+    atom = LookUpAddString(atable, s);
+    return atom;
+} // AddAtom
+
+/*
+ * AddAtomFixed() - Add an atom to the hash and string tables if it isn't already there.
+ *         Assign it the atom value of "atom".
+ */
+
+static int AddAtomFixed(AtomTable *atable, const char *s, int atom)
+{
+    int hashindex, lsize;
+
+    hashindex = LookUpAddStringHash(atable, s);
+    if (atable->nextFree >= atable->size || atom >= atable->size) {
+        lsize = atable->size*2;
+        if (lsize <= atom)
+            lsize = atom + 1;
+        GrowAtomTable(atable, lsize);
+    }
+    atable->amap[atom] = atable->htable.entry[hashindex].index;
+    atable->htable.entry[hashindex].value = atom;
+    //if (atom >= atable->nextFree)
+    //    atable->nextFree = atom + 1;
+    while (atom >= atable->nextFree) {
+        atable->arev[atable->nextFree] = lReverse(atable->nextFree);
+        atable->nextFree++;
+    }
+    return atom;
+} // AddAtomFixed
+
+/*
+ * InitAtomTable() - Initialize the atom table.
+ *
+ */
+
+int InitAtomTable(AtomTable *atable, int htsize)
+{
+    int ii;
+
+    htsize = htsize <= 0 ? INIT_HASH_TABLE_SIZE : htsize;
+    if (!InitStringTable(&atable->stable))
+        return 0;
+    if (!InitHashTable(&atable->htable, htsize))
+        return 0;
+
+    atable->nextFree = 0;
+    atable->amap = NULL;
+    atable->size = 0;
+    GrowAtomTable(atable, INIT_ATOM_TABLE_SIZE);
+    if (!atable->amap)
+        return 0;
+
+    // Initialize lower part of atom table to "<undefined>" atom:
+
+    AddAtomFixed(atable, "<undefined>", 0);
+    for (ii = 0; ii < FIRST_USER_TOKEN_SY; ii++)
+        atable->amap[ii] = atable->amap[0];
+
+    // Add single character tokens to the atom table:
+
+    {
+		const char *s = "~!%^&*()-+=|,.<>/?;:[]{}#";
+        char t[2];
+
+        t[1] = '\0';
+        while (*s) {
+            t[0] = *s;
+            AddAtomFixed(atable, t, s[0]);
+            s++;
+        }
+    }
+
+    // Add multiple character scanner tokens :
+
+    for (ii = 0; ii < sizeof(tokens)/sizeof(tokens[0]); ii++)
+        AddAtomFixed(atable, tokens[ii].str, tokens[ii].val);
+
+    // Add error symbol if running in error mode:
+
+    if (cpp->options.ErrorMode)
+        AddAtomFixed(atable, "error", ERROR_SY);
+
+    AddAtom(atable, "<*** end fixed atoms ***>");
+
+    return 1;
+} // InitAtomTable
+
+///////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////// Debug Printing Functions: //////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////////////////////
+
+/*
+ * PrintAtomTable()
+ *
+ */
+
+void PrintAtomTable(AtomTable *atable)
+{
+    int ii;
+    char str[200];
+
+    for (ii = 0; ii < atable->nextFree; ii++) {
+        sprintf(str, "%d: \"%s\"", ii, &atable->stable.strings[atable->amap[ii]]);
+        CPPDebugLogMsg(str);
+    }
+    sprintf(str, "Hash table: size=%d, entries=%d, collisions=",
+           atable->htable.size, atable->htable.entries);
+    CPPDebugLogMsg(str);
+    for (ii = 0; ii < HASH_TABLE_MAX_COLLISIONS; ii++) {
+        sprintf(str, " %d", atable->htable.counts[ii]);
+        CPPDebugLogMsg(str);
+    }
+
+} // PrintAtomTable
+
+
+/*
+ * GetStringOfAtom()
+ *
+ */
+
+char* GetStringOfAtom(AtomTable *atable, int atom)
+{
+	 char* chr_str;
+	 chr_str=&atable->stable.strings[atable->amap[atom]];
+	 return chr_str;
+} // GetStringOfAtom
+
+/*
+ * FreeAtomTable() - Free the atom table and associated memory
+ *
+ */
+
+void FreeAtomTable(AtomTable *atable)
+{
+    FreeStringTable(&atable->stable);
+    FreeHashTable(&atable->htable);
+    if (atable->amap)
+        free(atable->amap);
+    if (atable->arev)
+        free(atable->arev);
+    atable->amap = NULL;
+    atable->arev = NULL;
+    atable->nextFree = 0;
+    atable->size = 0;
+} // FreeAtomTable
+
+///////////////////////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////// End of atom.c ///////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////////////////////
+
diff --git a/Compiler/Preprocessor/atom.h b/Compiler/Preprocessor/atom.h
new file mode 100644
index 0000000..9d42037
--- /dev/null
+++ b/Compiler/Preprocessor/atom.h
@@ -0,0 +1,68 @@
+//
+// 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.
+//
+/****************************************************************************\
+Copyright (c) 2002, NVIDIA Corporation.
+
+NVIDIA Corporation("NVIDIA") supplies this software to you in
+consideration of your agreement to the following terms, and your use,
+installation, modification or redistribution of this NVIDIA software
+constitutes acceptance of these terms.  If you do not agree with these
+terms, please do not use, install, modify or redistribute this NVIDIA
+software.
+
+In consideration of your agreement to abide by the following terms, and
+subject to these terms, NVIDIA grants you a personal, non-exclusive
+license, under NVIDIA's copyrights in this original NVIDIA software (the
+"NVIDIA Software"), to use, reproduce, modify and redistribute the
+NVIDIA Software, with or without modifications, in source and/or binary
+forms; provided that if you redistribute the NVIDIA Software, you must
+retain the copyright notice of NVIDIA, this notice and the following
+text and disclaimers in all such redistributions of the NVIDIA Software.
+Neither the name, trademarks, service marks nor logos of NVIDIA
+Corporation may be used to endorse or promote products derived from the
+NVIDIA Software without specific prior written permission from NVIDIA.
+Except as expressly stated in this notice, no other rights or licenses
+express or implied, are granted by NVIDIA herein, including but not
+limited to any patent rights that may be infringed by your derivative
+works or by other works in which the NVIDIA Software may be
+incorporated. No hardware is licensed hereunder. 
+
+THE NVIDIA SOFTWARE IS BEING PROVIDED ON AN "AS IS" BASIS, WITHOUT
+WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED,
+INCLUDING WITHOUT LIMITATION, WARRANTIES OR CONDITIONS OF TITLE,
+NON-INFRINGEMENT, MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR
+ITS USE AND OPERATION EITHER ALONE OR IN COMBINATION WITH OTHER
+PRODUCTS.
+
+IN NO EVENT SHALL NVIDIA BE LIABLE FOR ANY SPECIAL, INDIRECT,
+INCIDENTAL, EXEMPLARY, CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+TO, LOST PROFITS; PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) OR ARISING IN ANY WAY
+OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE
+NVIDIA SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT,
+TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF
+NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+\****************************************************************************/
+//
+// atom.h
+//
+
+#if !defined(__ATOM_H)
+#define __ATOM_H 1
+
+typedef struct AtomTable_Rec AtomTable;
+
+extern AtomTable *atable;
+
+int InitAtomTable(AtomTable *atable, int htsize);
+void FreeAtomTable(AtomTable *atable);
+int AddAtom(AtomTable *atable, const char *s);
+void PrintAtomTable(AtomTable *atable);
+int LookUpAddString(AtomTable *atable, const char *s);
+const char *GetAtomString(AtomTable *atable, int atom);
+int GetReversedAtom(AtomTable *atable, int atom);
+char* GetStringOfAtom(AtomTable *atable, int atom);
+#endif // !defined(__ATOM_H)
diff --git a/Compiler/Preprocessor/compile.h b/Compiler/Preprocessor/compile.h
new file mode 100644
index 0000000..9e87afc
--- /dev/null
+++ b/Compiler/Preprocessor/compile.h
@@ -0,0 +1,104 @@
+//
+// 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.
+//
+/****************************************************************************\
+Copyright (c) 2002, NVIDIA Corporation.
+
+NVIDIA Corporation("NVIDIA") supplies this software to you in
+consideration of your agreement to the following terms, and your use,
+installation, modification or redistribution of this NVIDIA software
+constitutes acceptance of these terms.  If you do not agree with these
+terms, please do not use, install, modify or redistribute this NVIDIA
+software.
+
+In consideration of your agreement to abide by the following terms, and
+subject to these terms, NVIDIA grants you a personal, non-exclusive
+license, under NVIDIA's copyrights in this original NVIDIA software (the
+"NVIDIA Software"), to use, reproduce, modify and redistribute the
+NVIDIA Software, with or without modifications, in source and/or binary
+forms; provided that if you redistribute the NVIDIA Software, you must
+retain the copyright notice of NVIDIA, this notice and the following
+text and disclaimers in all such redistributions of the NVIDIA Software.
+Neither the name, trademarks, service marks nor logos of NVIDIA
+Corporation may be used to endorse or promote products derived from the
+NVIDIA Software without specific prior written permission from NVIDIA.
+Except as expressly stated in this notice, no other rights or licenses
+express or implied, are granted by NVIDIA herein, including but not
+limited to any patent rights that may be infringed by your derivative
+works or by other works in which the NVIDIA Software may be
+incorporated. No hardware is licensed hereunder. 
+
+THE NVIDIA SOFTWARE IS BEING PROVIDED ON AN "AS IS" BASIS, WITHOUT
+WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED,
+INCLUDING WITHOUT LIMITATION, WARRANTIES OR CONDITIONS OF TITLE,
+NON-INFRINGEMENT, MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR
+ITS USE AND OPERATION EITHER ALONE OR IN COMBINATION WITH OTHER
+PRODUCTS.
+
+IN NO EVENT SHALL NVIDIA BE LIABLE FOR ANY SPECIAL, INDIRECT,
+INCIDENTAL, EXEMPLARY, CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+TO, LOST PROFITS; PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) OR ARISING IN ANY WAY
+OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE
+NVIDIA SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT,
+TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF
+NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+\****************************************************************************/
+//
+// compile.h
+//
+
+#if !defined(__COMPILE_H)
+#define __COMPILE_H 1
+
+int InitCPPStruct(void);
+
+typedef struct Options_Rec{
+    const char *profileString;
+    int ErrorMode;
+    int Quiet;
+	
+    // Debug The Compiler options:
+    int DumpAtomTable;
+} Options;
+
+struct CPPStruct_Rec {
+    // Public members
+    SourceLoc *pLastSourceLoc;  // Set at the start of each statement by the tree walkers
+    Options options;            // Compile options and parameters
+
+    // Private members
+    SourceLoc lastSourceLoc;
+
+    // Scanner data:
+
+    SourceLoc *tokenLoc;        // Source location of most recent token seen by the scanner
+    int mostRecentToken;        // Most recent token seen by the scanner
+    InputSrc *currentInput;
+    int previous_token;
+    int notAVersionToken;      // used to make sure that #version is the first token seen in the file, if present
+    
+	void *pC;                   // storing the parseContext of the compile object in cpp.  
+     
+    // Private members:
+    SourceLoc ltokenLoc;
+	int ifdepth;                //current #if-#else-#endif nesting in the cpp.c file (pre-processor)    
+    int elsedepth[64];          //Keep a track of #if depth..Max allowed is 64.   
+    int elsetracker;            //#if-#else and #endif constructs...Counter.
+    const char *ErrMsg;
+    int CompileError;           //Indicate compile error when #error, #else,#elif mismatch.
+
+    //
+    // Globals used to communicate between PaParseStrings() and yy_input()and 
+    // also across the files.(gen_glslang.cpp and scanner.c)
+    //
+    int    PaWhichStr;            // which string we're parsing
+    int*   PaStrLen;              // array of lengths of the PaArgv strings
+    int    PaArgc;                // count of strings in the array
+    char** PaArgv;                // our array of strings to parse    
+    unsigned int tokensBeforeEOF : 1;
+};
+
+#endif // !defined(__COMPILE_H)
diff --git a/Compiler/Preprocessor/cpp.c b/Compiler/Preprocessor/cpp.c
new file mode 100644
index 0000000..d852fd4
--- /dev/null
+++ b/Compiler/Preprocessor/cpp.c
@@ -0,0 +1,1009 @@
+//
+// 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.
+//
+/****************************************************************************\
+Copyright (c) 2002, NVIDIA Corporation.
+
+NVIDIA Corporation("NVIDIA") supplies this software to you in
+consideration of your agreement to the following terms, and your use,
+installation, modification or redistribution of this NVIDIA software
+constitutes acceptance of these terms.  If you do not agree with these
+terms, please do not use, install, modify or redistribute this NVIDIA
+software.
+
+In consideration of your agreement to abide by the following terms, and
+subject to these terms, NVIDIA grants you a personal, non-exclusive
+license, under NVIDIA's copyrights in this original NVIDIA software (the
+"NVIDIA Software"), to use, reproduce, modify and redistribute the
+NVIDIA Software, with or without modifications, in source and/or binary
+forms; provided that if you redistribute the NVIDIA Software, you must
+retain the copyright notice of NVIDIA, this notice and the following
+text and disclaimers in all such redistributions of the NVIDIA Software.
+Neither the name, trademarks, service marks nor logos of NVIDIA
+Corporation may be used to endorse or promote products derived from the
+NVIDIA Software without specific prior written permission from NVIDIA.
+Except as expressly stated in this notice, no other rights or licenses
+express or implied, are granted by NVIDIA herein, including but not
+limited to any patent rights that may be infringed by your derivative
+works or by other works in which the NVIDIA Software may be
+incorporated. No hardware is licensed hereunder. 
+
+THE NVIDIA SOFTWARE IS BEING PROVIDED ON AN "AS IS" BASIS, WITHOUT
+WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED,
+INCLUDING WITHOUT LIMITATION, WARRANTIES OR CONDITIONS OF TITLE,
+NON-INFRINGEMENT, MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR
+ITS USE AND OPERATION EITHER ALONE OR IN COMBINATION WITH OTHER
+PRODUCTS.
+
+IN NO EVENT SHALL NVIDIA BE LIABLE FOR ANY SPECIAL, INDIRECT,
+INCIDENTAL, EXEMPLARY, CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+TO, LOST PROFITS; PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) OR ARISING IN ANY WAY
+OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE
+NVIDIA SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT,
+TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF
+NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+\****************************************************************************/
+//
+// cpp.c
+//
+
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+
+#include "slglobals.h"
+
+static int CPPif(yystypepp * yylvalpp);
+
+/* Don't use memory.c's replacements, as we clean up properly here */
+#undef malloc
+#undef free
+
+static int bindAtom = 0;
+static int constAtom = 0;
+static int defaultAtom = 0;
+static int defineAtom = 0;
+static int definedAtom = 0;
+static int elseAtom = 0;
+static int elifAtom = 0;
+static int endifAtom = 0;
+static int ifAtom = 0;
+static int ifdefAtom = 0;
+static int ifndefAtom = 0;
+static int includeAtom = 0;
+static int lineAtom = 0;
+static int pragmaAtom = 0;
+static int texunitAtom = 0;
+static int undefAtom = 0;
+static int errorAtom = 0;
+static int __LINE__Atom = 0;
+static int __FILE__Atom = 0;
+static int __VERSION__Atom = 0;
+static int versionAtom = 0;
+static int extensionAtom = 0;
+
+static Scope *macros = 0;
+#define MAX_MACRO_ARGS  64
+#define MAX_IF_NESTING  64
+
+static SourceLoc ifloc; /* outermost #if */
+
+int InitCPP(void)
+{
+    char        buffer[64], *t;
+    const char  *f;
+    // Add various atoms needed by the CPP line scanner:
+    bindAtom = LookUpAddString(atable, "bind");
+    constAtom = LookUpAddString(atable, "const");
+    defaultAtom = LookUpAddString(atable, "default");
+    defineAtom = LookUpAddString(atable, "define");
+    definedAtom = LookUpAddString(atable, "defined");
+    elifAtom = LookUpAddString(atable, "elif");
+    elseAtom = LookUpAddString(atable, "else");
+    endifAtom = LookUpAddString(atable, "endif");
+    ifAtom = LookUpAddString(atable, "if");
+    ifdefAtom = LookUpAddString(atable, "ifdef");
+    ifndefAtom = LookUpAddString(atable, "ifndef");
+    includeAtom = LookUpAddString(atable, "include");
+    lineAtom = LookUpAddString(atable, "line");
+    pragmaAtom = LookUpAddString(atable, "pragma");
+    texunitAtom = LookUpAddString(atable, "texunit");
+    undefAtom = LookUpAddString(atable, "undef");
+	errorAtom = LookUpAddString(atable, "error");
+    __LINE__Atom = LookUpAddString(atable, "__LINE__");
+    __FILE__Atom = LookUpAddString(atable, "__FILE__");
+	__VERSION__Atom = LookUpAddString(atable, "__VERSION__");
+    versionAtom = LookUpAddString(atable, "version");
+    extensionAtom = LookUpAddString(atable, "extension");
+    macros = NewScopeInPool(mem_CreatePool(0, 0));
+    strcpy(buffer, "PROFILE_");
+    t = buffer + strlen(buffer);
+    f = cpp->options.profileString;
+    while ((isalnum(*f) || *f == '_') && t < buffer + sizeof(buffer) - 1)
+        *t++ = toupper(*f++);
+    *t = 0;
+	return 1;
+} // InitCPP
+
+int FreeCPP(void)
+{
+    if (macros)
+    {
+        mem_FreePool(macros->pool);
+        macros = 0;
+    }
+
+    return 1;
+}
+
+int FinalCPP(void)
+{
+	if (cpp->ifdepth)
+		CPPErrorToInfoLog("#if mismatch");
+    return 1;
+}
+
+static int CPPdefine(yystypepp * yylvalpp)
+{
+    int token, name, args[MAX_MACRO_ARGS], argc;
+    const char *message;
+    MacroSymbol mac;
+    Symbol *symb;
+    SourceLoc dummyLoc;
+    memset(&mac, 0, sizeof(mac));
+    token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
+    if (token != CPP_IDENTIFIER) {
+        CPPErrorToInfoLog("#define");
+        return token;
+    }
+    name = yylvalpp->sc_ident;
+    token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
+    if (token == '(' && !yylvalpp->sc_int) {
+        // gather arguments
+        argc = 0;
+        do {
+            token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
+            if (argc == 0 && token == ')') break;
+            if (token != CPP_IDENTIFIER) {
+				CPPErrorToInfoLog("#define");
+                return token;
+            }
+            if (argc < MAX_MACRO_ARGS)
+                args[argc++] = yylvalpp->sc_ident;
+            token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
+        } while (token == ',');
+        if (token != ')') {
+            CPPErrorToInfoLog("#define");
+            return token;
+        }
+        mac.argc = argc;
+        mac.args = mem_Alloc(macros->pool, argc * sizeof(int));
+        memcpy(mac.args, args, argc * sizeof(int));
+        token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
+	}
+    mac.body = NewTokenStream(GetAtomString(atable, name), macros->pool);
+    while (token != '\n') {
+        while (token == '\\') {
+            token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
+            if (token == '\n')
+                token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
+            else
+                RecordToken(mac.body, '\\', yylvalpp);
+        }
+        RecordToken(mac.body, token, yylvalpp);
+        token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
+    };
+
+    symb = LookUpSymbol(macros, name);
+    if (symb) {
+        if (!symb->details.mac.undef) {
+            // already defined -- need to make sure they are identical
+            if (symb->details.mac.argc != mac.argc) goto error;
+            for (argc=0; argc < mac.argc; argc++)
+                if (symb->details.mac.args[argc] != mac.args[argc])
+                    goto error;
+            RewindTokenStream(symb->details.mac.body);
+            RewindTokenStream(mac.body);
+            do {
+                int old_lval, old_token;
+                old_token = ReadToken(symb->details.mac.body, yylvalpp);
+                old_lval = yylvalpp->sc_int;
+                token = ReadToken(mac.body, yylvalpp);
+                if (token != old_token || yylvalpp->sc_int != old_lval) { 
+                error:
+                    StoreStr("Macro Redefined");
+                    StoreStr(GetStringOfAtom(atable,name));
+                    message=GetStrfromTStr();
+                    DecLineNumber();
+                    CPPShInfoLogMsg(message);
+                    IncLineNumber();
+                    ResetTString();
+                    break; }
+            } while (token > 0);
+        }
+        //FreeMacro(&symb->details.mac);
+    } else {
+        dummyLoc.file = 0;
+        dummyLoc.line = 0;
+        symb = AddSymbol(&dummyLoc, macros, name, MACRO_S);
+    }
+    symb->details.mac = mac;
+    return '\n';
+} // CPPdefine
+
+static int CPPundef(yystypepp * yylvalpp)
+{
+    int token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
+    Symbol *symb;
+	if(token == '\n'){
+		CPPErrorToInfoLog("#undef");
+	    return token;
+    }
+    if (token != CPP_IDENTIFIER)
+          goto error;
+    symb = LookUpSymbol(macros, yylvalpp->sc_ident);
+    if (symb) {
+        symb->details.mac.undef = 1;
+    }
+    token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
+    if (token != '\n') {
+    error:
+        CPPErrorToInfoLog("#undef");
+    }
+    return token;
+} // CPPundef
+
+/* CPPelse -- skip forward to appropriate spot.  This is actually used
+** to skip to and #endif after seeing an #else, AND to skip to a #else,
+** #elif, or #endif after a #if/#ifdef/#ifndef/#elif test was false
+*/
+
+static int CPPelse(int matchelse, yystypepp * yylvalpp)
+{
+    int atom,depth=0;
+    int token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
+	
+	while (token > 0) {
+        if (token != '#') {
+		    while (token != '\n')
+                token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
+            
+            token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
+            continue;
+        }
+		if ((token = cpp->currentInput->scan(cpp->currentInput, yylvalpp)) != CPP_IDENTIFIER)
+			continue;
+        atom = yylvalpp->sc_ident;
+        if (atom == ifAtom || atom == ifdefAtom || atom == ifndefAtom){
+            depth++; cpp->ifdepth++; cpp->elsetracker++;
+		}
+		else if (atom == endifAtom) {
+            if(--depth<=0){
+		        cpp->elsedepth[cpp->elsetracker]=0;
+			    --cpp->elsetracker;
+                if (cpp->ifdepth) 
+                    --cpp->ifdepth;
+                break;
+            }             
+                --cpp->elsetracker;
+                --cpp->ifdepth;
+            }
+        else if (((int)(matchelse) != 0)&& depth==0) {
+			if (atom == elseAtom ) {
+                token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
+                if (token != '\n') {
+                    CPPWarningToInfoLog("unexpected tokens following #else preprocessor directive - expected a newline");
+                    while (token != '\n')
+                        token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
+                } 
+				break;
+			} 
+			else if (atom == elifAtom) {
+                /* we decrement cpp->ifdepth here, because CPPif will increment
+                 * it and we really want to leave it alone */
+				if (cpp->ifdepth){
+					--cpp->ifdepth;
+				    --cpp->elsetracker;
+				}
+                return CPPif(yylvalpp);
+            }
+		}
+        else if((atom==elseAtom) && (!ChkCorrectElseNesting())){
+            CPPErrorToInfoLog("#else after a #else");
+            cpp->CompileError=1;
+        }
+	};
+    return token;
+}
+
+enum eval_prec {
+    MIN_PREC,
+    COND, LOGOR, LOGAND, OR, XOR, AND, EQUAL, RELATION, SHIFT, ADD, MUL, UNARY,
+    MAX_PREC
+};
+
+static int op_logor(int a, int b) { return a || b; }
+static int op_logand(int a, int b) { return a && b; }
+static int op_or(int a, int b) { return a | b; }
+static int op_xor(int a, int b) { return a ^ b; }
+static int op_and(int a, int b) { return a & b; }
+static int op_eq(int a, int b) { return a == b; }
+static int op_ne(int a, int b) { return a != b; }
+static int op_ge(int a, int b) { return a >= b; }
+static int op_le(int a, int b) { return a <= b; }
+static int op_gt(int a, int b) { return a > b; }
+static int op_lt(int a, int b) { return a < b; }
+static int op_shl(int a, int b) { return a << b; }
+static int op_shr(int a, int b) { return a >> b; }
+static int op_add(int a, int b) { return a + b; }
+static int op_sub(int a, int b) { return a - b; }
+static int op_mul(int a, int b) { return a * b; }
+static int op_div(int a, int b) { return a / b; }
+static int op_mod(int a, int b) { return a % b; }
+static int op_pos(int a) { return a; }
+static int op_neg(int a) { return -a; }
+static int op_cmpl(int a) { return ~a; }
+static int op_not(int a) { return !a; }
+
+struct {
+    int token, prec, (*op)(int, int);
+} binop[] = {
+    { CPP_OR_OP, LOGOR, op_logor },
+    { CPP_AND_OP, LOGAND, op_logand },
+    { '|', OR, op_or },
+    { '^', XOR, op_xor },
+    { '&', AND, op_and },
+    { CPP_EQ_OP, EQUAL, op_eq },
+    { CPP_NE_OP, EQUAL, op_ne },
+    { '>', RELATION, op_gt },
+    { CPP_GE_OP, RELATION, op_ge },
+    { '<', RELATION, op_lt },
+    { CPP_LE_OP, RELATION, op_le },
+    { CPP_LEFT_OP, SHIFT, op_shl },
+    { CPP_RIGHT_OP, SHIFT, op_shr },
+    { '+', ADD, op_add },
+    { '-', ADD, op_sub },
+    { '*', MUL, op_mul },
+    { '/', MUL, op_div },
+    { '%', MUL, op_mod },
+};
+
+struct {
+    int token, (*op)(int);
+} unop[] = {
+    { '+', op_pos },
+    { '-', op_neg },
+    { '~', op_cmpl },
+    { '!', op_not },
+};
+
+#define ALEN(A) (sizeof(A)/sizeof(A[0]))
+
+static int eval(int token, int prec, int *res, int *err, yystypepp * yylvalpp)
+{
+    int         i, val;
+    Symbol      *s;
+    if (token == CPP_IDENTIFIER) {
+        if (yylvalpp->sc_ident == definedAtom) {
+            int needclose = 0;
+            token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
+            if (token == '(') {
+                needclose = 1;
+                token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
+            }
+            if (token != CPP_IDENTIFIER)
+                goto error;
+            *res = (s = LookUpSymbol(macros, yylvalpp->sc_ident))
+                        ? !s->details.mac.undef : 0;
+            token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
+            if (needclose) {
+                if (token != ')')
+                    goto error;
+                token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
+            }
+		} else if (MacroExpand(yylvalpp->sc_ident, yylvalpp)) {
+			token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
+            return eval(token, prec, res, err, yylvalpp);
+        } else {
+            goto error;
+        }
+	} else if (token == CPP_INTCONSTANT) {
+        *res = yylvalpp->sc_int;
+        token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
+    } else if (token == '(') {
+        token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
+        token = eval(token, MIN_PREC, res, err, yylvalpp);
+        if (!*err) {
+            if (token != ')')
+                goto error;
+            token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
+        }
+    } else {
+        for (i = ALEN(unop) - 1; i >= 0; i--) {
+            if (unop[i].token == token)
+                break;
+        }
+        if (i >= 0) {
+            token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
+            token = eval(token, UNARY, res, err, yylvalpp);
+            *res = unop[i].op(*res);
+        } else {
+            goto error;
+        }
+    }
+    while (!*err) {
+        if (token == ')' || token == '\n') break;
+        for (i = ALEN(binop) - 1; i >= 0; i--) {
+            if (binop[i].token == token)
+                break;
+        }
+        if (i < 0 || binop[i].prec <= prec)
+            break;
+        val = *res;
+        token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
+        token = eval(token, binop[i].prec, res, err, yylvalpp);
+        *res = binop[i].op(val, *res);
+    }
+    return token;
+error:
+    CPPErrorToInfoLog("incorrect preprocessor directive");
+    *err = 1;
+    *res = 0;
+    return token;
+} // eval
+
+static int CPPif(yystypepp * yylvalpp) {
+    int token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
+    int res = 0, err = 0;
+	cpp->elsetracker++;
+    if (!cpp->ifdepth++)
+        ifloc = *cpp->tokenLoc;
+	if(cpp->ifdepth >MAX_IF_NESTING){
+        CPPErrorToInfoLog("max #if nesting depth exceeded");
+		return 0;
+	}
+	token = eval(token, MIN_PREC, &res, &err, yylvalpp);
+    if (token != '\n') {
+        CPPWarningToInfoLog("unexpected tokens following the preprocessor directive - expected a newline");
+        while (token != '\n')
+            token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
+    } 
+    if (!res && !err) {
+        token = CPPelse(1, yylvalpp);
+    }
+
+    return token;
+} // CPPif
+
+static int CPPifdef(int defined, yystypepp * yylvalpp)
+{
+    int token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
+    int name = yylvalpp->sc_ident;
+	if(++cpp->ifdepth >MAX_IF_NESTING){
+	    CPPErrorToInfoLog("max #if nesting depth exceeded");
+		return 0;
+	}
+	cpp->elsetracker++;
+    if (token != CPP_IDENTIFIER) {
+            defined ? CPPErrorToInfoLog("ifdef"):CPPErrorToInfoLog("ifndef");
+    } else {
+        Symbol *s = LookUpSymbol(macros, name);
+        token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
+        if (token != '\n') {
+            CPPWarningToInfoLog("unexpected tokens following #ifdef preprocessor directive - expected a newline");
+            while (token != '\n')
+                token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
+        }
+        if (((s && !s->details.mac.undef) ? 1 : 0) != defined)
+            token = CPPelse(1, yylvalpp);
+    }
+    return token;
+} // CPPifdef
+
+static int CPPline(yystypepp * yylvalpp) 
+{
+    int token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
+	if(token=='\n'){
+		DecLineNumber();
+        CPPErrorToInfoLog("#line");
+        IncLineNumber();
+		return token;
+	}
+	else if (token == CPP_INTCONSTANT) {
+		yylvalpp->sc_int=atoi(yylvalpp->symbol_name);
+		SetLineNumber(yylvalpp->sc_int);
+        token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
+        
+		if (token == CPP_INTCONSTANT) {
+            yylvalpp->sc_int=atoi(yylvalpp->symbol_name);
+			SetStringNumber(yylvalpp->sc_int);
+            token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
+			if(token!='\n')
+				CPPErrorToInfoLog("#line");
+        }
+		else if (token == '\n'){
+			return token;
+		}
+		else{
+            CPPErrorToInfoLog("#line");
+		}
+	}
+	else{
+          CPPErrorToInfoLog("#line");
+	}
+    return token;
+}
+
+static int CPPerror(yystypepp * yylvalpp) {
+
+	int token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
+    const char *message;
+	
+    while (token != '\n') {
+		if (token == CPP_FLOATCONSTANT || token == CPP_INTCONSTANT){
+            StoreStr(yylvalpp->symbol_name);
+		}else if(token == CPP_IDENTIFIER || token == CPP_STRCONSTANT){
+			StoreStr(GetStringOfAtom(atable,yylvalpp->sc_ident));
+		}else {
+		    StoreStr(GetStringOfAtom(atable,token));
+		}
+		token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
+	}
+	DecLineNumber();
+	//store this msg into the shader's information log..set the Compile Error flag!!!!
+	message=GetStrfromTStr();
+    CPPShInfoLogMsg(message);
+    ResetTString();
+    cpp->CompileError=1;
+    IncLineNumber();
+    return '\n';
+}//CPPerror
+
+static int CPPpragma(yystypepp * yylvalpp)
+{
+	char SrcStrName[2];
+	char** allTokens;
+	int tokenCount = 0;
+	int maxTokenCount = 10;
+	const char* SrcStr;
+	int i;
+
+	int token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
+	
+	if (token=='\n') {
+		DecLineNumber();
+        CPPErrorToInfoLog("#pragma");
+        IncLineNumber();
+	    return token;
+	}
+	
+	allTokens = (char**)malloc(sizeof(char*) * maxTokenCount);	
+
+	while (token != '\n') {
+		if (tokenCount >= maxTokenCount) {
+			maxTokenCount *= 2;
+			allTokens = (char**)realloc((char**)allTokens, sizeof(char*) * maxTokenCount);
+		}
+		switch (token) {
+		case CPP_IDENTIFIER:
+			SrcStr = GetAtomString(atable, yylvalpp->sc_ident);
+			allTokens[tokenCount] = (char*)malloc(strlen(SrcStr) + 1);
+			strcpy(allTokens[tokenCount++], SrcStr);
+			break;
+		case CPP_INTCONSTANT:
+			SrcStr = yylvalpp->symbol_name;
+			allTokens[tokenCount] = (char*)malloc(strlen(SrcStr) + 1);
+			strcpy(allTokens[tokenCount++], SrcStr);
+			break;
+		case CPP_FLOATCONSTANT:
+			SrcStr = yylvalpp->symbol_name;
+			allTokens[tokenCount] = (char*)malloc(strlen(SrcStr) + 1);
+			strcpy(allTokens[tokenCount++], SrcStr);
+			break;
+		case -1:
+            // EOF
+            CPPShInfoLogMsg("#pragma directive must end with a newline");			
+			return token;
+		default:
+			SrcStrName[0] = token;
+			SrcStrName[1] = '\0';
+			allTokens[tokenCount] = (char*)malloc(2);
+			strcpy(allTokens[tokenCount++], SrcStrName);
+		}
+		token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
+	}
+
+	cpp->currentInput->ungetch(cpp->currentInput, token, yylvalpp);
+	HandlePragma((const char**)allTokens, tokenCount);
+	token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
+	
+	for (i = 0; i < tokenCount; ++i) {
+		free (allTokens[i]);
+	}
+	free (allTokens);	
+
+	return token;    
+} // CPPpragma
+
+#define GL2_VERSION_NUMBER 110
+
+static int CPPversion(yystypepp * yylvalpp)
+{
+
+    int token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
+
+    if (cpp->notAVersionToken == 1)
+        CPPShInfoLogMsg("#version must occur before any other statement in the program");
+
+    if(token=='\n'){
+		DecLineNumber();
+        CPPErrorToInfoLog("#version");
+        IncLineNumber();
+		return token;
+	}
+    if (token != CPP_INTCONSTANT)
+        CPPErrorToInfoLog("#version");
+	
+    yylvalpp->sc_int=atoi(yylvalpp->symbol_name);
+	//SetVersionNumber(yylvalpp->sc_int);
+    
+    if (yylvalpp->sc_int != GL2_VERSION_NUMBER)
+        CPPShInfoLogMsg("Version number not supported by GL2");
+
+    token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
+    
+	if (token == '\n'){
+		return token;
+	}
+	else{
+        CPPErrorToInfoLog("#version");
+	}
+    return token;
+} // CPPversion
+
+static int CPPextension(yystypepp * yylvalpp)
+{
+
+    int token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
+    char extensionName[80];
+
+    if(token=='\n'){
+		DecLineNumber();
+        CPPShInfoLogMsg("extension name not specified");
+        IncLineNumber();
+		return token;
+	}
+
+    if (token != CPP_IDENTIFIER)
+        CPPErrorToInfoLog("#extension");
+    
+    strcpy(extensionName, GetAtomString(atable, yylvalpp->sc_ident));
+	    
+    token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
+    if (token != ':') {
+        CPPShInfoLogMsg("':' missing after extension name");
+        return token;
+    }
+    
+    token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
+    if (token != CPP_IDENTIFIER) {
+        CPPShInfoLogMsg("behavior for extension not specified");
+        return token;
+    }
+
+    updateExtensionBehavior(extensionName, GetAtomString(atable, yylvalpp->sc_ident));
+
+    token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
+	if (token == '\n'){
+		return token;
+	}
+	else{
+        CPPErrorToInfoLog("#extension");
+	}
+    return token;
+} // CPPextension
+
+int readCPPline(yystypepp * yylvalpp)
+{
+    int token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
+    const char *message;
+    int isVersion = 0;
+
+    if (token == CPP_IDENTIFIER) {
+        if (yylvalpp->sc_ident == defineAtom) {
+             token = CPPdefine(yylvalpp);
+        } else if (yylvalpp->sc_ident == elseAtom) {
+			 if(ChkCorrectElseNesting()){
+                 if (!cpp->ifdepth ){
+                     CPPErrorToInfoLog("#else mismatch");
+                     cpp->CompileError=1;
+                 }
+                 token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
+                 if (token != '\n') {
+                     CPPWarningToInfoLog("unexpected tokens following #else preprocessor directive - expected a newline");
+                     while (token != '\n')
+                         token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
+                 }
+			     token = CPPelse(0, yylvalpp);
+             }else{
+                 CPPErrorToInfoLog("#else after a #else");
+                 cpp->ifdepth=0;
+                 cpp->notAVersionToken = 1;
+                 return 0;
+             }
+		} else if (yylvalpp->sc_ident == elifAtom) {
+            if (!cpp->ifdepth){
+                 CPPErrorToInfoLog("#elif mismatch");
+                 cpp->CompileError=1;
+            } 
+            // this token is really a dont care, but we still need to eat the tokens
+            token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); 
+            while (token != '\n')
+                token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
+		    token = CPPelse(0, yylvalpp);
+        } else if (yylvalpp->sc_ident == endifAtom) {
+			 cpp->elsedepth[cpp->elsetracker]=0;
+		     --cpp->elsetracker;
+             if (!cpp->ifdepth){
+                 CPPErrorToInfoLog("#endif mismatch");
+                 cpp->CompileError=1;
+             }
+             else
+			  	 --cpp->ifdepth;
+	    } else if (yylvalpp->sc_ident == ifAtom) {
+             token = CPPif(yylvalpp);
+        } else if (yylvalpp->sc_ident == ifdefAtom) {
+             token = CPPifdef(1, yylvalpp);
+        } else if (yylvalpp->sc_ident == ifndefAtom) {
+             token = CPPifdef(0, yylvalpp);
+        } else if (yylvalpp->sc_ident == lineAtom) {
+             token = CPPline(yylvalpp);
+        } else if (yylvalpp->sc_ident == pragmaAtom) {
+             token = CPPpragma(yylvalpp);
+        } else if (yylvalpp->sc_ident == undefAtom) {
+             token = CPPundef(yylvalpp);
+        } else if (yylvalpp->sc_ident == errorAtom) {
+             token = CPPerror(yylvalpp);
+        } else if (yylvalpp->sc_ident == versionAtom) {
+            token = CPPversion(yylvalpp);
+            isVersion = 1;
+        } else if (yylvalpp->sc_ident == extensionAtom) {
+            token = CPPextension(yylvalpp);
+        } else {
+            StoreStr("Invalid Directive");
+            StoreStr(GetStringOfAtom(atable,yylvalpp->sc_ident));
+            message=GetStrfromTStr();
+            CPPShInfoLogMsg(message);
+            ResetTString();
+        }
+    }
+    while (token != '\n' && token != 0 && token != EOF) {
+		token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
+	}
+        
+    cpp->notAVersionToken = !isVersion;
+
+    return token;
+} // readCPPline
+
+void FreeMacro(MacroSymbol *s) {
+    DeleteTokenStream(s->body);
+}
+
+static int eof_scan(InputSrc *in, yystypepp * yylvalpp) { return -1; }
+static void noop(InputSrc *in, int ch, yystypepp * yylvalpp) { }
+
+static void PushEofSrc() {
+    InputSrc *in = malloc(sizeof(InputSrc));
+    memset(in, 0, sizeof(InputSrc));
+    in->scan = eof_scan;
+    in->getch = eof_scan;
+    in->ungetch = noop;
+    in->prev = cpp->currentInput;
+    cpp->currentInput = in;
+}
+
+static void PopEofSrc() {
+    if (cpp->currentInput->scan == eof_scan) {
+        InputSrc *in = cpp->currentInput;
+        cpp->currentInput = in->prev;
+        free(in);
+    }
+}
+
+static TokenStream *PrescanMacroArg(TokenStream *a, yystypepp * yylvalpp) {
+    int token;
+    TokenStream *n;
+    RewindTokenStream(a);
+    do {
+        token = ReadToken(a, yylvalpp);
+        if (token == CPP_IDENTIFIER && LookUpSymbol(macros, yylvalpp->sc_ident))
+            break;
+    } while (token > 0);
+    if (token <= 0) return a;
+    n = NewTokenStream("macro arg", 0);
+    PushEofSrc();
+    ReadFromTokenStream(a, 0, 0);
+    while ((token = cpp->currentInput->scan(cpp->currentInput, yylvalpp)) > 0) {
+        if (token == CPP_IDENTIFIER && MacroExpand(yylvalpp->sc_ident, yylvalpp))
+            continue;
+        RecordToken(n, token, yylvalpp);
+    }
+    PopEofSrc();
+    DeleteTokenStream(a);
+    return n;
+} // PrescanMacroArg
+
+typedef struct MacroInputSrc {
+    InputSrc    base;
+    MacroSymbol *mac;
+    TokenStream **args;
+} MacroInputSrc;
+
+/* macro_scan ---
+** return the next token for a macro expanion, handling macro args 
+*/
+static int macro_scan(MacroInputSrc *in, yystypepp * yylvalpp) {
+    int i;
+    int token = ReadToken(in->mac->body, yylvalpp);
+    if (token == CPP_IDENTIFIER) {
+        for (i = in->mac->argc-1; i>=0; i--)
+            if (in->mac->args[i] == yylvalpp->sc_ident) break;
+        if (i >= 0) {
+            ReadFromTokenStream(in->args[i], yylvalpp->sc_ident, 0);
+            return cpp->currentInput->scan(cpp->currentInput, yylvalpp);
+        }
+    }
+    if (token > 0) return token;
+    in->mac->busy = 0;
+    cpp->currentInput = in->base.prev;
+    if (in->args) {
+        for (i=in->mac->argc-1; i>=0; i--)
+            DeleteTokenStream(in->args[i]);
+        free(in->args);
+    }
+    free(in);
+    return cpp->currentInput->scan(cpp->currentInput, yylvalpp);
+} // macro_scan
+
+/* MacroExpand
+** check an identifier (atom) to see if it a macro that should be expanded.
+** If it is, push an InputSrc that will produce the appropriate expansion
+** and return TRUE.  If not, return FALSE.
+*/
+
+int MacroExpand(int atom, yystypepp * yylvalpp)
+{
+    Symbol              *sym = LookUpSymbol(macros, atom);
+    MacroInputSrc       *in;
+    int i,j, token, depth=0;
+    const char *message;
+	if (atom == __LINE__Atom) {
+        yylvalpp->sc_int = GetLineNumber();
+        sprintf(yylvalpp->symbol_name,"%d",yylvalpp->sc_int);
+        UngetToken(CPP_INTCONSTANT, yylvalpp);
+        return 1;
+    }
+    if (atom == __FILE__Atom) {
+        yylvalpp->sc_int = GetStringNumber();
+        sprintf(yylvalpp->symbol_name,"%d",yylvalpp->sc_int);
+        UngetToken(CPP_INTCONSTANT, yylvalpp);
+        return 1;
+    }
+	if (atom == __VERSION__Atom) {
+        strcpy(yylvalpp->symbol_name,"100");
+        yylvalpp->sc_int = atoi(yylvalpp->symbol_name);
+        UngetToken(CPP_INTCONSTANT, yylvalpp);
+        return 1;
+    }
+    if (!sym || sym->details.mac.undef) return 0;
+    if (sym->details.mac.busy) return 0;        // no recursive expansions
+    in = malloc(sizeof(*in));
+    memset(in, 0, sizeof(*in));
+    in->base.scan = (void *)macro_scan;
+    in->base.line = cpp->currentInput->line;
+    in->base.name = cpp->currentInput->name;
+    in->mac = &sym->details.mac;
+    if (sym->details.mac.args) {
+        token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
+		if (token != '(') {
+            UngetToken(token, yylvalpp);
+            yylvalpp->sc_ident = atom;
+            return 0;
+        }
+        in->args = malloc(in->mac->argc * sizeof(TokenStream *));
+        for (i=0; i<in->mac->argc; i++)
+            in->args[i] = NewTokenStream("macro arg", 0);
+		i=0;j=0;
+        do{
+            depth = 0;
+			while(1) {
+                token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
+                if (token <= 0) {
+                    StoreStr("EOF in Macro ");
+                    StoreStr(GetStringOfAtom(atable,atom));
+                    message=GetStrfromTStr();
+                    CPPShInfoLogMsg(message);
+                    ResetTString();
+                    return 1;
+                }
+                if((in->mac->argc==0) && (token!=')')) break;
+                if (depth == 0 && (token == ',' || token == ')')) break;
+                if (token == '(') depth++;
+                if (token == ')') depth--;
+                RecordToken(in->args[i], token, yylvalpp);
+                j=1;
+			}
+            if (token == ')') {
+                if((in->mac->argc==1) &&j==0)
+                    break;
+                i++;
+                break;
+            }
+            i++;
+		}while(i < in->mac->argc);
+
+        if (i < in->mac->argc) {
+            StoreStr("Too few args in Macro ");
+            StoreStr(GetStringOfAtom(atable,atom));
+            message=GetStrfromTStr();
+            CPPShInfoLogMsg(message);
+            ResetTString();
+        } else if (token != ')') {
+            depth=0;
+			while (token >= 0 && (depth > 0 || token != ')')) {
+                if (token == ')') depth--;
+                token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
+                if (token == '(') depth++;
+            }
+			
+            if (token <= 0) {
+                StoreStr("EOF in Macro ");
+                StoreStr(GetStringOfAtom(atable,atom));
+                message=GetStrfromTStr();
+                CPPShInfoLogMsg(message);
+                ResetTString();
+                return 1;
+            }
+            StoreStr("Too many args in Macro ");
+            StoreStr(GetStringOfAtom(atable,atom));
+            message=GetStrfromTStr();
+            CPPShInfoLogMsg(message);
+            ResetTString();
+		}
+		for (i=0; i<in->mac->argc; i++) {
+            in->args[i] = PrescanMacroArg(in->args[i], yylvalpp);
+        }
+    }
+#if 0
+    printf("  <%s:%d>found macro %s\n", GetAtomString(atable, loc.file),
+           loc.line, GetAtomString(atable, atom));
+    for (i=0; i<in->mac->argc; i++) {
+        printf("\targ %s = '", GetAtomString(atable, in->mac->args[i]));
+        DumpTokenStream(stdout, in->args[i]);
+        printf("'\n");
+    }
+#endif
+	/*retain the input source*/
+    in->base.prev = cpp->currentInput;
+    sym->details.mac.busy = 1;
+    RewindTokenStream(sym->details.mac.body);
+    cpp->currentInput = &in->base;
+    return 1;
+} // MacroExpand
+
+int ChkCorrectElseNesting(void)
+{
+    if(cpp->elsedepth[cpp->elsetracker]==0){
+	  cpp->elsedepth[cpp->elsetracker]=1;
+      return 1;          
+    }
+    return 0;
+}
+
+
diff --git a/Compiler/Preprocessor/cpp.h b/Compiler/Preprocessor/cpp.h
new file mode 100644
index 0000000..85abbb5
--- /dev/null
+++ b/Compiler/Preprocessor/cpp.h
@@ -0,0 +1,91 @@
+//
+// 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.
+//
+/****************************************************************************\
+Copyright (c) 2002, NVIDIA Corporation.
+
+NVIDIA Corporation("NVIDIA") supplies this software to you in
+consideration of your agreement to the following terms, and your use,
+installation, modification or redistribution of this NVIDIA software
+constitutes acceptance of these terms.  If you do not agree with these
+terms, please do not use, install, modify or redistribute this NVIDIA
+software.
+
+In consideration of your agreement to abide by the following terms, and
+subject to these terms, NVIDIA grants you a personal, non-exclusive
+license, under NVIDIA's copyrights in this original NVIDIA software (the
+"NVIDIA Software"), to use, reproduce, modify and redistribute the
+NVIDIA Software, with or without modifications, in source and/or binary
+forms; provided that if you redistribute the NVIDIA Software, you must
+retain the copyright notice of NVIDIA, this notice and the following
+text and disclaimers in all such redistributions of the NVIDIA Software.
+Neither the name, trademarks, service marks nor logos of NVIDIA
+Corporation may be used to endorse or promote products derived from the
+NVIDIA Software without specific prior written permission from NVIDIA.
+Except as expressly stated in this notice, no other rights or licenses
+express or implied, are granted by NVIDIA herein, including but not
+limited to any patent rights that may be infringed by your derivative
+works or by other works in which the NVIDIA Software may be
+incorporated. No hardware is licensed hereunder. 
+
+THE NVIDIA SOFTWARE IS BEING PROVIDED ON AN "AS IS" BASIS, WITHOUT
+WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED,
+INCLUDING WITHOUT LIMITATION, WARRANTIES OR CONDITIONS OF TITLE,
+NON-INFRINGEMENT, MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR
+ITS USE AND OPERATION EITHER ALONE OR IN COMBINATION WITH OTHER
+PRODUCTS.
+
+IN NO EVENT SHALL NVIDIA BE LIABLE FOR ANY SPECIAL, INDIRECT,
+INCIDENTAL, EXEMPLARY, CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+TO, LOST PROFITS; PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) OR ARISING IN ANY WAY
+OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE
+NVIDIA SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT,
+TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF
+NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+\****************************************************************************/
+//
+// cpp.h
+//
+
+#if !defined(__CPP_H)
+#define __CPP_H 1
+
+#include "parser.h"
+#include "tokens.h"
+
+int InitCPP(void);
+int FinalCPP(void);
+int  readCPPline(yystypepp * yylvalpp);
+int MacroExpand(int atom, yystypepp * yylvalpp);
+int ChkCorrectElseNesting(void);
+
+typedef struct MacroSymbol {
+    int argc;
+    int *args;
+    TokenStream *body;
+    unsigned busy:1;
+    unsigned undef:1;
+} MacroSymbol;
+
+void FreeMacro(MacroSymbol *);
+int PredefineMacro(char *);
+
+void  CPPDebugLogMsg(const char *msg);      // Prints information into debug log
+void  CPPShInfoLogMsg(const char*);         // Store cpp Err Msg into Sh.Info.Log
+void  CPPWarningToInfoLog(const char *msg); // Prints warning messages into info log
+void  HandlePragma(const char**, int numTokens);  // #pragma directive container.
+void  ResetTString(void);                   // #error Message as TString.
+void  CPPErrorToInfoLog(char*);             // Stick all cpp errors into Sh.Info.log   .
+void  StoreStr(char*);                      // Store the TString in Parse Context.
+void  SetLineNumber(int);                   // Set line number.  
+void  SetStringNumber(int);                 // Set string number.    
+int   GetLineNumber(void);                  // Get the current String Number. 
+int   GetStringNumber(void);                // Get the current String Number. 
+const char* GetStrfromTStr(void);           // Convert TString to String.  
+void  updateExtensionBehavior(const char* extName, const char* behavior);
+int   FreeCPP(void);
+
+#endif // !(defined(__CPP_H)
diff --git a/Compiler/Preprocessor/cppstruct.c b/Compiler/Preprocessor/cppstruct.c
new file mode 100644
index 0000000..5144b6c
--- /dev/null
+++ b/Compiler/Preprocessor/cppstruct.c
@@ -0,0 +1,157 @@
+//
+// 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.
+//
+/****************************************************************************\
+Copyright (c) 2002, NVIDIA Corporation.
+
+NVIDIA Corporation("NVIDIA") supplies this software to you in
+consideration of your agreement to the following terms, and your use,
+installation, modification or redistribution of this NVIDIA software
+constitutes acceptance of these terms.  If you do not agree with these
+terms, please do not use, install, modify or redistribute this NVIDIA
+software.
+
+In consideration of your agreement to abide by the following terms, and
+subject to these terms, NVIDIA grants you a personal, non-exclusive
+license, under NVIDIA's copyrights in this original NVIDIA software (the
+"NVIDIA Software"), to use, reproduce, modify and redistribute the
+NVIDIA Software, with or without modifications, in source and/or binary
+forms; provided that if you redistribute the NVIDIA Software, you must
+retain the copyright notice of NVIDIA, this notice and the following
+text and disclaimers in all such redistributions of the NVIDIA Software.
+Neither the name, trademarks, service marks nor logos of NVIDIA
+Corporation may be used to endorse or promote products derived from the
+NVIDIA Software without specific prior written permission from NVIDIA.
+Except as expressly stated in this notice, no other rights or licenses
+express or implied, are granted by NVIDIA herein, including but not
+limited to any patent rights that may be infringed by your derivative
+works or by other works in which the NVIDIA Software may be
+incorporated. No hardware is licensed hereunder. 
+
+THE NVIDIA SOFTWARE IS BEING PROVIDED ON AN "AS IS" BASIS, WITHOUT
+WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED,
+INCLUDING WITHOUT LIMITATION, WARRANTIES OR CONDITIONS OF TITLE,
+NON-INFRINGEMENT, MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR
+ITS USE AND OPERATION EITHER ALONE OR IN COMBINATION WITH OTHER
+PRODUCTS.
+
+IN NO EVENT SHALL NVIDIA BE LIABLE FOR ANY SPECIAL, INDIRECT,
+INCIDENTAL, EXEMPLARY, CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+TO, LOST PROFITS; PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) OR ARISING IN ANY WAY
+OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE
+NVIDIA SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT,
+TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF
+NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+\****************************************************************************/
+//
+// cppstruct.c
+//
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "slglobals.h"
+
+CPPStruct  *cpp      = NULL;
+static int  refCount = 0;
+
+int InitPreprocessor(void);
+int ResetPreprocessor(void);
+int FreeCPPStruct(void);
+int FinalizePreprocessor(void);
+
+/*
+ * InitCPPStruct() - Initilaize the CPP structure.
+ *
+ */
+
+int InitCPPStruct(void)
+{
+    int len;
+    char *p;
+
+    cpp = (CPPStruct *) malloc(sizeof(CPPStruct));
+    if (cpp == NULL)
+        return 0;
+
+    refCount++;
+
+    // Initialize public members:
+    cpp->pLastSourceLoc = &cpp->lastSourceLoc;
+    
+	p = (char *) &cpp->options;
+    len = sizeof(cpp->options);
+    while (--len >= 0)
+        p[len] = 0;
+     
+    ResetPreprocessor();
+    return 1;
+} // InitCPPStruct
+
+int ResetPreprocessor(void)
+{
+    // Initialize private members:
+
+    cpp->lastSourceLoc.file = 0;
+    cpp->lastSourceLoc.line = 0;
+	cpp->pC=0;
+    cpp->CompileError=0; 
+	cpp->ifdepth=0;
+    for(cpp->elsetracker=0; cpp->elsetracker<64; cpp->elsetracker++)
+		cpp->elsedepth[cpp->elsetracker]=0; 
+	cpp->elsetracker=0;
+    cpp->tokensBeforeEOF = 0;
+    return 1;
+}
+
+//Intializing the Preprocessor.
+
+int InitPreprocessor(void)
+{
+   #  define CPP_STUFF true
+        #  ifdef CPP_STUFF
+            FreeCPPStruct();
+            InitCPPStruct();
+            cpp->options.Quiet = 1;
+            cpp->options.profileString = "generic";
+            if (!InitAtomTable(atable, 0))
+                return 1;
+            if (!InitScanner(cpp))
+	            return 1;
+       #  endif
+  return 0; 
+}
+
+//FreeCPPStruct() - Free the CPP structure.
+
+int FreeCPPStruct(void)
+{
+    if (refCount)
+    {
+       free(cpp);
+       refCount--;
+    }
+    
+    return 1;
+}
+
+//Finalizing the Preprocessor.
+
+int FinalizePreprocessor(void)
+{
+   #  define CPP_STUFF true
+        #  ifdef CPP_STUFF
+            FreeAtomTable(atable);
+            FreeCPPStruct();
+            FreeScanner();
+       #  endif
+  return 0; 
+}
+
+
+///////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////// End of cppstruct.c //////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////////////////////
diff --git a/Compiler/Preprocessor/memory.c b/Compiler/Preprocessor/memory.c
new file mode 100644
index 0000000..1a70231
--- /dev/null
+++ b/Compiler/Preprocessor/memory.c
@@ -0,0 +1,163 @@
+//
+// 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.
+//
+/****************************************************************************\
+Copyright (c) 2002, NVIDIA Corporation.
+
+NVIDIA Corporation("NVIDIA") supplies this software to you in
+consideration of your agreement to the following terms, and your use,
+installation, modification or redistribution of this NVIDIA software
+constitutes acceptance of these terms.  If you do not agree with these
+terms, please do not use, install, modify or redistribute this NVIDIA
+software.
+
+In consideration of your agreement to abide by the following terms, and
+subject to these terms, NVIDIA grants you a personal, non-exclusive
+license, under NVIDIA's copyrights in this original NVIDIA software (the
+"NVIDIA Software"), to use, reproduce, modify and redistribute the
+NVIDIA Software, with or without modifications, in source and/or binary
+forms; provided that if you redistribute the NVIDIA Software, you must
+retain the copyright notice of NVIDIA, this notice and the following
+text and disclaimers in all such redistributions of the NVIDIA Software.
+Neither the name, trademarks, service marks nor logos of NVIDIA
+Corporation may be used to endorse or promote products derived from the
+NVIDIA Software without specific prior written permission from NVIDIA.
+Except as expressly stated in this notice, no other rights or licenses
+express or implied, are granted by NVIDIA herein, including but not
+limited to any patent rights that may be infringed by your derivative
+works or by other works in which the NVIDIA Software may be
+incorporated. No hardware is licensed hereunder. 
+
+THE NVIDIA SOFTWARE IS BEING PROVIDED ON AN "AS IS" BASIS, WITHOUT
+WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED,
+INCLUDING WITHOUT LIMITATION, WARRANTIES OR CONDITIONS OF TITLE,
+NON-INFRINGEMENT, MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR
+ITS USE AND OPERATION EITHER ALONE OR IN COMBINATION WITH OTHER
+PRODUCTS.
+
+IN NO EVENT SHALL NVIDIA BE LIABLE FOR ANY SPECIAL, INDIRECT,
+INCIDENTAL, EXEMPLARY, CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+TO, LOST PROFITS; PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) OR ARISING IN ANY WAY
+OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE
+NVIDIA SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT,
+TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF
+NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+\****************************************************************************/
+//
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+
+#ifdef __STDC99__
+#include <stdint.h>
+#elif defined (_WIN64)
+typedef unsigned __int64 uintptr_t;
+#else 
+typedef unsigned int uintptr_t;
+#endif
+
+#include "memory.h"
+
+// default alignment and chunksize, if called with 0 arguments
+#define CHUNKSIZE       (64*1024)
+#define ALIGN           8
+
+// we need to call the `real' malloc and free, not our replacements
+#undef malloc
+#undef free
+
+struct chunk {
+    struct chunk        *next;
+};
+
+struct cleanup {
+    struct cleanup      *next;
+    void                (*fn)(void *);
+    void                *arg;
+};
+
+struct MemoryPool_rec {
+    struct chunk        *next;
+    uintptr_t           free, end;
+    size_t              chunksize;
+    uintptr_t           alignmask;
+    struct cleanup      *cleanup;
+};
+
+MemoryPool *mem_CreatePool(size_t chunksize, unsigned int align)
+{
+    MemoryPool  *pool;
+
+    if (align == 0) align = ALIGN;
+    if (chunksize == 0) chunksize = CHUNKSIZE;
+    if (align & (align-1)) return 0;
+    if (chunksize < sizeof(MemoryPool)) return 0;
+    if (chunksize & (align-1)) return 0;
+    if (!(pool = malloc(chunksize))) return 0;
+    pool->next = 0;
+    pool->chunksize = chunksize;
+    pool->alignmask = (uintptr_t)(align)-1;  
+    pool->free = ((uintptr_t)(pool + 1) + pool->alignmask) & ~pool->alignmask;
+    pool->end = (uintptr_t)pool + chunksize;
+    pool->cleanup = 0;
+    return pool;
+}
+
+void mem_FreePool(MemoryPool *pool)
+{
+    struct cleanup      *cleanup;
+    struct chunk        *p, *next;
+
+    for (cleanup = pool->cleanup; cleanup; cleanup = cleanup->next) {
+        cleanup->fn(cleanup->arg);
+    }
+    for (p = (struct chunk *)pool; p; p = next) {
+        next = p->next;
+        free(p);
+    }
+}
+
+void *mem_Alloc(MemoryPool *pool, size_t size)
+{
+    struct chunk *ch;
+    void *rv = (void *)pool->free;
+    size = (size + pool->alignmask) & ~pool->alignmask;
+    if (size <= 0) size = pool->alignmask;
+    pool->free += size;
+    if (pool->free > pool->end || pool->free < (uintptr_t)rv) {
+        size_t minreq = (size + sizeof(struct chunk) + pool->alignmask)
+                      & ~pool->alignmask;
+        pool->free = (uintptr_t)rv;
+        if (minreq >= pool->chunksize) {
+            // request size is too big for the chunksize, so allocate it as
+            // a single chunk of the right size
+            ch = malloc(minreq);
+            if (!ch) return 0;
+        } else {
+            ch = malloc(pool->chunksize);
+            if (!ch) return 0;
+            pool->free = (uintptr_t)ch + minreq;
+            pool->end = (uintptr_t)ch + pool->chunksize;
+        }
+        ch->next = pool->next;
+        pool->next = ch;
+        rv = (void *)(((uintptr_t)(ch+1) + pool->alignmask) & ~pool->alignmask);
+    }
+    return rv;
+}
+
+int mem_AddCleanup(MemoryPool *pool, void (*fn)(void *), void *arg) {
+    struct cleanup *cleanup;
+
+    pool->free = (pool->free + sizeof(void *) - 1) & ~(sizeof(void *)-1);
+    cleanup = mem_Alloc(pool, sizeof(struct cleanup));
+    if (!cleanup) return -1;
+    cleanup->next = pool->cleanup;
+    cleanup->fn = fn;
+    cleanup->arg = arg;
+    pool->cleanup = cleanup;
+    return 0;
+}
diff --git a/Compiler/Preprocessor/memory.h b/Compiler/Preprocessor/memory.h
new file mode 100644
index 0000000..3da7989
--- /dev/null
+++ b/Compiler/Preprocessor/memory.h
@@ -0,0 +1,61 @@
+//
+// 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.
+//
+/****************************************************************************\
+Copyright (c) 2002, NVIDIA Corporation.
+
+NVIDIA Corporation("NVIDIA") supplies this software to you in
+consideration of your agreement to the following terms, and your use,
+installation, modification or redistribution of this NVIDIA software
+constitutes acceptance of these terms.  If you do not agree with these
+terms, please do not use, install, modify or redistribute this NVIDIA
+software.
+
+In consideration of your agreement to abide by the following terms, and
+subject to these terms, NVIDIA grants you a personal, non-exclusive
+license, under NVIDIA's copyrights in this original NVIDIA software (the
+"NVIDIA Software"), to use, reproduce, modify and redistribute the
+NVIDIA Software, with or without modifications, in source and/or binary
+forms; provided that if you redistribute the NVIDIA Software, you must
+retain the copyright notice of NVIDIA, this notice and the following
+text and disclaimers in all such redistributions of the NVIDIA Software.
+Neither the name, trademarks, service marks nor logos of NVIDIA
+Corporation may be used to endorse or promote products derived from the
+NVIDIA Software without specific prior written permission from NVIDIA.
+Except as expressly stated in this notice, no other rights or licenses
+express or implied, are granted by NVIDIA herein, including but not
+limited to any patent rights that may be infringed by your derivative
+works or by other works in which the NVIDIA Software may be
+incorporated. No hardware is licensed hereunder. 
+
+THE NVIDIA SOFTWARE IS BEING PROVIDED ON AN "AS IS" BASIS, WITHOUT
+WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED,
+INCLUDING WITHOUT LIMITATION, WARRANTIES OR CONDITIONS OF TITLE,
+NON-INFRINGEMENT, MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR
+ITS USE AND OPERATION EITHER ALONE OR IN COMBINATION WITH OTHER
+PRODUCTS.
+
+IN NO EVENT SHALL NVIDIA BE LIABLE FOR ANY SPECIAL, INDIRECT,
+INCIDENTAL, EXEMPLARY, CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+TO, LOST PROFITS; PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) OR ARISING IN ANY WAY
+OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE
+NVIDIA SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT,
+TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF
+NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+\****************************************************************************/
+//
+#ifndef __MEMORY_H
+#define __MEMORY_H
+
+typedef struct MemoryPool_rec MemoryPool;
+
+extern MemoryPool *mem_CreatePool(size_t chunksize, unsigned align);
+extern void mem_FreePool(MemoryPool *);
+extern void *mem_Alloc(MemoryPool *p, size_t size);
+extern void *mem_Realloc(MemoryPool *p, void *old, size_t oldsize, size_t newsize);
+extern int mem_AddCleanup(MemoryPool *p, void (*fn)(void *), void *arg);
+
+#endif /* __MEMORY_H */
diff --git a/Compiler/Preprocessor/parser.h b/Compiler/Preprocessor/parser.h
new file mode 100644
index 0000000..91a6200
--- /dev/null
+++ b/Compiler/Preprocessor/parser.h
@@ -0,0 +1,98 @@
+//
+// 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.
+//
+/****************************************************************************\
+Copyright (c) 2002, NVIDIA Corporation.
+
+NVIDIA Corporation("NVIDIA") supplies this software to you in
+consideration of your agreement to the following terms, and your use,
+installation, modification or redistribution of this NVIDIA software
+constitutes acceptance of these terms.  If you do not agree with these
+terms, please do not use, install, modify or redistribute this NVIDIA
+software.
+
+In consideration of your agreement to abide by the following terms, and
+subject to these terms, NVIDIA grants you a personal, non-exclusive
+license, under NVIDIA's copyrights in this original NVIDIA software (the
+"NVIDIA Software"), to use, reproduce, modify and redistribute the
+NVIDIA Software, with or without modifications, in source and/or binary
+forms; provided that if you redistribute the NVIDIA Software, you must
+retain the copyright notice of NVIDIA, this notice and the following
+text and disclaimers in all such redistributions of the NVIDIA Software.
+Neither the name, trademarks, service marks nor logos of NVIDIA
+Corporation may be used to endorse or promote products derived from the
+NVIDIA Software without specific prior written permission from NVIDIA.
+Except as expressly stated in this notice, no other rights or licenses
+express or implied, are granted by NVIDIA herein, including but not
+limited to any patent rights that may be infringed by your derivative
+works or by other works in which the NVIDIA Software may be
+incorporated. No hardware is licensed hereunder. 
+
+THE NVIDIA SOFTWARE IS BEING PROVIDED ON AN "AS IS" BASIS, WITHOUT
+WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED,
+INCLUDING WITHOUT LIMITATION, WARRANTIES OR CONDITIONS OF TITLE,
+NON-INFRINGEMENT, MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR
+ITS USE AND OPERATION EITHER ALONE OR IN COMBINATION WITH OTHER
+PRODUCTS.
+
+IN NO EVENT SHALL NVIDIA BE LIABLE FOR ANY SPECIAL, INDIRECT,
+INCIDENTAL, EXEMPLARY, CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+TO, LOST PROFITS; PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) OR ARISING IN ANY WAY
+OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE
+NVIDIA SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT,
+TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF
+NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+\****************************************************************************/
+
+#ifndef BISON_PARSER_H
+# define BISON_PARSER_H
+
+#ifndef yystypepp
+typedef struct {
+    int    sc_int;
+    float  sc_fval;
+    int    sc_ident;
+	char   symbol_name[MAX_SYMBOL_NAME_LEN+1];
+} yystypepp;
+
+# define YYSTYPE_IS_TRIVIAL 1
+#endif
+# define	CPP_AND_OP	        257
+# define	CPP_SUB_ASSIGN	    259
+# define	CPP_MOD_ASSIGN	    260
+# define	CPP_ADD_ASSIGN	261
+# define	CPP_DIV_ASSIGN	262
+# define	CPP_MUL_ASSIGN	263
+# define	CPP_EQ_OP	        264
+# define    CPP_XOR_OP         265 
+# define	ERROR_SY	    266
+# define	CPP_FLOATCONSTANT	267
+# define	CPP_GE_OP	        268
+# define	CPP_RIGHT_OP        269
+# define	CPP_IDENTIFIER	    270
+# define	CPP_INTCONSTANT	    271
+# define	CPP_LE_OP	        272
+# define	CPP_LEFT_OP	        273
+# define	CPP_DEC_OP	274
+# define	CPP_NE_OP	        275
+# define	CPP_OR_OP	        276
+# define	CPP_INC_OP	    277
+# define	CPP_STRCONSTANT	    278
+# define	CPP_TYPEIDENTIFIER	279
+
+# define	FIRST_USER_TOKEN_SY	289
+
+# define	CPP_RIGHT_ASSIGN	    280
+# define	CPP_LEFT_ASSIGN	    281
+# define	CPP_AND_ASSIGN	282
+# define	CPP_OR_ASSIGN  	283
+# define	CPP_XOR_ASSIGN	284
+# define	CPP_LEFT_BRACKET	285
+# define	CPP_RIGHT_BRACKET	286
+# define	CPP_LEFT_BRACE	287
+# define	CPP_RIGHT_BRACE	288
+
+#endif /* not BISON_PARSER_H */
diff --git a/Compiler/Preprocessor/preprocess.h b/Compiler/Preprocessor/preprocess.h
new file mode 100644
index 0000000..323cd1e
--- /dev/null
+++ b/Compiler/Preprocessor/preprocess.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.
+//
+/****************************************************************************\
+Copyright (c) 2002, NVIDIA Corporation.
+
+NVIDIA Corporation("NVIDIA") supplies this software to you in
+consideration of your agreement to the following terms, and your use,
+installation, modification or redistribution of this NVIDIA software
+constitutes acceptance of these terms.  If you do not agree with these
+terms, please do not use, install, modify or redistribute this NVIDIA
+software.
+
+In consideration of your agreement to abide by the following terms, and
+subject to these terms, NVIDIA grants you a personal, non-exclusive
+license, under NVIDIA's copyrights in this original NVIDIA software (the
+"NVIDIA Software"), to use, reproduce, modify and redistribute the
+NVIDIA Software, with or without modifications, in source and/or binary
+forms; provided that if you redistribute the NVIDIA Software, you must
+retain the copyright notice of NVIDIA, this notice and the following
+text and disclaimers in all such redistributions of the NVIDIA Software.
+Neither the name, trademarks, service marks nor logos of NVIDIA
+Corporation may be used to endorse or promote products derived from the
+NVIDIA Software without specific prior written permission from NVIDIA.
+Except as expressly stated in this notice, no other rights or licenses
+express or implied, are granted by NVIDIA herein, including but not
+limited to any patent rights that may be infringed by your derivative
+works or by other works in which the NVIDIA Software may be
+incorporated. No hardware is licensed hereunder. 
+
+THE NVIDIA SOFTWARE IS BEING PROVIDED ON AN "AS IS" BASIS, WITHOUT
+WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED,
+INCLUDING WITHOUT LIMITATION, WARRANTIES OR CONDITIONS OF TITLE,
+NON-INFRINGEMENT, MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR
+ITS USE AND OPERATION EITHER ALONE OR IN COMBINATION WITH OTHER
+PRODUCTS.
+
+IN NO EVENT SHALL NVIDIA BE LIABLE FOR ANY SPECIAL, INDIRECT,
+INCIDENTAL, EXEMPLARY, CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+TO, LOST PROFITS; PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) OR ARISING IN ANY WAY
+OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE
+NVIDIA SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT,
+TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF
+NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+\****************************************************************************/
+
+# include "slglobals.h"
+extern CPPStruct *cpp;
+int InitCPPStruct(void);
+int InitScanner(CPPStruct *cpp);
+int InitAtomTable(AtomTable *atable, int htsize);
+int ScanFromString(char *s);
+char* GetStringOfAtom(AtomTable *atable, int atom);
diff --git a/Compiler/Preprocessor/scanner.c b/Compiler/Preprocessor/scanner.c
new file mode 100644
index 0000000..fcdf751
--- /dev/null
+++ b/Compiler/Preprocessor/scanner.c
@@ -0,0 +1,766 @@
+//
+// 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.
+//
+/****************************************************************************\
+Copyright (c) 2002, NVIDIA Corporation.
+
+NVIDIA Corporation("NVIDIA") supplies this software to you in
+consideration of your agreement to the following terms, and your use,
+installation, modification or redistribution of this NVIDIA software
+constitutes acceptance of these terms.  If you do not agree with these
+terms, please do not use, install, modify or redistribute this NVIDIA
+software.
+
+In consideration of your agreement to abide by the following terms, and
+subject to these terms, NVIDIA grants you a personal, non-exclusive
+license, under NVIDIA's copyrights in this original NVIDIA software (the
+"NVIDIA Software"), to use, reproduce, modify and redistribute the
+NVIDIA Software, with or without modifications, in source and/or binary
+forms; provided that if you redistribute the NVIDIA Software, you must
+retain the copyright notice of NVIDIA, this notice and the following
+text and disclaimers in all such redistributions of the NVIDIA Software.
+Neither the name, trademarks, service marks nor logos of NVIDIA
+Corporation may be used to endorse or promote products derived from the
+NVIDIA Software without specific prior written permission from NVIDIA.
+Except as expressly stated in this notice, no other rights or licenses
+express or implied, are granted by NVIDIA herein, including but not
+limited to any patent rights that may be infringed by your derivative
+works or by other works in which the NVIDIA Software may be
+incorporated. No hardware is licensed hereunder. 
+
+THE NVIDIA SOFTWARE IS BEING PROVIDED ON AN "AS IS" BASIS, WITHOUT
+WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED,
+INCLUDING WITHOUT LIMITATION, WARRANTIES OR CONDITIONS OF TITLE,
+NON-INFRINGEMENT, MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR
+ITS USE AND OPERATION EITHER ALONE OR IN COMBINATION WITH OTHER
+PRODUCTS.
+
+IN NO EVENT SHALL NVIDIA BE LIABLE FOR ANY SPECIAL, INDIRECT,
+INCIDENTAL, EXEMPLARY, CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+TO, LOST PROFITS; PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) OR ARISING IN ANY WAY
+OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE
+NVIDIA SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT,
+TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF
+NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+\****************************************************************************/
+//
+// scanner.c
+//
+
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#if 0
+    #include <ieeefp.h>
+    #else
+    #define isinff(x) (((*(int *)&(x) & 0x7f800000L)==0x7f800000L) && \
+                       ((*(int *)&(x) & 0x007fffffL)==0000000000L))
+#endif
+
+#include "slglobals.h"
+
+
+typedef struct StringInputSrc {
+    InputSrc base;
+    char *p;
+} StringInputSrc;
+
+static int eof_scan(InputSrc *is, yystypepp * yylvalpp)
+{
+    return EOF;
+} // eof_scan
+
+static void noop(InputSrc *in, int ch, yystypepp * yylvalpp) {}
+
+static InputSrc eof_inputsrc = { 0, &eof_scan, &eof_scan, &noop };
+
+static int byte_scan(InputSrc *, yystypepp * yylvalpp);
+
+#define EOL_SY '\n'
+
+#if defined(_WIN32)
+    #define DBG_BREAKPOINT() __asm int 3
+    #elif defined(_M_AMD64)
+    #define DBG_BREAKPOINT() assert(!"Dbg_Breakpoint");
+    #else
+    #define DBG_BREAKPOINT()
+    #endif
+
+    #if defined(_WIN32) && !defined(_M_AMD64)
+    __int64 RDTSC ( void ) {
+
+        __int64 v;
+    
+        __asm __emit 0x0f
+        __asm __emit 0x31
+        __asm mov dword ptr v, eax
+        __asm mov dword ptr v+4, edx
+    
+        return v;
+    }
+#endif
+
+
+int InitScanner(CPPStruct *cpp)
+{
+    // Add various atoms needed by the CPP line scanner:
+    if (!InitCPP())
+        return 0;
+
+    cpp->mostRecentToken = 0;
+    cpp->tokenLoc = &cpp->ltokenLoc;
+
+    cpp->ltokenLoc.file = 0;
+    cpp->ltokenLoc.line = 0;
+
+    cpp->currentInput = &eof_inputsrc;
+    cpp->previous_token = '\n';
+    cpp->notAVersionToken = 0;
+
+    return 1;
+} // InitScanner
+
+int FreeScanner(void)
+{
+    return (FreeCPP());
+}
+
+/*
+ * str_getch()
+ * takes care of reading from multiple strings.
+ * returns the next-char from the input stream.
+ * returns EOF when the complete shader is parsed.
+ */
+static int str_getch(StringInputSrc *in)
+{
+	for(;;){
+	   if (*in->p){
+	      if (*in->p == '\n') {
+             in->base.line++;
+             IncLineNumber();
+          }
+          return *in->p++;
+	   }
+	   if(++(cpp->PaWhichStr) < cpp->PaArgc){
+		  free(in);
+		  SetStringNumber(cpp->PaWhichStr);
+    	  SetLineNumber(1);
+		  ScanFromString(cpp->PaArgv[cpp->PaWhichStr]);
+		  in=(StringInputSrc*)cpp->currentInput;
+	      continue;             
+	   }
+	   else{
+	      cpp->currentInput = in->base.prev;
+	      cpp->PaWhichStr=0;
+          free(in);
+          return EOF;
+       }  
+	}
+} // str_getch
+
+static void str_ungetch(StringInputSrc *in, int ch, yystypepp *type) {
+    if (in->p[-1] == ch)in->p--;
+	else {
+		*(in->p)='\0'; //this would take care of shifting to the previous string.
+	    cpp->PaWhichStr--;
+	}  
+	if (ch == '\n') {
+        in->base.line--;
+        DecLineNumber();
+    }
+} // str_ungetch
+
+int ScanFromString(char *s)
+{
+    
+	StringInputSrc *in = malloc(sizeof(StringInputSrc));
+    memset(in, 0, sizeof(StringInputSrc));
+	in->p = s;
+    in->base.line = 1;
+    in->base.scan = byte_scan;
+    in->base.getch = (int (*)(InputSrc *, yystypepp *))str_getch;
+    in->base.ungetch = (void (*)(InputSrc *, int, yystypepp *))str_ungetch;
+    in->base.prev = cpp->currentInput;
+    cpp->currentInput = &in->base;
+
+    return 1;
+} // ScanFromString;
+
+
+///////////////////////////////////////////////////////////////////////////////////////////////
+/////////////////////////////////// Floating point constants: /////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////////////////////
+/*
+ * lBuildFloatValue() - Quick and dirty conversion to floating point.  Since all
+ *         we need is single precision this should be quite precise.
+ */
+
+static float lBuildFloatValue(const char *str, int len, int exp)
+{
+    double val, expval, ten;
+    int ii, llen, absexp;
+    float rv;
+
+    val = 0.0;
+    llen = len;
+    for (ii = 0; ii < len; ii++)
+        val = val*10.0 + (str[ii] - '0');
+    if (exp != 0) {
+        absexp = exp > 0 ? exp : -exp;
+        expval = 1.0f;
+        ten = 10.0;
+        while (absexp) {
+            if (absexp & 1)
+                expval *= ten;
+            ten *= ten;
+            absexp >>= 1;
+        }
+        if (exp >= 0) {
+            val *= expval;
+        } else {
+            val /= expval;
+        }
+    }
+    rv = (float)val;
+    if (isinff(rv)) {
+		CPPErrorToInfoLog(" ERROR___FP_CONST_OVERFLOW");
+    }
+    return rv;
+} // lBuildFloatValue
+
+
+/*
+ * lFloatConst() - Scan a floating point constant.  Assumes that the scanner
+ *         has seen at least one digit, followed by either a decimal '.' or the
+ *         letter 'e'.
+ */
+
+static int lFloatConst(char *str, int len, int ch, yystypepp * yylvalpp)
+{
+    int HasDecimal, declen, exp, ExpSign;
+    int str_len;
+    float lval;
+    
+    HasDecimal = 0;
+    declen = 0;
+    exp = 0;
+	
+    str_len=len;
+    if (ch == '.') {
+		str[len++]=ch;
+        HasDecimal = 1;
+        ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
+        while (ch >= '0' && ch <= '9') {
+            if (len < MAX_SYMBOL_NAME_LEN) {
+                declen++;
+                if (len > 0 || ch != '0') {
+                    str[len] = ch;
+                    len++;str_len++;
+                }
+                ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
+            } else {
+                CPPErrorToInfoLog("ERROR___FP_CONST_TOO_LONG");
+                len = 1,str_len=1;
+            }
+        }
+    }
+
+    // Exponent:
+
+    if (ch == 'e' || ch == 'E') {
+        ExpSign = 1;
+		str[len++]=ch;
+        ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
+        if (ch == '+') {
+            str[len++]=ch;  
+			ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
+        } else if (ch == '-') {
+            ExpSign = -1;
+			str[len++]=ch;
+            ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
+        }
+        if (ch >= '0' && ch <= '9') {
+            while (ch >= '0' && ch <= '9') {
+                exp = exp*10 + ch - '0';
+				str[len++]=ch;
+                ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
+            }
+        } else {
+            CPPErrorToInfoLog("ERROR___ERROR_IN_EXPONENT");
+        }
+        exp *= ExpSign;
+    }
+      
+    if (len == 0) {
+        lval = 0.0f;
+		strcpy(str,"0.0");
+    } else {
+        str[len]='\0';      
+        lval = lBuildFloatValue(str, str_len, exp - declen);
+    }
+    // Suffix:
+    
+    yylvalpp->sc_fval = lval;
+    strcpy(yylvalpp->symbol_name,str);
+    cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp);            
+    return CPP_FLOATCONSTANT;
+} // lFloatConst
+
+///////////////////////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////// Normal Scanner //////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////////////////////
+    
+static int byte_scan(InputSrc *in, yystypepp * yylvalpp)
+{
+    char symbol_name[MAX_SYMBOL_NAME_LEN + 1];
+    char string_val[MAX_STRING_LEN + 1];
+    int AlreadyComplained;
+    int len, ch, ii, ival = 0;
+
+    for (;;) {
+        yylvalpp->sc_int = 0;
+        ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
+		
+        while (ch == ' ' || ch == '\t' || ch == '\r') {
+            yylvalpp->sc_int = 1;
+            ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
+        }
+		
+        cpp->ltokenLoc.file = cpp->currentInput->name;
+        cpp->ltokenLoc.line = cpp->currentInput->line;
+        len = 0;
+        switch (ch) {
+        default:
+			return ch; // Single character token
+        case EOF:
+            return -1;
+		case 'A': case 'B': case 'C': case 'D': case 'E':
+        case 'F': case 'G': case 'H': case 'I': case 'J':
+        case 'K': case 'L': case 'M': case 'N': case 'O':
+        case 'P': case 'Q': case 'R': case 'S': case 'T':
+        case 'U': case 'V': case 'W': case 'X': case 'Y':
+        case 'Z': case '_':
+        case 'a': case 'b': case 'c': case 'd': case 'e':
+        case 'f': case 'g': case 'h': case 'i': case 'j':
+        case 'k': case 'l': case 'm': case 'n': case 'o':
+        case 'p': case 'q': case 'r': case 's': case 't':
+        case 'u': case 'v': case 'w': case 'x': case 'y':
+        case 'z':            
+            do {
+                if (len < MAX_SYMBOL_NAME_LEN) {
+                    symbol_name[len] = ch;
+                    len++;
+                    ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);					
+                } else {
+                    ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
+                }
+            } while ((ch >= 'a' && ch <= 'z') ||
+                     (ch >= 'A' && ch <= 'Z') ||
+                     (ch >= '0' && ch <= '9') ||
+                     ch == '_');
+            if (len >= MAX_SYMBOL_NAME_LEN)
+                len = MAX_SYMBOL_NAME_LEN - 1;
+            symbol_name[len] = '\0';
+            cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp);
+            yylvalpp->sc_ident = LookUpAddString(atable, symbol_name);
+            return CPP_IDENTIFIER;
+            break;
+        case '0':
+            yylvalpp->symbol_name[len++] = ch;
+            ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
+            if (ch == 'x' || ch == 'X') {
+				yylvalpp->symbol_name[len++] = ch;
+                ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
+                if ((ch >= '0' && ch <= '9') ||
+                    (ch >= 'A' && ch <= 'F') ||
+                    (ch >= 'a' && ch <= 'f'))
+                {
+                    AlreadyComplained = 0;
+                    ival = 0;
+                    do {
+						yylvalpp->symbol_name[len++] = ch;
+                        if (ival <= 0x0fffffff) {
+                            if (ch >= '0' && ch <= '9') {
+                                ii = ch - '0';
+                            } else if (ch >= 'A' && ch <= 'F') {
+                                ii = ch - 'A' + 10;
+                            } else {
+                                ii = ch - 'a' + 10;
+                            }
+                            ival = (ival << 4) | ii;
+                        } else {
+                            if (!AlreadyComplained)
+                                CPPErrorToInfoLog("ERROR___HEX_CONST_OVERFLOW");
+                            AlreadyComplained = 1;
+                        }
+                        ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
+                    } while ((ch >= '0' && ch <= '9') ||
+                             (ch >= 'A' && ch <= 'F') ||
+                             (ch >= 'a' && ch <= 'f'));
+                } else {
+                    CPPErrorToInfoLog("ERROR___ERROR_IN_HEX_CONSTANT");
+                }
+                yylvalpp->symbol_name[len] = '\0';
+				cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp);
+				yylvalpp->sc_int = ival;
+                return CPP_INTCONSTANT;
+            } else if (ch >= '0' && ch <= '7') { // octal integer constants
+                AlreadyComplained = 0;
+                ival = 0;
+                do {
+                    yylvalpp->symbol_name[len++] = ch;
+                    if (ival <= 0x1fffffff) {
+                        ii = ch - '0';
+                        ival = (ival << 3) | ii;
+                    } else {
+                        if (!AlreadyComplained)
+                           CPPErrorToInfoLog("ERROR___OCT_CONST_OVERFLOW");
+                        AlreadyComplained = 1;
+                    }
+                    ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
+                } while (ch >= '0' && ch <= '7');
+                if (ch == '.' || ch == 'e' || ch == 'f' || ch == 'h' || ch == 'x'|| ch == 'E') 
+                     return lFloatConst(yylvalpp->symbol_name, len, ch, yylvalpp);
+                yylvalpp->symbol_name[len] = '\0';
+				cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp);
+				yylvalpp->sc_int = ival;
+                return CPP_INTCONSTANT;
+            } else {
+				cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp);
+				ch = '0';
+            }
+            // Fall through...
+        case '1': case '2': case '3': case '4':
+        case '5': case '6': case '7': case '8': case '9':
+            do {
+                if (len < MAX_SYMBOL_NAME_LEN) {
+                    if (len > 0 || ch != '0') {
+                        yylvalpp->symbol_name[len] = ch;
+                   len++;
+                    }
+                    ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
+                }
+            } while (ch >= '0' && ch <= '9');
+            if (ch == '.' || ch == 'e' || ch == 'f' || ch == 'h' || ch == 'x'|| ch == 'E') {
+                return lFloatConst(yylvalpp->symbol_name, len, ch, yylvalpp);
+            } else {
+                yylvalpp->symbol_name[len] = '\0';
+				cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp);
+                ival = 0;
+                AlreadyComplained = 0;
+                for (ii = 0; ii < len; ii++) {
+                    ch = yylvalpp->symbol_name[ii] - '0';
+                    if ((ival > 214748364) || (ival == 214748364 && ch >= 8)) {
+                        if (!AlreadyComplained)
+                           CPPErrorToInfoLog("ERROR___INTEGER_CONST_OVERFLOW");
+                        AlreadyComplained = 1;
+                    }
+                    ival = ival*10 + ch;
+                }
+                yylvalpp->sc_int = ival;
+                if(ival==0)
+                   strcpy(yylvalpp->symbol_name,"0");
+                return CPP_INTCONSTANT;
+            }
+            break;
+        case '-':
+            ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
+            if (ch == '-') {
+                return CPP_DEC_OP;
+            } else if (ch == '=') {
+                return CPP_SUB_ASSIGN;
+            } else {
+                cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp);
+                return '-';
+            }
+        case '+':
+            ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
+            if (ch == '+') {
+                return CPP_INC_OP;
+            } else if (ch == '=') {
+                return CPP_ADD_ASSIGN;
+            } else {
+                cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp);
+                return '+';
+            }
+        case '*':
+            ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
+            if (ch == '=') {
+                return CPP_MUL_ASSIGN;
+            } else {
+                cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp);
+                return '*';
+            }
+        case '%':
+            ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
+            if (ch == '=') {
+                return CPP_MOD_ASSIGN;
+            } else if (ch == '>'){
+                return CPP_RIGHT_BRACE;
+            } else {
+                cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp);
+                return '%';
+            }
+        case ':':
+            ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
+            if (ch == '>') {
+                return CPP_RIGHT_BRACKET;
+            } else {
+                cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp);
+                return ':';
+            }
+        case '^':
+            ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
+            if (ch == '^') {
+                return CPP_XOR_OP;
+            } else {
+                if (ch == '=')
+                    return CPP_XOR_ASSIGN;
+                else{
+                  cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp);
+                  return '^';
+                }
+            }
+        
+        case '=':
+            ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
+            if (ch == '=') {
+                return CPP_EQ_OP;
+            } else {
+                cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp);
+                return '=';
+            }
+        case '!':
+            ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
+            if (ch == '=') {
+                return CPP_NE_OP;
+            } else {
+                cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp);
+                return '!';
+            }
+        case '|':
+            ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
+            if (ch == '|') {
+                return CPP_OR_OP;
+            } else {
+                if (ch == '=')
+                    return CPP_OR_ASSIGN;
+                else{
+                  cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp);
+                  return '|';
+                }
+            }
+        case '&':
+            ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
+            if (ch == '&') {
+                return CPP_AND_OP;
+            } else {
+                if (ch == '=')
+                    return CPP_AND_ASSIGN;
+                else{
+                  cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp);
+                  return '&';
+                }
+            }
+        case '<':
+            ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
+            if (ch == '<') {
+                ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
+                if(ch == '=')
+                    return CPP_LEFT_ASSIGN;
+                else{
+                    cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp);
+                    return CPP_LEFT_OP;
+                }
+            } else {
+                if (ch == '=') {
+                    return CPP_LE_OP;
+                } else {
+                    if (ch == '%')
+                        return CPP_LEFT_BRACE;
+                    else if (ch == ':')
+                        return CPP_LEFT_BRACKET;
+                    else{
+                        cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp);
+                        return '<';
+                    }
+                }
+            }
+        case '>':
+            ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
+            if (ch == '>') {
+                ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
+                if(ch == '=')
+                    return CPP_RIGHT_ASSIGN;
+                else{
+                    cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp);
+                    return CPP_RIGHT_OP;
+                }
+            } else {
+                if (ch == '=') {
+                    return CPP_GE_OP;
+                } else {
+                    cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp);
+                    return '>';
+                }
+            }
+        case '.':
+            ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
+            if (ch >= '0' && ch <= '9') {
+                cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp);
+                return lFloatConst(yylvalpp->symbol_name, 0, '.', yylvalpp);
+            } else {
+                if (ch == '.') {
+                    return -1; // Special EOF hack
+                } else {
+                    cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp);
+                    return '.';
+                }
+            }
+        case '/':
+            ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
+            if (ch == '/') {
+                do {
+                    ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
+                } while (ch != '\n' && ch != EOF);
+                if (ch == EOF)
+                    return -1;
+                return '\n';
+            } else if (ch == '*') {
+                int nlcount = 0;
+                ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
+                do {
+                    while (ch != '*') {
+                        if (ch == '\n') nlcount++;
+                        if (ch == EOF) {
+                            CPPErrorToInfoLog("ERROR___EOF_IN_COMMENT");
+                            return -1;
+                        }
+                        ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
+                    }
+                    ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
+                    if (ch == EOF) {
+                        CPPErrorToInfoLog("ERROR___EOF_IN_COMMENT");
+                        return -1;
+                    }
+                } while (ch != '/');
+                if (nlcount) {
+                    return '\n';
+                }
+                // Go try it again...
+            } else if (ch == '=') {
+                return CPP_DIV_ASSIGN;
+            } else {
+                cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp);
+                return '/';
+            }
+            break;
+        case '"':
+            ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
+            while (ch != '"' && ch != '\n' && ch != EOF) {
+                if (ch == '\\') {
+                    ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
+                    if (ch == '\n' || ch == EOF) {
+                        break;
+                    }
+                }
+                if (len < MAX_STRING_LEN) {
+                    string_val[len] = ch;
+                    len++;
+                    ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
+                }
+            };
+            string_val[len] = '\0';
+            if (ch == '"') {
+                yylvalpp->sc_ident = LookUpAddString(atable, string_val);
+                return CPP_STRCONSTANT;
+            } else {
+                CPPErrorToInfoLog("ERROR___CPP_EOL_IN_STRING");
+                return ERROR_SY;
+            }
+        }
+    }
+} // byte_scan
+
+int yylex_CPP(char* buf, int maxSize)
+{    
+	yystypepp yylvalpp;
+    int token = '\n';   
+
+    for(;;) {
+
+        char* tokenString = 0;
+        token = cpp->currentInput->scan(cpp->currentInput, &yylvalpp);
+		if(check_EOF(token))
+		    return 0;
+        if (token == '#') {
+            if (cpp->previous_token == '\n'|| cpp->previous_token == 0) {
+			    token = readCPPline(&yylvalpp);
+                if(check_EOF(token))
+                    return 0;
+			    continue;
+            } else {
+                CPPErrorToInfoLog("preprocessor command must not be preceded by any other statement in that line");
+                return 0;
+            }
+        }
+        cpp->previous_token = token;
+        // expand macros
+        if (token == CPP_IDENTIFIER && MacroExpand(yylvalpp.sc_ident, &yylvalpp)) {
+            cpp->notAVersionToken = 1;
+            continue;
+        }
+        
+        if (token == '\n')
+            continue;
+          
+        if (token == CPP_IDENTIFIER) {                
+            cpp->notAVersionToken = 1;
+            tokenString = GetStringOfAtom(atable,yylvalpp.sc_ident);
+        } else if (token == CPP_FLOATCONSTANT||token == CPP_INTCONSTANT){             
+            cpp->notAVersionToken = 1;            
+            tokenString = yylvalpp.symbol_name;
+		} else {            
+            cpp->notAVersionToken = 1;            
+            tokenString = GetStringOfAtom(atable,token);
+	    }
+
+        if (tokenString) {
+            if ((signed)strlen(tokenString) >= maxSize) {
+                cpp->tokensBeforeEOF = 1;
+                return maxSize;               
+            } else  if (strlen(tokenString) > 0) {
+			    strcpy(buf, tokenString);
+                cpp->tokensBeforeEOF = 1;
+                return (int)strlen(tokenString);
+            }  
+
+            return 0;
+        }
+    }
+
+    return 0;
+} // yylex
+
+//Checks if the token just read is EOF or not.
+int check_EOF(int token)
+{
+   if(token==-1){
+       if(cpp->ifdepth >0){
+		CPPErrorToInfoLog("#endif missing!! Compilation stopped");
+        cpp->CompileError=1;
+       }
+      return 1;
+   }
+   return 0;
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////
+/////////////////////////////////////// End of scanner.c //////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////////////////////
+
diff --git a/Compiler/Preprocessor/scanner.h b/Compiler/Preprocessor/scanner.h
new file mode 100644
index 0000000..288a090
--- /dev/null
+++ b/Compiler/Preprocessor/scanner.h
@@ -0,0 +1,90 @@
+//
+// 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.
+//
+/****************************************************************************\
+Copyright (c) 2002, NVIDIA Corporation.
+
+NVIDIA Corporation("NVIDIA") supplies this software to you in
+consideration of your agreement to the following terms, and your use,
+installation, modification or redistribution of this NVIDIA software
+constitutes acceptance of these terms.  If you do not agree with these
+terms, please do not use, install, modify or redistribute this NVIDIA
+software.
+
+In consideration of your agreement to abide by the following terms, and
+subject to these terms, NVIDIA grants you a personal, non-exclusive
+license, under NVIDIA's copyrights in this original NVIDIA software (the
+"NVIDIA Software"), to use, reproduce, modify and redistribute the
+NVIDIA Software, with or without modifications, in source and/or binary
+forms; provided that if you redistribute the NVIDIA Software, you must
+retain the copyright notice of NVIDIA, this notice and the following
+text and disclaimers in all such redistributions of the NVIDIA Software.
+Neither the name, trademarks, service marks nor logos of NVIDIA
+Corporation may be used to endorse or promote products derived from the
+NVIDIA Software without specific prior written permission from NVIDIA.
+Except as expressly stated in this notice, no other rights or licenses
+express or implied, are granted by NVIDIA herein, including but not
+limited to any patent rights that may be infringed by your derivative
+works or by other works in which the NVIDIA Software may be
+incorporated. No hardware is licensed hereunder. 
+
+THE NVIDIA SOFTWARE IS BEING PROVIDED ON AN "AS IS" BASIS, WITHOUT
+WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED,
+INCLUDING WITHOUT LIMITATION, WARRANTIES OR CONDITIONS OF TITLE,
+NON-INFRINGEMENT, MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR
+ITS USE AND OPERATION EITHER ALONE OR IN COMBINATION WITH OTHER
+PRODUCTS.
+
+IN NO EVENT SHALL NVIDIA BE LIABLE FOR ANY SPECIAL, INDIRECT,
+INCIDENTAL, EXEMPLARY, CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+TO, LOST PROFITS; PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) OR ARISING IN ANY WAY
+OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE
+NVIDIA SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT,
+TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF
+NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+\****************************************************************************/
+//
+// scanner.h
+//
+
+#if !defined(__SCANNER_H)
+#define __SCANNER_H 1
+
+#define MAX_SYMBOL_NAME_LEN 128
+#define MAX_STRING_LEN 512
+
+#include "parser.h"
+
+// Not really atom table stuff but needed first...
+
+typedef struct SourceLoc_Rec {
+    unsigned short file, line;
+} SourceLoc;
+
+int yyparse (void);
+
+int yylex_CPP(char* buf, int maxSize);
+
+typedef struct InputSrc {
+    struct InputSrc	*prev;
+    int			(*scan)(struct InputSrc *, yystypepp *);
+    int			(*getch)(struct InputSrc *, yystypepp *);
+    void		(*ungetch)(struct InputSrc *, int, yystypepp *);
+    int			name;  /* atom */
+    int			line;
+} InputSrc;
+
+int InitScanner(CPPStruct *cpp);   // Intialise the cpp scanner. 
+int ScanFromString(char *);      // Start scanning the input from the string mentioned.
+int check_EOF(int);              // check if we hit a EOF abruptly 
+void CPPErrorToInfoLog(char *);   // sticking the msg,line into the Shader's.Info.log
+void SetLineNumber(int);
+void SetStringNumber(int);
+void IncLineNumber(void);
+void DecLineNumber(void);
+int FreeScanner(void);                 // Free the cpp scanner
+#endif // !(defined(__SCANNER_H)
+
diff --git a/Compiler/Preprocessor/slglobals.h b/Compiler/Preprocessor/slglobals.h
new file mode 100644
index 0000000..852502f
--- /dev/null
+++ b/Compiler/Preprocessor/slglobals.h
@@ -0,0 +1,87 @@
+//
+// 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.
+//
+/****************************************************************************\
+Copyright (c) 2002, NVIDIA Corporation.
+
+NVIDIA Corporation("NVIDIA") supplies this software to you in
+consideration of your agreement to the following terms, and your use,
+installation, modification or redistribution of this NVIDIA software
+constitutes acceptance of these terms.  If you do not agree with these
+terms, please do not use, install, modify or redistribute this NVIDIA
+software.
+
+In consideration of your agreement to abide by the following terms, and
+subject to these terms, NVIDIA grants you a personal, non-exclusive
+license, under NVIDIA's copyrights in this original NVIDIA software (the
+"NVIDIA Software"), to use, reproduce, modify and redistribute the
+NVIDIA Software, with or without modifications, in source and/or binary
+forms; provided that if you redistribute the NVIDIA Software, you must
+retain the copyright notice of NVIDIA, this notice and the following
+text and disclaimers in all such redistributions of the NVIDIA Software.
+Neither the name, trademarks, service marks nor logos of NVIDIA
+Corporation may be used to endorse or promote products derived from the
+NVIDIA Software without specific prior written permission from NVIDIA.
+Except as expressly stated in this notice, no other rights or licenses
+express or implied, are granted by NVIDIA herein, including but not
+limited to any patent rights that may be infringed by your derivative
+works or by other works in which the NVIDIA Software may be
+incorporated. No hardware is licensed hereunder. 
+
+THE NVIDIA SOFTWARE IS BEING PROVIDED ON AN "AS IS" BASIS, WITHOUT
+WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED,
+INCLUDING WITHOUT LIMITATION, WARRANTIES OR CONDITIONS OF TITLE,
+NON-INFRINGEMENT, MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR
+ITS USE AND OPERATION EITHER ALONE OR IN COMBINATION WITH OTHER
+PRODUCTS.
+
+IN NO EVENT SHALL NVIDIA BE LIABLE FOR ANY SPECIAL, INDIRECT,
+INCIDENTAL, EXEMPLARY, CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+TO, LOST PROFITS; PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) OR ARISING IN ANY WAY
+OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE
+NVIDIA SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT,
+TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF
+NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+\****************************************************************************/
+//
+// slglobals.h
+//
+
+#if !defined(__SLGLOBALS_H)
+#define __SLGLOBALS_H 1
+
+typedef struct CPPStruct_Rec CPPStruct;
+
+extern CPPStruct *cpp;
+
+#undef  CPPC_DEBUG_THE_COMPILER
+#if defined(_DEBUG)
+#define CPPC_DEBUG_THE_COMPILER 1
+#endif
+
+#undef  CPPC_ENABLE_TOOLS
+#define CPPC_ENABLE_TOOLS 1
+
+#include "memory.h"
+#include "atom.h"
+#include "scanner.h"
+#include "cpp.h"
+#include "tokens.h"
+#include "symbols.h"
+#include "compile.h"
+#if !defined(NO_PARSER)
+#include "parser.h"
+#endif
+
+#if !defined(NULL)
+#define NULL 0
+#endif
+
+#endif // !(defined(__SLGLOBALS_H)
+
+
+    
+
diff --git a/Compiler/Preprocessor/symbols.c b/Compiler/Preprocessor/symbols.c
new file mode 100644
index 0000000..d97bae0
--- /dev/null
+++ b/Compiler/Preprocessor/symbols.c
@@ -0,0 +1,290 @@
+//
+// 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.
+//
+/****************************************************************************\
+Copyright (c) 2002, NVIDIA Corporation.
+
+NVIDIA Corporation("NVIDIA") supplies this software to you in
+consideration of your agreement to the following terms, and your use,
+installation, modification or redistribution of this NVIDIA software
+constitutes acceptance of these terms.  If you do not agree with these
+terms, please do not use, install, modify or redistribute this NVIDIA
+software.
+
+In consideration of your agreement to abide by the following terms, and
+subject to these terms, NVIDIA grants you a personal, non-exclusive
+license, under NVIDIA's copyrights in this original NVIDIA software (the
+"NVIDIA Software"), to use, reproduce, modify and redistribute the
+NVIDIA Software, with or without modifications, in source and/or binary
+forms; provided that if you redistribute the NVIDIA Software, you must
+retain the copyright notice of NVIDIA, this notice and the following
+text and disclaimers in all such redistributions of the NVIDIA Software.
+Neither the name, trademarks, service marks nor logos of NVIDIA
+Corporation may be used to endorse or promote products derived from the
+NVIDIA Software without specific prior written permission from NVIDIA.
+Except as expressly stated in this notice, no other rights or licenses
+express or implied, are granted by NVIDIA herein, including but not
+limited to any patent rights that may be infringed by your derivative
+works or by other works in which the NVIDIA Software may be
+incorporated. No hardware is licensed hereunder. 
+
+THE NVIDIA SOFTWARE IS BEING PROVIDED ON AN "AS IS" BASIS, WITHOUT
+WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED,
+INCLUDING WITHOUT LIMITATION, WARRANTIES OR CONDITIONS OF TITLE,
+NON-INFRINGEMENT, MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR
+ITS USE AND OPERATION EITHER ALONE OR IN COMBINATION WITH OTHER
+PRODUCTS.
+
+IN NO EVENT SHALL NVIDIA BE LIABLE FOR ANY SPECIAL, INDIRECT,
+INCIDENTAL, EXEMPLARY, CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+TO, LOST PROFITS; PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) OR ARISING IN ANY WAY
+OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE
+NVIDIA SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT,
+TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF
+NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+\****************************************************************************/
+//
+// symbols.c
+//
+
+#include <assert.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "slglobals.h"
+
+///////////////////////////////////////////////////////////////////////////////////////////////
+/////////////////////////////////// Symbol Table Variables: ///////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////////////////////
+
+Scope *ScopeList = NULL;
+Scope *CurrentScope = NULL;
+Scope *GlobalScope = NULL;
+
+static void unlinkScope(void *_scope) {
+    Scope *scope = _scope;
+
+    if (scope->next)
+        scope->next->prev = scope->prev;
+    if (scope->prev)
+        scope->prev->next = scope->next;
+    else
+        ScopeList = scope->next;
+}
+
+/*
+ * NewScope()
+ *
+ */
+Scope *NewScopeInPool(MemoryPool *pool)
+{
+    Scope *lScope;
+
+    lScope = mem_Alloc(pool, sizeof(Scope));
+    lScope->pool = pool;
+    lScope->parent = NULL;
+    lScope->funScope = NULL;
+    lScope->symbols = NULL;
+    
+    lScope->level = 0;
+
+    lScope->programs = NULL;
+    if ((lScope->next = ScopeList))
+        ScopeList->prev = lScope;
+    lScope->prev = 0;
+    ScopeList = lScope;
+    mem_AddCleanup(pool, unlinkScope, lScope);
+    return lScope;
+} // NewScope
+
+/*
+ * PushScope()
+ *
+ */
+
+void PushScope(Scope *fScope)
+{
+    Scope *lScope;
+
+    if (CurrentScope) {
+        fScope->level = CurrentScope->level + 1;
+        if (fScope->level == 1) {
+            if (!GlobalScope) {
+                /* HACK - CTD -- if GlobalScope==NULL and level==1, we're
+                 * defining a function in the superglobal scope.  Things
+                 * will break if we leave the level as 1, so we arbitrarily
+                 * set it to 2 */
+                fScope->level = 2;
+            }
+        }
+        if (fScope->level >= 2) {
+            lScope = fScope;
+            while (lScope->level > 2)
+                lScope = lScope->next;
+            fScope->funScope = lScope;
+        }
+    } else {
+        fScope->level = 0;
+    }
+    fScope->parent = CurrentScope;
+    CurrentScope = fScope;
+} // PushScope
+
+/*
+ * PopScope()
+ *
+ */
+
+Scope *PopScope(void)
+{
+    Scope *lScope;
+
+    lScope = CurrentScope;
+    if (CurrentScope)
+        CurrentScope = CurrentScope->parent;
+    return lScope;
+} // PopScope
+
+/*
+ * NewSymbol() - Allocate a new symbol node;
+ *
+ */
+
+Symbol *NewSymbol(SourceLoc *loc, Scope *fScope, int name, symbolkind kind)
+{
+    Symbol *lSymb;
+    char *pch;
+    int ii;
+
+    lSymb = (Symbol *) mem_Alloc(fScope->pool, sizeof(Symbol));
+    lSymb->left = NULL;
+    lSymb->right = NULL;
+    lSymb->next = NULL;
+    lSymb->name = name;
+    lSymb->loc = *loc;
+    lSymb->kind = kind;
+    
+    // Clear union area:
+
+    pch = (char *) &lSymb->details;
+    for (ii = 0; ii < sizeof(lSymb->details); ii++)
+        *pch++ = 0;
+    return lSymb;
+} // NewSymbol
+
+/*
+ * lAddToTree() - Using a binary tree is not a good idea for basic atom values because they
+ *         are generated in order.  We'll fix this later (by reversing the bit pattern).
+ */
+
+static void lAddToTree(Symbol **fSymbols, Symbol *fSymb)
+{
+    Symbol *lSymb;
+    int lrev, frev;
+
+    lSymb = *fSymbols;
+    if (lSymb) {
+        frev = GetReversedAtom(atable, fSymb->name);
+        while (lSymb) {
+            lrev = GetReversedAtom(atable, lSymb->name);
+            if (lrev == frev) {
+                CPPErrorToInfoLog("GetAtomString(atable, fSymb->name)");
+                break;
+            } else {
+                if (lrev > frev) {
+                    if (lSymb->left) {
+                        lSymb = lSymb->left;
+                    } else {
+                        lSymb->left = fSymb;
+                        break;
+                    }
+                } else {
+                    if (lSymb->right) {
+                        lSymb = lSymb->right;
+                    } else {
+                        lSymb->right = fSymb;
+                        break;
+                    }
+                }
+            }
+        }
+    } else {
+        *fSymbols = fSymb;
+    }
+} // lAddToTree
+
+
+/*
+ * AddSymbol() - Add a variable, type, or function name to a scope.
+ *
+ */
+
+Symbol *AddSymbol(SourceLoc *loc, Scope *fScope, int atom, symbolkind kind)
+{
+    Symbol *lSymb;
+
+    if (!fScope)
+        fScope = CurrentScope;
+    lSymb = NewSymbol(loc, fScope, atom, kind);
+    lAddToTree(&fScope->symbols, lSymb);
+    return lSymb;
+} // AddSymbol
+
+
+/*********************************************************************************************/
+/************************************ Symbol Semantic Functions ******************************/
+/*********************************************************************************************/
+
+/*
+ * LookUpLocalSymbol()
+ *
+ */
+
+Symbol *LookUpLocalSymbol(Scope *fScope, int atom)
+{
+    Symbol *lSymb;
+    int rname, ratom;
+
+    ratom = GetReversedAtom(atable, atom);
+    if (!fScope)
+        fScope = CurrentScope;
+    lSymb = fScope->symbols;
+    while (lSymb) {
+        rname = GetReversedAtom(atable, lSymb->name);
+        if (rname == ratom) {
+            return lSymb;
+        } else {
+            if (rname > ratom) {
+                lSymb = lSymb->left;
+            } else {
+                lSymb = lSymb->right;
+            }
+        }
+    }
+    return NULL;
+} // LookUpLocalSymbol
+
+/*
+ * LookUpSymbol()
+ *
+ */
+
+Symbol *LookUpSymbol(Scope *fScope, int atom)
+{
+    Symbol *lSymb;
+
+    if (!fScope)
+        fScope = CurrentScope;
+    while (fScope) {
+        lSymb = LookUpLocalSymbol(fScope, atom);
+        if (lSymb)
+            return lSymb;
+        fScope = fScope->parent;
+    }
+    return NULL;
+} // LookUpSymbol
+
diff --git a/Compiler/Preprocessor/symbols.h b/Compiler/Preprocessor/symbols.h
new file mode 100644
index 0000000..a94adbf
--- /dev/null
+++ b/Compiler/Preprocessor/symbols.h
@@ -0,0 +1,117 @@
+//
+// 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.
+//
+/****************************************************************************\
+Copyright (c) 2002, NVIDIA Corporation.
+
+NVIDIA Corporation("NVIDIA") supplies this software to you in
+consideration of your agreement to the following terms, and your use,
+installation, modification or redistribution of this NVIDIA software
+constitutes acceptance of these terms.  If you do not agree with these
+terms, please do not use, install, modify or redistribute this NVIDIA
+software.
+
+In consideration of your agreement to abide by the following terms, and
+subject to these terms, NVIDIA grants you a personal, non-exclusive
+license, under NVIDIA's copyrights in this original NVIDIA software (the
+"NVIDIA Software"), to use, reproduce, modify and redistribute the
+NVIDIA Software, with or without modifications, in source and/or binary
+forms; provided that if you redistribute the NVIDIA Software, you must
+retain the copyright notice of NVIDIA, this notice and the following
+text and disclaimers in all such redistributions of the NVIDIA Software.
+Neither the name, trademarks, service marks nor logos of NVIDIA
+Corporation may be used to endorse or promote products derived from the
+NVIDIA Software without specific prior written permission from NVIDIA.
+Except as expressly stated in this notice, no other rights or licenses
+express or implied, are granted by NVIDIA herein, including but not
+limited to any patent rights that may be infringed by your derivative
+works or by other works in which the NVIDIA Software may be
+incorporated. No hardware is licensed hereunder. 
+
+THE NVIDIA SOFTWARE IS BEING PROVIDED ON AN "AS IS" BASIS, WITHOUT
+WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED,
+INCLUDING WITHOUT LIMITATION, WARRANTIES OR CONDITIONS OF TITLE,
+NON-INFRINGEMENT, MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR
+ITS USE AND OPERATION EITHER ALONE OR IN COMBINATION WITH OTHER
+PRODUCTS.
+
+IN NO EVENT SHALL NVIDIA BE LIABLE FOR ANY SPECIAL, INDIRECT,
+INCIDENTAL, EXEMPLARY, CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+TO, LOST PROFITS; PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) OR ARISING IN ANY WAY
+OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE
+NVIDIA SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT,
+TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF
+NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+\****************************************************************************/
+//
+// symbols.h
+//
+
+#if !defined(__SYMBOLS_H)
+#define __SYMBOLS_H 1
+
+#include "memory.h"
+
+typedef enum symbolkind {
+   MACRO_S
+} symbolkind;
+
+// Typedefs for things defined here in "symbols.h":
+
+typedef struct Scope_Rec Scope;
+typedef struct Symbol_Rec Symbol;
+
+typedef struct SymbolList_Rec {
+    struct SymbolList_Rec *next;
+    Symbol *symb;
+} SymbolList;
+
+struct Scope_Rec {
+    Scope *next, *prev;     // doubly-linked list of all scopes
+    Scope *parent;
+    Scope *funScope;        // Points to base scope of enclosing function
+    MemoryPool *pool;       // pool used for allocation in this scope
+    Symbol *symbols;
+    
+	int level;              // 0 = super globals, 1 = globals, etc.
+
+    // Only used at global scope (level 1):
+    SymbolList *programs;   // List of programs for this compilation.
+};
+
+
+// Symbol table is a simple binary tree.
+
+#include "cpp.h"        // to get MacroSymbol def
+
+struct Symbol_Rec {
+    Symbol *left, *right;
+    Symbol *next;
+    int name;       // Name atom
+    SourceLoc loc;
+    symbolkind kind;
+    union {
+        MacroSymbol mac;
+    } details;
+};
+
+extern Scope *CurrentScope;
+extern Scope *GlobalScope;
+extern Scope *ScopeList;
+
+Scope *NewScopeInPool(MemoryPool *);
+#define NewScope()      NewScopeInPool(CurrentScope->pool)
+void PushScope(Scope *fScope);
+Scope *PopScope(void);
+Symbol *NewSymbol(SourceLoc *loc, Scope *fScope, int name, symbolkind kind);
+Symbol *AddSymbol(SourceLoc *loc, Scope *fScope, int atom, symbolkind kind);
+Symbol *LookUpLocalSymbol(Scope *fScope, int atom);
+Symbol *LookUpSymbol(Scope *fScope, int atom);
+void CPPErrorToInfoLog(char *);
+
+
+#endif // !defined(__SYMBOLS_H)
+
diff --git a/Compiler/Preprocessor/tokens.c b/Compiler/Preprocessor/tokens.c
new file mode 100644
index 0000000..b508f03
--- /dev/null
+++ b/Compiler/Preprocessor/tokens.c
@@ -0,0 +1,444 @@
+//
+// 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.
+//
+/****************************************************************************\
+Copyright (c) 2002, NVIDIA Corporation.
+
+NVIDIA Corporation("NVIDIA") supplies this software to you in
+consideration of your agreement to the following terms, and your use,
+installation, modification or redistribution of this NVIDIA software
+constitutes acceptance of these terms.  If you do not agree with these
+terms, please do not use, install, modify or redistribute this NVIDIA
+software.
+
+In consideration of your agreement to abide by the following terms, and
+subject to these terms, NVIDIA grants you a personal, non-exclusive
+license, under NVIDIA's copyrights in this original NVIDIA software (the
+"NVIDIA Software"), to use, reproduce, modify and redistribute the
+NVIDIA Software, with or without modifications, in source and/or binary
+forms; provided that if you redistribute the NVIDIA Software, you must
+retain the copyright notice of NVIDIA, this notice and the following
+text and disclaimers in all such redistributions of the NVIDIA Software.
+Neither the name, trademarks, service marks nor logos of NVIDIA
+Corporation may be used to endorse or promote products derived from the
+NVIDIA Software without specific prior written permission from NVIDIA.
+Except as expressly stated in this notice, no other rights or licenses
+express or implied, are granted by NVIDIA herein, including but not
+limited to any patent rights that may be infringed by your derivative
+works or by other works in which the NVIDIA Software may be
+incorporated. No hardware is licensed hereunder. 
+
+THE NVIDIA SOFTWARE IS BEING PROVIDED ON AN "AS IS" BASIS, WITHOUT
+WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED,
+INCLUDING WITHOUT LIMITATION, WARRANTIES OR CONDITIONS OF TITLE,
+NON-INFRINGEMENT, MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR
+ITS USE AND OPERATION EITHER ALONE OR IN COMBINATION WITH OTHER
+PRODUCTS.
+
+IN NO EVENT SHALL NVIDIA BE LIABLE FOR ANY SPECIAL, INDIRECT,
+INCIDENTAL, EXEMPLARY, CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+TO, LOST PROFITS; PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) OR ARISING IN ANY WAY
+OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE
+NVIDIA SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT,
+TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF
+NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+\****************************************************************************/
+//
+// tokens.c
+//
+
+#include <assert.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+
+#include "slglobals.h"
+
+///////////////////////////////////////////////////////////////////////////////////////////////
+//////////////////////// Preprocessor and Token Recorder and Playback: ////////////////////////
+///////////////////////////////////////////////////////////////////////////////////////////////
+
+/*
+ * idstr()
+ * Copy a string to a malloc'ed block and convert it into something suitable
+ * for an ID
+ *
+ */
+
+static char *idstr(const char *fstr, MemoryPool *pool)
+{
+    size_t len;
+    char *str, *t;
+    const char *f;
+
+    len = strlen(fstr);
+    if (!pool)
+        str = (char *) malloc(len + 1);
+    else
+        str = (char *) mem_Alloc(pool, len + 1);
+    
+    for (f=fstr, t=str; *f; f++) {
+        if (isalnum(*f)) *t++ = *f;
+        else if (*f == '.' || *f == '/') *t++ = '_';
+    }
+    *t = 0;
+    return str;
+} // idstr
+
+
+/*
+ * lNewBlock()
+ *
+ */
+
+static TokenBlock *lNewBlock(TokenStream *fTok, MemoryPool *pool)
+{
+    TokenBlock *lBlock;
+
+    if (!pool)
+        lBlock = (TokenBlock *) malloc(sizeof(TokenBlock) + 256);
+    else
+        lBlock = (TokenBlock *) mem_Alloc(pool, sizeof(TokenBlock) + 256);
+    lBlock->count = 0;
+    lBlock->current = 0;
+    lBlock->data = (unsigned char *) lBlock + sizeof(TokenBlock);
+    lBlock->max = 256;
+    lBlock->next = NULL;
+    if (fTok->head) {
+        fTok->current->next = lBlock;
+    } else {
+        fTok->head = lBlock;
+    }
+    fTok->current = lBlock;
+    return lBlock;
+} // lNewBlock
+
+/*
+ * lAddByte()
+ *
+ */
+
+static void lAddByte(TokenStream *fTok, unsigned char fVal)
+{
+    TokenBlock *lBlock;
+    lBlock = fTok->current;
+    if (lBlock->count >= lBlock->max)
+        lBlock = lNewBlock(fTok, 0);
+    lBlock->data[lBlock->count++] = fVal;
+} // lAddByte
+
+
+
+/*
+ * lReadByte() - Get the next byte from a stream.
+ *
+ */
+
+static int lReadByte(TokenStream *pTok)
+{
+    TokenBlock *lBlock;
+    int lval = -1;
+
+    lBlock = pTok->current;
+    if (lBlock) {
+        if (lBlock->current >= lBlock->count) {
+            lBlock = lBlock->next;
+            if (lBlock)
+                lBlock->current = 0;
+            pTok->current = lBlock;
+        }
+        if (lBlock)
+            lval = lBlock->data[lBlock->current++];
+    }
+    return lval;
+} // lReadByte
+
+/////////////////////////////////////// Global Functions://////////////////////////////////////
+
+/*
+ * NewTokenStream()
+ *
+ */
+
+TokenStream *NewTokenStream(const char *name, MemoryPool *pool)
+{
+    TokenStream *pTok;
+
+    if (!pool)
+        pTok = (TokenStream *) malloc(sizeof(TokenStream));
+    else
+        pTok = (TokenStream*)mem_Alloc(pool, sizeof(TokenStream));
+    pTok->next = NULL;
+    pTok->name = idstr(name, pool);
+    pTok->head = NULL;
+    pTok->current = NULL;
+    lNewBlock(pTok, pool);
+    return pTok;
+} // NewTokenStream
+
+/*
+ * DeleteTokenStream()
+ *
+ */
+
+void DeleteTokenStream(TokenStream *pTok)
+{
+    TokenBlock *pBlock, *nBlock;
+
+    if (pTok) {
+        pBlock = pTok->head;
+        while (pBlock) {
+            nBlock = pBlock->next;
+            free(pBlock);
+            pBlock = nBlock;
+        }
+        if (pTok->name)
+            free(pTok->name);
+        free(pTok);
+    }
+} // DeleteTokenStream
+
+/*
+ * RecordToken() - Add a token to the end of a list for later playback or printout.
+ *
+ */
+
+void RecordToken(TokenStream *pTok, int token, yystypepp * yylvalpp)
+{
+    const char *s;
+    unsigned char *str=NULL;
+
+    if (token > 256)
+        lAddByte(pTok, (unsigned char)((token & 0x7f) + 0x80));
+    else
+        lAddByte(pTok, (unsigned char)(token & 0x7f));
+    switch (token) {
+    case CPP_IDENTIFIER:
+    case CPP_TYPEIDENTIFIER:
+    case CPP_STRCONSTANT:
+        s = GetAtomString(atable, yylvalpp->sc_ident);
+        while (*s)
+            lAddByte(pTok, (unsigned char) *s++);
+        lAddByte(pTok, 0);
+        break;
+    case CPP_FLOATCONSTANT:
+    case CPP_INTCONSTANT:
+         str=yylvalpp->symbol_name;
+         while (*str){
+            lAddByte(pTok,(unsigned char) *str);
+            *str++;
+         }
+         lAddByte(pTok, 0);
+         break;
+    case '(':
+        lAddByte(pTok, (unsigned char)(yylvalpp->sc_int ? 1 : 0));
+    default:
+        break;
+    }
+} // RecordToken
+
+/*
+ * RewindTokenStream() - Reset a token stream in preperation for reading.
+ *
+ */
+
+void RewindTokenStream(TokenStream *pTok)
+{
+    if (pTok->head) {
+        pTok->current = pTok->head;
+        pTok->current->current = 0;
+    }
+} // RewindTokenStream
+
+/*
+ * ReadToken() - Read the next token from a stream.
+ *
+ */
+
+int ReadToken(TokenStream *pTok, yystypepp * yylvalpp)
+{
+    char symbol_name[MAX_SYMBOL_NAME_LEN + 1];
+    char string_val[MAX_STRING_LEN + 1];
+    int ltoken, len;
+    char ch;
+
+    ltoken = lReadByte(pTok);
+    if (ltoken >= 0) {
+        if (ltoken > 127)
+            ltoken += 128;
+        switch (ltoken) {
+        case CPP_IDENTIFIER:
+        case CPP_TYPEIDENTIFIER:
+            len = 0;
+            ch = lReadByte(pTok);
+            while ((ch >= 'a' && ch <= 'z') ||
+                     (ch >= 'A' && ch <= 'Z') ||
+                     (ch >= '0' && ch <= '9') ||
+                     ch == '_')
+            {
+                if (len < MAX_SYMBOL_NAME_LEN) {
+                    symbol_name[len] = ch;
+                    len++;
+                    ch = lReadByte(pTok);
+                }
+            }
+            symbol_name[len] = '\0';
+            assert(ch == '\0');
+            yylvalpp->sc_ident = LookUpAddString(atable, symbol_name);
+            return CPP_IDENTIFIER;
+            break;
+        case CPP_STRCONSTANT:
+            len = 0;
+            while ((ch = lReadByte(pTok)) != 0)
+                if (len < MAX_STRING_LEN)
+                    string_val[len++] = ch;
+            string_val[len] = 0;
+            yylvalpp->sc_ident = LookUpAddString(atable, string_val);
+            break;
+        case CPP_FLOATCONSTANT:
+            len = 0;
+            ch = lReadByte(pTok);
+            while ((ch >= '0' && ch <= '9')||(ch=='e'||ch=='E'||ch=='.')||(ch=='+'||ch=='-'))
+            {
+                if (len < MAX_SYMBOL_NAME_LEN) {
+                    symbol_name[len] = ch;
+                    len++;
+                    ch = lReadByte(pTok);
+                }
+            }
+            symbol_name[len] = '\0';
+            assert(ch == '\0');
+            strcpy(yylvalpp->symbol_name,symbol_name);
+            yylvalpp->sc_fval=(float)atof(yylvalpp->symbol_name);
+            break;
+        case CPP_INTCONSTANT:
+            len = 0;
+            ch = lReadByte(pTok);
+            while ((ch >= '0' && ch <= '9'))
+            {
+                if (len < MAX_SYMBOL_NAME_LEN) {
+                    symbol_name[len] = ch;
+                    len++;
+                    ch = lReadByte(pTok);
+                }
+            }
+            symbol_name[len] = '\0';
+            assert(ch == '\0');
+            strcpy(yylvalpp->symbol_name,symbol_name);
+            yylvalpp->sc_int=atoi(yylvalpp->symbol_name);
+            break;
+        case '(':
+            yylvalpp->sc_int = lReadByte(pTok);
+            break;
+        }
+        return ltoken;
+    }
+    return EOF_SY;
+} // ReadToken
+
+typedef struct TokenInputSrc {
+    InputSrc            base;
+    TokenStream         *tokens;
+    int                 (*final)(CPPStruct *);
+} TokenInputSrc;
+
+static int scan_token(TokenInputSrc *in, yystypepp * yylvalpp)
+{
+    int token = ReadToken(in->tokens, yylvalpp);
+    int (*final)(CPPStruct *);
+    cpp->tokenLoc->file = cpp->currentInput->name;
+    cpp->tokenLoc->line = cpp->currentInput->line;
+    if (token == '\n') {
+        in->base.line++;
+        return token;
+    }
+    if (token > 0) return token;
+    cpp->currentInput = in->base.prev;
+    final = in->final;
+    free(in);
+    if (final && !final(cpp)) return -1;
+    return cpp->currentInput->scan(cpp->currentInput, yylvalpp);
+}
+
+int ReadFromTokenStream(TokenStream *ts, int name, int (*final)(CPPStruct *))
+{
+    TokenInputSrc *in = malloc(sizeof(TokenInputSrc));
+    memset(in, 0, sizeof(TokenInputSrc));
+    in->base.name = name;
+    in->base.prev = cpp->currentInput;
+    in->base.scan = (int (*)(InputSrc *, yystypepp *))scan_token;
+    in->base.line = 1;
+    in->tokens = ts;
+    in->final = final;
+    RewindTokenStream(ts);
+    cpp->currentInput = &in->base;
+    return 1;
+}
+
+typedef struct UngotToken {
+    InputSrc    base;
+    int         token;
+    yystypepp     lval;
+} UngotToken;
+
+static int reget_token(UngotToken *t, yystypepp * yylvalpp)
+{
+    int token = t->token;
+    *yylvalpp = t->lval;
+    cpp->currentInput = t->base.prev;
+    free(t);
+    return token;
+}
+
+void UngetToken(int token, yystypepp * yylvalpp) {
+    UngotToken *t = malloc(sizeof(UngotToken));
+    memset(t, 0, sizeof(UngotToken));
+    t->token = token;
+    t->lval = *yylvalpp;
+    t->base.scan = (void *)reget_token;
+    t->base.prev = cpp->currentInput;
+    t->base.name = cpp->currentInput->name;
+    t->base.line = cpp->currentInput->line;
+    cpp->currentInput = &t->base;
+}
+
+
+void DumpTokenStream(FILE *fp, TokenStream *s, yystypepp * yylvalpp) {
+    int token;
+    char str[100];
+
+    if (fp == 0) fp = stdout;
+    RewindTokenStream(s);
+    while ((token = ReadToken(s, yylvalpp)) > 0) {
+        switch (token) {
+        case CPP_IDENTIFIER:
+        case CPP_TYPEIDENTIFIER:
+            sprintf(str, "%s ", GetAtomString(atable, yylvalpp->sc_ident));
+            break;
+        case CPP_STRCONSTANT:
+            sprintf(str, "\"%s\"", GetAtomString(atable, yylvalpp->sc_ident));
+            break;
+        case CPP_FLOATCONSTANT:
+            //printf("%g9.6 ", yylvalpp->sc_fval);
+            break;
+        case CPP_INTCONSTANT:
+            //printf("%d ", yylvalpp->sc_int);
+            break;
+        default:
+            if (token >= 127)
+                sprintf(str, "%s ", GetAtomString(atable, token));
+            else
+                sprintf(str, "%c", token);
+            break;
+        }
+        CPPDebugLogMsg(str);
+    }
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////
+/////////////////////////////////////// End of tokens.c ///////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////////////////////
diff --git a/Compiler/Preprocessor/tokens.h b/Compiler/Preprocessor/tokens.h
new file mode 100644
index 0000000..19938d7
--- /dev/null
+++ b/Compiler/Preprocessor/tokens.h
@@ -0,0 +1,94 @@
+//
+// 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.
+//
+/****************************************************************************\
+Copyright (c) 2002, NVIDIA Corporation.
+
+NVIDIA Corporation("NVIDIA") supplies this software to you in
+consideration of your agreement to the following terms, and your use,
+installation, modification or redistribution of this NVIDIA software
+constitutes acceptance of these terms.  If you do not agree with these
+terms, please do not use, install, modify or redistribute this NVIDIA
+software.
+
+In consideration of your agreement to abide by the following terms, and
+subject to these terms, NVIDIA grants you a personal, non-exclusive
+license, under NVIDIA's copyrights in this original NVIDIA software (the
+"NVIDIA Software"), to use, reproduce, modify and redistribute the
+NVIDIA Software, with or without modifications, in source and/or binary
+forms; provided that if you redistribute the NVIDIA Software, you must
+retain the copyright notice of NVIDIA, this notice and the following
+text and disclaimers in all such redistributions of the NVIDIA Software.
+Neither the name, trademarks, service marks nor logos of NVIDIA
+Corporation may be used to endorse or promote products derived from the
+NVIDIA Software without specific prior written permission from NVIDIA.
+Except as expressly stated in this notice, no other rights or licenses
+express or implied, are granted by NVIDIA herein, including but not
+limited to any patent rights that may be infringed by your derivative
+works or by other works in which the NVIDIA Software may be
+incorporated. No hardware is licensed hereunder. 
+
+THE NVIDIA SOFTWARE IS BEING PROVIDED ON AN "AS IS" BASIS, WITHOUT
+WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED,
+INCLUDING WITHOUT LIMITATION, WARRANTIES OR CONDITIONS OF TITLE,
+NON-INFRINGEMENT, MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR
+ITS USE AND OPERATION EITHER ALONE OR IN COMBINATION WITH OTHER
+PRODUCTS.
+
+IN NO EVENT SHALL NVIDIA BE LIABLE FOR ANY SPECIAL, INDIRECT,
+INCIDENTAL, EXEMPLARY, CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+TO, LOST PROFITS; PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) OR ARISING IN ANY WAY
+OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE
+NVIDIA SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT,
+TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF
+NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+\****************************************************************************/
+//
+// tokens.h
+//
+
+#if !defined(__TOKENS_H)
+#define __TOKENS_H 1
+
+#include "parser.h"
+
+#define EOF_SY (-1)
+
+typedef struct TokenBlock_Rec TokenBlock;
+
+typedef struct TokenStream_Rec {
+    struct TokenStream_Rec *next;
+    char *name;
+    TokenBlock *head;
+    TokenBlock *current;
+} TokenStream;
+
+struct TokenBlock_Rec {
+    TokenBlock *next;
+    int current;
+    int count;
+    int max;
+    unsigned char *data;
+};
+
+extern TokenStream stdlib_cpp_stream;
+
+
+TokenStream *NewTokenStream(const char *name, MemoryPool *pool);
+void DeleteTokenStream(TokenStream *pTok); 
+void RecordToken(TokenStream *pTok, int token, yystypepp * yylvalpp);
+void RewindTokenStream(TokenStream *pTok);
+int ReadToken(TokenStream *pTok, yystypepp * yylvalpp);
+int ReadFromTokenStream(TokenStream *pTok, int name, int (*final)(CPPStruct *));
+void UngetToken(int, yystypepp * yylvalpp);
+
+#if defined(CPPC_ENABLE_TOOLS)
+
+void DumpTokenStream(FILE *, TokenStream *, yystypepp * yylvalpp);
+
+#endif // defined(CPPC_ENABLE_TOOLS)
+
+#endif // !defined(__TOKENS_H)
diff --git a/Compiler/QualifierAlive.cpp b/Compiler/QualifierAlive.cpp
new file mode 100644
index 0000000..e47fd6f
--- /dev/null
+++ b/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 "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/Compiler/QualifierAlive.h b/Compiler/QualifierAlive.h
new file mode 100644
index 0000000..872a06f
--- /dev/null
+++ b/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/Compiler/RemoveTree.cpp b/Compiler/RemoveTree.cpp
new file mode 100644
index 0000000..9c4162e
--- /dev/null
+++ b/Compiler/RemoveTree.cpp
@@ -0,0 +1,76 @@
+//
+// 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 "intermediate.h"
+#include "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/Compiler/RemoveTree.h b/Compiler/RemoveTree.h
new file mode 100644
index 0000000..97a8216
--- /dev/null
+++ b/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/Compiler/ResourceLimits.h b/Compiler/ResourceLimits.h
new file mode 100644
index 0000000..7b7a4b7
--- /dev/null
+++ b/Compiler/ResourceLimits.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 _RESOURCE_LIMITS_INCLUDED_
+#define _RESOURCE_LIMITS_INCLUDED_
+
+struct TBuiltInResource
+{
+	int maxVertexAttribs;
+	int maxVertexUniformVectors;
+	int maxVaryingVectors;
+	int maxVertexTextureImageUnits;
+	int maxCombinedTextureImageUnits;
+	int maxTextureImageUnits;
+	int maxFragmentUniformVectors;
+	int maxDrawBuffers;
+};
+#endif // _RESOURCE_LIMITS_INCLUDED_
diff --git a/Compiler/ShHandle.h b/Compiler/ShHandle.h
new file mode 100644
index 0000000..cd6353e
--- /dev/null
+++ b/Compiler/ShHandle.h
@@ -0,0 +1,139 @@
+//
+// 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 _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 "ShaderLang.h"
+
+#include "InfoSink.h"
+
+class TCompiler;
+class TLinker;
+class TUniformMap;
+
+
+//
+// The base class used to back handles returned to the driver.
+//
+class TShHandleBase {
+public:
+    TShHandleBase() { }
+    virtual ~TShHandleBase() { }
+    virtual TCompiler* getAsCompiler() { return 0; }
+    virtual TLinker* getAsLinker() { return 0; }
+    virtual TUniformMap* getAsUniformMap() { return 0; }
+};
+
+//
+// The base class for the machine dependent linker to derive from
+// for managing where uniforms live.
+//
+class TUniformMap : public TShHandleBase {
+public:
+    TUniformMap() { }
+    virtual ~TUniformMap() { }
+    virtual TUniformMap* getAsUniformMap() { return this; }
+    virtual int getLocation(const char* name) = 0;    
+    virtual TInfoSink& getInfoSink() { return infoSink; }
+    TInfoSink infoSink;
+};
+class TIntermNode;
+
+//
+// The base class for the machine dependent compiler to derive from
+// for managing object code from the compile.
+//
+class TCompiler : public TShHandleBase {
+public:
+    TCompiler(EShLanguage l, TInfoSink& sink) : infoSink(sink) , language(l), haveValidObjectCode(false) { }
+    virtual ~TCompiler() { }
+    EShLanguage getLanguage() { return language; }
+    virtual TInfoSink& getInfoSink() { return infoSink; }
+
+    virtual bool compile(TIntermNode* root) = 0;
+
+    virtual TCompiler* getAsCompiler() { return this; }
+    virtual bool linkable() { return haveValidObjectCode; }
+    
+    TInfoSink& infoSink;
+protected:
+    EShLanguage language;
+    bool haveValidObjectCode;
+};
+
+//
+// Link operations are base on a list of compile results...
+//
+typedef TVector<TCompiler*> TCompilerList;
+typedef TVector<TShHandleBase*> THandleList;
+
+//
+// The base class for the machine dependent linker to derive from
+// to manage the resulting executable.
+//
+
+class TLinker : public TShHandleBase {
+public:
+    TLinker(EShExecutable e, TInfoSink& iSink) : 
+        infoSink(iSink),
+        executable(e), 
+        haveReturnableObjectCode(false),
+        appAttributeBindings(0),
+        fixedAttributeBindings(0),
+		excludedAttributes(0),
+		excludedCount(0),
+        uniformBindings(0) { }
+    virtual TLinker* getAsLinker() { return this; }
+    virtual ~TLinker() { }
+    virtual bool link(TCompilerList&, TUniformMap*) = 0;
+    virtual bool link(THandleList&) { return false; }
+    virtual void setAppAttributeBindings(const ShBindingTable* t)   { appAttributeBindings = t; }
+    virtual void setFixedAttributeBindings(const ShBindingTable* t) { fixedAttributeBindings = t; }
+	virtual void getAttributeBindings(ShBindingTable const **t) const = 0;
+	virtual void setExcludedAttributes(const int* attributes, int count) { excludedAttributes = attributes; excludedCount = count; }
+    virtual ShBindingTable* getUniformBindings() const  { return uniformBindings; }
+    virtual const void* getObjectCode() const { return 0; } // a real compiler would be returning object code here
+    virtual TInfoSink& getInfoSink() { return infoSink; }
+    TInfoSink& infoSink;
+protected:
+    EShExecutable executable;
+    bool haveReturnableObjectCode;  // true when objectCode is acceptable to send to driver
+
+    const ShBindingTable* appAttributeBindings;
+    const ShBindingTable* fixedAttributeBindings;
+	const int* excludedAttributes;
+	int excludedCount;
+    ShBindingTable* uniformBindings;                // created by the linker    
+};
+
+//
+// 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(EShLanguage, int);
+
+TShHandleBase* ConstructLinker(EShExecutable, int);
+void DeleteLinker(TShHandleBase*);
+    
+TUniformMap* ConstructUniformMap();
+void DeleteCompiler(TCompiler*);
+
+void DeleteUniformMap(TUniformMap*);
+
+#endif // _SHHANDLE_INCLUDED_
diff --git a/Compiler/ShaderLang.cpp b/Compiler/ShaderLang.cpp
new file mode 100644
index 0000000..461604a
--- /dev/null
+++ b/Compiler/ShaderLang.cpp
@@ -0,0 +1,587 @@
+//
+// 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.
+//
+
+//
+// Implement the top-level of interface to the compiler/linker,
+// as defined in ShaderLang.h
+//
+#include "SymbolTable.h"
+#include "ParseHelper.h"
+
+#include "ShHandle.h"
+#include "InitializeDll.h"
+
+#include "ShaderLang.h"
+#include "Initialize.h"
+
+#include "OutputHLSL.h"
+
+//
+// A symbol table for each language.  Each has a different
+// set of built-ins, and we want to preserve that from
+// compile to compile.
+//
+TSymbolTable SymbolTables[EShLangCount];
+
+
+TPoolAllocator* PerProcessGPA = 0;
+//
+// This is the platform independent interface between an OGL driver
+// and the shading language compiler/linker.
+//
+
+//
+// Driver must call this first, once, before doing any other
+// compiler/linker operations.
+//
+int ShInitialize()
+{
+    TInfoSink infoSink;
+    bool ret = true;
+
+    if (!InitProcess())
+        return 0;
+
+    // This method should be called once per process. If its called by multiple threads, then 
+    // we need to have thread synchronization code around the initialization of per process
+    // global pool allocator
+    if (!PerProcessGPA) { 
+        TPoolAllocator *builtInPoolAllocator = new TPoolAllocator(true);
+        builtInPoolAllocator->push();
+        TPoolAllocator* gPoolAllocator = &GlobalPoolAllocator;
+        SetGlobalPoolAllocatorPtr(builtInPoolAllocator);
+
+        TSymbolTable symTables[EShLangCount];
+        GenerateBuiltInSymbolTable(0, infoSink, symTables);
+
+        PerProcessGPA = new TPoolAllocator(true);
+        PerProcessGPA->push();
+        SetGlobalPoolAllocatorPtr(PerProcessGPA);
+
+        SymbolTables[EShLangVertex].copyTable(symTables[EShLangVertex]);
+        SymbolTables[EShLangFragment].copyTable(symTables[EShLangFragment]);
+
+        SetGlobalPoolAllocatorPtr(gPoolAllocator);
+
+        symTables[EShLangVertex].pop();
+        symTables[EShLangFragment].pop();
+
+        builtInPoolAllocator->popAll();
+        delete builtInPoolAllocator;        
+
+    }
+
+    return ret ? 1 : 0;
+}
+
+//
+// Driver calls these to create and destroy compiler/linker
+// objects.
+//
+
+ShHandle ShConstructCompiler(const EShLanguage language, int debugOptions)
+{
+    if (!InitThread())
+        return 0;
+
+    TShHandleBase* base = static_cast<TShHandleBase*>(ConstructCompiler(language, debugOptions));
+    
+    return reinterpret_cast<void*>(base);
+}
+
+ShHandle ShConstructLinker(const EShExecutable executable, int debugOptions)
+{
+    if (!InitThread())
+        return 0;
+
+    TShHandleBase* base = static_cast<TShHandleBase*>(ConstructLinker(executable, debugOptions));
+
+    return reinterpret_cast<void*>(base);
+}
+
+ShHandle ShConstructUniformMap()
+{
+    if (!InitThread())
+        return 0;
+
+    TShHandleBase* base = static_cast<TShHandleBase*>(ConstructUniformMap());
+
+    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());
+    else if (base->getAsLinker())
+        DeleteLinker(base->getAsLinker());
+    else if (base->getAsUniformMap())
+        DeleteUniformMap(base->getAsUniformMap());
+}
+
+//
+// Cleanup symbol tables
+//
+int __fastcall ShFinalize()
+{  
+  if (PerProcessGPA) {
+    PerProcessGPA->popAll();
+    delete PerProcessGPA;
+  }
+  return 1;
+}
+
+bool GenerateBuiltInSymbolTable(const TBuiltInResource* resources, TInfoSink& infoSink, TSymbolTable* symbolTables, EShLanguage language)
+{
+    TBuiltIns builtIns;
+    
+	if (resources) {
+		builtIns.initialize(*resources);
+		InitializeSymbolTable(builtIns.getBuiltInStrings(), language, infoSink, resources, symbolTables);
+	} else {
+		builtIns.initialize();
+		InitializeSymbolTable(builtIns.getBuiltInStrings(), EShLangVertex, infoSink, resources, symbolTables);
+		InitializeSymbolTable(builtIns.getBuiltInStrings(), EShLangFragment, infoSink, resources, symbolTables);
+	}
+
+    return true;
+}
+
+bool InitializeSymbolTable(TBuiltInStrings* BuiltInStrings, EShLanguage language, TInfoSink& infoSink, const TBuiltInResource* resources, TSymbolTable* symbolTables)
+{
+    TIntermediate intermediate(infoSink);	
+    TSymbolTable* symbolTable;
+	
+	if (resources)
+		symbolTable = symbolTables;
+	else
+		symbolTable = &symbolTables[language];
+
+    TParseContext parseContext(*symbolTable, intermediate, language, infoSink);
+
+    GlobalParseContext = &parseContext;
+    
+    setInitialState();
+
+    assert(symbolTable->isEmpty() || symbolTable->atSharedBuiltInLevel());
+       
+    //
+    // 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();
+    
+    //Initialize the Preprocessor
+    int ret = InitPreprocessor();
+    if (ret) {
+        infoSink.info.message(EPrefixInternalError,  "Unable to intialize the Preprocessor");
+        return false;
+    }
+    
+    for (TBuiltInStrings::iterator i  = BuiltInStrings[parseContext.language].begin();
+                                    i != BuiltInStrings[parseContext.language].end();
+                                    ++i) {
+        const char* builtInShaders[1];
+        int builtInLengths[1];
+
+        builtInShaders[0] = (*i).c_str();
+        builtInLengths[0] = (int) (*i).size();
+
+        if (PaParseStrings(const_cast<char**>(builtInShaders), builtInLengths, 1, parseContext) != 0) {
+            infoSink.info.message(EPrefixInternalError, "Unable to parse built-ins");
+            return false;
+        }
+    }
+
+	if (resources) {
+		IdentifyBuiltIns(parseContext.language, *symbolTable, *resources);
+	} else {									   
+		IdentifyBuiltIns(parseContext.language, *symbolTable);
+	}
+
+    FinalizePreprocessor();
+
+    return true;
+}
+
+//
+// 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,
+    const EShOptimizationLevel optLevel,
+    const TBuiltInResource* resources,
+    int debugOptions
+    )
+{
+    if (!InitThread())
+        return 0;
+
+    if (handle == 0)
+        return 0;
+
+    TShHandleBase* base = reinterpret_cast<TShHandleBase*>(handle);
+    TCompiler* compiler = base->getAsCompiler();
+    if (compiler == 0)
+        return 0;
+    
+    GlobalPoolAllocator.push();
+    compiler->infoSink.info.erase();
+    compiler->infoSink.debug.erase();
+    compiler->infoSink.obj.erase();
+
+    if (numStrings == 0)
+        return 1;
+
+    TIntermediate intermediate(compiler->infoSink);
+    TSymbolTable symbolTable(SymbolTables[compiler->getLanguage()]);
+    
+    GenerateBuiltInSymbolTable(resources, compiler->infoSink, &symbolTable, compiler->getLanguage());
+
+    TParseContext parseContext(symbolTable, intermediate, compiler->getLanguage(), compiler->infoSink);
+    parseContext.initializeExtensionBehavior();
+
+    GlobalParseContext = &parseContext;
+    
+    setInitialState();
+
+    InitPreprocessor();    
+    //
+    // Parse the application's shaders.  All the following symbol table
+    // work will be throw-away, so push a new allocation scope that can
+    // be thrown away, then push a scope for the current shader's globals.
+    //
+    bool success = true;
+    
+    symbolTable.push();
+    if (!symbolTable.atGlobalLevel())
+        parseContext.infoSink.info.message(EPrefixInternalError, "Wrong symbol table level");
+
+    int ret = PaParseStrings(const_cast<char**>(shaderStrings), 0, numStrings, parseContext);
+    if (ret)
+        success = false;
+
+    if (success && parseContext.treeRoot) {
+        if (optLevel == EShOptNoGeneration)
+            parseContext.infoSink.info.message(EPrefixNone, "No errors.  No code generation or linking was requested.");
+        else {
+            success = intermediate.postProcess(parseContext.treeRoot, parseContext.language);
+
+            if (success) {
+
+                if (debugOptions & EDebugOpIntermediate)
+                    intermediate.outputTree(parseContext.treeRoot);
+
+				if(debugOptions & EDebugOpObjectCode)
+				{
+					sh::OutputHLSL outputHLSL(parseContext);
+
+					outputHLSL.header();
+					parseContext.treeRoot->traverse(&outputHLSL);
+				}
+
+                //
+                // Call the machine dependent compiler
+                //
+                if (! compiler->compile(parseContext.treeRoot))
+                    success = false;
+            }
+        }
+    } else if (!success) {
+        parseContext.infoSink.info.prefix(EPrefixError);
+        parseContext.infoSink.info << parseContext.numErrors << " compilation errors.  No code generated.\n\n";
+        success = false;
+        if (debugOptions & EDebugOpIntermediate)
+            intermediate.outputTree(parseContext.treeRoot);
+    }
+
+    intermediate.remove(parseContext.treeRoot);
+
+    //
+    // Ensure symbol table is returned to the built-in level,
+    // throwing away all but the built-ins.
+    //
+    while (! symbolTable.atSharedBuiltInLevel())
+        symbolTable.pop();
+
+    FinalizePreprocessor();
+    //
+    // Throw away all the temporary memory used by the compilation process.
+    //
+    GlobalPoolAllocator.pop();
+
+    return success ? 1 : 0;
+}
+
+//
+// Do an actual link on the given compile objects.
+//
+// Return:  The return value of is really boolean, indicating
+// success or failure.
+//
+int ShLink(
+    const ShHandle linkHandle,
+    const ShHandle compHandles[],
+    const int numHandles,
+    ShHandle uniformMapHandle,
+    short int** uniformsAccessed,
+    int* numUniformsAccessed)
+
+{
+    if (!InitThread())
+        return 0;
+
+    TShHandleBase* base = reinterpret_cast<TShHandleBase*>(linkHandle);
+    TLinker* linker = static_cast<TLinker*>(base->getAsLinker());
+    if (linker == 0)
+        return 0;
+
+    int returnValue;
+    GlobalPoolAllocator.push();
+    returnValue = ShLinkExt(linkHandle, compHandles, numHandles);
+    GlobalPoolAllocator.pop();
+
+    if (returnValue)
+        return 1;
+
+    return 0;
+}
+//
+// This link method will be eventually used once the ICD supports the new linker interface
+//
+int ShLinkExt(
+    const ShHandle linkHandle,
+    const ShHandle compHandles[],
+    const int numHandles)
+{
+    if (linkHandle == 0 || numHandles == 0)
+        return 0;
+
+    THandleList cObjects;
+
+    {// support MSVC++6.0
+        for (int i = 0; i < numHandles; ++i) {
+            if (compHandles[i] == 0)
+                return 0;
+            TShHandleBase* base = reinterpret_cast<TShHandleBase*>(compHandles[i]);
+            if (base->getAsLinker()) {
+                cObjects.push_back(base->getAsLinker());
+            }
+            if (base->getAsCompiler())
+                cObjects.push_back(base->getAsCompiler());
+    
+    
+            if (cObjects[i] == 0)
+                return 0;
+        }
+    }
+
+    TShHandleBase* base = reinterpret_cast<TShHandleBase*>(linkHandle);
+    TLinker* linker = static_cast<TLinker*>(base->getAsLinker());
+
+    if (linker == 0)
+        return 0;
+
+    linker->infoSink.info.erase();
+    linker->infoSink.obj.erase();
+
+    {// support MSVC++6.0
+        for (int i = 0; i < numHandles; ++i) {
+            if (cObjects[i]->getAsCompiler()) {
+                if (! cObjects[i]->getAsCompiler()->linkable()) {
+                    linker->infoSink.info.message(EPrefixError, "Not all shaders have valid object code.");                
+                    return 0;
+                }
+            }
+        }
+    }
+
+    bool ret = linker->link(cObjects);
+
+    return ret ? 1 : 0;
+}
+
+//
+// ShSetEncrpytionMethod is a place-holder for specifying
+// how source code is encrypted.
+//
+void ShSetEncryptionMethod(ShHandle handle)
+{
+    if (handle == 0)
+        return;
+}
+
+//
+// Return any compiler/linker/uniformmap log of messages for the application.
+//
+const char* ShGetInfoLog(const ShHandle handle)
+{
+    if (!InitThread())
+        return 0;
+
+    if (handle == 0)
+        return 0;
+
+    TShHandleBase* base = static_cast<TShHandleBase*>(handle);
+    TInfoSink* infoSink;
+
+    if (base->getAsCompiler())
+        infoSink = &(base->getAsCompiler()->getInfoSink());
+    else if (base->getAsLinker())
+        infoSink = &(base->getAsLinker()->getInfoSink());
+
+    infoSink->info << infoSink->debug.c_str();
+    return infoSink->info.c_str();
+}
+
+//
+// Return any unlinked object code.
+//
+const char* ShGetObjectCode(const ShHandle handle)
+{
+    if (!InitThread())
+        return 0;
+
+    if (handle == 0)
+        return 0;
+
+    TShHandleBase* base = static_cast<TShHandleBase*>(handle);
+    TInfoSink* infoSink;
+
+    if (base->getAsCompiler())
+        infoSink = &(base->getAsCompiler()->getInfoSink());
+
+    return infoSink->obj.c_str();
+}
+
+//
+// Return the resulting binary code from the link process.  Structure
+// is machine dependent.
+//
+const void* ShGetExecutable(const ShHandle handle)
+{
+    if (!InitThread())
+        return 0;
+
+    if (handle == 0)
+        return 0;
+
+    TShHandleBase* base = reinterpret_cast<TShHandleBase*>(handle);
+    
+    TLinker* linker = static_cast<TLinker*>(base->getAsLinker());
+    if (linker == 0)
+        return 0;
+
+    return linker->getObjectCode();
+}
+
+//
+// Let the linker know where the application said it's attributes are bound.
+// The linker does not use these values, they are remapped by the ICD or
+// hardware.  It just needs them to know what's aliased.
+//
+// Return:  The return value of is really boolean, indicating
+// success or failure.
+//
+int ShSetVirtualAttributeBindings(const ShHandle handle, const ShBindingTable* table)
+{    
+    if (!InitThread())
+        return 0;
+
+    if (handle == 0)
+        return 0;
+
+    TShHandleBase* base = reinterpret_cast<TShHandleBase*>(handle);
+    TLinker* linker = static_cast<TLinker*>(base->getAsLinker());
+
+    if (linker == 0)
+        return 0;
+   
+    linker->setAppAttributeBindings(table);
+
+    return 1;
+}
+
+//
+// Let the linker know where the predefined attributes have to live.
+//
+int ShSetFixedAttributeBindings(const ShHandle handle, const ShBindingTable* table)
+{
+    if (!InitThread())
+        return 0;
+
+    if (handle == 0)
+        return 0;
+
+    TShHandleBase* base = reinterpret_cast<TShHandleBase*>(handle);
+    TLinker* linker = static_cast<TLinker*>(base->getAsLinker());
+
+    if (linker == 0)
+        return 0;
+
+    linker->setFixedAttributeBindings(table);
+    return 1;
+}
+
+//
+// Some attribute locations are off-limits to the linker...
+//
+int ShExcludeAttributes(const ShHandle handle, int *attributes, int count)
+{
+    if (!InitThread())
+        return 0;
+
+    if (handle == 0)
+        return 0;
+
+    TShHandleBase* base = reinterpret_cast<TShHandleBase*>(handle);
+    TLinker* linker = static_cast<TLinker*>(base->getAsLinker());
+    if (linker == 0)
+        return 0;
+
+    linker->setExcludedAttributes(attributes, count);
+
+    return 1;
+}
+
+//
+// Return the index for OpenGL to use for knowing where a uniform lives.
+//
+// Return:  The return value of is really boolean, indicating
+// success or failure.
+//
+int ShGetUniformLocation(const ShHandle handle, const char* name)
+{
+    if (!InitThread())
+        return 0;
+
+    if (handle == 0)
+        return -1;
+
+    TShHandleBase* base = reinterpret_cast<TShHandleBase*>(handle);
+    TUniformMap* uniformMap= base->getAsUniformMap();
+    if (uniformMap == 0)
+        return -1;
+
+    return uniformMap->getLocation(name);
+}
+
diff --git a/Compiler/ShaderLang.h b/Compiler/ShaderLang.h
new file mode 100644
index 0000000..4e695eb
--- /dev/null
+++ b/Compiler/ShaderLang.h
@@ -0,0 +1,179 @@
+//
+// 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_
+
+#include "ResourceLimits.h"
+
+#ifdef _WIN32
+#define C_DECL __cdecl
+#else
+#define __fastcall
+#define C_DECL
+#endif
+
+//
+// This is the platform independent interface between an OGL driver
+// and the shading language compiler/linker.
+//
+
+#ifdef __cplusplus
+	extern "C" {
+#endif
+//
+// Driver must call this first, once, before doing any other
+// compiler/linker operations.
+//
+int ShInitialize();
+//
+// Driver should call this at shutdown.
+//
+int __fastcall ShFinalize();
+//
+// Types of languages the compiler can consume.
+//
+typedef enum {
+	EShLangVertex,
+	EShLangFragment,
+	EShLangPack,
+	EShLangUnpack,
+	EShLangCount,
+} EShLanguage;
+
+//
+// Types of output the linker will create.
+//
+typedef enum {
+	EShExVertexFragment,
+	EShExPackFragment,
+	EShExUnpackFragment,
+	EShExFragment
+} EShExecutable;
+
+//
+// Optimization level for the compiler.
+//
+typedef enum {
+	EShOptNoGeneration,
+	EShOptNone,
+	EShOptSimple,       // Optimizations that can be done quickly
+	EShOptFull,         // Optimizations that will take more time
+} EShOptimizationLevel;
+
+//
+// Build a table for bindings.  This can be used for locating
+// attributes, uniforms, globals, etc., as needed.
+//
+typedef struct {
+	const char* name;
+	int binding;
+} ShBinding;
+
+typedef struct {
+	int numBindings;
+	ShBinding* bindings;  // array of bindings
+} ShBindingTable;
+
+//
+// ShHandle held by but opaque to the driver.  It is allocated,
+// managed, and de-allocated by the compiler/linker. It's contents 
+// are defined by and used by the compiler and linker.  For example,
+// symbol table information and object code passed from the compiler 
+// to the linker can be stored where ShHandle points.
+//
+// If handle creation fails, 0 will be returned.
+//
+typedef void* ShHandle;
+
+//
+// Driver calls these to create and destroy compiler/linker
+// objects.
+//
+ShHandle ShConstructCompiler(const EShLanguage, int debugOptions);  // one per shader
+ShHandle ShConstructLinker(const EShExecutable, int debugOptions);  // one per shader pair
+ShHandle ShConstructUniformMap();                 // one per uniform namespace (currently entire program object)
+void ShDestruct(ShHandle);
+
+//
+// The return value of ShCompile is boolean, indicating
+// success or failure.
+//
+// The info-log should be written by ShCompile into 
+// ShHandle, so it can answer future queries.
+//
+int ShCompile(
+	const ShHandle,
+	const char* const shaderStrings[],
+	const int numStrings,
+	const EShOptimizationLevel,
+	const TBuiltInResource *resources,
+	int debugOptions
+	);
+
+
+//
+// Similar to ShCompile, but accepts an opaque handle to an
+// intermediate language structure.
+//
+int ShCompileIntermediate(
+	ShHandle compiler,
+	ShHandle intermediate,
+	const EShOptimizationLevel,
+	int debuggable           // boolean
+	);
+
+int ShLink(
+	const ShHandle,               // linker object
+	const ShHandle h[],           // compiler objects to link together
+	const int numHandles,
+	ShHandle uniformMap,          // updated with new uniforms
+	short int** uniformsAccessed,  // returned with indexes of uniforms accessed
+	int* numUniformsAccessed); 	
+
+int ShLinkExt(
+	const ShHandle,               // linker object
+	const ShHandle h[],           // compiler objects to link together
+	const int numHandles);
+
+//
+// ShSetEncrpytionMethod is a place-holder for specifying
+// how source code is encrypted.
+//
+void ShSetEncryptionMethod(ShHandle);
+
+//
+// All the following return 0 if the information is not
+// available in the object passed down, or the object is bad.
+//
+const char* ShGetInfoLog(const ShHandle);
+const char* ShGetObjectCode(const ShHandle);
+const void* ShGetExecutable(const ShHandle);
+int ShSetVirtualAttributeBindings(const ShHandle, const ShBindingTable*);   // to detect user aliasing
+int ShSetFixedAttributeBindings(const ShHandle, const ShBindingTable*);     // to force any physical mappings
+int ShGetPhysicalAttributeBindings(const ShHandle, const ShBindingTable**); // for all attributes
+//
+// Tell the linker to never assign a vertex attribute to this list of physical attributes
+//
+int ShExcludeAttributes(const ShHandle, int *attributes, int count);
+
+//
+// Returns the location ID of the named uniform.
+// Returns -1 if error.
+//
+int ShGetUniformLocation(const ShHandle uniformMap, const char* name);
+
+enum TDebugOptions {
+	EDebugOpNone               = 0x000,
+	EDebugOpIntermediate       = 0x001,
+	EDebugOpAssembly           = 0x002,
+	EDebugOpObjectCode         = 0x004,
+	EDebugOpLinkMaps           = 0x008
+};
+#ifdef __cplusplus
+	}
+#endif
+
+#endif // _COMPILER_INTERFACE_INCLUDED_
diff --git a/Compiler/SymbolTable.cpp b/Compiler/SymbolTable.cpp
new file mode 100644
index 0000000..fa54a9a
--- /dev/null
+++ b/Compiler/SymbolTable.cpp
@@ -0,0 +1,211 @@
+//
+// 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.
+//
+
+//
+// Symbol table for parsing.  Most functionaliy and main ideas
+// are documented in the header file.
+//
+
+#include "SymbolTable.h"
+
+//
+// TType helper function needs a place to live.
+//
+
+//
+// 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[10];
+		sprintf(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::iterator tl = getStruct()->begin(); tl != getStruct()->end(); tl++)
+			structureSize += ((*tl).type)->getObjectSize();
+
+	return structureSize;
+}
+
+//
+// Dump functions.
+//
+
+void TVariable::dump(TInfoSink& infoSink) const
+{
+	infoSink.debug << getName().c_str() << ": " << type.getQualifierString() << " " << 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);
+		}
+	}
+}
+
+
+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 constUnion[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));
+	}
+}
diff --git a/Compiler/SymbolTable.h b/Compiler/SymbolTable.h
new file mode 100644
index 0000000..3af31ad
--- /dev/null
+++ b/Compiler/SymbolTable.h
@@ -0,0 +1,300 @@
+//
+// 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 _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 "Common.h"
+#include "intermediate.h"
+#include "InfoSink.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 changeQualifier(TQualifier qualifier) { type.changeQualifier(qualifier); }
+    void updateArrayInformationType(TType *t) { arrayInformationType = t; }
+    TType* getArrayInformationType() { return arrayInformationType; }
+
+    virtual void dump(TInfoSink &infoSink) const;
+
+    constUnion* getConstPointer() { 
+        if (!unionArray)
+            unionArray = new constUnion[type.getObjectSize()];
+
+        return unionArray;
+    }
+
+    constUnion* getConstPointer() const { return unionArray; }
+
+    void shareConstPointer( constUnion *constArray)
+    {
+        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
+    constUnion *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)),
+        op(o),
+        defined(false) { }
+    TFunction(const TString *name, TType& retType, TOperator tOp = EOpNull) : 
+        TSymbol(name), 
+        returnType(retType),
+        mangledName(*name + '('),
+        op(tOp),
+        defined(false) { }
+	virtual ~TFunction();
+    virtual bool isFunction() const { return true; }    
+    
+    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 setDefined() { defined = true; }
+    bool isDefined() { return defined; }
+
+    int getParamCount() const { return static_cast<int>(parameters.size()); }    
+          TParameter& operator [](int i)       { return parameters[i]; }
+    const TParameter& operator [](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;
+    bool defined;
+};
+
+
+class TSymbolTableLevel {
+public:
+	typedef std::map<TString, TSymbol*, std::less<TString>, pool_allocator<std::pair<const 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 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(TSymbolTable& symTable)
+    {
+        table.push_back(symTable.table[0]);
+        uniqueId = symTable.uniqueId;
+    }
+
+    ~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 atSharedBuiltInLevel() || atDynamicBuiltInLevel(); }
+    bool atSharedBuiltInLevel() { return table.size() == 1; }	
+    bool atGlobalLevel() { return table.size() <= 3; }
+    void push() { 
+        table.push_back(new TSymbolTableLevel);
+    }
+
+    void pop() { 
+        delete table[currentLevel()]; 
+        table.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;
+    }
+
+    TSymbolTableLevel* getGlobalLevel() { assert(table.size() >= 3); return table[2]; }
+    void relateToOperator(const char* name, TOperator op) { table[0]->relateToOperator(name, op); }
+    int getMaxSymbolId() { return uniqueId; }
+    void dump(TInfoSink &infoSink) const;
+	void copyTable(const TSymbolTable& copyOf);
+
+protected:    
+    int currentLevel() const { return static_cast<int>(table.size()) - 1; }
+    bool atDynamicBuiltInLevel() { return table.size() == 2; }
+
+    std::vector<TSymbolTableLevel*> table;
+    int uniqueId;     // for unique identification in code generation
+};
+
+#endif // _SYMBOL_TABLE_INCLUDED_
diff --git a/Compiler/Tools/bison.exe b/Compiler/Tools/bison.exe
new file mode 100644
index 0000000..4881bf6
--- /dev/null
+++ b/Compiler/Tools/bison.exe
Binary files differ
diff --git a/Compiler/Tools/bison.hairy b/Compiler/Tools/bison.hairy
new file mode 100644
index 0000000..999b555
--- /dev/null
+++ b/Compiler/Tools/bison.hairy
@@ -0,0 +1,334 @@
+
+extern int timeclock;
+
+
+int yyerror;		/*  Yyerror and yycost are set by guards.	*/
+int yycost;		/*  If yyerror is set to a nonzero value by a	*/
+			/*  guard, the reduction with which the guard	*/
+			/*  is associated is not performed, and the	*/
+			/*  error recovery mechanism is invoked.	*/
+			/*  Yycost indicates the cost of performing	*/
+			/*  the reduction given the attributes of the	*/
+			/*  symbols.					*/
+
+
+/*  YYMAXDEPTH indicates the size of the parser's state and value	*/
+/*  stacks.								*/
+
+#ifndef	YYMAXDEPTH
+#define	YYMAXDEPTH	500
+#endif
+
+/*  YYMAXRULES must be at least as large as the number of rules that	*/
+/*  could be placed in the rule queue.  That number could be determined	*/
+/*  from the grammar and the size of the stack, but, as yet, it is not.	*/
+
+#ifndef	YYMAXRULES
+#define	YYMAXRULES	100
+#endif
+
+#ifndef	YYMAXBACKUP
+#define YYMAXBACKUP	100
+#endif
+
+
+short	yyss[YYMAXDEPTH];	/*  the state stack			*/
+YYSTYPE	yyvs[YYMAXDEPTH];	/*  the semantic value stack		*/
+YYLTYPE yyls[YYMAXDEPTH];	/*  the location stack			*/
+short	yyrq[YYMAXRULES];	/*  the rule queue			*/
+int	yychar;			/*  the lookahead symbol		*/
+
+YYSTYPE	yylval;			/*  the semantic value of the		*/
+				/*  lookahead symbol			*/
+
+YYSTYPE yytval;			/*  the semantic value for the state	*/
+				/*  at the top of the state stack.	*/
+
+YYSTYPE yyval;			/*  the variable used to return		*/
+				/*  semantic values from the action	*/
+				/*  routines				*/
+
+YYLTYPE yylloc;		/*  location data for the lookahead	*/
+				/*  symbol				*/
+
+YYLTYPE yytloc;		/*  location data for the state at the	*/
+				/*  top of the state stack		*/
+
+
+int	yynunlexed;
+short	yyunchar[YYMAXBACKUP];
+YYSTYPE	yyunval[YYMAXBACKUP];
+YYLTYPE yyunloc[YYMAXBACKUP];
+
+short *yygssp;			/*  a pointer to the top of the state	*/
+				/*  stack; only set during error	*/
+				/*  recovery.				*/
+
+YYSTYPE *yygvsp;		/*  a pointer to the top of the value	*/
+				/*  stack; only set during error	*/
+				/*  recovery.				*/
+
+YYLTYPE *yyglsp;		/*  a pointer to the top of the		*/
+				/*  location stack; only set during	*/
+				/*  error recovery.			*/
+
+
+/*  Yyget is an interface between the parser and the lexical analyzer.	*/
+/*  It is costly to provide such an interface, but it avoids requiring	*/
+/*  the lexical analyzer to be able to back up the scan.		*/
+
+yyget()
+{
+  if (yynunlexed > 0)
+    {
+      yynunlexed--;
+      yychar = yyunchar[yynunlexed];
+      yylval = yyunval[yynunlexed];
+      yylloc = yyunloc[yynunlexed];
+    }
+  else if (yychar <= 0)
+    yychar = 0;
+  else
+    {
+      yychar = yylex();
+      if (yychar < 0)
+	yychar = 0;
+      else yychar = YYTRANSLATE(yychar);
+    }
+}
+
+
+
+yyunlex(chr, val, loc)
+int chr;
+YYSTYPE val;
+YYLTYPE loc;
+{
+  yyunchar[yynunlexed] = chr;
+  yyunval[yynunlexed] = val;
+  yyunloc[yynunlexed] = loc;
+  yynunlexed++;
+}
+
+
+
+yyrestore(first, last)
+register short *first;
+register short *last;
+{
+  register short *ssp;
+  register short *rp;
+  register int symbol;
+  register int state;
+  register int tvalsaved;
+
+  ssp = yygssp;
+  yyunlex(yychar, yylval, yylloc);
+
+  tvalsaved = 0;
+  while (first != last)
+    {
+      symbol = yystos[*ssp];
+      if (symbol < YYNTBASE)
+	{
+	  yyunlex(symbol, yytval, yytloc);
+	  tvalsaved = 1;
+	  ssp--;
+	}
+
+      ssp--;
+
+      if (first == yyrq)
+	first = yyrq + YYMAXRULES;
+
+      first--;
+
+      for (rp = yyrhs + yyprhs[*first]; symbol = *rp; rp++)
+	{
+	  if (symbol < YYNTBASE)
+	    state = yytable[yypact[*ssp] + symbol];
+	  else
+	    {
+	      state = yypgoto[symbol - YYNTBASE] + *ssp;
+
+	      if (state >= 0 && state <= YYLAST && yycheck[state] == *ssp)
+		state = yytable[state];
+	      else
+		state = yydefgoto[symbol - YYNTBASE];
+	    }
+
+	  *++ssp = state;
+	}
+    }
+
+  if ( ! tvalsaved && ssp > yyss)
+    {
+      yyunlex(yystos[*ssp], yytval, yytloc);
+      ssp--;
+    }
+
+  yygssp = ssp;
+}
+
+
+
+int
+yyparse()
+{
+  register int yystate;
+  register int yyn;
+  register short *yyssp;
+  register short *yyrq0;
+  register short *yyptr;
+  register YYSTYPE *yyvsp;
+
+  int yylen;
+  YYLTYPE *yylsp;
+  short *yyrq1;
+  short *yyrq2;
+
+  yystate = 0;
+  yyssp = yyss - 1;
+  yyvsp = yyvs - 1;
+  yylsp = yyls - 1;
+  yyrq0 = yyrq;
+  yyrq1 = yyrq0;
+  yyrq2 = yyrq0;
+
+  yychar = yylex();
+  if (yychar < 0)
+    yychar = 0;
+  else yychar = YYTRANSLATE(yychar);
+
+yynewstate:
+
+  if (yyssp >= yyss + YYMAXDEPTH - 1)
+    {
+      yyabort("Parser Stack Overflow");
+      YYABORT;
+    }
+
+  *++yyssp = yystate;
+
+yyresume:
+
+  yyn = yypact[yystate];
+  if (yyn == YYFLAG)
+    goto yydefault;
+
+  yyn += yychar;
+  if (yyn < 0 || yyn > YYLAST || yycheck[yyn] != yychar)
+    goto yydefault;
+
+  yyn = yytable[yyn];
+  if (yyn < 0)
+    {
+      yyn = -yyn;
+      goto yyreduce;
+    }
+  else if (yyn == 0)
+    goto yyerrlab;
+
+  yystate = yyn;
+
+  yyptr = yyrq2;
+  while (yyptr != yyrq1)
+    {
+      yyn = *yyptr++;
+      yylen = yyr2[yyn];
+      yyvsp -= yylen;
+      yylsp -= yylen;
+
+      yyguard(yyn, yyvsp, yylsp);
+      if (yyerror)
+	goto yysemerr;
+
+      yyaction(yyn, yyvsp, yylsp);
+      *++yyvsp = yyval;
+
+      yylsp++;
+      if (yylen == 0)
+	{
+	  yylsp->timestamp = timeclock;
+	  yylsp->first_line = yytloc.first_line;
+	  yylsp->first_column = yytloc.first_column;
+	  yylsp->last_line = (yylsp-1)->last_line;
+	  yylsp->last_column = (yylsp-1)->last_column;
+	  yylsp->text = 0;
+	}
+      else
+	{
+	  yylsp->last_line = (yylsp+yylen-1)->last_line;
+	  yylsp->last_column = (yylsp+yylen-1)->last_column;
+	}
+	  
+      if (yyptr == yyrq + YYMAXRULES)
+        yyptr = yyrq;
+    }
+
+  if (yystate == YYFINAL)
+    YYACCEPT;
+
+  yyrq2 = yyptr;
+  yyrq1 = yyrq0;
+
+  *++yyvsp = yytval;
+  *++yylsp = yytloc;
+  yytval = yylval;
+  yytloc = yylloc;
+  yyget();
+
+  goto yynewstate;
+
+yydefault:
+
+  yyn = yydefact[yystate];
+  if (yyn == 0)
+    goto yyerrlab;
+
+yyreduce:
+
+  *yyrq0++ = yyn;
+
+  if (yyrq0 == yyrq + YYMAXRULES)
+    yyrq0 = yyrq;
+
+  if (yyrq0 == yyrq2)
+    {
+      yyabort("Parser Rule Queue Overflow");
+      YYABORT;
+    }
+
+  yyssp -= yyr2[yyn];
+  yyn = yyr1[yyn];
+
+  yystate = yypgoto[yyn - YYNTBASE] + *yyssp;
+  if (yystate >= 0 && yystate <= YYLAST && yycheck[yystate] == *yyssp)
+    yystate = yytable[yystate];
+  else
+    yystate = yydefgoto[yyn - YYNTBASE];
+
+  goto yynewstate;
+
+yysemerr:
+  *--yyptr = yyn;
+  yyrq2 = yyptr;
+  yyvsp += yyr2[yyn];
+
+yyerrlab:
+
+  yygssp = yyssp;
+  yygvsp = yyvsp;
+  yyglsp = yylsp;
+  yyrestore(yyrq0, yyrq2);
+  yyrecover();
+  yystate = *yygssp;
+  yyssp = yygssp;
+  yyvsp = yygvsp;
+  yyrq0 = yyrq;
+  yyrq1 = yyrq0;
+  yyrq2 = yyrq0;
+  goto yyresume;
+}
+
+$
diff --git a/Compiler/Tools/bison.simple b/Compiler/Tools/bison.simple
new file mode 100644
index 0000000..08acea8
--- /dev/null
+++ b/Compiler/Tools/bison.simple
@@ -0,0 +1,699 @@
+/* -*-C-*-  Note some compilers choke on comments on `#line' lines.  */
+
+/* Skeleton output parser for bison,
+   Copyright (C) 1984, 1989, 1990 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 2, 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, write to the Free Software
+   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+/* As a special exception, when this file is copied by Bison into a
+   Bison output file, you may use that output file without restriction.
+   This special exception was added by the Free Software Foundation
+   in version 1.24 of Bison.  */
+
+#ifdef __GNUC__
+#define alloca __builtin_alloca
+#else /* not __GNUC__ */
+#if HAVE_ALLOCA_H
+#include <alloca.h>
+#else /* not HAVE_ALLOCA_H */
+#ifdef _AIX
+ #pragma alloca
+#else /* not _AIX */
+char *alloca ();
+#endif /* not _AIX */
+#endif /* not HAVE_ALLOCA_H */
+#endif /* not __GNUC__ */
+
+extern void yyerror(char* s);
+
+#ifndef alloca
+#ifdef __GNUC__
+#define alloca __builtin_alloca
+#else /* not GNU C.  */
+#if (!defined (__STDC__) && defined (sparc)) || defined (__sparc__) || defined (__sparc) || defined (__sgi)
+#include <alloca.h>
+#else /* not sparc */
+#if (defined (MSDOS) && !defined (__TURBOC__)) || defined (WIN32)
+#include <malloc.h>
+#else /* not MSDOS, or __TURBOC__ */
+#if defined(_AIX)
+#include <malloc.h>
+ #pragma alloca
+#else /* not MSDOS, __TURBOC__, or _AIX */
+#ifdef __hpux
+#ifdef __cplusplus
+extern "C" {
+void *alloca (unsigned int);
+};
+#else /* not __cplusplus */
+void *alloca ();
+#endif /* not __cplusplus */
+#endif /* __hpux */
+#endif /* not _AIX */
+#endif /* not MSDOS, or __TURBOC__ */
+#endif /* not sparc.  */
+#endif /* not GNU C.  */
+#endif /* alloca not defined.  */
+
+/* This is the parser code that is written into each bison parser
+  when the %semantic_parser declaration is not specified in the grammar.
+  It was written by Richard Stallman by simplifying the hairy parser
+  used when %semantic_parser is specified.  */
+
+/* Note: there must be only one dollar sign in this file.
+   It is replaced by the list of actions, each action
+   as one case of the switch.  */
+
+#define yyerrok		(yyerrstatus = 0)
+#define yyclearin	(yychar = YYEMPTY)
+#define YYEMPTY		-2
+#define YYEOF		0
+#define YYACCEPT	return(0)
+#define YYABORT 	return(1)
+#define YYERROR		goto yyerrlab1
+/* 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);			\
+      yychar1 = YYTRANSLATE (yychar);				\
+      YYPOPSTACK;						\
+      goto yybackup;						\
+    }								\
+  else								\
+    { yyerror ("syntax error: cannot back up"); YYERROR; }	\
+while (0)
+
+#define YYTERROR	1
+#define YYERRCODE	256
+
+#ifndef YYPURE
+#define YYLEX		yylex()
+#endif
+
+#ifdef YYPURE
+#ifdef YYLSP_NEEDED
+#ifdef YYLEX_PARAM
+#define YYLEX		yylex(&yylval, &yylloc, YYLEX_PARAM)
+#else
+#define YYLEX		yylex(&yylval, &yylloc)
+#endif
+#else /* not YYLSP_NEEDED */
+#ifdef YYLEX_PARAM
+#define YYLEX		yylex(&yylval, YYLEX_PARAM)
+#else
+#define YYLEX		yylex(&yylval)
+#endif
+#endif /* not YYLSP_NEEDED */
+#endif
+
+/* If nonreentrant, generate the variables here */
+
+#ifndef YYPURE
+
+int	yychar;			/*  the lookahead symbol		*/
+YYSTYPE	yylval;			/*  the semantic value of the		*/
+				/*  lookahead symbol			*/
+
+#ifdef YYLSP_NEEDED
+YYLTYPE yylloc;			/*  location data for the lookahead	*/
+				/*  symbol				*/
+#endif
+
+int yynerrs;			/*  number of parse errors so far       */
+#endif  /* not YYPURE */
+
+#if YYDEBUG != 0
+int yydebug;			/*  nonzero means print parse trace	*/
+/* Since this is uninitialized, it does not stop multiple parsers
+   from coexisting.  */
+#endif
+
+/*  YYINITDEPTH indicates the initial size of the parser's stacks	*/
+
+#ifndef	YYINITDEPTH
+#define YYINITDEPTH 200
+#endif
+
+/*  YYMAXDEPTH is the maximum size the stacks can grow to
+    (effective only if the built-in stack extension method is used).  */
+
+#if YYMAXDEPTH == 0
+#undef YYMAXDEPTH
+#endif
+
+#ifndef YYMAXDEPTH
+#define YYMAXDEPTH 10000
+#endif
+
+/* Prevent warning if -Wstrict-prototypes.  */
+#ifdef __GNUC__
+int yyparse (void);
+#endif
+
+#if __GNUC__ > 1		/* GNU C and GNU C++ define this.  */
+#define __yy_memcpy(FROM,TO,COUNT)	__builtin_memcpy(TO,FROM,COUNT)
+#else				/* not GNU C or C++ */
+#ifndef __cplusplus
+
+/* This is the most reliable way to avoid incompatibilities
+   in available built-in functions on various systems.  */
+static void
+__yy_memcpy (from, to, count)
+     char *from;
+     char *to;
+     size_t count;
+{
+  register char *f = from;
+  register char *t = to;
+  register size_t i = count;
+
+  while (i-- > 0)
+    *t++ = *f++;
+}
+
+#else /* __cplusplus */
+
+/* This is the most reliable way to avoid incompatibilities
+   in available built-in functions on various systems.  */
+static void
+__yy_memcpy (char *from, char *to, size_t count)
+{
+  register char *f = from;
+  register char *t = to;
+  register size_t i = count;
+
+  while (i-- > 0)
+    *t++ = *f++;
+}
+
+#endif
+#endif
+
+/* The user can define YYPARSE_PARAM as the name of an argument to be passed
+   into yyparse.  The argument should have type void *.
+   It should actually point to an object.
+   Grammar actions can access the variable by casting it
+   to the proper pointer type.  */
+
+#ifdef YYPARSE_PARAM
+#ifndef YYPARSE_PARAM_DECL
+#define YYPARSE_PARAM_DECL void *YYPARSE_PARAM;
+#endif 
+#else
+#define YYPARSE_PARAM
+#define YYPARSE_PARAM_DECL
+#endif
+
+extern YY_DECL;
+
+int
+yyparse(YYPARSE_PARAM_DECL YYPARSE_PARAM) {
+  register int yystate;
+  register int yyn;
+  register short *yyssp;
+  register YYSTYPE *yyvsp;
+  int yyerrstatus;	/*  number of tokens to shift before error messages enabled */
+  int yychar1 = 0;		/*  lookahead token as an internal (translated) token number */
+
+  short	yyssa[YYINITDEPTH];	/*  the state stack			*/
+  YYSTYPE yyvsa[YYINITDEPTH];	/*  the semantic value stack		*/
+
+  short *yyss = yyssa;		/*  refer to the stacks thru separate pointers */
+  YYSTYPE *yyvs = yyvsa;	/*  to allow yyoverflow to reallocate them elsewhere */
+
+#ifdef YYLSP_NEEDED
+  YYLTYPE yylsa[YYINITDEPTH];	/*  the location stack			*/
+  YYLTYPE *yyls = yylsa;
+  YYLTYPE *yylsp;
+
+#define YYPOPSTACK   (yyvsp--, yyssp--, yylsp--)
+#else
+#define YYPOPSTACK   (yyvsp--, yyssp--)
+#endif
+
+  size_t yystacksize = YYINITDEPTH;
+
+#ifdef YYPURE
+  int yychar;
+  YYSTYPE yylval;
+  int yynerrs;
+#ifdef YYLSP_NEEDED
+  YYLTYPE yylloc;
+#endif
+#endif
+
+  YYSTYPE yyval;		/*  the variable used to return		*/
+				/*  semantic values from the action	*/
+				/*  routines				*/
+
+  int yylen;
+
+#if YYDEBUG != 0
+  if (yydebug)
+    fprintf(stderr, "Starting parse\n");
+#endif
+
+  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 - 1;
+  yyvsp = yyvs;
+#ifdef YYLSP_NEEDED
+  yylsp = yyls;
+#endif
+
+/* Push a new state, which is found in  yystate  .  */
+/* In all cases, when you get here, the value and location stacks
+   have just been pushed. so pushing a state here evens the stacks.  */
+yynewstate:
+
+  *++yyssp = yystate;
+
+  if (yyssp >= yyss + yystacksize - 1)
+    {
+      /* 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;
+      short *yyss1 = yyss;
+#ifdef YYLSP_NEEDED
+      YYLTYPE *yyls1 = yyls;
+#endif
+
+      /* Get the current used size of the three stacks, in elements.  */
+      size_t size = yyssp - yyss + 1;
+
+#ifdef yyoverflow
+      /* Each stack pointer address is followed by the size of
+	 the data in use in that stack, in bytes.  */
+#ifdef YYLSP_NEEDED
+      /* This used to be a conditional around just the two extra args,
+	 but that might be undefined if yyoverflow is a macro.  */
+      yyoverflow("parser stack overflow",
+		 &yyss1, size * sizeof (*yyssp),
+		 &yyvs1, size * sizeof (*yyvsp),
+		 &yyls1, size * sizeof (*yylsp),
+		 &yystacksize);
+#else
+      yyoverflow("parser stack overflow",
+		 &yyss1, size * sizeof (*yyssp),
+		 &yyvs1, size * sizeof (*yyvsp),
+		 &yystacksize);
+#endif
+
+      yyss = yyss1; yyvs = yyvs1;
+#ifdef YYLSP_NEEDED
+      yyls = yyls1;
+#endif
+#else /* no yyoverflow */
+      /* Extend the stack our own way.  */
+      if (yystacksize >= YYMAXDEPTH)
+	{
+	  yyerror("parser stack overflow");
+	  return 2;
+	}
+      yystacksize *= 2;
+      if (yystacksize > YYMAXDEPTH)
+	yystacksize = YYMAXDEPTH;
+      yyss = (short *) alloca (yystacksize * sizeof (*yyssp));
+      __yy_memcpy ((char *)yyss1, (char *)yyss, size * sizeof (*yyssp));
+      yyvs = (YYSTYPE *) alloca (yystacksize * sizeof (*yyvsp));
+      __yy_memcpy ((char *)yyvs1, (char *)yyvs, size * sizeof (*yyvsp));
+#ifdef YYLSP_NEEDED
+      yyls = (YYLTYPE *) alloca (yystacksize * sizeof (*yylsp));
+      __yy_memcpy ((char *)yyls1, (char *)yyls, size * sizeof (*yylsp));
+#endif
+#endif /* no yyoverflow */
+
+      yyssp = yyss + size - 1;
+      yyvsp = yyvs + size - 1;
+#ifdef YYLSP_NEEDED
+      yylsp = yyls + size - 1;
+#endif
+
+#if YYDEBUG != 0
+      if (yydebug)
+	fprintf(stderr, "Stack size increased to %d\n", yystacksize);
+#endif
+
+      if (yyssp >= yyss + yystacksize - 1)
+	YYABORT;
+    }
+
+#if YYDEBUG != 0
+  if (yydebug)
+    fprintf(stderr, "Entering state %d\n", yystate);
+#endif
+
+  goto yybackup;
+ yybackup:
+
+/* Do appropriate processing given the current state.  */
+/* Read a lookahead token if we need one and don't already have one.  */
+/* yyresume: */
+
+  /* First try to decide what to do without reference to lookahead token.  */
+
+  yyn = yypact[yystate];
+  if (yyn == YYFLAG)
+    goto yydefault;
+
+  /* Not known => get a lookahead token if don't already have one.  */
+
+  /* yychar is either YYEMPTY or YYEOF
+     or a valid token in external form.  */
+
+  if (yychar == YYEMPTY)
+    {
+#if YYDEBUG != 0
+      if (yydebug)
+	fprintf(stderr, "Reading a token: ");
+#endif
+      yychar = YYLEX;
+    }
+
+  /* Convert token to internal form (in yychar1) for indexing tables with */
+
+  if (yychar <= 0)		/* This means end of input. */
+    {
+      yychar1 = 0;
+      yychar = YYEOF;		/* Don't call YYLEX any more */
+
+#if YYDEBUG != 0
+      if (yydebug)
+	fprintf(stderr, "Now at end of input.\n");
+#endif
+    }
+  else
+    {
+      yychar1 = YYTRANSLATE(yychar);
+
+#if YYDEBUG != 0
+      if (yydebug)
+	{
+	  fprintf (stderr, "Next token is %d (%s", yychar, yytname[yychar1]);
+	  /* Give the individual parser a way to print the precise meaning
+	     of a token, for further debugging info.  */
+#ifdef YYPRINT
+	  YYPRINT (stderr, yychar, yylval);
+#endif
+	  fprintf (stderr, ")\n");
+	}
+#endif
+    }
+
+  yyn += yychar1;
+  if (yyn < 0 || yyn > YYLAST || yycheck[yyn] != yychar1)
+    goto yydefault;
+
+  yyn = yytable[yyn];
+
+  /* yyn is what to do for this token type in this state.
+     Negative => reduce, -yyn is rule number.
+     Positive => shift, yyn is new state.
+       New state is final state => don't bother to shift,
+       just return success.
+     0, or most negative number => error.  */
+
+  if (yyn < 0)
+    {
+      if (yyn == YYFLAG)
+	goto yyerrlab;
+      yyn = -yyn;
+      goto yyreduce;
+    }
+  else if (yyn == 0)
+    goto yyerrlab;
+
+  if (yyn == YYFINAL)
+    YYACCEPT;
+
+  /* Shift the lookahead token.  */
+
+#if YYDEBUG != 0
+  if (yydebug)
+    fprintf(stderr, "Shifting token %d (%s), ", yychar, yytname[yychar1]);
+#endif
+
+  /* Discard the token being shifted unless it is eof.  */
+  if (yychar != YYEOF)
+    yychar = YYEMPTY;
+
+  *++yyvsp = yylval;
+#ifdef YYLSP_NEEDED
+  *++yylsp = yylloc;
+#endif
+
+  /* count tokens shifted since error; after three, turn off error status.  */
+  if (yyerrstatus) yyerrstatus--;
+
+  yystate = yyn;
+  goto yynewstate;
+
+/* Do the default action for the current state.  */
+yydefault:
+
+  yyn = yydefact[yystate];
+  if (yyn == 0)
+    goto yyerrlab;
+
+/* Do a reduction.  yyn is the number of a rule to reduce with.  */
+yyreduce:
+  yylen = yyr2[yyn];
+  if (yylen > 0)
+    yyval = yyvsp[1-yylen]; /* implement default value of the action */
+
+#if YYDEBUG != 0
+  if (yydebug)
+    {
+      int i;
+
+      fprintf (stderr, "Reducing via rule %d (line %d), ",
+	       yyn, yyrline[yyn]);
+
+      /* Print the symbols being reduced, and their result.  */
+      for (i = yyprhs[yyn]; yyrhs[i] > 0; i++)
+	fprintf (stderr, "%s ", yytname[yyrhs[i]]);
+      fprintf (stderr, " -> %s\n", yytname[yyr1[yyn]]);
+    }
+#endif
+
+$   /* the action file gets copied in in place of this dollarsign */
+  yyvsp -= yylen;
+  yyssp -= yylen;
+#ifdef YYLSP_NEEDED
+  yylsp -= yylen;
+#endif
+
+#if YYDEBUG != 0
+  if (yydebug)
+    {
+      short *ssp1 = yyss - 1;
+      fprintf (stderr, "state stack now");
+      while (ssp1 != yyssp)
+	fprintf (stderr, " %d", *++ssp1);
+      fprintf (stderr, "\n");
+    }
+#endif
+
+  *++yyvsp = yyval;
+
+#ifdef YYLSP_NEEDED
+  yylsp++;
+  if (yylen == 0)
+    {
+      yylsp->first_line = yylloc.first_line;
+      yylsp->first_column = yylloc.first_column;
+      yylsp->last_line = (yylsp-1)->last_line;
+      yylsp->last_column = (yylsp-1)->last_column;
+      yylsp->text = 0;
+    }
+  else
+    {
+      yylsp->last_line = (yylsp+yylen-1)->last_line;
+      yylsp->last_column = (yylsp+yylen-1)->last_column;
+    }
+#endif
+
+  /* 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 - YYNTBASE] + *yyssp;
+  if (yystate >= 0 && yystate <= YYLAST && yycheck[yystate] == *yyssp)
+    yystate = yytable[yystate];
+  else
+    yystate = yydefgoto[yyn - YYNTBASE];
+
+  goto yynewstate;
+
+yyerrlab:   /* here on detecting error */
+
+  if (! yyerrstatus)
+    /* If not already recovering from an error, report this error.  */
+    {
+      ++yynerrs;
+
+#ifdef YYERROR_VERBOSE
+      yyn = yypact[yystate];
+
+      if (yyn > YYFLAG && yyn < YYLAST)
+	{
+	  int size = 0;
+	  char *msg;
+	  int x, count;
+
+	  count = 0;
+	  /* Start X at -yyn if nec to avoid negative indexes in yycheck.  */
+	  for (x = (yyn < 0 ? -yyn : 0);
+	       x < (sizeof(yytname) / sizeof(char *)); x++)
+	    if (yycheck[x + yyn] == x)
+	      size += strlen(yytname[x]) + 15, count++;
+	  msg = (char *) malloc(size + 15);
+	  if (msg != 0)
+	    {
+	      strcpy(msg, "parse error");
+
+	      if (count < 5)
+		{
+		  count = 0;
+		  for (x = (yyn < 0 ? -yyn : 0);
+		       x < (sizeof(yytname) / sizeof(char *)); x++)
+		    if (yycheck[x + yyn] == x)
+		      {
+			strcat(msg, count == 0 ? ", expecting `" : " or `");
+			strcat(msg, yytname[x]);
+			strcat(msg, "'");
+			count++;
+		      }
+		}
+	      yyerror(msg);
+	      free(msg);
+	    }
+	  else
+	    yyerror ("parse error; also virtual memory exceeded");
+	}
+      else
+#endif /* YYERROR_VERBOSE */
+	yyerror("parse error");
+    }
+
+  goto yyerrlab1;
+yyerrlab1:   /* here on error raised explicitly by an action */
+
+  if (yyerrstatus == 3)
+    {
+      /* if just tried and failed to reuse lookahead token after an error, discard it.  */
+
+      /* return failure if at end of input */
+      if (yychar == YYEOF)
+	YYABORT;
+
+#if YYDEBUG != 0
+      if (yydebug)
+	fprintf(stderr, "Discarding token %d (%s).\n", yychar, yytname[yychar1]);
+#endif
+
+      yychar = YYEMPTY;
+    }
+
+  /* Else will try to reuse lookahead token
+     after shifting the error token.  */
+
+  yyerrstatus = 3;		/* Each real token shifted decrements this */
+
+  goto yyerrhandle;
+
+yyerrdefault:  /* current state does not do anything special for the error token. */
+
+#if 0
+  /* This is wrong; only states that explicitly want error tokens
+     should shift them.  */
+  yyn = yydefact[yystate];  /* If its default is to accept any token, ok.  Otherwise pop it.*/
+  if (yyn) goto yydefault;
+#endif
+
+yyerrpop:   /* pop the current state because it cannot handle the error token */
+
+  if (yyssp == yyss) YYABORT;
+  yyvsp--;
+  yystate = *--yyssp;
+#ifdef YYLSP_NEEDED
+  yylsp--;
+#endif
+
+#if YYDEBUG != 0
+  if (yydebug)
+    {
+      short *ssp1 = yyss - 1;
+      fprintf (stderr, "Error: state stack now");
+      while (ssp1 != yyssp)
+	fprintf (stderr, " %d", *++ssp1);
+      fprintf (stderr, "\n");
+    }
+#endif
+
+yyerrhandle:
+
+  yyn = yypact[yystate];
+  if (yyn == YYFLAG)
+    goto yyerrdefault;
+
+  yyn += YYTERROR;
+  if (yyn < 0 || yyn > YYLAST || yycheck[yyn] != YYTERROR)
+    goto yyerrdefault;
+
+  yyn = yytable[yyn];
+  if (yyn < 0)
+    {
+      if (yyn == YYFLAG)
+	goto yyerrpop;
+      yyn = -yyn;
+      goto yyreduce;
+    }
+  else if (yyn == 0)
+    goto yyerrpop;
+
+  if (yyn == YYFINAL)
+    YYACCEPT;
+
+#if YYDEBUG != 0
+  if (yydebug)
+    fprintf(stderr, "Shifting error token, ");
+#endif
+
+  *++yyvsp = yylval;
+#ifdef YYLSP_NEEDED
+  *++yylsp = yylloc;
+#endif
+
+  yystate = yyn;
+  goto yynewstate;
+}
diff --git a/Compiler/Tools/flex.exe b/Compiler/Tools/flex.exe
new file mode 100644
index 0000000..58f10ce
--- /dev/null
+++ b/Compiler/Tools/flex.exe
Binary files differ
diff --git a/Compiler/Types.h b/Compiler/Types.h
new file mode 100644
index 0000000..eba792c
--- /dev/null
+++ b/Compiler/Types.h
@@ -0,0 +1,300 @@
+//
+// 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 _TYPES_INCLUDED
+#define _TYPES_INCLUDED
+
+#include "Common.h"
+#include "BaseTypes.h"
+
+//
+// Need to have association of line numbers to types in a list for building structs.
+//
+class TType;
+struct TTypeLine {
+	TType* type;
+	int line;
+};
+typedef TVector<TTypeLine> TTypeList;
+
+inline TTypeList* NewPoolTTypeList()
+{
+	void* memory = GlobalPoolAllocator.allocate(sizeof(TTypeList));
+	return new(memory) TTypeList;
+}
+
+//
+// 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.
+//
+class TPublicType {
+public:
+	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 = EbpHigh;
+		size = 1;
+		matrix = false;
+		array = false;
+		arraySize = 0;
+		userDef = 0;
+		line = ln;
+	}
+
+	void setPrecision(TPrecision pcs)
+	{
+		precision = pcs;
+	}
+
+	void setAggregate(int s, bool m = false)
+	{
+		size = s;
+		matrix = m;
+	}
+
+	void setArray(bool a, int s = 0)
+	{
+		array = a;
+		arraySize = s;
+	}
+};
+
+typedef std::map<TTypeList*, TTypeList*> TStructureMap;
+typedef std::map<TTypeList*, TTypeList*>::iterator TStructureMapIterator;
+//
+// Base class for things that have a type.
+//
+class TType {
+public:
+	POOL_ALLOCATOR_NEW_DELETE(GlobalPoolAllocator)
+	explicit TType(TBasicType t, TQualifier q = EvqTemporary, int s = 1, bool m = false, bool a = false, TPrecision p = EbpHigh) :
+							type(t), precision(p), qualifier(q), size(s), matrix(m), array(a), arraySize(0),
+							structure(0), structureSize(0), maxArraySize(0), arrayInformationType(0), fieldName(0), mangled(0), typeName(0)
+							{ }
+	explicit 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),
+							structure(0), structureSize(0), maxArraySize(0), arrayInformationType(0), fieldName(0), mangled(0), typeName(0)
+							{
+							  if (p.userDef) {
+								  structure = p.userDef->getStruct();
+								  typeName = NewPoolTString(p.userDef->getTypeName().c_str());
+							  }
+							}
+	explicit TType(TTypeList* userDef, const TString& n, TPrecision p = EbpHigh) :
+							type(EbtStruct), precision(p), qualifier(EvqTemporary), size(1), matrix(false), array(false), arraySize(0),
+							structure(userDef), maxArraySize(0), arrayInformationType(0), fieldName(0), mangled(0) {
+								typeName = NewPoolTString(n.c_str());
+							}
+	explicit TType() {}
+	virtual ~TType() {}
+
+	TType(const TType& type) { *this = type; }
+
+	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;
+		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;
+	}
+
+	virtual void setType(TBasicType t, int s, bool m, bool a, int aS = 0)
+							{ type = t; size = s; matrix = m; array = a; arraySize = aS; }
+	virtual void setType(TBasicType t, int s, bool m, TType* userDef = 0)
+							{ type = t;
+							  size = s;
+							  matrix = m;
+							  if (userDef)
+								  structure = userDef->getStruct();
+							  // leave array information intact.
+							}
+	virtual void setTypeName(const TString& n) { typeName = NewPoolTString(n.c_str()); }
+	virtual void setFieldName(const TString& n) { fieldName = NewPoolTString(n.c_str()); }
+	virtual const TString& getTypeName() const
+	{
+		assert(typeName);
+		return *typeName;
+	}
+
+	virtual const TString& getFieldName() const
+	{
+		assert(fieldName);
+		return *fieldName;
+	}
+
+	virtual TBasicType getBasicType() const { return type; }
+	virtual TPrecision getPrecision() const { return precision; }
+	virtual TQualifier getQualifier() const { return qualifier; }
+	virtual void changePrecision(TPrecision p) { precision = p; }
+	virtual void changeQualifier(TQualifier q) { qualifier = q; }
+
+	// One-dimensional size of single instance type
+	virtual int getNominalSize() const { return size; }
+
+	// Full-dimensional size of single instance of type
+	virtual int getInstanceSize() const
+	{
+		if (matrix)
+			return size * size;
+		else
+			return size;
+	}
+
+	virtual bool isMatrix() const { return matrix ? true : false; }
+	virtual bool isArray() const  { return array ? true : false; }
+	int getArraySize() const { return arraySize; }
+	void setArraySize(int s) { array = true; arraySize = s; }
+	void setMaxArraySize (int s) { maxArraySize = s; }
+	int getMaxArraySize () const { return maxArraySize; }
+	void clearArrayness() { array = false; arraySize = 0; maxArraySize = 0; }
+	void setArrayInformationType(TType* t) { arrayInformationType = t; }
+	TType* getArrayInformationType() const { return arrayInformationType; }
+	virtual bool isVector() const { return size > 1 && !matrix; }
+	static 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";
+		}
+	}
+	const char* getBasicString() const { return TType::getBasicString(type); }
+	const char* getPrecisionString() const { return ::getPrecisionString(precision); }
+	const char* getQualifierString() const { return ::getQualifierString(qualifier); }
+	TTypeList* getStruct() { return structure; }
+
+	int getObjectSize() const
+	{
+		int totalSize;
+
+		if (getBasicType() == EbtStruct)
+			totalSize = getStructSize();
+		else if (matrix)
+			totalSize = size * size;
+		else
+			totalSize = size;
+
+		if (isArray())
+			totalSize *= Max(getArraySize(), getMaxArraySize());
+
+		return totalSize;
+	}
+
+	TTypeList* getStruct() const { return structure; }
+	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);
+	}
+	TString getCompleteString() const;
+
+protected:
+	void buildMangledName(TString&);
+	int getStructSize() const;
+
+	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;
+
+	TTypeList* structure;      // 0 unless this is a struct
+	mutable int structureSize;
+	int maxArraySize;
+	TType* arrayInformationType;
+	TString *fieldName;         // for structure field names
+	TString *mangled;
+	TString *typeName;          // for structure field type name
+};
+
+#endif // _TYPES_INCLUDED_
diff --git a/Compiler/glslang.l b/Compiler/glslang.l
new file mode 100644
index 0000000..6a76234
--- /dev/null
+++ b/Compiler/glslang.l
@@ -0,0 +1,605 @@
+/*
+//
+// 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.
+//
+*/
+/* Based on
+ANSI C grammar, Lex specification
+
+In 1985, Jeff Lee published this Lex specification together with a Yacc 
+grammar for the April 30, 1985 ANSI C draft.  Tom Stockfisch reposted 
+both to net.sources in 1987; that original, as mentioned in the answer 
+to question 17.25 of the comp.lang.c FAQ, can be ftp'ed from ftp.uu.net, 
+file usenet/net.sources/ansi.c.grammar.Z. 
+
+I intend to keep this version as close to the current C Standard grammar 
+as possible; please let me know if you discover discrepancies. 
+
+Jutta Degener, 1995 
+*/
+
+D           [0-9]
+L           [a-zA-Z_]
+H           [a-fA-F0-9]
+E           [Ee][+-]?{D}+
+O           [0-7]
+
+%option nounput 
+%{
+#include <stdio.h>
+#include <stdlib.h>
+#include "ParseHelper.h"
+#include "glslang_tab.h"
+
+/* windows only pragma */
+#ifdef _MSC_VER
+#pragma warning(disable : 4102)
+#endif
+
+int yy_input(char* buf, int max_size);
+TSourceLoc yylineno;
+
+#ifdef _WIN32
+    extern int yyparse(TParseContext&);
+    #define YY_DECL int yylex(YYSTYPE* pyylval, TParseContext& parseContext)    
+#else
+    extern int yyparse(void*);
+    #define YY_DECL int yylex(YYSTYPE* pyylval, void* parseContextLocal)
+    #define parseContext (*((TParseContext*)(parseContextLocal)))		
+#endif
+ 
+#define YY_INPUT(buf,result,max_size) (result = yy_input(buf, max_size))
+
+%}
+
+%option noyywrap
+%option never-interactive
+%option outfile="Gen_glslang.cpp"
+%x FIELDS
+
+
+%%
+<*>"//"[^\n]*"\n"     { /* ?? carriage and/or line-feed? */ };
+
+"invariant"    {  pyylval->lex.line = yylineno; return(INVARIANT); }
+"highp"        {  pyylval->lex.line = yylineno; return(HIGH_PRECISION); }
+"mediump"      {  pyylval->lex.line = yylineno; return(MEDIUM_PRECISION); }
+"lowp"         {  pyylval->lex.line = yylineno; return(LOW_PRECISION); }
+"precision"    {  pyylval->lex.line = yylineno; return(PRECISION); }
+
+"attribute"    {  pyylval->lex.line = yylineno; return(ATTRIBUTE); }
+"const"        {  pyylval->lex.line = yylineno; return(CONST_QUAL); }
+"uniform"      {  pyylval->lex.line = yylineno; return(UNIFORM); }
+"varying"      {  pyylval->lex.line = yylineno; return(VARYING); }
+
+"break"        {  pyylval->lex.line = yylineno; return(BREAK); }
+"continue"     {  pyylval->lex.line = yylineno; return(CONTINUE); }
+"do"           {  pyylval->lex.line = yylineno; return(DO); }
+"for"          {  pyylval->lex.line = yylineno; return(FOR); }
+"while"        {  pyylval->lex.line = yylineno; return(WHILE); }
+
+"if"           {  pyylval->lex.line = yylineno; return(IF); }
+"else"         {  pyylval->lex.line = yylineno; return(ELSE); }
+
+"in"           {  pyylval->lex.line = yylineno; return(IN_QUAL); }
+"out"          {  pyylval->lex.line = yylineno; return(OUT_QUAL); }
+"inout"        {  pyylval->lex.line = yylineno; return(INOUT_QUAL); }
+
+"float"        {  pyylval->lex.line = yylineno; parseContext.lexAfterType = true; return(FLOAT_TYPE); }
+"int"          {  pyylval->lex.line = yylineno; parseContext.lexAfterType = true; return(INT_TYPE); }
+"void"         {  pyylval->lex.line = yylineno; parseContext.lexAfterType = true; return(VOID_TYPE); }
+"bool"         {  pyylval->lex.line = yylineno; parseContext.lexAfterType = true; return(BOOL_TYPE); }
+"true"         {  pyylval->lex.line = yylineno; pyylval->lex.b = true;  return(BOOLCONSTANT); }
+"false"        {  pyylval->lex.line = yylineno; pyylval->lex.b = false; return(BOOLCONSTANT); }
+
+"discard"      {  pyylval->lex.line = yylineno; return(DISCARD); }
+"return"       {  pyylval->lex.line = yylineno; return(RETURN); }
+
+"mat2"         {  pyylval->lex.line = yylineno; parseContext.lexAfterType = true; return(MATRIX2); }
+"mat3"         {  pyylval->lex.line = yylineno; parseContext.lexAfterType = true; return(MATRIX3); }
+"mat4"         {  pyylval->lex.line = yylineno; parseContext.lexAfterType = true; return(MATRIX4); }
+
+"vec2"         {  pyylval->lex.line = yylineno; parseContext.lexAfterType = true; return (VEC2); }
+"vec3"         {  pyylval->lex.line = yylineno; parseContext.lexAfterType = true; return (VEC3); }
+"vec4"         {  pyylval->lex.line = yylineno; parseContext.lexAfterType = true; return (VEC4); }
+"ivec2"        {  pyylval->lex.line = yylineno; parseContext.lexAfterType = true; return (IVEC2); }
+"ivec3"        {  pyylval->lex.line = yylineno; parseContext.lexAfterType = true; return (IVEC3); }
+"ivec4"        {  pyylval->lex.line = yylineno; parseContext.lexAfterType = true; return (IVEC4); }
+"bvec2"        {  pyylval->lex.line = yylineno; parseContext.lexAfterType = true; return (BVEC2); }
+"bvec3"        {  pyylval->lex.line = yylineno; parseContext.lexAfterType = true; return (BVEC3); }
+"bvec4"        {  pyylval->lex.line = yylineno; parseContext.lexAfterType = true; return (BVEC4); }
+
+"sampler2D"       {  pyylval->lex.line = yylineno; parseContext.lexAfterType = true; return SAMPLER2D; }
+"samplerCube"     {  pyylval->lex.line = yylineno; parseContext.lexAfterType = true; return SAMPLERCUBE; }
+
+"struct"       {  pyylval->lex.line = yylineno; return(STRUCT); }
+
+"asm"          {  PaReservedWord(); return 0; }
+
+"class"        {  PaReservedWord(); return 0; }
+"union"        {  PaReservedWord(); return 0; }
+"enum"         {  PaReservedWord(); return 0; }
+"typedef"      {  PaReservedWord(); return 0; }
+"template"     {  PaReservedWord(); return 0; }
+"this"         {  PaReservedWord(); return 0; }
+"packed"       {  PaReservedWord(); return 0; }
+
+"goto"         {  PaReservedWord(); return 0; }
+"switch"       {  PaReservedWord(); return 0; }
+"default"      {  PaReservedWord(); return 0; }
+
+"inline"       {  PaReservedWord(); return 0; }
+"noinline"     {  PaReservedWord(); return 0; }
+"volatile"     {  PaReservedWord(); return 0; }
+"public"       {  PaReservedWord(); return 0; }
+"static"       {  PaReservedWord(); return 0; }
+"extern"       {  PaReservedWord(); return 0; }
+"external"     {  PaReservedWord(); return 0; }
+"interface"    {  PaReservedWord(); return 0; }
+
+"long"         {  PaReservedWord(); return 0; }
+"short"        {  PaReservedWord(); return 0; }
+"double"       {  PaReservedWord(); return 0; }
+"half"         {  PaReservedWord(); return 0; }
+"fixed"        {  PaReservedWord(); return 0; }
+"unsigned"     {  PaReservedWord(); return 0; }
+
+"input"        {  PaReservedWord(); return 0; }
+"output"       {  PaReservedWord(); return 0; }
+
+"hvec2"        {  PaReservedWord(); return 0; }
+"hvec3"        {  PaReservedWord(); return 0; }
+"hvec4"        {  PaReservedWord(); return 0; }
+"fvec2"        {  PaReservedWord(); return 0; }
+"fvec3"        {  PaReservedWord(); return 0; }
+"fvec4"        {  PaReservedWord(); return 0; }
+"dvec2"        {  PaReservedWord(); return 0; }
+"dvec3"        {  PaReservedWord(); return 0; }
+"dvec4"        {  PaReservedWord(); return 0; }
+
+"sizeof"       {  PaReservedWord(); return 0; }
+"cast"         {  PaReservedWord(); return 0; }
+
+"namespace"    {  PaReservedWord(); return 0; }
+"using"        {  PaReservedWord(); return 0; }
+
+{L}({L}|{D})*       {  
+   pyylval->lex.line = yylineno; 
+   pyylval->lex.string = NewPoolTString(yytext); 
+   return PaIdentOrType(*pyylval->lex.string, parseContext, pyylval->lex.symbol); 
+}
+
+0[xX]{H}+         { pyylval->lex.line = yylineno; pyylval->lex.i = strtol(yytext, 0, 0); return(INTCONSTANT); }
+0{O}+             { pyylval->lex.line = yylineno; pyylval->lex.i = strtol(yytext, 0, 0); return(INTCONSTANT); }
+0{D}+             { pyylval->lex.line = yylineno; parseContext.error(yylineno, "Invalid Octal number.", yytext, "", ""); parseContext.recover(); return 0;}
+{D}+              { pyylval->lex.line = yylineno; pyylval->lex.i = strtol(yytext, 0, 0); return(INTCONSTANT); }
+
+{D}+{E}           { pyylval->lex.line = yylineno; pyylval->lex.f = static_cast<float>(atof(yytext)); return(FLOATCONSTANT); }
+{D}+"."{D}*({E})? { pyylval->lex.line = yylineno; pyylval->lex.f = static_cast<float>(atof(yytext)); return(FLOATCONSTANT); }
+"."{D}+({E})?     { pyylval->lex.line = yylineno; pyylval->lex.f = static_cast<float>(atof(yytext)); return(FLOATCONSTANT); }
+
+"/*"            {  int ret = PaParseComment(pyylval->lex.line, parseContext); if (!ret) return ret; }   
+
+"+="            {  pyylval->lex.line = yylineno; return(ADD_ASSIGN); }
+"-="            {  pyylval->lex.line = yylineno; return(SUB_ASSIGN); }
+"*="            {  pyylval->lex.line = yylineno; return(MUL_ASSIGN); }
+"/="            {  pyylval->lex.line = yylineno; return(DIV_ASSIGN); }
+"%="            {  pyylval->lex.line = yylineno; return(MOD_ASSIGN); }
+"<<="           {  pyylval->lex.line = yylineno; return(LEFT_ASSIGN); }
+">>="           {  pyylval->lex.line = yylineno; return(RIGHT_ASSIGN); }
+"&="            {  pyylval->lex.line = yylineno; return(AND_ASSIGN); }
+"^="            {  pyylval->lex.line = yylineno; return(XOR_ASSIGN); }
+"|="            {  pyylval->lex.line = yylineno; return(OR_ASSIGN); }
+
+"++"            {  pyylval->lex.line = yylineno; return(INC_OP); }
+"--"            {  pyylval->lex.line = yylineno; return(DEC_OP); }
+"&&"            {  pyylval->lex.line = yylineno; return(AND_OP); }
+"||"            {  pyylval->lex.line = yylineno; return(OR_OP); }
+"^^"            {  pyylval->lex.line = yylineno; return(XOR_OP); }
+"<="            {  pyylval->lex.line = yylineno; return(LE_OP); }
+">="            {  pyylval->lex.line = yylineno; return(GE_OP); }
+"=="            {  pyylval->lex.line = yylineno; return(EQ_OP); }
+"!="            {  pyylval->lex.line = yylineno; return(NE_OP); }
+"<<"            {  pyylval->lex.line = yylineno; return(LEFT_OP); }
+">>"            {  pyylval->lex.line = yylineno; return(RIGHT_OP); }
+";"         {  pyylval->lex.line = yylineno; parseContext.lexAfterType = false; return(SEMICOLON); }
+("{"|"<%")      {  pyylval->lex.line = yylineno; parseContext.lexAfterType = false; return(LEFT_BRACE); }
+("}"|"%>")      {  pyylval->lex.line = yylineno; return(RIGHT_BRACE); }
+","         {  pyylval->lex.line = yylineno; if (parseContext.inTypeParen) parseContext.lexAfterType = false; return(COMMA); }
+":"         {  pyylval->lex.line = yylineno; return(COLON); }
+"="         {  pyylval->lex.line = yylineno; parseContext.lexAfterType = false; return(EQUAL); }
+"("         {  pyylval->lex.line = yylineno; parseContext.lexAfterType = false; parseContext.inTypeParen = true; return(LEFT_PAREN); }
+")"         {  pyylval->lex.line = yylineno; parseContext.inTypeParen = false; return(RIGHT_PAREN); }
+("["|"<:")      {  pyylval->lex.line = yylineno; return(LEFT_BRACKET); }
+("]"|":>")      {  pyylval->lex.line = yylineno; return(RIGHT_BRACKET); }
+"."         { BEGIN(FIELDS);  return(DOT); }
+"!"         {  pyylval->lex.line = yylineno; return(BANG); }
+"-"         {  pyylval->lex.line = yylineno; return(DASH); }
+"~"         {  pyylval->lex.line = yylineno; return(TILDE); }
+"+"         {  pyylval->lex.line = yylineno; return(PLUS); }
+"*"         {  pyylval->lex.line = yylineno; return(STAR); }
+"/"         {  pyylval->lex.line = yylineno; return(SLASH); }
+"%"         {  pyylval->lex.line = yylineno; return(PERCENT); }
+"<"         {  pyylval->lex.line = yylineno; return(LEFT_ANGLE); }
+">"         {  pyylval->lex.line = yylineno; return(RIGHT_ANGLE); }
+"|"         {  pyylval->lex.line = yylineno; return(VERTICAL_BAR); }
+"^"         {  pyylval->lex.line = yylineno; return(CARET); }
+"&"         {  pyylval->lex.line = yylineno; return(AMPERSAND); }
+"?"         {  pyylval->lex.line = yylineno; return(QUESTION); }
+
+<FIELDS>{L}({L}|{D})* { 
+BEGIN(INITIAL);      
+    pyylval->lex.line = yylineno;     
+    pyylval->lex.string = NewPoolTString(yytext); 
+    return FIELD_SELECTION; }
+<FIELDS>[ \t\v\f\r] {}
+
+[ \t\v\n\f\r]   {  }
+<*><<EOF>> { (&parseContext)->AfterEOF = true; yy_delete_buffer(YY_CURRENT_BUFFER); yyterminate();}
+<*>.    { parseContext.infoSink.info << "FLEX: Unknown char " << yytext << "\n";
+          return 0; }
+
+%%
+
+
+//Including Pre-processor.
+extern "C" {
+  #include "./preprocessor/preprocess.h"
+} 
+
+//
+// The YY_INPUT macro just calls this.  Maybe this could be just put into
+// the macro directly.
+//
+
+int yy_input(char* buf, int max_size)
+{
+    int len;
+
+    if ((len = yylex_CPP(buf, max_size)) == 0)
+        return 0;
+    if (len >= max_size) 
+        YY_FATAL_ERROR( "input buffer overflow, can't enlarge buffer because scanner uses REJECT" );
+
+    buf[len] = ' ';
+	return len+1;
+}
+
+
+//
+// Parse an array of strings using yyparse.  We set up globals used by
+// yywrap.
+//
+// Returns 0 for success, as per yyparse().
+//
+int PaParseStrings(char* argv[], int strLen[], int argc, TParseContext& parseContextLocal)
+{
+    int argv0len;
+    
+    ScanFromString(argv[0]); 
+    
+    //Storing the Current Compiler Parse context into the cpp structure.
+	cpp->pC = (void*)&parseContextLocal;
+	
+	if (!argv || argc == 0)
+        return 1;
+    
+    for (int i = 0; i < argc; ++i) {
+        if (!argv[i]) {
+            parseContextLocal.error(0, "Null shader source string", "", "");
+            parseContextLocal.recover();
+            return 1;
+        }
+    }
+    
+    if (!strLen) {
+        argv0len = (int) strlen(argv[0]);
+        strLen   = &argv0len;
+    }
+    yyrestart(0);
+    (&parseContextLocal)->AfterEOF = false;
+    cpp->PaWhichStr = 0;
+    cpp->PaArgv     = argv;
+    cpp->PaArgc     = argc;
+    cpp->PaStrLen   = strLen;
+    cpp->notAVersionToken = 0;
+    yylineno   = 1;
+   
+    if (*cpp->PaStrLen >= 0) {    
+        int ret;
+        #ifdef _WIN32
+            ret = yyparse(parseContextLocal);            
+        #else
+            ret = yyparse((void*)(&parseContextLocal));
+        #endif
+        if (cpp->CompileError == 1 || parseContextLocal.recoveredFromError || parseContextLocal.numErrors > 0)
+             return 1;
+        else
+             return 0;
+    }
+    else
+        return 0;
+}
+
+void yyerror(char *s) 
+{
+    if (((TParseContext *)cpp->pC)->AfterEOF) {
+        if (cpp->tokensBeforeEOF == 1) {
+            GlobalParseContext->error(yylineno, "syntax error", "pre-mature EOF", s, "");
+            GlobalParseContext->recover();
+        }
+    } else {
+        GlobalParseContext->error(yylineno, "syntax error", yytext, s, "");
+        GlobalParseContext->recover();
+    }            
+}
+
+void PaReservedWord()
+{
+    GlobalParseContext->error(yylineno, "Reserved word.", yytext, "", "");
+    GlobalParseContext->recover();
+}
+
+int PaIdentOrType(TString& id, TParseContext& parseContextLocal, TSymbol*& symbol)
+{
+    symbol = parseContextLocal.symbolTable.find(id);
+    if (parseContextLocal.lexAfterType == false && symbol && symbol->isVariable()) {
+        TVariable* variable = static_cast<TVariable*>(symbol);
+        if (variable->isUserType()) {
+            parseContextLocal.lexAfterType = true;
+            return TYPE_NAME;
+        }
+    }
+    
+    return IDENTIFIER;
+}
+
+int PaParseComment(int &lineno, TParseContext& parseContextLocal)
+{
+    int transitionFlag = 0;
+    int nextChar;
+    
+    while (transitionFlag != 2) {
+        nextChar = yyinput();
+        if (nextChar == '\n')
+             lineno++;
+        switch (nextChar) {
+        case '*' :
+            transitionFlag = 1;
+            break;
+        case '/' :  /* if star is the previous character, then it is the end of comment */
+            if (transitionFlag == 1) {
+                return 1 ;
+            }
+            break;
+        case EOF :
+            /* Raise error message here */
+            parseContextLocal.error(yylineno, "End of shader found before end of comment.", "", "", "");
+            GlobalParseContext->recover();
+            return YY_NULL; 
+        default :  /* Any other character will be a part of the comment */
+            transitionFlag = 0;
+        }
+    }
+    return 1;
+}
+
+extern "C" {
+
+void CPPDebugLogMsg(const char *msg)
+{
+    ((TParseContext *)cpp->pC)->infoSink.debug.message(EPrefixNone, msg);
+}
+
+void CPPWarningToInfoLog(const char *msg)
+{
+    ((TParseContext *)cpp->pC)->infoSink.info.message(EPrefixWarning, msg, yylineno); 
+}
+
+void CPPShInfoLogMsg(const char *msg)
+{
+    ((TParseContext *)cpp->pC)->error(yylineno,"", "",msg,"");
+    GlobalParseContext->recover();
+}
+
+void CPPErrorToInfoLog(char *msg)
+{
+    ((TParseContext *)cpp->pC)->error(yylineno,"syntax error", "",msg,"");
+    GlobalParseContext->recover();
+}
+
+void SetLineNumber(int line)
+{
+    yylineno &= ~SourceLocLineMask;
+    yylineno |= line;
+}
+
+void SetStringNumber(int string)
+{
+    yylineno = (string << SourceLocStringShift) | (yylineno & SourceLocLineMask);
+}
+
+int GetStringNumber(void)
+{
+    return yylineno >> 16;
+}
+
+int GetLineNumber(void)
+{
+    return yylineno & SourceLocLineMask;
+}
+
+void IncLineNumber(void)
+{
+    if ((yylineno & SourceLocLineMask) <= SourceLocLineMask)
+        ++yylineno;
+}
+
+void DecLineNumber(void)
+{
+    if ((yylineno & SourceLocLineMask) > 0)
+        --yylineno;
+}
+
+void HandlePragma(const char **tokens, int numTokens)
+{    
+    if (!strcmp(tokens[0], "optimize")) {
+        if (numTokens != 4) {
+            CPPShInfoLogMsg("optimize pragma syntax is incorrect");
+            return;
+        }
+        
+        if (strcmp(tokens[1], "(")) {
+            CPPShInfoLogMsg("\"(\" expected after 'optimize' keyword");
+            return;
+        }
+            
+        if (!strcmp(tokens[2], "on"))
+            ((TParseContext *)cpp->pC)->contextPragma.optimize = true;
+        else if (!strcmp(tokens[2], "off"))
+            ((TParseContext *)cpp->pC)->contextPragma.optimize = false;
+        else {
+            CPPShInfoLogMsg("\"on\" or \"off\" expected after '(' for 'optimize' pragma");
+            return;
+        }
+        
+        if (strcmp(tokens[3], ")")) {
+            CPPShInfoLogMsg("\")\" expected to end 'optimize' pragma");
+            return;
+        }
+    } else if (!strcmp(tokens[0], "debug")) {
+        if (numTokens != 4) {
+            CPPShInfoLogMsg("debug pragma syntax is incorrect");
+            return;
+        }
+        
+        if (strcmp(tokens[1], "(")) {
+            CPPShInfoLogMsg("\"(\" expected after 'debug' keyword");
+            return;
+        }
+            
+        if (!strcmp(tokens[2], "on"))
+            ((TParseContext *)cpp->pC)->contextPragma.debug = true;
+        else if (!strcmp(tokens[2], "off"))
+            ((TParseContext *)cpp->pC)->contextPragma.debug = false;
+        else {
+            CPPShInfoLogMsg("\"on\" or \"off\" expected after '(' for 'debug' pragma");
+            return;
+        }
+        
+        if (strcmp(tokens[3], ")")) {
+            CPPShInfoLogMsg("\")\" expected to end 'debug' pragma");
+            return;
+        }
+    } else {
+
+#ifdef PRAGMA_TABLE
+        //
+        // implementation specific pragma
+        // use ((TParseContext *)cpp->pC)->contextPragma.pragmaTable to store the information about pragma
+        // For now, just ignore the pragma that the implementation cannot recognize
+        // An Example of one such implementation for a pragma that has a syntax like
+        // #pragma pragmaname(pragmavalue)
+        // This implementation stores the current pragmavalue against the pragma name in pragmaTable.
+        //        
+        if (numTokens == 4 && !strcmp(tokens[1], "(") && !strcmp(tokens[3], ")")) {              
+            TPragmaTable& pragmaTable = ((TParseContext *)cpp->pC)->contextPragma.pragmaTable;
+            TPragmaTable::iterator iter;
+            iter = pragmaTable.find(TString(tokens[0]));
+            if (iter != pragmaTable.end()) {
+                iter->second = tokens[2];
+            } else {
+                pragmaTable[tokens[0]] = tokens[2];
+            }        
+        } else if (numTokens >= 2) {
+            TPragmaTable& pragmaTable = ((TParseContext *)cpp->pC)->contextPragma.pragmaTable;
+            TPragmaTable::iterator iter;
+            iter = pragmaTable.find(TString(tokens[0]));
+            if (iter != pragmaTable.end()) {
+                iter->second = tokens[1];
+            } else {
+                pragmaTable[tokens[0]] = tokens[1];
+            }
+        }
+#endif // PRAGMA_TABLE
+    }
+}
+
+void StoreStr(char *string)
+{
+    TString strSrc;
+    strSrc = TString(string);
+
+    ((TParseContext *)cpp->pC)->HashErrMsg = ((TParseContext *)cpp->pC)->HashErrMsg + " " + strSrc;
+}
+
+const char* GetStrfromTStr(void)
+{
+    cpp->ErrMsg = (((TParseContext *)cpp->pC)->HashErrMsg).c_str();
+    return cpp->ErrMsg;
+}
+
+void ResetTString(void)
+{
+    ((TParseContext *)cpp->pC)->HashErrMsg = "";
+}
+
+TBehavior GetBehavior(const char* behavior)
+{
+    if (!strcmp("require", behavior))
+        return EBhRequire;
+    else if (!strcmp("enable", behavior))
+        return EBhEnable;
+    else if (!strcmp("disable", behavior))
+        return EBhDisable;
+    else if (!strcmp("warn", behavior))
+        return EBhWarn;
+    else {
+        CPPShInfoLogMsg((TString("behavior '") + behavior + "' is not supported").c_str());
+        return EBhDisable;
+    }        
+}
+
+void  updateExtensionBehavior(const char* extName, const char* behavior)
+{
+    TBehavior behaviorVal = GetBehavior(behavior);
+    TMap<TString, TBehavior>:: iterator iter;
+    TString msg;
+    
+    // special cased for all extension
+    if (!strcmp(extName, "all")) {
+        if (behaviorVal == EBhRequire || behaviorVal == EBhEnable) {
+            CPPShInfoLogMsg("extension 'all' cannot have 'require' or 'enable' behavior");  
+            return;
+        } else {
+            for (iter =  ((TParseContext *)cpp->pC)->extensionBehavior.begin(); iter != ((TParseContext *)cpp->pC)->extensionBehavior.end(); ++iter)
+                iter->second = behaviorVal;
+        }        
+    } else {
+        iter = ((TParseContext *)cpp->pC)->extensionBehavior.find(TString(extName));
+        if (iter == ((TParseContext *)cpp->pC)->extensionBehavior.end()) {
+            switch (behaviorVal) {
+            case EBhRequire:
+                CPPShInfoLogMsg((TString("extension '") + extName + "' is not supported").c_str());  
+                break;
+            case EBhEnable:
+            case EBhWarn:
+            case EBhDisable:
+                msg = TString("extension '") + extName + "' is not supported";
+                ((TParseContext *)cpp->pC)->infoSink.info.message(EPrefixWarning, msg.c_str(), yylineno); 
+                break;
+            }
+            return;
+        } else
+            iter->second = behaviorVal;
+    }
+}
+        
+}  // extern "C"
+
+void setInitialState()
+{
+    yy_start = 1;
+}
diff --git a/Compiler/glslang.y b/Compiler/glslang.y
new file mode 100644
index 0000000..ec2603e
--- /dev/null
+++ b/Compiler/glslang.y
@@ -0,0 +1,2204 @@
+//
+// 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 is bison grammar and production code for parsing the OpenGL 2.0 shading
+ * languages.
+ */
+%{
+
+/* Based on:
+ANSI C Yacc grammar
+
+In 1985, Jeff Lee published his Yacc grammar (which is accompanied by a
+matching Lex specification) for the April 30, 1985 draft version of the
+ANSI C standard.  Tom Stockfisch reposted it to net.sources in 1987; that
+original, as mentioned in the answer to question 17.25 of the comp.lang.c
+FAQ, can be ftp'ed from ftp.uu.net, file usenet/net.sources/ansi.c.grammar.Z.
+
+I intend to keep this version as close to the current C Standard grammar as
+possible; please let me know if you discover discrepancies.
+
+Jutta Degener, 1995
+*/
+
+#include "SymbolTable.h"
+#include "ParseHelper.h"
+#include "ShaderLang.h"
+
+#ifdef _WIN32
+    #define YYPARSE_PARAM parseContext
+    #define YYPARSE_PARAM_DECL TParseContext&
+    #define YY_DECL int yylex(YYSTYPE* pyylval, TParseContext& parseContext)
+    #define YYLEX_PARAM parseContext
+#else
+    #define YYPARSE_PARAM parseContextLocal
+    #define parseContext (*((TParseContext*)(parseContextLocal)))
+    #define YY_DECL int yylex(YYSTYPE* pyylval, void* parseContextLocal)
+    #define YYLEX_PARAM (void*)(parseContextLocal)
+    extern void yyerror(char*);
+#endif
+
+#define FRAG_VERT_ONLY(S, L) {                                                  \
+    if (parseContext.language != EShLangFragment &&                             \
+        parseContext.language != EShLangVertex) {                               \
+        parseContext.error(L, " supported in vertex/fragment shaders only ", S, "", "");   \
+        parseContext.recover();                                                            \
+    }                                                                           \
+}
+
+#define VERTEX_ONLY(S, L) {                                                     \
+    if (parseContext.language != EShLangVertex) {                               \
+        parseContext.error(L, " supported in vertex shaders only ", S, "", "");            \
+        parseContext.recover();                                                            \
+    }                                                                           \
+}
+
+#define FRAG_ONLY(S, L) {                                                       \
+    if (parseContext.language != EShLangFragment) {                             \
+        parseContext.error(L, " supported in fragment shaders only ", S, "", "");          \
+        parseContext.recover();                                                            \
+    }                                                                           \
+}
+
+#define PACK_ONLY(S, L) {                                                       \
+    if (parseContext.language != EShLangPack) {                                 \
+        parseContext.error(L, " supported in pack shaders only ", S, "", "");              \
+        parseContext.recover();                                                            \
+    }                                                                           \
+}
+
+#define UNPACK_ONLY(S, L) {                                                     \
+    if (parseContext.language != EShLangUnpack) {                               \
+        parseContext.error(L, " supported in unpack shaders only ", S, "", "");            \
+        parseContext.recover();                                                            \
+    }                                                                           \
+}
+
+#define PACK_UNPACK_ONLY(S, L) {                                                \
+    if (parseContext.language != EShLangUnpack &&                               \
+        parseContext.language != EShLangPack) {                                 \
+        parseContext.error(L, " supported in pack/unpack shaders only ", S, "", "");       \
+        parseContext.recover();                                                            \
+    }                                                                           \
+}
+%}
+%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;
+}
+
+%{
+#ifndef _WIN32
+    extern int yylex(YYSTYPE*, void*);
+#endif
+%}
+
+%pure_parser /* Just in case is called from multiple threads */
+%expect 1 /* One shift reduce conflict because of if | else */
+%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
+%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) {
+            parseContext.error($1.line, "undeclared identifier", $1.string->c_str(), "");
+            parseContext.recover();
+            TType type(EbtFloat);
+            TVariable* fakeVariable = new TVariable($1.string, type);
+            parseContext.symbolTable.insert(*fakeVariable);
+            variable = fakeVariable;
+        } else {
+            // This identifier can only be a variable type symbol
+            if (! symbol->isVariable()) {
+                parseContext.error($1.line, "variable expected", $1.string->c_str(), "");
+                parseContext.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 ) {
+            constUnion* constArray = variable->getConstPointer();
+            TType t(variable->getType());
+            $$ = parseContext.intermediate.addConstantUnion(constArray, t, $1.line);
+        } else
+            $$ = parseContext.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)) {
+            parseContext.error($1.line, " integer constant overflow", "", "");
+            parseContext.recover();
+        }
+        constUnion *unionArray = new constUnion[1];
+        unionArray->setIConst($1.i);
+        $$ = parseContext.intermediate.addConstantUnion(unionArray, TType(EbtInt, EvqConst), $1.line);
+    }
+    | FLOATCONSTANT {
+        constUnion *unionArray = new constUnion[1];
+        unionArray->setFConst($1.f);
+        $$ = parseContext.intermediate.addConstantUnion(unionArray, TType(EbtFloat, EvqConst), $1.line);
+    }
+    | BOOLCONSTANT {
+        constUnion *unionArray = new constUnion[1];
+        unionArray->setBConst($1.b);
+        $$ = parseContext.intermediate.addConstantUnion(unionArray, TType(EbtBool, 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())
+                parseContext.error($2.line, " left of '[' is not of type array, matrix, or vector ", $1->getAsSymbolNode()->getSymbol().c_str(), "");
+            else
+                parseContext.error($2.line, " left of '[' is not of type array, matrix, or vector ", "expression", "");
+            parseContext.recover();
+        }
+        if ($1->getType().getQualifier() == EvqConst && $3->getQualifier() == EvqConst) {
+            if ($1->isArray()) { // constant folding for arrays
+                $$ = parseContext.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
+                $$ = parseContext.addConstVectorNode(fields, $1, $2.line);
+            } else if ($1->isMatrix()) { // constant folding for matrices
+                $$ = parseContext.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() ) {
+                    parseContext.error($2.line, "", "[", "field selection out of range '%d'", $3->getAsConstantUnion()->getUnionArrayPointer()->getIConst());
+                    parseContext.recover();
+                } else {
+                    if ($1->isArray()) {
+                        if ($1->getType().getArraySize() == 0) {
+                            if ($1->getType().getMaxArraySize() <= $3->getAsConstantUnion()->getUnionArrayPointer()->getIConst()) {
+                                if (parseContext.arraySetMaxSize($1->getAsSymbolNode(), $1->getTypePointer(), $3->getAsConstantUnion()->getUnionArrayPointer()->getIConst(), true, $2.line))
+                                    parseContext.recover();
+                            } else {
+                                if (parseContext.arraySetMaxSize($1->getAsSymbolNode(), $1->getTypePointer(), 0, false, $2.line))
+                                    parseContext.recover();
+                            }
+                        } else if ( $3->getAsConstantUnion()->getUnionArrayPointer()->getIConst() >= $1->getType().getArraySize()) {
+                            parseContext.error($2.line, "", "[", "array index out of range '%d'", $3->getAsConstantUnion()->getUnionArrayPointer()->getIConst());
+                            parseContext.recover();
+                        }
+                    }
+                    $$ = parseContext.intermediate.addIndex(EOpIndexDirect, $1, $3, $2.line);
+                }
+            } else {
+                if ($1->isArray() && $1->getType().getArraySize() == 0) {
+                    parseContext.error($2.line, "", "[", "array must be redeclared with a size before being indexed with a variable");
+                    parseContext.recover();
+                }
+
+                $$ = parseContext.intermediate.addIndex(EOpIndexIndirect, $1, $3, $2.line);
+            }
+        }
+        if ($$ == 0) {
+            constUnion *unionArray = new constUnion[1];
+            unionArray->setFConst(0.0f);
+            $$ = parseContext.intermediate.addConstantUnion(unionArray, TType(EbtFloat, EvqConst), $2.line);
+        } else if ($1->isArray()) {
+            if ($1->getType().getStruct())
+                $$->setType(TType($1->getType().getStruct(), $1->getType().getTypeName()));
+            else
+                $$->setType(TType($1->getBasicType(), EvqTemporary, $1->getNominalSize(), $1->isMatrix()));
+
+            if ($1->getType().getQualifier() == EvqConst)
+                $$->getTypePointer()->changeQualifier(EvqConst);
+        } else if ($1->isMatrix() && $1->getType().getQualifier() == EvqConst)
+            $$->setType(TType($1->getBasicType(), EvqConst, $1->getNominalSize()));
+        else if ($1->isMatrix())
+            $$->setType(TType($1->getBasicType(), EvqTemporary, $1->getNominalSize()));
+        else if ($1->isVector() && $1->getType().getQualifier() == EvqConst)
+            $$->setType(TType($1->getBasicType(), EvqConst));
+        else if ($1->isVector())
+            $$->setType(TType($1->getBasicType(), EvqTemporary));
+        else
+            $$->setType($1->getType());
+    }
+    | function_call {
+        $$ = $1;
+    }
+    | postfix_expression DOT FIELD_SELECTION {
+        if ($1->isArray()) {
+            parseContext.error($3.line, "cannot apply dot operator to an array", ".", "");
+            parseContext.recover();
+        }
+
+        if ($1->isVector()) {
+            TVectorFields fields;
+            if (! parseContext.parseVectorFields(*$3.string, $1->getNominalSize(), fields, $3.line)) {
+                fields.num = 1;
+                fields.offsets[0] = 0;
+                parseContext.recover();
+            }
+
+            if ($1->getType().getQualifier() == EvqConst) { // constant folding for vector fields
+                $$ = parseContext.addConstVectorNode(fields, $1, $3.line);
+                if ($$ == 0) {
+                    parseContext.recover();
+                    $$ = $1;
+                }
+                else
+                    $$->setType(TType($1->getBasicType(), EvqConst, (int) (*$3.string).size()));
+            } else {
+                if (fields.num == 1) {
+                    constUnion *unionArray = new constUnion[1];
+                    unionArray->setIConst(fields.offsets[0]);
+                    TIntermTyped* index = parseContext.intermediate.addConstantUnion(unionArray, TType(EbtInt, EvqConst), $3.line);
+                    $$ = parseContext.intermediate.addIndex(EOpIndexDirect, $1, index, $2.line);
+                    $$->setType(TType($1->getBasicType()));
+                } else {
+                    TString vectorString = *$3.string;
+                    TIntermTyped* index = parseContext.intermediate.addSwizzle(fields, $3.line);
+                    $$ = parseContext.intermediate.addIndex(EOpVectorSwizzle, $1, index, $2.line);
+                    $$->setType(TType($1->getBasicType(),EvqTemporary, (int) vectorString.size()));
+                }
+            }
+        } else if ($1->isMatrix()) {
+            TMatrixFields fields;
+            if (! parseContext.parseMatrixFields(*$3.string, $1->getNominalSize(), fields, $3.line)) {
+                fields.wholeRow = false;
+                fields.wholeCol = false;
+                fields.row = 0;
+                fields.col = 0;
+                parseContext.recover();
+            }
+
+            if (fields.wholeRow || fields.wholeCol) {
+                parseContext.error($2.line, " non-scalar fields not implemented yet", ".", "");
+                parseContext.recover();
+                constUnion *unionArray = new constUnion[1];
+                unionArray->setIConst(0);
+                TIntermTyped* index = parseContext.intermediate.addConstantUnion(unionArray, TType(EbtInt, EvqConst), $3.line);
+                $$ = parseContext.intermediate.addIndex(EOpIndexDirect, $1, index, $2.line);
+                $$->setType(TType($1->getBasicType(), EvqTemporary, $1->getNominalSize()));
+            } else {
+                constUnion *unionArray = new constUnion[1];
+                unionArray->setIConst(fields.col * $1->getNominalSize() + fields.row);
+                TIntermTyped* index = parseContext.intermediate.addConstantUnion(unionArray, TType(EbtInt, EvqConst), $3.line);
+                $$ = parseContext.intermediate.addIndex(EOpIndexDirect, $1, index, $2.line);
+                $$->setType(TType($1->getBasicType()));
+            }
+        } else if ($1->getBasicType() == EbtStruct) {
+            bool fieldFound = false;
+            TTypeList* fields = $1->getType().getStruct();
+            if (fields == 0) {
+                parseContext.error($2.line, "structure has no fields", "Internal Error", "");
+                parseContext.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) {
+                        $$ = parseContext.addConstStruct(*$3.string, $1, $2.line);
+                        if ($$ == 0) {
+                            parseContext.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()->changeQualifier(EvqConst);
+                        }
+                    } else {
+                        constUnion *unionArray = new constUnion[1];
+                        unionArray->setIConst(i);
+                        TIntermTyped* index = parseContext.intermediate.addConstantUnion(unionArray, TType(EbtInt, EvqConst), $3.line);
+                        $$ = parseContext.intermediate.addIndex(EOpIndexDirectStruct, $1, index, $2.line);
+                        $$->setType(*(*fields)[i].type);
+                    }
+                } else {
+                    parseContext.error($2.line, " no such field in structure", $3.string->c_str(), "");
+                    parseContext.recover();
+                    $$ = $1;
+                }
+            }
+        } else {
+            parseContext.error($2.line, " field selection requires structure, vector, or matrix on left hand side", $3.string->c_str(), "");
+            parseContext.recover();
+            $$ = $1;
+        }
+        // don't delete $3.string, it's from the pool
+    }
+    | postfix_expression INC_OP {
+        if (parseContext.lValueErrorCheck($2.line, "++", $1))
+            parseContext.recover();
+        $$ = parseContext.intermediate.addUnaryMath(EOpPostIncrement, $1, $2.line, parseContext.symbolTable);
+        if ($$ == 0) {
+            parseContext.unaryOpError($2.line, "++", $1->getCompleteString());
+            parseContext.recover();
+            $$ = $1;
+        }
+    }
+    | postfix_expression DEC_OP {
+        if (parseContext.lValueErrorCheck($2.line, "--", $1))
+            parseContext.recover();
+        $$ = parseContext.intermediate.addUnaryMath(EOpPostDecrement, $1, $2.line, parseContext.symbolTable);
+        if ($$ == 0) {
+            parseContext.unaryOpError($2.line, "--", $1->getCompleteString());
+            parseContext.recover();
+            $$ = $1;
+        }
+    }
+    ;
+
+integer_expression
+    : expression {
+        if (parseContext.integerErrorCheck($1, "[]"))
+            parseContext.recover();
+        $$ = $1;
+    }
+    ;
+
+function_call
+    : function_call_or_method {
+        TFunction* fnCall = $1.function;
+        TOperator op = fnCall->getBuiltInOp();
+
+        if (op == EOpArrayLength) {
+            if ($1.intermNode->getAsTyped() == 0 || $1.intermNode->getAsTyped()->getType().getArraySize() == 0) {
+                parseContext.error($1.line, "", fnCall->getName().c_str(), "array must be declared with a size before using this method");
+                parseContext.recover();
+            }
+
+            constUnion *unionArray = new constUnion[1];
+            unionArray->setIConst($1.intermNode->getAsTyped()->getType().getArraySize());
+            $$ = parseContext.intermediate.addConstantUnion(unionArray, TType(EbtInt, EvqConst), $1.line);
+        } else 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);  // use this to get the type back
+            if (parseContext.constructorErrorCheck($1.line, $1.intermNode, *fnCall, op, &type)) {
+                $$ = 0;
+            } else {
+                //
+                // It's a constructor, of type 'type'.
+                //
+                $$ = parseContext.addConstructor($1.intermNode, &type, op, fnCall, $1.line);
+            }
+
+            if ($$ == 0) {
+                parseContext.recover();
+                $$ = parseContext.intermediate.setAggregateOperator(0, op, $1.line);
+            }
+            $$->setType(type);
+        } else {
+            //
+            // Not a constructor.  Find it in the symbol table.
+            //
+            const TFunction* fnCandidate;
+            bool builtIn;
+            fnCandidate = parseContext.findFunction($1.line, fnCall, &builtIn);
+            if (fnCandidate) {
+                //
+                // A declared function.  But, it might still map to a built-in
+                // operation.
+                //
+                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.
+                        //
+                        $$ = parseContext.intermediate.addUnaryMath(op, $1.intermNode, 0, parseContext.symbolTable);
+                        if ($$ == 0)  {
+                            parseContext.error($1.intermNode->getLine(), " wrong operand type", "Internal Error",
+                                "built in unary operator function.  Type: %s",
+                                static_cast<TIntermTyped*>($1.intermNode)->getCompleteString().c_str());
+                            YYERROR;
+                        }
+                    } else {
+                        $$ = parseContext.intermediate.setAggregateOperator($1.intermAggregate, op, $1.line);
+                    }
+                } else {
+                    // This is a real function call
+
+                    $$ = parseContext.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;
+                    TQualifierList& qualifierList = $$->getAsAggregate()->getQualifier();
+                    for (int i = 0; i < fnCandidate->getParamCount(); ++i) {
+                        qual = (*fnCandidate)[i].type->getQualifier();
+                        if (qual == EvqOut || qual == EvqInOut) {
+                            if (parseContext.lValueErrorCheck($$->getLine(), "assign", $$->getAsAggregate()->getSequence()[i]->getAsTyped())) {
+                                parseContext.error($1.intermNode->getLine(), "Constant value cannot be passed for 'out' or 'inout' parameters.", "Error", "");
+                                parseContext.recover();
+                            }
+                        }
+                        qualifierList.push_back(qual);
+                    }
+                }
+                $$->setType(fnCandidate->getReturnType());
+            } else {
+                // error message was put out by PaFindFunction()
+                // Put on a dummy node for error recovery
+                constUnion *unionArray = new constUnion[1];
+                unionArray->setFConst(0.0f);
+                $$ = parseContext.intermediate.addConstantUnion(unionArray, TType(EbtFloat, EvqConst), $1.line);
+                parseContext.recover();
+            }
+        }
+        delete fnCall;
+    }
+    ;
+
+function_call_or_method
+    : function_call_generic {
+        $$ = $1;
+    }
+    | postfix_expression DOT function_call_generic {
+        parseContext.error($3.line, "methods are not supported", "", "");
+        parseContext.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 = parseContext.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 {
+        //
+        // Constructor
+        //
+        if ($1.array) {
+            if (parseContext.extensionErrorCheck($1.line, "GL_3DL_array_objects")) {
+                parseContext.recover();
+                $1.setArray(false);
+            }
+        }
+
+        if ($1.userDef) {
+            TString tempString = "";
+            TType type($1);
+            TFunction *function = new TFunction(&tempString, type, EOpConstructStruct);
+            $$ = function;
+        } else {
+            TOperator op = EOpNull;
+            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;
+            }
+            if (op == EOpNull) {
+                parseContext.error($1.line, "cannot construct this type", TType::getBasicString($1.type), "");
+                parseContext.recover();
+                $1.type = EbtFloat;
+                op = EOpConstructFloat;
+            }
+            TString tempString = "";
+            TType type($1);
+            TFunction *function = new TFunction(&tempString, type, op);
+            $$ = function;
+        }
+    }
+    | IDENTIFIER {
+        if (parseContext.reservedErrorCheck($1.line, *$1.string))
+            parseContext.recover();
+        TType type(EbtVoid);
+        TFunction *function = new TFunction($1.string, type);
+        $$ = function;
+    }
+    | FIELD_SELECTION {
+        if (parseContext.reservedErrorCheck($1.line, *$1.string))
+            parseContext.recover();
+        TType type(EbtVoid);
+        TFunction *function = new TFunction($1.string, type);
+        $$ = function;
+    }
+    ;
+
+unary_expression
+    : postfix_expression {
+        $$ = $1;
+    }
+    | INC_OP unary_expression {
+        if (parseContext.lValueErrorCheck($1.line, "++", $2))
+            parseContext.recover();
+        $$ = parseContext.intermediate.addUnaryMath(EOpPreIncrement, $2, $1.line, parseContext.symbolTable);
+        if ($$ == 0) {
+            parseContext.unaryOpError($1.line, "++", $2->getCompleteString());
+            parseContext.recover();
+            $$ = $2;
+        }
+    }
+    | DEC_OP unary_expression {
+        if (parseContext.lValueErrorCheck($1.line, "--", $2))
+            parseContext.recover();
+        $$ = parseContext.intermediate.addUnaryMath(EOpPreDecrement, $2, $1.line, parseContext.symbolTable);
+        if ($$ == 0) {
+            parseContext.unaryOpError($1.line, "--", $2->getCompleteString());
+            parseContext.recover();
+            $$ = $2;
+        }
+    }
+    | unary_operator unary_expression {
+        if ($1.op != EOpNull) {
+            $$ = parseContext.intermediate.addUnaryMath($1.op, $2, $1.line, parseContext.symbolTable);
+            if ($$ == 0) {
+                const char* errorOp = "";
+                switch($1.op) {
+                case EOpNegative:   errorOp = "-"; break;
+                case EOpLogicalNot: errorOp = "!"; break;
+                case EOpBitwiseNot: errorOp = "~"; break;
+				default: break;
+                }
+                parseContext.unaryOpError($1.line, errorOp, $2->getCompleteString());
+                parseContext.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; }
+    | TILDE { PACK_UNPACK_ONLY("~", $1.line);
+              $$.line = $1.line; $$.op = EOpBitwiseNot; }
+    ;
+// 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);
+        $$ = parseContext.intermediate.addBinaryMath(EOpMul, $1, $3, $2.line, parseContext.symbolTable);
+        if ($$ == 0) {
+            parseContext.binaryOpError($2.line, "*", $1->getCompleteString(), $3->getCompleteString());
+            parseContext.recover();
+            $$ = $1;
+        }
+    }
+    | multiplicative_expression SLASH unary_expression {
+        FRAG_VERT_ONLY("/", $2.line);
+        $$ = parseContext.intermediate.addBinaryMath(EOpDiv, $1, $3, $2.line, parseContext.symbolTable);
+        if ($$ == 0) {
+            parseContext.binaryOpError($2.line, "/", $1->getCompleteString(), $3->getCompleteString());
+            parseContext.recover();
+            $$ = $1;
+        }
+    }
+    | multiplicative_expression PERCENT unary_expression {
+        PACK_UNPACK_ONLY("%", $2.line);
+        $$ = parseContext.intermediate.addBinaryMath(EOpMod, $1, $3, $2.line, parseContext.symbolTable);
+        if ($$ == 0) {
+            parseContext.binaryOpError($2.line, "%", $1->getCompleteString(), $3->getCompleteString());
+            parseContext.recover();
+            $$ = $1;
+        }
+    }
+    ;
+
+additive_expression
+    : multiplicative_expression { $$ = $1; }
+    | additive_expression PLUS multiplicative_expression {
+        $$ = parseContext.intermediate.addBinaryMath(EOpAdd, $1, $3, $2.line, parseContext.symbolTable);
+        if ($$ == 0) {
+            parseContext.binaryOpError($2.line, "+", $1->getCompleteString(), $3->getCompleteString());
+            parseContext.recover();
+            $$ = $1;
+        }
+    }
+    | additive_expression DASH multiplicative_expression {
+        $$ = parseContext.intermediate.addBinaryMath(EOpSub, $1, $3, $2.line, parseContext.symbolTable);
+        if ($$ == 0) {
+            parseContext.binaryOpError($2.line, "-", $1->getCompleteString(), $3->getCompleteString());
+            parseContext.recover();
+            $$ = $1;
+        }
+    }
+    ;
+
+shift_expression
+    : additive_expression { $$ = $1; }
+    | shift_expression LEFT_OP additive_expression {
+        PACK_UNPACK_ONLY("<<", $2.line);
+        $$ = parseContext.intermediate.addBinaryMath(EOpLeftShift, $1, $3, $2.line, parseContext.symbolTable);
+        if ($$ == 0) {
+            parseContext.binaryOpError($2.line, "<<", $1->getCompleteString(), $3->getCompleteString());
+            parseContext.recover();
+            $$ = $1;
+        }
+    }
+    | shift_expression RIGHT_OP additive_expression {
+        PACK_UNPACK_ONLY(">>", $2.line);
+        $$ = parseContext.intermediate.addBinaryMath(EOpRightShift, $1, $3, $2.line, parseContext.symbolTable);
+        if ($$ == 0) {
+            parseContext.binaryOpError($2.line, ">>", $1->getCompleteString(), $3->getCompleteString());
+            parseContext.recover();
+            $$ = $1;
+        }
+    }
+    ;
+
+relational_expression
+    : shift_expression { $$ = $1; }
+    | relational_expression LEFT_ANGLE shift_expression {
+        $$ = parseContext.intermediate.addBinaryMath(EOpLessThan, $1, $3, $2.line, parseContext.symbolTable);
+        if ($$ == 0) {
+            parseContext.binaryOpError($2.line, "<", $1->getCompleteString(), $3->getCompleteString());
+            parseContext.recover();
+            constUnion *unionArray = new constUnion[1];
+            unionArray->setBConst(false);
+            $$ = parseContext.intermediate.addConstantUnion(unionArray, TType(EbtBool, EvqConst), $2.line);
+        }
+    }
+    | relational_expression RIGHT_ANGLE shift_expression  {
+        $$ = parseContext.intermediate.addBinaryMath(EOpGreaterThan, $1, $3, $2.line, parseContext.symbolTable);
+        if ($$ == 0) {
+            parseContext.binaryOpError($2.line, ">", $1->getCompleteString(), $3->getCompleteString());
+            parseContext.recover();
+            constUnion *unionArray = new constUnion[1];
+            unionArray->setBConst(false);
+            $$ = parseContext.intermediate.addConstantUnion(unionArray, TType(EbtBool, EvqConst), $2.line);
+        }
+    }
+    | relational_expression LE_OP shift_expression  {
+        $$ = parseContext.intermediate.addBinaryMath(EOpLessThanEqual, $1, $3, $2.line, parseContext.symbolTable);
+        if ($$ == 0) {
+            parseContext.binaryOpError($2.line, "<=", $1->getCompleteString(), $3->getCompleteString());
+            parseContext.recover();
+            constUnion *unionArray = new constUnion[1];
+            unionArray->setBConst(false);
+            $$ = parseContext.intermediate.addConstantUnion(unionArray, TType(EbtBool, EvqConst), $2.line);
+        }
+    }
+    | relational_expression GE_OP shift_expression  {
+        $$ = parseContext.intermediate.addBinaryMath(EOpGreaterThanEqual, $1, $3, $2.line, parseContext.symbolTable);
+        if ($$ == 0) {
+            parseContext.binaryOpError($2.line, ">=", $1->getCompleteString(), $3->getCompleteString());
+            parseContext.recover();
+            constUnion *unionArray = new constUnion[1];
+            unionArray->setBConst(false);
+            $$ = parseContext.intermediate.addConstantUnion(unionArray, TType(EbtBool, EvqConst), $2.line);
+        }
+    }
+    ;
+
+equality_expression
+    : relational_expression { $$ = $1; }
+    | equality_expression EQ_OP relational_expression  {
+        $$ = parseContext.intermediate.addBinaryMath(EOpEqual, $1, $3, $2.line, parseContext.symbolTable);
+        if ($$ == 0) {
+            parseContext.binaryOpError($2.line, "==", $1->getCompleteString(), $3->getCompleteString());
+            parseContext.recover();
+            constUnion *unionArray = new constUnion[1];
+            unionArray->setBConst(false);
+            $$ = parseContext.intermediate.addConstantUnion(unionArray, TType(EbtBool, EvqConst), $2.line);
+        } else if (($1->isArray() || $3->isArray()) && parseContext.extensionErrorCheck($2.line, "GL_3DL_array_objects"))
+            parseContext.recover();
+    }
+    | equality_expression NE_OP relational_expression {
+        $$ = parseContext.intermediate.addBinaryMath(EOpNotEqual, $1, $3, $2.line, parseContext.symbolTable);
+        if ($$ == 0) {
+            parseContext.binaryOpError($2.line, "!=", $1->getCompleteString(), $3->getCompleteString());
+            parseContext.recover();
+            constUnion *unionArray = new constUnion[1];
+            unionArray->setBConst(false);
+            $$ = parseContext.intermediate.addConstantUnion(unionArray, TType(EbtBool, EvqConst), $2.line);
+        } else if (($1->isArray() || $3->isArray()) && parseContext.extensionErrorCheck($2.line, "GL_3DL_array_objects"))
+            parseContext.recover();
+    }
+    ;
+
+and_expression
+    : equality_expression { $$ = $1; }
+    | and_expression AMPERSAND equality_expression {
+        PACK_UNPACK_ONLY("&", $2.line);
+        $$ = parseContext.intermediate.addBinaryMath(EOpAnd, $1, $3, $2.line, parseContext.symbolTable);
+        if ($$ == 0) {
+            parseContext.binaryOpError($2.line, "&", $1->getCompleteString(), $3->getCompleteString());
+            parseContext.recover();
+            $$ = $1;
+        }
+    }
+    ;
+
+exclusive_or_expression
+    : and_expression { $$ = $1; }
+    | exclusive_or_expression CARET and_expression {
+        PACK_UNPACK_ONLY("^", $2.line);
+        $$ = parseContext.intermediate.addBinaryMath(EOpExclusiveOr, $1, $3, $2.line, parseContext.symbolTable);
+        if ($$ == 0) {
+            parseContext.binaryOpError($2.line, "^", $1->getCompleteString(), $3->getCompleteString());
+            parseContext.recover();
+            $$ = $1;
+        }
+    }
+    ;
+
+inclusive_or_expression
+    : exclusive_or_expression { $$ = $1; }
+    | inclusive_or_expression VERTICAL_BAR exclusive_or_expression {
+        PACK_UNPACK_ONLY("|", $2.line);
+        $$ = parseContext.intermediate.addBinaryMath(EOpInclusiveOr, $1, $3, $2.line, parseContext.symbolTable);
+        if ($$ == 0) {
+            parseContext.binaryOpError($2.line, "|", $1->getCompleteString(), $3->getCompleteString());
+            parseContext.recover();
+            $$ = $1;
+        }
+    }
+    ;
+
+logical_and_expression
+    : inclusive_or_expression { $$ = $1; }
+    | logical_and_expression AND_OP inclusive_or_expression {
+        $$ = parseContext.intermediate.addBinaryMath(EOpLogicalAnd, $1, $3, $2.line, parseContext.symbolTable);
+        if ($$ == 0) {
+            parseContext.binaryOpError($2.line, "&&", $1->getCompleteString(), $3->getCompleteString());
+            parseContext.recover();
+            constUnion *unionArray = new constUnion[1];
+            unionArray->setBConst(false);
+            $$ = parseContext.intermediate.addConstantUnion(unionArray, TType(EbtBool, EvqConst), $2.line);
+        }
+    }
+    ;
+
+logical_xor_expression
+    : logical_and_expression { $$ = $1; }
+    | logical_xor_expression XOR_OP logical_and_expression  {
+        $$ = parseContext.intermediate.addBinaryMath(EOpLogicalXor, $1, $3, $2.line, parseContext.symbolTable);
+        if ($$ == 0) {
+            parseContext.binaryOpError($2.line, "^^", $1->getCompleteString(), $3->getCompleteString());
+            parseContext.recover();
+            constUnion *unionArray = new constUnion[1];
+            unionArray->setBConst(false);
+            $$ = parseContext.intermediate.addConstantUnion(unionArray, TType(EbtBool, EvqConst), $2.line);
+        }
+    }
+    ;
+
+logical_or_expression
+    : logical_xor_expression { $$ = $1; }
+    | logical_or_expression OR_OP logical_xor_expression  {
+        $$ = parseContext.intermediate.addBinaryMath(EOpLogicalOr, $1, $3, $2.line, parseContext.symbolTable);
+        if ($$ == 0) {
+            parseContext.binaryOpError($2.line, "||", $1->getCompleteString(), $3->getCompleteString());
+            parseContext.recover();
+            constUnion *unionArray = new constUnion[1];
+            unionArray->setBConst(false);
+            $$ = parseContext.intermediate.addConstantUnion(unionArray, TType(EbtBool, EvqConst), $2.line);
+        }
+    }
+    ;
+
+conditional_expression
+    : logical_or_expression { $$ = $1; }
+    | logical_or_expression QUESTION expression COLON assignment_expression {
+       if (parseContext.boolErrorCheck($2.line, $1))
+            parseContext.recover();
+
+        $$ = parseContext.intermediate.addSelection($1, $3, $5, $2.line);
+        if ($3->getType() != $5->getType())
+            $$ = 0;
+
+        if ($$ == 0) {
+            parseContext.binaryOpError($2.line, ":", $3->getCompleteString(), $5->getCompleteString());
+            parseContext.recover();
+            $$ = $5;
+        }
+    }
+    ;
+
+assignment_expression
+    : conditional_expression { $$ = $1; }
+    | unary_expression assignment_operator assignment_expression {
+        if (parseContext.lValueErrorCheck($2.line, "assign", $1))
+            parseContext.recover();
+        $$ = parseContext.intermediate.addAssign($2.op, $1, $3, $2.line);
+        if ($$ == 0) {
+            parseContext.assignError($2.line, "assign", $1->getCompleteString(), $3->getCompleteString());
+            parseContext.recover();
+            $$ = $1;
+        } else if (($1->isArray() || $3->isArray()) && parseContext.extensionErrorCheck($2.line, "GL_3DL_array_objects"))
+            parseContext.recover();
+    }
+    ;
+
+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; }
+    | MOD_ASSIGN   { PACK_UNPACK_ONLY("%=", $1.line);   $$.line = $1.line; $$.op = EOpModAssign; }
+    | ADD_ASSIGN   {                                    $$.line = $1.line; $$.op = EOpAddAssign; }
+    | SUB_ASSIGN   {                                    $$.line = $1.line; $$.op = EOpSubAssign; }
+    | LEFT_ASSIGN  { PACK_UNPACK_ONLY("<<=", $1.line);  $$.line = $1.line; $$.op = EOpLeftShiftAssign; }
+    | RIGHT_ASSIGN { PACK_UNPACK_ONLY("<<=", $1.line);  $$.line = $1.line; $$.op = EOpRightShiftAssign; }
+    | AND_ASSIGN   { PACK_UNPACK_ONLY("&=",  $1.line);  $$.line = $1.line; $$.op = EOpAndAssign; }
+    | XOR_ASSIGN   { PACK_UNPACK_ONLY("^=",  $1.line);  $$.line = $1.line; $$.op = EOpExclusiveOrAssign; }
+    | OR_ASSIGN    { PACK_UNPACK_ONLY("|=",  $1.line);  $$.line = $1.line; $$.op = EOpInclusiveOrAssign; }
+    ;
+
+expression
+    : assignment_expression {
+        $$ = $1;
+    }
+    | expression COMMA assignment_expression {
+        $$ = parseContext.intermediate.addComma($1, $3, $2.line);
+        if ($$ == 0) {
+            parseContext.binaryOpError($2.line, ",", $1->getCompleteString(), $3->getCompleteString());
+            parseContext.recover();
+            $$ = $3;
+        }
+    }
+    ;
+
+constant_expression
+    : conditional_expression {
+        if (parseContext.constErrorCheck($1))
+            parseContext.recover();
+        $$ = $1;
+    }
+    ;
+
+declaration
+    : function_prototype SEMICOLON   { $$ = 0; }
+    | init_declarator_list SEMICOLON {
+		if ($1.intermAggregate)
+            $1.intermAggregate->setOperator(EOpDeclaration);
+        $$ = $1.intermAggregate;
+    }
+    | PRECISION precision_qualifier type_specifier_no_prec SEMICOLON {
+    	$$ = 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*>(parseContext.symbolTable.find($1->getMangledName()));
+        if (prevDec) {
+            if (prevDec->getReturnType() != $1->getReturnType()) {
+                parseContext.error($2.line, "overloaded functions must have the same return type", $1->getReturnType().getBasicString(), "");
+                parseContext.recover();
+            }
+            for (int i = 0; i < prevDec->getParamCount(); ++i) {
+                if ((*prevDec)[i].type->getQualifier() != (*$1)[i].type->getQualifier()) {
+                    parseContext.error($2.line, "overloaded functions must have the same parameter qualifiers", (*$1)[i].type->getQualifierString(), "");
+                    parseContext.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;
+
+        parseContext.symbolTable.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
+            //
+            parseContext.error($2.line, "cannot be an argument type except for '(void)'", "void", "");
+            parseContext.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) {
+            parseContext.error($2.line, "no qualifiers allowed for function return", getQualifierString($1.qualifier), "");
+            parseContext.recover();
+        }
+        // make sure a sampler is not involved as well...
+        if (parseContext.structQualifierErrorCheck($2.line, $1))
+            parseContext.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;
+    }
+    ;
+
+parameter_declarator
+    // Type + name
+    : type_specifier IDENTIFIER {
+        if ($1.type == EbtVoid) {
+            parseContext.error($2.line, "illegal use of type 'void'", $2.string->c_str(), "");
+            parseContext.recover();
+        }
+        if (parseContext.reservedErrorCheck($2.line, *$2.string))
+            parseContext.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 (parseContext.arrayTypeErrorCheck($3.line, $1))
+            parseContext.recover();
+
+        if (parseContext.reservedErrorCheck($2.line, *$2.string))
+            parseContext.recover();
+
+        int size;
+        if (parseContext.arraySizeErrorCheck($3.line, $4, size))
+            parseContext.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 (parseContext.paramErrorCheck($3.line, $1.qualifier, $2, $$.param.type))
+            parseContext.recover();
+    }
+    | parameter_qualifier parameter_declarator {
+        $$ = $2;
+        if (parseContext.parameterSamplerErrorCheck($2.line, $1, *$2.param.type))
+            parseContext.recover();
+        if (parseContext.paramErrorCheck($2.line, EvqTemporary, $1, $$.param.type))
+            parseContext.recover();
+    }
+    //
+    // Only type
+    //
+    | type_qualifier parameter_qualifier parameter_type_specifier {
+        $$ = $3;
+        if (parseContext.paramErrorCheck($3.line, $1.qualifier, $2, $$.param.type))
+            parseContext.recover();
+    }
+    | parameter_qualifier parameter_type_specifier {
+        $$ = $2;
+        if (parseContext.parameterSamplerErrorCheck($2.line, $1, *$2.param.type))
+            parseContext.recover();
+        if (parseContext.paramErrorCheck($2.line, EvqTemporary, $1, $$.param.type))
+            parseContext.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 {
+        $$.intermAggregate = parseContext.intermediate.growAggregate($1.intermNode, parseContext.intermediate.addSymbol(0, *$3.string, TType($1.type), $3.line), $3.line);
+        
+        if (parseContext.structQualifierErrorCheck($3.line, $$.type))
+            parseContext.recover();
+
+        if (parseContext.nonInitConstErrorCheck($3.line, *$3.string, $$.type))
+            parseContext.recover();
+
+        if (parseContext.nonInitErrorCheck($3.line, *$3.string, $$.type))
+            parseContext.recover();
+    }
+    | init_declarator_list COMMA IDENTIFIER LEFT_BRACKET RIGHT_BRACKET {
+        if (parseContext.structQualifierErrorCheck($3.line, $1.type))
+            parseContext.recover();
+
+        if (parseContext.nonInitConstErrorCheck($3.line, *$3.string, $1.type))
+            parseContext.recover();
+
+        $$ = $1;
+
+        if (parseContext.arrayTypeErrorCheck($4.line, $1.type) || parseContext.arrayQualifierErrorCheck($4.line, $1.type))
+            parseContext.recover();
+        else {
+            $1.type.setArray(true);
+            TVariable* variable;
+            if (parseContext.arrayErrorCheck($4.line, *$3.string, $1.type, variable))
+                parseContext.recover();
+        }
+    }
+    | init_declarator_list COMMA IDENTIFIER LEFT_BRACKET constant_expression RIGHT_BRACKET {
+        if (parseContext.structQualifierErrorCheck($3.line, $1.type))
+            parseContext.recover();
+
+        if (parseContext.nonInitConstErrorCheck($3.line, *$3.string, $1.type))
+            parseContext.recover();
+
+        $$ = $1;
+
+        if (parseContext.arrayTypeErrorCheck($4.line, $1.type) || parseContext.arrayQualifierErrorCheck($4.line, $1.type))
+            parseContext.recover();
+        else {
+            int size;
+            if (parseContext.arraySizeErrorCheck($4.line, $5, size))
+                parseContext.recover();
+            $1.type.setArray(true, size);
+            TVariable* variable;
+            if (parseContext.arrayErrorCheck($4.line, *$3.string, $1.type, variable))
+                parseContext.recover();
+        }
+    }
+    | init_declarator_list COMMA IDENTIFIER LEFT_BRACKET RIGHT_BRACKET EQUAL initializer {
+        if (parseContext.structQualifierErrorCheck($3.line, $1.type))
+            parseContext.recover();
+
+        $$ = $1;
+
+        TVariable* variable = 0;
+        if (parseContext.arrayTypeErrorCheck($4.line, $1.type) || parseContext.arrayQualifierErrorCheck($4.line, $1.type))
+            parseContext.recover();
+        else {
+			$1.type.setArray(true, $7->getType().getArraySize());
+            if (parseContext.arrayErrorCheck($4.line, *$3.string, $1.type, variable))
+                parseContext.recover();
+        }
+
+        if (parseContext.extensionErrorCheck($$.line, "GL_3DL_array_objects"))
+            parseContext.recover();
+        else {
+            TIntermNode* intermNode;
+            if (!parseContext.executeInitializer($3.line, *$3.string, $1.type, $7, intermNode, variable)) {
+                //
+                // build the intermediate representation
+                //
+                if (intermNode)
+                    $$.intermAggregate = parseContext.intermediate.growAggregate($1.intermNode, intermNode, $6.line);
+                else
+                    $$.intermAggregate = $1.intermAggregate;
+            } else {
+                parseContext.recover();
+                $$.intermAggregate = 0;
+            }
+        }
+    }
+    | init_declarator_list COMMA IDENTIFIER LEFT_BRACKET constant_expression RIGHT_BRACKET EQUAL initializer {
+        if (parseContext.structQualifierErrorCheck($3.line, $1.type))
+            parseContext.recover();
+
+        $$ = $1;
+
+        TVariable* variable = 0;
+        if (parseContext.arrayTypeErrorCheck($4.line, $1.type) || parseContext.arrayQualifierErrorCheck($4.line, $1.type))
+            parseContext.recover();
+        else {
+            int size;
+            if (parseContext.arraySizeErrorCheck($4.line, $5, size))
+                parseContext.recover();
+            $1.type.setArray(true, size);
+            if (parseContext.arrayErrorCheck($4.line, *$3.string, $1.type, variable))
+                parseContext.recover();
+        }
+
+        if (parseContext.extensionErrorCheck($$.line, "GL_3DL_array_objects"))
+            parseContext.recover();
+        else {
+            TIntermNode* intermNode;
+            if (!parseContext.executeInitializer($3.line, *$3.string, $1.type, $8, intermNode, variable)) {
+                //
+                // build the intermediate representation
+                //
+                if (intermNode)
+                    $$.intermAggregate = parseContext.intermediate.growAggregate($1.intermNode, intermNode, $7.line);
+                else
+                    $$.intermAggregate = $1.intermAggregate;
+            } else {
+                parseContext.recover();
+                $$.intermAggregate = 0;
+            }
+        }
+    }
+    | init_declarator_list COMMA IDENTIFIER EQUAL initializer {
+        if (parseContext.structQualifierErrorCheck($3.line, $1.type))
+            parseContext.recover();
+
+        $$ = $1;
+
+        TIntermNode* intermNode;
+        if (!parseContext.executeInitializer($3.line, *$3.string, $1.type, $5, intermNode)) {
+            //
+            // build the intermediate representation
+            //
+            if (intermNode)
+		$$.intermAggregate = parseContext.intermediate.growAggregate($1.intermNode, intermNode, $4.line);
+            else
+                $$.intermAggregate = $1.intermAggregate;
+        } else {
+            parseContext.recover();
+            $$.intermAggregate = 0;
+        }
+    }
+    ;
+
+single_declaration
+    : fully_specified_type {
+        $$.type = $1;
+        $$.intermAggregate = 0;
+    }
+    | fully_specified_type IDENTIFIER {
+		$$.intermAggregate = parseContext.intermediate.makeAggregate(parseContext.intermediate.addSymbol(0, *$2.string, TType($1), $2.line), $2.line);
+        
+        if (parseContext.structQualifierErrorCheck($2.line, $$.type))
+            parseContext.recover();
+
+        if (parseContext.nonInitConstErrorCheck($2.line, *$2.string, $$.type))
+            parseContext.recover();
+            
+            $$.type = $1;
+
+        if (parseContext.nonInitErrorCheck($2.line, *$2.string, $$.type))
+            parseContext.recover();
+    }
+    | fully_specified_type IDENTIFIER LEFT_BRACKET RIGHT_BRACKET {
+        $$.intermAggregate = parseContext.intermediate.makeAggregate(parseContext.intermediate.addSymbol(0, *$2.string, TType($1), $2.line), $2.line);
+        
+        if (parseContext.structQualifierErrorCheck($2.line, $1))
+            parseContext.recover();
+
+        if (parseContext.nonInitConstErrorCheck($2.line, *$2.string, $1))
+            parseContext.recover();
+
+        $$.type = $1;
+
+        if (parseContext.arrayTypeErrorCheck($3.line, $1) || parseContext.arrayQualifierErrorCheck($3.line, $1))
+            parseContext.recover();
+        else {
+            $1.setArray(true);
+            TVariable* variable;
+            if (parseContext.arrayErrorCheck($3.line, *$2.string, $1, variable))
+                parseContext.recover();
+        }
+    }
+    | fully_specified_type IDENTIFIER LEFT_BRACKET constant_expression RIGHT_BRACKET {
+		TType type = TType($1);
+		int size;
+        if (parseContext.arraySizeErrorCheck($2.line, $4, size))
+            parseContext.recover();
+		type.setArraySize(size);
+        $$.intermAggregate = parseContext.intermediate.makeAggregate(parseContext.intermediate.addSymbol(0, *$2.string, type, $2.line), $2.line);
+        
+        if (parseContext.structQualifierErrorCheck($2.line, $1))
+            parseContext.recover();
+
+        if (parseContext.nonInitConstErrorCheck($2.line, *$2.string, $1))
+            parseContext.recover();
+
+        $$.type = $1;
+
+        if (parseContext.arrayTypeErrorCheck($3.line, $1) || parseContext.arrayQualifierErrorCheck($3.line, $1))
+            parseContext.recover();
+        else {
+            int size;
+            if (parseContext.arraySizeErrorCheck($3.line, $4, size))
+                parseContext.recover();
+
+            $1.setArray(true, size);
+            TVariable* variable;
+            if (parseContext.arrayErrorCheck($3.line, *$2.string, $1, variable))
+                parseContext.recover();
+        }
+    }
+    | fully_specified_type IDENTIFIER EQUAL initializer {
+        if (parseContext.structQualifierErrorCheck($2.line, $1))
+            parseContext.recover();
+
+        $$.type = $1;
+
+	    TIntermNode* intermNode;
+        if (!parseContext.executeInitializer($2.line, *$2.string, $1, $4, intermNode)) {
+		//
+		// Build intermediate representation
+		//
+            if(intermNode)
+				$$.intermAggregate = parseContext.intermediate.makeAggregate(intermNode, $3.line);
+            else
+				$$.intermAggregate = 0;
+        } else {
+			parseContext.recover();
+			$$.intermAggregate = 0;
+		}
+	}
+    | INVARIANT IDENTIFIER {
+		VERTEX_ONLY("invariant declaration", $1.line);
+		$$.qualifier = EvqInvariantVaryingOut;
+	    $$.intermAggregate = 0;
+    }
+
+//
+// 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 (parseContext.globalErrorCheck($1.line, parseContext.symbolTable.atGlobalLevel(), "input"))
+//            parseContext.recover();
+//        UNPACK_ONLY("input", $1.line);
+//        $$.qualifier = EvqInput;
+//    }
+//    | OUTPUT {
+//        if (parseContext.globalErrorCheck($1.line, parseContext.symbolTable.atGlobalLevel(), "output"))
+//            parseContext.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 (parseContext.reservedErrorCheck($2.line, *$2.string, parseContext))
+//            parseContext.recover();
+//        $$.variable = new TVariable($2.string, $1);
+//        if (! parseContext.symbolTable.insert(*$$.variable)) {
+//            parseContext.error($2.line, "redefinition", $$.variable->getName().c_str(), "");
+//            parseContext.recover();
+//            // don't have to delete $$.variable, the pool pop will take care of it
+//        }
+//    }
+//    ;
+
+fully_specified_type
+    : type_specifier {
+        $$ = $1;
+
+        if ($1.array) {
+            if (parseContext.extensionErrorCheck($1.line, "GL_3DL_array_objects")) {
+                parseContext.recover();
+                $1.setArray(false);
+            }
+        }
+    }
+    | type_qualifier type_specifier  {
+        if ($2.array && parseContext.extensionErrorCheck($2.line, "GL_3DL_array_objects")) {
+            parseContext.recover();
+            $2.setArray(false);
+        }
+        if ($2.array && parseContext.arrayQualifierErrorCheck($2.line, $1)) {
+            parseContext.recover();
+            $2.setArray(false);
+        }
+
+        if ($1.qualifier == EvqAttribute &&
+            ($2.type == EbtBool || $2.type == EbtInt)) {
+            parseContext.error($2.line, "cannot be bool or int", getQualifierString($1.qualifier), "");
+            parseContext.recover();
+        }
+        if (($1.qualifier == EvqVaryingIn || $1.qualifier == EvqVaryingOut) &&
+            ($2.type == EbtBool || $2.type == EbtInt)) {
+            parseContext.error($2.line, "cannot be bool or int", getQualifierString($1.qualifier), "");
+            parseContext.recover();
+        }
+        $$ = $2;
+        $$.qualifier = $1.qualifier;
+    }
+    ;
+
+type_qualifier
+    : CONST_QUAL {
+        $$.setBasic(EbtVoid, EvqConst, $1.line);
+    }
+    | ATTRIBUTE {
+        VERTEX_ONLY("attribute", $1.line);
+        if (parseContext.globalErrorCheck($1.line, parseContext.symbolTable.atGlobalLevel(), "attribute"))
+            parseContext.recover();
+        $$.setBasic(EbtVoid, EvqAttribute, $1.line);
+    }
+    | VARYING {
+        if (parseContext.globalErrorCheck($1.line, parseContext.symbolTable.atGlobalLevel(), "varying"))
+            parseContext.recover();
+        if (parseContext.language == EShLangVertex)
+            $$.setBasic(EbtVoid, EvqVaryingOut, $1.line);
+        else
+            $$.setBasic(EbtVoid, EvqVaryingIn, $1.line);
+    }
+    | INVARIANT VARYING {
+        if (parseContext.globalErrorCheck($1.line, parseContext.symbolTable.atGlobalLevel(), "invariant varying"))
+            parseContext.recover();
+        if (parseContext.language == EShLangVertex)
+            $$.setBasic(EbtVoid, EvqInvariantVaryingOut, $1.line);
+        else
+            $$.setBasic(EbtVoid, EvqInvariantVaryingIn, $1.line);
+    }
+    | UNIFORM {
+        if (parseContext.globalErrorCheck($1.line, parseContext.symbolTable.atGlobalLevel(), "uniform"))
+            parseContext.recover();
+        $$.setBasic(EbtVoid, EvqUniform, $1.line);
+    }
+    ;
+
+type_specifier
+    : type_specifier_no_prec {
+    	$$ = $1;
+    }
+    | precision_qualifier type_specifier_no_prec {
+    	$$ = $2;
+	$$.setPrecision($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 (parseContext.arrayTypeErrorCheck($2.line, $1))
+            parseContext.recover();
+        else {
+            int size;
+            if (parseContext.arraySizeErrorCheck($2.line, $3, size))
+                parseContext.recover();
+            $$.setArray(true, size);
+        }
+    }
+    ;
+
+type_specifier_nonarray
+    : VOID_TYPE {
+        TQualifier qual = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
+        $$.setBasic(EbtVoid, qual, $1.line);
+    }
+    | FLOAT_TYPE {
+        TQualifier qual = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
+        $$.setBasic(EbtFloat, qual, $1.line);
+    }
+    | INT_TYPE {
+        TQualifier qual = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
+        $$.setBasic(EbtInt, qual, $1.line);
+    }
+    | BOOL_TYPE {
+        TQualifier qual = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
+        $$.setBasic(EbtBool, qual, $1.line);
+    }
+//    | UNSIGNED INT_TYPE {
+//        PACK_UNPACK_ONLY("unsigned", $1.line);
+//        TQualifier qual = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
+//        $$.setBasic(EbtInt, qual, $1.line);
+//    }
+    | VEC2 {
+        TQualifier qual = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
+        $$.setBasic(EbtFloat, qual, $1.line);
+        $$.setAggregate(2);
+    }
+    | VEC3 {
+        TQualifier qual = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
+        $$.setBasic(EbtFloat, qual, $1.line);
+        $$.setAggregate(3);
+    }
+    | VEC4 {
+        TQualifier qual = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
+        $$.setBasic(EbtFloat, qual, $1.line);
+        $$.setAggregate(4);
+    }
+    | BVEC2 {
+        TQualifier qual = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
+        $$.setBasic(EbtBool, qual, $1.line);
+        $$.setAggregate(2);
+    }
+    | BVEC3 {
+        TQualifier qual = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
+        $$.setBasic(EbtBool, qual, $1.line);
+        $$.setAggregate(3);
+    }
+    | BVEC4 {
+        TQualifier qual = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
+        $$.setBasic(EbtBool, qual, $1.line);
+        $$.setAggregate(4);
+    }
+    | IVEC2 {
+        TQualifier qual = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
+        $$.setBasic(EbtInt, qual, $1.line);
+        $$.setAggregate(2);
+    }
+    | IVEC3 {
+        TQualifier qual = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
+        $$.setBasic(EbtInt, qual, $1.line);
+        $$.setAggregate(3);
+    }
+    | IVEC4 {
+        TQualifier qual = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
+        $$.setBasic(EbtInt, qual, $1.line);
+        $$.setAggregate(4);
+    }
+    | MATRIX2 {
+        FRAG_VERT_ONLY("mat2", $1.line);
+        TQualifier qual = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
+        $$.setBasic(EbtFloat, qual, $1.line);
+        $$.setAggregate(2, true);
+    }
+    | MATRIX3 {
+        FRAG_VERT_ONLY("mat3", $1.line);
+        TQualifier qual = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
+        $$.setBasic(EbtFloat, qual, $1.line);
+        $$.setAggregate(3, true);
+    }
+    | MATRIX4 {
+        FRAG_VERT_ONLY("mat4", $1.line);
+        TQualifier qual = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
+        $$.setBasic(EbtFloat, qual, $1.line);
+        $$.setAggregate(4, true);
+    }
+    | SAMPLER2D {
+        FRAG_VERT_ONLY("sampler2D", $1.line);
+        TQualifier qual = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
+        $$.setBasic(EbtSampler2D, qual, $1.line);
+    }
+    | SAMPLERCUBE {
+        FRAG_VERT_ONLY("samplerCube", $1.line);
+        TQualifier qual = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
+        $$.setBasic(EbtSamplerCube, qual, $1.line);
+    }
+    | struct_specifier {
+        FRAG_VERT_ONLY("struct", $1.line);
+        $$ = $1;
+        $$.qualifier = parseContext.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 = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
+        $$.setBasic(EbtStruct, qual, $1.line);
+        $$.userDef = &structure;
+    }
+    ;
+
+struct_specifier
+    : STRUCT IDENTIFIER LEFT_BRACE struct_declaration_list RIGHT_BRACE {
+        TType* structure = new TType($4, *$2.string);
+        TVariable* userTypeDef = new TVariable($2.string, *structure, true);
+        if (! parseContext.symbolTable.insert(*userTypeDef)) {
+            parseContext.error($2.line, "redefinition", $2.string->c_str(), "struct");
+            parseContext.recover();
+        }
+        $$.setBasic(EbtStruct, EvqTemporary, $1.line);
+        $$.userDef = structure;
+    }
+    | STRUCT LEFT_BRACE struct_declaration_list RIGHT_BRACE {
+        TType* structure = new TType($3, TString(""));
+        $$.setBasic(EbtStruct, EvqTemporary, $1.line);
+        $$.userDef = structure;
+    }
+    ;
+
+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()) {
+                    parseContext.error((*$2)[i].line, "duplicate field name in structure:", "struct", (*$2)[i].type->getFieldName().c_str());
+                    parseContext.recover();
+                }
+            }
+            $$->push_back((*$2)[i]);
+        }
+    }
+    ;
+
+struct_declaration
+    : type_specifier struct_declarator_list SEMICOLON {
+        $$ = $2;
+
+        if (parseContext.voidErrorCheck($1.line, (*$2)[0].type->getFieldName(), $1)) {
+            parseContext.recover();
+        }
+        for (unsigned int i = 0; i < $$->size(); ++i) {
+            //
+            // Careful not to replace already know aspects of type, like array-ness
+            //
+            (*$$)[i].type->setType($1.type, $1.size, $1.matrix, $1.userDef);
+
+            // don't allow arrays of arrays
+            if ((*$$)[i].type->isArray()) {
+                if (parseContext.arrayTypeErrorCheck($1.line, $1))
+                    parseContext.recover();
+            }
+            if ($1.array)
+                (*$$)[i].type->setArraySize($1.arraySize);
+            if ($1.userDef)
+                (*$$)[i].type->setTypeName($1.userDef->getTypeName());
+        }
+    }
+    ;
+
+struct_declarator_list
+    : struct_declarator {
+        $$ = NewPoolTTypeList();
+        $$->push_back($1);
+    }
+    | struct_declarator_list COMMA struct_declarator {
+        $$->push_back($3);
+    }
+    ;
+
+struct_declarator
+    : IDENTIFIER {
+        $$.type = new TType(EbtVoid);
+        $$.line = $1.line;
+        $$.type->setFieldName(*$1.string);
+    }
+    | IDENTIFIER LEFT_BRACKET constant_expression RIGHT_BRACKET {
+        $$.type = new TType(EbtVoid);
+        $$.line = $1.line;
+        $$.type->setFieldName(*$1.string);
+
+        int size;
+        if (parseContext.arraySizeErrorCheck($2.line, $3, size))
+            parseContext.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 { parseContext.symbolTable.push(); } statement_list { parseContext.symbolTable.pop(); } RIGHT_BRACE {
+        if ($3 != 0)
+            $3->setOperator(EOpSequence);
+        $$ = $3;
+    }
+    ;
+
+statement_no_new_scope
+    : compound_statement_no_new_scope { $$ = $1; }
+    | simple_statement                { $$ = $1; }
+    ;
+
+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->setOperator(EOpSequence);
+        $$ = $2;
+    }
+    ;
+
+statement_list
+    : statement {
+        $$ = parseContext.intermediate.makeAggregate($1, 0);
+    }
+    | statement_list statement {
+        $$ = parseContext.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 (parseContext.boolErrorCheck($1.line, $3))
+            parseContext.recover();
+        $$ = parseContext.intermediate.addSelection($3, $5, $1.line);
+    }
+    ;
+
+selection_rest_statement
+    : statement ELSE statement {
+        $$.node1 = $1;
+        $$.node2 = $3;
+    }
+    | statement {
+        $$.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 (parseContext.boolErrorCheck($1->getLine(), $1))
+            parseContext.recover();
+    }
+    | fully_specified_type IDENTIFIER EQUAL initializer {
+        TIntermNode* intermNode;
+        if (parseContext.structQualifierErrorCheck($2.line, $1))
+            parseContext.recover();
+        if (parseContext.boolErrorCheck($2.line, $1))
+            parseContext.recover();
+
+        if (!parseContext.executeInitializer($2.line, *$2.string, $1, $4, intermNode))
+            $$ = $4;
+        else {
+            parseContext.recover();
+            $$ = 0;
+        }
+    }
+    ;
+
+iteration_statement
+    : WHILE LEFT_PAREN { parseContext.symbolTable.push(); ++parseContext.loopNestingLevel; } condition RIGHT_PAREN statement_no_new_scope {
+        parseContext.symbolTable.pop();
+        $$ = parseContext.intermediate.addLoop(0, $6, $4, 0, true, $1.line);
+        --parseContext.loopNestingLevel;
+    }
+    | DO { ++parseContext.loopNestingLevel; } statement WHILE LEFT_PAREN expression RIGHT_PAREN SEMICOLON {
+        if (parseContext.boolErrorCheck($8.line, $6))
+            parseContext.recover();
+
+        $$ = parseContext.intermediate.addLoop(0, $3, $6, 0, false, $4.line);
+        --parseContext.loopNestingLevel;
+    }
+    | FOR LEFT_PAREN { parseContext.symbolTable.push(); ++parseContext.loopNestingLevel; } for_init_statement for_rest_statement RIGHT_PAREN statement_no_new_scope {
+        parseContext.symbolTable.pop();
+        $$ = parseContext.intermediate.addLoop($4, $7, reinterpret_cast<TIntermTyped*>($5.node1), reinterpret_cast<TIntermTyped*>($5.node2), true, $1.line);
+        --parseContext.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 (parseContext.loopNestingLevel <= 0) {
+            parseContext.error($1.line, "continue statement only allowed in loops", "", "");
+            parseContext.recover();
+        }
+        $$ = parseContext.intermediate.addBranch(EOpContinue, $1.line);
+    }
+    | BREAK SEMICOLON {
+        if (parseContext.loopNestingLevel <= 0) {
+            parseContext.error($1.line, "break statement only allowed in loops", "", "");
+            parseContext.recover();
+        }
+        $$ = parseContext.intermediate.addBranch(EOpBreak, $1.line);
+    }
+    | RETURN SEMICOLON {
+        $$ = parseContext.intermediate.addBranch(EOpReturn, $1.line);
+        if (parseContext.currentFunctionType->getBasicType() != EbtVoid) {
+            parseContext.error($1.line, "non-void function must return a value", "return", "");
+            parseContext.recover();
+        }
+    }
+    | RETURN expression SEMICOLON {
+        $$ = parseContext.intermediate.addBranch(EOpReturn, $2, $1.line);
+        parseContext.functionReturnsValue = true;
+        if (parseContext.currentFunctionType->getBasicType() == EbtVoid) {
+            parseContext.error($1.line, "void function cannot return a value", "return", "");
+            parseContext.recover();
+        } else if (*(parseContext.currentFunctionType) != $2->getType()) {
+            parseContext.error($1.line, "function return is not matching type:", "return", "");
+            parseContext.recover();
+        }
+    }
+    | DISCARD SEMICOLON {
+        FRAG_ONLY("discard", $1.line);
+        $$ = parseContext.intermediate.addBranch(EOpKill, $1.line);
+    }
+    ;
+
+// Grammar Note:  No 'goto'.  Gotos are not supported.
+
+translation_unit
+    : external_declaration {
+        $$ = $1;
+        parseContext.treeRoot = $$;
+    }
+    | translation_unit external_declaration {
+        $$ = parseContext.intermediate.growAggregate($1, $2, 0);
+        parseContext.treeRoot = $$;
+    }
+    ;
+
+external_declaration
+    : function_definition {
+        $$ = $1;
+    }
+    | declaration {
+        $$ = $1;
+    }
+    ;
+
+function_definition
+    : function_prototype {
+        TFunction& function = *($1.function);
+        TFunction* prevDec = static_cast<TFunction*>(parseContext.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.
+            //
+            parseContext.error($1.line, "function already has a body", function.getName().c_str(), "");
+            parseContext.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) {
+                parseContext.error($1.line, "function cannot take any parameter(s)", function.getName().c_str(), "");
+                parseContext.recover();
+            }
+            if (function.getReturnType().getBasicType() != EbtVoid) {
+                parseContext.error($1.line, "", function.getReturnType().getBasicString(), "main function cannot return a value");
+                parseContext.recover();
+            }
+        }
+
+        //
+        // New symbol table scope for body of function plus its arguments
+        //
+        parseContext.symbolTable.push();
+
+        //
+        // Remember the return type for later checking for RETURN statements.
+        //
+        parseContext.currentFunctionType = &(prevDec->getReturnType());
+        parseContext.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++) {
+            TParameter& param = function[i];
+            if (param.name != 0) {
+                TVariable *variable = new TVariable(param.name, *param.type);
+                //
+                // Insert the parameters with name in the symbol table.
+                //
+                if (! parseContext.symbolTable.insert(*variable)) {
+                    parseContext.error($1.line, "redefinition", variable->getName().c_str(), "");
+                    parseContext.recover();
+                    delete variable;
+                }
+                //
+                // Transfer ownership of name pointer to symbol table.
+                //
+                param.name = 0;
+
+                //
+                // Add the parameter to the HIL
+                //
+                paramNodes = parseContext.intermediate.growAggregate(
+                                               paramNodes,
+                                               parseContext.intermediate.addSymbol(variable->getUniqueId(),
+                                                                       variable->getName(),
+                                                                       variable->getType(), $1.line),
+                                               $1.line);
+            } else {
+                paramNodes = parseContext.intermediate.growAggregate(paramNodes, parseContext.intermediate.addSymbol(0, "", *param.type, $1.line), $1.line);
+            }
+        }
+        parseContext.intermediate.setAggregateOperator(paramNodes, EOpParameters, $1.line);
+        $1.intermAggregate = paramNodes;
+        parseContext.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 (parseContext.currentFunctionType->getBasicType() != EbtVoid && ! parseContext.functionReturnsValue) {
+            parseContext.error($1.line, "function does not return a value:", "", $1.function->getName().c_str());
+            parseContext.recover();
+        }
+        parseContext.symbolTable.pop();
+        $$ = parseContext.intermediate.growAggregate($1.intermAggregate, $3, 0);
+        parseContext.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(parseContext.contextPragma.optimize);
+        $$->getAsAggregate()->setDebug(parseContext.contextPragma.debug);
+        $$->getAsAggregate()->addToPragmaTable(parseContext.contextPragma.pragmaTable);
+    }
+    ;
+
+%%
diff --git a/Compiler/intermOut.cpp b/Compiler/intermOut.cpp
new file mode 100644
index 0000000..6e30b86
--- /dev/null
+++ b/Compiler/intermOut.cpp
@@ -0,0 +1,455 @@
+//
+// 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 "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(TInfoSink& i) : infoSink(i) { }
+	TInfoSink& infoSink;
+
+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
+{
+	char buf[100];
+	char *p = &buf[0];
+
+	if (qualifier != EvqTemporary && qualifier != EvqGlobal)
+		p += sprintf(p, "%s ", getQualifierString());
+	if (array)
+		p += sprintf(p, "array of ");
+	if (matrix)
+		p += sprintf(p, "%dX%d matrix of ", size, size);
+	else if (size > 1)
+		p += sprintf(p, "%d-component vector of ", size);
+
+	sprintf(p, "%s", getBasicString());
+
+	return TString(buf);
+}   
+
+//
+// Helper functions for printing, not part of traversing.
+//
+
+void OutputTreeText(TInfoSink& infoSink, TIntermNode* node, const int depth)
+{
+	int i;
+
+	infoSink.debug << FormatSourceLoc(node->getLine());
+
+	for (i = 0; i < depth; ++i)
+		infoSink.debug << "  ";
+}
+
+//
+// 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(infoSink, node, depth);
+
+	char buf[100];
+	sprintf(buf, "'%s' (%s)\n",
+		   node->getSymbol().c_str(),
+		   node->getCompleteString().c_str());
+
+	infoSink.debug << buf;
+}
+
+bool TOutputTraverser::visitBinary(Visit visit, TIntermBinary* node)
+{
+	TInfoSink& out = infoSink;
+
+	OutputTreeText(out, node, depth);
+
+	switch (node->getOp()) {
+	case EOpAssign:                   out.debug << "move second child to first child";           break;
+	case EOpAddAssign:                out.debug << "add second child into first child";          break;
+	case EOpSubAssign:                out.debug << "subtract second child into first child";     break;
+	case EOpMulAssign:                out.debug << "multiply second child into first child";     break;
+	case EOpVectorTimesMatrixAssign:  out.debug << "matrix mult second child into first child";  break;
+	case EOpVectorTimesScalarAssign:  out.debug << "vector scale second child into first child"; break;
+	case EOpMatrixTimesScalarAssign:  out.debug << "matrix scale second child into first child"; break;
+	case EOpMatrixTimesMatrixAssign:  out.debug << "matrix mult second child into first child"; break;
+	case EOpDivAssign:                out.debug << "divide second child into first child";       break;
+	case EOpModAssign:                out.debug << "mod second child into first child";          break;
+	case EOpAndAssign:                out.debug << "and second child into first child";          break;
+	case EOpInclusiveOrAssign:        out.debug << "or second child into first child";           break;
+	case EOpExclusiveOrAssign:        out.debug << "exclusive or second child into first child"; break;
+	case EOpLeftShiftAssign:          out.debug << "left shift second child into first child";   break;
+	case EOpRightShiftAssign:         out.debug << "right shift second child into first child";  break;
+
+	case EOpIndexDirect:   out.debug << "direct index";   break;
+	case EOpIndexIndirect: out.debug << "indirect index"; break;
+	case EOpIndexDirectStruct:   out.debug << "direct index for structure";   break;
+	case EOpVectorSwizzle: out.debug << "vector swizzle"; break;
+
+	case EOpAdd:    out.debug << "add";                     break;
+	case EOpSub:    out.debug << "subtract";                break;
+	case EOpMul:    out.debug << "component-wise multiply"; break;
+	case EOpDiv:    out.debug << "divide";                  break;
+	case EOpMod:    out.debug << "mod";                     break;
+	case EOpRightShift:  out.debug << "right-shift";  break;
+	case EOpLeftShift:   out.debug << "left-shift";   break;
+	case EOpAnd:         out.debug << "bitwise and";  break;
+	case EOpInclusiveOr: out.debug << "inclusive-or"; break;
+	case EOpExclusiveOr: out.debug << "exclusive-or"; break;
+	case EOpEqual:            out.debug << "Compare Equal";                 break;
+	case EOpNotEqual:         out.debug << "Compare Not Equal";             break;
+	case EOpLessThan:         out.debug << "Compare Less Than";             break;
+	case EOpGreaterThan:      out.debug << "Compare Greater Than";          break;
+	case EOpLessThanEqual:    out.debug << "Compare Less Than or Equal";    break;
+	case EOpGreaterThanEqual: out.debug << "Compare Greater Than or Equal"; break;
+
+	case EOpVectorTimesScalar: out.debug << "vector-scale";          break;
+	case EOpVectorTimesMatrix: out.debug << "vector-times-matrix";   break;
+	case EOpMatrixTimesVector: out.debug << "matrix-times-vector";   break;
+	case EOpMatrixTimesScalar: out.debug << "matrix-scale";          break;
+	case EOpMatrixTimesMatrix: out.debug << "matrix-multiply";       break;
+
+	case EOpLogicalOr:  out.debug << "logical-or";   break;
+	case EOpLogicalXor: out.debug << "logical-xor"; break;
+	case EOpLogicalAnd: out.debug << "logical-and"; break;
+	default: out.debug << "<unknown op>";
+	}
+
+	out.debug << " (" << node->getCompleteString() << ")";
+
+	out.debug << "\n";
+
+	return true;
+}
+
+bool TOutputTraverser::visitUnary(Visit visit, TIntermUnary* node)
+{
+	TInfoSink& out = infoSink;
+
+	OutputTreeText(out, node, depth);
+
+	switch (node->getOp()) {
+	case EOpNegative:       out.debug << "Negate value";         break;
+	case EOpVectorLogicalNot:
+	case EOpLogicalNot:     out.debug << "Negate conditional";   break;
+	case EOpBitwiseNot:     out.debug << "Bitwise not";          break;
+
+	case EOpPostIncrement:  out.debug << "Post-Increment";       break;
+	case EOpPostDecrement:  out.debug << "Post-Decrement";       break;
+	case EOpPreIncrement:   out.debug << "Pre-Increment";        break;
+	case EOpPreDecrement:   out.debug << "Pre-Decrement";        break;
+
+	case EOpConvIntToBool:  out.debug << "Convert int to bool";  break;
+	case EOpConvFloatToBool:out.debug << "Convert float to bool";break;
+	case EOpConvBoolToFloat:out.debug << "Convert bool to float";break;
+	case EOpConvIntToFloat: out.debug << "Convert int to float"; break;
+	case EOpConvFloatToInt: out.debug << "Convert float to int"; break;
+	case EOpConvBoolToInt:  out.debug << "Convert bool to int";  break;
+
+	case EOpRadians:        out.debug << "radians";              break;
+	case EOpDegrees:        out.debug << "degrees";              break;
+	case EOpSin:            out.debug << "sine";                 break;
+	case EOpCos:            out.debug << "cosine";               break;
+	case EOpTan:            out.debug << "tangent";              break;
+	case EOpAsin:           out.debug << "arc sine";             break;
+	case EOpAcos:           out.debug << "arc cosine";           break;
+	case EOpAtan:           out.debug << "arc tangent";          break;
+
+	case EOpExp:            out.debug << "exp";                  break;
+	case EOpLog:            out.debug << "log";                  break;
+	case EOpExp2:           out.debug << "exp2";                 break;
+	case EOpLog2:           out.debug << "log2";                 break;
+	case EOpSqrt:           out.debug << "sqrt";                 break;
+	case EOpInverseSqrt:    out.debug << "inverse sqrt";         break;
+
+	case EOpAbs:            out.debug << "Absolute value";       break;
+	case EOpSign:           out.debug << "Sign";                 break;
+	case EOpFloor:          out.debug << "Floor";                break;
+	case EOpCeil:           out.debug << "Ceiling";              break;
+	case EOpFract:          out.debug << "Fraction";             break;
+
+	case EOpLength:         out.debug << "length";               break;
+	case EOpNormalize:      out.debug << "normalize";            break;
+//	case EOpDPdx:           out.debug << "dPdx";                 break;               
+//	case EOpDPdy:           out.debug << "dPdy";                 break;   
+//	case EOpFwidth:         out.debug << "fwidth";               break;                   
+
+	case EOpAny:            out.debug << "any";                  break;
+	case EOpAll:            out.debug << "all";                  break;
+
+	default: out.debug.message(EPrefixError, "Bad unary op");
+	}
+
+	out.debug << " (" << node->getCompleteString() << ")";
+
+	out.debug << "\n";
+
+	return true;
+}
+
+bool TOutputTraverser::visitAggregate(Visit visit, TIntermAggregate* node)
+{
+	TInfoSink& out = infoSink;
+
+	if (node->getOp() == EOpNull) {
+		out.debug.message(EPrefixError, "node is still EOpNull!");
+		return true;
+	}
+
+	OutputTreeText(out, node, depth);
+
+	switch (node->getOp()) {
+	case EOpSequence:      out.debug << "Sequence\n"; return true;
+	case EOpComma:         out.debug << "Comma\n"; return true;
+	case EOpFunction:      out.debug << "Function Definition: " << node->getName(); break;
+	case EOpFunctionCall:  out.debug << "Function Call: " << node->getName(); break;
+	case EOpParameters:    out.debug << "Function Parameters: ";              break;
+
+	case EOpConstructFloat: out.debug << "Construct float"; break;
+	case EOpConstructVec2:  out.debug << "Construct vec2";  break;
+	case EOpConstructVec3:  out.debug << "Construct vec3";  break;
+	case EOpConstructVec4:  out.debug << "Construct vec4";  break;
+	case EOpConstructBool:  out.debug << "Construct bool";  break;
+	case EOpConstructBVec2: out.debug << "Construct bvec2"; break;
+	case EOpConstructBVec3: out.debug << "Construct bvec3"; break;
+	case EOpConstructBVec4: out.debug << "Construct bvec4"; break;
+	case EOpConstructInt:   out.debug << "Construct int";   break;
+	case EOpConstructIVec2: out.debug << "Construct ivec2"; break;
+	case EOpConstructIVec3: out.debug << "Construct ivec3"; break;
+	case EOpConstructIVec4: out.debug << "Construct ivec4"; break;
+	case EOpConstructMat2:  out.debug << "Construct mat2";  break;
+	case EOpConstructMat3:  out.debug << "Construct mat3";  break;
+	case EOpConstructMat4:  out.debug << "Construct mat4";  break;
+	case EOpConstructStruct:  out.debug << "Construct structure";  break;
+
+	case EOpLessThan:         out.debug << "Compare Less Than";             break;
+	case EOpGreaterThan:      out.debug << "Compare Greater Than";          break;
+	case EOpLessThanEqual:    out.debug << "Compare Less Than or Equal";    break;
+	case EOpGreaterThanEqual: out.debug << "Compare Greater Than or Equal"; break;
+	case EOpVectorEqual:      out.debug << "Equal";                         break;
+	case EOpVectorNotEqual:   out.debug << "NotEqual";                      break;
+
+	case EOpMod:           out.debug << "mod";         break;
+	case EOpPow:           out.debug << "pow";         break;
+
+	case EOpAtan:          out.debug << "arc tangent"; break;
+
+	case EOpMin:           out.debug << "min";         break;
+	case EOpMax:           out.debug << "max";         break;
+	case EOpClamp:         out.debug << "clamp";       break;
+	case EOpMix:           out.debug << "mix";         break;
+	case EOpStep:          out.debug << "step";        break;
+	case EOpSmoothStep:    out.debug << "smoothstep";  break;
+
+	case EOpDistance:      out.debug << "distance";                break;
+	case EOpDot:           out.debug << "dot-product";             break;
+	case EOpCross:         out.debug << "cross-product";           break;
+	case EOpFaceForward:   out.debug << "face-forward";            break;
+	case EOpReflect:       out.debug << "reflect";                 break;
+	case EOpRefract:       out.debug << "refract";                 break;
+	case EOpMul:           out.debug << "component-wise multiply"; break;
+
+	case EOpItof:          out.debug << "itof";        break;
+	case EOpFtoi:          out.debug << "ftoi";        break;
+	case EOpSkipPixels:    out.debug << "skipPixels";  break;
+	case EOpReadInput:     out.debug << "readInput";   break;
+	case EOpWritePixel:    out.debug << "writePixel";  break;
+	case EOpBitmapLsb:     out.debug << "bitmapLSB";   break;
+	case EOpBitmapMsb:     out.debug << "bitmapMSB";   break;
+	case EOpWriteOutput:   out.debug << "writeOutput"; break;
+	case EOpReadPixel:     out.debug << "readPixel";   break;
+
+	default: out.debug.message(EPrefixError, "Bad aggregation op");
+	}
+
+	if (node->getOp() != EOpSequence && node->getOp() != EOpParameters)
+		out.debug << " (" << node->getCompleteString() << ")";
+
+	out.debug << "\n";
+
+	return true;
+}
+
+bool TOutputTraverser::visitSelection(Visit visit, TIntermSelection* node)
+{
+	TInfoSink& out = infoSink;
+
+	OutputTreeText(out, node, depth);
+
+	out.debug << "Test condition and select";
+	out.debug << " (" << node->getCompleteString() << ")\n";
+
+	++depth;
+
+	OutputTreeText(infoSink, node, depth);
+	out.debug << "Condition\n";
+	node->getCondition()->traverse(this);
+
+	OutputTreeText(infoSink, node, depth);
+	if (node->getTrueBlock()) {
+		out.debug << "true case\n";
+		node->getTrueBlock()->traverse(this);
+	} else
+		out.debug << "true case is null\n";
+
+	if (node->getFalseBlock()) {
+		OutputTreeText(infoSink, node, depth);
+		out.debug << "false case\n";
+		node->getFalseBlock()->traverse(this);
+	}
+
+	--depth;
+
+	return false;
+}
+
+void TOutputTraverser::visitConstantUnion(TIntermConstantUnion* node)
+{
+	TInfoSink& out = infoSink;
+
+	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.debug << "true";
+			else
+				out.debug << "false";
+
+			out.debug << " (" << "const bool" << ")";
+
+			out.debug << "\n";
+			break;
+		case EbtFloat:
+			{
+				char buf[300];
+				sprintf(buf, "%f (%s)", node->getUnionArrayPointer()[i].getFConst(), "const float");
+
+				out.debug << buf << "\n";
+			}
+			break;
+		case EbtInt:
+			{
+				char buf[300];
+				sprintf(buf, "%d (%s)", node->getUnionArrayPointer()[i].getIConst(), "const int");
+
+				out.debug << buf << "\n";
+				break;
+			}
+		default:
+			out.info.message(EPrefixInternalError, "Unknown constant", node->getLine());
+			break;
+		}
+	}
+}
+
+bool TOutputTraverser::visitLoop(Visit visit, TIntermLoop* node)
+{
+	TInfoSink& out = infoSink;
+
+	OutputTreeText(out, node, depth);
+
+	out.debug << "Loop with condition ";
+	if (! node->testFirst())
+		out.debug << "not ";
+	out.debug << "tested first\n";
+
+	++depth;
+
+	OutputTreeText(infoSink, node, depth);
+	if (node->getTest()) {
+		out.debug << "Loop Condition\n";
+		node->getTest()->traverse(this);
+	} else
+		out.debug << "No loop condition\n";
+
+	OutputTreeText(infoSink, node, depth);
+	if (node->getBody()) {
+		out.debug << "Loop Body\n";
+		node->getBody()->traverse(this);
+	} else
+		out.debug << "No loop body\n";
+
+	if (node->getTerminal()) {
+		OutputTreeText(infoSink, node, depth);
+		out.debug << "Loop Terminal Expression\n";
+		node->getTerminal()->traverse(this);
+	}
+
+	--depth;
+
+	return false;
+}
+
+bool TOutputTraverser::visitBranch(Visit visit, TIntermBranch* node)
+{
+	TInfoSink& out = infoSink;
+
+	OutputTreeText(out, node, depth);
+
+	switch (node->getFlowOp()) {
+	case EOpKill:      out.debug << "Branch: Kill";           break;
+	case EOpBreak:     out.debug << "Branch: Break";          break;
+	case EOpContinue:  out.debug << "Branch: Continue";       break;
+	case EOpReturn:    out.debug << "Branch: Return";         break;
+	default:           out.debug << "Branch: Unknown Branch"; break;
+	}
+
+	if (node->getExpression()) {
+		out.debug << " with expression\n";
+		++depth;
+		node->getExpression()->traverse(this);
+		--depth;
+	} else
+		out.debug << "\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);
+
+	root->traverse(&it);
+}
diff --git a/Compiler/intermediate.h b/Compiler/intermediate.h
new file mode 100644
index 0000000..f80691e
--- /dev/null
+++ b/Compiler/intermediate.h
@@ -0,0 +1,508 @@
+//
+// 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.
+//
+
+//
+// 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 "Common.h"
+#include "Types.h"
+#include "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,
+
+	//
+	// Unary operators
+	//
+	
+	EOpNegative,
+	EOpLogicalNot,
+	EOpVectorLogicalNot,
+	EOpBitwiseNot,
+
+	EOpPostIncrement,
+	EOpPostDecrement,
+	EOpPreIncrement,
+	EOpPreDecrement,
+
+	EOpConvIntToBool,
+	EOpConvFloatToBool,
+	EOpConvBoolToFloat,
+	EOpConvIntToFloat,
+	EOpConvFloatToInt,
+	EOpConvBoolToInt,
+
+	//
+	// binary operations
+	//
+
+	EOpAdd,
+	EOpSub,
+	EOpMul,
+	EOpDiv,
+	EOpMod,
+	EOpRightShift,
+	EOpLeftShift,
+	EOpAnd,
+	EOpInclusiveOr,
+	EOpExclusiveOr,
+	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,
+	EOpMin,
+	EOpMax,
+	EOpClamp,
+	EOpMix,
+	EOpStep,
+	EOpSmoothStep,
+
+	EOpLength,
+	EOpDistance,
+	EOpDot,
+	EOpCross,
+	EOpNormalize,
+	EOpFaceForward,
+	EOpReflect,
+	EOpRefract,
+
+//	EOpDPdx,            // Fragment only
+//	EOpDPdy,            // Fragment only
+//	EOpFwidth,          // Fragment only
+
+	EOpMatrixTimesMatrix,
+
+	EOpAny,
+	EOpAll,
+	
+	EOpItof,         // pack/unpack only
+	EOpFtoi,         // pack/unpack only    
+	EOpSkipPixels,   // pack/unpack only
+	EOpReadInput,    // unpack only
+	EOpWritePixel,   // unpack only
+	EOpBitmapLsb,    // unpack only
+	EOpBitmapMsb,    // unpack only
+	EOpWriteOutput,  // pack only
+	EOpReadPixel,    // pack only
+	
+	//
+	// 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,
+	EOpModAssign,
+	EOpAndAssign,
+	EOpInclusiveOrAssign,
+	EOpExclusiveOrAssign,
+	EOpLeftShiftAssign,
+	EOpRightShiftAssign,
+
+	//
+	// Array operators
+	//
+
+	EOpArrayLength,
+};
+
+class TIntermTraverser;
+class TIntermAggregate;
+class TIntermBinary;
+class TIntermConstantUnion;
+class TIntermSelection;
+class TIntermTyped;
+class TIntermSymbol;
+class TInfoSink;
+
+//
+// Base class for the tree nodes
+//
+class TIntermNode {
+public:
+	POOL_ALLOCATOR_NEW_DELETE(GlobalPoolAllocator)
+
+	TIntermNode() : line(0) {}
+	virtual TSourceLoc getLine() const { return line; }
+	virtual 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 TIntermSelection* getAsSelectionNode() { return 0; }
+	virtual TIntermSymbol*    getAsSymbolNode()    { return 0; }
+	virtual ~TIntermNode() { }
+protected:
+	TSourceLoc line;
+};
+
+//
+// This is just to help yacc.
+//
+struct TIntermNodePair {
+	TIntermNode* node1;
+	TIntermNode* node2;
+};
+
+class TIntermSymbol;
+class TIntermBinary;
+
+//
+// Intermediate class for nodes that have a type.
+//
+class TIntermTyped : public TIntermNode {
+public:
+	TIntermTyped(const TType& t) : type(t)  { }
+	virtual TIntermTyped* getAsTyped()         { return this; }
+	virtual void setType(const TType& t) { type = t; }
+	virtual TType getType() const { return type; }
+	virtual TType* getTypePointer() { return &type; }
+	
+	virtual TBasicType getBasicType() const { return type.getBasicType(); }
+	virtual TQualifier getQualifier() const { return type.getQualifier(); }
+	virtual int getNominalSize() const { return type.getNominalSize(); }
+	virtual int getSize() const { return type.getInstanceSize(); }
+	virtual bool isMatrix() const { return type.isMatrix(); }
+	virtual bool isArray()  const { return type.isArray(); }
+	virtual bool isVector() const { return type.isVector(); }
+	const char* getBasicString()      const { return type.getBasicString(); }
+	const char* getQualifierString()  const { return type.getQualifierString(); }
+	TString getCompleteString() const { return type.getCompleteString(); }
+
+protected:
+	TType type;
+};
+
+//
+// Handle for, do-while, and while loops.
+//
+class TIntermLoop : public TIntermNode {
+public:
+	TIntermLoop(TIntermNode *init, TIntermNode* aBody, TIntermTyped* aTest, TIntermTyped* aTerminal, bool testFirst) : 
+	    init(init),
+		body(aBody),
+		test(aTest),
+		terminal(aTerminal),
+		first(testFirst) { }
+	virtual void traverse(TIntermTraverser*);
+	TIntermNode *getInit() { return init; }
+	TIntermNode *getBody() { return body; }
+	TIntermTyped *getTest() { return test; }
+	TIntermTyped *getTerminal() { return terminal; }
+	bool testFirst() { return first; }
+protected:
+	TIntermNode *init;
+	TIntermNode *body;       // code to loop over
+	TIntermTyped *test;      // exit condition associated with loop, could be 0 for 'for' loops
+	TIntermTyped *terminal;  // exists for for-loops
+	bool first;              // true for while and for, not for do-while
+};
+
+//
+// Handle break, continue, return, and kill.
+//
+class TIntermBranch : public TIntermNode {
+public:
+	TIntermBranch(TOperator op, TIntermTyped* e) :
+		flowOp(op),
+		expression(e) { }
+	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;} 
+	virtual int getId() const { return id; }
+	virtual const TString& getSymbol() const { return symbol;  }
+	virtual void traverse(TIntermTraverser*);
+	virtual TIntermSymbol* getAsSymbolNode() { return this; }
+protected:
+	int id;
+	TString symbol;
+};
+
+class TIntermConstantUnion : public TIntermTyped {
+public:
+	TIntermConstantUnion(constUnion *unionPointer, const TType& t) : TIntermTyped(t), unionArrayPointer(unionPointer) { }
+	constUnion* getUnionArrayPointer() const { return unionArrayPointer; }
+	void setUnionArrayPointer(constUnion *c) { unionArrayPointer = c; }
+	virtual TIntermConstantUnion* getAsConstantUnion()  { return this; }
+	virtual void traverse(TIntermTraverser* );
+	virtual TIntermTyped* fold(TOperator, TIntermTyped*, TInfoSink&);
+protected:
+	constUnion *unionArrayPointer;
+};
+
+//
+// Intermediate class for node types that hold operators.
+//
+class TIntermOperator : public TIntermTyped {
+public:
+	TOperator getOp() const { return op; }
+	bool modifiesState() const;
+	bool isConstructor() const;
+	virtual bool promote(TInfoSink&) { return true; }
+protected:
+	TIntermOperator(TOperator o) : TIntermTyped(TType(EbtFloat)), 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 void traverse(TIntermTraverser*);
+	virtual void setLeft(TIntermTyped* n) { left = n; }
+	virtual void setRight(TIntermTyped* n) { right = n; }
+	virtual TIntermTyped* getLeft() const { return left; }
+	virtual TIntermTyped* getRight() const { return right; }
+	virtual TIntermBinary* getAsBinaryNode() { return this; }
+	virtual 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 void setOperand(TIntermTyped* o) { operand = o; }
+	virtual TIntermTyped* getOperand() { return operand; }
+	virtual 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), pragmaTable(0) { }
+	TIntermAggregate(TOperator o) : TIntermOperator(o), pragmaTable(0) { }
+	~TIntermAggregate() { delete pragmaTable; }
+	virtual TIntermAggregate* getAsAggregate() { return this; }
+	virtual void setOperator(TOperator o) { op = o; }
+	virtual TIntermSequence& getSequence() { return sequence; }
+	virtual void setName(const TString& n) { name = n; }
+	virtual const TString& getName() const { return name; }
+	virtual void traverse(TIntermTraverser*);
+	virtual void setUserDefined() { userDefined = true; }
+	virtual bool isUserDefined() { return userDefined; }
+	virtual TQualifierList& getQualifier() { return qualifier; }
+	void setOptimize(bool o) { optimize = o; }
+	void setDebug(bool d) { debug = d; }
+	bool getOptimize() { return optimize; }
+	bool getDebug() { return debug; }
+	void addToPragmaTable(const TPragmaTable& pTable);
+	const TPragmaTable& getPragmaTable() const { return *pragmaTable; }
+protected:
+	TIntermAggregate(const TIntermAggregate&); // disallow copy constructor
+	TIntermAggregate& operator=(const TIntermAggregate&); // disallow assignment operator
+	TIntermSequence sequence;
+	TQualifierList qualifier;
+	TString name;
+	bool userDefined; // used for user defined function names
+	bool optimize;
+	bool debug;
+	TPragmaTable *pragmaTable;
+};
+
+//
+// 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)), condition(cond), trueBlock(trueB), falseBlock(falseB) {}
+	TIntermSelection(TIntermTyped* cond, TIntermNode* trueB, TIntermNode* falseB, const TType& type) :
+		TIntermTyped(type), condition(cond), trueBlock(trueB), falseBlock(falseB) {}
+	virtual void traverse(TIntermTraverser*);
+	virtual TIntermNode* getCondition() const { return condition; }
+	virtual TIntermNode* getTrueBlock() const { return trueBlock; }
+	virtual TIntermNode* getFalseBlock() const { return falseBlock; }
+	virtual 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 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/Compiler/localintermediate.h b/Compiler/localintermediate.h
new file mode 100644
index 0000000..b9cd3f2
--- /dev/null
+++ b/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 "intermediate.h"
+#include "ShaderLang.h"
+#include "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(constUnion*, const TType&, TSourceLoc);
+    TIntermTyped* promoteConstantUnion(TBasicType, TIntermConstantUnion*) ;
+    bool parseConstTree(TSourceLoc, TIntermNode*, constUnion*, TOperator, TSymbolTable&, TType, bool singleConstantParam = false);        
+    TIntermNode* addLoop(TIntermNode*, TIntermNode*, TIntermTyped*, TIntermTyped*, bool testFirst, TSourceLoc);
+    TIntermBranch* addBranch(TOperator, TSourceLoc);
+    TIntermBranch* addBranch(TOperator, TIntermTyped*, TSourceLoc);
+    TIntermTyped* addSwizzle(TVectorFields&, TSourceLoc);
+    bool postProcess(TIntermNode*, EShLanguage);
+	void remove(TIntermNode*);
+    void outputTree(TIntermNode*);
+    
+protected:
+    TInfoSink& infoSink;
+
+private:
+    void operator=(TIntermediate&); // prevent assignments
+};
+
+#endif // _LOCAL_INTERMEDIATE_INCLUDED_
diff --git a/Compiler/osinclude.h b/Compiler/osinclude.h
new file mode 100644
index 0000000..ddeb34e
--- /dev/null
+++ b/Compiler/osinclude.h
@@ -0,0 +1,41 @@
+//
+// 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 __OSINCLUDE_H
+#define __OSINCLUDE_H
+
+//
+// This file contains contains the window's specific datatypes and
+// declares any windows specific functions.
+//
+
+#if !(defined(_WIN32) || defined(_WIN64))
+#error Trying to include a windows specific file in a non windows build.
+#endif
+
+#define STRICT
+#define VC_EXTRALEAN 1
+#include <windows.h>
+#include <assert.h>
+
+
+//
+// Thread Local Storage Operations
+//
+typedef DWORD OS_TLSIndex;
+#define OS_INVALID_TLS_INDEX (TLS_OUT_OF_INDEXES)
+
+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);
+	return TlsGetValue(nIndex);
+}
+
+#endif // __OSINCLUDE_H
diff --git a/Compiler/ossource.cpp b/Compiler/ossource.cpp
new file mode 100644
index 0000000..ed93efe
--- /dev/null
+++ b/Compiler/ossource.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 "osinclude.h"
+//
+// This file contains contains the window's specific functions
+//
+
+#if !(defined(_WIN32) || defined(_WIN64))
+#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/Compiler/parseConst.cpp b/Compiler/parseConst.cpp
new file mode 100644
index 0000000..39606e9
--- /dev/null
+++ b/Compiler/parseConst.cpp
@@ -0,0 +1,227 @@
+//
+// 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 "ParseHelper.h"
+
+//
+// Use this class to carry along data from node to node in 
+// the traversal
+//
+class TConstTraverser : public TIntermTraverser {
+public:
+    TConstTraverser(constUnion* cUnion, bool singleConstParam, TOperator constructType, TInfoSink& sink, TSymbolTable& symTable, TType& t) : unionArray(cUnion), type(t),
+        constructorType(constructType), singleConstantParam(singleConstParam), infoSink(sink), symbolTable(symTable), error(false), isMatrix(false), matrixSize(0)
+	{
+		index = 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;
+    constUnion *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) {
+        char buf[200];
+        sprintf(buf, "'constructor' : assigning non-constant to %s", type.getCompleteString().c_str());
+        infoSink.info.message(EPrefixError, buf, 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)
+{
+    char buf[200];
+    sprintf(buf, "'constructor' : assigning non-constant to '%s'", type.getCompleteString().c_str());
+    infoSink.info.message(EPrefixError, buf, node->getLine());
+    error = true;
+    return false;  
+}
+
+bool TConstTraverser::visitAggregate(Visit visit, TIntermAggregate* node)
+{
+    if (!node->isConstructor() && node->getOp() != EOpComma) {
+        char buf[200];
+        sprintf(buf, "'constructor' : assigning non-constant to '%s'", type.getCompleteString().c_str());
+        infoSink.info.message(EPrefixError, buf, 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)
+{
+    constUnion* leftUnionArray = unionArray;
+    int instanceSize = type.getObjectSize();
+
+    if (index >= instanceSize)
+        return;
+
+    if (!singleConstantParam) {
+        int size = node->getType().getObjectSize();
+    
+        constUnion *rightUnionArray = node->getUnionArrayPointer();
+        for (int i=0; i < size; i++) {
+            if (index >= instanceSize)
+                return;
+            leftUnionArray[index] = rightUnionArray[i];
+
+            (index)++;
+        }
+    } else {
+        int totalSize = index + size;
+        constUnion *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);
+
+                (element)++;
+
+                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, constUnion* 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/Compiler/unistd.h b/Compiler/unistd.h
new file mode 100644
index 0000000..c7c9147
--- /dev/null
+++ b/Compiler/unistd.h
@@ -0,0 +1 @@
+// This is a NULL file and is meant to be empty
diff --git a/Include/Config.h b/Include/Config.h
new file mode 100644
index 0000000..42fe56e
--- /dev/null
+++ b/Include/Config.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.
+//
+
+// 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_
+
+#define EGLAPI
+#include <EGL/egl.h>
+#include <d3d9.h>
+
+#include <set>
+
+#include "angleutils.h"
+
+namespace egl
+{
+class Config
+{
+  public:
+    Config(D3DDISPLAYMODE displayMode, EGLint minSwapInterval, EGLint maxSwapInterval, D3DFORMAT renderTargetFormat, D3DFORMAT depthStencilFormat, EGLint multiSample);
+
+    void setDefaults();
+    void set(D3DDISPLAYMODE displayMode, EGLint minSwapInterval, EGLint maxSwapInterval, D3DFORMAT renderTargetFormat, D3DFORMAT depthStencilFormat, EGLint multiSample);
+    EGLConfig getHandle() const;
+
+    const D3DDISPLAYMODE mDisplayMode;
+    const D3DFORMAT mRenderTargetFormat;
+    const D3DFORMAT 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
+{
+  public:
+    ConfigSet();
+
+    void add(D3DDISPLAYMODE displayMode, EGLint minSwapInterval, EGLint maxSwapInterval, D3DFORMAT renderTargetFormat, D3DFORMAT depthStencilFormat, EGLint multiSample);
+    void enumerate();
+    size_t size() const;
+    bool getConfigs(EGLConfig *configs, const EGLint *attribList, EGLint configSize, EGLint *numConfig);
+    const egl::Config *get(EGLConfig configHandle);
+
+    typedef std::set<Config, SortConfig> Set;
+    typedef Set::iterator Iterator;
+    Set mSet;
+
+  private:
+    DISALLOW_COPY_AND_ASSIGN(ConfigSet);
+
+    static const EGLint mSortAttribs[];
+};
+}
+
+#endif   // INCLUDE_CONFIG_H_
diff --git a/Include/Context.h b/Include/Context.h
new file mode 100644
index 0000000..86a4d14
--- /dev/null
+++ b/Include/Context.h
@@ -0,0 +1,292 @@
+//
+// 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.
+//
+
+// Context.h: Defines the gl::Context class, managing all GL state and performing
+// rendering operations. It is the GLES2 specific implementation of EGLContext.
+
+#ifndef INCLUDE_CONTEXT_H_
+#define INCLUDE_CONTEXT_H_
+
+#define GL_APICALL
+#include <GLES2/gl2.h>
+#define EGLAPI
+#include <EGL/egl.h>
+#include <d3d9.h>
+
+#include <map>
+
+#include "angleutils.h"
+
+namespace egl
+{
+class Display;
+class Surface;
+class Config;
+}
+
+namespace gl
+{
+class Buffer;
+class Shader;
+class Program;
+class Texture;
+class Texture2D;
+class TextureCubeMap;
+class Framebuffer;
+class Renderbuffer;
+class Colorbuffer;
+class Depthbuffer;
+class Stencilbuffer;
+
+enum
+{
+    MAX_VERTEX_ATTRIBS = 8,
+    MAX_VERTEX_UNIFORM_VECTORS = 128,
+    MAX_VARYING_VECTORS = 8,
+    MAX_COMBINED_TEXTURE_IMAGE_UNITS = 8,
+    MAX_VERTEX_TEXTURE_IMAGE_UNITS = 0,
+    MAX_TEXTURE_IMAGE_UNITS = 8,
+    MAX_FRAGMENT_UNIFORM_VECTORS = 16,
+    MAX_RENDERBUFFER_SIZE = 4096,   // FIXME: Verify
+    MAX_DRAW_BUFFERS = 1,
+
+    IMPLEMENTATION_COLOR_READ_FORMAT = GL_RGB,
+    IMPLEMENTATION_COLOR_READ_TYPE = GL_UNSIGNED_SHORT_5_6_5
+};
+
+struct Color
+{
+    float red;
+    float green;
+    float blue;
+    float alpha;
+};
+
+// Helper structure describing a single vertex attribute array
+struct Array
+{
+    Array();
+
+    bool enabled;
+    GLuint boundBuffer;
+    GLint size;
+    GLenum type;
+    GLboolean normalized;
+    GLsizei stride;
+    const void *pointer;
+};
+
+// 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;
+    bool sampleAlphaToCoverage;
+    bool sampleCoverage;
+    GLclampf sampleCoverageValue;
+    GLboolean sampleCoverageInvert;
+    bool scissorTest;
+    bool dither;
+
+    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;
+    
+    int activeSampler;   // Active texture unit selector - GL_TEXTURE0
+    GLuint arrayBuffer;
+    GLuint elementArrayBuffer;
+    GLuint texture2D;
+    GLuint textureCubeMap;
+    GLuint framebuffer;
+    GLuint renderbuffer;
+    GLuint currentProgram;
+
+    Array vertexAttribute[MAX_VERTEX_ATTRIBS];
+    GLuint samplerTexture[MAX_TEXTURE_IMAGE_UNITS];
+
+    unsigned int startIndex;
+};
+
+class Context : public State
+{
+  public:
+    Context(const egl::Config *config);
+
+    ~Context();
+
+    void makeCurrent(egl::Display *display, egl::Surface *surface);
+
+    void setClearColor(float red, float green, float blue, float alpha);
+    void setClearDepth(float depth);
+    void setClearStencil(int stencil);
+
+    GLuint createBuffer();
+    GLuint createShader(GLenum type);
+    GLuint createProgram();
+    GLuint createTexture();
+    GLuint createFramebuffer();
+    GLuint createRenderbuffer();
+
+    void deleteBuffer(GLuint buffer);
+    void deleteShader(GLuint shader);
+    void deleteProgram(GLuint program);
+    void deleteTexture(GLuint texture);
+    void deleteFramebuffer(GLuint framebuffer);
+    void deleteRenderbuffer(GLuint renderbuffer);
+
+    void bindArrayBuffer(GLuint buffer);
+    void bindElementArrayBuffer(GLuint buffer);
+    void bindTexture2D(GLuint texture);
+    void bindTextureCubeMap(GLuint texture);
+    void bindFramebuffer(GLuint framebuffer);
+    void bindRenderbuffer(GLuint renderbuffer);
+    void useProgram(GLuint program);
+
+    void setFramebufferZero(Framebuffer *framebuffer);
+    void setColorbufferZero(Colorbuffer *renderbuffer);
+    void setDepthbufferZero(Depthbuffer *depthBuffer);
+    void setStencilbufferZero(Stencilbuffer *stencilBuffer);
+    void setRenderbuffer(Renderbuffer *renderbuffer);
+
+    Buffer *getBuffer(GLuint handle);
+    Shader *getShader(GLuint handle);
+    Program *getProgram(GLuint handle);
+    Texture *getTexture(GLuint handle);
+    Framebuffer *getFramebuffer(GLuint handle);
+    Renderbuffer *getRenderbuffer(GLuint handle);
+    Colorbuffer *getColorbuffer(GLuint handle);
+    Depthbuffer *getDepthbuffer(GLuint handle);
+    Stencilbuffer *getStencilbuffer(GLuint handle);
+
+    Buffer *getArrayBuffer();
+    Buffer *getElementArrayBuffer();
+    Program *getCurrentProgram();
+    Texture2D *getTexture2D();
+    TextureCubeMap *getTextureCubeMap();
+    Texture *getSamplerTexture(unsigned int sampler);
+    Framebuffer *getFramebuffer();
+
+    bool applyRenderTarget(bool ignoreViewport);
+    void applyState();
+    void applyVertexBuffer(int count);
+    void applyIndexBuffer(const void *indices, int length);
+    void applyShaders();
+    void applyTextures();
+
+    void readPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, 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();
+
+  private:
+    DISALLOW_COPY_AND_ASSIGN(Context);
+
+    void detachBuffer(GLuint buffer);
+    void detachTexture(GLuint texture);
+    void detachFramebuffer(GLuint framebuffer);
+    void detachRenderbuffer(GLuint renderbuffer);
+
+    const egl::Config *const mConfig;
+
+    Texture2D *mTexture2DZero;
+    TextureCubeMap *mTextureCubeMapZero;
+
+    Colorbuffer *mColorbufferZero;
+    Depthbuffer *mDepthbufferZero;
+    Stencilbuffer *mStencilbufferZero;
+
+    typedef std::map<GLuint, Buffer*> BufferMap;
+    BufferMap mBufferMap;
+
+    typedef std::map<GLuint, Shader*> ShaderMap;
+    ShaderMap mShaderMap;
+
+    typedef std::map<GLuint, Program*> ProgramMap;
+    ProgramMap mProgramMap;
+
+    typedef std::map<GLuint, Texture*> TextureMap;
+    TextureMap mTextureMap;
+
+    typedef std::map<GLuint, Framebuffer*> FramebufferMap;
+    FramebufferMap mFramebufferMap;
+
+    typedef std::map<GLuint, Renderbuffer*> RenderbufferMap;
+    RenderbufferMap mRenderbufferMap;
+
+    // Recorded errors
+    bool mInvalidEnum;
+    bool mInvalidValue;
+    bool mInvalidOperation;
+    bool mOutOfMemory;
+    bool mInvalidFramebufferOperation;
+};
+}
+
+extern "C"
+{
+// Exported functions for use by EGL
+gl::Context *glCreateContext(const egl::Config *config);
+void glDestroyContext(gl::Context *context);
+void glMakeCurrent(gl::Context *context, egl::Display *display, egl::Surface *surface);
+gl::Context *glGetCurrentContext();
+}
+
+#endif   // INCLUDE_CONTEXT_H_
diff --git a/Include/Display.h b/Include/Display.h
new file mode 100644
index 0000000..db58a74
--- /dev/null
+++ b/Include/Display.h
@@ -0,0 +1,74 @@
+//
+// 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.
+//
+
+// 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_
+
+#ifndef WIN32_LEAN_AND_MEAN
+#define WIN32_LEAN_AND_MEAN
+#endif
+#include <windows.h>
+#include <d3d9.h>
+
+#include "Config.h"
+#include "Surface.h"
+#include "Context.h"
+
+#include <set>
+
+namespace egl
+{
+class Display
+{
+  public:
+    Display(HDC deviceContext);
+
+    ~Display();
+
+    bool initialize();
+    void terminate();
+
+    bool getConfigs(EGLConfig *configs, const EGLint *attribList, EGLint configSize, EGLint *numConfig);
+    bool getConfigAttrib(EGLConfig config, EGLint attribute, EGLint *value);
+
+    egl::Surface *createWindowSurface(HWND window, EGLConfig config);
+    EGLContext createContext(EGLConfig configHandle);
+
+    void destroySurface(egl::Surface *surface);
+    void destroyContext(gl::Context *context);
+
+    bool isInitialized();
+    bool isValidConfig(EGLConfig config);
+    bool isValidContext(gl::Context *context);
+    bool isValidSurface(egl::Surface *surface);
+    bool hasExistingWindowSurface(HWND window);
+
+    virtual IDirect3DDevice9 *getDevice();
+
+  private:
+    DISALLOW_COPY_AND_ASSIGN(Display);
+    const HDC mDc;
+
+    UINT mAdapter;
+    D3DDEVTYPE mDeviceType;
+    IDirect3D9 *mD3d9;
+    IDirect3DDevice9 *mDevice;
+
+    typedef std::set<Surface*> SurfaceSet;
+    SurfaceSet mSurfaceSet;
+
+    ConfigSet mConfigSet;
+
+    typedef std::set<gl::Context*> ContextSet;
+    ContextSet mContextSet;
+};
+}
+
+#endif   // INCLUDE_DISPLAY_H_
diff --git a/Include/EGL/egl.h b/Include/EGL/egl.h
new file mode 100644
index 0000000..22eba93
--- /dev/null
+++ b/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.
+ */
+
+/*
+** 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_PRESERVED_RESOURCES		0x3030
+#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/Include/EGL/eglext.h b/Include/EGL/eglext.h
new file mode 100644
index 0000000..6969cf2
--- /dev/null
+++ b/Include/EGL/eglext.h
@@ -0,0 +1,137 @@
+#ifndef __eglext_h_
+#define __eglext_h_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+** 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.
+*/
+
+#include <EGL/eglplatform.h>
+
+/*************************************************************/
+
+/* Header file version number */
+/* Current version at http://www.khronos.org/registry/egl/ */
+#define EGL_EGLEXT_VERSION 3
+
+#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
+
+#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
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/Include/EGL/eglplatform.h b/Include/EGL/eglplatform.h
new file mode 100644
index 0000000..1b789bf
--- /dev/null
+++ b/Include/EGL/eglplatform.h
@@ -0,0 +1,113 @@
+#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
+ *
+ * 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
+
+#define EGLAPIENTRY  KHRONOS_APIENTRY
+#define EGLAPIENTRYP KHRONOS_APIENTRY*
+
+/* 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".
+ */
+
+#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(SUPPORT_X11)
+
+/* X11 (tentative)  */
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+
+typedef Display *EGLNativeDisplayType;
+typedef Pixmap   EGLNativePixmapType;
+typedef Window   EGLNativeWindowType;
+
+#else
+
+#if defined(_WIN64) ||  __WORDSIZE == 64
+typedef khronos_int64_t EGLNativeDisplayType;
+#else
+typedef int EGLNativeDisplayType;
+#endif
+typedef void *EGLNativeWindowType;
+typedef void *EGLNativePixmapType;
+
+#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.
+ */
+ #if defined(_WIN64) ||  __WORDSIZE == 64
+typedef khronos_int64_t EGLint;
+#else
+typedef khronos_int32_t EGLint;
+#endif
+
+#endif /* __eglplatform_h */
diff --git a/Include/GLES2/gl2.h b/Include/GLES2/gl2.h
new file mode 100644
index 0000000..59e376c
--- /dev/null
+++ b/Include/GLES2/gl2.h
@@ -0,0 +1,620 @@
+#ifndef __gl2_h_
+#define __gl2_h_
+
+/* $Revision: 8784 $ on $Date:: 2009-09-02 09:49:17 -0700 #$ */
+
+#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 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 char* 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 void* data, GLenum usage);
+GL_APICALL void         GL_APIENTRY glBufferSubData (GLenum target, GLintptr offset, GLsizeiptr size, const void* 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 void* data);
+GL_APICALL void         GL_APIENTRY glCompressedTexSubImage2D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void* 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 void* 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, char* name);
+GL_APICALL void         GL_APIENTRY glGetActiveUniform (GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, char* name);
+GL_APICALL void         GL_APIENTRY glGetAttachedShaders (GLuint program, GLsizei maxcount, GLsizei* count, GLuint* shaders);
+GL_APICALL int          GL_APIENTRY glGetAttribLocation (GLuint program, const char* 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, char* 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, char* 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, char* 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 char* 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, void** 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, void* 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 void* binary, GLsizei length);
+GL_APICALL void         GL_APIENTRY glShaderSource (GLuint shader, GLsizei count, const char** 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 void* 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 void* 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 void* ptr);
+GL_APICALL void         GL_APIENTRY glViewport (GLint x, GLint y, GLsizei width, GLsizei height);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __gl2_h_ */
diff --git a/Include/GLES2/gl2ext.h b/Include/GLES2/gl2ext.h
new file mode 100644
index 0000000..27cf711
--- /dev/null
+++ b/Include/GLES2/gl2ext.h
@@ -0,0 +1,610 @@
+#ifndef __gl2ext_h_
+#define __gl2ext_h_
+
+/* $Revision: 8936 $ on $Date:: 2009-09-17 17:16:47 -0700 #$ */
+
+#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_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_texture3D */
+#ifndef GL_OES_texture3D
+#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_half_float */
+#ifndef GL_OES_texture_half_float
+#define GL_HALF_FLOAT_OES                                       0x8D61
+#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_program_binary_Z400 */
+#ifndef GL_AMD_program_binary_Z400
+#define GL_Z400_BINARY_AMD                                      0x8740
+#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
+
+/*------------------------------------------------------------------------*
+ * EXT extension tokens
+ *------------------------------------------------------------------------*/
+
+/* 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_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_texture_format_BGRA8888 */
+#ifndef GL_EXT_texture_format_BGRA8888
+#define GL_BGRA                                                 0x80E1
+#endif
+
+/* 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
+
+#ifndef GL_EXT_blend_minmax
+#define GL_MIN_EXT                                              0x8007
+#define GL_MAX_EXT                                              0x8008
+#endif
+
+/*------------------------------------------------------------------------*
+ * IMG extension tokens
+ *------------------------------------------------------------------------*/
+
+/* GL_IMG_read_format */
+#ifndef GL_IMG_read_format
+#define GL_BGRA                                                 0x80E1
+#define GL_UNSIGNED_SHORT_4_4_4_4_REV                           0x8365
+#define GL_UNSIGNED_SHORT_1_5_5_5_REV                           0x8366
+#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
+
+/*------------------------------------------------------------------------*
+ * NV extension tokens
+ *------------------------------------------------------------------------*/
+
+/* 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
+
+/*------------------------------------------------------------------------*
+ * QCOM extension tokens
+ *------------------------------------------------------------------------*/
+
+/* GL_QCOM_driver_control */
+/* 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_AMD                              0x8823
+#endif
+
+/* 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. */
+
+/*------------------------------------------------------------------------*
+ * 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_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_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_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, void *binary);
+GL_APICALL void GL_APIENTRY glProgramBinaryOES (GLuint program, GLenum binaryFormat, const void *binary, GLint length);
+#endif
+typedef void (GL_APIENTRYP PFNGLGETPROGRAMBINARYOESPROC) (GLuint program, GLsizei bufSize, GLsizei *length, GLenum *binaryFormat, void *binary);
+typedef void (GL_APIENTRYP PFNGLPROGRAMBINARYOESPROC) (GLuint program, GLenum binaryFormat, const void *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, void** 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, void** 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 void* 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 void* 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 void* 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 void* 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 void* 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 void* 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 void* data);
+typedef void (GL_APIENTRYP PFNGLFRAMEBUFFERTEXTURE3DOES) (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLint zoffset);
+#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_linear */
+#ifndef GL_OES_texture_half_float_linear
+#define GL_OES_texture_half_float_linear 1
+#endif
+
+/* GL_OES_texture_float */
+#ifndef GL_OES_texture_float
+#define GL_OES_texture_float 1
+#endif
+
+/* GL_OES_texture_half_float */
+#ifndef GL_OES_texture_half_float
+#define GL_OES_texture_half_float 1
+#endif
+
+/* GL_OES_texture_npot */
+#ifndef GL_OES_texture_npot
+#define GL_OES_texture_npot 1
+#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
+
+/* GL_AMD_program_binary_Z400 */
+#ifndef GL_AMD_program_binary_Z400
+#define GL_AMD_program_binary_Z400 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, char *groupString);
+GL_APICALL void GL_APIENTRY glGetPerfMonitorCounterStringAMD (GLuint group, GLuint counter, GLsizei bufSize, GLsizei *length, char *counterString);
+GL_APICALL void GL_APIENTRY glGetPerfMonitorCounterInfoAMD (GLuint group, GLuint counter, GLenum pname, void *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, char *groupString);
+typedef void (GL_APIENTRYP PFNGLGETPERFMONITORCOUNTERSTRINGAMDPROC) (GLuint group, GLuint counter, GLsizei bufSize, GLsizei *length, char *counterString);
+typedef void (GL_APIENTRYP PFNGLGETPERFMONITORCOUNTERINFOAMDPROC) (GLuint group, GLuint counter, GLenum pname, void *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
+
+/*------------------------------------------------------------------------*
+ * EXT extension functions
+ *------------------------------------------------------------------------*/
+
+/* GL_EXT_texture_filter_anisotropic */
+#ifndef GL_EXT_texture_filter_anisotropic
+#define GL_EXT_texture_filter_anisotropic 1
+#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_texture_format_BGRA8888 */
+#ifndef GL_EXT_texture_format_BGRA8888
+#define GL_EXT_texture_format_BGRA8888 1
+#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_blend_minmax */
+#ifndef GL_EXT_blend_minmax
+#define GL_EXT_blend_minmax 1
+#endif
+
+/*------------------------------------------------------------------------*
+ * IMG extension functions
+ *------------------------------------------------------------------------*/
+
+/* GL_IMG_read_format */
+#ifndef GL_IMG_read_format
+#define GL_IMG_read_format 1
+#endif
+
+/* GL_IMG_texture_compression_pvrtc */
+#ifndef GL_IMG_texture_compression_pvrtc
+#define GL_IMG_texture_compression_pvrtc 1
+#endif
+
+/*------------------------------------------------------------------------*
+ * NV extension functions
+ *------------------------------------------------------------------------*/
+
+/* 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
+
+/*------------------------------------------------------------------------*
+ * QCOM extension functions
+ *------------------------------------------------------------------------*/
+
+/* 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, char *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, char *driverControlString);
+typedef void (GL_APIENTRYP PFNGLENABLEDRIVERCONTROLQCOMPROC) (GLuint driverControl);
+typedef void (GL_APIENTRYP PFNGLDISABLEDRIVERCONTROLQCOMPROC) (GLuint driverControl);
+#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_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, void *texels);
+GL_APICALL void GL_APIENTRY glExtGetBufferPointervQCOM (GLenum target, void **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, void *texels);
+typedef void (GL_APIENTRYP PFNGLEXTGETBUFFERPOINTERVQCOMPROC) (GLenum target, void **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 void GL_APIENTRY glExtIsProgramBinaryQCOM (GLuint program);
+GL_APICALL void GL_APIENTRY glExtGetProgramBinarySourceQCOM (GLuint program, GLenum shadertype, char *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 void (GL_APIENTRYP PFNGLEXTISPROGRAMBINARYQCOMPROC) (GLuint program);
+typedef void (GL_APIENTRYP PFNGLEXTGETPROGRAMBINARYSOURCEQCOMPROC) (GLuint program, GLenum shadertype, char *source, GLint *length);
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __gl2ext_h_ */
diff --git a/Include/GLES2/gl2extimg.h b/Include/GLES2/gl2extimg.h
new file mode 100644
index 0000000..042b28d
--- /dev/null
+++ b/Include/GLES2/gl2extimg.h
@@ -0,0 +1,51 @@
+#ifndef __gl2extimg_h_
+#define __gl2extimg_h_
+
+#include <GLES2/gl2.h>
+#include <GLES2/gl2ext.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*------------------------------------------------------------------------*
+ * IMG extension tokens
+ *------------------------------------------------------------------------*/
+
+/* GL_IMG_binary_shader */
+#ifndef GL_IMG_binary_shader
+#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_texture_format_BGRA8888 */
+#define GL_BGRA							0x80E1
+
+
+/*------------------------------------------------------------------------*
+ * IMG extension functions
+ *------------------------------------------------------------------------*/
+
+/* GL_IMG_binary_shader */
+#ifndef GL_IMG_binary_shader
+#define GL_IMG_binary_shader 1
+#endif
+
+/* GL_IMG_texture_compression_pvrtc */
+#ifndef GL_IMG_texture_compression_pvrtc
+#define GL_IMG_texture_compression_pvrtc 1
+#endif	
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __gl2extimg_h_ */
diff --git a/Include/GLES2/gl2platform.h b/Include/GLES2/gl2platform.h
new file mode 100644
index 0000000..3e9036c
--- /dev/null
+++ b/Include/GLES2/gl2platform.h
@@ -0,0 +1,29 @@
+#ifndef __gl2platform_h_
+#define __gl2platform_h_
+
+/* $Revision: 7173 $ on $Date:: 2009-01-09 11:18:21 -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
+ * Last modified on 2008/12/19
+ *
+ * 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
+
+#define GL_APIENTRY KHRONOS_APIENTRY
+
+#endif /* __gl2platform_h_ */
diff --git a/Include/KHR/khrplatform.h b/Include/KHR/khrplatform.h
new file mode 100644
index 0000000..8341f71
--- /dev/null
+++ b/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: 7820 $ on $Date: 2009-04-03 13:46:26 -0700 (Fri, 03 Apr 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/Include/Surface.h b/Include/Surface.h
new file mode 100644
index 0000000..e071a93
--- /dev/null
+++ b/Include/Surface.h
@@ -0,0 +1,62 @@
+//
+// 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.
+//
+
+// 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_
+
+#define EGLAPI
+#include <EGL/egl.h>
+#include <d3d9.h>
+
+#include "angleutils.h"
+
+namespace egl
+{
+class Surface
+{
+  public:
+    Surface(IDirect3DDevice9 *device, IDirect3DSwapChain9 *swapChain, EGLint configID);
+
+    ~Surface();
+
+    HWND getWindowHandle();
+    void swap();
+
+    EGLint getWidth() const;
+    EGLint getHeight() const;
+
+    virtual IDirect3DSurface9 *getRenderTarget();
+
+  private:
+    DISALLOW_COPY_AND_ASSIGN(Surface);
+    IDirect3DSwapChain9 *const mSwapChain;
+    IDirect3DSurface9 *mBackBuffer;
+    IDirect3DSurface9 *mRenderTarget;
+
+    const EGLint mConfigID;            // ID of EGLConfig 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 textureFormat;            // Format of texture: RGB, RGBA, or no texture
+//    EGLenum textureTarget;            // Type of texture: 2D or no texture
+//    EGLenum vgAlphaFormat;            // Alpha format for OpenVG
+//    EGLenum vgColorSpace;            // Color space for OpenVG
+};
+}
+
+#endif   // INCLUDE_SURFACE_H_
diff --git a/Include/angleutils.h b/Include/angleutils.h
new file mode 100644
index 0000000..f430741
--- /dev/null
+++ b/Include/angleutils.h
@@ -0,0 +1,14 @@
+//
+// 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.
+//
+
+// angleutils.h: Common ANGLE utilities.
+
+// A macro to disallow the copy constructor and operator= functions
+// This must be used in the private: declarations for a class
+#define DISALLOW_COPY_AND_ASSIGN(TypeName) \
+  TypeName(const TypeName&);               \
+  void operator=(const TypeName&)
+
diff --git a/Include/debug.h b/Include/debug.h
new file mode 100644
index 0000000..7885675
--- /dev/null
+++ b/Include/debug.h
@@ -0,0 +1,69 @@
+//
+// 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 COMMON_DEBUG_H_
+#define COMMON_DEBUG_H_
+
+#ifndef WIN32_LEAN_AND_MEAN
+#define WIN32_LEAN_AND_MEAN
+#endif
+#include <windows.h>
+#include <stdio.h>
+#include <assert.h>
+
+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
+#ifndef NDEBUG
+    #define TRACE(arguments, ...) gl::trace("trace: %s("arguments")\n", __FUNCTION__, __VA_ARGS__)
+#else
+    #define TRACE(...) ((void)0)
+#endif
+
+// A macro to output a function call and its arguments to the debugging log, to denote an item in need of fixing. Will occur even in release mode.
+#define FIXME(arguments, ...) gl::trace("fixme: %s("arguments")\n", __FUNCTION__, __VA_ARGS__)
+
+// A macro to output a function call and its arguments to the debugging log, in case of error. Will occur even in release mode.
+#define ERR(arguments, ...) gl::trace("err: %s("arguments")\n", __FUNCTION__, __VA_ARGS__)
+
+// A macro asserting a condition and outputting failures to the debug log
+#define ASSERT(expression) do { \
+    if(!(expression)) \
+        ERR("\t! Assert failed in %s(%d): "#expression"\n", __FUNCTION__, __LINE__); \
+    assert(expression); \
+    } while(0)
+
+
+// A macro to indicate unimplemented functionality
+#ifndef 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
+#ifndef 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/LICENSE b/LICENSE
new file mode 100644
index 0000000..0513b7d
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,32 @@
+// Copyright (C) 2002-2010 The ANGLE Project Authors. 
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+//
+//     Redistributions of source code must retain the above copyright
+//     notice, this list of conditions and the following disclaimer.
+//
+//     Redistributions in binary form must reproduce the above 
+//     copyright notice, this list of conditions and the following
+//     disclaimer in the documentation and/or other materials provided
+//     with the distribution.
+//
+//     Neither the name of TransGaming Inc., Google Inc., 3DLabs Inc.
+//     Ltd., nor the names of their contributors may be used to endorse
+//     or promote products derived from this software without specific
+//     prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+// COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+// POSSIBILITY OF SUCH DAMAGE.
diff --git a/libEGL/Config.cpp b/libEGL/Config.cpp
new file mode 100644
index 0000000..8ad5136
--- /dev/null
+++ b/libEGL/Config.cpp
@@ -0,0 +1,408 @@
+//
+// 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.
+//
+
+// 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 <algorithm>
+#include <vector>
+
+#include "debug.h"
+
+using namespace std;
+
+namespace egl
+{
+Config::Config(D3DDISPLAYMODE displayMode, EGLint minInterval, EGLint maxInterval, D3DFORMAT renderTargetFormat, D3DFORMAT depthStencilFormat, EGLint multiSample)
+    : mDisplayMode(displayMode), mRenderTargetFormat(renderTargetFormat), mDepthStencilFormat(depthStencilFormat), mMultiSample(multiSample)
+{
+    set(displayMode, minInterval, maxInterval, renderTargetFormat, depthStencilFormat, multiSample);
+}
+
+void Config::setDefaults()
+{
+    mBufferSize = 0;
+    mRedSize = 0;
+    mGreenSize = 0;
+    mBlueSize = 0;
+    mLuminanceSize = 0;
+    mAlphaSize = 0;
+    mAlphaMaskSize = 0;
+    mBindToTextureRGB = EGL_DONT_CARE;
+    mBindToTextureRGBA = EGL_DONT_CARE;
+    mColorBufferType = EGL_RGB_BUFFER;
+    mConfigCaveat = EGL_DONT_CARE;
+    mConfigID = EGL_DONT_CARE;
+    mConformant = 0;
+    mDepthSize = 0;
+    mLevel = 0;
+    mMatchNativePixmap = EGL_NONE;
+    mMaxPBufferWidth = 0;
+    mMaxPBufferHeight = 0;
+    mMaxPBufferPixels = 0;
+    mMaxSwapInterval = EGL_DONT_CARE;
+    mMinSwapInterval = EGL_DONT_CARE;
+    mNativeRenderable = EGL_DONT_CARE;
+    mNativeVisualID = 0;
+    mNativeVisualType = EGL_DONT_CARE;
+    mRenderableType = EGL_OPENGL_ES_BIT;
+    mSampleBuffers = 0;
+    mSamples = 0;
+    mStencilSize = 0;
+    mSurfaceType = EGL_WINDOW_BIT;
+    mTransparentType = EGL_NONE;
+    mTransparentRedValue = EGL_DONT_CARE;
+    mTransparentGreenValue = EGL_DONT_CARE;
+    mTransparentBlueValue = EGL_DONT_CARE;
+}
+
+void Config::set(D3DDISPLAYMODE displayMode, EGLint minInterval, EGLint maxInterval, D3DFORMAT renderTargetFormat, D3DFORMAT depthStencilFormat, EGLint multiSample)
+{
+    switch (renderTargetFormat)
+    {
+      case D3DFMT_A1R5G5B5:
+        mBufferSize = 16;
+        mRedSize = 5;
+        mGreenSize = 5;
+        mBlueSize = 5;
+        mAlphaSize = 1;
+        break;
+      case D3DFMT_A2R10G10B10:
+        mBufferSize = 32;
+        mRedSize = 10;
+        mGreenSize = 10;
+        mBlueSize = 10;
+        mAlphaSize = 2;
+        break;
+      case D3DFMT_A8R8G8B8:
+        mBufferSize = 32;
+        mRedSize = 8;
+        mGreenSize = 8;
+        mBlueSize = 8;
+        mAlphaSize = 8;
+        break;
+      case D3DFMT_R5G6B5:
+        mBufferSize = 16;
+        mRedSize = 5;
+        mGreenSize = 6;
+        mBlueSize = 5;
+        mAlphaSize = 0;
+        break;
+      case D3DFMT_X1R5G5B5:
+        mBufferSize = 16;
+        mRedSize = 5;
+        mGreenSize = 5;
+        mBlueSize = 5;
+        mAlphaSize = 0;
+        break;
+      case D3DFMT_X8R8G8B8:
+        mBufferSize = 32;
+        mRedSize = 8;
+        mGreenSize = 8;
+        mBlueSize = 8;
+        mAlphaSize = 0;
+        break;
+      default:
+        UNREACHABLE();   // Other formats should not be valid
+    }
+
+    mLuminanceSize = 0;
+    mAlphaMaskSize = 0;
+    mBindToTextureRGB = EGL_FALSE;
+    mBindToTextureRGBA = EGL_FALSE;
+    mColorBufferType = EGL_RGB_BUFFER;
+    mConfigCaveat = (displayMode.Format == renderTargetFormat) ? EGL_NONE : EGL_SLOW_CONFIG;
+    mConfigID = 0;
+    mConformant = EGL_OPENGL_ES2_BIT;
+
+    switch (depthStencilFormat)
+    {
+//      case D3DFMT_D16_LOCKABLE:
+//        mDepthSize = 16;
+//        mStencilSize = 0;
+//        break;
+      case D3DFMT_D32:
+        mDepthSize = 32;
+        mStencilSize = 0;
+        break;
+      case D3DFMT_D15S1:
+        mDepthSize = 16;
+        mStencilSize = 1;
+        break;
+      case D3DFMT_D24S8:
+        mDepthSize = 24;
+        mStencilSize = 8;
+        break;
+      case D3DFMT_D24X8:
+        mDepthSize = 24;
+        mStencilSize = 0;
+        break;
+      case D3DFMT_D24X4S4:
+        mDepthSize = 24;
+        mStencilSize = 4;
+        break;
+      case D3DFMT_D16:
+        mDepthSize = 16;
+        mStencilSize = 0;
+        break;
+//    case D3DFMT_D32F_LOCKABLE:
+//        mDepthSize = 32;
+//        mStencilSize = 0;
+//        break;
+//    case D3DFMT_D24FS8:
+//        mDepthSize = 24;
+//        mStencilSize = 8;
+//        break;
+      default:
+        UNREACHABLE();
+    }
+
+    mLevel = 0;
+    mMatchNativePixmap = EGL_NONE;
+    mMaxPBufferWidth = 0;
+    mMaxPBufferHeight = 0;
+    mMaxPBufferPixels = 0;
+    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(D3DDISPLAYMODE displayMode, EGLint minSwapInterval, EGLint maxSwapInterval, D3DFORMAT renderTargetFormat, D3DFORMAT depthStencilFormat, EGLint multiSample)
+{
+    Config config(displayMode, minSwapInterval, maxSwapInterval, renderTargetFormat, depthStencilFormat, multiSample);
+
+    mSet.insert(config);
+}
+
+void ConfigSet::enumerate()
+{
+    EGLint index = 1;
+
+    for (Iterator config = mSet.begin(); config != mSet.end(); config++)
+    {
+        config->mConfigID = index;
+        index++;
+    }
+}
+
+size_t ConfigSet::size() const
+{
+    return mSet.size();
+}
+
+bool ConfigSet::getConfigs(EGLConfig *configs, const EGLint *attribList, EGLint configSize, EGLint *numConfig)
+{
+    if (configs)
+    {
+        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;
+                  default:
+                    return false;
+                }
+
+                if (!match)
+                {
+                    break;
+                }
+
+                attribute += 2;
+            }
+
+            if (match)
+            {
+                passed.push_back(&*config);
+            }
+        }
+
+        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 = (EGLint)mSet.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/libEGL/Display.cpp b/libEGL/Display.cpp
new file mode 100644
index 0000000..abdf257
--- /dev/null
+++ b/libEGL/Display.cpp
@@ -0,0 +1,338 @@
+//
+// 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.
+//
+
+// 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 "debug.h"
+
+#include <vector>
+
+namespace egl
+{
+Display::Display(HDC deviceContext) : mDc(deviceContext)
+{
+    mD3d9 = NULL;
+    mDevice = NULL;
+
+    mAdapter = D3DADAPTER_DEFAULT;
+    mDeviceType = D3DDEVTYPE_HAL;
+}
+
+Display::~Display()
+{
+    terminate();
+}
+
+bool Display::initialize()
+{
+    if (isInitialized())
+    {
+        return true;
+    }
+
+    mD3d9 = Direct3DCreate9(D3D_SDK_VERSION);
+
+    if (mD3d9)
+    {
+        if (mDc != NULL)
+        {
+        //    UNIMPLEMENTED();   // FIXME: Determine which adapter index the device context corresponds to
+        }
+
+        D3DCAPS9 caps;
+        HRESULT result = mD3d9->GetDeviceCaps(mAdapter, mDeviceType, &caps);
+
+        if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY)
+        {
+            return error(EGL_BAD_ALLOC, false);
+        }
+
+        if (caps.PixelShaderVersion < D3DPS_VERSION(2, 0) || caps.VertexShaderVersion < D3DVS_VERSION(2, 0))
+        {
+            mD3d9->Release();
+            mD3d9 = NULL;
+        }
+        else
+        {
+            EGLint minSwapInterval = 4;
+            EGLint maxSwapInterval = 0;
+
+            if (caps.PresentationIntervals & D3DPRESENT_INTERVAL_IMMEDIATE)    {minSwapInterval = min(minSwapInterval, 0); maxSwapInterval = max(maxSwapInterval, 0);}
+            if (caps.PresentationIntervals & D3DPRESENT_INTERVAL_ONE)        {minSwapInterval = min(minSwapInterval, 1); maxSwapInterval = max(maxSwapInterval, 1);}
+            if (caps.PresentationIntervals & D3DPRESENT_INTERVAL_TWO)        {minSwapInterval = min(minSwapInterval, 2); maxSwapInterval = max(maxSwapInterval, 2);}
+            if (caps.PresentationIntervals & D3DPRESENT_INTERVAL_THREE)        {minSwapInterval = min(minSwapInterval, 3); maxSwapInterval = max(maxSwapInterval, 3);}
+            if (caps.PresentationIntervals & D3DPRESENT_INTERVAL_FOUR)        {minSwapInterval = min(minSwapInterval, 4); maxSwapInterval = max(maxSwapInterval, 4);}
+
+            const D3DFORMAT adapterFormats[] =
+            {
+                D3DFMT_A1R5G5B5,
+                D3DFMT_A2R10G10B10,
+                D3DFMT_A8R8G8B8,
+                D3DFMT_R5G6B5,
+                D3DFMT_X1R5G5B5,
+                D3DFMT_X8R8G8B8
+            };
+
+            const D3DFORMAT depthStencilFormats[] =
+            {
+            //    D3DFMT_D16_LOCKABLE,
+                D3DFMT_D32,
+                D3DFMT_D15S1,
+                D3DFMT_D24S8,
+                D3DFMT_D24X8,
+                D3DFMT_D24X4S4,
+                D3DFMT_D16,
+            //    D3DFMT_D32F_LOCKABLE,
+            //    D3DFMT_D24FS8
+            };
+
+            D3DDISPLAYMODE currentDisplayMode;
+            mD3d9->GetAdapterDisplayMode(mAdapter, &currentDisplayMode);
+
+            for (int formatIndex = 0; formatIndex < sizeof(adapterFormats) / sizeof(D3DFORMAT); formatIndex++)
+            {
+                D3DFORMAT renderTargetFormat = adapterFormats[formatIndex];
+
+                HRESULT result = mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, D3DUSAGE_RENDERTARGET, D3DRTYPE_SURFACE, renderTargetFormat);
+
+                if (SUCCEEDED(result))
+                {
+                    for (int depthStencilIndex = 0; depthStencilIndex < sizeof(depthStencilFormats) / sizeof(D3DFORMAT); depthStencilIndex++)
+                    {
+                        D3DFORMAT depthStencilFormat = depthStencilFormats[depthStencilIndex];
+                        HRESULT result = mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, D3DUSAGE_DEPTHSTENCIL, D3DRTYPE_SURFACE, depthStencilFormat);
+
+                        if (SUCCEEDED(result))
+                        {
+                            HRESULT result = mD3d9->CheckDepthStencilMatch(mAdapter, mDeviceType, currentDisplayMode.Format, renderTargetFormat, depthStencilFormat);   // FIXME: Only accept color formats available both in fullscreen and windowed?
+                            
+                            if (SUCCEEDED(result))
+                            {
+                                // FIXME: Enumerate multi-sampling
+
+                                mConfigSet.add(currentDisplayMode, minSwapInterval, maxSwapInterval, renderTargetFormat, depthStencilFormat, 0);
+                            }
+                        }
+                    }
+                }
+            }
+        }
+
+        mConfigSet.enumerate();
+    }
+
+    if (!isInitialized())
+    {
+        terminate();
+
+        return false;
+    }
+
+    return true;
+}
+
+void Display::terminate()
+{
+    for (SurfaceSet::iterator surface = mSurfaceSet.begin(); surface != mSurfaceSet.end(); surface++)
+    {
+        delete *surface;
+    }
+
+    for (ContextSet::iterator context = mContextSet.begin(); context != mContextSet.end(); context++)
+    {
+        glDestroyContext(*context);
+    }
+
+    if (mDevice)
+    {
+        mDevice->Release();
+        mDevice = NULL;
+    }
+
+    if (mD3d9)
+    {
+        mD3d9->Release();
+        mD3d9 = 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;
+      default:
+        return false;
+    }
+
+    return true;
+}
+
+egl::Surface *Display::createWindowSurface(HWND window, EGLConfig config)
+{
+    const egl::Config *configuration = mConfigSet.get(config);
+
+    UINT adapter = D3DADAPTER_DEFAULT;
+    D3DDEVTYPE deviceType = D3DDEVTYPE_HAL;
+    D3DPRESENT_PARAMETERS presentParameters = {0};
+
+    presentParameters.AutoDepthStencilFormat = configuration->mDepthStencilFormat;
+    presentParameters.BackBufferCount = 1;
+    presentParameters.BackBufferFormat = configuration->mRenderTargetFormat;
+    presentParameters.BackBufferWidth = 0;
+    presentParameters.BackBufferHeight = 0;
+    presentParameters.EnableAutoDepthStencil = configuration->mDepthSize ? TRUE : FALSE;
+    presentParameters.Flags = 0;
+    presentParameters.hDeviceWindow = window;
+    presentParameters.MultiSampleQuality = 0;                  // FIXME: Unimplemented
+    presentParameters.MultiSampleType = D3DMULTISAMPLE_NONE;   // FIXME: Unimplemented
+    presentParameters.PresentationInterval = configuration->mMinSwapInterval;
+    presentParameters.SwapEffect = D3DSWAPEFFECT_COPY;
+    presentParameters.Windowed = TRUE;   // FIXME
+
+    IDirect3DSwapChain9 *swapChain = NULL;
+
+    if (!mDevice)
+    {
+        HRESULT result = mD3d9->CreateDevice(adapter, deviceType, window, D3DCREATE_FPU_PRESERVE | D3DCREATE_MIXED_VERTEXPROCESSING | D3DCREATE_NOWINDOWCHANGES, &presentParameters, &mDevice);
+
+        if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY)
+        {
+            return error(EGL_BAD_ALLOC, (egl::Surface*)NULL);
+        }
+
+        ASSERT(SUCCEEDED(result));
+
+        if (mDevice)
+        {
+            mDevice->GetSwapChain(0, &swapChain);
+        }
+    }
+    else
+    {
+        HRESULT result = mDevice->CreateAdditionalSwapChain(&presentParameters, &swapChain);
+
+        if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY)
+        {
+            return error(EGL_BAD_ALLOC, (egl::Surface*)NULL);
+        }
+
+        ASSERT(SUCCEEDED(result));
+    }
+
+    Surface *surface = NULL;
+
+    if (swapChain)
+    {
+        surface = new Surface(mDevice, swapChain, configuration->mConfigID);
+        mSurfaceSet.insert(surface);
+
+        swapChain->Release();
+    }
+        
+    return surface;
+}
+
+EGLContext Display::createContext(EGLConfig configHandle)
+{
+    const egl::Config *config = mConfigSet.get(configHandle);
+
+    gl::Context *context = glCreateContext(config);
+    mContextSet.insert(context);
+
+    return context;
+}
+
+void Display::destroySurface(egl::Surface *surface)
+{
+    delete surface;
+    mSurfaceSet.erase(surface);
+}
+
+void Display::destroyContext(gl::Context *context)
+{
+    glDestroyContext(context);
+    mContextSet.erase(context);
+}
+
+bool Display::isInitialized()
+{
+    return mD3d9 != NULL && 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::hasExistingWindowSurface(HWND window)
+{
+    for (SurfaceSet::iterator surface = mSurfaceSet.begin(); surface != mSurfaceSet.end(); surface++)
+    {
+        if ((*surface)->getWindowHandle() == window)
+        {
+            return true;
+        }
+    }
+
+    return false;
+}
+
+IDirect3DDevice9 *Display::getDevice()
+{
+    return mDevice;
+}
+}
diff --git a/libEGL/Surface.cpp b/libEGL/Surface.cpp
new file mode 100644
index 0000000..0bfbad9
--- /dev/null
+++ b/libEGL/Surface.cpp
@@ -0,0 +1,174 @@
+//
+// 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.
+//
+
+// 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 "debug.h"
+
+namespace egl
+{
+Surface::Surface(IDirect3DDevice9 *device, IDirect3DSwapChain9 *swapChain, EGLint configID) : mSwapChain(swapChain), mConfigID(configID)
+{
+    mBackBuffer = NULL;
+    mRenderTarget = NULL;
+
+    mPixelAspectRatio = (EGLint)(1.0 * EGL_DISPLAY_SCALING);   // FIXME: Determine actual pixel aspect ratio
+    mRenderBuffer = EGL_BACK_BUFFER;
+    mSwapBehavior = EGL_BUFFER_PRESERVED;
+
+    if (mSwapChain)
+    {
+        mSwapChain->AddRef();
+        mSwapChain->GetBackBuffer(0, D3DBACKBUFFER_TYPE_MONO, &mBackBuffer);
+
+        D3DSURFACE_DESC description;
+        mBackBuffer->GetDesc(&description);
+
+        mWidth = description.Width;
+        mHeight = description.Height;
+
+        HRESULT result = device->CreateRenderTarget(mWidth, mHeight, description.Format, description.MultiSampleType, description.MultiSampleQuality, FALSE, &mRenderTarget, NULL);
+
+        if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY)
+        {
+            error(EGL_BAD_ALLOC);
+
+            return;
+        }
+
+        ASSERT(SUCCEEDED(result));
+    }
+}
+
+Surface::~Surface()
+{
+    if (mSwapChain)
+    {
+        mSwapChain->Release();
+    }
+
+    if (mBackBuffer)
+    {
+        mBackBuffer->Release();
+    }
+
+    if (mRenderTarget)
+    {
+        mRenderTarget->Release();
+    }
+}
+
+HWND Surface::getWindowHandle()
+{
+    if (mSwapChain)
+    {
+        D3DPRESENT_PARAMETERS presentParameters;
+        mSwapChain->GetPresentParameters(&presentParameters);
+
+        return presentParameters.hDeviceWindow;
+    }
+
+    return NULL;
+}
+
+void Surface::swap()
+{
+    if (mSwapChain)
+    {
+        IDirect3DDevice9 *device;
+        mSwapChain->GetDevice(&device);
+
+        D3DSURFACE_DESC description;
+        mBackBuffer->GetDesc(&description);
+
+        // Copy the render target into a texture
+        IDirect3DTexture9 *texture;
+        HRESULT result = device->CreateTexture(mWidth, mHeight, 1, D3DUSAGE_RENDERTARGET, description.Format, D3DPOOL_DEFAULT, &texture, NULL);
+
+        if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY)
+        {
+            return error(EGL_BAD_ALLOC);
+        }
+
+        ASSERT(SUCCEEDED(result));
+        
+        IDirect3DSurface9 *textureSurface;
+        texture->GetSurfaceLevel(0, &textureSurface);
+
+        device->StretchRect(mRenderTarget, NULL, textureSurface, NULL, D3DTEXF_POINT);
+        
+        // Disable all pipeline operations
+        device->SetRenderState(D3DRS_ZENABLE, D3DZB_FALSE);
+        device->SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID);
+        device->SetRenderState(D3DRS_ALPHATESTENABLE , FALSE);
+        device->SetRenderState(D3DRS_ALPHABLENDENABLE , FALSE);
+        device->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
+        device->SetRenderState(D3DRS_STENCILENABLE, FALSE);
+        device->SetRenderState(D3DRS_CLIPPLANEENABLE, 0);
+        device->SetRenderState(D3DRS_COLORWRITEENABLE, D3DCOLORWRITEENABLE_ALPHA | D3DCOLORWRITEENABLE_BLUE | D3DCOLORWRITEENABLE_GREEN | D3DCOLORWRITEENABLE_RED);
+        device->SetRenderState(D3DRS_SRGBWRITEENABLE, FALSE);
+        device->SetPixelShader(NULL);
+        device->SetVertexShader(NULL);
+
+        // Just sample the texture
+        device->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
+        device->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
+        device->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE);
+        device->SetTexture(0, texture);
+        device->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_POINT);
+        device->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_POINT);
+        device->SetSamplerState(0, D3DSAMP_SRGBTEXTURE, FALSE);
+        device->SetFVF(D3DFVF_XYZRHW | D3DFVF_TEX1);
+        device->SetRenderTarget(0, mBackBuffer);
+
+        // Render the texture upside down into the back buffer
+        float quad[4][6] = {{     0 - 0.5f,       0 - 0.5f, 0.0f, 1.0f, 0.0f, 1.0f},
+                            {mWidth - 0.5f,       0 - 0.5f, 0.0f, 1.0f, 1.0f, 1.0f},
+                            {mWidth - 0.5f, mHeight - 0.5f, 0.0f, 1.0f, 1.0f, 0.0f},
+                            {     0 - 0.5f, mHeight - 0.5f, 0.0f, 1.0f, 0.0f, 0.0f}};   // x, y, z, rhw, u, v
+
+        device->BeginScene();
+        device->DrawPrimitiveUP(D3DPT_TRIANGLEFAN, 2, quad, 6 * sizeof(float));
+        device->EndScene();
+
+        result = mSwapChain->Present(NULL, NULL, NULL, NULL, D3DPRESENT_INTERVAL_DEFAULT);   // FIXME: Get the swap interval from the associated Display
+
+        if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY || result == D3DERR_DRIVERINTERNALERROR)
+        {
+            return error(EGL_BAD_ALLOC);
+        }
+        
+        textureSurface->Release();
+        texture->Release();
+        device->Release();
+    }
+}
+
+EGLint Surface::getWidth() const
+{
+    return mWidth;
+}
+
+EGLint Surface::getHeight() const
+{
+    return mHeight;
+}
+
+IDirect3DSurface9 *Surface::getRenderTarget()
+{
+    if (mRenderTarget)
+    {
+        mRenderTarget->AddRef();
+    }
+
+    return mRenderTarget;
+}
+}
diff --git a/libEGL/libEGL.cpp b/libEGL/libEGL.cpp
new file mode 100644
index 0000000..8f52e21
--- /dev/null
+++ b/libEGL/libEGL.cpp
@@ -0,0 +1,1026 @@
+//
+// 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.
+//
+
+// libEGL.cpp: Implements the exported EGL functions.
+
+#include "main.h"
+#include "Display.h"
+#include "Context.h"
+#include "debug.h"
+
+#include <exception>
+
+bool validate(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;
+}
+
+bool validate(egl::Display *display, EGLConfig config)
+{
+    if (!validate(display))
+    {
+        return false;
+    }
+
+    if (!display->isValidConfig(config))
+    {
+        return error(EGL_BAD_CONFIG, false);
+    }
+
+    return true;
+}
+
+bool validate(egl::Display *display, gl::Context *context)
+{
+    if (!validate(display))
+    {
+        return false;
+    }
+
+    if (!display->isValidContext(context))
+    {
+        return error(EGL_BAD_CONTEXT, false);
+    }
+
+    return true;
+}
+
+bool validate(egl::Display *display, egl::Surface *surface)
+{
+    if (!validate(display))
+    {
+        return false;
+    }
+
+    if (!display->isValidSurface(surface))
+    {
+        return error(EGL_BAD_SURFACE, false);
+    }
+
+    return true;
+}
+
+extern "C"
+{
+EGLint __stdcall eglGetError(void)
+{
+    TRACE("");
+
+    EGLint error = egl::getCurrentError();
+
+    if (error != EGL_SUCCESS)
+    {
+        egl::setCurrentError(EGL_SUCCESS);
+    }
+
+    return error;
+}
+
+EGLDisplay __stdcall eglGetDisplay(EGLNativeDisplayType display_id)
+{
+    TRACE("EGLNativeDisplayType display_id = 0x%0.8p", display_id);
+
+    try
+    {
+        // FIXME: Return the same EGLDisplay handle when display_id already created a display
+
+        if (display_id == EGL_DEFAULT_DISPLAY)
+        {
+            return new egl::Display((HDC)NULL);
+        }
+        else
+        {
+            // FIXME: Check if display_id is a valid display device context
+
+            return new egl::Display((HDC)display_id);
+        }
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(EGL_BAD_ALLOC, EGL_NO_DISPLAY);
+    }
+
+    return EGL_NO_DISPLAY;
+}
+
+EGLBoolean __stdcall 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);
+        }
+
+        *major = 1;
+        *minor = 4;
+
+        return success(EGL_TRUE);
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(EGL_BAD_ALLOC, EGL_FALSE);
+    }
+
+    return EGL_FALSE;
+}
+
+EGLBoolean __stdcall 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 *__stdcall 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 (!validate(display))
+        {
+            return NULL;
+        }
+
+        switch (name)
+        {
+          case EGL_CLIENT_APIS:
+            return success("OpenGL_ES");
+          case EGL_EXTENSIONS:
+            return success("");
+          case EGL_VENDOR:
+            return success("TransGaming Inc.");
+          case EGL_VERSION:
+            return success("1.4 (git-devel "__DATE__" " __TIME__")");
+        }
+
+        return error(EGL_BAD_PARAMETER, (const char*)NULL);
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(EGL_BAD_ALLOC, (const char*)NULL);
+    }
+
+    return NULL;
+}
+
+EGLBoolean __stdcall 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 (!validate(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 __stdcall 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 (!validate(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 __stdcall 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 (!validate(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 __stdcall eglCreateWindowSurface(EGLDisplay dpy, EGLConfig config, EGLNativeWindowType win, 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, win, attrib_list);
+
+    try
+    {
+        egl::Display *display = static_cast<egl::Display*>(dpy);
+
+        if (!validate(display, config))
+        {
+            return EGL_NO_SURFACE;
+        }
+
+        HWND window = (HWND)win;
+
+        if (!IsWindow(window))
+        {
+            return error(EGL_BAD_NATIVE_WINDOW, EGL_NO_SURFACE);
+        }
+
+        if (attrib_list)
+        {
+            while (*attrib_list != EGL_NONE)
+            {
+                switch (attrib_list[0])
+                {
+                  case EGL_RENDER_BUFFER:
+                    switch (attrib_list[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);
+                }
+            }
+        }
+
+        if (display->hasExistingWindowSurface(window))
+        {
+            return error(EGL_BAD_ALLOC, EGL_NO_SURFACE);
+        }
+
+        EGLSurface surface = (EGLSurface)display->createWindowSurface(window, config);
+
+        return success(surface);
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(EGL_BAD_ALLOC, EGL_NO_SURFACE);
+    }
+
+    return EGL_NO_SURFACE;
+}
+
+EGLSurface __stdcall 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 (!validate(display, config))
+        {
+            return EGL_NO_SURFACE;
+        }
+
+        UNIMPLEMENTED();   // FIXME
+
+        return success(EGL_NO_DISPLAY);
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(EGL_BAD_ALLOC, EGL_NO_SURFACE);
+    }
+
+    return EGL_NO_SURFACE;
+}
+
+EGLSurface __stdcall 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 (!validate(display, config))
+        {
+            return EGL_NO_SURFACE;
+        }
+
+        UNIMPLEMENTED();   // FIXME
+
+        return success(EGL_NO_DISPLAY);
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(EGL_BAD_ALLOC, EGL_NO_SURFACE);
+    }
+
+    return EGL_NO_SURFACE;
+}
+
+EGLBoolean __stdcall 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);
+
+        if (!validate(display))
+        {
+            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 __stdcall 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);
+
+        if (!validate(display))
+        {
+            return EGL_FALSE;
+        }
+
+        if (surface == EGL_NO_SURFACE)
+        {
+            return error(EGL_BAD_SURFACE, EGL_FALSE);
+        }
+
+        egl::Surface *eglSurface = (egl::Surface*)surface;
+
+        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 __stdcall 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 __stdcall 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 __stdcall eglWaitClient(void)
+{
+    TRACE("");
+
+    try
+    {
+        UNIMPLEMENTED();   // FIXME
+
+        return success(0);
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(EGL_BAD_ALLOC, EGL_FALSE);
+    }
+
+    return EGL_FALSE;
+}
+
+EGLBoolean __stdcall 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 __stdcall 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);
+
+    try
+    {
+        egl::Display *display = static_cast<egl::Display*>(dpy);
+
+        if (!validate(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 __stdcall 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);
+
+        if (!validate(display))
+        {
+            return EGL_FALSE;
+        }
+
+        UNIMPLEMENTED();   // FIXME
+
+        return success(EGL_TRUE);
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(EGL_BAD_ALLOC, EGL_FALSE);
+    }
+
+    return EGL_FALSE;
+}
+
+EGLBoolean __stdcall 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);
+
+        if (!validate(display))
+        {
+            return EGL_FALSE;
+        }
+
+        UNIMPLEMENTED();   // FIXME
+
+        return success(EGL_TRUE);
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(EGL_BAD_ALLOC, EGL_FALSE);
+    }
+
+    return EGL_FALSE;
+}
+
+EGLBoolean __stdcall 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);
+
+        if(!validate(display))
+        {
+            return EGL_FALSE;
+        }
+
+        UNIMPLEMENTED();   // FIXME
+
+        return success(EGL_TRUE);
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(EGL_BAD_ALLOC, EGL_FALSE);
+    }
+
+    return EGL_FALSE;
+}
+
+EGLBoolean __stdcall 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(!validate(display))
+        {
+            return EGL_FALSE;
+        }
+
+    //    UNIMPLEMENTED();   // FIXME
+
+        return success(EGL_TRUE);
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(EGL_BAD_ALLOC, EGL_FALSE);
+    }
+
+    return EGL_FALSE;
+}
+
+EGLContext __stdcall 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
+    {
+        egl::Display *display = static_cast<egl::Display*>(dpy);
+
+        if (!validate(display, config))
+        {
+            return EGL_NO_CONTEXT;
+        }
+
+        EGLContext context = display->createContext(config);
+
+        return success(context);
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(EGL_BAD_ALLOC, EGL_NO_CONTEXT);
+    }
+
+    return EGL_NO_CONTEXT;
+}
+
+EGLBoolean __stdcall 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);
+
+        if (!validate(display))
+        {
+            return EGL_FALSE;
+        }
+
+        if (ctx == EGL_NO_CONTEXT)
+        {
+            return error(EGL_BAD_CONTEXT, EGL_FALSE);
+        }
+
+        display->destroyContext((gl::Context*)ctx);
+
+        return success(EGL_TRUE);
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(EGL_BAD_ALLOC, EGL_FALSE);
+    }
+
+    return EGL_FALSE;
+}
+
+EGLBoolean __stdcall 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);
+
+        if (ctx != EGL_NO_CONTEXT && !validate(display, context))
+        {
+            return EGL_FALSE;
+        }
+
+        if ((draw != EGL_NO_SURFACE && !validate(display, static_cast<egl::Surface*>(draw))) ||
+            (read != EGL_NO_SURFACE && !validate(display, static_cast<egl::Surface*>(read))))
+        {
+            return EGL_FALSE;
+        }
+
+        if (draw != read)
+        {
+            UNIMPLEMENTED();   // FIXME
+        }
+
+        glMakeCurrent(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 __stdcall eglGetCurrentContext(void)
+{
+    TRACE("");
+
+    try
+    {
+        EGLContext context = glGetCurrentContext();
+
+        return success(context);
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(EGL_BAD_ALLOC, EGL_NO_CONTEXT);
+    }
+
+    return EGL_NO_CONTEXT;
+}
+
+EGLSurface __stdcall eglGetCurrentSurface(EGLint readdraw)
+{
+    TRACE("EGLint readdraw = %d", readdraw);
+
+    try
+    {
+        UNIMPLEMENTED();   // FIXME
+
+        return success(EGL_NO_SURFACE);
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(EGL_BAD_ALLOC, EGL_NO_SURFACE);
+    }
+
+    return EGL_NO_SURFACE;
+}
+
+EGLDisplay __stdcall eglGetCurrentDisplay(void)
+{
+    TRACE("");
+
+    try
+    {
+        UNIMPLEMENTED();   // FIXME
+
+        return success(EGL_NO_DISPLAY);
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(EGL_BAD_ALLOC, EGL_NO_DISPLAY);
+    }
+
+    return EGL_NO_DISPLAY;
+}
+
+EGLBoolean __stdcall 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);
+
+        if (!validate(display))
+        {
+            return EGL_FALSE;
+        }
+
+        UNIMPLEMENTED();   // FIXME
+
+        return success(0);
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(EGL_BAD_ALLOC, EGL_FALSE);
+    }
+
+    return EGL_FALSE;
+}
+
+EGLBoolean __stdcall eglWaitGL(void)
+{
+    TRACE("");
+
+    try
+    {
+        UNIMPLEMENTED();   // FIXME
+
+        return success(0);
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(EGL_BAD_ALLOC, EGL_FALSE);
+    }
+
+    return EGL_FALSE;
+}
+
+EGLBoolean __stdcall 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 __stdcall 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);
+
+        if (!validate(display))
+        {
+            return EGL_FALSE;
+        }
+
+        if (surface == EGL_NO_SURFACE)
+        {
+            return error(EGL_BAD_SURFACE, EGL_FALSE);
+        }
+
+        egl::Surface *eglSurface = (egl::Surface*)surface;
+        eglSurface->swap();
+
+        return success(EGL_TRUE);
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(EGL_BAD_ALLOC, EGL_FALSE);
+    }
+
+    return EGL_FALSE;
+}
+
+EGLBoolean __stdcall 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);
+
+        if (!validate(display))
+        {
+            return EGL_FALSE;
+        }
+
+        UNIMPLEMENTED();   // FIXME
+
+        return success(0);
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(EGL_BAD_ALLOC, EGL_FALSE);
+    }
+
+    return EGL_FALSE;
+}
+
+__eglMustCastToProperFunctionPointerType __stdcall eglGetProcAddress(const char *procname)
+{
+    TRACE("const char *procname = \"%s\"", procname);
+
+    try
+    {
+        UNIMPLEMENTED();   // FIXME
+
+        return NULL;
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(EGL_BAD_ALLOC, (__eglMustCastToProperFunctionPointerType)NULL);
+    }
+
+    return NULL;
+}
+}
diff --git a/libEGL/libEGL.def b/libEGL/libEGL.def
new file mode 100644
index 0000000..71a5e67
--- /dev/null
+++ b/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/libEGL/libEGL.vcproj b/libEGL/libEGL.vcproj
new file mode 100644
index 0000000..78634f5
--- /dev/null
+++ b/libEGL/libEGL.vcproj
@@ -0,0 +1,266 @@
+<?xml version="1.0" encoding="Windows-1252"?>

+<VisualStudioProject

+	ProjectType="Visual C++"

+	Version="9.00"

+	Name="libEGL"

+	ProjectGUID="{E746FCA9-64C3-433E-85E8-9A5A67AB7ED6}"

+	RootNamespace="libEGL"

+	Keyword="Win32Proj"

+	TargetFrameworkVersion="131072"

+	>

+	<Platforms>

+		<Platform

+			Name="Win32"

+		/>

+	</Platforms>

+	<ToolFiles>

+	</ToolFiles>

+	<Configurations>

+		<Configuration

+			Name="Debug|Win32"

+			OutputDirectory="$(SolutionDir)$(ConfigurationName)"

+			IntermediateDirectory="$(ConfigurationName)"

+			ConfigurationType="2"

+			CharacterSet="1"

+			>

+			<Tool

+				Name="VCPreBuildEventTool"

+			/>

+			<Tool

+				Name="VCCustomBuildTool"

+			/>

+			<Tool

+				Name="VCXMLDataGeneratorTool"

+			/>

+			<Tool

+				Name="VCWebServiceProxyGeneratorTool"

+			/>

+			<Tool

+				Name="VCMIDLTool"

+			/>

+			<Tool

+				Name="VCCLCompilerTool"

+				Optimization="0"

+				AdditionalIncludeDirectories="../Include/"

+				PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;LIBEGL_EXPORTS;_CRT_SECURE_NO_DEPRECATE"

+				MinimalRebuild="true"

+				BasicRuntimeChecks="3"

+				RuntimeLibrary="1"

+				UsePrecompiledHeader="0"

+				WarningLevel="3"

+				Detect64BitPortabilityProblems="false"

+				DebugInformationFormat="4"

+			/>

+			<Tool

+				Name="VCManagedResourceCompilerTool"

+			/>

+			<Tool

+				Name="VCResourceCompilerTool"

+			/>

+			<Tool

+				Name="VCPreLinkEventTool"

+			/>

+			<Tool

+				Name="VCLinkerTool"

+				AdditionalDependencies="d3d9.lib"

+				LinkIncremental="2"

+				ModuleDefinitionFile="libEGL.def"

+				GenerateDebugInformation="true"

+				SubSystem="2"

+				RandomizedBaseAddress="1"

+				DataExecutionPrevention="0"

+				TargetMachine="1"

+			/>

+			<Tool

+				Name="VCALinkTool"

+			/>

+			<Tool

+				Name="VCManifestTool"

+			/>

+			<Tool

+				Name="VCXDCMakeTool"

+			/>

+			<Tool

+				Name="VCBscMakeTool"

+			/>

+			<Tool

+				Name="VCFxCopTool"

+			/>

+			<Tool

+				Name="VCAppVerifierTool"

+			/>

+			<Tool

+				Name="VCPostBuildEventTool"

+			/>

+		</Configuration>

+		<Configuration

+			Name="Release|Win32"

+			OutputDirectory="$(SolutionDir)$(ConfigurationName)"

+			IntermediateDirectory="$(ConfigurationName)"

+			ConfigurationType="2"

+			CharacterSet="1"

+			WholeProgramOptimization="1"

+			>

+			<Tool

+				Name="VCPreBuildEventTool"

+			/>

+			<Tool

+				Name="VCCustomBuildTool"

+			/>

+			<Tool

+				Name="VCXMLDataGeneratorTool"

+			/>

+			<Tool

+				Name="VCWebServiceProxyGeneratorTool"

+			/>

+			<Tool

+				Name="VCMIDLTool"

+			/>

+			<Tool

+				Name="VCCLCompilerTool"

+				AdditionalIncludeDirectories="../Include/"

+				PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;LIBEGL_EXPORTS;_CRT_SECURE_NO_DEPRECATE"

+				RuntimeLibrary="0"

+				UsePrecompiledHeader="0"

+				WarningLevel="3"

+				Detect64BitPortabilityProblems="false"

+				DebugInformationFormat="3"

+			/>

+			<Tool

+				Name="VCManagedResourceCompilerTool"

+			/>

+			<Tool

+				Name="VCResourceCompilerTool"

+			/>

+			<Tool

+				Name="VCPreLinkEventTool"

+			/>

+			<Tool

+				Name="VCLinkerTool"

+				AdditionalDependencies="d3d9.lib"

+				LinkIncremental="1"

+				ModuleDefinitionFile="libEGL.def"

+				GenerateDebugInformation="true"

+				SubSystem="2"

+				OptimizeReferences="2"

+				EnableCOMDATFolding="2"

+				RandomizedBaseAddress="1"

+				DataExecutionPrevention="0"

+				TargetMachine="1"

+			/>

+			<Tool

+				Name="VCALinkTool"

+			/>

+			<Tool

+				Name="VCManifestTool"

+			/>

+			<Tool

+				Name="VCXDCMakeTool"

+			/>

+			<Tool

+				Name="VCBscMakeTool"

+			/>

+			<Tool

+				Name="VCFxCopTool"

+			/>

+			<Tool

+				Name="VCAppVerifierTool"

+			/>

+			<Tool

+				Name="VCPostBuildEventTool"

+			/>

+		</Configuration>

+	</Configurations>

+	<References>

+	</References>

+	<Files>

+		<Filter

+			Name="Source Files"

+			Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"

+			UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"

+			>

+			<File

+				RelativePath=".\Config.cpp"

+				>

+			</File>

+			<File

+				RelativePath="..\Common\debug.cpp"

+				>

+			</File>

+			<File

+				RelativePath=".\Display.cpp"

+				>

+			</File>

+			<File

+				RelativePath=".\libEGL.cpp"

+				>

+			</File>

+			<File

+				RelativePath=".\main.cpp"

+				>

+			</File>

+			<File

+				RelativePath=".\Surface.cpp"

+				>

+			</File>

+		</Filter>

+		<Filter

+			Name="Header Files"

+			Filter="h;hpp;hxx;hm;inl;inc;xsd"

+			UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"

+			>

+			<File

+				RelativePath="..\Include\Config.h"

+				>

+			</File>

+			<File

+				RelativePath="..\Include\Context.h"

+				>

+			</File>

+			<File

+				RelativePath="..\Include\debug.h"

+				>

+			</File>

+			<File

+				RelativePath="..\Include\Display.h"

+				>

+			</File>

+			<File

+				RelativePath="..\Include\EGL\egl.h"

+				>

+			</File>

+			<File

+				RelativePath="..\Include\EGL\eglext.h"

+				>

+			</File>

+			<File

+				RelativePath="..\Include\EGL\eglplatform.h"

+				>

+			</File>

+			<File

+				RelativePath="..\Include\gateutils.h"

+				>

+			</File>

+			<File

+				RelativePath=".\main.h"

+				>

+			</File>

+			<File

+				RelativePath="..\Include\Surface.h"

+				>

+			</File>

+		</Filter>

+		<Filter

+			Name="Resource Files"

+			Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav"

+			UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"

+			>

+		</Filter>

+		<File

+			RelativePath=".\libEGL.def"

+			>

+		</File>

+	</Files>

+	<Globals>

+	</Globals>

+</VisualStudioProject>

diff --git a/libEGL/main.cpp b/libEGL/main.cpp
new file mode 100644
index 0000000..449892f
--- /dev/null
+++ b/libEGL/main.cpp
@@ -0,0 +1,116 @@
+//
+// 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.
+//
+
+// main.cpp: DLL entry point and management of thread-local data.
+
+#include "main.h"
+
+#include "debug.h"
+
+static DWORD currentTLS = TLS_OUT_OF_INDEXES;
+
+BOOL WINAPI DllMain(HINSTANCE instance, DWORD reason, LPVOID reserved)
+{
+    switch (reason)
+    {
+      case DLL_PROCESS_ATTACH:
+        {
+            #ifndef NDEBUG
+                FILE *debug = fopen("debug.txt", "rt");
+
+                if (debug)
+                {
+                    fclose(debug);
+                    debug = fopen("debug.txt", "wt");   // Erase
+                    fclose(debug);
+                }
+            #endif
+
+            currentTLS = TlsAlloc();
+
+            if (currentTLS == TLS_OUT_OF_INDEXES)
+            {
+                return FALSE;
+            }
+        }
+        // Fall throught to initialize index
+      case DLL_THREAD_ATTACH:
+        {
+            egl::Current *current = (egl::Current*)LocalAlloc(LPTR, sizeof(egl::Current)); 
+            
+            if (current)
+            {
+                TlsSetValue(currentTLS, current);
+                
+                current->error = EGL_SUCCESS;
+                current->API = EGL_OPENGL_ES_API;
+            }
+        }
+        break; 
+      case DLL_THREAD_DETACH:
+        {
+            void *current = TlsGetValue(currentTLS);
+        
+            if (current)
+            {
+                LocalFree((HLOCAL)current);
+            }
+        }
+        break; 
+      case DLL_PROCESS_DETACH:
+        {
+            void *current = TlsGetValue(currentTLS);
+            
+            if (current)
+            {
+                LocalFree((HLOCAL)current);
+            }
+ 
+            TlsFree(currentTLS);
+        }
+        break; 
+      default: 
+        break; 
+    } 
+ 
+    return TRUE;
+}
+
+namespace egl
+{
+void setCurrentError(EGLint error)
+{
+    Current *current = (Current*)TlsGetValue(currentTLS);
+
+    current->error = error;
+}
+
+EGLint getCurrentError()
+{
+    Current *current = (Current*)TlsGetValue(currentTLS);
+
+    return current->error;
+}
+
+void setCurrentAPI(EGLenum API)
+{
+    Current *current = (Current*)TlsGetValue(currentTLS);
+
+    current->API = API;
+}
+
+EGLenum getCurrentAPI()
+{
+    Current *current = (Current*)TlsGetValue(currentTLS);
+
+    return current->API;
+}
+}
+
+void error(EGLint errorCode)
+{
+    egl::setCurrentError(errorCode);
+}
diff --git a/libEGL/main.h b/libEGL/main.h
new file mode 100644
index 0000000..77a2857
--- /dev/null
+++ b/libEGL/main.h
@@ -0,0 +1,48 @@
+//
+// 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.
+//
+
+// main.h: Management of thread-local data.
+
+#ifndef LIBEGL_MAIN_H_
+#define LIBEGL_MAIN_H_
+
+#define EGLAPI
+#include <EGL/egl.h>
+
+namespace egl
+{
+struct Current
+{
+    EGLint error;
+    EGLenum API;
+};
+
+void setCurrentError(EGLint error);
+EGLint getCurrentError();
+
+void setCurrentAPI(EGLenum API);
+EGLenum getCurrentAPI();
+}
+
+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;
+}
+
+#endif  // LIBEGL_MAIN_H_
diff --git a/libGLESv2/Buffer.cpp b/libGLESv2/Buffer.cpp
new file mode 100644
index 0000000..f439229
--- /dev/null
+++ b/libGLESv2/Buffer.cpp
@@ -0,0 +1,120 @@
+//
+// 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.
+//
+
+// Buffer.cpp: Implements the gl::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"
+
+namespace gl
+{
+Buffer::Buffer()
+{
+    mSize = 0;
+    mData = NULL;
+
+    mVertexBuffer = NULL;
+    mIndexBuffer = NULL;
+}
+
+Buffer::~Buffer()
+{
+    erase();
+}
+
+void Buffer::storeData(GLsizeiptr size, const void *data)
+{
+    erase();
+
+    mSize = size;
+    mData = new unsigned char[size];
+
+    if (data)
+    {
+        memcpy(mData, data, size);
+    }
+}
+
+IDirect3DVertexBuffer9 *Buffer::getVertexBuffer()
+{
+    if (!mVertexBuffer)
+    {
+        IDirect3DDevice9 *device = getDevice();
+
+        HRESULT result = device->CreateVertexBuffer(mSize, 0, 0, D3DPOOL_MANAGED, &mVertexBuffer, NULL);
+
+        if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY)
+        {
+            return error(GL_OUT_OF_MEMORY, (IDirect3DVertexBuffer9*)NULL);
+        }
+
+        ASSERT(SUCCEEDED(result));
+
+        if (mVertexBuffer && mData)
+        {
+            void *dataStore;
+            mVertexBuffer->Lock(0, mSize, &dataStore, 0);
+            memcpy(dataStore, mData, mSize);
+            mVertexBuffer->Unlock();
+        }
+    }
+
+    return mVertexBuffer;
+}
+
+IDirect3DIndexBuffer9 *Buffer::getIndexBuffer()
+{
+    if (!mIndexBuffer)
+    {
+        IDirect3DDevice9 *device = getDevice();
+
+        HRESULT result = device->CreateIndexBuffer(mSize, 0, D3DFMT_INDEX16, D3DPOOL_MANAGED, &mIndexBuffer, NULL);
+
+        if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY)
+        {
+            return error(GL_OUT_OF_MEMORY, (IDirect3DIndexBuffer9*)NULL);
+        }
+
+        ASSERT(SUCCEEDED(result));
+
+        if (mIndexBuffer && mData)
+        {
+            void *dataStore;
+            mIndexBuffer->Lock(0, mSize, &dataStore, 0);
+            memcpy(dataStore, mData, mSize);
+            mIndexBuffer->Unlock();
+        }
+    }
+
+    return mIndexBuffer;
+}
+
+void Buffer::erase()
+{
+    mSize = 0;
+
+    if (mData)
+    {
+        delete[] mData;
+        mData = NULL;
+    }
+
+    if (mVertexBuffer)
+    {
+        mVertexBuffer->Release();
+        mVertexBuffer = NULL;
+    }
+
+    if (mIndexBuffer)
+    {
+        mIndexBuffer->Release();
+        mIndexBuffer = NULL;
+    }
+}
+}
diff --git a/libGLESv2/Buffer.h b/libGLESv2/Buffer.h
new file mode 100644
index 0000000..44ae5ad
--- /dev/null
+++ b/libGLESv2/Buffer.h
@@ -0,0 +1,47 @@
+//
+// 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.
+//
+
+// Buffer.h: Defines the gl::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_
+
+#define GL_APICALL
+#include <GLES2/gl2.h>
+#include <d3d9.h>
+
+#include "angleutils.h"
+
+namespace gl
+{
+class Buffer
+{
+  public:
+    Buffer();
+
+    ~Buffer();
+
+    void storeData(GLsizeiptr size, const void *data);
+    
+    IDirect3DVertexBuffer9 *getVertexBuffer();
+    IDirect3DIndexBuffer9 *getIndexBuffer();
+
+  private:
+    DISALLOW_COPY_AND_ASSIGN(Buffer);
+
+    void erase();
+
+    unsigned int mSize;
+    void *mData;
+
+    IDirect3DVertexBuffer9 *mVertexBuffer;
+    IDirect3DIndexBuffer9 *mIndexBuffer;
+};
+}
+
+#endif   // LIBGLESV2_BUFFER_H_
diff --git a/libGLESv2/Context.cpp b/libGLESv2/Context.cpp
new file mode 100644
index 0000000..2c6944c
--- /dev/null
+++ b/libGLESv2/Context.cpp
@@ -0,0 +1,1819 @@
+//
+// 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.
+//
+
+// 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 "Display.h"
+#include "Buffer.h"
+#include "Shader.h"
+#include "Program.h"
+#include "Texture.h"
+#include "FrameBuffer.h"
+#include "RenderBuffer.h"
+#include "mathutil.h"
+#include "utilities.h"
+
+namespace gl
+{
+Array::Array()
+{
+    enabled = false;
+    boundBuffer = 0;
+    size = 4;
+    type = GL_FLOAT;
+    normalized = GL_FALSE;
+    stride = 0;
+    pointer = NULL;
+}
+
+Context::Context(const egl::Config *config) : mConfig(config)
+{
+    setClearColor(0.0f, 0.0f, 0.0f, 0.0f);
+    depthClearValue = 1.0f;
+    stencilClearValue = 0;
+
+    cullFace = false;
+    cullMode = GL_BACK;
+    frontFace = GL_CCW;
+    depthTest = false;
+    depthFunc = GL_LESS;
+    blend = false;
+    sourceBlendRGB = GL_ONE;
+    sourceBlendAlpha = GL_ONE;
+    destBlendRGB = GL_ZERO;
+    destBlendAlpha = GL_ZERO;
+    blendEquationRGB = GL_FUNC_ADD;
+    blendEquationAlpha = GL_FUNC_ADD;
+    blendColor.red = 0;
+    blendColor.green = 0;
+    blendColor.blue = 0;
+    blendColor.alpha = 0;
+    stencilTest = false;
+    stencilFunc = GL_ALWAYS;
+    stencilRef = 0;
+    stencilMask = -1;
+    stencilWritemask = -1;
+    stencilBackFunc = GL_ALWAYS;
+    stencilBackRef = 0;
+    stencilBackMask = - 1;
+    stencilBackWritemask = -1;
+    stencilFail = GL_KEEP;
+    stencilPassDepthFail = GL_KEEP;
+    stencilPassDepthPass = GL_KEEP;
+    stencilBackFail = GL_KEEP;
+    stencilBackPassDepthFail = GL_KEEP;
+    stencilBackPassDepthPass = GL_KEEP;
+    polygonOffsetFill = false;
+    sampleAlphaToCoverage = false;
+    sampleCoverage = false;
+    sampleCoverageValue = 1.0f;
+    sampleCoverageInvert = GL_FALSE;
+    scissorTest = false;
+    dither = true;
+
+    viewportX = 0;
+    viewportY = 0;
+    viewportWidth = config->mDisplayMode.Width;
+    viewportHeight = config->mDisplayMode.Height;
+    zNear = 0.0f;
+    zFar = 1.0f;
+
+    scissorX = 0;
+    scissorY = 0;
+    scissorWidth = config->mDisplayMode.Width;
+    scissorHeight = config->mDisplayMode.Height;
+
+    colorMaskRed = true;
+    colorMaskGreen = true;
+    colorMaskBlue = true;
+    colorMaskAlpha = true;
+    depthMask = true;
+
+    // [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 = new Texture2D();
+    mTextureCubeMapZero = new TextureCubeMap();
+
+    mColorbufferZero = NULL;
+    mDepthbufferZero = NULL;
+    mStencilbufferZero = NULL;
+
+    activeSampler = 0;
+    arrayBuffer = 0;
+    elementArrayBuffer = 0;
+    bindTextureCubeMap(0);
+    bindTexture2D(0);
+    bindFramebuffer(0);
+    bindRenderbuffer(0);
+
+    for (int sampler = 0; sampler < MAX_TEXTURE_IMAGE_UNITS; sampler++)
+    {
+        samplerTexture[sampler] = 0;
+    }
+
+    currentProgram = 0;
+
+    mInvalidEnum = false;
+    mInvalidValue = false;
+    mInvalidOperation = false;
+    mOutOfMemory = false;
+    mInvalidFramebufferOperation = false;
+}
+
+Context::~Context()
+{
+    currentProgram = 0;
+
+    delete mTexture2DZero;
+    delete mTextureCubeMapZero;
+
+    delete mColorbufferZero;
+    delete mDepthbufferZero;
+    delete mStencilbufferZero;
+
+    while (!mBufferMap.empty())
+    {
+        deleteBuffer(mBufferMap.begin()->first);
+    }
+
+    while (!mProgramMap.empty())
+    {
+        deleteProgram(mProgramMap.begin()->first);
+    }
+
+    while (!mShaderMap.empty())
+    {
+        deleteShader(mShaderMap.begin()->first);
+    }
+
+    while (!mFramebufferMap.empty())
+    {
+        deleteFramebuffer(mFramebufferMap.begin()->first);
+    }
+
+    while (!mRenderbufferMap.empty())
+    {
+        deleteRenderbuffer(mRenderbufferMap.begin()->first);
+    }
+
+    while (!mTextureMap.empty())
+    {
+        deleteTexture(mTextureMap.begin()->first);
+    }
+}
+
+void Context::makeCurrent(egl::Display *display, egl::Surface *surface)
+{
+    IDirect3DDevice9 *device = display->getDevice();
+
+    // Wrap the existing Direct3D 9 resources into GL objects and assign them to the '0' names
+    IDirect3DSurface9 *defaultRenderTarget = surface->getRenderTarget();
+    IDirect3DSurface9 *defaultDepthStencil = NULL;
+    device->GetDepthStencilSurface(&defaultDepthStencil);
+
+    Framebuffer *framebufferZero = new Framebuffer();
+    Colorbuffer *colorbufferZero = new Colorbuffer(defaultRenderTarget);
+    Depthbuffer *depthbufferZero = new Depthbuffer(defaultDepthStencil);
+    Stencilbuffer *stencilbufferZero = new Stencilbuffer(defaultDepthStencil);
+
+    setFramebufferZero(framebufferZero);
+    setColorbufferZero(colorbufferZero);
+    setDepthbufferZero(depthbufferZero);
+    setStencilbufferZero(stencilbufferZero);
+
+    framebufferZero->setColorbuffer(GL_RENDERBUFFER, 0);
+    framebufferZero->setDepthbuffer(GL_RENDERBUFFER, 0);
+    framebufferZero->setStencilbuffer(GL_RENDERBUFFER, 0);
+
+    defaultRenderTarget->Release();
+
+    if (defaultDepthStencil)
+    {
+        defaultDepthStencil->Release();
+    }
+}
+
+void Context::setClearColor(float red, float green, float blue, float alpha)
+{
+    colorClearValue.red = red;
+    colorClearValue.green = green;
+    colorClearValue.blue = blue;
+    colorClearValue.alpha = alpha;
+}
+
+void Context::setClearDepth(float depth)
+{
+    depthClearValue = depth;
+}
+
+void Context::setClearStencil(int stencil)
+{
+    stencilClearValue = stencil;
+}
+
+// Returns an unused buffer name
+GLuint Context::createBuffer()
+{
+    unsigned int handle = 1;
+
+    while (mBufferMap.find(handle) != mBufferMap.end())
+    {
+        handle++;
+    }
+
+    mBufferMap[handle] = NULL;
+
+    return handle;
+}
+
+// Returns an unused shader/program name
+GLuint Context::createShader(GLenum type)
+{
+    unsigned int handle = 1;
+
+    while (mShaderMap.find(handle) != mShaderMap.end() || mProgramMap.find(handle) != mProgramMap.end())   // Shared name space
+    {
+        handle++;
+    }
+
+    if (type == GL_VERTEX_SHADER)
+    {
+        mShaderMap[handle] = new VertexShader();
+    }
+    else if (type == GL_FRAGMENT_SHADER)
+    {
+        mShaderMap[handle] = new FragmentShader();
+    }
+    else UNREACHABLE();
+
+    return handle;
+}
+
+// Returns an unused program/shader name
+GLuint Context::createProgram()
+{
+    unsigned int handle = 1;
+
+    while (mProgramMap.find(handle) != mProgramMap.end() || mShaderMap.find(handle) != mShaderMap.end())   // Shared name space
+    {
+        handle++;
+    }
+
+    mProgramMap[handle] = new Program();
+
+    return handle;
+}
+
+// Returns an unused texture name
+GLuint Context::createTexture()
+{
+    unsigned int handle = 1;
+
+    while (mTextureMap.find(handle) != mTextureMap.end())
+    {
+        handle++;
+    }
+
+    mTextureMap[handle] = NULL;
+
+    return handle;
+}
+
+// Returns an unused framebuffer name
+GLuint Context::createFramebuffer()
+{
+    unsigned int handle = 1;
+
+    while (mFramebufferMap.find(handle) != mFramebufferMap.end())
+    {
+        handle++;
+    }
+
+    mFramebufferMap[handle] = NULL;
+
+    return handle;
+}
+
+// Returns an unused renderbuffer name
+GLuint Context::createRenderbuffer()
+{
+    unsigned int handle = 1;
+
+    while(mRenderbufferMap.find(handle) != mRenderbufferMap.end())
+    {
+        handle++;
+    }
+
+    mRenderbufferMap[handle] = NULL;
+
+    return handle;
+}
+
+void Context::deleteBuffer(GLuint buffer)
+{
+    BufferMap::iterator bufferObject = mBufferMap.find(buffer);
+
+    if (bufferObject != mBufferMap.end())
+    {
+        detachBuffer(buffer);
+
+        delete bufferObject->second;
+        mBufferMap.erase(bufferObject);
+    }
+}
+
+void Context::deleteShader(GLuint shader)
+{
+    ShaderMap::iterator shaderObject = mShaderMap.find(shader);
+
+    if (shaderObject != mShaderMap.end())
+    {
+        if (!shaderObject->second->isAttached())
+        {
+            delete shaderObject->second;
+            mShaderMap.erase(shaderObject);
+        }
+        else
+        {
+            shaderObject->second->flagForDeletion();
+        }
+    }
+}
+
+void Context::deleteProgram(GLuint program)
+{
+    ProgramMap::iterator programObject = mProgramMap.find(program);
+
+    if (programObject != mProgramMap.end())
+    {
+        if (program != currentProgram)
+        {
+            delete programObject->second;
+            mProgramMap.erase(programObject);
+        }
+        else
+        {
+            programObject->second->flagForDeletion();
+        }
+    }
+}
+
+void Context::deleteTexture(GLuint texture)
+{
+    TextureMap::iterator textureObject = mTextureMap.find(texture);
+
+    if (textureObject != mTextureMap.end())
+    {
+        detachTexture(texture);
+
+        if (texture != 0)
+        {
+            delete textureObject->second;
+        }
+
+        mTextureMap.erase(textureObject);
+    }
+}
+
+void Context::deleteFramebuffer(GLuint framebuffer)
+{
+    FramebufferMap::iterator framebufferObject = mFramebufferMap.find(framebuffer);
+
+    if (framebufferObject != mFramebufferMap.end())
+    {
+        detachFramebuffer(framebuffer);
+
+        delete framebufferObject->second;
+        mFramebufferMap.erase(framebufferObject);
+    }
+}
+
+void Context::deleteRenderbuffer(GLuint renderbuffer)
+{
+    RenderbufferMap::iterator renderbufferObject = mRenderbufferMap.find(renderbuffer);
+
+    if (renderbufferObject != mRenderbufferMap.end())
+    {
+        detachRenderbuffer(renderbuffer);
+
+        delete renderbufferObject->second;
+        mRenderbufferMap.erase(renderbufferObject);
+    }
+}
+
+void Context::bindArrayBuffer(unsigned int buffer)
+{
+    if (buffer != 0 && !getBuffer(buffer))
+    {
+        mBufferMap[buffer] = new Buffer();
+    }
+
+    arrayBuffer = buffer;
+}
+
+void Context::bindElementArrayBuffer(unsigned int buffer)
+{
+    if (buffer != 0 && !getBuffer(buffer))
+    {
+        mBufferMap[buffer] = new Buffer();
+    }
+
+    elementArrayBuffer = buffer;
+}
+
+void Context::bindTexture2D(GLuint texture)
+{
+    if (!getTexture(texture) || texture == 0)
+    {
+        if (texture != 0)
+        {
+            mTextureMap[texture] = new Texture2D();
+        }
+        else   // Special case: 0 refers to different initial textures based on the target
+        {
+            mTextureMap[0] = mTexture2DZero;
+        }
+    }
+
+    texture2D = texture;
+
+    samplerTexture[activeSampler] = texture;
+}
+
+void Context::bindTextureCubeMap(GLuint texture)
+{
+    if (!getTexture(texture) || texture == 0)
+    {
+        if (texture != 0)
+        {
+            mTextureMap[texture] = new TextureCubeMap();
+        }
+        else   // Special case: 0 refers to different initial textures based on the target
+        {
+            mTextureMap[0] = mTextureCubeMapZero;
+        }
+    }
+
+    textureCubeMap = texture;
+
+    samplerTexture[activeSampler] = texture;
+}
+
+void Context::bindFramebuffer(GLuint framebuffer)
+{
+    if (!getFramebuffer(framebuffer))
+    {
+        mFramebufferMap[framebuffer] = new Framebuffer();
+    }
+
+    this->framebuffer = framebuffer;
+}
+
+void Context::bindRenderbuffer(GLuint renderbuffer)
+{
+    if (renderbuffer != 0 && !getRenderbuffer(renderbuffer))
+    {
+        mRenderbufferMap[renderbuffer] = new Renderbuffer();
+    }
+
+    this->renderbuffer = renderbuffer;
+}
+
+void Context::useProgram(GLuint program)
+{
+    Program *programObject = getCurrentProgram();
+
+    if (programObject && programObject->isFlaggedForDeletion())
+    {
+        deleteProgram(currentProgram);
+    }
+
+    currentProgram = program;
+}
+
+void Context::setFramebufferZero(Framebuffer *buffer)
+{
+    delete mFramebufferMap[0];
+    mFramebufferMap[0] = buffer;
+}
+
+void Context::setColorbufferZero(Colorbuffer *buffer)
+{
+    delete mColorbufferZero;
+    mColorbufferZero = buffer;
+}
+
+void Context::setDepthbufferZero(Depthbuffer *buffer)
+{
+    delete mDepthbufferZero;
+    mDepthbufferZero = buffer;
+}
+
+void Context::setStencilbufferZero(Stencilbuffer *buffer)
+{
+    delete mStencilbufferZero;
+    mStencilbufferZero = buffer;
+}
+
+void Context::setRenderbuffer(Renderbuffer *buffer)
+{
+    delete mRenderbufferMap[renderbuffer];
+    mRenderbufferMap[renderbuffer] = buffer;
+}
+
+Buffer *Context::getBuffer(unsigned int handle)
+{
+    BufferMap::iterator buffer = mBufferMap.find(handle);
+    
+    if (buffer == mBufferMap.end())
+    {
+        return NULL;
+    }
+    else
+    {
+        return buffer->second;
+    }
+}
+
+Shader *Context::getShader(unsigned int handle)
+{
+    ShaderMap::iterator shader = mShaderMap.find(handle);
+    
+    if (shader == mShaderMap.end())
+    {
+        return NULL;
+    }
+    else
+    {
+        return shader->second;
+    }
+}
+
+Program *Context::getProgram(unsigned int handle)
+{
+    ProgramMap::iterator program = mProgramMap.find(handle);
+    
+    if (program == mProgramMap.end())
+    {
+        return NULL;
+    }
+    else
+    {
+        return program->second;
+    }
+}
+
+Texture *Context::getTexture(unsigned int handle)
+{
+    TextureMap::iterator texture = mTextureMap.find(handle);
+    
+    if (texture == mTextureMap.end())
+    {
+        return NULL;
+    }
+    else
+    {
+        return texture->second;
+    }
+}
+
+Framebuffer *Context::getFramebuffer(unsigned int handle)
+{
+    FramebufferMap::iterator framebuffer = mFramebufferMap.find(handle);
+    
+    if (framebuffer == mFramebufferMap.end())
+    {
+        return NULL;
+    }
+    else
+    {
+        return framebuffer->second;
+    }
+}
+
+Renderbuffer *Context::getRenderbuffer(unsigned int handle)
+{
+    RenderbufferMap::iterator renderbuffer = mRenderbufferMap.find(handle);
+    
+    if (renderbuffer == mRenderbufferMap.end())
+    {
+        return NULL;
+    }
+    else
+    {
+        return renderbuffer->second;
+    }
+}
+
+Colorbuffer *Context::getColorbuffer(GLuint handle)
+{
+    if (handle != 0)
+    {
+        Renderbuffer *renderbuffer = getRenderbuffer(handle);
+
+        if(renderbuffer && renderbuffer->isColorbuffer())
+        {
+            return static_cast<Colorbuffer*>(renderbuffer);
+        }
+    }
+    else   // Special case: 0 refers to different initial render targets based on the attachment type
+    {
+        return mColorbufferZero;
+    }
+
+    return NULL;
+}
+
+Depthbuffer *Context::getDepthbuffer(GLuint handle)
+{
+    if (handle != 0)
+    {
+        Renderbuffer *renderbuffer = getRenderbuffer(handle);
+
+        if(renderbuffer && renderbuffer->isDepthbuffer())
+        {
+            return static_cast<Depthbuffer*>(renderbuffer);
+        }
+    }
+    else   // Special case: 0 refers to different initial render targets based on the attachment type
+    {
+        return mDepthbufferZero;
+    }
+
+    return NULL;
+}
+
+Stencilbuffer *Context::getStencilbuffer(GLuint handle)
+{
+    if (handle != 0)
+    {
+        Renderbuffer *renderbuffer = getRenderbuffer(handle);
+
+        if(renderbuffer && renderbuffer->isStencilbuffer())
+        {
+            return static_cast<Stencilbuffer*>(renderbuffer);
+        }
+    }
+    else
+    {
+        return mStencilbufferZero;
+    }
+
+    return NULL;
+}
+
+Buffer *Context::getArrayBuffer()
+{
+    return getBuffer(arrayBuffer);
+}
+
+Buffer *Context::getElementArrayBuffer()
+{
+    return getBuffer(elementArrayBuffer);
+}
+
+Program *Context::getCurrentProgram()
+{
+    return getProgram(currentProgram);
+}
+
+Texture2D *Context::getTexture2D()
+{
+    if (texture2D == 0)   // Special case: 0 refers to different initial textures based on the target
+    {
+        return mTexture2DZero;
+    }
+
+    return (Texture2D*)getTexture(texture2D);
+}
+
+TextureCubeMap *Context::getTextureCubeMap()
+{
+    if (textureCubeMap == 0)   // Special case: 0 refers to different initial textures based on the target
+    {
+        return mTextureCubeMapZero;
+    }
+
+    return (TextureCubeMap*)getTexture(textureCubeMap);
+}
+
+Texture *Context::getSamplerTexture(unsigned int sampler)
+{
+    return getTexture(samplerTexture[sampler]);
+}
+
+Framebuffer *Context::getFramebuffer()
+{
+    return getFramebuffer(framebuffer);
+}
+
+// Applies the render target surface, depth stencil surface, viewport rectangle and
+// scissor rectangle to the Direct3D 9 device
+bool Context::applyRenderTarget(bool ignoreViewport)
+{
+    IDirect3DDevice9 *device = getDevice();
+    Framebuffer *framebufferObject = getFramebuffer();
+
+    if (!framebufferObject || framebufferObject->completeness() != GL_FRAMEBUFFER_COMPLETE)
+    {
+        return false;
+    }
+
+    IDirect3DSurface9 *renderTarget = framebufferObject->getRenderTarget();
+    IDirect3DSurface9 *depthStencil = framebufferObject->getDepthStencil();
+
+    device->SetRenderTarget(0, renderTarget);
+    device->SetDepthStencilSurface(depthStencil);
+
+    D3DVIEWPORT9 viewport;
+    D3DSURFACE_DESC desc;
+    renderTarget->GetDesc(&desc);
+
+    if (ignoreViewport)
+    {
+        viewport.X = 0;
+        viewport.Y = 0;
+        viewport.Width = desc.Width;
+        viewport.Height = desc.Height;
+        viewport.MinZ = 0.0f;
+        viewport.MaxZ = 1.0f;
+    }
+    else
+    {
+        viewport.X = max(viewportX, 0);
+        viewport.Y = max(viewportY, 0);
+        viewport.Width = min(viewportWidth, (int)desc.Width - (int)viewport.X);
+        viewport.Height = min(viewportHeight, (int)desc.Height - (int)viewport.Y);
+        viewport.MinZ = clamp01(zNear);
+        viewport.MaxZ = clamp01(zFar);
+    }
+
+    device->SetViewport(&viewport);
+
+    if (scissorTest)
+    {
+        RECT rect = {scissorX,
+                     scissorY,
+                     scissorX + scissorWidth,
+                     scissorY + scissorHeight};
+
+        device->SetScissorRect(&rect);
+        device->SetRenderState(D3DRS_SCISSORTESTENABLE, TRUE);
+    }
+    else
+    {
+        device->SetRenderState(D3DRS_SCISSORTESTENABLE, FALSE);
+    }
+
+    if (currentProgram)
+    {
+        D3DSURFACE_DESC description;
+        renderTarget->GetDesc(&description);
+        Program *programObject = getCurrentProgram();
+
+        GLuint halfPixelSize = programObject->getUniformLocation("gl_HalfPixelSize");
+        GLfloat xy[2] = {1.0f / description.Width, 1.0f / description.Height};
+        programObject->setUniform2fv(halfPixelSize, 1, (GLfloat*)&xy);
+    }
+
+    return true;
+}
+
+// Applies the fixed-function state (culling, depth test, alpha blending, stenciling, etc) to the Direct3D 9 device
+void Context::applyState()
+{
+    IDirect3DDevice9 *device = getDevice();
+
+    if (cullFace)
+    {
+        device->SetRenderState(D3DRS_CULLMODE, es2dx::ConvertCullMode(cullMode, frontFace));
+    }
+    else
+    {
+        device->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
+    }
+
+    if (depthTest)
+    {
+        device->SetRenderState(D3DRS_ZENABLE, D3DZB_TRUE);
+        device->SetRenderState(D3DRS_ZFUNC, es2dx::ConvertComparison(depthFunc));
+    }
+    else
+    {
+        device->SetRenderState(D3DRS_ZENABLE, D3DZB_FALSE);
+    }
+
+    if (blend)
+    {
+        device->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
+
+        if (sourceBlendRGB != GL_CONSTANT_ALPHA && sourceBlendRGB != GL_ONE_MINUS_CONSTANT_ALPHA &&
+            destBlendRGB != GL_CONSTANT_ALPHA && destBlendRGB != GL_ONE_MINUS_CONSTANT_ALPHA)
+        {
+            device->SetRenderState(D3DRS_BLENDFACTOR, es2dx::ConvertColor(blendColor));
+        }
+        else
+        {
+            device->SetRenderState(D3DRS_BLENDFACTOR, D3DCOLOR_RGBA(unorm<8>(blendColor.alpha),
+                                                                    unorm<8>(blendColor.alpha),
+                                                                    unorm<8>(blendColor.alpha),
+                                                                    unorm<8>(blendColor.alpha)));
+        }
+
+        device->SetRenderState(D3DRS_SRCBLEND, es2dx::ConvertBlendFunc(sourceBlendRGB));
+        device->SetRenderState(D3DRS_DESTBLEND, es2dx::ConvertBlendFunc(destBlendRGB));
+        device->SetRenderState(D3DRS_BLENDOP, es2dx::ConvertBlendOp(blendEquationRGB));
+
+        if (sourceBlendRGB != sourceBlendAlpha || destBlendRGB != destBlendAlpha || blendEquationRGB != blendEquationAlpha)
+        {
+            device->SetRenderState(D3DRS_SEPARATEALPHABLENDENABLE, TRUE);
+
+            device->SetRenderState(D3DRS_SRCBLENDALPHA, es2dx::ConvertBlendFunc(sourceBlendAlpha));
+            device->SetRenderState(D3DRS_DESTBLENDALPHA, es2dx::ConvertBlendFunc(destBlendAlpha));
+            device->SetRenderState(D3DRS_BLENDOPALPHA, es2dx::ConvertBlendOp(blendEquationAlpha));
+
+        }
+        else
+        {
+            device->SetRenderState(D3DRS_SEPARATEALPHABLENDENABLE, FALSE);
+        }
+    }
+    else
+    {
+        device->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
+    }
+
+    if (stencilTest)
+    {
+        device->SetRenderState(D3DRS_STENCILENABLE, TRUE);
+        device->SetRenderState(D3DRS_TWOSIDEDSTENCILMODE, TRUE);
+
+        // FIXME: Unsupported by D3D9
+        const D3DRENDERSTATETYPE D3DRS_CCW_STENCILREF = D3DRS_STENCILREF;
+        const D3DRENDERSTATETYPE D3DRS_CCW_STENCILMASK = D3DRS_STENCILMASK;
+        const D3DRENDERSTATETYPE D3DRS_CCW_STENCILWRITEMASK = D3DRS_STENCILWRITEMASK;
+        ASSERT(stencilRef == stencilBackRef);
+        ASSERT(stencilMask == stencilBackMask);
+        ASSERT(stencilWritemask == stencilBackWritemask);
+
+        device->SetRenderState(frontFace == GL_CCW ? D3DRS_STENCILWRITEMASK : D3DRS_CCW_STENCILWRITEMASK, stencilWritemask);
+        device->SetRenderState(frontFace == GL_CCW ? D3DRS_STENCILFUNC : D3DRS_CCW_STENCILFUNC, es2dx::ConvertComparison(stencilFunc));
+
+        device->SetRenderState(frontFace == GL_CCW ? D3DRS_STENCILREF : D3DRS_CCW_STENCILREF, stencilRef);   // FIXME: Clamp to range
+        device->SetRenderState(frontFace == GL_CCW ? D3DRS_STENCILMASK : D3DRS_CCW_STENCILMASK, stencilMask);
+
+        device->SetRenderState(frontFace == GL_CCW ? D3DRS_STENCILFAIL : D3DRS_CCW_STENCILFAIL, es2dx::ConvertStencilOp(stencilFail));
+        device->SetRenderState(frontFace == GL_CCW ? D3DRS_STENCILZFAIL : D3DRS_CCW_STENCILZFAIL, es2dx::ConvertStencilOp(stencilPassDepthFail));
+        device->SetRenderState(frontFace == GL_CCW ? D3DRS_STENCILPASS : D3DRS_CCW_STENCILPASS, es2dx::ConvertStencilOp(stencilPassDepthPass));
+
+        device->SetRenderState(frontFace == GL_CW ? D3DRS_STENCILWRITEMASK : D3DRS_CCW_STENCILWRITEMASK, stencilBackWritemask);
+        device->SetRenderState(frontFace == GL_CW ? D3DRS_STENCILFUNC : D3DRS_CCW_STENCILFUNC, es2dx::ConvertComparison(stencilBackFunc));
+
+        device->SetRenderState(frontFace == GL_CW ? D3DRS_STENCILREF : D3DRS_CCW_STENCILREF, stencilBackRef);   // FIXME: Clamp to range
+        device->SetRenderState(frontFace == GL_CW ? D3DRS_STENCILMASK : D3DRS_CCW_STENCILMASK, stencilBackMask);
+
+        device->SetRenderState(frontFace == GL_CW ? D3DRS_STENCILFAIL : D3DRS_CCW_STENCILFAIL, es2dx::ConvertStencilOp(stencilBackFail));
+        device->SetRenderState(frontFace == GL_CW ? D3DRS_STENCILZFAIL : D3DRS_CCW_STENCILZFAIL, es2dx::ConvertStencilOp(stencilBackPassDepthFail));
+        device->SetRenderState(frontFace == GL_CW ? D3DRS_STENCILPASS : D3DRS_CCW_STENCILPASS, es2dx::ConvertStencilOp(stencilBackPassDepthPass));
+    }
+    else
+    {
+        device->SetRenderState(D3DRS_STENCILENABLE, FALSE);
+    }
+
+    device->SetRenderState(D3DRS_COLORWRITEENABLE, es2dx::ConvertColorMask(colorMaskRed, colorMaskGreen, colorMaskBlue, colorMaskAlpha));
+    device->SetRenderState(D3DRS_ZWRITEENABLE, depthMask ? TRUE : FALSE);
+
+    if (polygonOffsetFill)
+    {
+        UNIMPLEMENTED();   // FIXME
+    }
+
+    if (sampleAlphaToCoverage)
+    {
+        UNIMPLEMENTED();   // FIXME
+    }
+
+    if (sampleCoverage)
+    {
+        UNIMPLEMENTED();   // FIXME: Ignore when SAMPLE_BUFFERS is not one
+    }
+
+    device->SetRenderState(D3DRS_DITHERENABLE, dither ? TRUE : FALSE);
+}
+
+// Applies the vertex attribute and array bindings to the Direct3D 9 device
+void Context::applyVertexBuffer(int count)
+{
+    IDirect3DDevice9 *device = getDevice();
+    Program *programObject = getCurrentProgram();
+    IDirect3DVertexShader9 *vertexShader = programObject->getVertexShader();
+
+    D3DVERTEXELEMENT9 vertexElements[MAX_VERTEX_ATTRIBS + 1];
+    D3DVERTEXELEMENT9 *currentElement = &vertexElements[0];
+
+    for (int attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; attributeIndex++)
+    {
+        if (vertexAttribute[attributeIndex].enabled && programObject->isActiveAttribute(attributeIndex))
+        {
+            GLuint boundBuffer = vertexAttribute[attributeIndex].boundBuffer;    
+            UINT stride = vertexAttribute[attributeIndex].stride;
+            GLint size = vertexAttribute[attributeIndex].size;
+            GLenum type = vertexAttribute[attributeIndex].type;
+
+            if (stride == 0)
+            {
+                switch (type)
+                {
+                  case GL_BYTE:            stride = size * sizeof(GLbyte);        break;
+                  case GL_UNSIGNED_BYTE:    stride = size * sizeof(GLubyte);    break;
+                  case GL_SHORT:            stride = size * sizeof(GLshort);    break;
+                  case GL_UNSIGNED_SHORT:    stride = size * sizeof(GLushort);    break;
+                  case GL_FIXED:            stride = size * sizeof(GLfixed);    break;
+                  case GL_FLOAT:            stride = size * sizeof(GLfloat);    break;
+                  default: UNREACHABLE();
+                }
+            }
+
+            currentElement->Stream = attributeIndex;
+
+            if (boundBuffer)
+            {
+                currentElement->Offset = (unsigned short)vertexAttribute[attributeIndex].pointer;
+            }
+            else
+            {
+                currentElement->Offset = 0;
+            }
+
+            switch (type)
+            {
+              case GL_BYTE:
+                if (vertexAttribute[attributeIndex].normalized)
+                {
+                    UNIMPLEMENTED();   // FIXME
+                }
+                else
+                {
+                    UNIMPLEMENTED();   // FIXME
+                }
+                break;
+              case GL_UNSIGNED_BYTE:
+                if (vertexAttribute[attributeIndex].normalized)
+                {
+                    switch (size)
+                    {
+                    case 1: UNIMPLEMENTED();   // FIXME
+                    case 2: UNIMPLEMENTED();   // FIXME
+                    case 3: UNIMPLEMENTED();   // FIXME
+                    case 4: currentElement->Type = D3DDECLTYPE_UBYTE4N; break;
+                    default: UNREACHABLE();
+                    }
+                }
+                else
+                {
+                    UNIMPLEMENTED();   // FIXME
+                }
+                break;
+            case GL_SHORT:
+                if (vertexAttribute[attributeIndex].normalized)
+                {
+                    UNIMPLEMENTED();   // FIXME
+                }
+                else
+                {
+                    UNIMPLEMENTED();   // FIXME
+                }
+                break;
+            case GL_UNSIGNED_SHORT:
+                if (vertexAttribute[attributeIndex].normalized)
+                {
+                    UNIMPLEMENTED();   // FIXME
+                }
+                else
+                {
+                    UNIMPLEMENTED();   // FIXME
+                }
+                break;
+            case GL_FIXED:
+                UNIMPLEMENTED();   // FIXME
+                break;
+            case GL_FLOAT:
+                switch (size)
+                {
+                  case 1: currentElement->Type = D3DDECLTYPE_FLOAT1; break;
+                  case 2: currentElement->Type = D3DDECLTYPE_FLOAT2; break;
+                  case 3: currentElement->Type = D3DDECLTYPE_FLOAT3; break;
+                  case 4: currentElement->Type = D3DDECLTYPE_FLOAT4; break;
+                  default: UNREACHABLE();
+                }
+                break;
+              default: UNREACHABLE();
+            }
+
+            currentElement->Method = D3DDECLMETHOD_DEFAULT;
+            currentElement->Usage = D3DDECLUSAGE_TEXCOORD;
+            currentElement->UsageIndex = programObject->getInputMapping(attributeIndex);
+
+            currentElement++;
+
+            if (boundBuffer)
+            {
+                Buffer *buffer = getBuffer(boundBuffer);
+                IDirect3DVertexBuffer9 *streamData = buffer->getVertexBuffer();
+                device->SetStreamSource(attributeIndex, streamData, 0, stride);
+            }
+            else if (vertexAttribute[attributeIndex].pointer)
+            {
+                IDirect3DVertexBuffer9 *vertexBuffer = NULL;
+                void *data;
+
+                HRESULT result = device->CreateVertexBuffer(stride * count, 0, 0, D3DPOOL_MANAGED, &vertexBuffer, NULL);
+
+                if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY)
+                {
+                    return error(GL_OUT_OF_MEMORY);
+                }
+
+                ASSERT(SUCCEEDED(result));
+
+                vertexBuffer->Lock(0, 0, &data, 0);
+                memcpy(data, vertexAttribute[attributeIndex].pointer, stride *count);
+                vertexBuffer->Unlock();
+
+                device->SetStreamSource(attributeIndex, vertexBuffer, 0, stride);
+                vertexBuffer->Release();
+            }
+            else UNIMPLEMENTED();   // FIXME
+        }
+        else
+        {
+            device->SetStreamSource(attributeIndex, NULL, 0, 0);
+        }
+    }
+
+    D3DVERTEXELEMENT9 end = D3DDECL_END();
+    *currentElement = end;
+
+    IDirect3DVertexDeclaration9 *vertexDeclaration = NULL;
+    HRESULT result = device->CreateVertexDeclaration(vertexElements, &vertexDeclaration);
+
+    if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY)
+    {
+        return error(GL_OUT_OF_MEMORY);
+    }
+
+    ASSERT(SUCCEEDED(result));
+
+    if (vertexDeclaration)
+    {
+        device->SetVertexDeclaration(vertexDeclaration);
+        vertexDeclaration->Release();   // Will only effectively be deleted when no longer in use
+    }
+}
+
+// Applies the indices and element array bindings to the Direct3D 9 device
+void Context::applyIndexBuffer(const void *indices, int length)
+{
+    IDirect3DDevice9 *device = getDevice();
+
+    if (elementArrayBuffer)
+    {
+        Buffer *buffer = getBuffer(elementArrayBuffer);
+        IDirect3DIndexBuffer9 *indexBuffer = buffer->getIndexBuffer();
+
+        device->SetIndices(indexBuffer);
+        startIndex = (unsigned int)(size_t)indices / 2;   // FIXME: Assumes even value and 16-bit indices
+    }
+    else if (indices)
+    {
+        IDirect3DIndexBuffer9 *indexBuffer = NULL;
+        void *data;
+
+        HRESULT result = device->CreateIndexBuffer(length, 0, D3DFMT_INDEX16, D3DPOOL_MANAGED, &indexBuffer, NULL);
+
+        if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY)
+        {
+            return error(GL_OUT_OF_MEMORY);
+        }
+
+        ASSERT(SUCCEEDED(result));
+
+        if (indexBuffer)
+        {
+            indexBuffer->Lock(0, length, &data, 0);
+            memcpy(data, indices, length);
+            indexBuffer->Unlock();
+
+            device->SetIndices(indexBuffer);
+            indexBuffer->Release();   // Will only effectively be deleted when no longer in use
+        }
+
+        startIndex = 0;
+    }
+    else UNREACHABLE();
+}
+
+// Applies the shaders and shader constants to the Direct3D 9 device
+void Context::applyShaders()
+{
+    IDirect3DDevice9 *device = getDevice();
+    Program *programObject = getCurrentProgram();
+    IDirect3DVertexShader9 *vertexShader = programObject->getVertexShader();
+    IDirect3DPixelShader9 *pixelShader = programObject->getPixelShader();
+
+    device->SetVertexShader(vertexShader);
+    device->SetPixelShader(pixelShader);
+
+    programObject->applyUniforms();
+}
+
+// Applies the textures and sampler states to the Direct3D 9 device
+void Context::applyTextures()
+{
+    IDirect3DDevice9 *device = getDevice();
+    Program *programObject = getCurrentProgram();
+
+    for (int sampler = 0; sampler < MAX_TEXTURE_IMAGE_UNITS; sampler++)
+    {
+        unsigned int textureUnit = programObject->getSamplerMapping(sampler);
+        Texture *texture = getSamplerTexture(textureUnit);
+
+        if (texture && texture->isComplete())
+        {
+            GLenum wrapS = texture->getWrapS();
+            GLenum wrapT = texture->getWrapT();
+            GLenum minFilter = texture->getMinFilter();
+            GLenum magFilter = texture->getMagFilter();
+
+            device->SetSamplerState(sampler, D3DSAMP_ADDRESSU, es2dx::ConvertTextureWrap(wrapS));
+            device->SetSamplerState(sampler, D3DSAMP_ADDRESSV, es2dx::ConvertTextureWrap(wrapT));
+
+            device->SetSamplerState(sampler, D3DSAMP_MAGFILTER, es2dx::ConvertMagFilter(magFilter));
+            D3DTEXTUREFILTERTYPE d3dMinFilter, d3dMipFilter;
+            es2dx::ConvertMinFilter(minFilter, &d3dMinFilter, &d3dMipFilter);
+            device->SetSamplerState(sampler, D3DSAMP_MINFILTER, d3dMinFilter);
+            device->SetSamplerState(sampler, D3DSAMP_MIPFILTER, d3dMipFilter);
+
+            device->SetTexture(sampler, texture->getTexture());
+        }
+    }
+}
+
+void Context::readPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, void* pixels)
+{
+    Framebuffer *framebuffer = getFramebuffer();
+    IDirect3DSurface9 *renderTarget = framebuffer->getRenderTarget();
+    IDirect3DDevice9 *device = getDevice();
+
+    D3DSURFACE_DESC desc;
+    renderTarget->GetDesc(&desc);
+
+    IDirect3DSurface9 *systemSurface;
+    HRESULT result = device->CreateOffscreenPlainSurface(desc.Width, desc.Height, desc.Format, D3DPOOL_SYSTEMMEM, &systemSurface, NULL);
+
+    if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY)
+    {
+        return error(GL_OUT_OF_MEMORY);
+    }
+
+    ASSERT(SUCCEEDED(result));
+
+    if (desc.MultiSampleType != D3DMULTISAMPLE_NONE)
+    {
+        UNIMPLEMENTED();   // FIXME: Requires resolve using StretchRect into non-multisampled render target
+    }
+
+    result = device->GetRenderTargetData(renderTarget, systemSurface);
+
+    if (result == D3DERR_DRIVERINTERNALERROR)
+    {
+        systemSurface->Release();
+
+        return error(GL_OUT_OF_MEMORY);
+    }
+
+    if (FAILED(result))
+    {
+        UNREACHABLE();
+        systemSurface->Release();
+
+        return;   // No sensible error to generate
+    }
+
+    D3DLOCKED_RECT lock;
+    RECT rect = {max(x, 0),
+                 max(y, 0),
+                 min(x + width, (int)desc.Width),
+                 min(y + height, (int)desc.Height)};
+
+    result = systemSurface->LockRect(&lock, &rect, D3DLOCK_READONLY);
+
+    if (FAILED(result))
+    {
+        UNREACHABLE();
+        systemSurface->Release();
+
+        return;   // No sensible error to generate
+    }
+
+    unsigned char *source = (unsigned char*)lock.pBits;
+    unsigned char *dest = (unsigned char*)pixels;
+
+    for (int j = 0; j < rect.bottom - rect.top; j++)
+    {
+        for (int i = 0; i < rect.right - rect.left; i++)
+        {
+            float r;
+            float g;
+            float b;
+            float a;
+
+            switch (desc.Format)
+            {
+              case D3DFMT_R5G6B5:
+                {
+                    unsigned short rgb = *(unsigned short*)(source + 2 * i + j * lock.Pitch);
+
+                    a = 1.0f;
+                    b = (rgb & 0x001F) * (1.0f / 0x001F);
+                    g = (rgb & 0x07E0) * (1.0f / 0x07E0);
+                    r = (rgb & 0xF800) * (1.0f / 0xF800);
+                }
+                break;
+              case D3DFMT_X1R5G5B5:
+                {
+                    unsigned short xrgb = *(unsigned short*)(source + 2 * i + j * lock.Pitch);
+
+                    a = 1.0f;
+                    b = (xrgb & 0x001F) * (1.0f / 0x001F);
+                    g = (xrgb & 0x03E0) * (1.0f / 0x03E0);
+                    r = (xrgb & 0x7C00) * (1.0f / 0x7C00);
+                }
+                break;
+              case D3DFMT_A1R5G5B5:
+                {
+                    unsigned short argb = *(unsigned short*)(source + 2 * i + j * lock.Pitch);
+
+                    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 D3DFMT_A8R8G8B8:
+                {
+                    unsigned int argb = *(unsigned int*)(source + 4 * i + j * lock.Pitch);
+
+                    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 D3DFMT_X8R8G8B8:
+                {
+                    unsigned int xrgb = *(unsigned int*)(source + 4 * i + j * lock.Pitch);
+
+                    a = 1.0f;
+                    b = (xrgb & 0x000000FF) * (1.0f / 0x000000FF);
+                    g = (xrgb & 0x0000FF00) * (1.0f / 0x0000FF00);
+                    r = (xrgb & 0x00FF0000) * (1.0f / 0x00FF0000);
+                }
+                break;
+              case D3DFMT_A2R10G10B10:
+                {
+                    unsigned int argb = *(unsigned int*)(source + 4 * i + j * lock.Pitch);
+
+                    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;
+              default:
+                UNIMPLEMENTED();   // FIXME
+                UNREACHABLE();
+            }
+
+            switch (format)
+            {
+              case GL_RGBA:
+                switch (type)
+                {
+                  case GL_UNSIGNED_BYTE:
+                    dest[4 * (i + j * width) + 0] = (unsigned char)(255 * r + 0.5f);
+                    dest[4 * (i + j * width) + 1] = (unsigned char)(255 * g + 0.5f);
+                    dest[4 * (i + j * width) + 2] = (unsigned char)(255 * b + 0.5f);
+                    dest[4 * (i + j * width) + 3] = (unsigned char)(255 * a + 0.5f);
+                    break;
+                  default: UNREACHABLE();
+                }
+                break;
+              case IMPLEMENTATION_COLOR_READ_FORMAT:
+                switch (type)
+                {
+                  case IMPLEMENTATION_COLOR_READ_TYPE:
+                    break;
+                  default: UNREACHABLE();
+                }
+                break;
+              default: UNREACHABLE();
+            }
+        }
+    }
+
+    systemSurface->UnlockRect();
+
+    systemSurface->Release();
+}
+
+void Context::clear(GLbitfield mask)
+{
+    IDirect3DDevice9 *device = getDevice();
+    DWORD flags = 0;
+
+    if (mask & GL_COLOR_BUFFER_BIT)
+    {
+        mask &= ~GL_COLOR_BUFFER_BIT;
+        flags |= D3DCLEAR_TARGET;
+    }
+
+    if (mask & GL_DEPTH_BUFFER_BIT)
+    {
+        mask &= ~GL_DEPTH_BUFFER_BIT;
+        if (depthMask)
+        {
+            flags |= D3DCLEAR_ZBUFFER;
+        }
+    }
+
+    Framebuffer *framebufferObject = getFramebuffer();
+    IDirect3DSurface9 *depthStencil = framebufferObject->getDepthStencil();
+
+    GLuint stencilUnmasked = 0x0;
+
+    if ((mask & GL_STENCIL_BUFFER_BIT) && depthStencil)
+    {
+        D3DSURFACE_DESC desc;
+        depthStencil->GetDesc(&desc);
+
+        mask &= ~GL_STENCIL_BUFFER_BIT;
+        unsigned int stencilSize = es2dx::GetStencilSize(desc.Format);
+        stencilUnmasked = (0x1 << stencilSize) - 1;
+
+        if (stencilUnmasked != 0x0)
+        {
+            flags |= D3DCLEAR_STENCIL;
+        }
+    }
+
+    if (mask != 0)
+    {
+        return error(GL_INVALID_VALUE);
+    }
+
+    applyRenderTarget(true);   // Clips the clear to the scissor rectangle but not the viewport
+
+    D3DCOLOR color = D3DCOLOR_ARGB(unorm<8>(colorClearValue.alpha), unorm<8>(colorClearValue.red), unorm<8>(colorClearValue.green), unorm<8>(colorClearValue.blue));
+    float depth = clamp01(depthClearValue);
+    int stencil = stencilClearValue & 0x000000FF;
+
+    IDirect3DSurface9 *renderTarget = framebufferObject->getRenderTarget();
+
+    D3DSURFACE_DESC desc;
+    renderTarget->GetDesc(&desc);
+
+    bool alphaUnmasked = (es2dx::GetAlphaSize(desc.Format) == 0) || colorMaskAlpha;
+
+    const bool needMaskedStencilClear = (flags & D3DCLEAR_STENCIL) &&
+                                        (stencilWritemask & stencilUnmasked) != stencilUnmasked;
+    const bool needMaskedColorClear = (flags & D3DCLEAR_TARGET) &&
+                                      !(colorMaskRed && colorMaskGreen && 
+                                        colorMaskBlue && alphaUnmasked);
+
+    if (needMaskedColorClear || needMaskedStencilClear)
+    {
+        device->SetRenderState(D3DRS_ZWRITEENABLE, FALSE);
+        device->SetRenderState(D3DRS_ZFUNC, D3DCMP_ALWAYS);
+        device->SetRenderState(D3DRS_ZENABLE, FALSE);
+        device->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
+        device->SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID);
+        device->SetRenderState(D3DRS_ALPHATESTENABLE, FALSE);
+        device->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
+        device->SetRenderState(D3DRS_CLIPPLANEENABLE, 0);
+
+        if (flags & D3DCLEAR_TARGET)
+        {
+            device->SetRenderState(D3DRS_COLORWRITEENABLE, (colorMaskRed   ? D3DCOLORWRITEENABLE_RED   : 0) |
+                                                           (colorMaskGreen ? D3DCOLORWRITEENABLE_GREEN : 0) |
+                                                           (colorMaskBlue  ? D3DCOLORWRITEENABLE_BLUE  : 0) |
+                                                           (colorMaskAlpha ? D3DCOLORWRITEENABLE_ALPHA : 0));
+        }
+        else
+        {
+            device->SetRenderState(D3DRS_COLORWRITEENABLE, 0);
+        }
+
+        if (stencilUnmasked != 0x0 && (flags & D3DCLEAR_STENCIL))
+        {
+            device->SetRenderState(D3DRS_STENCILENABLE, TRUE);
+            device->SetRenderState(D3DRS_TWOSIDEDSTENCILMODE, FALSE);
+            device->SetRenderState(D3DRS_STENCILFUNC, D3DCMP_ALWAYS);
+            device->SetRenderState(D3DRS_STENCILREF, stencil);
+            device->SetRenderState(D3DRS_STENCILWRITEMASK, stencilWritemask);
+            device->SetRenderState(D3DRS_STENCILFAIL, D3DSTENCILOP_REPLACE); 
+            device->SetRenderState(D3DRS_STENCILZFAIL, D3DSTENCILOP_REPLACE);
+            device->SetRenderState(D3DRS_STENCILPASS, D3DSTENCILOP_REPLACE);
+        }
+        else
+        {
+            device->SetRenderState(D3DRS_STENCILENABLE, FALSE);
+        }
+
+        device->SetPixelShader(NULL);
+        device->SetVertexShader(NULL);
+        device->SetFVF(D3DFVF_XYZRHW | D3DFVF_DIFFUSE);
+
+        struct Vertex 
+        {
+            float x, y, z, w;
+            D3DCOLOR diffuse;
+        };
+
+        Vertex quad[4];
+        quad[0].x = 0.0f;
+        quad[0].y = (float)desc.Height;
+        quad[0].z = 0.0f;
+        quad[0].w = 1.0f;
+        quad[0].diffuse = color;
+
+        quad[1].x = (float)desc.Width;
+        quad[1].y = (float)desc.Height;
+        quad[1].z = 0.0f;
+        quad[1].w = 1.0f;
+        quad[1].diffuse = color;
+
+        quad[2].x = 0.0f;
+        quad[2].y = 0.0f;
+        quad[2].z = 0.0f;
+        quad[2].w = 1.0f;
+        quad[2].diffuse = color;
+
+        quad[3].x = (float)desc.Width;
+        quad[3].y = 0.0f;
+        quad[3].z = 0.0f;
+        quad[3].w = 1.0f;
+        quad[3].diffuse = color;
+
+        device->BeginScene();
+        device->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, quad, sizeof(Vertex));
+        device->EndScene();
+
+        if (flags & D3DCLEAR_ZBUFFER)
+        {
+            device->SetRenderState(D3DRS_ZENABLE, TRUE);
+            device->SetRenderState(D3DRS_ZWRITEENABLE, TRUE);
+            device->Clear(0, NULL, D3DCLEAR_ZBUFFER, color, depth, stencil);
+        }
+    }
+    else
+    {
+        device->Clear(0, NULL, flags, color, depth, stencil);
+    }
+}
+
+void Context::drawArrays(GLenum mode, GLint first, GLsizei count)
+{
+    if (!currentProgram)
+    {
+        return error(GL_INVALID_OPERATION);
+    }
+
+    IDirect3DDevice9 *device = getDevice();
+    D3DPRIMITIVETYPE primitiveType;
+    int primitiveCount;
+
+    if(!es2dx::ConvertPrimitiveType(mode, count, &primitiveType, &primitiveCount))
+        return error(GL_INVALID_ENUM);
+
+    if (primitiveCount <= 0)
+    {
+        return;
+    }
+
+    if (!applyRenderTarget(false))
+    {
+        return error(GL_INVALID_FRAMEBUFFER_OPERATION);
+    }
+
+    applyState();
+    applyVertexBuffer(count);
+    applyShaders();
+    applyTextures();
+
+    device->BeginScene();
+    device->DrawPrimitive(primitiveType, first, primitiveCount);
+    device->EndScene();
+}
+
+void Context::drawElements(GLenum mode, GLsizei count, GLenum type, const void* indices)
+{
+    if (!currentProgram)
+    {
+        return error(GL_INVALID_OPERATION);
+    }
+
+    if (!indices && !elementArrayBuffer)
+    {
+        return error(GL_INVALID_OPERATION);
+    }
+
+    IDirect3DDevice9 *device = getDevice();
+    D3DPRIMITIVETYPE primitiveType;
+    int primitiveCount;
+
+    if(!es2dx::ConvertPrimitiveType(mode, count, &primitiveType, &primitiveCount))
+        return error(GL_INVALID_ENUM);
+
+    if (primitiveCount <= 0)
+    {
+        return;
+    }
+
+    if (!applyRenderTarget(false))
+    {
+        return error(GL_INVALID_FRAMEBUFFER_OPERATION);
+    }
+
+    applyState();
+    applyVertexBuffer(count);
+    applyIndexBuffer(indices, count * sizeof(unsigned short));
+    applyShaders();
+    applyTextures();
+
+    device->BeginScene();
+    device->DrawIndexedPrimitive(primitiveType, 0, 0, count, startIndex, primitiveCount);
+    device->EndScene();
+}
+
+void Context::finish()
+{
+    IDirect3DDevice9 *device = getDevice();
+    IDirect3DQuery9 *occlusionQuery = NULL;
+
+    HRESULT result = device->CreateQuery(D3DQUERYTYPE_OCCLUSION, &occlusionQuery);
+
+    if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY)
+    {
+        return error(GL_OUT_OF_MEMORY);
+    }
+
+    ASSERT(SUCCEEDED(result));
+
+    if (occlusionQuery)
+    {
+        occlusionQuery->Issue(D3DISSUE_BEGIN);
+
+        // Render something outside the render target
+        device->SetPixelShader(NULL);
+        device->SetVertexShader(NULL);
+        device->SetFVF(D3DFVF_XYZRHW);
+        float data[4] = {-1.0f, -1.0f, -1.0f, 1.0f};
+        device->BeginScene();
+        device->DrawPrimitiveUP(D3DPT_POINTLIST, 1, data, sizeof(data));
+        device->EndScene();
+
+        occlusionQuery->Issue(D3DISSUE_END);
+
+        while (occlusionQuery->GetData(NULL, 0, D3DGETDATA_FLUSH) == S_FALSE)
+        {
+            // Keep polling, but allow other threads to do something useful first
+            Sleep(0);
+        }
+
+        occlusionQuery->Release();
+    }
+}
+
+void Context::flush()
+{
+    IDirect3DDevice9 *device = getDevice();
+    IDirect3DQuery9 *eventQuery = NULL;
+
+    HRESULT result = device->CreateQuery(D3DQUERYTYPE_EVENT, &eventQuery);
+
+    if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY)
+    {
+        return error(GL_OUT_OF_MEMORY);
+    }
+
+    ASSERT(SUCCEEDED(result));
+
+    if (eventQuery)
+    {
+        eventQuery->Issue(D3DISSUE_END);
+
+        while (eventQuery->GetData(NULL, 0, D3DGETDATA_FLUSH) == S_FALSE)
+        {
+            // Keep polling, but allow other threads to do something useful first
+            Sleep(0);
+        }
+
+        eventQuery->Release();
+    }
+}
+
+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;
+}
+
+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 (arrayBuffer == buffer)
+    {
+        arrayBuffer = 0;
+    }
+
+    if (elementArrayBuffer == buffer)
+    {
+        elementArrayBuffer = 0;
+    }
+
+    for (int attribute = 0; attribute < MAX_VERTEX_ATTRIBS; attribute++)
+    {
+        if (vertexAttribute[attribute].boundBuffer == buffer)
+        {
+            vertexAttribute[attribute].boundBuffer = 0;
+        }
+    }
+}
+
+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 sampler = 0; sampler < MAX_TEXTURE_IMAGE_UNITS; sampler++)
+    {
+        if (samplerTexture[sampler] == texture)
+        {
+            samplerTexture[sampler] = 0;
+        }
+    }
+
+    // [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 *framebuffer = getFramebuffer();
+
+    if (framebuffer)
+    {
+        framebuffer->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 (this->framebuffer == framebuffer)
+    {
+        bindFramebuffer(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 (this->renderbuffer == 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 *framebuffer = getFramebuffer();
+
+    if (framebuffer)
+    {
+        framebuffer->detachRenderbuffer(renderbuffer);
+    }
+}
+}
+
+extern "C"
+{
+gl::Context *glCreateContext(const egl::Config *config)
+{
+    return new gl::Context(config);
+}
+
+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/libGLESv2/Framebuffer.cpp b/libGLESv2/Framebuffer.cpp
new file mode 100644
index 0000000..f242abe
--- /dev/null
+++ b/libGLESv2/Framebuffer.cpp
@@ -0,0 +1,233 @@
+//
+// 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.
+//
+
+// Framebuffer.cpp: Implements the gl::Framebuffer class. Implements GL framebuffer
+// objects and related functionality. [OpenGL ES 2.0.24] section 4.4 page 105.
+
+#include "Framebuffer.h"
+
+#include "Renderbuffer.h"
+#include "Texture.h"
+#include "main.h"
+
+namespace gl
+{
+Framebuffer::Framebuffer()
+{
+    mColorbufferType = GL_NONE;
+    mColorbufferHandle = 0;
+
+    mDepthbufferType = GL_NONE;
+    mDepthbufferHandle = 0;
+
+    mStencilbufferType = GL_NONE;
+    mStencilbufferHandle = 0;
+}
+
+Framebuffer::~Framebuffer()
+{
+}
+
+void Framebuffer::setColorbuffer(GLenum type, GLuint colorbuffer)
+{
+    mColorbufferType = type;
+    mColorbufferHandle = colorbuffer;
+}
+
+void Framebuffer::setDepthbuffer(GLenum type, GLuint depthbuffer)
+{
+    mDepthbufferType = type;
+    mDepthbufferHandle = depthbuffer;
+}
+
+void Framebuffer::setStencilbuffer(GLenum type, GLuint stencilbuffer)
+{
+    mStencilbufferType = type;
+    mStencilbufferHandle = stencilbuffer;
+}
+
+void Framebuffer::detachTexture(GLuint texture)
+{
+    if (mColorbufferHandle == texture && mColorbufferType == GL_TEXTURE)
+    {
+        mColorbufferType = GL_NONE;
+        mColorbufferHandle = 0;
+    }
+}
+
+void Framebuffer::detachRenderbuffer(GLuint renderbuffer)
+{
+    if (mColorbufferHandle == renderbuffer && mColorbufferType == GL_RENDERBUFFER)
+    {
+        mColorbufferType = GL_NONE;
+        mColorbufferHandle = 0;
+    }
+
+    if (mDepthbufferHandle == renderbuffer && mDepthbufferType == GL_RENDERBUFFER)
+    {
+        mDepthbufferType = GL_NONE;
+        mDepthbufferHandle = 0;
+    }
+
+    if (mStencilbufferHandle == renderbuffer && mStencilbufferType == GL_RENDERBUFFER)
+    {
+        mStencilbufferType = GL_NONE;
+        mStencilbufferHandle = 0;
+    }
+}
+
+IDirect3DSurface9 *Framebuffer::getRenderTarget()
+{
+    Renderbuffer *colorbuffer = getColorbuffer();
+    
+    if (colorbuffer)
+    {
+        return colorbuffer->getRenderTarget();
+    }
+
+    return NULL;
+}
+
+IDirect3DSurface9 *Framebuffer::getDepthStencil()
+{
+    gl::Context *context = gl::getContext();
+    Depthbuffer *depthbuffer = context->getDepthbuffer(mDepthbufferHandle);
+    
+    if (depthbuffer)
+    {
+        return depthbuffer->getDepthStencil();
+    }
+
+    return NULL;
+}
+
+Colorbuffer *Framebuffer::getColorbuffer()
+{
+    gl::Context *context = gl::getContext();
+    Colorbuffer *colorbuffer = NULL;
+
+    if (mColorbufferType == GL_RENDERBUFFER)
+    {
+        colorbuffer = context->getColorbuffer(mColorbufferHandle);
+    }
+    else if (mColorbufferType == GL_TEXTURE)
+    {
+        colorbuffer = context->getTexture(mColorbufferHandle);
+    }
+    else UNREACHABLE();
+
+    if (colorbuffer && colorbuffer->isColorbuffer())
+    {
+        return colorbuffer;
+    }
+
+    return NULL;
+}
+
+Depthbuffer *Framebuffer::getDepthbuffer()
+{
+    gl::Context *context = gl::getContext();
+    Depthbuffer *depthbuffer = context->getDepthbuffer(mDepthbufferHandle);
+    
+    if (depthbuffer && depthbuffer->isDepthbuffer())
+    {
+        return depthbuffer;
+    }
+
+    return NULL;
+}
+
+Stencilbuffer *Framebuffer::getStencilbuffer()
+{
+    gl::Context *context = gl::getContext();
+    Stencilbuffer *stencilbuffer = context->getStencilbuffer(mStencilbufferHandle);
+    
+    if (stencilbuffer && stencilbuffer->isStencilbuffer())
+    {
+        return stencilbuffer;
+    }
+
+    return NULL;
+}
+
+GLenum Framebuffer::completeness()
+{
+    gl::Context *context = gl::getContext();
+
+    int width = 0;
+    int height = 0;
+
+    if (mColorbufferType != GL_NONE)
+    {
+        Colorbuffer *colorbuffer = getColorbuffer();
+
+        if (!colorbuffer)
+        {
+            return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
+        }
+
+        if (colorbuffer->getWidth() == 0 || colorbuffer->getHeight() == 0)
+        {
+            return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
+        }
+
+        width = colorbuffer->getWidth();
+        height = colorbuffer->getHeight();
+    }
+
+    if (mDepthbufferType != GL_NONE)
+    {
+        Depthbuffer *depthbuffer = context->getDepthbuffer(mDepthbufferHandle);
+
+        if (!depthbuffer)
+        {
+            return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
+        }
+
+        if (depthbuffer->getWidth() == 0 || depthbuffer->getHeight() == 0)
+        {
+            return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
+        }
+
+        if (width == 0)
+        {
+            width = depthbuffer->getWidth();
+            height = depthbuffer->getHeight();
+        }
+        else if (width != depthbuffer->getWidth() || height != depthbuffer->getHeight())
+        {
+            return GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS;
+        }
+    }
+
+    if (mStencilbufferType != GL_NONE)
+    {
+        Stencilbuffer *stencilbuffer = context->getStencilbuffer(mStencilbufferHandle);
+
+        if (!stencilbuffer)
+        {
+            return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
+        }
+
+        if (stencilbuffer->getWidth() == 0 || stencilbuffer->getHeight() == 0)
+        {
+            return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
+        }
+
+        if (width == 0)
+        {
+            width = stencilbuffer->getWidth();
+            height = stencilbuffer->getHeight();
+        }
+        else if (width != stencilbuffer->getWidth() || height != stencilbuffer->getHeight())
+        {
+            return GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS;
+        }
+    }
+
+    return GL_FRAMEBUFFER_COMPLETE;
+}
+}
diff --git a/libGLESv2/Framebuffer.h b/libGLESv2/Framebuffer.h
new file mode 100644
index 0000000..fd90ae1
--- /dev/null
+++ b/libGLESv2/Framebuffer.h
@@ -0,0 +1,62 @@
+//
+// 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.
+//
+
+// Framebuffer.h: Defines the gl::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_
+
+#define GL_APICALL
+#include <GLES2/gl2.h>
+#include <d3d9.h>
+
+#include "angleutils.h"
+
+namespace gl
+{
+class Colorbuffer;
+class Depthbuffer;
+class Stencilbuffer;
+
+class Framebuffer
+{
+  public:
+    Framebuffer();
+
+    ~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);
+
+    IDirect3DSurface9 *getRenderTarget();
+    IDirect3DSurface9 *getDepthStencil();
+
+    Colorbuffer *getColorbuffer();
+    Depthbuffer *getDepthbuffer();
+    Stencilbuffer *getStencilbuffer();
+
+    GLenum completeness();
+
+  private:
+    DISALLOW_COPY_AND_ASSIGN(Framebuffer);
+
+    GLuint mColorbufferHandle;
+    GLenum mColorbufferType;
+
+    GLuint mDepthbufferHandle;
+    GLenum mDepthbufferType;
+
+    GLuint mStencilbufferHandle;
+    GLenum mStencilbufferType;
+};
+}
+
+#endif   // LIBGLESV2_FRAMEBUFFER_H_
diff --git a/libGLESv2/Program.cpp b/libGLESv2/Program.cpp
new file mode 100644
index 0000000..0e73852
--- /dev/null
+++ b/libGLESv2/Program.cpp
@@ -0,0 +1,942 @@
+//
+// 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.
+//
+
+// Program.cpp: Implements the gl::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 "debug.h"
+
+namespace gl
+{
+Uniform::Uniform(UniformType type, const std::string &name, unsigned int bytes) : type(type), name(name), bytes(bytes)
+{
+    this->data = new unsigned char[bytes];
+    memset(this->data, 0, bytes);
+}
+
+Uniform::~Uniform()
+{
+    delete[] data;
+}
+
+Program::Program()
+{
+    mFragmentShader = NULL;
+    mVertexShader = NULL;
+
+    mPixelExecutable = NULL;
+    mVertexExecutable = NULL;
+    mConstantTablePS = NULL;
+    mConstantTableVS = NULL;
+
+    for (int index = 0; index < MAX_VERTEX_ATTRIBS; index++)
+    {
+        mAttributeName[index] = NULL;
+    }
+
+    unlink();
+
+    mDeleteStatus = false;
+}
+
+Program::~Program()
+{
+    unlink(true);
+}
+
+bool Program::attachShader(Shader *shader)
+{
+    if (shader->getType() == GL_VERTEX_SHADER)
+    {
+        if (mVertexShader)
+        {
+            return false;
+        }
+
+        mVertexShader = (VertexShader*)shader;
+        mVertexShader->attach();
+    }
+    else if (shader->getType() == GL_FRAGMENT_SHADER)
+    {
+        if (mFragmentShader)
+        {
+            return false;
+        }
+
+        mFragmentShader = (FragmentShader*)shader;
+        mFragmentShader->attach();
+    }
+    else UNREACHABLE();
+
+    return true;
+}
+
+bool Program::detachShader(Shader *shader)
+{
+    if (shader->getType() == GL_VERTEX_SHADER)
+    {
+        if (mVertexShader != shader)
+        {
+            return false;
+        }
+
+        mVertexShader->detach();
+        mVertexShader = NULL;
+    }
+    else if (shader->getType() == GL_FRAGMENT_SHADER)
+    {
+        if (mFragmentShader != shader)
+        {
+            return false;
+        }
+
+        mFragmentShader->detach();
+        mFragmentShader = NULL;
+    }
+    else UNREACHABLE();
+
+    unlink();
+
+    return true;
+}
+
+IDirect3DPixelShader9 *Program::getPixelShader()
+{
+    return mPixelExecutable;
+}
+
+IDirect3DVertexShader9 *Program::getVertexShader()
+{
+    return mVertexExecutable;
+}
+
+void Program::bindAttributeLocation(GLuint index, const char *name)
+{
+    if (index < MAX_VERTEX_ATTRIBS)
+    {
+        delete[] mAttributeName[index];
+        mAttributeName[index] = new char[strlen(name) + 1];
+        strcpy(mAttributeName[index], name);
+    }
+}
+
+GLuint Program::getAttributeLocation(const char *name)
+{
+    for (int index = 0; index < MAX_VERTEX_ATTRIBS; index++)
+    {
+        if (mAttributeName[index] && strcmp(mAttributeName[index], name) == 0)
+        {
+            return index;
+        }
+    }
+
+    return -1;
+}
+
+bool Program::isActiveAttribute(int attributeIndex)
+{
+    if (attributeIndex >= 0 && attributeIndex < MAX_VERTEX_ATTRIBS)
+    {
+        return mInputMapping[attributeIndex] != -1;
+    }
+
+    return false;
+}
+
+int Program::getInputMapping(int attributeIndex)
+{
+    if (attributeIndex >= 0 && attributeIndex < MAX_VERTEX_ATTRIBS)
+    {
+        return mInputMapping[attributeIndex];
+    }
+
+    return -1;
+}
+
+// Returns the index of the texture unit corresponding to a Direct3D 9 sampler
+// index referenced in the compiled HLSL shader
+GLint Program::getSamplerMapping(unsigned int samplerIndex)
+{
+    if (samplerIndex < MAX_TEXTURE_IMAGE_UNITS)
+    {
+        return mSamplerMapping[samplerIndex];
+    }
+
+    return 0;
+}
+
+GLint Program::getUniformLocation(const char *name)
+{
+    for (unsigned int location = 0; location < mUniforms.size(); location++)
+    {
+        if (mUniforms[location]->name == name)
+        {
+            return location;
+        }
+    }
+
+    return -1;
+}
+
+bool Program::setUniform1fv(GLint location, GLsizei count, const GLfloat* v)
+{
+    if (location < 0 || location >= (int)mUniforms.size())
+    {
+        return false;
+    }
+
+    if (mUniforms[location]->type != UNIFORM_1FV || mUniforms[location]->bytes < sizeof(GLfloat) * count)
+    {
+        return false;
+    }
+
+    memcpy(mUniforms[location]->data, v, sizeof(GLfloat) * count);
+
+    return true;
+}
+
+bool Program::setUniform2fv(GLint location, GLsizei count, const GLfloat *v)
+{
+    if (location < 0 || location >= (int)mUniforms.size())
+    {
+        return false;
+    }
+
+    if (mUniforms[location]->type != UNIFORM_2FV || mUniforms[location]->bytes < 2 * sizeof(GLfloat) * count)
+    {
+        return false;
+    }
+
+    memcpy(mUniforms[location]->data, v, 2 * sizeof(GLfloat) * count);
+
+    return true;
+}
+
+bool Program::setUniform3fv(GLint location, GLsizei count, const GLfloat *v)
+{
+    if (location < 0 || location >= (int)mUniforms.size())
+    {
+        return false;
+    }
+
+    if (mUniforms[location]->type != UNIFORM_3FV || mUniforms[location]->bytes < 3 * sizeof(GLfloat) * count)
+    {
+        return false;
+    }
+
+    memcpy(mUniforms[location]->data, v, 3 * sizeof(GLfloat) * count);
+
+    return true;
+}
+
+bool Program::setUniform4fv(GLint location, GLsizei count, const GLfloat *v)
+{
+    if (location < 0 || location >= (int)mUniforms.size())
+    {
+        return false;
+    }
+
+    if (mUniforms[location]->type != UNIFORM_4FV || mUniforms[location]->bytes < 4 * sizeof(GLfloat) * count)
+    {
+        return false;
+    }
+
+    memcpy(mUniforms[location]->data, v, 4 * sizeof(GLfloat) * count);
+
+    return true;
+}
+
+bool Program::setUniformMatrix2fv(GLint location, GLsizei count, const GLfloat *value)
+{
+    if (location < 0 || location >= (int)mUniforms.size())
+    {
+        return false;
+    }
+
+    if (mUniforms[location]->type != UNIFORM_MATRIX_2FV || mUniforms[location]->bytes < 4 * sizeof(GLfloat) * count)
+    {
+        return false;
+    }
+
+    memcpy(mUniforms[location]->data, value, 4 * sizeof(GLfloat) * count);
+
+    return true;
+}
+
+bool Program::setUniformMatrix3fv(GLint location, GLsizei count, const GLfloat *value)
+{
+    if (location < 0 || location >= (int)mUniforms.size())
+    {
+        return false;
+    }
+
+    if (mUniforms[location]->type != UNIFORM_MATRIX_3FV || mUniforms[location]->bytes < 9 * sizeof(GLfloat) * count)
+    {
+        return false;
+    }
+
+    memcpy(mUniforms[location]->data, value, 9 * sizeof(GLfloat) * count);
+
+    return true;
+}
+
+bool Program::setUniformMatrix4fv(GLint location, GLsizei count, const GLfloat *value)
+{
+    if (location < 0 || location >= (int)mUniforms.size())
+    {
+        return false;
+    }
+
+    if (mUniforms[location]->type != UNIFORM_MATRIX_4FV || mUniforms[location]->bytes <  16 * sizeof(GLfloat) * count)
+    {
+        return false;
+    }
+
+    memcpy(mUniforms[location]->data, value, 16 * sizeof(GLfloat) * count);
+
+    return true;
+}
+
+bool Program::setUniform1iv(GLint location, GLsizei count, const GLint *v)
+{
+    if (location < 0 || location >= (int)mUniforms.size())
+    {
+        return false;
+    }
+
+    if (mUniforms[location]->type != UNIFORM_1IV || mUniforms[location]->bytes < sizeof(GLint) * count)
+    {
+        return false;
+    }
+
+    memcpy(mUniforms[location]->data, v, sizeof(GLint) * count);
+
+    return true;
+}
+
+// Applies all the uniforms set for this program object to the Direct3D 9 device
+void Program::applyUniforms()
+{
+    for (unsigned int location = 0; location < mUniforms.size(); location++)
+    {
+        int bytes = mUniforms[location]->bytes;
+        GLfloat *f = (GLfloat*)mUniforms[location]->data;
+        GLint *i = (GLint*)mUniforms[location]->data;
+
+        switch (mUniforms[location]->type)
+        {
+          case UNIFORM_1FV:        applyUniform1fv(location, bytes / sizeof(GLfloat), f);            break;
+          case UNIFORM_2FV:        applyUniform2fv(location, bytes / 2 / sizeof(GLfloat), f);        break;
+          case UNIFORM_3FV:        applyUniform3fv(location, bytes / 3 / sizeof(GLfloat), f);        break;
+          case UNIFORM_4FV:        applyUniform4fv(location, bytes / 4 / sizeof(GLfloat), f);        break;
+          case UNIFORM_MATRIX_2FV: applyUniformMatrix2fv(location, bytes / 4 / sizeof(GLfloat), f);  break;
+          case UNIFORM_MATRIX_3FV: applyUniformMatrix3fv(location, bytes / 9 / sizeof(GLfloat), f);  break;
+          case UNIFORM_MATRIX_4FV: applyUniformMatrix4fv(location, bytes / 16 / sizeof(GLfloat), f); break;
+          case UNIFORM_1IV:        applyUniform1iv(location, bytes / sizeof(GLint), i);              break;
+          default:
+            UNIMPLEMENTED();   // FIXME
+            UNREACHABLE();
+        }
+    }
+}
+
+// Compiles the HLSL code of the attached shaders into executable binaries
+ID3DXBuffer *Program::compileToBinary(const char *hlsl, const char *profile, ID3DXConstantTable **constantTable)
+{
+    if (!hlsl)
+    {
+        return NULL;
+    }
+
+    ID3DXBuffer *binary = NULL;
+    ID3DXBuffer *errorMessage = NULL;
+
+    HRESULT result = D3DXCompileShader(hlsl, (UINT)strlen(hlsl), NULL, 0, "main", profile, D3DXSHADER_USE_LEGACY_D3DX9_31_DLL, &binary, &errorMessage, constantTable);
+
+    if (SUCCEEDED(result))
+    {
+        return binary;
+    }
+
+    if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY)
+    {
+        return error(GL_OUT_OF_MEMORY, (ID3DXBuffer*)NULL);
+    }
+
+    if (errorMessage)
+    {
+        const char *message = (const char*)errorMessage->GetBufferPointer();
+        trace(hlsl);
+        trace(message);
+    }
+
+    return NULL;
+}
+
+// Links the HLSL 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()
+{
+    if (mLinked)
+    {
+        return;
+    }
+
+    unlink();
+
+    if (!mFragmentShader || !mFragmentShader->isCompiled())
+    {
+        return;
+    }
+
+    if (!mVertexShader || !mVertexShader->isCompiled())
+    {
+        return;
+    }
+
+    const char *pixelHLSL = mFragmentShader->linkHLSL();
+    const char *vertexHLSL = mVertexShader->linkHLSL(pixelHLSL);
+    ID3DXBuffer *vertexBinary = compileToBinary(vertexHLSL, "vs_2_0", &mConstantTableVS);
+    ID3DXBuffer *pixelBinary = compileToBinary(pixelHLSL, "ps_2_0", &mConstantTablePS);
+
+    if (vertexBinary && pixelBinary)
+    {
+        IDirect3DDevice9 *device = getDevice();
+        HRESULT vertexResult = device->CreateVertexShader((DWORD*)vertexBinary->GetBufferPointer(), &mVertexExecutable);
+        HRESULT pixelResult = device->CreatePixelShader((DWORD*)pixelBinary->GetBufferPointer(), &mPixelExecutable);
+
+        if (vertexResult == D3DERR_OUTOFVIDEOMEMORY || vertexResult == E_OUTOFMEMORY || pixelResult == D3DERR_OUTOFVIDEOMEMORY || pixelResult == E_OUTOFMEMORY)
+        {
+            return error(GL_OUT_OF_MEMORY);
+        }
+
+        ASSERT(SUCCEEDED(vertexResult) && SUCCEEDED(pixelResult));
+        
+        vertexBinary->Release();
+        pixelBinary->Release();
+        vertexBinary = NULL;
+        pixelBinary = NULL;
+
+        if (mVertexExecutable && mPixelExecutable)
+        {
+            if (!linkAttributes())
+            {
+                return;
+            }
+
+            D3DXCONSTANTTABLE_DESC constantTableDescription;
+            D3DXCONSTANT_DESC constantDescription;
+            UINT descriptionCount = 1;
+            
+            mConstantTablePS->GetDesc(&constantTableDescription);
+
+            for (unsigned int constantIndex = 0; constantIndex < constantTableDescription.Constants; constantIndex++)
+            {
+                D3DXHANDLE constantHandle = mConstantTablePS->GetConstant(0, constantIndex);
+                mConstantTablePS->GetConstantDesc(constantHandle, &constantDescription, &descriptionCount);
+                
+                UniformArray::iterator uniform = mUniforms.begin();
+
+                while (uniform != mUniforms.end())
+                {
+                    if ((*uniform)->name == constantDescription.Name)
+                    {
+                        UNREACHABLE();   // Redefinition; detect at compile
+                    }
+
+                    uniform++;
+                }
+
+                if (uniform == mUniforms.end())
+                {
+                    defineUniform(constantDescription);
+                }
+            }
+
+            mConstantTableVS->GetDesc(&constantTableDescription);
+
+            for (unsigned int constantIndex = 0; constantIndex < constantTableDescription.Constants; constantIndex++)
+            {
+                D3DXHANDLE constantHandle = mConstantTableVS->GetConstant(0, constantIndex);
+                mConstantTableVS->GetConstantDesc(constantHandle, &constantDescription, &descriptionCount);
+
+                UniformArray::iterator uniform = mUniforms.begin();
+
+                while (uniform != mUniforms.end())
+                {
+                    if ((*uniform)->name == constantDescription.Name)
+                    {
+                        UNIMPLEMENTED();   // FIXME: Verify it's the same type as the fragment uniform
+
+                        if (true)
+                        {
+                            break;
+                        }
+                        else
+                        {
+                            return;
+                        }
+                    }
+
+                    uniform++;
+                }
+
+                if (uniform == mUniforms.end())
+                {
+                    defineUniform(constantDescription);
+                }
+            }
+
+            mLinked = true;
+
+            return;
+        }
+    }
+}
+
+// Determines the mapping between GL attributes and Direct3D 9 vertex stream usage indices
+bool Program::linkAttributes()
+{
+    for (int attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; attributeIndex++)
+    {
+        const char *name = mVertexShader->getAttributeName(attributeIndex);
+
+        if (name)
+        {
+            GLuint location = getAttributeLocation(name);
+
+            if (location == -1)   // Not set by glBindAttribLocation
+            {
+                int availableIndex = 0;
+
+                while (availableIndex < MAX_VERTEX_ATTRIBS && mAttributeName[availableIndex] && mVertexShader->isActiveAttribute(mAttributeName[availableIndex]))
+                {
+                    availableIndex++;
+                }
+
+                if (availableIndex == MAX_VERTEX_ATTRIBS)
+                {
+                    return false;   // Fail to link
+                }
+
+                delete[] mAttributeName[availableIndex];
+                mAttributeName[availableIndex] = new char[strlen(name) + 1];   // FIXME: Check allocation
+                strcpy(mAttributeName[availableIndex], name);
+            }
+        }
+    }
+
+    for (int attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; attributeIndex++)
+    {
+        mInputMapping[attributeIndex] = mVertexShader->getInputMapping(mAttributeName[attributeIndex]);
+    }
+
+    return true;
+}
+
+// Adds the description of a constant found in the binary shader to the list of uniforms
+void Program::defineUniform(const D3DXCONSTANT_DESC &constantDescription)
+{
+    if (constantDescription.Rows == 1)   // Vectors and scalars
+    {
+        switch (constantDescription.Type)
+        {
+          case D3DXPT_SAMPLER2D:
+          case D3DXPT_SAMPLERCUBE:
+          case D3DXPT_BOOL:
+            switch (constantDescription.Columns)
+            {
+              case 1:
+                mUniforms.push_back(new Uniform(UNIFORM_1IV, constantDescription.Name, 1 * sizeof(GLint) * constantDescription.Elements));
+                break;
+              default:
+                UNIMPLEMENTED();   // FIXME
+                UNREACHABLE();
+            }
+            break;
+          case D3DXPT_FLOAT:
+            switch (constantDescription.Columns)
+            {
+              case 1:
+                mUniforms.push_back(new Uniform(UNIFORM_1FV, constantDescription.Name, 1 * sizeof(GLfloat) * constantDescription.Elements));
+                break;
+              case 2:
+                mUniforms.push_back(new Uniform(UNIFORM_2FV, constantDescription.Name, 2 * sizeof(GLfloat) * constantDescription.Elements));
+                break;
+              case 3:
+                mUniforms.push_back(new Uniform(UNIFORM_3FV, constantDescription.Name, 3 * sizeof(GLfloat) * constantDescription.Elements));
+                break;
+              case 4:
+                mUniforms.push_back(new Uniform(UNIFORM_4FV, constantDescription.Name, 4 * sizeof(GLfloat) * constantDescription.Elements));
+                break;
+              default: UNREACHABLE();
+            }
+            break;
+          default:
+            UNIMPLEMENTED();   // FIXME
+            UNREACHABLE();
+        }
+    }
+    else if (constantDescription.Rows == constantDescription.Columns)  // Square matrices
+    {
+        switch (constantDescription.Type)
+        {
+          case D3DXPT_FLOAT:
+            switch (constantDescription.Rows)
+            {
+              case 2:
+                mUniforms.push_back(new Uniform(UNIFORM_MATRIX_2FV, constantDescription.Name, 2 * 2 * sizeof(GLfloat) * constantDescription.Elements));
+                break;
+              case 3:
+                mUniforms.push_back(new Uniform(UNIFORM_MATRIX_3FV, constantDescription.Name, 3 * 3 * sizeof(GLfloat) * constantDescription.Elements));
+                break;
+              case 4:
+                mUniforms.push_back(new Uniform(UNIFORM_MATRIX_4FV, constantDescription.Name, 4 * 4 * sizeof(GLfloat) * constantDescription.Elements));
+                break;
+              default: UNREACHABLE();
+            }
+            break;
+          default: UNREACHABLE();
+        }
+    }
+    else UNREACHABLE();
+}
+
+bool Program::applyUniform1fv(GLint location, GLsizei count, const GLfloat *v)
+{
+    D3DXHANDLE constantPS = mConstantTablePS->GetConstantByName(0, mUniforms[location]->name.c_str());
+    D3DXHANDLE constantVS = mConstantTableVS->GetConstantByName(0, mUniforms[location]->name.c_str());
+    IDirect3DDevice9 *device = getDevice();
+
+    if (constantPS)
+    {
+        mConstantTablePS->SetFloatArray(device, constantPS, v, count);
+    }
+
+    if (constantVS)
+    {
+        mConstantTableVS->SetFloatArray(device, constantVS, v, count);
+    }
+
+    return true;
+}
+
+bool Program::applyUniform2fv(GLint location, GLsizei count, const GLfloat *v)
+{
+    D3DXVECTOR4 *vector = new D3DXVECTOR4[count];
+
+    for (int i = 0; i < count; i++)
+    {
+        vector[i] = D3DXVECTOR4(v[0], v[1], 0, 0);
+
+        v += 2;
+    }
+
+    D3DXHANDLE constantPS = mConstantTablePS->GetConstantByName(0, mUniforms[location]->name.c_str());
+    D3DXHANDLE constantVS = mConstantTableVS->GetConstantByName(0, mUniforms[location]->name.c_str());
+    IDirect3DDevice9 *device = getDevice();
+
+    if (constantPS)
+    {
+        mConstantTablePS->SetVectorArray(device, constantPS, vector, count);
+    }
+
+    if (constantVS)
+    {
+        mConstantTableVS->SetVectorArray(device, constantVS, vector, count);
+    }
+
+    delete[] vector;
+
+    return true;
+}
+
+bool Program::applyUniform3fv(GLint location, GLsizei count, const GLfloat *v)
+{
+    D3DXVECTOR4 *vector = new D3DXVECTOR4[count];
+
+    for (int i = 0; i < count; i++)
+    {
+        vector[i] = D3DXVECTOR4(v[0], v[1], v[2], 0);
+
+        v += 3;
+    }
+
+    D3DXHANDLE constantPS = mConstantTablePS->GetConstantByName(0, mUniforms[location]->name.c_str());
+    D3DXHANDLE constantVS = mConstantTableVS->GetConstantByName(0, mUniforms[location]->name.c_str());
+    IDirect3DDevice9 *device = getDevice();
+
+    if (constantPS)
+    {
+        mConstantTablePS->SetVectorArray(device, constantPS, vector, count);
+    }
+
+    if (constantVS)
+    {
+        mConstantTableVS->SetVectorArray(device, constantVS, vector, count);
+    }
+
+    delete[] vector;
+
+    return true;
+}
+
+bool Program::applyUniform4fv(GLint location, GLsizei count, const GLfloat *v)
+{
+    D3DXHANDLE constantPS = mConstantTablePS->GetConstantByName(0, mUniforms[location]->name.c_str());
+    D3DXHANDLE constantVS = mConstantTableVS->GetConstantByName(0, mUniforms[location]->name.c_str());
+    IDirect3DDevice9 *device = getDevice();
+
+    if (constantPS)
+    {
+        mConstantTablePS->SetVectorArray(device, constantPS, (D3DXVECTOR4*)v, count);
+    }
+
+    if (constantVS)
+    {
+        mConstantTableVS->SetVectorArray(device, constantVS, (D3DXVECTOR4*)v, count);
+    }
+
+    return true;
+}
+
+bool Program::applyUniformMatrix2fv(GLint location, GLsizei count, const GLfloat *value)
+{
+    D3DXMATRIX *matrix = new D3DXMATRIX[count];
+
+    for (int i = 0; i < count; i++)
+    {
+        matrix[i] = D3DXMATRIX(value[0], value[2], 0, 0,
+                               value[1], value[3], 0, 0,
+                               0,        0,        1, 0,
+                               0,        0,        0, 1);
+
+        value += 4;
+    }
+
+    D3DXHANDLE constantPS = mConstantTablePS->GetConstantByName(0, mUniforms[location]->name.c_str());
+    D3DXHANDLE constantVS = mConstantTableVS->GetConstantByName(0, mUniforms[location]->name.c_str());
+    IDirect3DDevice9 *device = getDevice();
+
+    if (constantPS)
+    {
+        mConstantTablePS->SetMatrixArray(device, constantPS, matrix, count);
+    }
+
+    if (constantVS)
+    {
+        mConstantTableVS->SetMatrixArray(device, constantVS, matrix, count);
+    }
+
+    delete[] matrix;
+
+    return true;
+}
+
+bool Program::applyUniformMatrix3fv(GLint location, GLsizei count, const GLfloat *value)
+{
+    D3DXMATRIX *matrix = new D3DXMATRIX[count];
+
+    for (int i = 0; i < count; i++)
+    {
+        matrix[i] = D3DXMATRIX(value[0], value[3], value[6], 0,
+                               value[1], value[4], value[7], 0,
+                               value[2], value[5], value[8], 0,
+                               0,        0,        0,        1);
+
+        value += 9;
+    }
+
+    D3DXHANDLE constantPS = mConstantTablePS->GetConstantByName(0, mUniforms[location]->name.c_str());
+    D3DXHANDLE constantVS = mConstantTableVS->GetConstantByName(0, mUniforms[location]->name.c_str());
+    IDirect3DDevice9 *device = getDevice();
+
+    if (constantPS)
+    {
+        mConstantTablePS->SetMatrixArray(device, constantPS, matrix, count);
+    }
+
+    if (constantVS)
+    {
+        mConstantTableVS->SetMatrixArray(device, constantVS, matrix, count);
+    }
+
+    delete[] matrix;
+
+    return true;
+}
+
+bool Program::applyUniformMatrix4fv(GLint location, GLsizei count, const GLfloat *value)
+{
+    D3DXMATRIX *matrix = new D3DXMATRIX[count];
+
+    for (int i = 0; i < count; i++)
+    {
+        matrix[i] = D3DXMATRIX(value[0], value[4], value[8],  value[12],
+                               value[1], value[5], value[9],  value[13],
+                               value[2], value[6], value[10], value[14],
+                               value[3], value[7], value[11], value[15]);
+
+        value += 16;
+    }
+
+    D3DXHANDLE constantPS = mConstantTablePS->GetConstantByName(0, mUniforms[location]->name.c_str());
+    D3DXHANDLE constantVS = mConstantTableVS->GetConstantByName(0, mUniforms[location]->name.c_str());
+    IDirect3DDevice9 *device = getDevice();
+
+    if (constantPS)
+    {
+        mConstantTablePS->SetMatrixArray(device, constantPS, matrix, count);
+    }
+
+    if (constantVS)
+    {
+        mConstantTableVS->SetMatrixArray(device, constantVS, matrix, count);
+    }
+
+    delete[] matrix;
+
+    return true;
+}
+
+bool Program::applyUniform1iv(GLint location, GLsizei count, const GLint *v)
+{
+    D3DXHANDLE constantPS = mConstantTablePS->GetConstantByName(0, mUniforms[location]->name.c_str());
+    D3DXHANDLE constantVS = mConstantTableVS->GetConstantByName(0, mUniforms[location]->name.c_str());
+    IDirect3DDevice9 *device = getDevice();
+
+    if (constantPS)
+    {
+        D3DXCONSTANT_DESC constantDescription;
+        UINT descriptionCount = 1;
+        HRESULT result = mConstantTablePS->GetConstantDesc(constantPS, &constantDescription, &descriptionCount);
+
+        if (SUCCEEDED(result))
+        {
+            return false;
+        }
+
+        if (constantDescription.RegisterSet == D3DXRS_SAMPLER)
+        {
+            unsigned int firstIndex = mConstantTablePS->GetSamplerIndex(constantPS);
+
+            for (unsigned int samplerIndex = firstIndex; samplerIndex < firstIndex + count; samplerIndex++)
+            {
+                GLint mappedSampler = v[0];
+            
+                if (mappedSampler >= 0 && mappedSampler < MAX_TEXTURE_IMAGE_UNITS)
+                {
+                    if (samplerIndex >= 0 && samplerIndex < MAX_TEXTURE_IMAGE_UNITS)
+                    {
+                        mSamplerMapping[samplerIndex] = mappedSampler;
+                    }
+                }
+            }
+            
+            return true;
+        }
+    }
+
+    if (constantPS)
+    {
+        mConstantTablePS->SetIntArray(device, constantPS, v, count);
+    }
+
+    if (constantVS)
+    {
+        mConstantTableVS->SetIntArray(device, constantVS, v, count);
+    }
+
+    return true;
+}
+
+// Returns the program object to an unlinked state, after detaching a shader, before re-linking, or at destruction
+void Program::unlink(bool destroy)
+{
+    if (destroy)   // Object being destructed
+    {
+        if (mFragmentShader)
+        {
+            mFragmentShader->detach();
+            mFragmentShader = NULL;
+        }
+
+        if (mVertexShader)
+        {
+            mVertexShader->detach();
+            mVertexShader = NULL;
+        }
+
+        for (int index = 0; index < MAX_VERTEX_ATTRIBS; index++)
+        {
+            delete[] mAttributeName[index];
+            mAttributeName[index] = NULL;
+        }
+    }
+
+    if (mPixelExecutable)
+    {
+        mPixelExecutable->Release();
+        mPixelExecutable = NULL;
+    }
+
+    if (mVertexExecutable)
+    {
+        mVertexExecutable->Release();
+        mVertexExecutable = NULL;
+    }
+
+    if (mConstantTablePS)
+    {
+        mConstantTablePS->Release();
+        mConstantTablePS = NULL;
+    }
+
+    if (mConstantTableVS)
+    {
+        mConstantTableVS->Release();
+        mConstantTableVS = NULL;
+    }
+
+    for (int index = 0; index < MAX_VERTEX_ATTRIBS; index++)
+    {
+        mInputMapping[index] = 0;
+    }
+
+    for (int index = 0; index < MAX_TEXTURE_IMAGE_UNITS; index++)
+    {
+        mSamplerMapping[index] = 0;
+    }
+
+    while (!mUniforms.empty())
+    {
+        delete mUniforms.back();
+        mUniforms.pop_back();
+    }
+
+    mLinked = false;
+}
+
+bool Program::isLinked()
+{
+    return mLinked;
+}
+
+void Program::flagForDeletion()
+{
+    mDeleteStatus = true;
+}
+
+bool Program::isFlaggedForDeletion() const
+{
+    return mDeleteStatus;
+}
+}
diff --git a/libGLESv2/Program.h b/libGLESv2/Program.h
new file mode 100644
index 0000000..20f4caa
--- /dev/null
+++ b/libGLESv2/Program.h
@@ -0,0 +1,129 @@
+//
+// 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.
+//
+
+// Program.h: Defines the gl::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 "Context.h"
+
+#include <d3dx9.h>
+#include <string>
+#include <vector>
+
+namespace gl
+{
+class FragmentShader;
+class VertexShader;
+
+enum UniformType
+{
+    UNIFORM_1FV,
+    UNIFORM_2FV,
+    UNIFORM_3FV,
+    UNIFORM_4FV,
+    UNIFORM_MATRIX_2FV,
+    UNIFORM_MATRIX_3FV,
+    UNIFORM_MATRIX_4FV,
+    UNIFORM_1IV
+};
+
+// Helper class representing a single shader uniform
+class Uniform
+{
+  public:
+    Uniform(UniformType type, const std::string &name, unsigned int bytes);
+
+    ~Uniform();
+
+    const UniformType type;
+    const std::string name;
+    const unsigned int bytes;
+    unsigned char *data;
+
+  private:
+    DISALLOW_COPY_AND_ASSIGN(Uniform);
+};
+
+class Program
+{
+  public:
+    Program();
+
+    ~Program();
+
+    bool attachShader(Shader *shader);
+    bool detachShader(Shader *shader);
+
+    IDirect3DPixelShader9 *getPixelShader();
+    IDirect3DVertexShader9 *getVertexShader();
+
+    void bindAttributeLocation(GLuint index, const char *name);
+    GLuint getAttributeLocation(const char *name);
+    bool isActiveAttribute(int attributeIndex);
+    int getInputMapping(int attributeIndex);
+
+    GLint getSamplerMapping(unsigned int samplerIndex);
+
+    GLint getUniformLocation(const char *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);
+
+    void applyUniforms();
+    
+    void link();
+    bool isLinked();
+
+    void flagForDeletion();
+    bool isFlaggedForDeletion() const;
+
+  private:
+    DISALLOW_COPY_AND_ASSIGN(Program);
+
+    ID3DXBuffer *compileToBinary(const char *hlsl, const char *profile, ID3DXConstantTable **constantTable);
+    void unlink(bool destroy = false);
+
+    bool linkAttributes();
+    void defineUniform(const D3DXCONSTANT_DESC &constantDescription);
+    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);
+
+    FragmentShader *mFragmentShader;
+    VertexShader *mVertexShader;
+
+    IDirect3DPixelShader9 *mPixelExecutable;
+    IDirect3DVertexShader9 *mVertexExecutable;
+    ID3DXConstantTable *mConstantTablePS;
+    ID3DXConstantTable *mConstantTableVS;
+
+    char *mAttributeName[MAX_VERTEX_ATTRIBS];
+    int mInputMapping[MAX_VERTEX_ATTRIBS];
+
+    GLint mSamplerMapping[MAX_TEXTURE_IMAGE_UNITS];
+
+    typedef std::vector<Uniform*> UniformArray;
+    UniformArray mUniforms;
+
+    bool mLinked;
+    bool mDeleteStatus;   // Flag to indicate that the program can be deleted when no longer in use
+};
+}
+
+#endif   // LIBGLESV2_PROGRAM_H_
diff --git a/libGLESv2/Renderbuffer.cpp b/libGLESv2/Renderbuffer.cpp
new file mode 100644
index 0000000..b44cab1
--- /dev/null
+++ b/libGLESv2/Renderbuffer.cpp
@@ -0,0 +1,264 @@
+//
+// 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.
+//
+
+// Renderbuffer.cpp: the gl::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 "utilities.h"
+
+namespace gl
+{
+Renderbuffer::Renderbuffer()
+{
+    mWidth = 0;
+    mHeight = 0;
+}
+
+Renderbuffer::~Renderbuffer()
+{
+}
+
+bool Renderbuffer::isColorbuffer()
+{
+    return false;
+}
+
+bool Renderbuffer::isDepthbuffer()
+{
+    return false;
+}
+
+bool Renderbuffer::isStencilbuffer()
+{
+    return false;
+}
+
+IDirect3DSurface9 *Renderbuffer::getRenderTarget()
+{
+    return NULL;
+}
+
+IDirect3DSurface9 *Renderbuffer::getDepthStencil()
+{
+    return NULL;
+}
+
+int Renderbuffer::getWidth()
+{
+    return mWidth;
+}
+
+int Renderbuffer::getHeight()
+{
+    return mHeight;
+}
+
+Colorbuffer::Colorbuffer(IDirect3DSurface9 *renderTarget) : mRenderTarget(renderTarget)
+{
+    if (renderTarget)
+    {
+        renderTarget->AddRef();
+
+        D3DSURFACE_DESC description;
+        renderTarget->GetDesc(&description);
+
+        mWidth = description.Width;
+        mHeight = description.Height;
+    }
+}
+
+Colorbuffer::~Colorbuffer()
+{
+    if (mRenderTarget)
+    {
+        mRenderTarget->Release();
+    }
+}
+
+bool Colorbuffer::isColorbuffer()
+{
+    return true;
+}
+
+GLuint Colorbuffer::getRedSize()
+{
+    if (mRenderTarget)
+    {
+        D3DSURFACE_DESC description;
+        mRenderTarget->GetDesc(&description);
+
+        return es2dx::GetRedSize(description.Format);
+    }
+
+    return 0;
+}
+
+GLuint Colorbuffer::getGreenSize()
+{
+    if (mRenderTarget)
+    {
+        D3DSURFACE_DESC description;
+        mRenderTarget->GetDesc(&description);
+
+        return es2dx::GetGreenSize(description.Format);
+    }
+
+    return 0;
+}
+
+GLuint Colorbuffer::getBlueSize()
+{
+    if (mRenderTarget)
+    {
+        D3DSURFACE_DESC description;
+        mRenderTarget->GetDesc(&description);
+
+        return es2dx::GetBlueSize(description.Format);
+    }
+
+    return 0;
+}
+
+GLuint Colorbuffer::getAlphaSize()
+{
+    if (mRenderTarget)
+    {
+        D3DSURFACE_DESC description;
+        mRenderTarget->GetDesc(&description);
+
+        return es2dx::GetAlphaSize(description.Format);
+    }
+
+    return 0;
+}
+
+IDirect3DSurface9 *Colorbuffer::getRenderTarget()
+{
+    return mRenderTarget;
+}
+
+Depthbuffer::Depthbuffer(IDirect3DSurface9 *depthStencil) : mDepthStencil(depthStencil)
+{
+    if (depthStencil)
+    {
+        depthStencil->AddRef();
+
+        D3DSURFACE_DESC description;
+        depthStencil->GetDesc(&description);
+
+        mWidth = description.Width;
+        mHeight = description.Height;
+    }
+}
+
+Depthbuffer::Depthbuffer(int width, int height)
+{
+    IDirect3DDevice9 *device = getDevice();
+
+    mDepthStencil = NULL;
+    HRESULT result = device->CreateDepthStencilSurface(width, height, D3DFMT_D24S8, D3DMULTISAMPLE_NONE, 0, FALSE, &mDepthStencil, 0);
+
+    if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY)
+    {
+        error(GL_OUT_OF_MEMORY);
+
+        return;
+    }
+
+    ASSERT(SUCCEEDED(result));
+
+    if (mDepthStencil)
+    {
+        mWidth = width;
+        mHeight = height;
+    }
+    else
+    {
+        mWidth = 0;
+        mHeight = 0;
+    }
+}
+
+Depthbuffer::~Depthbuffer()
+{
+    if (mDepthStencil)
+    {
+        mDepthStencil->Release();
+    }
+}
+
+bool Depthbuffer::isDepthbuffer()
+{
+    return true;
+}
+
+GLuint Depthbuffer::getDepthSize()
+{
+    if (mDepthStencil)
+    {
+        D3DSURFACE_DESC description;
+        mDepthStencil->GetDesc(&description);
+
+        es2dx::GetDepthSize(description.Format);
+    }
+
+    return 0;
+}
+
+IDirect3DSurface9 *Depthbuffer::getDepthStencil()
+{
+    return mDepthStencil;
+}
+
+Stencilbuffer::Stencilbuffer(IDirect3DSurface9 *depthStencil) : mDepthStencil(depthStencil)
+ {
+    if (depthStencil)
+    {
+        depthStencil->AddRef();
+
+        D3DSURFACE_DESC description;
+        depthStencil->GetDesc(&description);
+
+        mWidth = description.Width;
+        mHeight = description.Height;
+    }
+ }
+
+Stencilbuffer::~Stencilbuffer()
+{
+    if (mDepthStencil)
+    {
+        mDepthStencil->Release();
+    }
+}
+
+GLuint Stencilbuffer::getStencilSize()
+{
+    if (mDepthStencil)
+    {
+        D3DSURFACE_DESC description;
+        mDepthStencil->GetDesc(&description);
+
+        return es2dx::GetStencilSize(description.Format);
+    }
+
+    return 0;
+}
+
+bool Stencilbuffer::isStencilbuffer()
+{
+    return true;
+}
+
+IDirect3DSurface9 *Stencilbuffer::getDepthStencil()
+{
+    return mDepthStencil;
+}
+}
diff --git a/libGLESv2/Renderbuffer.h b/libGLESv2/Renderbuffer.h
new file mode 100644
index 0000000..c0210a6
--- /dev/null
+++ b/libGLESv2/Renderbuffer.h
@@ -0,0 +1,108 @@
+//
+// 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.
+//
+
+// Renderbuffer.h: Defines the virtual gl::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.
+
+#ifndef LIBGLESV2_RENDERBUFFER_H_
+#define LIBGLESV2_RENDERBUFFER_H_
+
+#define GL_APICALL
+#include <GLES2/gl2.h>
+#include <d3d9.h>
+
+#include "angleutils.h"
+
+namespace gl
+{
+class Renderbuffer
+{
+  public:
+    Renderbuffer();
+
+    virtual ~Renderbuffer();
+
+    virtual bool isColorbuffer();
+    virtual bool isDepthbuffer();
+    virtual bool isStencilbuffer();
+
+    virtual IDirect3DSurface9 *getRenderTarget();
+    virtual IDirect3DSurface9 *getDepthStencil();
+
+    int getWidth();
+    int getHeight();
+
+  protected:
+    int mWidth;
+    int mHeight;
+
+  private:
+    DISALLOW_COPY_AND_ASSIGN(Renderbuffer);
+};
+
+class Colorbuffer : public Renderbuffer
+{
+  public:
+    Colorbuffer(IDirect3DSurface9 *renderTarget);
+
+    ~Colorbuffer();
+
+    bool isColorbuffer();
+
+    GLuint getRedSize();
+    GLuint getGreenSize();
+    GLuint getBlueSize();
+    GLuint getAlphaSize();
+
+    IDirect3DSurface9 *getRenderTarget();
+
+  protected:
+    IDirect3DSurface9 *mRenderTarget;
+
+  private:
+    DISALLOW_COPY_AND_ASSIGN(Colorbuffer);
+};
+
+class Depthbuffer : public Renderbuffer
+{
+  public:
+    Depthbuffer(IDirect3DSurface9 *depthStencil);
+    Depthbuffer(int width, int height);
+
+    ~Depthbuffer();
+
+    bool isDepthbuffer();
+
+    GLuint getDepthSize();
+
+    IDirect3DSurface9 *getDepthStencil();
+
+  private:
+    DISALLOW_COPY_AND_ASSIGN(Depthbuffer);
+    IDirect3DSurface9 *mDepthStencil;
+};
+
+class Stencilbuffer : public Renderbuffer
+{
+  public:
+    Stencilbuffer(IDirect3DSurface9 *depthStencil);
+
+    ~Stencilbuffer();
+
+    bool isStencilbuffer();
+
+    GLuint getStencilSize();
+
+    IDirect3DSurface9 *getDepthStencil();
+
+  private:
+    DISALLOW_COPY_AND_ASSIGN(Stencilbuffer);
+    IDirect3DSurface9 *mDepthStencil;
+};
+}
+
+#endif   // LIBGLESV2_RENDERBUFFER_H_
diff --git a/libGLESv2/Shader.cpp b/libGLESv2/Shader.cpp
new file mode 100644
index 0000000..4ee2ce2
--- /dev/null
+++ b/libGLESv2/Shader.cpp
@@ -0,0 +1,337 @@
+//
+// 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.
+//
+
+// Shader.cpp: Implements the gl::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 "Shaderlang.h"
+#include "debug.h"
+
+namespace gl
+{
+void *Shader::mFragmentCompiler = NULL;
+void *Shader::mVertexCompiler = NULL;
+
+Shader::Shader()
+{
+    mSource = NULL;
+    mHlsl = NULL;
+    mErrors = NULL;
+
+    // Perform a one-time initialization of the shader compiler (or after being destructed by releaseCompiler)
+    if (!mFragmentCompiler)
+    {
+        int result = ShInitialize();
+
+        if (result)
+        {
+            mFragmentCompiler = ShConstructCompiler(EShLangFragment, EDebugOpObjectCode);
+            mVertexCompiler = ShConstructCompiler(EShLangVertex, EDebugOpObjectCode);
+        }
+    }
+
+    mAttachCount = 0;
+    mDeleteStatus = false;
+}
+
+Shader::~Shader()
+{
+    delete[] mSource;
+    delete[] mHlsl;
+    delete[] mErrors;
+}
+
+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';
+}
+
+bool Shader::isCompiled()
+{
+    return mHlsl != NULL;
+}
+
+const char *Shader::linkHLSL()
+{
+    return mHlsl;
+}
+
+void Shader::attach()
+{
+    mAttachCount++;
+}
+
+void Shader::detach()
+{
+    mAttachCount--;
+}
+
+bool Shader::isAttached() const
+{
+    return mAttachCount > 0;
+}
+
+bool Shader::isDeletable() const
+{
+    return mDeleteStatus == true && mAttachCount == 0;
+}
+
+void Shader::flagForDeletion()
+{
+    mDeleteStatus = true;
+}
+
+void Shader::releaseCompiler()
+{
+    ShDestruct(mFragmentCompiler);
+    ShDestruct(mVertexCompiler);
+
+    mFragmentCompiler = NULL;
+    mVertexCompiler = NULL;
+}
+
+void Shader::compileToHLSL(void *compiler)
+{
+    if (isCompiled() || !mSource)
+    {
+        return;
+    }
+
+    trace(mSource);
+
+    delete[] mErrors;
+    mErrors = NULL;
+
+    TBuiltInResource 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;
+
+    int result = ShCompile(compiler, &mSource, 1, EShOptNone, &resources, EDebugOpObjectCode);
+    const char *obj = ShGetObjectCode(compiler);
+    const char *info = ShGetInfoLog(compiler);
+
+    if (result)
+    {
+        mHlsl = new char[strlen(obj) + 1];
+        strcpy(mHlsl, obj);
+
+        trace(mHlsl);
+    }
+    else
+    {
+        mErrors = new char[strlen(info) + 1];
+        strcpy(mErrors, info);
+
+        trace(mErrors);
+    }
+}
+
+InputMapping::InputMapping()
+{
+    mAttribute = NULL;
+    mSemanticIndex = -1;
+}
+
+InputMapping::InputMapping(const char *attribute, int semanticIndex)
+{
+    mAttribute = new char[strlen(attribute) + 1];
+    strcpy(mAttribute, attribute);
+    mSemanticIndex = semanticIndex;
+}
+
+InputMapping &InputMapping::operator=(const InputMapping &inputMapping)
+{
+    delete[] mAttribute;
+
+    mAttribute = new char[strlen(inputMapping.mAttribute) + 1];
+    strcpy(mAttribute, inputMapping.mAttribute);
+    mSemanticIndex = inputMapping.mSemanticIndex;
+
+    return *this;
+}
+
+InputMapping::~InputMapping()
+{
+    delete[] mAttribute;
+}
+
+VertexShader::VertexShader()
+{
+}
+
+VertexShader::~VertexShader()
+{
+}
+
+GLenum VertexShader::getType()
+{
+    return GL_VERTEX_SHADER;
+}
+
+void VertexShader::compile()
+{
+    compileToHLSL(mVertexCompiler);
+    parseAttributes();
+}
+
+const char *VertexShader::linkHLSL(const char *pixelHLSL)
+{
+    if (mHlsl && pixelHLSL)
+    {
+        const char *input = strstr(pixelHLSL, "struct PS_INPUT");
+        char *output = strstr(mHlsl, "struct VS_OUTPUT");
+
+        while (*input != '}' && output)
+        {
+            char varyingName[100];
+            int semanticIndex;
+            int matches = sscanf(input, "%s : TEXCOORD%d;", varyingName, &semanticIndex);
+            
+            if (matches == 2)
+            {
+                ASSERT(semanticIndex < 10 && semanticIndex < MAX_VARYING_VECTORS);
+                char *varying = strstr(output, varyingName);
+                varying = strstr(varying, " : TEXCOORD0;");
+
+                if (output)
+                {
+                    varying[11] = '0' + semanticIndex;
+                }
+                else
+                {
+                    return NULL;
+                }
+
+                input = strstr(input, ";");
+            }
+
+            input++;
+        }
+    }
+
+    return mHlsl;
+}
+
+const char *VertexShader::getAttributeName(unsigned int attributeIndex)
+{
+    if (attributeIndex < MAX_VERTEX_ATTRIBS)
+    {
+        return mInputMapping[attributeIndex].mAttribute;
+    }
+
+    return 0;
+}
+
+bool VertexShader::isActiveAttribute(const char *attributeName)
+{
+    return getInputMapping(attributeName) != -1;
+}
+
+int VertexShader::getInputMapping(const char *attributeName)
+{
+    if (attributeName)
+    {
+        for (int index = 0; index < MAX_VERTEX_ATTRIBS; index++)
+        {
+            if (mInputMapping[index].mAttribute && strcmp(mInputMapping[index].mAttribute, attributeName) == 0)
+            {
+                return mInputMapping[index].mSemanticIndex;
+            }
+        }
+    }
+
+    return -1;
+}
+
+void VertexShader::parseAttributes()
+{
+    if (mHlsl)
+    {
+        const char *input = strstr(mHlsl, "struct VS_INPUT");
+
+        for (int attributeIndex = 0; *input != '}'; input++)
+        {
+            char attributeName[100];
+            int semanticIndex;
+
+            int matches = sscanf(input, "%s : TEXCOORD%d;", attributeName, &semanticIndex);
+
+            if (matches == 2)
+            {
+                ASSERT(attributeIndex < MAX_VERTEX_ATTRIBS);
+                mInputMapping[attributeIndex] = InputMapping(attributeName, semanticIndex);
+                attributeIndex++;
+
+                input = strstr(input, ";");
+            }
+        }
+    }
+}
+
+FragmentShader::FragmentShader()
+{
+}
+
+FragmentShader::~FragmentShader()
+{
+}
+
+GLenum FragmentShader::getType()
+{
+    return GL_FRAGMENT_SHADER;
+}
+
+void FragmentShader::compile()
+{
+    compileToHLSL(mFragmentCompiler);
+}
+}
diff --git a/libGLESv2/Shader.h b/libGLESv2/Shader.h
new file mode 100644
index 0000000..3bac7f8
--- /dev/null
+++ b/libGLESv2/Shader.h
@@ -0,0 +1,114 @@
+//
+// 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.
+//
+
+// Shader.h: Defines the abstract gl::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 "Context.h"
+
+#define GL_APICALL
+#include <GLES2/gl2.h>
+#include <d3dx9.h>
+
+namespace gl
+{
+class Shader
+{
+  public:
+    Shader();
+
+    virtual ~Shader();
+
+    virtual GLenum getType() = 0;
+
+    void deleteSource();
+    void setSource(GLsizei count, const char **string, const GLint *length);
+
+    virtual void compile() = 0;
+    bool isCompiled();
+    const char *linkHLSL();
+
+    void attach();
+    void detach();
+    bool isAttached() const;
+    bool isDeletable() const;
+    void flagForDeletion();
+
+    static void releaseCompiler();
+
+  protected:
+    DISALLOW_COPY_AND_ASSIGN(Shader);
+
+    void compileToHLSL(void *compiler);
+
+    int mAttachCount;     // 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
+
+    char *mSource;
+    char *mHlsl;
+    char *mErrors;
+
+    static void *mFragmentCompiler;
+    static void *mVertexCompiler;
+};
+
+class InputMapping
+{
+  public:
+    InputMapping();
+    InputMapping(const char *attribute, int semanticIndex);
+
+    ~InputMapping();
+
+    InputMapping &operator=(const InputMapping &inputMapping);
+
+    char *mAttribute;
+    int mSemanticIndex;   // TEXCOORDi
+};
+
+class VertexShader : public Shader
+{
+  public:
+    VertexShader();
+
+    ~VertexShader();
+
+    GLenum getType();
+    void compile();
+    const char *linkHLSL(const char *pixelHLSL);
+    const char *getAttributeName(unsigned int attributeIndex);
+    bool isActiveAttribute(const char *attributeName);
+    int getInputMapping(const char *attributeName);
+
+  private:
+    DISALLOW_COPY_AND_ASSIGN(VertexShader);
+
+    void parseAttributes();
+
+    InputMapping mInputMapping[MAX_VERTEX_ATTRIBS];
+};
+
+class FragmentShader : public Shader
+{
+  public:
+    FragmentShader();
+
+    ~FragmentShader();
+
+    GLenum getType();
+    void compile();
+
+  private:
+    DISALLOW_COPY_AND_ASSIGN(FragmentShader);
+};
+}
+
+#endif   // LIBGLESV2_SHADER_H_
diff --git a/libGLESv2/Texture.cpp b/libGLESv2/Texture.cpp
new file mode 100644
index 0000000..72e9282
--- /dev/null
+++ b/libGLESv2/Texture.cpp
@@ -0,0 +1,671 @@
+//
+// 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.
+//
+
+// Texture.cpp: Implements the gl::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 "debug.h"
+
+namespace gl
+{
+Texture::Texture() : Colorbuffer(0)
+{
+    mMinFilter = GL_NEAREST_MIPMAP_LINEAR;
+    mMagFilter = GL_LINEAR;
+    mWrapS = GL_REPEAT;
+    mWrapT = GL_REPEAT;
+}
+
+Texture::~Texture()
+{
+}
+
+// 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;
+    }
+}
+
+GLenum Texture::getMinFilter()
+{
+    return mMinFilter;
+}
+
+GLenum Texture::getMagFilter()
+{
+    return mMagFilter;
+}
+
+GLenum Texture::getWrapS()
+{
+    return mWrapS;
+}
+
+GLenum Texture::getWrapT()
+{
+    return mWrapT;
+}
+
+// Copies an Image into an already locked Direct3D 9 surface, performing format conversions as necessary
+void Texture::copyImage(D3DLOCKED_RECT &lock, D3DFORMAT format, Image &image)
+{
+    if (lock.pBits && image.pixels)
+    {
+        for (int y = 0; y < image.height; y++)
+        {
+            unsigned char *source = (unsigned char*)image.pixels + y * image.width * pixelSize(image);
+            unsigned short *source16 = (unsigned short*)source;
+            unsigned char *dest = (unsigned char*)lock.pBits + y * lock.Pitch;
+
+            for (int x = 0; x < image.width; x++)
+            {
+                unsigned char r;
+                unsigned char g;
+                unsigned char b;
+                unsigned char a;
+
+                switch (image.format)
+                {
+                  case GL_ALPHA:
+                    UNIMPLEMENTED();
+                    break;
+                  case GL_LUMINANCE:
+                    UNIMPLEMENTED();
+                    break;
+                  case GL_LUMINANCE_ALPHA:
+                    UNIMPLEMENTED();
+                    break;
+                  case GL_RGB:
+                    switch (image.type)
+                    {
+                      case GL_UNSIGNED_BYTE:          UNIMPLEMENTED(); break;
+                      case GL_UNSIGNED_SHORT_5_6_5:
+                        {
+                            unsigned short rgba = source16[x];
+
+                            a = 0xFF;
+                            b = ((rgba & 0x001F) << 3) | ((rgba & 0x001F) >> 2);
+                            g = ((rgba & 0x07E0) >> 3) | ((rgba & 0x07E0) >> 9);
+                            r = ((rgba & 0xF800) >> 8) | ((rgba & 0xF800) >> 13);
+                        }
+                        break;
+                      default: UNREACHABLE();
+                    }
+                    break;
+                  case GL_RGBA:
+                    switch (image.type)
+                    {
+                      case GL_UNSIGNED_BYTE:
+                        r = source[x * 4 + 0];
+                        g = source[x * 4 + 1];
+                        b = source[x * 4 + 2];
+                        a = source[x * 4 + 3];
+                        break;
+                      case GL_UNSIGNED_SHORT_4_4_4_4:
+                        {
+                            unsigned short rgba = source16[x];
+
+                            a = ((rgba & 0x000F) << 4) | ((rgba & 0x000F) >> 0);
+                            b = ((rgba & 0x00F0) << 0) | ((rgba & 0x00F0) >> 4);
+                            g = ((rgba & 0x0F00) >> 4) | ((rgba & 0x0F00) >> 8);
+                            r = ((rgba & 0xF000) >> 8) | ((rgba & 0xF000) >> 12);
+                        }
+                        break;
+                      case GL_UNSIGNED_SHORT_5_5_5_1:    UNIMPLEMENTED();            break;
+                      default: UNREACHABLE();
+                    }
+                    break;
+                  default: UNREACHABLE();
+                }
+
+                switch (format)
+                {
+                  case D3DFMT_A8R8G8B8:
+                    dest[4 * x + 0] = b;
+                    dest[4 * x + 1] = g;
+                    dest[4 * x + 2] = r;
+                    dest[4 * x + 3] = a;
+                    break;
+                  default: UNREACHABLE();
+                }
+            }
+        }
+    }
+}
+
+// Selects an internal Direct3D 9 format for storing an Image
+D3DFORMAT Texture::selectFormat(const Image &image)
+{
+    switch (image.format)
+    {
+      case GL_ALPHA:
+        UNIMPLEMENTED();
+        break;
+      case GL_LUMINANCE:
+        UNIMPLEMENTED();
+        break;
+      case GL_LUMINANCE_ALPHA:
+        UNIMPLEMENTED();
+        break;
+      case GL_RGB:
+        switch (image.type)
+        {
+          case GL_UNSIGNED_BYTE:        UNIMPLEMENTED();
+          case GL_UNSIGNED_SHORT_5_6_5: return D3DFMT_A8R8G8B8;
+          default: UNREACHABLE();
+        }
+        break;
+      case GL_RGBA:
+        switch (image.type)
+        {
+          case GL_UNSIGNED_BYTE:          return D3DFMT_A8R8G8B8;
+          case GL_UNSIGNED_SHORT_4_4_4_4: return D3DFMT_A8R8G8B8;
+          case GL_UNSIGNED_SHORT_5_5_5_1: UNIMPLEMENTED();
+          default: UNREACHABLE();
+        }
+        break;
+      default: UNREACHABLE();
+    }
+
+    return D3DFMT_UNKNOWN;
+}
+
+// Returns the size, in bytes, of a single texel in an Image
+int Texture::pixelSize(const Image &image)
+{
+    switch (image.type)
+    {
+      case GL_UNSIGNED_BYTE:
+        switch (image.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;
+          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:
+        return sizeof(unsigned short);
+      default: UNREACHABLE();
+    }
+
+    return 0;
+}
+
+Texture2D::Texture2D()
+{
+    for (int level = 0; level < MAX_TEXTURE_LEVELS; level++)
+    {
+        mImageArray[level].pixels = NULL;
+    }
+
+    mTexture = NULL;
+}
+
+Texture2D::~Texture2D()
+{
+    for (int level = 0; level < MAX_TEXTURE_LEVELS; level++)
+    {
+        delete[] mImageArray[level].pixels;
+    }
+
+    if (mTexture)
+    {
+        mTexture->Release();
+        mTexture = NULL;
+    }
+}
+
+GLenum Texture2D::getTarget() const
+{
+    return GL_TEXTURE_2D;
+}
+
+void Texture2D::setImage(GLint level, GLenum internalFormat, GLsizei width, GLsizei height, GLenum format, GLenum type, const void *pixels)
+{
+    if (level < 0 || level >= MAX_TEXTURE_LEVELS)
+    {
+        return;
+    }
+
+    mImageArray[level].internalFormat = internalFormat;
+    mImageArray[level].width = width;
+    mImageArray[level].height = height;
+    mImageArray[level].format = format;
+    mImageArray[level].type = type;
+
+    delete[] mImageArray[level].pixels;
+    mImageArray[level].pixels = NULL;
+
+    int imageSize = pixelSize(mImageArray[level]) * width * height;
+    mImageArray[level].pixels = new unsigned char[imageSize];
+
+    if(pixels)
+    {
+        memcpy(mImageArray[level].pixels, pixels, imageSize);
+    }
+
+    if (level == 0)
+    {
+        mWidth = width;
+        mHeight = height;
+    }
+}
+
+// Tests for GL texture object completeness. [OpenGL ES 2.0.24] section 3.7.10 page 81.
+bool Texture2D::isComplete()
+{
+    if (mWidth <= 0 || mHeight <= 0)
+    {
+        return false;
+    }
+
+    bool mipmapping;
+
+    switch (mMagFilter)
+    {
+      case GL_NEAREST:
+      case GL_LINEAR:
+        mipmapping = false;
+        break;
+      case GL_NEAREST_MIPMAP_NEAREST:
+      case GL_LINEAR_MIPMAP_NEAREST:
+      case GL_NEAREST_MIPMAP_LINEAR:
+      case GL_LINEAR_MIPMAP_LINEAR:
+        mipmapping = true;
+        break;
+     default: UNREACHABLE();
+    }
+
+    if (mipmapping)
+    {
+        int q = log2(max(mWidth, mHeight));
+
+        for (int level = 1; level <= q; level++)
+        {
+            if (mImageArray[level].format != mImageArray[0].format)
+            {
+                return false;
+            }
+
+            if (mImageArray[level].internalFormat != mImageArray[0].internalFormat)
+            {
+                return false;
+            }
+
+            if (mImageArray[level].type != mImageArray[0].type)
+            {
+                return false;
+            }
+
+            if (mImageArray[level].width != (mImageArray[level - 1].width + 1) / 2)
+            {
+                return false;
+            }
+
+            if (mImageArray[level].height != (mImageArray[level - 1].height + 1) / 2)
+            {
+                return false;
+            }
+        }
+    }
+
+    return true;
+}
+
+// Constructs a Direct3D 9 texture resource from the texture images, or returns an existing one
+IDirect3DBaseTexture9 *Texture2D::getTexture()
+{
+    if (!isComplete())
+    {
+        return NULL;
+    }
+
+    if (!mTexture)   // FIXME: Recreate when changed (same for getRenderTarget)
+    {
+        IDirect3DDevice9 *device = getDevice();
+        D3DFORMAT format = selectFormat(mImageArray[0]);
+
+        HRESULT result = device->CreateTexture(mWidth, mHeight, 0, D3DUSAGE_RENDERTARGET, format, D3DPOOL_DEFAULT, &mTexture, NULL);
+
+        if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY)
+        {
+            error(GL_OUT_OF_MEMORY, 0);
+        }
+
+        ASSERT(SUCCEEDED(result));
+
+        IDirect3DTexture9 *lockableTexture;
+        result = device->CreateTexture(mWidth, mHeight, 0, D3DUSAGE_DYNAMIC, format, D3DPOOL_SYSTEMMEM, &lockableTexture, NULL);
+
+        if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY)
+        {
+            error(GL_OUT_OF_MEMORY,(IDirect3DBaseTexture9*)NULL);
+        }
+
+        ASSERT(SUCCEEDED(result));
+
+        if (mTexture)   // FIXME: Handle failure
+        {
+            int levelCount = mTexture->GetLevelCount();
+
+            for (int level = 0; level < levelCount; level++)
+            {
+                D3DLOCKED_RECT lock = {0};
+                lockableTexture->LockRect(level, &lock, NULL, 0);
+
+                copyImage(lock, format, mImageArray[level]);
+
+                lockableTexture->UnlockRect(level);
+            }
+
+            device->UpdateTexture(lockableTexture, mTexture);
+            lockableTexture->Release();
+        }
+    }
+
+    return mTexture;
+}
+
+// Returns the top-level texture surface as a render target
+IDirect3DSurface9 *Texture2D::getRenderTarget()
+{
+    if (!mRenderTarget && getTexture())
+    {
+        mTexture->GetSurfaceLevel(0, &mRenderTarget);    
+    }
+
+    return mRenderTarget;
+}
+
+TextureCubeMap::TextureCubeMap()
+{
+    for (int face = 0; face < 6; face++)
+    {
+        for (int level = 0; level < MAX_TEXTURE_LEVELS; level++)
+        {
+            mImageArray[face][level].pixels = NULL;
+        }
+    }
+
+    mTexture = NULL;
+}
+
+TextureCubeMap::~TextureCubeMap()
+{
+    for (int face = 0; face < 6; face++)
+    {
+        for (int level = 0; level < MAX_TEXTURE_LEVELS; level++)
+        {
+            delete[] mImageArray[face][level].pixels;
+        }
+    }
+
+    if (mTexture)
+    {
+        mTexture->Release();
+        mTexture = NULL;
+    }
+}
+
+GLenum TextureCubeMap::getTarget() const
+{
+    return GL_TEXTURE_CUBE_MAP;
+}
+
+void TextureCubeMap::setImagePosX(GLint level, GLenum internalFormat, GLsizei width, GLsizei height, GLenum format, GLenum type, const void *pixels)
+{
+    setImage(0, level, internalFormat, width, height, format, type, pixels);
+}
+
+void TextureCubeMap::setImageNegX(GLint level, GLenum internalFormat, GLsizei width, GLsizei height, GLenum format, GLenum type, const void *pixels)
+{
+    setImage(1, level, internalFormat, width, height, format, type, pixels);
+}
+
+void TextureCubeMap::setImagePosY(GLint level, GLenum internalFormat, GLsizei width, GLsizei height, GLenum format, GLenum type, const void *pixels)
+{
+    setImage(2, level, internalFormat, width, height, format, type, pixels);
+}
+
+void TextureCubeMap::setImageNegY(GLint level, GLenum internalFormat, GLsizei width, GLsizei height, GLenum format, GLenum type, const void *pixels)
+{
+    setImage(3, level, internalFormat, width, height, format, type, pixels);
+}
+
+void TextureCubeMap::setImagePosZ(GLint level, GLenum internalFormat, GLsizei width, GLsizei height, GLenum format, GLenum type, const void *pixels)
+{
+    setImage(4, level, internalFormat, width, height, format, type, pixels);
+}
+
+void TextureCubeMap::setImageNegZ(GLint level, GLenum internalFormat, GLsizei width, GLsizei height, GLenum format, GLenum type, const void *pixels)
+{
+    setImage(5, level, internalFormat, width, height, format, type, pixels);
+}
+
+// Tests for GL texture object completeness. [OpenGL ES 2.0.24] section 3.7.10 page 81.
+bool TextureCubeMap::isComplete()
+{
+    if (mWidth <= 0 || mHeight <= 0 || mWidth != mHeight)
+    {
+        return false;
+    }
+
+    bool mipmapping;
+
+    switch (mMagFilter)
+    {
+      case GL_NEAREST:
+      case GL_LINEAR:
+        mipmapping = false;
+        break;
+      case GL_NEAREST_MIPMAP_NEAREST:
+      case GL_LINEAR_MIPMAP_NEAREST:
+      case GL_NEAREST_MIPMAP_LINEAR:
+      case GL_LINEAR_MIPMAP_LINEAR:
+        mipmapping = true;
+        break;
+      default: UNREACHABLE();
+    }
+
+    for (int face = 0; face < 6; face++)
+    {
+        if (mImageArray[face][0].width != mWidth || mImageArray[face][0].height != mHeight)
+        {
+            return false;
+        }
+    }
+
+    if (mipmapping)
+    {
+        int q = log2(mWidth);
+
+        for (int face = 0; face < 6; face++)
+        {
+            for (int level = 1; level <= q; level++)
+            {
+                if (mImageArray[face][level].format != mImageArray[0][0].format)
+                {
+                    return false;
+                }
+
+                if (mImageArray[face][level].internalFormat != mImageArray[0][0].internalFormat)
+                {
+                    return false;
+                }
+
+                if (mImageArray[face][level].type != mImageArray[0][0].type)
+                {
+                    return false;
+                }
+
+                if (mImageArray[face][level].width != (mImageArray[0][level - 1].width + 1) / 2)
+                {
+                    return false;
+                }
+
+                if (mImageArray[face][level].height != (mImageArray[0][level - 1].height + 1) / 2)
+                {
+                    return false;
+                }
+            }
+        }
+    }
+
+    return true;
+}
+
+// Constructs a Direct3D 9 texture resource from the texture images, or returns an existing one
+IDirect3DBaseTexture9 *TextureCubeMap::getTexture()
+{
+    if (!isComplete())
+    {
+        return NULL;
+    }
+
+    if (!mTexture)   // FIXME: Recreate when changed (same for getRenderTarget)
+    {
+        IDirect3DDevice9 *device = getDevice();
+        D3DFORMAT format = selectFormat(mImageArray[0][0]);
+
+        HRESULT result = device->CreateCubeTexture(mWidth, 0, D3DUSAGE_RENDERTARGET, format, D3DPOOL_DEFAULT, &mTexture, NULL);
+
+        if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY)
+        {
+            error(GL_OUT_OF_MEMORY, (IDirect3DBaseTexture9*)NULL);
+        }
+
+        ASSERT(SUCCEEDED(result));
+
+        IDirect3DCubeTexture9 *lockableTexture;
+        result = device->CreateCubeTexture(mWidth, 0, D3DUSAGE_DYNAMIC, format, D3DPOOL_SYSTEMMEM, &lockableTexture, NULL);
+
+        if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY)
+        {
+            return error(GL_OUT_OF_MEMORY, (IDirect3DBaseTexture9*)NULL);
+        }
+
+        ASSERT(SUCCEEDED(result));
+
+        if (mTexture)
+        {
+            for (int face = 0; face < 6; face++)
+            {
+                for (int level = 0; level < MAX_TEXTURE_LEVELS; level++)
+                {
+                    D3DLOCKED_RECT lock = {0};
+                    lockableTexture->LockRect((D3DCUBEMAP_FACES)face, level, &lock, NULL, 0);
+
+                    copyImage(lock, format, mImageArray[face][level]);
+
+                    lockableTexture->UnlockRect((D3DCUBEMAP_FACES)face, level);
+                }
+            }
+
+            device->UpdateTexture(lockableTexture, mTexture);
+            lockableTexture->Release();
+        }
+    }
+
+    return mTexture;
+}
+
+void TextureCubeMap::setImage(int face, GLint level, GLenum internalFormat, GLsizei width, GLsizei height, GLenum format, GLenum type, const void *pixels)
+{
+    if (level < 0 || level >= MAX_TEXTURE_LEVELS)
+    {
+        return;
+    }
+
+    mImageArray[face][level].internalFormat = internalFormat;
+    mImageArray[face][level].width = width;
+    mImageArray[face][level].height = height;
+    mImageArray[face][level].format = format;
+    mImageArray[face][level].type = type;
+
+    delete[] mImageArray[face][level].pixels;
+    mImageArray[face][level].pixels = NULL;
+
+    int imageSize = pixelSize(mImageArray[face][level]) * width * height;
+    mImageArray[face][level].pixels = new unsigned char[imageSize];
+
+    if (pixels)
+    {
+        memcpy(mImageArray[face][level].pixels, pixels, imageSize);
+    }
+
+    if (face == 0 && level == 0)
+    {
+        mWidth = width;
+        mHeight = height;
+    }
+}
+}
diff --git a/libGLESv2/Texture.h b/libGLESv2/Texture.h
new file mode 100644
index 0000000..fc3a30b
--- /dev/null
+++ b/libGLESv2/Texture.h
@@ -0,0 +1,141 @@
+//
+// 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.
+//
+
+// Texture.h: Defines the abstract gl::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"
+
+#define GL_APICALL
+#include <GLES2/gl2.h>
+#include <d3d9.h>
+
+namespace gl
+{
+enum
+{
+    MAX_TEXTURE_SIZE = 2048,
+    MAX_CUBE_MAP_TEXTURE_SIZE = 2048,
+    
+    MAX_TEXTURE_LEVELS = 11   // log2 of MAX_TEXTURE_SIZE
+};
+
+// Helper structure representing a single image layer
+struct Image
+{
+    GLenum internalFormat;
+    GLsizei width;
+    GLsizei height;
+    GLenum format;
+    GLenum type;
+    void *pixels;
+};
+
+class Texture : public Colorbuffer
+{
+  public:
+    Texture();
+
+    ~Texture();
+
+    virtual GLenum getTarget() const = 0;
+
+    bool setMinFilter(GLenum filter);
+    bool setMagFilter(GLenum filter);
+    bool setWrapS(GLenum wrap);
+    bool setWrapT(GLenum wrap);
+
+    GLenum getMinFilter();
+    GLenum getMagFilter();
+    GLenum getWrapS();
+    GLenum getWrapT();
+
+    virtual bool isComplete() = 0;
+    virtual IDirect3DBaseTexture9 *getTexture() = 0;
+
+  protected:
+    void copyImage(D3DLOCKED_RECT &lock, D3DFORMAT format, Image &image);
+
+    static D3DFORMAT selectFormat(const Image &image);
+    static int pixelSize(const Image &image);
+
+    GLenum mMinFilter;
+    GLenum mMagFilter;
+    GLenum mWrapS;
+    GLenum mWrapT;
+
+  private:
+    DISALLOW_COPY_AND_ASSIGN(Texture);
+};
+
+class Texture2D : public Texture
+{
+  public:
+    Texture2D();
+
+    ~Texture2D();
+
+    GLenum getTarget() const;
+
+    void setImage(GLint level, GLenum internalFormat, GLsizei width, GLsizei height, GLenum format, GLenum type, const void *pixels);
+
+    bool setMinFilter(GLenum filter);
+    bool setMagFilter(GLenum filter);
+    bool setWrapS(GLenum wrap);
+    bool setWrapT(GLenum wrap);
+
+    GLenum getMinFilter();
+    GLenum getMagFilter();
+    GLenum getWrapS();
+    GLenum getWrapT();
+
+    bool isComplete();
+    IDirect3DBaseTexture9 *getTexture();
+    IDirect3DSurface9 *getRenderTarget();
+
+  private:
+    DISALLOW_COPY_AND_ASSIGN(Texture2D);
+
+    Image mImageArray[MAX_TEXTURE_LEVELS];
+
+    IDirect3DTexture9 *mTexture;
+};
+
+class TextureCubeMap : public Texture
+{
+  public:
+    TextureCubeMap();
+
+    ~TextureCubeMap();
+
+    GLenum getTarget() const;
+
+    void setImagePosX(GLint level, GLenum internalFormat, GLsizei width, GLsizei height, GLenum format, GLenum type, const void *pixels);
+    void setImageNegX(GLint level, GLenum internalFormat, GLsizei width, GLsizei height, GLenum format, GLenum type, const void *pixels);
+    void setImagePosY(GLint level, GLenum internalFormat, GLsizei width, GLsizei height, GLenum format, GLenum type, const void *pixels);
+    void setImageNegY(GLint level, GLenum internalFormat, GLsizei width, GLsizei height, GLenum format, GLenum type, const void *pixels);
+    void setImagePosZ(GLint level, GLenum internalFormat, GLsizei width, GLsizei height, GLenum format, GLenum type, const void *pixels);
+    void setImageNegZ(GLint level, GLenum internalFormat, GLsizei width, GLsizei height, GLenum format, GLenum type, const void *pixels);
+
+    bool isComplete();
+    IDirect3DBaseTexture9 *getTexture();
+
+  private:
+    DISALLOW_COPY_AND_ASSIGN(TextureCubeMap);
+
+    void setImage(int face, GLint level, GLenum internalFormat, GLsizei width, GLsizei height, GLenum format, GLenum type, const void *pixels);
+
+    Image mImageArray[6][MAX_TEXTURE_LEVELS];
+
+    IDirect3DCubeTexture9 *mTexture;
+};
+}
+
+#endif   // LIBGLESV2_TEXTURE_H_
diff --git a/libGLESv2/libGLESv2.cpp b/libGLESv2/libGLESv2.cpp
new file mode 100644
index 0000000..21c41b2
--- /dev/null
+++ b/libGLESv2/libGLESv2.cpp
@@ -0,0 +1,3836 @@
+//
+// 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.
+//
+
+// libGLESv2.cpp: Implements the exported OpenGL ES 2.0 functions.
+
+#define GL_APICALL
+#include <GLES2/gl2.h>
+#include <GLES2/gl2ext.h>
+
+#include "Context.h"
+#include "main.h"
+#include "Program.h"
+#include "Shader.h"
+#include "Buffer.h"
+#include "Texture.h"
+#include "Renderbuffer.h"
+#include "Framebuffer.h"
+#include "mathutil.h"
+#include "debug.h"
+
+#include <exception>
+
+extern "C"
+{
+
+void __stdcall glActiveTexture(GLenum texture)
+{
+    TRACE("GLenum texture = 0x%X", texture);
+
+    try
+    {
+        if (texture < GL_TEXTURE0 || texture > GL_TEXTURE0 + gl::MAX_TEXTURE_IMAGE_UNITS - 1)
+        {
+            return error(GL_INVALID_ENUM);
+        }
+
+        gl::Context *context = gl::getContext();
+
+        if (context)
+        {
+            context->activeSampler = texture - GL_TEXTURE0;
+        }
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(GL_OUT_OF_MEMORY);
+    }
+}
+
+void __stdcall 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 || !shaderObject)
+            {
+                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 __stdcall glBindAttribLocation(GLuint program, GLuint index, const char* name)
+{
+    TRACE("GLuint program = %d, GLuint index = %d, const char* 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)
+            {
+                return error(GL_INVALID_VALUE);
+            }
+
+            programObject->bindAttributeLocation(index, name);
+        }
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(GL_OUT_OF_MEMORY);
+    }
+}
+
+void __stdcall 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 __stdcall glBindFramebuffer(GLenum target, GLuint framebuffer)
+{
+    TRACE("GLenum target = 0x%X, GLuint framebuffer = %d", target, framebuffer);
+
+    try
+    {
+        if (target != GL_FRAMEBUFFER)
+        {
+            return error(GL_INVALID_ENUM);
+        }
+
+        gl::Context *context = gl::getContext();
+
+        if (context)
+        {
+            context->bindFramebuffer(framebuffer);
+        }
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(GL_OUT_OF_MEMORY);
+    }
+}
+
+void __stdcall 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 __stdcall 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 __stdcall 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->blendColor.red = gl::clamp01(red);
+            context->blendColor.blue = gl::clamp01(blue);
+            context->blendColor.green = gl::clamp01(green);
+            context->blendColor.alpha = gl::clamp01(alpha);
+        }
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(GL_OUT_OF_MEMORY);
+    }
+}
+
+void __stdcall glBlendEquation(GLenum mode)
+{
+    glBlendEquationSeparate(mode, mode);
+}
+
+void __stdcall 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->blendEquationRGB = modeRGB;
+            context->blendEquationAlpha = modeAlpha;
+        }
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(GL_OUT_OF_MEMORY);
+    }
+}
+
+void __stdcall glBlendFunc(GLenum sfactor, GLenum dfactor)
+{
+    glBlendFuncSeparate(sfactor, dfactor, sfactor, dfactor);
+}
+
+void __stdcall 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);
+        }
+
+        if ((srcRGB == GL_CONSTANT_COLOR && dstRGB == GL_CONSTANT_ALPHA) ||
+            (srcRGB == GL_CONSTANT_ALPHA && dstRGB == GL_CONSTANT_COLOR))
+        {
+            UNIMPLEMENTED();
+        }
+
+        gl::Context *context = gl::getContext();
+
+        if (context)
+        {
+            context->sourceBlendRGB = srcRGB;
+            context->sourceBlendAlpha = srcAlpha;
+            context->destBlendRGB = dstRGB;
+            context->destBlendAlpha = dstAlpha;
+        }
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(GL_OUT_OF_MEMORY);
+    }
+}
+
+void __stdcall glBufferData(GLenum target, GLsizeiptr size, const void* data, GLenum usage)
+{
+    TRACE("GLenum target = 0x%X, GLsizeiptr size = %d, const void* 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->storeData(size, data);
+        }
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(GL_OUT_OF_MEMORY);
+    }
+}
+
+void __stdcall glBufferSubData(GLenum target, GLintptr offset, GLsizeiptr size, const void* data)
+{
+    TRACE("GLenum target = 0x%X, GLintptr offset = %d, GLsizeiptr size = %d, const void* data = 0x%0.8p", target, offset, size, data);
+
+    try
+    {
+        if (size < 0)
+        {
+            return error(GL_INVALID_VALUE);
+        }
+
+        UNIMPLEMENTED();   // FIXME
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(GL_OUT_OF_MEMORY);
+    }
+}
+
+GLenum __stdcall glCheckFramebufferStatus(GLenum target)
+{
+    TRACE("GLenum target = 0x%X", target);
+
+    try
+    {
+        if (target != GL_FRAMEBUFFER)
+        {
+            return error(GL_INVALID_ENUM, 0);
+        }
+
+        gl::Context *context = gl::getContext();
+
+        if (context)
+        {
+            gl::Framebuffer *framebuffer = context->getFramebuffer();
+
+            return framebuffer->completeness();
+        }
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(GL_OUT_OF_MEMORY, 0);
+    }
+
+    return 0;
+}
+
+void __stdcall glClear(GLbitfield mask)
+{
+    TRACE("GLbitfield mask = %X", mask);
+
+    try
+    {
+        gl::Context *context = gl::getContext();
+
+        if (context)
+        {
+            context->clear(mask);
+        }
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(GL_OUT_OF_MEMORY);
+    }
+}
+
+void __stdcall 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 __stdcall 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 __stdcall 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 __stdcall 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->colorMaskRed = red != GL_FALSE;
+            context->colorMaskGreen = green != GL_FALSE;
+            context->colorMaskBlue = blue != GL_FALSE;
+            context->colorMaskAlpha = alpha != GL_FALSE;
+        }
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(GL_OUT_OF_MEMORY);
+    }
+}
+
+void __stdcall glCompileShader(GLuint shader)
+{
+    TRACE("GLuint shader = %d", shader);
+
+    try
+    {
+        gl::Context *context = gl::getContext();
+
+        if (context)
+        {
+            gl::Shader *shaderObject = context->getShader(shader);
+            
+            if (!shaderObject)
+            {
+                return error(GL_INVALID_VALUE);
+            }
+
+            shaderObject->compile();
+        }
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(GL_OUT_OF_MEMORY);
+    }
+}
+
+void __stdcall glCompressedTexImage2D(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const void* 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 void* data = 0x%0.8p",
+          target, level, internalformat, width, height, border, imageSize, data);
+
+    try
+    {
+        if (width < 0 || height < 0 || imageSize < 0)
+        {
+            return error(GL_INVALID_VALUE);
+        }
+
+        UNIMPLEMENTED();   // FIXME
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(GL_OUT_OF_MEMORY);
+    }
+}
+
+void __stdcall glCompressedTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void* 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 void* data = 0x%0.8p",
+          target, level, xoffset, yoffset, width, height, format, imageSize, data);
+
+    try
+    {
+        if (width < 0 || height < 0 || imageSize < 0)
+        {
+            return error(GL_INVALID_VALUE);
+        }
+
+        UNIMPLEMENTED();   // FIXME
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(GL_OUT_OF_MEMORY);
+    }
+}
+
+void __stdcall 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 (width < 0 || height < 0)
+        {
+            return error(GL_INVALID_VALUE);
+        }
+
+        UNIMPLEMENTED();   // FIXME
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(GL_OUT_OF_MEMORY);
+    }
+}
+
+void __stdcall 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 (width < 0 || height < 0)
+        {
+            return error(GL_INVALID_VALUE);
+        }
+
+        UNIMPLEMENTED();   // FIXME
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(GL_OUT_OF_MEMORY);
+    }
+}
+
+GLuint __stdcall 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 __stdcall 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 __stdcall 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->cullMode = mode;
+                }
+            }
+            break;
+          default:
+            return error(GL_INVALID_ENUM);
+        }
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(GL_OUT_OF_MEMORY);
+    }
+}
+
+void __stdcall 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 __stdcall 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 __stdcall glDeleteProgram(GLuint program)
+{
+    TRACE("GLuint program = %d", program);
+
+    try
+    {
+        gl::Context *context = gl::getContext();
+
+        if (context)
+        {
+            context->deleteProgram(program);
+        }
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(GL_OUT_OF_MEMORY);
+    }
+}
+
+void __stdcall 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 __stdcall glDeleteShader(GLuint shader)
+{
+    TRACE("GLuint shader = %d", shader);
+
+    try
+    {
+        gl::Context *context = gl::getContext();
+
+        if (context)
+        {
+            context->deleteShader(shader);
+        }
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(GL_OUT_OF_MEMORY);
+    }
+}
+
+void __stdcall 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 __stdcall 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->depthFunc = func;
+        }
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(GL_OUT_OF_MEMORY);
+    }
+}
+
+void __stdcall glDepthMask(GLboolean flag)
+{
+    TRACE("GLboolean flag = %d", flag);
+
+    try
+    {
+        gl::Context *context = gl::getContext();
+
+        if (context)
+        {
+            context->depthMask = flag != GL_FALSE;
+        }
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(GL_OUT_OF_MEMORY);
+    }
+}
+
+void __stdcall glDepthRangef(GLclampf zNear, GLclampf zFar)
+{
+    TRACE("GLclampf zNear = %f, GLclampf zFar = %f", zNear, zFar);
+
+    try
+    {
+        gl::Context *context = gl::getContext();
+
+        if (context)
+        {
+            context->zNear = zNear;
+            context->zFar = zFar;
+        }
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(GL_OUT_OF_MEMORY);
+    }
+}
+
+void __stdcall 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 || !shaderObject)
+            {
+                return error(GL_INVALID_VALUE);
+            }
+
+            if (!programObject->detachShader(shaderObject))
+            {
+                return error(GL_INVALID_OPERATION);
+            }
+
+            if (shaderObject->isDeletable())
+            {
+                context->deleteShader(shader);
+            }
+        }
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(GL_OUT_OF_MEMORY);
+    }
+}
+
+void __stdcall glDisable(GLenum cap)
+{
+    TRACE("GLenum cap = 0x%X", cap);
+
+    try
+    {
+        gl::Context *context = gl::getContext();
+
+        if (context)
+        {
+            switch (cap)
+            {
+              case GL_CULL_FACE:                context->cullFace = false;              break;
+              case GL_POLYGON_OFFSET_FILL:      context->polygonOffsetFill = false;     break;
+              case GL_SAMPLE_ALPHA_TO_COVERAGE: context->sampleAlphaToCoverage = false; break;
+              case GL_SAMPLE_COVERAGE:          context->sampleCoverage = false;        break;
+              case GL_SCISSOR_TEST:             context->scissorTest = false;           break;
+              case GL_STENCIL_TEST:             context->stencilTest = false;           break;
+              case GL_DEPTH_TEST:               context->depthTest = false;             break;
+              case GL_BLEND:                    context->blend = false;                 break;
+              case GL_DITHER:                   context->dither = false;                break;
+              default:
+                return error(GL_INVALID_ENUM);
+            }
+        }
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(GL_OUT_OF_MEMORY);
+    }
+}
+
+void __stdcall 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->vertexAttribute[index].enabled = false;
+        }
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(GL_OUT_OF_MEMORY);
+    }
+}
+
+void __stdcall 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 __stdcall glDrawElements(GLenum mode, GLsizei count, GLenum type, const void* indices)
+{
+    TRACE("GLenum mode = 0x%X, GLsizei count = %d, GLenum type = 0x%X, const void* indices = 0x%0.8p", mode, count, type, indices);
+
+    try
+    {
+        if (count < 0)
+        {
+            return error(GL_INVALID_VALUE);
+        }
+
+        switch (type)
+        {
+          case GL_UNSIGNED_BYTE:
+            UNIMPLEMENTED();   // FIXME
+          case GL_UNSIGNED_SHORT:
+            break;
+          default:
+            return error(GL_INVALID_ENUM);
+        }
+
+        gl::Context *context = gl::getContext();
+
+        if (context)
+        {
+            context->drawElements(mode, count, type, indices);
+        }
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(GL_OUT_OF_MEMORY);
+    }
+}
+
+void __stdcall glEnable(GLenum cap)
+{
+    TRACE("GLenum cap = 0x%X", cap);
+
+    try
+    {
+        gl::Context *context = gl::getContext();
+
+        if (context)
+        {
+            switch (cap)
+            {
+              case GL_CULL_FACE:                context->cullFace = true;              break;
+              case GL_POLYGON_OFFSET_FILL:      context->polygonOffsetFill = true;     break;
+              case GL_SAMPLE_ALPHA_TO_COVERAGE: context->sampleAlphaToCoverage = true; break;
+              case GL_SAMPLE_COVERAGE:          context->sampleCoverage = true;        break;
+              case GL_SCISSOR_TEST:             context->scissorTest = true;           break;
+              case GL_STENCIL_TEST:             context->stencilTest = true;           break;
+              case GL_DEPTH_TEST:               context->depthTest = true;             break;
+              case GL_BLEND:                    context->blend = true;                 break;
+              case GL_DITHER:                   context->dither = true;                break;
+              default:
+                return error(GL_INVALID_ENUM);
+            }
+        }
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(GL_OUT_OF_MEMORY);
+    }
+}
+
+void __stdcall 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->vertexAttribute[index].enabled = true;
+        }
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(GL_OUT_OF_MEMORY);
+    }
+}
+
+void __stdcall glFinish(void)
+{
+    TRACE("");
+
+    try
+    {
+        gl::Context *context = gl::getContext();
+
+        if (context)
+        {
+            context->finish();
+        }
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(GL_OUT_OF_MEMORY);
+    }
+}
+
+void __stdcall glFlush(void)
+{
+    TRACE("");
+
+    try
+    {
+        gl::Context *context = gl::getContext();
+
+        if (context)
+        {
+            context->flush();
+        }
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(GL_OUT_OF_MEMORY);
+    }
+}
+
+void __stdcall 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 || renderbuffertarget != GL_RENDERBUFFER)
+        {
+            return error(GL_INVALID_ENUM);
+        }
+
+        gl::Context *context = gl::getContext();
+
+        if (context)
+        {
+            gl::Framebuffer *framebuffer = context->getFramebuffer();
+
+            if (context->framebuffer == 0 || !framebuffer)
+            {
+                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 __stdcall 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)
+        {
+            return error(GL_INVALID_ENUM);
+        }
+
+        switch (attachment)
+        {
+          case GL_COLOR_ATTACHMENT0:
+            break;
+          default:
+            return error(GL_INVALID_ENUM);
+        }
+
+        gl::Context *context = gl::getContext();
+
+        if (context)
+        {
+            if (texture)
+            {
+                switch (textarget)
+                {
+                  case GL_TEXTURE_2D:
+                    if (!context->getTexture2D())
+                    {
+                        return error(GL_INVALID_OPERATION);
+                    }
+                    break;
+                  case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
+                    UNIMPLEMENTED();   // FIXME
+                    break;
+                  case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
+                    UNIMPLEMENTED();   // FIXME
+                    break;
+                  case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
+                    UNIMPLEMENTED();   // FIXME
+                    break;
+                  case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
+                    UNIMPLEMENTED();   // FIXME
+                    break;
+                  case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
+                    UNIMPLEMENTED();   // FIXME
+                    break;
+                  case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
+                    UNIMPLEMENTED();   // FIXME
+                    break;
+                  default:
+                    return error(GL_INVALID_ENUM);
+                }
+
+                if (level != 0)
+                {
+                    return error(GL_INVALID_VALUE);
+                }
+            }
+
+            gl::Framebuffer *framebuffer = context->getFramebuffer();
+
+            if (context->framebuffer == 0 || !framebuffer)
+            {
+                return error(GL_INVALID_OPERATION);
+            }
+
+            framebuffer->setColorbuffer(GL_TEXTURE, texture);
+        }
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(GL_OUT_OF_MEMORY);
+    }
+}
+
+void __stdcall 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->frontFace = mode;
+                }
+            }
+            break;
+          default:
+            return error(GL_INVALID_ENUM);
+        }
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(GL_OUT_OF_MEMORY);
+    }
+}
+
+void __stdcall 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 __stdcall glGenerateMipmap(GLenum target)
+{
+    TRACE("GLenum target = 0x%X", target);
+
+    try
+    {
+        UNIMPLEMENTED();   // FIXME
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(GL_OUT_OF_MEMORY);
+    }
+}
+
+void __stdcall 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 __stdcall 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 __stdcall 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 __stdcall glGetActiveAttrib(GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, char* 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, char* name = %0.8p",
+          program, index, bufsize, length, size, type, name);
+
+    try
+    {
+        if (bufsize < 0)
+        {
+            return error(GL_INVALID_VALUE);
+        }
+
+        UNIMPLEMENTED();   // FIXME
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(GL_OUT_OF_MEMORY);
+    }
+}
+
+void __stdcall glGetActiveUniform(GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, char* 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, char* name = 0x%0.8p",
+          program, index, bufsize, length, size, type, name);
+
+    try
+    {
+        if (bufsize < 0)
+        {
+            return error(GL_INVALID_VALUE);
+        }
+
+        UNIMPLEMENTED();   // FIXME
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(GL_OUT_OF_MEMORY);
+    }
+}
+
+void __stdcall 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);
+        }
+
+        UNIMPLEMENTED();   // FIXME
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(GL_OUT_OF_MEMORY);
+    }
+}
+
+int __stdcall glGetAttribLocation(GLuint program, const char* name)
+{
+    TRACE("GLuint program = %d, const char* name = %s", program, name);
+
+    try
+    {
+        gl::Context *context = gl::getContext();
+
+        if (context)
+        {
+            gl::Program *programObject = context->getProgram(program);
+
+            if (!programObject)
+            {
+                return error(GL_INVALID_VALUE, -1);
+            }
+
+            return programObject->getAttributeLocation(name);
+        }
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(GL_OUT_OF_MEMORY, -1);
+    }
+
+    return -1;
+}
+
+void __stdcall glGetBooleanv(GLenum pname, GLboolean* params)
+{
+    TRACE("GLenum pname = 0x%X, GLboolean* params = 0x%0.8p",  pname, params);
+
+    try
+    {
+        switch (pname)
+        {
+          case GL_SHADER_COMPILER: *params = GL_TRUE; break;
+          default:
+            UNIMPLEMENTED();   // FIXME
+            return error(GL_INVALID_ENUM);
+        }
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(GL_OUT_OF_MEMORY);
+    }
+}
+
+void __stdcall 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
+    {
+        UNIMPLEMENTED();   // FIXME
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(GL_OUT_OF_MEMORY);
+    }
+}
+
+GLenum __stdcall glGetError(void)
+{
+    TRACE("");
+
+    gl::Context *context = gl::getContext();
+
+    if (context)
+    {
+        return context->getError();
+    }
+
+    return GL_NO_ERROR;
+}
+
+void __stdcall glGetFloatv(GLenum pname, GLfloat* params)
+{
+    TRACE("GLenum pname = 0x%X, GLfloat* params = 0x%0.8p", pname, params);
+
+    try
+    {
+        UNIMPLEMENTED();   // FIXME
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(GL_OUT_OF_MEMORY);
+    }
+}
+
+void __stdcall 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 (context->framebuffer == 0)
+            {
+                return error(GL_INVALID_OPERATION);
+            }
+
+            UNIMPLEMENTED();   // FIXME
+        }
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(GL_OUT_OF_MEMORY);
+    }
+}
+
+void __stdcall 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)
+        {
+            switch (pname)
+            {
+              case GL_MAX_VERTEX_ATTRIBS:               *params = gl::MAX_VERTEX_ATTRIBS;               break;
+              case GL_MAX_VERTEX_UNIFORM_VECTORS:       *params = gl::MAX_VERTEX_UNIFORM_VECTORS;       break;
+              case GL_MAX_VARYING_VECTORS:              *params = gl::MAX_VARYING_VECTORS;              break;
+              case GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS: *params = gl::MAX_COMBINED_TEXTURE_IMAGE_UNITS; break;
+              case GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS:   *params = gl::MAX_VERTEX_TEXTURE_IMAGE_UNITS;   break;
+              case GL_MAX_TEXTURE_IMAGE_UNITS:          *params = gl::MAX_TEXTURE_IMAGE_UNITS;          break;
+              case GL_MAX_FRAGMENT_UNIFORM_VECTORS:     *params = gl::MAX_FRAGMENT_UNIFORM_VECTORS;     break;
+              case GL_MAX_RENDERBUFFER_SIZE:            *params = gl::MAX_RENDERBUFFER_SIZE;            break;
+              case GL_NUM_SHADER_BINARY_FORMATS:        *params = 0;                                break;
+              case GL_ARRAY_BUFFER_BINDING:             *params = context->arrayBuffer;             break;
+              case GL_FRAMEBUFFER_BINDING:              *params = context->framebuffer;             break;
+              case GL_RENDERBUFFER_BINDING:             *params = context->renderbuffer;            break;
+              case GL_CURRENT_PROGRAM:                  *params = context->currentProgram;          break;
+              case GL_RED_BITS:
+              case GL_GREEN_BITS:
+              case GL_BLUE_BITS:
+              case GL_ALPHA_BITS:
+                {
+                    gl::Framebuffer *framebuffer = context->getFramebuffer();
+                    gl::Colorbuffer *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:
+                {
+                    gl::Framebuffer *framebuffer = context->getFramebuffer();
+                    gl::Depthbuffer *depthbuffer = framebuffer->getDepthbuffer();
+
+                    if (depthbuffer)
+                    {
+                        *params = depthbuffer->getDepthSize();
+                    }
+                    else
+                    {
+                        *params = 0;
+                    }
+                }
+                break;
+              case GL_STENCIL_BITS:
+                {
+                    gl::Framebuffer *framebuffer = context->getFramebuffer();
+                    gl::Stencilbuffer *stencilbuffer = framebuffer->getStencilbuffer();
+
+                    if (stencilbuffer)
+                    {
+                        *params = stencilbuffer->getStencilSize();
+                    }
+                    else
+                    {
+                        *params = 0;
+                    }
+                }
+                break;
+              default:
+                UNIMPLEMENTED();   // FIXME
+                return error(GL_INVALID_ENUM);
+            }
+        }
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(GL_OUT_OF_MEMORY);
+    }
+}
+
+void __stdcall 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:
+                UNIMPLEMENTED();   // FIXME
+                *params = GL_FALSE;
+                return;
+              case GL_LINK_STATUS:
+                *params = programObject->isLinked();
+                return;
+              case GL_VALIDATE_STATUS:
+                UNIMPLEMENTED();   // FIXME
+                *params = GL_TRUE;
+                return;
+              case GL_INFO_LOG_LENGTH:
+                UNIMPLEMENTED();   // FIXME
+                *params = 0;
+                return;
+              case GL_ATTACHED_SHADERS:
+                UNIMPLEMENTED();   // FIXME
+                *params = 2;
+                return;
+              case GL_ACTIVE_ATTRIBUTES:
+                UNIMPLEMENTED();   // FIXME
+                *params = 0;
+                return;
+              case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH:
+                UNIMPLEMENTED();   // FIXME
+                *params = 0;
+                return;
+              case GL_ACTIVE_UNIFORMS:
+                UNIMPLEMENTED();   // FIXME
+                *params = 0;
+                return;
+              case GL_ACTIVE_UNIFORM_MAX_LENGTH:
+                UNIMPLEMENTED();   // FIXME
+                *params = 0;
+                return;
+              default:
+                return error(GL_INVALID_ENUM);
+            }
+        }
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(GL_OUT_OF_MEMORY);
+    }
+}
+
+void __stdcall glGetProgramInfoLog(GLuint program, GLsizei bufsize, GLsizei* length, char* infolog)
+{
+    TRACE("GLuint program = %d, GLsizei bufsize = %d, GLsizei* length = 0x%0.8p, char* infolog = 0x%0.8p", program, bufsize, length, infolog);
+
+    try
+    {
+        if (bufsize < 0)
+        {
+            return error(GL_INVALID_VALUE);
+        }
+
+        UNIMPLEMENTED();   // FIXME
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(GL_OUT_OF_MEMORY);
+    }
+}
+
+void __stdcall 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
+    {
+        UNIMPLEMENTED();   // FIXME
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(GL_OUT_OF_MEMORY);
+    }
+}
+
+void __stdcall 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:
+                UNIMPLEMENTED();   // FIXME
+                *params = GL_FALSE;
+                return;
+              case GL_COMPILE_STATUS:
+                *params = shaderObject->isCompiled() ? GL_TRUE : GL_FALSE;
+                return;
+              case GL_INFO_LOG_LENGTH:
+                UNIMPLEMENTED();   // FIXME
+                *params = 0;
+                return;
+              case GL_SHADER_SOURCE_LENGTH:
+                UNIMPLEMENTED();   // FIXME
+                *params = 1;
+                return;
+              default:
+                return error(GL_INVALID_ENUM);
+            }
+        }
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(GL_OUT_OF_MEMORY);
+    }
+}
+
+void __stdcall glGetShaderInfoLog(GLuint shader, GLsizei bufsize, GLsizei* length, char* infolog)
+{
+    TRACE("GLuint shader = %d, GLsizei bufsize = %d, GLsizei* length = 0x%0.8p, char* infolog = 0x%0.8p", shader, bufsize, length, infolog);
+
+    try
+    {
+        if (bufsize < 0)
+        {
+            return error(GL_INVALID_VALUE);
+        }
+
+        UNIMPLEMENTED();   // FIXME
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(GL_OUT_OF_MEMORY);
+    }
+}
+
+void __stdcall 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
+    {
+        UNIMPLEMENTED();   // FIXME
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(GL_OUT_OF_MEMORY);
+    }
+}
+
+void __stdcall glGetShaderSource(GLuint shader, GLsizei bufsize, GLsizei* length, char* source)
+{
+    TRACE("GLuint shader = %d, GLsizei bufsize = %d, GLsizei* length = 0x%0.8p, char* source = 0x%0.8p", shader, bufsize, length, source);
+
+    try
+    {
+        if (bufsize < 0)
+        {
+            return error(GL_INVALID_VALUE);
+        }
+
+        UNIMPLEMENTED();   // FIXME
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(GL_OUT_OF_MEMORY);
+    }
+}
+
+const GLubyte* __stdcall glGetString(GLenum name)
+{
+    TRACE("GLenum name = 0x%X", name);
+
+    try
+    {
+        switch (name)
+        {
+          case GL_VENDOR:
+            return (GLubyte*)"TransGaming Inc.";
+          case GL_RENDERER:
+            return (GLubyte*)"ANGLE";
+          case GL_VERSION:
+            return (GLubyte*)"OpenGL ES 2.0 (git-devel "__DATE__ " " __TIME__")";
+          case GL_SHADING_LANGUAGE_VERSION:
+            return (GLubyte*)"OpenGL ES GLSL ES 1.00 (git-devel "__DATE__ " " __TIME__")";
+          case GL_EXTENSIONS:
+            return (GLubyte*)"";
+          default:
+            return error(GL_INVALID_ENUM, (GLubyte*)NULL);
+        }
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(GL_OUT_OF_MEMORY, (GLubyte*)NULL);
+    }
+
+    return NULL;
+}
+
+void __stdcall 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
+    {
+        UNIMPLEMENTED();   // FIXME
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(GL_OUT_OF_MEMORY);
+    }
+}
+
+void __stdcall 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
+    {
+        UNIMPLEMENTED();   // FIXME
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(GL_OUT_OF_MEMORY);
+    }
+}
+
+void __stdcall glGetUniformfv(GLuint program, GLint location, GLfloat* params)
+{
+    TRACE("GLuint program = %d, GLint location = %d, GLfloat* params = 0x%0.8p", program, location, params);
+
+    try
+    {
+        UNIMPLEMENTED();   // FIXME
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(GL_OUT_OF_MEMORY);
+    }
+}
+
+void __stdcall glGetUniformiv(GLuint program, GLint location, GLint* params)
+{
+    TRACE("GLuint program = %d, GLint location = %d, GLint* params = 0x%0.8p", program, location, params);
+
+    try
+    {
+        UNIMPLEMENTED();   // FIXME
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(GL_OUT_OF_MEMORY);
+    }
+}
+
+int __stdcall glGetUniformLocation(GLuint program, const char* name)
+{
+    TRACE("GLuint program = %d, const char* 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)
+            {
+                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 __stdcall glGetVertexAttribfv(GLuint index, GLenum pname, GLfloat* params)
+{
+    TRACE("GLuint index = %d, GLenum pname = 0x%X, GLfloat* params = 0x%0.8p", index, pname, params);
+
+    try
+    {
+        if (index >= gl::MAX_VERTEX_ATTRIBS)
+        {
+            return error(GL_INVALID_VALUE);
+        }
+
+        UNIMPLEMENTED();   // FIXME
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(GL_OUT_OF_MEMORY);
+    }
+}
+
+void __stdcall glGetVertexAttribiv(GLuint index, GLenum pname, GLint* params)
+{
+    TRACE("GLuint index = %d, GLenum pname = 0x%X, GLint* params = 0x%0.8p", index, pname, params);
+
+    try
+    {
+        if (index >= gl::MAX_VERTEX_ATTRIBS)
+        {
+            return error(GL_INVALID_VALUE);
+        }
+
+        UNIMPLEMENTED();   // FIXME
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(GL_OUT_OF_MEMORY);
+    }
+}
+
+void __stdcall glGetVertexAttribPointerv(GLuint index, GLenum pname, void** pointer)
+{
+    TRACE("GLuint index = %d, GLenum pname = 0x%X, void** pointer = 0x%0.8p", index, pname, pointer);
+
+    try
+    {
+        if (index >= gl::MAX_VERTEX_ATTRIBS)
+        {
+            return error(GL_INVALID_VALUE);
+        }
+
+        UNIMPLEMENTED();   // FIXME
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(GL_OUT_OF_MEMORY);
+    }
+}
+
+void __stdcall glHint(GLenum target, GLenum mode)
+{
+    TRACE("GLenum target = 0x%X, GLenum mode = 0x%X", target, mode);
+
+    try
+    {
+        UNIMPLEMENTED();   // FIXME
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(GL_OUT_OF_MEMORY);
+    }
+}
+
+GLboolean __stdcall 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 __stdcall 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->cullFace;
+              case GL_POLYGON_OFFSET_FILL:      return context->polygonOffsetFill;
+              case GL_SAMPLE_ALPHA_TO_COVERAGE: return context->sampleAlphaToCoverage;
+              case GL_SAMPLE_COVERAGE:          return context->sampleCoverage;
+              case GL_SCISSOR_TEST:             return context->scissorTest;
+              case GL_STENCIL_TEST:             return context->stencilTest;
+              case GL_DEPTH_TEST:               return context->depthTest;
+              case GL_BLEND:                    return context->blend;
+              case GL_DITHER:                   return context->dither;
+              default:
+                return error(GL_INVALID_ENUM, false);
+            }
+        }
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(GL_OUT_OF_MEMORY, false);
+    }
+
+    return false;
+}
+
+GLboolean __stdcall 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 __stdcall 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 __stdcall 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 __stdcall 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 __stdcall 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 __stdcall glLineWidth(GLfloat width)
+{
+    TRACE("GLfloat width = %f", width);
+
+    try
+    {
+        if (width <= 0.0f)
+        {
+            return error(GL_INVALID_VALUE);
+        }
+
+        if (width != 1.0f)
+        {
+            UNIMPLEMENTED();   // FIXME
+        }
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(GL_OUT_OF_MEMORY);
+    }
+}
+
+void __stdcall glLinkProgram(GLuint program)
+{
+    TRACE("GLuint program = %d", program);
+
+    try
+    {
+        gl::Context *context = gl::getContext();
+
+        if (context)
+        {
+            gl::Program *programObject = context->getProgram(program);
+
+            if (!programObject)
+            {
+                return error(GL_INVALID_VALUE);
+            }
+
+            programObject->link();
+        }
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(GL_OUT_OF_MEMORY);
+    }
+}
+
+void __stdcall glPixelStorei(GLenum pname, GLint param)
+{
+    TRACE("GLenum pname = 0x%X, GLint param = %d", pname, param);
+
+    try
+    {
+        switch (pname)
+        {
+          case GL_UNPACK_ALIGNMENT:
+        //    UNIMPLEMENTED();   // FIXME
+            break;
+          case GL_PACK_ALIGNMENT:
+        //    UNIMPLEMENTED();   // FIXME
+            break;
+          default:
+            return error(GL_INVALID_ENUM);
+        }
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(GL_OUT_OF_MEMORY);
+    }
+}
+
+void __stdcall glPolygonOffset(GLfloat factor, GLfloat units)
+{
+    TRACE("GLfloat factor = %f, GLfloat units = %f", factor, units);
+
+    try
+    {
+        if (factor != 0.0f || units != 0.0f)
+        {
+            UNIMPLEMENTED();   // FIXME
+        }
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(GL_OUT_OF_MEMORY);
+    }
+}
+
+void __stdcall glReadPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, void* pixels)
+{
+    TRACE("GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d, GLenum format = 0x%X, GLenum type = 0x%X, void* pixels = 0x%0.8p", x, y, width, height, format, type,  pixels);
+
+    try
+    {
+        if (width < 0 || height < 0)
+        {
+            return error(GL_INVALID_VALUE);
+        }
+
+        switch (format)
+        {
+          case GL_RGBA:
+            switch (type)
+            {
+              case GL_UNSIGNED_BYTE:
+                break;
+              default:
+                return error(GL_INVALID_OPERATION);
+            }
+            break;
+          case gl::IMPLEMENTATION_COLOR_READ_FORMAT:
+            switch (type)
+            {
+              case gl::IMPLEMENTATION_COLOR_READ_TYPE:
+                break;
+              default:
+                return error(GL_INVALID_OPERATION);
+            }
+            break;
+          default:
+            return error(GL_INVALID_OPERATION);
+        }
+
+        gl::Context *context = gl::getContext();
+
+        if (context)
+        {
+            context->readPixels(x, y, width, height, format, type, pixels);
+        }
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(GL_OUT_OF_MEMORY);
+    }
+}
+
+void __stdcall glReleaseShaderCompiler(void)
+{
+    TRACE("");
+
+    try
+    {
+        gl::Shader::releaseCompiler();
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(GL_OUT_OF_MEMORY);
+    }
+}
+
+void __stdcall glRenderbufferStorage(GLenum target, GLenum internalformat, GLsizei width, GLsizei height)
+{
+    TRACE("GLenum target = 0x%X, GLenum internalformat = 0x%X, GLsizei width = %d, GLsizei height = %d", target, internalformat, width, height);
+
+    try
+    {
+        switch (target)
+        {
+          case GL_RENDERBUFFER:
+            break;
+          default:
+            return error(GL_INVALID_ENUM);
+        }
+
+        switch (internalformat)
+        {
+          case GL_DEPTH_COMPONENT16:
+          case GL_RGBA4:
+          case GL_RGB5_A1:
+          case GL_RGB565:
+          case GL_STENCIL_INDEX8:
+            break;
+          default:
+            return error(GL_INVALID_ENUM);
+        }
+
+        if (width < 0 || height < 0 || width > gl::MAX_RENDERBUFFER_SIZE || height > gl::MAX_RENDERBUFFER_SIZE)
+        {
+            return error(GL_INVALID_VALUE);
+        }
+
+        gl::Context *context = gl::getContext();
+
+        if (context)
+        {
+            if (context->framebuffer == 0 || context->renderbuffer == 0)
+            {
+                return error(GL_INVALID_OPERATION);
+            }
+
+            switch (internalformat)
+            {
+              case GL_DEPTH_COMPONENT16:
+                context->setRenderbuffer(new gl::Depthbuffer(width, height));
+                break;
+              case GL_RGBA4:
+              case GL_RGB5_A1:
+              case GL_RGB565:
+                UNIMPLEMENTED();   // FIXME
+            //    context->setRenderbuffer(new Colorbuffer(renderTarget));
+                break;
+              case GL_STENCIL_INDEX8:
+                UNIMPLEMENTED();   // FIXME
+            //    context->setRenderbuffer(new Stencilbuffer(depthStencil));
+                break;
+              default:
+                return error(GL_INVALID_ENUM);
+            }
+        }
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(GL_OUT_OF_MEMORY);
+    }
+}
+
+void __stdcall glSampleCoverage(GLclampf value, GLboolean invert)
+{
+    TRACE("GLclampf value = %f, GLboolean invert = %d", value, invert);
+
+    try
+    {
+        gl::Context* context = gl::getContext();
+        
+        if (context)
+        {
+            context->sampleCoverageValue = gl::clamp01(value);
+            context->sampleCoverageInvert = invert;
+        }
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(GL_OUT_OF_MEMORY);
+    }
+}
+
+void __stdcall 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->scissorX = x;
+            context->scissorY = y;
+            context->scissorWidth = width;
+            context->scissorHeight = height;
+        }
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(GL_OUT_OF_MEMORY);
+    }
+}
+
+void __stdcall glShaderBinary(GLsizei n, const GLuint* shaders, GLenum binaryformat, const void* binary, GLsizei length)
+{
+    TRACE("GLsizei n = %d, const GLuint* shaders = 0x%0.8p, GLenum binaryformat = 0x%X, const void* binary = 0x%0.8p, GLsizei length = %d", 
+           n, shaders, binaryformat, binary, length);
+
+    try
+    {
+        if (n < 0 || length < 0)
+        {
+            return error(GL_INVALID_VALUE);
+        }
+
+        UNIMPLEMENTED();   // FIXME
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(GL_OUT_OF_MEMORY);
+    }
+}
+
+void __stdcall glShaderSource(GLuint shader, GLsizei count, const char** string, const GLint* length)
+{
+    TRACE("GLuint shader = %d, GLsizei count = %d, const char** 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)
+            {
+                return error(GL_INVALID_VALUE);
+            }
+
+            shaderObject->setSource(count, string, length);
+        }
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(GL_OUT_OF_MEMORY);
+    }
+}
+
+void __stdcall glStencilFunc(GLenum func, GLint ref, GLuint mask)
+{
+    glStencilFuncSeparate(GL_FRONT_AND_BACK, func, ref, mask); 
+}
+
+void __stdcall 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->stencilFunc = func;
+                context->stencilRef = ref;
+                context->stencilMask = mask;
+            }
+
+            if (face == GL_BACK || face == GL_FRONT_AND_BACK)
+            {
+                context->stencilBackFunc = func;
+                context->stencilBackRef = ref;
+                context->stencilBackMask = mask;
+            }
+        }
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(GL_OUT_OF_MEMORY);
+    }
+}
+
+void __stdcall glStencilMask(GLuint mask)
+{
+    glStencilMaskSeparate(GL_FRONT_AND_BACK, mask);
+}
+
+void __stdcall 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->stencilWritemask = mask;
+            }
+
+            if (face == GL_BACK || face == GL_FRONT_AND_BACK)
+            {
+                context->stencilBackWritemask = mask;
+            }
+        }
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(GL_OUT_OF_MEMORY);
+    }
+}
+
+void __stdcall glStencilOp(GLenum fail, GLenum zfail, GLenum zpass)
+{
+    glStencilOpSeparate(GL_FRONT_AND_BACK, fail, zfail, zpass);
+}
+
+void __stdcall 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->stencilFail = fail;
+                context->stencilPassDepthFail = zfail;
+                context->stencilPassDepthPass = zpass;
+            }
+
+            if (face == GL_BACK || face == GL_FRONT_AND_BACK)
+            {
+                context->stencilBackFail = fail;
+                context->stencilBackPassDepthFail = zfail;
+                context->stencilBackPassDepthPass = zpass;
+            }
+        }
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(GL_OUT_OF_MEMORY);
+    }
+}
+
+void __stdcall glTexImage2D(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const void* 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 void* pixels =  0x%0.8p", target, level, internalformat, width, height, border, format, type, pixels);
+
+    try
+    {
+        if (level < 0 || width < 0 || height < 0)
+        {
+            return error(GL_INVALID_VALUE);
+        }
+
+        if (level > 0 && (!gl::isPow2(width) || !gl::isPow2(height)))
+        {
+            return error(GL_INVALID_VALUE);
+        }
+        
+        switch (target)
+        {
+          case GL_TEXTURE_2D:
+            if (width > (gl::MAX_TEXTURE_SIZE >> level) || height > (gl::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 (!gl::isPow2(width) || !gl::isPow2(height))
+            {
+                return error(GL_INVALID_VALUE);
+            }
+
+            if (width > (gl::MAX_CUBE_MAP_TEXTURE_SIZE >> level) || height > (gl::MAX_CUBE_MAP_TEXTURE_SIZE >> level))
+            {
+                return error(GL_INVALID_VALUE);
+            }
+            break;
+          default:
+            return error(GL_INVALID_ENUM);
+        }
+
+        if (internalformat != format)
+        {
+            return error(GL_INVALID_OPERATION);
+        }
+
+        switch (internalformat)
+        {
+          case GL_ALPHA:
+          case GL_LUMINANCE:
+          case GL_LUMINANCE_ALPHA:
+            switch (type)
+            {
+              case GL_UNSIGNED_BYTE:
+                break;
+              default:
+                return error(GL_INVALID_ENUM);
+            }
+            break;
+          case GL_RGB:
+            switch (type)
+            {
+              case GL_UNSIGNED_BYTE:
+              case GL_UNSIGNED_SHORT_5_6_5:
+                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:
+                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)
+        {
+            if (target == GL_TEXTURE_2D)
+            {
+                gl::Texture2D *texture = context->getTexture2D();
+
+                if (!texture)
+                {
+                    return error(GL_INVALID_OPERATION);
+                }
+
+                texture->setImage(level, internalformat, width, height, format, type, pixels);
+            }
+            else
+            {
+                gl::TextureCubeMap *texture = context->getTextureCubeMap();
+
+                if (!texture)
+                {
+                    return error(GL_INVALID_OPERATION);
+                }
+
+                switch (target)
+                {
+                  case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
+                    texture->setImagePosX(level, internalformat, width, height, format, type, pixels);
+                    break;
+                  case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
+                    texture->setImageNegX(level, internalformat, width, height, format, type, pixels);
+                    break;
+                  case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
+                    texture->setImagePosY(level, internalformat, width, height, format, type, pixels);
+                    break;
+                  case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
+                    texture->setImageNegY(level, internalformat, width, height, format, type, pixels);
+                    break;
+                  case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
+                    texture->setImagePosZ(level, internalformat, width, height, format, type, pixels);
+                    break;
+                  case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
+                    texture->setImageNegZ(level, internalformat, width, height, format, type, pixels);
+                    break;
+                  default: UNREACHABLE();
+                }
+            }
+        }
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(GL_OUT_OF_MEMORY);
+    }
+}
+
+void __stdcall glTexParameterf(GLenum target, GLenum pname, GLfloat param)
+{
+    glTexParameteri(target, pname, (GLint)param);
+}
+
+void __stdcall glTexParameterfv(GLenum target, GLenum pname, const GLfloat* params)
+{
+    glTexParameteri(target, pname, (GLint)*params);
+}
+
+void __stdcall glTexParameteri(GLenum target, GLenum pname, GLint 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;
+              default:
+                return error(GL_INVALID_ENUM);
+            }
+        }
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(GL_OUT_OF_MEMORY);
+    }
+}
+
+void __stdcall glTexParameteriv(GLenum target, GLenum pname, const GLint* params)
+{
+    glTexParameteri(target, pname, *params);
+}
+
+void __stdcall glTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void* 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 void* pixels = 0x%0.8p",
+           target, level, xoffset, yoffset, width, height, format, type, pixels);
+
+    try
+    {
+        if (width < 0 || height < 0)
+        {
+            return error(GL_INVALID_VALUE);
+        }
+
+        UNIMPLEMENTED();   // FIXME
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(GL_OUT_OF_MEMORY);
+    }
+}
+
+void __stdcall glUniform1f(GLint location, GLfloat x)
+{
+    glUniform1fv(location, 1, &x);
+}
+
+void __stdcall 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 (location == -1)
+        {
+            return;
+        }
+
+        if (count < 0)
+        {
+            return error(GL_INVALID_VALUE);
+        }
+
+        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 __stdcall glUniform1i(GLint location, GLint x)
+{
+    glUniform1iv(location, 1, &x);
+}
+
+void __stdcall 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);
+        }
+
+        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 __stdcall glUniform2f(GLint location, GLfloat x, GLfloat y)
+{
+    GLfloat xy[2] = {x, y};
+
+    glUniform2fv(location, 1, (GLfloat*)&xy);
+}
+
+void __stdcall 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 (location == -1)
+        {
+            return;
+        }
+
+        if (count < 0)
+        {
+            return error(GL_INVALID_VALUE);
+        }
+
+        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 __stdcall glUniform2i(GLint location, GLint x, GLint y)
+{
+    GLint xy[4] = {x, y};
+
+    glUniform2iv(location, 1, (GLint*)&xy);
+}
+
+void __stdcall 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);
+        }
+
+        UNIMPLEMENTED();   // FIXME
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(GL_OUT_OF_MEMORY);
+    }
+}
+
+void __stdcall glUniform3f(GLint location, GLfloat x, GLfloat y, GLfloat z)
+{
+    GLfloat xyz[3] = {x, y, z};
+
+    glUniform3fv(location, 1, (GLfloat*)&xyz);
+}
+
+void __stdcall 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 __stdcall glUniform3i(GLint location, GLint x, GLint y, GLint z)
+{
+    GLint xyz[3] = {x, y, z};
+
+    glUniform3iv(location, 1, (GLint*)&xyz);
+}
+
+void __stdcall 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);
+        }
+
+        UNIMPLEMENTED();   // FIXME
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(GL_OUT_OF_MEMORY);
+    }
+}
+
+void __stdcall glUniform4f(GLint location, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
+{
+    GLfloat xyzw[4] = {x, y, z, w};
+
+    glUniform4fv(location, 1, (GLfloat*)&xyzw);
+}
+
+void __stdcall 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 __stdcall glUniform4i(GLint location, GLint x, GLint y, GLint z, GLint w)
+{
+    GLint xyzw[4] = {x, y, z, w};
+
+    glUniform4iv(location, 1, (GLint*)&xyzw);
+}
+
+void __stdcall 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);
+        }
+
+        UNIMPLEMENTED();   // FIXME
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(GL_OUT_OF_MEMORY);
+    }
+}
+
+void __stdcall 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 __stdcall 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 __stdcall 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 __stdcall glUseProgram(GLuint program)
+{
+    TRACE("GLuint program = %d", program);
+
+    try
+    {
+        gl::Context *context = gl::getContext();
+
+        if (context)
+        {
+            gl::Program *programObject = context->getProgram(program);
+
+            if (programObject && !programObject->isLinked())
+            {
+                return error(GL_INVALID_OPERATION);
+            }
+
+            context->useProgram(program);
+        }
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(GL_OUT_OF_MEMORY);
+    }
+}
+
+void __stdcall glValidateProgram(GLuint program)
+{
+    TRACE("GLuint program = %d", program);
+
+    try
+    {
+        UNIMPLEMENTED();   // FIXME
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(GL_OUT_OF_MEMORY);
+    }
+}
+
+void __stdcall 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);
+        }
+
+        UNIMPLEMENTED();   // FIXME
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(GL_OUT_OF_MEMORY);
+    }
+}
+
+void __stdcall 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);
+        }
+
+        UNIMPLEMENTED();   // FIXME
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(GL_OUT_OF_MEMORY);
+    }
+}
+
+void __stdcall 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);
+        }
+
+        UNIMPLEMENTED();   // FIXME
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(GL_OUT_OF_MEMORY);
+    }
+}
+
+void __stdcall 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);
+        }
+
+        UNIMPLEMENTED();   // FIXME
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(GL_OUT_OF_MEMORY);
+    }
+}
+
+void __stdcall 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);
+        }
+
+        UNIMPLEMENTED();   // FIXME
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(GL_OUT_OF_MEMORY);
+    }
+}
+
+void __stdcall 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);
+        }
+
+        UNIMPLEMENTED();   // FIXME
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(GL_OUT_OF_MEMORY);
+    }
+}
+
+void __stdcall 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);
+        }
+
+        UNIMPLEMENTED();   // FIXME
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(GL_OUT_OF_MEMORY);
+    }
+}
+
+void __stdcall 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);
+        }
+
+        UNIMPLEMENTED();   // FIXME
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(GL_OUT_OF_MEMORY);
+    }
+}
+
+void __stdcall glVertexAttribPointer(GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void* ptr)
+{
+    TRACE("GLuint index = %d, GLint size = %d, GLenum type = 0x%X, GLboolean normalized = %d, GLsizei stride = %d, const void* 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->vertexAttribute[index].boundBuffer = context->arrayBuffer;
+            context->vertexAttribute[index].size = size;
+            context->vertexAttribute[index].type = type;
+            context->vertexAttribute[index].normalized = normalized;
+            context->vertexAttribute[index].stride = stride;
+            context->vertexAttribute[index].pointer = ptr;
+        }
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(GL_OUT_OF_MEMORY);
+    }
+}
+
+void __stdcall 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->viewportX = x;
+            context->viewportY = y;
+            context->viewportWidth = width;
+            context->viewportHeight = height;
+        }
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(GL_OUT_OF_MEMORY);
+    }
+}
+
+void __stdcall glTexImage3DOES(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const void* 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 void* 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);
+    }
+}
+}
diff --git a/libGLESv2/libGLESv2.def b/libGLESv2/libGLESv2.def
new file mode 100644
index 0000000..2ae969f
--- /dev/null
+++ b/libGLESv2/libGLESv2.def
@@ -0,0 +1,153 @@
+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
+	
+    ; EGL dependencies
+	glCreateContext					@144 NONAME
+	glDestroyContext				@145 NONAME
+	glMakeCurrent					@146 NONAME
+	glGetCurrentContext				@147 NONAME
\ No newline at end of file
diff --git a/libGLESv2/libGLESv2.vcproj b/libGLESv2/libGLESv2.vcproj
new file mode 100644
index 0000000..9752c42
--- /dev/null
+++ b/libGLESv2/libGLESv2.vcproj
@@ -0,0 +1,331 @@
+<?xml version="1.0" encoding="Windows-1252"?>

+<VisualStudioProject

+	ProjectType="Visual C++"

+	Version="9.00"

+	Name="libGLESv2"

+	ProjectGUID="{B5871A7A-968C-42E3-A33B-981E6F448E78}"

+	RootNamespace="libGLESv2"

+	Keyword="Win32Proj"

+	TargetFrameworkVersion="131072"

+	>

+	<Platforms>

+		<Platform

+			Name="Win32"

+		/>

+	</Platforms>

+	<ToolFiles>

+	</ToolFiles>

+	<Configurations>

+		<Configuration

+			Name="Debug|Win32"

+			OutputDirectory="$(SolutionDir)$(ConfigurationName)"

+			IntermediateDirectory="$(ConfigurationName)"

+			ConfigurationType="2"

+			CharacterSet="1"

+			>

+			<Tool

+				Name="VCPreBuildEventTool"

+			/>

+			<Tool

+				Name="VCCustomBuildTool"

+			/>

+			<Tool

+				Name="VCXMLDataGeneratorTool"

+			/>

+			<Tool

+				Name="VCWebServiceProxyGeneratorTool"

+			/>

+			<Tool

+				Name="VCMIDLTool"

+			/>

+			<Tool

+				Name="VCCLCompilerTool"

+				Optimization="0"

+				AdditionalIncludeDirectories="../Include/; ../Compiler/"

+				PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;LIBGLESV2_EXPORTS;_CRT_SECURE_NO_DEPRECATE"

+				MinimalRebuild="true"

+				BasicRuntimeChecks="3"

+				RuntimeLibrary="1"

+				UsePrecompiledHeader="0"

+				WarningLevel="3"

+				Detect64BitPortabilityProblems="false"

+				DebugInformationFormat="4"

+			/>

+			<Tool

+				Name="VCManagedResourceCompilerTool"

+			/>

+			<Tool

+				Name="VCResourceCompilerTool"

+			/>

+			<Tool

+				Name="VCPreLinkEventTool"

+			/>

+			<Tool

+				Name="VCLinkerTool"

+				AdditionalDependencies="D3dx9.lib"

+				LinkIncremental="2"

+				ModuleDefinitionFile="libGLESv2.def"

+				GenerateDebugInformation="true"

+				SubSystem="2"

+				RandomizedBaseAddress="1"

+				DataExecutionPrevention="0"

+				TargetMachine="1"

+			/>

+			<Tool

+				Name="VCALinkTool"

+			/>

+			<Tool

+				Name="VCManifestTool"

+			/>

+			<Tool

+				Name="VCXDCMakeTool"

+			/>

+			<Tool

+				Name="VCBscMakeTool"

+			/>

+			<Tool

+				Name="VCFxCopTool"

+			/>

+			<Tool

+				Name="VCAppVerifierTool"

+			/>

+			<Tool

+				Name="VCPostBuildEventTool"

+			/>

+		</Configuration>

+		<Configuration

+			Name="Release|Win32"

+			OutputDirectory="$(SolutionDir)$(ConfigurationName)"

+			IntermediateDirectory="$(ConfigurationName)"

+			ConfigurationType="2"

+			CharacterSet="1"

+			WholeProgramOptimization="1"

+			>

+			<Tool

+				Name="VCPreBuildEventTool"

+			/>

+			<Tool

+				Name="VCCustomBuildTool"

+			/>

+			<Tool

+				Name="VCXMLDataGeneratorTool"

+			/>

+			<Tool

+				Name="VCWebServiceProxyGeneratorTool"

+			/>

+			<Tool

+				Name="VCMIDLTool"

+			/>

+			<Tool

+				Name="VCCLCompilerTool"

+				AdditionalIncludeDirectories="../Include/; ../Compiler/"

+				PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;LIBGLESV2_EXPORTS;_CRT_SECURE_NO_DEPRECATE"

+				RuntimeLibrary="0"

+				UsePrecompiledHeader="0"

+				WarningLevel="3"

+				Detect64BitPortabilityProblems="false"

+				DebugInformationFormat="3"

+			/>

+			<Tool

+				Name="VCManagedResourceCompilerTool"

+			/>

+			<Tool

+				Name="VCResourceCompilerTool"

+			/>

+			<Tool

+				Name="VCPreLinkEventTool"

+			/>

+			<Tool

+				Name="VCLinkerTool"

+				AdditionalDependencies="D3dx9.lib"

+				LinkIncremental="1"

+				IgnoreAllDefaultLibraries="false"

+				ModuleDefinitionFile="libGLESv2.def"

+				GenerateDebugInformation="true"

+				SubSystem="2"

+				OptimizeReferences="2"

+				EnableCOMDATFolding="2"

+				RandomizedBaseAddress="1"

+				DataExecutionPrevention="0"

+				TargetMachine="1"

+			/>

+			<Tool

+				Name="VCALinkTool"

+			/>

+			<Tool

+				Name="VCManifestTool"

+			/>

+			<Tool

+				Name="VCXDCMakeTool"

+			/>

+			<Tool

+				Name="VCBscMakeTool"

+			/>

+			<Tool

+				Name="VCFxCopTool"

+			/>

+			<Tool

+				Name="VCAppVerifierTool"

+			/>

+			<Tool

+				Name="VCPostBuildEventTool"

+			/>

+		</Configuration>

+	</Configurations>

+	<References>

+	</References>

+	<Files>

+		<Filter

+			Name="Source Files"

+			Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"

+			UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"

+			>

+			<File

+				RelativePath=".\Buffer.cpp"

+				>

+			</File>

+			<File

+				RelativePath=".\Context.cpp"

+				>

+			</File>

+			<File

+				RelativePath="..\Common\debug.cpp"

+				>

+			</File>

+			<File

+				RelativePath=".\Framebuffer.cpp"

+				>

+			</File>

+			<File

+				RelativePath=".\libGLESv2.cpp"

+				>

+			</File>

+			<File

+				RelativePath=".\main.cpp"

+				>

+			</File>

+			<File

+				RelativePath=".\Program.cpp"

+				>

+			</File>

+			<File

+				RelativePath=".\Renderbuffer.cpp"

+				>

+			</File>

+			<File

+				RelativePath=".\Shader.cpp"

+				>

+			</File>

+			<File

+				RelativePath=".\Texture.cpp"

+				>

+			</File>

+			<File

+				RelativePath=".\utilities.cpp"

+				>

+			</File>

+		</Filter>

+		<Filter

+			Name="Header Files"

+			Filter="h;hpp;hxx;hm;inl;inc;xsd"

+			UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"

+			>

+			<File

+				RelativePath="..\Include\angleutils.h"

+				>

+			</File>

+			<File

+				RelativePath=".\Buffer.h"

+				>

+			</File>

+			<File

+				RelativePath="..\Include\Config.h"

+				>

+			</File>

+			<File

+				RelativePath="..\Include\Context.h"

+				>

+			</File>

+			<File

+				RelativePath="..\Include\debug.h"

+				>

+			</File>

+			<File

+				RelativePath="..\Include\Display.h"

+				>

+			</File>

+			<File

+				RelativePath=".\Framebuffer.h"

+				>

+			</File>

+			<File

+				RelativePath="..\Include\GLES2\gl2.h"

+				>

+			</File>

+			<File

+				RelativePath="..\Include\GLES2\gl2ext.h"

+				>

+			</File>

+			<File

+				RelativePath="..\Include\GLES2\gl2platform.h"

+				>

+			</File>

+			<File

+				RelativePath="..\Include\KHR\khrplatform.h"

+				>

+			</File>

+			<File

+				RelativePath=".\main.h"

+				>

+			</File>

+			<File

+				RelativePath=".\mathutil.h"

+				>

+			</File>

+			<File

+				RelativePath=".\Program.h"

+				>

+			</File>

+			<File

+				RelativePath=".\Renderbuffer.h"

+				>

+			</File>

+			<File

+				RelativePath=".\Shader.h"

+				>

+			</File>

+			<File

+				RelativePath=".\Texture.h"

+				>

+			</File>

+			<File

+				RelativePath=".\utilities.h"

+				>

+			</File>

+		</Filter>

+		<Filter

+			Name="Resource Files"

+			Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav"

+			UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"

+			>

+		</Filter>

+		<File

+			RelativePath="..\AUTHORS"

+			>

+		</File>

+		<File

+			RelativePath="..\CONTRIBUTORS"

+			>

+		</File>

+		<File

+			RelativePath=".\libGLESv2.def"

+			>

+		</File>

+		<File

+			RelativePath="..\LICENSE"

+			>

+		</File>

+	</Files>

+	<Globals>

+	</Globals>

+</VisualStudioProject>

diff --git a/libGLESv2/main.cpp b/libGLESv2/main.cpp
new file mode 100644
index 0000000..d729038
--- /dev/null
+++ b/libGLESv2/main.cpp
@@ -0,0 +1,136 @@
+//
+// 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.
+//
+
+// main.cpp: DLL entry point and management of thread-local data.
+
+#include "main.h"
+
+#include "Framebuffer.h"
+#include "Surface.h"
+#include "debug.h"
+
+static DWORD currentTLS = TLS_OUT_OF_INDEXES;
+
+BOOL WINAPI DllMain(HINSTANCE instance, DWORD reason, LPVOID reserved)
+{
+    switch (reason)
+    {
+      case DLL_PROCESS_ATTACH:
+        {
+            currentTLS = TlsAlloc();
+
+            if (currentTLS == TLS_OUT_OF_INDEXES)
+            {
+                return FALSE;
+            }
+        }
+        // Fall throught to initialize index
+      case DLL_THREAD_ATTACH: 
+        {
+            gl::Current *current = (gl::Current*)LocalAlloc(LPTR, sizeof(gl::Current)); 
+            
+            if (current)
+            {
+                TlsSetValue(currentTLS, current);
+
+                current->context = NULL;
+                current->display = NULL;
+            }
+        }
+        break; 
+      case DLL_THREAD_DETACH:
+        {
+            void *current = TlsGetValue(currentTLS);
+        
+            if (current)
+            {
+                LocalFree((HLOCAL)current);
+            }
+        }
+        break; 
+      case DLL_PROCESS_DETACH:
+        {
+            void *current = TlsGetValue(currentTLS);
+
+            if (current)
+            {
+                LocalFree((HLOCAL)current);
+            }
+ 
+            TlsFree(currentTLS);
+        }
+        break; 
+      default: 
+        break; 
+    } 
+ 
+    return TRUE;
+}
+
+namespace gl
+{
+void makeCurrent(Context *context, egl::Display *display, egl::Surface *surface)
+{
+    Current *current = (Current*)TlsGetValue(currentTLS);
+
+    current->context = context;
+    current->display = display;
+
+    if (context && display && surface)
+    {
+        context->makeCurrent(display, surface);
+    }
+}
+
+Context *getContext()
+{
+    Current *current = (Current*)TlsGetValue(currentTLS);
+
+    return current->context;
+}
+
+IDirect3DDevice9 *getDevice()
+{
+    Current *current = (Current*)TlsGetValue(currentTLS);
+    egl::Display *display = current->display;
+
+    return display->getDevice();
+}
+}
+
+// Records an error code
+void error(GLenum errorCode)
+{
+    gl::Context *context = glGetCurrentContext();
+
+    if (context)
+    {
+        switch (errorCode)
+        {
+          case GL_INVALID_ENUM:
+            context->recordInvalidEnum();
+            gl::trace("\t! Error generated: invalid enum\n");
+            break;
+          case GL_INVALID_VALUE:
+            context->recordInvalidValue();
+            gl::trace("\t! Error generated: invalid value\n");
+            break;
+          case GL_INVALID_OPERATION:
+            context->recordInvalidOperation();
+            gl::trace("\t! Error generated: invalid operation\n");
+            break;
+          case GL_OUT_OF_MEMORY:
+            context->recordOutOfMemory();
+            gl::trace("\t! Error generated: out of memory\n");
+            break;
+          case GL_INVALID_FRAMEBUFFER_OPERATION:
+            context->recordInvalidFramebufferOperation();
+            gl::trace("\t! Error generated: invalid framebuffer operation\n");
+            break;
+          default: UNREACHABLE();
+        }
+    }
+}
diff --git a/libGLESv2/main.h b/libGLESv2/main.h
new file mode 100644
index 0000000..d8cc5c2
--- /dev/null
+++ b/libGLESv2/main.h
@@ -0,0 +1,45 @@
+//
+// 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.
+//
+
+// main.h: Management of thread-local data.
+
+#ifndef LIBGLESV2_MAIN_H_
+#define LIBGLESV2_MAIN_H_
+
+#define GL_APICALL
+#include <GLES2/gl2.h>
+
+#include "Context.h"
+#include "Display.h"
+#include "debug.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();
+
+IDirect3DDevice9 *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/libGLESv2/mathutil.h b/libGLESv2/mathutil.h
new file mode 100644
index 0000000..93c9945
--- /dev/null
+++ b/libGLESv2/mathutil.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.
+//
+
+// mathutil.h: Math and bit manipulation functions.
+
+#ifndef LIBGLESV2_MATHUTIL_H_
+#define LIBGLESV2_MATHUTIL_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 float clamp01(float x)
+{
+    return x < 0 ? 0 : (x > 1 ? 1 : x);
+}
+
+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/libGLESv2/utilities.cpp b/libGLESv2/utilities.cpp
new file mode 100644
index 0000000..4c604f9
--- /dev/null
+++ b/libGLESv2/utilities.cpp
@@ -0,0 +1,358 @@
+//
+// 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.
+//
+
+// utilities.cpp: Conversion functions and other utility routines.
+
+#include "utilities.h"
+
+#include "debug.h"
+#include "mathutil.h"
+#include "Context.h"
+
+namespace es2dx
+{
+
+D3DCMPFUNC ConvertComparison(GLenum comparison) 
+{
+    D3DCMPFUNC d3dComp = D3DCMP_ALWAYS;
+    switch (comparison)
+    {
+      case GL_NEVER:    d3dComp = D3DCMP_NEVER;        break;
+      case GL_ALWAYS:   d3dComp = D3DCMP_ALWAYS;       break;
+      case GL_LESS:     d3dComp = D3DCMP_LESS;         break;
+      case GL_LEQUAL:   d3dComp = D3DCMP_LESSEQUAL;    break;
+      case GL_EQUAL:    d3dComp = D3DCMP_EQUAL;        break;
+      case GL_GREATER:  d3dComp = D3DCMP_GREATER;      break;
+      case GL_GEQUAL:   d3dComp = D3DCMP_GREATEREQUAL; break;
+      case GL_NOTEQUAL: d3dComp = D3DCMP_NOTEQUAL;     break;
+      default: UNREACHABLE();
+    }
+
+    return d3dComp;
+}
+
+D3DCOLOR ConvertColor(gl::Color color)
+{
+    return D3DCOLOR_RGBA(gl::unorm<8>(color.red),
+                         gl::unorm<8>(color.blue),
+                         gl::unorm<8>(color.green),
+                         gl::unorm<8>(color.alpha));
+}
+
+D3DBLEND ConvertBlendFunc(GLenum blend)
+{
+    D3DBLEND d3dBlend = D3DBLEND_ZERO;
+
+    switch (blend)
+    {
+      case GL_ZERO:                     d3dBlend = D3DBLEND_ZERO;           break;
+      case GL_ONE:                      d3dBlend = D3DBLEND_ONE;            break;
+      case GL_SRC_COLOR:                d3dBlend = D3DBLEND_SRCCOLOR;       break;
+      case GL_ONE_MINUS_SRC_COLOR:      d3dBlend = D3DBLEND_INVSRCCOLOR;    break;
+      case GL_DST_COLOR:                d3dBlend = D3DBLEND_DESTCOLOR;      break;
+      case GL_ONE_MINUS_DST_COLOR:      d3dBlend = D3DBLEND_INVDESTCOLOR;   break;
+      case GL_SRC_ALPHA:                d3dBlend = D3DBLEND_SRCALPHA;       break;
+      case GL_ONE_MINUS_SRC_ALPHA:      d3dBlend = D3DBLEND_INVSRCALPHA;    break;
+      case GL_DST_ALPHA:                d3dBlend = D3DBLEND_DESTALPHA;      break;
+      case GL_ONE_MINUS_DST_ALPHA:      d3dBlend = D3DBLEND_INVDESTALPHA;   break;
+      case GL_CONSTANT_COLOR:           d3dBlend = D3DBLEND_BLENDFACTOR;    break;
+      case GL_ONE_MINUS_CONSTANT_COLOR: d3dBlend = D3DBLEND_INVBLENDFACTOR; break;
+      case GL_CONSTANT_ALPHA:           d3dBlend = D3DBLEND_BLENDFACTOR;    break;
+      case GL_ONE_MINUS_CONSTANT_ALPHA: d3dBlend = D3DBLEND_INVBLENDFACTOR; break;
+      case GL_SRC_ALPHA_SATURATE:       d3dBlend = D3DBLEND_SRCALPHASAT;    break;
+      default: UNREACHABLE();
+    }
+
+    return d3dBlend;
+}
+
+D3DBLENDOP ConvertBlendOp(GLenum blendOp)
+{
+    D3DBLENDOP d3dBlendOp = D3DBLENDOP_ADD;
+
+    switch (blendOp)
+    {
+      case GL_FUNC_ADD:              d3dBlendOp = D3DBLENDOP_ADD;         break;
+      case GL_FUNC_SUBTRACT:         d3dBlendOp = D3DBLENDOP_SUBTRACT;    break;
+      case GL_FUNC_REVERSE_SUBTRACT: d3dBlendOp = D3DBLENDOP_REVSUBTRACT; break;
+      default: UNREACHABLE();
+    }
+
+    return d3dBlendOp;
+}
+
+D3DSTENCILOP ConvertStencilOp(GLenum stencilOp)
+{
+    D3DSTENCILOP d3dStencilOp = D3DSTENCILOP_KEEP;
+
+    switch (stencilOp)
+    {
+      case GL_ZERO:      d3dStencilOp = D3DSTENCILOP_ZERO;    break;
+      case GL_KEEP:      d3dStencilOp = D3DSTENCILOP_KEEP;    break;
+      case GL_REPLACE:   d3dStencilOp = D3DSTENCILOP_REPLACE; break;
+      case GL_INCR:      d3dStencilOp = D3DSTENCILOP_INCRSAT; break;
+      case GL_DECR:      d3dStencilOp = D3DSTENCILOP_DECRSAT; break;
+      case GL_INVERT:    d3dStencilOp = D3DSTENCILOP_INVERT;  break;
+      case GL_INCR_WRAP: d3dStencilOp = D3DSTENCILOP_INCR;    break;
+      case GL_DECR_WRAP: d3dStencilOp = D3DSTENCILOP_DECR;    break;
+      default: UNREACHABLE();
+    }
+
+    return d3dStencilOp;
+}
+
+D3DTEXTUREADDRESS ConvertTextureWrap(GLenum wrap)
+{
+    D3DTEXTUREADDRESS d3dWrap = D3DTADDRESS_WRAP;
+
+    switch (wrap)
+    {
+      case GL_REPEAT:            d3dWrap = D3DTADDRESS_WRAP;   break;
+      case GL_CLAMP_TO_EDGE:     d3dWrap = D3DTADDRESS_CLAMP;  break;
+      case GL_MIRRORED_REPEAT:   d3dWrap = D3DTADDRESS_MIRROR; break;
+      default: UNREACHABLE();
+    }
+
+    return d3dWrap;
+}
+
+D3DCULL ConvertCullMode(GLenum cullFace, GLenum frontFace)
+{
+    D3DCULL cull = D3DCULL_CCW;
+    switch (cullFace)
+    {
+      case GL_FRONT:
+        cull = (frontFace == GL_CCW ? D3DCULL_CW : D3DCULL_CCW);
+        break;
+      case GL_BACK:
+        cull = (frontFace == GL_CCW ? D3DCULL_CCW : D3DCULL_CW);
+        break;
+      case GL_FRONT_AND_BACK:
+        UNIMPLEMENTED();   // FIXME
+        break;
+      default: UNREACHABLE();
+    }
+
+    return cull;
+}
+
+DWORD ConvertColorMask(bool red, bool green, bool blue, bool alpha)
+{
+    return (red   ? D3DCOLORWRITEENABLE_RED   : 0) |
+           (green ? D3DCOLORWRITEENABLE_GREEN : 0) |
+           (blue  ? D3DCOLORWRITEENABLE_BLUE  : 0) |
+           (alpha ? D3DCOLORWRITEENABLE_ALPHA : 0);
+}
+
+D3DTEXTUREFILTERTYPE ConvertMagFilter(GLenum magFilter)
+{
+    D3DTEXTUREFILTERTYPE d3dMagFilter = D3DTEXF_POINT;
+    switch (magFilter)
+    {
+      case GL_NEAREST: d3dMagFilter = D3DTEXF_POINT;  break;
+      case GL_LINEAR:  d3dMagFilter = D3DTEXF_LINEAR; break;
+      default: UNREACHABLE();
+    }
+
+    return d3dMagFilter;
+}
+
+void ConvertMinFilter(GLenum minFilter, D3DTEXTUREFILTERTYPE *d3dMinFilter, D3DTEXTUREFILTERTYPE *d3dMipFilter)
+{
+    switch (minFilter)
+    {
+      case GL_NEAREST:
+        *d3dMinFilter = D3DTEXF_POINT;
+        *d3dMipFilter = D3DTEXF_NONE;
+        break;
+      case GL_LINEAR:
+        *d3dMinFilter = D3DTEXF_LINEAR;
+        *d3dMipFilter = D3DTEXF_NONE;
+        break;
+      case GL_NEAREST_MIPMAP_NEAREST:
+        *d3dMinFilter = D3DTEXF_POINT;
+        *d3dMipFilter = D3DTEXF_POINT;
+        break;
+      case GL_LINEAR_MIPMAP_NEAREST:
+        *d3dMinFilter = D3DTEXF_LINEAR;
+        *d3dMipFilter = D3DTEXF_POINT;
+        break;
+      case GL_NEAREST_MIPMAP_LINEAR:
+        *d3dMinFilter = D3DTEXF_POINT;
+        *d3dMipFilter = D3DTEXF_LINEAR;
+        break;
+      case GL_LINEAR_MIPMAP_LINEAR:
+        *d3dMinFilter = D3DTEXF_LINEAR;
+        *d3dMipFilter = D3DTEXF_LINEAR;
+        break;
+      default: 
+        *d3dMinFilter = D3DTEXF_POINT;
+        *d3dMipFilter = D3DTEXF_NONE;
+        UNREACHABLE();
+    }
+}
+
+unsigned int GetStencilSize(D3DFORMAT stencilFormat)
+{
+    switch(stencilFormat)
+    {
+      case D3DFMT_D24FS8:
+      case D3DFMT_D24S8:
+        return 8;
+      case D3DFMT_D24X4S4:
+        return 4;
+      case D3DFMT_D15S1:
+        return 1;
+      case D3DFMT_D16_LOCKABLE:
+      case D3DFMT_D32:
+      case D3DFMT_D24X8:
+      case D3DFMT_D32F_LOCKABLE:
+      case D3DFMT_D16:
+        return 0;
+//      case D3DFMT_D32_LOCKABLE:  return 0;   // DirectX 9Ex only
+//      case D3DFMT_S8_LOCKABLE:   return 8;   // DirectX 9Ex only
+      default: UNREACHABLE();
+    }
+    return 0;
+}
+
+unsigned int GetAlphaSize(D3DFORMAT colorFormat)
+{
+    switch (colorFormat)
+    {
+      case D3DFMT_A2R10G10B10:  
+        return 2;
+      case D3DFMT_A8R8G8B8:
+        return 8;
+      case D3DFMT_A1R5G5B5:
+        return 1;
+      case D3DFMT_X8R8G8B8:
+      case D3DFMT_X1R5G5B5:
+      case D3DFMT_R5G6B5:
+        return 0;
+      default: UNREACHABLE();
+    }
+    return 0;
+}
+
+unsigned int GetRedSize(D3DFORMAT colorFormat)
+{
+    switch (colorFormat)
+    {
+      case D3DFMT_A2R10G10B10:  
+        return 10;
+      case D3DFMT_A8R8G8B8:
+      case D3DFMT_X8R8G8B8:
+        return 8;
+      case D3DFMT_A1R5G5B5:
+      case D3DFMT_R5G6B5:
+      case D3DFMT_X1R5G5B5:
+        return 5;
+      default: UNREACHABLE();
+    }
+    return 0;
+}
+
+unsigned int GetGreenSize(D3DFORMAT colorFormat)
+{
+    switch (colorFormat)
+    {
+      case D3DFMT_A2R10G10B10:  
+        return 10;
+      case D3DFMT_A8R8G8B8:
+      case D3DFMT_X8R8G8B8:
+        return 8;
+      case D3DFMT_A1R5G5B5:
+      case D3DFMT_X1R5G5B5:
+        return 5;
+      case D3DFMT_R5G6B5:
+        return 6;
+      default: UNREACHABLE();
+    }
+    return 0;
+}
+
+unsigned int GetBlueSize(D3DFORMAT colorFormat)
+{
+    switch (colorFormat)
+    {
+      case D3DFMT_A2R10G10B10:  
+        return 10;
+      case D3DFMT_A8R8G8B8:
+      case D3DFMT_X8R8G8B8:
+        return 8;
+      case D3DFMT_A1R5G5B5:
+      case D3DFMT_R5G6B5:
+      case D3DFMT_X1R5G5B5:
+        return 5;
+      default: UNREACHABLE();
+    }
+    return 0;
+}
+
+unsigned int GetDepthSize(D3DFORMAT depthFormat)
+{
+    switch (depthFormat)
+    {
+      case D3DFMT_D16_LOCKABLE:  return 16;
+      case D3DFMT_D32:           return 32;
+      case D3DFMT_D15S1:         return 15;
+      case D3DFMT_D24S8:         return 24;
+      case D3DFMT_D24X8:         return 24;
+      case D3DFMT_D24X4S4:       return 24;
+      case D3DFMT_D16:           return 16;
+      case D3DFMT_D32F_LOCKABLE: return 32;
+      case D3DFMT_D24FS8:        return 24;
+//      case D3DFMT_D32_LOCKABLE:  return 32;   // D3D9Ex only
+//      case D3DFMT_S8_LOCKABLE:   return 0;    // D3D9Ex only
+      default:
+        UNREACHABLE();
+    }
+    return 0;
+}
+
+bool ConvertPrimitiveType(GLenum primitiveType, GLsizei primitiveCount, 
+                          D3DPRIMITIVETYPE *d3dPrimitiveType, int *d3dPrimitiveCount)
+{
+    switch (primitiveType)
+    {
+      case GL_POINTS:
+        *d3dPrimitiveType = D3DPT_POINTLIST;
+        *d3dPrimitiveCount = primitiveCount;
+        break;
+      case GL_LINES:
+        *d3dPrimitiveType = D3DPT_LINELIST;
+        *d3dPrimitiveCount = primitiveCount / 2;
+        break;
+      case GL_LINE_LOOP:
+        UNIMPLEMENTED();   // FIXME: Emulate using an index buffer
+        *d3dPrimitiveType = D3DPT_LINELIST;
+        *d3dPrimitiveCount = primitiveCount;
+        break;
+      case GL_LINE_STRIP:
+        *d3dPrimitiveType = D3DPT_LINESTRIP;
+        *d3dPrimitiveCount = primitiveCount - 1;
+        break;
+      case GL_TRIANGLES:
+        *d3dPrimitiveType = D3DPT_TRIANGLELIST;
+        *d3dPrimitiveCount = primitiveCount / 3;
+        break;
+      case GL_TRIANGLE_STRIP:
+        *d3dPrimitiveType = D3DPT_TRIANGLESTRIP;
+        *d3dPrimitiveCount = primitiveCount - 2;
+        break;
+      case GL_TRIANGLE_FAN:
+        *d3dPrimitiveType = D3DPT_TRIANGLEFAN;
+        *d3dPrimitiveCount = primitiveCount - 2;
+        break;
+      default:
+        return false;
+    }
+
+    return true;
+}
+
+}
diff --git a/libGLESv2/utilities.h b/libGLESv2/utilities.h
new file mode 100644
index 0000000..2222f5b
--- /dev/null
+++ b/libGLESv2/utilities.h
@@ -0,0 +1,45 @@
+//
+// 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.
+//
+
+// utilities.h: Conversion functions and other utility routines.
+
+#ifndef LIBGLESV2_UTILITIES_H
+#define LIBGLESV2_UTILITIES_H
+
+#define GL_APICALL
+#include <GLES2/gl2.h>
+#include <d3d9.h>
+
+namespace gl
+{
+struct Color;
+}
+
+namespace es2dx
+{
+
+D3DCMPFUNC ConvertComparison(GLenum comparison);
+D3DCOLOR ConvertColor(gl::Color color);
+D3DBLEND ConvertBlendFunc(GLenum blend);
+D3DBLENDOP ConvertBlendOp(GLenum blendOp);
+D3DSTENCILOP ConvertStencilOp(GLenum stencilOp);
+D3DTEXTUREADDRESS ConvertTextureWrap(GLenum wrap);
+D3DCULL ConvertCullMode(GLenum cullFace, GLenum frontFace);
+DWORD ConvertColorMask(bool red, bool green, bool blue, bool alpha);
+D3DTEXTUREFILTERTYPE ConvertMagFilter(GLenum magFilter);
+void ConvertMinFilter(GLenum minFilter, D3DTEXTUREFILTERTYPE *d3dMinFilter, D3DTEXTUREFILTERTYPE *d3dMipFilter);
+unsigned int GetAlphaSize(D3DFORMAT colorFormat);
+unsigned int GetRedSize(D3DFORMAT colorFormat);
+unsigned int GetGreenSize(D3DFORMAT colorFormat);
+unsigned int GetBlueSize(D3DFORMAT colorFormat);
+unsigned int GetDepthSize(D3DFORMAT depthFormat);
+unsigned int GetStencilSize(D3DFORMAT stencilFormat);
+bool ConvertPrimitiveType(GLenum primitiveType, GLsizei primitiveCount, 
+                          D3DPRIMITIVETYPE *d3dPrimitiveType, int *d3dPrimitiveCount);
+
+}
+
+#endif  // LIBGLESV2_UTILITIES_H