Missing files from previous commit.
authordino@apple.com <dino@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 24 Feb 2014 00:58:19 +0000 (00:58 +0000)
committerdino@apple.com <dino@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 24 Feb 2014 00:58:19 +0000 (00:58 +0000)
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@164567 268f45cc-cd09-0410-ab3c-d52691b4dbfc

189 files changed:
Source/ThirdParty/ANGLE/ChangeLog
Source/ThirdParty/ANGLE/src/compiler/translator/BaseTypes.h [new file with mode: 0644]
Source/ThirdParty/ANGLE/src/compiler/translator/BuiltInFunctionEmulator.cpp [new file with mode: 0644]
Source/ThirdParty/ANGLE/src/compiler/translator/BuiltInFunctionEmulator.h [new file with mode: 0644]
Source/ThirdParty/ANGLE/src/compiler/translator/CodeGen.cpp [new file with mode: 0644]
Source/ThirdParty/ANGLE/src/compiler/translator/Common.h [new file with mode: 0644]
Source/ThirdParty/ANGLE/src/compiler/translator/Compiler.cpp [new file with mode: 0644]
Source/ThirdParty/ANGLE/src/compiler/translator/ConstantUnion.h [new file with mode: 0644]
Source/ThirdParty/ANGLE/src/compiler/translator/DetectCallDepth.cpp [new file with mode: 0644]
Source/ThirdParty/ANGLE/src/compiler/translator/DetectCallDepth.h [new file with mode: 0644]
Source/ThirdParty/ANGLE/src/compiler/translator/DetectDiscontinuity.cpp [new file with mode: 0644]
Source/ThirdParty/ANGLE/src/compiler/translator/DetectDiscontinuity.h [new file with mode: 0644]
Source/ThirdParty/ANGLE/src/compiler/translator/Diagnostics.cpp [new file with mode: 0644]
Source/ThirdParty/ANGLE/src/compiler/translator/Diagnostics.h [new file with mode: 0644]
Source/ThirdParty/ANGLE/src/compiler/translator/DirectiveHandler.cpp [new file with mode: 0644]
Source/ThirdParty/ANGLE/src/compiler/translator/DirectiveHandler.h [new file with mode: 0644]
Source/ThirdParty/ANGLE/src/compiler/translator/ExtensionBehavior.h [new file with mode: 0644]
Source/ThirdParty/ANGLE/src/compiler/translator/ForLoopUnroll.cpp [new file with mode: 0644]
Source/ThirdParty/ANGLE/src/compiler/translator/ForLoopUnroll.h [new file with mode: 0644]
Source/ThirdParty/ANGLE/src/compiler/translator/HashNames.h [new file with mode: 0644]
Source/ThirdParty/ANGLE/src/compiler/translator/InfoSink.cpp [new file with mode: 0644]
Source/ThirdParty/ANGLE/src/compiler/translator/InfoSink.h [new file with mode: 0644]
Source/ThirdParty/ANGLE/src/compiler/translator/Initialize.cpp [new file with mode: 0644]
Source/ThirdParty/ANGLE/src/compiler/translator/Initialize.h [new file with mode: 0644]
Source/ThirdParty/ANGLE/src/compiler/translator/InitializeDll.cpp [new file with mode: 0644]
Source/ThirdParty/ANGLE/src/compiler/translator/InitializeDll.h [new file with mode: 0644]
Source/ThirdParty/ANGLE/src/compiler/translator/InitializeGlobals.h [new file with mode: 0644]
Source/ThirdParty/ANGLE/src/compiler/translator/InitializeParseContext.cpp [new file with mode: 0644]
Source/ThirdParty/ANGLE/src/compiler/translator/InitializeParseContext.h [new file with mode: 0644]
Source/ThirdParty/ANGLE/src/compiler/translator/InitializeVariables.cpp [new file with mode: 0644]
Source/ThirdParty/ANGLE/src/compiler/translator/InitializeVariables.h [new file with mode: 0644]
Source/ThirdParty/ANGLE/src/compiler/translator/IntermTraverse.cpp [new file with mode: 0644]
Source/ThirdParty/ANGLE/src/compiler/translator/Intermediate.cpp [new file with mode: 0644]
Source/ThirdParty/ANGLE/src/compiler/translator/MMap.h [new file with mode: 0644]
Source/ThirdParty/ANGLE/src/compiler/translator/MapLongVariableNames.cpp [new file with mode: 0644]
Source/ThirdParty/ANGLE/src/compiler/translator/MapLongVariableNames.h [new file with mode: 0644]
Source/ThirdParty/ANGLE/src/compiler/translator/NodeSearch.h [new file with mode: 0644]
Source/ThirdParty/ANGLE/src/compiler/translator/OutputESSL.cpp [new file with mode: 0644]
Source/ThirdParty/ANGLE/src/compiler/translator/OutputESSL.h [new file with mode: 0644]
Source/ThirdParty/ANGLE/src/compiler/translator/OutputGLSL.cpp [new file with mode: 0644]
Source/ThirdParty/ANGLE/src/compiler/translator/OutputGLSL.h [new file with mode: 0644]
Source/ThirdParty/ANGLE/src/compiler/translator/OutputGLSLBase.cpp [new file with mode: 0644]
Source/ThirdParty/ANGLE/src/compiler/translator/OutputGLSLBase.h [new file with mode: 0644]
Source/ThirdParty/ANGLE/src/compiler/translator/OutputHLSL.cpp [new file with mode: 0644]
Source/ThirdParty/ANGLE/src/compiler/translator/OutputHLSL.h [new file with mode: 0644]
Source/ThirdParty/ANGLE/src/compiler/translator/ParseContext.cpp [new file with mode: 0644]
Source/ThirdParty/ANGLE/src/compiler/translator/ParseContext.h [new file with mode: 0644]
Source/ThirdParty/ANGLE/src/compiler/translator/PoolAlloc.cpp [new file with mode: 0644]
Source/ThirdParty/ANGLE/src/compiler/translator/PoolAlloc.h [new file with mode: 0644]
Source/ThirdParty/ANGLE/src/compiler/translator/Pragma.h [new file with mode: 0644]
Source/ThirdParty/ANGLE/src/compiler/translator/QualifierAlive.cpp [new file with mode: 0644]
Source/ThirdParty/ANGLE/src/compiler/translator/QualifierAlive.h [new file with mode: 0644]
Source/ThirdParty/ANGLE/src/compiler/translator/RemoveTree.cpp [new file with mode: 0644]
Source/ThirdParty/ANGLE/src/compiler/translator/RemoveTree.h [new file with mode: 0644]
Source/ThirdParty/ANGLE/src/compiler/translator/RenameFunction.h [new file with mode: 0644]
Source/ThirdParty/ANGLE/src/compiler/translator/RewriteElseBlocks.cpp [new file with mode: 0644]
Source/ThirdParty/ANGLE/src/compiler/translator/RewriteElseBlocks.h [new file with mode: 0644]
Source/ThirdParty/ANGLE/src/compiler/translator/SearchSymbol.cpp [new file with mode: 0644]
Source/ThirdParty/ANGLE/src/compiler/translator/SearchSymbol.h [new file with mode: 0644]
Source/ThirdParty/ANGLE/src/compiler/translator/ShHandle.h [new file with mode: 0644]
Source/ThirdParty/ANGLE/src/compiler/translator/ShaderLang.cpp [new file with mode: 0644]
Source/ThirdParty/ANGLE/src/compiler/translator/SymbolTable.cpp [new file with mode: 0644]
Source/ThirdParty/ANGLE/src/compiler/translator/SymbolTable.h [new file with mode: 0644]
Source/ThirdParty/ANGLE/src/compiler/translator/TranslatorESSL.cpp [new file with mode: 0644]
Source/ThirdParty/ANGLE/src/compiler/translator/TranslatorESSL.h [new file with mode: 0644]
Source/ThirdParty/ANGLE/src/compiler/translator/TranslatorGLSL.cpp [new file with mode: 0644]
Source/ThirdParty/ANGLE/src/compiler/translator/TranslatorGLSL.h [new file with mode: 0644]
Source/ThirdParty/ANGLE/src/compiler/translator/TranslatorHLSL.cpp [new file with mode: 0644]
Source/ThirdParty/ANGLE/src/compiler/translator/TranslatorHLSL.h [new file with mode: 0644]
Source/ThirdParty/ANGLE/src/compiler/translator/Types.h [new file with mode: 0644]
Source/ThirdParty/ANGLE/src/compiler/translator/UnfoldShortCircuit.cpp [new file with mode: 0644]
Source/ThirdParty/ANGLE/src/compiler/translator/UnfoldShortCircuit.h [new file with mode: 0644]
Source/ThirdParty/ANGLE/src/compiler/translator/UnfoldShortCircuitAST.cpp [new file with mode: 0644]
Source/ThirdParty/ANGLE/src/compiler/translator/UnfoldShortCircuitAST.h [new file with mode: 0644]
Source/ThirdParty/ANGLE/src/compiler/translator/Uniform.cpp [new file with mode: 0644]
Source/ThirdParty/ANGLE/src/compiler/translator/Uniform.h [new file with mode: 0644]
Source/ThirdParty/ANGLE/src/compiler/translator/ValidateLimitations.cpp [new file with mode: 0644]
Source/ThirdParty/ANGLE/src/compiler/translator/ValidateLimitations.h [new file with mode: 0644]
Source/ThirdParty/ANGLE/src/compiler/translator/VariableInfo.cpp [new file with mode: 0644]
Source/ThirdParty/ANGLE/src/compiler/translator/VariableInfo.h [new file with mode: 0644]
Source/ThirdParty/ANGLE/src/compiler/translator/VariablePacker.cpp [new file with mode: 0644]
Source/ThirdParty/ANGLE/src/compiler/translator/VariablePacker.h [new file with mode: 0644]
Source/ThirdParty/ANGLE/src/compiler/translator/VersionGLSL.cpp [new file with mode: 0644]
Source/ThirdParty/ANGLE/src/compiler/translator/VersionGLSL.h [new file with mode: 0644]
Source/ThirdParty/ANGLE/src/compiler/translator/compilerdebug.cpp [new file with mode: 0644]
Source/ThirdParty/ANGLE/src/compiler/translator/compilerdebug.h [new file with mode: 0644]
Source/ThirdParty/ANGLE/src/compiler/translator/depgraph/DependencyGraph.cpp [new file with mode: 0644]
Source/ThirdParty/ANGLE/src/compiler/translator/depgraph/DependencyGraph.h [new file with mode: 0644]
Source/ThirdParty/ANGLE/src/compiler/translator/depgraph/DependencyGraphBuilder.cpp [new file with mode: 0644]
Source/ThirdParty/ANGLE/src/compiler/translator/depgraph/DependencyGraphBuilder.h [new file with mode: 0644]
Source/ThirdParty/ANGLE/src/compiler/translator/depgraph/DependencyGraphOutput.cpp [new file with mode: 0644]
Source/ThirdParty/ANGLE/src/compiler/translator/depgraph/DependencyGraphOutput.h [new file with mode: 0644]
Source/ThirdParty/ANGLE/src/compiler/translator/depgraph/DependencyGraphTraverse.cpp [new file with mode: 0644]
Source/ThirdParty/ANGLE/src/compiler/translator/generate_parser.sh [new file with mode: 0644]
Source/ThirdParty/ANGLE/src/compiler/translator/glslang.h [new file with mode: 0644]
Source/ThirdParty/ANGLE/src/compiler/translator/glslang.l [new file with mode: 0644]
Source/ThirdParty/ANGLE/src/compiler/translator/glslang.y [new file with mode: 0644]
Source/ThirdParty/ANGLE/src/compiler/translator/glslang_lex.cpp [new file with mode: 0644]
Source/ThirdParty/ANGLE/src/compiler/translator/glslang_tab.cpp [new file with mode: 0644]
Source/ThirdParty/ANGLE/src/compiler/translator/glslang_tab.h [new file with mode: 0644]
Source/ThirdParty/ANGLE/src/compiler/translator/intermOut.cpp [new file with mode: 0644]
Source/ThirdParty/ANGLE/src/compiler/translator/intermediate.h [new file with mode: 0644]
Source/ThirdParty/ANGLE/src/compiler/translator/localintermediate.h [new file with mode: 0644]
Source/ThirdParty/ANGLE/src/compiler/translator/osinclude.h [new file with mode: 0644]
Source/ThirdParty/ANGLE/src/compiler/translator/ossource_posix.cpp [new file with mode: 0644]
Source/ThirdParty/ANGLE/src/compiler/translator/ossource_win.cpp [new file with mode: 0644]
Source/ThirdParty/ANGLE/src/compiler/translator/parseConst.cpp [new file with mode: 0644]
Source/ThirdParty/ANGLE/src/compiler/translator/timing/RestrictFragmentShaderTiming.cpp [new file with mode: 0644]
Source/ThirdParty/ANGLE/src/compiler/translator/timing/RestrictFragmentShaderTiming.h [new file with mode: 0644]
Source/ThirdParty/ANGLE/src/compiler/translator/timing/RestrictVertexShaderTiming.cpp [new file with mode: 0644]
Source/ThirdParty/ANGLE/src/compiler/translator/timing/RestrictVertexShaderTiming.h [new file with mode: 0644]
Source/ThirdParty/ANGLE/src/compiler/translator/util.cpp [new file with mode: 0644]
Source/ThirdParty/ANGLE/src/compiler/translator/util.h [new file with mode: 0644]
Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d11/BufferStorage11.cpp [new file with mode: 0644]
Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d11/BufferStorage11.h [new file with mode: 0644]
Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d11/Fence11.cpp [new file with mode: 0644]
Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d11/Fence11.h [new file with mode: 0644]
Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d11/Image11.cpp [new file with mode: 0644]
Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d11/Image11.h [new file with mode: 0644]
Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d11/IndexBuffer11.cpp [new file with mode: 0644]
Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d11/IndexBuffer11.h [new file with mode: 0644]
Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d11/InputLayoutCache.cpp [new file with mode: 0644]
Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d11/InputLayoutCache.h [new file with mode: 0644]
Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d11/Query11.cpp [new file with mode: 0644]
Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d11/Query11.h [new file with mode: 0644]
Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d11/RenderStateCache.cpp [new file with mode: 0644]
Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d11/RenderStateCache.h [new file with mode: 0644]
Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d11/RenderTarget11.cpp [new file with mode: 0644]
Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d11/RenderTarget11.h [new file with mode: 0644]
Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d11/Renderer11.cpp [new file with mode: 0644]
Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d11/Renderer11.h [new file with mode: 0644]
Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d11/ShaderExecutable11.cpp [new file with mode: 0644]
Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d11/ShaderExecutable11.h [new file with mode: 0644]
Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d11/SwapChain11.cpp [new file with mode: 0644]
Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d11/SwapChain11.h [new file with mode: 0644]
Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d11/TextureStorage11.cpp [new file with mode: 0644]
Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d11/TextureStorage11.h [new file with mode: 0644]
Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d11/VertexBuffer11.cpp [new file with mode: 0644]
Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d11/VertexBuffer11.h [new file with mode: 0644]
Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d11/renderer11_utils.cpp [new file with mode: 0644]
Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d11/renderer11_utils.h [new file with mode: 0644]
Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d11/shaders/Clear11.hlsl [new file with mode: 0644]
Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d11/shaders/Passthrough11.hlsl [new file with mode: 0644]
Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d11/shaders/compiled/clear11vs.h [new file with mode: 0644]
Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d11/shaders/compiled/clearmultiple11ps.h [new file with mode: 0644]
Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d11/shaders/compiled/clearsingle11ps.h [new file with mode: 0644]
Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d11/shaders/compiled/passthrough11vs.h [new file with mode: 0644]
Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d11/shaders/compiled/passthroughlum11ps.h [new file with mode: 0644]
Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d11/shaders/compiled/passthroughlumalpha11ps.h [new file with mode: 0644]
Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d11/shaders/compiled/passthroughrgb11ps.h [new file with mode: 0644]
Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d11/shaders/compiled/passthroughrgba11ps.h [new file with mode: 0644]
Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d11/shaders/generate_shaders.bat [new file with mode: 0644]
Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d9/Blit.cpp [new file with mode: 0644]
Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d9/Blit.h [new file with mode: 0644]
Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d9/BufferStorage9.cpp [new file with mode: 0644]
Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d9/BufferStorage9.h [new file with mode: 0644]
Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d9/Fence9.cpp [new file with mode: 0644]
Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d9/Fence9.h [new file with mode: 0644]
Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d9/Image9.cpp [new file with mode: 0644]
Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d9/Image9.h [new file with mode: 0644]
Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d9/IndexBuffer9.cpp [new file with mode: 0644]
Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d9/IndexBuffer9.h [new file with mode: 0644]
Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d9/Query9.cpp [new file with mode: 0644]
Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d9/Query9.h [new file with mode: 0644]
Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d9/RenderTarget9.cpp [new file with mode: 0644]
Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d9/RenderTarget9.h [new file with mode: 0644]
Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d9/Renderer9.cpp [new file with mode: 0644]
Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d9/Renderer9.h [new file with mode: 0644]
Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d9/ShaderExecutable9.cpp [new file with mode: 0644]
Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d9/ShaderExecutable9.h [new file with mode: 0644]
Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d9/SwapChain9.cpp [new file with mode: 0644]
Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d9/SwapChain9.h [new file with mode: 0644]
Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d9/TextureStorage9.cpp [new file with mode: 0644]
Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d9/TextureStorage9.h [new file with mode: 0644]
Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d9/VertexBuffer9.cpp [new file with mode: 0644]
Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d9/VertexBuffer9.h [new file with mode: 0644]
Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d9/VertexDeclarationCache.cpp [new file with mode: 0644]
Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d9/VertexDeclarationCache.h [new file with mode: 0644]
Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d9/renderer9_utils.cpp [new file with mode: 0644]
Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d9/renderer9_utils.h [new file with mode: 0644]
Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d9/shaders/Blit.ps [new file with mode: 0644]
Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d9/shaders/Blit.vs [new file with mode: 0644]
Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d9/shaders/compiled/componentmaskps.h [new file with mode: 0644]
Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d9/shaders/compiled/flipyvs.h [new file with mode: 0644]
Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d9/shaders/compiled/luminanceps.h [new file with mode: 0644]
Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d9/shaders/compiled/passthroughps.h [new file with mode: 0644]
Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d9/shaders/compiled/standardvs.h [new file with mode: 0644]
Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d9/shaders/generate_shaders.bat [new file with mode: 0644]
Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d9/vertexconversion.h [new file with mode: 0644]

index 41bb12d5c1d00059db310820db369830faaf9682..b4ef5b203df9b4832434945ff810633a9ce4dab7 100644 (file)
@@ -1,3 +1,7 @@
+2014-02-23  Dean Jackson  <dino@apple.com>
+
+        Missing files from previous commit.
+
 2014-02-23  Dean Jackson  <dino@apple.com>
 
         Update ANGLE to 836bd2176e5607b14846cf1fbc5932dbc91318f4
diff --git a/Source/ThirdParty/ANGLE/src/compiler/translator/BaseTypes.h b/Source/ThirdParty/ANGLE/src/compiler/translator/BaseTypes.h
new file mode 100644 (file)
index 0000000..620fd45
--- /dev/null
@@ -0,0 +1,149 @@
+//
+// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#ifndef _BASICTYPES_INCLUDED_
+#define _BASICTYPES_INCLUDED_
+
+//
+// Precision qualifiers
+//
+enum TPrecision
+{
+    // These need to be kept sorted
+    EbpUndefined,
+    EbpLow,
+    EbpMedium,
+    EbpHigh
+};
+
+inline const char* getPrecisionString(TPrecision p)
+{
+    switch(p)
+    {
+    case EbpHigh:   return "highp";   break;
+    case EbpMedium:   return "mediump"; break;
+    case EbpLow:    return "lowp";    break;
+    default:      return "mediump";   break;   // Safest fallback
+    }
+}
+
+//
+// Basic type.  Arrays, vectors, etc., are orthogonal to this.
+//
+enum TBasicType
+{
+    EbtVoid,
+    EbtFloat,
+    EbtInt,
+    EbtBool,
+    EbtGuardSamplerBegin,  // non type:  see implementation of IsSampler()
+    EbtSampler2D,
+    EbtSamplerCube,
+    EbtSamplerExternalOES,  // Only valid if OES_EGL_image_external exists.
+    EbtSampler2DRect,       // Only valid if GL_ARB_texture_rectangle exists.
+    EbtGuardSamplerEnd,    // non type:  see implementation of IsSampler()
+    EbtStruct,
+    EbtAddress,            // should be deprecated??
+    EbtInvariant          // used as a type when qualifying a previously declared variable as being invariant
+};
+
+inline const char* getBasicString(TBasicType t)
+{
+    switch (t)
+    {
+    case EbtVoid:              return "void";              break;
+    case EbtFloat:             return "float";             break;
+    case EbtInt:               return "int";               break;
+    case EbtBool:              return "bool";              break;
+    case EbtSampler2D:         return "sampler2D";         break;
+    case EbtSamplerCube:       return "samplerCube";       break;
+    case EbtSamplerExternalOES: return "samplerExternalOES"; break;
+    case EbtSampler2DRect:     return "sampler2DRect";     break;
+    case EbtStruct:            return "structure";         break;
+    default:                   return "unknown type";
+    }
+}
+
+inline bool IsSampler(TBasicType type)
+{
+    return type > EbtGuardSamplerBegin && type < EbtGuardSamplerEnd;
+}
+
+//
+// Qualifiers and built-ins.  These are mainly used to see what can be read
+// or written, and by the machine dependent translator to know which registers
+// to allocate variables in.  Since built-ins tend to go to different registers
+// than varying or uniform, it makes sense they are peers, not sub-classes.
+//
+enum TQualifier
+{
+    EvqTemporary,     // For temporaries (within a function), read/write
+    EvqGlobal,        // For globals read/write
+    EvqInternal,      // For internal use, not visible to the user
+    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
+
+    // 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,
+    EvqFragDepth,
+
+    // 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 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;
+    case EvqFragDepth:      return "FragDepth";     break;
+    default:                return "unknown qualifier";
+    }
+}
+
+#endif // _BASICTYPES_INCLUDED_
diff --git a/Source/ThirdParty/ANGLE/src/compiler/translator/BuiltInFunctionEmulator.cpp b/Source/ThirdParty/ANGLE/src/compiler/translator/BuiltInFunctionEmulator.cpp
new file mode 100644 (file)
index 0000000..92b71c6
--- /dev/null
@@ -0,0 +1,406 @@
+//
+// Copyright (c) 2002-2011 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "compiler/translator/BuiltInFunctionEmulator.h"
+
+#include "compiler/translator/SymbolTable.h"
+
+namespace {
+
+// we use macros here instead of function definitions to work around more GLSL
+// compiler bugs, in particular on NVIDIA hardware on Mac OSX. Macros are
+// problematic because if the argument has side-effects they will be repeatedly
+// evaluated. This is unlikely to show up in real shaders, but is something to
+// consider.
+const char* kFunctionEmulationVertexSource[] = {
+    "#error no emulation for cos(float)",
+    "#error no emulation for cos(vec2)",
+    "#error no emulation for cos(vec3)",
+    "#error no emulation for cos(vec4)",
+
+    "#define webgl_distance_emu(x, y) ((x) >= (y) ? (x) - (y) : (y) - (x))",
+    "#error no emulation for distance(vec2, vec2)",
+    "#error no emulation for distance(vec3, vec3)",
+    "#error no emulation for distance(vec4, vec4)",
+
+    "#define webgl_dot_emu(x, y) ((x) * (y))",
+    "#error no emulation for dot(vec2, vec2)",
+    "#error no emulation for dot(vec3, vec3)",
+    "#error no emulation for dot(vec4, vec4)",
+
+    "#define webgl_length_emu(x) ((x) >= 0.0 ? (x) : -(x))",
+    "#error no emulation for length(vec2)",
+    "#error no emulation for length(vec3)",
+    "#error no emulation for length(vec4)",
+
+    "#define webgl_normalize_emu(x) ((x) == 0.0 ? 0.0 : ((x) > 0.0 ? 1.0 : -1.0))",
+    "#error no emulation for normalize(vec2)",
+    "#error no emulation for normalize(vec3)",
+    "#error no emulation for normalize(vec4)",
+
+    "#define webgl_reflect_emu(I, N) ((I) - 2.0 * (N) * (I) * (N))",
+    "#error no emulation for reflect(vec2, vec2)",
+    "#error no emulation for reflect(vec3, vec3)",
+    "#error no emulation for reflect(vec4, vec4)"
+};
+
+const char* kFunctionEmulationFragmentSource[] = {
+    "webgl_emu_precision float webgl_cos_emu(webgl_emu_precision float a) { return cos(a); }",
+    "webgl_emu_precision vec2 webgl_cos_emu(webgl_emu_precision vec2 a) { return cos(a); }",
+    "webgl_emu_precision vec3 webgl_cos_emu(webgl_emu_precision vec3 a) { return cos(a); }",
+    "webgl_emu_precision vec4 webgl_cos_emu(webgl_emu_precision vec4 a) { return cos(a); }",
+
+    "#define webgl_distance_emu(x, y) ((x) >= (y) ? (x) - (y) : (y) - (x))",
+    "#error no emulation for distance(vec2, vec2)",
+    "#error no emulation for distance(vec3, vec3)",
+    "#error no emulation for distance(vec4, vec4)",
+
+    "#define webgl_dot_emu(x, y) ((x) * (y))",
+    "#error no emulation for dot(vec2, vec2)",
+    "#error no emulation for dot(vec3, vec3)",
+    "#error no emulation for dot(vec4, vec4)",
+
+    "#define webgl_length_emu(x) ((x) >= 0.0 ? (x) : -(x))",
+    "#error no emulation for length(vec2)",
+    "#error no emulation for length(vec3)",
+    "#error no emulation for length(vec4)",
+
+    "#define webgl_normalize_emu(x) ((x) == 0.0 ? 0.0 : ((x) > 0.0 ? 1.0 : -1.0))",
+    "#error no emulation for normalize(vec2)",
+    "#error no emulation for normalize(vec3)",
+    "#error no emulation for normalize(vec4)",
+
+    "#define webgl_reflect_emu(I, N) ((I) - 2.0 * (N) * (I) * (N))",
+    "#error no emulation for reflect(vec2, vec2)",
+    "#error no emulation for reflect(vec3, vec3)",
+    "#error no emulation for reflect(vec4, vec4)"
+};
+
+const bool kFunctionEmulationVertexMask[] = {
+#if defined(__APPLE__)
+    // Work around ATI driver bugs in Mac.
+    false, // TFunctionCos1
+    false, // TFunctionCos2
+    false, // TFunctionCos3
+    false, // TFunctionCos4
+    true,  // TFunctionDistance1_1
+    false, // TFunctionDistance2_2
+    false, // TFunctionDistance3_3
+    false, // TFunctionDistance4_4
+    true,  // TFunctionDot1_1
+    false, // TFunctionDot2_2
+    false, // TFunctionDot3_3
+    false, // TFunctionDot4_4
+    true,  // TFunctionLength1
+    false, // TFunctionLength2
+    false, // TFunctionLength3
+    false, // TFunctionLength4
+    true,  // TFunctionNormalize1
+    false, // TFunctionNormalize2
+    false, // TFunctionNormalize3
+    false, // TFunctionNormalize4
+    true,  // TFunctionReflect1_1
+    false, // TFunctionReflect2_2
+    false, // TFunctionReflect3_3
+    false, // TFunctionReflect4_4
+#else
+    // Work around D3D driver bug in Win.
+    false, // TFunctionCos1
+    false, // TFunctionCos2
+    false, // TFunctionCos3
+    false, // TFunctionCos4
+    false, // TFunctionDistance1_1
+    false, // TFunctionDistance2_2
+    false, // TFunctionDistance3_3
+    false, // TFunctionDistance4_4
+    false, // TFunctionDot1_1
+    false, // TFunctionDot2_2
+    false, // TFunctionDot3_3
+    false, // TFunctionDot4_4
+    false, // TFunctionLength1
+    false, // TFunctionLength2
+    false, // TFunctionLength3
+    false, // TFunctionLength4
+    false, // TFunctionNormalize1
+    false, // TFunctionNormalize2
+    false, // TFunctionNormalize3
+    false, // TFunctionNormalize4
+    false, // TFunctionReflect1_1
+    false, // TFunctionReflect2_2
+    false, // TFunctionReflect3_3
+    false, // TFunctionReflect4_4
+#endif
+    false  // TFunctionUnknown
+};
+
+const bool kFunctionEmulationFragmentMask[] = {
+#if defined(__APPLE__)
+    // Work around ATI driver bugs in Mac.
+    true,  // TFunctionCos1
+    true,  // TFunctionCos2
+    true,  // TFunctionCos3
+    true,  // TFunctionCos4
+    true,  // TFunctionDistance1_1
+    false, // TFunctionDistance2_2
+    false, // TFunctionDistance3_3
+    false, // TFunctionDistance4_4
+    true,  // TFunctionDot1_1
+    false, // TFunctionDot2_2
+    false, // TFunctionDot3_3
+    false, // TFunctionDot4_4
+    true,  // TFunctionLength1
+    false, // TFunctionLength2
+    false, // TFunctionLength3
+    false, // TFunctionLength4
+    true,  // TFunctionNormalize1
+    false, // TFunctionNormalize2
+    false, // TFunctionNormalize3
+    false, // TFunctionNormalize4
+    true,  // TFunctionReflect1_1
+    false, // TFunctionReflect2_2
+    false, // TFunctionReflect3_3
+    false, // TFunctionReflect4_4
+#else
+    // Work around D3D driver bug in Win.
+    false, // TFunctionCos1
+    false, // TFunctionCos2
+    false, // TFunctionCos3
+    false, // TFunctionCos4
+    false, // TFunctionDistance1_1
+    false, // TFunctionDistance2_2
+    false, // TFunctionDistance3_3
+    false, // TFunctionDistance4_4
+    false, // TFunctionDot1_1
+    false, // TFunctionDot2_2
+    false, // TFunctionDot3_3
+    false, // TFunctionDot4_4
+    false, // TFunctionLength1
+    false, // TFunctionLength2
+    false, // TFunctionLength3
+    false, // TFunctionLength4
+    false, // TFunctionNormalize1
+    false, // TFunctionNormalize2
+    false, // TFunctionNormalize3
+    false, // TFunctionNormalize4
+    false, // TFunctionReflect1_1
+    false, // TFunctionReflect2_2
+    false, // TFunctionReflect3_3
+    false, // TFunctionReflect4_4
+#endif
+    false  // TFunctionUnknown
+};
+
+class BuiltInFunctionEmulationMarker : public TIntermTraverser {
+public:
+    BuiltInFunctionEmulationMarker(BuiltInFunctionEmulator& emulator)
+        : mEmulator(emulator)
+    {
+    }
+
+    virtual bool visitUnary(Visit visit, TIntermUnary* node)
+    {
+        if (visit == PreVisit) {
+            bool needToEmulate = mEmulator.SetFunctionCalled(
+                node->getOp(), node->getOperand()->getType());
+            if (needToEmulate)
+                node->setUseEmulatedFunction();
+        }
+        return true;
+    }
+
+    virtual bool visitAggregate(Visit visit, TIntermAggregate* node)
+    {
+        if (visit == PreVisit) {
+            // Here we handle all the built-in functions instead of the ones we
+            // currently identified as problematic.
+            switch (node->getOp()) {
+                case EOpLessThan:
+                case EOpGreaterThan:
+                case EOpLessThanEqual:
+                case EOpGreaterThanEqual:
+                case EOpVectorEqual:
+                case EOpVectorNotEqual:
+                case EOpMod:
+                case EOpPow:
+                case EOpAtan:
+                case EOpMin:
+                case EOpMax:
+                case EOpClamp:
+                case EOpMix:
+                case EOpStep:
+                case EOpSmoothStep:
+                case EOpDistance:
+                case EOpDot:
+                case EOpCross:
+                case EOpFaceForward:
+                case EOpReflect:
+                case EOpRefract:
+                case EOpMul:
+                    break;
+                default:
+                    return true;
+            };
+            const TIntermSequence& sequence = node->getSequence();
+            // Right now we only handle built-in functions with two parameters.
+            if (sequence.size() != 2)
+                return true;
+            TIntermTyped* param1 = sequence[0]->getAsTyped();
+            TIntermTyped* param2 = sequence[1]->getAsTyped();
+            if (!param1 || !param2)
+                return true;
+            bool needToEmulate = mEmulator.SetFunctionCalled(
+                node->getOp(), param1->getType(), param2->getType());
+            if (needToEmulate)
+                node->setUseEmulatedFunction();
+        }
+        return true;
+    }
+
+private:
+    BuiltInFunctionEmulator& mEmulator;
+};
+
+}  // anonymous namepsace
+
+BuiltInFunctionEmulator::BuiltInFunctionEmulator(ShShaderType shaderType)
+{
+    if (shaderType == SH_FRAGMENT_SHADER) {
+        mFunctionMask = kFunctionEmulationFragmentMask;
+        mFunctionSource = kFunctionEmulationFragmentSource;
+    } else {
+        mFunctionMask = kFunctionEmulationVertexMask;
+        mFunctionSource = kFunctionEmulationVertexSource;
+    }
+}
+
+bool BuiltInFunctionEmulator::SetFunctionCalled(
+    TOperator op, const TType& param)
+{
+    TBuiltInFunction function = IdentifyFunction(op, param);
+    return SetFunctionCalled(function);
+}
+
+bool BuiltInFunctionEmulator::SetFunctionCalled(
+    TOperator op, const TType& param1, const TType& param2)
+{
+    TBuiltInFunction function = IdentifyFunction(op, param1, param2);
+    return SetFunctionCalled(function);
+}
+
+bool BuiltInFunctionEmulator::SetFunctionCalled(
+    BuiltInFunctionEmulator::TBuiltInFunction function) {
+    if (function == TFunctionUnknown || mFunctionMask[function] == false)
+        return false;
+    for (size_t i = 0; i < mFunctions.size(); ++i) {
+        if (mFunctions[i] == function)
+            return true;
+    }
+    mFunctions.push_back(function);
+    return true;
+}
+
+void BuiltInFunctionEmulator::OutputEmulatedFunctionDefinition(
+    TInfoSinkBase& out, bool withPrecision) const
+{
+    if (mFunctions.size() == 0)
+        return;
+    out << "// BEGIN: Generated code for built-in function emulation\n\n";
+    if (withPrecision) {
+        out << "#if defined(GL_FRAGMENT_PRECISION_HIGH)\n"
+            << "#define webgl_emu_precision highp\n"
+            << "#else\n"
+            << "#define webgl_emu_precision mediump\n"
+            << "#endif\n\n";
+    } else {
+        out << "#define webgl_emu_precision\n\n";
+    }
+    for (size_t i = 0; i < mFunctions.size(); ++i) {
+        out << mFunctionSource[mFunctions[i]] << "\n\n";
+    }
+    out << "// END: Generated code for built-in function emulation\n\n";
+}
+
+BuiltInFunctionEmulator::TBuiltInFunction
+BuiltInFunctionEmulator::IdentifyFunction(
+    TOperator op, const TType& param)
+{
+    if (param.getNominalSize() > 4)
+        return TFunctionUnknown;
+    unsigned int function = TFunctionUnknown;
+    switch (op) {
+        case EOpCos:
+            function = TFunctionCos1;
+            break;
+        case EOpLength:
+            function = TFunctionLength1;
+            break;
+        case EOpNormalize:
+            function = TFunctionNormalize1;
+            break;
+        default:
+            break;
+    }
+    if (function == TFunctionUnknown)
+        return TFunctionUnknown;
+    if (param.isVector())
+        function += param.getNominalSize() - 1;
+    return static_cast<TBuiltInFunction>(function);
+}
+
+BuiltInFunctionEmulator::TBuiltInFunction
+BuiltInFunctionEmulator::IdentifyFunction(
+    TOperator op, const TType& param1, const TType& param2)
+{
+    // Right now for all the emulated functions with two parameters, the two
+    // parameters have the same type.
+    if (param1.isVector() != param2.isVector() ||
+        param1.getNominalSize() != param2.getNominalSize() ||
+        param1.getNominalSize() > 4)
+        return TFunctionUnknown;
+
+    unsigned int function = TFunctionUnknown;
+    switch (op) {
+        case EOpDistance:
+            function = TFunctionDistance1_1;
+            break;
+        case EOpDot:
+            function = TFunctionDot1_1;
+            break;
+        case EOpReflect:
+            function = TFunctionReflect1_1;
+            break;
+        default:
+            break;
+    }
+    if (function == TFunctionUnknown)
+        return TFunctionUnknown;
+    if (param1.isVector())
+        function += param1.getNominalSize() - 1;
+    return static_cast<TBuiltInFunction>(function);
+}
+
+void BuiltInFunctionEmulator::MarkBuiltInFunctionsForEmulation(
+    TIntermNode* root)
+{
+    ASSERT(root);
+
+    BuiltInFunctionEmulationMarker marker(*this);
+    root->traverse(&marker);
+}
+
+void BuiltInFunctionEmulator::Cleanup()
+{
+    mFunctions.clear();
+}
+
+//static
+TString BuiltInFunctionEmulator::GetEmulatedFunctionName(
+    const TString& name)
+{
+    ASSERT(name[name.length() - 1] == '(');
+    return "webgl_" + name.substr(0, name.length() - 1) + "_emu(";
+}
+
diff --git a/Source/ThirdParty/ANGLE/src/compiler/translator/BuiltInFunctionEmulator.h b/Source/ThirdParty/ANGLE/src/compiler/translator/BuiltInFunctionEmulator.h
new file mode 100644 (file)
index 0000000..cfb71a8
--- /dev/null
@@ -0,0 +1,93 @@
+//
+// Copyright (c) 2011 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#ifndef COMPILIER_BUILT_IN_FUNCTION_EMULATOR_H_
+#define COMPILIER_BUILT_IN_FUNCTION_EMULATOR_H_
+
+#include "GLSLANG/ShaderLang.h"
+
+#include "compiler/translator/InfoSink.h"
+#include "compiler/translator/intermediate.h"
+
+//
+// This class decides which built-in functions need to be replaced with the
+// emulated ones.
+// It's only a workaround for OpenGL driver bugs, and isn't needed in general.
+//
+class BuiltInFunctionEmulator {
+public:
+    BuiltInFunctionEmulator(ShShaderType shaderType);
+    // Records that a function is called by the shader and might needs to be
+    // emulated.  If the function's group is not in mFunctionGroupFilter, this
+    // becomes an no-op.
+    // Returns true if the function call needs to be replaced with an emulated
+    // one.
+    bool SetFunctionCalled(TOperator op, const TType& param);
+    bool SetFunctionCalled(
+        TOperator op, const TType& param1, const TType& param2);
+
+    // Output function emulation definition.  This should be before any other
+    // shader source.
+    void OutputEmulatedFunctionDefinition(TInfoSinkBase& out, bool withPrecision) const;
+
+    void MarkBuiltInFunctionsForEmulation(TIntermNode* root);
+
+    void Cleanup();
+
+    // "name(" becomes "webgl_name_emu(".
+    static TString GetEmulatedFunctionName(const TString& name);
+
+private:
+    //
+    // Built-in functions.
+    //
+    enum TBuiltInFunction {
+        TFunctionCos1 = 0,  // float cos(float);
+        TFunctionCos2,  // vec2 cos(vec2);
+        TFunctionCos3,  // vec3 cos(vec3);
+        TFunctionCos4,  // vec4 cos(vec4);
+
+        TFunctionDistance1_1,  // float distance(float, float);
+        TFunctionDistance2_2,  // vec2 distance(vec2, vec2);
+        TFunctionDistance3_3,  // vec3 distance(vec3, vec3);
+        TFunctionDistance4_4,  // vec4 distance(vec4, vec4);
+
+        TFunctionDot1_1,  // float dot(float, float);
+        TFunctionDot2_2,  // vec2 dot(vec2, vec2);
+        TFunctionDot3_3,  // vec3 dot(vec3, vec3);
+        TFunctionDot4_4,  // vec4 dot(vec4, vec4);
+
+        TFunctionLength1,  // float length(float);
+        TFunctionLength2,  // float length(vec2);
+        TFunctionLength3,  // float length(vec3);
+        TFunctionLength4,  // float length(vec4);
+
+        TFunctionNormalize1,  // float normalize(float);
+        TFunctionNormalize2,  // vec2 normalize(vec2);
+        TFunctionNormalize3,  // vec3 normalize(vec3);
+        TFunctionNormalize4,  // vec4 normalize(vec4);
+
+        TFunctionReflect1_1,  // float reflect(float, float);
+        TFunctionReflect2_2,  // vec2 reflect(vec2, vec2);
+        TFunctionReflect3_3,  // vec3 reflect(vec3, vec3);
+        TFunctionReflect4_4,  // vec4 reflect(vec4, vec4);
+
+        TFunctionUnknown
+    };
+
+    TBuiltInFunction IdentifyFunction(TOperator op, const TType& param);
+    TBuiltInFunction IdentifyFunction(
+        TOperator op, const TType& param1, const TType& param2);
+
+    bool SetFunctionCalled(TBuiltInFunction function);
+
+    std::vector<TBuiltInFunction> mFunctions;
+
+    const bool* mFunctionMask;  // a boolean flag for each function.
+    const char** mFunctionSource;
+};
+
+#endif  // COMPILIER_BUILT_IN_FUNCTION_EMULATOR_H_
diff --git a/Source/ThirdParty/ANGLE/src/compiler/translator/CodeGen.cpp b/Source/ThirdParty/ANGLE/src/compiler/translator/CodeGen.cpp
new file mode 100644 (file)
index 0000000..8f5d129
--- /dev/null
@@ -0,0 +1,38 @@
+//
+// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "compiler/translator/TranslatorESSL.h"
+#include "compiler/translator/TranslatorGLSL.h"
+#include "compiler/translator/TranslatorHLSL.h"
+
+//
+// This function must be provided to create the actual
+// compile object used by higher level code.  It returns
+// a subclass of TCompiler.
+//
+TCompiler* ConstructCompiler(
+    ShShaderType type, ShShaderSpec spec, ShShaderOutput output)
+{
+    switch (output) {
+      case SH_ESSL_OUTPUT:
+        return new TranslatorESSL(type, spec);
+      case SH_GLSL_OUTPUT:
+        return new TranslatorGLSL(type, spec);
+      case SH_HLSL9_OUTPUT:
+      case SH_HLSL11_OUTPUT:
+        return new TranslatorHLSL(type, spec, output);
+      default:
+        return NULL;
+    }
+}
+
+//
+// Delete the compiler made by ConstructCompiler
+//
+void DeleteCompiler(TCompiler* compiler)
+{
+    delete compiler;
+}
diff --git a/Source/ThirdParty/ANGLE/src/compiler/translator/Common.h b/Source/ThirdParty/ANGLE/src/compiler/translator/Common.h
new file mode 100644 (file)
index 0000000..c972ee6
--- /dev/null
@@ -0,0 +1,92 @@
+//
+// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#ifndef _COMMON_INCLUDED_
+#define _COMMON_INCLUDED_
+
+#include <map>
+#include <sstream>
+#include <string>
+#include <vector>
+#include <limits>
+#include <stdio.h>
+
+#include "compiler/translator/PoolAlloc.h"
+#include "compiler/translator/compilerdebug.h"
+#include "common/angleutils.h"
+
+struct TSourceLoc {
+    int first_file;
+    int first_line;
+    int last_file;
+    int last_line;
+};
+
+//
+// Put POOL_ALLOCATOR_NEW_DELETE in base classes to make them use this scheme.
+//
+#define POOL_ALLOCATOR_NEW_DELETE()                                                  \
+    void* operator new(size_t s) { return GetGlobalPoolAllocator()->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 GetGlobalPoolAllocator()->allocate(s); } \
+    void* operator new[](size_t, void *_Where) { return (_Where); }                  \
+    void operator delete[](void*) { }                                                \
+    void operator delete[](void *, void *) { }
+
+//
+// Pool version of string.
+//
+typedef pool_allocator<char> TStringAllocator;
+typedef std::basic_string <char, std::char_traits<char>, TStringAllocator> TString;
+typedef std::basic_ostringstream<char, std::char_traits<char>, TStringAllocator> TStringStream;
+inline TString* NewPoolTString(const char* s)
+{
+  void* memory = GetGlobalPoolAllocator()->allocate(sizeof(TString));
+  return new(memory) TString(s);
+}
+
+//
+// Persistent string memory.  Should only be used for strings that survive
+// across compiles.
+//
+#define TPersistString std::string
+#define TPersistStringStream std::ostringstream
+
+//
+// Pool allocator versions of vectors, lists, and maps
+//
+template <class T> class TVector : public std::vector<T, pool_allocator<T> > {
+public:
+    typedef typename std::vector<T, pool_allocator<T> >::size_type size_type;
+    TVector() : std::vector<T, pool_allocator<T> >() {}
+    TVector(const pool_allocator<T>& a) : std::vector<T, pool_allocator<T> >(a) {}
+    TVector(size_type i): std::vector<T, pool_allocator<T> >(i) {}
+};
+
+template <class K, class D, class CMP = std::less<K> > 
+class TMap : public std::map<K, D, CMP, pool_allocator<std::pair<const K, D> > > {
+public:
+    typedef pool_allocator<std::pair<const K, D> > tAllocator;
+
+    TMap() : std::map<K, D, CMP, tAllocator>() {}
+    // use correct two-stage name lookup supported in gcc 3.4 and above
+    TMap(const tAllocator& a) : std::map<K, D, CMP, tAllocator>(std::map<K, D, CMP, tAllocator>::key_compare(), a) {}
+};
+
+// Integer to TString conversion
+template <typename T>
+inline TString str(T i)
+{
+    ASSERT(std::numeric_limits<T>::is_integer);
+    char buffer[((8 * sizeof(T)) / 3) + 3];
+    const char *formatStr = std::numeric_limits<T>::is_signed ? "%d" : "%u";
+    snprintf(buffer, sizeof(buffer), formatStr, i);
+    return buffer;
+}
+
+#endif // _COMMON_INCLUDED_
diff --git a/Source/ThirdParty/ANGLE/src/compiler/translator/Compiler.cpp b/Source/ThirdParty/ANGLE/src/compiler/translator/Compiler.cpp
new file mode 100644 (file)
index 0000000..0028800
--- /dev/null
@@ -0,0 +1,538 @@
+//
+// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "compiler/translator/BuiltInFunctionEmulator.h"
+#include "compiler/translator/DetectCallDepth.h"
+#include "compiler/translator/ForLoopUnroll.h"
+#include "compiler/translator/Initialize.h"
+#include "compiler/translator/InitializeParseContext.h"
+#include "compiler/translator/InitializeVariables.h"
+#include "compiler/translator/MapLongVariableNames.h"
+#include "compiler/translator/ParseContext.h"
+#include "compiler/translator/RenameFunction.h"
+#include "compiler/translator/ShHandle.h"
+#include "compiler/translator/UnfoldShortCircuitAST.h"
+#include "compiler/translator/ValidateLimitations.h"
+#include "compiler/translator/VariablePacker.h"
+#include "compiler/translator/depgraph/DependencyGraph.h"
+#include "compiler/translator/depgraph/DependencyGraphOutput.h"
+#include "compiler/translator/timing/RestrictFragmentShaderTiming.h"
+#include "compiler/translator/timing/RestrictVertexShaderTiming.h"
+#include "third_party/compiler/ArrayBoundsClamper.h"
+
+bool isWebGLBasedSpec(ShShaderSpec spec)
+{
+     return spec == SH_WEBGL_SPEC || spec == SH_CSS_SHADERS_SPEC;
+}
+
+namespace {
+class TScopedPoolAllocator
+{
+  public:
+    TScopedPoolAllocator(TPoolAllocator* allocator) : mAllocator(allocator)
+    {
+        mAllocator->push();
+        SetGlobalPoolAllocator(mAllocator);
+    }
+    ~TScopedPoolAllocator()
+    {
+        SetGlobalPoolAllocator(NULL);
+        mAllocator->pop();
+    }
+
+  private:
+    TPoolAllocator* mAllocator;
+};
+
+class TScopedSymbolTableLevel
+{
+  public:
+    TScopedSymbolTableLevel(TSymbolTable* table) : mTable(table)
+    {
+        ASSERT(mTable->atBuiltInLevel());
+        mTable->push();
+    }
+    ~TScopedSymbolTableLevel()
+    {
+        while (!mTable->atBuiltInLevel())
+            mTable->pop();
+    }
+
+  private:
+    TSymbolTable* mTable;
+};
+}  // namespace
+
+TShHandleBase::TShHandleBase()
+{
+    allocator.push();
+    SetGlobalPoolAllocator(&allocator);
+}
+
+TShHandleBase::~TShHandleBase()
+{
+    SetGlobalPoolAllocator(NULL);
+    allocator.popAll();
+}
+
+TCompiler::TCompiler(ShShaderType type, ShShaderSpec spec)
+    : shaderType(type),
+      shaderSpec(spec),
+      maxUniformVectors(0),
+      maxVaryingVectors(0),
+      maxExpressionComplexity(0),
+      maxCallStackDepth(0),
+      fragmentPrecisionHigh(false),
+      clampingStrategy(SH_CLAMP_WITH_CLAMP_INTRINSIC),
+      builtInFunctionEmulator(type)
+{
+    longNameMap = LongNameMap::GetInstance();
+}
+
+TCompiler::~TCompiler()
+{
+    ASSERT(longNameMap);
+    longNameMap->Release();
+}
+
+bool TCompiler::Init(const ShBuiltInResources& resources)
+{
+    maxUniformVectors = (shaderType == SH_VERTEX_SHADER) ?
+        resources.MaxVertexUniformVectors :
+        resources.MaxFragmentUniformVectors;
+    maxVaryingVectors = resources.MaxVaryingVectors;
+    maxExpressionComplexity = resources.MaxExpressionComplexity;
+    maxCallStackDepth = resources.MaxCallStackDepth;
+
+    SetGlobalPoolAllocator(&allocator);
+
+    // Generate built-in symbol table.
+    if (!InitBuiltInSymbolTable(resources))
+        return false;
+    InitExtensionBehavior(resources, extensionBehavior);
+    fragmentPrecisionHigh = resources.FragmentPrecisionHigh == 1;
+
+    arrayBoundsClamper.SetClampingStrategy(resources.ArrayIndexClampingStrategy);
+    clampingStrategy = resources.ArrayIndexClampingStrategy;
+
+    hashFunction = resources.HashFunction;
+
+    return true;
+}
+
+bool TCompiler::compile(const char* const shaderStrings[],
+                        size_t numStrings,
+                        int compileOptions)
+{
+    TScopedPoolAllocator scopedAlloc(&allocator);
+    clearResults();
+
+    if (numStrings == 0)
+        return true;
+
+    // If compiling for WebGL, validate loop and indexing as well.
+    if (isWebGLBasedSpec(shaderSpec))
+        compileOptions |= SH_VALIDATE_LOOP_INDEXING;
+
+    // First string is path of source file if flag is set. The actual source follows.
+    const char* sourcePath = NULL;
+    size_t firstSource = 0;
+    if (compileOptions & SH_SOURCE_PATH)
+    {
+        sourcePath = shaderStrings[0];
+        ++firstSource;
+    }
+
+    TIntermediate intermediate(infoSink);
+    TParseContext parseContext(symbolTable, extensionBehavior, intermediate,
+                               shaderType, shaderSpec, compileOptions, true,
+                               sourcePath, infoSink);
+    parseContext.fragmentPrecisionHigh = fragmentPrecisionHigh;
+    SetGlobalParseContext(&parseContext);
+
+    // We preserve symbols at the built-in level from compile-to-compile.
+    // Start pushing the user-defined symbols at global level.
+    TScopedSymbolTableLevel scopedSymbolLevel(&symbolTable);
+
+    // Parse shader.
+    bool success =
+        (PaParseStrings(numStrings - firstSource, &shaderStrings[firstSource], NULL, &parseContext) == 0) &&
+        (parseContext.treeRoot != NULL);
+    if (success)
+    {
+        TIntermNode* root = parseContext.treeRoot;
+        success = intermediate.postProcess(root);
+
+        if (success)
+            success = detectCallDepth(root, infoSink, (compileOptions & SH_LIMIT_CALL_STACK_DEPTH) != 0);
+
+        if (success && (compileOptions & SH_VALIDATE_LOOP_INDEXING))
+            success = validateLimitations(root);
+
+        if (success && (compileOptions & SH_TIMING_RESTRICTIONS))
+            success = enforceTimingRestrictions(root, (compileOptions & SH_DEPENDENCY_GRAPH) != 0);
+
+        if (success && shaderSpec == SH_CSS_SHADERS_SPEC)
+            rewriteCSSShader(root);
+
+        // Unroll for-loop markup needs to happen after validateLimitations pass.
+        if (success && (compileOptions & SH_UNROLL_FOR_LOOP_WITH_INTEGER_INDEX))
+            ForLoopUnroll::MarkForLoopsWithIntegerIndicesForUnrolling(root);
+
+        // Built-in function emulation needs to happen after validateLimitations pass.
+        if (success && (compileOptions & SH_EMULATE_BUILT_IN_FUNCTIONS))
+            builtInFunctionEmulator.MarkBuiltInFunctionsForEmulation(root);
+
+        // Clamping uniform array bounds needs to happen after validateLimitations pass.
+        if (success && (compileOptions & SH_CLAMP_INDIRECT_ARRAY_BOUNDS))
+            arrayBoundsClamper.MarkIndirectArrayBoundsForClamping(root);
+
+        // Disallow expressions deemed too complex.
+        if (success && (compileOptions & SH_LIMIT_EXPRESSION_COMPLEXITY))
+            success = limitExpressionComplexity(root);
+
+        // Call mapLongVariableNames() before collectAttribsUniforms() so in
+        // collectAttribsUniforms() we already have the mapped symbol names and
+        // we could composite mapped and original variable names.
+        // Also, if we hash all the names, then no need to do this for long names.
+        if (success && (compileOptions & SH_MAP_LONG_VARIABLE_NAMES) && hashFunction == NULL)
+            mapLongVariableNames(root);
+
+        if (success && shaderType == SH_VERTEX_SHADER && (compileOptions & SH_INIT_GL_POSITION))
+            initializeGLPosition(root);
+
+        if (success && (compileOptions & SH_UNFOLD_SHORT_CIRCUIT))
+        {
+            UnfoldShortCircuitAST unfoldShortCircuit;
+            root->traverse(&unfoldShortCircuit);
+            unfoldShortCircuit.updateTree();
+        }
+
+        if (success && (compileOptions & SH_VARIABLES))
+        {
+            collectVariables(root);
+            if (compileOptions & SH_ENFORCE_PACKING_RESTRICTIONS)
+                success = enforcePackingRestrictions();
+
+            if (success && shaderType == SH_VERTEX_SHADER &&
+                (compileOptions & SH_INIT_VARYINGS_WITHOUT_STATIC_USE))
+                initializeVaryingsWithoutStaticUse(root);
+        }
+
+        if (success && (compileOptions & SH_INTERMEDIATE_TREE))
+            intermediate.outputTree(root);
+
+        if (success && (compileOptions & SH_OBJECT_CODE))
+            translate(root);
+    }
+
+    // Cleanup memory.
+    intermediate.remove(parseContext.treeRoot);
+
+    return success;
+}
+
+bool TCompiler::InitBuiltInSymbolTable(const ShBuiltInResources &resources)
+{
+    compileResources = resources;
+
+    assert(symbolTable.isEmpty());
+    symbolTable.push();
+
+    TPublicType integer;
+    integer.type = EbtInt;
+    integer.size = 1;
+    integer.matrix = false;
+    integer.array = false;
+
+    TPublicType floatingPoint;
+    floatingPoint.type = EbtFloat;
+    floatingPoint.size = 1;
+    floatingPoint.matrix = false;
+    floatingPoint.array = false;
+
+    TPublicType sampler;
+    sampler.size = 1;
+    sampler.matrix = false;
+    sampler.array = false;
+
+    switch(shaderType)
+    {
+      case SH_FRAGMENT_SHADER:
+        symbolTable.setDefaultPrecision(integer, EbpMedium);
+        break;
+      case SH_VERTEX_SHADER:
+        symbolTable.setDefaultPrecision(integer, EbpHigh);
+        symbolTable.setDefaultPrecision(floatingPoint, EbpHigh);
+        break;
+      default:
+        assert(false && "Language not supported");
+    }
+    // We set defaults for all the sampler types, even those that are
+    // only available if an extension exists.
+    for (int samplerType = EbtGuardSamplerBegin + 1;
+         samplerType < EbtGuardSamplerEnd; ++samplerType)
+    {
+        sampler.type = static_cast<TBasicType>(samplerType);
+        symbolTable.setDefaultPrecision(sampler, EbpLow);
+    }
+
+    InsertBuiltInFunctions(shaderType, shaderSpec, resources, symbolTable);
+
+    IdentifyBuiltIns(shaderType, shaderSpec, resources, symbolTable);
+
+    return true;
+}
+
+void TCompiler::clearResults()
+{
+    arrayBoundsClamper.Cleanup();
+    infoSink.info.erase();
+    infoSink.obj.erase();
+    infoSink.debug.erase();
+
+    attribs.clear();
+    uniforms.clear();
+    varyings.clear();
+
+    builtInFunctionEmulator.Cleanup();
+
+    nameMap.clear();
+}
+
+bool TCompiler::detectCallDepth(TIntermNode* root, TInfoSink& infoSink, bool limitCallStackDepth)
+{
+    DetectCallDepth detect(infoSink, limitCallStackDepth, maxCallStackDepth);
+    root->traverse(&detect);
+    switch (detect.detectCallDepth())
+    {
+      case DetectCallDepth::kErrorNone:
+        return true;
+      case DetectCallDepth::kErrorMissingMain:
+        infoSink.info.prefix(EPrefixError);
+        infoSink.info << "Missing main()";
+        return false;
+      case DetectCallDepth::kErrorRecursion:
+        infoSink.info.prefix(EPrefixError);
+        infoSink.info << "Function recursion detected";
+        return false;
+      case DetectCallDepth::kErrorMaxDepthExceeded:
+        infoSink.info.prefix(EPrefixError);
+        infoSink.info << "Function call stack too deep";
+        return false;
+      default:
+        UNREACHABLE();
+        return false;
+    }
+}
+
+void TCompiler::rewriteCSSShader(TIntermNode* root)
+{
+    RenameFunction renamer("main(", "css_main(");
+    root->traverse(&renamer);
+}
+
+bool TCompiler::validateLimitations(TIntermNode* root)
+{
+    ValidateLimitations validate(shaderType, infoSink.info);
+    root->traverse(&validate);
+    return validate.numErrors() == 0;
+}
+
+bool TCompiler::enforceTimingRestrictions(TIntermNode* root, bool outputGraph)
+{
+    if (shaderSpec != SH_WEBGL_SPEC)
+    {
+        infoSink.info << "Timing restrictions must be enforced under the WebGL spec.";
+        return false;
+    }
+
+    if (shaderType == SH_FRAGMENT_SHADER)
+    {
+        TDependencyGraph graph(root);
+
+        // Output any errors first.
+        bool success = enforceFragmentShaderTimingRestrictions(graph);
+        
+        // Then, output the dependency graph.
+        if (outputGraph)
+        {
+            TDependencyGraphOutput output(infoSink.info);
+            output.outputAllSpanningTrees(graph);
+        }
+        
+        return success;
+    }
+    else
+    {
+        return enforceVertexShaderTimingRestrictions(root);
+    }
+}
+
+bool TCompiler::limitExpressionComplexity(TIntermNode* root)
+{
+    TIntermTraverser traverser;
+    root->traverse(&traverser);
+    TDependencyGraph graph(root);
+
+    for (TFunctionCallVector::const_iterator iter = graph.beginUserDefinedFunctionCalls();
+         iter != graph.endUserDefinedFunctionCalls();
+         ++iter)
+    {
+        TGraphFunctionCall* samplerSymbol = *iter;
+        TDependencyGraphTraverser graphTraverser;
+        samplerSymbol->traverse(&graphTraverser);
+    }
+
+    if (traverser.getMaxDepth() > maxExpressionComplexity)
+    {
+        infoSink.info << "Expression too complex.";
+        return false;
+    }
+    return true;
+}
+
+bool TCompiler::enforceFragmentShaderTimingRestrictions(const TDependencyGraph& graph)
+{
+    RestrictFragmentShaderTiming restrictor(infoSink.info);
+    restrictor.enforceRestrictions(graph);
+    return restrictor.numErrors() == 0;
+}
+
+bool TCompiler::enforceVertexShaderTimingRestrictions(TIntermNode* root)
+{
+    RestrictVertexShaderTiming restrictor(infoSink.info);
+    restrictor.enforceRestrictions(root);
+    return restrictor.numErrors() == 0;
+}
+
+void TCompiler::collectVariables(TIntermNode* root)
+{
+    CollectVariables collect(attribs, uniforms, varyings, hashFunction);
+    root->traverse(&collect);
+}
+
+bool TCompiler::enforcePackingRestrictions()
+{
+    VariablePacker packer;
+    bool success = packer.CheckVariablesWithinPackingLimits(maxUniformVectors, uniforms);
+    if (!success) {
+        infoSink.info.prefix(EPrefixError);
+        infoSink.info << "too many uniforms";
+        return false;
+    }
+
+    success = packer.CheckVariablesWithinPackingLimits(maxVaryingVectors, varyings);
+
+    if (!success) {
+        infoSink.info.prefix(EPrefixError);
+        infoSink.info << "too many varyings";
+        return false;
+    }
+
+    return true;
+}
+
+void TCompiler::initializeGLPosition(TIntermNode* root)
+{
+    InitializeVariables::InitVariableInfoList variables;
+    InitializeVariables::InitVariableInfo var(
+        "gl_Position", TType(EbtFloat, EbpUndefined, EvqPosition, 4));
+    variables.push_back(var);
+    InitializeVariables initializer(variables);
+    root->traverse(&initializer);
+}
+
+void TCompiler::initializeVaryingsWithoutStaticUse(TIntermNode* root)
+{
+    InitializeVariables::InitVariableInfoList variables;
+    for (size_t ii = 0; ii < varyings.size(); ++ii)
+    {
+        const TVariableInfo& varying = varyings[ii];
+        if (varying.staticUse)
+            continue;
+        unsigned char size = 0;
+        bool matrix = false;
+        switch (varying.type)
+        {
+          case SH_FLOAT:
+            size = 1;
+            break;
+          case SH_FLOAT_VEC2:
+            size = 2;
+            break;
+          case SH_FLOAT_VEC3:
+            size = 3;
+            break;
+          case SH_FLOAT_VEC4:
+            size = 4;
+            break;
+          case SH_FLOAT_MAT2:
+            size = 2;
+            matrix = true;
+            break;
+          case SH_FLOAT_MAT3:
+            size = 3;
+            matrix = true;
+            break;
+          case SH_FLOAT_MAT4:
+            size = 4;
+            matrix = true;
+            break;
+          default:
+            ASSERT(false);
+        }
+        TType type(EbtFloat, EbpUndefined, EvqVaryingOut, size, matrix, varying.isArray);
+        TString name = varying.name.c_str();
+        if (varying.isArray)
+        {
+            type.setArraySize(varying.size);
+            name = name.substr(0, name.find_first_of('['));
+        }
+
+        InitializeVariables::InitVariableInfo var(name, type);
+        variables.push_back(var);
+    }
+    InitializeVariables initializer(variables);
+    root->traverse(&initializer);
+}
+
+void TCompiler::mapLongVariableNames(TIntermNode* root)
+{
+    ASSERT(longNameMap);
+    MapLongVariableNames map(longNameMap);
+    root->traverse(&map);
+}
+
+int TCompiler::getMappedNameMaxLength() const
+{
+    return MAX_SHORTENED_IDENTIFIER_SIZE + 1;
+}
+
+const TExtensionBehavior& TCompiler::getExtensionBehavior() const
+{
+    return extensionBehavior;
+}
+
+const ShBuiltInResources& TCompiler::getResources() const
+{
+    return compileResources;
+}
+
+const ArrayBoundsClamper& TCompiler::getArrayBoundsClamper() const
+{
+    return arrayBoundsClamper;
+}
+
+ShArrayIndexClampingStrategy TCompiler::getArrayIndexClampingStrategy() const
+{
+    return clampingStrategy;
+}
+
+const BuiltInFunctionEmulator& TCompiler::getBuiltInFunctionEmulator() const
+{
+    return builtInFunctionEmulator;
+}
diff --git a/Source/ThirdParty/ANGLE/src/compiler/translator/ConstantUnion.h b/Source/ThirdParty/ANGLE/src/compiler/translator/ConstantUnion.h
new file mode 100644 (file)
index 0000000..b1e3788
--- /dev/null
@@ -0,0 +1,257 @@
+//
+// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#ifndef _CONSTANT_UNION_INCLUDED_
+#define _CONSTANT_UNION_INCLUDED_
+
+#include <assert.h>
+
+class ConstantUnion {
+public:
+    POOL_ALLOCATOR_NEW_DELETE();
+    ConstantUnion()
+    {
+        iConst = 0;
+        type = EbtVoid;
+    }
+
+    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
+    {
+        return i == iConst;
+    }
+
+    bool operator==(const float f) const
+    {
+        return f == fConst;
+    }
+
+    bool operator==(const bool b) const
+    {
+        return b == bConst;
+    }
+
+    bool operator==(const ConstantUnion& constant) const
+    {
+        if (constant.type != type)
+            return false;
+
+        switch (type) {
+        case EbtInt:
+            return constant.iConst == iConst;
+        case EbtFloat:
+            return constant.fConst == fConst;
+        case EbtBool:
+            return constant.bConst == bConst;
+        default:
+            return false;
+        }
+    }
+
+    bool operator!=(const int i) const
+    {
+        return !operator==(i);
+    }
+
+    bool operator!=(const float f) const
+    {
+        return !operator==(f);
+    }
+
+    bool operator!=(const bool b) const
+    {
+        return !operator==(b);
+    }
+
+    bool operator!=(const ConstantUnion& constant) const
+    {
+        return !operator==(constant);
+    }
+
+    bool operator>(const ConstantUnion& constant) const
+    { 
+        assert(type == constant.type);
+        switch (type) {
+        case EbtInt:
+            return iConst > constant.iConst;
+        case EbtFloat:
+            return fConst > constant.fConst;
+        default:
+            return false;   // Invalid operation, handled at semantic analysis
+        }
+    }
+
+    bool operator<(const ConstantUnion& constant) const
+    { 
+        assert(type == constant.type);
+        switch (type) {
+        case EbtInt:
+            return iConst < constant.iConst;
+        case EbtFloat:
+            return fConst < constant.fConst;
+        default:
+            return false;   // Invalid operation, handled at semantic analysis
+        }
+    }
+
+    ConstantUnion operator+(const ConstantUnion& constant) const
+    { 
+        ConstantUnion returnValue;
+        assert(type == constant.type);
+        switch (type) {
+        case EbtInt: returnValue.setIConst(iConst + constant.iConst); break;
+        case EbtFloat: returnValue.setFConst(fConst + constant.fConst); break;
+        default: assert(false && "Default missing");
+        }
+
+        return returnValue;
+    }
+
+    ConstantUnion operator-(const ConstantUnion& constant) const
+    { 
+        ConstantUnion returnValue;
+        assert(type == constant.type);
+        switch (type) {
+        case EbtInt: returnValue.setIConst(iConst - constant.iConst); break;
+        case EbtFloat: returnValue.setFConst(fConst - constant.fConst); break;
+        default: assert(false && "Default missing");
+        }
+
+        return returnValue;
+    }
+
+    ConstantUnion operator*(const ConstantUnion& constant) const
+    { 
+        ConstantUnion returnValue;
+        assert(type == constant.type);
+        switch (type) {
+        case EbtInt: returnValue.setIConst(iConst * constant.iConst); break;
+        case EbtFloat: returnValue.setFConst(fConst * constant.fConst); break; 
+        default: assert(false && "Default missing");
+        }
+
+        return returnValue;
+    }
+
+    ConstantUnion operator%(const ConstantUnion& constant) const
+    { 
+        ConstantUnion returnValue;
+        assert(type == constant.type);
+        switch (type) {
+        case EbtInt: returnValue.setIConst(iConst % constant.iConst); break;
+        default:     assert(false && "Default missing");
+        }
+
+        return returnValue;
+    }
+
+    ConstantUnion operator>>(const ConstantUnion& constant) const
+    { 
+        ConstantUnion returnValue;
+        assert(type == constant.type);
+        switch (type) {
+        case EbtInt: returnValue.setIConst(iConst >> constant.iConst); break;
+        default:     assert(false && "Default missing");
+        }
+
+        return returnValue;
+    }
+
+    ConstantUnion operator<<(const ConstantUnion& constant) const
+    { 
+        ConstantUnion returnValue;
+        assert(type == constant.type);
+        switch (type) {
+        case EbtInt: returnValue.setIConst(iConst << constant.iConst); break;
+        default:     assert(false && "Default missing");
+        }
+
+        return returnValue;
+    }
+
+    ConstantUnion operator&(const ConstantUnion& constant) const
+    { 
+        ConstantUnion returnValue;
+        assert(type == constant.type);
+        switch (type) {
+        case EbtInt:  returnValue.setIConst(iConst & constant.iConst); break;
+        default:     assert(false && "Default missing");
+        }
+
+        return returnValue;
+    }
+
+    ConstantUnion operator|(const ConstantUnion& constant) const
+    { 
+        ConstantUnion returnValue;
+        assert(type == constant.type);
+        switch (type) {
+        case EbtInt:  returnValue.setIConst(iConst | constant.iConst); break;
+        default:     assert(false && "Default missing");
+        }
+
+        return returnValue;
+    }
+
+    ConstantUnion operator^(const ConstantUnion& constant) const
+    { 
+        ConstantUnion returnValue;
+        assert(type == constant.type);
+        switch (type) {
+        case EbtInt:  returnValue.setIConst(iConst ^ constant.iConst); break;
+        default:     assert(false && "Default missing");
+        }
+
+        return returnValue;
+    }
+
+    ConstantUnion operator&&(const ConstantUnion& constant) const
+    { 
+        ConstantUnion returnValue;
+        assert(type == constant.type);
+        switch (type) {
+        case EbtBool: returnValue.setBConst(bConst && constant.bConst); break;
+        default:     assert(false && "Default missing");
+        }
+
+        return returnValue;
+    }
+
+    ConstantUnion operator||(const ConstantUnion& constant) const
+    { 
+        ConstantUnion returnValue;
+        assert(type == constant.type);
+        switch (type) {
+        case EbtBool: returnValue.setBConst(bConst || constant.bConst); break;
+        default:     assert(false && "Default missing");
+        }
+
+        return returnValue;
+    }
+
+    TBasicType getType() const { return type; }
+private:
+
+    union  {
+        int iConst;  // used for ivec, scalar ints
+        bool bConst; // used for bvec, scalar bools
+        float fConst;   // used for vec, mat, scalar floats
+    } ;
+
+    TBasicType type;
+};
+
+#endif // _CONSTANT_UNION_INCLUDED_
diff --git a/Source/ThirdParty/ANGLE/src/compiler/translator/DetectCallDepth.cpp b/Source/ThirdParty/ANGLE/src/compiler/translator/DetectCallDepth.cpp
new file mode 100644 (file)
index 0000000..bfc1d58
--- /dev/null
@@ -0,0 +1,185 @@
+//
+// Copyright (c) 2002-2011 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "compiler/translator/DetectCallDepth.h"
+#include "compiler/translator/InfoSink.h"
+
+DetectCallDepth::FunctionNode::FunctionNode(const TString& fname)
+    : name(fname),
+      visit(PreVisit)
+{
+}
+
+const TString& DetectCallDepth::FunctionNode::getName() const
+{
+    return name;
+}
+
+void DetectCallDepth::FunctionNode::addCallee(
+    DetectCallDepth::FunctionNode* callee)
+{
+    for (size_t i = 0; i < callees.size(); ++i) {
+        if (callees[i] == callee)
+            return;
+    }
+    callees.push_back(callee);
+}
+
+int DetectCallDepth::FunctionNode::detectCallDepth(DetectCallDepth* detectCallDepth, int depth)
+{
+    ASSERT(visit == PreVisit);
+    ASSERT(detectCallDepth);
+
+    int maxDepth = depth;
+    visit = InVisit;
+    for (size_t i = 0; i < callees.size(); ++i) {
+        switch (callees[i]->visit) {
+            case InVisit:
+                // cycle detected, i.e., recursion detected.
+                return kInfiniteCallDepth;
+            case PostVisit:
+                break;
+            case PreVisit: {
+                // Check before we recurse so we don't go too depth
+                if (detectCallDepth->checkExceedsMaxDepth(depth))
+                    return depth;
+                int callDepth = callees[i]->detectCallDepth(detectCallDepth, depth + 1);
+                // Check after we recurse so we can exit immediately and provide info.
+                if (detectCallDepth->checkExceedsMaxDepth(callDepth)) {
+                    detectCallDepth->getInfoSink().info << "<-" << callees[i]->getName();
+                    return callDepth;
+                }
+                maxDepth = std::max(callDepth, maxDepth);
+                break;
+            }
+            default:
+                UNREACHABLE();
+                break;
+        }
+    }
+    visit = PostVisit;
+    return maxDepth;
+}
+
+void DetectCallDepth::FunctionNode::reset()
+{
+    visit = PreVisit;
+}
+
+DetectCallDepth::DetectCallDepth(TInfoSink& infoSink, bool limitCallStackDepth, int maxCallStackDepth)
+    : TIntermTraverser(true, false, true, false),
+      currentFunction(NULL),
+      infoSink(infoSink),
+      maxDepth(limitCallStackDepth ? maxCallStackDepth : FunctionNode::kInfiniteCallDepth)
+{
+}
+
+DetectCallDepth::~DetectCallDepth()
+{
+    for (size_t i = 0; i < functions.size(); ++i)
+        delete functions[i];
+}
+
+bool DetectCallDepth::visitAggregate(Visit visit, TIntermAggregate* node)
+{
+    switch (node->getOp())
+    {
+        case EOpPrototype:
+            // Function declaration.
+            // Don't add FunctionNode here because node->getName() is the
+            // unmangled function name.
+            break;
+        case EOpFunction: {
+            // Function definition.
+            if (visit == PreVisit) {
+                currentFunction = findFunctionByName(node->getName());
+                if (currentFunction == NULL) {
+                    currentFunction = new FunctionNode(node->getName());
+                    functions.push_back(currentFunction);
+                }
+            } else if (visit == PostVisit) {
+                currentFunction = NULL;
+            }
+            break;
+        }
+        case EOpFunctionCall: {
+            // Function call.
+            if (visit == PreVisit) {
+                FunctionNode* func = findFunctionByName(node->getName());
+                if (func == NULL) {
+                    func = new FunctionNode(node->getName());
+                    functions.push_back(func);
+                }
+                if (currentFunction)
+                    currentFunction->addCallee(func);
+            }
+            break;
+        }
+        default:
+            break;
+    }
+    return true;
+}
+
+bool DetectCallDepth::checkExceedsMaxDepth(int depth)
+{
+    return depth >= maxDepth;
+}
+
+void DetectCallDepth::resetFunctionNodes()
+{
+    for (size_t i = 0; i < functions.size(); ++i) {
+        functions[i]->reset();
+    }
+}
+
+DetectCallDepth::ErrorCode DetectCallDepth::detectCallDepthForFunction(FunctionNode* func)
+{
+    currentFunction = NULL;
+    resetFunctionNodes();
+
+    int maxCallDepth = func->detectCallDepth(this, 1);
+
+    if (maxCallDepth == FunctionNode::kInfiniteCallDepth)
+        return kErrorRecursion;
+
+    if (maxCallDepth >= maxDepth)
+        return kErrorMaxDepthExceeded;
+
+    return kErrorNone;
+}
+
+DetectCallDepth::ErrorCode DetectCallDepth::detectCallDepth()
+{
+    if (maxDepth != FunctionNode::kInfiniteCallDepth) {
+        // Check all functions because the driver may fail on them
+        // TODO: Before detectingRecursion, strip unused functions.
+        for (size_t i = 0; i < functions.size(); ++i) {
+            ErrorCode error = detectCallDepthForFunction(functions[i]);
+            if (error != kErrorNone)
+                return error;
+        }
+    } else {
+        FunctionNode* main = findFunctionByName("main(");
+        if (main == NULL)
+            return kErrorMissingMain;
+
+        return detectCallDepthForFunction(main);
+    }
+
+    return kErrorNone;
+}
+
+DetectCallDepth::FunctionNode* DetectCallDepth::findFunctionByName(
+    const TString& name)
+{
+    for (size_t i = 0; i < functions.size(); ++i) {
+        if (functions[i]->getName() == name)
+            return functions[i];
+    }
+    return NULL;
+}
+
diff --git a/Source/ThirdParty/ANGLE/src/compiler/translator/DetectCallDepth.h b/Source/ThirdParty/ANGLE/src/compiler/translator/DetectCallDepth.h
new file mode 100644 (file)
index 0000000..5e7f23d
--- /dev/null
@@ -0,0 +1,80 @@
+//
+// Copyright (c) 2002-2011 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#ifndef COMPILER_DETECT_RECURSION_H_
+#define COMPILER_DETECT_RECURSION_H_
+
+#include "GLSLANG/ShaderLang.h"
+
+#include <limits.h>
+#include "compiler/translator/intermediate.h"
+#include "compiler/translator/VariableInfo.h"
+
+class TInfoSink;
+
+// Traverses intermediate tree to detect function recursion.
+class DetectCallDepth : public TIntermTraverser {
+public:
+    enum ErrorCode {
+        kErrorMissingMain,
+        kErrorRecursion,
+        kErrorMaxDepthExceeded,
+        kErrorNone
+    };
+
+    DetectCallDepth(TInfoSink& infoSync, bool limitCallStackDepth, int maxCallStackDepth);
+    ~DetectCallDepth();
+
+    virtual bool visitAggregate(Visit, TIntermAggregate*);
+
+    bool checkExceedsMaxDepth(int depth);
+
+    ErrorCode detectCallDepth();
+
+private:
+    class FunctionNode {
+    public:
+        static const int kInfiniteCallDepth = INT_MAX;
+
+        FunctionNode(const TString& fname);
+
+        const TString& getName() const;
+
+        // If a function is already in the callee list, this becomes a no-op.
+        void addCallee(FunctionNode* callee);
+
+        // Returns kInifinityCallDepth if recursive function calls are detected.
+        int detectCallDepth(DetectCallDepth* detectCallDepth, int depth);
+
+        // Reset state.
+        void reset();
+
+    private:
+        // mangled function name is unique.
+        TString name;
+
+        // functions that are directly called by this function.
+        TVector<FunctionNode*> callees;
+
+        Visit visit;
+    };
+
+    ErrorCode detectCallDepthForFunction(FunctionNode* func);
+    FunctionNode* findFunctionByName(const TString& name);
+    void resetFunctionNodes();
+
+    TInfoSink& getInfoSink() { return infoSink; }
+
+    TVector<FunctionNode*> functions;
+    FunctionNode* currentFunction;
+    TInfoSink& infoSink;
+    int maxDepth;
+
+    DetectCallDepth(const DetectCallDepth&);
+    void operator=(const DetectCallDepth&);
+};
+
+#endif  // COMPILER_DETECT_RECURSION_H_
diff --git a/Source/ThirdParty/ANGLE/src/compiler/translator/DetectDiscontinuity.cpp b/Source/ThirdParty/ANGLE/src/compiler/translator/DetectDiscontinuity.cpp
new file mode 100644 (file)
index 0000000..334eb0b
--- /dev/null
@@ -0,0 +1,139 @@
+//
+// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// Contains analysis utilities for dealing with HLSL's lack of support for
+// the use of intrinsic functions which (implicitly or explicitly) compute
+// gradients of functions with discontinuities. 
+//
+
+#include "compiler/translator/DetectDiscontinuity.h"
+
+#include "compiler/translator/ParseContext.h"
+
+namespace sh
+{
+bool DetectLoopDiscontinuity::traverse(TIntermNode *node)
+{
+    mLoopDepth = 0;
+    mLoopDiscontinuity = false;
+    node->traverse(this);
+    return mLoopDiscontinuity;
+}
+
+bool DetectLoopDiscontinuity::visitLoop(Visit visit, TIntermLoop *loop)
+{
+    if (visit == PreVisit)
+    {
+        ++mLoopDepth;
+    }
+    else if (visit == PostVisit)
+    {
+        --mLoopDepth;
+    }
+
+    return true;
+}
+
+bool DetectLoopDiscontinuity::visitBranch(Visit visit, TIntermBranch *node)
+{
+    if (mLoopDiscontinuity)
+    {
+        return false;
+    }
+
+    if (!mLoopDepth)
+    {
+        return true;
+    }
+
+    switch (node->getFlowOp())
+    {
+      case EOpKill:
+        break;
+      case EOpBreak:
+      case EOpContinue:
+      case EOpReturn:
+        mLoopDiscontinuity = true;
+        break;
+      default: UNREACHABLE();
+    }
+
+    return !mLoopDiscontinuity;
+}
+
+bool DetectLoopDiscontinuity::visitAggregate(Visit visit, TIntermAggregate *node)
+{
+    return !mLoopDiscontinuity;
+}
+
+bool containsLoopDiscontinuity(TIntermNode *node)
+{
+    DetectLoopDiscontinuity detectLoopDiscontinuity;
+    return detectLoopDiscontinuity.traverse(node);
+}
+
+bool DetectGradientOperation::traverse(TIntermNode *node)
+{
+    mGradientOperation = false;
+    node->traverse(this);
+    return mGradientOperation;
+}
+
+bool DetectGradientOperation::visitUnary(Visit visit, TIntermUnary *node)
+{
+    if (mGradientOperation)
+    {
+        return false;
+    }
+
+    switch (node->getOp())
+    {
+      case EOpDFdx:
+      case EOpDFdy:
+        mGradientOperation = true;
+      default:
+        break;
+    }
+
+    return !mGradientOperation;
+}
+
+bool DetectGradientOperation::visitAggregate(Visit visit, TIntermAggregate *node)
+{
+    if (mGradientOperation)
+    {
+        return false;
+    }
+
+    if (node->getOp() == EOpFunctionCall)
+    {
+        if (!node->isUserDefined())
+        {
+            TString name = TFunction::unmangleName(node->getName());
+
+            if (name == "texture2D" ||
+                name == "texture2DProj" ||
+                name == "textureCube")
+            {
+                mGradientOperation = true;
+            }
+        }
+        else
+        {
+            // When a user defined function is called, we have to
+            // conservatively assume it to contain gradient operations
+            mGradientOperation = true;
+        }
+    }
+
+    return !mGradientOperation;
+}
+
+bool containsGradientOperation(TIntermNode *node)
+{
+    DetectGradientOperation detectGradientOperation;
+    return detectGradientOperation.traverse(node);
+}
+}
diff --git a/Source/ThirdParty/ANGLE/src/compiler/translator/DetectDiscontinuity.h b/Source/ThirdParty/ANGLE/src/compiler/translator/DetectDiscontinuity.h
new file mode 100644 (file)
index 0000000..1dd8be9
--- /dev/null
@@ -0,0 +1,52 @@
+//
+// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// Contains analysis utilities for dealing with HLSL's lack of support for
+// the use of intrinsic functions which (implicitly or explicitly) compute
+// gradients of functions with discontinuities. 
+//
+
+#ifndef COMPILER_DETECTDISCONTINUITY_H_
+#define COMPILER_DETECTDISCONTINUITY_H_
+
+#include "compiler/translator/intermediate.h"
+
+namespace sh
+{
+// Checks whether a loop can run for a variable number of iterations
+class DetectLoopDiscontinuity : public TIntermTraverser
+{
+  public:
+    bool traverse(TIntermNode *node);
+
+  protected:
+    bool visitBranch(Visit visit, TIntermBranch *node);
+    bool visitLoop(Visit visit, TIntermLoop *loop);
+    bool visitAggregate(Visit visit, TIntermAggregate *node);
+
+    int mLoopDepth;
+    bool mLoopDiscontinuity;
+};
+
+bool containsLoopDiscontinuity(TIntermNode *node);
+
+// Checks for intrinsic functions which compute gradients
+class DetectGradientOperation : public TIntermTraverser
+{
+  public:
+    bool traverse(TIntermNode *node);
+
+  protected:
+    bool visitUnary(Visit visit, TIntermUnary *node);
+    bool visitAggregate(Visit visit, TIntermAggregate *node);
+
+    bool mGradientOperation;
+};
+
+bool containsGradientOperation(TIntermNode *node);
+
+}
+
+#endif   // COMPILER_DETECTDISCONTINUITY_H_
diff --git a/Source/ThirdParty/ANGLE/src/compiler/translator/Diagnostics.cpp b/Source/ThirdParty/ANGLE/src/compiler/translator/Diagnostics.cpp
new file mode 100644 (file)
index 0000000..99506c0
--- /dev/null
@@ -0,0 +1,63 @@
+//
+// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "compiler/translator/Diagnostics.h"
+
+#include "compiler/translator/compilerdebug.h"
+#include "compiler/translator/InfoSink.h"
+#include "compiler/preprocessor/SourceLocation.h"
+
+TDiagnostics::TDiagnostics(TInfoSink& infoSink) :
+    mInfoSink(infoSink),
+    mNumErrors(0),
+    mNumWarnings(0)
+{
+}
+
+TDiagnostics::~TDiagnostics()
+{
+}
+
+void TDiagnostics::writeInfo(Severity severity,
+                             const pp::SourceLocation& loc,
+                             const std::string& reason,
+                             const std::string& token,
+                             const std::string& extra)
+{
+    TPrefixType prefix = EPrefixNone;
+    switch (severity)
+    {
+      case PP_ERROR:
+        ++mNumErrors;
+        prefix = EPrefixError;
+        break;
+      case PP_WARNING:
+        ++mNumWarnings;
+        prefix = EPrefixWarning;
+        break;
+      default:
+        UNREACHABLE();
+        break;
+    }
+
+    TInfoSinkBase& sink = mInfoSink.info;
+    /* VC++ format: file(linenum) : error #: 'token' : extrainfo */
+    sink.prefix(prefix);
+    sink.location(loc.file, loc.line);
+    sink << "'" << token <<  "' : " << reason << " " << extra << "\n";
+}
+
+void TDiagnostics::writeDebug(const std::string& str)
+{
+    mInfoSink.debug << str;
+}
+
+void TDiagnostics::print(ID id,
+                         const pp::SourceLocation& loc,
+                         const std::string& text)
+{
+    writeInfo(severity(id), loc, message(id), text, "");
+}
diff --git a/Source/ThirdParty/ANGLE/src/compiler/translator/Diagnostics.h b/Source/ThirdParty/ANGLE/src/compiler/translator/Diagnostics.h
new file mode 100644 (file)
index 0000000..cb71bb1
--- /dev/null
@@ -0,0 +1,44 @@
+//
+// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#ifndef COMPILER_DIAGNOSTICS_H_
+#define COMPILER_DIAGNOSTICS_H_
+
+#include "compiler/preprocessor/DiagnosticsBase.h"
+
+class TInfoSink;
+
+class TDiagnostics : public pp::Diagnostics
+{
+  public:
+    TDiagnostics(TInfoSink& infoSink);
+    virtual ~TDiagnostics();
+
+    TInfoSink& infoSink() { return mInfoSink; }
+
+    int numErrors() const { return mNumErrors; }
+    int numWarnings() const { return mNumWarnings; }
+
+    void writeInfo(Severity severity,
+                   const pp::SourceLocation& loc,
+                   const std::string& reason,
+                   const std::string& token,
+                   const std::string& extra);
+
+    void writeDebug(const std::string& str);
+
+  protected:
+    virtual void print(ID id,
+                       const pp::SourceLocation& loc,
+                       const std::string& text);
+
+  private:
+    TInfoSink& mInfoSink;
+    int mNumErrors;
+    int mNumWarnings;
+};
+
+#endif  // COMPILER_DIAGNOSTICS_H_
diff --git a/Source/ThirdParty/ANGLE/src/compiler/translator/DirectiveHandler.cpp b/Source/ThirdParty/ANGLE/src/compiler/translator/DirectiveHandler.cpp
new file mode 100644 (file)
index 0000000..662c8ae
--- /dev/null
@@ -0,0 +1,161 @@
+//
+// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "compiler/translator/DirectiveHandler.h"
+
+#include <sstream>
+
+#include "compiler/translator/compilerdebug.h"
+#include "compiler/translator/Diagnostics.h"
+
+static TBehavior getBehavior(const std::string& str)
+{
+    static const std::string kRequire("require");
+    static const std::string kEnable("enable");
+    static const std::string kDisable("disable");
+    static const std::string kWarn("warn");
+
+    if (str == kRequire) return EBhRequire;
+    else if (str == kEnable) return EBhEnable;
+    else if (str == kDisable) return EBhDisable;
+    else if (str == kWarn) return EBhWarn;
+    return EBhUndefined;
+}
+
+TDirectiveHandler::TDirectiveHandler(TExtensionBehavior& extBehavior,
+                                     TDiagnostics& diagnostics)
+    : mExtensionBehavior(extBehavior),
+      mDiagnostics(diagnostics)
+{
+}
+
+TDirectiveHandler::~TDirectiveHandler()
+{
+}
+
+void TDirectiveHandler::handleError(const pp::SourceLocation& loc,
+                                    const std::string& msg)
+{
+    mDiagnostics.writeInfo(pp::Diagnostics::PP_ERROR, loc, msg, "", "");
+}
+
+void TDirectiveHandler::handlePragma(const pp::SourceLocation& loc,
+                                     const std::string& name,
+                                     const std::string& value)
+{
+    static const std::string kSTDGL("STDGL");
+    static const std::string kOptimize("optimize");
+    static const std::string kDebug("debug");
+    static const std::string kOn("on");
+    static const std::string kOff("off");
+
+    bool invalidValue = false;
+    if (name == kSTDGL)
+    {
+        // The STDGL pragma is used to reserve pragmas for use by future
+        // revisions of GLSL. Ignore it.
+        return;
+    }
+    else if (name == kOptimize)
+    {
+        if (value == kOn) mPragma.optimize = true;
+        else if (value == kOff) mPragma.optimize = false;
+        else invalidValue = true;
+    }
+    else if (name == kDebug)
+    {
+        if (value == kOn) mPragma.debug = true;
+        else if (value == kOff) mPragma.debug = false;
+        else invalidValue = true;
+    }
+    else
+    {
+        mDiagnostics.report(pp::Diagnostics::PP_UNRECOGNIZED_PRAGMA, loc, name);
+        return;
+    }
+
+    if (invalidValue)
+      mDiagnostics.writeInfo(pp::Diagnostics::PP_ERROR, loc,
+                             "invalid pragma value", value,
+                             "'on' or 'off' expected");
+}
+
+void TDirectiveHandler::handleExtension(const pp::SourceLocation& loc,
+                                        const std::string& name,
+                                        const std::string& behavior)
+{
+    static const std::string kExtAll("all");
+
+    TBehavior behaviorVal = getBehavior(behavior);
+    if (behaviorVal == EBhUndefined)
+    {
+        mDiagnostics.writeInfo(pp::Diagnostics::PP_ERROR, loc,
+                               "behavior", name, "invalid");
+        return;
+    }
+
+    if (name == kExtAll)
+    {
+        if (behaviorVal == EBhRequire)
+        {
+            mDiagnostics.writeInfo(pp::Diagnostics::PP_ERROR, loc,
+                                   "extension", name,
+                                   "cannot have 'require' behavior");
+        }
+        else if (behaviorVal == EBhEnable)
+        {
+            mDiagnostics.writeInfo(pp::Diagnostics::PP_ERROR, loc,
+                                   "extension", name,
+                                   "cannot have 'enable' behavior");
+        }
+        else
+        {
+            for (TExtensionBehavior::iterator iter = mExtensionBehavior.begin();
+                 iter != mExtensionBehavior.end(); ++iter)
+                iter->second = behaviorVal;
+        }
+        return;
+    }
+
+    TExtensionBehavior::iterator iter = mExtensionBehavior.find(name);
+    if (iter != mExtensionBehavior.end())
+    {
+        iter->second = behaviorVal;
+        return;
+    }
+
+    pp::Diagnostics::Severity severity = pp::Diagnostics::PP_ERROR;
+    switch (behaviorVal) {
+      case EBhRequire:
+        severity = pp::Diagnostics::PP_ERROR;
+        break;
+      case EBhEnable:
+      case EBhWarn:
+      case EBhDisable:
+        severity = pp::Diagnostics::PP_WARNING;
+        break;
+      default:
+        UNREACHABLE();
+        break;
+    }
+    mDiagnostics.writeInfo(severity, loc,
+                           "extension", name, "is not supported");
+}
+
+void TDirectiveHandler::handleVersion(const pp::SourceLocation& loc,
+                                      int version)
+{
+    static const int kVersion = 100;
+
+    if (version != kVersion)
+    {
+        std::stringstream stream;
+        stream << version;
+        std::string str = stream.str();
+        mDiagnostics.writeInfo(pp::Diagnostics::PP_ERROR, loc,
+                               "version number", str, "not supported");
+    }
+}
diff --git a/Source/ThirdParty/ANGLE/src/compiler/translator/DirectiveHandler.h b/Source/ThirdParty/ANGLE/src/compiler/translator/DirectiveHandler.h
new file mode 100644 (file)
index 0000000..eb5f055
--- /dev/null
@@ -0,0 +1,46 @@
+//
+// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#ifndef COMPILER_DIRECTIVE_HANDLER_H_
+#define COMPILER_DIRECTIVE_HANDLER_H_
+
+#include "compiler/translator/ExtensionBehavior.h"
+#include "compiler/translator/Pragma.h"
+#include "compiler/preprocessor/DirectiveHandlerBase.h"
+
+class TDiagnostics;
+
+class TDirectiveHandler : public pp::DirectiveHandler
+{
+  public:
+    TDirectiveHandler(TExtensionBehavior& extBehavior,
+                      TDiagnostics& diagnostics);
+    virtual ~TDirectiveHandler();
+
+    const TPragma& pragma() const { return mPragma; }
+    const TExtensionBehavior& extensionBehavior() const { return mExtensionBehavior; }
+
+    virtual void handleError(const pp::SourceLocation& loc,
+                             const std::string& msg);
+
+    virtual void handlePragma(const pp::SourceLocation& loc,
+                              const std::string& name,
+                              const std::string& value);
+
+    virtual void handleExtension(const pp::SourceLocation& loc,
+                                 const std::string& name,
+                                 const std::string& behavior);
+
+    virtual void handleVersion(const pp::SourceLocation& loc,
+                               int version);
+
+  private:
+    TPragma mPragma;
+    TExtensionBehavior& mExtensionBehavior;
+    TDiagnostics& mDiagnostics;
+};
+
+#endif  // COMPILER_DIRECTIVE_HANDLER_H_
diff --git a/Source/ThirdParty/ANGLE/src/compiler/translator/ExtensionBehavior.h b/Source/ThirdParty/ANGLE/src/compiler/translator/ExtensionBehavior.h
new file mode 100644 (file)
index 0000000..5c1595f
--- /dev/null
@@ -0,0 +1,37 @@
+//
+// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#ifndef _EXTENSION_BEHAVIOR_INCLUDED_
+#define _EXTENSION_BEHAVIOR_INCLUDED_
+
+#include <map>
+#include <string>
+
+typedef enum
+{
+    EBhRequire,
+    EBhEnable,
+    EBhWarn,
+    EBhDisable,
+    EBhUndefined
+} TBehavior;
+
+inline const char* getBehaviorString(TBehavior b)
+{
+    switch(b)
+    {
+      case EBhRequire: return "require";
+      case EBhEnable: return "enable";
+      case EBhWarn: return "warn";
+      case EBhDisable: return "disable";
+      default: return NULL;
+    }
+}
+
+// Mapping between extension name and behavior.
+typedef std::map<std::string, TBehavior> TExtensionBehavior;
+
+#endif // _EXTENSION_TABLE_INCLUDED_
diff --git a/Source/ThirdParty/ANGLE/src/compiler/translator/ForLoopUnroll.cpp b/Source/ThirdParty/ANGLE/src/compiler/translator/ForLoopUnroll.cpp
new file mode 100644 (file)
index 0000000..89e6f1a
--- /dev/null
@@ -0,0 +1,215 @@
+//
+// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "compiler/translator/ForLoopUnroll.h"
+
+namespace {
+
+class IntegerForLoopUnrollMarker : public TIntermTraverser {
+public:
+
+    virtual bool visitLoop(Visit, TIntermLoop* node)
+    {
+        // This is called after ValidateLimitations pass, so all the ASSERT
+        // should never fail.
+        // See ValidateLimitations::validateForLoopInit().
+        ASSERT(node);
+        ASSERT(node->getType() == ELoopFor);
+        ASSERT(node->getInit());
+        TIntermAggregate* decl = node->getInit()->getAsAggregate();
+        ASSERT(decl && decl->getOp() == EOpDeclaration);
+        TIntermSequence& declSeq = decl->getSequence();
+        ASSERT(declSeq.size() == 1);
+        TIntermBinary* declInit = declSeq[0]->getAsBinaryNode();
+        ASSERT(declInit && declInit->getOp() == EOpInitialize);
+        ASSERT(declInit->getLeft());
+        TIntermSymbol* symbol = declInit->getLeft()->getAsSymbolNode();
+        ASSERT(symbol);
+        TBasicType type = symbol->getBasicType();
+        ASSERT(type == EbtInt || type == EbtFloat);
+        if (type == EbtInt)
+            node->setUnrollFlag(true);
+        return true;
+    }
+
+};
+
+}  // anonymous namepsace
+
+void ForLoopUnroll::FillLoopIndexInfo(TIntermLoop* node, TLoopIndexInfo& info)
+{
+    ASSERT(node->getType() == ELoopFor);
+    ASSERT(node->getUnrollFlag());
+
+    TIntermNode* init = node->getInit();
+    ASSERT(init != NULL);
+    TIntermAggregate* decl = init->getAsAggregate();
+    ASSERT((decl != NULL) && (decl->getOp() == EOpDeclaration));
+    TIntermSequence& declSeq = decl->getSequence();
+    ASSERT(declSeq.size() == 1);
+    TIntermBinary* declInit = declSeq[0]->getAsBinaryNode();
+    ASSERT((declInit != NULL) && (declInit->getOp() == EOpInitialize));
+    TIntermSymbol* symbol = declInit->getLeft()->getAsSymbolNode();
+    ASSERT(symbol != NULL);
+    ASSERT(symbol->getBasicType() == EbtInt);
+
+    info.id = symbol->getId();
+
+    ASSERT(declInit->getRight() != NULL);
+    TIntermConstantUnion* initNode = declInit->getRight()->getAsConstantUnion();
+    ASSERT(initNode != NULL);
+
+    info.initValue = evaluateIntConstant(initNode);
+    info.currentValue = info.initValue;
+
+    TIntermNode* cond = node->getCondition();
+    ASSERT(cond != NULL);
+    TIntermBinary* binOp = cond->getAsBinaryNode();
+    ASSERT(binOp != NULL);
+    ASSERT(binOp->getRight() != NULL);
+    ASSERT(binOp->getRight()->getAsConstantUnion() != NULL);
+
+    info.incrementValue = getLoopIncrement(node);
+    info.stopValue = evaluateIntConstant(
+        binOp->getRight()->getAsConstantUnion());
+    info.op = binOp->getOp();
+}
+
+void ForLoopUnroll::Step()
+{
+    ASSERT(mLoopIndexStack.size() > 0);
+    TLoopIndexInfo& info = mLoopIndexStack[mLoopIndexStack.size() - 1];
+    info.currentValue += info.incrementValue;
+}
+
+bool ForLoopUnroll::SatisfiesLoopCondition()
+{
+    ASSERT(mLoopIndexStack.size() > 0);
+    TLoopIndexInfo& info = mLoopIndexStack[mLoopIndexStack.size() - 1];
+    // Relational operator is one of: > >= < <= == or !=.
+    switch (info.op) {
+      case EOpEqual:
+        return (info.currentValue == info.stopValue);
+      case EOpNotEqual:
+        return (info.currentValue != info.stopValue);
+      case EOpLessThan:
+        return (info.currentValue < info.stopValue);
+      case EOpGreaterThan:
+        return (info.currentValue > info.stopValue);
+      case EOpLessThanEqual:
+        return (info.currentValue <= info.stopValue);
+      case EOpGreaterThanEqual:
+        return (info.currentValue >= info.stopValue);
+      default:
+        UNREACHABLE();
+    }
+    return false;
+}
+
+bool ForLoopUnroll::NeedsToReplaceSymbolWithValue(TIntermSymbol* symbol)
+{
+    for (TVector<TLoopIndexInfo>::iterator i = mLoopIndexStack.begin();
+         i != mLoopIndexStack.end();
+         ++i) {
+        if (i->id == symbol->getId())
+            return true;
+    }
+    return false;
+}
+
+int ForLoopUnroll::GetLoopIndexValue(TIntermSymbol* symbol)
+{
+    for (TVector<TLoopIndexInfo>::iterator i = mLoopIndexStack.begin();
+         i != mLoopIndexStack.end();
+         ++i) {
+        if (i->id == symbol->getId())
+            return i->currentValue;
+    }
+    UNREACHABLE();
+    return false;
+}
+
+void ForLoopUnroll::Push(TLoopIndexInfo& info)
+{
+    mLoopIndexStack.push_back(info);
+}
+
+void ForLoopUnroll::Pop()
+{
+    mLoopIndexStack.pop_back();
+}
+
+// static
+void ForLoopUnroll::MarkForLoopsWithIntegerIndicesForUnrolling(
+    TIntermNode* root)
+{
+    ASSERT(root);
+
+    IntegerForLoopUnrollMarker marker;
+    root->traverse(&marker);
+}
+
+int ForLoopUnroll::getLoopIncrement(TIntermLoop* node)
+{
+    TIntermNode* expr = node->getExpression();
+    ASSERT(expr != NULL);
+    // for expression has one of the following forms:
+    //     loop_index++
+    //     loop_index--
+    //     loop_index += constant_expression
+    //     loop_index -= constant_expression
+    //     ++loop_index
+    //     --loop_index
+    // The last two forms are not specified in the spec, but I am assuming
+    // its an oversight.
+    TIntermUnary* unOp = expr->getAsUnaryNode();
+    TIntermBinary* binOp = unOp ? NULL : expr->getAsBinaryNode();
+
+    TOperator op = EOpNull;
+    TIntermConstantUnion* incrementNode = NULL;
+    if (unOp != NULL) {
+        op = unOp->getOp();
+    } else if (binOp != NULL) {
+        op = binOp->getOp();
+        ASSERT(binOp->getRight() != NULL);
+        incrementNode = binOp->getRight()->getAsConstantUnion();
+        ASSERT(incrementNode != NULL);
+    }
+
+    int increment = 0;
+    // The operator is one of: ++ -- += -=.
+    switch (op) {
+        case EOpPostIncrement:
+        case EOpPreIncrement:
+            ASSERT((unOp != NULL) && (binOp == NULL));
+            increment = 1;
+            break;
+        case EOpPostDecrement:
+        case EOpPreDecrement:
+            ASSERT((unOp != NULL) && (binOp == NULL));
+            increment = -1;
+            break;
+        case EOpAddAssign:
+            ASSERT((unOp == NULL) && (binOp != NULL));
+            increment = evaluateIntConstant(incrementNode);
+            break;
+        case EOpSubAssign:
+            ASSERT((unOp == NULL) && (binOp != NULL));
+            increment = - evaluateIntConstant(incrementNode);
+            break;
+        default:
+            ASSERT(false);
+    }
+
+    return increment;
+}
+
+int ForLoopUnroll::evaluateIntConstant(TIntermConstantUnion* node)
+{
+    ASSERT((node != NULL) && (node->getUnionArrayPointer() != NULL));
+    return node->getIConst(0);
+}
+
diff --git a/Source/ThirdParty/ANGLE/src/compiler/translator/ForLoopUnroll.h b/Source/ThirdParty/ANGLE/src/compiler/translator/ForLoopUnroll.h
new file mode 100644 (file)
index 0000000..afd70d1
--- /dev/null
@@ -0,0 +1,52 @@
+//
+// Copyright (c) 2011 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#ifndef COMPILER_FORLOOPUNROLL_H_
+#define COMPILER_FORLOOPUNROLL_H_
+
+#include "compiler/translator/intermediate.h"
+
+struct TLoopIndexInfo {
+    int id;
+    int initValue;
+    int stopValue;
+    int incrementValue;
+    TOperator op;
+    int currentValue;
+};
+
+class ForLoopUnroll {
+public:
+    ForLoopUnroll() { }
+
+    void FillLoopIndexInfo(TIntermLoop* node, TLoopIndexInfo& info);
+
+    // Update the info.currentValue for the next loop iteration.
+    void Step();
+
+    // Return false if loop condition is no longer satisfied.
+    bool SatisfiesLoopCondition();
+
+    // Check if the symbol is the index of a loop that's unrolled.
+    bool NeedsToReplaceSymbolWithValue(TIntermSymbol* symbol);
+
+    // Return the current value of a given loop index symbol.
+    int GetLoopIndexValue(TIntermSymbol* symbol);
+
+    void Push(TLoopIndexInfo& info);
+    void Pop();
+
+    static void MarkForLoopsWithIntegerIndicesForUnrolling(TIntermNode* root);
+
+private:
+    int getLoopIncrement(TIntermLoop* node);
+
+    int evaluateIntConstant(TIntermConstantUnion* node);
+
+    TVector<TLoopIndexInfo> mLoopIndexStack;
+};
+
+#endif
diff --git a/Source/ThirdParty/ANGLE/src/compiler/translator/HashNames.h b/Source/ThirdParty/ANGLE/src/compiler/translator/HashNames.h
new file mode 100644 (file)
index 0000000..751265b
--- /dev/null
@@ -0,0 +1,19 @@
+//
+// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#ifndef COMPILER_HASH_NAMES_H_
+#define COMPILER_HASH_NAMES_H_
+
+#include <map>
+
+#include "compiler/translator/intermediate.h"
+#include "GLSLANG/ShaderLang.h"
+
+#define HASHED_NAME_PREFIX "webgl_"
+
+typedef std::map<TPersistString, TPersistString> NameMap;
+
+#endif  // COMPILER_HASH_NAMES_H_
diff --git a/Source/ThirdParty/ANGLE/src/compiler/translator/InfoSink.cpp b/Source/ThirdParty/ANGLE/src/compiler/translator/InfoSink.cpp
new file mode 100644 (file)
index 0000000..cd59658
--- /dev/null
@@ -0,0 +1,54 @@
+//
+// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "compiler/translator/InfoSink.h"
+
+void TInfoSinkBase::prefix(TPrefixType p) {
+    switch(p) {
+        case EPrefixNone:
+            break;
+        case EPrefixWarning:
+            sink.append("WARNING: ");
+            break;
+        case EPrefixError:
+            sink.append("ERROR: ");
+            break;
+        case EPrefixInternalError:
+            sink.append("INTERNAL ERROR: ");
+            break;
+        case EPrefixUnimplemented:
+            sink.append("UNIMPLEMENTED: ");
+            break;
+        case EPrefixNote:
+            sink.append("NOTE: ");
+            break;
+        default:
+            sink.append("UNKOWN ERROR: ");
+            break;
+    }
+}
+
+void TInfoSinkBase::location(int file, int line) {
+    TPersistStringStream stream;
+    if (line)
+        stream << file << ":" << line;
+    else
+        stream << file << ":? ";
+    stream << ": ";
+
+    sink.append(stream.str());
+}
+
+void TInfoSinkBase::location(const TSourceLoc& loc) {
+    location(loc.first_file, loc.first_line);
+}
+
+void TInfoSinkBase::message(TPrefixType p, const TSourceLoc& loc, const char* m) {
+    prefix(p);
+    location(loc);
+    sink.append(m);
+    sink.append("\n");
+}
diff --git a/Source/ThirdParty/ANGLE/src/compiler/translator/InfoSink.h b/Source/ThirdParty/ANGLE/src/compiler/translator/InfoSink.h
new file mode 100644 (file)
index 0000000..698a8b4
--- /dev/null
@@ -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.
+//
+
+#ifndef _INFOSINK_INCLUDED_
+#define _INFOSINK_INCLUDED_
+
+#include <math.h>
+#include <stdlib.h>
+#include "compiler/translator/Common.h"
+
+// Returns the fractional part of the given floating-point number.
+inline float fractionalPart(float f) {
+  float intPart = 0.0f;
+  return modff(f, &intPart);
+}
+
+//
+// TPrefixType is used to centralize how info log messages start.
+// See below.
+//
+enum TPrefixType {
+    EPrefixNone,
+    EPrefixWarning,
+    EPrefixError,
+    EPrefixInternalError,
+    EPrefixUnimplemented,
+    EPrefixNote
+};
+
+//
+// Encapsulate info logs for all objects that have them.
+//
+// The methods are a general set of tools for getting a variety of
+// messages and types inserted into the log.
+//
+class TInfoSinkBase {
+public:
+    TInfoSinkBase() {}
+
+    template <typename T>
+    TInfoSinkBase& operator<<(const T& t) {
+        TPersistStringStream stream;
+        stream << t;
+        sink.append(stream.str());
+        return *this;
+    }
+    // Override << operator for specific types. It is faster to append strings
+    // and characters directly to the sink.
+    TInfoSinkBase& operator<<(char c) {
+        sink.append(1, c);
+        return *this;
+    }
+    TInfoSinkBase& operator<<(const char* str) {
+        sink.append(str);
+        return *this;
+    }
+    TInfoSinkBase& operator<<(const TPersistString& str) {
+        sink.append(str);
+        return *this;
+    }
+    TInfoSinkBase& operator<<(const TString& str) {
+        sink.append(str.c_str());
+        return *this;
+    }
+    // Make sure floats are written with correct precision.
+    TInfoSinkBase& operator<<(float f) {
+        // Make sure that at least one decimal point is written. If a number
+        // does not have a fractional part, the default precision format does
+        // not write the decimal portion which gets interpreted as integer by
+        // the compiler.
+        TPersistStringStream stream;
+        if (fractionalPart(f) == 0.0f) {
+            stream.precision(1);
+            stream << std::showpoint << std::fixed << f;
+        } else {
+            stream.unsetf(std::ios::fixed);
+            stream.unsetf(std::ios::scientific);
+            stream.precision(8);
+            stream << f;
+        }
+        sink.append(stream.str());
+        return *this;
+    }
+    // Write boolean values as their names instead of integral value.
+    TInfoSinkBase& operator<<(bool b) {
+        const char* str = b ? "true" : "false";
+        sink.append(str);
+        return *this;
+    }
+
+    void erase() { sink.clear(); }
+    int size() { return static_cast<int>(sink.size()); }
+
+    const TPersistString& str() const { return sink; }
+    const char* c_str() const { return sink.c_str(); }
+
+    void prefix(TPrefixType p);
+    void location(int file, int line);
+    void location(const TSourceLoc& loc);
+    void message(TPrefixType p, const TSourceLoc& loc, const char* m);
+
+private:
+    TPersistString sink;
+};
+
+class TInfoSink {
+public:
+    TInfoSinkBase info;
+    TInfoSinkBase debug;
+    TInfoSinkBase obj;
+};
+
+#endif // _INFOSINK_INCLUDED_
diff --git a/Source/ThirdParty/ANGLE/src/compiler/translator/Initialize.cpp b/Source/ThirdParty/ANGLE/src/compiler/translator/Initialize.cpp
new file mode 100644 (file)
index 0000000..db728b2
--- /dev/null
@@ -0,0 +1,564 @@
+//
+// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+//
+// Create strings that declare built-in definitions, add built-ins that
+// cannot be expressed in the files, and establish mappings between 
+// built-in functions and operators.
+//
+
+#include "compiler/translator/Initialize.h"
+
+#include "compiler/translator/intermediate.h"
+
+void InsertBuiltInFunctions(ShShaderType type, ShShaderSpec spec, const ShBuiltInResources &resources, TSymbolTable &symbolTable)
+{
+    TType *float1 = new TType(EbtFloat, EbpUndefined, EvqGlobal, 1);
+    TType *float2 = new TType(EbtFloat, EbpUndefined, EvqGlobal, 2);
+    TType *float3 = new TType(EbtFloat, EbpUndefined, EvqGlobal, 3);
+    TType *float4 = new TType(EbtFloat, EbpUndefined, EvqGlobal, 4);
+
+    TType *int2 = new TType(EbtInt, EbpUndefined, EvqGlobal, 2);
+    TType *int3 = new TType(EbtInt, EbpUndefined, EvqGlobal, 3);
+    TType *int4 = new TType(EbtInt, EbpUndefined, EvqGlobal, 4);
+
+    //
+    // Angle and Trigonometric Functions.
+    //
+    symbolTable.insertBuiltIn(float1, "radians", float1);
+    symbolTable.insertBuiltIn(float2, "radians", float2);
+    symbolTable.insertBuiltIn(float3, "radians", float3);
+    symbolTable.insertBuiltIn(float4, "radians", float4);
+
+    symbolTable.insertBuiltIn(float1, "degrees", float1);
+    symbolTable.insertBuiltIn(float2, "degrees", float2);
+    symbolTable.insertBuiltIn(float3, "degrees", float3);
+    symbolTable.insertBuiltIn(float4, "degrees", float4);
+
+    symbolTable.insertBuiltIn(float1, "sin", float1);
+    symbolTable.insertBuiltIn(float2, "sin", float2);
+    symbolTable.insertBuiltIn(float3, "sin", float3);
+    symbolTable.insertBuiltIn(float4, "sin", float4);
+
+    symbolTable.insertBuiltIn(float1, "cos", float1);
+    symbolTable.insertBuiltIn(float2, "cos", float2);
+    symbolTable.insertBuiltIn(float3, "cos", float3);
+    symbolTable.insertBuiltIn(float4, "cos", float4);
+
+    symbolTable.insertBuiltIn(float1, "tan", float1);
+    symbolTable.insertBuiltIn(float2, "tan", float2);
+    symbolTable.insertBuiltIn(float3, "tan", float3);
+    symbolTable.insertBuiltIn(float4, "tan", float4);
+
+    symbolTable.insertBuiltIn(float1, "asin", float1);
+    symbolTable.insertBuiltIn(float2, "asin", float2);
+    symbolTable.insertBuiltIn(float3, "asin", float3);
+    symbolTable.insertBuiltIn(float4, "asin", float4);
+
+    symbolTable.insertBuiltIn(float1, "acos", float1);
+    symbolTable.insertBuiltIn(float2, "acos", float2);
+    symbolTable.insertBuiltIn(float3, "acos", float3);
+    symbolTable.insertBuiltIn(float4, "acos", float4);
+
+    symbolTable.insertBuiltIn(float1, "atan", float1, float1);
+    symbolTable.insertBuiltIn(float2, "atan", float2, float2);
+    symbolTable.insertBuiltIn(float3, "atan", float3, float3);
+    symbolTable.insertBuiltIn(float4, "atan", float4, float4);
+
+    symbolTable.insertBuiltIn(float1, "atan", float1);
+    symbolTable.insertBuiltIn(float2, "atan", float2);
+    symbolTable.insertBuiltIn(float3, "atan", float3);
+    symbolTable.insertBuiltIn(float4, "atan", float4);
+
+    //
+    // Exponential Functions.
+    //
+    symbolTable.insertBuiltIn(float1, "pow", float1, float1);
+    symbolTable.insertBuiltIn(float2, "pow", float2, float2);
+    symbolTable.insertBuiltIn(float3, "pow", float3, float3);
+    symbolTable.insertBuiltIn(float4, "pow", float4, float4);
+
+    symbolTable.insertBuiltIn(float1, "exp", float1);
+    symbolTable.insertBuiltIn(float2, "exp", float2);
+    symbolTable.insertBuiltIn(float3, "exp", float3);
+    symbolTable.insertBuiltIn(float4, "exp", float4);
+
+    symbolTable.insertBuiltIn(float1, "log", float1);
+    symbolTable.insertBuiltIn(float2, "log", float2);
+    symbolTable.insertBuiltIn(float3, "log", float3);
+    symbolTable.insertBuiltIn(float4, "log", float4);
+
+    symbolTable.insertBuiltIn(float1, "exp2", float1);
+    symbolTable.insertBuiltIn(float2, "exp2", float2);
+    symbolTable.insertBuiltIn(float3, "exp2", float3);
+    symbolTable.insertBuiltIn(float4, "exp2", float4);
+
+    symbolTable.insertBuiltIn(float1, "log2", float1);
+    symbolTable.insertBuiltIn(float2, "log2", float2);
+    symbolTable.insertBuiltIn(float3, "log2", float3);
+    symbolTable.insertBuiltIn(float4, "log2", float4);
+
+    symbolTable.insertBuiltIn(float1, "sqrt", float1);
+    symbolTable.insertBuiltIn(float2, "sqrt", float2);
+    symbolTable.insertBuiltIn(float3, "sqrt", float3);
+    symbolTable.insertBuiltIn(float4, "sqrt", float4);
+
+    symbolTable.insertBuiltIn(float1, "inversesqrt", float1);
+    symbolTable.insertBuiltIn(float2, "inversesqrt", float2);
+    symbolTable.insertBuiltIn(float3, "inversesqrt", float3);
+    symbolTable.insertBuiltIn(float4, "inversesqrt", float4);
+
+    //
+    // Common Functions.
+    //
+    symbolTable.insertBuiltIn(float1, "abs", float1);
+    symbolTable.insertBuiltIn(float2, "abs", float2);
+    symbolTable.insertBuiltIn(float3, "abs", float3);
+    symbolTable.insertBuiltIn(float4, "abs", float4);
+
+    symbolTable.insertBuiltIn(float1, "sign", float1);
+    symbolTable.insertBuiltIn(float2, "sign", float2);
+    symbolTable.insertBuiltIn(float3, "sign", float3);
+    symbolTable.insertBuiltIn(float4, "sign", float4);
+
+    symbolTable.insertBuiltIn(float1, "floor", float1);
+    symbolTable.insertBuiltIn(float2, "floor", float2);
+    symbolTable.insertBuiltIn(float3, "floor", float3);
+    symbolTable.insertBuiltIn(float4, "floor", float4);
+
+    symbolTable.insertBuiltIn(float1, "ceil", float1);
+    symbolTable.insertBuiltIn(float2, "ceil", float2);
+    symbolTable.insertBuiltIn(float3, "ceil", float3);
+    symbolTable.insertBuiltIn(float4, "ceil", float4);
+
+    symbolTable.insertBuiltIn(float1, "fract", float1);
+    symbolTable.insertBuiltIn(float2, "fract", float2);
+    symbolTable.insertBuiltIn(float3, "fract", float3);
+    symbolTable.insertBuiltIn(float4, "fract", float4);
+
+    symbolTable.insertBuiltIn(float1, "mod", float1, float1);
+    symbolTable.insertBuiltIn(float2, "mod", float2, float1);
+    symbolTable.insertBuiltIn(float3, "mod", float3, float1);
+    symbolTable.insertBuiltIn(float4, "mod", float4, float1);
+    symbolTable.insertBuiltIn(float2, "mod", float2, float2);
+    symbolTable.insertBuiltIn(float3, "mod", float3, float3);
+    symbolTable.insertBuiltIn(float4, "mod", float4, float4);
+
+    symbolTable.insertBuiltIn(float1, "min", float1, float1);
+    symbolTable.insertBuiltIn(float2, "min", float2, float1);
+    symbolTable.insertBuiltIn(float3, "min", float3, float1);
+    symbolTable.insertBuiltIn(float4, "min", float4, float1);
+    symbolTable.insertBuiltIn(float2, "min", float2, float2);
+    symbolTable.insertBuiltIn(float3, "min", float3, float3);
+    symbolTable.insertBuiltIn(float4, "min", float4, float4);
+
+    symbolTable.insertBuiltIn(float1, "max", float1, float1);
+    symbolTable.insertBuiltIn(float2, "max", float2, float1);
+    symbolTable.insertBuiltIn(float3, "max", float3, float1);
+    symbolTable.insertBuiltIn(float4, "max", float4, float1);
+    symbolTable.insertBuiltIn(float2, "max", float2, float2);
+    symbolTable.insertBuiltIn(float3, "max", float3, float3);
+    symbolTable.insertBuiltIn(float4, "max", float4, float4);
+
+    symbolTable.insertBuiltIn(float1, "clamp", float1, float1, float1);
+    symbolTable.insertBuiltIn(float2, "clamp", float2, float1, float1);
+    symbolTable.insertBuiltIn(float3, "clamp", float3, float1, float1);
+    symbolTable.insertBuiltIn(float4, "clamp", float4, float1, float1);
+    symbolTable.insertBuiltIn(float2, "clamp", float2, float2, float2);
+    symbolTable.insertBuiltIn(float3, "clamp", float3, float3, float3);
+    symbolTable.insertBuiltIn(float4, "clamp", float4, float4, float4);
+
+    symbolTable.insertBuiltIn(float1, "mix", float1, float1, float1);
+    symbolTable.insertBuiltIn(float2, "mix", float2, float2, float1);
+    symbolTable.insertBuiltIn(float3, "mix", float3, float3, float1);
+    symbolTable.insertBuiltIn(float4, "mix", float4, float4, float1);
+    symbolTable.insertBuiltIn(float2, "mix", float2, float2, float2);
+    symbolTable.insertBuiltIn(float3, "mix", float3, float3, float3);
+    symbolTable.insertBuiltIn(float4, "mix", float4, float4, float4);
+
+    symbolTable.insertBuiltIn(float1, "step", float1, float1);
+    symbolTable.insertBuiltIn(float2, "step", float2, float2);
+    symbolTable.insertBuiltIn(float3, "step", float3, float3);
+    symbolTable.insertBuiltIn(float4, "step", float4, float4);
+    symbolTable.insertBuiltIn(float2, "step", float1, float2);
+    symbolTable.insertBuiltIn(float3, "step", float1, float3);
+    symbolTable.insertBuiltIn(float4, "step", float1, float4);
+
+    symbolTable.insertBuiltIn(float1, "smoothstep", float1, float1, float1);
+    symbolTable.insertBuiltIn(float2, "smoothstep", float2, float2, float2);
+    symbolTable.insertBuiltIn(float3, "smoothstep", float3, float3, float3);
+    symbolTable.insertBuiltIn(float4, "smoothstep", float4, float4, float4);
+    symbolTable.insertBuiltIn(float2, "smoothstep", float1, float1, float2);
+    symbolTable.insertBuiltIn(float3, "smoothstep", float1, float1, float3);
+    symbolTable.insertBuiltIn(float4, "smoothstep", float1, float1, float4);
+
+    //
+    // Geometric Functions.
+    //
+    symbolTable.insertBuiltIn(float1, "length", float1);
+    symbolTable.insertBuiltIn(float1, "length", float2);
+    symbolTable.insertBuiltIn(float1, "length", float3);
+    symbolTable.insertBuiltIn(float1, "length", float4);
+
+    symbolTable.insertBuiltIn(float1, "distance", float1, float1);
+    symbolTable.insertBuiltIn(float1, "distance", float2, float2);
+    symbolTable.insertBuiltIn(float1, "distance", float3, float3);
+    symbolTable.insertBuiltIn(float1, "distance", float4, float4);
+
+    symbolTable.insertBuiltIn(float1, "dot", float1, float1);
+    symbolTable.insertBuiltIn(float1, "dot", float2, float2);
+    symbolTable.insertBuiltIn(float1, "dot", float3, float3);
+    symbolTable.insertBuiltIn(float1, "dot", float4, float4);
+
+    symbolTable.insertBuiltIn(float3, "cross", float3, float3);
+    symbolTable.insertBuiltIn(float1, "normalize", float1);
+    symbolTable.insertBuiltIn(float2, "normalize", float2);
+    symbolTable.insertBuiltIn(float3, "normalize", float3);
+    symbolTable.insertBuiltIn(float4, "normalize", float4);
+
+    symbolTable.insertBuiltIn(float1, "faceforward", float1, float1, float1);
+    symbolTable.insertBuiltIn(float2, "faceforward", float2, float2, float2);
+    symbolTable.insertBuiltIn(float3, "faceforward", float3, float3, float3);
+    symbolTable.insertBuiltIn(float4, "faceforward", float4, float4, float4);
+
+    symbolTable.insertBuiltIn(float1, "reflect", float1, float1);
+    symbolTable.insertBuiltIn(float2, "reflect", float2, float2);
+    symbolTable.insertBuiltIn(float3, "reflect", float3, float3);
+    symbolTable.insertBuiltIn(float4, "reflect", float4, float4);
+
+    symbolTable.insertBuiltIn(float1, "refract", float1, float1, float1);
+    symbolTable.insertBuiltIn(float2, "refract", float2, float2, float1);
+    symbolTable.insertBuiltIn(float3, "refract", float3, float3, float1);
+    symbolTable.insertBuiltIn(float4, "refract", float4, float4, float1);
+
+    TType *mat2 = new TType(EbtFloat, EbpUndefined, EvqGlobal, 2, true);
+    TType *mat3 = new TType(EbtFloat, EbpUndefined, EvqGlobal, 3, true);
+    TType *mat4 = new TType(EbtFloat, EbpUndefined, EvqGlobal, 4, true);
+
+    //
+    // Matrix Functions.
+    //
+    symbolTable.insertBuiltIn(mat2, "matrixCompMult", mat2, mat2);
+    symbolTable.insertBuiltIn(mat3, "matrixCompMult", mat3, mat3);
+    symbolTable.insertBuiltIn(mat4, "matrixCompMult", mat4, mat4);
+
+    TType *bool1 = new TType(EbtBool, EbpUndefined, EvqGlobal, 1);
+    TType *bool2 = new TType(EbtBool, EbpUndefined, EvqGlobal, 2);
+    TType *bool3 = new TType(EbtBool, EbpUndefined, EvqGlobal, 3);
+    TType *bool4 = new TType(EbtBool, EbpUndefined, EvqGlobal, 4);
+
+    //
+    // Vector relational functions.
+    //
+    symbolTable.insertBuiltIn(bool2, "lessThan", float2, float2);
+    symbolTable.insertBuiltIn(bool3, "lessThan", float3, float3);
+    symbolTable.insertBuiltIn(bool4, "lessThan", float4, float4);
+
+    symbolTable.insertBuiltIn(bool2, "lessThan", int2, int2);
+    symbolTable.insertBuiltIn(bool3, "lessThan", int3, int3);
+    symbolTable.insertBuiltIn(bool4, "lessThan", int4, int4);
+
+    symbolTable.insertBuiltIn(bool2, "lessThanEqual", float2, float2);
+    symbolTable.insertBuiltIn(bool3, "lessThanEqual", float3, float3);
+    symbolTable.insertBuiltIn(bool4, "lessThanEqual", float4, float4);
+
+    symbolTable.insertBuiltIn(bool2, "lessThanEqual", int2, int2);
+    symbolTable.insertBuiltIn(bool3, "lessThanEqual", int3, int3);
+    symbolTable.insertBuiltIn(bool4, "lessThanEqual", int4, int4);
+
+    symbolTable.insertBuiltIn(bool2, "greaterThan", float2, float2);
+    symbolTable.insertBuiltIn(bool3, "greaterThan", float3, float3);
+    symbolTable.insertBuiltIn(bool4, "greaterThan", float4, float4);
+
+    symbolTable.insertBuiltIn(bool2, "greaterThan", int2, int2);
+    symbolTable.insertBuiltIn(bool3, "greaterThan", int3, int3);
+    symbolTable.insertBuiltIn(bool4, "greaterThan", int4, int4);
+
+    symbolTable.insertBuiltIn(bool2, "greaterThanEqual", float2, float2);
+    symbolTable.insertBuiltIn(bool3, "greaterThanEqual", float3, float3);
+    symbolTable.insertBuiltIn(bool4, "greaterThanEqual", float4, float4);
+
+    symbolTable.insertBuiltIn(bool2, "greaterThanEqual", int2, int2);
+    symbolTable.insertBuiltIn(bool3, "greaterThanEqual", int3, int3);
+    symbolTable.insertBuiltIn(bool4, "greaterThanEqual", int4, int4);
+
+    symbolTable.insertBuiltIn(bool2, "equal", float2, float2);
+    symbolTable.insertBuiltIn(bool3, "equal", float3, float3);
+    symbolTable.insertBuiltIn(bool4, "equal", float4, float4);
+
+    symbolTable.insertBuiltIn(bool2, "equal", int2, int2);
+    symbolTable.insertBuiltIn(bool3, "equal", int3, int3);
+    symbolTable.insertBuiltIn(bool4, "equal", int4, int4);
+
+    symbolTable.insertBuiltIn(bool2, "equal", bool2, bool2);
+    symbolTable.insertBuiltIn(bool3, "equal", bool3, bool3);
+    symbolTable.insertBuiltIn(bool4, "equal", bool4, bool4);
+
+    symbolTable.insertBuiltIn(bool2, "notEqual", float2, float2);
+    symbolTable.insertBuiltIn(bool3, "notEqual", float3, float3);
+    symbolTable.insertBuiltIn(bool4, "notEqual", float4, float4);
+
+    symbolTable.insertBuiltIn(bool2, "notEqual", int2, int2);
+    symbolTable.insertBuiltIn(bool3, "notEqual", int3, int3);
+    symbolTable.insertBuiltIn(bool4, "notEqual", int4, int4);
+
+    symbolTable.insertBuiltIn(bool2, "notEqual", bool2, bool2);
+    symbolTable.insertBuiltIn(bool3, "notEqual", bool3, bool3);
+    symbolTable.insertBuiltIn(bool4, "notEqual", bool4, bool4);
+
+    symbolTable.insertBuiltIn(bool1, "any", bool2);
+    symbolTable.insertBuiltIn(bool1, "any", bool3);
+    symbolTable.insertBuiltIn(bool1, "any", bool4);
+
+    symbolTable.insertBuiltIn(bool1, "all", bool2);
+    symbolTable.insertBuiltIn(bool1, "all", bool3);
+    symbolTable.insertBuiltIn(bool1, "all", bool4);
+
+    symbolTable.insertBuiltIn(bool2, "not", bool2);
+    symbolTable.insertBuiltIn(bool3, "not", bool3);
+    symbolTable.insertBuiltIn(bool4, "not", bool4);
+
+    TType *sampler2D = new TType(EbtSampler2D, EbpUndefined, EvqGlobal, 1);
+    TType *samplerCube = new TType(EbtSamplerCube, EbpUndefined, EvqGlobal, 1);
+
+    //
+    // Texture Functions for GLSL ES 1.0
+    //
+    symbolTable.insertBuiltIn(float4, "texture2D", sampler2D, float2);
+    symbolTable.insertBuiltIn(float4, "texture2DProj", sampler2D, float3);
+    symbolTable.insertBuiltIn(float4, "texture2DProj", sampler2D, float4);
+    symbolTable.insertBuiltIn(float4, "textureCube", samplerCube, float3);
+
+    if (resources.OES_EGL_image_external)
+    {
+        TType *samplerExternalOES = new TType(EbtSamplerExternalOES, EbpUndefined, EvqGlobal, 1);
+
+        symbolTable.insertBuiltIn(float4, "texture2D", samplerExternalOES, float2);
+        symbolTable.insertBuiltIn(float4, "texture2DProj", samplerExternalOES, float3);
+        symbolTable.insertBuiltIn(float4, "texture2DProj", samplerExternalOES, float4);
+    }
+
+    if (resources.ARB_texture_rectangle)
+    {
+        TType *sampler2DRect = new TType(EbtSampler2DRect, EbpUndefined, EvqGlobal, 1);
+
+        symbolTable.insertBuiltIn(float4, "texture2DRect", sampler2DRect, float2);
+        symbolTable.insertBuiltIn(float4, "texture2DRectProj", sampler2DRect, float3);
+        symbolTable.insertBuiltIn(float4, "texture2DRectProj", sampler2DRect, float4);
+    }
+
+    if (type == SH_FRAGMENT_SHADER)
+    {
+        symbolTable.insertBuiltIn(float4, "texture2D", sampler2D, float2, float1);
+        symbolTable.insertBuiltIn(float4, "texture2DProj", sampler2D, float3, float1);
+        symbolTable.insertBuiltIn(float4, "texture2DProj", sampler2D, float4, float1);
+        symbolTable.insertBuiltIn(float4, "textureCube", samplerCube, float3, float1);
+
+        if (resources.OES_standard_derivatives)
+        {
+            symbolTable.insertBuiltIn(float1, "dFdx", float1);
+            symbolTable.insertBuiltIn(float2, "dFdx", float2);
+            symbolTable.insertBuiltIn(float3, "dFdx", float3);
+            symbolTable.insertBuiltIn(float4, "dFdx", float4);
+            
+            symbolTable.insertBuiltIn(float1, "dFdy", float1);
+            symbolTable.insertBuiltIn(float2, "dFdy", float2);
+            symbolTable.insertBuiltIn(float3, "dFdy", float3);
+            symbolTable.insertBuiltIn(float4, "dFdy", float4);
+
+            symbolTable.insertBuiltIn(float1, "fwidth", float1);
+            symbolTable.insertBuiltIn(float2, "fwidth", float2);
+            symbolTable.insertBuiltIn(float3, "fwidth", float3);
+            symbolTable.insertBuiltIn(float4, "fwidth", float4);
+        }
+    }
+
+    if(type == SH_VERTEX_SHADER)
+    {
+        symbolTable.insertBuiltIn(float4, "texture2DLod", sampler2D, float2, float1);
+        symbolTable.insertBuiltIn(float4, "texture2DProjLod", sampler2D, float3, float1);
+        symbolTable.insertBuiltIn(float4, "texture2DProjLod", sampler2D, float4, float1);
+        symbolTable.insertBuiltIn(float4, "textureCubeLod", samplerCube, float3, float1);
+    }
+
+    //
+    // Depth range in window coordinates
+    //
+    TFieldList *fields = NewPoolTFieldList();
+    TField *near = new TField(new TType(EbtFloat, EbpHigh, EvqGlobal, 1), NewPoolTString("near"));
+    TField *far = new TField(new TType(EbtFloat, EbpHigh, EvqGlobal, 1), NewPoolTString("far"));
+    TField *diff = new TField(new TType(EbtFloat, EbpHigh, EvqGlobal, 1), NewPoolTString("diff"));
+    fields->push_back(near);
+    fields->push_back(far);
+    fields->push_back(diff);
+    TStructure *depthRangeStruct = new TStructure(NewPoolTString("gl_DepthRangeParameters"), fields);
+    TVariable *depthRangeParameters = new TVariable(&depthRangeStruct->name(), depthRangeStruct, true);
+    symbolTable.insert(*depthRangeParameters);
+    TVariable *depthRange = new TVariable(NewPoolTString("gl_DepthRange"), TType(depthRangeStruct));
+    depthRange->setQualifier(EvqUniform);
+    symbolTable.insert(*depthRange);
+
+    //
+    // Implementation dependent built-in constants.
+    //
+    symbolTable.insertConstInt("gl_MaxVertexAttribs", resources.MaxVertexAttribs);
+    symbolTable.insertConstInt("gl_MaxVertexUniformVectors", resources.MaxVertexUniformVectors);
+    symbolTable.insertConstInt("gl_MaxVaryingVectors", resources.MaxVaryingVectors);
+    symbolTable.insertConstInt("gl_MaxVertexTextureImageUnits", resources.MaxVertexTextureImageUnits);
+    symbolTable.insertConstInt("gl_MaxCombinedTextureImageUnits", resources.MaxCombinedTextureImageUnits);
+    symbolTable.insertConstInt("gl_MaxTextureImageUnits", resources.MaxTextureImageUnits);
+    symbolTable.insertConstInt("gl_MaxFragmentUniformVectors", resources.MaxFragmentUniformVectors);
+
+    if (spec != SH_CSS_SHADERS_SPEC)
+    {
+        symbolTable.insertConstInt("gl_MaxDrawBuffers", resources.MaxDrawBuffers);
+    }
+}
+
+void IdentifyBuiltIns(ShShaderType type, ShShaderSpec spec,
+                      const ShBuiltInResources &resources,
+                      TSymbolTable &symbolTable)
+{
+    //
+    // First, insert some special built-in variables that are not in 
+    // the built-in header files.
+    //
+    switch(type) {
+    case SH_FRAGMENT_SHADER:
+        symbolTable.insert(*new TVariable(NewPoolTString("gl_FragCoord"),                       TType(EbtFloat, EbpMedium, EvqFragCoord,   4)));
+        symbolTable.insert(*new TVariable(NewPoolTString("gl_FrontFacing"),                     TType(EbtBool,  EbpUndefined, EvqFrontFacing, 1)));
+        symbolTable.insert(*new TVariable(NewPoolTString("gl_PointCoord"),                      TType(EbtFloat, EbpMedium, EvqPointCoord,  2)));
+
+        //
+        // In CSS Shaders, gl_FragColor, gl_FragData, and gl_MaxDrawBuffers are not available.
+        // Instead, css_MixColor and css_ColorMatrix are available.
+        //
+        if (spec != SH_CSS_SHADERS_SPEC) {
+            symbolTable.insert(*new TVariable(NewPoolTString("gl_FragColor"),                   TType(EbtFloat, EbpMedium, EvqFragColor,   4)));
+            symbolTable.insert(*new TVariable(NewPoolTString("gl_FragData[gl_MaxDrawBuffers]"), TType(EbtFloat, EbpMedium, EvqFragData,    4)));
+            if (resources.EXT_frag_depth) {
+                symbolTable.insert(*new TVariable(NewPoolTString("gl_FragDepthEXT"),            TType(EbtFloat, resources.FragmentPrecisionHigh ? EbpHigh : EbpMedium, EvqFragDepth, 1)));
+                symbolTable.relateToExtension("gl_FragDepthEXT", "GL_EXT_frag_depth");
+            }
+        } else {
+            symbolTable.insert(*new TVariable(NewPoolTString("css_MixColor"),                   TType(EbtFloat, EbpMedium, EvqGlobal,      4)));
+            symbolTable.insert(*new TVariable(NewPoolTString("css_ColorMatrix"),                TType(EbtFloat, EbpMedium, EvqGlobal,      4, true)));
+        }
+
+        break;
+
+    case SH_VERTEX_SHADER:
+        symbolTable.insert(*new TVariable(NewPoolTString("gl_Position"),    TType(EbtFloat, EbpHigh, EvqPosition,    4)));
+        symbolTable.insert(*new TVariable(NewPoolTString("gl_PointSize"),   TType(EbtFloat, EbpMedium, EvqPointSize,   1)));
+        break;
+
+    default: assert(false && "Language not supported");
+    }
+
+    //
+    // Next, identify which built-ins from the already loaded headers have
+    // a mapping to an operator.  Those that are not identified as such are
+    // expected to be resolved through a library of functions, versus as
+    // operations.
+    //
+    symbolTable.relateToOperator("matrixCompMult",   EOpMul);
+
+    symbolTable.relateToOperator("equal",            EOpVectorEqual);
+    symbolTable.relateToOperator("notEqual",         EOpVectorNotEqual);
+    symbolTable.relateToOperator("lessThan",         EOpLessThan);
+    symbolTable.relateToOperator("greaterThan",      EOpGreaterThan);
+    symbolTable.relateToOperator("lessThanEqual",    EOpLessThanEqual);
+    symbolTable.relateToOperator("greaterThanEqual", EOpGreaterThanEqual);
+    
+    symbolTable.relateToOperator("radians",      EOpRadians);
+    symbolTable.relateToOperator("degrees",      EOpDegrees);
+    symbolTable.relateToOperator("sin",          EOpSin);
+    symbolTable.relateToOperator("cos",          EOpCos);
+    symbolTable.relateToOperator("tan",          EOpTan);
+    symbolTable.relateToOperator("asin",         EOpAsin);
+    symbolTable.relateToOperator("acos",         EOpAcos);
+    symbolTable.relateToOperator("atan",         EOpAtan);
+
+    symbolTable.relateToOperator("pow",          EOpPow);
+    symbolTable.relateToOperator("exp2",         EOpExp2);
+    symbolTable.relateToOperator("log",          EOpLog);
+    symbolTable.relateToOperator("exp",          EOpExp);
+    symbolTable.relateToOperator("log2",         EOpLog2);
+    symbolTable.relateToOperator("sqrt",         EOpSqrt);
+    symbolTable.relateToOperator("inversesqrt",  EOpInverseSqrt);
+
+    symbolTable.relateToOperator("abs",          EOpAbs);
+    symbolTable.relateToOperator("sign",         EOpSign);
+    symbolTable.relateToOperator("floor",        EOpFloor);
+    symbolTable.relateToOperator("ceil",         EOpCeil);
+    symbolTable.relateToOperator("fract",        EOpFract);
+    symbolTable.relateToOperator("mod",          EOpMod);
+    symbolTable.relateToOperator("min",          EOpMin);
+    symbolTable.relateToOperator("max",          EOpMax);
+    symbolTable.relateToOperator("clamp",        EOpClamp);
+    symbolTable.relateToOperator("mix",          EOpMix);
+    symbolTable.relateToOperator("step",         EOpStep);
+    symbolTable.relateToOperator("smoothstep",   EOpSmoothStep);
+
+    symbolTable.relateToOperator("length",       EOpLength);
+    symbolTable.relateToOperator("distance",     EOpDistance);
+    symbolTable.relateToOperator("dot",          EOpDot);
+    symbolTable.relateToOperator("cross",        EOpCross);
+    symbolTable.relateToOperator("normalize",    EOpNormalize);
+    symbolTable.relateToOperator("faceforward",  EOpFaceForward);
+    symbolTable.relateToOperator("reflect",      EOpReflect);
+    symbolTable.relateToOperator("refract",      EOpRefract);
+    
+    symbolTable.relateToOperator("any",          EOpAny);
+    symbolTable.relateToOperator("all",          EOpAll);
+    symbolTable.relateToOperator("not",          EOpVectorLogicalNot);
+
+    // Map language-specific operators.
+    switch(type) {
+    case SH_VERTEX_SHADER:
+        break;
+    case SH_FRAGMENT_SHADER:
+        if (resources.OES_standard_derivatives) {
+            symbolTable.relateToOperator("dFdx",   EOpDFdx);
+            symbolTable.relateToOperator("dFdy",   EOpDFdy);
+            symbolTable.relateToOperator("fwidth", EOpFwidth);
+
+            symbolTable.relateToExtension("dFdx", "GL_OES_standard_derivatives");
+            symbolTable.relateToExtension("dFdy", "GL_OES_standard_derivatives");
+            symbolTable.relateToExtension("fwidth", "GL_OES_standard_derivatives");
+        }
+        break;
+    default: break;
+    }
+
+    // Finally add resource-specific variables.
+    switch(type) {
+    case SH_FRAGMENT_SHADER:
+        if (spec != SH_CSS_SHADERS_SPEC) {
+            // Set up gl_FragData.  The array size.
+            TType fragData(EbtFloat, EbpMedium, EvqFragData, 4, false, true);
+            fragData.setArraySize(resources.MaxDrawBuffers);
+            symbolTable.insert(*new TVariable(NewPoolTString("gl_FragData"),    fragData));
+        }
+        break;
+    default: break;
+    }
+}
+
+void InitExtensionBehavior(const ShBuiltInResources& resources,
+                           TExtensionBehavior& extBehavior)
+{
+    if (resources.OES_standard_derivatives)
+        extBehavior["GL_OES_standard_derivatives"] = EBhUndefined;
+    if (resources.OES_EGL_image_external)
+        extBehavior["GL_OES_EGL_image_external"] = EBhUndefined;
+    if (resources.ARB_texture_rectangle)
+        extBehavior["GL_ARB_texture_rectangle"] = EBhUndefined;
+    if (resources.EXT_draw_buffers)
+        extBehavior["GL_EXT_draw_buffers"] = EBhUndefined;
+    if (resources.EXT_frag_depth)
+        extBehavior["GL_EXT_frag_depth"] = EBhUndefined;
+}
diff --git a/Source/ThirdParty/ANGLE/src/compiler/translator/Initialize.h b/Source/ThirdParty/ANGLE/src/compiler/translator/Initialize.h
new file mode 100644 (file)
index 0000000..b564286
--- /dev/null
@@ -0,0 +1,23 @@
+//
+// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#ifndef _INITIALIZE_INCLUDED_
+#define _INITIALIZE_INCLUDED_
+
+#include "compiler/translator/Common.h"
+#include "compiler/translator/ShHandle.h"
+#include "compiler/translator/SymbolTable.h"
+
+void InsertBuiltInFunctions(ShShaderType type, ShShaderSpec spec, const ShBuiltInResources &resources, TSymbolTable &table);
+
+void IdentifyBuiltIns(ShShaderType type, ShShaderSpec spec,
+                      const ShBuiltInResources& resources,
+                      TSymbolTable& symbolTable);
+
+void InitExtensionBehavior(const ShBuiltInResources& resources,
+                           TExtensionBehavior& extensionBehavior);
+
+#endif // _INITIALIZE_INCLUDED_
diff --git a/Source/ThirdParty/ANGLE/src/compiler/translator/InitializeDll.cpp b/Source/ThirdParty/ANGLE/src/compiler/translator/InitializeDll.cpp
new file mode 100644 (file)
index 0000000..43f8178
--- /dev/null
@@ -0,0 +1,32 @@
+//
+// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "compiler/translator/InitializeDll.h"
+
+#include "compiler/translator/InitializeGlobals.h"
+#include "compiler/translator/InitializeParseContext.h"
+#include "compiler/translator/osinclude.h"
+
+bool InitProcess()
+{
+    if (!InitializePoolIndex()) {
+        assert(0 && "InitProcess(): Failed to initalize global pool");
+        return false;
+    }
+
+    if (!InitializeParseContextIndex()) {
+        assert(0 && "InitProcess(): Failed to initalize parse context");
+        return false;
+    }
+
+    return true;
+}
+
+void DetachProcess()
+{
+    FreeParseContextIndex();
+    FreePoolIndex();
+}
diff --git a/Source/ThirdParty/ANGLE/src/compiler/translator/InitializeDll.h b/Source/ThirdParty/ANGLE/src/compiler/translator/InitializeDll.h
new file mode 100644 (file)
index 0000000..43070cc
--- /dev/null
@@ -0,0 +1,13 @@
+//
+// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+#ifndef __INITIALIZEDLL_H
+#define __INITIALIZEDLL_H
+
+bool InitProcess();
+void DetachProcess();
+
+#endif // __INITIALIZEDLL_H
+
diff --git a/Source/ThirdParty/ANGLE/src/compiler/translator/InitializeGlobals.h b/Source/ThirdParty/ANGLE/src/compiler/translator/InitializeGlobals.h
new file mode 100644 (file)
index 0000000..0715941
--- /dev/null
@@ -0,0 +1,13 @@
+//
+// 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_
+
+bool InitializePoolIndex();
+void FreePoolIndex();
+
+#endif // __INITIALIZE_GLOBALS_INCLUDED_
diff --git a/Source/ThirdParty/ANGLE/src/compiler/translator/InitializeParseContext.cpp b/Source/ThirdParty/ANGLE/src/compiler/translator/InitializeParseContext.cpp
new file mode 100644 (file)
index 0000000..b4defae
--- /dev/null
@@ -0,0 +1,40 @@
+//
+// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "compiler/translator/InitializeParseContext.h"
+
+#include "compiler/translator/osinclude.h"
+
+OS_TLSIndex GlobalParseContextIndex = OS_INVALID_TLS_INDEX;
+
+bool InitializeParseContextIndex()
+{
+    assert(GlobalParseContextIndex == OS_INVALID_TLS_INDEX);
+
+    GlobalParseContextIndex = OS_AllocTLSIndex();
+    return GlobalParseContextIndex != OS_INVALID_TLS_INDEX;
+}
+
+void FreeParseContextIndex()
+{
+    assert(GlobalParseContextIndex != OS_INVALID_TLS_INDEX);
+
+    OS_FreeTLSIndex(GlobalParseContextIndex);
+    GlobalParseContextIndex = OS_INVALID_TLS_INDEX;
+}
+
+void SetGlobalParseContext(TParseContext* context)
+{
+    assert(GlobalParseContextIndex != OS_INVALID_TLS_INDEX);
+    OS_SetTLSValue(GlobalParseContextIndex, context);
+}
+
+TParseContext* GetGlobalParseContext()
+{
+    assert(GlobalParseContextIndex != OS_INVALID_TLS_INDEX);
+    return static_cast<TParseContext*>(OS_GetTLSValue(GlobalParseContextIndex));
+}
+
diff --git a/Source/ThirdParty/ANGLE/src/compiler/translator/InitializeParseContext.h b/Source/ThirdParty/ANGLE/src/compiler/translator/InitializeParseContext.h
new file mode 100644 (file)
index 0000000..bffbab8
--- /dev/null
@@ -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_
+
+bool InitializeParseContextIndex();
+void FreeParseContextIndex();
+
+struct TParseContext;
+extern void SetGlobalParseContext(TParseContext* context);
+extern TParseContext* GetGlobalParseContext();
+
+#endif // __INITIALIZE_PARSE_CONTEXT_INCLUDED_
diff --git a/Source/ThirdParty/ANGLE/src/compiler/translator/InitializeVariables.cpp b/Source/ThirdParty/ANGLE/src/compiler/translator/InitializeVariables.cpp
new file mode 100644 (file)
index 0000000..115c561
--- /dev/null
@@ -0,0 +1,116 @@
+//
+// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "compiler/translator/InitializeVariables.h"
+#include "compiler/translator/compilerdebug.h"
+
+namespace
+{
+
+TIntermConstantUnion* constructFloatConstUnionNode(const TType& type)
+{
+    TType myType = type;
+    unsigned char size = myType.getNominalSize();
+    if (myType.isMatrix())
+        size *= size;
+    ConstantUnion *u = new ConstantUnion[size];
+    for (int ii = 0; ii < size; ++ii)
+        u[ii].setFConst(0.0f);
+
+    myType.clearArrayness();
+    myType.setQualifier(EvqConst);
+    TIntermConstantUnion *node = new TIntermConstantUnion(u, myType);
+    return node;
+}
+
+TIntermConstantUnion* constructIndexNode(int index)
+{
+    ConstantUnion *u = new ConstantUnion[1];
+    u[0].setIConst(index);
+
+    TType type(EbtInt, EbpUndefined, EvqConst, 1);
+    TIntermConstantUnion *node = new TIntermConstantUnion(u, type);
+    return node;
+}
+
+}  // namespace anonymous
+
+bool InitializeVariables::visitAggregate(Visit visit, TIntermAggregate* node)
+{
+    bool visitChildren = !mCodeInserted;
+    switch (node->getOp())
+    {
+      case EOpSequence:
+        break;
+      case EOpFunction:
+      {
+        // Function definition.
+        ASSERT(visit == PreVisit);
+        if (node->getName() == "main(")
+        {
+            TIntermSequence &sequence = node->getSequence();
+            ASSERT((sequence.size() == 1) || (sequence.size() == 2));
+            TIntermAggregate *body = NULL;
+            if (sequence.size() == 1)
+            {
+                body = new TIntermAggregate(EOpSequence);
+                sequence.push_back(body);
+            }
+            else
+            {
+                body = sequence[1]->getAsAggregate();
+            }
+            ASSERT(body);
+            insertInitCode(body->getSequence());
+            mCodeInserted = true;
+        }
+        break;
+      }
+      default:
+        visitChildren = false;
+        break;
+    }
+    return visitChildren;
+}
+
+void InitializeVariables::insertInitCode(TIntermSequence& sequence)
+{
+    for (size_t ii = 0; ii < mVariables.size(); ++ii)
+    {
+        const InitVariableInfo& varInfo = mVariables[ii];
+
+        if (varInfo.type.isArray())
+        {
+            for (int index = varInfo.type.getArraySize() - 1; index >= 0; --index)
+            {
+                TIntermBinary *assign = new TIntermBinary(EOpAssign);
+                sequence.insert(sequence.begin(), assign);
+
+                TIntermBinary *indexDirect = new TIntermBinary(EOpIndexDirect);
+                TIntermSymbol *symbol = new TIntermSymbol(0, varInfo.name, varInfo.type);
+                indexDirect->setLeft(symbol);
+                TIntermConstantUnion *indexNode = constructIndexNode(index);
+                indexDirect->setRight(indexNode);
+
+                assign->setLeft(indexDirect);
+
+                TIntermConstantUnion *zeroConst = constructFloatConstUnionNode(varInfo.type);
+                assign->setRight(zeroConst);
+            }
+        }
+        else
+        {
+            TIntermBinary *assign = new TIntermBinary(EOpAssign);
+            sequence.insert(sequence.begin(), assign);
+            TIntermSymbol *symbol = new TIntermSymbol(0, varInfo.name, varInfo.type);
+            assign->setLeft(symbol);
+            TIntermConstantUnion *zeroConst = constructFloatConstUnionNode(varInfo.type);
+            assign->setRight(zeroConst);
+        }
+
+    }
+}
+
diff --git a/Source/ThirdParty/ANGLE/src/compiler/translator/InitializeVariables.h b/Source/ThirdParty/ANGLE/src/compiler/translator/InitializeVariables.h
new file mode 100644 (file)
index 0000000..1cd6d7e
--- /dev/null
@@ -0,0 +1,50 @@
+//
+// Copyright (c) 2002-2013 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_INITIALIZE_VARIABLES_H_
+#define COMPILER_INITIALIZE_VARIABLES_H_
+
+#include "compiler/translator/intermediate.h"
+
+class InitializeVariables : public TIntermTraverser
+{
+  public:
+    struct InitVariableInfo
+    {
+        TString name;
+        TType type;
+
+        InitVariableInfo(const TString& _name, const TType& _type)
+            : name(_name),
+              type(_type)
+        {
+        }
+    };
+    typedef TVector<InitVariableInfo> InitVariableInfoList;
+
+    InitializeVariables(const InitVariableInfoList& vars)
+        : mCodeInserted(false),
+          mVariables(vars)
+    {
+    }
+
+  protected:
+    virtual bool visitBinary(Visit visit, TIntermBinary* node) { return false; }
+    virtual bool visitUnary(Visit visit, TIntermUnary* node) { return false; }
+    virtual bool visitSelection(Visit visit, TIntermSelection* node) { return false; }
+    virtual bool visitLoop(Visit visit, TIntermLoop* node) { return false; }
+    virtual bool visitBranch(Visit visit, TIntermBranch* node) { return false; }
+
+    virtual bool visitAggregate(Visit visit, TIntermAggregate* node);
+
+  private:
+    void insertInitCode(TIntermSequence& sequence);
+
+    InitVariableInfoList mVariables;
+    bool mCodeInserted;
+};
+
+#endif  // COMPILER_INITIALIZE_VARIABLES_H_
diff --git a/Source/ThirdParty/ANGLE/src/compiler/translator/IntermTraverse.cpp b/Source/ThirdParty/ANGLE/src/compiler/translator/IntermTraverse.cpp
new file mode 100644 (file)
index 0000000..554b834
--- /dev/null
@@ -0,0 +1,259 @@
+//
+// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "compiler/translator/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(this);
+
+        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(this);
+        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(this);
+
+        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(this);
+        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(this);
+
+        if (it->rightToLeft)
+        {
+            if (expr)
+                expr->traverse(it);
+
+            if (body)
+                body->traverse(it);
+
+            if (cond)
+                cond->traverse(it);
+
+            if (init)
+                init->traverse(it);
+        }
+        else
+        {
+            if (init)
+                init->traverse(it);
+
+            if (cond)
+                cond->traverse(it);
+
+            if (body)
+                body->traverse(it);
+
+            if (expr)
+                expr->traverse(it);
+        }
+
+        it->decrementDepth();
+    }
+
+    if (visit && it->postVisit)
+        it->visitLoop(PostVisit, this);
+}
+
+//
+// Traverse a branch node.  Same comments in binary node apply here.
+//
+void TIntermBranch::traverse(TIntermTraverser *it)
+{
+    bool visit = true;
+
+    if (it->preVisit)
+        visit = it->visitBranch(PreVisit, this);
+    
+    if (visit && expression) {
+        it->incrementDepth(this);
+        expression->traverse(it);
+        it->decrementDepth();
+    }
+
+    if (visit && it->postVisit)
+        it->visitBranch(PostVisit, this);
+}
+
diff --git a/Source/ThirdParty/ANGLE/src/compiler/translator/Intermediate.cpp b/Source/ThirdParty/ANGLE/src/compiler/translator/Intermediate.cpp
new file mode 100644 (file)
index 0000000..777cab5
--- /dev/null
@@ -0,0 +1,1500 @@
+//
+// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+//
+// Build the intermediate representation.
+//
+
+#include <float.h>
+#include <limits.h>
+#include <algorithm>
+
+#include "compiler/translator/HashNames.h"
+#include "compiler/translator/localintermediate.h"
+#include "compiler/translator/QualifierAlive.h"
+#include "compiler/translator/RemoveTree.h"
+
+bool CompareStructure(const TType& leftNodeType, ConstantUnion* rightUnionArray, ConstantUnion* leftUnionArray);
+
+static TPrecision GetHigherPrecision(TPrecision left, TPrecision right)
+{
+    return left > right ? left : right;
+}
+
+const char* getOperatorString(TOperator op)
+{
+    switch (op) {
+      case EOpInitialize: return "=";
+      case EOpAssign: return "=";
+      case EOpAddAssign: return "+=";
+      case EOpSubAssign: return "-=";
+      case EOpDivAssign: return "/=";
+
+      // Fall-through.
+      case EOpMulAssign: 
+      case EOpVectorTimesMatrixAssign:
+      case EOpVectorTimesScalarAssign:
+      case EOpMatrixTimesScalarAssign:
+      case EOpMatrixTimesMatrixAssign: return "*=";
+
+      // Fall-through.
+      case EOpIndexDirect:
+      case EOpIndexIndirect: return "[]";
+
+      case EOpIndexDirectStruct: return ".";
+      case EOpVectorSwizzle: return ".";
+      case EOpAdd: return "+";
+      case EOpSub: return "-";
+      case EOpMul: return "*";
+      case EOpDiv: return "/";
+      case EOpMod: UNIMPLEMENTED(); break;
+      case EOpEqual: return "==";
+      case EOpNotEqual: return "!=";
+      case EOpLessThan: return "<";
+      case EOpGreaterThan: return ">";
+      case EOpLessThanEqual: return "<=";
+      case EOpGreaterThanEqual: return ">=";
+
+      // Fall-through.
+      case EOpVectorTimesScalar:
+      case EOpVectorTimesMatrix:
+      case EOpMatrixTimesVector:
+      case EOpMatrixTimesScalar:
+      case EOpMatrixTimesMatrix: return "*";
+
+      case EOpLogicalOr: return "||";
+      case EOpLogicalXor: return "^^";
+      case EOpLogicalAnd: return "&&";
+      case EOpNegative: return "-";
+      case EOpVectorLogicalNot: return "not";
+      case EOpLogicalNot: return "!";
+      case EOpPostIncrement: return "++";
+      case EOpPostDecrement: return "--";
+      case EOpPreIncrement: return "++";
+      case EOpPreDecrement: return "--";
+
+      // Fall-through.
+      case EOpConvIntToBool:
+      case EOpConvFloatToBool: return "bool";
+      // Fall-through.
+      case EOpConvBoolToFloat:
+      case EOpConvIntToFloat: return "float";
+      // Fall-through.
+      case EOpConvFloatToInt:
+      case EOpConvBoolToInt: return "int";
+
+      case EOpRadians: return "radians";
+      case EOpDegrees: return "degrees";
+      case EOpSin: return "sin";
+      case EOpCos: return "cos";
+      case EOpTan: return "tan";
+      case EOpAsin: return "asin";
+      case EOpAcos: return "acos";
+      case EOpAtan: return "atan";
+      case EOpExp: return "exp";
+      case EOpLog: return "log";
+      case EOpExp2: return "exp2";
+      case EOpLog2: return "log2";
+      case EOpSqrt: return "sqrt";
+      case EOpInverseSqrt: return "inversesqrt";
+      case EOpAbs: return "abs";
+      case EOpSign: return "sign";
+      case EOpFloor: return "floor";
+      case EOpCeil: return "ceil";
+      case EOpFract: return "fract";
+      case EOpLength: return "length";
+      case EOpNormalize: return "normalize";
+      case EOpDFdx: return "dFdx";
+      case EOpDFdy: return "dFdy";
+      case EOpFwidth: return "fwidth";
+      case EOpAny: return "any";
+      case EOpAll: return "all";
+
+      default: break;
+    }
+    return "";
+}
+
+////////////////////////////////////////////////////////////////////////////
+//
+// First set of functions are to help build the intermediate representation.
+// These functions are not member functions of the nodes.
+// They are called from parser productions.
+//
+/////////////////////////////////////////////////////////////////////////////
+
+//
+// Add a terminal node for an identifier in an expression.
+//
+// Returns the added node.
+//
+TIntermSymbol* TIntermediate::addSymbol(int id, const TString& name, const TType& type, const 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, const TSourceLoc& line, TSymbolTable& symbolTable)
+{
+    switch (op) {
+        case EOpEqual:
+        case EOpNotEqual:
+            if (left->isArray())
+                return 0;
+            break;
+        case EOpLessThan:
+        case EOpGreaterThan:
+        case EOpLessThanEqual:
+        case EOpGreaterThanEqual:
+            if (left->isMatrix() || left->isArray() || left->isVector() || left->getBasicType() == EbtStruct) {
+                return 0;
+            }
+            break;
+        case EOpLogicalOr:
+        case EOpLogicalXor:
+        case EOpLogicalAnd:
+            if (left->getBasicType() != EbtBool || left->isMatrix() || left->isArray() || left->isVector()) {
+                return 0;
+            }
+            break;
+        case EOpAdd:
+        case EOpSub:
+        case EOpDiv:
+        case EOpMul:
+            if (left->getBasicType() == EbtStruct || left->getBasicType() == EbtBool)
+                return 0;
+        default: break;
+    }
+
+    //
+    // First try converting the children to compatible types.
+    //
+    if (left->getType().getStruct() && right->getType().getStruct()) {
+        if (left->getType() != right->getType())
+            return 0;
+    } else {
+        TIntermTyped* child = addConversion(op, left->getType(), right);
+        if (child)
+            right = child;
+        else {
+            child = addConversion(op, right->getType(), left);
+            if (child)
+                left = child;
+            else
+                return 0;
+        }
+    }
+
+    //
+    // Need a new node holding things together then.  Make
+    // one and promote it to the right type.
+    //
+    TIntermBinary* node = new TIntermBinary(op);
+    node->setLine(line);
+
+    node->setLeft(left);
+    node->setRight(right);
+    if (!node->promote(infoSink))
+        return 0;
+
+    //
+    // See if we can fold constants.
+    //
+    TIntermTyped* typedReturnNode = 0;
+    TIntermConstantUnion *leftTempConstant = left->getAsConstantUnion();
+    TIntermConstantUnion *rightTempConstant = right->getAsConstantUnion();
+    if (leftTempConstant && rightTempConstant) {
+        typedReturnNode = leftTempConstant->fold(node->getOp(), rightTempConstant, infoSink);
+
+        if (typedReturnNode)
+            return typedReturnNode;
+    }
+
+    return node;
+}
+
+//
+// Connect two nodes through an assignment.
+//
+// Returns the added node.
+//
+TIntermTyped* TIntermediate::addAssign(TOperator op, TIntermTyped* left, TIntermTyped* right, const TSourceLoc& line)
+{
+    //
+    // Like adding binary math, except the conversion can only go
+    // from right to left.
+    //
+    TIntermBinary* node = new TIntermBinary(op);
+    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, const TSourceLoc& line)
+{
+    TIntermBinary* node = new TIntermBinary(op);
+    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, const TSourceLoc& line, TSymbolTable& symbolTable)
+{
+    TIntermUnary* node;
+    TIntermTyped* child = childNode->getAsTyped();
+
+    if (child == 0) {
+        infoSink.info.message(EPrefixInternalError, line, "Bad type in AddUnaryMath");
+        return 0;
+    }
+
+    switch (op) {
+        case EOpLogicalNot:
+            if (child->getType().getBasicType() != EbtBool || child->getType().isMatrix() || child->getType().isArray() || child->getType().isVector()) {
+                return 0;
+            }
+            break;
+
+        case EOpPostIncrement:
+        case EOpPreIncrement:
+        case EOpPostDecrement:
+        case EOpPreDecrement:
+        case EOpNegative:
+            if (child->getType().getBasicType() == EbtStruct || child->getType().isArray())
+                return 0;
+        default: break;
+    }
+
+    //
+    // Do we need to promote the operand?
+    //
+    // Note: Implicit promotions were removed from the language.
+    //
+    TBasicType newType = EbtVoid;
+    switch (op) {
+        case EOpConstructInt:   newType = EbtInt;   break;
+        case EOpConstructBool:  newType = EbtBool;  break;
+        case EOpConstructFloat: newType = EbtFloat; break;
+        default: break;
+    }
+
+    if (newType != EbtVoid) {
+        child = addConversion(op, TType(newType, child->getPrecision(), EvqTemporary,
+            child->getNominalSize(),
+            child->isMatrix(),
+            child->isArray()),
+            child);
+        if (child == 0)
+            return 0;
+    }
+
+    //
+    // For constructors, we are now done, it's all in the conversion.
+    //
+    switch (op) {
+        case EOpConstructInt:
+        case EOpConstructBool:
+        case EOpConstructFloat:
+            return child;
+        default: break;
+    }
+
+    TIntermConstantUnion *childTempConstant = 0;
+    if (child->getAsConstantUnion())
+        childTempConstant = child->getAsConstantUnion();
+
+    //
+    // Make a new node for the operator.
+    //
+    node = new TIntermUnary(op);
+    node->setLine(line);
+    node->setOperand(child);
+
+    if (! node->promote(infoSink))
+        return 0;
+
+    if (childTempConstant)  {
+        TIntermTyped* newChild = childTempConstant->fold(op, 0, infoSink);
+
+        if (newChild)
+            return newChild;
+    }
+
+    return node;
+}
+
+//
+// This is the safe way to change the operator on an aggregate, as it
+// does lots of error checking and fixing.  Especially for establishing
+// a function call's operation on it's set of parameters.  Sequences
+// of instructions are also aggregates, but they just direnctly set
+// their operator to EOpSequence.
+//
+// Returns an aggregate node, which could be the one passed in if
+// it was already an aggregate but no operator was set.
+//
+TIntermAggregate* TIntermediate::setAggregateOperator(TIntermNode* node, TOperator op, const 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);
+        }
+    } else
+        aggNode = new TIntermAggregate();
+
+    //
+    // Set the operator.
+    //
+    aggNode->setOp(op);
+    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, node->getLine(), "Bad promotion node");
+                        return 0;
+                }
+                break;
+            case EbtBool:
+                switch (node->getBasicType()) {
+                    case EbtInt:   newOp = EOpConvIntToBool;   break;
+                    case EbtFloat: newOp = EOpConvFloatToBool; break;
+                    default:
+                        infoSink.info.message(EPrefixInternalError, node->getLine(), "Bad promotion node");
+                        return 0;
+                }
+                break;
+            case EbtInt:
+                switch (node->getBasicType()) {
+                    case EbtBool:   newOp = EOpConvBoolToInt;  break;
+                    case EbtFloat:  newOp = EOpConvFloatToInt; break;
+                    default:
+                        infoSink.info.message(EPrefixInternalError, node->getLine(), "Bad promotion node");
+                        return 0;
+                }
+                break;
+            default:
+                infoSink.info.message(EPrefixInternalError, node->getLine(), "Bad promotion type");
+                return 0;
+        }
+
+        TType type(promoteTo, node->getPrecision(), EvqTemporary, node->getNominalSize(), node->isMatrix(), node->isArray());
+        newNode = new TIntermUnary(newOp, type);
+        newNode->setLine(node->getLine());
+        newNode->setOperand(node);
+
+        return newNode;
+    }
+}
+
+//
+// Safe way to combine two nodes into an aggregate.  Works with null pointers,
+// a node that's not a aggregate yet, etc.
+//
+// Returns the resulting aggregate, unless 0 was passed in for
+// both existing nodes.
+//
+TIntermAggregate* TIntermediate::growAggregate(TIntermNode* left, TIntermNode* right, const 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);
+
+    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, const TSourceLoc& line)
+{
+    if (node == 0)
+        return 0;
+
+    TIntermAggregate* aggNode = new TIntermAggregate;
+    aggNode->getSequence().push_back(node);
+    aggNode->setLine(line);
+
+    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, const TSourceLoc& line)
+{
+    //
+    // For compile time constant selections, prune the code and
+    // test now.
+    //
+
+    if (cond->getAsTyped() && cond->getAsTyped()->getAsConstantUnion()) {
+        if (cond->getAsConstantUnion()->getBConst(0) == true)
+            return nodePair.node1 ? setAggregateOperator(nodePair.node1, EOpSequence, nodePair.node1->getLine()) : NULL;
+        else
+            return nodePair.node2 ? setAggregateOperator(nodePair.node2, EOpSequence, nodePair.node2->getLine()) : NULL;
+    }
+
+    TIntermSelection* node = new TIntermSelection(cond, nodePair.node1, nodePair.node2);
+    node->setLine(line);
+
+    return node;
+}
+
+
+TIntermTyped* TIntermediate::addComma(TIntermTyped* left, TIntermTyped* right, const TSourceLoc& line)
+{
+    if (left->getType().getQualifier() == EvqConst && right->getType().getQualifier() == EvqConst) {
+        return right;
+    } else {
+        TIntermTyped *commaAggregate = growAggregate(left, right, line);
+        commaAggregate->getAsAggregate()->setOp(EOpComma);
+        commaAggregate->setType(right->getType());
+        commaAggregate->getTypePointer()->setQualifier(EvqTemporary);
+        return commaAggregate;
+    }
+}
+
+//
+// For "?:" test nodes.  There are three children; a condition,
+// a true path, and a false path.  The two paths are specified
+// as separate parameters.
+//
+// Returns the selection node created, or 0 if one could not be.
+//
+TIntermTyped* TIntermediate::addSelection(TIntermTyped* cond, TIntermTyped* trueBlock, TIntermTyped* falseBlock, const 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()->getBConst(0))
+            return trueBlock;
+        else
+            return falseBlock;
+    }
+
+    //
+    // Make a selection node.
+    //
+    TIntermSelection* node = new TIntermSelection(cond, trueBlock, falseBlock, trueBlock->getType());
+    node->getTypePointer()->setQualifier(EvqTemporary);
+    node->setLine(line);
+
+    return node;
+}
+
+//
+// Constant terminal nodes.  Has a union that contains bool, float or int constants
+//
+// Returns the constant union node created.
+//
+
+TIntermConstantUnion* TIntermediate::addConstantUnion(ConstantUnion* unionArrayPointer, const TType& t, const TSourceLoc& line)
+{
+    TIntermConstantUnion* node = new TIntermConstantUnion(unionArrayPointer, t);
+    node->setLine(line);
+
+    return node;
+}
+
+TIntermTyped* TIntermediate::addSwizzle(TVectorFields& fields, const TSourceLoc& line)
+{
+
+    TIntermAggregate* node = new TIntermAggregate(EOpSequence);
+
+    node->setLine(line);
+    TIntermConstantUnion* constIntNode;
+    TIntermSequence &sequenceVector = node->getSequence();
+    ConstantUnion* unionArray;
+
+    for (int i = 0; i < fields.num; i++) {
+        unionArray = new ConstantUnion[1];
+        unionArray->setIConst(fields.offsets[i]);
+        constIntNode = addConstantUnion(unionArray, TType(EbtInt, EbpUndefined, EvqConst), line);
+        sequenceVector.push_back(constIntNode);
+    }
+
+    return node;
+}
+
+//
+// Create loop nodes.
+//
+TIntermNode* TIntermediate::addLoop(TLoopType type, TIntermNode* init, TIntermTyped* cond, TIntermTyped* expr, TIntermNode* body, const TSourceLoc& line)
+{
+    TIntermNode* node = new TIntermLoop(type, init, cond, expr, body);
+    node->setLine(line);
+
+    return node;
+}
+
+//
+// Add branches.
+//
+TIntermBranch* TIntermediate::addBranch(TOperator branchOp, const TSourceLoc& line)
+{
+    return addBranch(branchOp, 0, line);
+}
+
+TIntermBranch* TIntermediate::addBranch(TOperator branchOp, TIntermTyped* expression, const TSourceLoc& line)
+{
+    TIntermBranch* node = new TIntermBranch(branchOp, expression);
+    node->setLine(line);
+
+    return node;
+}
+
+//
+// This is to be executed once the final root is put on top by the parsing
+// process.
+//
+bool TIntermediate::postProcess(TIntermNode* root)
+{
+    if (root == 0)
+        return true;
+
+    //
+    // First, finish off the top level sequence, if any
+    //
+    TIntermAggregate* aggRoot = root->getAsAggregate();
+    if (aggRoot && aggRoot->getOp() == EOpNull)
+        aggRoot->setOp(EOpSequence);
+
+    return true;
+}
+
+//
+// This deletes the tree.
+//
+void TIntermediate::remove(TIntermNode* root)
+{
+    if (root)
+        RemoveAllTreeNodes(root);
+}
+
+////////////////////////////////////////////////////////////////
+//
+// Member functions of the nodes used for building the tree.
+//
+////////////////////////////////////////////////////////////////
+
+#define REPLACE_IF_IS(node, type, original, replacement) \
+    if (node == original) { \
+        node = static_cast<type *>(replacement); \
+        return true; \
+    }
+
+bool TIntermLoop::replaceChildNode(
+    TIntermNode *original, TIntermNode *replacement)
+{
+    REPLACE_IF_IS(init, TIntermNode, original, replacement);
+    REPLACE_IF_IS(cond, TIntermTyped, original, replacement);
+    REPLACE_IF_IS(expr, TIntermTyped, original, replacement);
+    REPLACE_IF_IS(body, TIntermNode, original, replacement);
+    return false;
+}
+
+bool TIntermBranch::replaceChildNode(
+    TIntermNode *original, TIntermNode *replacement)
+{
+    REPLACE_IF_IS(expression, TIntermTyped, original, replacement);
+    return false;
+}
+
+bool TIntermBinary::replaceChildNode(
+    TIntermNode *original, TIntermNode *replacement)
+{
+    REPLACE_IF_IS(left, TIntermTyped, original, replacement);
+    REPLACE_IF_IS(right, TIntermTyped, original, replacement);
+    return false;
+}
+
+bool TIntermUnary::replaceChildNode(
+    TIntermNode *original, TIntermNode *replacement)
+{
+    REPLACE_IF_IS(operand, TIntermTyped, original, replacement);
+    return false;
+}
+
+bool TIntermAggregate::replaceChildNode(
+    TIntermNode *original, TIntermNode *replacement)
+{
+    for (size_t ii = 0; ii < sequence.size(); ++ii)
+    {
+        REPLACE_IF_IS(sequence[ii], TIntermNode, original, replacement);
+    }
+    return false;
+}
+
+bool TIntermSelection::replaceChildNode(
+    TIntermNode *original, TIntermNode *replacement)
+{
+    REPLACE_IF_IS(condition, TIntermTyped, original, replacement);
+    REPLACE_IF_IS(trueBlock, TIntermNode, original, replacement);
+    REPLACE_IF_IS(falseBlock, TIntermNode, original, replacement);
+    return false;
+}
+
+//
+// Say whether or not an operation node changes the value of a variable.
+//
+bool TIntermOperator::isAssignment() const
+{
+    switch (op) {
+        case EOpPostIncrement:
+        case EOpPostDecrement:
+        case EOpPreIncrement:
+        case EOpPreDecrement:
+        case EOpAssign:
+        case EOpAddAssign:
+        case EOpSubAssign:
+        case EOpMulAssign:
+        case EOpVectorTimesMatrixAssign:
+        case EOpVectorTimesScalarAssign:
+        case EOpMatrixTimesScalarAssign:
+        case EOpMatrixTimesMatrixAssign:
+        case EOpDivAssign:
+            return true;
+        default:
+            return false;
+    }
+}
+
+//
+// returns true if the operator is for one of the constructors
+//
+bool TIntermOperator::isConstructor() const
+{
+    switch (op) {
+        case EOpConstructVec2:
+        case EOpConstructVec3:
+        case EOpConstructVec4:
+        case EOpConstructMat2:
+        case EOpConstructMat3:
+        case EOpConstructMat4:
+        case EOpConstructFloat:
+        case EOpConstructIVec2:
+        case EOpConstructIVec3:
+        case EOpConstructIVec4:
+        case EOpConstructInt:
+        case EOpConstructBVec2:
+        case EOpConstructBVec3:
+        case EOpConstructBVec4:
+        case EOpConstructBool:
+        case EOpConstructStruct:
+            return true;
+        default:
+            return false;
+    }
+}
+
+//
+// Make sure the type of a unary operator is appropriate for its
+// combination of operation and operand type.
+//
+// Returns false in nothing makes sense.
+//
+bool TIntermUnary::promote(TInfoSink&)
+{
+    switch (op) {
+        case EOpLogicalNot:
+            if (operand->getBasicType() != EbtBool)
+                return false;
+            break;
+        case EOpNegative:
+        case EOpPostIncrement:
+        case EOpPostDecrement:
+        case EOpPreIncrement:
+        case EOpPreDecrement:
+            if (operand->getBasicType() == EbtBool)
+                return false;
+            break;
+
+            // operators for built-ins are already type checked against their prototype
+        case EOpAny:
+        case EOpAll:
+        case EOpVectorLogicalNot:
+            return true;
+
+        default:
+            if (operand->getBasicType() != EbtFloat)
+                return false;
+    }
+
+    setType(operand->getType());
+    type.setQualifier(EvqTemporary);
+
+    return true;
+}
+
+//
+// Establishes the type of the resultant operation, as well as
+// makes the operator the correct one for the operands.
+//
+// Returns false if operator can't work on operands.
+//
+bool TIntermBinary::promote(TInfoSink& infoSink)
+{
+    // This function only handles scalars, vectors, and matrices.
+    if (left->isArray() || right->isArray()) {
+        infoSink.info.message(EPrefixInternalError, getLine(), "Invalid operation for arrays");
+        return false;
+    }
+
+    // GLSL ES 2.0 does not support implicit type casting.
+    // So the basic type should always match.
+    if (left->getBasicType() != right->getBasicType())
+        return false;
+
+    //
+    // Base assumption:  just make the type the same as the left
+    // operand.  Then only deviations from this need be coded.
+    //
+    setType(left->getType());
+
+    // The result gets promoted to the highest precision.
+    TPrecision higherPrecision = GetHigherPrecision(left->getPrecision(), right->getPrecision());
+    getTypePointer()->setPrecision(higherPrecision);
+
+    // Binary operations results in temporary variables unless both
+    // operands are const.
+    if (left->getQualifier() != EvqConst || right->getQualifier() != EvqConst) {
+        getTypePointer()->setQualifier(EvqTemporary);
+    }
+
+    int size = std::max(left->getNominalSize(), right->getNominalSize());
+
+    //
+    // All scalars. Code after this test assumes this case is removed!
+    //
+    if (size == 1) {
+        switch (op) {
+            //
+            // Promote to conditional
+            //
+            case EOpEqual:
+            case EOpNotEqual:
+            case EOpLessThan:
+            case EOpGreaterThan:
+            case EOpLessThanEqual:
+            case EOpGreaterThanEqual:
+                setType(TType(EbtBool, EbpUndefined));
+                break;
+
+            //
+            // And and Or operate on conditionals
+            //
+            case EOpLogicalAnd:
+            case EOpLogicalOr:
+                // Both operands must be of type bool.
+                if (left->getBasicType() != EbtBool || right->getBasicType() != EbtBool)
+                    return false;
+                setType(TType(EbtBool, EbpUndefined));
+                break;
+
+            default:
+                break;
+        }
+        return true;
+    }
+
+    // If we reach here, at least one of the operands is vector or matrix.
+    // The other operand could be a scalar, vector, or matrix.
+    // Are the sizes compatible?
+    //
+    if (left->getNominalSize() != right->getNominalSize()) {
+        // If the nominal size of operands do not match:
+        // One of them must be scalar.
+        if (left->getNominalSize() != 1 && right->getNominalSize() != 1)
+            return false;
+        // Operator cannot be of type pure assignment.
+        if (op == EOpAssign || op == EOpInitialize)
+            return false;
+    }
+
+    //
+    // Can these two operands be combined?
+    //
+    TBasicType basicType = left->getBasicType();
+    switch (op) {
+        case EOpMul:
+            if (!left->isMatrix() && right->isMatrix()) {
+                if (left->isVector())
+                    op = EOpVectorTimesMatrix;
+                else {
+                    op = EOpMatrixTimesScalar;
+                    setType(TType(basicType, higherPrecision, EvqTemporary, size, true));
+                }
+            } else if (left->isMatrix() && !right->isMatrix()) {
+                if (right->isVector()) {
+                    op = EOpMatrixTimesVector;
+                    setType(TType(basicType, higherPrecision, EvqTemporary, size, false));
+                } else {
+                    op = EOpMatrixTimesScalar;
+                }
+            } else if (left->isMatrix() && right->isMatrix()) {
+                op = EOpMatrixTimesMatrix;
+            } else if (!left->isMatrix() && !right->isMatrix()) {
+                if (left->isVector() && right->isVector()) {
+                    // leave as component product
+                } else if (left->isVector() || right->isVector()) {
+                    op = EOpVectorTimesScalar;
+                    setType(TType(basicType, higherPrecision, EvqTemporary, size, false));
+                }
+            } else {
+                infoSink.info.message(EPrefixInternalError, getLine(), "Missing elses");
+                return false;
+            }
+            break;
+        case EOpMulAssign:
+            if (!left->isMatrix() && right->isMatrix()) {
+                if (left->isVector())
+                    op = EOpVectorTimesMatrixAssign;
+                else {
+                    return false;
+                }
+            } else if (left->isMatrix() && !right->isMatrix()) {
+                if (right->isVector()) {
+                    return false;
+                } else {
+                    op = EOpMatrixTimesScalarAssign;
+                }
+            } else if (left->isMatrix() && right->isMatrix()) {
+                op = EOpMatrixTimesMatrixAssign;
+            } else if (!left->isMatrix() && !right->isMatrix()) {
+                if (left->isVector() && right->isVector()) {
+                    // leave as component product
+                } else if (left->isVector() || right->isVector()) {
+                    if (! left->isVector())
+                        return false;
+                    op = EOpVectorTimesScalarAssign;
+                    setType(TType(basicType, higherPrecision, EvqTemporary, size, false));
+                }
+            } else {
+                infoSink.info.message(EPrefixInternalError, getLine(), "Missing elses");
+                return false;
+            }
+            break;
+
+        case EOpAssign:
+        case EOpInitialize:
+        case EOpAdd:
+        case EOpSub:
+        case EOpDiv:
+        case EOpAddAssign:
+        case EOpSubAssign:
+        case EOpDivAssign:
+            if ((left->isMatrix() && right->isVector()) ||
+                (left->isVector() && right->isMatrix()))
+                return false;
+            setType(TType(basicType, higherPrecision, EvqTemporary, size, left->isMatrix() || right->isMatrix()));
+            break;
+
+        case EOpEqual:
+        case EOpNotEqual:
+        case EOpLessThan:
+        case EOpGreaterThan:
+        case EOpLessThanEqual:
+        case EOpGreaterThanEqual:
+            if ((left->isMatrix() && right->isVector()) ||
+                (left->isVector() && right->isMatrix()))
+                return false;
+            setType(TType(EbtBool, EbpUndefined));
+            break;
+
+        default:
+            return false;
+    }
+    
+    return true;
+}
+
+bool CompareStruct(const TType& leftNodeType, ConstantUnion* rightUnionArray, ConstantUnion* leftUnionArray)
+{
+    const TFieldList& fields = leftNodeType.getStruct()->fields();
+
+    size_t structSize = fields.size();
+    size_t index = 0;
+
+    for (size_t j = 0; j < structSize; j++) {
+        size_t size = fields[j]->type()->getObjectSize();
+        for (size_t i = 0; i < size; i++) {
+            if (fields[j]->type()->getBasicType() == EbtStruct) {
+                if (!CompareStructure(*(fields[j]->type()), &rightUnionArray[index], &leftUnionArray[index]))
+                    return false;
+            } else {
+                if (leftUnionArray[index] != rightUnionArray[index])
+                    return false;
+                index++;
+            }
+        }
+    }
+    return true;
+}
+
+bool CompareStructure(const TType& leftNodeType, ConstantUnion* rightUnionArray, ConstantUnion* leftUnionArray)
+{
+    if (leftNodeType.isArray()) {
+        TType typeWithoutArrayness = leftNodeType;
+        typeWithoutArrayness.clearArrayness();
+
+        size_t arraySize = leftNodeType.getArraySize();
+
+        for (size_t i = 0; i < arraySize; ++i) {
+            size_t offset = typeWithoutArrayness.getObjectSize() * i;
+            if (!CompareStruct(typeWithoutArrayness, &rightUnionArray[offset], &leftUnionArray[offset]))
+                return false;
+        }
+    } else
+        return CompareStruct(leftNodeType, rightUnionArray, leftUnionArray);
+
+    return true;
+}
+
+//
+// The fold functions see if an operation on a constant can be done in place,
+// without generating run-time code.
+//
+// Returns the node to keep using, which may or may not be the node passed in.
+//
+
+TIntermTyped* TIntermConstantUnion::fold(TOperator op, TIntermTyped* constantNode, TInfoSink& infoSink)
+{
+    ConstantUnion *unionArray = getUnionArrayPointer();
+    size_t objectSize = getType().getObjectSize();
+
+    if (constantNode) {  // binary operations
+        TIntermConstantUnion *node = constantNode->getAsConstantUnion();
+        ConstantUnion *rightUnionArray = node->getUnionArrayPointer();
+        TType returnType = getType();
+
+        // for a case like float f = 1.2 + vec4(2,3,4,5);
+        if (constantNode->getType().getObjectSize() == 1 && objectSize > 1) {
+            rightUnionArray = new ConstantUnion[objectSize];
+            for (size_t i = 0; i < objectSize; ++i)
+                rightUnionArray[i] = *node->getUnionArrayPointer();
+            returnType = getType();
+        } else if (constantNode->getType().getObjectSize() > 1 && objectSize == 1) {
+            // for a case like float f = vec4(2,3,4,5) + 1.2;
+            unionArray = new ConstantUnion[constantNode->getType().getObjectSize()];
+            for (size_t i = 0; i < constantNode->getType().getObjectSize(); ++i)
+                unionArray[i] = *getUnionArrayPointer();
+            returnType = node->getType();
+            objectSize = constantNode->getType().getObjectSize();
+        }
+
+        ConstantUnion* tempConstArray = 0;
+        TIntermConstantUnion *tempNode;
+
+        bool boolNodeFlag = false;
+        switch(op) {
+            case EOpAdd:
+                tempConstArray = new ConstantUnion[objectSize];
+                {// support MSVC++6.0
+                    for (size_t i = 0; i < objectSize; i++)
+                        tempConstArray[i] = unionArray[i] + rightUnionArray[i];
+                }
+                break;
+            case EOpSub:
+                tempConstArray = new ConstantUnion[objectSize];
+                {// support MSVC++6.0
+                    for (size_t i = 0; i < objectSize; i++)
+                        tempConstArray[i] = unionArray[i] - rightUnionArray[i];
+                }
+                break;
+
+            case EOpMul:
+            case EOpVectorTimesScalar:
+            case EOpMatrixTimesScalar:
+                tempConstArray = new ConstantUnion[objectSize];
+                {// support MSVC++6.0
+                    for (size_t 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, getLine(), "Constant Folding cannot be done for matrix multiply");
+                    return 0;
+                }
+                {// support MSVC++6.0
+                    int size = getNominalSize();
+                    tempConstArray = new ConstantUnion[size*size];
+                    for (int row = 0; row < size; row++) {
+                        for (int column = 0; column < size; column++) {
+                            tempConstArray[size * column + row].setFConst(0.0f);
+                            for (int i = 0; i < size; i++) {
+                                tempConstArray[size * column + row].setFConst(tempConstArray[size * column + row].getFConst() + unionArray[i * size + row].getFConst() * (rightUnionArray[column * size + i].getFConst()));
+                            }
+                        }
+                    }
+                }
+                break;
+            case EOpDiv:
+                tempConstArray = new ConstantUnion[objectSize];
+                {// support MSVC++6.0
+                    for (size_t i = 0; i < objectSize; i++) {
+                        switch (getType().getBasicType()) {
+            case EbtFloat:
+                if (rightUnionArray[i] == 0.0f) {
+                    infoSink.info.message(EPrefixWarning, getLine(), "Divide by zero error during constant folding");
+                    tempConstArray[i].setFConst(unionArray[i].getFConst() < 0 ? -FLT_MAX : FLT_MAX);
+                } else
+                    tempConstArray[i].setFConst(unionArray[i].getFConst() / rightUnionArray[i].getFConst());
+                break;
+
+            case EbtInt:
+                if (rightUnionArray[i] == 0) {
+                    infoSink.info.message(EPrefixWarning, getLine(), "Divide by zero error during constant folding");
+                    tempConstArray[i].setIConst(INT_MAX);
+                } else
+                    tempConstArray[i].setIConst(unionArray[i].getIConst() / rightUnionArray[i].getIConst());
+                break;
+            default:
+                infoSink.info.message(EPrefixInternalError, getLine(), "Constant folding cannot be done for \"/\"");
+                return 0;
+                        }
+                    }
+                }
+                break;
+
+            case EOpMatrixTimesVector:
+                if (node->getBasicType() != EbtFloat) {
+                    infoSink.info.message(EPrefixInternalError, getLine(), "Constant Folding cannot be done for matrix times vector");
+                    return 0;
+                }
+                tempConstArray = new ConstantUnion[getNominalSize()];
+
+                {// support MSVC++6.0
+                    for (int size = getNominalSize(), i = 0; i < size; i++) {
+                        tempConstArray[i].setFConst(0.0f);
+                        for (int j = 0; j < size; j++) {
+                            tempConstArray[i].setFConst(tempConstArray[i].getFConst() + ((unionArray[j*size + i].getFConst()) * rightUnionArray[j].getFConst()));
+                        }
+                    }
+                }
+
+                tempNode = new TIntermConstantUnion(tempConstArray, node->getType());
+                tempNode->setLine(getLine());
+
+                return tempNode;
+
+            case EOpVectorTimesMatrix:
+                if (getType().getBasicType() != EbtFloat) {
+                    infoSink.info.message(EPrefixInternalError, getLine(), "Constant Folding cannot be done for vector times matrix");
+                    return 0;
+                }
+
+                tempConstArray = new ConstantUnion[getNominalSize()];
+                {// support MSVC++6.0
+                    for (int size = getNominalSize(), i = 0; i < size; i++) {
+                        tempConstArray[i].setFConst(0.0f);
+                        for (int j = 0; j < size; j++) {
+                            tempConstArray[i].setFConst(tempConstArray[i].getFConst() + ((unionArray[j].getFConst()) * rightUnionArray[i*size + j].getFConst()));
+                        }
+                    }
+                }
+                break;
+
+            case EOpLogicalAnd: // this code is written for possible future use, will not get executed currently
+                tempConstArray = new ConstantUnion[objectSize];
+                {// support MSVC++6.0
+                    for (size_t i = 0; i < objectSize; i++)
+                        tempConstArray[i] = unionArray[i] && rightUnionArray[i];
+                }
+                break;
+
+            case EOpLogicalOr: // this code is written for possible future use, will not get executed currently
+                tempConstArray = new ConstantUnion[objectSize];
+                {// support MSVC++6.0
+                    for (size_t i = 0; i < objectSize; i++)
+                        tempConstArray[i] = unionArray[i] || rightUnionArray[i];
+                }
+                break;
+
+            case EOpLogicalXor:
+                tempConstArray = new ConstantUnion[objectSize];
+                {// support MSVC++6.0
+                    for (size_t i = 0; i < objectSize; i++)
+                        switch (getType().getBasicType()) {
+            case EbtBool: tempConstArray[i].setBConst((unionArray[i] == rightUnionArray[i]) ? false : true); break;
+            default: assert(false && "Default missing");
+                    }
+                }
+                break;
+
+            case EOpLessThan:
+                assert(objectSize == 1);
+                tempConstArray = new ConstantUnion[1];
+                tempConstArray->setBConst(*unionArray < *rightUnionArray);
+                returnType = TType(EbtBool, EbpUndefined, EvqConst);
+                break;
+            case EOpGreaterThan:
+                assert(objectSize == 1);
+                tempConstArray = new ConstantUnion[1];
+                tempConstArray->setBConst(*unionArray > *rightUnionArray);
+                returnType = TType(EbtBool, EbpUndefined, EvqConst);
+                break;
+            case EOpLessThanEqual:
+                {
+                    assert(objectSize == 1);
+                    ConstantUnion constant;
+                    constant.setBConst(*unionArray > *rightUnionArray);
+                    tempConstArray = new ConstantUnion[1];
+                    tempConstArray->setBConst(!constant.getBConst());
+                    returnType = TType(EbtBool, EbpUndefined, EvqConst);
+                    break;
+                }
+            case EOpGreaterThanEqual:
+                {
+                    assert(objectSize == 1);
+                    ConstantUnion constant;
+                    constant.setBConst(*unionArray < *rightUnionArray);
+                    tempConstArray = new ConstantUnion[1];
+                    tempConstArray->setBConst(!constant.getBConst());
+                    returnType = TType(EbtBool, EbpUndefined, EvqConst);
+                    break;
+                }
+
+            case EOpEqual:
+                if (getType().getBasicType() == EbtStruct) {
+                    if (!CompareStructure(node->getType(), node->getUnionArrayPointer(), unionArray))
+                        boolNodeFlag = true;
+                } else {
+                    for (size_t i = 0; i < objectSize; i++) {
+                        if (unionArray[i] != rightUnionArray[i]) {
+                            boolNodeFlag = true;
+                            break;  // break out of for loop
+                        }
+                    }
+                }
+
+                tempConstArray = new ConstantUnion[1];
+                if (!boolNodeFlag) {
+                    tempConstArray->setBConst(true);
+                }
+                else {
+                    tempConstArray->setBConst(false);
+                }
+
+                tempNode = new TIntermConstantUnion(tempConstArray, TType(EbtBool, EbpUndefined, EvqConst));
+                tempNode->setLine(getLine());
+
+                return tempNode;
+
+            case EOpNotEqual:
+                if (getType().getBasicType() == EbtStruct) {
+                    if (CompareStructure(node->getType(), node->getUnionArrayPointer(), unionArray))
+                        boolNodeFlag = true;
+                } else {
+                    for (size_t i = 0; i < objectSize; i++) {
+                        if (unionArray[i] == rightUnionArray[i]) {
+                            boolNodeFlag = true;
+                            break;  // break out of for loop
+                        }
+                    }
+                }
+
+                tempConstArray = new ConstantUnion[1];
+                if (!boolNodeFlag) {
+                    tempConstArray->setBConst(true);
+                }
+                else {
+                    tempConstArray->setBConst(false);
+                }
+
+                tempNode = new TIntermConstantUnion(tempConstArray, TType(EbtBool, EbpUndefined, EvqConst));
+                tempNode->setLine(getLine());
+
+                return tempNode;
+
+            default:
+                infoSink.info.message(EPrefixInternalError, getLine(), "Invalid operator for constant folding");
+                return 0;
+        }
+        tempNode = new TIntermConstantUnion(tempConstArray, returnType);
+        tempNode->setLine(getLine());
+
+        return tempNode;
+    } else {
+        //
+        // Do unary operations
+        //
+        TIntermConstantUnion *newNode = 0;
+        ConstantUnion* tempConstArray = new ConstantUnion[objectSize];
+        for (size_t 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, getLine(), "Unary operation not folded into constant");
+                            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, getLine(), "Unary operation not folded into constant");
+                            return 0;
+                    }
+                    break;
+                default:
+                    return 0;
+            }
+        }
+        newNode = new TIntermConstantUnion(tempConstArray, getType());
+        newNode->setLine(getLine());
+        return newNode;
+    }
+}
+
+TIntermTyped* TIntermediate::promoteConstantUnion(TBasicType promoteTo, TIntermConstantUnion* node)
+{
+    size_t size = node->getType().getObjectSize();
+
+    ConstantUnion *leftUnionArray = new ConstantUnion[size];
+
+    for (size_t i = 0; i < size; i++) {
+
+        switch (promoteTo) {
+            case EbtFloat:
+                switch (node->getType().getBasicType()) {
+                    case EbtInt:
+                        leftUnionArray[i].setFConst(static_cast<float>(node->getIConst(i)));
+                        break;
+                    case EbtBool:
+                        leftUnionArray[i].setFConst(static_cast<float>(node->getBConst(i)));
+                        break;
+                    case EbtFloat:
+                        leftUnionArray[i].setFConst(static_cast<float>(node->getFConst(i)));
+                        break;
+                    default:
+                        infoSink.info.message(EPrefixInternalError, node->getLine(), "Cannot promote");
+                        return 0;
+                }
+                break;
+            case EbtInt:
+                switch (node->getType().getBasicType()) {
+                    case EbtInt:
+                        leftUnionArray[i].setIConst(static_cast<int>(node->getIConst(i)));
+                        break;
+                    case EbtBool:
+                        leftUnionArray[i].setIConst(static_cast<int>(node->getBConst(i)));
+                        break;
+                    case EbtFloat:
+                        leftUnionArray[i].setIConst(static_cast<int>(node->getFConst(i)));
+                        break;
+                    default:
+                        infoSink.info.message(EPrefixInternalError, node->getLine(), "Cannot promote");
+                        return 0;
+                }
+                break;
+            case EbtBool:
+                switch (node->getType().getBasicType()) {
+                    case EbtInt:
+                        leftUnionArray[i].setBConst(node->getIConst(i) != 0);
+                        break;
+                    case EbtBool:
+                        leftUnionArray[i].setBConst(node->getBConst(i));
+                        break;
+                    case EbtFloat:
+                        leftUnionArray[i].setBConst(node->getFConst(i) != 0.0f);
+                        break;
+                    default:
+                        infoSink.info.message(EPrefixInternalError, node->getLine(), "Cannot promote");
+                        return 0;
+                }
+
+                break;
+            default:
+                infoSink.info.message(EPrefixInternalError, node->getLine(), "Incorrect data type found");
+                return 0;
+        }
+
+    }
+
+    const TType& t = node->getType();
+
+    return addConstantUnion(leftUnionArray, TType(promoteTo, t.getPrecision(), t.getQualifier(), t.getNominalSize(), t.isMatrix(), t.isArray()), node->getLine());
+}
+
+// static
+TString TIntermTraverser::hash(const TString& name, ShHashFunction64 hashFunction)
+{
+    if (hashFunction == NULL || name.empty())
+        return name;
+    khronos_uint64_t number = (*hashFunction)(name.c_str(), name.length());
+    TStringStream stream;
+    stream << HASHED_NAME_PREFIX << std::hex << number;
+    TString hashedName = stream.str();
+    return hashedName;
+}
diff --git a/Source/ThirdParty/ANGLE/src/compiler/translator/MMap.h b/Source/ThirdParty/ANGLE/src/compiler/translator/MMap.h
new file mode 100644 (file)
index 0000000..a308671
--- /dev/null
@@ -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/Source/ThirdParty/ANGLE/src/compiler/translator/MapLongVariableNames.cpp b/Source/ThirdParty/ANGLE/src/compiler/translator/MapLongVariableNames.cpp
new file mode 100644 (file)
index 0000000..ef629c2
--- /dev/null
@@ -0,0 +1,115 @@
+//
+// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "compiler/translator/MapLongVariableNames.h"
+
+namespace {
+
+TString mapLongName(size_t id, const TString& name, bool isGlobal)
+{
+    ASSERT(name.size() > MAX_SHORTENED_IDENTIFIER_SIZE);
+    TStringStream stream;
+    stream << "webgl_";
+    if (isGlobal)
+        stream << "g";
+    stream << id;
+    if (name[0] != '_')
+        stream << "_";
+    stream << name.substr(0, MAX_SHORTENED_IDENTIFIER_SIZE - stream.str().size());
+    return stream.str();
+}
+
+LongNameMap* gLongNameMapInstance = NULL;
+
+}  // anonymous namespace
+
+LongNameMap::LongNameMap()
+    : refCount(0)
+{
+}
+
+LongNameMap::~LongNameMap()
+{
+}
+
+// static
+LongNameMap* LongNameMap::GetInstance()
+{
+    if (gLongNameMapInstance == NULL)
+        gLongNameMapInstance = new LongNameMap;
+    gLongNameMapInstance->refCount++;
+    return gLongNameMapInstance;
+}
+
+void LongNameMap::Release()
+{
+    ASSERT(gLongNameMapInstance == this);
+    ASSERT(refCount > 0);
+    refCount--;
+    if (refCount == 0) {
+        delete gLongNameMapInstance;
+        gLongNameMapInstance = NULL;
+    }
+}
+
+const char* LongNameMap::Find(const char* originalName) const
+{
+    std::map<std::string, std::string>::const_iterator it = mLongNameMap.find(
+        originalName);
+    if (it != mLongNameMap.end())
+        return (*it).second.c_str();
+    return NULL;
+}
+
+void LongNameMap::Insert(const char* originalName, const char* mappedName)
+{
+    mLongNameMap.insert(std::map<std::string, std::string>::value_type(
+        originalName, mappedName));
+}
+
+size_t LongNameMap::Size() const
+{
+    return mLongNameMap.size();
+}
+
+MapLongVariableNames::MapLongVariableNames(LongNameMap* globalMap)
+{
+    ASSERT(globalMap);
+    mGlobalMap = globalMap;
+}
+
+void MapLongVariableNames::visitSymbol(TIntermSymbol* symbol)
+{
+    ASSERT(symbol != NULL);
+    if (symbol->getSymbol().size() > MAX_SHORTENED_IDENTIFIER_SIZE) {
+        switch (symbol->getQualifier()) {
+          case EvqVaryingIn:
+          case EvqVaryingOut:
+          case EvqInvariantVaryingIn:
+          case EvqInvariantVaryingOut:
+          case EvqUniform:
+            symbol->setSymbol(
+                mapGlobalLongName(symbol->getSymbol()));
+            break;
+          default:
+            symbol->setSymbol(
+                mapLongName(symbol->getId(), symbol->getSymbol(), false));
+            break;
+        };
+    }
+}
+
+TString MapLongVariableNames::mapGlobalLongName(const TString& name)
+{
+    ASSERT(mGlobalMap);
+    const char* mappedName = mGlobalMap->Find(name.c_str());
+    if (mappedName != NULL)
+        return mappedName;
+    size_t id = mGlobalMap->Size();
+    TString rt = mapLongName(id, name, true);
+    mGlobalMap->Insert(name.c_str(), rt.c_str());
+    return rt;
+}
diff --git a/Source/ThirdParty/ANGLE/src/compiler/translator/MapLongVariableNames.h b/Source/ThirdParty/ANGLE/src/compiler/translator/MapLongVariableNames.h
new file mode 100644 (file)
index 0000000..3b085a3
--- /dev/null
@@ -0,0 +1,58 @@
+//
+// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#ifndef COMPILER_MAP_LONG_VARIABLE_NAMES_H_
+#define COMPILER_MAP_LONG_VARIABLE_NAMES_H_
+
+#include "GLSLANG/ShaderLang.h"
+
+#include "compiler/translator/intermediate.h"
+#include "compiler/translator/VariableInfo.h"
+
+// This size does not include '\0' in the end.
+#define MAX_SHORTENED_IDENTIFIER_SIZE 32
+
+// This is a ref-counted singleton. GetInstance() returns a pointer to the
+// singleton, and after use, call Release(). GetInstance() and Release() should
+// be paired.
+class LongNameMap {
+public:
+    static LongNameMap* GetInstance();
+    void Release();
+
+    // Return the mapped name if <originalName, mappedName> is in the map;
+    // otherwise, return NULL.
+    const char* Find(const char* originalName) const;
+
+    // Insert a pair into the map.
+    void Insert(const char* originalName, const char* mappedName);
+
+    // Return the number of entries in the map.
+    size_t Size() const;
+
+private:
+    LongNameMap();
+    ~LongNameMap();
+
+    size_t refCount;
+    std::map<std::string, std::string> mLongNameMap;
+};
+
+// Traverses intermediate tree to map attributes and uniforms names that are
+// longer than MAX_SHORTENED_IDENTIFIER_SIZE to MAX_SHORTENED_IDENTIFIER_SIZE.
+class MapLongVariableNames : public TIntermTraverser {
+public:
+    MapLongVariableNames(LongNameMap* globalMap);
+
+    virtual void visitSymbol(TIntermSymbol*);
+
+private:
+    TString mapGlobalLongName(const TString& name);
+
+    LongNameMap* mGlobalMap;
+};
+
+#endif  // COMPILER_MAP_LONG_VARIABLE_NAMES_H_
diff --git a/Source/ThirdParty/ANGLE/src/compiler/translator/NodeSearch.h b/Source/ThirdParty/ANGLE/src/compiler/translator/NodeSearch.h
new file mode 100644 (file)
index 0000000..b58c7ec
--- /dev/null
@@ -0,0 +1,80 @@
+//
+// Copyright (c) 2002-2013 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.
+//
+// NodeSearch.h: Utilities for searching translator node graphs
+//
+
+#ifndef TRANSLATOR_NODESEARCH_H_
+#define TRANSLATOR_NODESEARCH_H_
+
+#include "compiler/translator/intermediate.h"
+
+namespace sh
+{
+
+template <class Parent>
+class NodeSearchTraverser : public TIntermTraverser
+{
+  public:
+    NodeSearchTraverser()
+        : mFound(false)
+    {}
+
+    bool found() const { return mFound; }
+
+    static bool search(TIntermNode *node)
+    {
+        Parent searchTraverser;
+        node->traverse(&searchTraverser);
+        return searchTraverser.found();
+    }
+
+  protected:
+    bool mFound;
+};
+
+class FindDiscard : public NodeSearchTraverser<FindDiscard>
+{
+  public:
+    virtual bool visitBranch(Visit visit, TIntermBranch *node)
+    {
+        switch (node->getFlowOp())
+        {
+          case EOpKill:
+            mFound = true;
+            break;
+
+          default: break;
+        }
+
+        return !mFound;
+    }
+};
+
+class FindSideEffectRewriting : public NodeSearchTraverser<FindSideEffectRewriting>
+{
+  public:
+    virtual bool visitBinary(Visit visit, TIntermBinary *node)
+    {
+        switch (node->getOp())
+        {
+          case EOpLogicalOr:
+          case EOpLogicalAnd:
+            if (node->getRight()->hasSideEffects())
+            {
+                mFound = true;
+            }
+            break;
+
+          default: break;
+        }
+
+        return !mFound;
+    }
+};
+
+}
+
+#endif // TRANSLATOR_NODESEARCH_H_
diff --git a/Source/ThirdParty/ANGLE/src/compiler/translator/OutputESSL.cpp b/Source/ThirdParty/ANGLE/src/compiler/translator/OutputESSL.cpp
new file mode 100644 (file)
index 0000000..8367412
--- /dev/null
@@ -0,0 +1,26 @@
+//
+// Copyright (c) 2002-2011 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "compiler/translator/OutputESSL.h"
+
+TOutputESSL::TOutputESSL(TInfoSinkBase& objSink,
+                         ShArrayIndexClampingStrategy clampingStrategy,
+                         ShHashFunction64 hashFunction,
+                         NameMap& nameMap,
+                         TSymbolTable& symbolTable)
+    : TOutputGLSLBase(objSink, clampingStrategy, hashFunction, nameMap, symbolTable)
+{
+}
+
+bool TOutputESSL::writeVariablePrecision(TPrecision precision)
+{
+    if (precision == EbpUndefined)
+        return false;
+
+    TInfoSinkBase& out = objSink();
+    out << getPrecisionString(precision);
+    return true;
+}
diff --git a/Source/ThirdParty/ANGLE/src/compiler/translator/OutputESSL.h b/Source/ThirdParty/ANGLE/src/compiler/translator/OutputESSL.h
new file mode 100644 (file)
index 0000000..2f02979
--- /dev/null
@@ -0,0 +1,25 @@
+//
+// Copyright (c) 2002-2011 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#ifndef CROSSCOMPILERGLSL_OUTPUTESSL_H_
+#define CROSSCOMPILERGLSL_OUTPUTESSL_H_
+
+#include "compiler/translator/OutputGLSLBase.h"
+
+class TOutputESSL : public TOutputGLSLBase
+{
+public:
+    TOutputESSL(TInfoSinkBase& objSink,
+                ShArrayIndexClampingStrategy clampingStrategy,
+                ShHashFunction64 hashFunction,
+                NameMap& nameMap,
+                TSymbolTable& symbolTable);
+
+protected:
+    virtual bool writeVariablePrecision(TPrecision precision);
+};
+
+#endif  // CROSSCOMPILERGLSL_OUTPUTESSL_H_
diff --git a/Source/ThirdParty/ANGLE/src/compiler/translator/OutputGLSL.cpp b/Source/ThirdParty/ANGLE/src/compiler/translator/OutputGLSL.cpp
new file mode 100644 (file)
index 0000000..5589560
--- /dev/null
@@ -0,0 +1,35 @@
+//
+// Copyright (c) 2002-2011 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "compiler/translator/OutputGLSL.h"
+
+TOutputGLSL::TOutputGLSL(TInfoSinkBase& objSink,
+                         ShArrayIndexClampingStrategy clampingStrategy,
+                         ShHashFunction64 hashFunction,
+                         NameMap& nameMap,
+                         TSymbolTable& symbolTable)
+    : TOutputGLSLBase(objSink, clampingStrategy, hashFunction, nameMap, symbolTable)
+{
+}
+
+bool TOutputGLSL::writeVariablePrecision(TPrecision)
+{
+    return false;
+}
+
+void TOutputGLSL::visitSymbol(TIntermSymbol* node)
+{
+    TInfoSinkBase& out = objSink();
+
+    if (node->getSymbol() == "gl_FragDepthEXT")
+    {
+        out << "gl_FragDepth";
+    }
+    else
+    {
+        TOutputGLSLBase::visitSymbol(node);
+    }
+}
diff --git a/Source/ThirdParty/ANGLE/src/compiler/translator/OutputGLSL.h b/Source/ThirdParty/ANGLE/src/compiler/translator/OutputGLSL.h
new file mode 100644 (file)
index 0000000..e1f114d
--- /dev/null
@@ -0,0 +1,26 @@
+//
+// Copyright (c) 2002-2011 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#ifndef CROSSCOMPILERGLSL_OUTPUTGLSL_H_
+#define CROSSCOMPILERGLSL_OUTPUTGLSL_H_
+
+#include "compiler/translator/OutputGLSLBase.h"
+
+class TOutputGLSL : public TOutputGLSLBase
+{
+public:
+    TOutputGLSL(TInfoSinkBase& objSink,
+                ShArrayIndexClampingStrategy clampingStrategy,
+                ShHashFunction64 hashFunction,
+                NameMap& nameMap,
+                TSymbolTable& symbolTable);
+
+protected:
+    virtual bool writeVariablePrecision(TPrecision);
+    virtual void visitSymbol(TIntermSymbol* node);
+};
+
+#endif  // CROSSCOMPILERGLSL_OUTPUTGLSL_H_
diff --git a/Source/ThirdParty/ANGLE/src/compiler/translator/OutputGLSLBase.cpp b/Source/ThirdParty/ANGLE/src/compiler/translator/OutputGLSLBase.cpp
new file mode 100644 (file)
index 0000000..f2f0a3d
--- /dev/null
@@ -0,0 +1,817 @@
+//
+// Copyright (c) 2002-2011 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "compiler/translator/OutputGLSLBase.h"
+#include "compiler/translator/compilerdebug.h"
+
+#include <cfloat>
+
+namespace
+{
+TString arrayBrackets(const TType& type)
+{
+    ASSERT(type.isArray());
+    TInfoSinkBase out;
+    out << "[" << type.getArraySize() << "]";
+    return TString(out.c_str());
+}
+
+bool isSingleStatement(TIntermNode* node) {
+    if (const TIntermAggregate* aggregate = node->getAsAggregate())
+    {
+        return (aggregate->getOp() != EOpFunction) &&
+               (aggregate->getOp() != EOpSequence);
+    }
+    else if (const TIntermSelection* selection = node->getAsSelectionNode())
+    {
+        // Ternary operators are usually part of an assignment operator.
+        // This handles those rare cases in which they are all by themselves.
+        return selection->usesTernaryOperator();
+    }
+    else if (node->getAsLoopNode())
+    {
+        return false;
+    }
+    return true;
+}
+}  // namespace
+
+TOutputGLSLBase::TOutputGLSLBase(TInfoSinkBase& objSink,
+                                 ShArrayIndexClampingStrategy clampingStrategy,
+                                 ShHashFunction64 hashFunction,
+                                 NameMap& nameMap,
+                                 TSymbolTable& symbolTable)
+    : TIntermTraverser(true, true, true),
+      mObjSink(objSink),
+      mDeclaringVariables(false),
+      mClampingStrategy(clampingStrategy),
+      mHashFunction(hashFunction),
+      mNameMap(nameMap),
+      mSymbolTable(symbolTable)
+{
+}
+
+void TOutputGLSLBase::writeTriplet(Visit visit, const char* preStr, const char* inStr, const char* postStr)
+{
+    TInfoSinkBase& out = objSink();
+    if (visit == PreVisit && preStr)
+    {
+        out << preStr;
+    }
+    else if (visit == InVisit && inStr)
+    {
+        out << inStr;
+    }
+    else if (visit == PostVisit && postStr)
+    {
+        out << postStr;
+    }
+}
+
+void TOutputGLSLBase::writeVariableType(const TType& type)
+{
+    TInfoSinkBase& out = objSink();
+    TQualifier qualifier = type.getQualifier();
+    // TODO(alokp): Validate qualifier for variable declarations.
+    if ((qualifier != EvqTemporary) && (qualifier != EvqGlobal))
+        out << type.getQualifierString() << " ";
+    // Declare the struct if we have not done so already.
+    if ((type.getBasicType() == EbtStruct) && !structDeclared(type.getStruct()))
+    {
+        declareStruct(type.getStruct());
+    }
+    else
+    {
+        if (writeVariablePrecision(type.getPrecision()))
+            out << " ";
+        out << getTypeName(type);
+    }
+}
+
+void TOutputGLSLBase::writeFunctionParameters(const TIntermSequence& args)
+{
+    TInfoSinkBase& out = objSink();
+    for (TIntermSequence::const_iterator iter = args.begin();
+         iter != args.end(); ++iter)
+    {
+        const TIntermSymbol* arg = (*iter)->getAsSymbolNode();
+        ASSERT(arg != NULL);
+
+        const TType& type = arg->getType();
+        writeVariableType(type);
+
+        const TString& name = arg->getSymbol();
+        if (!name.empty())
+            out << " " << hashName(name);
+        if (type.isArray())
+            out << arrayBrackets(type);
+
+        // Put a comma if this is not the last argument.
+        if (iter != args.end() - 1)
+            out << ", ";
+    }
+}
+
+const ConstantUnion* TOutputGLSLBase::writeConstantUnion(const TType& type,
+                                                         const ConstantUnion* pConstUnion)
+{
+    TInfoSinkBase& out = objSink();
+
+    if (type.getBasicType() == EbtStruct)
+    {
+        const TStructure* structure = type.getStruct();
+        out << hashName(structure->name()) << "(";
+
+        const TFieldList& fields = structure->fields();
+        for (size_t i = 0; i < fields.size(); ++i)
+        {
+            const TType* fieldType = fields[i]->type();
+            ASSERT(fieldType != NULL);
+            pConstUnion = writeConstantUnion(*fieldType, pConstUnion);
+            if (i != fields.size() - 1) out << ", ";
+        }
+        out << ")";
+    }
+    else
+    {
+        size_t size = type.getObjectSize();
+        bool writeType = size > 1;
+        if (writeType) out << getTypeName(type) << "(";
+        for (size_t i = 0; i < size; ++i, ++pConstUnion)
+        {
+            switch (pConstUnion->getType())
+            {
+                case EbtFloat: out << std::min(FLT_MAX, std::max(-FLT_MAX, pConstUnion->getFConst())); break;
+                case EbtInt: out << pConstUnion->getIConst(); break;
+                case EbtBool: out << pConstUnion->getBConst(); break;
+                default: UNREACHABLE();
+            }
+            if (i != size - 1) out << ", ";
+        }
+        if (writeType) out << ")";
+    }
+    return pConstUnion;
+}
+
+void TOutputGLSLBase::visitSymbol(TIntermSymbol* node)
+{
+    TInfoSinkBase& out = objSink();
+    if (mLoopUnroll.NeedsToReplaceSymbolWithValue(node))
+        out << mLoopUnroll.GetLoopIndexValue(node);
+    else
+        out << hashVariableName(node->getSymbol());
+
+    if (mDeclaringVariables && node->getType().isArray())
+        out << arrayBrackets(node->getType());
+}
+
+void TOutputGLSLBase::visitConstantUnion(TIntermConstantUnion* node)
+{
+    writeConstantUnion(node->getType(), node->getUnionArrayPointer());
+}
+
+bool TOutputGLSLBase::visitBinary(Visit visit, TIntermBinary* node)
+{
+    bool visitChildren = true;
+    TInfoSinkBase& out = objSink();
+    switch (node->getOp())
+    {
+        case EOpInitialize:
+            if (visit == InVisit)
+            {
+                out << " = ";
+                // RHS of initialize is not being declared.
+                mDeclaringVariables = false;
+            }
+            break;
+        case EOpAssign: writeTriplet(visit, "(", " = ", ")"); break;
+        case EOpAddAssign: writeTriplet(visit, "(", " += ", ")"); break;
+        case EOpSubAssign: writeTriplet(visit, "(", " -= ", ")"); break;
+        case EOpDivAssign: writeTriplet(visit, "(", " /= ", ")"); break;
+        // Notice the fall-through.
+        case EOpMulAssign: 
+        case EOpVectorTimesMatrixAssign:
+        case EOpVectorTimesScalarAssign:
+        case EOpMatrixTimesScalarAssign:
+        case EOpMatrixTimesMatrixAssign:
+            writeTriplet(visit, "(", " *= ", ")");
+            break;
+
+        case EOpIndexDirect:
+            writeTriplet(visit, NULL, "[", "]");
+            break;
+        case EOpIndexIndirect:
+            if (node->getAddIndexClamp())
+            {
+                if (visit == InVisit)
+                {
+                    if (mClampingStrategy == SH_CLAMP_WITH_CLAMP_INTRINSIC) {
+                        out << "[int(clamp(float(";
+                    } else {
+                        out << "[webgl_int_clamp(";
+                    }
+                }
+                else if (visit == PostVisit)
+                {
+                    int maxSize;
+                    TIntermTyped *left = node->getLeft();
+                    TType leftType = left->getType();
+
+                    if (left->isArray())
+                    {
+                        // The shader will fail validation if the array length is not > 0.
+                        maxSize = leftType.getArraySize() - 1;
+                    }
+                    else
+                    {
+                        maxSize = leftType.getNominalSize() - 1;
+                    }
+
+                    if (mClampingStrategy == SH_CLAMP_WITH_CLAMP_INTRINSIC) {
+                        out << "), 0.0, float(" << maxSize << ")))]";
+                    } else {
+                        out << ", 0, " << maxSize << ")]";
+                    }
+                }
+            }
+            else
+            {
+                writeTriplet(visit, NULL, "[", "]");
+            }
+            break;
+        case EOpIndexDirectStruct:
+            if (visit == InVisit)
+            {
+                // Here we are writing out "foo.bar", where "foo" is struct
+                // and "bar" is field. In AST, it is represented as a binary
+                // node, where left child represents "foo" and right child "bar".
+                // The node itself represents ".". The struct field "bar" is
+                // actually stored as an index into TStructure::fields.
+                out << ".";
+                const TStructure* structure = node->getLeft()->getType().getStruct();
+                const TIntermConstantUnion* index = node->getRight()->getAsConstantUnion();
+                const TField* field = structure->fields()[index->getIConst(0)];
+
+                TString fieldName = field->name();
+                if (!mSymbolTable.findBuiltIn(structure->name()))
+                    fieldName = hashName(fieldName);
+
+                out << fieldName;
+                visitChildren = false;
+            }
+            break;
+        case EOpVectorSwizzle:
+            if (visit == InVisit)
+            {
+                out << ".";
+                TIntermAggregate* rightChild = node->getRight()->getAsAggregate();
+                TIntermSequence& sequence = rightChild->getSequence();
+                for (TIntermSequence::iterator sit = sequence.begin(); sit != sequence.end(); ++sit)
+                {
+                    TIntermConstantUnion* element = (*sit)->getAsConstantUnion();
+                    ASSERT(element->getBasicType() == EbtInt);
+                    ASSERT(element->getNominalSize() == 1);
+                    const ConstantUnion& data = element->getUnionArrayPointer()[0];
+                    ASSERT(data.getType() == EbtInt);
+                    switch (data.getIConst())
+                    {
+                        case 0: out << "x"; break;
+                        case 1: out << "y"; break;
+                        case 2: out << "z"; break;
+                        case 3: out << "w"; break;
+                        default: UNREACHABLE(); break;
+                    }
+                }
+                visitChildren = false;
+            }
+            break;
+
+        case EOpAdd: writeTriplet(visit, "(", " + ", ")"); break;
+        case EOpSub: writeTriplet(visit, "(", " - ", ")"); break;
+        case EOpMul: writeTriplet(visit, "(", " * ", ")"); break;
+        case EOpDiv: writeTriplet(visit, "(", " / ", ")"); break;
+        case EOpMod: UNIMPLEMENTED(); break;
+        case EOpEqual: writeTriplet(visit, "(", " == ", ")"); break;
+        case EOpNotEqual: writeTriplet(visit, "(", " != ", ")"); break;
+        case EOpLessThan: writeTriplet(visit, "(", " < ", ")"); break;
+        case EOpGreaterThan: writeTriplet(visit, "(", " > ", ")"); break;
+        case EOpLessThanEqual: writeTriplet(visit, "(", " <= ", ")"); break;
+        case EOpGreaterThanEqual: writeTriplet(visit, "(", " >= ", ")"); break;
+
+        // Notice the fall-through.
+        case EOpVectorTimesScalar:
+        case EOpVectorTimesMatrix:
+        case EOpMatrixTimesVector:
+        case EOpMatrixTimesScalar:
+        case EOpMatrixTimesMatrix:
+            writeTriplet(visit, "(", " * ", ")");
+            break;
+
+        case EOpLogicalOr: writeTriplet(visit, "(", " || ", ")"); break;
+        case EOpLogicalXor: writeTriplet(visit, "(", " ^^ ", ")"); break;
+        case EOpLogicalAnd: writeTriplet(visit, "(", " && ", ")"); break;
+        default: UNREACHABLE(); break;
+    }
+
+    return visitChildren;
+}
+
+bool TOutputGLSLBase::visitUnary(Visit visit, TIntermUnary* node)
+{
+    TString preString;
+    TString postString = ")";
+
+    switch (node->getOp())
+    {
+        case EOpNegative: preString = "(-"; break;
+        case EOpVectorLogicalNot: preString = "not("; break;
+        case EOpLogicalNot: preString = "(!"; break;
+
+        case EOpPostIncrement: preString = "("; postString = "++)"; break;
+        case EOpPostDecrement: preString = "("; postString = "--)"; break;
+        case EOpPreIncrement: preString = "(++"; break;
+        case EOpPreDecrement: preString = "(--"; break;
+
+        case EOpConvIntToBool:
+        case EOpConvFloatToBool:
+            switch (node->getOperand()->getType().getNominalSize())
+            {
+                case 1: preString =  "bool(";  break;
+                case 2: preString = "bvec2("; break;
+                case 3: preString = "bvec3("; break;
+                case 4: preString = "bvec4("; break;
+                default: UNREACHABLE();
+            }
+            break;
+        case EOpConvBoolToFloat:
+        case EOpConvIntToFloat:
+            switch (node->getOperand()->getType().getNominalSize())
+            {
+                case 1: preString = "float(";  break;
+                case 2: preString = "vec2("; break;
+                case 3: preString = "vec3("; break;
+                case 4: preString = "vec4("; break;
+                default: UNREACHABLE();
+            }
+            break;
+        case EOpConvFloatToInt:
+        case EOpConvBoolToInt:
+            switch (node->getOperand()->getType().getNominalSize())
+            {
+                case 1: preString = "int(";  break;
+                case 2: preString = "ivec2("; break;
+                case 3: preString = "ivec3("; break;
+                case 4: preString = "ivec4("; break;
+                default: UNREACHABLE();
+            }
+            break;
+
+        case EOpRadians: preString = "radians("; break;
+        case EOpDegrees: preString = "degrees("; break;
+        case EOpSin: preString = "sin("; break;
+        case EOpCos: preString = "cos("; break;
+        case EOpTan: preString = "tan("; break;
+        case EOpAsin: preString = "asin("; break;
+        case EOpAcos: preString = "acos("; break;
+        case EOpAtan: preString = "atan("; break;
+
+        case EOpExp: preString = "exp("; break;
+        case EOpLog: preString = "log("; break;
+        case EOpExp2: preString = "exp2("; break;
+        case EOpLog2: preString = "log2("; break;
+        case EOpSqrt: preString = "sqrt("; break;
+        case EOpInverseSqrt: preString = "inversesqrt("; break;
+
+        case EOpAbs: preString = "abs("; break;
+        case EOpSign: preString = "sign("; break;
+        case EOpFloor: preString = "floor("; break;
+        case EOpCeil: preString = "ceil("; break;
+        case EOpFract: preString = "fract("; break;
+
+        case EOpLength: preString = "length("; break;
+        case EOpNormalize: preString = "normalize("; break;
+
+        case EOpDFdx: preString = "dFdx("; break;
+        case EOpDFdy: preString = "dFdy("; break;
+        case EOpFwidth: preString = "fwidth("; break;
+
+        case EOpAny: preString = "any("; break;
+        case EOpAll: preString = "all("; break;
+
+        default: UNREACHABLE(); break;
+    }
+
+    if (visit == PreVisit && node->getUseEmulatedFunction())
+        preString = BuiltInFunctionEmulator::GetEmulatedFunctionName(preString);
+    writeTriplet(visit, preString.c_str(), NULL, postString.c_str());
+
+    return true;
+}
+
+bool TOutputGLSLBase::visitSelection(Visit visit, TIntermSelection* node)
+{
+    TInfoSinkBase& out = objSink();
+
+    if (node->usesTernaryOperator())
+    {
+        // Notice two brackets at the beginning and end. The outer ones
+        // encapsulate the whole ternary expression. This preserves the
+        // order of precedence when ternary expressions are used in a
+        // compound expression, i.e., c = 2 * (a < b ? 1 : 2).
+        out << "((";
+        node->getCondition()->traverse(this);
+        out << ") ? (";
+        node->getTrueBlock()->traverse(this);
+        out << ") : (";
+        node->getFalseBlock()->traverse(this);
+        out << "))";
+    }
+    else
+    {
+        out << "if (";
+        node->getCondition()->traverse(this);
+        out << ")\n";
+
+        incrementDepth(node);
+        visitCodeBlock(node->getTrueBlock());
+
+        if (node->getFalseBlock())
+        {
+            out << "else\n";
+            visitCodeBlock(node->getFalseBlock());
+        }
+        decrementDepth();
+    }
+    return false;
+}
+
+bool TOutputGLSLBase::visitAggregate(Visit visit, TIntermAggregate* node)
+{
+    bool visitChildren = true;
+    TInfoSinkBase& out = objSink();
+    TString preString;
+    bool delayedWrite = false;
+    switch (node->getOp())
+    {
+        case EOpSequence: {
+            // Scope the sequences except when at the global scope.
+            if (depth > 0) out << "{\n";
+
+            incrementDepth(node);
+            const TIntermSequence& sequence = node->getSequence();
+            for (TIntermSequence::const_iterator iter = sequence.begin();
+                 iter != sequence.end(); ++iter)
+            {
+                TIntermNode* node = *iter;
+                ASSERT(node != NULL);
+                node->traverse(this);
+
+                if (isSingleStatement(node))
+                    out << ";\n";
+            }
+            decrementDepth();
+
+            // Scope the sequences except when at the global scope.
+            if (depth > 0) out << "}\n";
+            visitChildren = false;
+            break;
+        }
+        case EOpPrototype: {
+            // Function declaration.
+            ASSERT(visit == PreVisit);
+            writeVariableType(node->getType());
+            out << " " << hashName(node->getName());
+
+            out << "(";
+            writeFunctionParameters(node->getSequence());
+            out << ")";
+
+            visitChildren = false;
+            break;
+        }
+        case EOpFunction: {
+            // Function definition.
+            ASSERT(visit == PreVisit);
+            writeVariableType(node->getType());
+            out << " " << hashFunctionName(node->getName());
+
+            incrementDepth(node);
+            // Function definition node contains one or two children nodes
+            // representing function parameters and function body. The latter
+            // is not present in case of empty function bodies.
+            const TIntermSequence& sequence = node->getSequence();
+            ASSERT((sequence.size() == 1) || (sequence.size() == 2));
+            TIntermSequence::const_iterator seqIter = sequence.begin();
+
+            // Traverse function parameters.
+            TIntermAggregate* params = (*seqIter)->getAsAggregate();
+            ASSERT(params != NULL);
+            ASSERT(params->getOp() == EOpParameters);
+            params->traverse(this);
+
+            // Traverse function body.
+            TIntermAggregate* body = ++seqIter != sequence.end() ?
+                (*seqIter)->getAsAggregate() : NULL;
+            visitCodeBlock(body);
+            decrementDepth();
+            // Fully processed; no need to visit children.
+            visitChildren = false;
+            break;
+        }
+        case EOpFunctionCall:
+            // Function call.
+            if (visit == PreVisit)
+            {
+                out << hashFunctionName(node->getName()) << "(";
+            }
+            else if (visit == InVisit)
+            {
+                out << ", ";
+            }
+            else
+            {
+                out << ")";
+            }
+            break;
+        case EOpParameters: {
+            // Function parameters.
+            ASSERT(visit == PreVisit);
+            out << "(";
+            writeFunctionParameters(node->getSequence());
+            out << ")";
+            visitChildren = false;
+            break;
+        }
+        case EOpDeclaration: {
+            // Variable declaration.
+            if (visit == PreVisit)
+            {
+                const TIntermSequence& sequence = node->getSequence();
+                const TIntermTyped* variable = sequence.front()->getAsTyped();
+                writeVariableType(variable->getType());
+                out << " ";
+                mDeclaringVariables = true;
+            }
+            else if (visit == InVisit)
+            {
+                out << ", ";
+                mDeclaringVariables = true;
+            }
+            else
+            {
+                mDeclaringVariables = false;
+            }
+            break;
+        }
+        case EOpConstructFloat: writeTriplet(visit, "float(", NULL, ")"); break;
+        case EOpConstructVec2: writeTriplet(visit, "vec2(", ", ", ")"); break;
+        case EOpConstructVec3: writeTriplet(visit, "vec3(", ", ", ")"); break;
+        case EOpConstructVec4: writeTriplet(visit, "vec4(", ", ", ")"); break;
+        case EOpConstructBool: writeTriplet(visit, "bool(", NULL, ")"); break;
+        case EOpConstructBVec2: writeTriplet(visit, "bvec2(", ", ", ")"); break;
+        case EOpConstructBVec3: writeTriplet(visit, "bvec3(", ", ", ")"); break;
+        case EOpConstructBVec4: writeTriplet(visit, "bvec4(", ", ", ")"); break;
+        case EOpConstructInt: writeTriplet(visit, "int(", NULL, ")"); break;
+        case EOpConstructIVec2: writeTriplet(visit, "ivec2(", ", ", ")"); break;
+        case EOpConstructIVec3: writeTriplet(visit, "ivec3(", ", ", ")"); break;
+        case EOpConstructIVec4: writeTriplet(visit, "ivec4(", ", ", ")"); break;
+        case EOpConstructMat2: writeTriplet(visit, "mat2(", ", ", ")"); break;
+        case EOpConstructMat3: writeTriplet(visit, "mat3(", ", ", ")"); break;
+        case EOpConstructMat4: writeTriplet(visit, "mat4(", ", ", ")"); break;
+        case EOpConstructStruct:
+            if (visit == PreVisit)
+            {
+                const TType& type = node->getType();
+                ASSERT(type.getBasicType() == EbtStruct);
+                out << hashName(type.getStruct()->name()) << "(";
+            }
+            else if (visit == InVisit)
+            {
+                out << ", ";
+            }
+            else
+            {
+                out << ")";
+            }
+            break;
+
+        case EOpLessThan: preString = "lessThan("; delayedWrite = true; break;
+        case EOpGreaterThan: preString = "greaterThan("; delayedWrite = true; break;
+        case EOpLessThanEqual: preString = "lessThanEqual("; delayedWrite = true; break;
+        case EOpGreaterThanEqual: preString = "greaterThanEqual("; delayedWrite = true; break;
+        case EOpVectorEqual: preString = "equal("; delayedWrite = true; break;
+        case EOpVectorNotEqual: preString = "notEqual("; delayedWrite = true; break;
+        case EOpComma: writeTriplet(visit, NULL, ", ", NULL); break;
+
+        case EOpMod: preString = "mod("; delayedWrite = true; break;
+        case EOpPow: preString = "pow("; delayedWrite = true; break;
+        case EOpAtan: preString = "atan("; delayedWrite = true; break;
+        case EOpMin: preString = "min("; delayedWrite = true; break;
+        case EOpMax: preString = "max("; delayedWrite = true; break;
+        case EOpClamp: preString = "clamp("; delayedWrite = true; break;
+        case EOpMix: preString = "mix("; delayedWrite = true; break;
+        case EOpStep: preString = "step("; delayedWrite = true; break;
+        case EOpSmoothStep: preString = "smoothstep("; delayedWrite = true; break;
+
+        case EOpDistance: preString = "distance("; delayedWrite = true; break;
+        case EOpDot: preString = "dot("; delayedWrite = true; break;
+        case EOpCross: preString = "cross("; delayedWrite = true; break;
+        case EOpFaceForward: preString = "faceforward("; delayedWrite = true; break;
+        case EOpReflect: preString = "reflect("; delayedWrite = true; break;
+        case EOpRefract: preString = "refract("; delayedWrite = true; break;
+        case EOpMul: preString = "matrixCompMult("; delayedWrite = true; break;
+
+        default: UNREACHABLE(); break;
+    }
+    if (delayedWrite && visit == PreVisit && node->getUseEmulatedFunction())
+        preString = BuiltInFunctionEmulator::GetEmulatedFunctionName(preString);
+    if (delayedWrite)
+        writeTriplet(visit, preString.c_str(), ", ", ")");
+    return visitChildren;
+}
+
+bool TOutputGLSLBase::visitLoop(Visit visit, TIntermLoop* node)
+{
+    TInfoSinkBase& out = objSink();
+
+    incrementDepth(node);
+    // Loop header.
+    TLoopType loopType = node->getType();
+    if (loopType == ELoopFor)  // for loop
+    {
+        if (!node->getUnrollFlag()) {
+            out << "for (";
+            if (node->getInit())
+                node->getInit()->traverse(this);
+            out << "; ";
+
+            if (node->getCondition())
+                node->getCondition()->traverse(this);
+            out << "; ";
+
+            if (node->getExpression())
+                node->getExpression()->traverse(this);
+            out << ")\n";
+        }
+    }
+    else if (loopType == ELoopWhile)  // while loop
+    {
+        out << "while (";
+        ASSERT(node->getCondition() != NULL);
+        node->getCondition()->traverse(this);
+        out << ")\n";
+    }
+    else  // do-while loop
+    {
+        ASSERT(loopType == ELoopDoWhile);
+        out << "do\n";
+    }
+
+    // Loop body.
+    if (node->getUnrollFlag())
+    {
+        TLoopIndexInfo indexInfo;
+        mLoopUnroll.FillLoopIndexInfo(node, indexInfo);
+        mLoopUnroll.Push(indexInfo);
+        while (mLoopUnroll.SatisfiesLoopCondition())
+        {
+            visitCodeBlock(node->getBody());
+            mLoopUnroll.Step();
+        }
+        mLoopUnroll.Pop();
+    }
+    else
+    {
+        visitCodeBlock(node->getBody());
+    }
+
+    // Loop footer.
+    if (loopType == ELoopDoWhile)  // do-while loop
+    {
+        out << "while (";
+        ASSERT(node->getCondition() != NULL);
+        node->getCondition()->traverse(this);
+        out << ");\n";
+    }
+    decrementDepth();
+
+    // No need to visit children. They have been already processed in
+    // this function.
+    return false;
+}
+
+bool TOutputGLSLBase::visitBranch(Visit visit, TIntermBranch* node)
+{
+    switch (node->getFlowOp())
+    {
+        case EOpKill: writeTriplet(visit, "discard", NULL, NULL); break;
+        case EOpBreak: writeTriplet(visit, "break", NULL, NULL); break;
+        case EOpContinue: writeTriplet(visit, "continue", NULL, NULL); break;
+        case EOpReturn: writeTriplet(visit, "return ", NULL, NULL); break;
+        default: UNREACHABLE(); break;
+    }
+
+    return true;
+}
+
+void TOutputGLSLBase::visitCodeBlock(TIntermNode* node) {
+    TInfoSinkBase &out = objSink();
+    if (node != NULL)
+    {
+        node->traverse(this);
+        // Single statements not part of a sequence need to be terminated
+        // with semi-colon.
+        if (isSingleStatement(node))
+            out << ";\n";
+    }
+    else
+    {
+        out << "{\n}\n";  // Empty code block.
+    }
+}
+
+TString TOutputGLSLBase::getTypeName(const TType& type)
+{
+    TInfoSinkBase out;
+    if (type.isMatrix())
+    {
+        out << "mat";
+        out << type.getNominalSize();
+    }
+    else if (type.isVector())
+    {
+        switch (type.getBasicType())
+        {
+            case EbtFloat: out << "vec"; break;
+            case EbtInt: out << "ivec"; break;
+            case EbtBool: out << "bvec"; break;
+            default: UNREACHABLE(); break;
+        }
+        out << type.getNominalSize();
+    }
+    else
+    {
+        if (type.getBasicType() == EbtStruct)
+            out << hashName(type.getStruct()->name());
+        else
+            out << type.getBasicString();
+    }
+    return TString(out.c_str());
+}
+
+TString TOutputGLSLBase::hashName(const TString& name)
+{
+    if (mHashFunction == NULL || name.empty())
+        return name;
+    NameMap::const_iterator it = mNameMap.find(name.c_str());
+    if (it != mNameMap.end())
+        return it->second.c_str();
+    TString hashedName = TIntermTraverser::hash(name, mHashFunction);
+    mNameMap[name.c_str()] = hashedName.c_str();
+    return hashedName;
+}
+
+TString TOutputGLSLBase::hashVariableName(const TString& name)
+{
+    if (mSymbolTable.findBuiltIn(name) != NULL)
+        return name;
+    return hashName(name);
+}
+
+TString TOutputGLSLBase::hashFunctionName(const TString& mangled_name)
+{
+    TString name = TFunction::unmangleName(mangled_name);
+    if (mSymbolTable.findBuiltIn(mangled_name) != NULL || name == "main")
+        return name;
+    return hashName(name);
+}
+
+bool TOutputGLSLBase::structDeclared(const TStructure* structure) const
+{
+    return mDeclaredStructs.find(structure->name()) != mDeclaredStructs.end();
+}
+
+void TOutputGLSLBase::declareStruct(const TStructure* structure)
+{
+    TInfoSinkBase& out = objSink();
+
+    out << "struct " << hashName(structure->name()) << "{\n";
+    const TFieldList& fields = structure->fields();
+    for (size_t i = 0; i < fields.size(); ++i)
+    {
+        const TField* field = fields[i];
+        if (writeVariablePrecision(field->type()->getPrecision()))
+            out << " ";
+        out << getTypeName(*field->type()) << " " << hashName(field->name());
+        if (field->type()->isArray())
+            out << arrayBrackets(*field->type());
+        out << ";\n";
+    }
+    out << "}";
+
+    mDeclaredStructs.insert(structure->name());
+}
diff --git a/Source/ThirdParty/ANGLE/src/compiler/translator/OutputGLSLBase.h b/Source/ThirdParty/ANGLE/src/compiler/translator/OutputGLSLBase.h
new file mode 100644 (file)
index 0000000..76bec4d
--- /dev/null
@@ -0,0 +1,79 @@
+//
+// Copyright (c) 2002-2011 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#ifndef CROSSCOMPILERGLSL_OUTPUTGLSLBASE_H_
+#define CROSSCOMPILERGLSL_OUTPUTGLSLBASE_H_
+
+#include <set>
+
+#include "compiler/translator/ForLoopUnroll.h"
+#include "compiler/translator/intermediate.h"
+#include "compiler/translator/ParseContext.h"
+
+class TOutputGLSLBase : public TIntermTraverser
+{
+public:
+    TOutputGLSLBase(TInfoSinkBase& objSink,
+                    ShArrayIndexClampingStrategy clampingStrategy,
+                    ShHashFunction64 hashFunction,
+                    NameMap& nameMap,
+                    TSymbolTable& symbolTable);
+
+protected:
+    TInfoSinkBase& objSink() { return mObjSink; }
+    void writeTriplet(Visit visit, const char* preStr, const char* inStr, const char* postStr);
+    void writeVariableType(const TType& type);
+    virtual bool writeVariablePrecision(TPrecision precision) = 0;
+    void writeFunctionParameters(const TIntermSequence& args);
+    const ConstantUnion* writeConstantUnion(const TType& type, const ConstantUnion* pConstUnion);
+    TString getTypeName(const TType& type);
+
+    virtual void visitSymbol(TIntermSymbol* node);
+    virtual void visitConstantUnion(TIntermConstantUnion* node);
+    virtual bool visitBinary(Visit visit, TIntermBinary* node);
+    virtual bool visitUnary(Visit visit, TIntermUnary* node);
+    virtual bool visitSelection(Visit visit, TIntermSelection* node);
+    virtual bool visitAggregate(Visit visit, TIntermAggregate* node);
+    virtual bool visitLoop(Visit visit, TIntermLoop* node);
+    virtual bool visitBranch(Visit visit, TIntermBranch* node);
+
+    void visitCodeBlock(TIntermNode* node);
+
+
+    // Return the original name if hash function pointer is NULL;
+    // otherwise return the hashed name.
+    TString hashName(const TString& name);
+    // Same as hashName(), but without hashing built-in variables.
+    TString hashVariableName(const TString& name);
+    // Same as hashName(), but without hashing built-in functions.
+    TString hashFunctionName(const TString& mangled_name);
+
+private:
+    bool structDeclared(const TStructure* structure) const;
+    void declareStruct(const TStructure* structure);
+
+    TInfoSinkBase& mObjSink;
+    bool mDeclaringVariables;
+
+    // Structs are declared as the tree is traversed. This set contains all
+    // the structs already declared. It is maintained so that a struct is
+    // declared only once.
+    typedef std::set<TString> DeclaredStructs;
+    DeclaredStructs mDeclaredStructs;
+
+    ForLoopUnroll mLoopUnroll;
+
+    ShArrayIndexClampingStrategy mClampingStrategy;
+
+    // name hashing.
+    ShHashFunction64 mHashFunction;
+
+    NameMap& mNameMap;
+
+    TSymbolTable& mSymbolTable;
+};
+
+#endif  // CROSSCOMPILERGLSL_OUTPUTGLSLBASE_H_
diff --git a/Source/ThirdParty/ANGLE/src/compiler/translator/OutputHLSL.cpp b/Source/ThirdParty/ANGLE/src/compiler/translator/OutputHLSL.cpp
new file mode 100644 (file)
index 0000000..af996df
--- /dev/null
@@ -0,0 +1,3138 @@
+//
+// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "compiler/translator/OutputHLSL.h"
+
+#include "common/angleutils.h"
+#include "compiler/translator/compilerdebug.h"
+#include "compiler/translator/DetectDiscontinuity.h"
+#include "compiler/translator/InfoSink.h"
+#include "compiler/translator/SearchSymbol.h"
+#include "compiler/translator/UnfoldShortCircuit.h"
+#include "compiler/translator/NodeSearch.h"
+#include "compiler/translator/RewriteElseBlocks.h"
+
+#include <algorithm>
+#include <cfloat>
+#include <stdio.h>
+
+namespace sh
+{
+
+OutputHLSL::OutputHLSL(TParseContext &context, const ShBuiltInResources& resources, ShShaderOutput outputType)
+    : TIntermTraverser(true, true, true), mContext(context), mOutputType(outputType)
+{
+    mUnfoldShortCircuit = new UnfoldShortCircuit(context, this);
+    mInsideFunction = false;
+
+    mUsesTexture2D = false;
+    mUsesTexture2D_bias = false;
+    mUsesTexture2DProj = false;
+    mUsesTexture2DProj_bias = false;
+    mUsesTexture2DProjLod = false;
+    mUsesTexture2DLod = false;
+    mUsesTextureCube = false;
+    mUsesTextureCube_bias = false;
+    mUsesTextureCubeLod = false;
+    mUsesTexture2DLod0 = false;
+    mUsesTexture2DLod0_bias = false;
+    mUsesTexture2DProjLod0 = false;
+    mUsesTexture2DProjLod0_bias = false;
+    mUsesTextureCubeLod0 = false;
+    mUsesTextureCubeLod0_bias = false;
+    mUsesFragColor = false;
+    mUsesFragData = false;
+    mUsesDepthRange = false;
+    mUsesFragCoord = false;
+    mUsesPointCoord = false;
+    mUsesFrontFacing = false;
+    mUsesPointSize = false;
+    mUsesFragDepth = false;
+    mUsesXor = false;
+    mUsesMod1 = false;
+    mUsesMod2v = false;
+    mUsesMod2f = false;
+    mUsesMod3v = false;
+    mUsesMod3f = false;
+    mUsesMod4v = false;
+    mUsesMod4f = false;
+    mUsesFaceforward1 = false;
+    mUsesFaceforward2 = false;
+    mUsesFaceforward3 = false;
+    mUsesFaceforward4 = false;
+    mUsesAtan2_1 = false;
+    mUsesAtan2_2 = false;
+    mUsesAtan2_3 = false;
+    mUsesAtan2_4 = false;
+    mUsesDiscardRewriting = false;
+
+    mNumRenderTargets = resources.EXT_draw_buffers ? resources.MaxDrawBuffers : 1;
+
+    mScopeDepth = 0;
+
+    mUniqueIndex = 0;
+
+    mContainsLoopDiscontinuity = false;
+    mOutputLod0Function = false;
+    mInsideDiscontinuousLoop = false;
+
+    mExcessiveLoopIndex = NULL;
+
+    if (mOutputType == SH_HLSL9_OUTPUT)
+    {
+        if (mContext.shaderType == SH_FRAGMENT_SHADER)
+        {
+            mUniformRegister = 3;   // Reserve registers for dx_DepthRange, dx_ViewCoords and dx_DepthFront
+        }
+        else
+        {
+            mUniformRegister = 2;   // Reserve registers for dx_DepthRange and dx_ViewAdjust
+        }
+    }
+    else
+    {
+        mUniformRegister = 0;
+    }
+
+    mSamplerRegister = 0;
+}
+
+OutputHLSL::~OutputHLSL()
+{
+    delete mUnfoldShortCircuit;
+}
+
+void OutputHLSL::output()
+{
+    mContainsLoopDiscontinuity = mContext.shaderType == SH_FRAGMENT_SHADER && containsLoopDiscontinuity(mContext.treeRoot);
+
+    // Work around D3D9 bug that would manifest in vertex shaders with selection blocks which
+    // use a vertex attribute as a condition, and some related computation in the else block.
+    if (mOutputType == SH_HLSL9_OUTPUT && mContext.shaderType == SH_VERTEX_SHADER)
+    {
+        RewriteElseBlocks(mContext.treeRoot);
+    }
+
+    mContext.treeRoot->traverse(this);   // Output the body first to determine what has to go in the header
+    header();
+
+    mContext.infoSink().obj << mHeader.c_str();
+    mContext.infoSink().obj << mBody.c_str();
+}
+
+TInfoSinkBase &OutputHLSL::getBodyStream()
+{
+    return mBody;
+}
+
+const ActiveUniforms &OutputHLSL::getUniforms()
+{
+    return mActiveUniforms;
+}
+
+int OutputHLSL::vectorSize(const TType &type) const
+{
+    int elementSize = type.isMatrix() ? type.getNominalSize() : 1;
+    int arraySize = type.isArray() ? type.getArraySize() : 1;
+
+    return elementSize * arraySize;
+}
+
+void OutputHLSL::header()
+{
+    ShShaderType shaderType = mContext.shaderType;
+    TInfoSinkBase &out = mHeader;
+
+    for (StructDeclarations::iterator structDeclaration = mStructDeclarations.begin(); structDeclaration != mStructDeclarations.end(); structDeclaration++)
+    {
+        out << *structDeclaration;
+    }
+
+    for (Constructors::iterator constructor = mConstructors.begin(); constructor != mConstructors.end(); constructor++)
+    {
+        out << *constructor;
+    }
+
+    TString uniforms;
+    TString varyings;
+    TString attributes;
+
+    for (ReferencedSymbols::const_iterator uniform = mReferencedUniforms.begin(); uniform != mReferencedUniforms.end(); uniform++)
+    {
+        const TType &type = uniform->second->getType();
+        const TString &name = uniform->second->getSymbol();
+
+        if (mOutputType == SH_HLSL11_OUTPUT && IsSampler(type.getBasicType()))   // Also declare the texture
+        {
+            int index = samplerRegister(mReferencedUniforms[name]);
+
+            uniforms += "uniform SamplerState sampler_" + decorateUniform(name, type) + arrayString(type) + 
+                        " : register(s" + str(index) + ");\n";
+
+            uniforms += "uniform " + textureString(type) + " texture_" + decorateUniform(name, type) + arrayString(type) + 
+                        " : register(t" + str(index) + ");\n";
+        }
+        else
+        {
+            uniforms += "uniform " + typeString(type) + " " + decorateUniform(name, type) + arrayString(type) + 
+                        " : register(" + registerString(mReferencedUniforms[name]) + ");\n";
+        }
+    }
+
+    for (ReferencedSymbols::const_iterator varying = mReferencedVaryings.begin(); varying != mReferencedVaryings.end(); varying++)
+    {
+        const TType &type = varying->second->getType();
+        const TString &name = varying->second->getSymbol();
+
+        // Program linking depends on this exact format
+        varyings += "static " + typeString(type) + " " + decorate(name) + arrayString(type) + " = " + initializer(type) + ";\n";
+    }
+
+    for (ReferencedSymbols::const_iterator attribute = mReferencedAttributes.begin(); attribute != mReferencedAttributes.end(); attribute++)
+    {
+        const TType &type = attribute->second->getType();
+        const TString &name = attribute->second->getSymbol();
+
+        attributes += "static " + typeString(type) + " " + decorate(name) + arrayString(type) + " = " + initializer(type) + ";\n";
+    }
+
+    if (mUsesDiscardRewriting)
+    {
+        out << "#define ANGLE_USES_DISCARD_REWRITING" << "\n";
+    }
+
+    if (shaderType == SH_FRAGMENT_SHADER)
+    {
+        TExtensionBehavior::const_iterator iter = mContext.extensionBehavior().find("GL_EXT_draw_buffers");
+        const bool usingMRTExtension = (iter != mContext.extensionBehavior().end() && (iter->second == EBhEnable || iter->second == EBhRequire));
+
+        const unsigned int numColorValues = usingMRTExtension ? mNumRenderTargets : 1;
+
+        out << "// Varyings\n";
+        out <<  varyings;
+        out << "\n"
+               "static float4 gl_Color[" << numColorValues << "] =\n"
+               "{\n";
+        for (unsigned int i = 0; i < numColorValues; i++)
+        {
+            out << "    float4(0, 0, 0, 0)";
+            if (i + 1 != numColorValues)
+            {
+                out << ",";
+            }
+            out << "\n";
+        }
+        out << "};\n";
+
+        if (mUsesFragDepth)
+        {
+            out << "static float gl_Depth = 0.0;\n";
+        }
+
+        if (mUsesFragCoord)
+        {
+            out << "static float4 gl_FragCoord = float4(0, 0, 0, 0);\n";
+        }
+
+        if (mUsesPointCoord)
+        {
+            out << "static float2 gl_PointCoord = float2(0.5, 0.5);\n";
+        }
+
+        if (mUsesFrontFacing)
+        {
+            out << "static bool gl_FrontFacing = false;\n";
+        }
+
+        out << "\n";
+
+        if (mUsesDepthRange)
+        {
+            out << "struct gl_DepthRangeParameters\n"
+                   "{\n"
+                   "    float near;\n"
+                   "    float far;\n"
+                   "    float diff;\n"
+                   "};\n"
+                   "\n";
+        }
+
+        if (mOutputType == SH_HLSL11_OUTPUT)
+        {
+            out << "cbuffer DriverConstants : register(b1)\n"
+                   "{\n";
+
+            if (mUsesDepthRange)
+            {
+                out << "    float3 dx_DepthRange : packoffset(c0);\n";
+            }
+
+            if (mUsesFragCoord)
+            {
+                out << "    float4 dx_ViewCoords : packoffset(c1);\n";
+            }
+
+            if (mUsesFragCoord || mUsesFrontFacing)
+            {
+                out << "    float3 dx_DepthFront : packoffset(c2);\n";
+            }
+
+            out << "};\n";
+        }
+        else
+        {
+            if (mUsesDepthRange)
+            {
+                out << "uniform float3 dx_DepthRange : register(c0);";
+            }
+
+            if (mUsesFragCoord)
+            {
+                out << "uniform float4 dx_ViewCoords : register(c1);\n";
+            }
+
+            if (mUsesFragCoord || mUsesFrontFacing)
+            {
+                out << "uniform float3 dx_DepthFront : register(c2);\n";
+            }
+        }
+
+        out << "\n";
+
+        if (mUsesDepthRange)
+        {
+            out << "static gl_DepthRangeParameters gl_DepthRange = {dx_DepthRange.x, dx_DepthRange.y, dx_DepthRange.z};\n"
+                   "\n";
+        }
+        
+        out <<  uniforms;
+        out << "\n";
+
+        if (mUsesTexture2D)
+        {
+            if (mOutputType == SH_HLSL9_OUTPUT)
+            {
+                out << "float4 gl_texture2D(sampler2D s, float2 t)\n"
+                       "{\n"
+                       "    return tex2D(s, t);\n"
+                       "}\n"
+                       "\n";
+            }
+            else if (mOutputType == SH_HLSL11_OUTPUT)
+            {
+                out << "float4 gl_texture2D(Texture2D t, SamplerState s, float2 uv)\n"
+                       "{\n"
+                       "    return t.Sample(s, uv);\n"
+                       "}\n"
+                       "\n";
+            }
+            else UNREACHABLE();
+        }
+
+        if (mUsesTexture2D_bias)
+        {
+            if (mOutputType == SH_HLSL9_OUTPUT)
+            {
+                out << "float4 gl_texture2D(sampler2D s, float2 t, float bias)\n"
+                       "{\n"
+                       "    return tex2Dbias(s, float4(t.x, t.y, 0, bias));\n"
+                       "}\n"
+                       "\n";
+            }
+            else if (mOutputType == SH_HLSL11_OUTPUT)
+            {
+                out << "float4 gl_texture2D(Texture2D t, SamplerState s, float2 uv, float bias)\n"
+                       "{\n"
+                       "    return t.SampleBias(s, uv, bias);\n"
+                       "}\n"
+                       "\n";
+            }
+            else UNREACHABLE();
+        }
+
+        if (mUsesTexture2DProj)
+        {
+            if (mOutputType == SH_HLSL9_OUTPUT)
+            {
+                out << "float4 gl_texture2DProj(sampler2D s, float3 t)\n"
+                       "{\n"
+                       "    return tex2Dproj(s, float4(t.x, t.y, 0, t.z));\n"
+                       "}\n"
+                       "\n"
+                       "float4 gl_texture2DProj(sampler2D s, float4 t)\n"
+                       "{\n"
+                       "    return tex2Dproj(s, t);\n"
+                       "}\n"
+                       "\n";
+            }
+            else if (mOutputType == SH_HLSL11_OUTPUT)
+            {
+                out << "float4 gl_texture2DProj(Texture2D t, SamplerState s, float3 uvw)\n"
+                       "{\n"
+                       "    return t.Sample(s, float2(uvw.x / uvw.z, uvw.y / uvw.z));\n"
+                       "}\n"
+                       "\n"
+                       "float4 gl_texture2DProj(Texture2D t, SamplerState s, float4 uvw)\n"
+                       "{\n"
+                       "    return t.Sample(s, float2(uvw.x / uvw.w, uvw.y / uvw.w));\n"
+                       "}\n"
+                       "\n";
+            }
+            else UNREACHABLE();
+        }
+
+        if (mUsesTexture2DProj_bias)
+        {
+            if (mOutputType == SH_HLSL9_OUTPUT)
+            {
+                out << "float4 gl_texture2DProj(sampler2D s, float3 t, float bias)\n"
+                       "{\n"
+                       "    return tex2Dbias(s, float4(t.x / t.z, t.y / t.z, 0, bias));\n"
+                       "}\n"
+                       "\n"
+                       "float4 gl_texture2DProj(sampler2D s, float4 t, float bias)\n"
+                       "{\n"
+                       "    return tex2Dbias(s, float4(t.x / t.w, t.y / t.w, 0, bias));\n"
+                       "}\n"
+                       "\n";
+            }
+            else if (mOutputType == SH_HLSL11_OUTPUT)
+            {
+                out << "float4 gl_texture2DProj(Texture2D t, SamplerState s, float3 uvw, float bias)\n"
+                       "{\n"
+                       "    return t.SampleBias(s, float2(uvw.x / uvw.z, uvw.y / uvw.z), bias);\n"
+                       "}\n"
+                       "\n"
+                       "float4 gl_texture2DProj(Texture2D t, SamplerState s, float4 uvw, float bias)\n"
+                       "{\n"
+                       "    return t.SampleBias(s, float2(uvw.x / uvw.w, uvw.y / uvw.w), bias);\n"
+                       "}\n"
+                       "\n";
+            }
+            else UNREACHABLE();
+        }
+
+        if (mUsesTextureCube)
+        {
+            if (mOutputType == SH_HLSL9_OUTPUT)
+            {
+                out << "float4 gl_textureCube(samplerCUBE s, float3 t)\n"
+                       "{\n"
+                       "    return texCUBE(s, t);\n"
+                       "}\n"
+                       "\n";
+            }
+            else if (mOutputType == SH_HLSL11_OUTPUT)
+            {
+                out << "float4 gl_textureCube(TextureCube t, SamplerState s, float3 uvw)\n"
+                       "{\n"
+                       "    return t.Sample(s, uvw);\n"
+                       "}\n"
+                       "\n";
+            }
+            else UNREACHABLE();
+        }
+
+        if (mUsesTextureCube_bias)
+        {
+            if (mOutputType == SH_HLSL9_OUTPUT)
+            {
+                out << "float4 gl_textureCube(samplerCUBE s, float3 t, float bias)\n"
+                       "{\n"
+                       "    return texCUBEbias(s, float4(t.x, t.y, t.z, bias));\n"
+                       "}\n"
+                       "\n";
+            }
+            else if (mOutputType == SH_HLSL11_OUTPUT)
+            {
+                out << "float4 gl_textureCube(TextureCube t, SamplerState s, float3 uvw, float bias)\n"
+                       "{\n"
+                       "    return t.SampleBias(s, uvw, bias);\n"
+                       "}\n"
+                       "\n";
+            }
+            else UNREACHABLE();
+        }
+
+        // These *Lod0 intrinsics are not available in GL fragment shaders.
+        // They are used to sample using discontinuous texture coordinates.
+        if (mUsesTexture2DLod0)
+        {
+            if (mOutputType == SH_HLSL9_OUTPUT)
+            {
+                out << "float4 gl_texture2DLod0(sampler2D s, float2 t)\n"
+                       "{\n"
+                       "    return tex2Dlod(s, float4(t.x, t.y, 0, 0));\n"
+                       "}\n"
+                       "\n";
+            }
+            else if (mOutputType == SH_HLSL11_OUTPUT)
+            {
+                out << "float4 gl_texture2DLod0(Texture2D t, SamplerState s, float2 uv)\n"
+                       "{\n"
+                       "    return t.SampleLevel(s, uv, 0);\n"
+                       "}\n"
+                       "\n";
+            }
+            else UNREACHABLE();
+        }
+
+        if (mUsesTexture2DLod0_bias)
+        {
+            if (mOutputType == SH_HLSL9_OUTPUT)
+            {
+                out << "float4 gl_texture2DLod0(sampler2D s, float2 t, float bias)\n"
+                       "{\n"
+                       "    return tex2Dlod(s, float4(t.x, t.y, 0, 0));\n"
+                       "}\n"
+                       "\n";
+            }
+            else if (mOutputType == SH_HLSL11_OUTPUT)
+            {
+                out << "float4 gl_texture2DLod0(Texture2D t, SamplerState s, float2 uv, float bias)\n"
+                       "{\n"
+                       "    return t.SampleLevel(s, uv, 0);\n"
+                       "}\n"
+                       "\n";
+            }
+            else UNREACHABLE();
+        }
+
+        if (mUsesTexture2DProjLod0)
+        {
+            if (mOutputType == SH_HLSL9_OUTPUT)
+            {
+                out << "float4 gl_texture2DProjLod0(sampler2D s, float3 t)\n"
+                       "{\n"
+                       "    return tex2Dlod(s, float4(t.x / t.z, t.y / t.z, 0, 0));\n"
+                       "}\n"
+                       "\n"
+                       "float4 gl_texture2DProjLod(sampler2D s, float4 t)\n"
+                       "{\n"
+                       "    return tex2Dlod(s, float4(t.x / t.w, t.y / t.w, 0, 0));\n"
+                       "}\n"
+                       "\n";
+            }
+            else if (mOutputType == SH_HLSL11_OUTPUT)
+            {
+                out << "float4 gl_texture2DProjLod0(Texture2D t, SamplerState s, float3 uvw)\n"
+                       "{\n"
+                       "    return t.SampleLevel(s, float2(uvw.x / uvw.z, uvw.y / uvw.z), 0);\n"
+                       "}\n"
+                       "\n"
+                       "float4 gl_texture2DProjLod0(Texture2D t, SamplerState s, float4 uvw)\n"
+                       "{\n"
+                       "    return t.SampleLevel(s, float2(uvw.x / uvw.w, uvw.y / uvw.w), 0);\n"
+                       "}\n"
+                       "\n";
+            }
+            else UNREACHABLE();
+        }
+
+        if (mUsesTexture2DProjLod0_bias)
+        {
+            if (mOutputType == SH_HLSL9_OUTPUT)
+            {
+                out << "float4 gl_texture2DProjLod0_bias(sampler2D s, float3 t, float bias)\n"
+                       "{\n"
+                       "    return tex2Dlod(s, float4(t.x / t.z, t.y / t.z, 0, 0));\n"
+                       "}\n"
+                       "\n"
+                       "float4 gl_texture2DProjLod_bias(sampler2D s, float4 t, float bias)\n"
+                       "{\n"
+                       "    return tex2Dlod(s, float4(t.x / t.w, t.y / t.w, 0, 0));\n"
+                       "}\n"
+                       "\n";
+            }
+            else if (mOutputType == SH_HLSL11_OUTPUT)
+            {
+                out << "float4 gl_texture2DProjLod_bias(Texture2D t, SamplerState s, float3 uvw, float bias)\n"
+                       "{\n"
+                       "    return t.SampleLevel(s, float2(uvw.x / uvw.z, uvw.y / uvw.z), 0);\n"
+                       "}\n"
+                       "\n"
+                       "float4 gl_texture2DProjLod_bias(Texture2D t, SamplerState s, float4 uvw, float bias)\n"
+                       "{\n"
+                       "    return t.SampleLevel(s, float2(uvw.x / uvw.w, uvw.y / uvw.w), 0);\n"
+                       "}\n"
+                       "\n";
+            }
+            else UNREACHABLE();
+        }
+
+        if (mUsesTextureCubeLod0)
+        {
+            if (mOutputType == SH_HLSL9_OUTPUT)
+            {
+                out << "float4 gl_textureCubeLod0(samplerCUBE s, float3 t)\n"
+                       "{\n"
+                       "    return texCUBElod(s, float4(t.x, t.y, t.z, 0));\n"
+                       "}\n"
+                       "\n";
+            }
+            else if (mOutputType == SH_HLSL11_OUTPUT)
+            {
+                out << "float4 gl_textureCubeLod0(TextureCube t, SamplerState s, float3 uvw)\n"
+                       "{\n"
+                       "    return t.SampleLevel(s, uvw, 0);\n"
+                       "}\n"
+                       "\n";
+            }
+            else UNREACHABLE();
+        }
+
+        if (mUsesTextureCubeLod0_bias)
+        {
+            if (mOutputType == SH_HLSL9_OUTPUT)
+            {
+                out << "float4 gl_textureCubeLod0(samplerCUBE s, float3 t, float bias)\n"
+                       "{\n"
+                       "    return texCUBElod(s, float4(t.x, t.y, t.z, 0));\n"
+                       "}\n"
+                       "\n";
+            }
+            else if (mOutputType == SH_HLSL11_OUTPUT)
+            {
+                out << "float4 gl_textureCubeLod0(TextureCube t, SamplerState s, float3 uvw, float bias)\n"
+                       "{\n"
+                       "    return t.SampleLevel(s, uvw, 0);\n"
+                       "}\n"
+                       "\n";
+            }
+            else UNREACHABLE();
+        }
+
+        if (usingMRTExtension && mNumRenderTargets > 1)
+        {
+            out << "#define GL_USES_MRT\n";
+        }
+
+        if (mUsesFragColor)
+        {
+            out << "#define GL_USES_FRAG_COLOR\n";
+        }
+
+        if (mUsesFragData)
+        {
+            out << "#define GL_USES_FRAG_DATA\n";
+        }
+    }
+    else   // Vertex shader
+    {
+        out << "// Attributes\n";
+        out <<  attributes;
+        out << "\n"
+               "static float4 gl_Position = float4(0, 0, 0, 0);\n";
+        
+        if (mUsesPointSize)
+        {
+            out << "static float gl_PointSize = float(1);\n";
+        }
+
+        out << "\n"
+               "// Varyings\n";
+        out <<  varyings;
+        out << "\n";
+
+        if (mUsesDepthRange)
+        {
+            out << "struct gl_DepthRangeParameters\n"
+                   "{\n"
+                   "    float near;\n"
+                   "    float far;\n"
+                   "    float diff;\n"
+                   "};\n"
+                   "\n";
+        }
+
+        if (mOutputType == SH_HLSL11_OUTPUT)
+        {
+            if (mUsesDepthRange)
+            {
+                out << "cbuffer DriverConstants : register(b1)\n"
+                       "{\n"
+                       "    float3 dx_DepthRange : packoffset(c0);\n"
+                       "};\n"
+                       "\n";
+            }
+        }
+        else
+        {
+            if (mUsesDepthRange)
+            {
+                out << "uniform float3 dx_DepthRange : register(c0);\n";
+            }
+
+            out << "uniform float4 dx_ViewAdjust : register(c1);\n"
+                   "\n";
+        }
+
+        if (mUsesDepthRange)
+        {
+            out << "static gl_DepthRangeParameters gl_DepthRange = {dx_DepthRange.x, dx_DepthRange.y, dx_DepthRange.z};\n"
+                   "\n";
+        }
+
+        out << uniforms;
+        out << "\n";
+        
+        if (mUsesTexture2D)
+        {
+            if (mOutputType == SH_HLSL9_OUTPUT)
+            {
+                out << "float4 gl_texture2D(sampler2D s, float2 t)\n"
+                       "{\n"
+                       "    return tex2Dlod(s, float4(t.x, t.y, 0, 0));\n"
+                       "}\n"
+                       "\n";
+            }
+            else if (mOutputType == SH_HLSL11_OUTPUT)
+            {
+                out << "float4 gl_texture2D(Texture2D t, SamplerState s, float2 uv)\n"
+                       "{\n"
+                       "    return t.SampleLevel(s, uv, 0);\n"
+                       "}\n"
+                       "\n";
+            }
+            else UNREACHABLE();
+        }
+
+        if (mUsesTexture2DLod)
+        {
+            if (mOutputType == SH_HLSL9_OUTPUT)
+            {
+                out << "float4 gl_texture2DLod(sampler2D s, float2 t, float lod)\n"
+                       "{\n"
+                       "    return tex2Dlod(s, float4(t.x, t.y, 0, lod));\n"
+                       "}\n"
+                       "\n";
+            }
+            else if (mOutputType == SH_HLSL11_OUTPUT)
+            {
+                out << "float4 gl_texture2DLod(Texture2D t, SamplerState s, float2 uv, float lod)\n"
+                       "{\n"
+                       "    return t.SampleLevel(s, uv, lod);\n"
+                       "}\n"
+                       "\n";
+            }
+            else UNREACHABLE();
+        }
+
+        if (mUsesTexture2DProj)
+        {
+            if (mOutputType == SH_HLSL9_OUTPUT)
+            {
+                out << "float4 gl_texture2DProj(sampler2D s, float3 t)\n"
+                       "{\n"
+                       "    return tex2Dlod(s, float4(t.x / t.z, t.y / t.z, 0, 0));\n"
+                       "}\n"
+                       "\n"
+                       "float4 gl_texture2DProj(sampler2D s, float4 t)\n"
+                       "{\n"
+                       "    return tex2Dlod(s, float4(t.x / t.w, t.y / t.w, 0, 0));\n"
+                       "}\n"
+                       "\n";
+            }
+            else if (mOutputType == SH_HLSL11_OUTPUT)
+            {
+                out << "float4 gl_texture2DProj(Texture2D t, SamplerState s, float3 uvw)\n"
+                       "{\n"
+                       "    return t.SampleLevel(s, float2(uvw.x / uvw.z, uvw.y / uvw.z), 0);\n"
+                       "}\n"
+                       "\n"
+                       "float4 gl_texture2DProj(Texture2D t, SamplerState s, float4 uvw)\n"
+                       "{\n"
+                       "    return t.SampleLevel(s, float2(uvw.x / uvw.w, uvw.y / uvw.w), 0);\n"
+                       "}\n"
+                       "\n";
+            }
+            else UNREACHABLE();
+        }
+
+        if (mUsesTexture2DProjLod)
+        {
+            if (mOutputType == SH_HLSL9_OUTPUT)
+            {
+                out << "float4 gl_texture2DProjLod(sampler2D s, float3 t, float lod)\n"
+                       "{\n"
+                       "    return tex2Dlod(s, float4(t.x / t.z, t.y / t.z, 0, lod));\n"
+                       "}\n"
+                       "\n"
+                       "float4 gl_texture2DProjLod(sampler2D s, float4 t, float lod)\n"
+                       "{\n"
+                       "    return tex2Dlod(s, float4(t.x / t.w, t.y / t.w, 0, lod));\n"
+                       "}\n"
+                       "\n";
+            }
+            else if (mOutputType == SH_HLSL11_OUTPUT)
+            {
+                out << "float4 gl_texture2DProjLod(Texture2D t, SamplerState s, float3 uvw, float lod)\n"
+                       "{\n"
+                       "    return t.SampleLevel(s, float2(uvw.x / uvw.z, uvw.y / uvw.z), lod);\n"
+                       "}\n"
+                       "\n"
+                       "float4 gl_texture2DProjLod(Texture2D t, SamplerState s, float4 uvw, float lod)\n"
+                       "{\n"
+                       "    return t.SampleLevel(s, float2(uvw.x / uvw.w, uvw.y / uvw.w), lod);\n"
+                       "}\n"
+                       "\n";
+            }
+            else UNREACHABLE();
+        }
+
+        if (mUsesTextureCube)
+        {
+            if (mOutputType == SH_HLSL9_OUTPUT)
+            {
+                out << "float4 gl_textureCube(samplerCUBE s, float3 t)\n"
+                       "{\n"
+                       "    return texCUBElod(s, float4(t.x, t.y, t.z, 0));\n"
+                       "}\n"
+                       "\n";
+            }
+            else if (mOutputType == SH_HLSL11_OUTPUT)
+            {
+                out << "float4 gl_textureCube(TextureCube t, SamplerState s, float3 uvw)\n"
+                       "{\n"
+                       "    return t.SampleLevel(s, uvw, 0);\n"
+                       "}\n"
+                       "\n";
+            }
+            else UNREACHABLE();
+        }
+
+        if (mUsesTextureCubeLod)
+        {
+            if (mOutputType == SH_HLSL9_OUTPUT)
+            {
+                out << "float4 gl_textureCubeLod(samplerCUBE s, float3 t, float lod)\n"
+                       "{\n"
+                       "    return texCUBElod(s, float4(t.x, t.y, t.z, lod));\n"
+                       "}\n"
+                       "\n";
+            }
+            else if (mOutputType == SH_HLSL11_OUTPUT)
+            {
+                out << "float4 gl_textureCubeLod(TextureCube t, SamplerState s, float3 uvw, float lod)\n"
+                       "{\n"
+                       "    return t.SampleLevel(s, uvw, lod);\n"
+                       "}\n"
+                       "\n";
+            }
+            else UNREACHABLE();
+        }
+    }
+
+    if (mUsesFragCoord)
+    {
+        out << "#define GL_USES_FRAG_COORD\n";
+    }
+
+    if (mUsesPointCoord)
+    {
+        out << "#define GL_USES_POINT_COORD\n";
+    }
+
+    if (mUsesFrontFacing)
+    {
+        out << "#define GL_USES_FRONT_FACING\n";
+    }
+
+    if (mUsesPointSize)
+    {
+        out << "#define GL_USES_POINT_SIZE\n";
+    }
+
+    if (mUsesFragDepth)
+    {
+        out << "#define GL_USES_FRAG_DEPTH\n";
+    }
+
+    if (mUsesDepthRange)
+    {
+        out << "#define GL_USES_DEPTH_RANGE\n";
+    }
+
+    if (mUsesXor)
+    {
+        out << "bool xor(bool p, bool q)\n"
+               "{\n"
+               "    return (p || q) && !(p && q);\n"
+               "}\n"
+               "\n";
+    }
+
+    if (mUsesMod1)
+    {
+        out << "float mod(float x, float y)\n"
+               "{\n"
+               "    return x - y * floor(x / y);\n"
+               "}\n"
+               "\n";
+    }
+
+    if (mUsesMod2v)
+    {
+        out << "float2 mod(float2 x, float2 y)\n"
+               "{\n"
+               "    return x - y * floor(x / y);\n"
+               "}\n"
+               "\n";
+    }
+
+    if (mUsesMod2f)
+    {
+        out << "float2 mod(float2 x, float y)\n"
+               "{\n"
+               "    return x - y * floor(x / y);\n"
+               "}\n"
+               "\n";
+    }
+    
+    if (mUsesMod3v)
+    {
+        out << "float3 mod(float3 x, float3 y)\n"
+               "{\n"
+               "    return x - y * floor(x / y);\n"
+               "}\n"
+               "\n";
+    }
+
+    if (mUsesMod3f)
+    {
+        out << "float3 mod(float3 x, float y)\n"
+               "{\n"
+               "    return x - y * floor(x / y);\n"
+               "}\n"
+               "\n";
+    }
+
+    if (mUsesMod4v)
+    {
+        out << "float4 mod(float4 x, float4 y)\n"
+               "{\n"
+               "    return x - y * floor(x / y);\n"
+               "}\n"
+               "\n";
+    }
+
+    if (mUsesMod4f)
+    {
+        out << "float4 mod(float4 x, float y)\n"
+               "{\n"
+               "    return x - y * floor(x / y);\n"
+               "}\n"
+               "\n";
+    }
+
+    if (mUsesFaceforward1)
+    {
+        out << "float faceforward(float N, float I, float Nref)\n"
+               "{\n"
+               "    if(dot(Nref, I) >= 0)\n"
+               "    {\n"
+               "        return -N;\n"
+               "    }\n"
+               "    else\n"
+               "    {\n"
+               "        return N;\n"
+               "    }\n"
+               "}\n"
+               "\n";
+    }
+
+    if (mUsesFaceforward2)
+    {
+        out << "float2 faceforward(float2 N, float2 I, float2 Nref)\n"
+               "{\n"
+               "    if(dot(Nref, I) >= 0)\n"
+               "    {\n"
+               "        return -N;\n"
+               "    }\n"
+               "    else\n"
+               "    {\n"
+               "        return N;\n"
+               "    }\n"
+               "}\n"
+               "\n";
+    }
+
+    if (mUsesFaceforward3)
+    {
+        out << "float3 faceforward(float3 N, float3 I, float3 Nref)\n"
+               "{\n"
+               "    if(dot(Nref, I) >= 0)\n"
+               "    {\n"
+               "        return -N;\n"
+               "    }\n"
+               "    else\n"
+               "    {\n"
+               "        return N;\n"
+               "    }\n"
+               "}\n"
+               "\n";
+    }
+
+    if (mUsesFaceforward4)
+    {
+        out << "float4 faceforward(float4 N, float4 I, float4 Nref)\n"
+               "{\n"
+               "    if(dot(Nref, I) >= 0)\n"
+               "    {\n"
+               "        return -N;\n"
+               "    }\n"
+               "    else\n"
+               "    {\n"
+               "        return N;\n"
+               "    }\n"
+               "}\n"
+               "\n";
+    }
+
+    if (mUsesAtan2_1)
+    {
+        out << "float atanyx(float y, float x)\n"
+               "{\n"
+               "    if(x == 0 && y == 0) x = 1;\n"   // Avoid producing a NaN
+               "    return atan2(y, x);\n"
+               "}\n";
+    }
+
+    if (mUsesAtan2_2)
+    {
+        out << "float2 atanyx(float2 y, float2 x)\n"
+               "{\n"
+               "    if(x[0] == 0 && y[0] == 0) x[0] = 1;\n"
+               "    if(x[1] == 0 && y[1] == 0) x[1] = 1;\n"
+               "    return float2(atan2(y[0], x[0]), atan2(y[1], x[1]));\n"
+               "}\n";
+    }
+
+    if (mUsesAtan2_3)
+    {
+        out << "float3 atanyx(float3 y, float3 x)\n"
+               "{\n"
+               "    if(x[0] == 0 && y[0] == 0) x[0] = 1;\n"
+               "    if(x[1] == 0 && y[1] == 0) x[1] = 1;\n"
+               "    if(x[2] == 0 && y[2] == 0) x[2] = 1;\n"
+               "    return float3(atan2(y[0], x[0]), atan2(y[1], x[1]), atan2(y[2], x[2]));\n"
+               "}\n";
+    }
+
+    if (mUsesAtan2_4)
+    {
+        out << "float4 atanyx(float4 y, float4 x)\n"
+               "{\n"
+               "    if(x[0] == 0 && y[0] == 0) x[0] = 1;\n"
+               "    if(x[1] == 0 && y[1] == 0) x[1] = 1;\n"
+               "    if(x[2] == 0 && y[2] == 0) x[2] = 1;\n"
+               "    if(x[3] == 0 && y[3] == 0) x[3] = 1;\n"
+               "    return float4(atan2(y[0], x[0]), atan2(y[1], x[1]), atan2(y[2], x[2]), atan2(y[3], x[3]));\n"
+               "}\n";
+    }
+}
+
+void OutputHLSL::visitSymbol(TIntermSymbol *node)
+{
+    TInfoSinkBase &out = mBody;
+
+    TString name = node->getSymbol();
+
+    if (name == "gl_FragColor")
+    {
+        out << "gl_Color[0]";
+        mUsesFragColor = true;
+    }
+    else if (name == "gl_FragData")
+    {
+        out << "gl_Color";
+        mUsesFragData = true;
+    }
+    else if (name == "gl_DepthRange")
+    {
+        mUsesDepthRange = true;
+        out << name;
+    }
+    else if (name == "gl_FragCoord")
+    {
+        mUsesFragCoord = true;
+        out << name;
+    }
+    else if (name == "gl_PointCoord")
+    {
+        mUsesPointCoord = true;
+        out << name;
+    }
+    else if (name == "gl_FrontFacing")
+    {
+        mUsesFrontFacing = true;
+        out << name;
+    }
+    else if (name == "gl_PointSize")
+    {
+        mUsesPointSize = true;
+        out << name;
+    }
+    else if (name == "gl_FragDepthEXT")
+    {
+        mUsesFragDepth = true;
+        out << "gl_Depth";
+    }
+    else
+    {
+        TQualifier qualifier = node->getQualifier();
+
+        if (qualifier == EvqUniform)
+        {
+            mReferencedUniforms[name] = node;
+            out << decorateUniform(name, node->getType());
+        }
+        else if (qualifier == EvqAttribute)
+        {
+            mReferencedAttributes[name] = node;
+            out << decorate(name);
+        }
+        else if (qualifier == EvqVaryingOut || qualifier == EvqInvariantVaryingOut || qualifier == EvqVaryingIn || qualifier == EvqInvariantVaryingIn)
+        {
+            mReferencedVaryings[name] = node;
+            out << decorate(name);
+        }
+        else if (qualifier == EvqInternal)
+        {
+            out << name;
+        }
+        else
+        {
+            out << decorate(name);
+        }
+    }
+}
+
+bool OutputHLSL::visitBinary(Visit visit, TIntermBinary *node)
+{
+    TInfoSinkBase &out = mBody;
+
+    switch (node->getOp())
+    {
+      case EOpAssign:                  outputTriplet(visit, "(", " = ", ")");           break;
+      case EOpInitialize:
+        if (visit == PreVisit)
+        {
+            // GLSL allows to write things like "float x = x;" where a new variable x is defined
+            // and the value of an existing variable x is assigned. HLSL uses C semantics (the
+            // new variable is created before the assignment is evaluated), so we need to convert
+            // this to "float t = x, x = t;".
+
+            TIntermSymbol *symbolNode = node->getLeft()->getAsSymbolNode();
+            TIntermTyped *expression = node->getRight();
+
+            sh::SearchSymbol searchSymbol(symbolNode->getSymbol());
+            expression->traverse(&searchSymbol);
+            bool sameSymbol = searchSymbol.foundMatch();
+
+            if (sameSymbol)
+            {
+                // Type already printed
+                out << "t" + str(mUniqueIndex) + " = ";
+                expression->traverse(this);
+                out << ", ";
+                symbolNode->traverse(this);
+                out << " = t" + str(mUniqueIndex);
+
+                mUniqueIndex++;
+                return false;
+            }
+        }
+        else if (visit == InVisit)
+        {
+            out << " = ";
+        }
+        break;
+      case EOpAddAssign:               outputTriplet(visit, "(", " += ", ")");          break;
+      case EOpSubAssign:               outputTriplet(visit, "(", " -= ", ")");          break;
+      case EOpMulAssign:               outputTriplet(visit, "(", " *= ", ")");          break;
+      case EOpVectorTimesScalarAssign: outputTriplet(visit, "(", "