Add ANGLE as a 3rdparty library to Qt.
authorJason Barron <jason.barron@digia.com>
Mon, 15 Oct 2012 12:16:51 +0000 (14:16 +0200)
committerThe Qt Project <gerrit-noreply@qt-project.org>
Wed, 24 Oct 2012 00:29:15 +0000 (02:29 +0200)
ANGLE is a component that implements the OpenGL ES 2.0 API on
top of DirectX 9. See the following for more info:

http://code.google.com/p/angleproject/

ANGLE is now the default configuration on Windows. If you
want to use desktop OpenGL, you should build Qt with the
following configure options:

    -opengl desktop

To configure Qt to use another OpenGL ES 2 implementation,
you should use:

    -opengl es2 -no-angle

Task-number: QTBUG-24207

Change-Id: Iefcbeaa37ed920f431729749ab8333b248fe5134
Reviewed-by: Friedemann Kleint <Friedemann.Kleint@digia.com>
239 files changed:
src/3rdparty/angle/.gitignore [new file with mode: 0644]
src/3rdparty/angle/AUTHORS [new file with mode: 0644]
src/3rdparty/angle/CONTRIBUTORS [new file with mode: 0644]
src/3rdparty/angle/LICENSE [new file with mode: 0644]
src/3rdparty/angle/LICENSE.preprocessor [new file with mode: 0644]
src/3rdparty/angle/include/EGL/egl.h [new file with mode: 0644]
src/3rdparty/angle/include/EGL/eglext.h [new file with mode: 0644]
src/3rdparty/angle/include/EGL/eglplatform.h [new file with mode: 0644]
src/3rdparty/angle/include/GLES2/gl2.h [new file with mode: 0644]
src/3rdparty/angle/include/GLES2/gl2ext.h [new file with mode: 0644]
src/3rdparty/angle/include/GLES2/gl2platform.h [new file with mode: 0644]
src/3rdparty/angle/include/GLSLANG/ShaderLang.h [new file with mode: 0644]
src/3rdparty/angle/include/KHR/khrplatform.h [new file with mode: 0644]
src/3rdparty/angle/src/common/RefCountObject.cpp [new file with mode: 0644]
src/3rdparty/angle/src/common/RefCountObject.h [new file with mode: 0644]
src/3rdparty/angle/src/common/angleutils.h [new file with mode: 0644]
src/3rdparty/angle/src/common/debug.cpp [new file with mode: 0644]
src/3rdparty/angle/src/common/debug.h [new file with mode: 0644]
src/3rdparty/angle/src/common/version.h [new file with mode: 0644]
src/3rdparty/angle/src/compiler/BaseTypes.h [new file with mode: 0644]
src/3rdparty/angle/src/compiler/BuiltInFunctionEmulator.cpp [new file with mode: 0644]
src/3rdparty/angle/src/compiler/BuiltInFunctionEmulator.h [new file with mode: 0644]
src/3rdparty/angle/src/compiler/CodeGenGLSL.cpp [new file with mode: 0644]
src/3rdparty/angle/src/compiler/CodeGenHLSL.cpp [new file with mode: 0644]
src/3rdparty/angle/src/compiler/Common.h [new file with mode: 0644]
src/3rdparty/angle/src/compiler/Compiler.cpp [new file with mode: 0644]
src/3rdparty/angle/src/compiler/ConstantUnion.h [new file with mode: 0644]
src/3rdparty/angle/src/compiler/DetectDiscontinuity.cpp [new file with mode: 0644]
src/3rdparty/angle/src/compiler/DetectDiscontinuity.h [new file with mode: 0644]
src/3rdparty/angle/src/compiler/DetectRecursion.cpp [new file with mode: 0644]
src/3rdparty/angle/src/compiler/DetectRecursion.h [new file with mode: 0644]
src/3rdparty/angle/src/compiler/Diagnostics.cpp [new file with mode: 0644]
src/3rdparty/angle/src/compiler/Diagnostics.h [new file with mode: 0644]
src/3rdparty/angle/src/compiler/DirectiveHandler.cpp [new file with mode: 0644]
src/3rdparty/angle/src/compiler/DirectiveHandler.h [new file with mode: 0644]
src/3rdparty/angle/src/compiler/ExtensionBehavior.h [new file with mode: 0644]
src/3rdparty/angle/src/compiler/ForLoopUnroll.cpp [new file with mode: 0644]
src/3rdparty/angle/src/compiler/ForLoopUnroll.h [new file with mode: 0644]
src/3rdparty/angle/src/compiler/InfoSink.cpp [new file with mode: 0644]
src/3rdparty/angle/src/compiler/InfoSink.h [new file with mode: 0644]
src/3rdparty/angle/src/compiler/Initialize.cpp [new file with mode: 0644]
src/3rdparty/angle/src/compiler/Initialize.h [new file with mode: 0644]
src/3rdparty/angle/src/compiler/InitializeDll.cpp [new file with mode: 0644]
src/3rdparty/angle/src/compiler/InitializeDll.h [new file with mode: 0644]
src/3rdparty/angle/src/compiler/InitializeGlobals.h [new file with mode: 0644]
src/3rdparty/angle/src/compiler/InitializeParseContext.cpp [new file with mode: 0644]
src/3rdparty/angle/src/compiler/InitializeParseContext.h [new file with mode: 0644]
src/3rdparty/angle/src/compiler/IntermTraverse.cpp [new file with mode: 0644]
src/3rdparty/angle/src/compiler/Intermediate.cpp [new file with mode: 0644]
src/3rdparty/angle/src/compiler/MMap.h [new file with mode: 0644]
src/3rdparty/angle/src/compiler/MapLongVariableNames.cpp [new file with mode: 0644]
src/3rdparty/angle/src/compiler/MapLongVariableNames.h [new file with mode: 0644]
src/3rdparty/angle/src/compiler/OutputESSL.cpp [new file with mode: 0644]
src/3rdparty/angle/src/compiler/OutputESSL.h [new file with mode: 0644]
src/3rdparty/angle/src/compiler/OutputGLSL.cpp [new file with mode: 0644]
src/3rdparty/angle/src/compiler/OutputGLSL.h [new file with mode: 0644]
src/3rdparty/angle/src/compiler/OutputGLSLBase.cpp [new file with mode: 0644]
src/3rdparty/angle/src/compiler/OutputGLSLBase.h [new file with mode: 0644]
src/3rdparty/angle/src/compiler/OutputHLSL.cpp [new file with mode: 0644]
src/3rdparty/angle/src/compiler/OutputHLSL.h [new file with mode: 0644]
src/3rdparty/angle/src/compiler/ParseHelper.cpp [new file with mode: 0644]
src/3rdparty/angle/src/compiler/ParseHelper.h [new file with mode: 0644]
src/3rdparty/angle/src/compiler/PoolAlloc.cpp [new file with mode: 0644]
src/3rdparty/angle/src/compiler/PoolAlloc.h [new file with mode: 0644]
src/3rdparty/angle/src/compiler/Pragma.h [new file with mode: 0644]
src/3rdparty/angle/src/compiler/QualifierAlive.cpp [new file with mode: 0644]
src/3rdparty/angle/src/compiler/QualifierAlive.h [new file with mode: 0644]
src/3rdparty/angle/src/compiler/RemoveTree.cpp [new file with mode: 0644]
src/3rdparty/angle/src/compiler/RemoveTree.h [new file with mode: 0644]
src/3rdparty/angle/src/compiler/RenameFunction.h [new file with mode: 0644]
src/3rdparty/angle/src/compiler/SearchSymbol.cpp [new file with mode: 0644]
src/3rdparty/angle/src/compiler/SearchSymbol.h [new file with mode: 0644]
src/3rdparty/angle/src/compiler/ShHandle.h [new file with mode: 0644]
src/3rdparty/angle/src/compiler/ShaderLang.cpp [new file with mode: 0644]
src/3rdparty/angle/src/compiler/SymbolTable.cpp [new file with mode: 0644]
src/3rdparty/angle/src/compiler/SymbolTable.h [new file with mode: 0644]
src/3rdparty/angle/src/compiler/TranslatorESSL.cpp [new file with mode: 0644]
src/3rdparty/angle/src/compiler/TranslatorESSL.h [new file with mode: 0644]
src/3rdparty/angle/src/compiler/TranslatorGLSL.cpp [new file with mode: 0644]
src/3rdparty/angle/src/compiler/TranslatorGLSL.h [new file with mode: 0644]
src/3rdparty/angle/src/compiler/TranslatorHLSL.cpp [new file with mode: 0644]
src/3rdparty/angle/src/compiler/TranslatorHLSL.h [new file with mode: 0644]
src/3rdparty/angle/src/compiler/Types.h [new file with mode: 0644]
src/3rdparty/angle/src/compiler/UnfoldShortCircuit.cpp [new file with mode: 0644]
src/3rdparty/angle/src/compiler/UnfoldShortCircuit.h [new file with mode: 0644]
src/3rdparty/angle/src/compiler/ValidateLimitations.cpp [new file with mode: 0644]
src/3rdparty/angle/src/compiler/ValidateLimitations.h [new file with mode: 0644]
src/3rdparty/angle/src/compiler/VariableInfo.cpp [new file with mode: 0644]
src/3rdparty/angle/src/compiler/VariableInfo.h [new file with mode: 0644]
src/3rdparty/angle/src/compiler/VariablePacker.cpp [new file with mode: 0644]
src/3rdparty/angle/src/compiler/VariablePacker.h [new file with mode: 0644]
src/3rdparty/angle/src/compiler/VersionGLSL.cpp [new file with mode: 0644]
src/3rdparty/angle/src/compiler/VersionGLSL.h [new file with mode: 0644]
src/3rdparty/angle/src/compiler/debug.cpp [new file with mode: 0644]
src/3rdparty/angle/src/compiler/debug.h [new file with mode: 0644]
src/3rdparty/angle/src/compiler/depgraph/DependencyGraph.cpp [new file with mode: 0644]
src/3rdparty/angle/src/compiler/depgraph/DependencyGraph.h [new file with mode: 0644]
src/3rdparty/angle/src/compiler/depgraph/DependencyGraphBuilder.cpp [new file with mode: 0644]
src/3rdparty/angle/src/compiler/depgraph/DependencyGraphBuilder.h [new file with mode: 0644]
src/3rdparty/angle/src/compiler/depgraph/DependencyGraphOutput.cpp [new file with mode: 0644]
src/3rdparty/angle/src/compiler/depgraph/DependencyGraphOutput.h [new file with mode: 0644]
src/3rdparty/angle/src/compiler/depgraph/DependencyGraphTraverse.cpp [new file with mode: 0644]
src/3rdparty/angle/src/compiler/glslang.h [new file with mode: 0644]
src/3rdparty/angle/src/compiler/glslang.l [new file with mode: 0644]
src/3rdparty/angle/src/compiler/glslang.y [new file with mode: 0644]
src/3rdparty/angle/src/compiler/intermOut.cpp [new file with mode: 0644]
src/3rdparty/angle/src/compiler/intermediate.h [new file with mode: 0644]
src/3rdparty/angle/src/compiler/localintermediate.h [new file with mode: 0644]
src/3rdparty/angle/src/compiler/osinclude.h [new file with mode: 0644]
src/3rdparty/angle/src/compiler/ossource_nspr.cpp [new file with mode: 0644]
src/3rdparty/angle/src/compiler/ossource_posix.cpp [new file with mode: 0644]
src/3rdparty/angle/src/compiler/ossource_win.cpp [new file with mode: 0644]
src/3rdparty/angle/src/compiler/parseConst.cpp [new file with mode: 0644]
src/3rdparty/angle/src/compiler/preprocessor/atom.c [new file with mode: 0644]
src/3rdparty/angle/src/compiler/preprocessor/atom.h [new file with mode: 0644]
src/3rdparty/angle/src/compiler/preprocessor/compile.h [new file with mode: 0644]
src/3rdparty/angle/src/compiler/preprocessor/cpp.c [new file with mode: 0644]
src/3rdparty/angle/src/compiler/preprocessor/cpp.h [new file with mode: 0644]
src/3rdparty/angle/src/compiler/preprocessor/cppstruct.c [new file with mode: 0644]
src/3rdparty/angle/src/compiler/preprocessor/length_limits.h [new file with mode: 0644]
src/3rdparty/angle/src/compiler/preprocessor/memory.c [new file with mode: 0644]
src/3rdparty/angle/src/compiler/preprocessor/memory.h [new file with mode: 0644]
src/3rdparty/angle/src/compiler/preprocessor/new/Diagnostics.cpp [new file with mode: 0644]
src/3rdparty/angle/src/compiler/preprocessor/new/Diagnostics.h [new file with mode: 0644]
src/3rdparty/angle/src/compiler/preprocessor/new/DirectiveHandler.cpp [new file with mode: 0644]
src/3rdparty/angle/src/compiler/preprocessor/new/DirectiveHandler.h [new file with mode: 0644]
src/3rdparty/angle/src/compiler/preprocessor/new/DirectiveParser.cpp [new file with mode: 0644]
src/3rdparty/angle/src/compiler/preprocessor/new/DirectiveParser.h [new file with mode: 0644]
src/3rdparty/angle/src/compiler/preprocessor/new/ExpressionParser.h [new file with mode: 0644]
src/3rdparty/angle/src/compiler/preprocessor/new/ExpressionParser.y [new file with mode: 0644]
src/3rdparty/angle/src/compiler/preprocessor/new/Input.cpp [new file with mode: 0644]
src/3rdparty/angle/src/compiler/preprocessor/new/Input.h [new file with mode: 0644]
src/3rdparty/angle/src/compiler/preprocessor/new/Lexer.cpp [new file with mode: 0644]
src/3rdparty/angle/src/compiler/preprocessor/new/Lexer.h [new file with mode: 0644]
src/3rdparty/angle/src/compiler/preprocessor/new/Macro.cpp [new file with mode: 0644]
src/3rdparty/angle/src/compiler/preprocessor/new/Macro.h [new file with mode: 0644]
src/3rdparty/angle/src/compiler/preprocessor/new/MacroExpander.cpp [new file with mode: 0644]
src/3rdparty/angle/src/compiler/preprocessor/new/MacroExpander.h [new file with mode: 0644]
src/3rdparty/angle/src/compiler/preprocessor/new/Preprocessor.cpp [new file with mode: 0644]
src/3rdparty/angle/src/compiler/preprocessor/new/Preprocessor.h [new file with mode: 0644]
src/3rdparty/angle/src/compiler/preprocessor/new/SourceLocation.h [new file with mode: 0644]
src/3rdparty/angle/src/compiler/preprocessor/new/Token.cpp [new file with mode: 0644]
src/3rdparty/angle/src/compiler/preprocessor/new/Token.h [new file with mode: 0644]
src/3rdparty/angle/src/compiler/preprocessor/new/Tokenizer.h [new file with mode: 0644]
src/3rdparty/angle/src/compiler/preprocessor/new/Tokenizer.l [new file with mode: 0644]
src/3rdparty/angle/src/compiler/preprocessor/new/numeric_lex.h [new file with mode: 0644]
src/3rdparty/angle/src/compiler/preprocessor/new/pp_utils.h [new file with mode: 0644]
src/3rdparty/angle/src/compiler/preprocessor/parser.h [new file with mode: 0644]
src/3rdparty/angle/src/compiler/preprocessor/preprocess.h [new file with mode: 0644]
src/3rdparty/angle/src/compiler/preprocessor/scanner.c [new file with mode: 0644]
src/3rdparty/angle/src/compiler/preprocessor/scanner.h [new file with mode: 0644]
src/3rdparty/angle/src/compiler/preprocessor/slglobals.h [new file with mode: 0644]
src/3rdparty/angle/src/compiler/preprocessor/symbols.c [new file with mode: 0644]
src/3rdparty/angle/src/compiler/preprocessor/symbols.h [new file with mode: 0644]
src/3rdparty/angle/src/compiler/preprocessor/tokens.c [new file with mode: 0644]
src/3rdparty/angle/src/compiler/preprocessor/tokens.h [new file with mode: 0644]
src/3rdparty/angle/src/compiler/timing/RestrictFragmentShaderTiming.cpp [new file with mode: 0644]
src/3rdparty/angle/src/compiler/timing/RestrictFragmentShaderTiming.h [new file with mode: 0644]
src/3rdparty/angle/src/compiler/timing/RestrictVertexShaderTiming.cpp [new file with mode: 0644]
src/3rdparty/angle/src/compiler/timing/RestrictVertexShaderTiming.h [new file with mode: 0644]
src/3rdparty/angle/src/compiler/util.cpp [new file with mode: 0644]
src/3rdparty/angle/src/compiler/util.h [new file with mode: 0644]
src/3rdparty/angle/src/libEGL/Config.cpp [new file with mode: 0644]
src/3rdparty/angle/src/libEGL/Config.h [new file with mode: 0644]
src/3rdparty/angle/src/libEGL/Display.cpp [new file with mode: 0644]
src/3rdparty/angle/src/libEGL/Display.h [new file with mode: 0644]
src/3rdparty/angle/src/libEGL/ShaderCache.h [new file with mode: 0644]
src/3rdparty/angle/src/libEGL/Surface.cpp [new file with mode: 0644]
src/3rdparty/angle/src/libEGL/Surface.h [new file with mode: 0644]
src/3rdparty/angle/src/libEGL/libEGL.cpp [new file with mode: 0644]
src/3rdparty/angle/src/libEGL/libEGL.def [new file with mode: 0644]
src/3rdparty/angle/src/libEGL/libEGL.rc [new file with mode: 0644]
src/3rdparty/angle/src/libEGL/main.cpp [new file with mode: 0644]
src/3rdparty/angle/src/libEGL/main.h [new file with mode: 0644]
src/3rdparty/angle/src/libEGL/resource.h [new file with mode: 0644]
src/3rdparty/angle/src/libGLESv2/BinaryStream.h [new file with mode: 0644]
src/3rdparty/angle/src/libGLESv2/Blit.cpp [new file with mode: 0644]
src/3rdparty/angle/src/libGLESv2/Blit.h [new file with mode: 0644]
src/3rdparty/angle/src/libGLESv2/Buffer.cpp [new file with mode: 0644]
src/3rdparty/angle/src/libGLESv2/Buffer.h [new file with mode: 0644]
src/3rdparty/angle/src/libGLESv2/Context.cpp [new file with mode: 0644]
src/3rdparty/angle/src/libGLESv2/Context.h [new file with mode: 0644]
src/3rdparty/angle/src/libGLESv2/D3DConstantTable.cpp [new file with mode: 0644]
src/3rdparty/angle/src/libGLESv2/D3DConstantTable.h [new file with mode: 0644]
src/3rdparty/angle/src/libGLESv2/Fence.cpp [new file with mode: 0644]
src/3rdparty/angle/src/libGLESv2/Fence.h [new file with mode: 0644]
src/3rdparty/angle/src/libGLESv2/Float16ToFloat32.cpp [new file with mode: 0644]
src/3rdparty/angle/src/libGLESv2/Float16ToFloat32.py [new file with mode: 0644]
src/3rdparty/angle/src/libGLESv2/Framebuffer.cpp [new file with mode: 0644]
src/3rdparty/angle/src/libGLESv2/Framebuffer.h [new file with mode: 0644]
src/3rdparty/angle/src/libGLESv2/HandleAllocator.cpp [new file with mode: 0644]
src/3rdparty/angle/src/libGLESv2/HandleAllocator.h [new file with mode: 0644]
src/3rdparty/angle/src/libGLESv2/IndexDataManager.cpp [new file with mode: 0644]
src/3rdparty/angle/src/libGLESv2/IndexDataManager.h [new file with mode: 0644]
src/3rdparty/angle/src/libGLESv2/Program.cpp [new file with mode: 0644]
src/3rdparty/angle/src/libGLESv2/Program.h [new file with mode: 0644]
src/3rdparty/angle/src/libGLESv2/ProgramBinary.cpp [new file with mode: 0644]
src/3rdparty/angle/src/libGLESv2/ProgramBinary.h [new file with mode: 0644]
src/3rdparty/angle/src/libGLESv2/Query.cpp [new file with mode: 0644]
src/3rdparty/angle/src/libGLESv2/Query.h [new file with mode: 0644]
src/3rdparty/angle/src/libGLESv2/Renderbuffer.cpp [new file with mode: 0644]
src/3rdparty/angle/src/libGLESv2/Renderbuffer.h [new file with mode: 0644]
src/3rdparty/angle/src/libGLESv2/ResourceManager.cpp [new file with mode: 0644]
src/3rdparty/angle/src/libGLESv2/ResourceManager.h [new file with mode: 0644]
src/3rdparty/angle/src/libGLESv2/Shader.cpp [new file with mode: 0644]
src/3rdparty/angle/src/libGLESv2/Shader.h [new file with mode: 0644]
src/3rdparty/angle/src/libGLESv2/Texture.cpp [new file with mode: 0644]
src/3rdparty/angle/src/libGLESv2/Texture.h [new file with mode: 0644]
src/3rdparty/angle/src/libGLESv2/TextureSSE2.cpp [new file with mode: 0644]
src/3rdparty/angle/src/libGLESv2/VertexDataManager.cpp [new file with mode: 0644]
src/3rdparty/angle/src/libGLESv2/VertexDataManager.h [new file with mode: 0644]
src/3rdparty/angle/src/libGLESv2/libGLESv2.cpp [new file with mode: 0644]
src/3rdparty/angle/src/libGLESv2/libGLESv2.def [new file with mode: 0644]
src/3rdparty/angle/src/libGLESv2/libGLESv2.rc [new file with mode: 0644]
src/3rdparty/angle/src/libGLESv2/main.cpp [new file with mode: 0644]
src/3rdparty/angle/src/libGLESv2/main.h [new file with mode: 0644]
src/3rdparty/angle/src/libGLESv2/mathutil.h [new file with mode: 0644]
src/3rdparty/angle/src/libGLESv2/resource.h [new file with mode: 0644]
src/3rdparty/angle/src/libGLESv2/shaders/Blit.ps [new file with mode: 0644]
src/3rdparty/angle/src/libGLESv2/shaders/Blit.vs [new file with mode: 0644]
src/3rdparty/angle/src/libGLESv2/utilities.cpp [new file with mode: 0644]
src/3rdparty/angle/src/libGLESv2/utilities.h [new file with mode: 0644]
src/3rdparty/angle/src/libGLESv2/vertexconversion.h [new file with mode: 0644]
src/angle/README.qt [new file with mode: 0644]
src/angle/angle.pro [new file with mode: 0644]
src/angle/patches/0003-Fix-Float16ToFloat32.py.patch [new file with mode: 0644]
src/angle/src/common/common.pri [new file with mode: 0644]
src/angle/src/compiler/compiler.pro [new file with mode: 0644]
src/angle/src/compiler/preprocessor/preprocessor.pro [new file with mode: 0644]
src/angle/src/compiler/translator_common.pro [new file with mode: 0644]
src/angle/src/compiler/translator_hlsl.pro [new file with mode: 0644]
src/angle/src/config.pri [new file with mode: 0644]
src/angle/src/libEGL/libEGL.pro [new file with mode: 0644]
src/angle/src/libGLESv2/libGLESv2.pro [new file with mode: 0644]
src/angle/src/src.pro [new file with mode: 0644]
src/plugins/platforms/windows/qwindowseglcontext.cpp
src/src.pro
sync.profile
tools/configure/configureapp.cpp

diff --git a/src/3rdparty/angle/.gitignore b/src/3rdparty/angle/.gitignore
new file mode 100644 (file)
index 0000000..cfa07de
--- /dev/null
@@ -0,0 +1,35 @@
+# This file is used to ignore files which are generated when building ANGLE
+# ----------------------------------------------------------------------------
+
+# Directories from ANGLE we don't want/need
+build
+extensions
+samples
+tests
+third_party
+src/ipch
+.svn
+
+# Files from ANGLE we don't want/need
+DEPS
+*.gyp
+*.gypi
+*.sh
+*.bat
+codereview.settings
+
+# Generated by flex/bison
+src/compiler/preprocessor/new/Tokenizer.cpp
+src/compiler/preprocessor/new/ExpressionParser.cpp
+src/compiler/glslang_lex.cpp
+src/compiler/glslang_tab.cpp
+src/compiler/glslang_tab.h
+
+# Generated by FXC
+src/libGLESv2/shaders/standardvs.h
+src/libGLESv2/shaders/flipyvs.h
+src/libGLESv2/shaders/luminanceps.h
+src/libGLESv2/shaders/componentmaskps.h
+src/libGLESv2/shaders/passthroughps.h
+
+
diff --git a/src/3rdparty/angle/AUTHORS b/src/3rdparty/angle/AUTHORS
new file mode 100644 (file)
index 0000000..0294632
--- /dev/null
@@ -0,0 +1,30 @@
+# This is the official list of The ANGLE Project Authors
+# for copyright purposes.
+# This file is distinct from the CONTRIBUTORS files.
+# See the latter for an explanation.
+
+# Names should be added to this file as
+#      Name or Organization
+# Email addresses for individuals are tracked elsewhere to avoid spam.
+
+Google Inc.
+TransGaming Inc.
+3DLabs Inc. Ltd.
+
+Adobe Systems Inc.
+Autodesk, Inc.
+Cloud Party, Inc.
+Intel Corporation
+Mozilla Corporation
+Turbulenz
+
+Jacek Caban
+Mark Callow
+Ginn Chen
+James Hauxwell
+Sam Hocevar
+Pierre Leveille
+Boying Lu
+Aitor Moreno
+Yuri O'Donnell
+Josh Soref
diff --git a/src/3rdparty/angle/CONTRIBUTORS b/src/3rdparty/angle/CONTRIBUTORS
new file mode 100644 (file)
index 0000000..29f9ad3
--- /dev/null
@@ -0,0 +1,70 @@
+# This is the official list of people who can contribute
+# (and who have contributed) code to the ANGLE project
+# repository.
+# The AUTHORS file lists the copyright holders; this file
+# lists people.  For example, Google employees are listed here
+# but not in AUTHORS, because Google holds the copyright.
+#
+
+TransGaming Inc.
+ Nicolas Capens
+ Daniel Koch
+ Andrew Lewycky
+ Gavriel State
+ Shannon Woods
+
+Google Inc.
+ Brent Austin
+ Michael Bai
+ John Bauman
+ Peter Beverloo
+ Steve Block
+ Rachel Blum
+ Eric Boren
+ Henry Bridge
+ Nat Duca
+ Peter Kasting
+ Vangelis Kokkevis
+ Zhenyao Mo
+ Daniel Nicoara
+ Alastair Patrick
+ Alok Priyadarshi
+ Kenneth Russell
+ Brian Salomon
+ Gregg Tavares
+ Jeff Timanus
+ Ben Vanik
+ Adrienne Walker
+ thestig@chromium.org
+
+Adobe Systems Inc.
+ Alexandru Chiculita
+ Steve Minns
+ Max Vujovic
+
+Autodesk, Inc.
+ Ranger Harke
+
+Cloud Party, Inc.
+ Conor Dickinson
+
+Intel Corporation
+ Jin Yang
+ Andy Chen
+ Josh Triplett
+
+Mozilla Corp.
+ Ehsan Akhgari
+ Jeff Gilbert
+ Mike Hommey
+ Benoit Jacob
+ Makoto Kato
+ Vladimir Vukicevic
+
+Turbulenz
+ Michael Braithwaite
+
+Ulrik Persson (ddefrostt)
+Mark Banner (standard8mbp)
+David Kilzer
+
diff --git a/src/3rdparty/angle/LICENSE b/src/3rdparty/angle/LICENSE
new file mode 100644 (file)
index 0000000..0513b7d
--- /dev/null
@@ -0,0 +1,32 @@
+// Copyright (C) 2002-2010 The ANGLE Project Authors. 
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+//
+//     Redistributions of source code must retain the above copyright
+//     notice, this list of conditions and the following disclaimer.
+//
+//     Redistributions in binary form must reproduce the above 
+//     copyright notice, this list of conditions and the following
+//     disclaimer in the documentation and/or other materials provided
+//     with the distribution.
+//
+//     Neither the name of TransGaming Inc., Google Inc., 3DLabs Inc.
+//     Ltd., nor the names of their contributors may be used to endorse
+//     or promote products derived from this software without specific
+//     prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+// COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+// POSSIBILITY OF SUCH DAMAGE.
diff --git a/src/3rdparty/angle/LICENSE.preprocessor b/src/3rdparty/angle/LICENSE.preprocessor
new file mode 100644 (file)
index 0000000..0ec2123
--- /dev/null
@@ -0,0 +1,45 @@
+Files in src/compiler/preprocessor are provided under the following license:
+
+****************************************************************************
+Copyright (c) 2002, NVIDIA Corporation.
+
+NVIDIA Corporation("NVIDIA") supplies this software to you in
+consideration of your agreement to the following terms, and your use,
+installation, modification or redistribution of this NVIDIA software
+constitutes acceptance of these terms.  If you do not agree with these
+terms, please do not use, install, modify or redistribute this NVIDIA
+software.
+
+In consideration of your agreement to abide by the following terms, and
+subject to these terms, NVIDIA grants you a personal, non-exclusive
+license, under NVIDIA's copyrights in this original NVIDIA software (the
+"NVIDIA Software"), to use, reproduce, modify and redistribute the
+NVIDIA Software, with or without modifications, in source and/or binary
+forms; provided that if you redistribute the NVIDIA Software, you must
+retain the copyright notice of NVIDIA, this notice and the following
+text and disclaimers in all such redistributions of the NVIDIA Software.
+Neither the name, trademarks, service marks nor logos of NVIDIA
+Corporation may be used to endorse or promote products derived from the
+NVIDIA Software without specific prior written permission from NVIDIA.
+Except as expressly stated in this notice, no other rights or licenses
+express or implied, are granted by NVIDIA herein, including but not
+limited to any patent rights that may be infringed by your derivative
+works or by other works in which the NVIDIA Software may be
+incorporated. No hardware is licensed hereunder. 
+
+THE NVIDIA SOFTWARE IS BEING PROVIDED ON AN "AS IS" BASIS, WITHOUT
+WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED,
+INCLUDING WITHOUT LIMITATION, WARRANTIES OR CONDITIONS OF TITLE,
+NON-INFRINGEMENT, MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR
+ITS USE AND OPERATION EITHER ALONE OR IN COMBINATION WITH OTHER
+PRODUCTS.
+
+IN NO EVENT SHALL NVIDIA BE LIABLE FOR ANY SPECIAL, INDIRECT,
+INCIDENTAL, EXEMPLARY, CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+TO, LOST PROFITS; PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) OR ARISING IN ANY WAY
+OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE
+NVIDIA SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT,
+TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF
+NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+****************************************************************************
diff --git a/src/3rdparty/angle/include/EGL/egl.h b/src/3rdparty/angle/include/EGL/egl.h
new file mode 100644 (file)
index 0000000..99ea342
--- /dev/null
@@ -0,0 +1,329 @@
+/* -*- mode: c; tab-width: 8; -*- */
+/* vi: set sw=4 ts=8: */
+/* Reference version of egl.h for EGL 1.4.
+ * $Revision: 9356 $ on $Date: 2009-10-21 02:52:25 -0700 (Wed, 21 Oct 2009) $
+ */
+
+/*
+** Copyright (c) 2007-2009 The Khronos Group Inc.
+**
+** Permission is hereby granted, free of charge, to any person obtaining a
+** copy of this software and/or associated documentation files (the
+** "Materials"), to deal in the Materials without restriction, including
+** without limitation the rights to use, copy, modify, merge, publish,
+** distribute, sublicense, and/or sell copies of the Materials, and to
+** permit persons to whom the Materials are furnished to do so, subject to
+** the following conditions:
+**
+** The above copyright notice and this permission notice shall be included
+** in all copies or substantial portions of the Materials.
+**
+** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+*/
+
+#ifndef __egl_h_
+#define __egl_h_
+
+/* All platform-dependent types and macro boilerplate (such as EGLAPI
+ * and EGLAPIENTRY) should go in eglplatform.h.
+ */
+#include <EGL/eglplatform.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* EGL Types */
+/* EGLint is defined in eglplatform.h */
+typedef unsigned int EGLBoolean;
+typedef unsigned int EGLenum;
+typedef void *EGLConfig;
+typedef void *EGLContext;
+typedef void *EGLDisplay;
+typedef void *EGLSurface;
+typedef void *EGLClientBuffer;
+
+/* EGL Versioning */
+#define EGL_VERSION_1_0                        1
+#define EGL_VERSION_1_1                        1
+#define EGL_VERSION_1_2                        1
+#define EGL_VERSION_1_3                        1
+#define EGL_VERSION_1_4                        1
+
+/* EGL Enumerants. Bitmasks and other exceptional cases aside, most
+ * enums are assigned unique values starting at 0x3000.
+ */
+
+/* EGL aliases */
+#define EGL_FALSE                      0
+#define EGL_TRUE                       1
+
+/* Out-of-band handle values */
+#define EGL_DEFAULT_DISPLAY            ((EGLNativeDisplayType)0)
+#define EGL_NO_CONTEXT                 ((EGLContext)0)
+#define EGL_NO_DISPLAY                 ((EGLDisplay)0)
+#define EGL_NO_SURFACE                 ((EGLSurface)0)
+
+/* Out-of-band attribute value */
+#define EGL_DONT_CARE                  ((EGLint)-1)
+
+/* Errors / GetError return values */
+#define EGL_SUCCESS                    0x3000
+#define EGL_NOT_INITIALIZED            0x3001
+#define EGL_BAD_ACCESS                 0x3002
+#define EGL_BAD_ALLOC                  0x3003
+#define EGL_BAD_ATTRIBUTE              0x3004
+#define EGL_BAD_CONFIG                 0x3005
+#define EGL_BAD_CONTEXT                        0x3006
+#define EGL_BAD_CURRENT_SURFACE                0x3007
+#define EGL_BAD_DISPLAY                        0x3008
+#define EGL_BAD_MATCH                  0x3009
+#define EGL_BAD_NATIVE_PIXMAP          0x300A
+#define EGL_BAD_NATIVE_WINDOW          0x300B
+#define EGL_BAD_PARAMETER              0x300C
+#define EGL_BAD_SURFACE                        0x300D
+#define EGL_CONTEXT_LOST               0x300E  /* EGL 1.1 - IMG_power_management */
+
+/* Reserved 0x300F-0x301F for additional errors */
+
+/* Config attributes */
+#define EGL_BUFFER_SIZE                        0x3020
+#define EGL_ALPHA_SIZE                 0x3021
+#define EGL_BLUE_SIZE                  0x3022
+#define EGL_GREEN_SIZE                 0x3023
+#define EGL_RED_SIZE                   0x3024
+#define EGL_DEPTH_SIZE                 0x3025
+#define EGL_STENCIL_SIZE               0x3026
+#define EGL_CONFIG_CAVEAT              0x3027
+#define EGL_CONFIG_ID                  0x3028
+#define EGL_LEVEL                      0x3029
+#define EGL_MAX_PBUFFER_HEIGHT         0x302A
+#define EGL_MAX_PBUFFER_PIXELS         0x302B
+#define EGL_MAX_PBUFFER_WIDTH          0x302C
+#define EGL_NATIVE_RENDERABLE          0x302D
+#define EGL_NATIVE_VISUAL_ID           0x302E
+#define EGL_NATIVE_VISUAL_TYPE         0x302F
+#define EGL_SAMPLES                    0x3031
+#define EGL_SAMPLE_BUFFERS             0x3032
+#define EGL_SURFACE_TYPE               0x3033
+#define EGL_TRANSPARENT_TYPE           0x3034
+#define EGL_TRANSPARENT_BLUE_VALUE     0x3035
+#define EGL_TRANSPARENT_GREEN_VALUE    0x3036
+#define EGL_TRANSPARENT_RED_VALUE      0x3037
+#define EGL_NONE                       0x3038  /* Attrib list terminator */
+#define EGL_BIND_TO_TEXTURE_RGB                0x3039
+#define EGL_BIND_TO_TEXTURE_RGBA       0x303A
+#define EGL_MIN_SWAP_INTERVAL          0x303B
+#define EGL_MAX_SWAP_INTERVAL          0x303C
+#define EGL_LUMINANCE_SIZE             0x303D
+#define EGL_ALPHA_MASK_SIZE            0x303E
+#define EGL_COLOR_BUFFER_TYPE          0x303F
+#define EGL_RENDERABLE_TYPE            0x3040
+#define EGL_MATCH_NATIVE_PIXMAP                0x3041  /* Pseudo-attribute (not queryable) */
+#define EGL_CONFORMANT                 0x3042
+
+/* Reserved 0x3041-0x304F for additional config attributes */
+
+/* Config attribute values */
+#define EGL_SLOW_CONFIG                        0x3050  /* EGL_CONFIG_CAVEAT value */
+#define EGL_NON_CONFORMANT_CONFIG      0x3051  /* EGL_CONFIG_CAVEAT value */
+#define EGL_TRANSPARENT_RGB            0x3052  /* EGL_TRANSPARENT_TYPE value */
+#define EGL_RGB_BUFFER                 0x308E  /* EGL_COLOR_BUFFER_TYPE value */
+#define EGL_LUMINANCE_BUFFER           0x308F  /* EGL_COLOR_BUFFER_TYPE value */
+
+/* More config attribute values, for EGL_TEXTURE_FORMAT */
+#define EGL_NO_TEXTURE                 0x305C
+#define EGL_TEXTURE_RGB                        0x305D
+#define EGL_TEXTURE_RGBA               0x305E
+#define EGL_TEXTURE_2D                 0x305F
+
+/* Config attribute mask bits */
+#define EGL_PBUFFER_BIT                        0x0001  /* EGL_SURFACE_TYPE mask bits */
+#define EGL_PIXMAP_BIT                 0x0002  /* EGL_SURFACE_TYPE mask bits */
+#define EGL_WINDOW_BIT                 0x0004  /* EGL_SURFACE_TYPE mask bits */
+#define EGL_VG_COLORSPACE_LINEAR_BIT   0x0020  /* EGL_SURFACE_TYPE mask bits */
+#define EGL_VG_ALPHA_FORMAT_PRE_BIT    0x0040  /* EGL_SURFACE_TYPE mask bits */
+#define EGL_MULTISAMPLE_RESOLVE_BOX_BIT 0x0200 /* EGL_SURFACE_TYPE mask bits */
+#define EGL_SWAP_BEHAVIOR_PRESERVED_BIT 0x0400 /* EGL_SURFACE_TYPE mask bits */
+
+#define EGL_OPENGL_ES_BIT              0x0001  /* EGL_RENDERABLE_TYPE mask bits */
+#define EGL_OPENVG_BIT                 0x0002  /* EGL_RENDERABLE_TYPE mask bits */
+#define EGL_OPENGL_ES2_BIT             0x0004  /* EGL_RENDERABLE_TYPE mask bits */
+#define EGL_OPENGL_BIT                 0x0008  /* EGL_RENDERABLE_TYPE mask bits */
+
+/* QueryString targets */
+#define EGL_VENDOR                     0x3053
+#define EGL_VERSION                    0x3054
+#define EGL_EXTENSIONS                 0x3055
+#define EGL_CLIENT_APIS                        0x308D
+
+/* QuerySurface / SurfaceAttrib / CreatePbufferSurface targets */
+#define EGL_HEIGHT                     0x3056
+#define EGL_WIDTH                      0x3057
+#define EGL_LARGEST_PBUFFER            0x3058
+#define EGL_TEXTURE_FORMAT             0x3080
+#define EGL_TEXTURE_TARGET             0x3081
+#define EGL_MIPMAP_TEXTURE             0x3082
+#define EGL_MIPMAP_LEVEL               0x3083
+#define EGL_RENDER_BUFFER              0x3086
+#define EGL_VG_COLORSPACE              0x3087
+#define EGL_VG_ALPHA_FORMAT            0x3088
+#define EGL_HORIZONTAL_RESOLUTION      0x3090
+#define EGL_VERTICAL_RESOLUTION                0x3091
+#define EGL_PIXEL_ASPECT_RATIO         0x3092
+#define EGL_SWAP_BEHAVIOR              0x3093
+#define EGL_MULTISAMPLE_RESOLVE                0x3099
+
+/* EGL_RENDER_BUFFER values / BindTexImage / ReleaseTexImage buffer targets */
+#define EGL_BACK_BUFFER                        0x3084
+#define EGL_SINGLE_BUFFER              0x3085
+
+/* OpenVG color spaces */
+#define EGL_VG_COLORSPACE_sRGB         0x3089  /* EGL_VG_COLORSPACE value */
+#define EGL_VG_COLORSPACE_LINEAR       0x308A  /* EGL_VG_COLORSPACE value */
+
+/* OpenVG alpha formats */
+#define EGL_VG_ALPHA_FORMAT_NONPRE     0x308B  /* EGL_ALPHA_FORMAT value */
+#define EGL_VG_ALPHA_FORMAT_PRE                0x308C  /* EGL_ALPHA_FORMAT value */
+
+/* Constant scale factor by which fractional display resolutions &
+ * aspect ratio are scaled when queried as integer values.
+ */
+#define EGL_DISPLAY_SCALING            10000
+
+/* Unknown display resolution/aspect ratio */
+#define EGL_UNKNOWN                    ((EGLint)-1)
+
+/* Back buffer swap behaviors */
+#define EGL_BUFFER_PRESERVED           0x3094  /* EGL_SWAP_BEHAVIOR value */
+#define EGL_BUFFER_DESTROYED           0x3095  /* EGL_SWAP_BEHAVIOR value */
+
+/* CreatePbufferFromClientBuffer buffer types */
+#define EGL_OPENVG_IMAGE               0x3096
+
+/* QueryContext targets */
+#define EGL_CONTEXT_CLIENT_TYPE                0x3097
+
+/* CreateContext attributes */
+#define EGL_CONTEXT_CLIENT_VERSION     0x3098
+
+/* Multisample resolution behaviors */
+#define EGL_MULTISAMPLE_RESOLVE_DEFAULT 0x309A /* EGL_MULTISAMPLE_RESOLVE value */
+#define EGL_MULTISAMPLE_RESOLVE_BOX    0x309B  /* EGL_MULTISAMPLE_RESOLVE value */
+
+/* BindAPI/QueryAPI targets */
+#define EGL_OPENGL_ES_API              0x30A0
+#define EGL_OPENVG_API                 0x30A1
+#define EGL_OPENGL_API                 0x30A2
+
+/* GetCurrentSurface targets */
+#define EGL_DRAW                       0x3059
+#define EGL_READ                       0x305A
+
+/* WaitNative engines */
+#define EGL_CORE_NATIVE_ENGINE         0x305B
+
+/* EGL 1.2 tokens renamed for consistency in EGL 1.3 */
+#define EGL_COLORSPACE                 EGL_VG_COLORSPACE
+#define EGL_ALPHA_FORMAT               EGL_VG_ALPHA_FORMAT
+#define EGL_COLORSPACE_sRGB            EGL_VG_COLORSPACE_sRGB
+#define EGL_COLORSPACE_LINEAR          EGL_VG_COLORSPACE_LINEAR
+#define EGL_ALPHA_FORMAT_NONPRE                EGL_VG_ALPHA_FORMAT_NONPRE
+#define EGL_ALPHA_FORMAT_PRE           EGL_VG_ALPHA_FORMAT_PRE
+
+/* EGL extensions must request enum blocks from the Khronos
+ * API Registrar, who maintains the enumerant registry. Submit
+ * a bug in Khronos Bugzilla against task "Registry".
+ */
+
+
+
+/* EGL Functions */
+
+EGLAPI EGLint EGLAPIENTRY eglGetError(void);
+
+EGLAPI EGLDisplay EGLAPIENTRY eglGetDisplay(EGLNativeDisplayType display_id);
+EGLAPI EGLBoolean EGLAPIENTRY eglInitialize(EGLDisplay dpy, EGLint *major, EGLint *minor);
+EGLAPI EGLBoolean EGLAPIENTRY eglTerminate(EGLDisplay dpy);
+
+EGLAPI const char * EGLAPIENTRY eglQueryString(EGLDisplay dpy, EGLint name);
+
+EGLAPI EGLBoolean EGLAPIENTRY eglGetConfigs(EGLDisplay dpy, EGLConfig *configs,
+                        EGLint config_size, EGLint *num_config);
+EGLAPI EGLBoolean EGLAPIENTRY eglChooseConfig(EGLDisplay dpy, const EGLint *attrib_list,
+                          EGLConfig *configs, EGLint config_size,
+                          EGLint *num_config);
+EGLAPI EGLBoolean EGLAPIENTRY eglGetConfigAttrib(EGLDisplay dpy, EGLConfig config,
+                             EGLint attribute, EGLint *value);
+
+EGLAPI EGLSurface EGLAPIENTRY eglCreateWindowSurface(EGLDisplay dpy, EGLConfig config,
+                                 EGLNativeWindowType win,
+                                 const EGLint *attrib_list);
+EGLAPI EGLSurface EGLAPIENTRY eglCreatePbufferSurface(EGLDisplay dpy, EGLConfig config,
+                                  const EGLint *attrib_list);
+EGLAPI EGLSurface EGLAPIENTRY eglCreatePixmapSurface(EGLDisplay dpy, EGLConfig config,
+                                 EGLNativePixmapType pixmap,
+                                 const EGLint *attrib_list);
+EGLAPI EGLBoolean EGLAPIENTRY eglDestroySurface(EGLDisplay dpy, EGLSurface surface);
+EGLAPI EGLBoolean EGLAPIENTRY eglQuerySurface(EGLDisplay dpy, EGLSurface surface,
+                          EGLint attribute, EGLint *value);
+
+EGLAPI EGLBoolean EGLAPIENTRY eglBindAPI(EGLenum api);
+EGLAPI EGLenum EGLAPIENTRY eglQueryAPI(void);
+
+EGLAPI EGLBoolean EGLAPIENTRY eglWaitClient(void);
+
+EGLAPI EGLBoolean EGLAPIENTRY eglReleaseThread(void);
+
+EGLAPI EGLSurface EGLAPIENTRY eglCreatePbufferFromClientBuffer(
+             EGLDisplay dpy, EGLenum buftype, EGLClientBuffer buffer,
+             EGLConfig config, const EGLint *attrib_list);
+
+EGLAPI EGLBoolean EGLAPIENTRY eglSurfaceAttrib(EGLDisplay dpy, EGLSurface surface,
+                           EGLint attribute, EGLint value);
+EGLAPI EGLBoolean EGLAPIENTRY eglBindTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer);
+EGLAPI EGLBoolean EGLAPIENTRY eglReleaseTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer);
+
+
+EGLAPI EGLBoolean EGLAPIENTRY eglSwapInterval(EGLDisplay dpy, EGLint interval);
+
+
+EGLAPI EGLContext EGLAPIENTRY eglCreateContext(EGLDisplay dpy, EGLConfig config,
+                           EGLContext share_context,
+                           const EGLint *attrib_list);
+EGLAPI EGLBoolean EGLAPIENTRY eglDestroyContext(EGLDisplay dpy, EGLContext ctx);
+EGLAPI EGLBoolean EGLAPIENTRY eglMakeCurrent(EGLDisplay dpy, EGLSurface draw,
+                         EGLSurface read, EGLContext ctx);
+
+EGLAPI EGLContext EGLAPIENTRY eglGetCurrentContext(void);
+EGLAPI EGLSurface EGLAPIENTRY eglGetCurrentSurface(EGLint readdraw);
+EGLAPI EGLDisplay EGLAPIENTRY eglGetCurrentDisplay(void);
+EGLAPI EGLBoolean EGLAPIENTRY eglQueryContext(EGLDisplay dpy, EGLContext ctx,
+                          EGLint attribute, EGLint *value);
+
+EGLAPI EGLBoolean EGLAPIENTRY eglWaitGL(void);
+EGLAPI EGLBoolean EGLAPIENTRY eglWaitNative(EGLint engine);
+EGLAPI EGLBoolean EGLAPIENTRY eglSwapBuffers(EGLDisplay dpy, EGLSurface surface);
+EGLAPI EGLBoolean EGLAPIENTRY eglCopyBuffers(EGLDisplay dpy, EGLSurface surface,
+                         EGLNativePixmapType target);
+
+/* This is a generic function pointer type, whose name indicates it must
+ * be cast to the proper type *and calling convention* before use.
+ */
+typedef void (*__eglMustCastToProperFunctionPointerType)(void);
+
+/* Now, define eglGetProcAddress using the generic function ptr. type */
+EGLAPI __eglMustCastToProperFunctionPointerType EGLAPIENTRY
+       eglGetProcAddress(const char *procname);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __egl_h_ */
diff --git a/src/3rdparty/angle/include/EGL/eglext.h b/src/3rdparty/angle/include/EGL/eglext.h
new file mode 100644 (file)
index 0000000..b670840
--- /dev/null
@@ -0,0 +1,348 @@
+#ifndef __eglext_h_
+#define __eglext_h_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+** Copyright (c) 2007-2012 The Khronos Group Inc.
+**
+** Permission is hereby granted, free of charge, to any person obtaining a
+** copy of this software and/or associated documentation files (the
+** "Materials"), to deal in the Materials without restriction, including
+** without limitation the rights to use, copy, modify, merge, publish,
+** distribute, sublicense, and/or sell copies of the Materials, and to
+** permit persons to whom the Materials are furnished to do so, subject to
+** the following conditions:
+**
+** The above copyright notice and this permission notice shall be included
+** in all copies or substantial portions of the Materials.
+**
+** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+*/
+
+#include <EGL/eglplatform.h>
+
+/*************************************************************/
+
+/* Header file version number */
+/* Current version at http://www.khronos.org/registry/egl/ */
+/* $Revision: 16473 $ on $Date: 2012-01-04 02:20:48 -0800 (Wed, 04 Jan 2012) $ */
+#define EGL_EGLEXT_VERSION 11
+
+#ifndef EGL_KHR_config_attribs
+#define EGL_KHR_config_attribs 1
+#define EGL_CONFORMANT_KHR                     0x3042  /* EGLConfig attribute */
+#define EGL_VG_COLORSPACE_LINEAR_BIT_KHR       0x0020  /* EGL_SURFACE_TYPE bitfield */
+#define EGL_VG_ALPHA_FORMAT_PRE_BIT_KHR                0x0040  /* EGL_SURFACE_TYPE bitfield */
+#endif
+
+#ifndef EGL_KHR_lock_surface
+#define EGL_KHR_lock_surface 1
+#define EGL_READ_SURFACE_BIT_KHR               0x0001  /* EGL_LOCK_USAGE_HINT_KHR bitfield */
+#define EGL_WRITE_SURFACE_BIT_KHR              0x0002  /* EGL_LOCK_USAGE_HINT_KHR bitfield */
+#define EGL_LOCK_SURFACE_BIT_KHR               0x0080  /* EGL_SURFACE_TYPE bitfield */
+#define EGL_OPTIMAL_FORMAT_BIT_KHR             0x0100  /* EGL_SURFACE_TYPE bitfield */
+#define EGL_MATCH_FORMAT_KHR                   0x3043  /* EGLConfig attribute */
+#define EGL_FORMAT_RGB_565_EXACT_KHR           0x30C0  /* EGL_MATCH_FORMAT_KHR value */
+#define EGL_FORMAT_RGB_565_KHR                 0x30C1  /* EGL_MATCH_FORMAT_KHR value */
+#define EGL_FORMAT_RGBA_8888_EXACT_KHR         0x30C2  /* EGL_MATCH_FORMAT_KHR value */
+#define EGL_FORMAT_RGBA_8888_KHR               0x30C3  /* EGL_MATCH_FORMAT_KHR value */
+#define EGL_MAP_PRESERVE_PIXELS_KHR            0x30C4  /* eglLockSurfaceKHR attribute */
+#define EGL_LOCK_USAGE_HINT_KHR                        0x30C5  /* eglLockSurfaceKHR attribute */
+#define EGL_BITMAP_POINTER_KHR                 0x30C6  /* eglQuerySurface attribute */
+#define EGL_BITMAP_PITCH_KHR                   0x30C7  /* eglQuerySurface attribute */
+#define EGL_BITMAP_ORIGIN_KHR                  0x30C8  /* eglQuerySurface attribute */
+#define EGL_BITMAP_PIXEL_RED_OFFSET_KHR                0x30C9  /* eglQuerySurface attribute */
+#define EGL_BITMAP_PIXEL_GREEN_OFFSET_KHR      0x30CA  /* eglQuerySurface attribute */
+#define EGL_BITMAP_PIXEL_BLUE_OFFSET_KHR       0x30CB  /* eglQuerySurface attribute */
+#define EGL_BITMAP_PIXEL_ALPHA_OFFSET_KHR      0x30CC  /* eglQuerySurface attribute */
+#define EGL_BITMAP_PIXEL_LUMINANCE_OFFSET_KHR  0x30CD  /* eglQuerySurface attribute */
+#define EGL_LOWER_LEFT_KHR                     0x30CE  /* EGL_BITMAP_ORIGIN_KHR value */
+#define EGL_UPPER_LEFT_KHR                     0x30CF  /* EGL_BITMAP_ORIGIN_KHR value */
+#ifdef EGL_EGLEXT_PROTOTYPES
+EGLAPI EGLBoolean EGLAPIENTRY eglLockSurfaceKHR (EGLDisplay display, EGLSurface surface, const EGLint *attrib_list);
+EGLAPI EGLBoolean EGLAPIENTRY eglUnlockSurfaceKHR (EGLDisplay display, EGLSurface surface);
+#endif /* EGL_EGLEXT_PROTOTYPES */
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLLOCKSURFACEKHRPROC) (EGLDisplay display, EGLSurface surface, const EGLint *attrib_list);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLUNLOCKSURFACEKHRPROC) (EGLDisplay display, EGLSurface surface);
+#endif
+
+#ifndef EGL_KHR_image
+#define EGL_KHR_image 1
+#define EGL_NATIVE_PIXMAP_KHR                  0x30B0  /* eglCreateImageKHR target */
+typedef void *EGLImageKHR;
+#define EGL_NO_IMAGE_KHR                       ((EGLImageKHR)0)
+#ifdef EGL_EGLEXT_PROTOTYPES
+EGLAPI EGLImageKHR EGLAPIENTRY eglCreateImageKHR (EGLDisplay dpy, EGLContext ctx, EGLenum target, EGLClientBuffer buffer, const EGLint *attrib_list);
+EGLAPI EGLBoolean EGLAPIENTRY eglDestroyImageKHR (EGLDisplay dpy, EGLImageKHR image);
+#endif /* EGL_EGLEXT_PROTOTYPES */
+typedef EGLImageKHR (EGLAPIENTRYP PFNEGLCREATEIMAGEKHRPROC) (EGLDisplay dpy, EGLContext ctx, EGLenum target, EGLClientBuffer buffer, const EGLint *attrib_list);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLDESTROYIMAGEKHRPROC) (EGLDisplay dpy, EGLImageKHR image);
+#endif
+
+#ifndef EGL_KHR_vg_parent_image
+#define EGL_KHR_vg_parent_image 1
+#define EGL_VG_PARENT_IMAGE_KHR                        0x30BA  /* eglCreateImageKHR target */
+#endif
+
+#ifndef EGL_KHR_gl_texture_2D_image
+#define EGL_KHR_gl_texture_2D_image 1
+#define EGL_GL_TEXTURE_2D_KHR                  0x30B1  /* eglCreateImageKHR target */
+#define EGL_GL_TEXTURE_LEVEL_KHR               0x30BC  /* eglCreateImageKHR attribute */
+#endif
+
+#ifndef EGL_KHR_gl_texture_cubemap_image
+#define EGL_KHR_gl_texture_cubemap_image 1
+#define EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X_KHR 0x30B3  /* eglCreateImageKHR target */
+#define EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_X_KHR 0x30B4  /* eglCreateImageKHR target */
+#define EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Y_KHR 0x30B5  /* eglCreateImageKHR target */
+#define EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_KHR 0x30B6  /* eglCreateImageKHR target */
+#define EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Z_KHR 0x30B7  /* eglCreateImageKHR target */
+#define EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_KHR 0x30B8  /* eglCreateImageKHR target */
+#endif
+
+#ifndef EGL_KHR_gl_texture_3D_image
+#define EGL_KHR_gl_texture_3D_image 1
+#define EGL_GL_TEXTURE_3D_KHR                  0x30B2  /* eglCreateImageKHR target */
+#define EGL_GL_TEXTURE_ZOFFSET_KHR             0x30BD  /* eglCreateImageKHR attribute */
+#endif
+
+#ifndef EGL_KHR_gl_renderbuffer_image
+#define EGL_KHR_gl_renderbuffer_image 1
+#define EGL_GL_RENDERBUFFER_KHR                        0x30B9  /* eglCreateImageKHR target */
+#endif
+
+#if KHRONOS_SUPPORT_INT64   /* EGLTimeKHR requires 64-bit uint support */
+#ifndef EGL_KHR_reusable_sync
+#define EGL_KHR_reusable_sync 1
+
+typedef void* EGLSyncKHR;
+typedef khronos_utime_nanoseconds_t EGLTimeKHR;
+
+#define EGL_SYNC_STATUS_KHR                    0x30F1
+#define EGL_SIGNALED_KHR                       0x30F2
+#define EGL_UNSIGNALED_KHR                     0x30F3
+#define EGL_TIMEOUT_EXPIRED_KHR                        0x30F5
+#define EGL_CONDITION_SATISFIED_KHR            0x30F6
+#define EGL_SYNC_TYPE_KHR                      0x30F7
+#define EGL_SYNC_REUSABLE_KHR                  0x30FA
+#define EGL_SYNC_FLUSH_COMMANDS_BIT_KHR                0x0001  /* eglClientWaitSyncKHR <flags> bitfield */
+#define EGL_FOREVER_KHR                                0xFFFFFFFFFFFFFFFFull
+#define EGL_NO_SYNC_KHR                                ((EGLSyncKHR)0)
+#ifdef EGL_EGLEXT_PROTOTYPES
+EGLAPI EGLSyncKHR EGLAPIENTRY eglCreateSyncKHR(EGLDisplay dpy, EGLenum type, const EGLint *attrib_list);
+EGLAPI EGLBoolean EGLAPIENTRY eglDestroySyncKHR(EGLDisplay dpy, EGLSyncKHR sync);
+EGLAPI EGLint EGLAPIENTRY eglClientWaitSyncKHR(EGLDisplay dpy, EGLSyncKHR sync, EGLint flags, EGLTimeKHR timeout);
+EGLAPI EGLBoolean EGLAPIENTRY eglSignalSyncKHR(EGLDisplay dpy, EGLSyncKHR sync, EGLenum mode);
+EGLAPI EGLBoolean EGLAPIENTRY eglGetSyncAttribKHR(EGLDisplay dpy, EGLSyncKHR sync, EGLint attribute, EGLint *value);
+#endif /* EGL_EGLEXT_PROTOTYPES */
+typedef EGLSyncKHR (EGLAPIENTRYP PFNEGLCREATESYNCKHRPROC) (EGLDisplay dpy, EGLenum type, const EGLint *attrib_list);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLDESTROYSYNCKHRPROC) (EGLDisplay dpy, EGLSyncKHR sync);
+typedef EGLint (EGLAPIENTRYP PFNEGLCLIENTWAITSYNCKHRPROC) (EGLDisplay dpy, EGLSyncKHR sync, EGLint flags, EGLTimeKHR timeout);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLSIGNALSYNCKHRPROC) (EGLDisplay dpy, EGLSyncKHR sync, EGLenum mode);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLGETSYNCATTRIBKHRPROC) (EGLDisplay dpy, EGLSyncKHR sync, EGLint attribute, EGLint *value);
+#endif
+#endif
+
+#ifndef EGL_KHR_image_base
+#define EGL_KHR_image_base 1
+/* Most interfaces defined by EGL_KHR_image_pixmap above */
+#define EGL_IMAGE_PRESERVED_KHR                        0x30D2  /* eglCreateImageKHR attribute */
+#endif
+
+#ifndef EGL_KHR_image_pixmap
+#define EGL_KHR_image_pixmap 1
+/* Interfaces defined by EGL_KHR_image above */
+#endif
+
+#ifndef EGL_IMG_context_priority
+#define EGL_IMG_context_priority 1
+#define EGL_CONTEXT_PRIORITY_LEVEL_IMG         0x3100
+#define EGL_CONTEXT_PRIORITY_HIGH_IMG          0x3101
+#define EGL_CONTEXT_PRIORITY_MEDIUM_IMG                0x3102
+#define EGL_CONTEXT_PRIORITY_LOW_IMG           0x3103
+#endif
+
+#ifndef EGL_KHR_lock_surface2
+#define EGL_KHR_lock_surface2 1
+#define EGL_BITMAP_PIXEL_SIZE_KHR              0x3110
+#endif
+
+#ifndef EGL_NV_coverage_sample
+#define EGL_NV_coverage_sample 1
+#define EGL_COVERAGE_BUFFERS_NV                        0x30E0
+#define EGL_COVERAGE_SAMPLES_NV                        0x30E1
+#endif
+
+#ifndef EGL_NV_depth_nonlinear
+#define EGL_NV_depth_nonlinear 1
+#define EGL_DEPTH_ENCODING_NV                  0x30E2
+#define EGL_DEPTH_ENCODING_NONE_NV 0
+#define EGL_DEPTH_ENCODING_NONLINEAR_NV                0x30E3
+#endif
+
+#if KHRONOS_SUPPORT_INT64   /* EGLTimeNV requires 64-bit uint support */
+#ifndef EGL_NV_sync
+#define EGL_NV_sync 1
+#define EGL_SYNC_PRIOR_COMMANDS_COMPLETE_NV    0x30E6
+#define EGL_SYNC_STATUS_NV                     0x30E7
+#define EGL_SIGNALED_NV                                0x30E8
+#define EGL_UNSIGNALED_NV                      0x30E9
+#define EGL_SYNC_FLUSH_COMMANDS_BIT_NV         0x0001
+#define EGL_FOREVER_NV                         0xFFFFFFFFFFFFFFFFull
+#define EGL_ALREADY_SIGNALED_NV                        0x30EA
+#define EGL_TIMEOUT_EXPIRED_NV                 0x30EB
+#define EGL_CONDITION_SATISFIED_NV             0x30EC
+#define EGL_SYNC_TYPE_NV                       0x30ED
+#define EGL_SYNC_CONDITION_NV                  0x30EE
+#define EGL_SYNC_FENCE_NV                      0x30EF
+#define EGL_NO_SYNC_NV                         ((EGLSyncNV)0)
+typedef void* EGLSyncNV;
+typedef khronos_utime_nanoseconds_t EGLTimeNV;
+#ifdef EGL_EGLEXT_PROTOTYPES
+EGLSyncNV eglCreateFenceSyncNV (EGLDisplay dpy, EGLenum condition, const EGLint *attrib_list);
+EGLBoolean eglDestroySyncNV (EGLSyncNV sync);
+EGLBoolean eglFenceNV (EGLSyncNV sync);
+EGLint eglClientWaitSyncNV (EGLSyncNV sync, EGLint flags, EGLTimeNV timeout);
+EGLBoolean eglSignalSyncNV (EGLSyncNV sync, EGLenum mode);
+EGLBoolean eglGetSyncAttribNV (EGLSyncNV sync, EGLint attribute, EGLint *value);
+#endif /* EGL_EGLEXT_PROTOTYPES */
+typedef EGLSyncNV (EGLAPIENTRYP PFNEGLCREATEFENCESYNCNVPROC) (EGLDisplay dpy, EGLenum condition, const EGLint *attrib_list);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLDESTROYSYNCNVPROC) (EGLSyncNV sync);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLFENCENVPROC) (EGLSyncNV sync);
+typedef EGLint (EGLAPIENTRYP PFNEGLCLIENTWAITSYNCNVPROC) (EGLSyncNV sync, EGLint flags, EGLTimeNV timeout);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLSIGNALSYNCNVPROC) (EGLSyncNV sync, EGLenum mode);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLGETSYNCATTRIBNVPROC) (EGLSyncNV sync, EGLint attribute, EGLint *value);
+#endif
+#endif
+
+#if KHRONOS_SUPPORT_INT64   /* Dependent on EGL_KHR_reusable_sync which requires 64-bit uint support */
+#ifndef EGL_KHR_fence_sync
+#define EGL_KHR_fence_sync 1
+/* Reuses most tokens and entry points from EGL_KHR_reusable_sync */
+#define EGL_SYNC_PRIOR_COMMANDS_COMPLETE_KHR   0x30F0
+#define EGL_SYNC_CONDITION_KHR                 0x30F8
+#define EGL_SYNC_FENCE_KHR                     0x30F9
+#endif
+#endif
+
+#ifndef EGL_HI_clientpixmap
+#define EGL_HI_clientpixmap 1
+
+/* Surface Attribute */
+#define EGL_CLIENT_PIXMAP_POINTER_HI           0x8F74
+/*
+ * Structure representing a client pixmap
+ * (pixmap's data is in client-space memory).
+ */
+struct EGLClientPixmapHI
+{
+       void*           pData;
+       EGLint          iWidth;
+       EGLint          iHeight;
+       EGLint          iStride;
+};
+
+#ifdef EGL_EGLEXT_PROTOTYPES
+EGLAPI EGLSurface EGLAPIENTRY eglCreatePixmapSurfaceHI(EGLDisplay dpy, EGLConfig config, struct EGLClientPixmapHI* pixmap);
+#endif /* EGL_EGLEXT_PROTOTYPES */
+typedef EGLSurface (EGLAPIENTRYP PFNEGLCREATEPIXMAPSURFACEHIPROC) (EGLDisplay dpy, EGLConfig config, struct EGLClientPixmapHI* pixmap);
+#endif /* EGL_HI_clientpixmap */
+
+#ifndef EGL_HI_colorformats
+#define EGL_HI_colorformats 1
+/* Config Attribute */
+#define EGL_COLOR_FORMAT_HI                    0x8F70
+/* Color Formats */
+#define EGL_COLOR_RGB_HI                       0x8F71
+#define EGL_COLOR_RGBA_HI                      0x8F72
+#define EGL_COLOR_ARGB_HI                      0x8F73
+#endif /* EGL_HI_colorformats */
+
+#ifndef EGL_MESA_drm_image
+#define EGL_MESA_drm_image 1
+#define EGL_DRM_BUFFER_FORMAT_MESA             0x31D0      /* CreateDRMImageMESA attribute */
+#define EGL_DRM_BUFFER_USE_MESA                        0x31D1      /* CreateDRMImageMESA attribute */
+#define EGL_DRM_BUFFER_FORMAT_ARGB32_MESA      0x31D2      /* EGL_IMAGE_FORMAT_MESA attribute value */
+#define EGL_DRM_BUFFER_MESA                    0x31D3      /* eglCreateImageKHR target */
+#define EGL_DRM_BUFFER_STRIDE_MESA             0x31D4
+#define EGL_DRM_BUFFER_USE_SCANOUT_MESA                0x00000001  /* EGL_DRM_BUFFER_USE_MESA bits */
+#define EGL_DRM_BUFFER_USE_SHARE_MESA          0x00000002  /* EGL_DRM_BUFFER_USE_MESA bits */
+#ifdef EGL_EGLEXT_PROTOTYPES
+EGLAPI EGLImageKHR EGLAPIENTRY eglCreateDRMImageMESA (EGLDisplay dpy, const EGLint *attrib_list);
+EGLAPI EGLBoolean EGLAPIENTRY eglExportDRMImageMESA (EGLDisplay dpy, EGLImageKHR image, EGLint *name, EGLint *handle, EGLint *stride);
+#endif /* EGL_EGLEXT_PROTOTYPES */
+typedef EGLImageKHR (EGLAPIENTRYP PFNEGLCREATEDRMIMAGEMESAPROC) (EGLDisplay dpy, const EGLint *attrib_list);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLEXPORTDRMIMAGEMESAPROC) (EGLDisplay dpy, EGLImageKHR image, EGLint *name, EGLint *handle, EGLint *stride);
+#endif
+
+#ifndef EGL_NV_post_sub_buffer
+#define EGL_NV_post_sub_buffer 1
+#define EGL_POST_SUB_BUFFER_SUPPORTED_NV       0x30BE
+#ifdef EGL_EGLEXT_PROTOTYPES
+EGLAPI EGLBoolean EGLAPIENTRY eglPostSubBufferNV (EGLDisplay dpy, EGLSurface surface, EGLint x, EGLint y, EGLint width, EGLint height);
+#endif /* EGL_EGLEXT_PROTOTYPES */
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLPOSTSUBBUFFERNVPROC) (EGLDisplay dpy, EGLSurface surface, EGLint x, EGLint y, EGLint width, EGLint height);
+#endif
+
+#ifndef EGL_ANGLE_query_surface_pointer
+#define EGL_ANGLE_query_surface_pointer 1
+#ifdef EGL_EGLEXT_PROTOTYPES
+EGLAPI EGLBoolean eglQuerySurfacePointerANGLE(EGLDisplay dpy, EGLSurface surface, EGLint attribute, void **value);
+#endif
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYSURFACEPOINTERANGLEPROC) (EGLDisplay dpy, EGLSurface surface, EGLint attribute, void **value);
+#endif
+
+#ifndef EGL_ANGLE_software_display
+#define EGL_ANGLE_software_display 1
+#define EGL_SOFTWARE_DISPLAY_ANGLE ((EGLNativeDisplayType)-1)
+#endif
+
+#ifndef EGL_ANGLE_surface_d3d_texture_2d_share_handle
+#define EGL_ANGLE_surface_d3d_texture_2d_share_handle 1
+#define EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE  0x3200
+#endif
+
+#ifndef EGL_NV_coverage_sample_resolve
+#define EGL_NV_coverage_sample_resolve 1
+#define EGL_COVERAGE_SAMPLE_RESOLVE_NV         0x3131
+#define EGL_COVERAGE_SAMPLE_RESOLVE_DEFAULT_NV 0x3132
+#define EGL_COVERAGE_SAMPLE_RESOLVE_NONE_NV    0x3133
+#endif
+
+#if KHRONOS_SUPPORT_INT64   /* EGLTimeKHR requires 64-bit uint support */
+#ifndef EGL_NV_system_time
+#define EGL_NV_system_time 1
+
+typedef khronos_utime_nanoseconds_t EGLuint64NV;
+
+#ifdef EGL_EGLEXT_PROTOTYPES
+EGLAPI EGLuint64NV EGLAPIENTRY eglGetSystemTimeFrequencyNV(void);
+EGLAPI EGLuint64NV EGLAPIENTRY eglGetSystemTimeNV(void);
+#endif /* EGL_EGLEXT_PROTOTYPES */
+typedef EGLuint64NV (EGLAPIENTRYP PFNEGLGETSYSTEMTIMEFREQUENCYNVPROC) (void);
+typedef EGLuint64NV (EGLAPIENTRYP PFNEGLGETSYSTEMTIMENVPROC) (void);
+#endif
+#endif
+
+#ifndef EGL_EXT_create_context_robustness
+#define EGL_EXT_create_context_robustness 1
+#define EGL_CONTEXT_OPENGL_ROBUST_ACCESS_EXT   0x30BF
+#define EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_EXT 0x3138
+#define EGL_NO_RESET_NOTIFICATION_EXT          0x31BE
+#define EGL_LOSE_CONTEXT_ON_RESET_EXT          0x31BF
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/3rdparty/angle/include/EGL/eglplatform.h b/src/3rdparty/angle/include/EGL/eglplatform.h
new file mode 100644 (file)
index 0000000..34283f2
--- /dev/null
@@ -0,0 +1,129 @@
+#ifndef __eglplatform_h_
+#define __eglplatform_h_
+
+/*
+** Copyright (c) 2007-2009 The Khronos Group Inc.
+**
+** Permission is hereby granted, free of charge, to any person obtaining a
+** copy of this software and/or associated documentation files (the
+** "Materials"), to deal in the Materials without restriction, including
+** without limitation the rights to use, copy, modify, merge, publish,
+** distribute, sublicense, and/or sell copies of the Materials, and to
+** permit persons to whom the Materials are furnished to do so, subject to
+** the following conditions:
+**
+** The above copyright notice and this permission notice shall be included
+** in all copies or substantial portions of the Materials.
+**
+** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+*/
+
+/* Platform-specific types and definitions for egl.h
+ * $Revision: 12306 $ on $Date: 2010-08-25 09:51:28 -0700 (Wed, 25 Aug 2010) $
+ *
+ * Adopters may modify khrplatform.h and this file to suit their platform.
+ * You are encouraged to submit all modifications to the Khronos group so that
+ * they can be included in future versions of this file.  Please submit changes
+ * by sending them to the public Khronos Bugzilla (http://khronos.org/bugzilla)
+ * by filing a bug against product "EGL" component "Registry".
+ */
+
+#include <KHR/khrplatform.h>
+
+/* Macros used in EGL function prototype declarations.
+ *
+ * EGL functions should be prototyped as:
+ *
+ * EGLAPI return-type EGLAPIENTRY eglFunction(arguments);
+ * typedef return-type (EXPAPIENTRYP PFNEGLFUNCTIONPROC) (arguments);
+ *
+ * KHRONOS_APICALL and KHRONOS_APIENTRY are defined in KHR/khrplatform.h
+ */
+
+#ifndef EGLAPI
+#define EGLAPI KHRONOS_APICALL
+#endif
+
+#ifndef EGLAPIENTRY
+#define EGLAPIENTRY  KHRONOS_APIENTRY
+#endif
+#define EGLAPIENTRYP EGLAPIENTRY*
+
+/* The types NativeDisplayType, NativeWindowType, and NativePixmapType
+ * are aliases of window-system-dependent types, such as X Display * or
+ * Windows Device Context. They must be defined in platform-specific
+ * code below. The EGL-prefixed versions of Native*Type are the same
+ * types, renamed in EGL 1.3 so all types in the API start with "EGL".
+ *
+ * Khronos STRONGLY RECOMMENDS that you use the default definitions
+ * provided below, since these changes affect both binary and source
+ * portability of applications using EGL running on different EGL
+ * implementations.
+ */
+
+#if defined(_WIN32) || defined(__VC32__) && !defined(__CYGWIN__) && !defined(__SCITECH_SNAP__) /* Win32 and WinCE */
+#ifndef WIN32_LEAN_AND_MEAN
+#define WIN32_LEAN_AND_MEAN 1
+#endif
+#include <windows.h>
+
+typedef HDC     EGLNativeDisplayType;
+typedef HBITMAP EGLNativePixmapType;
+typedef HWND    EGLNativeWindowType;
+
+#elif defined(__WINSCW__) || defined(__SYMBIAN32__)  /* Symbian */
+
+typedef int   EGLNativeDisplayType;
+typedef void *EGLNativeWindowType;
+typedef void *EGLNativePixmapType;
+
+#elif defined(WL_EGL_PLATFORM)
+
+typedef struct wl_display     *EGLNativeDisplayType;
+typedef struct wl_egl_pixmap  *EGLNativePixmapType;
+typedef struct wl_egl_window  *EGLNativeWindowType;
+
+#elif defined(__unix__) && !defined(ANDROID)
+
+/* X11 (tentative)  */
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+
+typedef Display *EGLNativeDisplayType;
+typedef Pixmap   EGLNativePixmapType;
+typedef Window   EGLNativeWindowType;
+
+#elif defined(ANDROID)
+
+struct egl_native_pixmap_t;
+
+typedef struct ANativeWindow*           EGLNativeWindowType;
+typedef struct egl_native_pixmap_t*     EGLNativePixmapType;
+typedef void*                           EGLNativeDisplayType;
+
+#else
+#error "Platform not recognized"
+#endif
+
+/* EGL 1.2 types, renamed for consistency in EGL 1.3 */
+typedef EGLNativeDisplayType NativeDisplayType;
+typedef EGLNativePixmapType  NativePixmapType;
+typedef EGLNativeWindowType  NativeWindowType;
+
+
+/* Define EGLint. This must be a signed integral type large enough to contain
+ * all legal attribute names and values passed into and out of EGL, whether
+ * their type is boolean, bitmask, enumerant (symbolic constant), integer,
+ * handle, or other.  While in general a 32-bit integer will suffice, if
+ * handles are 64 bit types, then EGLint should be defined as a signed 64-bit
+ * integer type.
+ */
+typedef khronos_int32_t EGLint;
+
+#endif /* __eglplatform_h */
diff --git a/src/3rdparty/angle/include/GLES2/gl2.h b/src/3rdparty/angle/include/GLES2/gl2.h
new file mode 100644 (file)
index 0000000..e1d3b87
--- /dev/null
@@ -0,0 +1,621 @@
+#ifndef __gl2_h_
+#define __gl2_h_
+
+/* $Revision: 10602 $ on $Date:: 2010-03-04 22:35:34 -0800 #$ */
+
+#include <GLES2/gl2platform.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * This document is licensed under the SGI Free Software B License Version
+ * 2.0. For details, see http://oss.sgi.com/projects/FreeB/ .
+ */
+
+/*-------------------------------------------------------------------------
+ * Data type definitions
+ *-----------------------------------------------------------------------*/
+
+typedef void             GLvoid;
+typedef char             GLchar;
+typedef unsigned int     GLenum;
+typedef unsigned char    GLboolean;
+typedef unsigned int     GLbitfield;
+typedef khronos_int8_t   GLbyte;
+typedef short            GLshort;
+typedef int              GLint;
+typedef int              GLsizei;
+typedef khronos_uint8_t  GLubyte;
+typedef unsigned short   GLushort;
+typedef unsigned int     GLuint;
+typedef khronos_float_t  GLfloat;
+typedef khronos_float_t  GLclampf;
+typedef khronos_int32_t  GLfixed;
+
+/* GL types for handling large vertex buffer objects */
+typedef khronos_intptr_t GLintptr;
+typedef khronos_ssize_t  GLsizeiptr;
+
+/* OpenGL ES core versions */
+#define GL_ES_VERSION_2_0                 1
+
+/* ClearBufferMask */
+#define GL_DEPTH_BUFFER_BIT               0x00000100
+#define GL_STENCIL_BUFFER_BIT             0x00000400
+#define GL_COLOR_BUFFER_BIT               0x00004000
+
+/* Boolean */
+#define GL_FALSE                          0
+#define GL_TRUE                           1
+
+/* BeginMode */
+#define GL_POINTS                         0x0000
+#define GL_LINES                          0x0001
+#define GL_LINE_LOOP                      0x0002
+#define GL_LINE_STRIP                     0x0003
+#define GL_TRIANGLES                      0x0004
+#define GL_TRIANGLE_STRIP                 0x0005
+#define GL_TRIANGLE_FAN                   0x0006
+
+/* AlphaFunction (not supported in ES20) */
+/*      GL_NEVER */
+/*      GL_LESS */
+/*      GL_EQUAL */
+/*      GL_LEQUAL */
+/*      GL_GREATER */
+/*      GL_NOTEQUAL */
+/*      GL_GEQUAL */
+/*      GL_ALWAYS */
+
+/* BlendingFactorDest */
+#define GL_ZERO                           0
+#define GL_ONE                            1
+#define GL_SRC_COLOR                      0x0300
+#define GL_ONE_MINUS_SRC_COLOR            0x0301
+#define GL_SRC_ALPHA                      0x0302
+#define GL_ONE_MINUS_SRC_ALPHA            0x0303
+#define GL_DST_ALPHA                      0x0304
+#define GL_ONE_MINUS_DST_ALPHA            0x0305
+
+/* BlendingFactorSrc */
+/*      GL_ZERO */
+/*      GL_ONE */
+#define GL_DST_COLOR                      0x0306
+#define GL_ONE_MINUS_DST_COLOR            0x0307
+#define GL_SRC_ALPHA_SATURATE             0x0308
+/*      GL_SRC_ALPHA */
+/*      GL_ONE_MINUS_SRC_ALPHA */
+/*      GL_DST_ALPHA */
+/*      GL_ONE_MINUS_DST_ALPHA */
+
+/* BlendEquationSeparate */
+#define GL_FUNC_ADD                       0x8006
+#define GL_BLEND_EQUATION                 0x8009
+#define GL_BLEND_EQUATION_RGB             0x8009    /* same as BLEND_EQUATION */
+#define GL_BLEND_EQUATION_ALPHA           0x883D
+
+/* BlendSubtract */
+#define GL_FUNC_SUBTRACT                  0x800A
+#define GL_FUNC_REVERSE_SUBTRACT          0x800B
+
+/* Separate Blend Functions */
+#define GL_BLEND_DST_RGB                  0x80C8
+#define GL_BLEND_SRC_RGB                  0x80C9
+#define GL_BLEND_DST_ALPHA                0x80CA
+#define GL_BLEND_SRC_ALPHA                0x80CB
+#define GL_CONSTANT_COLOR                 0x8001
+#define GL_ONE_MINUS_CONSTANT_COLOR       0x8002
+#define GL_CONSTANT_ALPHA                 0x8003
+#define GL_ONE_MINUS_CONSTANT_ALPHA       0x8004
+#define GL_BLEND_COLOR                    0x8005
+
+/* Buffer Objects */
+#define GL_ARRAY_BUFFER                   0x8892
+#define GL_ELEMENT_ARRAY_BUFFER           0x8893
+#define GL_ARRAY_BUFFER_BINDING           0x8894
+#define GL_ELEMENT_ARRAY_BUFFER_BINDING   0x8895
+
+#define GL_STREAM_DRAW                    0x88E0
+#define GL_STATIC_DRAW                    0x88E4
+#define GL_DYNAMIC_DRAW                   0x88E8
+
+#define GL_BUFFER_SIZE                    0x8764
+#define GL_BUFFER_USAGE                   0x8765
+
+#define GL_CURRENT_VERTEX_ATTRIB          0x8626
+
+/* CullFaceMode */
+#define GL_FRONT                          0x0404
+#define GL_BACK                           0x0405
+#define GL_FRONT_AND_BACK                 0x0408
+
+/* DepthFunction */
+/*      GL_NEVER */
+/*      GL_LESS */
+/*      GL_EQUAL */
+/*      GL_LEQUAL */
+/*      GL_GREATER */
+/*      GL_NOTEQUAL */
+/*      GL_GEQUAL */
+/*      GL_ALWAYS */
+
+/* EnableCap */
+#define GL_TEXTURE_2D                     0x0DE1
+#define GL_CULL_FACE                      0x0B44
+#define GL_BLEND                          0x0BE2
+#define GL_DITHER                         0x0BD0
+#define GL_STENCIL_TEST                   0x0B90
+#define GL_DEPTH_TEST                     0x0B71
+#define GL_SCISSOR_TEST                   0x0C11
+#define GL_POLYGON_OFFSET_FILL            0x8037
+#define GL_SAMPLE_ALPHA_TO_COVERAGE       0x809E
+#define GL_SAMPLE_COVERAGE                0x80A0
+
+/* ErrorCode */
+#define GL_NO_ERROR                       0
+#define GL_INVALID_ENUM                   0x0500
+#define GL_INVALID_VALUE                  0x0501
+#define GL_INVALID_OPERATION              0x0502
+#define GL_OUT_OF_MEMORY                  0x0505
+
+/* FrontFaceDirection */
+#define GL_CW                             0x0900
+#define GL_CCW                            0x0901
+
+/* GetPName */
+#define GL_LINE_WIDTH                     0x0B21
+#define GL_ALIASED_POINT_SIZE_RANGE       0x846D
+#define GL_ALIASED_LINE_WIDTH_RANGE       0x846E
+#define GL_CULL_FACE_MODE                 0x0B45
+#define GL_FRONT_FACE                     0x0B46
+#define GL_DEPTH_RANGE                    0x0B70
+#define GL_DEPTH_WRITEMASK                0x0B72
+#define GL_DEPTH_CLEAR_VALUE              0x0B73
+#define GL_DEPTH_FUNC                     0x0B74
+#define GL_STENCIL_CLEAR_VALUE            0x0B91
+#define GL_STENCIL_FUNC                   0x0B92
+#define GL_STENCIL_FAIL                   0x0B94
+#define GL_STENCIL_PASS_DEPTH_FAIL        0x0B95
+#define GL_STENCIL_PASS_DEPTH_PASS        0x0B96
+#define GL_STENCIL_REF                    0x0B97
+#define GL_STENCIL_VALUE_MASK             0x0B93
+#define GL_STENCIL_WRITEMASK              0x0B98
+#define GL_STENCIL_BACK_FUNC              0x8800
+#define GL_STENCIL_BACK_FAIL              0x8801
+#define GL_STENCIL_BACK_PASS_DEPTH_FAIL   0x8802
+#define GL_STENCIL_BACK_PASS_DEPTH_PASS   0x8803
+#define GL_STENCIL_BACK_REF               0x8CA3
+#define GL_STENCIL_BACK_VALUE_MASK        0x8CA4
+#define GL_STENCIL_BACK_WRITEMASK         0x8CA5
+#define GL_VIEWPORT                       0x0BA2
+#define GL_SCISSOR_BOX                    0x0C10
+/*      GL_SCISSOR_TEST */
+#define GL_COLOR_CLEAR_VALUE              0x0C22
+#define GL_COLOR_WRITEMASK                0x0C23
+#define GL_UNPACK_ALIGNMENT               0x0CF5
+#define GL_PACK_ALIGNMENT                 0x0D05
+#define GL_MAX_TEXTURE_SIZE               0x0D33
+#define GL_MAX_VIEWPORT_DIMS              0x0D3A
+#define GL_SUBPIXEL_BITS                  0x0D50
+#define GL_RED_BITS                       0x0D52
+#define GL_GREEN_BITS                     0x0D53
+#define GL_BLUE_BITS                      0x0D54
+#define GL_ALPHA_BITS                     0x0D55
+#define GL_DEPTH_BITS                     0x0D56
+#define GL_STENCIL_BITS                   0x0D57
+#define GL_POLYGON_OFFSET_UNITS           0x2A00
+/*      GL_POLYGON_OFFSET_FILL */
+#define GL_POLYGON_OFFSET_FACTOR          0x8038
+#define GL_TEXTURE_BINDING_2D             0x8069
+#define GL_SAMPLE_BUFFERS                 0x80A8
+#define GL_SAMPLES                        0x80A9
+#define GL_SAMPLE_COVERAGE_VALUE          0x80AA
+#define GL_SAMPLE_COVERAGE_INVERT         0x80AB
+
+/* GetTextureParameter */
+/*      GL_TEXTURE_MAG_FILTER */
+/*      GL_TEXTURE_MIN_FILTER */
+/*      GL_TEXTURE_WRAP_S */
+/*      GL_TEXTURE_WRAP_T */
+
+#define GL_NUM_COMPRESSED_TEXTURE_FORMATS 0x86A2
+#define GL_COMPRESSED_TEXTURE_FORMATS     0x86A3
+
+/* HintMode */
+#define GL_DONT_CARE                      0x1100
+#define GL_FASTEST                        0x1101
+#define GL_NICEST                         0x1102
+
+/* HintTarget */
+#define GL_GENERATE_MIPMAP_HINT            0x8192
+
+/* DataType */
+#define GL_BYTE                           0x1400
+#define GL_UNSIGNED_BYTE                  0x1401
+#define GL_SHORT                          0x1402
+#define GL_UNSIGNED_SHORT                 0x1403
+#define GL_INT                            0x1404
+#define GL_UNSIGNED_INT                   0x1405
+#define GL_FLOAT                          0x1406
+#define GL_FIXED                          0x140C
+
+/* PixelFormat */
+#define GL_DEPTH_COMPONENT                0x1902
+#define GL_ALPHA                          0x1906
+#define GL_RGB                            0x1907
+#define GL_RGBA                           0x1908
+#define GL_LUMINANCE                      0x1909
+#define GL_LUMINANCE_ALPHA                0x190A
+
+/* PixelType */
+/*      GL_UNSIGNED_BYTE */
+#define GL_UNSIGNED_SHORT_4_4_4_4         0x8033
+#define GL_UNSIGNED_SHORT_5_5_5_1         0x8034
+#define GL_UNSIGNED_SHORT_5_6_5           0x8363
+
+/* Shaders */
+#define GL_FRAGMENT_SHADER                  0x8B30
+#define GL_VERTEX_SHADER                    0x8B31
+#define GL_MAX_VERTEX_ATTRIBS               0x8869
+#define GL_MAX_VERTEX_UNIFORM_VECTORS       0x8DFB
+#define GL_MAX_VARYING_VECTORS              0x8DFC
+#define GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS 0x8B4D
+#define GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS   0x8B4C
+#define GL_MAX_TEXTURE_IMAGE_UNITS          0x8872
+#define GL_MAX_FRAGMENT_UNIFORM_VECTORS     0x8DFD
+#define GL_SHADER_TYPE                      0x8B4F
+#define GL_DELETE_STATUS                    0x8B80
+#define GL_LINK_STATUS                      0x8B82
+#define GL_VALIDATE_STATUS                  0x8B83
+#define GL_ATTACHED_SHADERS                 0x8B85
+#define GL_ACTIVE_UNIFORMS                  0x8B86
+#define GL_ACTIVE_UNIFORM_MAX_LENGTH        0x8B87
+#define GL_ACTIVE_ATTRIBUTES                0x8B89
+#define GL_ACTIVE_ATTRIBUTE_MAX_LENGTH      0x8B8A
+#define GL_SHADING_LANGUAGE_VERSION         0x8B8C
+#define GL_CURRENT_PROGRAM                  0x8B8D
+
+/* StencilFunction */
+#define GL_NEVER                          0x0200
+#define GL_LESS                           0x0201
+#define GL_EQUAL                          0x0202
+#define GL_LEQUAL                         0x0203
+#define GL_GREATER                        0x0204
+#define GL_NOTEQUAL                       0x0205
+#define GL_GEQUAL                         0x0206
+#define GL_ALWAYS                         0x0207
+
+/* StencilOp */
+/*      GL_ZERO */
+#define GL_KEEP                           0x1E00
+#define GL_REPLACE                        0x1E01
+#define GL_INCR                           0x1E02
+#define GL_DECR                           0x1E03
+#define GL_INVERT                         0x150A
+#define GL_INCR_WRAP                      0x8507
+#define GL_DECR_WRAP                      0x8508
+
+/* StringName */
+#define GL_VENDOR                         0x1F00
+#define GL_RENDERER                       0x1F01
+#define GL_VERSION                        0x1F02
+#define GL_EXTENSIONS                     0x1F03
+
+/* TextureMagFilter */
+#define GL_NEAREST                        0x2600
+#define GL_LINEAR                         0x2601
+
+/* TextureMinFilter */
+/*      GL_NEAREST */
+/*      GL_LINEAR */
+#define GL_NEAREST_MIPMAP_NEAREST         0x2700
+#define GL_LINEAR_MIPMAP_NEAREST          0x2701
+#define GL_NEAREST_MIPMAP_LINEAR          0x2702
+#define GL_LINEAR_MIPMAP_LINEAR           0x2703
+
+/* TextureParameterName */
+#define GL_TEXTURE_MAG_FILTER             0x2800
+#define GL_TEXTURE_MIN_FILTER             0x2801
+#define GL_TEXTURE_WRAP_S                 0x2802
+#define GL_TEXTURE_WRAP_T                 0x2803
+
+/* TextureTarget */
+/*      GL_TEXTURE_2D */
+#define GL_TEXTURE                        0x1702
+
+#define GL_TEXTURE_CUBE_MAP               0x8513
+#define GL_TEXTURE_BINDING_CUBE_MAP       0x8514
+#define GL_TEXTURE_CUBE_MAP_POSITIVE_X    0x8515
+#define GL_TEXTURE_CUBE_MAP_NEGATIVE_X    0x8516
+#define GL_TEXTURE_CUBE_MAP_POSITIVE_Y    0x8517
+#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Y    0x8518
+#define GL_TEXTURE_CUBE_MAP_POSITIVE_Z    0x8519
+#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Z    0x851A
+#define GL_MAX_CUBE_MAP_TEXTURE_SIZE      0x851C
+
+/* TextureUnit */
+#define GL_TEXTURE0                       0x84C0
+#define GL_TEXTURE1                       0x84C1
+#define GL_TEXTURE2                       0x84C2
+#define GL_TEXTURE3                       0x84C3
+#define GL_TEXTURE4                       0x84C4
+#define GL_TEXTURE5                       0x84C5
+#define GL_TEXTURE6                       0x84C6
+#define GL_TEXTURE7                       0x84C7
+#define GL_TEXTURE8                       0x84C8
+#define GL_TEXTURE9                       0x84C9
+#define GL_TEXTURE10                      0x84CA
+#define GL_TEXTURE11                      0x84CB
+#define GL_TEXTURE12                      0x84CC
+#define GL_TEXTURE13                      0x84CD
+#define GL_TEXTURE14                      0x84CE
+#define GL_TEXTURE15                      0x84CF
+#define GL_TEXTURE16                      0x84D0
+#define GL_TEXTURE17                      0x84D1
+#define GL_TEXTURE18                      0x84D2
+#define GL_TEXTURE19                      0x84D3
+#define GL_TEXTURE20                      0x84D4
+#define GL_TEXTURE21                      0x84D5
+#define GL_TEXTURE22                      0x84D6
+#define GL_TEXTURE23                      0x84D7
+#define GL_TEXTURE24                      0x84D8
+#define GL_TEXTURE25                      0x84D9
+#define GL_TEXTURE26                      0x84DA
+#define GL_TEXTURE27                      0x84DB
+#define GL_TEXTURE28                      0x84DC
+#define GL_TEXTURE29                      0x84DD
+#define GL_TEXTURE30                      0x84DE
+#define GL_TEXTURE31                      0x84DF
+#define GL_ACTIVE_TEXTURE                 0x84E0
+
+/* TextureWrapMode */
+#define GL_REPEAT                         0x2901
+#define GL_CLAMP_TO_EDGE                  0x812F
+#define GL_MIRRORED_REPEAT                0x8370
+
+/* Uniform Types */
+#define GL_FLOAT_VEC2                     0x8B50
+#define GL_FLOAT_VEC3                     0x8B51
+#define GL_FLOAT_VEC4                     0x8B52
+#define GL_INT_VEC2                       0x8B53
+#define GL_INT_VEC3                       0x8B54
+#define GL_INT_VEC4                       0x8B55
+#define GL_BOOL                           0x8B56
+#define GL_BOOL_VEC2                      0x8B57
+#define GL_BOOL_VEC3                      0x8B58
+#define GL_BOOL_VEC4                      0x8B59
+#define GL_FLOAT_MAT2                     0x8B5A
+#define GL_FLOAT_MAT3                     0x8B5B
+#define GL_FLOAT_MAT4                     0x8B5C
+#define GL_SAMPLER_2D                     0x8B5E
+#define GL_SAMPLER_CUBE                   0x8B60
+
+/* Vertex Arrays */
+#define GL_VERTEX_ATTRIB_ARRAY_ENABLED        0x8622
+#define GL_VERTEX_ATTRIB_ARRAY_SIZE           0x8623
+#define GL_VERTEX_ATTRIB_ARRAY_STRIDE         0x8624
+#define GL_VERTEX_ATTRIB_ARRAY_TYPE           0x8625
+#define GL_VERTEX_ATTRIB_ARRAY_NORMALIZED     0x886A
+#define GL_VERTEX_ATTRIB_ARRAY_POINTER        0x8645
+#define GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING 0x889F
+
+/* Read Format */
+#define GL_IMPLEMENTATION_COLOR_READ_TYPE   0x8B9A
+#define GL_IMPLEMENTATION_COLOR_READ_FORMAT 0x8B9B
+
+/* Shader Source */
+#define GL_COMPILE_STATUS                 0x8B81
+#define GL_INFO_LOG_LENGTH                0x8B84
+#define GL_SHADER_SOURCE_LENGTH           0x8B88
+#define GL_SHADER_COMPILER                0x8DFA
+
+/* Shader Binary */
+#define GL_SHADER_BINARY_FORMATS          0x8DF8
+#define GL_NUM_SHADER_BINARY_FORMATS      0x8DF9
+
+/* Shader Precision-Specified Types */
+#define GL_LOW_FLOAT                      0x8DF0
+#define GL_MEDIUM_FLOAT                   0x8DF1
+#define GL_HIGH_FLOAT                     0x8DF2
+#define GL_LOW_INT                        0x8DF3
+#define GL_MEDIUM_INT                     0x8DF4
+#define GL_HIGH_INT                       0x8DF5
+
+/* Framebuffer Object. */
+#define GL_FRAMEBUFFER                    0x8D40
+#define GL_RENDERBUFFER                   0x8D41
+
+#define GL_RGBA4                          0x8056
+#define GL_RGB5_A1                        0x8057
+#define GL_RGB565                         0x8D62
+#define GL_DEPTH_COMPONENT16              0x81A5
+#define GL_STENCIL_INDEX                  0x1901
+#define GL_STENCIL_INDEX8                 0x8D48
+
+#define GL_RENDERBUFFER_WIDTH             0x8D42
+#define GL_RENDERBUFFER_HEIGHT            0x8D43
+#define GL_RENDERBUFFER_INTERNAL_FORMAT   0x8D44
+#define GL_RENDERBUFFER_RED_SIZE          0x8D50
+#define GL_RENDERBUFFER_GREEN_SIZE        0x8D51
+#define GL_RENDERBUFFER_BLUE_SIZE         0x8D52
+#define GL_RENDERBUFFER_ALPHA_SIZE        0x8D53
+#define GL_RENDERBUFFER_DEPTH_SIZE        0x8D54
+#define GL_RENDERBUFFER_STENCIL_SIZE      0x8D55
+
+#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE           0x8CD0
+#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME           0x8CD1
+#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL         0x8CD2
+#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE 0x8CD3
+
+#define GL_COLOR_ATTACHMENT0              0x8CE0
+#define GL_DEPTH_ATTACHMENT               0x8D00
+#define GL_STENCIL_ATTACHMENT             0x8D20
+
+#define GL_NONE                           0
+
+#define GL_FRAMEBUFFER_COMPLETE                      0x8CD5
+#define GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT         0x8CD6
+#define GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT 0x8CD7
+#define GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS         0x8CD9
+#define GL_FRAMEBUFFER_UNSUPPORTED                   0x8CDD
+
+#define GL_FRAMEBUFFER_BINDING            0x8CA6
+#define GL_RENDERBUFFER_BINDING           0x8CA7
+#define GL_MAX_RENDERBUFFER_SIZE          0x84E8
+
+#define GL_INVALID_FRAMEBUFFER_OPERATION  0x0506
+
+/*-------------------------------------------------------------------------
+ * GL core functions.
+ *-----------------------------------------------------------------------*/
+
+GL_APICALL void         GL_APIENTRY glActiveTexture (GLenum texture);
+GL_APICALL void         GL_APIENTRY glAttachShader (GLuint program, GLuint shader);
+GL_APICALL void         GL_APIENTRY glBindAttribLocation (GLuint program, GLuint index, const GLchar* name);
+GL_APICALL void         GL_APIENTRY glBindBuffer (GLenum target, GLuint buffer);
+GL_APICALL void         GL_APIENTRY glBindFramebuffer (GLenum target, GLuint framebuffer);
+GL_APICALL void         GL_APIENTRY glBindRenderbuffer (GLenum target, GLuint renderbuffer);
+GL_APICALL void         GL_APIENTRY glBindTexture (GLenum target, GLuint texture);
+GL_APICALL void         GL_APIENTRY glBlendColor (GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha);
+GL_APICALL void         GL_APIENTRY glBlendEquation ( GLenum mode );
+GL_APICALL void         GL_APIENTRY glBlendEquationSeparate (GLenum modeRGB, GLenum modeAlpha);
+GL_APICALL void         GL_APIENTRY glBlendFunc (GLenum sfactor, GLenum dfactor);
+GL_APICALL void         GL_APIENTRY glBlendFuncSeparate (GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha);
+GL_APICALL void         GL_APIENTRY glBufferData (GLenum target, GLsizeiptr size, const GLvoid* data, GLenum usage);
+GL_APICALL void         GL_APIENTRY glBufferSubData (GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid* data);
+GL_APICALL GLenum       GL_APIENTRY glCheckFramebufferStatus (GLenum target);
+GL_APICALL void         GL_APIENTRY glClear (GLbitfield mask);
+GL_APICALL void         GL_APIENTRY glClearColor (GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha);
+GL_APICALL void         GL_APIENTRY glClearDepthf (GLclampf depth);
+GL_APICALL void         GL_APIENTRY glClearStencil (GLint s);
+GL_APICALL void         GL_APIENTRY glColorMask (GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha);
+GL_APICALL void         GL_APIENTRY glCompileShader (GLuint shader);
+GL_APICALL void         GL_APIENTRY glCompressedTexImage2D (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid* data);
+GL_APICALL void         GL_APIENTRY glCompressedTexSubImage2D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const GLvoid* data);
+GL_APICALL void         GL_APIENTRY glCopyTexImage2D (GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border);
+GL_APICALL void         GL_APIENTRY glCopyTexSubImage2D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height);
+GL_APICALL GLuint       GL_APIENTRY glCreateProgram (void);
+GL_APICALL GLuint       GL_APIENTRY glCreateShader (GLenum type);
+GL_APICALL void         GL_APIENTRY glCullFace (GLenum mode);
+GL_APICALL void         GL_APIENTRY glDeleteBuffers (GLsizei n, const GLuint* buffers);
+GL_APICALL void         GL_APIENTRY glDeleteFramebuffers (GLsizei n, const GLuint* framebuffers);
+GL_APICALL void         GL_APIENTRY glDeleteProgram (GLuint program);
+GL_APICALL void         GL_APIENTRY glDeleteRenderbuffers (GLsizei n, const GLuint* renderbuffers);
+GL_APICALL void         GL_APIENTRY glDeleteShader (GLuint shader);
+GL_APICALL void         GL_APIENTRY glDeleteTextures (GLsizei n, const GLuint* textures);
+GL_APICALL void         GL_APIENTRY glDepthFunc (GLenum func);
+GL_APICALL void         GL_APIENTRY glDepthMask (GLboolean flag);
+GL_APICALL void         GL_APIENTRY glDepthRangef (GLclampf zNear, GLclampf zFar);
+GL_APICALL void         GL_APIENTRY glDetachShader (GLuint program, GLuint shader);
+GL_APICALL void         GL_APIENTRY glDisable (GLenum cap);
+GL_APICALL void         GL_APIENTRY glDisableVertexAttribArray (GLuint index);
+GL_APICALL void         GL_APIENTRY glDrawArrays (GLenum mode, GLint first, GLsizei count);
+GL_APICALL void         GL_APIENTRY glDrawElements (GLenum mode, GLsizei count, GLenum type, const GLvoid* indices);
+GL_APICALL void         GL_APIENTRY glEnable (GLenum cap);
+GL_APICALL void         GL_APIENTRY glEnableVertexAttribArray (GLuint index);
+GL_APICALL void         GL_APIENTRY glFinish (void);
+GL_APICALL void         GL_APIENTRY glFlush (void);
+GL_APICALL void         GL_APIENTRY glFramebufferRenderbuffer (GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer);
+GL_APICALL void         GL_APIENTRY glFramebufferTexture2D (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level);
+GL_APICALL void         GL_APIENTRY glFrontFace (GLenum mode);
+GL_APICALL void         GL_APIENTRY glGenBuffers (GLsizei n, GLuint* buffers);
+GL_APICALL void         GL_APIENTRY glGenerateMipmap (GLenum target);
+GL_APICALL void         GL_APIENTRY glGenFramebuffers (GLsizei n, GLuint* framebuffers);
+GL_APICALL void         GL_APIENTRY glGenRenderbuffers (GLsizei n, GLuint* renderbuffers);
+GL_APICALL void         GL_APIENTRY glGenTextures (GLsizei n, GLuint* textures);
+GL_APICALL void         GL_APIENTRY glGetActiveAttrib (GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, GLchar* name);
+GL_APICALL void         GL_APIENTRY glGetActiveUniform (GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, GLchar* name);
+GL_APICALL void         GL_APIENTRY glGetAttachedShaders (GLuint program, GLsizei maxcount, GLsizei* count, GLuint* shaders);
+GL_APICALL int          GL_APIENTRY glGetAttribLocation (GLuint program, const GLchar* name);
+GL_APICALL void         GL_APIENTRY glGetBooleanv (GLenum pname, GLboolean* params);
+GL_APICALL void         GL_APIENTRY glGetBufferParameteriv (GLenum target, GLenum pname, GLint* params);
+GL_APICALL GLenum       GL_APIENTRY glGetError (void);
+GL_APICALL void         GL_APIENTRY glGetFloatv (GLenum pname, GLfloat* params);
+GL_APICALL void         GL_APIENTRY glGetFramebufferAttachmentParameteriv (GLenum target, GLenum attachment, GLenum pname, GLint* params);
+GL_APICALL void         GL_APIENTRY glGetIntegerv (GLenum pname, GLint* params);
+GL_APICALL void         GL_APIENTRY glGetProgramiv (GLuint program, GLenum pname, GLint* params);
+GL_APICALL void         GL_APIENTRY glGetProgramInfoLog (GLuint program, GLsizei bufsize, GLsizei* length, GLchar* infolog);
+GL_APICALL void         GL_APIENTRY glGetRenderbufferParameteriv (GLenum target, GLenum pname, GLint* params);
+GL_APICALL void         GL_APIENTRY glGetShaderiv (GLuint shader, GLenum pname, GLint* params);
+GL_APICALL void         GL_APIENTRY glGetShaderInfoLog (GLuint shader, GLsizei bufsize, GLsizei* length, GLchar* infolog);
+GL_APICALL void         GL_APIENTRY glGetShaderPrecisionFormat (GLenum shadertype, GLenum precisiontype, GLint* range, GLint* precision);
+GL_APICALL void         GL_APIENTRY glGetShaderSource (GLuint shader, GLsizei bufsize, GLsizei* length, GLchar* source);
+GL_APICALL const GLubyte* GL_APIENTRY glGetString (GLenum name);
+GL_APICALL void         GL_APIENTRY glGetTexParameterfv (GLenum target, GLenum pname, GLfloat* params);
+GL_APICALL void         GL_APIENTRY glGetTexParameteriv (GLenum target, GLenum pname, GLint* params);
+GL_APICALL void         GL_APIENTRY glGetUniformfv (GLuint program, GLint location, GLfloat* params);
+GL_APICALL void         GL_APIENTRY glGetUniformiv (GLuint program, GLint location, GLint* params);
+GL_APICALL int          GL_APIENTRY glGetUniformLocation (GLuint program, const GLchar* name);
+GL_APICALL void         GL_APIENTRY glGetVertexAttribfv (GLuint index, GLenum pname, GLfloat* params);
+GL_APICALL void         GL_APIENTRY glGetVertexAttribiv (GLuint index, GLenum pname, GLint* params);
+GL_APICALL void         GL_APIENTRY glGetVertexAttribPointerv (GLuint index, GLenum pname, GLvoid** pointer);
+GL_APICALL void         GL_APIENTRY glHint (GLenum target, GLenum mode);
+GL_APICALL GLboolean    GL_APIENTRY glIsBuffer (GLuint buffer);
+GL_APICALL GLboolean    GL_APIENTRY glIsEnabled (GLenum cap);
+GL_APICALL GLboolean    GL_APIENTRY glIsFramebuffer (GLuint framebuffer);
+GL_APICALL GLboolean    GL_APIENTRY glIsProgram (GLuint program);
+GL_APICALL GLboolean    GL_APIENTRY glIsRenderbuffer (GLuint renderbuffer);
+GL_APICALL GLboolean    GL_APIENTRY glIsShader (GLuint shader);
+GL_APICALL GLboolean    GL_APIENTRY glIsTexture (GLuint texture);
+GL_APICALL void         GL_APIENTRY glLineWidth (GLfloat width);
+GL_APICALL void         GL_APIENTRY glLinkProgram (GLuint program);
+GL_APICALL void         GL_APIENTRY glPixelStorei (GLenum pname, GLint param);
+GL_APICALL void         GL_APIENTRY glPolygonOffset (GLfloat factor, GLfloat units);
+GL_APICALL void         GL_APIENTRY glReadPixels (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid* pixels);
+GL_APICALL void         GL_APIENTRY glReleaseShaderCompiler (void);
+GL_APICALL void         GL_APIENTRY glRenderbufferStorage (GLenum target, GLenum internalformat, GLsizei width, GLsizei height);
+GL_APICALL void         GL_APIENTRY glSampleCoverage (GLclampf value, GLboolean invert);
+GL_APICALL void         GL_APIENTRY glScissor (GLint x, GLint y, GLsizei width, GLsizei height);
+GL_APICALL void         GL_APIENTRY glShaderBinary (GLsizei n, const GLuint* shaders, GLenum binaryformat, const GLvoid* binary, GLsizei length);
+GL_APICALL void         GL_APIENTRY glShaderSource (GLuint shader, GLsizei count, const GLchar** string, const GLint* length);
+GL_APICALL void         GL_APIENTRY glStencilFunc (GLenum func, GLint ref, GLuint mask);
+GL_APICALL void         GL_APIENTRY glStencilFuncSeparate (GLenum face, GLenum func, GLint ref, GLuint mask);
+GL_APICALL void         GL_APIENTRY glStencilMask (GLuint mask);
+GL_APICALL void         GL_APIENTRY glStencilMaskSeparate (GLenum face, GLuint mask);
+GL_APICALL void         GL_APIENTRY glStencilOp (GLenum fail, GLenum zfail, GLenum zpass);
+GL_APICALL void         GL_APIENTRY glStencilOpSeparate (GLenum face, GLenum fail, GLenum zfail, GLenum zpass);
+GL_APICALL void         GL_APIENTRY glTexImage2D (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid* pixels);
+GL_APICALL void         GL_APIENTRY glTexParameterf (GLenum target, GLenum pname, GLfloat param);
+GL_APICALL void         GL_APIENTRY glTexParameterfv (GLenum target, GLenum pname, const GLfloat* params);
+GL_APICALL void         GL_APIENTRY glTexParameteri (GLenum target, GLenum pname, GLint param);
+GL_APICALL void         GL_APIENTRY glTexParameteriv (GLenum target, GLenum pname, const GLint* params);
+GL_APICALL void         GL_APIENTRY glTexSubImage2D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid* pixels);
+GL_APICALL void         GL_APIENTRY glUniform1f (GLint location, GLfloat x);
+GL_APICALL void         GL_APIENTRY glUniform1fv (GLint location, GLsizei count, const GLfloat* v);
+GL_APICALL void         GL_APIENTRY glUniform1i (GLint location, GLint x);
+GL_APICALL void         GL_APIENTRY glUniform1iv (GLint location, GLsizei count, const GLint* v);
+GL_APICALL void         GL_APIENTRY glUniform2f (GLint location, GLfloat x, GLfloat y);
+GL_APICALL void         GL_APIENTRY glUniform2fv (GLint location, GLsizei count, const GLfloat* v);
+GL_APICALL void         GL_APIENTRY glUniform2i (GLint location, GLint x, GLint y);
+GL_APICALL void         GL_APIENTRY glUniform2iv (GLint location, GLsizei count, const GLint* v);
+GL_APICALL void         GL_APIENTRY glUniform3f (GLint location, GLfloat x, GLfloat y, GLfloat z);
+GL_APICALL void         GL_APIENTRY glUniform3fv (GLint location, GLsizei count, const GLfloat* v);
+GL_APICALL void         GL_APIENTRY glUniform3i (GLint location, GLint x, GLint y, GLint z);
+GL_APICALL void         GL_APIENTRY glUniform3iv (GLint location, GLsizei count, const GLint* v);
+GL_APICALL void         GL_APIENTRY glUniform4f (GLint location, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+GL_APICALL void         GL_APIENTRY glUniform4fv (GLint location, GLsizei count, const GLfloat* v);
+GL_APICALL void         GL_APIENTRY glUniform4i (GLint location, GLint x, GLint y, GLint z, GLint w);
+GL_APICALL void         GL_APIENTRY glUniform4iv (GLint location, GLsizei count, const GLint* v);
+GL_APICALL void         GL_APIENTRY glUniformMatrix2fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
+GL_APICALL void         GL_APIENTRY glUniformMatrix3fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
+GL_APICALL void         GL_APIENTRY glUniformMatrix4fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
+GL_APICALL void         GL_APIENTRY glUseProgram (GLuint program);
+GL_APICALL void         GL_APIENTRY glValidateProgram (GLuint program);
+GL_APICALL void         GL_APIENTRY glVertexAttrib1f (GLuint indx, GLfloat x);
+GL_APICALL void         GL_APIENTRY glVertexAttrib1fv (GLuint indx, const GLfloat* values);
+GL_APICALL void         GL_APIENTRY glVertexAttrib2f (GLuint indx, GLfloat x, GLfloat y);
+GL_APICALL void         GL_APIENTRY glVertexAttrib2fv (GLuint indx, const GLfloat* values);
+GL_APICALL void         GL_APIENTRY glVertexAttrib3f (GLuint indx, GLfloat x, GLfloat y, GLfloat z);
+GL_APICALL void         GL_APIENTRY glVertexAttrib3fv (GLuint indx, const GLfloat* values);
+GL_APICALL void         GL_APIENTRY glVertexAttrib4f (GLuint indx, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+GL_APICALL void         GL_APIENTRY glVertexAttrib4fv (GLuint indx, const GLfloat* values);
+GL_APICALL void         GL_APIENTRY glVertexAttribPointer (GLuint indx, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid* ptr);
+GL_APICALL void         GL_APIENTRY glViewport (GLint x, GLint y, GLsizei width, GLsizei height);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __gl2_h_ */
diff --git a/src/3rdparty/angle/include/GLES2/gl2ext.h b/src/3rdparty/angle/include/GLES2/gl2ext.h
new file mode 100644 (file)
index 0000000..e297fbf
--- /dev/null
@@ -0,0 +1,1504 @@
+#ifndef __gl2ext_h_
+#define __gl2ext_h_
+
+/* $Revision: 16482 $ on $Date:: 2012-01-04 13:44:55 -0500 #$ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * This document is licensed under the SGI Free Software B License Version
+ * 2.0. For details, see http://oss.sgi.com/projects/FreeB/ .
+ */
+
+#ifndef GL_APIENTRYP
+#   define GL_APIENTRYP GL_APIENTRY*
+#endif
+
+/*------------------------------------------------------------------------*
+ * OES extension tokens
+ *------------------------------------------------------------------------*/
+
+/* GL_OES_compressed_ETC1_RGB8_texture */
+#ifndef GL_OES_compressed_ETC1_RGB8_texture
+#define GL_ETC1_RGB8_OES                                        0x8D64
+#endif
+
+/* GL_OES_compressed_paletted_texture */
+#ifndef GL_OES_compressed_paletted_texture
+#define GL_PALETTE4_RGB8_OES                                    0x8B90
+#define GL_PALETTE4_RGBA8_OES                                   0x8B91
+#define GL_PALETTE4_R5_G6_B5_OES                                0x8B92
+#define GL_PALETTE4_RGBA4_OES                                   0x8B93
+#define GL_PALETTE4_RGB5_A1_OES                                 0x8B94
+#define GL_PALETTE8_RGB8_OES                                    0x8B95
+#define GL_PALETTE8_RGBA8_OES                                   0x8B96
+#define GL_PALETTE8_R5_G6_B5_OES                                0x8B97
+#define GL_PALETTE8_RGBA4_OES                                   0x8B98
+#define GL_PALETTE8_RGB5_A1_OES                                 0x8B99
+#endif
+
+/* GL_OES_depth24 */
+#ifndef GL_OES_depth24
+#define GL_DEPTH_COMPONENT24_OES                                0x81A6
+#endif
+
+/* GL_OES_depth32 */
+#ifndef GL_OES_depth32
+#define GL_DEPTH_COMPONENT32_OES                                0x81A7
+#endif
+
+/* GL_OES_depth_texture */
+/* No new tokens introduced by this extension. */
+
+/* GL_OES_EGL_image */
+#ifndef GL_OES_EGL_image
+typedef void* GLeglImageOES;
+#endif
+
+/* GL_OES_EGL_image_external */
+#ifndef GL_OES_EGL_image_external
+/* GLeglImageOES defined in GL_OES_EGL_image already. */
+#define GL_TEXTURE_EXTERNAL_OES                                 0x8D65
+#define GL_SAMPLER_EXTERNAL_OES                                 0x8D66
+#define GL_TEXTURE_BINDING_EXTERNAL_OES                         0x8D67
+#define GL_REQUIRED_TEXTURE_IMAGE_UNITS_OES                     0x8D68
+#endif
+
+/* GL_OES_element_index_uint */
+#ifndef GL_OES_element_index_uint
+#define GL_UNSIGNED_INT                                         0x1405
+#endif
+
+/* GL_OES_get_program_binary */
+#ifndef GL_OES_get_program_binary
+#define GL_PROGRAM_BINARY_LENGTH_OES                            0x8741
+#define GL_NUM_PROGRAM_BINARY_FORMATS_OES                       0x87FE
+#define GL_PROGRAM_BINARY_FORMATS_OES                           0x87FF
+#endif
+
+/* GL_OES_mapbuffer */
+#ifndef GL_OES_mapbuffer
+#define GL_WRITE_ONLY_OES                                       0x88B9
+#define GL_BUFFER_ACCESS_OES                                    0x88BB
+#define GL_BUFFER_MAPPED_OES                                    0x88BC
+#define GL_BUFFER_MAP_POINTER_OES                               0x88BD
+#endif
+
+/* GL_OES_packed_depth_stencil */
+#ifndef GL_OES_packed_depth_stencil
+#define GL_DEPTH_STENCIL_OES                                    0x84F9
+#define GL_UNSIGNED_INT_24_8_OES                                0x84FA
+#define GL_DEPTH24_STENCIL8_OES                                 0x88F0
+#endif
+
+/* GL_OES_rgb8_rgba8 */
+#ifndef GL_OES_rgb8_rgba8
+#define GL_RGB8_OES                                             0x8051
+#define GL_RGBA8_OES                                            0x8058
+#endif
+
+/* GL_OES_standard_derivatives */
+#ifndef GL_OES_standard_derivatives
+#define GL_FRAGMENT_SHADER_DERIVATIVE_HINT_OES                  0x8B8B
+#endif
+
+/* GL_OES_stencil1 */
+#ifndef GL_OES_stencil1
+#define GL_STENCIL_INDEX1_OES                                   0x8D46
+#endif
+
+/* GL_OES_stencil4 */
+#ifndef GL_OES_stencil4
+#define GL_STENCIL_INDEX4_OES                                   0x8D47
+#endif
+
+/* GL_OES_texture_3D */
+#ifndef GL_OES_texture_3D
+#define GL_TEXTURE_WRAP_R_OES                                   0x8072
+#define GL_TEXTURE_3D_OES                                       0x806F
+#define GL_TEXTURE_BINDING_3D_OES                               0x806A
+#define GL_MAX_3D_TEXTURE_SIZE_OES                              0x8073
+#define GL_SAMPLER_3D_OES                                       0x8B5F
+#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_3D_ZOFFSET_OES        0x8CD4
+#endif
+
+/* GL_OES_texture_float */
+/* No new tokens introduced by this extension. */
+
+/* GL_OES_texture_float_linear */
+/* No new tokens introduced by this extension. */
+
+/* GL_OES_texture_half_float */
+#ifndef GL_OES_texture_half_float
+#define GL_HALF_FLOAT_OES                                       0x8D61
+#endif
+
+/* GL_OES_texture_half_float_linear */
+/* No new tokens introduced by this extension. */
+
+/* GL_OES_texture_npot */
+/* No new tokens introduced by this extension. */
+
+/* GL_OES_vertex_array_object */
+#ifndef GL_OES_vertex_array_object
+#define GL_VERTEX_ARRAY_BINDING_OES                             0x85B5
+#endif
+
+/* GL_OES_vertex_half_float */
+/* GL_HALF_FLOAT_OES defined in GL_OES_texture_half_float already. */
+
+/* GL_OES_vertex_type_10_10_10_2 */
+#ifndef GL_OES_vertex_type_10_10_10_2
+#define GL_UNSIGNED_INT_10_10_10_2_OES                          0x8DF6
+#define GL_INT_10_10_10_2_OES                                   0x8DF7
+#endif
+
+/*------------------------------------------------------------------------*
+ * AMD extension tokens
+ *------------------------------------------------------------------------*/
+
+/* GL_AMD_compressed_3DC_texture */
+#ifndef GL_AMD_compressed_3DC_texture
+#define GL_3DC_X_AMD                                            0x87F9
+#define GL_3DC_XY_AMD                                           0x87FA
+#endif
+
+/* GL_AMD_compressed_ATC_texture */
+#ifndef GL_AMD_compressed_ATC_texture
+#define GL_ATC_RGB_AMD                                          0x8C92
+#define GL_ATC_RGBA_EXPLICIT_ALPHA_AMD                          0x8C93
+#define GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD                      0x87EE
+#endif
+
+/* GL_AMD_performance_monitor */
+#ifndef GL_AMD_performance_monitor
+#define GL_COUNTER_TYPE_AMD                                     0x8BC0
+#define GL_COUNTER_RANGE_AMD                                    0x8BC1
+#define GL_UNSIGNED_INT64_AMD                                   0x8BC2
+#define GL_PERCENTAGE_AMD                                       0x8BC3
+#define GL_PERFMON_RESULT_AVAILABLE_AMD                         0x8BC4
+#define GL_PERFMON_RESULT_SIZE_AMD                              0x8BC5
+#define GL_PERFMON_RESULT_AMD                                   0x8BC6
+#endif
+
+/* GL_AMD_program_binary_Z400 */
+#ifndef GL_AMD_program_binary_Z400
+#define GL_Z400_BINARY_AMD                                      0x8740
+#endif
+
+/*------------------------------------------------------------------------*
+ * ANGLE extension tokens
+ *------------------------------------------------------------------------*/
+
+/* GL_ANGLE_framebuffer_blit */
+#ifndef GL_ANGLE_framebuffer_blit
+#define GL_READ_FRAMEBUFFER_ANGLE                               0x8CA8
+#define GL_DRAW_FRAMEBUFFER_ANGLE                               0x8CA9
+#define GL_DRAW_FRAMEBUFFER_BINDING_ANGLE                       0x8CA6
+#define GL_READ_FRAMEBUFFER_BINDING_ANGLE                       0x8CAA
+#endif
+
+/* GL_ANGLE_framebuffer_multisample */
+#ifndef GL_ANGLE_framebuffer_multisample
+#define GL_RENDERBUFFER_SAMPLES_ANGLE                           0x8CAB
+#define GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_ANGLE             0x8D56
+#define GL_MAX_SAMPLES_ANGLE                                    0x8D57
+#endif
+
+/* GL_ANGLE_pack_reverse_row_order */
+#ifndef GL_ANGLE_pack_reverse_row_order
+#define GL_PACK_REVERSE_ROW_ORDER_ANGLE                         0x93A4
+#endif
+
+/* GL_ANGLE_texture_compression_dxt3 */
+#ifndef GL_ANGLE_texture_compression_dxt3
+#define GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE                      0x83F2
+#endif
+
+/* GL_ANGLE_texture_compression_dxt5 */
+#ifndef GL_ANGLE_texture_compression_dxt5
+#define GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE                      0x83F3
+#endif
+
+/* GL_ANGLE_translated_shader_source */
+#ifndef GL_ANGLE_translated_shader_source
+#define GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE                0x93A0
+#endif
+
+/* GL_ANGLE_texture_usage */
+#ifndef GL_ANGLE_texture_usage
+#define GL_TEXTURE_USAGE_ANGLE                                  0x93A2
+#define GL_FRAMEBUFFER_ATTACHMENT_ANGLE                         0x93A3
+#endif
+
+/* GL_ANGLE_instanced_arrays */
+#ifndef GL_ANGLE_instanced_arrays
+#define GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE                    0x88FE
+#endif
+
+/* GL_ANGLE_program_binary */
+#ifndef GL_ANGLE_program_binary
+#define GL_PROGRAM_BINARY_ANGLE                                 0x93A6
+#endif
+
+/*------------------------------------------------------------------------*
+ * APPLE extension tokens
+ *------------------------------------------------------------------------*/
+
+/* GL_APPLE_rgb_422 */
+#ifndef GL_APPLE_rgb_422
+#define GL_RGB_422_APPLE                                        0x8A1F
+#define GL_UNSIGNED_SHORT_8_8_APPLE                             0x85BA
+#define GL_UNSIGNED_SHORT_8_8_REV_APPLE                         0x85BB
+#endif
+
+/* GL_APPLE_framebuffer_multisample */
+#ifndef GL_APPLE_framebuffer_multisample
+#define GL_RENDERBUFFER_SAMPLES_APPLE                           0x8CAB
+#define GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_APPLE             0x8D56
+#define GL_MAX_SAMPLES_APPLE                                    0x8D57
+#define GL_READ_FRAMEBUFFER_APPLE                               0x8CA8
+#define GL_DRAW_FRAMEBUFFER_APPLE                               0x8CA9
+#define GL_DRAW_FRAMEBUFFER_BINDING_APPLE                       0x8CA6
+#define GL_READ_FRAMEBUFFER_BINDING_APPLE                       0x8CAA
+#endif
+
+/* GL_APPLE_texture_format_BGRA8888 */
+#ifndef GL_APPLE_texture_format_BGRA8888
+#define GL_BGRA_EXT                                             0x80E1
+#endif
+
+/* GL_APPLE_texture_max_level */
+#ifndef GL_APPLE_texture_max_level
+#define GL_TEXTURE_MAX_LEVEL_APPLE                              0x813D
+#endif
+
+/*------------------------------------------------------------------------*
+ * ARM extension tokens
+ *------------------------------------------------------------------------*/
+
+/* GL_ARM_mali_shader_binary */
+#ifndef GL_ARM_mali_shader_binary
+#define GL_MALI_SHADER_BINARY_ARM                               0x8F60
+#endif
+
+/* GL_ARM_rgba8 */
+/* No new tokens introduced by this extension. */
+
+/*------------------------------------------------------------------------*
+ * EXT extension tokens
+ *------------------------------------------------------------------------*/
+
+/* GL_EXT_blend_minmax */
+#ifndef GL_EXT_blend_minmax
+#define GL_MIN_EXT                                              0x8007
+#define GL_MAX_EXT                                              0x8008
+#endif
+
+/* GL_EXT_color_buffer_half_float */
+#ifndef GL_EXT_color_buffer_half_float
+#define GL_RGBA16F_EXT                                          0x881A
+#define GL_RGB16F_EXT                                           0x881B
+#define GL_RG16F_EXT                                            0x822F
+#define GL_R16F_EXT                                             0x822D
+#define GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE_EXT            0x8211
+#define GL_UNSIGNED_NORMALIZED_EXT                              0x8C17
+#endif
+
+/* GL_EXT_debug_label */
+#ifndef GL_EXT_debug_label
+#define GL_PROGRAM_PIPELINE_OBJECT_EXT                          0x8A4F
+#define GL_PROGRAM_OBJECT_EXT                                   0x8B40
+#define GL_SHADER_OBJECT_EXT                                    0x8B48
+#define GL_BUFFER_OBJECT_EXT                                    0x9151
+#define GL_QUERY_OBJECT_EXT                                     0x9153
+#define GL_VERTEX_ARRAY_OBJECT_EXT                              0x9154
+#endif
+
+/* GL_EXT_debug_marker */
+/* No new tokens introduced by this extension. */
+
+/* GL_EXT_discard_framebuffer */
+#ifndef GL_EXT_discard_framebuffer
+#define GL_COLOR_EXT                                            0x1800
+#define GL_DEPTH_EXT                                            0x1801
+#define GL_STENCIL_EXT                                          0x1802
+#endif
+
+/* GL_EXT_multisampled_render_to_texture */
+#ifndef GL_EXT_multisampled_render_to_texture
+#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_SAMPLES_EXT           0x8D6C
+#define GL_RENDERBUFFER_SAMPLES_EXT                             0x9133
+#define GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_EXT               0x9134
+#define GL_MAX_SAMPLES_EXT                                      0x9135
+#endif
+
+/* GL_EXT_multi_draw_arrays */
+/* No new tokens introduced by this extension. */
+
+/* GL_EXT_occlusion_query_boolean */
+#ifndef GL_EXT_occlusion_query_boolean
+#define GL_ANY_SAMPLES_PASSED_EXT                               0x8C2F
+#define GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT                  0x8D6A
+#define GL_CURRENT_QUERY_EXT                                    0x8865
+#define GL_QUERY_RESULT_EXT                                     0x8866
+#define GL_QUERY_RESULT_AVAILABLE_EXT                           0x8867
+#endif
+
+/* GL_EXT_read_format_bgra */
+#ifndef GL_EXT_read_format_bgra
+#define GL_BGRA_EXT                                             0x80E1
+#define GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT                       0x8365
+#define GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT                       0x8366
+#endif
+
+/* GL_EXT_robustness */
+#ifndef GL_EXT_robustness
+/* reuse GL_NO_ERROR */
+#define GL_GUILTY_CONTEXT_RESET_EXT                             0x8253
+#define GL_INNOCENT_CONTEXT_RESET_EXT                           0x8254
+#define GL_UNKNOWN_CONTEXT_RESET_EXT                            0x8255
+#define GL_CONTEXT_ROBUST_ACCESS_EXT                            0x90F3
+#define GL_RESET_NOTIFICATION_STRATEGY_EXT                      0x8256
+#define GL_LOSE_CONTEXT_ON_RESET_EXT                            0x8252
+#define GL_NO_RESET_NOTIFICATION_EXT                            0x8261
+#endif
+
+/* GL_EXT_separate_shader_objects */
+#ifndef GL_EXT_separate_shader_objects
+#define GL_VERTEX_SHADER_BIT_EXT                                0x00000001
+#define GL_FRAGMENT_SHADER_BIT_EXT                              0x00000002
+#define GL_ALL_SHADER_BITS_EXT                                  0xFFFFFFFF
+#define GL_PROGRAM_SEPARABLE_EXT                                0x8258
+#define GL_ACTIVE_PROGRAM_EXT                                   0x8259
+#define GL_PROGRAM_PIPELINE_BINDING_EXT                         0x825A
+#endif
+
+/* GL_EXT_shader_texture_lod */
+/* No new tokens introduced by this extension. */
+
+/* GL_EXT_shadow_samplers */
+#ifndef GL_EXT_shadow_samplers
+#define GL_TEXTURE_COMPARE_MODE_EXT                             0x884C
+#define GL_TEXTURE_COMPARE_FUNC_EXT                             0x884D
+#define GL_COMPARE_REF_TO_TEXTURE_EXT                           0x884E
+#endif
+
+/* GL_EXT_sRGB */
+#ifndef GL_EXT_sRGB
+#define GL_SRGB_EXT                                             0x8C40
+#define GL_SRGB_ALPHA_EXT                                       0x8C42
+#define GL_SRGB8_ALPHA8_EXT                                     0x8C43
+#define GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING_EXT            0x8210
+#endif
+
+/* GL_EXT_texture_compression_dxt1 */
+#ifndef GL_EXT_texture_compression_dxt1
+#define GL_COMPRESSED_RGB_S3TC_DXT1_EXT                         0x83F0
+#define GL_COMPRESSED_RGBA_S3TC_DXT1_EXT                        0x83F1
+#endif
+
+/* GL_EXT_texture_filter_anisotropic */
+#ifndef GL_EXT_texture_filter_anisotropic
+#define GL_TEXTURE_MAX_ANISOTROPY_EXT                           0x84FE
+#define GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT                       0x84FF
+#endif
+
+/* GL_EXT_texture_format_BGRA8888 */
+#ifndef GL_EXT_texture_format_BGRA8888
+#define GL_BGRA_EXT                                             0x80E1
+#endif
+
+/* GL_EXT_texture_rg */
+#ifndef GL_EXT_texture_rg
+#define GL_RED_EXT                                              0x1903
+#define GL_RG_EXT                                               0x8227
+#define GL_R8_EXT                                               0x8229
+#define GL_RG8_EXT                                              0x822B
+#endif
+
+/* GL_EXT_texture_storage */
+#ifndef GL_EXT_texture_storage
+#define GL_TEXTURE_IMMUTABLE_FORMAT_EXT                         0x912F
+#define GL_ALPHA8_EXT                                           0x803C  
+#define GL_LUMINANCE8_EXT                                       0x8040
+#define GL_LUMINANCE8_ALPHA8_EXT                                0x8045
+#define GL_RGBA32F_EXT                                          0x8814  
+#define GL_RGB32F_EXT                                           0x8815
+#define GL_ALPHA32F_EXT                                         0x8816
+#define GL_LUMINANCE32F_EXT                                     0x8818
+#define GL_LUMINANCE_ALPHA32F_EXT                               0x8819
+/* reuse GL_RGBA16F_EXT */
+#define GL_RGB16F_EXT                                           0x881B
+#define GL_ALPHA16F_EXT                                         0x881C
+#define GL_LUMINANCE16F_EXT                                     0x881E
+#define GL_LUMINANCE_ALPHA16F_EXT                               0x881F
+#define GL_RGB10_A2_EXT                                         0x8059  
+#define GL_RGB10_EXT                                            0x8052
+#define GL_BGRA8_EXT                                            0x93A1
+#endif
+
+/* GL_EXT_texture_type_2_10_10_10_REV */
+#ifndef GL_EXT_texture_type_2_10_10_10_REV
+#define GL_UNSIGNED_INT_2_10_10_10_REV_EXT                      0x8368
+#endif
+
+/* GL_EXT_unpack_subimage */
+#ifndef GL_EXT_unpack_subimage
+#define GL_UNPACK_ROW_LENGTH                                    0x0CF2
+#define GL_UNPACK_SKIP_ROWS                                     0x0CF3
+#define GL_UNPACK_SKIP_PIXELS                                   0x0CF4
+#endif
+
+/*------------------------------------------------------------------------*
+ * DMP extension tokens
+ *------------------------------------------------------------------------*/
+
+/* GL_DMP_shader_binary */
+#ifndef GL_DMP_shader_binary
+#define GL_SHADER_BINARY_DMP                                    0x9250
+#endif
+
+/*------------------------------------------------------------------------*
+ * IMG extension tokens
+ *------------------------------------------------------------------------*/
+
+/* GL_IMG_program_binary */
+#ifndef GL_IMG_program_binary
+#define GL_SGX_PROGRAM_BINARY_IMG                               0x9130
+#endif
+
+/* GL_IMG_read_format */
+#ifndef GL_IMG_read_format
+#define GL_BGRA_IMG                                             0x80E1
+#define GL_UNSIGNED_SHORT_4_4_4_4_REV_IMG                       0x8365
+#endif
+
+/* GL_IMG_shader_binary */
+#ifndef GL_IMG_shader_binary
+#define GL_SGX_BINARY_IMG                                       0x8C0A
+#endif
+
+/* GL_IMG_texture_compression_pvrtc */
+#ifndef GL_IMG_texture_compression_pvrtc
+#define GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG                      0x8C00
+#define GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG                      0x8C01
+#define GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG                     0x8C02
+#define GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG                     0x8C03
+#endif
+
+/* GL_IMG_multisampled_render_to_texture */
+#ifndef GL_IMG_multisampled_render_to_texture
+#define GL_RENDERBUFFER_SAMPLES_IMG                             0x9133
+#define GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_IMG               0x9134
+#define GL_MAX_SAMPLES_IMG                                      0x9135
+#define GL_TEXTURE_SAMPLES_IMG                                  0x9136
+#endif
+
+/*------------------------------------------------------------------------*
+ * NV extension tokens
+ *------------------------------------------------------------------------*/
+
+/* GL_NV_coverage_sample */
+#ifndef GL_NV_coverage_sample
+#define GL_COVERAGE_COMPONENT_NV                                0x8ED0
+#define GL_COVERAGE_COMPONENT4_NV                               0x8ED1
+#define GL_COVERAGE_ATTACHMENT_NV                               0x8ED2
+#define GL_COVERAGE_BUFFERS_NV                                  0x8ED3
+#define GL_COVERAGE_SAMPLES_NV                                  0x8ED4
+#define GL_COVERAGE_ALL_FRAGMENTS_NV                            0x8ED5
+#define GL_COVERAGE_EDGE_FRAGMENTS_NV                           0x8ED6
+#define GL_COVERAGE_AUTOMATIC_NV                                0x8ED7
+#define GL_COVERAGE_BUFFER_BIT_NV                               0x8000
+#endif
+
+/* GL_NV_depth_nonlinear */
+#ifndef GL_NV_depth_nonlinear
+#define GL_DEPTH_COMPONENT16_NONLINEAR_NV                       0x8E2C
+#endif
+
+/* GL_NV_draw_buffers */
+#ifndef GL_NV_draw_buffers
+#define GL_MAX_DRAW_BUFFERS_NV                                  0x8824
+#define GL_DRAW_BUFFER0_NV                                      0x8825
+#define GL_DRAW_BUFFER1_NV                                      0x8826
+#define GL_DRAW_BUFFER2_NV                                      0x8827
+#define GL_DRAW_BUFFER3_NV                                      0x8828
+#define GL_DRAW_BUFFER4_NV                                      0x8829
+#define GL_DRAW_BUFFER5_NV                                      0x882A
+#define GL_DRAW_BUFFER6_NV                                      0x882B
+#define GL_DRAW_BUFFER7_NV                                      0x882C
+#define GL_DRAW_BUFFER8_NV                                      0x882D
+#define GL_DRAW_BUFFER9_NV                                      0x882E
+#define GL_DRAW_BUFFER10_NV                                     0x882F
+#define GL_DRAW_BUFFER11_NV                                     0x8830
+#define GL_DRAW_BUFFER12_NV                                     0x8831
+#define GL_DRAW_BUFFER13_NV                                     0x8832
+#define GL_DRAW_BUFFER14_NV                                     0x8833
+#define GL_DRAW_BUFFER15_NV                                     0x8834
+#define GL_COLOR_ATTACHMENT0_NV                                 0x8CE0
+#define GL_COLOR_ATTACHMENT1_NV                                 0x8CE1
+#define GL_COLOR_ATTACHMENT2_NV                                 0x8CE2
+#define GL_COLOR_ATTACHMENT3_NV                                 0x8CE3
+#define GL_COLOR_ATTACHMENT4_NV                                 0x8CE4
+#define GL_COLOR_ATTACHMENT5_NV                                 0x8CE5
+#define GL_COLOR_ATTACHMENT6_NV                                 0x8CE6
+#define GL_COLOR_ATTACHMENT7_NV                                 0x8CE7
+#define GL_COLOR_ATTACHMENT8_NV                                 0x8CE8
+#define GL_COLOR_ATTACHMENT9_NV                                 0x8CE9
+#define GL_COLOR_ATTACHMENT10_NV                                0x8CEA
+#define GL_COLOR_ATTACHMENT11_NV                                0x8CEB
+#define GL_COLOR_ATTACHMENT12_NV                                0x8CEC
+#define GL_COLOR_ATTACHMENT13_NV                                0x8CED
+#define GL_COLOR_ATTACHMENT14_NV                                0x8CEE
+#define GL_COLOR_ATTACHMENT15_NV                                0x8CEF
+#endif
+
+/* GL_NV_fbo_color_attachments */
+#ifndef GL_NV_fbo_color_attachments
+#define GL_MAX_COLOR_ATTACHMENTS_NV                             0x8CDF
+/* GL_COLOR_ATTACHMENT{0-15}_NV defined in GL_NV_draw_buffers already. */
+#endif
+
+/* GL_NV_fence */
+#ifndef GL_NV_fence
+#define GL_ALL_COMPLETED_NV                                     0x84F2
+#define GL_FENCE_STATUS_NV                                      0x84F3
+#define GL_FENCE_CONDITION_NV                                   0x84F4
+#endif
+
+/* GL_NV_read_buffer */
+#ifndef GL_NV_read_buffer
+#define GL_READ_BUFFER_NV                                       0x0C02
+#endif
+
+/* GL_NV_read_buffer_front */
+/* No new tokens introduced by this extension. */
+
+/* GL_NV_read_depth */
+/* No new tokens introduced by this extension. */
+
+/* GL_NV_read_depth_stencil */
+/* No new tokens introduced by this extension. */
+
+/* GL_NV_read_stencil */
+/* No new tokens introduced by this extension. */
+
+/* GL_NV_texture_compression_s3tc_update */
+/* No new tokens introduced by this extension. */
+
+/* GL_NV_texture_npot_2D_mipmap */
+/* No new tokens introduced by this extension. */
+
+/*------------------------------------------------------------------------*
+ * QCOM extension tokens
+ *------------------------------------------------------------------------*/
+
+/* GL_QCOM_alpha_test */
+#ifndef GL_QCOM_alpha_test
+#define GL_ALPHA_TEST_QCOM                                      0x0BC0
+#define GL_ALPHA_TEST_FUNC_QCOM                                 0x0BC1
+#define GL_ALPHA_TEST_REF_QCOM                                  0x0BC2
+#endif
+
+/* GL_QCOM_driver_control */
+/* No new tokens introduced by this extension. */
+
+/* GL_QCOM_extended_get */
+#ifndef GL_QCOM_extended_get
+#define GL_TEXTURE_WIDTH_QCOM                                   0x8BD2
+#define GL_TEXTURE_HEIGHT_QCOM                                  0x8BD3
+#define GL_TEXTURE_DEPTH_QCOM                                   0x8BD4
+#define GL_TEXTURE_INTERNAL_FORMAT_QCOM                         0x8BD5
+#define GL_TEXTURE_FORMAT_QCOM                                  0x8BD6
+#define GL_TEXTURE_TYPE_QCOM                                    0x8BD7
+#define GL_TEXTURE_IMAGE_VALID_QCOM                             0x8BD8
+#define GL_TEXTURE_NUM_LEVELS_QCOM                              0x8BD9
+#define GL_TEXTURE_TARGET_QCOM                                  0x8BDA
+#define GL_TEXTURE_OBJECT_VALID_QCOM                            0x8BDB
+#define GL_STATE_RESTORE                                        0x8BDC
+#endif
+
+/* GL_QCOM_extended_get2 */
+/* No new tokens introduced by this extension. */
+
+/* GL_QCOM_perfmon_global_mode */
+#ifndef GL_QCOM_perfmon_global_mode
+#define GL_PERFMON_GLOBAL_MODE_QCOM                             0x8FA0
+#endif
+
+/* GL_QCOM_writeonly_rendering */
+#ifndef GL_QCOM_writeonly_rendering
+#define GL_WRITEONLY_RENDERING_QCOM                             0x8823
+#endif
+
+/* GL_QCOM_tiled_rendering */
+#ifndef GL_QCOM_tiled_rendering
+#define GL_COLOR_BUFFER_BIT0_QCOM                               0x00000001
+#define GL_COLOR_BUFFER_BIT1_QCOM                               0x00000002
+#define GL_COLOR_BUFFER_BIT2_QCOM                               0x00000004
+#define GL_COLOR_BUFFER_BIT3_QCOM                               0x00000008
+#define GL_COLOR_BUFFER_BIT4_QCOM                               0x00000010
+#define GL_COLOR_BUFFER_BIT5_QCOM                               0x00000020
+#define GL_COLOR_BUFFER_BIT6_QCOM                               0x00000040
+#define GL_COLOR_BUFFER_BIT7_QCOM                               0x00000080
+#define GL_DEPTH_BUFFER_BIT0_QCOM                               0x00000100
+#define GL_DEPTH_BUFFER_BIT1_QCOM                               0x00000200
+#define GL_DEPTH_BUFFER_BIT2_QCOM                               0x00000400
+#define GL_DEPTH_BUFFER_BIT3_QCOM                               0x00000800
+#define GL_DEPTH_BUFFER_BIT4_QCOM                               0x00001000
+#define GL_DEPTH_BUFFER_BIT5_QCOM                               0x00002000
+#define GL_DEPTH_BUFFER_BIT6_QCOM                               0x00004000
+#define GL_DEPTH_BUFFER_BIT7_QCOM                               0x00008000
+#define GL_STENCIL_BUFFER_BIT0_QCOM                             0x00010000
+#define GL_STENCIL_BUFFER_BIT1_QCOM                             0x00020000
+#define GL_STENCIL_BUFFER_BIT2_QCOM                             0x00040000
+#define GL_STENCIL_BUFFER_BIT3_QCOM                             0x00080000
+#define GL_STENCIL_BUFFER_BIT4_QCOM                             0x00100000
+#define GL_STENCIL_BUFFER_BIT5_QCOM                             0x00200000
+#define GL_STENCIL_BUFFER_BIT6_QCOM                             0x00400000
+#define GL_STENCIL_BUFFER_BIT7_QCOM                             0x00800000
+#define GL_MULTISAMPLE_BUFFER_BIT0_QCOM                         0x01000000
+#define GL_MULTISAMPLE_BUFFER_BIT1_QCOM                         0x02000000
+#define GL_MULTISAMPLE_BUFFER_BIT2_QCOM                         0x04000000
+#define GL_MULTISAMPLE_BUFFER_BIT3_QCOM                         0x08000000
+#define GL_MULTISAMPLE_BUFFER_BIT4_QCOM                         0x10000000
+#define GL_MULTISAMPLE_BUFFER_BIT5_QCOM                         0x20000000
+#define GL_MULTISAMPLE_BUFFER_BIT6_QCOM                         0x40000000
+#define GL_MULTISAMPLE_BUFFER_BIT7_QCOM                         0x80000000
+#endif
+
+/*------------------------------------------------------------------------*
+ * VIV extension tokens
+ *------------------------------------------------------------------------*/
+
+/* GL_VIV_shader_binary */
+#ifndef GL_VIV_shader_binary
+#define GL_SHADER_BINARY_VIV                                    0x8FC4
+#endif
+
+/*------------------------------------------------------------------------*
+ * End of extension tokens, start of corresponding extension functions
+ *------------------------------------------------------------------------*/
+
+/*------------------------------------------------------------------------*
+ * OES extension functions
+ *------------------------------------------------------------------------*/
+
+/* GL_OES_compressed_ETC1_RGB8_texture */
+#ifndef GL_OES_compressed_ETC1_RGB8_texture
+#define GL_OES_compressed_ETC1_RGB8_texture 1
+#endif
+
+/* GL_OES_compressed_paletted_texture */
+#ifndef GL_OES_compressed_paletted_texture
+#define GL_OES_compressed_paletted_texture 1
+#endif
+
+/* GL_OES_depth24 */
+#ifndef GL_OES_depth24
+#define GL_OES_depth24 1
+#endif
+
+/* GL_OES_depth32 */
+#ifndef GL_OES_depth32
+#define GL_OES_depth32 1
+#endif
+
+/* GL_OES_depth_texture */
+#ifndef GL_OES_depth_texture
+#define GL_OES_depth_texture 1
+#endif
+
+/* GL_OES_EGL_image */
+#ifndef GL_OES_EGL_image
+#define GL_OES_EGL_image 1
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glEGLImageTargetTexture2DOES (GLenum target, GLeglImageOES image);
+GL_APICALL void GL_APIENTRY glEGLImageTargetRenderbufferStorageOES (GLenum target, GLeglImageOES image);
+#endif
+typedef void (GL_APIENTRYP PFNGLEGLIMAGETARGETTEXTURE2DOESPROC) (GLenum target, GLeglImageOES image);
+typedef void (GL_APIENTRYP PFNGLEGLIMAGETARGETRENDERBUFFERSTORAGEOESPROC) (GLenum target, GLeglImageOES image);
+#endif
+
+/* GL_OES_EGL_image_external */
+#ifndef GL_OES_EGL_image_external
+#define GL_OES_EGL_image_external 1
+/* glEGLImageTargetTexture2DOES defined in GL_OES_EGL_image already. */
+#endif
+
+/* GL_OES_element_index_uint */
+#ifndef GL_OES_element_index_uint
+#define GL_OES_element_index_uint 1
+#endif
+
+/* GL_OES_fbo_render_mipmap */
+#ifndef GL_OES_fbo_render_mipmap
+#define GL_OES_fbo_render_mipmap 1
+#endif
+
+/* GL_OES_fragment_precision_high */
+#ifndef GL_OES_fragment_precision_high
+#define GL_OES_fragment_precision_high 1
+#endif
+
+/* GL_OES_get_program_binary */
+#ifndef GL_OES_get_program_binary
+#define GL_OES_get_program_binary 1
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glGetProgramBinaryOES (GLuint program, GLsizei bufSize, GLsizei *length, GLenum *binaryFormat, GLvoid *binary);
+GL_APICALL void GL_APIENTRY glProgramBinaryOES (GLuint program, GLenum binaryFormat, const GLvoid *binary, GLint length);
+#endif
+typedef void (GL_APIENTRYP PFNGLGETPROGRAMBINARYOESPROC) (GLuint program, GLsizei bufSize, GLsizei *length, GLenum *binaryFormat, GLvoid *binary);
+typedef void (GL_APIENTRYP PFNGLPROGRAMBINARYOESPROC) (GLuint program, GLenum binaryFormat, const GLvoid *binary, GLint length);
+#endif
+
+/* GL_OES_mapbuffer */
+#ifndef GL_OES_mapbuffer
+#define GL_OES_mapbuffer 1
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void* GL_APIENTRY glMapBufferOES (GLenum target, GLenum access);
+GL_APICALL GLboolean GL_APIENTRY glUnmapBufferOES (GLenum target);
+GL_APICALL void GL_APIENTRY glGetBufferPointervOES (GLenum target, GLenum pname, GLvoid** params);
+#endif
+typedef void* (GL_APIENTRYP PFNGLMAPBUFFEROESPROC) (GLenum target, GLenum access);
+typedef GLboolean (GL_APIENTRYP PFNGLUNMAPBUFFEROESPROC) (GLenum target);
+typedef void (GL_APIENTRYP PFNGLGETBUFFERPOINTERVOESPROC) (GLenum target, GLenum pname, GLvoid** params);
+#endif
+
+/* GL_OES_packed_depth_stencil */
+#ifndef GL_OES_packed_depth_stencil
+#define GL_OES_packed_depth_stencil 1
+#endif
+
+/* GL_OES_rgb8_rgba8 */
+#ifndef GL_OES_rgb8_rgba8
+#define GL_OES_rgb8_rgba8 1
+#endif
+
+/* GL_OES_standard_derivatives */
+#ifndef GL_OES_standard_derivatives
+#define GL_OES_standard_derivatives 1
+#endif
+
+/* GL_OES_stencil1 */
+#ifndef GL_OES_stencil1
+#define GL_OES_stencil1 1
+#endif
+
+/* GL_OES_stencil4 */
+#ifndef GL_OES_stencil4
+#define GL_OES_stencil4 1
+#endif
+
+/* GL_OES_texture_3D */
+#ifndef GL_OES_texture_3D
+#define GL_OES_texture_3D 1
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glTexImage3DOES (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const GLvoid* pixels);
+GL_APICALL void GL_APIENTRY glTexSubImage3DOES (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const GLvoid* pixels);
+GL_APICALL void GL_APIENTRY glCopyTexSubImage3DOES (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height);
+GL_APICALL void GL_APIENTRY glCompressedTexImage3DOES (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const GLvoid* data);
+GL_APICALL void GL_APIENTRY glCompressedTexSubImage3DOES (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const GLvoid* data);
+GL_APICALL void GL_APIENTRY glFramebufferTexture3DOES (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLint zoffset);
+#endif
+typedef void (GL_APIENTRYP PFNGLTEXIMAGE3DOESPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const GLvoid* pixels);
+typedef void (GL_APIENTRYP PFNGLTEXSUBIMAGE3DOESPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const GLvoid* pixels);
+typedef void (GL_APIENTRYP PFNGLCOPYTEXSUBIMAGE3DOESPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height);
+typedef void (GL_APIENTRYP PFNGLCOMPRESSEDTEXIMAGE3DOESPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const GLvoid* data);
+typedef void (GL_APIENTRYP PFNGLCOMPRESSEDTEXSUBIMAGE3DOESPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const GLvoid* data);
+typedef void (GL_APIENTRYP PFNGLFRAMEBUFFERTEXTURE3DOES) (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLint zoffset);
+#endif
+
+/* GL_OES_texture_float */
+#ifndef GL_OES_texture_float
+#define GL_OES_texture_float 1
+#endif
+
+/* GL_OES_texture_float_linear */
+#ifndef GL_OES_texture_float_linear
+#define GL_OES_texture_float_linear 1
+#endif
+
+/* GL_OES_texture_half_float */
+#ifndef GL_OES_texture_half_float
+#define GL_OES_texture_half_float 1
+#endif
+
+/* GL_OES_texture_half_float_linear */
+#ifndef GL_OES_texture_half_float_linear
+#define GL_OES_texture_half_float_linear 1
+#endif
+
+/* GL_OES_texture_npot */
+#ifndef GL_OES_texture_npot
+#define GL_OES_texture_npot 1
+#endif
+
+/* GL_OES_vertex_array_object */
+#ifndef GL_OES_vertex_array_object
+#define GL_OES_vertex_array_object 1
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glBindVertexArrayOES (GLuint array);
+GL_APICALL void GL_APIENTRY glDeleteVertexArraysOES (GLsizei n, const GLuint *arrays);
+GL_APICALL void GL_APIENTRY glGenVertexArraysOES (GLsizei n, GLuint *arrays);
+GL_APICALL GLboolean GL_APIENTRY glIsVertexArrayOES (GLuint array);
+#endif
+typedef void (GL_APIENTRYP PFNGLBINDVERTEXARRAYOESPROC) (GLuint array);
+typedef void (GL_APIENTRYP PFNGLDELETEVERTEXARRAYSOESPROC) (GLsizei n, const GLuint *arrays);
+typedef void (GL_APIENTRYP PFNGLGENVERTEXARRAYSOESPROC) (GLsizei n, GLuint *arrays);
+typedef GLboolean (GL_APIENTRYP PFNGLISVERTEXARRAYOESPROC) (GLuint array);
+#endif
+
+/* GL_OES_vertex_half_float */
+#ifndef GL_OES_vertex_half_float
+#define GL_OES_vertex_half_float 1
+#endif
+
+/* GL_OES_vertex_type_10_10_10_2 */
+#ifndef GL_OES_vertex_type_10_10_10_2
+#define GL_OES_vertex_type_10_10_10_2 1
+#endif
+
+/*------------------------------------------------------------------------*
+ * AMD extension functions
+ *------------------------------------------------------------------------*/
+
+/* GL_AMD_compressed_3DC_texture */
+#ifndef GL_AMD_compressed_3DC_texture
+#define GL_AMD_compressed_3DC_texture 1
+#endif
+
+/* GL_AMD_compressed_ATC_texture */
+#ifndef GL_AMD_compressed_ATC_texture
+#define GL_AMD_compressed_ATC_texture 1
+#endif
+
+/* AMD_performance_monitor */
+#ifndef GL_AMD_performance_monitor
+#define GL_AMD_performance_monitor 1
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glGetPerfMonitorGroupsAMD (GLint *numGroups, GLsizei groupsSize, GLuint *groups);
+GL_APICALL void GL_APIENTRY glGetPerfMonitorCountersAMD (GLuint group, GLint *numCounters, GLint *maxActiveCounters, GLsizei counterSize, GLuint *counters);
+GL_APICALL void GL_APIENTRY glGetPerfMonitorGroupStringAMD (GLuint group, GLsizei bufSize, GLsizei *length, GLchar *groupString);
+GL_APICALL void GL_APIENTRY glGetPerfMonitorCounterStringAMD (GLuint group, GLuint counter, GLsizei bufSize, GLsizei *length, GLchar *counterString);
+GL_APICALL void GL_APIENTRY glGetPerfMonitorCounterInfoAMD (GLuint group, GLuint counter, GLenum pname, GLvoid *data);
+GL_APICALL void GL_APIENTRY glGenPerfMonitorsAMD (GLsizei n, GLuint *monitors);
+GL_APICALL void GL_APIENTRY glDeletePerfMonitorsAMD (GLsizei n, GLuint *monitors);
+GL_APICALL void GL_APIENTRY glSelectPerfMonitorCountersAMD (GLuint monitor, GLboolean enable, GLuint group, GLint numCounters, GLuint *countersList);
+GL_APICALL void GL_APIENTRY glBeginPerfMonitorAMD (GLuint monitor);
+GL_APICALL void GL_APIENTRY glEndPerfMonitorAMD (GLuint monitor);
+GL_APICALL void GL_APIENTRY glGetPerfMonitorCounterDataAMD (GLuint monitor, GLenum pname, GLsizei dataSize, GLuint *data, GLint *bytesWritten);
+#endif
+typedef void (GL_APIENTRYP PFNGLGETPERFMONITORGROUPSAMDPROC) (GLint *numGroups, GLsizei groupsSize, GLuint *groups);
+typedef void (GL_APIENTRYP PFNGLGETPERFMONITORCOUNTERSAMDPROC) (GLuint group, GLint *numCounters, GLint *maxActiveCounters, GLsizei counterSize, GLuint *counters);
+typedef void (GL_APIENTRYP PFNGLGETPERFMONITORGROUPSTRINGAMDPROC) (GLuint group, GLsizei bufSize, GLsizei *length, GLchar *groupString);
+typedef void (GL_APIENTRYP PFNGLGETPERFMONITORCOUNTERSTRINGAMDPROC) (GLuint group, GLuint counter, GLsizei bufSize, GLsizei *length, GLchar *counterString);
+typedef void (GL_APIENTRYP PFNGLGETPERFMONITORCOUNTERINFOAMDPROC) (GLuint group, GLuint counter, GLenum pname, GLvoid *data);
+typedef void (GL_APIENTRYP PFNGLGENPERFMONITORSAMDPROC) (GLsizei n, GLuint *monitors);
+typedef void (GL_APIENTRYP PFNGLDELETEPERFMONITORSAMDPROC) (GLsizei n, GLuint *monitors);
+typedef void (GL_APIENTRYP PFNGLSELECTPERFMONITORCOUNTERSAMDPROC) (GLuint monitor, GLboolean enable, GLuint group, GLint numCounters, GLuint *countersList);
+typedef void (GL_APIENTRYP PFNGLBEGINPERFMONITORAMDPROC) (GLuint monitor);
+typedef void (GL_APIENTRYP PFNGLENDPERFMONITORAMDPROC) (GLuint monitor);
+typedef void (GL_APIENTRYP PFNGLGETPERFMONITORCOUNTERDATAAMDPROC) (GLuint monitor, GLenum pname, GLsizei dataSize, GLuint *data, GLint *bytesWritten);
+#endif
+
+/* GL_AMD_program_binary_Z400 */
+#ifndef GL_AMD_program_binary_Z400
+#define GL_AMD_program_binary_Z400 1
+#endif
+
+/*------------------------------------------------------------------------*
+ * ANGLE extension functions
+ *------------------------------------------------------------------------*/
+
+/* GL_ANGLE_framebuffer_blit */
+#ifndef GL_ANGLE_framebuffer_blit
+#define GL_ANGLE_framebuffer_blit 1
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glBlitFramebufferANGLE (GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter);
+#endif
+typedef void (GL_APIENTRYP PFNGLBLITFRAMEBUFFERANGLEPROC) (GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter);
+#endif
+
+/* GL_ANGLE_framebuffer_multisample */
+#ifndef GL_ANGLE_framebuffer_multisample
+#define GL_ANGLE_framebuffer_multisample 1
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glRenderbufferStorageMultisampleANGLE (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height);
+#endif
+typedef void (GL_APIENTRYP PFNGLRENDERBUFFERSTORAGEMULTISAMPLEANGLEPROC) (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height);
+#endif
+
+/* GL_ANGLE_pack_reverse_row_order */
+#ifndef GL_ANGLE_pack_reverse_row_order
+#define GL_ANGLE_pack_reverse_row_order 1
+#endif
+
+/* GL_ANGLE_texture_compression_dxt3 */
+#ifndef GL_ANGLE_texture_compression_dxt3
+#define GL_ANGLE_texture_compression_dxt3 1
+#endif
+
+/* GL_ANGLE_texture_compression_dxt5 */
+#ifndef GL_ANGLE_texture_compression_dxt5
+#define GL_ANGLE_texture_compression_dxt5 1
+#endif
+
+/* GL_ANGLE_translated_shader_source */
+#ifndef GL_ANGLE_translated_shader_source
+#define GL_ANGLE_translated_shader_source 1
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glGetTranslatedShaderSourceANGLE (GLuint shader, GLsizei bufsize, GLsizei* length, GLchar* source);
+#endif
+typedef void (GL_APIENTRYP PFNGLGETTRANSLATEDSHADERSOURCEANGLEPROC) (GLuint shader, GLsizei bufsize, GLsizei* length, GLchar* source);
+#endif
+
+/* GL_ANGLE_texture_usage */
+#ifndef GL_ANGLE_texture_usage
+#define GL_ANGLE_texture_usage 1
+#endif
+
+/* GL_ANGLE_instanced_arrays */
+#ifndef GL_ANGLE_instanced_arrays
+#define GL_ANGLE_instanced_arrays 1
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glVertexAttribDivisorANGLE(GLuint index, GLuint divisor);
+GL_APICALL void GL_APIENTRY glDrawArraysInstancedANGLE(GLenum mode, GLint first, GLsizei count, GLsizei primcount);
+GL_APICALL void GL_APIENTRY glDrawElementsInstancedANGLE(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, GLsizei primcount);
+#endif
+typedef void (GL_APIENTRYP PFNGLVERTEXATTRIBDIVISORANGLEPROC) (GLuint index, GLuint divisor);
+typedef void (GL_APIENTRYP PFNGLDRAWARRAYSINSTANCEDANGLEPROC) (GLenum mode, GLint first, GLsizei count, GLsizei primcount);
+typedef void (GL_APIENTRYP PFNGLDRAWELEMENTSINSTANCEDANGLEPROC) (GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, GLsizei primcount);
+#endif
+
+/*------------------------------------------------------------------------*
+ * APPLE extension functions
+ *------------------------------------------------------------------------*/
+
+/* GL_APPLE_rgb_422 */
+#ifndef GL_APPLE_rgb_422
+#define GL_APPLE_rgb_422 1
+#endif
+
+/* GL_APPLE_framebuffer_multisample */
+#ifndef GL_APPLE_framebuffer_multisample
+#define GL_APPLE_framebuffer_multisample 1
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glRenderbufferStorageMultisampleAPPLE (GLenum, GLsizei, GLenum, GLsizei, GLsizei);
+GL_APICALL void GL_APIENTRY glResolveMultisampleFramebufferAPPLE (void);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (GL_APIENTRYP PFNGLRENDERBUFFERSTORAGEMULTISAMPLEAPPLEPROC) (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height);
+typedef void (GL_APIENTRYP PFNGLRESOLVEMULTISAMPLEFRAMEBUFFERAPPLEPROC) (void);
+#endif
+
+/* GL_APPLE_texture_format_BGRA8888 */
+#ifndef GL_APPLE_texture_format_BGRA8888
+#define GL_APPLE_texture_format_BGRA8888 1
+#endif
+
+/* GL_APPLE_texture_max_level */
+#ifndef GL_APPLE_texture_max_level
+#define GL_APPLE_texture_max_level 1
+#endif
+
+/*------------------------------------------------------------------------*
+ * ARM extension functions
+ *------------------------------------------------------------------------*/
+
+/* GL_ARM_mali_shader_binary */
+#ifndef GL_ARM_mali_shader_binary
+#define GL_ARM_mali_shader_binary 1
+#endif
+
+/* GL_ARM_rgba8 */
+#ifndef GL_ARM_rgba8
+#define GL_ARM_rgba8 1
+#endif
+
+/*------------------------------------------------------------------------*
+ * EXT extension functions
+ *------------------------------------------------------------------------*/
+
+/* GL_EXT_blend_minmax */
+#ifndef GL_EXT_blend_minmax
+#define GL_EXT_blend_minmax 1
+#endif
+
+/* GL_EXT_color_buffer_half_float */
+#ifndef GL_EXT_color_buffer_half_float
+#define GL_EXT_color_buffer_half_float 1
+#endif
+
+/* GL_EXT_debug_label */
+#ifndef GL_EXT_debug_label
+#define GL_EXT_debug_label 1
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glLabelObjectEXT (GLenum type, GLuint object, GLsizei length, const GLchar *label);
+GL_APICALL void GL_APIENTRY glGetObjectLabelEXT (GLenum type, GLuint object, GLsizei bufSize, GLsizei *length, GLchar *label);
+#endif
+typedef void (GL_APIENTRYP PFNGLLABELOBJECTEXTPROC) (GLenum type, GLuint object, GLsizei length, const GLchar *label);
+typedef void (GL_APIENTRYP PFNGLGETOBJECTLABELEXTPROC) (GLenum type, GLuint object, GLsizei bufSize, GLsizei *length, GLchar *label);
+#endif
+
+/* GL_EXT_debug_marker */
+#ifndef GL_EXT_debug_marker
+#define GL_EXT_debug_marker 1
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glInsertEventMarkerEXT (GLsizei length, const GLchar *marker);
+GL_APICALL void GL_APIENTRY glPushGroupMarkerEXT (GLsizei length, const GLchar *marker);
+GL_APICALL void GL_APIENTRY glPopGroupMarkerEXT (void);
+#endif
+typedef void (GL_APIENTRYP PFNGLINSERTEVENTMARKEREXTPROC) (GLsizei length, const GLchar *marker);
+typedef void (GL_APIENTRYP PFNGLPUSHGROUPMARKEREXTPROC) (GLsizei length, const GLchar *marker);
+typedef void (GL_APIENTRYP PFNGLPOPGROUPMARKEREXTPROC) (void);
+#endif
+
+/* GL_EXT_discard_framebuffer */
+#ifndef GL_EXT_discard_framebuffer
+#define GL_EXT_discard_framebuffer 1
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glDiscardFramebufferEXT (GLenum target, GLsizei numAttachments, const GLenum *attachments);
+#endif
+typedef void (GL_APIENTRYP PFNGLDISCARDFRAMEBUFFEREXTPROC) (GLenum target, GLsizei numAttachments, const GLenum *attachments);
+#endif
+
+/* GL_EXT_multisampled_render_to_texture */
+#ifndef GL_EXT_multisampled_render_to_texture
+#define GL_EXT_multisampled_render_to_texture 1
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glRenderbufferStorageMultisampleEXT (GLenum, GLsizei, GLenum, GLsizei, GLsizei);
+GL_APICALL void GL_APIENTRY glFramebufferTexture2DMultisampleEXT (GLenum, GLenum, GLenum, GLuint, GLint, GLsizei);
+#endif
+typedef void (GL_APIENTRYP PFNGLRENDERBUFFERSTORAGEMULTISAMPLEEXTPROC) (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height);
+typedef void (GL_APIENTRYP PFNGLFRAMEBUFFERTEXTURE2DMULTISAMPLEEXTPROC) (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLsizei samples);
+#endif
+
+#ifndef GL_EXT_multi_draw_arrays
+#define GL_EXT_multi_draw_arrays 1
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glMultiDrawArraysEXT (GLenum, GLint *, GLsizei *, GLsizei);
+GL_APICALL void GL_APIENTRY glMultiDrawElementsEXT (GLenum, const GLsizei *, GLenum, const GLvoid* *, GLsizei);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (GL_APIENTRYP PFNGLMULTIDRAWARRAYSEXTPROC) (GLenum mode, GLint *first, GLsizei *count, GLsizei primcount);
+typedef void (GL_APIENTRYP PFNGLMULTIDRAWELEMENTSEXTPROC) (GLenum mode, const GLsizei *count, GLenum type, const GLvoid* *indices, GLsizei primcount);
+#endif
+
+/* GL_EXT_occlusion_query_boolean */
+#ifndef GL_EXT_occlusion_query_boolean
+#define GL_EXT_occlusion_query_boolean 1
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glGenQueriesEXT (GLsizei n, GLuint *ids);
+GL_APICALL void GL_APIENTRY glDeleteQueriesEXT (GLsizei n, const GLuint *ids);
+GL_APICALL GLboolean GL_APIENTRY glIsQueryEXT (GLuint id);
+GL_APICALL void GL_APIENTRY glBeginQueryEXT (GLenum target, GLuint id);
+GL_APICALL void GL_APIENTRY glEndQueryEXT (GLenum target);
+GL_APICALL void GL_APIENTRY glGetQueryivEXT (GLenum target, GLenum pname, GLint *params);
+GL_APICALL void GL_APIENTRY glGetQueryObjectuivEXT (GLuint id, GLenum pname, GLuint *params);
+#endif
+typedef void (GL_APIENTRYP PFNGLGENQUERIESEXTPROC) (GLsizei n, GLuint *ids);
+typedef void (GL_APIENTRYP PFNGLDELETEQUERIESEXTPROC) (GLsizei n, const GLuint *ids);
+typedef GLboolean (GL_APIENTRYP PFNGLISQUERYEXTPROC) (GLuint id);
+typedef void (GL_APIENTRYP PFNGLBEGINQUERYEXTPROC) (GLenum target, GLuint id);
+typedef void (GL_APIENTRYP PFNGLENDQUERYEXTPROC) (GLenum target);
+typedef void (GL_APIENTRYP PFNGLGETQUERYIVEXTPROC) (GLenum target, GLenum pname, GLint *params);
+typedef void (GL_APIENTRYP PFNGLGETQUERYOBJECTUIVEXTPROC) (GLuint id, GLenum pname, GLuint *params);
+#endif
+
+/* GL_EXT_read_format_bgra */
+#ifndef GL_EXT_read_format_bgra
+#define GL_EXT_read_format_bgra 1
+#endif
+
+/* GL_EXT_robustness */
+#ifndef GL_EXT_robustness
+#define GL_EXT_robustness 1
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL GLenum GL_APIENTRY glGetGraphicsResetStatusEXT (void);
+GL_APICALL void GL_APIENTRY glReadnPixelsEXT (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLsizei bufSize, void *data);
+GL_APICALL void GL_APIENTRY glGetnUniformfvEXT (GLuint program, GLint location, GLsizei bufSize, float *params);
+GL_APICALL void GL_APIENTRY glGetnUniformivEXT (GLuint program, GLint location, GLsizei bufSize, GLint *params);
+#endif
+typedef GLenum (GL_APIENTRYP PFNGLGETGRAPHICSRESETSTATUSEXTPROC) (void);
+typedef void (GL_APIENTRYP PFNGLREADNPIXELSEXTPROC) (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLsizei bufSize, void *data);
+typedef void (GL_APIENTRYP PFNGLGETNUNIFORMFVEXTPROC) (GLuint program, GLint location, GLsizei bufSize, float *params);
+typedef void (GL_APIENTRYP PFNGLGETNUNIFORMIVEXTPROC) (GLuint program, GLint location, GLsizei bufSize, GLint *params);
+#endif
+
+/* GL_EXT_separate_shader_objects */
+#ifndef GL_EXT_separate_shader_objects
+#define GL_EXT_separate_shader_objects 1
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glUseProgramStagesEXT (GLuint pipeline, GLbitfield stages, GLuint program);
+GL_APICALL void GL_APIENTRY glActiveShaderProgramEXT (GLuint pipeline, GLuint program);
+GL_APICALL GLuint GL_APIENTRY glCreateShaderProgramvEXT (GLenum type, GLsizei count, const GLchar **strings);
+GL_APICALL void GL_APIENTRY glBindProgramPipelineEXT (GLuint pipeline);
+GL_APICALL void GL_APIENTRY glDeleteProgramPipelinesEXT (GLsizei n, const GLuint *pipelines);
+GL_APICALL void GL_APIENTRY glGenProgramPipelinesEXT (GLsizei n, GLuint *pipelines);
+GL_APICALL GLboolean GL_APIENTRY glIsProgramPipelineEXT (GLuint pipeline);
+GL_APICALL void GL_APIENTRY glProgramParameteriEXT (GLuint program, GLenum pname, GLint value);
+GL_APICALL void GL_APIENTRY glGetProgramPipelineivEXT (GLuint pipeline, GLenum pname, GLint *params);
+GL_APICALL void GL_APIENTRY glProgramUniform1iEXT (GLuint program, GLint location, GLint x);
+GL_APICALL void GL_APIENTRY glProgramUniform2iEXT (GLuint program, GLint location, GLint x, GLint y);
+GL_APICALL void GL_APIENTRY glProgramUniform3iEXT (GLuint program, GLint location, GLint x, GLint y, GLint z);
+GL_APICALL void GL_APIENTRY glProgramUniform4iEXT (GLuint program, GLint location, GLint x, GLint y, GLint z, GLint w);
+GL_APICALL void GL_APIENTRY glProgramUniform1fEXT (GLuint program, GLint location, GLfloat x);
+GL_APICALL void GL_APIENTRY glProgramUniform2fEXT (GLuint program, GLint location, GLfloat x, GLfloat y);
+GL_APICALL void GL_APIENTRY glProgramUniform3fEXT (GLuint program, GLint location, GLfloat x, GLfloat y, GLfloat z);
+GL_APICALL void GL_APIENTRY glProgramUniform4fEXT (GLuint program, GLint location, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+GL_APICALL void GL_APIENTRY glProgramUniform1ivEXT (GLuint program, GLint location, GLsizei count, const GLint *value);
+GL_APICALL void GL_APIENTRY glProgramUniform2ivEXT (GLuint program, GLint location, GLsizei count, const GLint *value);
+GL_APICALL void GL_APIENTRY glProgramUniform3ivEXT (GLuint program, GLint location, GLsizei count, const GLint *value);
+GL_APICALL void GL_APIENTRY glProgramUniform4ivEXT (GLuint program, GLint location, GLsizei count, const GLint *value);
+GL_APICALL void GL_APIENTRY glProgramUniform1fvEXT (GLuint program, GLint location, GLsizei count, const GLfloat *value);
+GL_APICALL void GL_APIENTRY glProgramUniform2fvEXT (GLuint program, GLint location, GLsizei count, const GLfloat *value);
+GL_APICALL void GL_APIENTRY glProgramUniform3fvEXT (GLuint program, GLint location, GLsizei count, const GLfloat *value);
+GL_APICALL void GL_APIENTRY glProgramUniform4fvEXT (GLuint program, GLint location, GLsizei count, const GLfloat *value);
+GL_APICALL void GL_APIENTRY glProgramUniformMatrix2fvEXT (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GL_APICALL void GL_APIENTRY glProgramUniformMatrix3fvEXT (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GL_APICALL void GL_APIENTRY glProgramUniformMatrix4fvEXT (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GL_APICALL void GL_APIENTRY glValidateProgramPipelineEXT (GLuint pipeline);
+GL_APICALL void GL_APIENTRY glGetProgramPipelineInfoLogEXT (GLuint pipeline, GLsizei bufSize, GLsizei *length, GLchar *infoLog);
+#endif
+typedef void (GL_APIENTRYP PFNGLUSEPROGRAMSTAGESEXTPROC) (GLuint pipeline, GLbitfield stages, GLuint program);
+typedef void (GL_APIENTRYP PFNGLACTIVESHADERPROGRAMEXTPROC) (GLuint pipeline, GLuint program);
+typedef GLuint (GL_APIENTRYP PFNGLCREATESHADERPROGRAMVEXTPROC) (GLenum type, GLsizei count, const GLchar **strings);
+typedef void (GL_APIENTRYP PFNGLBINDPROGRAMPIPELINEEXTPROC) (GLuint pipeline);
+typedef void (GL_APIENTRYP PFNGLDELETEPROGRAMPIPELINESEXTPROC) (GLsizei n, const GLuint *pipelines);
+typedef void (GL_APIENTRYP PFNGLGENPROGRAMPIPELINESEXTPROC) (GLsizei n, GLuint *pipelines);
+typedef GLboolean (GL_APIENTRYP PFNGLISPROGRAMPIPELINEEXTPROC) (GLuint pipeline);
+typedef void (GL_APIENTRYP PFNGLPROGRAMPARAMETERIEXTPROC) (GLuint program, GLenum pname, GLint value);
+typedef void (GL_APIENTRYP PFNGLGETPROGRAMPIPELINEIVEXTPROC) (GLuint pipeline, GLenum pname, GLint *params);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM1IEXTPROC) (GLuint program, GLint location, GLint x);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM2IEXTPROC) (GLuint program, GLint location, GLint x, GLint y);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM3IEXTPROC) (GLuint program, GLint location, GLint x, GLint y, GLint z);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM4IEXTPROC) (GLuint program, GLint location, GLint x, GLint y, GLint z, GLint w);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM1FEXTPROC) (GLuint program, GLint location, GLfloat x);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM2FEXTPROC) (GLuint program, GLint location, GLfloat x, GLfloat y);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM3FEXTPROC) (GLuint program, GLint location, GLfloat x, GLfloat y, GLfloat z);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM4FEXTPROC) (GLuint program, GLint location, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM1IVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLint *value);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM2IVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLint *value);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM3IVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLint *value);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM4IVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLint *value);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM1FVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM2FVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM3FVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM4FVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORMMATRIX2FVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORMMATRIX3FVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORMMATRIX4FVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLVALIDATEPROGRAMPIPELINEEXTPROC) (GLuint pipeline);
+typedef void (GL_APIENTRYP PFNGLGETPROGRAMPIPELINEINFOLOGEXTPROC) (GLuint pipeline, GLsizei bufSize, GLsizei *length, GLchar *infoLog);
+#endif
+
+/* GL_EXT_shader_texture_lod */
+#ifndef GL_EXT_shader_texture_lod
+#define GL_EXT_shader_texture_lod 1
+#endif
+
+/* GL_EXT_shadow_samplers */
+#ifndef GL_EXT_shadow_samplers
+#define GL_EXT_shadow_samplers 1
+#endif
+
+/* GL_EXT_sRGB */
+#ifndef GL_EXT_sRGB
+#define GL_EXT_sRGB 1
+#endif
+
+/* GL_EXT_texture_compression_dxt1 */
+#ifndef GL_EXT_texture_compression_dxt1
+#define GL_EXT_texture_compression_dxt1 1
+#endif
+
+/* GL_EXT_texture_filter_anisotropic */
+#ifndef GL_EXT_texture_filter_anisotropic
+#define GL_EXT_texture_filter_anisotropic 1
+#endif
+
+/* GL_EXT_texture_format_BGRA8888 */
+#ifndef GL_EXT_texture_format_BGRA8888
+#define GL_EXT_texture_format_BGRA8888 1
+#endif
+
+/* GL_EXT_texture_rg */
+#ifndef GL_EXT_texture_rg
+#define GL_EXT_texture_rg 1
+#endif
+
+/* GL_EXT_texture_storage */
+#ifndef GL_EXT_texture_storage
+#define GL_EXT_texture_storage 1
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glTexStorage1DEXT (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width);
+GL_APICALL void GL_APIENTRY glTexStorage2DEXT (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height);
+GL_APICALL void GL_APIENTRY glTexStorage3DEXT (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth);
+GL_APICALL void GL_APIENTRY glTextureStorage1DEXT (GLuint texture, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width);
+GL_APICALL void GL_APIENTRY glTextureStorage2DEXT (GLuint texture, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height);
+GL_APICALL void GL_APIENTRY glTextureStorage3DEXT (GLuint texture, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth);
+#endif
+typedef void (GL_APIENTRYP PFNGLTEXSTORAGE1DEXTPROC) (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width);
+typedef void (GL_APIENTRYP PFNGLTEXSTORAGE2DEXTPROC) (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height);
+typedef void (GL_APIENTRYP PFNGLTEXSTORAGE3DEXTPROC) (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth);
+typedef void (GL_APIENTRYP PFNGLTEXTURESTORAGE1DEXTPROC) (GLuint texture, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width);
+typedef void (GL_APIENTRYP PFNGLTEXTURESTORAGE2DEXTPROC) (GLuint texture, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height);
+typedef void (GL_APIENTRYP PFNGLTEXTURESTORAGE3DEXTPROC) (GLuint texture, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth);
+#endif
+
+/* GL_EXT_texture_type_2_10_10_10_REV */
+#ifndef GL_EXT_texture_type_2_10_10_10_REV
+#define GL_EXT_texture_type_2_10_10_10_REV 1
+#endif
+
+/* GL_EXT_unpack_subimage */
+#ifndef GL_EXT_unpack_subimage
+#define GL_EXT_unpack_subimage 1
+#endif
+
+/*------------------------------------------------------------------------*
+ * DMP extension functions
+ *------------------------------------------------------------------------*/
+
+/* GL_DMP_shader_binary */
+#ifndef GL_DMP_shader_binary
+#define GL_DMP_shader_binary 1
+#endif
+
+/*------------------------------------------------------------------------*
+ * IMG extension functions
+ *------------------------------------------------------------------------*/
+
+/* GL_IMG_program_binary */
+#ifndef GL_IMG_program_binary
+#define GL_IMG_program_binary 1
+#endif
+
+/* GL_IMG_read_format */
+#ifndef GL_IMG_read_format
+#define GL_IMG_read_format 1
+#endif
+
+/* GL_IMG_shader_binary */
+#ifndef GL_IMG_shader_binary
+#define GL_IMG_shader_binary 1
+#endif
+
+/* GL_IMG_texture_compression_pvrtc */
+#ifndef GL_IMG_texture_compression_pvrtc
+#define GL_IMG_texture_compression_pvrtc 1
+#endif
+
+/* GL_IMG_multisampled_render_to_texture */
+#ifndef GL_IMG_multisampled_render_to_texture
+#define GL_IMG_multisampled_render_to_texture 1
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glRenderbufferStorageMultisampleIMG (GLenum, GLsizei, GLenum, GLsizei, GLsizei);
+GL_APICALL void GL_APIENTRY glFramebufferTexture2DMultisampleIMG (GLenum, GLenum, GLenum, GLuint, GLint, GLsizei);
+#endif
+typedef void (GL_APIENTRYP PFNGLRENDERBUFFERSTORAGEMULTISAMPLEIMG) (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height);
+typedef void (GL_APIENTRYP PFNGLFRAMEBUFFERTEXTURE2DMULTISAMPLEIMG) (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLsizei samples);
+#endif
+
+/*------------------------------------------------------------------------*
+ * NV extension functions
+ *------------------------------------------------------------------------*/
+
+/* GL_NV_coverage_sample */
+#ifndef GL_NV_coverage_sample
+#define GL_NV_coverage_sample 1
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glCoverageMaskNV (GLboolean mask);
+GL_APICALL void GL_APIENTRY glCoverageOperationNV (GLenum operation);
+#endif
+typedef void (GL_APIENTRYP PFNGLCOVERAGEMASKNVPROC) (GLboolean mask);
+typedef void (GL_APIENTRYP PFNGLCOVERAGEOPERATIONNVPROC) (GLenum operation);
+#endif
+
+/* GL_NV_depth_nonlinear */
+#ifndef GL_NV_depth_nonlinear
+#define GL_NV_depth_nonlinear 1
+#endif
+
+/* GL_NV_draw_buffers */
+#ifndef GL_NV_draw_buffers
+#define GL_NV_draw_buffers 1
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glDrawBuffersNV (GLsizei n, const GLenum *bufs);
+#endif
+typedef void (GL_APIENTRYP PFNGLDRAWBUFFERSNVPROC) (GLsizei n, const GLenum *bufs);
+#endif
+
+/* GL_NV_fbo_color_attachments */
+#ifndef GL_NV_fbo_color_attachments
+#define GL_NV_fbo_color_attachments 1
+#endif
+
+/* GL_NV_fence */
+#ifndef GL_NV_fence
+#define GL_NV_fence 1
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glDeleteFencesNV (GLsizei, const GLuint *);
+GL_APICALL void GL_APIENTRY glGenFencesNV (GLsizei, GLuint *);
+GL_APICALL GLboolean GL_APIENTRY glIsFenceNV (GLuint);
+GL_APICALL GLboolean GL_APIENTRY glTestFenceNV (GLuint);
+GL_APICALL void GL_APIENTRY glGetFenceivNV (GLuint, GLenum, GLint *);
+GL_APICALL void GL_APIENTRY glFinishFenceNV (GLuint);
+GL_APICALL void GL_APIENTRY glSetFenceNV (GLuint, GLenum);
+#endif
+typedef void (GL_APIENTRYP PFNGLDELETEFENCESNVPROC) (GLsizei n, const GLuint *fences);
+typedef void (GL_APIENTRYP PFNGLGENFENCESNVPROC) (GLsizei n, GLuint *fences);
+typedef GLboolean (GL_APIENTRYP PFNGLISFENCENVPROC) (GLuint fence);
+typedef GLboolean (GL_APIENTRYP PFNGLTESTFENCENVPROC) (GLuint fence);
+typedef void (GL_APIENTRYP PFNGLGETFENCEIVNVPROC) (GLuint fence, GLenum pname, GLint *params);
+typedef void (GL_APIENTRYP PFNGLFINISHFENCENVPROC) (GLuint fence);
+typedef void (GL_APIENTRYP PFNGLSETFENCENVPROC) (GLuint fence, GLenum condition);
+#endif
+
+/* GL_NV_read_buffer */
+#ifndef GL_NV_read_buffer
+#define GL_NV_read_buffer 1
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glReadBufferNV (GLenum mode);
+#endif
+typedef void (GL_APIENTRYP PFNGLREADBUFFERNVPROC) (GLenum mode);
+#endif
+
+/* GL_NV_read_buffer_front */
+#ifndef GL_NV_read_buffer_front
+#define GL_NV_read_buffer_front 1
+#endif
+
+/* GL_NV_read_depth */
+#ifndef GL_NV_read_depth
+#define GL_NV_read_depth 1
+#endif
+
+/* GL_NV_read_depth_stencil */
+#ifndef GL_NV_read_depth_stencil
+#define GL_NV_read_depth_stencil 1
+#endif
+
+/* GL_NV_read_stencil */
+#ifndef GL_NV_read_stencil
+#define GL_NV_read_stencil 1
+#endif
+
+/* GL_NV_texture_compression_s3tc_update */
+#ifndef GL_NV_texture_compression_s3tc_update
+#define GL_NV_texture_compression_s3tc_update 1
+#endif
+
+/* GL_NV_texture_npot_2D_mipmap */
+#ifndef GL_NV_texture_npot_2D_mipmap
+#define GL_NV_texture_npot_2D_mipmap 1
+#endif
+
+/*------------------------------------------------------------------------*
+ * QCOM extension functions
+ *------------------------------------------------------------------------*/
+
+/* GL_QCOM_alpha_test */
+#ifndef GL_QCOM_alpha_test
+#define GL_QCOM_alpha_test 1
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glAlphaFuncQCOM (GLenum func, GLclampf ref);
+#endif
+typedef void (GL_APIENTRYP PFNGLALPHAFUNCQCOMPROC) (GLenum func, GLclampf ref);
+#endif
+
+/* GL_QCOM_driver_control */
+#ifndef GL_QCOM_driver_control
+#define GL_QCOM_driver_control 1
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glGetDriverControlsQCOM (GLint *num, GLsizei size, GLuint *driverControls);
+GL_APICALL void GL_APIENTRY glGetDriverControlStringQCOM (GLuint driverControl, GLsizei bufSize, GLsizei *length, GLchar *driverControlString);
+GL_APICALL void GL_APIENTRY glEnableDriverControlQCOM (GLuint driverControl);
+GL_APICALL void GL_APIENTRY glDisableDriverControlQCOM (GLuint driverControl);
+#endif
+typedef void (GL_APIENTRYP PFNGLGETDRIVERCONTROLSQCOMPROC) (GLint *num, GLsizei size, GLuint *driverControls);
+typedef void (GL_APIENTRYP PFNGLGETDRIVERCONTROLSTRINGQCOMPROC) (GLuint driverControl, GLsizei bufSize, GLsizei *length, GLchar *driverControlString);
+typedef void (GL_APIENTRYP PFNGLENABLEDRIVERCONTROLQCOMPROC) (GLuint driverControl);
+typedef void (GL_APIENTRYP PFNGLDISABLEDRIVERCONTROLQCOMPROC) (GLuint driverControl);
+#endif
+
+/* GL_QCOM_extended_get */
+#ifndef GL_QCOM_extended_get
+#define GL_QCOM_extended_get 1
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glExtGetTexturesQCOM (GLuint *textures, GLint maxTextures, GLint *numTextures);
+GL_APICALL void GL_APIENTRY glExtGetBuffersQCOM (GLuint *buffers, GLint maxBuffers, GLint *numBuffers);
+GL_APICALL void GL_APIENTRY glExtGetRenderbuffersQCOM (GLuint *renderbuffers, GLint maxRenderbuffers, GLint *numRenderbuffers);
+GL_APICALL void GL_APIENTRY glExtGetFramebuffersQCOM (GLuint *framebuffers, GLint maxFramebuffers, GLint *numFramebuffers);
+GL_APICALL void GL_APIENTRY glExtGetTexLevelParameterivQCOM (GLuint texture, GLenum face, GLint level, GLenum pname, GLint *params);
+GL_APICALL void GL_APIENTRY glExtTexObjectStateOverrideiQCOM (GLenum target, GLenum pname, GLint param);
+GL_APICALL void GL_APIENTRY glExtGetTexSubImageQCOM (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, GLvoid *texels);
+GL_APICALL void GL_APIENTRY glExtGetBufferPointervQCOM (GLenum target, GLvoid **params);
+#endif
+typedef void (GL_APIENTRYP PFNGLEXTGETTEXTURESQCOMPROC) (GLuint *textures, GLint maxTextures, GLint *numTextures);
+typedef void (GL_APIENTRYP PFNGLEXTGETBUFFERSQCOMPROC) (GLuint *buffers, GLint maxBuffers, GLint *numBuffers);
+typedef void (GL_APIENTRYP PFNGLEXTGETRENDERBUFFERSQCOMPROC) (GLuint *renderbuffers, GLint maxRenderbuffers, GLint *numRenderbuffers);
+typedef void (GL_APIENTRYP PFNGLEXTGETFRAMEBUFFERSQCOMPROC) (GLuint *framebuffers, GLint maxFramebuffers, GLint *numFramebuffers);
+typedef void (GL_APIENTRYP PFNGLEXTGETTEXLEVELPARAMETERIVQCOMPROC) (GLuint texture, GLenum face, GLint level, GLenum pname, GLint *params);
+typedef void (GL_APIENTRYP PFNGLEXTTEXOBJECTSTATEOVERRIDEIQCOMPROC) (GLenum target, GLenum pname, GLint param);
+typedef void (GL_APIENTRYP PFNGLEXTGETTEXSUBIMAGEQCOMPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, GLvoid *texels);
+typedef void (GL_APIENTRYP PFNGLEXTGETBUFFERPOINTERVQCOMPROC) (GLenum target, GLvoid **params);
+#endif
+
+/* GL_QCOM_extended_get2 */
+#ifndef GL_QCOM_extended_get2
+#define GL_QCOM_extended_get2 1
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glExtGetShadersQCOM (GLuint *shaders, GLint maxShaders, GLint *numShaders);
+GL_APICALL void GL_APIENTRY glExtGetProgramsQCOM (GLuint *programs, GLint maxPrograms, GLint *numPrograms);
+GL_APICALL GLboolean GL_APIENTRY glExtIsProgramBinaryQCOM (GLuint program);
+GL_APICALL void GL_APIENTRY glExtGetProgramBinarySourceQCOM (GLuint program, GLenum shadertype, GLchar *source, GLint *length);
+#endif
+typedef void (GL_APIENTRYP PFNGLEXTGETSHADERSQCOMPROC) (GLuint *shaders, GLint maxShaders, GLint *numShaders);
+typedef void (GL_APIENTRYP PFNGLEXTGETPROGRAMSQCOMPROC) (GLuint *programs, GLint maxPrograms, GLint *numPrograms);
+typedef GLboolean (GL_APIENTRYP PFNGLEXTISPROGRAMBINARYQCOMPROC) (GLuint program);
+typedef void (GL_APIENTRYP PFNGLEXTGETPROGRAMBINARYSOURCEQCOMPROC) (GLuint program, GLenum shadertype, GLchar *source, GLint *length);
+#endif
+
+/* GL_QCOM_perfmon_global_mode */
+#ifndef GL_QCOM_perfmon_global_mode
+#define GL_QCOM_perfmon_global_mode 1
+#endif
+
+/* GL_QCOM_writeonly_rendering */
+#ifndef GL_QCOM_writeonly_rendering
+#define GL_QCOM_writeonly_rendering 1
+#endif
+
+/* GL_QCOM_tiled_rendering */
+#ifndef GL_QCOM_tiled_rendering
+#define GL_QCOM_tiled_rendering 1
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glStartTilingQCOM (GLuint x, GLuint y, GLuint width, GLuint height, GLbitfield preserveMask);
+GL_APICALL void GL_APIENTRY glEndTilingQCOM (GLbitfield preserveMask);
+#endif
+typedef void (GL_APIENTRYP PFNGLSTARTTILINGQCOMPROC) (GLuint x, GLuint y, GLuint width, GLuint height, GLbitfield preserveMask);
+typedef void (GL_APIENTRYP PFNGLENDTILINGQCOMPROC) (GLbitfield preserveMask);
+#endif
+
+/*------------------------------------------------------------------------*
+ * VIV extension tokens
+ *------------------------------------------------------------------------*/
+
+/* GL_VIV_shader_binary */
+#ifndef GL_VIV_shader_binary
+#define GL_VIV_shader_binary 1
+#endif
+
+/* GL_ANGLE_program_binary */
+#ifndef GL_ANGLE_program_binary
+#define GL_ANGLE_program_binary 1
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __gl2ext_h_ */
diff --git a/src/3rdparty/angle/include/GLES2/gl2platform.h b/src/3rdparty/angle/include/GLES2/gl2platform.h
new file mode 100644 (file)
index 0000000..c9fa3c4
--- /dev/null
@@ -0,0 +1,30 @@
+#ifndef __gl2platform_h_
+#define __gl2platform_h_
+
+/* $Revision: 10602 $ on $Date:: 2010-03-04 22:35:34 -0800 #$ */
+
+/*
+ * This document is licensed under the SGI Free Software B License Version
+ * 2.0. For details, see http://oss.sgi.com/projects/FreeB/ .
+ */
+
+/* Platform-specific types and definitions for OpenGL ES 2.X  gl2.h
+ *
+ * Adopters may modify khrplatform.h and this file to suit their platform.
+ * You are encouraged to submit all modifications to the Khronos group so that
+ * they can be included in future versions of this file.  Please submit changes
+ * by sending them to the public Khronos Bugzilla (http://khronos.org/bugzilla)
+ * by filing a bug against product "OpenGL-ES" component "Registry".
+ */
+
+#include <KHR/khrplatform.h>
+
+#ifndef GL_APICALL
+#define GL_APICALL  KHRONOS_APICALL
+#endif
+
+#ifndef GL_APIENTRY
+#define GL_APIENTRY KHRONOS_APIENTRY
+#endif
+
+#endif /* __gl2platform_h_ */
diff --git a/src/3rdparty/angle/include/GLSLANG/ShaderLang.h b/src/3rdparty/angle/include/GLSLANG/ShaderLang.h
new file mode 100644 (file)
index 0000000..d925029
--- /dev/null
@@ -0,0 +1,354 @@
+//
+// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+#ifndef _COMPILER_INTERFACE_INCLUDED_
+#define _COMPILER_INTERFACE_INCLUDED_
+
+#if defined(COMPONENT_BUILD)
+#if defined(_WIN32) || defined(_WIN64)
+
+#if defined(COMPILER_IMPLEMENTATION)
+#define COMPILER_EXPORT __declspec(dllexport)
+#else
+#define COMPILER_EXPORT __declspec(dllimport)
+#endif  // defined(COMPILER_IMPLEMENTATION)
+
+#else  // defined(WIN32)
+#define COMPILER_EXPORT __attribute__((visibility("default")))
+#endif
+
+#else  // defined(COMPONENT_BUILD)
+#define COMPILER_EXPORT
+#endif
+
+//
+// This is the platform independent interface between an OGL driver
+// and the shading language compiler.
+//
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// Version number for shader translation API.
+// It is incremented everytime the API changes.
+#define SH_VERSION 107
+
+//
+// The names of the following enums have been derived by replacing GL prefix
+// with SH. For example, SH_INFO_LOG_LENGTH is equivalent to GL_INFO_LOG_LENGTH.
+// The enum values are also equal to the values of their GL counterpart. This
+// is done to make it easier for applications to use the shader library.
+//
+typedef enum {
+  SH_FRAGMENT_SHADER = 0x8B30,
+  SH_VERTEX_SHADER   = 0x8B31
+} ShShaderType;
+
+typedef enum {
+  SH_GLES2_SPEC = 0x8B40,
+  SH_WEBGL_SPEC = 0x8B41,
+
+  // The CSS Shaders spec is a subset of the WebGL spec.
+  //
+  // In both CSS vertex and fragment shaders, ANGLE:
+  // (1) Reserves the "css_" prefix.
+  // (2) Renames the main function to css_main.
+  // (3) Disables the gl_MaxDrawBuffers built-in.
+  //
+  // In CSS fragment shaders, ANGLE:
+  // (1) Disables the gl_FragColor built-in.
+  // (2) Disables the gl_FragData built-in.
+  // (3) Enables the css_MixColor built-in.
+  // (4) Enables the css_ColorMatrix built-in.
+  //
+  // After passing a CSS shader through ANGLE, the browser is expected to append
+  // a new main function to it.
+  // This new main function will call the css_main function.
+  // It may also perform additional operations like varying assignment, texture
+  // access, and gl_FragColor assignment in order to implement the CSS Shaders
+  // blend modes.
+  //
+  SH_CSS_SHADERS_SPEC = 0x8B42
+} ShShaderSpec;
+
+typedef enum {
+  SH_ESSL_OUTPUT = 0x8B45,
+  SH_GLSL_OUTPUT = 0x8B46,
+  SH_HLSL_OUTPUT = 0x8B47
+} ShShaderOutput;
+
+typedef enum {
+  SH_NONE           = 0,
+  SH_INT            = 0x1404,
+  SH_FLOAT          = 0x1406,
+  SH_FLOAT_VEC2     = 0x8B50,
+  SH_FLOAT_VEC3     = 0x8B51,
+  SH_FLOAT_VEC4     = 0x8B52,
+  SH_INT_VEC2       = 0x8B53,
+  SH_INT_VEC3       = 0x8B54,
+  SH_INT_VEC4       = 0x8B55,
+  SH_BOOL           = 0x8B56,
+  SH_BOOL_VEC2      = 0x8B57,
+  SH_BOOL_VEC3      = 0x8B58,
+  SH_BOOL_VEC4      = 0x8B59,
+  SH_FLOAT_MAT2     = 0x8B5A,
+  SH_FLOAT_MAT3     = 0x8B5B,
+  SH_FLOAT_MAT4     = 0x8B5C,
+  SH_SAMPLER_2D     = 0x8B5E,
+  SH_SAMPLER_CUBE   = 0x8B60,
+  SH_SAMPLER_2D_RECT_ARB = 0x8B63,
+  SH_SAMPLER_EXTERNAL_OES = 0x8D66
+} ShDataType;
+
+typedef enum {
+  SH_INFO_LOG_LENGTH             =  0x8B84,
+  SH_OBJECT_CODE_LENGTH          =  0x8B88,  // GL_SHADER_SOURCE_LENGTH
+  SH_ACTIVE_UNIFORMS             =  0x8B86,
+  SH_ACTIVE_UNIFORM_MAX_LENGTH   =  0x8B87,
+  SH_ACTIVE_ATTRIBUTES           =  0x8B89,
+  SH_ACTIVE_ATTRIBUTE_MAX_LENGTH =  0x8B8A,
+  SH_MAPPED_NAME_MAX_LENGTH      =  0x8B8B
+} ShShaderInfo;
+
+// Compile options.
+typedef enum {
+  SH_VALIDATE                = 0,
+  SH_VALIDATE_LOOP_INDEXING  = 0x0001,
+  SH_INTERMEDIATE_TREE       = 0x0002,
+  SH_OBJECT_CODE             = 0x0004,
+  SH_ATTRIBUTES_UNIFORMS     = 0x0008,
+  SH_LINE_DIRECTIVES         = 0x0010,
+  SH_SOURCE_PATH             = 0x0020,
+  SH_MAP_LONG_VARIABLE_NAMES = 0x0040,
+  SH_UNROLL_FOR_LOOP_WITH_INTEGER_INDEX = 0x0080,
+
+  // This is needed only as a workaround for certain OpenGL driver bugs.
+  SH_EMULATE_BUILT_IN_FUNCTIONS = 0x0100,
+
+  // This is an experimental flag to enforce restrictions that aim to prevent 
+  // timing attacks.
+  // It generates compilation errors for shaders that could expose sensitive
+  // texture information via the timing channel.
+  // To use this flag, you must compile the shader under the WebGL spec
+  // (using the SH_WEBGL_SPEC flag).
+  SH_TIMING_RESTRICTIONS = 0x0200,
+    
+  // This flag prints the dependency graph that is used to enforce timing
+  // restrictions on fragment shaders.
+  // This flag only has an effect if all of the following are true:
+  // - The shader spec is SH_WEBGL_SPEC.
+  // - The compile options contain the SH_TIMING_RESTRICTIONS flag.
+  // - The shader type is SH_FRAGMENT_SHADER.
+  SH_DEPENDENCY_GRAPH = 0x0400,
+
+  // Enforce the GLSL 1.017 Appendix A section 7 packing restrictions.
+  SH_ENFORCE_PACKING_RESTRICTIONS = 0x0800,
+} ShCompileOptions;
+
+//
+// Driver must call this first, once, before doing any other
+// compiler operations.
+// If the function succeeds, the return value is nonzero, else zero.
+//
+COMPILER_EXPORT int ShInitialize();
+//
+// Driver should call this at shutdown.
+// If the function succeeds, the return value is nonzero, else zero.
+//
+COMPILER_EXPORT int ShFinalize();
+
+//
+// Implementation dependent built-in resources (constants and extensions).
+// The names for these resources has been obtained by stripping gl_/GL_.
+//
+typedef struct
+{
+    // Constants.
+    int MaxVertexAttribs;
+    int MaxVertexUniformVectors;
+    int MaxVaryingVectors;
+    int MaxVertexTextureImageUnits;
+    int MaxCombinedTextureImageUnits;
+    int MaxTextureImageUnits;
+    int MaxFragmentUniformVectors;
+    int MaxDrawBuffers;
+
+    // Extensions.
+    // Set to 1 to enable the extension, else 0.
+    int OES_standard_derivatives;
+    int OES_EGL_image_external;
+    int ARB_texture_rectangle;
+} ShBuiltInResources;
+
+//
+// Initialize built-in resources with minimum expected values.
+//
+COMPILER_EXPORT void ShInitBuiltInResources(ShBuiltInResources* resources);
+
+//
+// ShHandle held by but opaque to the driver.  It is allocated,
+// managed, and de-allocated by the compiler. It's contents 
+// are defined by and used by the compiler.
+//
+// If handle creation fails, 0 will be returned.
+//
+typedef void* ShHandle;
+
+//
+// Driver calls these to create and destroy compiler objects.
+//
+// Returns the handle of constructed compiler, null if the requested compiler is
+// not supported.
+// Parameters:
+// type: Specifies the type of shader - SH_FRAGMENT_SHADER or SH_VERTEX_SHADER.
+// spec: Specifies the language spec the compiler must conform to -
+//       SH_GLES2_SPEC or SH_WEBGL_SPEC.
+// output: Specifies the output code type - SH_ESSL_OUTPUT, SH_GLSL_OUTPUT,
+//         or SH_HLSL_OUTPUT.
+// resources: Specifies the built-in resources.
+COMPILER_EXPORT ShHandle ShConstructCompiler(
+    ShShaderType type,
+    ShShaderSpec spec,
+    ShShaderOutput output,
+    const ShBuiltInResources* resources);
+COMPILER_EXPORT void ShDestruct(ShHandle handle);
+
+//
+// Compiles the given shader source.
+// If the function succeeds, the return value is nonzero, else zero.
+// Parameters:
+// handle: Specifies the handle of compiler to be used.
+// shaderStrings: Specifies an array of pointers to null-terminated strings
+//                containing the shader source code.
+// numStrings: Specifies the number of elements in shaderStrings array.
+// compileOptions: A mask containing the following parameters:
+// SH_VALIDATE: Validates shader to ensure that it conforms to the spec
+//              specified during compiler construction.
+// SH_VALIDATE_LOOP_INDEXING: Validates loop and indexing in the shader to
+//                            ensure that they do not exceed the minimum
+//                            functionality mandated in GLSL 1.0 spec,
+//                            Appendix A, Section 4 and 5.
+//                            There is no need to specify this parameter when
+//                            compiling for WebGL - it is implied.
+// SH_INTERMEDIATE_TREE: Writes intermediate tree to info log.
+//                       Can be queried by calling ShGetInfoLog().
+// SH_OBJECT_CODE: Translates intermediate tree to glsl or hlsl shader.
+//                 Can be queried by calling ShGetObjectCode().
+// SH_ATTRIBUTES_UNIFORMS: Extracts attributes and uniforms.
+//                         Can be queried by calling ShGetActiveAttrib() and
+//                         ShGetActiveUniform().
+//
+COMPILER_EXPORT int ShCompile(
+    const ShHandle handle,
+    const char* const shaderStrings[],
+    const int numStrings,
+    int compileOptions
+    );
+
+// Returns a parameter from a compiled shader.
+// Parameters:
+// handle: Specifies the compiler
+// pname: Specifies the parameter to query.
+// The following parameters are defined:
+// SH_INFO_LOG_LENGTH: the number of characters in the information log
+//                     including the null termination character.
+// SH_OBJECT_CODE_LENGTH: the number of characters in the object code
+//                        including the null termination character.
+// SH_ACTIVE_ATTRIBUTES: the number of active attribute variables.
+// SH_ACTIVE_ATTRIBUTE_MAX_LENGTH: the length of the longest active attribute
+//                                 variable name including the null
+//                                 termination character.
+// SH_ACTIVE_UNIFORMS: the number of active uniform variables.
+// SH_ACTIVE_UNIFORM_MAX_LENGTH: the length of the longest active uniform
+//                               variable name including the null
+//                               termination character.
+// SH_MAPPED_NAME_MAX_LENGTH: the length of the mapped variable name including
+//                            the null termination character.
+// 
+// params: Requested parameter
+COMPILER_EXPORT void ShGetInfo(const ShHandle handle,
+                               ShShaderInfo pname,
+                               int* params);
+
+// Returns nul-terminated information log for a compiled shader.
+// Parameters:
+// handle: Specifies the compiler
+// infoLog: Specifies an array of characters that is used to return
+//          the information log. It is assumed that infoLog has enough memory
+//          to accomodate the information log. The size of the buffer required
+//          to store the returned information log can be obtained by calling
+//          ShGetInfo with SH_INFO_LOG_LENGTH.
+COMPILER_EXPORT void ShGetInfoLog(const ShHandle handle, char* infoLog);
+
+// Returns null-terminated object code for a compiled shader.
+// Parameters:
+// handle: Specifies the compiler
+// infoLog: Specifies an array of characters that is used to return
+//          the object code. It is assumed that infoLog has enough memory to
+//          accomodate the object code. The size of the buffer required to
+//          store the returned object code can be obtained by calling
+//          ShGetInfo with SH_OBJECT_CODE_LENGTH.
+COMPILER_EXPORT void ShGetObjectCode(const ShHandle handle, char* objCode);
+
+// Returns information about an active attribute variable.
+// Parameters:
+// handle: Specifies the compiler
+// index: Specifies the index of the attribute variable to be queried.
+// length: Returns the number of characters actually written in the string
+//         indicated by name (excluding the null terminator) if a value other
+//         than NULL is passed.
+// size: Returns the size of the attribute variable.
+// type: Returns the data type of the attribute variable.
+// name: Returns a null terminated string containing the name of the
+//       attribute variable. It is assumed that name has enough memory to
+//       accomodate the attribute variable name. The size of the buffer
+//       required to store the attribute variable name can be obtained by
+//       calling ShGetInfo with SH_ACTIVE_ATTRIBUTE_MAX_LENGTH.
+// mappedName: Returns a null terminated string containing the mapped name of
+//             the attribute variable, It is assumed that mappedName has enough
+//             memory (SH_MAPPED_NAME_MAX_LENGTH), or NULL if don't care
+//             about the mapped name. If the name is not mapped, then name and
+//             mappedName are the same.
+COMPILER_EXPORT void ShGetActiveAttrib(const ShHandle handle,
+                                       int index,
+                                       int* length,
+                                       int* size,
+                                       ShDataType* type,
+                                       char* name,
+                                       char* mappedName);
+
+// Returns information about an active uniform variable.
+// Parameters:
+// handle: Specifies the compiler
+// index: Specifies the index of the uniform variable to be queried.
+// length: Returns the number of characters actually written in the string
+//         indicated by name (excluding the null terminator) if a value
+//         other than NULL is passed.
+// size: Returns the size of the uniform variable.
+// type: Returns the data type of the uniform variable.
+// name: Returns a null terminated string containing the name of the
+//       uniform variable. It is assumed that name has enough memory to
+//       accomodate the uniform variable name. The size of the buffer required
+//       to store the uniform variable name can be obtained by calling
+//       ShGetInfo with SH_ACTIVE_UNIFORMS_MAX_LENGTH.
+// mappedName: Returns a null terminated string containing the mapped name of
+//             the uniform variable, It is assumed that mappedName has enough
+//             memory (SH_MAPPED_NAME_MAX_LENGTH), or NULL if don't care
+//             about the mapped name. If the name is not mapped, then name and
+//             mappedName are the same.
+COMPILER_EXPORT void ShGetActiveUniform(const ShHandle handle,
+                                        int index,
+                                        int* length,
+                                        int* size,
+                                        ShDataType* type,
+                                        char* name,
+                                        char* mappedName);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // _COMPILER_INTERFACE_INCLUDED_
diff --git a/src/3rdparty/angle/include/KHR/khrplatform.h b/src/3rdparty/angle/include/KHR/khrplatform.h
new file mode 100644 (file)
index 0000000..8ec0d19
--- /dev/null
@@ -0,0 +1,269 @@
+#ifndef __khrplatform_h_
+#define __khrplatform_h_
+
+/*
+** Copyright (c) 2008-2009 The Khronos Group Inc.
+**
+** Permission is hereby granted, free of charge, to any person obtaining a
+** copy of this software and/or associated documentation files (the
+** "Materials"), to deal in the Materials without restriction, including
+** without limitation the rights to use, copy, modify, merge, publish,
+** distribute, sublicense, and/or sell copies of the Materials, and to
+** permit persons to whom the Materials are furnished to do so, subject to
+** the following conditions:
+**
+** The above copyright notice and this permission notice shall be included
+** in all copies or substantial portions of the Materials.
+**
+** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+*/
+
+/* Khronos platform-specific types and definitions.
+ *
+ * $Revision: 9356 $ on $Date: 2009-10-21 02:52:25 -0700 (Wed, 21 Oct 2009) $
+ *
+ * Adopters may modify this file to suit their platform. Adopters are
+ * encouraged to submit platform specific modifications to the Khronos
+ * group so that they can be included in future versions of this file.
+ * Please submit changes by sending them to the public Khronos Bugzilla
+ * (http://khronos.org/bugzilla) by filing a bug against product
+ * "Khronos (general)" component "Registry".
+ *
+ * A predefined template which fills in some of the bug fields can be
+ * reached using http://tinyurl.com/khrplatform-h-bugreport, but you
+ * must create a Bugzilla login first.
+ *
+ *
+ * See the Implementer's Guidelines for information about where this file
+ * should be located on your system and for more details of its use:
+ *    http://www.khronos.org/registry/implementers_guide.pdf
+ *
+ * This file should be included as
+ *        #include <KHR/khrplatform.h>
+ * by Khronos client API header files that use its types and defines.
+ *
+ * The types in khrplatform.h should only be used to define API-specific types.
+ *
+ * Types defined in khrplatform.h:
+ *    khronos_int8_t              signed   8  bit
+ *    khronos_uint8_t             unsigned 8  bit
+ *    khronos_int16_t             signed   16 bit
+ *    khronos_uint16_t            unsigned 16 bit
+ *    khronos_int32_t             signed   32 bit
+ *    khronos_uint32_t            unsigned 32 bit
+ *    khronos_int64_t             signed   64 bit
+ *    khronos_uint64_t            unsigned 64 bit
+ *    khronos_intptr_t            signed   same number of bits as a pointer
+ *    khronos_uintptr_t           unsigned same number of bits as a pointer
+ *    khronos_ssize_t             signed   size
+ *    khronos_usize_t             unsigned size
+ *    khronos_float_t             signed   32 bit floating point
+ *    khronos_time_ns_t           unsigned 64 bit time in nanoseconds
+ *    khronos_utime_nanoseconds_t unsigned time interval or absolute time in
+ *                                         nanoseconds
+ *    khronos_stime_nanoseconds_t signed time interval in nanoseconds
+ *    khronos_boolean_enum_t      enumerated boolean type. This should
+ *      only be used as a base type when a client API's boolean type is
+ *      an enum. Client APIs which use an integer or other type for
+ *      booleans cannot use this as the base type for their boolean.
+ *
+ * Tokens defined in khrplatform.h:
+ *
+ *    KHRONOS_FALSE, KHRONOS_TRUE Enumerated boolean false/true values.
+ *
+ *    KHRONOS_SUPPORT_INT64 is 1 if 64 bit integers are supported; otherwise 0.
+ *    KHRONOS_SUPPORT_FLOAT is 1 if floats are supported; otherwise 0.
+ *
+ * Calling convention macros defined in this file:
+ *    KHRONOS_APICALL
+ *    KHRONOS_APIENTRY
+ *    KHRONOS_APIATTRIBUTES
+ *
+ * These may be used in function prototypes as:
+ *
+ *      KHRONOS_APICALL void KHRONOS_APIENTRY funcname(
+ *                                  int arg1,
+ *                                  int arg2) KHRONOS_APIATTRIBUTES;
+ */
+
+/*-------------------------------------------------------------------------
+ * Definition of KHRONOS_APICALL
+ *-------------------------------------------------------------------------
+ * This precedes the return type of the function in the function prototype.
+ */
+#if defined(_WIN32) && !defined(__SCITECH_SNAP__)
+#   define KHRONOS_APICALL __declspec(dllimport)
+#elif defined (__SYMBIAN32__)
+#   define KHRONOS_APICALL IMPORT_C
+#else
+#   define KHRONOS_APICALL
+#endif
+
+/*-------------------------------------------------------------------------
+ * Definition of KHRONOS_APIENTRY
+ *-------------------------------------------------------------------------
+ * This follows the return type of the function  and precedes the function
+ * name in the function prototype.
+ */
+#if defined(_WIN32) && !defined(_WIN32_WCE) && !defined(__SCITECH_SNAP__)
+    /* Win32 but not WinCE */
+#   define KHRONOS_APIENTRY __stdcall
+#else
+#   define KHRONOS_APIENTRY
+#endif
+
+/*-------------------------------------------------------------------------
+ * Definition of KHRONOS_APIATTRIBUTES
+ *-------------------------------------------------------------------------
+ * This follows the closing parenthesis of the function prototype arguments.
+ */
+#if defined (__ARMCC_2__)
+#define KHRONOS_APIATTRIBUTES __softfp
+#else
+#define KHRONOS_APIATTRIBUTES
+#endif
+
+/*-------------------------------------------------------------------------
+ * basic type definitions
+ *-----------------------------------------------------------------------*/
+#if (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) || defined(__GNUC__) || defined(__SCO__) || defined(__USLC__)
+
+
+/*
+ * Using <stdint.h>
+ */
+#include <stdint.h>
+typedef int32_t                 khronos_int32_t;
+typedef uint32_t                khronos_uint32_t;
+typedef int64_t                 khronos_int64_t;
+typedef uint64_t                khronos_uint64_t;
+#define KHRONOS_SUPPORT_INT64   1
+#define KHRONOS_SUPPORT_FLOAT   1
+
+#elif defined(__VMS ) || defined(__sgi)
+
+/*
+ * Using <inttypes.h>
+ */
+#include <inttypes.h>
+typedef int32_t                 khronos_int32_t;
+typedef uint32_t                khronos_uint32_t;
+typedef int64_t                 khronos_int64_t;
+typedef uint64_t                khronos_uint64_t;
+#define KHRONOS_SUPPORT_INT64   1
+#define KHRONOS_SUPPORT_FLOAT   1
+
+#elif defined(_WIN32) && !defined(__SCITECH_SNAP__)
+
+/*
+ * Win32
+ */
+typedef __int32                 khronos_int32_t;
+typedef unsigned __int32        khronos_uint32_t;
+typedef __int64                 khronos_int64_t;
+typedef unsigned __int64        khronos_uint64_t;
+#define KHRONOS_SUPPORT_INT64   1
+#define KHRONOS_SUPPORT_FLOAT   1
+
+#elif defined(__sun__) || defined(__digital__)
+
+/*
+ * Sun or Digital
+ */
+typedef int                     khronos_int32_t;
+typedef unsigned int            khronos_uint32_t;
+#if defined(__arch64__) || defined(_LP64)
+typedef long int                khronos_int64_t;
+typedef unsigned long int       khronos_uint64_t;
+#else
+typedef long long int           khronos_int64_t;
+typedef unsigned long long int  khronos_uint64_t;
+#endif /* __arch64__ */
+#define KHRONOS_SUPPORT_INT64   1
+#define KHRONOS_SUPPORT_FLOAT   1
+
+#elif 0
+
+/*
+ * Hypothetical platform with no float or int64 support
+ */
+typedef int                     khronos_int32_t;
+typedef unsigned int            khronos_uint32_t;
+#define KHRONOS_SUPPORT_INT64   0
+#define KHRONOS_SUPPORT_FLOAT   0
+
+#else
+
+/*
+ * Generic fallback
+ */
+#include <stdint.h>
+typedef int32_t                 khronos_int32_t;
+typedef uint32_t                khronos_uint32_t;
+typedef int64_t                 khronos_int64_t;
+typedef uint64_t                khronos_uint64_t;
+#define KHRONOS_SUPPORT_INT64   1
+#define KHRONOS_SUPPORT_FLOAT   1
+
+#endif
+
+
+/*
+ * Types that are (so far) the same on all platforms
+ */
+typedef signed   char          khronos_int8_t;
+typedef unsigned char          khronos_uint8_t;
+typedef signed   short int     khronos_int16_t;
+typedef unsigned short int     khronos_uint16_t;
+typedef signed   long  int     khronos_intptr_t;
+typedef unsigned long  int     khronos_uintptr_t;
+typedef signed   long  int     khronos_ssize_t;
+typedef unsigned long  int     khronos_usize_t;
+
+#if KHRONOS_SUPPORT_FLOAT
+/*
+ * Float type
+ */
+typedef          float         khronos_float_t;
+#endif
+
+#if KHRONOS_SUPPORT_INT64
+/* Time types
+ *
+ * These types can be used to represent a time interval in nanoseconds or
+ * an absolute Unadjusted System Time.  Unadjusted System Time is the number
+ * of nanoseconds since some arbitrary system event (e.g. since the last
+ * time the system booted).  The Unadjusted System Time is an unsigned
+ * 64 bit value that wraps back to 0 every 584 years.  Time intervals
+ * may be either signed or unsigned.
+ */
+typedef khronos_uint64_t       khronos_utime_nanoseconds_t;
+typedef khronos_int64_t        khronos_stime_nanoseconds_t;
+#endif
+
+/*
+ * Dummy value used to pad enum types to 32 bits.
+ */
+#ifndef KHRONOS_MAX_ENUM
+#define KHRONOS_MAX_ENUM 0x7FFFFFFF
+#endif
+
+/*
+ * Enumerated boolean type
+ *
+ * Values other than zero should be considered to be true.  Therefore
+ * comparisons should not be made against KHRONOS_TRUE.
+ */
+typedef enum {
+    KHRONOS_FALSE = 0,
+    KHRONOS_TRUE  = 1,
+    KHRONOS_BOOLEAN_ENUM_FORCE_SIZE = KHRONOS_MAX_ENUM
+} khronos_boolean_enum_t;
+
+#endif /* __khrplatform_h_ */
diff --git a/src/3rdparty/angle/src/common/RefCountObject.cpp b/src/3rdparty/angle/src/common/RefCountObject.cpp
new file mode 100644 (file)
index 0000000..c1ef90c
--- /dev/null
@@ -0,0 +1,47 @@
+//
+// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// RefCountObject.cpp: Defines the gl::RefCountObject base class that provides
+// lifecycle support for GL objects using the traditional BindObject scheme, but
+// that need to be reference counted for correct cross-context deletion.
+// (Concretely, textures, buffers and renderbuffers.)
+
+#include "RefCountObject.h"
+
+RefCountObject::RefCountObject(GLuint id)
+{
+    mId = id;
+    mRefCount = 0;
+}
+
+RefCountObject::~RefCountObject()
+{
+    ASSERT(mRefCount == 0);
+}
+
+void RefCountObject::addRef() const
+{
+    mRefCount++;
+}
+
+void RefCountObject::release() const
+{
+    ASSERT(mRefCount > 0);
+
+    if (--mRefCount == 0)
+    {
+        delete this;
+    }
+}
+
+void RefCountObjectBindingPointer::set(RefCountObject *newObject)
+{
+    // addRef first in case newObject == mObject and this is the last reference to it.
+    if (newObject != NULL) newObject->addRef();
+    if (mObject != NULL) mObject->release();
+
+    mObject = newObject;
+}
diff --git a/src/3rdparty/angle/src/common/RefCountObject.h b/src/3rdparty/angle/src/common/RefCountObject.h
new file mode 100644 (file)
index 0000000..727c71c
--- /dev/null
@@ -0,0 +1,65 @@
+//
+// 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.
+//
+
+// RefCountObject.h: Defines the gl::RefCountObject base class that provides
+// lifecycle support for GL objects using the traditional BindObject scheme, but
+// that need to be reference counted for correct cross-context deletion.
+// (Concretely, textures, buffers and renderbuffers.)
+
+#ifndef COMMON_REFCOUNTOBJECT_H_
+#define COMMON_REFCOUNTOBJECT_H_
+
+#include <cstddef>
+
+#define GL_APICALL
+#include <GLES2/gl2.h>
+
+#include "common/debug.h"
+
+class RefCountObject
+{
+  public:
+    explicit RefCountObject(GLuint id);
+    virtual ~RefCountObject();
+
+    virtual void addRef() const;
+    virtual void release() const;
+
+    GLuint id() const { return mId; }
+    
+  private:
+    GLuint mId;
+
+    mutable std::size_t mRefCount;
+};
+
+class RefCountObjectBindingPointer
+{
+  protected:
+    RefCountObjectBindingPointer() : mObject(NULL) { }
+    ~RefCountObjectBindingPointer() { ASSERT(mObject == NULL); } // Objects have to be released before the resource manager is destroyed, so they must be explicitly cleaned up.
+
+    void set(RefCountObject *newObject);
+    RefCountObject *get() const { return mObject; }
+
+  public:
+    GLuint id() const { return (mObject != NULL) ? mObject->id() : 0; }
+    bool operator ! () const { return (get() == NULL); }
+
+  private:
+    RefCountObject *mObject;
+};
+
+template <class ObjectType>
+class BindingPointer : public RefCountObjectBindingPointer
+{
+  public:
+    void set(ObjectType *newObject) { RefCountObjectBindingPointer::set(newObject); }
+    ObjectType *get() const { return static_cast<ObjectType*>(RefCountObjectBindingPointer::get()); }
+    ObjectType *operator -> () const { return get(); }
+};
+
+#endif   // COMMON_REFCOUNTOBJECT_H_
diff --git a/src/3rdparty/angle/src/common/angleutils.h b/src/3rdparty/angle/src/common/angleutils.h
new file mode 100644 (file)
index 0000000..ff9730c
--- /dev/null
@@ -0,0 +1,26 @@
+//
+// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// angleutils.h: Common ANGLE utilities.
+
+#ifndef COMMON_ANGLEUTILS_H_
+#define COMMON_ANGLEUTILS_H_
+
+// A macro to disallow the copy constructor and operator= functions
+// This must be used in the private: declarations for a class
+#define DISALLOW_COPY_AND_ASSIGN(TypeName) \
+  TypeName(const TypeName&);               \
+  void operator=(const TypeName&)
+
+#if defined(_MSC_VER)
+#define snprintf _snprintf
+#endif
+
+#define VENDOR_ID_AMD 0x1002
+#define VENDOR_ID_INTEL 0x8086
+#define VENDOR_ID_NVIDIA 0x10DE
+
+#endif // COMMON_ANGLEUTILS_H_
diff --git a/src/3rdparty/angle/src/common/debug.cpp b/src/3rdparty/angle/src/common/debug.cpp
new file mode 100644 (file)
index 0000000..b2238f9
--- /dev/null
@@ -0,0 +1,103 @@
+//
+// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// debug.cpp: Debugging utilities.
+
+#include "common/debug.h"
+
+#include <stdio.h>
+#include <stdarg.h>
+#include <d3d9.h>
+#include <windows.h>
+
+namespace gl
+{
+
+typedef void (WINAPI *PerfOutputFunction)(D3DCOLOR, LPCWSTR);
+
+static void output(bool traceFileDebugOnly, PerfOutputFunction perfFunc, const char *format, va_list vararg)
+{
+#if !defined(ANGLE_DISABLE_PERF)
+    if (perfActive())
+    {
+        char message[32768];
+        int len = vsprintf_s(message, format, vararg);
+        if (len < 0)
+        {
+            return;
+        }
+
+        // There are no ASCII variants of these D3DPERF functions.
+        wchar_t wideMessage[32768];
+        for (int i = 0; i < len; ++i)
+        {
+            wideMessage[i] = message[i];
+        }
+        wideMessage[len] = 0;
+
+        perfFunc(0, wideMessage);
+    }
+#endif
+
+#if !defined(ANGLE_DISABLE_TRACE)
+#if defined(NDEBUG)
+    if (traceFileDebugOnly)
+    {
+        return;
+    }
+#endif
+
+    FILE* file = fopen(TRACE_OUTPUT_FILE, "a");
+    if (file)
+    {
+        vfprintf(file, format, vararg);
+        fclose(file);
+    }
+#endif
+}
+
+void trace(bool traceFileDebugOnly, const char *format, ...)
+{
+    va_list vararg;
+    va_start(vararg, format);
+#if defined(ANGLE_DISABLE_PERF)
+    output(traceFileDebugOnly, NULL, format, vararg);
+#else
+    output(traceFileDebugOnly, D3DPERF_SetMarker, format, vararg);
+#endif
+    va_end(vararg);
+}
+
+bool perfActive()
+{
+#if defined(ANGLE_DISABLE_PERF)
+    return false;
+#else
+    static bool active = D3DPERF_GetStatus() != 0;
+    return active;
+#endif
+}
+
+ScopedPerfEventHelper::ScopedPerfEventHelper(const char* format, ...)
+{
+#if !defined(ANGLE_DISABLE_PERF)
+    va_list vararg;
+    va_start(vararg, format);
+    output(true, reinterpret_cast<PerfOutputFunction>(D3DPERF_BeginEvent), format, vararg);
+    va_end(vararg);
+#endif
+}
+
+ScopedPerfEventHelper::~ScopedPerfEventHelper()
+{
+#if !defined(ANGLE_DISABLE_PERF)
+    if (perfActive())
+    {
+        D3DPERF_EndEvent();
+    }
+#endif
+}
+}
diff --git a/src/3rdparty/angle/src/common/debug.h b/src/3rdparty/angle/src/common/debug.h
new file mode 100644 (file)
index 0000000..5f8f60f
--- /dev/null
@@ -0,0 +1,105 @@
+//
+// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// debug.h: Debugging utilities.
+
+#ifndef COMMON_DEBUG_H_
+#define COMMON_DEBUG_H_
+
+#include <stdio.h>
+#include <assert.h>
+
+#include "common/angleutils.h"
+
+#if !defined(TRACE_OUTPUT_FILE)
+#define TRACE_OUTPUT_FILE "debug.txt"
+#endif
+
+namespace gl
+{
+    // Outputs text to the debugging log
+    void trace(bool traceFileDebugOnly, const char *format, ...);
+
+    // Returns whether D3DPERF is active.
+    bool perfActive();
+
+    // Pairs a D3D begin event with an end event.
+    class ScopedPerfEventHelper
+    {
+      public:
+        ScopedPerfEventHelper(const char* format, ...);
+        ~ScopedPerfEventHelper();
+
+      private:
+        DISALLOW_COPY_AND_ASSIGN(ScopedPerfEventHelper);
+    };
+}
+
+// A macro to output a trace of a function call and its arguments to the debugging log
+#if defined(ANGLE_DISABLE_TRACE) && defined(ANGLE_DISABLE_PERF)
+#define TRACE(message, ...) (void(0))
+#else
+#define TRACE(message, ...) gl::trace(true, "trace: %s(%d): " message "\n", __FUNCTION__, __LINE__, ##__VA_ARGS__)
+#endif
+
+// A macro to output a function call and its arguments to the debugging log, to denote an item in need of fixing.
+#if defined(ANGLE_DISABLE_TRACE) && defined(ANGLE_DISABLE_PERF)
+#define FIXME(message, ...) (void(0))
+#else
+#define FIXME(message, ...) gl::trace(false, "fixme: %s(%d): " message "\n", __FUNCTION__, __LINE__, ##__VA_ARGS__)
+#endif
+
+// A macro to output a function call and its arguments to the debugging log, in case of error.
+#if defined(ANGLE_DISABLE_TRACE) && defined(ANGLE_DISABLE_PERF)
+#define ERR(message, ...) (void(0))
+#else
+#define ERR(message, ...) gl::trace(false, "err: %s(%d): " message "\n", __FUNCTION__, __LINE__, ##__VA_ARGS__)
+#endif
+
+// A macro to log a performance event around a scope.
+#if defined(ANGLE_DISABLE_TRACE) && defined(ANGLE_DISABLE_PERF)
+#define EVENT(message, ...) (void(0))
+#elif defined(_MSC_VER)
+#define EVENT(message, ...) gl::ScopedPerfEventHelper scopedPerfEventHelper ## __LINE__(__FUNCTION__ message "\n", __VA_ARGS__);
+#else
+#define EVENT(message, ...) gl::ScopedPerfEventHelper scopedPerfEventHelper(message "\n", ##__VA_ARGS__);
+#endif
+
+// A macro asserting a condition and outputting failures to the debug log
+#if !defined(NDEBUG)
+#define ASSERT(expression) do { \
+    if(!(expression)) \
+        ERR("\t! Assert failed in %s(%d): "#expression"\n", __FUNCTION__, __LINE__); \
+        assert(expression); \
+    } while(0)
+#else
+#define ASSERT(expression) (void(0))
+#endif
+
+// A macro to indicate unimplemented functionality
+#if !defined(NDEBUG)
+#define UNIMPLEMENTED() do { \
+    FIXME("\t! Unimplemented: %s(%d)\n", __FUNCTION__, __LINE__); \
+    assert(false); \
+    } while(0)
+#else
+    #define UNIMPLEMENTED() FIXME("\t! Unimplemented: %s(%d)\n", __FUNCTION__, __LINE__)
+#endif
+
+// A macro for code which is not expected to be reached under valid assumptions
+#if !defined(NDEBUG)
+#define UNREACHABLE() do { \
+    ERR("\t! Unreachable reached: %s(%d)\n", __FUNCTION__, __LINE__); \
+    assert(false); \
+    } while(0)
+#else
+    #define UNREACHABLE() ERR("\t! Unreachable reached: %s(%d)\n", __FUNCTION__, __LINE__)
+#endif
+
+// A macro functioning as a compile-time assert to validate constant conditions
+#define META_ASSERT(condition) typedef int COMPILE_TIME_ASSERT_##__LINE__[static_cast<bool>(condition)?1:-1]
+
+#endif   // COMMON_DEBUG_H_
diff --git a/src/3rdparty/angle/src/common/version.h b/src/3rdparty/angle/src/common/version.h
new file mode 100644 (file)
index 0000000..fec98a1
--- /dev/null
@@ -0,0 +1,10 @@
+#define MAJOR_VERSION 1
+#define MINOR_VERSION 0
+#define BUILD_VERSION 0
+#define BUILD_REVISION 1318
+
+#define STRINGIFY(x) #x
+#define MACRO_STRINGIFY(x) STRINGIFY(x)
+
+#define REVISION_STRING MACRO_STRINGIFY(BUILD_REVISION)
+#define VERSION_STRING MACRO_STRINGIFY(MAJOR_VERSION) "." MACRO_STRINGIFY(MINOR_VERSION) "." MACRO_STRINGIFY(BUILD_VERSION) "." MACRO_STRINGIFY(BUILD_REVISION)
diff --git a/src/3rdparty/angle/src/compiler/BaseTypes.h b/src/3rdparty/angle/src/compiler/BaseTypes.h
new file mode 100644 (file)
index 0000000..5f83185
--- /dev/null
@@ -0,0 +1,152 @@
+//
+// 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
+    EvqConst,         // User defined constants and non-output parameters in functions
+    EvqAttribute,     // Readonly
+    EvqVaryingIn,     // readonly, fragment shaders only
+    EvqVaryingOut,    // vertex shaders only  read/write
+    EvqInvariantVaryingIn,     // readonly, fragment shaders only
+    EvqInvariantVaryingOut,    // vertex shaders only  read/write
+    EvqUniform,       // Readonly, vertex and fragment
+
+    // pack/unpack input and output
+    EvqInput,
+    EvqOutput,
+
+    // parameters
+    EvqIn,
+    EvqOut,
+    EvqInOut,
+    EvqConstReadOnly,
+
+    // built-ins written by vertex shader
+    EvqPosition,
+    EvqPointSize,
+
+    // built-ins read by fragment shader
+    EvqFragCoord,
+    EvqFrontFacing,
+    EvqPointCoord,
+
+    // built-ins written by fragment shader
+    EvqFragColor,
+    EvqFragData,
+
+    // end of list
+    EvqLast,
+};
+
+//
+// This is just for debug print out, carried along with the definitions above.
+//
+inline const char* getQualifierString(TQualifier q)
+{
+    switch(q)
+    {
+    case EvqTemporary:      return "Temporary";      break;
+    case EvqGlobal:         return "Global";         break;
+    case EvqConst:          return "const";          break;
+    case EvqConstReadOnly:  return "const";          break;
+    case EvqAttribute:      return "attribute";      break;
+    case EvqVaryingIn:      return "varying";        break;
+    case EvqVaryingOut:     return "varying";        break;
+    case EvqInvariantVaryingIn: return "invariant varying";    break;
+    case EvqInvariantVaryingOut:return "invariant varying";    break;
+    case EvqUniform:        return "uniform";        break;
+    case EvqIn:             return "in";             break;
+    case EvqOut:            return "out";            break;
+    case EvqInOut:          return "inout";          break;
+    case EvqInput:          return "input";          break;
+    case EvqOutput:         return "output";         break;
+    case EvqPosition:       return "Position";       break;
+    case EvqPointSize:      return "PointSize";      break;
+    case EvqFragCoord:      return "FragCoord";      break;
+    case EvqFrontFacing:    return "FrontFacing";    break;
+    case EvqFragColor:      return "FragColor";      break;
+    case EvqFragData:       return "FragData";      break;
+    default:                return "unknown qualifier";
+    }
+}
+
+#endif // _BASICTYPES_INCLUDED_
diff --git a/src/3rdparty/angle/src/compiler/BuiltInFunctionEmulator.cpp b/src/3rdparty/angle/src/compiler/BuiltInFunctionEmulator.cpp
new file mode 100644 (file)
index 0000000..1c4b25f
--- /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/BuiltInFunctionEmulator.h"
+
+#include "compiler/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/src/3rdparty/angle/src/compiler/BuiltInFunctionEmulator.h b/src/3rdparty/angle/src/compiler/BuiltInFunctionEmulator.h
new file mode 100644 (file)
index 0000000..0d904f4
--- /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/InfoSink.h"
+#include "compiler/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/src/3rdparty/angle/src/compiler/CodeGenGLSL.cpp b/src/3rdparty/angle/src/compiler/CodeGenGLSL.cpp
new file mode 100644 (file)
index 0000000..226bf8f
--- /dev/null
@@ -0,0 +1,34 @@
+//
+// 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/TranslatorGLSL.h"
+#include "compiler/TranslatorESSL.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_GLSL_OUTPUT:
+        return new TranslatorGLSL(type, spec);
+      case SH_ESSL_OUTPUT:
+        return new TranslatorESSL(type, spec);
+      default:
+        return NULL;
+    }
+}
+
+//
+// Delete the compiler made by ConstructCompiler
+//
+void DeleteCompiler(TCompiler* compiler)
+{
+    delete compiler;
+}
diff --git a/src/3rdparty/angle/src/compiler/CodeGenHLSL.cpp b/src/3rdparty/angle/src/compiler/CodeGenHLSL.cpp
new file mode 100644 (file)
index 0000000..f46ff66
--- /dev/null
@@ -0,0 +1,31 @@
+//
+// 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/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_HLSL_OUTPUT:
+      return new TranslatorHLSL(type, spec);
+    default:
+      return NULL;
+  }
+}
+
+//
+// Delete the compiler made by ConstructCompiler
+//
+void DeleteCompiler(TCompiler* compiler)
+{
+    delete compiler;
+}
diff --git a/src/3rdparty/angle/src/compiler/Common.h b/src/3rdparty/angle/src/compiler/Common.h
new file mode 100644 (file)
index 0000000..27a5598
--- /dev/null
@@ -0,0 +1,89 @@
+//
+// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#ifndef _COMMON_INCLUDED_
+#define _COMMON_INCLUDED_
+
+#include <map>
+#include <sstream>
+#include <string>
+#include <vector>
+
+#include "compiler/PoolAlloc.h"
+
+// We need two pieces of information to report errors/warnings - string and
+// line number. We encode these into a single int so that it can be easily
+// incremented/decremented by lexer. The right SOURCE_LOC_LINE_SIZE bits store
+// line number while the rest store the string number. Since the shaders are
+// usually small, we should not run out of memory. SOURCE_LOC_LINE_SIZE
+// can be increased to alleviate this issue.
+typedef int TSourceLoc;
+const unsigned int SOURCE_LOC_LINE_SIZE = 16;  // in bits.
+const unsigned int SOURCE_LOC_LINE_MASK = (1 << SOURCE_LOC_LINE_SIZE) - 1;
+
+inline TSourceLoc EncodeSourceLoc(int string, int line) {
+    return (string << SOURCE_LOC_LINE_SIZE) | (line & SOURCE_LOC_LINE_MASK);
+}
+
+inline void DecodeSourceLoc(TSourceLoc loc, int* string, int* line) {
+    if (string) *string = loc >> SOURCE_LOC_LINE_SIZE;
+    if (line) *line = loc & SOURCE_LOC_LINE_MASK;
+}
+
+//
+// Put POOL_ALLOCATOR_NEW_DELETE in base classes to make them use this scheme.
+//
+#define POOL_ALLOCATOR_NEW_DELETE(A)                                  \
+    void* operator new(size_t s) { return (A).allocate(s); }          \
+    void* operator new(size_t, void *_Where) { return (_Where);        }     \
+    void operator delete(void*) { }                                   \
+    void operator delete(void *, void *) { }                          \
+    void* operator new[](size_t s) { return (A).allocate(s); }        \
+    void* operator new[](size_t, void *_Where) { return (_Where);      } \
+    void operator delete[](void*) { }                                 \
+    void operator delete[](void *, void *) { }
+
+//
+// Pool version of string.
+//
+typedef pool_allocator<char> TStringAllocator;
+typedef std::basic_string <char, std::char_traits<char>, TStringAllocator> TString;
+typedef std::basic_ostringstream<char, std::char_traits<char>, TStringAllocator> TStringStream;
+inline TString* NewPoolTString(const char* s)
+{
+       void* memory = GlobalPoolAllocator.allocate(sizeof(TString));
+       return new(memory) TString(s);
+}
+
+//
+// Persistent string memory.  Should only be used for strings that survive
+// across compiles.
+//
+#define TPersistString std::string
+#define TPersistStringStream std::ostringstream
+
+//
+// Pool allocator versions of vectors, lists, and maps
+//
+template <class T> class TVector : public std::vector<T, pool_allocator<T> > {
+public:
+    typedef typename std::vector<T, pool_allocator<T> >::size_type size_type;
+    TVector() : std::vector<T, pool_allocator<T> >() {}
+    TVector(const pool_allocator<T>& a) : std::vector<T, pool_allocator<T> >(a) {}
+    TVector(size_type i): std::vector<T, pool_allocator<T> >(i) {}
+};
+
+template <class K, class D, class CMP = std::less<K> > 
+class TMap : public std::map<K, D, CMP, pool_allocator<std::pair<const K, D> > > {
+public:
+    typedef pool_allocator<std::pair<const K, D> > tAllocator;
+
+    TMap() : std::map<K, D, CMP, tAllocator>() {}
+    // use correct two-stage name lookup supported in gcc 3.4 and above
+    TMap(const tAllocator& a) : std::map<K, D, CMP, tAllocator>(std::map<K, D, CMP, tAllocator>::key_compare(), a) {}
+};
+
+#endif // _COMMON_INCLUDED_
diff --git a/src/3rdparty/angle/src/compiler/Compiler.cpp b/src/3rdparty/angle/src/compiler/Compiler.cpp
new file mode 100644 (file)
index 0000000..9e7f75c
--- /dev/null
@@ -0,0 +1,350 @@
+//
+// 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/BuiltInFunctionEmulator.h"
+#include "compiler/DetectRecursion.h"
+#include "compiler/ForLoopUnroll.h"
+#include "compiler/Initialize.h"
+#include "compiler/InitializeParseContext.h"
+#include "compiler/MapLongVariableNames.h"
+#include "compiler/ParseHelper.h"
+#include "compiler/RenameFunction.h"
+#include "compiler/ShHandle.h"
+#include "compiler/ValidateLimitations.h"
+#include "compiler/VariablePacker.h"
+#include "compiler/depgraph/DependencyGraph.h"
+#include "compiler/depgraph/DependencyGraphOutput.h"
+#include "compiler/timing/RestrictFragmentShaderTiming.h"
+#include "compiler/timing/RestrictVertexShaderTiming.h"
+
+bool isWebGLBasedSpec(ShShaderSpec spec)
+{
+     return spec == SH_WEBGL_SPEC || spec == SH_CSS_SHADERS_SPEC;
+}
+
+namespace {
+bool InitializeSymbolTable(
+    const TBuiltInStrings& builtInStrings,
+    ShShaderType type, ShShaderSpec spec, const ShBuiltInResources& resources,
+    TInfoSink& infoSink, TSymbolTable& symbolTable)
+{
+    TIntermediate intermediate(infoSink);
+    TExtensionBehavior extBehavior;
+    InitExtensionBehavior(resources, extBehavior);
+    // The builtins deliberately don't specify precisions for the function
+    // arguments and return types. For that reason we don't try to check them.
+    TParseContext parseContext(symbolTable, extBehavior, intermediate, type, spec, 0, false, NULL, infoSink);
+
+    GlobalParseContext = &parseContext;
+
+    assert(symbolTable.isEmpty());       
+    //
+    // Parse the built-ins.  This should only happen once per
+    // language symbol table.
+    //
+    // Push the symbol table to give it an initial scope.  This
+    // push should not have a corresponding pop, so that built-ins
+    // are preserved, and the test for an empty table fails.
+    //
+    symbolTable.push();
+
+    for (TBuiltInStrings::const_iterator i = builtInStrings.begin(); i != builtInStrings.end(); ++i)
+    {
+        const char* builtInShaders = i->c_str();
+        int builtInLengths = static_cast<int>(i->size());
+        if (builtInLengths <= 0)
+          continue;
+
+        if (PaParseStrings(1, &builtInShaders, &builtInLengths, &parseContext) != 0)
+        {
+            infoSink.info.message(EPrefixInternalError, "Unable to parse built-ins");
+            return false;
+        }
+    }
+
+    IdentifyBuiltIns(type, spec, resources, symbolTable);
+
+    return true;
+}
+
+class TScopedPoolAllocator {
+public:
+    TScopedPoolAllocator(TPoolAllocator* allocator, bool pushPop)
+        : mAllocator(allocator), mPushPopAllocator(pushPop) {
+        if (mPushPopAllocator) mAllocator->push();
+        SetGlobalPoolAllocator(mAllocator);
+    }
+    ~TScopedPoolAllocator() {
+        SetGlobalPoolAllocator(NULL);
+        if (mPushPopAllocator) mAllocator->pop();
+    }
+
+private:
+    TPoolAllocator* mAllocator;
+    bool mPushPopAllocator;
+};
+}  // namespace
+
+TShHandleBase::TShHandleBase() {
+    allocator.push();
+    SetGlobalPoolAllocator(&allocator);
+}
+
+TShHandleBase::~TShHandleBase() {
+    SetGlobalPoolAllocator(NULL);
+    allocator.popAll();
+}
+
+TCompiler::TCompiler(ShShaderType type, ShShaderSpec spec)
+    : shaderType(type),
+      shaderSpec(spec),
+      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;
+    TScopedPoolAllocator scopedAlloc(&allocator, false);
+
+    // Generate built-in symbol table.
+    if (!InitBuiltInSymbolTable(resources))
+        return false;
+    InitExtensionBehavior(resources, extensionBehavior);
+
+    return true;
+}
+
+bool TCompiler::compile(const char* const shaderStrings[],
+                        const int numStrings,
+                        int compileOptions)
+{
+    TScopedPoolAllocator scopedAlloc(&allocator, true);
+    clearResults();
+
+    if (numStrings == 0)
+        return true;
+
+    // If compiling for WebGL, validate loop and indexing as well.
+    if (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;
+    int firstSource = 0;
+    if (compileOptions & SH_SOURCE_PATH)
+    {
+        sourcePath = shaderStrings[0];
+        ++firstSource;
+    }
+
+    TIntermediate intermediate(infoSink);
+    TParseContext parseContext(symbolTable, extensionBehavior, intermediate,
+                               shaderType, shaderSpec, compileOptions, true,
+                               sourcePath, infoSink);
+    GlobalParseContext = &parseContext;
+
+    // We preserve symbols at the built-in level from compile-to-compile.
+    // Start pushing the user-defined symbols at global level.
+    symbolTable.push();
+    if (!symbolTable.atGlobalLevel())
+        infoSink.info.message(EPrefixInternalError, "Wrong symbol table level");
+
+    // Parse shader.
+    bool success =
+        (PaParseStrings(numStrings - firstSource, &shaderStrings[firstSource], NULL, &parseContext) == 0) &&
+        (parseContext.treeRoot != NULL);
+    if (success) {
+        TIntermNode* root = parseContext.treeRoot;
+        success = intermediate.postProcess(root);
+
+        if (success)
+            success = detectRecursion(root);
+
+        if (success && (compileOptions & SH_VALIDATE_LOOP_INDEXING))
+            success = validateLimitations(root);
+
+        if (success && (compileOptions & SH_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);
+
+        // Call mapLongVariableNames() before collectAttribsUniforms() so in
+        // collectAttribsUniforms() we already have the mapped symbol names and
+        // we could composite mapped and original variable names.
+        if (success && (compileOptions & SH_MAP_LONG_VARIABLE_NAMES))
+            mapLongVariableNames(root);
+
+        if (success && (compileOptions & SH_ATTRIBUTES_UNIFORMS)) {
+            collectAttribsUniforms(root);
+            if (compileOptions & SH_ENFORCE_PACKING_RESTRICTIONS) {
+                success = enforcePackingRestrictions();
+                if (!success) {
+                    infoSink.info.message(EPrefixError, "too many uniforms");
+                }
+            }
+        }
+
+        if (success && (compileOptions & SH_INTERMEDIATE_TREE))
+            intermediate.outputTree(root);
+
+        if (success && (compileOptions & SH_OBJECT_CODE))
+            translate(root);
+    }
+
+    // Cleanup memory.
+    intermediate.remove(parseContext.treeRoot);
+    // Ensure symbol table is returned to the built-in level,
+    // throwing away all but the built-ins.
+    while (!symbolTable.atBuiltInLevel())
+        symbolTable.pop();
+
+    return success;
+}
+
+bool TCompiler::InitBuiltInSymbolTable(const ShBuiltInResources& resources)
+{
+    TBuiltIns builtIns;
+
+    builtIns.initialize(shaderType, shaderSpec, resources);
+    return InitializeSymbolTable(builtIns.getBuiltInStrings(),
+        shaderType, shaderSpec, resources, infoSink, symbolTable);
+}
+
+void TCompiler::clearResults()
+{
+    infoSink.info.erase();
+    infoSink.obj.erase();
+    infoSink.debug.erase();
+
+    attribs.clear();
+    uniforms.clear();
+
+    builtInFunctionEmulator.Cleanup();
+}
+
+bool TCompiler::detectRecursion(TIntermNode* root)
+{
+    DetectRecursion detect;
+    root->traverse(&detect);
+    switch (detect.detectRecursion()) {
+        case DetectRecursion::kErrorNone:
+            return true;
+        case DetectRecursion::kErrorMissingMain:
+            infoSink.info.message(EPrefixError, "Missing main()");
+            return false;
+        case DetectRecursion::kErrorRecursion:
+            infoSink.info.message(EPrefixError, "Function recursion detected");
+            return false;
+        default:
+            UNREACHABLE();
+            return false;
+    }
+}
+
+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::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::collectAttribsUniforms(TIntermNode* root)
+{
+    CollectAttribsUniforms collect(attribs, uniforms);
+    root->traverse(&collect);
+}
+
+bool TCompiler::enforcePackingRestrictions()
+{
+    VariablePacker packer;
+    return packer.CheckVariablesWithinPackingLimits(maxUniformVectors, uniforms);
+}
+
+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 BuiltInFunctionEmulator& TCompiler::getBuiltInFunctionEmulator() const
+{
+    return builtInFunctionEmulator;
+}
diff --git a/src/3rdparty/angle/src/compiler/ConstantUnion.h b/src/3rdparty/angle/src/compiler/ConstantUnion.h
new file mode 100644 (file)
index 0000000..fd9d94d
--- /dev/null
@@ -0,0 +1,256 @@
+//
+// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#ifndef _CONSTANT_UNION_INCLUDED_
+#define _CONSTANT_UNION_INCLUDED_
+
+#include <assert.h>
+
+class ConstantUnion {
+public:
+    ConstantUnion()
+    {
+        iConst = 0;
+    }
+
+    POOL_ALLOCATOR_NEW_DELETE(GlobalPoolAllocator)        
+    void setIConst(int i) {iConst = i; type = EbtInt; }
+    void setFConst(float f) {fConst = f; type = EbtFloat; }
+    void setBConst(bool b) {bConst = b; type = EbtBool; }
+
+    int getIConst() { return iConst; }
+    float getFConst() { return fConst; }
+    bool getBConst() { return bConst; }
+    int getIConst() const { return iConst; }
+    float getFConst() const { return fConst; }
+    bool getBConst() const { return bConst; }
+
+    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/src/3rdparty/angle/src/compiler/DetectDiscontinuity.cpp b/src/3rdparty/angle/src/compiler/DetectDiscontinuity.cpp
new file mode 100644 (file)
index 0000000..472232a
--- /dev/null
@@ -0,0 +1,119 @@
+//
+// 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/DetectDiscontinuity.h"
+
+#include "compiler/ParseHelper.h"
+
+namespace sh
+{
+bool DetectLoopDiscontinuity::traverse(TIntermNode *node)
+{
+    mLoopDiscontinuity = false;
+    node->traverse(this);
+    return mLoopDiscontinuity;
+}
+
+bool DetectLoopDiscontinuity::visitBranch(Visit visit, TIntermBranch *node)
+{
+    if (mLoopDiscontinuity)
+    {
+        return false;
+    }
+
+    switch (node->getFlowOp())
+    {
+      case EOpKill:
+        break;
+      case EOpBreak:
+      case EOpContinue:
+        mLoopDiscontinuity = true;
+      case EOpReturn:
+        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/src/3rdparty/angle/src/compiler/DetectDiscontinuity.h b/src/3rdparty/angle/src/compiler/DetectDiscontinuity.h
new file mode 100644 (file)
index 0000000..8bda4c3
--- /dev/null
@@ -0,0 +1,50 @@
+//
+// 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/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 visitAggregate(Visit visit, TIntermAggregate *node);
+
+    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/src/3rdparty/angle/src/compiler/DetectRecursion.cpp b/src/3rdparty/angle/src/compiler/DetectRecursion.cpp
new file mode 100644 (file)
index 0000000..c09780d
--- /dev/null
@@ -0,0 +1,125 @@
+//
+// 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/DetectRecursion.h"
+
+DetectRecursion::FunctionNode::FunctionNode(const TString& fname)
+    : name(fname),
+      visit(PreVisit)
+{
+}
+
+const TString& DetectRecursion::FunctionNode::getName() const
+{
+    return name;
+}
+
+void DetectRecursion::FunctionNode::addCallee(
+    DetectRecursion::FunctionNode* callee)
+{
+    for (size_t i = 0; i < callees.size(); ++i) {
+        if (callees[i] == callee)
+            return;
+    }
+    callees.push_back(callee);
+}
+
+bool DetectRecursion::FunctionNode::detectRecursion()
+{
+    ASSERT(visit == PreVisit);
+    visit = InVisit;
+    for (size_t i = 0; i < callees.size(); ++i) {
+        switch (callees[i]->visit) {
+            case InVisit:
+                // cycle detected, i.e., recursion detected.
+                return true;
+            case PostVisit:
+                break;
+            case PreVisit: {
+                bool recursion = callees[i]->detectRecursion();
+                if (recursion)
+                    return true;
+                break;
+            }
+            default:
+                UNREACHABLE();
+                break;
+        }
+    }
+    visit = PostVisit;
+    return false;
+}
+
+DetectRecursion::DetectRecursion()
+    : currentFunction(NULL)
+{
+}
+
+DetectRecursion::~DetectRecursion()
+{
+    for (size_t i = 0; i < functions.size(); ++i)
+        delete functions[i];
+}
+
+bool DetectRecursion::visitAggregate(Visit visit, TIntermAggregate* node)
+{
+    switch (node->getOp())
+    {
+        case EOpPrototype:
+            // Function declaration.
+            // Don't add FunctionNode here because node->getName() is the
+            // unmangled function name.
+            break;
+        case EOpFunction: {
+            // Function definition.
+            if (visit == PreVisit) {
+                currentFunction = findFunctionByName(node->getName());
+                if (currentFunction == NULL) {
+                    currentFunction = new FunctionNode(node->getName());
+                    functions.push_back(currentFunction);
+                }
+            }
+            break;
+        }
+        case EOpFunctionCall: {
+            // Function call.
+            if (visit == PreVisit) {
+                ASSERT(currentFunction != NULL);
+                FunctionNode* func = findFunctionByName(node->getName());
+                if (func == NULL) {
+                    func = new FunctionNode(node->getName());
+                    functions.push_back(func);
+                }
+                currentFunction->addCallee(func);
+            }
+            break;
+        }
+        default:
+            break;
+    }
+    return true;
+}
+
+DetectRecursion::ErrorCode DetectRecursion::detectRecursion()
+{
+    FunctionNode* main = findFunctionByName("main(");
+    if (main == NULL)
+        return kErrorMissingMain;
+    if (main->detectRecursion())
+        return kErrorRecursion;
+    return kErrorNone;
+}
+
+DetectRecursion::FunctionNode* DetectRecursion::findFunctionByName(
+    const TString& name)
+{
+    for (size_t i = 0; i < functions.size(); ++i) {
+        if (functions[i]->getName() == name)
+            return functions[i];
+    }
+    return NULL;
+}
+
diff --git a/src/3rdparty/angle/src/compiler/DetectRecursion.h b/src/3rdparty/angle/src/compiler/DetectRecursion.h
new file mode 100644 (file)
index 0000000..bbac79d
--- /dev/null
@@ -0,0 +1,60 @@
+//
+// Copyright (c) 2002-2011 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#ifndef COMPILER_DETECT_RECURSION_H_
+#define COMPILER_DETECT_RECURSION_H_
+
+#include "GLSLANG/ShaderLang.h"
+
+#include "compiler/intermediate.h"
+#include "compiler/VariableInfo.h"
+
+// Traverses intermediate tree to detect function recursion.
+class DetectRecursion : public TIntermTraverser {
+public:
+    enum ErrorCode {
+        kErrorMissingMain,
+        kErrorRecursion,
+        kErrorNone
+    };
+
+    DetectRecursion();
+    ~DetectRecursion();
+
+    virtual bool visitAggregate(Visit, TIntermAggregate*);
+
+    ErrorCode detectRecursion();
+
+private:
+    class FunctionNode {
+    public:
+        FunctionNode(const TString& fname);
+
+        const TString& getName() const;
+
+        // If a function is already in the callee list, this becomes a no-op.
+        void addCallee(FunctionNode* callee);
+
+        // Return true if recursive function calls are detected.
+        bool detectRecursion();
+
+    private:
+        // mangled function name is unique.
+        TString name;
+
+        // functions that are directly called by this function.
+        TVector<FunctionNode*> callees;
+
+        Visit visit;
+    };
+
+    FunctionNode* findFunctionByName(const TString& name);
+
+    TVector<FunctionNode*> functions;
+    FunctionNode* currentFunction;
+};
+
+#endif  // COMPILER_DETECT_RECURSION_H_
diff --git a/src/3rdparty/angle/src/compiler/Diagnostics.cpp b/src/3rdparty/angle/src/compiler/Diagnostics.cpp
new file mode 100644 (file)
index 0000000..8aa1cb6
--- /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/Diagnostics.h"
+
+#include "compiler/debug.h"
+#include "compiler/InfoSink.h"
+#include "compiler/preprocessor/new/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 ERROR:
+        ++mNumErrors;
+        prefix = EPrefixError;
+        break;
+      case WARNING:
+        ++mNumWarnings;
+        prefix = EPrefixWarning;
+        break;
+      default:
+        UNREACHABLE();
+        break;
+    }
+
+    TInfoSinkBase& sink = mInfoSink.info;
+    /* VC++ format: file(linenum) : error #: 'token' : extrainfo */
+    sink.prefix(prefix);
+    sink.location(EncodeSourceLoc(loc.file, loc.line));
+    sink << "'" << token <<  "' : " << reason << " " << extra << "\n";
+}
+
+void TDiagnostics::writeDebug(const std::string& str)
+{
+    mInfoSink.debug << str;
+}
+
+void TDiagnostics::print(ID id,
+                         const pp::SourceLocation& loc,
+                         const std::string& text)
+{
+    writeInfo(severity(id), loc, message(id), text, "");
+}
diff --git a/src/3rdparty/angle/src/compiler/Diagnostics.h b/src/3rdparty/angle/src/compiler/Diagnostics.h
new file mode 100644 (file)
index 0000000..3670414
--- /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/new/Diagnostics.h"
+
+class TInfoSink;
+
+class TDiagnostics : public pp::Diagnostics
+{
+  public:
+    TDiagnostics(TInfoSink& infoSink);
+    virtual ~TDiagnostics();
+
+    TInfoSink& infoSink() { return mInfoSink; }
+
+    int numErrors() const { return mNumErrors; }
+    int numWarnings() const { return mNumWarnings; }
+
+    void writeInfo(Severity severity,
+                   const pp::SourceLocation& loc,
+                   const std::string& reason,
+                   const std::string& token,
+                   const std::string& extra);
+
+    void writeDebug(const std::string& str);
+
+  protected:
+    virtual void print(ID id,
+                       const pp::SourceLocation& loc,
+                       const std::string& text);
+
+  private:
+    TInfoSink& mInfoSink;
+    int mNumErrors;
+    int mNumWarnings;
+};
+
+#endif  // COMPILER_DIAGNOSTICS_H_
diff --git a/src/3rdparty/angle/src/compiler/DirectiveHandler.cpp b/src/3rdparty/angle/src/compiler/DirectiveHandler.cpp
new file mode 100644 (file)
index 0000000..d1f6ab3
--- /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/DirectiveHandler.h"
+
+#include <sstream>
+
+#include "compiler/debug.h"
+#include "compiler/Diagnostics.h"
+
+static TBehavior getBehavior(const std::string& str)
+{
+    static const std::string kRequire("require");
+    static const std::string kEnable("enable");
+    static const std::string kDisable("disable");
+    static const std::string kWarn("warn");
+
+    if (str == kRequire) return EBhRequire;
+    else if (str == kEnable) return EBhEnable;
+    else if (str == kDisable) return EBhDisable;
+    else if (str == kWarn) return EBhWarn;
+    return EBhUndefined;
+}
+
+TDirectiveHandler::TDirectiveHandler(TExtensionBehavior& extBehavior,
+                                     TDiagnostics& diagnostics)
+    : mExtensionBehavior(extBehavior),
+      mDiagnostics(diagnostics)
+{
+}
+
+TDirectiveHandler::~TDirectiveHandler()
+{
+}
+
+void TDirectiveHandler::handleError(const pp::SourceLocation& loc,
+                                    const std::string& msg)
+{
+    mDiagnostics.writeInfo(pp::Diagnostics::ERROR, loc, msg, "", "");
+}
+
+void TDirectiveHandler::handlePragma(const pp::SourceLocation& loc,
+                                     const std::string& name,
+                                     const std::string& value)
+{
+    static const std::string kSTDGL("STDGL");
+    static const std::string kOptimize("optimize");
+    static const std::string kDebug("debug");
+    static const std::string kOn("on");
+    static const std::string kOff("off");
+
+    bool invalidValue = false;
+    if (name == kSTDGL)
+    {
+        // The STDGL pragma is used to reserve pragmas for use by future
+        // revisions of GLSL. Ignore it.
+        return;
+    }
+    else if (name == kOptimize)
+    {
+        if (value == kOn) mPragma.optimize = true;
+        else if (value == kOff) mPragma.optimize = false;
+        else invalidValue = true;
+    }
+    else if (name == kDebug)
+    {
+        if (value == kOn) mPragma.debug = true;
+        else if (value == kOff) mPragma.debug = false;
+        else invalidValue = true;
+    }
+    else
+    {
+        mDiagnostics.report(pp::Diagnostics::UNRECOGNIZED_PRAGMA, loc, name);
+        return;
+    }
+
+    if (invalidValue)
+      mDiagnostics.writeInfo(pp::Diagnostics::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::ERROR, loc,
+                               "behavior", name, "invalid");
+        return;
+    }
+
+    if (name == kExtAll)
+    {
+        if (behaviorVal == EBhRequire)
+        {
+            mDiagnostics.writeInfo(pp::Diagnostics::ERROR, loc,
+                                   "extension", name,
+                                   "cannot have 'require' behavior");
+        }
+        else if (behaviorVal == EBhEnable)
+        {
+            mDiagnostics.writeInfo(pp::Diagnostics::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::ERROR;
+    switch (behaviorVal) {
+      case EBhRequire:
+        severity = pp::Diagnostics::ERROR;
+        break;
+      case EBhEnable:
+      case EBhWarn:
+      case EBhDisable:
+        severity = pp::Diagnostics::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::ERROR, loc,
+                               "version number", str, "not supported");
+    }
+}
diff --git a/src/3rdparty/angle/src/compiler/DirectiveHandler.h b/src/3rdparty/angle/src/compiler/DirectiveHandler.h
new file mode 100644 (file)
index 0000000..21d3dfc
--- /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/ExtensionBehavior.h"
+#include "compiler/Pragma.h"
+#include "compiler/preprocessor/new/DirectiveHandler.h"
+
+class TDiagnostics;
+
+class TDirectiveHandler : public pp::DirectiveHandler
+{
+  public:
+    TDirectiveHandler(TExtensionBehavior& extBehavior,
+                      TDiagnostics& diagnostics);
+    virtual ~TDirectiveHandler();
+
+    const TPragma& pragma() const { return mPragma; }
+    const TExtensionBehavior& extensionBehavior() const { return mExtensionBehavior; }
+
+    virtual void handleError(const pp::SourceLocation& loc,
+                             const std::string& msg);
+
+    virtual void handlePragma(const pp::SourceLocation& loc,
+                              const std::string& name,
+                              const std::string& value);
+
+    virtual void handleExtension(const pp::SourceLocation& loc,
+                                 const std::string& name,
+                                 const std::string& behavior);
+
+    virtual void handleVersion(const pp::SourceLocation& loc,
+                               int version);
+
+  private:
+    TPragma mPragma;
+    TExtensionBehavior& mExtensionBehavior;
+    TDiagnostics& mDiagnostics;
+};
+
+#endif  // COMPILER_DIRECTIVE_HANDLER_H_
diff --git a/src/3rdparty/angle/src/compiler/ExtensionBehavior.h b/src/3rdparty/angle/src/compiler/ExtensionBehavior.h
new file mode 100644 (file)
index 0000000..6040980
--- /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/src/3rdparty/angle/src/compiler/ForLoopUnroll.cpp b/src/3rdparty/angle/src/compiler/ForLoopUnroll.cpp
new file mode 100644 (file)
index 0000000..fdc3f44
--- /dev/null
@@ -0,0 +1,215 @@
+//
+// 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/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->getUnionArrayPointer()->getIConst();
+}
+
diff --git a/src/3rdparty/angle/src/compiler/ForLoopUnroll.h b/src/3rdparty/angle/src/compiler/ForLoopUnroll.h
new file mode 100644 (file)
index 0000000..e800e25
--- /dev/null
@@ -0,0 +1,48 @@
+//
+// Copyright (c) 2011 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "compiler/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;
+};
+
diff --git a/src/3rdparty/angle/src/compiler/InfoSink.cpp b/src/3rdparty/angle/src/compiler/InfoSink.cpp
new file mode 100644 (file)
index 0000000..ba32f78
--- /dev/null
@@ -0,0 +1,59 @@
+//
+// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "compiler/InfoSink.h"
+
+void TInfoSinkBase::prefix(TPrefixType message) {
+    switch(message) {
+        case EPrefixNone:
+            break;
+        case EPrefixWarning:
+            sink.append("WARNING: ");
+            break;
+        case EPrefixError:
+            sink.append("ERROR: ");
+            break;
+        case EPrefixInternalError:
+            sink.append("INTERNAL ERROR: ");
+            break;
+        case EPrefixUnimplemented:
+            sink.append("UNIMPLEMENTED: ");
+            break;
+        case EPrefixNote:
+            sink.append("NOTE: ");
+            break;
+        default:
+            sink.append("UNKOWN ERROR: ");
+            break;
+    }
+}
+
+void TInfoSinkBase::location(TSourceLoc loc) {
+    int string = 0, line = 0;
+    DecodeSourceLoc(loc, &string, &line);
+
+    TPersistStringStream stream;
+    if (line)
+        stream << string << ":" << line;
+    else
+        stream << string << ":? ";
+    stream << ": ";
+
+    sink.append(stream.str());
+}
+
+void TInfoSinkBase::message(TPrefixType message, const char* s) {
+    prefix(message);
+    sink.append(s);
+    sink.append("\n");
+}
+
+void TInfoSinkBase::message(TPrefixType message, const char* s, TSourceLoc loc) {
+    prefix(message);
+    location(loc);
+    sink.append(s);
+    sink.append("\n");
+}
diff --git a/src/3rdparty/angle/src/compiler/InfoSink.h b/src/3rdparty/angle/src/compiler/InfoSink.h
new file mode 100644 (file)
index 0000000..e2224e9
--- /dev/null
@@ -0,0 +1,115 @@
+//
+// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#ifndef _INFOSINK_INCLUDED_
+#define _INFOSINK_INCLUDED_
+
+#include <math.h>
+#include "compiler/Common.h"
+
+// Returns the fractional part of the given floating-point number.
+inline float fractionalPart(float f) {
+  float intPart = 0.0f;
+  return modff(f, &intPart);
+}
+
+//
+// TPrefixType is used to centralize how info log messages start.
+// See below.
+//
+enum TPrefixType {
+    EPrefixNone,
+    EPrefixWarning,
+    EPrefixError,
+    EPrefixInternalError,
+    EPrefixUnimplemented,
+    EPrefixNote
+};
+
+//
+// Encapsulate info logs for all objects that have them.
+//
+// The methods are a general set of tools for getting a variety of
+// messages and types inserted into the log.
+//
+class TInfoSinkBase {
+public:
+    TInfoSinkBase() {}
+
+    template <typename T>
+    TInfoSinkBase& operator<<(const T& t) {
+        TPersistStringStream stream;
+        stream << t;
+        sink.append(stream.str());
+        return *this;
+    }
+    // Override << operator for specific types. It is faster to append strings
+    // and characters directly to the sink.
+    TInfoSinkBase& operator<<(char c) {
+        sink.append(1, c);
+        return *this;
+    }
+    TInfoSinkBase& operator<<(const char* str) {
+        sink.append(str);
+        return *this;
+    }
+    TInfoSinkBase& operator<<(const TPersistString& str) {
+        sink.append(str);
+        return *this;
+    }
+    TInfoSinkBase& operator<<(const TString& str) {
+        sink.append(str.c_str());
+        return *this;
+    }
+    // Make sure floats are written with correct precision.
+    TInfoSinkBase& operator<<(float f) {
+        // Make sure that at least one decimal point is written. If a number
+        // does not have a fractional part, the default precision format does
+        // not write the decimal portion which gets interpreted as integer by
+        // the compiler.
+        TPersistStringStream stream;
+        if (fractionalPart(f) == 0.0f) {
+            stream.precision(1);
+            stream << std::showpoint << std::fixed << f;
+        } else {
+            stream.unsetf(std::ios::fixed);
+            stream.unsetf(std::ios::scientific);
+            stream.precision(8);
+            stream << f;
+        }
+        sink.append(stream.str());
+        return *this;
+    }
+    // Write boolean values as their names instead of integral value.
+    TInfoSinkBase& operator<<(bool b) {
+        const char* str = b ? "true" : "false";
+        sink.append(str);
+        return *this;
+    }
+
+    void erase() { sink.clear(); }
+    int size() { return static_cast<int>(sink.size()); }
+
+    const TPersistString& str() const { return sink; }
+    const char* c_str() const { return sink.c_str(); }
+
+    void prefix(TPrefixType message);
+    void location(TSourceLoc loc);
+    void message(TPrefixType message, const char* s);
+    void message(TPrefixType message, const char* s, TSourceLoc loc);
+
+private:
+    TPersistString sink;
+};
+
+class TInfoSink {
+public:
+    TInfoSinkBase info;
+    TInfoSinkBase debug;
+    TInfoSinkBase obj;
+};
+
+#endif // _INFOSINK_INCLUDED_
diff --git a/src/3rdparty/angle/src/compiler/Initialize.cpp b/src/3rdparty/angle/src/compiler/Initialize.cpp
new file mode 100644 (file)
index 0000000..3e94ce7
--- /dev/null
@@ -0,0 +1,657 @@
+//
+// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+//
+// Create strings that declare built-in definitions, add built-ins that
+// cannot be expressed in the files, and establish mappings between 
+// built-in functions and operators.
+//
+
+#include "compiler/Initialize.h"
+
+#include "compiler/intermediate.h"
+
+//============================================================================
+//
+// Prototypes for built-in functions seen by both vertex and fragment shaders.
+//
+//============================================================================
+static TString BuiltInFunctionsCommon(const ShBuiltInResources& resources)
+{
+    TString s;
+
+    //
+    // Angle and Trigonometric Functions.
+    //
+    s.append(TString("float radians(float degrees);"));
+    s.append(TString("vec2  radians(vec2  degrees);"));
+    s.append(TString("vec3  radians(vec3  degrees);"));
+    s.append(TString("vec4  radians(vec4  degrees);"));
+
+    s.append(TString("float degrees(float radians);"));
+    s.append(TString("vec2  degrees(vec2  radians);"));
+    s.append(TString("vec3  degrees(vec3  radians);"));
+    s.append(TString("vec4  degrees(vec4  radians);"));
+
+    s.append(TString("float sin(float angle);"));
+    s.append(TString("vec2  sin(vec2  angle);"));
+    s.append(TString("vec3  sin(vec3  angle);"));
+    s.append(TString("vec4  sin(vec4  angle);"));
+
+    s.append(TString("float cos(float angle);"));
+    s.append(TString("vec2  cos(vec2  angle);"));
+    s.append(TString("vec3  cos(vec3  angle);"));
+    s.append(TString("vec4  cos(vec4  angle);"));
+
+    s.append(TString("float tan(float angle);"));
+    s.append(TString("vec2  tan(vec2  angle);"));
+    s.append(TString("vec3  tan(vec3  angle);"));
+    s.append(TString("vec4  tan(vec4  angle);"));
+
+    s.append(TString("float asin(float x);"));
+    s.append(TString("vec2  asin(vec2  x);"));
+    s.append(TString("vec3  asin(vec3  x);"));
+    s.append(TString("vec4  asin(vec4  x);"));
+
+    s.append(TString("float acos(float x);"));
+    s.append(TString("vec2  acos(vec2  x);"));
+    s.append(TString("vec3  acos(vec3  x);"));
+    s.append(TString("vec4  acos(vec4  x);"));
+
+    s.append(TString("float atan(float y, float x);"));
+    s.append(TString("vec2  atan(vec2  y, vec2  x);"));
+    s.append(TString("vec3  atan(vec3  y, vec3  x);"));
+    s.append(TString("vec4  atan(vec4  y, vec4  x);"));
+
+    s.append(TString("float atan(float y_over_x);"));
+    s.append(TString("vec2  atan(vec2  y_over_x);"));
+    s.append(TString("vec3  atan(vec3  y_over_x);"));
+    s.append(TString("vec4  atan(vec4  y_over_x);"));
+
+    //
+    // Exponential Functions.
+    //
+    s.append(TString("float pow(float x, float y);"));
+    s.append(TString("vec2  pow(vec2  x, vec2  y);"));
+    s.append(TString("vec3  pow(vec3  x, vec3  y);"));
+    s.append(TString("vec4  pow(vec4  x, vec4  y);"));
+
+    s.append(TString("float exp(float x);"));
+    s.append(TString("vec2  exp(vec2  x);"));
+    s.append(TString("vec3  exp(vec3  x);"));
+    s.append(TString("vec4  exp(vec4  x);"));
+
+    s.append(TString("float log(float x);"));
+    s.append(TString("vec2  log(vec2  x);"));
+    s.append(TString("vec3  log(vec3  x);"));
+    s.append(TString("vec4  log(vec4  x);"));
+
+    s.append(TString("float exp2(float x);"));
+    s.append(TString("vec2  exp2(vec2  x);"));
+    s.append(TString("vec3  exp2(vec3  x);"));
+    s.append(TString("vec4  exp2(vec4  x);"));
+
+    s.append(TString("float log2(float x);"));
+    s.append(TString("vec2  log2(vec2  x);"));
+    s.append(TString("vec3  log2(vec3  x);"));
+    s.append(TString("vec4  log2(vec4  x);"));
+
+    s.append(TString("float sqrt(float x);"));
+    s.append(TString("vec2  sqrt(vec2  x);"));
+    s.append(TString("vec3  sqrt(vec3  x);"));
+    s.append(TString("vec4  sqrt(vec4  x);"));
+
+    s.append(TString("float inversesqrt(float x);"));
+    s.append(TString("vec2  inversesqrt(vec2  x);"));
+    s.append(TString("vec3  inversesqrt(vec3  x);"));
+    s.append(TString("vec4  inversesqrt(vec4  x);"));
+
+    //
+    // Common Functions.
+    //
+    s.append(TString("float abs(float x);"));
+    s.append(TString("vec2  abs(vec2  x);"));
+    s.append(TString("vec3  abs(vec3  x);"));
+    s.append(TString("vec4  abs(vec4  x);"));
+
+    s.append(TString("float sign(float x);"));
+    s.append(TString("vec2  sign(vec2  x);"));
+    s.append(TString("vec3  sign(vec3  x);"));
+    s.append(TString("vec4  sign(vec4  x);"));
+
+    s.append(TString("float floor(float x);"));
+    s.append(TString("vec2  floor(vec2  x);"));
+    s.append(TString("vec3  floor(vec3  x);"));
+    s.append(TString("vec4  floor(vec4  x);"));
+
+    s.append(TString("float ceil(float x);"));
+    s.append(TString("vec2  ceil(vec2  x);"));
+    s.append(TString("vec3  ceil(vec3  x);"));
+    s.append(TString("vec4  ceil(vec4  x);"));
+
+    s.append(TString("float fract(float x);"));
+    s.append(TString("vec2  fract(vec2  x);"));
+    s.append(TString("vec3  fract(vec3  x);"));
+    s.append(TString("vec4  fract(vec4  x);"));
+
+    s.append(TString("float mod(float x, float y);"));
+    s.append(TString("vec2  mod(vec2  x, float y);"));
+    s.append(TString("vec3  mod(vec3  x, float y);"));
+    s.append(TString("vec4  mod(vec4  x, float y);"));
+    s.append(TString("vec2  mod(vec2  x, vec2  y);"));
+    s.append(TString("vec3  mod(vec3  x, vec3  y);"));
+    s.append(TString("vec4  mod(vec4  x, vec4  y);"));
+
+    s.append(TString("float min(float x, float y);"));
+    s.append(TString("vec2  min(vec2  x, float y);"));
+    s.append(TString("vec3  min(vec3  x, float y);"));
+    s.append(TString("vec4  min(vec4  x, float y);"));
+    s.append(TString("vec2  min(vec2  x, vec2  y);"));
+    s.append(TString("vec3  min(vec3  x, vec3  y);"));
+    s.append(TString("vec4  min(vec4  x, vec4  y);"));
+
+    s.append(TString("float max(float x, float y);"));
+    s.append(TString("vec2  max(vec2  x, float y);"));
+    s.append(TString("vec3  max(vec3  x, float y);"));
+    s.append(TString("vec4  max(vec4  x, float y);"));
+    s.append(TString("vec2  max(vec2  x, vec2  y);"));
+    s.append(TString("vec3  max(vec3  x, vec3  y);"));
+    s.append(TString("vec4  max(vec4  x, vec4  y);"));
+
+    s.append(TString("float clamp(float x, float minVal, float maxVal);"));
+    s.append(TString("vec2  clamp(vec2  x, float minVal, float maxVal);"));
+    s.append(TString("vec3  clamp(vec3  x, float minVal, float maxVal);"));
+    s.append(TString("vec4  clamp(vec4  x, float minVal, float maxVal);"));
+    s.append(TString("vec2  clamp(vec2  x, vec2  minVal, vec2  maxVal);"));
+    s.append(TString("vec3  clamp(vec3  x, vec3  minVal, vec3  maxVal);"));
+    s.append(TString("vec4  clamp(vec4  x, vec4  minVal, vec4  maxVal);"));
+
+    s.append(TString("float mix(float x, float y, float a);"));
+    s.append(TString("vec2  mix(vec2  x, vec2  y, float a);"));
+    s.append(TString("vec3  mix(vec3  x, vec3  y, float a);"));
+    s.append(TString("vec4  mix(vec4  x, vec4  y, float a);"));
+    s.append(TString("vec2  mix(vec2  x, vec2  y, vec2  a);"));
+    s.append(TString("vec3  mix(vec3  x, vec3  y, vec3  a);"));
+    s.append(TString("vec4  mix(vec4  x, vec4  y, vec4  a);"));
+
+    s.append(TString("float step(float edge, float x);"));
+    s.append(TString("vec2  step(vec2  edge, vec2  x);"));
+    s.append(TString("vec3  step(vec3  edge, vec3  x);"));
+    s.append(TString("vec4  step(vec4  edge, vec4  x);"));
+    s.append(TString("vec2  step(float edge, vec2  x);"));
+    s.append(TString("vec3  step(float edge, vec3  x);"));
+    s.append(TString("vec4  step(float edge, vec4  x);"));
+
+    s.append(TString("float smoothstep(float edge0, float edge1, float x);"));
+    s.append(TString("vec2  smoothstep(vec2  edge0, vec2  edge1, vec2  x);"));
+    s.append(TString("vec3  smoothstep(vec3  edge0, vec3  edge1, vec3  x);"));
+    s.append(TString("vec4  smoothstep(vec4  edge0, vec4  edge1, vec4  x);"));
+    s.append(TString("vec2  smoothstep(float edge0, float edge1, vec2  x);"));
+    s.append(TString("vec3  smoothstep(float edge0, float edge1, vec3  x);"));
+    s.append(TString("vec4  smoothstep(float edge0, float edge1, vec4  x);"));
+
+    //
+    // Geometric Functions.
+    //
+    s.append(TString("float length(float x);"));
+    s.append(TString("float length(vec2  x);"));
+    s.append(TString("float length(vec3  x);"));
+    s.append(TString("float length(vec4  x);"));
+
+    s.append(TString("float distance(float p0, float p1);"));
+    s.append(TString("float distance(vec2  p0, vec2  p1);"));
+    s.append(TString("float distance(vec3  p0, vec3  p1);"));
+    s.append(TString("float distance(vec4  p0, vec4  p1);"));
+
+    s.append(TString("float dot(float x, float y);"));
+    s.append(TString("float dot(vec2  x, vec2  y);"));
+    s.append(TString("float dot(vec3  x, vec3  y);"));
+    s.append(TString("float dot(vec4  x, vec4  y);"));
+
+    s.append(TString("vec3 cross(vec3 x, vec3 y);"));
+    s.append(TString("float normalize(float x);"));
+    s.append(TString("vec2  normalize(vec2  x);"));
+    s.append(TString("vec3  normalize(vec3  x);"));
+    s.append(TString("vec4  normalize(vec4  x);"));
+
+    s.append(TString("float faceforward(float N, float I, float Nref);"));
+    s.append(TString("vec2  faceforward(vec2  N, vec2  I, vec2  Nref);"));
+    s.append(TString("vec3  faceforward(vec3  N, vec3  I, vec3  Nref);"));
+    s.append(TString("vec4  faceforward(vec4  N, vec4  I, vec4  Nref);"));
+
+    s.append(TString("float reflect(float I, float N);"));
+    s.append(TString("vec2  reflect(vec2  I, vec2  N);"));
+    s.append(TString("vec3  reflect(vec3  I, vec3  N);"));
+    s.append(TString("vec4  reflect(vec4  I, vec4  N);"));
+
+    s.append(TString("float refract(float I, float N, float eta);"));
+    s.append(TString("vec2  refract(vec2  I, vec2  N, float eta);"));
+    s.append(TString("vec3  refract(vec3  I, vec3  N, float eta);"));
+    s.append(TString("vec4  refract(vec4  I, vec4  N, float eta);"));
+
+    //
+    // Matrix Functions.
+    //
+    s.append(TString("mat2 matrixCompMult(mat2 x, mat2 y);"));
+    s.append(TString("mat3 matrixCompMult(mat3 x, mat3 y);"));
+    s.append(TString("mat4 matrixCompMult(mat4 x, mat4 y);"));
+
+    //
+    // Vector relational functions.
+    //
+    s.append(TString("bvec2 lessThan(vec2 x, vec2 y);"));
+    s.append(TString("bvec3 lessThan(vec3 x, vec3 y);"));
+    s.append(TString("bvec4 lessThan(vec4 x, vec4 y);"));
+
+    s.append(TString("bvec2 lessThan(ivec2 x, ivec2 y);"));
+    s.append(TString("bvec3 lessThan(ivec3 x, ivec3 y);"));
+    s.append(TString("bvec4 lessThan(ivec4 x, ivec4 y);"));
+
+    s.append(TString("bvec2 lessThanEqual(vec2 x, vec2 y);"));
+    s.append(TString("bvec3 lessThanEqual(vec3 x, vec3 y);"));
+    s.append(TString("bvec4 lessThanEqual(vec4 x, vec4 y);"));
+
+    s.append(TString("bvec2 lessThanEqual(ivec2 x, ivec2 y);"));
+    s.append(TString("bvec3 lessThanEqual(ivec3 x, ivec3 y);"));
+    s.append(TString("bvec4 lessThanEqual(ivec4 x, ivec4 y);"));
+
+    s.append(TString("bvec2 greaterThan(vec2 x, vec2 y);"));
+    s.append(TString("bvec3 greaterThan(vec3 x, vec3 y);"));
+    s.append(TString("bvec4 greaterThan(vec4 x, vec4 y);"));
+
+    s.append(TString("bvec2 greaterThan(ivec2 x, ivec2 y);"));
+    s.append(TString("bvec3 greaterThan(ivec3 x, ivec3 y);"));
+    s.append(TString("bvec4 greaterThan(ivec4 x, ivec4 y);"));
+
+    s.append(TString("bvec2 greaterThanEqual(vec2 x, vec2 y);"));
+    s.append(TString("bvec3 greaterThanEqual(vec3 x, vec3 y);"));
+    s.append(TString("bvec4 greaterThanEqual(vec4 x, vec4 y);"));
+
+    s.append(TString("bvec2 greaterThanEqual(ivec2 x, ivec2 y);"));
+    s.append(TString("bvec3 greaterThanEqual(ivec3 x, ivec3 y);"));
+    s.append(TString("bvec4 greaterThanEqual(ivec4 x, ivec4 y);"));
+
+    s.append(TString("bvec2 equal(vec2 x, vec2 y);"));
+    s.append(TString("bvec3 equal(vec3 x, vec3 y);"));
+    s.append(TString("bvec4 equal(vec4 x, vec4 y);"));
+
+    s.append(TString("bvec2 equal(ivec2 x, ivec2 y);"));
+    s.append(TString("bvec3 equal(ivec3 x, ivec3 y);"));
+    s.append(TString("bvec4 equal(ivec4 x, ivec4 y);"));
+
+    s.append(TString("bvec2 equal(bvec2 x, bvec2 y);"));
+    s.append(TString("bvec3 equal(bvec3 x, bvec3 y);"));
+    s.append(TString("bvec4 equal(bvec4 x, bvec4 y);"));
+
+    s.append(TString("bvec2 notEqual(vec2 x, vec2 y);"));
+    s.append(TString("bvec3 notEqual(vec3 x, vec3 y);"));
+    s.append(TString("bvec4 notEqual(vec4 x, vec4 y);"));
+
+    s.append(TString("bvec2 notEqual(ivec2 x, ivec2 y);"));
+    s.append(TString("bvec3 notEqual(ivec3 x, ivec3 y);"));
+    s.append(TString("bvec4 notEqual(ivec4 x, ivec4 y);"));
+
+    s.append(TString("bvec2 notEqual(bvec2 x, bvec2 y);"));
+    s.append(TString("bvec3 notEqual(bvec3 x, bvec3 y);"));
+    s.append(TString("bvec4 notEqual(bvec4 x, bvec4 y);"));
+
+    s.append(TString("bool any(bvec2 x);"));
+    s.append(TString("bool any(bvec3 x);"));
+    s.append(TString("bool any(bvec4 x);"));
+
+    s.append(TString("bool all(bvec2 x);"));
+    s.append(TString("bool all(bvec3 x);"));
+    s.append(TString("bool all(bvec4 x);"));
+
+    s.append(TString("bvec2 not(bvec2 x);"));
+    s.append(TString("bvec3 not(bvec3 x);"));
+    s.append(TString("bvec4 not(bvec4 x);"));
+
+    //
+    // Texture Functions.
+    //
+    s.append(TString("vec4 texture2D(sampler2D sampler, vec2 coord);"));
+    s.append(TString("vec4 texture2DProj(sampler2D sampler, vec3 coord);"));
+    s.append(TString("vec4 texture2DProj(sampler2D sampler, vec4 coord);"));
+    s.append(TString("vec4 textureCube(samplerCube sampler, vec3 coord);"));
+
+    if (resources.OES_EGL_image_external) {
+        s.append(TString("vec4 texture2D(samplerExternalOES sampler, vec2 coord);"));
+        s.append(TString("vec4 texture2DProj(samplerExternalOES sampler, vec3 coord);"));
+        s.append(TString("vec4 texture2DProj(samplerExternalOES sampler, vec4 coord);"));
+    }
+
+    if (resources.ARB_texture_rectangle) {
+        s.append(TString("vec4 texture2DRect(sampler2DRect sampler, vec2 coord);"));
+        s.append(TString("vec4 texture2DRectProj(sampler2DRect sampler, vec3 coord);"));
+        s.append(TString("vec4 texture2DRectProj(sampler2DRect sampler, vec4 coord);"));
+    }
+
+    //
+    // Noise functions.
+    //
+    //s.append(TString("float noise1(float x);"));
+    //s.append(TString("float noise1(vec2  x);"));
+    //s.append(TString("float noise1(vec3  x);"));
+    //s.append(TString("float noise1(vec4  x);"));
+
+    //s.append(TString("vec2 noise2(float x);"));
+    //s.append(TString("vec2 noise2(vec2  x);"));
+    //s.append(TString("vec2 noise2(vec3  x);"));
+    //s.append(TString("vec2 noise2(vec4  x);"));
+
+    //s.append(TString("vec3 noise3(float x);"));
+    //s.append(TString("vec3 noise3(vec2  x);"));
+    //s.append(TString("vec3 noise3(vec3  x);"));
+    //s.append(TString("vec3 noise3(vec4  x);"));
+
+    //s.append(TString("vec4 noise4(float x);"));
+    //s.append(TString("vec4 noise4(vec2  x);"));
+    //s.append(TString("vec4 noise4(vec3  x);"));
+    //s.append(TString("vec4 noise4(vec4  x);"));
+
+    return s;
+}
+
+//============================================================================
+//
+// Prototypes for built-in functions seen by vertex shaders only.
+//
+//============================================================================
+static TString BuiltInFunctionsVertex(const ShBuiltInResources& resources)
+{
+    TString s;
+
+    //
+    // Geometric Functions.
+    //
+    //s.append(TString("vec4 ftransform();"));
+
+    //
+    // Texture Functions.
+    //
+    s.append(TString("vec4 texture2DLod(sampler2D sampler, vec2 coord, float lod);"));
+    s.append(TString("vec4 texture2DProjLod(sampler2D sampler, vec3 coord, float lod);"));
+    s.append(TString("vec4 texture2DProjLod(sampler2D sampler, vec4 coord, float lod);"));
+    s.append(TString("vec4 textureCubeLod(samplerCube sampler, vec3 coord, float lod);"));
+
+    return s;
+}
+
+//============================================================================
+//
+// Prototypes for built-in functions seen by fragment shaders only.
+//
+//============================================================================
+static TString BuiltInFunctionsFragment(const ShBuiltInResources& resources)
+{
+    TString s;
+
+    //
+    // Texture Functions.
+    //
+    s.append(TString("vec4 texture2D(sampler2D sampler, vec2 coord, float bias);"));
+    s.append(TString("vec4 texture2DProj(sampler2D sampler, vec3 coord, float bias);"));
+    s.append(TString("vec4 texture2DProj(sampler2D sampler, vec4 coord, float bias);"));
+    s.append(TString("vec4 textureCube(samplerCube sampler, vec3 coord, float bias);"));
+
+    if (resources.OES_standard_derivatives) {
+        s.append(TString("float dFdx(float p);"));
+        s.append(TString("vec2  dFdx(vec2  p);"));
+        s.append(TString("vec3  dFdx(vec3  p);"));
+        s.append(TString("vec4  dFdx(vec4  p);"));
+
+        s.append(TString("float dFdy(float p);"));
+        s.append(TString("vec2  dFdy(vec2  p);"));
+        s.append(TString("vec3  dFdy(vec3  p);"));
+        s.append(TString("vec4  dFdy(vec4  p);"));
+
+        s.append(TString("float fwidth(float p);"));
+        s.append(TString("vec2  fwidth(vec2  p);"));
+        s.append(TString("vec3  fwidth(vec3  p);"));
+        s.append(TString("vec4  fwidth(vec4  p);"));
+    }
+
+    return s;
+}
+
+//============================================================================
+//
+// Standard uniforms.
+//
+//============================================================================
+static TString StandardUniforms()
+{
+    TString s;
+
+    //
+    // Depth range in window coordinates
+    //
+    s.append(TString("struct gl_DepthRangeParameters {"));
+    s.append(TString("    highp float near;"));        // n
+    s.append(TString("    highp float far;"));         // f
+    s.append(TString("    highp float diff;"));        // f - n
+    s.append(TString("};"));
+    s.append(TString("uniform gl_DepthRangeParameters gl_DepthRange;"));
+
+    return s;
+}
+
+//============================================================================
+//
+// Default precision for vertex shaders.
+//
+//============================================================================
+static TString DefaultPrecisionVertex()
+{
+    TString s;
+
+    s.append(TString("precision highp int;"));
+    s.append(TString("precision highp float;"));
+
+    return s;
+}
+
+//============================================================================
+//
+// Default precision for fragment shaders.
+//
+//============================================================================
+static TString DefaultPrecisionFragment()
+{
+    TString s;
+
+    s.append(TString("precision mediump int;"));
+    // No default precision for float in fragment shaders
+
+    return s;
+}
+
+//============================================================================
+//
+// Implementation dependent built-in constants.
+//
+//============================================================================
+static TString BuiltInConstants(ShShaderSpec spec, const ShBuiltInResources &resources)
+{
+    TStringStream s;
+
+    s << "const int gl_MaxVertexAttribs = " << resources.MaxVertexAttribs << ";";
+    s << "const int gl_MaxVertexUniformVectors = " << resources.MaxVertexUniformVectors << ";";
+
+    s << "const int gl_MaxVaryingVectors = " << resources.MaxVaryingVectors << ";";
+    s << "const int gl_MaxVertexTextureImageUnits = " << resources.MaxVertexTextureImageUnits << ";";
+    s << "const int gl_MaxCombinedTextureImageUnits = " << resources.MaxCombinedTextureImageUnits << ";";
+    s << "const int gl_MaxTextureImageUnits = " << resources.MaxTextureImageUnits << ";";
+    s << "const int gl_MaxFragmentUniformVectors = " << resources.MaxFragmentUniformVectors << ";";
+
+    if (spec != SH_CSS_SHADERS_SPEC)
+        s << "const int gl_MaxDrawBuffers = " << resources.MaxDrawBuffers << ";";
+
+    return s.str();
+}
+
+void TBuiltIns::initialize(ShShaderType type, ShShaderSpec spec,
+                           const ShBuiltInResources& resources)
+{
+    switch (type) {
+    case SH_FRAGMENT_SHADER:
+        builtInStrings.push_back(DefaultPrecisionFragment());
+        builtInStrings.push_back(BuiltInFunctionsCommon(resources));
+        builtInStrings.push_back(BuiltInFunctionsFragment(resources));
+        builtInStrings.push_back(StandardUniforms());
+        break;
+
+    case SH_VERTEX_SHADER:
+        builtInStrings.push_back(DefaultPrecisionVertex());
+        builtInStrings.push_back(BuiltInFunctionsCommon(resources));
+        builtInStrings.push_back(BuiltInFunctionsVertex(resources));
+        builtInStrings.push_back(StandardUniforms());
+        break;
+
+    default: assert(false && "Language not supported");
+    }
+
+    builtInStrings.push_back(BuiltInConstants(spec, resources));
+}
+
+void IdentifyBuiltIns(ShShaderType type, ShShaderSpec spec,
+                      const ShBuiltInResources& resources,
+                      TSymbolTable& symbolTable)
+{
+    //
+    // First, insert some special built-in variables that are not in 
+    // the built-in header files.
+    //
+    switch(type) {
+    case SH_FRAGMENT_SHADER:
+        symbolTable.insert(*new TVariable(NewPoolTString("gl_FragCoord"),                       TType(EbtFloat, EbpMedium, EvqFragCoord,   4)));
+        symbolTable.insert(*new TVariable(NewPoolTString("gl_FrontFacing"),                     TType(EbtBool,  EbpUndefined, EvqFrontFacing, 1)));
+        symbolTable.insert(*new TVariable(NewPoolTString("gl_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)));
+        } 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("not",              EOpVectorLogicalNot);
+
+    symbolTable.relateToOperator("matrixCompMult",   EOpMul);
+
+    symbolTable.relateToOperator("equal",            EOpVectorEqual);
+    symbolTable.relateToOperator("notEqual",         EOpVectorNotEqual);
+    symbolTable.relateToOperator("lessThan",         EOpLessThan);
+    symbolTable.relateToOperator("greaterThan",      EOpGreaterThan);
+    symbolTable.relateToOperator("lessThanEqual",    EOpLessThanEqual);
+    symbolTable.relateToOperator("greaterThanEqual", EOpGreaterThanEqual);
+    
+    symbolTable.relateToOperator("radians",      EOpRadians);
+    symbolTable.relateToOperator("degrees",      EOpDegrees);
+    symbolTable.relateToOperator("sin",          EOpSin);
+    symbolTable.relateToOperator("cos",          EOpCos);
+    symbolTable.relateToOperator("tan",          EOpTan);
+    symbolTable.relateToOperator("asin",         EOpAsin);
+    symbolTable.relateToOperator("acos",         EOpAcos);
+    symbolTable.relateToOperator("atan",         EOpAtan);
+
+    symbolTable.relateToOperator("pow",          EOpPow);
+    symbolTable.relateToOperator("exp2",         EOpExp2);
+    symbolTable.relateToOperator("log",          EOpLog);
+    symbolTable.relateToOperator("exp",          EOpExp);
+    symbolTable.relateToOperator("log2",         EOpLog2);
+    symbolTable.relateToOperator("sqrt",         EOpSqrt);
+    symbolTable.relateToOperator("inversesqrt",  EOpInverseSqrt);
+
+    symbolTable.relateToOperator("abs",          EOpAbs);
+    symbolTable.relateToOperator("sign",         EOpSign);
+    symbolTable.relateToOperator("floor",        EOpFloor);
+    symbolTable.relateToOperator("ceil",         EOpCeil);
+    symbolTable.relateToOperator("fract",        EOpFract);
+    symbolTable.relateToOperator("mod",          EOpMod);
+    symbolTable.relateToOperator("min",          EOpMin);
+    symbolTable.relateToOperator("max",          EOpMax);
+    symbolTable.relateToOperator("clamp",        EOpClamp);
+    symbolTable.relateToOperator("mix",          EOpMix);
+    symbolTable.relateToOperator("step",         EOpStep);
+    symbolTable.relateToOperator("smoothstep",   EOpSmoothStep);
+
+    symbolTable.relateToOperator("length",       EOpLength);
+    symbolTable.relateToOperator("distance",     EOpDistance);
+    symbolTable.relateToOperator("dot",          EOpDot);
+    symbolTable.relateToOperator("cross",        EOpCross);
+    symbolTable.relateToOperator("normalize",    EOpNormalize);
+    symbolTable.relateToOperator("faceforward",  EOpFaceForward);
+    symbolTable.relateToOperator("reflect",      EOpReflect);
+    symbolTable.relateToOperator("refract",      EOpRefract);
+    
+    symbolTable.relateToOperator("any",          EOpAny);
+    symbolTable.relateToOperator("all",          EOpAll);
+
+    // Map language-specific operators.
+    switch(type) {
+    case SH_VERTEX_SHADER:
+        break;
+    case SH_FRAGMENT_SHADER:
+        if (resources.OES_standard_derivatives) {
+            symbolTable.relateToOperator("dFdx",   EOpDFdx);
+            symbolTable.relateToOperator("dFdy",   EOpDFdy);
+            symbolTable.relateToOperator("fwidth", EOpFwidth);
+
+            symbolTable.relateToExtension("dFdx", "GL_OES_standard_derivatives");
+            symbolTable.relateToExtension("dFdy", "GL_OES_standard_derivatives");
+            symbolTable.relateToExtension("fwidth", "GL_OES_standard_derivatives");
+        }
+        break;
+    default: break;
+    }
+
+    // Finally add resource-specific variables.
+    switch(type) {
+    case SH_FRAGMENT_SHADER:
+        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;
+}
diff --git a/src/3rdparty/angle/src/compiler/Initialize.h b/src/3rdparty/angle/src/compiler/Initialize.h
new file mode 100644 (file)
index 0000000..8b0adc6
--- /dev/null
@@ -0,0 +1,35 @@
+//
+// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#ifndef _INITIALIZE_INCLUDED_
+#define _INITIALIZE_INCLUDED_
+
+#include "compiler/Common.h"
+#include "compiler/ShHandle.h"
+#include "compiler/SymbolTable.h"
+
+typedef TVector<TString> TBuiltInStrings;
+
+class TBuiltIns {
+public:
+    POOL_ALLOCATOR_NEW_DELETE(GlobalPoolAllocator)
+
+    void initialize(ShShaderType type, ShShaderSpec spec,
+                    const ShBuiltInResources& resources);
+    const TBuiltInStrings& getBuiltInStrings() { return builtInStrings; }
+
+protected:
+    TBuiltInStrings builtInStrings;
+};
+
+void IdentifyBuiltIns(ShShaderType type, ShShaderSpec spec,
+                      const ShBuiltInResources& resources,
+                      TSymbolTable& symbolTable);
+
+void InitExtensionBehavior(const ShBuiltInResources& resources,
+                           TExtensionBehavior& extensionBehavior);
+
+#endif // _INITIALIZE_INCLUDED_
diff --git a/src/3rdparty/angle/src/compiler/InitializeDll.cpp b/src/3rdparty/angle/src/compiler/InitializeDll.cpp
new file mode 100644 (file)
index 0000000..8763cfe
--- /dev/null
@@ -0,0 +1,115 @@
+//
+// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "compiler/InitializeDll.h"
+
+#include "compiler/InitializeGlobals.h"
+#include "compiler/InitializeParseContext.h"
+#include "compiler/osinclude.h"
+
+OS_TLSIndex ThreadInitializeIndex = OS_INVALID_TLS_INDEX;
+
+bool InitProcess()
+{
+    if (ThreadInitializeIndex != OS_INVALID_TLS_INDEX) {
+        //
+        // Function is re-entrant.
+        //
+        return true;
+    }
+
+    ThreadInitializeIndex = OS_AllocTLSIndex();
+
+    if (ThreadInitializeIndex == OS_INVALID_TLS_INDEX) {
+        assert(0 && "InitProcess(): Failed to allocate TLS area for init flag");
+        return false;
+    }
+
+
+    if (!InitializePoolIndex()) {
+        assert(0 && "InitProcess(): Failed to initalize global pool");
+        return false;
+    }
+
+    if (!InitializeParseContextIndex()) {
+        assert(0 && "InitProcess(): Failed to initalize parse context");
+        return false;
+    }
+
+    return InitThread();
+}
+
+bool DetachProcess()
+{
+    bool success = true;
+
+    if (ThreadInitializeIndex == OS_INVALID_TLS_INDEX)
+        return true;
+
+    success = DetachThread();
+
+    if (!FreeParseContextIndex())
+        success = false;
+
+    FreePoolIndex();
+
+    OS_FreeTLSIndex(ThreadInitializeIndex);
+    ThreadInitializeIndex = OS_INVALID_TLS_INDEX;
+
+    return success;
+}
+
+bool InitThread()
+{
+    //
+    // This function is re-entrant
+    //
+    if (ThreadInitializeIndex == OS_INVALID_TLS_INDEX) {
+        assert(0 && "InitThread(): Process hasn't been initalised.");
+        return false;
+    }
+
+    if (OS_GetTLSValue(ThreadInitializeIndex) != 0)
+        return true;
+
+    InitializeGlobalPools();
+
+    if (!InitializeGlobalParseContext())
+        return false;
+
+    if (!OS_SetTLSValue(ThreadInitializeIndex, (void *)1)) {
+        assert(0 && "InitThread(): Unable to set init flag.");
+        return false;
+    }
+
+    return true;
+}
+
+bool DetachThread()
+{
+    bool success = true;
+
+    if (ThreadInitializeIndex == OS_INVALID_TLS_INDEX)
+        return true;
+
+    //
+    // Function is re-entrant and this thread may not have been initalised.
+    //
+    if (OS_GetTLSValue(ThreadInitializeIndex) != 0) {
+        if (!OS_SetTLSValue(ThreadInitializeIndex, (void *)0)) {
+            assert(0 && "DetachThread(): Unable to clear init flag.");
+            success = false;
+        }
+
+        if (!FreeParseContext())
+            success = false;
+
+        FreeGlobalPools();
+    }
+
+    return success;
+}
+
diff --git a/src/3rdparty/angle/src/compiler/InitializeDll.h b/src/3rdparty/angle/src/compiler/InitializeDll.h
new file mode 100644 (file)
index 0000000..857238e
--- /dev/null
@@ -0,0 +1,16 @@
+//
+// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+#ifndef __INITIALIZEDLL_H
+#define __INITIALIZEDLL_H
+
+bool InitProcess();
+bool DetachProcess();
+
+bool InitThread();
+bool DetachThread();
+
+#endif // __INITIALIZEDLL_H
+
diff --git a/src/3rdparty/angle/src/compiler/InitializeGlobals.h b/src/3rdparty/angle/src/compiler/InitializeGlobals.h
new file mode 100644 (file)
index 0000000..842a452
--- /dev/null
@@ -0,0 +1,15 @@
+//
+// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#ifndef __INITIALIZE_GLOBALS_INCLUDED_
+#define __INITIALIZE_GLOBALS_INCLUDED_
+
+void InitializeGlobalPools();
+void FreeGlobalPools();
+bool InitializePoolIndex();
+void FreePoolIndex();
+
+#endif // __INITIALIZE_GLOBALS_INCLUDED_
diff --git a/src/3rdparty/angle/src/compiler/InitializeParseContext.cpp b/src/3rdparty/angle/src/compiler/InitializeParseContext.cpp
new file mode 100644 (file)
index 0000000..1f40cf5
--- /dev/null
@@ -0,0 +1,96 @@
+//
+// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "compiler/InitializeParseContext.h"
+
+#include "compiler/osinclude.h"
+
+OS_TLSIndex GlobalParseContextIndex = OS_INVALID_TLS_INDEX;
+
+bool InitializeParseContextIndex()
+{
+    if (GlobalParseContextIndex != OS_INVALID_TLS_INDEX) {
+        assert(0 && "InitializeParseContextIndex(): Parse Context already initalized");
+        return false;
+    }
+
+    //
+    // Allocate a TLS index.
+    //
+    GlobalParseContextIndex = OS_AllocTLSIndex();
+    
+    if (GlobalParseContextIndex == OS_INVALID_TLS_INDEX) {
+        assert(0 && "InitializeParseContextIndex(): Parse Context already initalized");
+        return false;
+    }
+
+    return true;
+}
+
+bool FreeParseContextIndex()
+{
+    OS_TLSIndex tlsiIndex = GlobalParseContextIndex;
+
+    if (GlobalParseContextIndex == OS_INVALID_TLS_INDEX) {
+        assert(0 && "FreeParseContextIndex(): Parse Context index not initalized");
+        return false;
+    }
+
+    GlobalParseContextIndex = OS_INVALID_TLS_INDEX;
+
+    return OS_FreeTLSIndex(tlsiIndex);
+}
+
+bool InitializeGlobalParseContext()
+{
+    if (GlobalParseContextIndex == OS_INVALID_TLS_INDEX) {
+        assert(0 && "InitializeGlobalParseContext(): Parse Context index not initalized");
+        return false;
+    }
+
+    TThreadParseContext *lpParseContext = static_cast<TThreadParseContext *>(OS_GetTLSValue(GlobalParseContextIndex));
+    if (lpParseContext != 0) {
+        assert(0 && "InitializeParseContextIndex(): Parse Context already initalized");
+        return false;
+    }
+
+    TThreadParseContext *lpThreadData = new TThreadParseContext();
+    if (lpThreadData == 0) {
+        assert(0 && "InitializeGlobalParseContext(): Unable to create thread parse context");
+        return false;
+    }
+
+    lpThreadData->lpGlobalParseContext = 0;
+    OS_SetTLSValue(GlobalParseContextIndex, lpThreadData);
+
+    return true;
+}
+
+bool FreeParseContext()
+{
+    if (GlobalParseContextIndex == OS_INVALID_TLS_INDEX) {
+        assert(0 && "FreeParseContext(): Parse Context index not initalized");
+        return false;
+    }
+
+    TThreadParseContext *lpParseContext = static_cast<TThreadParseContext *>(OS_GetTLSValue(GlobalParseContextIndex));
+    if (lpParseContext)
+        delete lpParseContext;
+
+    return true;
+}
+
+TParseContextPointer& GetGlobalParseContext()
+{
+    //
+    // Minimal error checking for speed
+    //
+
+    TThreadParseContext *lpParseContext = static_cast<TThreadParseContext *>(OS_GetTLSValue(GlobalParseContextIndex));
+
+    return lpParseContext->lpGlobalParseContext;
+}
+
diff --git a/src/3rdparty/angle/src/compiler/InitializeParseContext.h b/src/3rdparty/angle/src/compiler/InitializeParseContext.h
new file mode 100644 (file)
index 0000000..aa53b73
--- /dev/null
@@ -0,0 +1,26 @@
+//
+// 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();
+bool FreeParseContextIndex();
+
+bool InitializeGlobalParseContext();
+bool FreeParseContext();
+
+struct TParseContext;
+typedef TParseContext* TParseContextPointer;
+extern TParseContextPointer& GetGlobalParseContext();
+#define GlobalParseContext GetGlobalParseContext()
+
+typedef struct TThreadParseContextRec
+{
+    TParseContext *lpGlobalParseContext;
+} TThreadParseContext;
+
+#endif // __INITIALIZE_PARSE_CONTEXT_INCLUDED_
diff --git a/src/3rdparty/angle/src/compiler/IntermTraverse.cpp b/src/3rdparty/angle/src/compiler/IntermTraverse.cpp
new file mode 100644 (file)
index 0000000..a13877f
--- /dev/null
@@ -0,0 +1,293 @@
+//
+// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "compiler/intermediate.h"
+
+//
+// Traverse the intermediate representation tree, and
+// call a node type specific function for each node.
+// Done recursively through the member function Traverse().
+// Node types can be skipped if their function to call is 0,
+// but their subtree will still be traversed.
+// Nodes with children can have their whole subtree skipped
+// if preVisit is turned on and the type specific function
+// returns false.
+//
+// preVisit, postVisit, and rightToLeft control what order
+// nodes are visited in.
+//
+
+//
+// Traversal functions for terminals are straighforward....
+//
+void TIntermSymbol::traverse(TIntermTraverser* it)
+{
+       it->visitSymbol(this);
+}
+
+void TIntermConstantUnion::traverse(TIntermTraverser* it)
+{
+       it->visitConstantUnion(this);
+}
+
+//
+// Traverse a binary node.
+//
+void TIntermBinary::traverse(TIntermTraverser* it)
+{
+       bool visit = true;
+
+       //
+       // visit the node before children if pre-visiting.
+       //
+       if(it->preVisit)
+       {
+               visit = it->visitBinary(PreVisit, this);
+       }
+       
+       //
+       // Visit the children, in the right order.
+       //
+       if(visit)
+       {
+               it->incrementDepth();
+
+               if(it->rightToLeft) 
+               {
+                       if(right)
+                       {
+                               right->traverse(it);
+                       }
+                       
+                       if(it->inVisit)
+                       {
+                               visit = it->visitBinary(InVisit, this);
+                       }
+
+                       if(visit && left)
+                       {
+                               left->traverse(it);
+                       }
+               }
+               else
+               {
+                       if(left)
+                       {
+                               left->traverse(it);
+                       }
+                       
+                       if(it->inVisit)
+                       {
+                               visit = it->visitBinary(InVisit, this);
+                       }
+
+                       if(visit && right)
+                       {
+                               right->traverse(it);
+                       }
+               }
+
+               it->decrementDepth();
+       }
+
+       //
+       // Visit the node after the children, if requested and the traversal
+       // hasn't been cancelled yet.
+       //
+       if(visit && it->postVisit)
+       {
+               it->visitBinary(PostVisit, this);
+       }
+}
+
+//
+// Traverse a unary node.  Same comments in binary node apply here.
+//
+void TIntermUnary::traverse(TIntermTraverser* it)
+{
+       bool visit = true;
+
+       if (it->preVisit)
+               visit = it->visitUnary(PreVisit, this);
+
+       if (visit) {
+               it->incrementDepth();
+               operand->traverse(it);
+               it->decrementDepth();
+       }
+       
+       if (visit && it->postVisit)
+               it->visitUnary(PostVisit, this);
+}
+
+//
+// Traverse an aggregate node.  Same comments in binary node apply here.
+//
+void TIntermAggregate::traverse(TIntermTraverser* it)
+{
+       bool visit = true;
+       
+       if(it->preVisit)
+       {
+               visit = it->visitAggregate(PreVisit, this);
+       }
+       
+       if(visit)
+       {
+               it->incrementDepth();
+
+               if(it->rightToLeft)
+               {
+                       for(TIntermSequence::reverse_iterator sit = sequence.rbegin(); sit != sequence.rend(); sit++)
+                       {
+                               (*sit)->traverse(it);
+
+                               if(visit && it->inVisit)
+                               {
+                                       if(*sit != sequence.front())
+                                       {
+                                               visit = it->visitAggregate(InVisit, this);
+                                       }
+                               }
+                       }
+               }
+               else
+               {
+                       for(TIntermSequence::iterator sit = sequence.begin(); sit != sequence.end(); sit++)
+                       {
+                               (*sit)->traverse(it);
+
+                               if(visit && it->inVisit)
+                               {
+                                       if(*sit != sequence.back())
+                                       {
+                                               visit = it->visitAggregate(InVisit, this);
+                                       }
+                               }
+                       }
+               }
+               
+               it->decrementDepth();
+       }
+
+       if(visit && it->postVisit)
+       {
+               it->visitAggregate(PostVisit, this);
+       }
+}
+
+//
+// Traverse a selection node.  Same comments in binary node apply here.
+//
+void TIntermSelection::traverse(TIntermTraverser* it)
+{
+       bool visit = true;
+
+       if (it->preVisit)
+               visit = it->visitSelection(PreVisit, this);
+       
+       if (visit) {
+               it->incrementDepth();
+               if (it->rightToLeft) {
+                       if (falseBlock)
+                               falseBlock->traverse(it);
+                       if (trueBlock)
+                               trueBlock->traverse(it);
+                       condition->traverse(it);
+               } else {
+                       condition->traverse(it);
+                       if (trueBlock)
+                               trueBlock->traverse(it);
+                       if (falseBlock)
+                               falseBlock->traverse(it);
+               }
+               it->decrementDepth();
+       }
+
+       if (visit && it->postVisit)
+               it->visitSelection(PostVisit, this);
+}
+
+//
+// Traverse a loop node.  Same comments in binary node apply here.
+//
+void TIntermLoop::traverse(TIntermTraverser* it)
+{
+       bool visit = true;
+
+       if(it->preVisit)
+       {
+               visit = it->visitLoop(PreVisit, this);
+       }
+       
+       if(visit)
+       {
+               it->incrementDepth();
+
+               if(it->rightToLeft)
+               {
+                       if(expr)
+                       {
+                               expr->traverse(it);
+                       }
+
+                       if(body)
+                       {
+                               body->traverse(it);
+                       }
+
+                       if(cond)
+                       {
+                               cond->traverse(it);
+                       }
+               }
+               else
+               {
+                       if(cond)
+                       {
+                               cond->traverse(it);
+                       }
+
+                       if(body)
+                       {
+                               body->traverse(it);
+                       }
+
+                       if(expr)
+                       {
+                               expr->traverse(it);
+                       }
+               }
+
+               it->decrementDepth();
+       }
+
+       if(visit && it->postVisit)
+       {
+               it->visitLoop(PostVisit, this);
+       }
+}
+
+//
+// Traverse a branch node.  Same comments in binary node apply here.
+//
+void TIntermBranch::traverse(TIntermTraverser* it)
+{
+       bool visit = true;
+
+       if (it->preVisit)
+               visit = it->visitBranch(PreVisit, this);
+       
+       if (visit && expression) {
+               it->incrementDepth();
+               expression->traverse(it);
+               it->decrementDepth();
+       }
+
+       if (visit && it->postVisit)
+               it->visitBranch(PostVisit, this);
+}
+
diff --git a/src/3rdparty/angle/src/compiler/Intermediate.cpp b/src/3rdparty/angle/src/compiler/Intermediate.cpp
new file mode 100644 (file)
index 0000000..92c4505
--- /dev/null
@@ -0,0 +1,1447 @@
+//
+// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+//
+// Build the intermediate representation.
+//
+
+#include <float.h>
+#include <limits.h>
+#include <algorithm>
+
+#include "compiler/localintermediate.h"
+#include "compiler/QualifierAlive.h"
+#include "compiler/RemoveTree.h"
+
+bool CompareStructure(const TType& leftNodeType, ConstantUnion* rightUnionArray, ConstantUnion* leftUnionArray);
+
+static TPrecision GetHigherPrecision( TPrecision left, TPrecision right ){
+    return left > right ? left : right;
+}
+
+const char* getOperatorString(TOperator op) {
+    switch (op) {
+      case EOpInitialize: return "=";
+      case EOpAssign: return "=";
+      case EOpAddAssign: return "+=";
+      case EOpSubAssign: return "-=";
+      case EOpDivAssign: return "/=";
+
+      // Fall-through.
+      case EOpMulAssign: 
+      case EOpVectorTimesMatrixAssign:
+      case EOpVectorTimesScalarAssign:
+      case EOpMatrixTimesScalarAssign:
+      case EOpMatrixTimesMatrixAssign: return "*=";
+
+      // Fall-through.
+      case EOpIndexDirect:
+      case EOpIndexIndirect: return "[]";
+
+      case EOpIndexDirectStruct: return ".";
+      case EOpVectorSwizzle: return ".";
+      case EOpAdd: return "+";
+      case EOpSub: return "-";
+      case EOpMul: return "*";
+      case EOpDiv: return "/";
+      case EOpMod: UNIMPLEMENTED(); break;
+      case EOpEqual: return "==";
+      case EOpNotEqual: return "!=";
+      case EOpLessThan: return "<";
+      case EOpGreaterThan: return ">";
+      case EOpLessThanEqual: return "<=";
+      case EOpGreaterThanEqual: return ">=";
+
+      // Fall-through.
+      case EOpVectorTimesScalar:
+      case EOpVectorTimesMatrix:
+      case EOpMatrixTimesVector:
+      case EOpMatrixTimesScalar:
+      case EOpMatrixTimesMatrix: return "*";
+
+      case EOpLogicalOr: return "||";
+      case EOpLogicalXor: return "^^";
+      case EOpLogicalAnd: return "&&";
+      case EOpNegative: return "-";
+      case EOpVectorLogicalNot: return "not";
+      case EOpLogicalNot: return "!";
+      case EOpPostIncrement: return "++";
+      case EOpPostDecrement: return "--";
+      case EOpPreIncrement: return "++";
+      case EOpPreDecrement: return "--";
+
+      // Fall-through.
+      case EOpConvIntToBool:
+      case EOpConvFloatToBool: return "bool";
+      // Fall-through.
+      case EOpConvBoolToFloat:
+      case EOpConvIntToFloat: return "float";
+      // Fall-through.
+      case EOpConvFloatToInt:
+      case EOpConvBoolToInt: return "int";
+
+      case EOpRadians: return "radians";
+      case EOpDegrees: return "degrees";
+      case EOpSin: return "sin";
+      case EOpCos: return "cos";
+      case EOpTan: return "tan";
+      case EOpAsin: return "asin";
+      case EOpAcos: return "acos";
+      case EOpAtan: return "atan";
+      case EOpExp: return "exp";
+      case EOpLog: return "log";
+      case EOpExp2: return "exp2";
+      case EOpLog2: return "log2";
+      case EOpSqrt: return "sqrt";
+      case EOpInverseSqrt: return "inversesqrt";
+      case EOpAbs: return "abs";
+      case EOpSign: return "sign";
+      case EOpFloor: return "floor";
+      case EOpCeil: return "ceil";
+      case EOpFract: return "fract";
+      case EOpLength: return "length";
+      case EOpNormalize: return "normalize";
+      case EOpDFdx: return "dFdx";
+      case EOpDFdy: return "dFdy";
+      case EOpFwidth: return "fwidth";
+      case EOpAny: return "any";
+      case EOpAll: return "all";
+
+      default: break;
+    }
+    return "";
+}
+
+////////////////////////////////////////////////////////////////////////////
+//
+// First set of functions are to help build the intermediate representation.
+// These functions are not member functions of the nodes.
+// They are called from parser productions.
+//
+/////////////////////////////////////////////////////////////////////////////
+
+//
+// Add a terminal node for an identifier in an expression.
+//
+// Returns the added node.
+//
+TIntermSymbol* TIntermediate::addSymbol(int id, const TString& name, const TType& type, TSourceLoc line)
+{
+    TIntermSymbol* node = new TIntermSymbol(id, name, type);
+    node->setLine(line);
+
+    return node;
+}
+
+//
+// Connect two nodes with a new parent that does a binary operation on the nodes.
+//
+// Returns the added node.
+//
+TIntermTyped* TIntermediate::addBinaryMath(TOperator op, TIntermTyped* left, TIntermTyped* right, TSourceLoc line, TSymbolTable& symbolTable)
+{
+    switch (op) {
+        case EOpEqual:
+        case EOpNotEqual:
+            if (left->isArray())
+                return 0;
+            break;
+        case EOpLessThan:
+        case EOpGreaterThan:
+        case EOpLessThanEqual:
+        case EOpGreaterThanEqual:
+            if (left->isMatrix() || left->isArray() || left->isVector() || left->getBasicType() == EbtStruct) {
+                return 0;
+            }
+            break;
+        case EOpLogicalOr:
+        case EOpLogicalXor:
+        case EOpLogicalAnd:
+            if (left->getBasicType() != EbtBool || left->isMatrix() || left->isArray() || left->isVector()) {
+                return 0;
+            }
+            break;
+        case EOpAdd:
+        case EOpSub:
+        case EOpDiv:
+        case EOpMul:
+            if (left->getBasicType() == EbtStruct || left->getBasicType() == EbtBool)
+                return 0;
+        default: break;
+    }
+
+    //
+    // First try converting the children to compatible types.
+    //
+    if (left->getType().getStruct() && right->getType().getStruct()) {
+        if (left->getType() != right->getType())
+            return 0;
+    } else {
+        TIntermTyped* child = addConversion(op, left->getType(), right);
+        if (child)
+            right = child;
+        else {
+            child = addConversion(op, right->getType(), left);
+            if (child)
+                left = child;
+            else
+                return 0;
+        }
+    }
+
+    //
+    // Need a new node holding things together then.  Make
+    // one and promote it to the right type.
+    //
+    TIntermBinary* node = new TIntermBinary(op);
+    if (line == 0)
+        line = right->getLine();
+    node->setLine(line);
+
+    node->setLeft(left);
+    node->setRight(right);
+    if (!node->promote(infoSink))
+        return 0;
+
+    //
+    // See if we can fold constants.
+    //
+    TIntermTyped* typedReturnNode = 0;
+    TIntermConstantUnion *leftTempConstant = left->getAsConstantUnion();
+    TIntermConstantUnion *rightTempConstant = right->getAsConstantUnion();
+    if (leftTempConstant && rightTempConstant) {
+        typedReturnNode = leftTempConstant->fold(node->getOp(), rightTempConstant, infoSink);
+
+        if (typedReturnNode)
+            return typedReturnNode;
+    }
+
+    return node;
+}
+
+//
+// Connect two nodes through an assignment.
+//
+// Returns the added node.
+//
+TIntermTyped* TIntermediate::addAssign(TOperator op, TIntermTyped* left, TIntermTyped* right, TSourceLoc line)
+{
+    //
+    // Like adding binary math, except the conversion can only go
+    // from right to left.
+    //
+    TIntermBinary* node = new TIntermBinary(op);
+    if (line == 0)
+        line = left->getLine();
+    node->setLine(line);
+
+    TIntermTyped* child = addConversion(op, left->getType(), right);
+    if (child == 0)
+        return 0;
+
+    node->setLeft(left);
+    node->setRight(child);
+    if (! node->promote(infoSink))
+        return 0;
+
+    return node;
+}
+
+//
+// Connect two nodes through an index operator, where the left node is the base
+// of an array or struct, and the right node is a direct or indirect offset.
+//
+// Returns the added node.
+// The caller should set the type of the returned node.
+//
+TIntermTyped* TIntermediate::addIndex(TOperator op, TIntermTyped* base, TIntermTyped* index, TSourceLoc line)
+{
+    TIntermBinary* node = new TIntermBinary(op);
+    if (line == 0)
+        line = index->getLine();
+    node->setLine(line);
+    node->setLeft(base);
+    node->setRight(index);
+
+    // caller should set the type
+
+    return node;
+}
+
+//
+// Add one node as the parent of another that it operates on.
+//
+// Returns the added node.
+//
+TIntermTyped* TIntermediate::addUnaryMath(TOperator op, TIntermNode* childNode, TSourceLoc line, TSymbolTable& symbolTable)
+{
+    TIntermUnary* node;
+    TIntermTyped* child = childNode->getAsTyped();
+
+    if (child == 0) {
+        infoSink.info.message(EPrefixInternalError, "Bad type in AddUnaryMath", line);
+        return 0;
+    }
+
+    switch (op) {
+        case EOpLogicalNot:
+            if (child->getType().getBasicType() != EbtBool || child->getType().isMatrix() || child->getType().isArray() || child->getType().isVector()) {
+                return 0;
+            }
+            break;
+
+        case EOpPostIncrement:
+        case EOpPreIncrement:
+        case EOpPostDecrement:
+        case EOpPreDecrement:
+        case EOpNegative:
+            if (child->getType().getBasicType() == EbtStruct || child->getType().isArray())
+                return 0;
+        default: break;
+    }
+
+    //
+    // Do we need to promote the operand?
+    //
+    // Note: Implicit promotions were removed from the language.
+    //
+    TBasicType newType = EbtVoid;
+    switch (op) {
+        case EOpConstructInt:   newType = EbtInt;   break;
+        case EOpConstructBool:  newType = EbtBool;  break;
+        case EOpConstructFloat: newType = EbtFloat; break;
+        default: break;
+    }
+
+    if (newType != EbtVoid) {
+        child = addConversion(op, TType(newType, child->getPrecision(), EvqTemporary,
+            child->getNominalSize(),
+            child->isMatrix(),
+            child->isArray()),
+            child);
+        if (child == 0)
+            return 0;
+    }
+
+    //
+    // For constructors, we are now done, it's all in the conversion.
+    //
+    switch (op) {
+        case EOpConstructInt:
+        case EOpConstructBool:
+        case EOpConstructFloat:
+            return child;
+        default: break;
+    }
+
+    TIntermConstantUnion *childTempConstant = 0;
+    if (child->getAsConstantUnion())
+        childTempConstant = child->getAsConstantUnion();
+
+    //
+    // Make a new node for the operator.
+    //
+    node = new TIntermUnary(op);
+    if (line == 0)
+        line = child->getLine();
+    node->setLine(line);
+    node->setOperand(child);
+
+    if (! node->promote(infoSink))
+        return 0;
+
+    if (childTempConstant)  {
+        TIntermTyped* newChild = childTempConstant->fold(op, 0, infoSink);
+
+        if (newChild)
+            return newChild;
+    }
+
+    return node;
+}
+
+//
+// This is the safe way to change the operator on an aggregate, as it
+// does lots of error checking and fixing.  Especially for establishing
+// a function call's operation on it's set of parameters.  Sequences
+// of instructions are also aggregates, but they just direnctly set
+// their operator to EOpSequence.
+//
+// Returns an aggregate node, which could be the one passed in if
+// it was already an aggregate but no operator was set.
+//
+TIntermAggregate* TIntermediate::setAggregateOperator(TIntermNode* node, TOperator op, TSourceLoc line)
+{
+    TIntermAggregate* aggNode;
+
+    //
+    // Make sure we have an aggregate.  If not turn it into one.
+    //
+    if (node) {
+        aggNode = node->getAsAggregate();
+        if (aggNode == 0 || aggNode->getOp() != EOpNull) {
+            //
+            // Make an aggregate containing this node.
+            //
+            aggNode = new TIntermAggregate();
+            aggNode->getSequence().push_back(node);
+            if (line == 0)
+                line = node->getLine();
+        }
+    } else
+        aggNode = new TIntermAggregate();
+
+    //
+    // Set the operator.
+    //
+    aggNode->setOp(op);
+    if (line != 0)
+        aggNode->setLine(line);
+
+    return aggNode;
+}
+
+//
+// Convert one type to another.
+//
+// Returns the node representing the conversion, which could be the same
+// node passed in if no conversion was needed.
+//
+// Return 0 if a conversion can't be done.
+//
+TIntermTyped* TIntermediate::addConversion(TOperator op, const TType& type, TIntermTyped* node)
+{
+    //
+    // Does the base type allow operation?
+    //
+    switch (node->getBasicType()) {
+        case EbtVoid:
+        case EbtSampler2D:
+        case EbtSamplerCube:
+            return 0;
+        default: break;
+    }
+
+    //
+    // Otherwise, if types are identical, no problem
+    //
+    if (type == node->getType())
+        return node;
+
+    //
+    // If one's a structure, then no conversions.
+    //
+    if (type.getStruct() || node->getType().getStruct())
+        return 0;
+
+    //
+    // If one's an array, then no conversions.
+    //
+    if (type.isArray() || node->getType().isArray())
+        return 0;
+
+    TBasicType promoteTo;
+
+    switch (op) {
+        //
+        // Explicit conversions
+        //
+        case EOpConstructBool:
+            promoteTo = EbtBool;
+            break;
+        case EOpConstructFloat:
+            promoteTo = EbtFloat;
+            break;
+        case EOpConstructInt:
+            promoteTo = EbtInt;
+            break;
+        default:
+            //
+            // implicit conversions were removed from the language.
+            //
+            if (type.getBasicType() != node->getType().getBasicType())
+                return 0;
+            //
+            // Size and structure could still differ, but that's
+            // handled by operator promotion.
+            //
+            return node;
+    }
+
+    if (node->getAsConstantUnion()) {
+
+        return (promoteConstantUnion(promoteTo, node->getAsConstantUnion()));
+    } else {
+
+        //
+        // Add a new newNode for the conversion.
+        //
+        TIntermUnary* newNode = 0;
+
+        TOperator newOp = EOpNull;
+        switch (promoteTo) {
+            case EbtFloat:
+                switch (node->getBasicType()) {
+                    case EbtInt:   newOp = EOpConvIntToFloat;  break;
+                    case EbtBool:  newOp = EOpConvBoolToFloat; break;
+                    default:
+                        infoSink.info.message(EPrefixInternalError, "Bad promotion node", node->getLine());
+                        return 0;
+                }
+                break;
+            case EbtBool:
+                switch (node->getBasicType()) {
+                    case EbtInt:   newOp = EOpConvIntToBool;   break;
+                    case EbtFloat: newOp = EOpConvFloatToBool; break;
+                    default:
+                        infoSink.info.message(EPrefixInternalError, "Bad promotion node", node->getLine());
+                        return 0;
+                }
+                break;
+            case EbtInt:
+                switch (node->getBasicType()) {
+                    case EbtBool:   newOp = EOpConvBoolToInt;  break;
+                    case EbtFloat:  newOp = EOpConvFloatToInt; break;
+                    default:
+                        infoSink.info.message(EPrefixInternalError, "Bad promotion node", node->getLine());
+                        return 0;
+                }
+                break;
+            default:
+                infoSink.info.message(EPrefixInternalError, "Bad promotion type", node->getLine());
+                return 0;
+        }
+
+        TType type(promoteTo, node->getPrecision(), EvqTemporary, node->getNominalSize(), node->isMatrix(), node->isArray());
+        newNode = new TIntermUnary(newOp, type);
+        newNode->setLine(node->getLine());
+        newNode->setOperand(node);
+
+        return newNode;
+    }
+}
+
+//
+// Safe way to combine two nodes into an aggregate.  Works with null pointers,
+// a node that's not a aggregate yet, etc.
+//
+// Returns the resulting aggregate, unless 0 was passed in for
+// both existing nodes.
+//
+TIntermAggregate* TIntermediate::growAggregate(TIntermNode* left, TIntermNode* right, TSourceLoc line)
+{
+    if (left == 0 && right == 0)
+        return 0;
+
+    TIntermAggregate* aggNode = 0;
+    if (left)
+        aggNode = left->getAsAggregate();
+    if (!aggNode || aggNode->getOp() != EOpNull) {
+        aggNode = new TIntermAggregate;
+        if (left)
+            aggNode->getSequence().push_back(left);
+    }
+
+    if (right)
+        aggNode->getSequence().push_back(right);
+
+    if (line != 0)
+        aggNode->setLine(line);
+
+    return aggNode;
+}
+
+//
+// Turn an existing node into an aggregate.
+//
+// Returns an aggregate, unless 0 was passed in for the existing node.
+//
+TIntermAggregate* TIntermediate::makeAggregate(TIntermNode* node, TSourceLoc line)
+{
+    if (node == 0)
+        return 0;
+
+    TIntermAggregate* aggNode = new TIntermAggregate;
+    aggNode->getSequence().push_back(node);
+
+    if (line != 0)
+        aggNode->setLine(line);
+    else
+        aggNode->setLine(node->getLine());
+
+    return aggNode;
+}
+
+//
+// For "if" test nodes.  There are three children; a condition,
+// a true path, and a false path.  The two paths are in the
+// nodePair.
+//
+// Returns the selection node created.
+//
+TIntermNode* TIntermediate::addSelection(TIntermTyped* cond, TIntermNodePair nodePair, TSourceLoc line)
+{
+    //
+    // For compile time constant selections, prune the code and
+    // test now.
+    //
+
+    if (cond->getAsTyped() && cond->getAsTyped()->getAsConstantUnion()) {
+        if (cond->getAsTyped()->getAsConstantUnion()->getUnionArrayPointer()->getBConst() == true)
+            return nodePair.node1 ? setAggregateOperator(nodePair.node1, EOpSequence, nodePair.node1->getLine()) : NULL;
+        else
+            return nodePair.node2 ? setAggregateOperator(nodePair.node2, EOpSequence, nodePair.node2->getLine()) : NULL;
+    }
+
+    TIntermSelection* node = new TIntermSelection(cond, nodePair.node1, nodePair.node2);
+    node->setLine(line);
+
+    return node;
+}
+
+
+TIntermTyped* TIntermediate::addComma(TIntermTyped* left, TIntermTyped* right, TSourceLoc line)
+{
+    if (left->getType().getQualifier() == EvqConst && right->getType().getQualifier() == EvqConst) {
+        return right;
+    } else {
+        TIntermTyped *commaAggregate = growAggregate(left, right, line);
+        commaAggregate->getAsAggregate()->setOp(EOpComma);
+        commaAggregate->setType(right->getType());
+        commaAggregate->getTypePointer()->setQualifier(EvqTemporary);
+        return commaAggregate;
+    }
+}
+
+//
+// For "?:" test nodes.  There are three children; a condition,
+// a true path, and a false path.  The two paths are specified
+// as separate parameters.
+//
+// Returns the selection node created, or 0 if one could not be.
+//
+TIntermTyped* TIntermediate::addSelection(TIntermTyped* cond, TIntermTyped* trueBlock, TIntermTyped* falseBlock, TSourceLoc line)
+{
+    //
+    // Get compatible types.
+    //
+    TIntermTyped* child = addConversion(EOpSequence, trueBlock->getType(), falseBlock);
+    if (child)
+        falseBlock = child;
+    else {
+        child = addConversion(EOpSequence, falseBlock->getType(), trueBlock);
+        if (child)
+            trueBlock = child;
+        else
+            return 0;
+    }
+
+    //
+    // See if all the operands are constant, then fold it otherwise not.
+    //
+
+    if (cond->getAsConstantUnion() && trueBlock->getAsConstantUnion() && falseBlock->getAsConstantUnion()) {
+        if (cond->getAsConstantUnion()->getUnionArrayPointer()->getBConst())
+            return trueBlock;
+        else
+            return falseBlock;
+    }
+
+    //
+    // Make a selection node.
+    //
+    TIntermSelection* node = new TIntermSelection(cond, trueBlock, falseBlock, trueBlock->getType());
+    node->getTypePointer()->setQualifier(EvqTemporary);
+    node->setLine(line);
+
+    return node;
+}
+
+//
+// Constant terminal nodes.  Has a union that contains bool, float or int constants
+//
+// Returns the constant union node created.
+//
+
+TIntermConstantUnion* TIntermediate::addConstantUnion(ConstantUnion* unionArrayPointer, const TType& t, TSourceLoc line)
+{
+    TIntermConstantUnion* node = new TIntermConstantUnion(unionArrayPointer, t);
+    node->setLine(line);
+
+    return node;
+}
+
+TIntermTyped* TIntermediate::addSwizzle(TVectorFields& fields, TSourceLoc line)
+{
+
+    TIntermAggregate* node = new TIntermAggregate(EOpSequence);
+
+    node->setLine(line);
+    TIntermConstantUnion* constIntNode;
+    TIntermSequence &sequenceVector = node->getSequence();
+    ConstantUnion* unionArray;
+
+    for (int i = 0; i < fields.num; i++) {
+        unionArray = new ConstantUnion[1];
+        unionArray->setIConst(fields.offsets[i]);
+        constIntNode = addConstantUnion(unionArray, TType(EbtInt, EbpUndefined, EvqConst), line);
+        sequenceVector.push_back(constIntNode);
+    }
+
+    return node;
+}
+
+//
+// Create loop nodes.
+//
+TIntermNode* TIntermediate::addLoop(TLoopType type, TIntermNode* init, TIntermTyped* cond, TIntermTyped* expr, TIntermNode* body, TSourceLoc line)
+{
+    TIntermNode* node = new TIntermLoop(type, init, cond, expr, body);
+    node->setLine(line);
+
+    return node;
+}
+
+//
+// Add branches.
+//
+TIntermBranch* TIntermediate::addBranch(TOperator branchOp, TSourceLoc line)
+{
+    return addBranch(branchOp, 0, line);
+}
+
+TIntermBranch* TIntermediate::addBranch(TOperator branchOp, TIntermTyped* expression, TSourceLoc line)
+{
+    TIntermBranch* node = new TIntermBranch(branchOp, expression);
+    node->setLine(line);
+
+    return node;
+}
+
+//
+// This is to be executed once the final root is put on top by the parsing
+// process.
+//
+bool TIntermediate::postProcess(TIntermNode* root)
+{
+    if (root == 0)
+        return true;
+
+    //
+    // First, finish off the top level sequence, if any
+    //
+    TIntermAggregate* aggRoot = root->getAsAggregate();
+    if (aggRoot && aggRoot->getOp() == EOpNull)
+        aggRoot->setOp(EOpSequence);
+
+    return true;
+}
+
+//
+// This deletes the tree.
+//
+void TIntermediate::remove(TIntermNode* root)
+{
+    if (root)
+        RemoveAllTreeNodes(root);
+}
+
+////////////////////////////////////////////////////////////////
+//
+// Member functions of the nodes used for building the tree.
+//
+////////////////////////////////////////////////////////////////
+
+//
+// Say whether or not an operation node changes the value of a variable.
+//
+// Returns true if state is modified.
+//
+bool TIntermOperator::modifiesState() const
+{
+    switch (op) {
+        case EOpPostIncrement:
+        case EOpPostDecrement:
+        case EOpPreIncrement:
+        case EOpPreDecrement:
+        case EOpAssign:
+        case EOpAddAssign:
+        case EOpSubAssign:
+        case EOpMulAssign:
+        case EOpVectorTimesMatrixAssign:
+        case EOpVectorTimesScalarAssign:
+        case EOpMatrixTimesScalarAssign:
+        case EOpMatrixTimesMatrixAssign:
+        case EOpDivAssign:
+            return true;
+        default:
+            return false;
+    }
+}
+
+//
+// returns true if the operator is for one of the constructors
+//
+bool TIntermOperator::isConstructor() const
+{
+    switch (op) {
+        case EOpConstructVec2:
+        case EOpConstructVec3:
+        case EOpConstructVec4:
+        case EOpConstructMat2:
+        case EOpConstructMat3:
+        case EOpConstructMat4:
+        case EOpConstructFloat:
+        case EOpConstructIVec2:
+        case EOpConstructIVec3:
+        case EOpConstructIVec4:
+        case EOpConstructInt:
+        case EOpConstructBVec2:
+        case EOpConstructBVec3:
+        case EOpConstructBVec4:
+        case EOpConstructBool:
+        case EOpConstructStruct:
+            return true;
+        default:
+            return false;
+    }
+}
+//
+// Make sure the type of a unary operator is appropriate for its
+// combination of operation and operand type.
+//
+// Returns false in nothing makes sense.
+//
+bool TIntermUnary::promote(TInfoSink&)
+{
+    switch (op) {
+        case EOpLogicalNot:
+            if (operand->getBasicType() != EbtBool)
+                return false;
+            break;
+        case EOpNegative:
+        case EOpPostIncrement:
+        case EOpPostDecrement:
+        case EOpPreIncrement:
+        case EOpPreDecrement:
+            if (operand->getBasicType() == EbtBool)
+                return false;
+            break;
+
+            // operators for built-ins are already type checked against their prototype
+        case EOpAny:
+        case EOpAll:
+        case EOpVectorLogicalNot:
+            return true;
+
+        default:
+            if (operand->getBasicType() != EbtFloat)
+                return false;
+    }
+
+    setType(operand->getType());
+
+    return true;
+}
+
+//
+// Establishes the type of the resultant operation, as well as
+// makes the operator the correct one for the operands.
+//
+// Returns false if operator can't work on operands.
+//
+bool TIntermBinary::promote(TInfoSink& infoSink)
+{
+    // This function only handles scalars, vectors, and matrices.
+    if (left->isArray() || right->isArray()) {
+        infoSink.info.message(EPrefixInternalError, "Invalid operation for arrays", getLine());
+        return false;
+    }
+
+    // GLSL ES 2.0 does not support implicit type casting.
+    // So the basic type should always match.
+    if (left->getBasicType() != right->getBasicType())
+        return false;
+
+    //
+    // Base assumption:  just make the type the same as the left
+    // operand.  Then only deviations from this need be coded.
+    //
+    setType(left->getType());
+
+    // The result gets promoted to the highest precision.
+    TPrecision higherPrecision = GetHigherPrecision(left->getPrecision(), right->getPrecision());
+    getTypePointer()->setPrecision(higherPrecision);
+
+    // Binary operations results in temporary variables unless both
+    // operands are const.
+    if (left->getQualifier() != EvqConst || right->getQualifier() != EvqConst) {
+        getTypePointer()->setQualifier(EvqTemporary);
+    }
+
+    int size = std::max(left->getNominalSize(), right->getNominalSize());
+
+    //
+    // All scalars. Code after this test assumes this case is removed!
+    //
+    if (size == 1) {
+        switch (op) {
+            //
+            // Promote to conditional
+            //
+            case EOpEqual:
+            case EOpNotEqual:
+            case EOpLessThan:
+            case EOpGreaterThan:
+            case EOpLessThanEqual:
+            case EOpGreaterThanEqual:
+                setType(TType(EbtBool, EbpUndefined));
+                break;
+
+            //
+            // And and Or operate on conditionals
+            //
+            case EOpLogicalAnd:
+            case EOpLogicalOr:
+                // Both operands must be of type bool.
+                if (left->getBasicType() != EbtBool || right->getBasicType() != EbtBool)
+                    return false;
+                setType(TType(EbtBool, EbpUndefined));
+                break;
+
+            default:
+                break;
+        }
+        return true;
+    }
+
+    // If we reach here, at least one of the operands is vector or matrix.
+    // The other operand could be a scalar, vector, or matrix.
+    // Are the sizes compatible?
+    //
+    if (left->getNominalSize() != right->getNominalSize()) {
+        // If the nominal size of operands do not match:
+        // One of them must be scalar.
+        if (left->getNominalSize() != 1 && right->getNominalSize() != 1)
+            return false;
+        // Operator cannot be of type pure assignment.
+        if (op == EOpAssign || op == EOpInitialize)
+            return false;
+    }
+
+    //
+    // Can these two operands be combined?
+    //
+    TBasicType basicType = left->getBasicType();
+    switch (op) {
+        case EOpMul:
+            if (!left->isMatrix() && right->isMatrix()) {
+                if (left->isVector())
+                    op = EOpVectorTimesMatrix;
+                else {
+                    op = EOpMatrixTimesScalar;
+                    setType(TType(basicType, higherPrecision, EvqTemporary, size, true));
+                }
+            } else if (left->isMatrix() && !right->isMatrix()) {
+                if (right->isVector()) {
+                    op = EOpMatrixTimesVector;
+                    setType(TType(basicType, higherPrecision, EvqTemporary, size, false));
+                } else {
+                    op = EOpMatrixTimesScalar;
+                }
+            } else if (left->isMatrix() && right->isMatrix()) {
+                op = EOpMatrixTimesMatrix;
+            } else if (!left->isMatrix() && !right->isMatrix()) {
+                if (left->isVector() && right->isVector()) {
+                    // leave as component product
+                } else if (left->isVector() || right->isVector()) {
+                    op = EOpVectorTimesScalar;
+                    setType(TType(basicType, higherPrecision, EvqTemporary, size, false));
+                }
+            } else {
+                infoSink.info.message(EPrefixInternalError, "Missing elses", getLine());
+                return false;
+            }
+            break;
+        case EOpMulAssign:
+            if (!left->isMatrix() && right->isMatrix()) {
+                if (left->isVector())
+                    op = EOpVectorTimesMatrixAssign;
+                else {
+                    return false;
+                }
+            } else if (left->isMatrix() && !right->isMatrix()) {
+                if (right->isVector()) {
+                    return false;
+                } else {
+                    op = EOpMatrixTimesScalarAssign;
+                }
+            } else if (left->isMatrix() && right->isMatrix()) {
+                op = EOpMatrixTimesMatrixAssign;
+            } else if (!left->isMatrix() && !right->isMatrix()) {
+                if (left->isVector() && right->isVector()) {
+                    // leave as component product
+                } else if (left->isVector() || right->isVector()) {
+                    if (! left->isVector())
+                        return false;
+                    op = EOpVectorTimesScalarAssign;
+                    setType(TType(basicType, higherPrecision, EvqTemporary, size, false));
+                }
+            } else {
+                infoSink.info.message(EPrefixInternalError, "Missing elses", getLine());
+                return false;
+            }
+            break;
+
+        case EOpAssign:
+        case EOpInitialize:
+        case EOpAdd:
+        case EOpSub:
+        case EOpDiv:
+        case EOpAddAssign:
+        case EOpSubAssign:
+        case EOpDivAssign:
+            if ((left->isMatrix() && right->isVector()) ||
+                (left->isVector() && right->isMatrix()))
+                return false;
+            setType(TType(basicType, higherPrecision, EvqTemporary, size, left->isMatrix() || right->isMatrix()));
+            break;
+
+        case EOpEqual:
+        case EOpNotEqual:
+        case EOpLessThan:
+        case EOpGreaterThan:
+        case EOpLessThanEqual:
+        case EOpGreaterThanEqual:
+            if ((left->isMatrix() && right->isVector()) ||
+                (left->isVector() && right->isMatrix()))
+                return false;
+            setType(TType(EbtBool, EbpUndefined));
+            break;
+
+        default:
+            return false;
+    }
+    
+    return true;
+}
+
+bool CompareStruct(const TType& leftNodeType, ConstantUnion* rightUnionArray, ConstantUnion* leftUnionArray)
+{
+    const TTypeList* fields = leftNodeType.getStruct();
+
+    size_t structSize = fields->size();
+    int index = 0;
+
+    for (size_t j = 0; j < structSize; j++) {
+        int size = (*fields)[j].type->getObjectSize();
+        for (int i = 0; i < size; i++) {
+            if ((*fields)[j].type->getBasicType() == EbtStruct) {
+                if (!CompareStructure(*(*fields)[j].type, &rightUnionArray[index], &leftUnionArray[index]))
+                    return false;
+            } else {
+                if (leftUnionArray[index] != rightUnionArray[index])
+                    return false;
+                index++;
+            }
+
+        }
+    }
+    return true;
+}
+
+bool CompareStructure(const TType& leftNodeType, ConstantUnion* rightUnionArray, ConstantUnion* leftUnionArray)
+{
+    if (leftNodeType.isArray()) {
+        TType typeWithoutArrayness = leftNodeType;
+        typeWithoutArrayness.clearArrayness();
+
+        int arraySize = leftNodeType.getArraySize();
+
+        for (int i = 0; i < arraySize; ++i) {
+            int offset = typeWithoutArrayness.getObjectSize() * i;
+            if (!CompareStruct(typeWithoutArrayness, &rightUnionArray[offset], &leftUnionArray[offset]))
+                return false;
+        }
+    } else
+        return CompareStruct(leftNodeType, rightUnionArray, leftUnionArray);
+
+    return true;
+}
+
+//
+// The fold functions see if an operation on a constant can be done in place,
+// without generating run-time code.
+//
+// Returns the node to keep using, which may or may not be the node passed in.
+//
+
+TIntermTyped* TIntermConstantUnion::fold(TOperator op, TIntermTyped* constantNode, TInfoSink& infoSink)
+{
+    ConstantUnion *unionArray = getUnionArrayPointer();
+    int objectSize = getType().getObjectSize();
+
+    if (constantNode) {  // binary operations
+        TIntermConstantUnion *node = constantNode->getAsConstantUnion();
+        ConstantUnion *rightUnionArray = node->getUnionArrayPointer();
+        TType returnType = getType();
+
+        // for a case like float f = 1.2 + vec4(2,3,4,5);
+        if (constantNode->getType().getObjectSize() == 1 && objectSize > 1) {
+            rightUnionArray = new ConstantUnion[objectSize];
+            for (int i = 0; i < objectSize; ++i)
+                rightUnionArray[i] = *node->getUnionArrayPointer();
+            returnType = getType();
+        } else if (constantNode->getType().getObjectSize() > 1 && objectSize == 1) {
+            // for a case like float f = vec4(2,3,4,5) + 1.2;
+            unionArray = new ConstantUnion[constantNode->getType().getObjectSize()];
+            for (int i = 0; i < constantNode->getType().getObjectSize(); ++i)
+                unionArray[i] = *getUnionArrayPointer();
+            returnType = node->getType();
+            objectSize = constantNode->getType().getObjectSize();
+        }
+
+        ConstantUnion* tempConstArray = 0;
+        TIntermConstantUnion *tempNode;
+
+        bool boolNodeFlag = false;
+        switch(op) {
+            case EOpAdd:
+                tempConstArray = new ConstantUnion[objectSize];
+                {// support MSVC++6.0
+                    for (int i = 0; i < objectSize; i++)
+                        tempConstArray[i] = unionArray[i] + rightUnionArray[i];
+                }
+                break;
+            case EOpSub:
+                tempConstArray = new ConstantUnion[objectSize];
+                {// support MSVC++6.0
+                    for (int i = 0; i < objectSize; i++)
+                        tempConstArray[i] = unionArray[i] - rightUnionArray[i];
+                }
+                break;
+
+            case EOpMul:
+            case EOpVectorTimesScalar:
+            case EOpMatrixTimesScalar:
+                tempConstArray = new ConstantUnion[objectSize];
+                {// support MSVC++6.0
+                    for (int i = 0; i < objectSize; i++)
+                        tempConstArray[i] = unionArray[i] * rightUnionArray[i];
+                }
+                break;
+            case EOpMatrixTimesMatrix:
+                if (getType().getBasicType() != EbtFloat || node->getBasicType() != EbtFloat) {
+                    infoSink.info.message(EPrefixInternalError, "Constant Folding cannot be done for matrix multiply", getLine());
+                    return 0;
+                }
+                {// support MSVC++6.0
+                    int size = getNominalSize();
+                    tempConstArray = new ConstantUnion[size*size];
+                    for (int row = 0; row < size; row++) {
+                        for (int column = 0; column < size; column++) {
+                            tempConstArray[size * column + row].setFConst(0.0f);
+                            for (int i = 0; i < size; i++) {
+                                tempConstArray[size * column + row].setFConst(tempConstArray[size * column + row].getFConst() + unionArray[i * size + row].getFConst() * (rightUnionArray[column * size + i].getFConst()));
+                            }
+                        }
+                    }
+                }
+                break;
+            case EOpDiv:
+                tempConstArray = new ConstantUnion[objectSize];
+                {// support MSVC++6.0
+                    for (int i = 0; i < objectSize; i++) {
+                        switch (getType().getBasicType()) {
+            case EbtFloat:
+                if (rightUnionArray[i] == 0.0f) {
+                    infoSink.info.message(EPrefixWarning, "Divide by zero error during constant folding", getLine());
+                    tempConstArray[i].setFConst(FLT_MAX);
+                } else
+                    tempConstArray[i].setFConst(unionArray[i].getFConst() / rightUnionArray[i].getFConst());
+                break;
+
+            case EbtInt:
+                if (rightUnionArray[i] == 0) {
+                    infoSink.info.message(EPrefixWarning, "Divide by zero error during constant folding", getLine());
+                    tempConstArray[i].setIConst(INT_MAX);
+                } else
+                    tempConstArray[i].setIConst(unionArray[i].getIConst() / rightUnionArray[i].getIConst());
+                break;
+            default:
+                infoSink.info.message(EPrefixInternalError, "Constant folding cannot be done for \"/\"", getLine());
+                return 0;
+                        }
+                    }
+                }
+                break;
+
+            case EOpMatrixTimesVector:
+                if (node->getBasicType() != EbtFloat) {
+                    infoSink.info.message(EPrefixInternalError, "Constant Folding cannot be done for matrix times vector", getLine());
+                    return 0;
+                }
+                tempConstArray = new ConstantUnion[getNominalSize()];
+
+                {// support MSVC++6.0
+                    for (int size = getNominalSize(), i = 0; i < size; i++) {
+                        tempConstArray[i].setFConst(0.0f);
+                        for (int j = 0; j < size; j++) {
+                            tempConstArray[i].setFConst(tempConstArray[i].getFConst() + ((unionArray[j*size + i].getFConst()) * rightUnionArray[j].getFConst()));
+                        }
+                    }
+                }
+
+                tempNode = new TIntermConstantUnion(tempConstArray, node->getType());
+                tempNode->setLine(getLine());
+
+                return tempNode;
+
+            case EOpVectorTimesMatrix:
+                if (getType().getBasicType() != EbtFloat) {
+                    infoSink.info.message(EPrefixInternalError, "Constant Folding cannot be done for vector times matrix", getLine());
+                    return 0;
+                }
+
+                tempConstArray = new ConstantUnion[getNominalSize()];
+                {// support MSVC++6.0
+                    for (int size = getNominalSize(), i = 0; i < size; i++) {
+                        tempConstArray[i].setFConst(0.0f);
+                        for (int j = 0; j < size; j++) {
+                            tempConstArray[i].setFConst(tempConstArray[i].getFConst() + ((unionArray[j].getFConst()) * rightUnionArray[i*size + j].getFConst()));
+                        }
+                    }
+                }
+                break;
+
+            case EOpLogicalAnd: // this code is written for possible future use, will not get executed currently
+                tempConstArray = new ConstantUnion[objectSize];
+                {// support MSVC++6.0
+                    for (int i = 0; i < objectSize; i++)
+                        tempConstArray[i] = unionArray[i] && rightUnionArray[i];
+                }
+                break;
+
+            case EOpLogicalOr: // this code is written for possible future use, will not get executed currently
+                tempConstArray = new ConstantUnion[objectSize];
+                {// support MSVC++6.0
+                    for (int i = 0; i < objectSize; i++)
+                        tempConstArray[i] = unionArray[i] || rightUnionArray[i];
+                }
+                break;
+
+            case EOpLogicalXor:
+                tempConstArray = new ConstantUnion[objectSize];
+                {// support MSVC++6.0
+                    for (int i = 0; i < objectSize; i++)
+                        switch (getType().getBasicType()) {
+            case EbtBool: tempConstArray[i].setBConst((unionArray[i] == rightUnionArray[i]) ? false : true); break;
+            default: assert(false && "Default missing");
+                    }
+                }
+                break;
+
+            case EOpLessThan:
+                assert(objectSize == 1);
+                tempConstArray = new ConstantUnion[1];
+                tempConstArray->setBConst(*unionArray < *rightUnionArray);
+                returnType = TType(EbtBool, EbpUndefined, EvqConst);
+                break;
+            case EOpGreaterThan:
+                assert(objectSize == 1);
+                tempConstArray = new ConstantUnion[1];
+                tempConstArray->setBConst(*unionArray > *rightUnionArray);
+                returnType = TType(EbtBool, EbpUndefined, EvqConst);
+                break;
+            case EOpLessThanEqual:
+                {
+                    assert(objectSize == 1);
+                    ConstantUnion constant;
+                    constant.setBConst(*unionArray > *rightUnionArray);
+                    tempConstArray = new ConstantUnion[1];
+                    tempConstArray->setBConst(!constant.getBConst());
+                    returnType = TType(EbtBool, EbpUndefined, EvqConst);
+                    break;
+                }
+            case EOpGreaterThanEqual:
+                {
+                    assert(objectSize == 1);
+                    ConstantUnion constant;
+                    constant.setBConst(*unionArray < *rightUnionArray);
+                    tempConstArray = new ConstantUnion[1];
+                    tempConstArray->setBConst(!constant.getBConst());
+                    returnType = TType(EbtBool, EbpUndefined, EvqConst);
+                    break;
+                }
+
+            case EOpEqual:
+                if (getType().getBasicType() == EbtStruct) {
+                    if (!CompareStructure(node->getType(), node->getUnionArrayPointer(), unionArray))
+                        boolNodeFlag = true;
+                } else {
+                    for (int i = 0; i < objectSize; i++) {
+                        if (unionArray[i] != rightUnionArray[i]) {
+                            boolNodeFlag = true;
+                            break;  // break out of for loop
+                        }
+                    }
+                }
+
+                tempConstArray = new ConstantUnion[1];
+                if (!boolNodeFlag) {
+                    tempConstArray->setBConst(true);
+                }
+                else {
+                    tempConstArray->setBConst(false);
+                }
+
+                tempNode = new TIntermConstantUnion(tempConstArray, TType(EbtBool, EbpUndefined, EvqConst));
+                tempNode->setLine(getLine());
+
+                return tempNode;
+
+            case EOpNotEqual:
+                if (getType().getBasicType() == EbtStruct) {
+                    if (CompareStructure(node->getType(), node->getUnionArrayPointer(), unionArray))
+                        boolNodeFlag = true;
+                } else {
+                    for (int i = 0; i < objectSize; i++) {
+                        if (unionArray[i] == rightUnionArray[i]) {
+                            boolNodeFlag = true;
+                            break;  // break out of for loop
+                        }
+                    }
+                }
+
+                tempConstArray = new ConstantUnion[1];
+                if (!boolNodeFlag) {
+                    tempConstArray->setBConst(true);
+                }
+                else {
+                    tempConstArray->setBConst(false);
+                }
+
+                tempNode = new TIntermConstantUnion(tempConstArray, TType(EbtBool, EbpUndefined, EvqConst));
+                tempNode->setLine(getLine());
+
+                return tempNode;
+
+            default:
+                infoSink.info.message(EPrefixInternalError, "Invalid operator for constant folding", getLine());
+                return 0;
+        }
+        tempNode = new TIntermConstantUnion(tempConstArray, returnType);
+        tempNode->setLine(getLine());
+
+        return tempNode;
+    } else {
+        //
+        // Do unary operations
+        //
+        TIntermConstantUnion *newNode = 0;
+        ConstantUnion* tempConstArray = new ConstantUnion[objectSize];
+        for (int i = 0; i < objectSize; i++) {
+            switch(op) {
+                case EOpNegative:
+                    switch (getType().getBasicType()) {
+                        case EbtFloat: tempConstArray[i].setFConst(-unionArray[i].getFConst()); break;
+                        case EbtInt:   tempConstArray[i].setIConst(-unionArray[i].getIConst()); break;
+                        default:
+                            infoSink.info.message(EPrefixInternalError, "Unary operation not folded into constant", getLine());
+                            return 0;
+                    }
+                    break;
+                case EOpLogicalNot: // this code is written for possible future use, will not get executed currently
+                    switch (getType().getBasicType()) {
+                        case EbtBool:  tempConstArray[i].setBConst(!unionArray[i].getBConst()); break;
+                        default:
+                            infoSink.info.message(EPrefixInternalError, "Unary operation not folded into constant", getLine());
+                            return 0;
+                    }
+                    break;
+                default:
+                    return 0;
+            }
+        }
+        newNode = new TIntermConstantUnion(tempConstArray, getType());
+        newNode->setLine(getLine());
+        return newNode;
+    }
+}
+
+TIntermTyped* TIntermediate::promoteConstantUnion(TBasicType promoteTo, TIntermConstantUnion* node)
+{
+    ConstantUnion *rightUnionArray = node->getUnionArrayPointer();
+    int size = node->getType().getObjectSize();
+
+    ConstantUnion *leftUnionArray = new ConstantUnion[size];
+
+    for (int i=0; i < size; i++) {
+
+        switch (promoteTo) {
+            case EbtFloat:
+                switch (node->getType().getBasicType()) {
+                    case EbtInt:
+                        leftUnionArray[i].setFConst(static_cast<float>(rightUnionArray[i].getIConst()));
+                        break;
+                    case EbtBool:
+                        leftUnionArray[i].setFConst(static_cast<float>(rightUnionArray[i].getBConst()));
+                        break;
+                    case EbtFloat:
+                        leftUnionArray[i] = rightUnionArray[i];
+                        break;
+                    default:
+                        infoSink.info.message(EPrefixInternalError, "Cannot promote", node->getLine());
+                        return 0;
+                }
+                break;
+            case EbtInt:
+                switch (node->getType().getBasicType()) {
+                    case EbtInt:
+                        leftUnionArray[i] = rightUnionArray[i];
+                        break;
+                    case EbtBool:
+                        leftUnionArray[i].setIConst(static_cast<int>(rightUnionArray[i].getBConst()));
+                        break;
+                    case EbtFloat:
+                        leftUnionArray[i].setIConst(static_cast<int>(rightUnionArray[i].getFConst()));
+                        break;
+                    default:
+                        infoSink.info.message(EPrefixInternalError, "Cannot promote", node->getLine());
+                        return 0;
+                }
+                break;
+            case EbtBool:
+                switch (node->getType().getBasicType()) {
+                    case EbtInt:
+                        leftUnionArray[i].setBConst(rightUnionArray[i].getIConst() != 0);
+                        break;
+                    case EbtBool:
+                        leftUnionArray[i] = rightUnionArray[i];
+                        break;
+                    case EbtFloat:
+                        leftUnionArray[i].setBConst(rightUnionArray[i].getFConst() != 0.0f);
+                        break;
+                    default:
+                        infoSink.info.message(EPrefixInternalError, "Cannot promote", node->getLine());
+                        return 0;
+                }
+
+                break;
+            default:
+                infoSink.info.message(EPrefixInternalError, "Incorrect data type found", node->getLine());
+                return 0;
+        }
+
+    }
+
+    const TType& t = node->getType();
+
+    return addConstantUnion(leftUnionArray, TType(promoteTo, t.getPrecision(), t.getQualifier(), t.getNominalSize(), t.isMatrix(), t.isArray()), node->getLine());
+}
+
diff --git a/src/3rdparty/angle/src/compiler/MMap.h b/src/3rdparty/angle/src/compiler/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/src/3rdparty/angle/src/compiler/MapLongVariableNames.cpp b/src/3rdparty/angle/src/compiler/MapLongVariableNames.cpp
new file mode 100644 (file)
index 0000000..a503101
--- /dev/null
@@ -0,0 +1,122 @@
+//
+// 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/MapLongVariableNames.h"
+
+namespace {
+
+TString mapLongName(int 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));
+}
+
+int 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;
+        };
+    }
+}
+
+bool MapLongVariableNames::visitLoop(Visit, TIntermLoop* node)
+{
+    if (node->getInit())
+        node->getInit()->traverse(this);
+    return true;
+}
+
+TString MapLongVariableNames::mapGlobalLongName(const TString& name)
+{
+    ASSERT(mGlobalMap);
+    const char* mappedName = mGlobalMap->Find(name.c_str());
+    if (mappedName != NULL)
+        return mappedName;
+    int id = mGlobalMap->Size();
+    TString rt = mapLongName(id, name, true);
+    mGlobalMap->Insert(name.c_str(), rt.c_str());
+    return rt;
+}
diff --git a/src/3rdparty/angle/src/compiler/MapLongVariableNames.h b/src/3rdparty/angle/src/compiler/MapLongVariableNames.h
new file mode 100644 (file)
index 0000000..fb2c7e8
--- /dev/null
@@ -0,0 +1,59 @@
+//
+// 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/intermediate.h"
+#include "compiler/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.
+    int 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*);
+    virtual bool visitLoop(Visit, TIntermLoop*);
+
+private:
+    TString mapGlobalLongName(const TString& name);
+
+    LongNameMap* mGlobalMap;
+};
+
+#endif  // COMPILER_MAP_LONG_VARIABLE_NAMES_H_
diff --git a/src/3rdparty/angle/src/compiler/OutputESSL.cpp b/src/3rdparty/angle/src/compiler/OutputESSL.cpp
new file mode 100644 (file)
index 0000000..64ee92d
--- /dev/null
@@ -0,0 +1,22 @@
+//
+// 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/OutputESSL.h"
+
+TOutputESSL::TOutputESSL(TInfoSinkBase& objSink)
+    : TOutputGLSLBase(objSink)
+{
+}
+
+bool TOutputESSL::writeVariablePrecision(TPrecision precision)
+{
+    if (precision == EbpUndefined)
+        return false;
+
+    TInfoSinkBase& out = objSink();
+    out << getPrecisionString(precision);
+    return true;
+}
diff --git a/src/3rdparty/angle/src/compiler/OutputESSL.h b/src/3rdparty/angle/src/compiler/OutputESSL.h
new file mode 100644 (file)
index 0000000..4fa73c8
--- /dev/null
@@ -0,0 +1,21 @@
+//
+// 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/OutputGLSLBase.h"
+
+class TOutputESSL : public TOutputGLSLBase
+{
+public:
+    TOutputESSL(TInfoSinkBase& objSink);
+
+protected:
+    virtual bool writeVariablePrecision(TPrecision precision);
+};
+
+#endif  // CROSSCOMPILERGLSL_OUTPUTESSL_H_
diff --git a/src/3rdparty/angle/src/compiler/OutputGLSL.cpp b/src/3rdparty/angle/src/compiler/OutputGLSL.cpp
new file mode 100644 (file)
index 0000000..dd31b4b
--- /dev/null
@@ -0,0 +1,17 @@
+//
+// 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/OutputGLSL.h"
+
+TOutputGLSL::TOutputGLSL(TInfoSinkBase& objSink)
+    : TOutputGLSLBase(objSink)
+{
+}
+
+bool TOutputGLSL::writeVariablePrecision(TPrecision)
+{
+    return false;
+}
diff --git a/src/3rdparty/angle/src/compiler/OutputGLSL.h b/src/3rdparty/angle/src/compiler/OutputGLSL.h
new file mode 100644 (file)
index 0000000..0fe2356
--- /dev/null
@@ -0,0 +1,21 @@
+//
+// 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/OutputGLSLBase.h"
+
+class TOutputGLSL : public TOutputGLSLBase
+{
+public:
+    TOutputGLSL(TInfoSinkBase& objSink);
+
+protected:
+    virtual bool writeVariablePrecision(TPrecision);
+};
+
+#endif  // CROSSCOMPILERGLSL_OUTPUTGLSL_H_
diff --git a/src/3rdparty/angle/src/compiler/OutputGLSLBase.cpp b/src/3rdparty/angle/src/compiler/OutputGLSLBase.cpp
new file mode 100644 (file)
index 0000000..552fa50
--- /dev/null
@@ -0,0 +1,720 @@
+//
+// 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/OutputGLSLBase.h"
+#include "compiler/debug.h"
+
+namespace
+{
+TString 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 << type.getTypeName();
+        else
+            out << type.getBasicString();
+    }
+    return TString(out.c_str());
+}
+
+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)
+    : TIntermTraverser(true, true, true),
+      mObjSink(objSink),
+      mDeclaringVariables(false)
+{
+}
+
+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) &&
+        (mDeclaredStructs.find(type.getTypeName()) == mDeclaredStructs.end()))
+    {
+        out << "struct " << type.getTypeName() << "{\n";
+        const TTypeList* structure = type.getStruct();
+        ASSERT(structure != NULL);
+        for (size_t i = 0; i < structure->size(); ++i)
+        {
+            const TType* fieldType = (*structure)[i].type;
+            ASSERT(fieldType != NULL);
+            if (writeVariablePrecision(fieldType->getPrecision()))
+                out << " ";
+            out << getTypeName(*fieldType) << " " << fieldType->getFieldName();
+            if (fieldType->isArray())
+                out << arrayBrackets(*fieldType);
+            out << ";\n";
+        }
+        out << "}";
+        mDeclaredStructs.insert(type.getTypeName());
+    }
+    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 << " " << 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)
+    {
+        out << type.getTypeName() << "(";
+        const TTypeList* structure = type.getStruct();
+        ASSERT(structure != NULL);
+        for (size_t i = 0; i < structure->size(); ++i)
+        {
+            const TType* fieldType = (*structure)[i].type;
+            ASSERT(fieldType != NULL);
+            pConstUnion = writeConstantUnion(*fieldType, pConstUnion);
+            if (i != structure->size() - 1) out << ", ";
+        }
+        out << ")";
+    }
+    else
+    {
+        int size = type.getObjectSize();
+        bool writeType = size > 1;
+        if (writeType) out << getTypeName(type) << "(";
+        for (int i = 0; i < size; ++i, ++pConstUnion)
+        {
+            switch (pConstUnion->getType())
+            {
+                case EbtFloat: out << 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 << 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:
+        case EOpIndexIndirect:
+            writeTriplet(visit, NULL, "[", "]");
+            break;
+        case EOpIndexDirectStruct:
+            if (visit == InVisit)
+            {
+                out << ".";
+                // TODO(alokp): ASSERT
+                out << node->getType().getFieldName();
+                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();
+        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();
+            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 << " " << node->getName();
+
+            out << "(";
+            writeFunctionParameters(node->getSequence());
+            out << ")";
+
+            visitChildren = false;
+            break;
+        }
+        case EOpFunction: {
+            // Function definition.
+            ASSERT(visit == PreVisit);
+            writeVariableType(node->getType());
+            out << " " << TFunction::unmangleName(node->getName());
+
+            incrementDepth();
+            // 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)
+            {
+                TString functionName = TFunction::unmangleName(node->getName());
+                out << functionName << "(";
+            }
+            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 << type.getTypeName() << "(";
+            }
+            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();
+    // 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.
+    }
+}
diff --git a/src/3rdparty/angle/src/compiler/OutputGLSLBase.h b/src/3rdparty/angle/src/compiler/OutputGLSLBase.h
new file mode 100644 (file)
index 0000000..efd0b5f
--- /dev/null
@@ -0,0 +1,53 @@
+//
+// 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/ForLoopUnroll.h"
+#include "compiler/intermediate.h"
+#include "compiler/ParseHelper.h"
+
+class TOutputGLSLBase : public TIntermTraverser
+{
+public:
+    TOutputGLSLBase(TInfoSinkBase& objSink);
+
+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);
+
+    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);
+
+private:
+    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;
+};
+
+#endif  // CROSSCOMPILERGLSL_OUTPUTGLSLBASE_H_
diff --git a/src/3rdparty/angle/src/compiler/OutputHLSL.cpp b/src/3rdparty/angle/src/compiler/OutputHLSL.cpp
new file mode 100644 (file)
index 0000000..a430695
--- /dev/null
@@ -0,0 +1,2664 @@
+//
+// 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/OutputHLSL.h"
+
+#include "common/angleutils.h"
+#include "compiler/debug.h"
+#include "compiler/InfoSink.h"
+#include "compiler/UnfoldShortCircuit.h"
+#include "compiler/SearchSymbol.h"
+#include "compiler/DetectDiscontinuity.h"
+
+#include <stdio.h>
+#include <algorithm>
+
+namespace sh
+{
+// Integer to TString conversion
+TString str(int i)
+{
+    char buffer[20];
+    snprintf(buffer, sizeof(buffer), "%d", i);
+    return buffer;
+}
+
+OutputHLSL::OutputHLSL(TParseContext &context) : TIntermTraverser(true, true, true), mContext(context)
+{
+    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;
+    mUsesDepthRange = false;
+    mUsesFragCoord = false;
+    mUsesPointCoord = false;
+    mUsesFrontFacing = false;
+    mUsesPointSize = 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;
+    mUsesEqualMat2 = false;
+    mUsesEqualMat3 = false;
+    mUsesEqualMat4 = false;
+    mUsesEqualVec2 = false;
+    mUsesEqualVec3 = false;
+    mUsesEqualVec4 = false;
+    mUsesEqualIVec2 = false;
+    mUsesEqualIVec3 = false;
+    mUsesEqualIVec4 = false;
+    mUsesEqualBVec2 = false;
+    mUsesEqualBVec3 = false;
+    mUsesEqualBVec4 = false;
+    mUsesAtan2_1 = false;
+    mUsesAtan2_2 = false;
+    mUsesAtan2_3 = false;
+    mUsesAtan2_4 = false;
+
+    mScopeDepth = 0;
+
+    mUniqueIndex = 0;
+
+    mContainsLoopDiscontinuity = false;
+    mOutputLod0Function = false;
+    mInsideDiscontinuousLoop = false;
+
+    mExcessiveLoopIndex = NULL;
+}
+
+OutputHLSL::~OutputHLSL()
+{
+    delete mUnfoldShortCircuit;
+}
+
+void OutputHLSL::output()
+{
+    mContainsLoopDiscontinuity = containsLoopDiscontinuity(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;
+}
+
+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;
+    }
+
+    if (shaderType == SH_FRAGMENT_SHADER)
+    {
+        TString uniforms;
+        TString varyings;
+
+        TSymbolTableLevel *symbols = mContext.symbolTable.getGlobalLevel();
+        int semanticIndex = 0;
+
+        for (TSymbolTableLevel::const_iterator namedSymbol = symbols->begin(); namedSymbol != symbols->end(); namedSymbol++)
+        {
+            const TSymbol *symbol = (*namedSymbol).second;
+            const TString &name = symbol->getName();
+
+            if (symbol->isVariable())
+            {
+                const TVariable *variable = static_cast<const TVariable*>(symbol);
+                const TType &type = variable->getType();
+                TQualifier qualifier = type.getQualifier();
+
+                if (qualifier == EvqUniform)
+                {
+                    if (mReferencedUniforms.find(name.c_str()) != mReferencedUniforms.end())
+                    {
+                        uniforms += "uniform " + typeString(type) + " " + decorateUniform(name, type) + arrayString(type) + ";\n";
+                    }
+                }
+                else if (qualifier == EvqVaryingIn || qualifier == EvqInvariantVaryingIn)
+                {
+                    if (mReferencedVaryings.find(name.c_str()) != mReferencedVaryings.end())
+                    {
+                        // Program linking depends on this exact format
+                        varyings += "static " + typeString(type) + " " + decorate(name) + arrayString(type) + " = " + initializer(type) + ";\n";
+
+                        semanticIndex += type.isArray() ? type.getArraySize() : 1;
+                    }
+                }
+                else if (qualifier == EvqGlobal || qualifier == EvqTemporary)
+                {
+                    // Globals are declared and intialized as an aggregate node
+                }
+                else if (qualifier == EvqConst)
+                {
+                    // Constants are repeated as literals where used
+                }
+                else UNREACHABLE();
+            }
+        }
+
+        out << "// Varyings\n";
+        out <<  varyings;
+        out << "\n"
+               "static float4 gl_Color[1] = {float4(0, 0, 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 (mUsesFragCoord)
+        {
+            out << "uniform float4 dx_Coord;\n"
+                   "uniform float2 dx_Depth;\n";
+        }
+
+        if (mUsesFrontFacing)
+        {
+            out << "uniform bool dx_PointsOrLines;\n"
+                   "uniform bool dx_FrontCCW;\n";
+        }
+        
+        out << "\n";
+        out <<  uniforms;
+        out << "\n";
+
+        if (mUsesTexture2D)
+        {
+            out << "float4 gl_texture2D(sampler2D s, float2 t)\n"
+                   "{\n"
+                   "    return tex2D(s, t);\n"
+                   "}\n"
+                   "\n";
+        }
+
+        if (mUsesTexture2D_bias)
+        {
+            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";
+        }
+
+        if (mUsesTexture2DProj)
+        {
+            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";
+        }
+
+        if (mUsesTexture2DProj_bias)
+        {
+            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";
+        }
+
+        if (mUsesTextureCube)
+        {
+            out << "float4 gl_textureCube(samplerCUBE s, float3 t)\n"
+                   "{\n"
+                   "    return texCUBE(s, t);\n"
+                   "}\n"
+                   "\n";
+        }
+
+        if (mUsesTextureCube_bias)
+        {
+            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";
+        }
+
+        // These *Lod0 intrinsics are not available in GL fragment shaders.
+        // They are used to sample using discontinuous texture coordinates.
+        if (mUsesTexture2DLod0)
+        {
+            out << "float4 gl_texture2DLod0(sampler2D s, float2 t)\n"
+                   "{\n"
+                   "    return tex2Dlod(s, float4(t.x, t.y, 0, 0));\n"
+                   "}\n"
+                   "\n";
+        }
+
+        if (mUsesTexture2DLod0_bias)
+        {
+            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";
+        }
+
+        if (mUsesTexture2DProjLod0)
+        {
+            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";
+        }
+
+        if (mUsesTexture2DProjLod0_bias)
+        {
+            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";
+        }
+
+        if (mUsesTextureCubeLod0)
+        {
+            out << "float4 gl_textureCubeLod0(samplerCUBE s, float3 t)\n"
+                   "{\n"
+                   "    return texCUBElod(s, float4(t.x, t.y, t.z, 0));\n"
+                   "}\n"
+                   "\n";
+        }
+
+        if (mUsesTextureCubeLod0_bias)
+        {
+            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   // Vertex shader
+    {
+        TString uniforms;
+        TString attributes;
+        TString varyings;
+
+        TSymbolTableLevel *symbols = mContext.symbolTable.getGlobalLevel();
+
+        for (TSymbolTableLevel::const_iterator namedSymbol = symbols->begin(); namedSymbol != symbols->end(); namedSymbol++)
+        {
+            const TSymbol *symbol = (*namedSymbol).second;
+            const TString &name = symbol->getName();
+
+            if (symbol->isVariable())
+            {
+                const TVariable *variable = static_cast<const TVariable*>(symbol);
+                const TType &type = variable->getType();
+                TQualifier qualifier = type.getQualifier();
+
+                if (qualifier == EvqUniform)
+                {
+                    if (mReferencedUniforms.find(name.c_str()) != mReferencedUniforms.end())
+                    {
+                        uniforms += "uniform " + typeString(type) + " " + decorateUniform(name, type) + arrayString(type) + ";\n";
+                    }
+                }
+                else if (qualifier == EvqAttribute)
+                {
+                    if (mReferencedAttributes.find(name.c_str()) != mReferencedAttributes.end())
+                    {
+                        attributes += "static " + typeString(type) + " " + decorate(name) + arrayString(type) + " = " + initializer(type) + ";\n";
+                    }
+                }
+                else if (qualifier == EvqVaryingOut || qualifier == EvqInvariantVaryingOut)
+                {
+                    if (mReferencedVaryings.find(name.c_str()) != mReferencedVaryings.end())
+                    {
+                        // Program linking depends on this exact format
+                        varyings += "static " + typeString(type) + " " + decorate(name) + arrayString(type) + " = " + initializer(type) + ";\n";
+                    }
+                }
+                else if (qualifier == EvqGlobal || qualifier == EvqTemporary)
+                {
+                    // Globals are declared and intialized as an aggregate node
+                }
+                else if (qualifier == EvqConst)
+                {
+                    // Constants are repeated as literals where used
+                }
+                else UNREACHABLE();
+            }
+        }
+
+        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"
+               "uniform float2 dx_HalfPixelSize;\n"
+               "\n";
+        out <<  uniforms;
+        out << "\n";
+        
+        if (mUsesTexture2D)
+        {
+            out << "float4 gl_texture2D(sampler2D s, float2 t)\n"
+                   "{\n"
+                   "    return tex2Dlod(s, float4(t.x, t.y, 0, 0));\n"
+                   "}\n"
+                   "\n";
+        }
+
+        if (mUsesTexture2DLod)
+        {
+            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";
+        }
+
+        if (mUsesTexture2DProj)
+        {
+            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";
+        }
+
+        if (mUsesTexture2DProjLod)
+        {
+            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";
+        }
+
+        if (mUsesTextureCube)
+        {
+            out << "float4 gl_textureCube(samplerCUBE s, float3 t)\n"
+                   "{\n"
+                   "    return texCUBElod(s, float4(t.x, t.y, t.z, 0));\n"
+                   "}\n"
+                   "\n";
+        }
+
+        if (mUsesTextureCubeLod)
+        {
+            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";
+        }
+    }
+
+    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 (mUsesDepthRange)
+    {
+        out << "struct gl_DepthRangeParameters\n"
+               "{\n"
+               "    float near;\n"
+               "    float far;\n"
+               "    float diff;\n"
+               "};\n"
+               "\n"
+               "uniform float3 dx_DepthRange;"
+               "static gl_DepthRangeParameters gl_DepthRange = {dx_DepthRange.x, dx_DepthRange.y, dx_DepthRange.z};\n"
+               "\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 (mUsesEqualMat2)
+    {
+        out << "bool equal(float2x2 m, float2x2 n)\n"
+               "{\n"
+               "    return m[0][0] == n[0][0] && m[0][1] == n[0][1] &&\n"
+               "           m[1][0] == n[1][0] && m[1][1] == n[1][1];\n"
+               "}\n";
+    }
+
+    if (mUsesEqualMat3)
+    {
+        out << "bool equal(float3x3 m, float3x3 n)\n"
+               "{\n"
+               "    return m[0][0] == n[0][0] && m[0][1] == n[0][1] && m[0][2] == n[0][2] &&\n"
+               "           m[1][0] == n[1][0] && m[1][1] == n[1][1] && m[1][2] == n[1][2] &&\n"
+               "           m[2][0] == n[2][0] && m[2][1] == n[2][1] && m[2][2] == n[2][2];\n"
+               "}\n";
+    }
+
+    if (mUsesEqualMat4)
+    {
+        out << "bool equal(float4x4 m, float4x4 n)\n"
+               "{\n"
+               "    return m[0][0] == n[0][0] && m[0][1] == n[0][1] && m[0][2] == n[0][2] && m[0][3] == n[0][3] &&\n"
+               "           m[1][0] == n[1][0] && m[1][1] == n[1][1] && m[1][2] == n[1][2] && m[1][3] == n[1][3] &&\n"
+               "           m[2][0] == n[2][0] && m[2][1] == n[2][1] && m[2][2] == n[2][2] && m[2][3] == n[2][3] &&\n"
+               "           m[3][0] == n[3][0] && m[3][1] == n[3][1] && m[3][2] == n[3][2] && m[3][3] == n[3][3];\n"
+               "}\n";
+    }
+
+    if (mUsesEqualVec2)
+    {
+        out << "bool equal(float2 v, float2 u)\n"
+               "{\n"
+               "    return v.x == u.x && v.y == u.y;\n"
+               "}\n";
+    }
+
+    if (mUsesEqualVec3)
+    {
+        out << "bool equal(float3 v, float3 u)\n"
+               "{\n"
+               "    return v.x == u.x && v.y == u.y && v.z == u.z;\n"
+               "}\n";
+    }
+
+    if (mUsesEqualVec4)
+    {
+        out << "bool equal(float4 v, float4 u)\n"
+               "{\n"
+               "    return v.x == u.x && v.y == u.y && v.z == u.z && v.w == u.w;\n"
+               "}\n";
+    }
+
+    if (mUsesEqualIVec2)
+    {
+        out << "bool equal(int2 v, int2 u)\n"
+               "{\n"
+               "    return v.x == u.x && v.y == u.y;\n"
+               "}\n";
+    }
+
+    if (mUsesEqualIVec3)
+    {
+        out << "bool equal(int3 v, int3 u)\n"
+               "{\n"
+               "    return v.x == u.x && v.y == u.y && v.z == u.z;\n"
+               "}\n";
+    }
+
+    if (mUsesEqualIVec4)
+    {
+        out << "bool equal(int4 v, int4 u)\n"
+               "{\n"
+               "    return v.x == u.x && v.y == u.y && v.z == u.z && v.w == u.w;\n"
+               "}\n";
+    }
+
+    if (mUsesEqualBVec2)
+    {
+        out << "bool equal(bool2 v, bool2 u)\n"
+               "{\n"
+               "    return v.x == u.x && v.y == u.y;\n"
+               "}\n";
+    }
+
+    if (mUsesEqualBVec3)
+    {
+        out << "bool equal(bool3 v, bool3 u)\n"
+               "{\n"
+               "    return v.x == u.x && v.y == u.y && v.z == u.z;\n"
+               "}\n";
+    }
+
+    if (mUsesEqualBVec4)
+    {
+        out << "bool equal(bool4 v, bool4 u)\n"
+               "{\n"
+               "    return v.x == u.x && v.y == u.y && v.z == u.z && v.w == u.w;\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]";
+    }
+    else if (name == "gl_FragData")
+    {
+        out << "gl_Color";
+    }
+    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
+    {
+        TQualifier qualifier = node->getQualifier();
+
+        if (qualifier == EvqUniform)
+        {
+            mReferencedUniforms.insert(name.c_str());
+            out << decorateUniform(name, node->getType());
+        }
+        else if (qualifier == EvqAttribute)
+        {
+            mReferencedAttributes.insert(name.c_str());
+            out << decorate(name);
+        }
+        else if (qualifier == EvqVaryingOut || qualifier == EvqInvariantVaryingOut || qualifier == EvqVaryingIn || qualifier == EvqInvariantVaryingIn)
+        {
+            mReferencedVaryings.insert(name.c_str());
+            out << decorate(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, "(", " *= ", ")");          break;
+      case EOpMatrixTimesScalarAssign: outputTriplet(visit, "(", " *= ", ")");          break;
+      case EOpVectorTimesMatrixAssign:
+        if (visit == PreVisit)
+        {
+            out << "(";
+        }
+        else if (visit == InVisit)
+        {
+            out << " = mul(";
+            node->getLeft()->traverse(this);
+            out << ", transpose(";   
+        }
+        else
+        {
+            out << ")))";
+        }
+        break;
+      case EOpMatrixTimesMatrixAssign:
+        if (visit == PreVisit)
+        {
+            out << "(";
+        }
+        else if (visit == InVisit)
+        {
+            out << " = mul(";
+            node->getLeft()->traverse(this);
+            out << ", ";   
+        }
+        else
+        {
+            out << "))";
+        }
+        break;
+      case EOpDivAssign:               outputTriplet(visit, "(", " /= ", ")");          break;
+      case EOpIndexDirect:             outputTriplet(visit, "", "[", "]");              break;
+      case EOpIndexIndirect:           outputTriplet(visit, "", "[", "]");              break;
+      case EOpIndexDirectStruct:
+        if (visit == InVisit)
+        {
+            out << "." + decorateField(node->getType().getFieldName(), node->getLeft()->getType());
+
+            return false;
+        }
+        break;
+      case EOpVectorSwizzle:
+        if (visit == InVisit)
+        {
+            out << ".";
+
+            TIntermAggregate *swizzle = node->getRight()->getAsAggregate();
+
+            if (swizzle)
+            {
+                TIntermSequence &sequence = swizzle->getSequence();
+
+                for (TIntermSequence::iterator sit = sequence.begin(); sit != sequence.end(); sit++)
+                {
+                    TIntermConstantUnion *element = (*sit)->getAsConstantUnion();
+
+                    if (element)
+                    {
+                        int i = element->getUnionArrayPointer()[0].getIConst();
+
+                        switch (i)
+                        {
+                        case 0: out << "x"; break;
+                        case 1: out << "y"; break;
+                        case 2: out << "z"; break;
+                        case 3: out << "w"; break;
+                        default: UNREACHABLE();
+                        }
+                    }
+                    else UNREACHABLE();
+                }
+            }
+            else UNREACHABLE();
+
+            return false;   // Fully processed
+        }
+        break;
+      case EOpAdd:               outputTriplet(visit, "(", " + ", ")"); break;
+      case EOpSub:               outputTriplet(visit, "(", " - ", ")"); break;
+      case EOpMul:               outputTriplet(visit, "(", " * ", ")"); break;
+      case EOpDiv:               outputTriplet(visit, "(", " / ", ")"); break;
+      case EOpEqual:
+      case EOpNotEqual:
+        if (node->getLeft()->isScalar())
+        {
+            if (node->getOp() == EOpEqual)
+            {
+                outputTriplet(visit, "(", " == ", ")");
+            }
+            else
+            {
+                outputTriplet(visit, "(", " != ", ")");
+            }
+        }
+        else if (node->getLeft()->getBasicType() == EbtStruct)
+        {
+            if (node->getOp() == EOpEqual)
+            {
+                out << "(";
+            }
+            else
+            {
+                out << "!(";
+            }
+
+            const TTypeList *fields = node->getLeft()->getType().getStruct();
+
+            for (size_t i = 0; i < fields->size(); i++)
+            {
+                const TType *fieldType = (*fields)[i].type;
+
+                node->getLeft()->traverse(this);
+                out << "." + decorateField(fieldType->getFieldName(), node->getLeft()->getType()) + " == ";
+                node->getRight()->traverse(this);
+                out << "." + decorateField(fieldType->getFieldName(), node->getLeft()->getType());
+
+                if (i < fields->size() - 1)
+                {
+                    out << " && ";
+                }
+            }
+
+            out << ")";
+
+            return false;
+        }
+        else
+        {
+            if (node->getLeft()->isMatrix())
+            {
+                switch (node->getLeft()->getNominalSize())
+                {
+                  case 2: mUsesEqualMat2 = true; break;
+                  case 3: mUsesEqualMat3 = true; break;
+                  case 4: mUsesEqualMat4 = true; break;
+                  default: UNREACHABLE();
+                }
+            }
+            else if (node->getLeft()->isVector())
+            {
+                switch (node->getLeft()->getBasicType())
+                {
+                  case EbtFloat:
+                    switch (node->getLeft()->getNominalSize())
+                    {
+                      case 2: mUsesEqualVec2 = true; break;
+                      case 3: mUsesEqualVec3 = true; break;
+                      case 4: mUsesEqualVec4 = true; break;
+                      default: UNREACHABLE();
+                    }
+                    break;
+                  case EbtInt:
+                    switch (node->getLeft()->getNominalSize())
+                    {
+                      case 2: mUsesEqualIVec2 = true; break;
+                      case 3: mUsesEqualIVec3 = true; break;
+                      case 4: mUsesEqualIVec4 = true; break;
+                      default: UNREACHABLE();
+                    }
+                    break;
+                  case EbtBool:
+                    switch (node->getLeft()->getNominalSize())
+                    {
+                      case 2: mUsesEqualBVec2 = true; break;
+                      case 3: mUsesEqualBVec3 = true; break;
+                      case 4: mUsesEqualBVec4 = true; break;
+                      default: UNREACHABLE();
+                    }
+                    break;
+                  default: UNREACHABLE();
+                }
+            }
+            else UNREACHABLE();
+
+            if (node->getOp() == EOpEqual)
+            {
+                outputTriplet(visit, "equal(", ", ", ")");
+            }
+            else
+            {
+                outputTriplet(visit, "!equal(", ", ", ")");
+            }
+        }
+        break;
+      case EOpLessThan:          outputTriplet(visit, "(", " < ", ")");   break;
+      case EOpGreaterThan:       outputTriplet(visit, "(", " > ", ")");   break;
+      case EOpLessThanEqual:     outputTriplet(visit, "(", " <= ", ")");  break;
+      case EOpGreaterThanEqual:  outputTriplet(visit, "(", " >= ", ")");  break;
+      case EOpVectorTimesScalar: outputTriplet(visit, "(", " * ", ")");   break;
+      case EOpMatrixTimesScalar: outputTriplet(visit, "(", " * ", ")");   break;
+      case EOpVectorTimesMatrix: outputTriplet(visit, "mul(", ", transpose(", "))"); break;
+      case EOpMatrixTimesVector: outputTriplet(visit, "mul(transpose(", "), ", ")"); break;
+      case EOpMatrixTimesMatrix: outputTriplet(visit, "transpose(mul(transpose(", "), transpose(", ")))"); break;
+      case EOpLogicalOr:
+        out << "s" << mUnfoldShortCircuit->getNextTemporaryIndex();
+        return false;
+      case EOpLogicalXor:
+        mUsesXor = true;
+        outputTriplet(visit, "xor(", ", ", ")");
+        break;
+      case EOpLogicalAnd:
+        out << "s" << mUnfoldShortCircuit->getNextTemporaryIndex();
+        return false;
+      default: UNREACHABLE();
+    }
+
+    return true;
+}
+
+bool OutputHLSL::visitUnary(Visit visit, TIntermUnary *node)
+{
+    switch (node->getOp())
+    {
+      case EOpNegative:         outputTriplet(visit, "(-", "", ")");  break;
+      case EOpVectorLogicalNot: outputTriplet(visit, "(!", "", ")");  break;
+      case EOpLogicalNot:       outputTriplet(visit, "(!", "", ")");  break;
+      case EOpPostIncrement:    outputTriplet(visit, "(", "", "++)"); break;
+      case EOpPostDecrement:    outputTriplet(visit, "(", "", "--)"); break;
+      case EOpPreIncrement:     outputTriplet(visit, "(++", "", ")"); break;
+      case EOpPreDecrement:     outputTriplet(visit, "(--", "", ")"); break;
+      case EOpConvIntToBool:
+      case EOpConvFloatToBool:
+        switch (node->getOperand()->getType().getNominalSize())
+        {
+          case 1:    outputTriplet(visit, "bool(", "", ")");  break;
+          case 2:    outputTriplet(visit, "bool2(", "", ")"); break;
+          case 3:    outputTriplet(visit, "bool3(", "", ")"); break;
+          case 4:    outputTriplet(visit, "bool4(", "", ")"); break;
+          default: UNREACHABLE();
+        }
+        break;
+      case EOpConvBoolToFloat:
+      case EOpConvIntToFloat:
+        switch (node->getOperand()->getType().getNominalSize())
+        {
+          case 1:    outputTriplet(visit, "float(", "", ")");  break;
+          case 2:    outputTriplet(visit, "float2(", "", ")"); break;
+          case 3:    outputTriplet(visit, "float3(", "", ")"); break;
+          case 4:    outputTriplet(visit, "float4(", "", ")"); break;
+          default: UNREACHABLE();
+        }
+        break;
+      case EOpConvFloatToInt:
+      case EOpConvBoolToInt:
+        switch (node->getOperand()->getType().getNominalSize())
+        {
+          case 1:    outputTriplet(visit, "int(", "", ")");  break;
+          case 2:    outputTriplet(visit, "int2(", "", ")"); break;
+          case 3:    outputTriplet(visit, "int3(", "", ")"); break;
+          case 4:    outputTriplet(visit, "int4(", "", ")"); break;
+          default: UNREACHABLE();
+        }
+        break;
+      case EOpRadians:          outputTriplet(visit, "radians(", "", ")");   break;
+      case EOpDegrees:          outputTriplet(visit, "degrees(", "", ")");   break;
+      case EOpSin:              outputTriplet(visit, "sin(", "", ")");       break;
+      case EOpCos:              outputTriplet(visit, "cos(", "", ")");       break;
+      case EOpTan:              outputTriplet(visit, "tan(", "", ")");       break;
+      case EOpAsin:             outputTriplet(visit, "asin(", "", ")");      break;
+      case EOpAcos:             outputTriplet(visit, "acos(", "", ")");      break;
+      case EOpAtan:             outputTriplet(visit, "atan(", "", ")");      break;
+      case EOpExp:              outputTriplet(visit, "exp(", "", ")");       break;
+      case EOpLog:              outputTriplet(visit, "log(", "", ")");       break;
+      case EOpExp2:             outputTriplet(visit, "exp2(", "", ")");      break;
+      case EOpLog2:             outputTriplet(visit, "log2(", "", ")");      break;
+      case EOpSqrt:             outputTriplet(visit, "sqrt(", "", ")");      break;
+      case EOpInverseSqrt:      outputTriplet(visit, "rsqrt(", "", ")");     break;
+      case EOpAbs:              outputTriplet(visit, "abs(", "", ")");       break;
+      case EOpSign:             outputTriplet(visit, "sign(", "", ")");      break;
+      case EOpFloor:            outputTriplet(visit, "floor(", "", ")");     break;
+      case EOpCeil:             outputTriplet(visit, "ceil(", "", ")");      break;
+      case EOpFract:            outputTriplet(visit, "frac(", "", ")");      break;
+      case EOpLength:           outputTriplet(visit, "length(", "", ")");    break;
+      case EOpNormalize:        outputTriplet(visit, "normalize(", "", ")"); break;
+      case EOpDFdx:
+        if(mInsideDiscontinuousLoop || mOutputLod0Function)
+        {
+            outputTriplet(visit, "(", "", ", 0.0)");
+        }
+        else
+        {
+            outputTriplet(visit, "ddx(", "", ")");
+        }
+        break;
+      case EOpDFdy:
+        if(mInsideDiscontinuousLoop || mOutputLod0Function)
+        {
+            outputTriplet(visit, "(", "", ", 0.0)");
+        }
+        else
+        {
+           outputTriplet(visit, "ddy(", "", ")");
+        }
+        break;
+      case EOpFwidth:
+        if(mInsideDiscontinuousLoop || mOutputLod0Function)
+        {
+            outputTriplet(visit, "(", "", ", 0.0)");
+        }
+        else
+        {
+            outputTriplet(visit, "fwidth(", "", ")");
+        }
+        break;
+      case EOpAny:              outputTriplet(visit, "any(", "", ")");       break;
+      case EOpAll:              outputTriplet(visit, "all(", "", ")");       break;
+      default: UNREACHABLE();
+    }
+
+    return true;
+}
+
+bool OutputHLSL::visitAggregate(Visit visit, TIntermAggregate *node)
+{
+    TInfoSinkBase &out = mBody;
+
+    switch (node->getOp())
+    {
+      case EOpSequence:
+        {
+            if (mInsideFunction)
+            {
+                outputLineDirective(node->getLine());
+                out << "{\n";
+
+                mScopeDepth++;
+
+                if (mScopeBracket.size() < mScopeDepth)
+                {
+                    mScopeBracket.push_back(0);   // New scope level
+                }
+                else
+                {
+                    mScopeBracket[mScopeDepth - 1]++;   // New scope at existing level
+                }
+            }
+
+            for (TIntermSequence::iterator sit = node->getSequence().begin(); sit != node->getSequence().end(); sit++)
+            {
+                outputLineDirective((*sit)->getLine());
+
+                traverseStatements(*sit);
+
+                out << ";\n";
+            }
+
+            if (mInsideFunction)
+            {
+                outputLineDirective(node->getEndLine());
+                out << "}\n";
+
+                mScopeDepth--;
+            }
+
+            return false;
+        }
+      case EOpDeclaration:
+        if (visit == PreVisit)
+        {
+            TIntermSequence &sequence = node->getSequence();
+            TIntermTyped *variable = sequence[0]->getAsTyped();
+            bool visit = true;
+
+            if (variable && (variable->getQualifier() == EvqTemporary || variable->getQualifier() == EvqGlobal))
+            {
+                if (variable->getType().getStruct())
+                {
+                    addConstructor(variable->getType(), scopedStruct(variable->getType().getTypeName()), NULL);
+                }
+
+                if (!variable->getAsSymbolNode() || variable->getAsSymbolNode()->getSymbol() != "")   // Variable declaration
+                {
+                    if (!mInsideFunction)
+                    {
+                        out << "static ";
+                    }
+
+                    out << typeString(variable->getType()) + " ";
+
+                    for (TIntermSequence::iterator sit = sequence.begin(); sit != sequence.end(); sit++)
+                    {
+                        TIntermSymbol *symbol = (*sit)->getAsSymbolNode();
+
+                        if (symbol)
+                        {
+                            symbol->traverse(this);
+                            out << arrayString(symbol->getType());
+                            out << " = " + initializer(variable->getType());
+                        }
+                        else
+                        {
+                            (*sit)->traverse(this);
+                        }
+
+                        if (visit && this->inVisit)
+                        {
+                            if (*sit != sequence.back())
+                            {
+                                visit = this->visitAggregate(InVisit, node);
+                            }
+                        }
+                    }
+
+                    if (visit && this->postVisit)
+                    {
+                        this->visitAggregate(PostVisit, node);
+                    }
+                }
+                else if (variable->getAsSymbolNode() && variable->getAsSymbolNode()->getSymbol() == "")   // Type (struct) declaration
+                {
+                    // Already added to constructor map
+                }
+                else UNREACHABLE();
+            }
+            
+            return false;
+        }
+        else if (visit == InVisit)
+        {
+            out << ", ";
+        }
+        break;
+      case EOpPrototype:
+        if (visit == PreVisit)
+        {
+            out << typeString(node->getType()) << " " << decorate(node->getName()) << (mOutputLod0Function ? "Lod0(" : "(");
+
+            TIntermSequence &arguments = node->getSequence();
+
+            for (unsigned int i = 0; i < arguments.size(); i++)
+            {
+                TIntermSymbol *symbol = arguments[i]->getAsSymbolNode();
+
+                if (symbol)
+                {
+                    out << argumentString(symbol);
+
+                    if (i < arguments.size() - 1)
+                    {
+                        out << ", ";
+                    }
+                }
+                else UNREACHABLE();
+            }
+
+            out << ");\n";
+
+            // Also prototype the Lod0 variant if needed
+            if (mContainsLoopDiscontinuity && !mOutputLod0Function)
+            {
+                mOutputLod0Function = true;
+                node->traverse(this);
+                mOutputLod0Function = false;
+            }
+
+            return false;
+        }
+        break;
+      case EOpComma:            outputTriplet(visit, "(", ", ", ")");                break;
+      case EOpFunction:
+        {
+            TString name = TFunction::unmangleName(node->getName());
+
+            out << typeString(node->getType()) << " ";
+
+            if (name == "main")
+            {
+                out << "gl_main(";
+            }
+            else
+            {
+                out << decorate(name) << (mOutputLod0Function ? "Lod0(" : "(");
+            }
+
+            TIntermSequence &sequence = node->getSequence();
+            TIntermSequence &arguments = sequence[0]->getAsAggregate()->getSequence();
+
+            for (unsigned int i = 0; i < arguments.size(); i++)
+            {
+                TIntermSymbol *symbol = arguments[i]->getAsSymbolNode();
+
+                if (symbol)
+                {
+                    if (symbol->getType().getStruct())
+                    {
+                        addConstructor(symbol->getType(), scopedStruct(symbol->getType().getTypeName()), NULL);
+                    }
+
+                    out << argumentString(symbol);
+
+                    if (i < arguments.size() - 1)
+                    {
+                        out << ", ";
+                    }
+                }
+                else UNREACHABLE();
+            }
+
+            out << ")\n"
+                "{\n";
+            
+            if (sequence.size() > 1)
+            {
+                mInsideFunction = true;
+                sequence[1]->traverse(this);
+                mInsideFunction = false;
+            }
+            
+            out << "}\n";
+
+            if (mContainsLoopDiscontinuity && !mOutputLod0Function)
+            {
+                if (name != "main")
+                {
+                    mOutputLod0Function = true;
+                    node->traverse(this);
+                    mOutputLod0Function = false;
+                }
+            }
+
+            return false;
+        }
+        break;
+      case EOpFunctionCall:
+        {
+            if (visit == PreVisit)
+            {
+                TString name = TFunction::unmangleName(node->getName());
+                bool lod0 = mInsideDiscontinuousLoop || mOutputLod0Function;
+
+                if (node->isUserDefined())
+                {
+                    out << decorate(name) << (lod0 ? "Lod0(" : "(");
+                }
+                else
+                {
+                    if (name == "texture2D")
+                    {
+                        if (!lod0)
+                        {
+                            if (node->getSequence().size() == 2)
+                            {
+                                mUsesTexture2D = true;
+                            }
+                            else if (node->getSequence().size() == 3)
+                            {
+                                mUsesTexture2D_bias = true;
+                            }
+                            else UNREACHABLE();
+
+                            out << "gl_texture2D(";
+                        }
+                        else
+                        {
+                            if (node->getSequence().size() == 2)
+                            {
+                                mUsesTexture2DLod0 = true;
+                            }
+                            else if (node->getSequence().size() == 3)
+                            {
+                                mUsesTexture2DLod0_bias = true;
+                            }
+                            else UNREACHABLE();
+
+                            out << "gl_texture2DLod0(";
+                        }
+                    }
+                    else if (name == "texture2DProj")
+                    {
+                        if (!lod0)
+                        {
+                            if (node->getSequence().size() == 2)
+                            {
+                                mUsesTexture2DProj = true;
+                            }
+                            else if (node->getSequence().size() == 3)
+                            {
+                                mUsesTexture2DProj_bias = true;
+                            }
+                            else UNREACHABLE();
+
+                            out << "gl_texture2DProj(";
+                        }
+                        else
+                        {
+                            if (node->getSequence().size() == 2)
+                            {
+                                mUsesTexture2DProjLod0 = true;
+                            }
+                            else if (node->getSequence().size() == 3)
+                            {
+                                mUsesTexture2DProjLod0_bias = true;
+                            }
+                            else UNREACHABLE();
+
+                            out << "gl_texture2DProjLod0(";
+                        }
+                    }
+                    else if (name == "textureCube")
+                    {
+                        if (!lod0)
+                        {
+                            if (node->getSequence().size() == 2)
+                            {
+                                mUsesTextureCube = true;
+                            }
+                            else if (node->getSequence().size() == 3)
+                            {
+                                mUsesTextureCube_bias = true;
+                            }
+                            else UNREACHABLE();
+
+                            out << "gl_textureCube(";
+                        }
+                        else
+                        {
+                            if (node->getSequence().size() == 2)
+                            {
+                                mUsesTextureCubeLod0 = true;
+                            }
+                            else if (node->getSequence().size() == 3)
+                            {
+                                mUsesTextureCubeLod0_bias = true;
+                            }
+                            else UNREACHABLE();
+
+                            out << "gl_textureCubeLod0(";
+                        }
+                    }
+                    else if (name == "texture2DLod")
+                    {
+                        if (node->getSequence().size() == 3)
+                        {
+                            mUsesTexture2DLod = true;
+                        }
+                        else UNREACHABLE();
+
+                        out << "gl_texture2DLod(";
+                    }
+                    else if (name == "texture2DProjLod")
+                    {
+                        if (node->getSequence().size() == 3)
+                        {
+                            mUsesTexture2DProjLod = true;
+                        }
+                        else UNREACHABLE();
+
+                        out << "gl_texture2DProjLod(";
+                    }
+                    else if (name == "textureCubeLod")
+                    {
+                        if (node->getSequence().size() == 3)
+                        {
+                            mUsesTextureCubeLod = true;
+                        }
+                        else UNREACHABLE();
+
+                        out << "gl_textureCubeLod(";
+                    }
+                    else UNREACHABLE();
+                }
+            }
+            else if (visit == InVisit)
+            {
+                out << ", ";
+            }
+            else
+            {
+                out << ")";
+            }
+        }
+        break;
+      case EOpParameters:       outputTriplet(visit, "(", ", ", ")\n{\n");             break;
+      case EOpConstructFloat:
+        addConstructor(node->getType(), "vec1", &node->getSequence());
+        outputTriplet(visit, "vec1(", "", ")");
+        break;
+      case EOpConstructVec2:
+        addConstructor(node->getType(), "vec2", &node->getSequence());
+        outputTriplet(visit, "vec2(", ", ", ")");
+        break;
+      case EOpConstructVec3:
+        addConstructor(node->getType(), "vec3", &node->getSequence());
+        outputTriplet(visit, "vec3(", ", ", ")");
+        break;
+      case EOpConstructVec4:
+        addConstructor(node->getType(), "vec4", &node->getSequence());
+        outputTriplet(visit, "vec4(", ", ", ")");
+        break;
+      case EOpConstructBool:
+        addConstructor(node->getType(), "bvec1", &node->getSequence());
+        outputTriplet(visit, "bvec1(", "", ")");
+        break;
+      case EOpConstructBVec2:
+        addConstructor(node->getType(), "bvec2", &node->getSequence());
+        outputTriplet(visit, "bvec2(", ", ", ")");
+        break;
+      case EOpConstructBVec3:
+        addConstructor(node->getType(), "bvec3", &node->getSequence());
+        outputTriplet(visit, "bvec3(", ", ", ")");
+        break;
+      case EOpConstructBVec4:
+        addConstructor(node->getType(), "bvec4", &node->getSequence());
+        outputTriplet(visit, "bvec4(", ", ", ")");
+        break;
+      case EOpConstructInt:
+        addConstructor(node->getType(), "ivec1", &node->getSequence());
+        outputTriplet(visit, "ivec1(", "", ")");
+        break;
+      case EOpConstructIVec2:
+        addConstructor(node->getType(), "ivec2", &node->getSequence());
+        outputTriplet(visit, "ivec2(", ", ", ")");
+        break;
+      case EOpConstructIVec3:
+        addConstructor(node->getType(), "ivec3", &node->getSequence());
+        outputTriplet(visit, "ivec3(", ", ", ")");
+        break;
+      case EOpConstructIVec4:
+        addConstructor(node->getType(), "ivec4", &node->getSequence());
+        outputTriplet(visit, "ivec4(", ", ", ")");
+        break;
+      case EOpConstructMat2:
+        addConstructor(node->getType(), "mat2", &node->getSequence());
+        outputTriplet(visit, "mat2(", ", ", ")");
+        break;
+      case EOpConstructMat3:
+        addConstructor(node->getType(), "mat3", &node->getSequence());
+        outputTriplet(visit, "mat3(", ", ", ")");
+        break;
+      case EOpConstructMat4: 
+        addConstructor(node->getType(), "mat4", &node->getSequence());
+        outputTriplet(visit, "mat4(", ", ", ")");
+        break;
+      case EOpConstructStruct:
+        addConstructor(node->getType(), scopedStruct(node->getType().getTypeName()), &node->getSequence());
+        outputTriplet(visit, structLookup(node->getType().getTypeName()) + "_ctor(", ", ", ")");
+        break;
+      case EOpLessThan:         outputTriplet(visit, "(", " < ", ")");                 break;
+      case EOpGreaterThan:      outputTriplet(visit, "(", " > ", ")");                 break;
+      case EOpLessThanEqual:    outputTriplet(visit, "(", " <= ", ")");                break;
+      case EOpGreaterThanEqual: outputTriplet(visit, "(", " >= ", ")");                break;
+      case EOpVectorEqual:      outputTriplet(visit, "(", " == ", ")");                break;
+      case EOpVectorNotEqual:   outputTriplet(visit, "(", " != ", ")");                break;
+      case EOpMod:
+        {
+            // We need to look at the number of components in both arguments
+            switch (node->getSequence()[0]->getAsTyped()->getNominalSize() * 10
+                     + node->getSequence()[1]->getAsTyped()->getNominalSize())
+            {
+              case 11: mUsesMod1 = true; break;
+              case 22: mUsesMod2v = true; break;
+              case 21: mUsesMod2f = true; break;
+              case 33: mUsesMod3v = true; break;
+              case 31: mUsesMod3f = true; break;
+              case 44: mUsesMod4v = true; break;
+              case 41: mUsesMod4f = true; break;
+              default: UNREACHABLE();
+            }
+
+            outputTriplet(visit, "mod(", ", ", ")");
+        }
+        break;
+      case EOpPow:              outputTriplet(visit, "pow(", ", ", ")");               break;
+      case EOpAtan:
+        ASSERT(node->getSequence().size() == 2);   // atan(x) is a unary operator
+        switch (node->getSequence()[0]->getAsTyped()->getNominalSize())
+        {
+          case 1: mUsesAtan2_1 = true; break;
+          case 2: mUsesAtan2_2 = true; break;
+          case 3: mUsesAtan2_3 = true; break;
+          case 4: mUsesAtan2_4 = true; break;
+          default: UNREACHABLE();
+        }
+        outputTriplet(visit, "atanyx(", ", ", ")");
+        break;
+      case EOpMin:           outputTriplet(visit, "min(", ", ", ")");           break;
+      case EOpMax:           outputTriplet(visit, "max(", ", ", ")");           break;
+      case EOpClamp:         outputTriplet(visit, "clamp(", ", ", ")");         break;
+      case EOpMix:           outputTriplet(visit, "lerp(", ", ", ")");          break;
+      case EOpStep:          outputTriplet(visit, "step(", ", ", ")");          break;
+      case EOpSmoothStep:    outputTriplet(visit, "smoothstep(", ", ", ")");    break;
+      case EOpDistance:      outputTriplet(visit, "distance(", ", ", ")");      break;
+      case EOpDot:           outputTriplet(visit, "dot(", ", ", ")");           break;
+      case EOpCross:         outputTriplet(visit, "cross(", ", ", ")");         break;
+      case EOpFaceForward:
+        {
+            switch (node->getSequence()[0]->getAsTyped()->getNominalSize())   // Number of components in the first argument
+            {
+            case 1: mUsesFaceforward1 = true; break;
+            case 2: mUsesFaceforward2 = true; break;
+            case 3: mUsesFaceforward3 = true; break;
+            case 4: mUsesFaceforward4 = true; break;
+            default: UNREACHABLE();
+            }
+            
+            outputTriplet(visit, "faceforward(", ", ", ")");
+        }
+        break;
+      case EOpReflect:       outputTriplet(visit, "reflect(", ", ", ")");       break;
+      case EOpRefract:       outputTriplet(visit, "refract(", ", ", ")");       break;
+      case EOpMul:           outputTriplet(visit, "(", " * ", ")");             break;
+      default: UNREACHABLE();
+    }
+
+    return true;
+}
+
+bool OutputHLSL::visitSelection(Visit visit, TIntermSelection *node)
+{
+    TInfoSinkBase &out = mBody;
+
+    if (node->usesTernaryOperator())
+    {
+        out << "s" << mUnfoldShortCircuit->getNextTemporaryIndex();
+    }
+    else  // if/else statement
+    {
+        mUnfoldShortCircuit->traverse(node->getCondition());
+
+        out << "if(";
+
+        node->getCondition()->traverse(this);
+
+        out << ")\n";
+        
+        outputLineDirective(node->getLine());
+        out << "{\n";
+
+        if (node->getTrueBlock())
+        {
+            traverseStatements(node->getTrueBlock());
+        }
+
+        outputLineDirective(node->getLine());
+        out << ";\n}\n";
+
+        if (node->getFalseBlock())
+        {
+            out << "else\n";
+
+            outputLineDirective(node->getFalseBlock()->getLine());
+            out << "{\n";
+
+            outputLineDirective(node->getFalseBlock()->getLine());
+            traverseStatements(node->getFalseBlock());
+
+            outputLineDirective(node->getFalseBlock()->getLine());
+            out << ";\n}\n";
+        }
+    }
+
+    return false;
+}
+
+void OutputHLSL::visitConstantUnion(TIntermConstantUnion *node)
+{
+    writeConstantUnion(node->getType(), node->getUnionArrayPointer());
+}
+
+bool OutputHLSL::visitLoop(Visit visit, TIntermLoop *node)
+{
+    bool wasDiscontinuous = mInsideDiscontinuousLoop;
+
+    if (!mInsideDiscontinuousLoop)
+    {
+        mInsideDiscontinuousLoop = containsLoopDiscontinuity(node);
+    }
+
+    if (handleExcessiveLoop(node))
+    {
+        return false;
+    }
+
+    TInfoSinkBase &out = mBody;
+
+    if (node->getType() == ELoopDoWhile)
+    {
+        out << "{do\n";
+
+        outputLineDirective(node->getLine());
+        out << "{\n";
+    }
+    else
+    {
+        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";
+        
+        outputLineDirective(node->getLine());
+        out << "{\n";
+    }
+
+    if (node->getBody())
+    {
+        traverseStatements(node->getBody());
+    }
+
+    outputLineDirective(node->getLine());
+    out << ";}\n";
+
+    if (node->getType() == ELoopDoWhile)
+    {
+        outputLineDirective(node->getCondition()->getLine());
+        out << "while(\n";
+
+        node->getCondition()->traverse(this);
+
+        out << ");";
+    }
+
+    out << "}\n";
+
+    mInsideDiscontinuousLoop = wasDiscontinuous;
+
+    return false;
+}
+
+bool OutputHLSL::visitBranch(Visit visit, TIntermBranch *node)
+{
+    TInfoSinkBase &out = mBody;
+
+    switch (node->getFlowOp())
+    {
+      case EOpKill:     outputTriplet(visit, "discard;\n", "", "");  break;
+      case EOpBreak:
+        if (visit == PreVisit)
+        {
+            if (mExcessiveLoopIndex)
+            {
+                out << "{Break";
+                mExcessiveLoopIndex->traverse(this);
+                out << " = true; break;}\n";
+            }
+            else
+            {
+                out << "break;\n";
+            }
+        }
+        break;
+      case EOpContinue: outputTriplet(visit, "continue;\n", "", ""); break;
+      case EOpReturn:
+        if (visit == PreVisit)
+        {
+            if (node->getExpression())
+            {
+                out << "return ";
+            }
+            else
+            {
+                out << "return;\n";
+            }
+        }
+        else if (visit == PostVisit)
+        {
+            if (node->getExpression())
+            {
+                out << ";\n";
+            }
+        }
+        break;
+      default: UNREACHABLE();
+    }
+
+    return true;
+}
+
+void OutputHLSL::traverseStatements(TIntermNode *node)
+{
+    if (isSingleStatement(node))
+    {
+        mUnfoldShortCircuit->traverse(node);
+    }
+
+    node->traverse(this);
+}
+
+bool OutputHLSL::isSingleStatement(TIntermNode *node)
+{
+    TIntermAggregate *aggregate = node->getAsAggregate();
+
+    if (aggregate)
+    {
+        if (aggregate->getOp() == EOpSequence)
+        {
+            return false;
+        }
+        else
+        {
+            for (TIntermSequence::iterator sit = aggregate->getSequence().begin(); sit != aggregate->getSequence().end(); sit++)
+            {
+                if (!isSingleStatement(*sit))
+                {
+                    return false;
+                }
+            }
+
+            return true;
+        }
+    }
+
+    return true;
+}
+
+// Handle loops with more than 254 iterations (unsupported by D3D9) by splitting them
+// (The D3D documentation says 255 iterations, but the compiler complains at anything more than 254).
+bool OutputHLSL::handleExcessiveLoop(TIntermLoop *node)
+{
+    const int MAX_LOOP_ITERATIONS = 254;
+    TInfoSinkBase &out = mBody;
+
+    // Parse loops of the form:
+    // for(int index = initial; index [comparator] limit; index += increment)
+    TIntermSymbol *index = NULL;
+    TOperator comparator = EOpNull;
+    int initial = 0;
+    int limit = 0;
+    int increment = 0;
+
+    // Parse index name and intial value
+    if (node->getInit())
+    {
+        TIntermAggregate *init = node->getInit()->getAsAggregate();
+
+        if (init)
+        {
+            TIntermSequence &sequence = init->getSequence();
+            TIntermTyped *variable = sequence[0]->getAsTyped();
+
+            if (variable && variable->getQualifier() == EvqTemporary)
+            {
+                TIntermBinary *assign = variable->getAsBinaryNode();
+
+                if (assign->getOp() == EOpInitialize)
+                {
+                    TIntermSymbol *symbol = assign->getLeft()->getAsSymbolNode();
+                    TIntermConstantUnion *constant = assign->getRight()->getAsConstantUnion();
+
+                    if (symbol && constant)
+                    {
+                        if (constant->getBasicType() == EbtInt && constant->getNominalSize() == 1)
+                        {
+                            index = symbol;
+                            initial = constant->getUnionArrayPointer()[0].getIConst();
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+    // Parse comparator and limit value
+    if (index != NULL && node->getCondition())
+    {
+        TIntermBinary *test = node->getCondition()->getAsBinaryNode();
+        
+        if (test && test->getLeft()->getAsSymbolNode()->getId() == index->getId())
+        {
+            TIntermConstantUnion *constant = test->getRight()->getAsConstantUnion();
+
+            if (constant)
+            {
+                if (constant->getBasicType() == EbtInt && constant->getNominalSize() == 1)
+                {
+                    comparator = test->getOp();
+                    limit = constant->getUnionArrayPointer()[0].getIConst();
+                }
+            }
+        }
+    }
+
+    // Parse increment
+    if (index != NULL && comparator != EOpNull && node->getExpression())
+    {
+        TIntermBinary *binaryTerminal = node->getExpression()->getAsBinaryNode();
+        TIntermUnary *unaryTerminal = node->getExpression()->getAsUnaryNode();
+        
+        if (binaryTerminal)
+        {
+            TOperator op = binaryTerminal->getOp();
+            TIntermConstantUnion *constant = binaryTerminal->getRight()->getAsConstantUnion();
+
+            if (constant)
+            {
+                if (constant->getBasicType() == EbtInt && constant->getNominalSize() == 1)
+                {
+                    int value = constant->getUnionArrayPointer()[0].getIConst();
+
+                    switch (op)
+                    {
+                      case EOpAddAssign: increment = value;  break;
+                      case EOpSubAssign: increment = -value; break;
+                      default: UNIMPLEMENTED();
+                    }
+                }
+            }
+        }
+        else if (unaryTerminal)
+        {
+            TOperator op = unaryTerminal->getOp();
+
+            switch (op)
+            {
+              case EOpPostIncrement: increment = 1;  break;
+              case EOpPostDecrement: increment = -1; break;
+              case EOpPreIncrement:  increment = 1;  break;
+              case EOpPreDecrement:  increment = -1; break;
+              default: UNIMPLEMENTED();
+            }
+        }
+    }
+
+    if (index != NULL && comparator != EOpNull && increment != 0)
+    {
+        if (comparator == EOpLessThanEqual)
+        {
+            comparator = EOpLessThan;
+            limit += 1;
+        }
+
+        if (comparator == EOpLessThan)
+        {
+            int iterations = (limit - initial) / increment;
+
+            if (iterations <= MAX_LOOP_ITERATIONS)
+            {
+                return false;   // Not an excessive loop
+            }
+
+            TIntermSymbol *restoreIndex = mExcessiveLoopIndex;
+            mExcessiveLoopIndex = index;
+
+            out << "{int ";
+            index->traverse(this);
+            out << ";\n"
+                   "bool Break";
+            index->traverse(this);
+            out << " = false;\n";
+
+            bool firstLoopFragment = true;
+
+            while (iterations > 0)
+            {
+                int clampedLimit = initial + increment * std::min(MAX_LOOP_ITERATIONS, iterations);
+
+                if (!firstLoopFragment)
+                {
+                    out << "if(!Break";
+                    index->traverse(this);
+                    out << ") {\n";
+                }
+
+                if (iterations <= MAX_LOOP_ITERATIONS)   // Last loop fragment
+                {
+                    mExcessiveLoopIndex = NULL;   // Stops setting the Break flag
+                }
+                
+                // for(int index = initial; index < clampedLimit; index += increment)
+
+                out << "for(";
+                index->traverse(this);
+                out << " = ";
+                out << initial;
+
+                out << "; ";
+                index->traverse(this);
+                out << " < ";
+                out << clampedLimit;
+
+                out << "; ";
+                index->traverse(this);
+                out << " += ";
+                out << increment;
+                out << ")\n";
+                
+                outputLineDirective(node->getLine());
+                out << "{\n";
+
+                if (node->getBody())
+                {
+                    node->getBody()->traverse(this);
+                }
+
+                outputLineDirective(node->getLine());
+                out << ";}\n";
+
+                if (!firstLoopFragment)
+                {
+                    out << "}\n";
+                }
+
+                firstLoopFragment = false;
+
+                initial += MAX_LOOP_ITERATIONS * increment;
+                iterations -= MAX_LOOP_ITERATIONS;
+            }
+            
+            out << "}";
+
+            mExcessiveLoopIndex = restoreIndex;
+
+            return true;
+        }
+        else UNIMPLEMENTED();
+    }
+
+    return false;   // Not handled as an excessive loop
+}
+
+void OutputHLSL::outputTriplet(Visit visit, const TString &preString, const TString &inString, const TString &postString)
+{
+    TInfoSinkBase &out = mBody;
+
+    if (visit == PreVisit)
+    {
+        out << preString;
+    }
+    else if (visit == InVisit)
+    {
+        out << inString;
+    }
+    else if (visit == PostVisit)
+    {
+        out << postString;
+    }
+}
+
+void OutputHLSL::outputLineDirective(int line)
+{
+    if ((mContext.compileOptions & SH_LINE_DIRECTIVES) && (line > 0))
+    {
+        mBody << "\n";
+        mBody << "#line " << line;
+
+        if (mContext.sourcePath)
+        {
+            mBody << " \"" << mContext.sourcePath << "\"";
+        }
+        
+        mBody << "\n";
+    }
+}
+
+TString OutputHLSL::argumentString(const TIntermSymbol *symbol)
+{
+    TQualifier qualifier = symbol->getQualifier();
+    const TType &type = symbol->getType();
+    TString name = symbol->getSymbol();
+
+    if (name.empty())   // HLSL demands named arguments, also for prototypes
+    {
+        name = "x" + str(mUniqueIndex++);
+    }
+    else
+    {
+        name = decorate(name);
+    }
+
+    return qualifierString(qualifier) + " " + typeString(type) + " " + name + arrayString(type);
+}
+
+TString OutputHLSL::qualifierString(TQualifier qualifier)
+{
+    switch(qualifier)
+    {
+      case EvqIn:            return "in";
+      case EvqOut:           return "out";
+      case EvqInOut:         return "inout";
+      case EvqConstReadOnly: return "const";
+      default: UNREACHABLE();
+    }
+
+    return "";
+}
+
+TString OutputHLSL::typeString(const TType &type)
+{
+    if (type.getBasicType() == EbtStruct)
+    {
+        if (type.getTypeName() != "")
+        {
+            return structLookup(type.getTypeName());
+        }
+        else   // Nameless structure, define in place
+        {
+            const TTypeList &fields = *type.getStruct();
+
+            TString string = "struct\n"
+                             "{\n";
+
+            for (unsigned int i = 0; i < fields.size(); i++)
+            {
+                const TType &field = *fields[i].type;
+
+                string += "    " + typeString(field) + " " + decorate(field.getFieldName()) + arrayString(field) + ";\n";
+            }
+
+            string += "} ";
+
+            return string;
+        }
+    }
+    else if (type.isMatrix())
+    {
+        switch (type.getNominalSize())
+        {
+          case 2: return "float2x2";
+          case 3: return "float3x3";
+          case 4: return "float4x4";
+        }
+    }
+    else
+    {
+        switch (type.getBasicType())
+        {
+          case EbtFloat:
+            switch (type.getNominalSize())
+            {
+              case 1: return "float";
+              case 2: return "float2";
+              case 3: return "float3";
+              case 4: return "float4";
+            }
+          case EbtInt:
+            switch (type.getNominalSize())
+            {
+              case 1: return "int";
+              case 2: return "int2";
+              case 3: return "int3";
+              case 4: return "int4";
+            }
+          case EbtBool:
+            switch (type.getNominalSize())
+            {
+              case 1: return "bool";
+              case 2: return "bool2";
+              case 3: return "bool3";
+              case 4: return "bool4";
+            }
+          case EbtVoid:
+            return "void";
+          case EbtSampler2D:
+            return "sampler2D";
+          case EbtSamplerCube:
+            return "samplerCUBE";
+          case EbtSamplerExternalOES:
+            return "sampler2D";
+          default:
+            break;
+        }
+    }
+
+    UNIMPLEMENTED();   // FIXME
+    return "<unknown type>";
+}
+
+TString OutputHLSL::arrayString(const TType &type)
+{
+    if (!type.isArray())
+    {
+        return "";
+    }
+
+    return "[" + str(type.getArraySize()) + "]";
+}
+
+TString OutputHLSL::initializer(const TType &type)
+{
+    TString string;
+
+    for (int component = 0; component < type.getObjectSize(); component++)
+    {
+        string += "0";
+
+        if (component < type.getObjectSize() - 1)
+        {
+            string += ", ";
+        }
+    }
+
+    return "{" + string + "}";
+}
+
+void OutputHLSL::addConstructor(const TType &type, const TString &name, const TIntermSequence *parameters)
+{
+    if (name == "")
+    {
+        return;   // Nameless structures don't have constructors
+    }
+
+    if (type.getStruct() && mStructNames.find(decorate(name)) != mStructNames.end())
+    {
+        return;   // Already added
+    }
+
+    TType ctorType = type;
+    ctorType.clearArrayness();
+    ctorType.setPrecision(EbpHigh);
+    ctorType.setQualifier(EvqTemporary);
+
+    TString ctorName = type.getStruct() ? decorate(name) : name;
+
+    typedef std::vector<TType> ParameterArray;
+    ParameterArray ctorParameters;
+
+    if (type.getStruct())
+    {
+        mStructNames.insert(decorate(name));
+
+        TString structure;
+        structure += "struct " + decorate(name) + "\n"
+                     "{\n";
+
+        const TTypeList &fields = *type.getStruct();
+
+        for (unsigned int i = 0; i < fields.size(); i++)
+        {
+            const TType &field = *fields[i].type;
+
+            structure += "    " + typeString(field) + " " + decorateField(field.getFieldName(), type) + arrayString(field) + ";\n";
+        }
+
+        structure += "};\n";
+
+        if (std::find(mStructDeclarations.begin(), mStructDeclarations.end(), structure) == mStructDeclarations.end())
+        {
+            mStructDeclarations.push_back(structure);
+        }
+
+        for (unsigned int i = 0; i < fields.size(); i++)
+        {
+            ctorParameters.push_back(*fields[i].type);
+        }
+    }
+    else if (parameters)
+    {
+        for (TIntermSequence::const_iterator parameter = parameters->begin(); parameter != parameters->end(); parameter++)
+        {
+            ctorParameters.push_back((*parameter)->getAsTyped()->getType());
+        }
+    }
+    else UNREACHABLE();
+
+    TString constructor;
+
+    if (ctorType.getStruct())
+    {
+        constructor += ctorName + " " + ctorName + "_ctor(";
+    }
+    else   // Built-in type
+    {
+        constructor += typeString(ctorType) + " " + ctorName + "(";
+    }
+
+    for (unsigned int parameter = 0; parameter < ctorParameters.size(); parameter++)
+    {
+        const TType &type = ctorParameters[parameter];
+
+        constructor += typeString(type) + " x" + str(parameter) + arrayString(type);
+
+        if (parameter < ctorParameters.size() - 1)
+        {
+            constructor += ", ";
+        }
+    }
+
+    constructor += ")\n"
+                   "{\n";
+
+    if (ctorType.getStruct())
+    {
+        constructor += "    " + ctorName + " structure = {";
+    }
+    else
+    {
+        constructor += "    return " + typeString(ctorType) + "(";
+    }
+
+    if (ctorType.isMatrix() && ctorParameters.size() == 1)
+    {
+        int dim = ctorType.getNominalSize();
+        const TType &parameter = ctorParameters[0];
+
+        if (parameter.isScalar())
+        {
+            for (int row = 0; row < dim; row++)
+            {
+                for (int col = 0; col < dim; col++)
+                {
+                    constructor += TString((row == col) ? "x0" : "0.0");
+                    
+                    if (row < dim - 1 || col < dim - 1)
+                    {
+                        constructor += ", ";
+                    }
+                }
+            }
+        }
+        else if (parameter.isMatrix())
+        {
+            for (int row = 0; row < dim; row++)
+            {
+                for (int col = 0; col < dim; col++)
+                {
+                    if (row < parameter.getNominalSize() && col < parameter.getNominalSize())
+                    {
+                        constructor += TString("x0") + "[" + str(row) + "]" + "[" + str(col) + "]";
+                    }
+                    else
+                    {
+                        constructor += TString((row == col) ? "1.0" : "0.0");
+                    }
+
+                    if (row < dim - 1 || col < dim - 1)
+                    {
+                        constructor += ", ";
+                    }
+                }
+            }
+        }
+        else UNREACHABLE();
+    }
+    else
+    {
+        int remainingComponents = ctorType.getObjectSize();
+        int parameterIndex = 0;
+
+        while (remainingComponents > 0)
+        {
+            const TType &parameter = ctorParameters[parameterIndex];
+            bool moreParameters = parameterIndex < (int)ctorParameters.size() - 1;
+
+            constructor += "x" + str(parameterIndex);
+
+            if (parameter.isScalar())
+            {
+                remainingComponents -= parameter.getObjectSize();
+            }
+            else if (parameter.isVector())
+            {
+                if (remainingComponents == parameter.getObjectSize() || moreParameters)
+                {
+                    remainingComponents -= parameter.getObjectSize();
+                }
+                else if (remainingComponents < parameter.getNominalSize())
+                {
+                    switch (remainingComponents)
+                    {
+                      case 1: constructor += ".x";    break;
+                      case 2: constructor += ".xy";   break;
+                      case 3: constructor += ".xyz";  break;
+                      case 4: constructor += ".xyzw"; break;
+                      default: UNREACHABLE();
+                    }
+
+                    remainingComponents = 0;
+                }
+                else UNREACHABLE();
+            }
+            else if (parameter.isMatrix() || parameter.getStruct())
+            {
+                ASSERT(remainingComponents == parameter.getObjectSize() || moreParameters);
+                
+                remainingComponents -= parameter.getObjectSize();
+            }
+            else UNREACHABLE();
+
+            if (moreParameters)
+            {
+                parameterIndex++;
+            }
+
+            if (remainingComponents)
+            {
+                constructor += ", ";
+            }
+        }
+    }
+
+    if (ctorType.getStruct())
+    {
+        constructor += "};\n"
+                       "    return structure;\n"
+                       "}\n";
+    }
+    else
+    {
+        constructor += ");\n"
+                       "}\n";
+    }
+
+    mConstructors.insert(constructor);
+}
+
+const ConstantUnion *OutputHLSL::writeConstantUnion(const TType &type, const ConstantUnion *constUnion)
+{
+    TInfoSinkBase &out = mBody;
+
+    if (type.getBasicType() == EbtStruct)
+    {
+        out << structLookup(type.getTypeName()) + "_ctor(";
+        
+        const TTypeList *structure = type.getStruct();
+
+        for (size_t i = 0; i < structure->size(); i++)
+        {
+            const TType *fieldType = (*structure)[i].type;
+
+            constUnion = writeConstantUnion(*fieldType, constUnion);
+
+            if (i != structure->size() - 1)
+            {
+                out << ", ";
+            }
+        }
+
+        out << ")";
+    }
+    else
+    {
+        int size = type.getObjectSize();
+        bool writeType = size > 1;
+        
+        if (writeType)
+        {
+            out << typeString(type) << "(";
+        }
+
+        for (int i = 0; i < size; i++, constUnion++)
+        {
+            switch (constUnion->getType())
+            {
+              case EbtFloat: out << constUnion->getFConst(); break;
+              case EbtInt:   out << constUnion->getIConst(); break;
+              case EbtBool:  out << constUnion->getBConst(); break;
+              default: UNREACHABLE();
+            }
+
+            if (i != size - 1)
+            {
+                out << ", ";
+            }
+        }
+
+        if (writeType)
+        {
+            out << ")";
+        }
+    }
+
+    return constUnion;
+}
+
+TString OutputHLSL::scopeString(unsigned int depthLimit)
+{
+    TString string;
+
+    for (unsigned int i = 0; i < mScopeBracket.size() && i < depthLimit; i++)
+    {
+        string += "_" + str(i);
+    }
+
+    return string;
+}
+
+TString OutputHLSL::scopedStruct(const TString &typeName)
+{
+    if (typeName == "")
+    {
+        return typeName;
+    }
+
+    return typeName + scopeString(mScopeDepth);
+}
+
+TString OutputHLSL::structLookup(const TString &typeName)
+{
+    for (int depth = mScopeDepth; depth >= 0; depth--)
+    {
+        TString scopedName = decorate(typeName + scopeString(depth));
+
+        for (StructNames::iterator structName = mStructNames.begin(); structName != mStructNames.end(); structName++)
+        {
+            if (*structName == scopedName)
+            {
+                return scopedName;
+            }
+        }
+    }
+
+    UNREACHABLE();   // Should have found a matching constructor
+
+    return typeName;
+}
+
+TString OutputHLSL::decorate(const TString &string)
+{
+    if (string.compare(0, 3, "gl_") != 0 && string.compare(0, 3, "dx_") != 0)
+    {
+        return "_" + string;
+    }
+    
+    return string;
+}
+
+TString OutputHLSL::decorateUniform(const TString &string, const TType &type)
+{
+    if (type.isArray())
+    {
+        return "ar_" + string;   // Allows identifying arrays of size 1
+    }
+    else if (type.getBasicType() == EbtSamplerExternalOES)
+    {
+        return "ex_" + string;
+    }
+    
+    return decorate(string);
+}
+
+TString OutputHLSL::decorateField(const TString &string, const TType &structure)
+{
+    if (structure.getTypeName().compare(0, 3, "gl_") != 0)
+    {
+        return decorate(string);
+    }
+
+    return string;
+}
+}
diff --git a/src/3rdparty/angle/src/compiler/OutputHLSL.h b/src/3rdparty/angle/src/compiler/OutputHLSL.h
new file mode 100644 (file)
index 0000000..dc843fb
--- /dev/null
@@ -0,0 +1,152 @@
+//
+// 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_OUTPUTHLSL_H_
+#define COMPILER_OUTPUTHLSL_H_
+
+#include <list>
+#include <set>
+
+#include "compiler/intermediate.h"
+#include "compiler/ParseHelper.h"
+
+namespace sh
+{
+class UnfoldShortCircuit;
+
+class OutputHLSL : public TIntermTraverser
+{
+  public:
+    explicit OutputHLSL(TParseContext &context);
+    ~OutputHLSL();
+
+    void output();
+
+    TInfoSinkBase &getBodyStream();
+
+    TString typeString(const TType &type);
+    static TString qualifierString(TQualifier qualifier);
+    static TString arrayString(const TType &type);
+    static TString initializer(const TType &type);
+    static TString decorate(const TString &string);                      // Prepends an underscore to avoid naming clashes
+    static TString decorateUniform(const TString &string, const TType &type);
+    static TString decorateField(const TString &string, const TType &structure);
+
+  protected:
+    void header();
+
+    // Visit AST nodes and output their code to the body stream
+    void visitSymbol(TIntermSymbol*);
+    void visitConstantUnion(TIntermConstantUnion*);
+    bool visitBinary(Visit visit, TIntermBinary*);
+    bool visitUnary(Visit visit, TIntermUnary*);
+    bool visitSelection(Visit visit, TIntermSelection*);
+    bool visitAggregate(Visit visit, TIntermAggregate*);
+    bool visitLoop(Visit visit, TIntermLoop*);
+    bool visitBranch(Visit visit, TIntermBranch*);
+
+    void traverseStatements(TIntermNode *node);
+    bool isSingleStatement(TIntermNode *node);
+    bool handleExcessiveLoop(TIntermLoop *node);
+    void outputTriplet(Visit visit, const TString &preString, const TString &inString, const TString &postString);
+    void outputLineDirective(int line);
+    TString argumentString(const TIntermSymbol *symbol);
+    int vectorSize(const TType &type) const;
+
+    void addConstructor(const TType &type, const TString &name, const TIntermSequence *parameters);
+    const ConstantUnion *writeConstantUnion(const TType &type, const ConstantUnion *constUnion);
+
+    TString scopeString(unsigned int depthLimit);
+    TString scopedStruct(const TString &typeName);
+    TString structLookup(const TString &typeName);
+
+    TParseContext &mContext;
+    UnfoldShortCircuit *mUnfoldShortCircuit;
+    bool mInsideFunction;
+
+    // Output streams
+    TInfoSinkBase mHeader;
+    TInfoSinkBase mBody;
+    TInfoSinkBase mFooter;
+
+    std::set<std::string> mReferencedUniforms;
+    std::set<std::string> mReferencedAttributes;
+    std::set<std::string> mReferencedVaryings;
+
+    // Parameters determining what goes in the header output
+    bool mUsesTexture2D;
+    bool mUsesTexture2D_bias;
+    bool mUsesTexture2DLod;
+    bool mUsesTexture2DProj;
+    bool mUsesTexture2DProj_bias;
+    bool mUsesTexture2DProjLod;
+    bool mUsesTextureCube;
+    bool mUsesTextureCube_bias;
+    bool mUsesTextureCubeLod;
+    bool mUsesTexture2DLod0;
+    bool mUsesTexture2DLod0_bias;
+    bool mUsesTexture2DProjLod0;
+    bool mUsesTexture2DProjLod0_bias;
+    bool mUsesTextureCubeLod0;
+    bool mUsesTextureCubeLod0_bias;
+    bool mUsesDepthRange;
+    bool mUsesFragCoord;
+    bool mUsesPointCoord;
+    bool mUsesFrontFacing;
+    bool mUsesPointSize;
+    bool mUsesXor;
+    bool mUsesMod1;
+    bool mUsesMod2v;
+    bool mUsesMod2f;
+    bool mUsesMod3v;
+    bool mUsesMod3f;
+    bool mUsesMod4v;
+    bool mUsesMod4f;
+    bool mUsesFaceforward1;
+    bool mUsesFaceforward2;
+    bool mUsesFaceforward3;
+    bool mUsesFaceforward4;
+    bool mUsesEqualMat2;
+    bool mUsesEqualMat3;
+    bool mUsesEqualMat4;
+    bool mUsesEqualVec2;
+    bool mUsesEqualVec3;
+    bool mUsesEqualVec4;
+    bool mUsesEqualIVec2;
+    bool mUsesEqualIVec3;
+    bool mUsesEqualIVec4;
+    bool mUsesEqualBVec2;
+    bool mUsesEqualBVec3;
+    bool mUsesEqualBVec4;
+    bool mUsesAtan2_1;
+    bool mUsesAtan2_2;
+    bool mUsesAtan2_3;
+    bool mUsesAtan2_4;
+
+    typedef std::set<TString> Constructors;
+    Constructors mConstructors;
+
+    typedef std::set<TString> StructNames;
+    StructNames mStructNames;
+
+    typedef std::list<TString> StructDeclarations;
+    StructDeclarations mStructDeclarations;
+
+    typedef std::vector<int> ScopeBracket;
+    ScopeBracket mScopeBracket;
+    unsigned int mScopeDepth;
+
+    int mUniqueIndex;   // For creating unique names
+
+    bool mContainsLoopDiscontinuity;
+    bool mOutputLod0Function;
+    bool mInsideDiscontinuousLoop;
+
+    TIntermSymbol *mExcessiveLoopIndex;
+};
+}
+
+#endif   // COMPILER_OUTPUTHLSL_H_
diff --git a/src/3rdparty/angle/src/compiler/ParseHelper.cpp b/src/3rdparty/angle/src/compiler/ParseHelper.cpp
new file mode 100644 (file)
index 0000000..508f172
--- /dev/null
@@ -0,0 +1,1528 @@
+//
+// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "compiler/ParseHelper.h"
+
+#include <stdarg.h>
+#include <stdio.h>
+
+#include "compiler/glslang.h"
+#include "compiler/preprocessor/new/SourceLocation.h"
+
+///////////////////////////////////////////////////////////////////////
+//
+// Sub- vector and matrix fields
+//
+////////////////////////////////////////////////////////////////////////
+
+//
+// Look at a '.' field selector string and change it into offsets
+// for a vector.
+//
+bool TParseContext::parseVectorFields(const TString& compString, int vecSize, TVectorFields& fields, int line)
+{
+    fields.num = (int) compString.size();
+    if (fields.num > 4) {
+        error(line, "illegal vector field selection", compString.c_str());
+        return false;
+    }
+
+    enum {
+        exyzw,
+        ergba,
+        estpq,
+    } fieldSet[4];
+
+    for (int i = 0; i < fields.num; ++i) {
+        switch (compString[i])  {
+        case 'x': 
+            fields.offsets[i] = 0;
+            fieldSet[i] = exyzw;
+            break;
+        case 'r': 
+            fields.offsets[i] = 0;
+            fieldSet[i] = ergba;
+            break;
+        case 's':
+            fields.offsets[i] = 0;
+            fieldSet[i] = estpq;
+            break;
+        case 'y': 
+            fields.offsets[i] = 1;
+            fieldSet[i] = exyzw;
+            break;
+        case 'g': 
+            fields.offsets[i] = 1;
+            fieldSet[i] = ergba;
+            break;
+        case 't':
+            fields.offsets[i] = 1;
+            fieldSet[i] = estpq;
+            break;
+        case 'z': 
+            fields.offsets[i] = 2;
+            fieldSet[i] = exyzw;
+            break;
+        case 'b': 
+            fields.offsets[i] = 2;
+            fieldSet[i] = ergba;
+            break;
+        case 'p':
+            fields.offsets[i] = 2;
+            fieldSet[i] = estpq;
+            break;
+        
+        case 'w': 
+            fields.offsets[i] = 3;
+            fieldSet[i] = exyzw;
+            break;
+        case 'a': 
+            fields.offsets[i] = 3;
+            fieldSet[i] = ergba;
+            break;
+        case 'q':
+            fields.offsets[i] = 3;
+            fieldSet[i] = estpq;
+            break;
+        default:
+            error(line, "illegal vector field selection", compString.c_str());
+            return false;
+        }
+    }
+
+    for (int i = 0; i < fields.num; ++i) {
+        if (fields.offsets[i] >= vecSize) {
+            error(line, "vector field selection out of range",  compString.c_str());
+            return false;
+        }
+
+        if (i > 0) {
+            if (fieldSet[i] != fieldSet[i-1]) {
+                error(line, "illegal - vector component fields not from the same set", compString.c_str());
+                return false;
+            }
+        }
+    }
+
+    return true;
+}
+
+
+//
+// Look at a '.' field selector string and change it into offsets
+// for a matrix.
+//
+bool TParseContext::parseMatrixFields(const TString& compString, int matSize, TMatrixFields& fields, int line)
+{
+    fields.wholeRow = false;
+    fields.wholeCol = false;
+    fields.row = -1;
+    fields.col = -1;
+
+    if (compString.size() != 2) {
+        error(line, "illegal length of matrix field selection", compString.c_str());
+        return false;
+    }
+
+    if (compString[0] == '_') {
+        if (compString[1] < '0' || compString[1] > '3') {
+            error(line, "illegal matrix field selection", compString.c_str());
+            return false;
+        }
+        fields.wholeCol = true;
+        fields.col = compString[1] - '0';
+    } else if (compString[1] == '_') {
+        if (compString[0] < '0' || compString[0] > '3') {
+            error(line, "illegal matrix field selection", compString.c_str());
+            return false;
+        }
+        fields.wholeRow = true;
+        fields.row = compString[0] - '0';
+    } else {
+        if (compString[0] < '0' || compString[0] > '3' ||
+            compString[1] < '0' || compString[1] > '3') {
+            error(line, "illegal matrix field selection", compString.c_str());
+            return false;
+        }
+        fields.row = compString[0] - '0';
+        fields.col = compString[1] - '0';
+    }
+
+    if (fields.row >= matSize || fields.col >= matSize) {
+        error(line, "matrix field selection out of range", compString.c_str());
+        return false;
+    }
+
+    return true;
+}
+
+///////////////////////////////////////////////////////////////////////
+//
+// Errors
+//
+////////////////////////////////////////////////////////////////////////
+
+//
+// Track whether errors have occurred.
+//
+void TParseContext::recover()
+{
+}
+
+//
+// Used by flex/bison to output all syntax and parsing errors.
+//
+void TParseContext::error(TSourceLoc loc,
+                          const char* reason, const char* token, 
+                          const char* extraInfo)
+{
+    pp::SourceLocation srcLoc;
+    DecodeSourceLoc(loc, &srcLoc.file, &srcLoc.line);
+    diagnostics.writeInfo(pp::Diagnostics::ERROR,
+                          srcLoc, reason, token, extraInfo);
+
+}
+
+void TParseContext::warning(TSourceLoc loc,
+                            const char* reason, const char* token,
+                            const char* extraInfo) {
+    pp::SourceLocation srcLoc;
+    DecodeSourceLoc(loc, &srcLoc.file, &srcLoc.line);
+    diagnostics.writeInfo(pp::Diagnostics::WARNING,
+                          srcLoc, reason, token, extraInfo);
+}
+
+void TParseContext::trace(const char* str)
+{
+    diagnostics.writeDebug(str);
+}
+
+//
+// Same error message for all places assignments don't work.
+//
+void TParseContext::assignError(int line, const char* op, TString left, TString right)
+{
+    std::stringstream extraInfoStream;
+    extraInfoStream << "cannot convert from '" << right << "' to '" << left << "'";
+    std::string extraInfo = extraInfoStream.str();
+    error(line, "", op, extraInfo.c_str());
+}
+
+//
+// Same error message for all places unary operations don't work.
+//
+void TParseContext::unaryOpError(int line, const char* op, TString operand)
+{
+    std::stringstream extraInfoStream;
+    extraInfoStream << "no operation '" << op << "' exists that takes an operand of type " << operand 
+                    << " (or there is no acceptable conversion)";
+    std::string extraInfo = extraInfoStream.str();
+    error(line, " wrong operand type", op, extraInfo.c_str());
+}
+
+//
+// Same error message for all binary operations don't work.
+//
+void TParseContext::binaryOpError(int line, const char* op, TString left, TString right)
+{
+    std::stringstream extraInfoStream;
+    extraInfoStream << "no operation '" << op << "' exists that takes a left-hand operand of type '" << left 
+                    << "' and a right operand of type '" << right << "' (or there is no acceptable conversion)";
+    std::string extraInfo = extraInfoStream.str();
+    error(line, " wrong operand types ", op, extraInfo.c_str()); 
+}
+
+bool TParseContext::precisionErrorCheck(int line, TPrecision precision, TBasicType type){
+    if (!checksPrecisionErrors)
+        return false;
+    switch( type ){
+    case EbtFloat:
+        if( precision == EbpUndefined ){
+            error( line, "No precision specified for (float)", "" );
+            return true;
+        }
+        break;
+    case EbtInt:
+        if( precision == EbpUndefined ){
+            error( line, "No precision specified (int)", "" );
+            return true;
+        }
+        break;
+    default:
+        return false;
+    }
+    return false;
+}
+
+//
+// Both test and if necessary, spit out an error, to see if the node is really
+// an l-value that can be operated on this way.
+//
+// Returns true if the was an error.
+//
+bool TParseContext::lValueErrorCheck(int line, const char* op, TIntermTyped* node)
+{
+    TIntermSymbol* symNode = node->getAsSymbolNode();
+    TIntermBinary* binaryNode = node->getAsBinaryNode();
+
+    if (binaryNode) {
+        bool errorReturn;
+
+        switch(binaryNode->getOp()) {
+        case EOpIndexDirect:
+        case EOpIndexIndirect:
+        case EOpIndexDirectStruct:
+            return lValueErrorCheck(line, op, binaryNode->getLeft());
+        case EOpVectorSwizzle:
+            errorReturn = lValueErrorCheck(line, op, binaryNode->getLeft());
+            if (!errorReturn) {
+                int offset[4] = {0,0,0,0};
+
+                TIntermTyped* rightNode = binaryNode->getRight();
+                TIntermAggregate *aggrNode = rightNode->getAsAggregate();
+                
+                for (TIntermSequence::iterator p = aggrNode->getSequence().begin(); 
+                                               p != aggrNode->getSequence().end(); p++) {
+                    int value = (*p)->getAsTyped()->getAsConstantUnion()->getUnionArrayPointer()->getIConst();
+                    offset[value]++;     
+                    if (offset[value] > 1) {
+                        error(line, " l-value of swizzle cannot have duplicate components", op);
+
+                        return true;
+                    }
+                }
+            } 
+
+            return errorReturn;
+        default: 
+            break;
+        }
+        error(line, " l-value required", op);
+
+        return true;
+    }
+
+
+    const char* symbol = 0;
+    if (symNode != 0)
+        symbol = symNode->getSymbol().c_str();
+
+    const char* message = 0;
+    switch (node->getQualifier()) {
+    case EvqConst:          message = "can't modify a const";        break;
+    case EvqConstReadOnly:  message = "can't modify a const";        break;
+    case EvqAttribute:      message = "can't modify an attribute";   break;
+    case EvqUniform:        message = "can't modify a uniform";      break;
+    case EvqVaryingIn:      message = "can't modify a varying";      break;
+    case EvqInput:          message = "can't modify an input";       break;
+    case EvqFragCoord:      message = "can't modify gl_FragCoord";   break;
+    case EvqFrontFacing:    message = "can't modify gl_FrontFacing"; break;
+    case EvqPointCoord:     message = "can't modify gl_PointCoord";  break;
+    default:
+
+        //
+        // Type that can't be written to?
+        //
+        switch (node->getBasicType()) {
+        case EbtSampler2D:
+        case EbtSamplerCube:
+            message = "can't modify a sampler";
+            break;
+        case EbtVoid:
+            message = "can't modify void";
+            break;
+        default: 
+            break;
+        }
+    }
+
+    if (message == 0 && binaryNode == 0 && symNode == 0) {
+        error(line, " l-value required", op);
+
+        return true;
+    }
+
+
+    //
+    // Everything else is okay, no error.
+    //
+    if (message == 0)
+        return false;
+
+    //
+    // If we get here, we have an error and a message.
+    //
+    if (symNode) {
+        std::stringstream extraInfoStream;
+        extraInfoStream << "\"" << symbol << "\" (" << message << ")";
+        std::string extraInfo = extraInfoStream.str();
+        error(line, " l-value required", op, extraInfo.c_str());
+    }
+    else {
+        std::stringstream extraInfoStream;
+        extraInfoStream << "(" << message << ")";
+        std::string extraInfo = extraInfoStream.str();
+        error(line, " l-value required", op, extraInfo.c_str());
+    }
+
+    return true;
+}
+
+//
+// Both test, and if necessary spit out an error, to see if the node is really
+// a constant.
+//
+// Returns true if the was an error.
+//
+bool TParseContext::constErrorCheck(TIntermTyped* node)
+{
+    if (node->getQualifier() == EvqConst)
+        return false;
+
+    error(node->getLine(), "constant expression required", "");
+
+    return true;
+}
+
+//
+// Both test, and if necessary spit out an error, to see if the node is really
+// an integer.
+//
+// Returns true if the was an error.
+//
+bool TParseContext::integerErrorCheck(TIntermTyped* node, const char* token)
+{
+    if (node->getBasicType() == EbtInt && node->getNominalSize() == 1)
+        return false;
+
+    error(node->getLine(), "integer expression required", token);
+
+    return true;
+}
+
+//
+// Both test, and if necessary spit out an error, to see if we are currently
+// globally scoped.
+//
+// Returns true if the was an error.
+//
+bool TParseContext::globalErrorCheck(int line, bool global, const char* token)
+{
+    if (global)
+        return false;
+
+    error(line, "only allowed at global scope", token);
+
+    return true;
+}
+
+//
+// For now, keep it simple:  if it starts "gl_", it's reserved, independent
+// of scope.  Except, if the symbol table is at the built-in push-level,
+// which is when we are parsing built-ins.
+// Also checks for "webgl_" and "_webgl_" reserved identifiers if parsing a
+// webgl shader.
+//
+// Returns true if there was an error.
+//
+bool TParseContext::reservedErrorCheck(int line, const TString& identifier)
+{
+    static const char* reservedErrMsg = "reserved built-in name";
+    if (!symbolTable.atBuiltInLevel()) {
+        if (identifier.compare(0, 3, "gl_") == 0) {
+            error(line, reservedErrMsg, "gl_");
+            return true;
+        }
+        if (isWebGLBasedSpec(shaderSpec)) {
+            if (identifier.compare(0, 6, "webgl_") == 0) {
+                error(line, reservedErrMsg, "webgl_");
+                return true;
+            }
+            if (identifier.compare(0, 7, "_webgl_") == 0) {
+                error(line, reservedErrMsg, "_webgl_");
+                return true;
+            }
+            if (shaderSpec == SH_CSS_SHADERS_SPEC && identifier.compare(0, 4, "css_") == 0) {
+                error(line, reservedErrMsg, "css_");
+                return true;
+            }
+        }
+        if (identifier.find("__") != TString::npos) {
+            error(line, "identifiers containing two consecutive underscores (__) are reserved as possible future keywords", identifier.c_str());
+            return true;
+        }
+    }
+
+    return false;
+}
+
+//
+// Make sure there is enough data provided to the constructor to build
+// something of the type of the constructor.  Also returns the type of
+// the constructor.
+//
+// Returns true if there was an error in construction.
+//
+bool TParseContext::constructorErrorCheck(int line, TIntermNode* node, TFunction& function, TOperator op, TType* type)
+{
+    *type = function.getReturnType();
+
+    bool constructingMatrix = false;
+    switch(op) {
+    case EOpConstructMat2:
+    case EOpConstructMat3:
+    case EOpConstructMat4:
+        constructingMatrix = true;
+        break;
+    default: 
+        break;
+    }
+
+    //
+    // Note: It's okay to have too many components available, but not okay to have unused
+    // arguments.  'full' will go to true when enough args have been seen.  If we loop
+    // again, there is an extra argument, so 'overfull' will become true.
+    //
+
+    int size = 0;
+    bool constType = true;
+    bool full = false;
+    bool overFull = false;
+    bool matrixInMatrix = false;
+    bool arrayArg = false;
+    for (int i = 0; i < function.getParamCount(); ++i) {
+        const TParameter& param = function.getParam(i);
+        size += param.type->getObjectSize();
+        
+        if (constructingMatrix && param.type->isMatrix())
+            matrixInMatrix = true;
+        if (full)
+            overFull = true;
+        if (op != EOpConstructStruct && !type->isArray() && size >= type->getObjectSize())
+            full = true;
+        if (param.type->getQualifier() != EvqConst)
+            constType = false;
+        if (param.type->isArray())
+            arrayArg = true;
+    }
+    
+    if (constType)
+        type->setQualifier(EvqConst);
+
+    if (type->isArray() && type->getArraySize() != function.getParamCount()) {
+        error(line, "array constructor needs one argument per array element", "constructor");
+        return true;
+    }
+
+    if (arrayArg && op != EOpConstructStruct) {
+        error(line, "constructing from a non-dereferenced array", "constructor");
+        return true;
+    }
+
+    if (matrixInMatrix && !type->isArray()) {
+        if (function.getParamCount() != 1) {
+          error(line, "constructing matrix from matrix can only take one argument", "constructor");
+          return true;
+        }
+    }
+
+    if (overFull) {
+        error(line, "too many arguments", "constructor");
+        return true;
+    }
+    
+    if (op == EOpConstructStruct && !type->isArray() && int(type->getStruct()->size()) != function.getParamCount()) {
+        error(line, "Number of constructor parameters does not match the number of structure fields", "constructor");
+        return true;
+    }
+
+    if (!type->isMatrix() || !matrixInMatrix) {
+        if ((op != EOpConstructStruct && size != 1 && size < type->getObjectSize()) ||
+            (op == EOpConstructStruct && size < type->getObjectSize())) {
+            error(line, "not enough data provided for construction", "constructor");
+            return true;
+        }
+    }
+
+    TIntermTyped *typed = node ? node->getAsTyped() : 0;
+    if (typed == 0) {
+        error(line, "constructor argument does not have a type", "constructor");
+        return true;
+    }
+    if (op != EOpConstructStruct && IsSampler(typed->getBasicType())) {
+        error(line, "cannot convert a sampler", "constructor");
+        return true;
+    }
+    if (typed->getBasicType() == EbtVoid) {
+        error(line, "cannot convert a void", "constructor");
+        return true;
+    }
+
+    return false;
+}
+
+// This function checks to see if a void variable has been declared and raise an error message for such a case
+//
+// returns true in case of an error
+//
+bool TParseContext::voidErrorCheck(int line, const TString& identifier, const TPublicType& pubType)
+{
+    if (pubType.type == EbtVoid) {
+        error(line, "illegal use of type 'void'", identifier.c_str());
+        return true;
+    } 
+
+    return false;
+}
+
+// This function checks to see if the node (for the expression) contains a scalar boolean expression or not
+//
+// returns true in case of an error
+//
+bool TParseContext::boolErrorCheck(int line, const TIntermTyped* type)
+{
+    if (type->getBasicType() != EbtBool || type->isArray() || type->isMatrix() || type->isVector()) {
+        error(line, "boolean expression expected", "");
+        return true;
+    } 
+
+    return false;
+}
+
+// This function checks to see if the node (for the expression) contains a scalar boolean expression or not
+//
+// returns true in case of an error
+//
+bool TParseContext::boolErrorCheck(int line, const TPublicType& pType)
+{
+    if (pType.type != EbtBool || pType.array || pType.matrix || (pType.size > 1)) {
+        error(line, "boolean expression expected", "");
+        return true;
+    } 
+
+    return false;
+}
+
+bool TParseContext::samplerErrorCheck(int line, const TPublicType& pType, const char* reason)
+{
+    if (pType.type == EbtStruct) {
+        if (containsSampler(*pType.userDef)) {
+            error(line, reason, getBasicString(pType.type), "(structure contains a sampler)");
+        
+            return true;
+        }
+        
+        return false;
+    } else if (IsSampler(pType.type)) {
+        error(line, reason, getBasicString(pType.type));
+
+        return true;
+    }
+
+    return false;
+}
+
+bool TParseContext::structQualifierErrorCheck(int line, const TPublicType& pType)
+{
+    if ((pType.qualifier == EvqVaryingIn || pType.qualifier == EvqVaryingOut || pType.qualifier == EvqAttribute) &&
+        pType.type == EbtStruct) {
+        error(line, "cannot be used with a structure", getQualifierString(pType.qualifier));
+        
+        return true;
+    }
+
+    if (pType.qualifier != EvqUniform && samplerErrorCheck(line, pType, "samplers must be uniform"))
+        return true;
+
+    return false;
+}
+
+bool TParseContext::parameterSamplerErrorCheck(int line, TQualifier qualifier, const TType& type)
+{
+    if ((qualifier == EvqOut || qualifier == EvqInOut) && 
+             type.getBasicType() != EbtStruct && IsSampler(type.getBasicType())) {
+        error(line, "samplers cannot be output parameters", type.getBasicString());
+        return true;
+    }
+
+    return false;
+}
+
+bool TParseContext::containsSampler(TType& type)
+{
+    if (IsSampler(type.getBasicType()))
+        return true;
+
+    if (type.getBasicType() == EbtStruct) {
+        TTypeList& structure = *type.getStruct();
+        for (unsigned int i = 0; i < structure.size(); ++i) {
+            if (containsSampler(*structure[i].type))
+                return true;
+        }
+    }
+
+    return false;
+}
+
+//
+// Do size checking for an array type's size.
+//
+// Returns true if there was an error.
+//
+bool TParseContext::arraySizeErrorCheck(int line, TIntermTyped* expr, int& size)
+{
+    TIntermConstantUnion* constant = expr->getAsConstantUnion();
+    if (constant == 0 || constant->getBasicType() != EbtInt) {
+        error(line, "array size must be a constant integer expression", "");
+        return true;
+    }
+
+    size = constant->getUnionArrayPointer()->getIConst();
+
+    if (size <= 0) {
+        error(line, "array size must be a positive integer", "");
+        size = 1;
+        return true;
+    }
+
+    return false;
+}
+
+//
+// See if this qualifier can be an array.
+//
+// Returns true if there is an error.
+//
+bool TParseContext::arrayQualifierErrorCheck(int line, TPublicType type)
+{
+    if ((type.qualifier == EvqAttribute) || (type.qualifier == EvqConst)) {
+        error(line, "cannot declare arrays of this qualifier", TType(type).getCompleteString().c_str());
+        return true;
+    }
+
+    return false;
+}
+
+//
+// See if this type can be an array.
+//
+// Returns true if there is an error.
+//
+bool TParseContext::arrayTypeErrorCheck(int line, TPublicType type)
+{
+    //
+    // Can the type be an array?
+    //
+    if (type.array) {
+        error(line, "cannot declare arrays of arrays", TType(type).getCompleteString().c_str());
+        return true;
+    }
+
+    return false;
+}
+
+//
+// Do all the semantic checking for declaring an array, with and 
+// without a size, and make the right changes to the symbol table.
+//
+// size == 0 means no specified size.
+//
+// Returns true if there was an error.
+//
+bool TParseContext::arrayErrorCheck(int line, TString& identifier, TPublicType type, TVariable*& variable)
+{
+    //
+    // Don't check for reserved word use until after we know it's not in the symbol table,
+    // because reserved arrays can be redeclared.
+    //
+
+    bool builtIn = false; 
+    bool sameScope = false;
+    TSymbol* symbol = symbolTable.find(identifier, &builtIn, &sameScope);
+    if (symbol == 0 || !sameScope) {
+        if (reservedErrorCheck(line, identifier))
+            return true;
+        
+        variable = new TVariable(&identifier, TType(type));
+
+        if (type.arraySize)
+            variable->getType().setArraySize(type.arraySize);
+
+        if (! symbolTable.insert(*variable)) {
+            delete variable;
+            error(line, "INTERNAL ERROR inserting new symbol", identifier.c_str());
+            return true;
+        }
+    } else {
+        if (! symbol->isVariable()) {
+            error(line, "variable expected", identifier.c_str());
+            return true;
+        }
+
+        variable = static_cast<TVariable*>(symbol);
+        if (! variable->getType().isArray()) {
+            error(line, "redeclaring non-array as array", identifier.c_str());
+            return true;
+        }
+        if (variable->getType().getArraySize() > 0) {
+            error(line, "redeclaration of array with size", identifier.c_str());
+            return true;
+        }
+        
+        if (! variable->getType().sameElementType(TType(type))) {
+            error(line, "redeclaration of array with a different type", identifier.c_str());
+            return true;
+        }
+
+        TType* t = variable->getArrayInformationType();
+        while (t != 0) {
+            if (t->getMaxArraySize() > type.arraySize) {
+                error(line, "higher index value already used for the array", identifier.c_str());
+                return true;
+            }
+            t->setArraySize(type.arraySize);
+            t = t->getArrayInformationType();
+        }
+
+        if (type.arraySize)
+            variable->getType().setArraySize(type.arraySize);
+    } 
+
+    if (voidErrorCheck(line, identifier, type))
+        return true;
+
+    return false;
+}
+
+bool TParseContext::arraySetMaxSize(TIntermSymbol *node, TType* type, int size, bool updateFlag, TSourceLoc line)
+{
+    bool builtIn = false;
+    TSymbol* symbol = symbolTable.find(node->getSymbol(), &builtIn);
+    if (symbol == 0) {
+        error(line, " undeclared identifier", node->getSymbol().c_str());
+        return true;
+    }
+    TVariable* variable = static_cast<TVariable*>(symbol);
+
+    type->setArrayInformationType(variable->getArrayInformationType());
+    variable->updateArrayInformationType(type);
+
+    // special casing to test index value of gl_FragData. If the accessed index is >= gl_MaxDrawBuffers
+    // its an error
+    if (node->getSymbol() == "gl_FragData") {
+        TSymbol* fragData = symbolTable.find("gl_MaxDrawBuffers", &builtIn);
+        ASSERT(fragData);
+
+        int fragDataValue = static_cast<TVariable*>(fragData)->getConstPointer()[0].getIConst();
+        if (fragDataValue <= size) {
+            error(line, "", "[", "gl_FragData can only have a max array size of up to gl_MaxDrawBuffers");
+            return true;
+        }
+    }
+
+    // we dont want to update the maxArraySize when this flag is not set, we just want to include this 
+    // node type in the chain of node types so that its updated when a higher maxArraySize comes in.
+    if (!updateFlag)
+        return false;
+
+    size++;
+    variable->getType().setMaxArraySize(size);
+    type->setMaxArraySize(size);
+    TType* tt = type;
+
+    while(tt->getArrayInformationType() != 0) {
+        tt = tt->getArrayInformationType();
+        tt->setMaxArraySize(size);
+    }
+
+    return false;
+}
+
+//
+// Enforce non-initializer type/qualifier rules.
+//
+// Returns true if there was an error.
+//
+bool TParseContext::nonInitConstErrorCheck(int line, TString& identifier, TPublicType& type, bool array)
+{
+    if (type.qualifier == EvqConst)
+    {
+        // Make the qualifier make sense.
+        type.qualifier = EvqTemporary;
+        
+        if (array)
+        {
+            error(line, "arrays may not be declared constant since they cannot be initialized", identifier.c_str());
+        }
+        else if (type.isStructureContainingArrays())
+        {
+            error(line, "structures containing arrays may not be declared constant since they cannot be initialized", identifier.c_str());
+        }
+        else
+        {
+            error(line, "variables with qualifier 'const' must be initialized", identifier.c_str());
+        }
+
+        return true;
+    }
+
+    return false;
+}
+
+//
+// Do semantic checking for a variable declaration that has no initializer,
+// and update the symbol table.
+//
+// Returns true if there was an error.
+//
+bool TParseContext::nonInitErrorCheck(int line, TString& identifier, TPublicType& type, TVariable*& variable)
+{
+    if (reservedErrorCheck(line, identifier))
+        recover();
+
+    variable = new TVariable(&identifier, TType(type));
+
+    if (! symbolTable.insert(*variable)) {
+        error(line, "redefinition", variable->getName().c_str());
+        delete variable;
+        variable = 0;
+        return true;
+    }
+
+    if (voidErrorCheck(line, identifier, type))
+        return true;
+
+    return false;
+}
+
+bool TParseContext::paramErrorCheck(int line, TQualifier qualifier, TQualifier paramQualifier, TType* type)
+{    
+    if (qualifier != EvqConst && qualifier != EvqTemporary) {
+        error(line, "qualifier not allowed on function parameter", getQualifierString(qualifier));
+        return true;
+    }
+    if (qualifier == EvqConst && paramQualifier != EvqIn) {
+        error(line, "qualifier not allowed with ", getQualifierString(qualifier), getQualifierString(paramQualifier));
+        return true;
+    }
+
+    if (qualifier == EvqConst)
+        type->setQualifier(EvqConstReadOnly);
+    else
+        type->setQualifier(paramQualifier);
+
+    return false;
+}
+
+bool TParseContext::extensionErrorCheck(int line, const TString& extension)
+{
+    const TExtensionBehavior& extBehavior = extensionBehavior();
+    TExtensionBehavior::const_iterator iter = extBehavior.find(extension.c_str());
+    if (iter == extBehavior.end()) {
+        error(line, "extension", extension.c_str(), "is not supported");
+        return true;
+    }
+    // In GLSL ES, an extension's default behavior is "disable".
+    if (iter->second == EBhDisable || iter->second == EBhUndefined) {
+        error(line, "extension", extension.c_str(), "is disabled");
+        return true;
+    }
+    if (iter->second == EBhWarn) {
+        warning(line, "extension", extension.c_str(), "is being used");
+        return false;
+    }
+
+    return false;
+}
+
+bool TParseContext::supportsExtension(const char* extension)
+{
+    const TExtensionBehavior& extbehavior = extensionBehavior();
+    TExtensionBehavior::const_iterator iter = extbehavior.find(extension);
+    return (iter != extbehavior.end());
+}
+
+void TParseContext::handleExtensionDirective(int line, const char* extName, const char* behavior)
+{
+    pp::SourceLocation loc;
+    DecodeSourceLoc(line, &loc.file, &loc.line);
+    directiveHandler.handleExtension(loc, extName, behavior);
+}
+
+void TParseContext::handlePragmaDirective(int line, const char* name, const char* value)
+{
+    pp::SourceLocation loc;
+    DecodeSourceLoc(line, &loc.file, &loc.line);
+    directiveHandler.handlePragma(loc, name, value);
+}
+
+/////////////////////////////////////////////////////////////////////////////////
+//
+// Non-Errors.
+//
+/////////////////////////////////////////////////////////////////////////////////
+
+//
+// Look up a function name in the symbol table, and make sure it is a function.
+//
+// Return the function symbol if found, otherwise 0.
+//
+const TFunction* TParseContext::findFunction(int line, TFunction* call, bool *builtIn)
+{
+    // First find by unmangled name to check whether the function name has been
+    // hidden by a variable name or struct typename.
+    const TSymbol* symbol = symbolTable.find(call->getName(), builtIn);
+    if (symbol == 0) {
+        symbol = symbolTable.find(call->getMangledName(), builtIn);
+    }
+
+    if (symbol == 0) {
+        error(line, "no matching overloaded function found", call->getName().c_str());
+        return 0;
+    }
+
+    if (!symbol->isFunction()) {
+        error(line, "function name expected", call->getName().c_str());
+        return 0;
+    }
+
+    return static_cast<const TFunction*>(symbol);
+}
+
+//
+// Initializers show up in several places in the grammar.  Have one set of
+// code to handle them here.
+//
+bool TParseContext::executeInitializer(TSourceLoc line, TString& identifier, TPublicType& pType, 
+                                       TIntermTyped* initializer, TIntermNode*& intermNode, TVariable* variable)
+{
+    TType type = TType(pType);
+
+    if (variable == 0) {
+        if (reservedErrorCheck(line, identifier))
+            return true;
+
+        if (voidErrorCheck(line, identifier, pType))
+            return true;
+
+        //
+        // add variable to symbol table
+        //
+        variable = new TVariable(&identifier, type);
+        if (! symbolTable.insert(*variable)) {
+            error(line, "redefinition", variable->getName().c_str());
+            return true;
+            // don't delete variable, it's used by error recovery, and the pool 
+            // pop will take care of the memory
+        }
+    }
+
+    //
+    // identifier must be of type constant, a global, or a temporary
+    //
+    TQualifier qualifier = variable->getType().getQualifier();
+    if ((qualifier != EvqTemporary) && (qualifier != EvqGlobal) && (qualifier != EvqConst)) {
+        error(line, " cannot initialize this type of qualifier ", variable->getType().getQualifierString());
+        return true;
+    }
+    //
+    // test for and propagate constant
+    //
+
+    if (qualifier == EvqConst) {
+        if (qualifier != initializer->getType().getQualifier()) {
+            std::stringstream extraInfoStream;
+            extraInfoStream << "'" << variable->getType().getCompleteString() << "'";
+            std::string extraInfo = extraInfoStream.str();
+            error(line, " assigning non-constant to", "=", extraInfo.c_str());
+            variable->getType().setQualifier(EvqTemporary);
+            return true;
+        }
+        if (type != initializer->getType()) {
+            error(line, " non-matching types for const initializer ", 
+                variable->getType().getQualifierString());
+            variable->getType().setQualifier(EvqTemporary);
+            return true;
+        }
+        if (initializer->getAsConstantUnion()) { 
+            ConstantUnion* unionArray = variable->getConstPointer();
+
+            if (type.getObjectSize() == 1 && type.getBasicType() != EbtStruct) {
+                *unionArray = (initializer->getAsConstantUnion()->getUnionArrayPointer())[0];
+            } else {
+                variable->shareConstPointer(initializer->getAsConstantUnion()->getUnionArrayPointer());
+            }
+        } else if (initializer->getAsSymbolNode()) {
+            const TSymbol* symbol = symbolTable.find(initializer->getAsSymbolNode()->getSymbol());
+            const TVariable* tVar = static_cast<const TVariable*>(symbol);
+
+            ConstantUnion* constArray = tVar->getConstPointer();
+            variable->shareConstPointer(constArray);
+        } else {
+            std::stringstream extraInfoStream;
+            extraInfoStream << "'" << variable->getType().getCompleteString() << "'";
+            std::string extraInfo = extraInfoStream.str();
+            error(line, " cannot assign to", "=", extraInfo.c_str());
+            variable->getType().setQualifier(EvqTemporary);
+            return true;
+        }
+    }
+    if (qualifier != EvqConst) {
+        TIntermSymbol* intermSymbol = intermediate.addSymbol(variable->getUniqueId(), variable->getName(), variable->getType(), line);
+        intermNode = intermediate.addAssign(EOpInitialize, intermSymbol, initializer, line);
+        if (intermNode == 0) {
+            assignError(line, "=", intermSymbol->getCompleteString(), initializer->getCompleteString());
+            return true;
+        }
+    } else 
+        intermNode = 0;
+
+    return false;
+}
+
+bool TParseContext::areAllChildConst(TIntermAggregate* aggrNode)
+{
+    ASSERT(aggrNode != NULL);
+    if (!aggrNode->isConstructor())
+        return false;
+
+    bool allConstant = true;
+
+    // check if all the child nodes are constants so that they can be inserted into 
+    // the parent node
+    TIntermSequence &sequence = aggrNode->getSequence() ;
+    for (TIntermSequence::iterator p = sequence.begin(); p != sequence.end(); ++p) {
+        if (!(*p)->getAsTyped()->getAsConstantUnion())
+            return false;
+    }
+
+    return allConstant;
+}
+
+// This function is used to test for the correctness of the parameters passed to various constructor functions
+// and also convert them to the right datatype if it is allowed and required. 
+//
+// Returns 0 for an error or the constructed node (aggregate or typed) for no error.
+//
+TIntermTyped* TParseContext::addConstructor(TIntermNode* node, const TType* type, TOperator op, TFunction* fnCall, TSourceLoc line)
+{
+    if (node == 0)
+        return 0;
+
+    TIntermAggregate* aggrNode = node->getAsAggregate();
+    
+    TTypeList::const_iterator memberTypes;
+    if (op == EOpConstructStruct)
+        memberTypes = type->getStruct()->begin();
+    
+    TType elementType = *type;
+    if (type->isArray())
+        elementType.clearArrayness();
+
+    bool singleArg;
+    if (aggrNode) {
+        if (aggrNode->getOp() != EOpNull || aggrNode->getSequence().size() == 1)
+            singleArg = true;
+        else
+            singleArg = false;
+    } else
+        singleArg = true;
+
+    TIntermTyped *newNode;
+    if (singleArg) {
+        // If structure constructor or array constructor is being called 
+        // for only one parameter inside the structure, we need to call constructStruct function once.
+        if (type->isArray())
+            newNode = constructStruct(node, &elementType, 1, node->getLine(), false);
+        else if (op == EOpConstructStruct)
+            newNode = constructStruct(node, (*memberTypes).type, 1, node->getLine(), false);
+        else
+            newNode = constructBuiltIn(type, op, node, node->getLine(), false);
+
+        if (newNode && newNode->getAsAggregate()) {
+            TIntermTyped* constConstructor = foldConstConstructor(newNode->getAsAggregate(), *type);
+            if (constConstructor)
+                return constConstructor;
+        }
+
+        return newNode;
+    }
+    
+    //
+    // Handle list of arguments.
+    //
+    TIntermSequence &sequenceVector = aggrNode->getSequence() ;    // Stores the information about the parameter to the constructor
+    // if the structure constructor contains more than one parameter, then construct
+    // each parameter
+    
+    int paramCount = 0;  // keeps a track of the constructor parameter number being checked    
+    
+    // for each parameter to the constructor call, check to see if the right type is passed or convert them 
+    // to the right type if possible (and allowed).
+    // for structure constructors, just check if the right type is passed, no conversion is allowed.
+    
+    for (TIntermSequence::iterator p = sequenceVector.begin(); 
+                                   p != sequenceVector.end(); p++, paramCount++) {
+        if (type->isArray())
+            newNode = constructStruct(*p, &elementType, paramCount+1, node->getLine(), true);
+        else if (op == EOpConstructStruct)
+            newNode = constructStruct(*p, (memberTypes[paramCount]).type, paramCount+1, node->getLine(), true);
+        else
+            newNode = constructBuiltIn(type, op, *p, node->getLine(), true);
+        
+        if (newNode) {
+            *p = newNode;
+        }
+    }
+
+    TIntermTyped* constructor = intermediate.setAggregateOperator(aggrNode, op, line);
+    TIntermTyped* constConstructor = foldConstConstructor(constructor->getAsAggregate(), *type);
+    if (constConstructor)
+        return constConstructor;
+
+    return constructor;
+}
+
+TIntermTyped* TParseContext::foldConstConstructor(TIntermAggregate* aggrNode, const TType& type)
+{
+    bool canBeFolded = areAllChildConst(aggrNode);
+    aggrNode->setType(type);
+    if (canBeFolded) {
+        bool returnVal = false;
+        ConstantUnion* unionArray = new ConstantUnion[type.getObjectSize()];
+        if (aggrNode->getSequence().size() == 1)  {
+            returnVal = intermediate.parseConstTree(aggrNode->getLine(), aggrNode, unionArray, aggrNode->getOp(), symbolTable,  type, true);
+        }
+        else {
+            returnVal = intermediate.parseConstTree(aggrNode->getLine(), aggrNode, unionArray, aggrNode->getOp(), symbolTable,  type);
+        }
+        if (returnVal)
+            return 0;
+
+        return intermediate.addConstantUnion(unionArray, type, aggrNode->getLine());
+    }
+
+    return 0;
+}
+
+// Function for constructor implementation. Calls addUnaryMath with appropriate EOp value
+// for the parameter to the constructor (passed to this function). Essentially, it converts
+// the parameter types correctly. If a constructor expects an int (like ivec2) and is passed a 
+// float, then float is converted to int.
+//
+// Returns 0 for an error or the constructed node.
+//
+TIntermTyped* TParseContext::constructBuiltIn(const TType* type, TOperator op, TIntermNode* node, TSourceLoc line, bool subset)
+{
+    TIntermTyped* newNode;
+    TOperator basicOp;
+
+    //
+    // First, convert types as needed.
+    //
+    switch (op) {
+    case EOpConstructVec2:
+    case EOpConstructVec3:
+    case EOpConstructVec4:
+    case EOpConstructMat2:
+    case EOpConstructMat3:
+    case EOpConstructMat4:
+    case EOpConstructFloat:
+        basicOp = EOpConstructFloat;
+        break;
+
+    case EOpConstructIVec2:
+    case EOpConstructIVec3:
+    case EOpConstructIVec4:
+    case EOpConstructInt:
+        basicOp = EOpConstructInt;
+        break;
+
+    case EOpConstructBVec2:
+    case EOpConstructBVec3:
+    case EOpConstructBVec4:
+    case EOpConstructBool:
+        basicOp = EOpConstructBool;
+        break;
+
+    default:
+        error(line, "unsupported construction", "");
+        recover();
+
+        return 0;
+    }
+    newNode = intermediate.addUnaryMath(basicOp, node, node->getLine(), symbolTable);
+    if (newNode == 0) {
+        error(line, "can't convert", "constructor");
+        return 0;
+    }
+
+    //
+    // Now, if there still isn't an operation to do the construction, and we need one, add one.
+    //
+    
+    // Otherwise, skip out early.
+    if (subset || (newNode != node && newNode->getType() == *type))
+        return newNode;
+
+    // setAggregateOperator will insert a new node for the constructor, as needed.
+    return intermediate.setAggregateOperator(newNode, op, line);
+}
+
+// This function tests for the type of the parameters to the structures constructors. Raises
+// an error message if the expected type does not match the parameter passed to the constructor.
+//
+// Returns 0 for an error or the input node itself if the expected and the given parameter types match.
+//
+TIntermTyped* TParseContext::constructStruct(TIntermNode* node, TType* type, int paramCount, TSourceLoc line, bool subset)
+{
+    if (*type == node->getAsTyped()->getType()) {
+        if (subset)
+            return node->getAsTyped();
+        else
+            return intermediate.setAggregateOperator(node->getAsTyped(), EOpConstructStruct, line);
+    } else {
+        std::stringstream extraInfoStream;
+        extraInfoStream << "cannot convert parameter " << paramCount 
+                        << " from '" << node->getAsTyped()->getType().getBasicString()
+                        << "' to '" << type->getBasicString() << "'";
+        std::string extraInfo = extraInfoStream.str();
+        error(line, "", "constructor", extraInfo.c_str());
+        recover();
+    }
+
+    return 0;
+}
+
+//
+// This function returns the tree representation for the vector field(s) being accessed from contant vector.
+// If only one component of vector is accessed (v.x or v[0] where v is a contant vector), then a contant node is
+// returned, else an aggregate node is returned (for v.xy). The input to this function could either be the symbol
+// node or it could be the intermediate tree representation of accessing fields in a constant structure or column of 
+// a constant matrix.
+//
+TIntermTyped* TParseContext::addConstVectorNode(TVectorFields& fields, TIntermTyped* node, TSourceLoc line)
+{
+    TIntermTyped* typedNode;
+    TIntermConstantUnion* tempConstantNode = node->getAsConstantUnion();
+
+    ConstantUnion *unionArray;
+    if (tempConstantNode) {
+        unionArray = tempConstantNode->getUnionArrayPointer();
+        ASSERT(unionArray);
+
+        if (!unionArray) {
+            return node;
+        }
+    } else { // The node has to be either a symbol node or an aggregate node or a tempConstant node, else, its an error
+        error(line, "Cannot offset into the vector", "Error");
+        recover();
+
+        return 0;
+    }
+
+    ConstantUnion* constArray = new ConstantUnion[fields.num];
+
+    for (int i = 0; i < fields.num; i++) {
+        if (fields.offsets[i] >= node->getType().getObjectSize()) {
+            std::stringstream extraInfoStream;
+            extraInfoStream << "vector field selection out of range '" << fields.offsets[i] << "'";
+            std::string extraInfo = extraInfoStream.str();
+            error(line, "", "[", extraInfo.c_str());
+            recover();
+            fields.offsets[i] = 0;
+        }
+        
+        constArray[i] = unionArray[fields.offsets[i]];
+
+    } 
+    typedNode = intermediate.addConstantUnion(constArray, node->getType(), line);
+    return typedNode;
+}
+
+//
+// This function returns the column being accessed from a constant matrix. The values are retrieved from
+// the symbol table and parse-tree is built for a vector (each column of a matrix is a vector). The input 
+// to the function could either be a symbol node (m[0] where m is a constant matrix)that represents a 
+// constant matrix or it could be the tree representation of the constant matrix (s.m1[0] where s is a constant structure)
+//
+TIntermTyped* TParseContext::addConstMatrixNode(int index, TIntermTyped* node, TSourceLoc line)
+{
+    TIntermTyped* typedNode;
+    TIntermConstantUnion* tempConstantNode = node->getAsConstantUnion();
+
+    if (index >= node->getType().getNominalSize()) {
+        std::stringstream extraInfoStream;
+        extraInfoStream << "matrix field selection out of range '" << index << "'";
+        std::string extraInfo = extraInfoStream.str();
+        error(line, "", "[", extraInfo.c_str());
+        recover();
+        index = 0;
+    }
+
+    if (tempConstantNode) {
+         ConstantUnion* unionArray = tempConstantNode->getUnionArrayPointer();
+         int size = tempConstantNode->getType().getNominalSize();
+         typedNode = intermediate.addConstantUnion(&unionArray[size*index], tempConstantNode->getType(), line);
+    } else {
+        error(line, "Cannot offset into the matrix", "Error");
+        recover();
+
+        return 0;
+    }
+
+    return typedNode;
+}
+
+
+//
+// This function returns an element of an array accessed from a constant array. The values are retrieved from
+// the symbol table and parse-tree is built for the type of the element. The input 
+// to the function could either be a symbol node (a[0] where a is a constant array)that represents a 
+// constant array or it could be the tree representation of the constant array (s.a1[0] where s is a constant structure)
+//
+TIntermTyped* TParseContext::addConstArrayNode(int index, TIntermTyped* node, TSourceLoc line)
+{
+    TIntermTyped* typedNode;
+    TIntermConstantUnion* tempConstantNode = node->getAsConstantUnion();
+    TType arrayElementType = node->getType();
+    arrayElementType.clearArrayness();
+
+    if (index >= node->getType().getArraySize()) {
+        std::stringstream extraInfoStream;
+        extraInfoStream << "array field selection out of range '" << index << "'";
+        std::string extraInfo = extraInfoStream.str();
+        error(line, "", "[", extraInfo.c_str());
+        recover();
+        index = 0;
+    }
+
+    int arrayElementSize = arrayElementType.getObjectSize();
+
+    if (tempConstantNode) {
+         ConstantUnion* unionArray = tempConstantNode->getUnionArrayPointer();
+         typedNode = intermediate.addConstantUnion(&unionArray[arrayElementSize * index], tempConstantNode->getType(), line);
+    } else {
+        error(line, "Cannot offset into the array", "Error");
+        recover();
+
+        return 0;
+    }
+
+    return typedNode;
+}
+
+
+//
+// This function returns the value of a particular field inside a constant structure from the symbol table. 
+// If there is an embedded/nested struct, it appropriately calls addConstStructNested or addConstStructFromAggr
+// function and returns the parse-tree with the values of the embedded/nested struct.
+//
+TIntermTyped* TParseContext::addConstStruct(TString& identifier, TIntermTyped* node, TSourceLoc line)
+{
+    const TTypeList* fields = node->getType().getStruct();
+    TIntermTyped *typedNode;
+    int instanceSize = 0;
+    unsigned int index = 0;
+    TIntermConstantUnion *tempConstantNode = node->getAsConstantUnion();
+
+    for ( index = 0; index < fields->size(); ++index) {
+        if ((*fields)[index].type->getFieldName() == identifier) {
+            break;
+        } else {
+            instanceSize += (*fields)[index].type->getObjectSize();
+        }
+    }
+
+    if (tempConstantNode) {
+         ConstantUnion* constArray = tempConstantNode->getUnionArrayPointer();
+
+         typedNode = intermediate.addConstantUnion(constArray+instanceSize, tempConstantNode->getType(), line); // type will be changed in the calling function
+    } else {
+        error(line, "Cannot offset into the structure", "Error");
+        recover();
+
+        return 0;
+    }
+
+    return typedNode;
+}
+
+bool TParseContext::enterStructDeclaration(int line, const TString& identifier)
+{
+    ++structNestingLevel;
+
+    // Embedded structure definitions are not supported per GLSL ES spec.
+    // They aren't allowed in GLSL either, but we need to detect this here
+    // so we don't rely on the GLSL compiler to catch it.
+    if (structNestingLevel > 1) {
+        error(line, "", "Embedded struct definitions are not allowed");
+        return true;
+    }
+
+    return false;
+}
+
+void TParseContext::exitStructDeclaration()
+{
+    --structNestingLevel;
+}
+
+namespace {
+
+const int kWebGLMaxStructNesting = 4;
+
+}  // namespace
+
+bool TParseContext::structNestingErrorCheck(TSourceLoc line, const TType& fieldType)
+{
+    if (!isWebGLBasedSpec(shaderSpec)) {
+        return false;
+    }
+
+    if (fieldType.getBasicType() != EbtStruct) {
+        return false;
+    }
+
+    // We're already inside a structure definition at this point, so add
+    // one to the field's struct nesting.
+    if (1 + fieldType.getDeepestStructNesting() > kWebGLMaxStructNesting) {
+        std::stringstream extraInfoStream;
+        extraInfoStream << "Reference of struct type " << fieldType.getTypeName() 
+                        << " exceeds maximum struct nesting of " << kWebGLMaxStructNesting;
+        std::string extraInfo = extraInfoStream.str();
+        error(line, "", "", extraInfo.c_str());
+        return true;
+    }
+
+    return false;
+}
+
+//
+// Parse an array of strings using yyparse.
+//
+// Returns 0 for success.
+//
+int PaParseStrings(int count, const char* const string[], const int length[],
+                   TParseContext* context) {
+    if ((count == 0) || (string == NULL))
+        return 1;
+
+    if (glslang_initialize(context))
+        return 1;
+
+    int error = glslang_scan(count, string, length, context);
+    if (!error)
+        error = glslang_parse(context);
+
+    glslang_finalize(context);
+
+    return (error == 0) && (context->numErrors() == 0) ? 0 : 1;
+}
+
+
+
diff --git a/src/3rdparty/angle/src/compiler/ParseHelper.h b/src/3rdparty/angle/src/compiler/ParseHelper.h
new file mode 100644 (file)
index 0000000..824ee00
--- /dev/null
@@ -0,0 +1,140 @@
+//
+// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+#ifndef _PARSER_HELPER_INCLUDED_
+#define _PARSER_HELPER_INCLUDED_
+
+#include "compiler/Diagnostics.h"
+#include "compiler/DirectiveHandler.h"
+#include "compiler/localintermediate.h"
+#include "compiler/preprocessor/new/Preprocessor.h"
+#include "compiler/ShHandle.h"
+#include "compiler/SymbolTable.h"
+
+struct TMatrixFields {
+    bool wholeRow;
+    bool wholeCol;
+    int row;
+    int col;
+};
+
+//
+// The following are extra variables needed during parsing, grouped together so
+// they can be passed to the parser without needing a global.
+//
+struct TParseContext {
+    TParseContext(TSymbolTable& symt, TExtensionBehavior& ext, TIntermediate& interm, ShShaderType type, ShShaderSpec spec, int options, bool checksPrecErrors, const char* sourcePath, TInfoSink& is) :
+            intermediate(interm),
+            symbolTable(symt),
+            shaderType(type),
+            shaderSpec(spec),
+            compileOptions(options),
+            sourcePath(sourcePath),
+            treeRoot(0),
+            lexAfterType(false),
+            loopNestingLevel(0),
+            structNestingLevel(0),
+            inTypeParen(false),
+            currentFunctionType(NULL),
+            functionReturnsValue(false),
+            checksPrecisionErrors(checksPrecErrors),
+            diagnostics(is),
+            directiveHandler(ext, diagnostics),
+            preprocessor(&diagnostics, &directiveHandler),
+            scanner(NULL) {  }
+    TIntermediate& intermediate; // to hold and build a parse tree
+    TSymbolTable& symbolTable;   // symbol table that goes with the language currently being parsed
+    ShShaderType shaderType;              // vertex or fragment language (future: pack or unpack)
+    ShShaderSpec shaderSpec;              // The language specification compiler conforms to - GLES2 or WebGL.
+    int compileOptions;
+    const char* sourcePath;      // Path of source file or NULL.
+    TIntermNode* treeRoot;       // root of parse tree being created
+    bool lexAfterType;           // true if we've recognized a type, so can only be looking for an identifier
+    int loopNestingLevel;        // 0 if outside all loops
+    int structNestingLevel;      // incremented while parsing a struct declaration
+    bool inTypeParen;            // true if in parentheses, looking only for an identifier
+    const TType* currentFunctionType;  // the return type of the function that's currently being parsed
+    bool functionReturnsValue;   // true if a non-void function has a return
+    bool checksPrecisionErrors;  // true if an error will be generated when a variable is declared without precision, explicit or implicit.
+    TString HashErrMsg;
+    bool AfterEOF;
+    TDiagnostics diagnostics;
+    TDirectiveHandler directiveHandler;
+    pp::Preprocessor preprocessor;
+    void* scanner;
+
+    int numErrors() const { return diagnostics.numErrors(); }
+    TInfoSink& infoSink() { return diagnostics.infoSink(); }
+    void error(TSourceLoc loc, const char *reason, const char* token,
+               const char* extraInfo="");
+    void warning(TSourceLoc loc, const char* reason, const char* token,
+                 const char* extraInfo="");
+    void trace(const char* str);
+    void recover();
+
+    bool parseVectorFields(const TString&, int vecSize, TVectorFields&, int line);
+    bool parseMatrixFields(const TString&, int matSize, TMatrixFields&, int line);
+
+    bool reservedErrorCheck(int line, const TString& identifier);
+    void assignError(int line, const char* op, TString left, TString right);
+    void unaryOpError(int line, const char* op, TString operand);
+    void binaryOpError(int line, const char* op, TString left, TString right);
+    bool precisionErrorCheck(int line, TPrecision precision, TBasicType type);
+    bool lValueErrorCheck(int line, const char* op, TIntermTyped*);
+    bool constErrorCheck(TIntermTyped* node);
+    bool integerErrorCheck(TIntermTyped* node, const char* token);
+    bool globalErrorCheck(int line, bool global, const char* token);
+    bool constructorErrorCheck(int line, TIntermNode*, TFunction&, TOperator, TType*);
+    bool arraySizeErrorCheck(int line, TIntermTyped* expr, int& size);
+    bool arrayQualifierErrorCheck(int line, TPublicType type);
+    bool arrayTypeErrorCheck(int line, TPublicType type);
+    bool arrayErrorCheck(int line, TString& identifier, TPublicType type, TVariable*& variable);
+    bool voidErrorCheck(int, const TString&, const TPublicType&);
+    bool boolErrorCheck(int, const TIntermTyped*);
+    bool boolErrorCheck(int, const TPublicType&);
+    bool samplerErrorCheck(int line, const TPublicType& pType, const char* reason);
+    bool structQualifierErrorCheck(int line, const TPublicType& pType);
+    bool parameterSamplerErrorCheck(int line, TQualifier qualifier, const TType& type);
+    bool nonInitConstErrorCheck(int line, TString& identifier, TPublicType& type, bool array);
+    bool nonInitErrorCheck(int line, TString& identifier, TPublicType& type, TVariable*& variable);
+    bool paramErrorCheck(int line, TQualifier qualifier, TQualifier paramQualifier, TType* type);
+    bool extensionErrorCheck(int line, const TString&);
+
+    const TExtensionBehavior& extensionBehavior() const { return directiveHandler.extensionBehavior(); }
+    bool supportsExtension(const char* extension);
+    void handleExtensionDirective(int line, const char* extName, const char* behavior);
+
+    const TPragma& pragma() const { return directiveHandler.pragma(); }
+    void handlePragmaDirective(int line, const char* name, const char* value);
+
+    bool containsSampler(TType& type);
+    bool areAllChildConst(TIntermAggregate* aggrNode);
+    const TFunction* findFunction(int line, TFunction* pfnCall, bool *builtIn = 0);
+    bool executeInitializer(TSourceLoc line, TString& identifier, TPublicType& pType,
+                            TIntermTyped* initializer, TIntermNode*& intermNode, TVariable* variable = 0);
+    bool arraySetMaxSize(TIntermSymbol*, TType*, int, bool, TSourceLoc);
+
+    TIntermTyped* addConstructor(TIntermNode*, const TType*, TOperator, TFunction*, TSourceLoc);
+    TIntermTyped* foldConstConstructor(TIntermAggregate* aggrNode, const TType& type);
+    TIntermTyped* constructStruct(TIntermNode*, TType*, int, TSourceLoc, bool subset);
+    TIntermTyped* constructBuiltIn(const TType*, TOperator, TIntermNode*, TSourceLoc, bool subset);
+    TIntermTyped* addConstVectorNode(TVectorFields&, TIntermTyped*, TSourceLoc);
+    TIntermTyped* addConstMatrixNode(int , TIntermTyped*, TSourceLoc);
+    TIntermTyped* addConstArrayNode(int index, TIntermTyped* node, TSourceLoc line);
+    TIntermTyped* addConstStruct(TString& , TIntermTyped*, TSourceLoc);
+
+    // Performs an error check for embedded struct declarations.
+    // Returns true if an error was raised due to the declaration of
+    // this struct.
+    bool enterStructDeclaration(TSourceLoc line, const TString& identifier);
+    void exitStructDeclaration();
+
+    bool structNestingErrorCheck(TSourceLoc line, const TType& fieldType);
+};
+
+int PaParseStrings(int count, const char* const string[], const int length[],
+                   TParseContext* context);
+
+#endif // _PARSER_HELPER_INCLUDED_
diff --git a/src/3rdparty/angle/src/compiler/PoolAlloc.cpp b/src/3rdparty/angle/src/compiler/PoolAlloc.cpp
new file mode 100644 (file)
index 0000000..9ef4f59
--- /dev/null
@@ -0,0 +1,310 @@
+//
+// 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/PoolAlloc.h"
+
+#ifndef _MSC_VER
+#include <stdint.h>
+#endif
+#include <stdio.h>
+
+#include "common/angleutils.h"
+#include "compiler/InitializeGlobals.h"
+#include "compiler/osinclude.h"
+
+OS_TLSIndex PoolIndex = OS_INVALID_TLS_INDEX;
+
+void InitializeGlobalPools()
+{
+    TThreadGlobalPools* globalPools= static_cast<TThreadGlobalPools*>(OS_GetTLSValue(PoolIndex));    
+    if (globalPools)
+        return;
+
+    TThreadGlobalPools* threadData = new TThreadGlobalPools();
+    threadData->globalPoolAllocator = 0;
+
+    OS_SetTLSValue(PoolIndex, threadData);
+}
+
+void FreeGlobalPools()
+{
+    // Release the allocated memory for this thread.
+    TThreadGlobalPools* globalPools= static_cast<TThreadGlobalPools*>(OS_GetTLSValue(PoolIndex));    
+    if (!globalPools)
+        return;
+    delete globalPools;
+}
+
+bool InitializePoolIndex()
+{
+    // Allocate a TLS index.
+    if ((PoolIndex = OS_AllocTLSIndex()) == OS_INVALID_TLS_INDEX)
+        return false;
+
+    return true;
+}
+
+void FreePoolIndex()
+{
+    // Release the TLS index.
+    OS_FreeTLSIndex(PoolIndex);
+}
+
+TPoolAllocator& GetGlobalPoolAllocator()
+{
+    TThreadGlobalPools* threadData = static_cast<TThreadGlobalPools*>(OS_GetTLSValue(PoolIndex));
+
+    return *threadData->globalPoolAllocator;
+}
+
+void SetGlobalPoolAllocator(TPoolAllocator* poolAllocator)
+{
+    TThreadGlobalPools* threadData = static_cast<TThreadGlobalPools*>(OS_GetTLSValue(PoolIndex));
+
+    threadData->globalPoolAllocator = poolAllocator;
+}
+
+//
+// Implement the functionality of the TPoolAllocator class, which
+// is documented in PoolAlloc.h.
+//
+TPoolAllocator::TPoolAllocator(int growthIncrement, int allocationAlignment) : 
+    pageSize(growthIncrement),
+    alignment(allocationAlignment),
+    freeList(0),
+    inUseList(0),
+    numCalls(0),
+    totalBytes(0)
+{
+    //
+    // Don't allow page sizes we know are smaller than all common
+    // OS page sizes.
+    //
+    if (pageSize < 4*1024)
+        pageSize = 4*1024;
+
+    //
+    // A large currentPageOffset indicates a new page needs to
+    // be obtained to allocate memory.
+    //
+    currentPageOffset = pageSize;
+
+    //
+    // Adjust alignment to be at least pointer aligned and
+    // power of 2.
+    //
+    size_t minAlign = sizeof(void*);
+    alignment &= ~(minAlign - 1);
+    if (alignment < minAlign)
+        alignment = minAlign;
+    size_t a = 1;
+    while (a < alignment)
+        a <<= 1;
+    alignment = a;
+    alignmentMask = a - 1;
+
+    //
+    // Align header skip
+    //
+    headerSkip = minAlign;
+    if (headerSkip < sizeof(tHeader)) {
+        headerSkip = (sizeof(tHeader) + alignmentMask) & ~alignmentMask;
+    }
+}
+
+TPoolAllocator::~TPoolAllocator()
+{
+    while (inUseList) {
+        tHeader* next = inUseList->nextPage;
+        inUseList->~tHeader();
+        delete [] reinterpret_cast<char*>(inUseList);
+        inUseList = next;
+    }
+
+    // We should not check the guard blocks
+    // here, because we did it already when the block was
+    // placed into the free list.
+    //
+    while (freeList) {
+        tHeader* next = freeList->nextPage;
+        delete [] reinterpret_cast<char*>(freeList);
+        freeList = next;
+    }
+}
+
+// Support MSVC++ 6.0
+const unsigned char TAllocation::guardBlockBeginVal = 0xfb;
+const unsigned char TAllocation::guardBlockEndVal   = 0xfe;
+const unsigned char TAllocation::userDataFill       = 0xcd;
+
+#ifdef GUARD_BLOCKS
+    const size_t TAllocation::guardBlockSize = 16;
+#else
+    const size_t TAllocation::guardBlockSize = 0;
+#endif
+
+//
+// Check a single guard block for damage
+//
+void TAllocation::checkGuardBlock(unsigned char* blockMem, unsigned char val, const char* locText) const
+{
+#ifdef GUARD_BLOCKS
+    for (size_t x = 0; x < guardBlockSize; x++) {
+        if (blockMem[x] != val) {
+            char assertMsg[80];
+
+            // We don't print the assert message.  It's here just to be helpful.
+#if defined(_MSC_VER)
+            snprintf(assertMsg, sizeof(assertMsg), "PoolAlloc: Damage %s %Iu byte allocation at 0x%p\n",
+                    locText, size, data());
+#else
+            snprintf(assertMsg, sizeof(assertMsg), "PoolAlloc: Damage %s %zu byte allocation at 0x%p\n",
+                    locText, size, data());
+#endif
+            assert(0 && "PoolAlloc: Damage in guard block");
+        }
+    }
+#endif
+}
+
+
+void TPoolAllocator::push()
+{
+    tAllocState state = { currentPageOffset, inUseList };
+
+    stack.push_back(state);
+        
+    //
+    // Indicate there is no current page to allocate from.
+    //
+    currentPageOffset = pageSize;
+}
+
+//
+// Do a mass-deallocation of all the individual allocations
+// that have occurred since the last push(), or since the
+// last pop(), or since the object's creation.
+//
+// The deallocated pages are saved for future allocations.
+//
+void TPoolAllocator::pop()
+{
+    if (stack.size() < 1)
+        return;
+
+    tHeader* page = stack.back().page;
+    currentPageOffset = stack.back().offset;
+
+    while (inUseList != page) {
+        // invoke destructor to free allocation list
+        inUseList->~tHeader();
+        
+        tHeader* nextInUse = inUseList->nextPage;
+        if (inUseList->pageCount > 1)
+            delete [] reinterpret_cast<char*>(inUseList);
+        else {
+            inUseList->nextPage = freeList;
+            freeList = inUseList;
+        }
+        inUseList = nextInUse;
+    }
+
+    stack.pop_back();
+}
+
+//
+// Do a mass-deallocation of all the individual allocations
+// that have occurred.
+//
+void TPoolAllocator::popAll()
+{
+    while (stack.size() > 0)
+        pop();
+}
+
+void* TPoolAllocator::allocate(size_t numBytes)
+{
+    // If we are using guard blocks, all allocations are bracketed by
+    // them: [guardblock][allocation][guardblock].  numBytes is how
+    // much memory the caller asked for.  allocationSize is the total
+    // size including guard blocks.  In release build,
+    // guardBlockSize=0 and this all gets optimized away.
+    size_t allocationSize = TAllocation::allocationSize(numBytes);
+    
+    //
+    // Just keep some interesting statistics.
+    //
+    ++numCalls;
+    totalBytes += numBytes;
+
+    //
+    // Do the allocation, most likely case first, for efficiency.
+    // This step could be moved to be inline sometime.
+    //
+    if (currentPageOffset + allocationSize <= pageSize) {
+        //
+        // Safe to allocate from currentPageOffset.
+        //
+        unsigned char* memory = reinterpret_cast<unsigned char *>(inUseList) + currentPageOffset;
+        currentPageOffset += allocationSize;
+        currentPageOffset = (currentPageOffset + alignmentMask) & ~alignmentMask;
+
+        return initializeAllocation(inUseList, memory, numBytes);
+    }
+
+    if (allocationSize + headerSkip > pageSize) {
+        //
+        // Do a multi-page allocation.  Don't mix these with the others.
+        // The OS is efficient and allocating and free-ing multiple pages.
+        //
+        size_t numBytesToAlloc = allocationSize + headerSkip;
+        tHeader* memory = reinterpret_cast<tHeader*>(::new char[numBytesToAlloc]);
+        if (memory == 0)
+            return 0;
+
+        // Use placement-new to initialize header
+        new(memory) tHeader(inUseList, (numBytesToAlloc + pageSize - 1) / pageSize);
+        inUseList = memory;
+
+        currentPageOffset = pageSize;  // make next allocation come from a new page
+
+        // No guard blocks for multi-page allocations (yet)
+        return reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(memory) + headerSkip);
+    }
+
+    //
+    // Need a simple page to allocate from.
+    //
+    tHeader* memory;
+    if (freeList) {
+        memory = freeList;
+        freeList = freeList->nextPage;
+    } else {
+        memory = reinterpret_cast<tHeader*>(::new char[pageSize]);
+        if (memory == 0)
+            return 0;
+    }
+
+    // Use placement-new to initialize header
+    new(memory) tHeader(inUseList, 1);
+    inUseList = memory;
+    
+    unsigned char* ret = reinterpret_cast<unsigned char *>(inUseList) + headerSkip;
+    currentPageOffset = (headerSkip + allocationSize + alignmentMask) & ~alignmentMask;
+
+    return initializeAllocation(inUseList, ret, numBytes);
+}
+
+
+//
+// Check all allocations in a list for damage by calling check on each.
+//
+void TAllocation::checkAllocList() const
+{
+    for (const TAllocation* alloc = this; alloc != 0; alloc = alloc->prevAlloc)
+        alloc->check();
+}
diff --git a/src/3rdparty/angle/src/compiler/PoolAlloc.h b/src/3rdparty/angle/src/compiler/PoolAlloc.h
new file mode 100644 (file)
index 0000000..a8a59c6
--- /dev/null
@@ -0,0 +1,306 @@
+//
+// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#ifndef _POOLALLOC_INCLUDED_
+#define _POOLALLOC_INCLUDED_
+
+#ifdef _DEBUG
+#define GUARD_BLOCKS  // define to enable guard block sanity checking
+#endif
+
+//
+// This header defines an allocator that can be used to efficiently
+// allocate a large number of small requests for heap memory, with the 
+// intention that they are not individually deallocated, but rather 
+// collectively deallocated at one time.
+//
+// This simultaneously
+//
+// * Makes each individual allocation much more efficient; the
+//     typical allocation is trivial.
+// * Completely avoids the cost of doing individual deallocation.
+// * Saves the trouble of tracking down and plugging a large class of leaks.
+//
+// Individual classes can use this allocator by supplying their own
+// new and delete methods.
+//
+// STL containers can use this allocator by using the pool_allocator
+// class as the allocator (second) template argument.
+//
+
+#include <stddef.h>
+#include <string.h>
+#include <vector>
+
+// If we are using guard blocks, we must track each indivual
+// allocation.  If we aren't using guard blocks, these
+// never get instantiated, so won't have any impact.
+// 
+
+class TAllocation {
+public:
+    TAllocation(size_t size, unsigned char* mem, TAllocation* prev = 0) :
+        size(size), mem(mem), prevAlloc(prev) {
+        // Allocations are bracketed:
+        //    [allocationHeader][initialGuardBlock][userData][finalGuardBlock]
+        // This would be cleaner with if (guardBlockSize)..., but that
+        // makes the compiler print warnings about 0 length memsets,
+        // even with the if() protecting them.
+#ifdef GUARD_BLOCKS
+        memset(preGuard(), guardBlockBeginVal, guardBlockSize);
+        memset(data(),      userDataFill,       size);
+        memset(postGuard(), guardBlockEndVal,   guardBlockSize);
+#endif
+    }
+
+    void check() const {
+        checkGuardBlock(preGuard(),  guardBlockBeginVal, "before");
+        checkGuardBlock(postGuard(), guardBlockEndVal,   "after");
+    }
+
+    void checkAllocList() const;
+
+    // Return total size needed to accomodate user buffer of 'size',
+    // plus our tracking data.
+    inline static size_t allocationSize(size_t size) {
+        return size + 2 * guardBlockSize + headerSize();
+    }
+
+    // Offset from surrounding buffer to get to user data buffer.
+    inline static unsigned char* offsetAllocation(unsigned char* m) {
+        return m + guardBlockSize + headerSize();
+    }
+
+private:
+    void checkGuardBlock(unsigned char* blockMem, unsigned char val, const char* locText) const;
+
+    // Find offsets to pre and post guard blocks, and user data buffer
+    unsigned char* preGuard()  const { return mem + headerSize(); }
+    unsigned char* data()      const { return preGuard() + guardBlockSize; }
+    unsigned char* postGuard() const { return data() + size; }
+
+    size_t size;                  // size of the user data area
+    unsigned char* mem;           // beginning of our allocation (pts to header)
+    TAllocation* prevAlloc;       // prior allocation in the chain
+
+    // Support MSVC++ 6.0
+    const static unsigned char guardBlockBeginVal;
+    const static unsigned char guardBlockEndVal;
+    const static unsigned char userDataFill;
+
+    const static size_t guardBlockSize;
+#ifdef GUARD_BLOCKS
+    inline static size_t headerSize() { return sizeof(TAllocation); }
+#else
+    inline static size_t headerSize() { return 0; }
+#endif
+};
+
+//
+// There are several stacks.  One is to track the pushing and popping
+// of the user, and not yet implemented.  The others are simply a 
+// repositories of free pages or used pages.
+//
+// Page stacks are linked together with a simple header at the beginning
+// of each allocation obtained from the underlying OS.  Multi-page allocations
+// are returned to the OS.  Individual page allocations are kept for future
+// re-use.
+//
+// The "page size" used is not, nor must it match, the underlying OS
+// page size.  But, having it be about that size or equal to a set of 
+// pages is likely most optimal.
+//
+class TPoolAllocator {
+public:
+    TPoolAllocator(int growthIncrement = 8*1024, int allocationAlignment = 16);
+
+    //
+    // Don't call the destructor just to free up the memory, call pop()
+    //
+    ~TPoolAllocator();
+
+    //
+    // Call push() to establish a new place to pop memory too.  Does not
+    // have to be called to get things started.
+    //
+    void push();
+
+    //
+    // Call pop() to free all memory allocated since the last call to push(),
+    // or if no last call to push, frees all memory since first allocation.
+    //
+    void pop();
+
+    //
+    // Call popAll() to free all memory allocated.
+    //
+    void popAll();
+
+    //
+    // Call allocate() to actually acquire memory.  Returns 0 if no memory
+    // available, otherwise a properly aligned pointer to 'numBytes' of memory.
+    //
+    void* allocate(size_t numBytes);
+
+    //
+    // There is no deallocate.  The point of this class is that
+    // deallocation can be skipped by the user of it, as the model
+    // of use is to simultaneously deallocate everything at once
+    // by calling pop(), and to not have to solve memory leak problems.
+    //
+
+protected:
+    friend struct tHeader;
+    
+    struct tHeader {
+        tHeader(tHeader* nextPage, size_t pageCount) :
+            nextPage(nextPage),
+            pageCount(pageCount)
+#ifdef GUARD_BLOCKS
+          , lastAllocation(0)
+#endif
+            { }
+
+        ~tHeader() {
+#ifdef GUARD_BLOCKS
+            if (lastAllocation)
+                lastAllocation->checkAllocList();
+#endif
+        }
+
+        tHeader* nextPage;
+        size_t pageCount;
+#ifdef GUARD_BLOCKS
+        TAllocation* lastAllocation;
+#endif
+    };
+
+    struct tAllocState {
+        size_t offset;
+        tHeader* page;
+    };
+    typedef std::vector<tAllocState> tAllocStack;
+
+    // Track allocations if and only if we're using guard blocks
+    void* initializeAllocation(tHeader* block, unsigned char* memory, size_t numBytes) {
+#ifdef GUARD_BLOCKS
+        new(memory) TAllocation(numBytes, memory, block->lastAllocation);
+        block->lastAllocation = reinterpret_cast<TAllocation*>(memory);
+#endif
+        // This is optimized entirely away if GUARD_BLOCKS is not defined.
+        return TAllocation::offsetAllocation(memory);
+    }
+
+    size_t pageSize;        // granularity of allocation from the OS
+    size_t alignment;       // all returned allocations will be aligned at 
+                            // this granularity, which will be a power of 2
+    size_t alignmentMask;
+    size_t headerSkip;      // amount of memory to skip to make room for the
+                            //      header (basically, size of header, rounded
+                            //      up to make it aligned
+    size_t currentPageOffset;  // next offset in top of inUseList to allocate from
+    tHeader* freeList;      // list of popped memory
+    tHeader* inUseList;     // list of all memory currently being used
+    tAllocStack stack;      // stack of where to allocate from, to partition pool
+
+    int numCalls;           // just an interesting statistic
+    size_t totalBytes;      // just an interesting statistic
+private:
+    TPoolAllocator& operator=(const TPoolAllocator&);  // dont allow assignment operator
+    TPoolAllocator(const TPoolAllocator&);  // dont allow default copy constructor
+};
+
+
+//
+// There could potentially be many pools with pops happening at
+// different times.  But a simple use is to have a global pop
+// with everyone using the same global allocator.
+//
+extern TPoolAllocator& GetGlobalPoolAllocator();
+extern void SetGlobalPoolAllocator(TPoolAllocator* poolAllocator);
+#define GlobalPoolAllocator GetGlobalPoolAllocator()
+
+struct TThreadGlobalPools
+{
+    TPoolAllocator* globalPoolAllocator;
+};
+
+//
+// This STL compatible allocator is intended to be used as the allocator
+// parameter to templatized STL containers, like vector and map.
+//
+// It will use the pools for allocation, and not
+// do any deallocation, but will still do destruction.
+//
+template<class T>
+class pool_allocator {
+public:
+    typedef size_t size_type;
+    typedef ptrdiff_t difference_type;
+    typedef T* pointer;
+    typedef const T* const_pointer;
+    typedef T& reference;
+    typedef const T& const_reference;
+    typedef T value_type;
+
+    template<class Other> 
+    struct rebind {
+        typedef pool_allocator<Other> other;
+    };
+    pointer address(reference x) const { return &x; }
+    const_pointer address(const_reference x) const { return &x; }
+
+    pool_allocator() : allocator(&GlobalPoolAllocator) { }
+    pool_allocator(TPoolAllocator& a) : allocator(&a) { }
+    pool_allocator(const pool_allocator<T>& p) : allocator(p.allocator) { }
+
+    template <class Other>
+    pool_allocator<T>& operator=(const pool_allocator<Other>& p) {
+      allocator = p.allocator;
+      return *this;
+    }
+
+    template<class Other>
+    pool_allocator(const pool_allocator<Other>& p) : allocator(&p.getAllocator()) { }
+
+#if defined(__SUNPRO_CC) && !defined(_RWSTD_ALLOCATOR)
+    // libCStd on some platforms have a different allocate/deallocate interface.
+    // Caller pre-bakes sizeof(T) into 'n' which is the number of bytes to be
+    // allocated, not the number of elements.
+    void* allocate(size_type n) { 
+        return getAllocator().allocate(n);
+    }
+    void* allocate(size_type n, const void*) {
+        return getAllocator().allocate(n);
+    }
+    void deallocate(void*, size_type) {}
+#else
+    pointer allocate(size_type n) { 
+        return reinterpret_cast<pointer>(getAllocator().allocate(n * sizeof(T)));
+    }
+    pointer allocate(size_type n, const void*) { 
+        return reinterpret_cast<pointer>(getAllocator().allocate(n * sizeof(T)));
+    }
+    void deallocate(pointer, size_type) {}
+#endif  // _RWSTD_ALLOCATOR
+
+    void construct(pointer p, const T& val) { new ((void *)p) T(val); }
+    void destroy(pointer p) { p->T::~T(); }
+
+    bool operator==(const pool_allocator& rhs) const { return &getAllocator() == &rhs.getAllocator(); }
+    bool operator!=(const pool_allocator& rhs) const { return &getAllocator() != &rhs.getAllocator(); }
+
+    size_type max_size() const { return static_cast<size_type>(-1) / sizeof(T); }
+    size_type max_size(int size) const { return static_cast<size_type>(-1) / size; }
+
+    void setAllocator(TPoolAllocator* a) { allocator = a; }
+    TPoolAllocator& getAllocator() const { return *allocator; }
+
+protected:
+    TPoolAllocator* allocator;
+};
+
+#endif // _POOLALLOC_INCLUDED_
diff --git a/src/3rdparty/angle/src/compiler/Pragma.h b/src/3rdparty/angle/src/compiler/Pragma.h
new file mode 100644 (file)
index 0000000..2f74412
--- /dev/null
@@ -0,0 +1,19 @@
+//
+// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#ifndef COMPILER_PRAGMA_H_
+#define COMPILER_PRAGMA_H_
+
+struct TPragma {
+    // By default optimization is turned on and debug is turned off.
+    TPragma() : optimize(true), debug(false) { }
+    TPragma(bool o, bool d) : optimize(o), debug(d) { }
+
+    bool optimize;
+    bool debug;
+};
+
+#endif // COMPILER_PRAGMA_H_
diff --git a/src/3rdparty/angle/src/compiler/QualifierAlive.cpp b/src/3rdparty/angle/src/compiler/QualifierAlive.cpp
new file mode 100644 (file)
index 0000000..92a6874
--- /dev/null
@@ -0,0 +1,58 @@
+//
+// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "compiler/intermediate.h"
+
+class TAliveTraverser : public TIntermTraverser {
+public:
+    TAliveTraverser(TQualifier q) : TIntermTraverser(true, false, false, true), found(false), qualifier(q)
+    {
+    }
+
+       bool wasFound() { return found; }
+
+protected:
+    bool found;
+    TQualifier qualifier;
+
+    void visitSymbol(TIntermSymbol*);
+    bool visitSelection(Visit, TIntermSelection*);
+};
+
+//
+// Report whether or not a variable of the given qualifier type
+// is guaranteed written.  Not always possible to determine if
+// it is written conditionally.
+//
+// ?? It does not do this well yet, this is just a place holder
+// that simply determines if it was reference at all, anywhere.
+//
+bool QualifierWritten(TIntermNode* node, TQualifier qualifier)
+{
+    TAliveTraverser it(qualifier);
+
+    if (node)
+        node->traverse(&it);
+
+    return it.wasFound();
+}
+
+void TAliveTraverser::visitSymbol(TIntermSymbol* node)
+{
+    //
+    // If it's what we're looking for, record it.
+    //
+    if (node->getQualifier() == qualifier)
+        found = true;
+}
+
+bool TAliveTraverser::visitSelection(Visit preVisit, TIntermSelection* node)
+{
+    if (wasFound())
+        return false;
+
+    return true;
+}
diff --git a/src/3rdparty/angle/src/compiler/QualifierAlive.h b/src/3rdparty/angle/src/compiler/QualifierAlive.h
new file mode 100644 (file)
index 0000000..872a06f
--- /dev/null
@@ -0,0 +1,7 @@
+//
+// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+bool QualifierWritten(TIntermNode* root, TQualifier);
diff --git a/src/3rdparty/angle/src/compiler/RemoveTree.cpp b/src/3rdparty/angle/src/compiler/RemoveTree.cpp
new file mode 100644 (file)
index 0000000..a4b8c1e
--- /dev/null
@@ -0,0 +1,77 @@
+//
+// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "compiler/intermediate.h"
+#include "compiler/RemoveTree.h"
+
+//
+// Code to recursively delete the intermediate tree.
+//
+
+class RemoveTree : public TIntermTraverser
+{
+public:
+       RemoveTree() : TIntermTraverser(false, false, true)
+       {
+       }
+
+protected:
+       void visitSymbol(TIntermSymbol*);
+       void visitConstantUnion(TIntermConstantUnion*);
+       bool visitBinary(Visit visit, TIntermBinary*);
+       bool visitUnary(Visit visit, TIntermUnary*);
+       bool visitSelection(Visit visit, TIntermSelection*);
+       bool visitAggregate(Visit visit, TIntermAggregate*);
+};
+
+void RemoveTree::visitSymbol(TIntermSymbol* node)
+{
+       delete node;
+}
+
+bool RemoveTree::visitBinary(Visit visit, TIntermBinary* node)
+{
+       delete node;
+
+       return true;
+}
+
+bool RemoveTree::visitUnary(Visit visit, TIntermUnary* node)
+{
+    delete node;
+
+       return true;
+}
+
+bool RemoveTree::visitAggregate(Visit visit, TIntermAggregate* node)
+{
+       delete node;
+
+       return true;
+}
+
+bool RemoveTree::visitSelection(Visit visit, TIntermSelection* node)
+{
+       delete node;
+
+       return true;
+}
+
+void RemoveTree::visitConstantUnion(TIntermConstantUnion* node)
+{
+       delete node;
+}
+
+//
+// Entry point.
+//
+void RemoveAllTreeNodes(TIntermNode* root)
+{
+    RemoveTree it;
+
+    root->traverse(&it);
+}
+
diff --git a/src/3rdparty/angle/src/compiler/RemoveTree.h b/src/3rdparty/angle/src/compiler/RemoveTree.h
new file mode 100644 (file)
index 0000000..97a8216
--- /dev/null
@@ -0,0 +1,7 @@
+//
+// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+void RemoveAllTreeNodes(TIntermNode*);
diff --git a/src/3rdparty/angle/src/compiler/RenameFunction.h b/src/3rdparty/angle/src/compiler/RenameFunction.h
new file mode 100644 (file)
index 0000000..3908bfd
--- /dev/null
@@ -0,0 +1,36 @@
+//
+// 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_RENAME_FUNCTION
+#define COMPILER_RENAME_FUNCTION
+
+#include "compiler/intermediate.h"
+
+//
+// Renames a function, including its declaration and any calls to it.
+//
+class RenameFunction : public TIntermTraverser
+{
+public:
+    RenameFunction(const TString& oldFunctionName, const TString& newFunctionName)
+    : TIntermTraverser(true, false, false)
+    , mOldFunctionName(oldFunctionName)
+    , mNewFunctionName(newFunctionName) {}
+
+    virtual bool visitAggregate(Visit visit, TIntermAggregate* node)
+    {
+        TOperator op = node->getOp();
+        if ((op == EOpFunction || op == EOpFunctionCall) && node->getName() == mOldFunctionName)
+            node->setName(mNewFunctionName);
+        return true;
+    }
+
+private:
+    const TString mOldFunctionName;
+    const TString mNewFunctionName;
+};
+
+#endif  // COMPILER_RENAME_FUNCTION
diff --git a/src/3rdparty/angle/src/compiler/SearchSymbol.cpp b/src/3rdparty/angle/src/compiler/SearchSymbol.cpp
new file mode 100644 (file)
index 0000000..9368f1a
--- /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.
+//
+// SearchSymbol is an AST traverser to detect the use of a given symbol name
+//
+
+#include "compiler/SearchSymbol.h"
+
+#include "compiler/InfoSink.h"
+#include "compiler/OutputHLSL.h"
+
+namespace sh
+{
+SearchSymbol::SearchSymbol(const TString &symbol) : mSymbol(symbol)
+{
+    match = false;
+}
+
+void SearchSymbol::traverse(TIntermNode *node)
+{
+    node->traverse(this);
+}
+
+void SearchSymbol::visitSymbol(TIntermSymbol *symbolNode)
+{
+    if (symbolNode->getSymbol() == mSymbol)
+    {
+        match = true;
+    }
+}
+
+bool SearchSymbol::foundMatch() const
+{
+    return match;
+}
+}
diff --git a/src/3rdparty/angle/src/compiler/SearchSymbol.h b/src/3rdparty/angle/src/compiler/SearchSymbol.h
new file mode 100644 (file)
index 0000000..6bc0b90
--- /dev/null
@@ -0,0 +1,33 @@
+//
+// 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.
+//
+// SearchSymbol is an AST traverser to detect the use of a given symbol name
+//
+
+#ifndef COMPILER_SEARCHSYMBOL_H_
+#define COMPILER_SEARCHSYMBOL_H_
+
+#include "compiler/intermediate.h"
+#include "compiler/ParseHelper.h"
+
+namespace sh
+{
+class SearchSymbol : public TIntermTraverser
+{
+  public:
+    SearchSymbol(const TString &symbol);
+
+    void traverse(TIntermNode *node);
+    void visitSymbol(TIntermSymbol *symbolNode);
+
+    bool foundMatch() const;
+
+  protected:
+    const TString &mSymbol;
+    bool match;
+};
+}
+
+#endif   // COMPILER_SEARCHSYMBOL_H_
diff --git a/src/3rdparty/angle/src/compiler/ShHandle.h b/src/3rdparty/angle/src/compiler/ShHandle.h
new file mode 100644 (file)
index 0000000..6ba302a
--- /dev/null
@@ -0,0 +1,142 @@
+//
+// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#ifndef _SHHANDLE_INCLUDED_
+#define _SHHANDLE_INCLUDED_
+
+//
+// Machine independent part of the compiler private objects
+// sent as ShHandle to the driver.
+//
+// This should not be included by driver code.
+//
+
+#include "GLSLANG/ShaderLang.h"
+
+#include "compiler/BuiltInFunctionEmulator.h"
+#include "compiler/ExtensionBehavior.h"
+#include "compiler/InfoSink.h"
+#include "compiler/SymbolTable.h"
+#include "compiler/VariableInfo.h"
+
+class LongNameMap;
+class TCompiler;
+class TDependencyGraph;
+
+//
+// Helper function to identify specs that are based on the WebGL spec,
+// like the CSS Shaders spec.
+//
+bool isWebGLBasedSpec(ShShaderSpec spec);
+
+//
+// The base class used to back handles returned to the driver.
+//
+class TShHandleBase {
+public:
+    TShHandleBase();
+    virtual ~TShHandleBase();
+    virtual TCompiler* getAsCompiler() { return 0; }
+
+protected:
+    // Memory allocator. Allocates and tracks memory required by the compiler.
+    // Deallocates all memory when compiler is destructed.
+    TPoolAllocator allocator;
+};
+
+//
+// The base class for the machine dependent compiler to derive from
+// for managing object code from the compile.
+//
+class TCompiler : public TShHandleBase {
+public:
+    TCompiler(ShShaderType type, ShShaderSpec spec);
+    virtual ~TCompiler();
+    virtual TCompiler* getAsCompiler() { return this; }
+
+    bool Init(const ShBuiltInResources& resources);
+    bool compile(const char* const shaderStrings[],
+                 const int numStrings,
+                 int compileOptions);
+
+    // Get results of the last compilation.
+    TInfoSink& getInfoSink() { return infoSink; }
+    const TVariableInfoList& getAttribs() const { return attribs; }
+    const TVariableInfoList& getUniforms() const { return uniforms; }
+    int getMappedNameMaxLength() const;
+
+protected:
+    ShShaderType getShaderType() const { return shaderType; }
+    ShShaderSpec getShaderSpec() const { return shaderSpec; }
+    // Initialize symbol-table with built-in symbols.
+    bool InitBuiltInSymbolTable(const ShBuiltInResources& resources);
+    // Clears the results from the previous compilation.
+    void clearResults();
+    // Return true if function recursion is detected.
+    bool detectRecursion(TIntermNode* root);
+    // Rewrites a shader's intermediate tree according to the CSS Shaders spec.
+    void rewriteCSSShader(TIntermNode* root);
+    // Returns true if the given shader does not exceed the minimum
+    // functionality mandated in GLSL 1.0 spec Appendix A.
+    bool validateLimitations(TIntermNode* root);
+    // Collect info for all attribs and uniforms.
+    void collectAttribsUniforms(TIntermNode* root);
+    // Map long variable names into shorter ones.
+    void mapLongVariableNames(TIntermNode* root);
+    // Translate to object code.
+    virtual void translate(TIntermNode* root) = 0;
+    // Returns true if, after applying the packing rules in the GLSL 1.017 spec
+    // Appendix A, section 7, the shader does not use too many uniforms.
+    bool enforcePackingRestrictions();
+    // Returns true if the shader passes the restrictions that aim to prevent timing attacks.
+    bool enforceTimingRestrictions(TIntermNode* root, bool outputGraph);
+    // Returns true if the shader does not use samplers.
+    bool enforceVertexShaderTimingRestrictions(TIntermNode* root);
+    // Returns true if the shader does not use sampler dependent values to affect control 
+    // flow or in operations whose time can depend on the input values.
+    bool enforceFragmentShaderTimingRestrictions(const TDependencyGraph& graph);
+    // Get built-in extensions with default behavior.
+    const TExtensionBehavior& getExtensionBehavior() const;
+
+    const BuiltInFunctionEmulator& getBuiltInFunctionEmulator() const;
+
+private:
+    ShShaderType shaderType;
+    ShShaderSpec shaderSpec;
+
+    int maxUniformVectors;
+
+    // Built-in symbol table for the given language, spec, and resources.
+    // It is preserved from compile-to-compile.
+    TSymbolTable symbolTable;
+    // Built-in extensions with default behavior.
+    TExtensionBehavior extensionBehavior;
+
+    BuiltInFunctionEmulator builtInFunctionEmulator;
+
+    // Results of compilation.
+    TInfoSink infoSink;  // Output sink.
+    TVariableInfoList attribs;  // Active attributes in the compiled shader.
+    TVariableInfoList uniforms;  // Active uniforms in the compiled shader.
+
+    // Cached copy of the ref-counted singleton.
+    LongNameMap* longNameMap;
+};
+
+//
+// This is the interface between the machine independent code
+// and the machine dependent code.
+//
+// The machine dependent code should derive from the classes
+// above. Then Construct*() and Delete*() will create and 
+// destroy the machine dependent objects, which contain the
+// above machine independent information.
+//
+TCompiler* ConstructCompiler(
+    ShShaderType type, ShShaderSpec spec, ShShaderOutput output);
+void DeleteCompiler(TCompiler*);
+
+#endif // _SHHANDLE_INCLUDED_
diff --git a/src/3rdparty/angle/src/compiler/ShaderLang.cpp b/src/3rdparty/angle/src/compiler/ShaderLang.cpp
new file mode 100644 (file)
index 0000000..56f5c7f
--- /dev/null
@@ -0,0 +1,285 @@
+//
+// 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.
+//
+
+//
+// Implement the top-level of interface to the compiler,
+// as defined in ShaderLang.h
+//
+
+#include "GLSLANG/ShaderLang.h"
+
+#include "compiler/InitializeDll.h"
+#include "compiler/preprocessor/length_limits.h"
+#include "compiler/ShHandle.h"
+
+//
+// This is the platform independent interface between an OGL driver
+// and the shading language compiler.
+//
+
+static bool checkActiveUniformAndAttribMaxLengths(const ShHandle handle,
+                                                  int expectedValue)
+{
+    int activeUniformLimit = 0;
+    ShGetInfo(handle, SH_ACTIVE_UNIFORM_MAX_LENGTH, &activeUniformLimit);
+    int activeAttribLimit = 0;
+    ShGetInfo(handle, SH_ACTIVE_ATTRIBUTE_MAX_LENGTH, &activeAttribLimit);
+    return (expectedValue == activeUniformLimit && expectedValue == activeAttribLimit);
+}
+
+static bool checkMappedNameMaxLength(const ShHandle handle, int expectedValue)
+{
+    int mappedNameMaxLength = 0;
+    ShGetInfo(handle, SH_MAPPED_NAME_MAX_LENGTH, &mappedNameMaxLength);
+    return (expectedValue == mappedNameMaxLength);
+}
+
+static void getVariableInfo(ShShaderInfo varType,
+                            const ShHandle handle,
+                            int index,
+                            int* length,
+                            int* size,
+                            ShDataType* type,
+                            char* name,
+                            char* mappedName)
+{
+    if (!handle || !size || !type || !name)
+        return;
+    ASSERT((varType == SH_ACTIVE_ATTRIBUTES) ||
+           (varType == SH_ACTIVE_UNIFORMS));
+
+    TShHandleBase* base = reinterpret_cast<TShHandleBase*>(handle);
+    TCompiler* compiler = base->getAsCompiler();
+    if (compiler == 0)
+        return;
+
+    const TVariableInfoList& varList = varType == SH_ACTIVE_ATTRIBUTES ?
+        compiler->getAttribs() : compiler->getUniforms();
+    if (index < 0 || index >= static_cast<int>(varList.size()))
+        return;
+
+    const TVariableInfo& varInfo = varList[index];
+    if (length) *length = varInfo.name.size();
+    *size = varInfo.size;
+    *type = varInfo.type;
+
+    // This size must match that queried by
+    // SH_ACTIVE_UNIFORM_MAX_LENGTH and SH_ACTIVE_ATTRIBUTE_MAX_LENGTH
+    // in ShGetInfo, below.
+    int activeUniformAndAttribLength = 1 + MAX_SYMBOL_NAME_LEN;
+    ASSERT(checkActiveUniformAndAttribMaxLengths(handle, activeUniformAndAttribLength));
+    strncpy(name, varInfo.name.c_str(), activeUniformAndAttribLength);
+    name[activeUniformAndAttribLength - 1] = 0;
+    if (mappedName) {
+        // This size must match that queried by
+        // SH_MAPPED_NAME_MAX_LENGTH in ShGetInfo, below.
+        int maxMappedNameLength = 1 + MAX_SYMBOL_NAME_LEN;
+        ASSERT(checkMappedNameMaxLength(handle, maxMappedNameLength));
+        strncpy(mappedName, varInfo.mappedName.c_str(), maxMappedNameLength);
+        mappedName[maxMappedNameLength - 1] = 0;
+    }
+}
+
+//
+// Driver must call this first, once, before doing any other
+// compiler operations.
+//
+int ShInitialize()
+{
+    if (!InitProcess())
+        return 0;
+
+    return 1;
+}
+
+//
+// Cleanup symbol tables
+//
+int ShFinalize()
+{
+    if (!DetachProcess())
+        return 0;
+
+    return 1;
+}
+
+//
+// Initialize built-in resources with minimum expected values.
+//
+void ShInitBuiltInResources(ShBuiltInResources* resources)
+{
+    // Constants.
+    resources->MaxVertexAttribs = 8;
+    resources->MaxVertexUniformVectors = 128;
+    resources->MaxVaryingVectors = 8;
+    resources->MaxVertexTextureImageUnits = 0;
+    resources->MaxCombinedTextureImageUnits = 8;
+    resources->MaxTextureImageUnits = 8;
+    resources->MaxFragmentUniformVectors = 16;
+    resources->MaxDrawBuffers = 1;
+
+    // Extensions.
+    resources->OES_standard_derivatives = 0;
+    resources->OES_EGL_image_external = 0;
+    resources->ARB_texture_rectangle = 0;
+}
+
+//
+// Driver calls these to create and destroy compiler objects.
+//
+ShHandle ShConstructCompiler(ShShaderType type, ShShaderSpec spec,
+                             ShShaderOutput output,
+                             const ShBuiltInResources* resources)
+{
+    if (!InitThread())
+        return 0;
+
+    TShHandleBase* base = static_cast<TShHandleBase*>(ConstructCompiler(type, spec, output));
+    TCompiler* compiler = base->getAsCompiler();
+    if (compiler == 0)
+        return 0;
+
+    // Generate built-in symbol table.
+    if (!compiler->Init(*resources)) {
+        ShDestruct(base);
+        return 0;
+    }
+
+    return reinterpret_cast<void*>(base);
+}
+
+void ShDestruct(ShHandle handle)
+{
+    if (handle == 0)
+        return;
+
+    TShHandleBase* base = static_cast<TShHandleBase*>(handle);
+
+    if (base->getAsCompiler())
+        DeleteCompiler(base->getAsCompiler());
+}
+
+//
+// Do an actual compile on the given strings.  The result is left 
+// in the given compile object.
+//
+// Return:  The return value of ShCompile is really boolean, indicating
+// success or failure.
+//
+int ShCompile(
+    const ShHandle handle,
+    const char* const shaderStrings[],
+    const int numStrings,
+    int compileOptions)
+{
+    if (!InitThread())
+        return 0;
+
+    if (handle == 0)
+        return 0;
+
+    TShHandleBase* base = reinterpret_cast<TShHandleBase*>(handle);
+    TCompiler* compiler = base->getAsCompiler();
+    if (compiler == 0)
+        return 0;
+
+    bool success = compiler->compile(shaderStrings, numStrings, compileOptions);
+    return success ? 1 : 0;
+}
+
+void ShGetInfo(const ShHandle handle, ShShaderInfo pname, int* params)
+{
+    if (!handle || !params)
+        return;
+
+    TShHandleBase* base = static_cast<TShHandleBase*>(handle);
+    TCompiler* compiler = base->getAsCompiler();
+    if (!compiler) return;
+
+    switch(pname)
+    {
+    case SH_INFO_LOG_LENGTH:
+        *params = compiler->getInfoSink().info.size() + 1;
+        break;
+    case SH_OBJECT_CODE_LENGTH:
+        *params = compiler->getInfoSink().obj.size() + 1;
+        break;
+    case SH_ACTIVE_UNIFORMS:
+        *params = compiler->getUniforms().size();
+        break;
+    case SH_ACTIVE_UNIFORM_MAX_LENGTH:
+        *params = 1 +  MAX_SYMBOL_NAME_LEN;
+        break;
+    case SH_ACTIVE_ATTRIBUTES:
+        *params = compiler->getAttribs().size();
+        break;
+    case SH_ACTIVE_ATTRIBUTE_MAX_LENGTH:
+        *params = 1 + MAX_SYMBOL_NAME_LEN;
+        break;
+    case SH_MAPPED_NAME_MAX_LENGTH:
+        // Use longer length than MAX_SHORTENED_IDENTIFIER_SIZE to
+        // handle array and struct dereferences.
+        *params = 1 + MAX_SYMBOL_NAME_LEN;
+        break;
+    default: UNREACHABLE();
+    }
+}
+
+//
+// Return any compiler log of messages for the application.
+//
+void ShGetInfoLog(const ShHandle handle, char* infoLog)
+{
+    if (!handle || !infoLog)
+        return;
+
+    TShHandleBase* base = static_cast<TShHandleBase*>(handle);
+    TCompiler* compiler = base->getAsCompiler();
+    if (!compiler) return;
+
+    TInfoSink& infoSink = compiler->getInfoSink();
+    strcpy(infoLog, infoSink.info.c_str());
+}
+
+//
+// Return any object code.
+//
+void ShGetObjectCode(const ShHandle handle, char* objCode)
+{
+    if (!handle || !objCode)
+        return;
+
+    TShHandleBase* base = static_cast<TShHandleBase*>(handle);
+    TCompiler* compiler = base->getAsCompiler();
+    if (!compiler) return;
+
+    TInfoSink& infoSink = compiler->getInfoSink();
+    strcpy(objCode, infoSink.obj.c_str());
+}
+
+void ShGetActiveAttrib(const ShHandle handle,
+                       int index,
+                       int* length,
+                       int* size,
+                       ShDataType* type,
+                       char* name,
+                       char* mappedName)
+{
+    getVariableInfo(SH_ACTIVE_ATTRIBUTES,
+                    handle, index, length, size, type, name, mappedName);
+}
+
+void ShGetActiveUniform(const ShHandle handle,
+                        int index,
+                        int* length,
+                        int* size,
+                        ShDataType* type,
+                        char* name,
+                        char* mappedName)
+{
+    getVariableInfo(SH_ACTIVE_UNIFORMS,
+                    handle, index, length, size, type, name, mappedName);
+}
diff --git a/src/3rdparty/angle/src/compiler/SymbolTable.cpp b/src/3rdparty/angle/src/compiler/SymbolTable.cpp
new file mode 100644 (file)
index 0000000..847c1e4
--- /dev/null
@@ -0,0 +1,279 @@
+//
+// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+//
+// Symbol table for parsing.  Most functionaliy and main ideas
+// are documented in the header file.
+//
+
+#if defined(_MSC_VER)
+#pragma warning(disable: 4718)
+#endif
+
+#include "compiler/SymbolTable.h"
+
+#include <stdio.h>
+#include <algorithm>
+
+#include "common/angleutils.h"
+
+TType::TType(const TPublicType &p) :
+            type(p.type), precision(p.precision), qualifier(p.qualifier), size(p.size), matrix(p.matrix), array(p.array), arraySize(p.arraySize),
+            maxArraySize(0), arrayInformationType(0), structure(0), structureSize(0), deepestStructNesting(0), fieldName(0), mangled(0), typeName(0)
+{
+    if (p.userDef) {
+        structure = p.userDef->getStruct();
+        typeName = NewPoolTString(p.userDef->getTypeName().c_str());
+        computeDeepestStructNesting();
+    }
+}
+
+//
+// Recursively generate mangled names.
+//
+void TType::buildMangledName(TString& mangledName)
+{
+    if (isMatrix())
+        mangledName += 'm';
+    else if (isVector())
+        mangledName += 'v';
+
+    switch (type) {
+    case EbtFloat:              mangledName += 'f';      break;
+    case EbtInt:                mangledName += 'i';      break;
+    case EbtBool:               mangledName += 'b';      break;
+    case EbtSampler2D:          mangledName += "s2";     break;
+    case EbtSamplerCube:        mangledName += "sC";     break;
+    case EbtStruct:
+        mangledName += "struct-";
+        if (typeName)
+            mangledName += *typeName;
+        {// support MSVC++6.0
+            for (unsigned int i = 0; i < structure->size(); ++i) {
+                mangledName += '-';
+                (*structure)[i].type->buildMangledName(mangledName);
+            }
+        }
+    default:
+        break;
+    }
+
+    mangledName += static_cast<char>('0' + getNominalSize());
+    if (isArray()) {
+        char buf[20];
+        snprintf(buf, sizeof(buf), "%d", arraySize);
+        mangledName += '[';
+        mangledName += buf;
+        mangledName += ']';
+    }
+}
+
+int TType::getStructSize() const
+{
+    if (!getStruct()) {
+        assert(false && "Not a struct");
+        return 0;
+    }
+
+    if (structureSize == 0)
+        for (TTypeList::const_iterator tl = getStruct()->begin(); tl != getStruct()->end(); tl++)
+            structureSize += ((*tl).type)->getObjectSize();
+
+    return structureSize;
+}
+
+void TType::computeDeepestStructNesting()
+{
+    if (!getStruct()) {
+        return;
+    }
+
+    int maxNesting = 0;
+    for (TTypeList::const_iterator tl = getStruct()->begin(); tl != getStruct()->end(); ++tl) {
+        maxNesting = std::max(maxNesting, ((*tl).type)->getDeepestStructNesting());
+    }
+
+    deepestStructNesting = 1 + maxNesting;
+}
+
+bool TType::isStructureContainingArrays() const
+{
+    if (!structure)
+    {
+        return false;
+    }
+
+    for (TTypeList::const_iterator member = structure->begin(); member != structure->end(); member++)
+    {
+        if (member->type->isArray() ||
+            member->type->isStructureContainingArrays())
+        {
+            return true;
+        }
+    }
+
+    return false;
+}
+
+//
+// Dump functions.
+//
+
+void TVariable::dump(TInfoSink& infoSink) const
+{
+    infoSink.debug << getName().c_str() << ": " << type.getQualifierString() << " " << type.getPrecisionString() << " " << type.getBasicString();
+    if (type.isArray()) {
+        infoSink.debug << "[0]";
+    }
+    infoSink.debug << "\n";
+}
+
+void TFunction::dump(TInfoSink &infoSink) const
+{
+    infoSink.debug << getName().c_str() << ": " <<  returnType.getBasicString() << " " << getMangledName().c_str() << "\n";
+}
+
+void TSymbolTableLevel::dump(TInfoSink &infoSink) const
+{
+    tLevel::const_iterator it;
+    for (it = level.begin(); it != level.end(); ++it)
+        (*it).second->dump(infoSink);
+}
+
+void TSymbolTable::dump(TInfoSink &infoSink) const
+{
+    for (int level = currentLevel(); level >= 0; --level) {
+        infoSink.debug << "LEVEL " << level << "\n";
+        table[level]->dump(infoSink);
+    }
+}
+
+//
+// Functions have buried pointers to delete.
+//
+TFunction::~TFunction()
+{
+    for (TParamList::iterator i = parameters.begin(); i != parameters.end(); ++i)
+        delete (*i).type;
+}
+
+//
+// Symbol table levels are a map of pointers to symbols that have to be deleted.
+//
+TSymbolTableLevel::~TSymbolTableLevel()
+{
+    for (tLevel::iterator it = level.begin(); it != level.end(); ++it)
+        delete (*it).second;
+}
+
+//
+// Change all function entries in the table with the non-mangled name
+// to be related to the provided built-in operation.  This is a low
+// performance operation, and only intended for symbol tables that
+// live across a large number of compiles.
+//
+void TSymbolTableLevel::relateToOperator(const char* name, TOperator op)
+{
+    tLevel::iterator it;
+    for (it = level.begin(); it != level.end(); ++it) {
+        if ((*it).second->isFunction()) {
+            TFunction* function = static_cast<TFunction*>((*it).second);
+            if (function->getName() == name)
+                function->relateToOperator(op);
+        }
+    }
+}
+
+//
+// Change all function entries in the table with the non-mangled name
+// to be related to the provided built-in extension. This is a low
+// performance operation, and only intended for symbol tables that
+// live across a large number of compiles.
+//
+void TSymbolTableLevel::relateToExtension(const char* name, const TString& ext)
+{
+    for (tLevel::iterator it = level.begin(); it != level.end(); ++it) {
+        if (it->second->isFunction()) {
+            TFunction* function = static_cast<TFunction*>(it->second);
+            if (function->getName() == name)
+                function->relateToExtension(ext);
+        }
+    }
+}
+
+TSymbol::TSymbol(const TSymbol& copyOf)
+{
+    name = NewPoolTString(copyOf.name->c_str());
+    uniqueId = copyOf.uniqueId;
+}
+
+TVariable::TVariable(const TVariable& copyOf, TStructureMap& remapper) : TSymbol(copyOf)
+{
+    type.copyType(copyOf.type, remapper);
+    userType = copyOf.userType;
+    // for builtIn symbol table level, unionArray and arrayInformation pointers should be NULL
+    assert(copyOf.arrayInformationType == 0);
+    arrayInformationType = 0;
+
+    if (copyOf.unionArray) {
+        assert(!copyOf.type.getStruct());
+        assert(copyOf.type.getObjectSize() == 1);
+        unionArray = new ConstantUnion[1];
+        unionArray[0] = copyOf.unionArray[0];
+    } else
+        unionArray = 0;
+}
+
+TVariable* TVariable::clone(TStructureMap& remapper)
+{
+    TVariable *variable = new TVariable(*this, remapper);
+
+    return variable;
+}
+
+TFunction::TFunction(const TFunction& copyOf, TStructureMap& remapper) : TSymbol(copyOf)
+{
+    for (unsigned int i = 0; i < copyOf.parameters.size(); ++i) {
+        TParameter param;
+        parameters.push_back(param);
+        parameters.back().copyParam(copyOf.parameters[i], remapper);
+    }
+
+    returnType.copyType(copyOf.returnType, remapper);
+    mangledName = copyOf.mangledName;
+    op = copyOf.op;
+    defined = copyOf.defined;
+}
+
+TFunction* TFunction::clone(TStructureMap& remapper)
+{
+    TFunction *function = new TFunction(*this, remapper);
+
+    return function;
+}
+
+TSymbolTableLevel* TSymbolTableLevel::clone(TStructureMap& remapper)
+{
+    TSymbolTableLevel *symTableLevel = new TSymbolTableLevel();
+    tLevel::iterator iter;
+    for (iter = level.begin(); iter != level.end(); ++iter) {
+        symTableLevel->insert(*iter->second->clone(remapper));
+    }
+
+    return symTableLevel;
+}
+
+void TSymbolTable::copyTable(const TSymbolTable& copyOf)
+{
+    TStructureMap remapper;
+    uniqueId = copyOf.uniqueId;
+    for (unsigned int i = 0; i < copyOf.table.size(); ++i) {
+        table.push_back(copyOf.table[i]->clone(remapper));
+    }
+    for( unsigned int i = 0; i < copyOf.precisionStack.size(); i++) {
+        precisionStack.push_back( copyOf.precisionStack[i] );
+    }
+}
diff --git a/src/3rdparty/angle/src/compiler/SymbolTable.h b/src/3rdparty/angle/src/compiler/SymbolTable.h
new file mode 100644 (file)
index 0000000..a89499e
--- /dev/null
@@ -0,0 +1,359 @@
+//
+// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#ifndef _SYMBOL_TABLE_INCLUDED_
+#define _SYMBOL_TABLE_INCLUDED_
+
+//
+// Symbol table for parsing.  Has these design characteristics:
+//
+// * Same symbol table can be used to compile many shaders, to preserve
+//   effort of creating and loading with the large numbers of built-in
+//   symbols.
+//
+// * Name mangling will be used to give each function a unique name
+//   so that symbol table lookups are never ambiguous.  This allows
+//   a simpler symbol table structure.
+//
+// * Pushing and popping of scope, so symbol table will really be a stack 
+//   of symbol tables.  Searched from the top, with new inserts going into
+//   the top.
+//
+// * Constants:  Compile time constant symbols will keep their values
+//   in the symbol table.  The parser can substitute constants at parse
+//   time, including doing constant folding and constant propagation.
+//
+// * No temporaries:  Temporaries made from operations (+, --, .xy, etc.)
+//   are tracked in the intermediate representation, not the symbol table.
+//
+
+#include <assert.h>
+
+#include "compiler/InfoSink.h"
+#include "compiler/intermediate.h"
+
+//
+// Symbol base class.  (Can build functions or variables out of these...)
+//
+class TSymbol {    
+public:
+    POOL_ALLOCATOR_NEW_DELETE(GlobalPoolAllocator)
+    TSymbol(const TString *n) :  name(n) { }
+    virtual ~TSymbol() { /* don't delete name, it's from the pool */ }
+    const TString& getName() const { return *name; }
+    virtual const TString& getMangledName() const { return getName(); }
+    virtual bool isFunction() const { return false; }
+    virtual bool isVariable() const { return false; }
+    void setUniqueId(int id) { uniqueId = id; }
+    int getUniqueId() const { return uniqueId; }
+    virtual void dump(TInfoSink &infoSink) const = 0;  
+    TSymbol(const TSymbol&);
+    virtual TSymbol* clone(TStructureMap& remapper) = 0;
+
+protected:
+    const TString *name;
+    unsigned int uniqueId;      // For real comparing during code generation
+};
+
+//
+// Variable class, meaning a symbol that's not a function.
+// 
+// There could be a separate class heirarchy for Constant variables;
+// Only one of int, bool, or float, (or none) is correct for
+// any particular use, but it's easy to do this way, and doesn't
+// seem worth having separate classes, and "getConst" can't simply return
+// different values for different types polymorphically, so this is 
+// just simple and pragmatic.
+//
+class TVariable : public TSymbol {
+public:
+    TVariable(const TString *name, const TType& t, bool uT = false ) : TSymbol(name), type(t), userType(uT), unionArray(0), arrayInformationType(0) { }
+    virtual ~TVariable() { }
+    virtual bool isVariable() const { return true; }    
+    TType& getType() { return type; }    
+    const TType& getType() const { return type; }
+    bool isUserType() const { return userType; }
+    void setQualifier(TQualifier qualifier) { type.setQualifier(qualifier); }
+    void updateArrayInformationType(TType *t) { arrayInformationType = t; }
+    TType* getArrayInformationType() { return arrayInformationType; }
+
+    virtual void dump(TInfoSink &infoSink) const;
+
+    ConstantUnion* getConstPointer()
+    { 
+        if (!unionArray)
+            unionArray = new ConstantUnion[type.getObjectSize()];
+
+        return unionArray;
+    }
+
+    ConstantUnion* getConstPointer() const { return unionArray; }
+
+    void shareConstPointer( ConstantUnion *constArray)
+    {
+        if (unionArray == constArray)
+            return;
+
+        delete[] unionArray;
+        unionArray = constArray;  
+    }
+    TVariable(const TVariable&, TStructureMap& remapper); // copy constructor
+    virtual TVariable* clone(TStructureMap& remapper);
+
+protected:
+    TType type;
+    bool userType;
+    // we are assuming that Pool Allocator will free the memory allocated to unionArray
+    // when this object is destroyed
+    ConstantUnion *unionArray;
+    TType *arrayInformationType;  // this is used for updating maxArraySize in all the references to a given symbol
+};
+
+//
+// The function sub-class of symbols and the parser will need to
+// share this definition of a function parameter.
+//
+struct TParameter {
+    TString *name;
+    TType* type;
+    void copyParam(const TParameter& param, TStructureMap& remapper)
+    {
+        name = NewPoolTString(param.name->c_str());
+        type = param.type->clone(remapper);
+    }
+};
+
+//
+// The function sub-class of a symbol.  
+//
+class TFunction : public TSymbol {
+public:
+    TFunction(TOperator o) :
+        TSymbol(0),
+        returnType(TType(EbtVoid, EbpUndefined)),
+        op(o),
+        defined(false) { }
+    TFunction(const TString *name, TType& retType, TOperator tOp = EOpNull) : 
+        TSymbol(name), 
+        returnType(retType),
+        mangledName(TFunction::mangleName(*name)),
+        op(tOp),
+        defined(false) { }
+    virtual ~TFunction();
+    virtual bool isFunction() const { return true; }    
+
+    static TString mangleName(const TString& name) { return name + '('; }
+    static TString unmangleName(const TString& mangledName)
+    {
+        return TString(mangledName.c_str(), mangledName.find_first_of('('));
+    }
+
+    void addParameter(TParameter& p) 
+    { 
+        parameters.push_back(p);
+        mangledName = mangledName + p.type->getMangledName();
+    }
+
+    const TString& getMangledName() const { return mangledName; }
+    const TType& getReturnType() const { return returnType; }
+
+    void relateToOperator(TOperator o) { op = o; }
+    TOperator getBuiltInOp() const { return op; }
+
+    void relateToExtension(const TString& ext) { extension = ext; }
+    const TString& getExtension() const { return extension; }
+
+    void setDefined() { defined = true; }
+    bool isDefined() { return defined; }
+
+    int getParamCount() const { return static_cast<int>(parameters.size()); }  
+    const TParameter& getParam(int i) const { return parameters[i]; }
+
+    virtual void dump(TInfoSink &infoSink) const;
+    TFunction(const TFunction&, TStructureMap& remapper);
+    virtual TFunction* clone(TStructureMap& remapper);
+
+protected:
+    typedef TVector<TParameter> TParamList;
+    TParamList parameters;
+    TType returnType;
+    TString mangledName;
+    TOperator op;
+    TString extension;
+    bool defined;
+};
+
+
+class TSymbolTableLevel {
+public:
+    typedef TMap<TString, TSymbol*> tLevel;
+    typedef tLevel::const_iterator const_iterator;
+    typedef const tLevel::value_type tLevelPair;
+    typedef std::pair<tLevel::iterator, bool> tInsertResult;
+
+    POOL_ALLOCATOR_NEW_DELETE(GlobalPoolAllocator)
+    TSymbolTableLevel() { }
+    ~TSymbolTableLevel();
+
+    bool insert(TSymbol& symbol) 
+    {
+        //
+        // returning true means symbol was added to the table
+        //
+        tInsertResult result;
+        result = level.insert(tLevelPair(symbol.getMangledName(), &symbol));
+
+        return result.second;
+    }
+
+    TSymbol* find(const TString& name) const
+    {
+        tLevel::const_iterator it = level.find(name);
+        if (it == level.end())
+            return 0;
+        else
+            return (*it).second;
+    }
+
+    const_iterator begin() const
+    {
+        return level.begin();
+    }
+
+    const_iterator end() const
+    {
+        return level.end();
+    }
+
+    void relateToOperator(const char* name, TOperator op);
+    void relateToExtension(const char* name, const TString& ext);
+    void dump(TInfoSink &infoSink) const;
+    TSymbolTableLevel* clone(TStructureMap& remapper);
+
+protected:
+    tLevel level;
+};
+
+class TSymbolTable {
+public:
+    TSymbolTable() : uniqueId(0)
+    {
+        //
+        // The symbol table cannot be used until push() is called, but
+        // the lack of an initial call to push() can be used to detect
+        // that the symbol table has not been preloaded with built-ins.
+        //
+    }
+
+    ~TSymbolTable()
+    {
+        // level 0 is always built In symbols, so we never pop that out
+        while (table.size() > 1)
+            pop();
+    }
+
+    //
+    // When the symbol table is initialized with the built-ins, there should
+    // 'push' calls, so that built-ins are at level 0 and the shader
+    // globals are at level 1.
+    //
+    bool isEmpty() { return table.size() == 0; }
+    bool atBuiltInLevel() { return table.size() == 1; }
+    bool atGlobalLevel() { return table.size() <= 2; }
+    void push()
+    {
+        table.push_back(new TSymbolTableLevel);
+        precisionStack.push_back( PrecisionStackLevel() );
+    }
+
+    void pop()
+    { 
+        delete table[currentLevel()]; 
+        table.pop_back(); 
+        precisionStack.pop_back();
+    }
+
+    bool insert(TSymbol& symbol)
+    {
+        symbol.setUniqueId(++uniqueId);
+        return table[currentLevel()]->insert(symbol);
+    }
+
+    TSymbol* find(const TString& name, bool* builtIn = 0, bool *sameScope = 0) 
+    {
+        int level = currentLevel();
+        TSymbol* symbol;
+        do {
+            symbol = table[level]->find(name);
+            --level;
+        } while (symbol == 0 && level >= 0);
+        level++;
+        if (builtIn)
+            *builtIn = level == 0;
+        if (sameScope)
+            *sameScope = level == currentLevel();
+        return symbol;
+    }
+
+    TSymbol *findBuiltIn(const TString &name)
+    {
+        return table[0]->find(name);
+    }
+
+    TSymbolTableLevel* getGlobalLevel() {
+        assert(table.size() >= 2);
+        return table[1];
+    }
+
+    TSymbolTableLevel* getOuterLevel() {
+        assert(table.size() >= 2);
+        return table[currentLevel() - 1];
+    }
+
+    void relateToOperator(const char* name, TOperator op) {
+        table[0]->relateToOperator(name, op);
+    }
+    void relateToExtension(const char* name, const TString& ext) {
+        table[0]->relateToExtension(name, ext);
+    }
+    int getMaxSymbolId() { return uniqueId; }
+    void dump(TInfoSink &infoSink) const;
+    void copyTable(const TSymbolTable& copyOf);
+
+    void setDefaultPrecision( TBasicType type, TPrecision prec ){
+        if( type != EbtFloat && type != EbtInt ) return; // Only set default precision for int/float
+        int indexOfLastElement = static_cast<int>(precisionStack.size()) - 1;
+        precisionStack[indexOfLastElement][type] = prec; // Uses map operator [], overwrites the current value
+    }
+
+    // Searches down the precisionStack for a precision qualifier for the specified TBasicType
+    TPrecision getDefaultPrecision( TBasicType type){
+        if( type != EbtFloat && type != EbtInt ) return EbpUndefined;
+        int level = static_cast<int>(precisionStack.size()) - 1;
+        assert( level >= 0); // Just to be safe. Should not happen.
+        PrecisionStackLevel::iterator it;
+        TPrecision prec = EbpUndefined; // If we dont find anything we return this. Should we error check this?
+        while( level >= 0 ){
+            it = precisionStack[level].find( type );
+            if( it != precisionStack[level].end() ){
+                prec = (*it).second;
+                break;
+            }
+            level--;
+        }
+        return prec;
+    }
+
+protected:    
+    int currentLevel() const { return static_cast<int>(table.size()) - 1; }
+
+    std::vector<TSymbolTableLevel*> table;
+    typedef std::map< TBasicType, TPrecision > PrecisionStackLevel;
+    std::vector< PrecisionStackLevel > precisionStack;
+    int uniqueId;     // for unique identification in code generation
+};
+
+#endif // _SYMBOL_TABLE_INCLUDED_
diff --git a/src/3rdparty/angle/src/compiler/TranslatorESSL.cpp b/src/3rdparty/angle/src/compiler/TranslatorESSL.cpp
new file mode 100644 (file)
index 0000000..e3a2c2a
--- /dev/null
@@ -0,0 +1,40 @@
+//
+// 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/TranslatorESSL.h"
+
+#include "compiler/OutputESSL.h"
+
+TranslatorESSL::TranslatorESSL(ShShaderType type, ShShaderSpec spec)
+    : TCompiler(type, spec) {
+}
+
+void TranslatorESSL::translate(TIntermNode* root) {
+    TInfoSinkBase& sink = getInfoSink().obj;
+
+    // Write built-in extension behaviors.
+    writeExtensionBehavior();
+
+    // Write emulated built-in functions if needed.
+    getBuiltInFunctionEmulator().OutputEmulatedFunctionDefinition(
+        sink, getShaderType() == SH_FRAGMENT_SHADER);
+
+    // Write translated shader.
+    TOutputESSL outputESSL(sink);
+    root->traverse(&outputESSL);
+}
+
+void TranslatorESSL::writeExtensionBehavior() {
+    TInfoSinkBase& sink = getInfoSink().obj;
+    const TExtensionBehavior& extensionBehavior = getExtensionBehavior();
+    for (TExtensionBehavior::const_iterator iter = extensionBehavior.begin();
+         iter != extensionBehavior.end(); ++iter) {
+        if (iter->second != EBhUndefined) {
+            sink << "#extension " << iter->first << " : "
+                 << getBehaviorString(iter->second) << "\n";
+        }
+    }
+}
diff --git a/src/3rdparty/angle/src/compiler/TranslatorESSL.h b/src/3rdparty/angle/src/compiler/TranslatorESSL.h
new file mode 100644 (file)
index 0000000..a1196bd
--- /dev/null
@@ -0,0 +1,23 @@
+//
+// 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_TRANSLATORESSL_H_
+#define COMPILER_TRANSLATORESSL_H_
+
+#include "compiler/ShHandle.h"
+
+class TranslatorESSL : public TCompiler {
+public:
+    TranslatorESSL(ShShaderType type, ShShaderSpec spec);
+
+protected:
+    virtual void translate(TIntermNode* root);
+
+private:
+    void writeExtensionBehavior();
+};
+
+#endif  // COMPILER_TRANSLATORESSL_H_
diff --git a/src/3rdparty/angle/src/compiler/TranslatorGLSL.cpp b/src/3rdparty/angle/src/compiler/TranslatorGLSL.cpp
new file mode 100644 (file)
index 0000000..bb07a1e
--- /dev/null
@@ -0,0 +1,41 @@
+//
+// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "compiler/TranslatorGLSL.h"
+
+#include "compiler/OutputGLSL.h"
+#include "compiler/VersionGLSL.h"
+
+static void writeVersion(ShShaderType type, TIntermNode* root,
+                         TInfoSinkBase& sink) {
+    TVersionGLSL versionGLSL(type);
+    root->traverse(&versionGLSL);
+    int version = versionGLSL.getVersion();
+    // We need to write version directive only if it is greater than 110.
+    // If there is no version directive in the shader, 110 is implied.
+    if (version > 110) {
+        sink << "#version " << version << "\n";
+    }
+}
+
+TranslatorGLSL::TranslatorGLSL(ShShaderType type, ShShaderSpec spec)
+    : TCompiler(type, spec) {
+}
+
+void TranslatorGLSL::translate(TIntermNode* root) {
+    TInfoSinkBase& sink = getInfoSink().obj;
+
+    // Write GLSL version.
+    writeVersion(getShaderType(), root, sink);
+
+    // Write emulated built-in functions if needed.
+    getBuiltInFunctionEmulator().OutputEmulatedFunctionDefinition(
+        sink, false);
+
+    // Write translated shader.
+    TOutputGLSL outputGLSL(sink);
+    root->traverse(&outputGLSL);
+}
diff --git a/src/3rdparty/angle/src/compiler/TranslatorGLSL.h b/src/3rdparty/angle/src/compiler/TranslatorGLSL.h
new file mode 100644 (file)
index 0000000..c2ce06d
--- /dev/null
@@ -0,0 +1,20 @@
+//
+// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#ifndef COMPILER_TRANSLATORGLSL_H_
+#define COMPILER_TRANSLATORGLSL_H_
+
+#include "compiler/ShHandle.h"
+
+class TranslatorGLSL : public TCompiler {
+public:
+    TranslatorGLSL(ShShaderType type, ShShaderSpec spec);
+
+protected:
+    virtual void translate(TIntermNode* root);
+};
+
+#endif  // COMPILER_TRANSLATORGLSL_H_
diff --git a/src/3rdparty/angle/src/compiler/TranslatorHLSL.cpp b/src/3rdparty/angle/src/compiler/TranslatorHLSL.cpp
new file mode 100644 (file)
index 0000000..f41decd
--- /dev/null
@@ -0,0 +1,23 @@
+//
+// 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/TranslatorHLSL.h"
+
+#include "compiler/InitializeParseContext.h"
+#include "compiler/OutputHLSL.h"
+
+TranslatorHLSL::TranslatorHLSL(ShShaderType type, ShShaderSpec spec)
+    : TCompiler(type, spec)
+{
+}
+
+void TranslatorHLSL::translate(TIntermNode *root)
+{
+    TParseContext& parseContext = *GetGlobalParseContext();
+    sh::OutputHLSL outputHLSL(parseContext);
+
+    outputHLSL.output();
+}
diff --git a/src/3rdparty/angle/src/compiler/TranslatorHLSL.h b/src/3rdparty/angle/src/compiler/TranslatorHLSL.h
new file mode 100644 (file)
index 0000000..c3f672b
--- /dev/null
@@ -0,0 +1,20 @@
+//
+// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#ifndef COMPILER_TRANSLATORHLSL_H_
+#define COMPILER_TRANSLATORHLSL_H_
+
+#include "compiler/ShHandle.h"
+
+class TranslatorHLSL : public TCompiler {
+public:
+    TranslatorHLSL(ShShaderType type, ShShaderSpec spec);
+
+protected:
+    virtual void translate(TIntermNode* root);
+};
+
+#endif  // COMPILER_TRANSLATORHLSL_H_
diff --git a/src/3rdparty/angle/src/compiler/Types.h b/src/3rdparty/angle/src/compiler/Types.h
new file mode 100644 (file)
index 0000000..d457667
--- /dev/null
@@ -0,0 +1,318 @@
+//
+// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#ifndef _TYPES_INCLUDED
+#define _TYPES_INCLUDED
+
+#include "compiler/BaseTypes.h"
+#include "compiler/Common.h"
+#include "compiler/debug.h"
+
+class TType;
+struct TPublicType;
+
+//
+// Need to have association of line numbers to types in a list for building structs.
+//
+struct TTypeLine {
+    TType* type;
+    int line;
+};
+typedef TVector<TTypeLine> TTypeList;
+
+inline TTypeList* NewPoolTTypeList()
+{
+    void* memory = GlobalPoolAllocator.allocate(sizeof(TTypeList));
+    return new(memory) TTypeList;
+}
+
+typedef TMap<TTypeList*, TTypeList*> TStructureMap;
+typedef TMap<TTypeList*, TTypeList*>::iterator TStructureMapIterator;
+
+//
+// Base class for things that have a type.
+//
+class TType
+{
+public:
+    POOL_ALLOCATOR_NEW_DELETE(GlobalPoolAllocator)
+    TType() {}
+    TType(TBasicType t, TPrecision p, TQualifier q = EvqTemporary, int s = 1, bool m = false, bool a = false) :
+            type(t), precision(p), qualifier(q), size(s), matrix(m), array(a), arraySize(0),
+            maxArraySize(0), arrayInformationType(0), structure(0), structureSize(0), deepestStructNesting(0), fieldName(0), mangled(0), typeName(0)
+    {
+    }
+    explicit TType(const TPublicType &p);
+    TType(TTypeList* userDef, const TString& n, TPrecision p = EbpUndefined) :
+            type(EbtStruct), precision(p), qualifier(EvqTemporary), size(1), matrix(false), array(false), arraySize(0),
+            maxArraySize(0), arrayInformationType(0), structure(userDef), structureSize(0), deepestStructNesting(0), fieldName(0), mangled(0)
+    {
+        typeName = NewPoolTString(n.c_str());
+    }
+
+    void copyType(const TType& copyOf, TStructureMap& remapper)
+    {
+        type = copyOf.type;
+        precision = copyOf.precision;
+        qualifier = copyOf.qualifier;
+        size = copyOf.size;
+        matrix = copyOf.matrix;
+        array = copyOf.array;
+        arraySize = copyOf.arraySize;
+
+        TStructureMapIterator iter;
+        if (copyOf.structure) {
+            if ((iter = remapper.find(structure)) == remapper.end()) {
+                // create the new structure here
+                structure = NewPoolTTypeList();
+                for (unsigned int i = 0; i < copyOf.structure->size(); ++i) {
+                    TTypeLine typeLine;
+                    typeLine.line = (*copyOf.structure)[i].line;
+                    typeLine.type = (*copyOf.structure)[i].type->clone(remapper);
+                    structure->push_back(typeLine);
+                }
+            } else {
+                structure = iter->second;
+            }
+        } else
+            structure = 0;
+
+        fieldName = 0;
+        if (copyOf.fieldName)
+            fieldName = NewPoolTString(copyOf.fieldName->c_str());
+        typeName = 0;
+        if (copyOf.typeName)
+            typeName = NewPoolTString(copyOf.typeName->c_str());
+
+        mangled = 0;
+        if (copyOf.mangled)
+            mangled = NewPoolTString(copyOf.mangled->c_str());
+
+        structureSize = copyOf.structureSize;
+        maxArraySize = copyOf.maxArraySize;
+        deepestStructNesting = copyOf.deepestStructNesting;
+        assert(copyOf.arrayInformationType == 0);
+        arrayInformationType = 0; // arrayInformationType should not be set for builtIn symbol table level
+    }
+
+    TType* clone(TStructureMap& remapper)
+    {
+        TType *newType = new TType();
+        newType->copyType(*this, remapper);
+
+        return newType;
+    }
+
+    TBasicType getBasicType() const { return type; }
+    void setBasicType(TBasicType t) { type = t; }
+
+    TPrecision getPrecision() const { return precision; }
+    void setPrecision(TPrecision p) { precision = p; }
+
+    TQualifier getQualifier() const { return qualifier; }
+    void setQualifier(TQualifier q) { qualifier = q; }
+
+    // One-dimensional size of single instance type
+    int getNominalSize() const { return size; }
+    void setNominalSize(int s) { size = s; }
+    // Full size of single instance of type
+    int getObjectSize() const
+    {
+        int totalSize;
+
+        if (getBasicType() == EbtStruct)
+            totalSize = getStructSize();
+        else if (matrix)
+            totalSize = size * size;
+        else
+            totalSize = size;
+
+        if (isArray())
+            totalSize *= std::max(getArraySize(), getMaxArraySize());
+
+        return totalSize;
+    }
+
+    bool isMatrix() const { return matrix ? true : false; }
+    void setMatrix(bool m) { matrix = m; }
+
+    bool isArray() const  { return array ? true : false; }
+    int getArraySize() const { return arraySize; }
+    void setArraySize(int s) { array = true; arraySize = s; }
+    int getMaxArraySize () const { return maxArraySize; }
+    void setMaxArraySize (int s) { maxArraySize = s; }
+    void clearArrayness() { array = false; arraySize = 0; maxArraySize = 0; }
+    void setArrayInformationType(TType* t) { arrayInformationType = t; }
+    TType* getArrayInformationType() const { return arrayInformationType; }
+
+    bool isVector() const { return size > 1 && !matrix; }
+    bool isScalar() const { return size == 1 && !matrix && !structure; }
+
+    TTypeList* getStruct() const { return structure; }
+    void setStruct(TTypeList* s) { structure = s; computeDeepestStructNesting(); }
+
+    const TString& getTypeName() const
+    {
+        assert(typeName);
+        return *typeName;
+    }
+    void setTypeName(const TString& n)
+    {
+        typeName = NewPoolTString(n.c_str());
+    }
+
+    bool isField() const { return fieldName != 0; }
+    const TString& getFieldName() const
+    {
+        assert(fieldName);
+        return *fieldName;
+    }
+    void setFieldName(const TString& n)
+    {
+        fieldName = NewPoolTString(n.c_str());
+    }
+
+    TString& getMangledName() {
+        if (!mangled) {
+            mangled = NewPoolTString("");
+            buildMangledName(*mangled);
+            *mangled += ';' ;
+        }
+
+        return *mangled;
+    }
+
+    bool sameElementType(const TType& right) const {
+        return      type == right.type   &&
+                    size == right.size   &&
+                  matrix == right.matrix &&
+               structure == right.structure;
+    }
+    bool operator==(const TType& right) const {
+        return      type == right.type   &&
+                    size == right.size   &&
+                  matrix == right.matrix &&
+                   array == right.array  && (!array || arraySize == right.arraySize) &&
+               structure == right.structure;
+        // don't check the qualifier, it's not ever what's being sought after
+    }
+    bool operator!=(const TType& right) const {
+        return !operator==(right);
+    }
+    bool operator<(const TType& right) const {
+        if (type != right.type) return type < right.type;
+        if (size != right.size) return size < right.size;
+        if (matrix != right.matrix) return matrix < right.matrix;
+        if (array != right.array) return array < right.array;
+        if (arraySize != right.arraySize) return arraySize < right.arraySize;
+        if (structure != right.structure) return structure < right.structure;
+
+        return false;
+    }
+
+    const char* getBasicString() const { return ::getBasicString(type); }
+    const char* getPrecisionString() const { return ::getPrecisionString(precision); }
+    const char* getQualifierString() const { return ::getQualifierString(qualifier); }
+    TString getCompleteString() const;
+
+    // If this type is a struct, returns the deepest struct nesting of
+    // any field in the struct. For example:
+    //   struct nesting1 {
+    //     vec4 position;
+    //   };
+    //   struct nesting2 {
+    //     nesting1 field1;
+    //     vec4 field2;
+    //   };
+    // For type "nesting2", this method would return 2 -- the number
+    // of structures through which indirection must occur to reach the
+    // deepest field (nesting2.field1.position).
+    int getDeepestStructNesting() const { return deepestStructNesting; }
+
+    bool isStructureContainingArrays() const;
+
+protected:
+    void buildMangledName(TString&);
+    int getStructSize() const;
+    void computeDeepestStructNesting();
+
+    TBasicType type      : 6;
+    TPrecision precision;
+    TQualifier qualifier : 7;
+    int size             : 8; // size of vector or matrix, not size of array
+    unsigned int matrix  : 1;
+    unsigned int array   : 1;
+    int arraySize;
+    int maxArraySize;
+    TType* arrayInformationType;
+
+    TTypeList* structure;      // 0 unless this is a struct
+    mutable int structureSize;
+    int deepestStructNesting;
+
+    TString *fieldName;         // for structure field names
+    TString *mangled;
+    TString *typeName;          // for structure field type name
+};
+
+//
+// This is a workaround for a problem with the yacc stack,  It can't have
+// types that it thinks have non-trivial constructors.  It should
+// just be used while recognizing the grammar, not anything else.  Pointers
+// could be used, but also trying to avoid lots of memory management overhead.
+//
+// Not as bad as it looks, there is no actual assumption that the fields
+// match up or are name the same or anything like that.
+//
+struct TPublicType
+{
+    TBasicType type;
+    TQualifier qualifier;
+    TPrecision precision;
+    int size;          // size of vector or matrix, not size of array
+    bool matrix;
+    bool array;
+    int arraySize;
+    TType* userDef;
+    int line;
+
+    void setBasic(TBasicType bt, TQualifier q, int ln = 0)
+    {
+        type = bt;
+        qualifier = q;
+        precision = EbpUndefined;
+        size = 1;
+        matrix = false;
+        array = false;
+        arraySize = 0;
+        userDef = 0;
+        line = ln;
+    }
+
+    void setAggregate(int s, bool m = false)
+    {
+        size = s;
+        matrix = m;
+    }
+
+    void setArray(bool a, int s = 0)
+    {
+        array = a;
+        arraySize = s;
+    }
+
+    bool isStructureContainingArrays() const
+    {
+        if (!userDef)
+        {
+            return false;
+        }
+
+        return userDef->isStructureContainingArrays();
+    }
+};
+
+#endif // _TYPES_INCLUDED_
diff --git a/src/3rdparty/angle/src/compiler/UnfoldShortCircuit.cpp b/src/3rdparty/angle/src/compiler/UnfoldShortCircuit.cpp
new file mode 100644 (file)
index 0000000..1782ebc
--- /dev/null
@@ -0,0 +1,172 @@
+//
+// 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.
+//
+// UnfoldShortCircuit is an AST traverser to output short-circuiting operators as if-else statements.
+// The results are assigned to s# temporaries, which are used by the main translator instead of
+// the original expression.
+//
+
+#include "compiler/UnfoldShortCircuit.h"
+
+#include "compiler/InfoSink.h"
+#include "compiler/OutputHLSL.h"
+
+namespace sh
+{
+UnfoldShortCircuit::UnfoldShortCircuit(TParseContext &context, OutputHLSL *outputHLSL) : mContext(context), mOutputHLSL(outputHLSL)
+{
+    mTemporaryIndex = 0;
+}
+
+void UnfoldShortCircuit::traverse(TIntermNode *node)
+{
+    int rewindIndex = mTemporaryIndex;
+    node->traverse(this);
+    mTemporaryIndex = rewindIndex;
+}
+
+bool UnfoldShortCircuit::visitBinary(Visit visit, TIntermBinary *node)
+{
+    TInfoSinkBase &out = mOutputHLSL->getBodyStream();
+
+    switch (node->getOp())
+    {
+      case EOpLogicalOr:
+        // "x || y" is equivalent to "x ? true : y", which unfolds to "bool s; if(x) s = true; else s = y;",
+        // and then further simplifies down to "bool s = x; if(!s) s = y;".
+        {
+            int i = mTemporaryIndex;
+
+            out << "bool s" << i << ";\n";
+
+            out << "{\n";
+
+            mTemporaryIndex = i + 1;
+            node->getLeft()->traverse(this);
+            out << "s" << i << " = ";
+            mTemporaryIndex = i + 1;
+            node->getLeft()->traverse(mOutputHLSL);
+            out << ";\n";
+            out << "if(!s" << i << ")\n"
+                   "{\n";
+            mTemporaryIndex = i + 1;
+            node->getRight()->traverse(this);
+            out << "    s" << i << " = ";
+            mTemporaryIndex = i + 1;
+            node->getRight()->traverse(mOutputHLSL);
+            out << ";\n"
+                   "}\n";
+
+            out << "}\n";
+
+            mTemporaryIndex = i + 1;
+        }
+        return false;
+      case EOpLogicalAnd:
+        // "x && y" is equivalent to "x ? y : false", which unfolds to "bool s; if(x) s = y; else s = false;",
+        // and then further simplifies down to "bool s = x; if(s) s = y;".
+        {
+            int i = mTemporaryIndex;
+
+            out << "bool s" << i << ";\n";
+
+            out << "{\n";
+
+            mTemporaryIndex = i + 1;
+            node->getLeft()->traverse(this);
+            out << "s" << i << " = ";
+            mTemporaryIndex = i + 1;
+            node->getLeft()->traverse(mOutputHLSL);
+            out << ";\n";
+            out << "if(s" << i << ")\n"
+                   "{\n";
+            mTemporaryIndex = i + 1;
+            node->getRight()->traverse(this);
+            out << "    s" << i << " = ";
+            mTemporaryIndex = i + 1;
+            node->getRight()->traverse(mOutputHLSL);
+            out << ";\n"
+                   "}\n";
+
+            out << "}\n";
+
+            mTemporaryIndex = i + 1;
+        }
+        return false;
+    }
+
+    return true;
+}
+
+bool UnfoldShortCircuit::visitSelection(Visit visit, TIntermSelection *node)
+{
+    TInfoSinkBase &out = mOutputHLSL->getBodyStream();
+
+    // Unfold "b ? x : y" into "type s; if(b) s = x; else s = y;"
+    if (node->usesTernaryOperator())
+    {
+        int i = mTemporaryIndex;
+
+        out << mOutputHLSL->typeString(node->getType()) << " s" << i << ";\n";
+
+        mTemporaryIndex = i + 1;
+        node->getCondition()->traverse(this);
+        out << "if(";
+        mTemporaryIndex = i + 1;
+        node->getCondition()->traverse(mOutputHLSL);
+        out << ")\n"
+               "{\n";
+        mTemporaryIndex = i + 1;
+        node->getTrueBlock()->traverse(this);
+        out << "    s" << i << " = ";
+        mTemporaryIndex = i + 1;
+        node->getTrueBlock()->traverse(mOutputHLSL);
+        out << ";\n"
+               "}\n"
+               "else\n"
+               "{\n";
+        mTemporaryIndex = i + 1;
+        node->getFalseBlock()->traverse(this);
+        out << "    s" << i << " = ";
+        mTemporaryIndex = i + 1;
+        node->getFalseBlock()->traverse(mOutputHLSL);
+        out << ";\n"
+               "}\n";
+
+        mTemporaryIndex = i + 1;
+    }
+
+    return false;
+}
+
+bool UnfoldShortCircuit::visitLoop(Visit visit, TIntermLoop *node)
+{
+    int rewindIndex = mTemporaryIndex;
+
+    if (node->getInit())
+    {
+        node->getInit()->traverse(this);
+    }
+    
+    if (node->getCondition())
+    {
+        node->getCondition()->traverse(this);
+    }
+
+    if (node->getExpression())
+    {
+        node->getExpression()->traverse(this);
+    }
+
+    mTemporaryIndex = rewindIndex;
+
+    return false;
+}
+
+int UnfoldShortCircuit::getNextTemporaryIndex()
+{
+    return mTemporaryIndex++;
+}
+}
diff --git a/src/3rdparty/angle/src/compiler/UnfoldShortCircuit.h b/src/3rdparty/angle/src/compiler/UnfoldShortCircuit.h
new file mode 100644 (file)
index 0000000..cb176a5
--- /dev/null
@@ -0,0 +1,39 @@
+//
+// 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.
+//
+// UnfoldShortCircuit is an AST traverser to output short-circuiting operators as if-else statements
+//
+
+#ifndef COMPILER_UNFOLDSHORTCIRCUIT_H_
+#define COMPILER_UNFOLDSHORTCIRCUIT_H_
+
+#include "compiler/intermediate.h"
+#include "compiler/ParseHelper.h"
+
+namespace sh
+{
+class OutputHLSL;
+
+class UnfoldShortCircuit : public TIntermTraverser
+{
+  public:
+    UnfoldShortCircuit(TParseContext &context, OutputHLSL *outputHLSL);
+
+    void traverse(TIntermNode *node);
+    bool visitBinary(Visit visit, TIntermBinary*);
+    bool visitSelection(Visit visit, TIntermSelection *node);
+    bool visitLoop(Visit visit, TIntermLoop *node);
+
+    int getNextTemporaryIndex();
+
+  protected:
+    TParseContext &mContext;
+    OutputHLSL *const mOutputHLSL;
+
+    int mTemporaryIndex;
+};
+}
+
+#endif   // COMPILER_UNFOLDSHORTCIRCUIT_H_
diff --git a/src/3rdparty/angle/src/compiler/ValidateLimitations.cpp b/src/3rdparty/angle/src/compiler/ValidateLimitations.cpp
new file mode 100644 (file)
index 0000000..d69ec6b
--- /dev/null
@@ -0,0 +1,512 @@
+//
+// 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/ValidateLimitations.h"
+#include "compiler/InfoSink.h"
+#include "compiler/InitializeParseContext.h"
+#include "compiler/ParseHelper.h"
+
+namespace {
+bool IsLoopIndex(const TIntermSymbol* symbol, const TLoopStack& stack) {
+    for (TLoopStack::const_iterator i = stack.begin(); i != stack.end(); ++i) {
+        if (i->index.id == symbol->getId())
+            return true;
+    }
+    return false;
+}
+
+void MarkLoopForUnroll(const TIntermSymbol* symbol, TLoopStack& stack) {
+    for (TLoopStack::iterator i = stack.begin(); i != stack.end(); ++i) {
+        if (i->index.id == symbol->getId()) {
+            ASSERT(i->loop != NULL);
+            i->loop->setUnrollFlag(true);
+            return;
+        }
+    }
+    UNREACHABLE();
+}
+
+// Traverses a node to check if it represents a constant index expression.
+// Definition:
+// constant-index-expressions are a superset of constant-expressions.
+// Constant-index-expressions can include loop indices as defined in
+// GLSL ES 1.0 spec, Appendix A, section 4.
+// The following are constant-index-expressions:
+// - Constant expressions
+// - Loop indices as defined in section 4
+// - Expressions composed of both of the above
+class ValidateConstIndexExpr : public TIntermTraverser {
+public:
+    ValidateConstIndexExpr(const TLoopStack& stack)
+        : mValid(true), mLoopStack(stack) {}
+
+    // Returns true if the parsed node represents a constant index expression.
+    bool isValid() const { return mValid; }
+
+    virtual void visitSymbol(TIntermSymbol* symbol) {
+        // Only constants and loop indices are allowed in a
+        // constant index expression.
+        if (mValid) {
+            mValid = (symbol->getQualifier() == EvqConst) ||
+                     IsLoopIndex(symbol, mLoopStack);
+        }
+    }
+
+private:
+    bool mValid;
+    const TLoopStack& mLoopStack;
+};
+
+// Traverses a node to check if it uses a loop index.
+// If an int loop index is used in its body as a sampler array index,
+// mark the loop for unroll.
+class ValidateLoopIndexExpr : public TIntermTraverser {
+public:
+    ValidateLoopIndexExpr(TLoopStack& stack)
+        : mUsesFloatLoopIndex(false),
+          mUsesIntLoopIndex(false),
+          mLoopStack(stack) {}
+
+    bool usesFloatLoopIndex() const { return mUsesFloatLoopIndex; }
+    bool usesIntLoopIndex() const { return mUsesIntLoopIndex; }
+
+    virtual void visitSymbol(TIntermSymbol* symbol) {
+        if (IsLoopIndex(symbol, mLoopStack)) {
+            switch (symbol->getBasicType()) {
+              case EbtFloat:
+                mUsesFloatLoopIndex = true;
+                break;
+              case EbtInt:
+                mUsesIntLoopIndex = true;
+                MarkLoopForUnroll(symbol, mLoopStack);
+                break;
+              default:
+                UNREACHABLE();
+            }
+        }
+    }
+
+private:
+    bool mUsesFloatLoopIndex;
+    bool mUsesIntLoopIndex;
+    TLoopStack& mLoopStack;
+};
+}  // namespace
+
+ValidateLimitations::ValidateLimitations(ShShaderType shaderType,
+                                         TInfoSinkBase& sink)
+    : mShaderType(shaderType),
+      mSink(sink),
+      mNumErrors(0)
+{
+}
+
+bool ValidateLimitations::visitBinary(Visit, TIntermBinary* node)
+{
+    // Check if loop index is modified in the loop body.
+    validateOperation(node, node->getLeft());
+
+    // Check indexing.
+    switch (node->getOp()) {
+      case EOpIndexDirect:
+        validateIndexing(node);
+        break;
+      case EOpIndexIndirect:
+#if defined(__APPLE__)
+        // Loop unrolling is a work-around for a Mac Cg compiler bug where it
+        // crashes when a sampler array's index is also the loop index.
+        // Once Apple fixes this bug, we should remove the code in this CL.
+        // See http://codereview.appspot.com/4331048/.
+        if ((node->getLeft() != NULL) && (node->getRight() != NULL) &&
+            (node->getLeft()->getAsSymbolNode())) {
+            TIntermSymbol* symbol = node->getLeft()->getAsSymbolNode();
+            if (IsSampler(symbol->getBasicType()) && symbol->isArray()) {
+                ValidateLoopIndexExpr validate(mLoopStack);
+                node->getRight()->traverse(&validate);
+                if (validate.usesFloatLoopIndex()) {
+                    error(node->getLine(),
+                          "sampler array index is float loop index",
+                          "for");
+                }
+            }
+        }
+#endif
+        validateIndexing(node);
+        break;
+      default: break;
+    }
+    return true;
+}
+
+bool ValidateLimitations::visitUnary(Visit, TIntermUnary* node)
+{
+    // Check if loop index is modified in the loop body.
+    validateOperation(node, node->getOperand());
+
+    return true;
+}
+
+bool ValidateLimitations::visitAggregate(Visit, TIntermAggregate* node)
+{
+    switch (node->getOp()) {
+      case EOpFunctionCall:
+        validateFunctionCall(node);
+        break;
+      default:
+        break;
+    }
+    return true;
+}
+
+bool ValidateLimitations::visitLoop(Visit, TIntermLoop* node)
+{
+    if (!validateLoopType(node))
+        return false;
+
+    TLoopInfo info;
+    memset(&info, 0, sizeof(TLoopInfo));
+    info.loop = node;
+    if (!validateForLoopHeader(node, &info))
+        return false;
+
+    TIntermNode* body = node->getBody();
+    if (body != NULL) {
+        mLoopStack.push_back(info);
+        body->traverse(this);
+        mLoopStack.pop_back();
+    }
+
+    // The loop is fully processed - no need to visit children.
+    return false;
+}
+
+void ValidateLimitations::error(TSourceLoc loc,
+                                const char *reason, const char* token)
+{
+    mSink.prefix(EPrefixError);
+    mSink.location(loc);
+    mSink << "'" << token << "' : " << reason << "\n";
+    ++mNumErrors;
+}
+
+bool ValidateLimitations::withinLoopBody() const
+{
+    return !mLoopStack.empty();
+}
+
+bool ValidateLimitations::isLoopIndex(const TIntermSymbol* symbol) const
+{
+    return IsLoopIndex(symbol, mLoopStack);
+}
+
+bool ValidateLimitations::validateLoopType(TIntermLoop* node) {
+    TLoopType type = node->getType();
+    if (type == ELoopFor)
+        return true;
+
+    // Reject while and do-while loops.
+    error(node->getLine(),
+          "This type of loop is not allowed",
+          type == ELoopWhile ? "while" : "do");
+    return false;
+}
+
+bool ValidateLimitations::validateForLoopHeader(TIntermLoop* node,
+                                                TLoopInfo* info)
+{
+    ASSERT(node->getType() == ELoopFor);
+
+    //
+    // The for statement has the form:
+    //    for ( init-declaration ; condition ; expression ) statement
+    //
+    if (!validateForLoopInit(node, info))
+        return false;
+    if (!validateForLoopCond(node, info))
+        return false;
+    if (!validateForLoopExpr(node, info))
+        return false;
+
+    return true;
+}
+
+bool ValidateLimitations::validateForLoopInit(TIntermLoop* node,
+                                              TLoopInfo* info)
+{
+    TIntermNode* init = node->getInit();
+    if (init == NULL) {
+        error(node->getLine(), "Missing init declaration", "for");
+        return false;
+    }
+
+    //
+    // init-declaration has the form:
+    //     type-specifier identifier = constant-expression
+    //
+    TIntermAggregate* decl = init->getAsAggregate();
+    if ((decl == NULL) || (decl->getOp() != EOpDeclaration)) {
+        error(init->getLine(), "Invalid init declaration", "for");
+        return false;
+    }
+    // To keep things simple do not allow declaration list.
+    TIntermSequence& declSeq = decl->getSequence();
+    if (declSeq.size() != 1) {
+        error(decl->getLine(), "Invalid init declaration", "for");
+        return false;
+    }
+    TIntermBinary* declInit = declSeq[0]->getAsBinaryNode();
+    if ((declInit == NULL) || (declInit->getOp() != EOpInitialize)) {
+        error(decl->getLine(), "Invalid init declaration", "for");
+        return false;
+    }
+    TIntermSymbol* symbol = declInit->getLeft()->getAsSymbolNode();
+    if (symbol == NULL) {
+        error(declInit->getLine(), "Invalid init declaration", "for");
+        return false;
+    }
+    // The loop index has type int or float.
+    TBasicType type = symbol->getBasicType();
+    if ((type != EbtInt) && (type != EbtFloat)) {
+        error(symbol->getLine(),
+              "Invalid type for loop index", getBasicString(type));
+        return false;
+    }
+    // The loop index is initialized with constant expression.
+    if (!isConstExpr(declInit->getRight())) {
+        error(declInit->getLine(),
+              "Loop index cannot be initialized with non-constant expression",
+              symbol->getSymbol().c_str());
+        return false;
+    }
+
+    info->index.id = symbol->getId();
+    return true;
+}
+
+bool ValidateLimitations::validateForLoopCond(TIntermLoop* node,
+                                              TLoopInfo* info)
+{
+    TIntermNode* cond = node->getCondition();
+    if (cond == NULL) {
+        error(node->getLine(), "Missing condition", "for");
+        return false;
+    }
+    //
+    // condition has the form:
+    //     loop_index relational_operator constant_expression
+    //
+    TIntermBinary* binOp = cond->getAsBinaryNode();
+    if (binOp == NULL) {
+        error(node->getLine(), "Invalid condition", "for");
+        return false;
+    }
+    // Loop index should be to the left of relational operator.
+    TIntermSymbol* symbol = binOp->getLeft()->getAsSymbolNode();
+    if (symbol == NULL) {
+        error(binOp->getLine(), "Invalid condition", "for");
+        return false;
+    }
+    if (symbol->getId() != info->index.id) {
+        error(symbol->getLine(),
+              "Expected loop index", symbol->getSymbol().c_str());
+        return false;
+    }
+    // Relational operator is one of: > >= < <= == or !=.
+    switch (binOp->getOp()) {
+      case EOpEqual:
+      case EOpNotEqual:
+      case EOpLessThan:
+      case EOpGreaterThan:
+      case EOpLessThanEqual:
+      case EOpGreaterThanEqual:
+        break;
+      default:
+        error(binOp->getLine(),
+              "Invalid relational operator",
+              getOperatorString(binOp->getOp()));
+        break;
+    }
+    // Loop index must be compared with a constant.
+    if (!isConstExpr(binOp->getRight())) {
+        error(binOp->getLine(),
+              "Loop index cannot be compared with non-constant expression",
+              symbol->getSymbol().c_str());
+        return false;
+    }
+
+    return true;
+}
+
+bool ValidateLimitations::validateForLoopExpr(TIntermLoop* node,
+                                              TLoopInfo* info)
+{
+    TIntermNode* expr = node->getExpression();
+    if (expr == NULL) {
+        error(node->getLine(), "Missing expression", "for");
+        return false;
+    }
+
+    // for expression has one of the following forms:
+    //     loop_index++
+    //     loop_index--
+    //     loop_index += constant_expression
+    //     loop_index -= constant_expression
+    //     ++loop_index
+    //     --loop_index
+    // The last two forms are not specified in the spec, but I am assuming
+    // its an oversight.
+    TIntermUnary* unOp = expr->getAsUnaryNode();
+    TIntermBinary* binOp = unOp ? NULL : expr->getAsBinaryNode();
+
+    TOperator op = EOpNull;
+    TIntermSymbol* symbol = NULL;
+    if (unOp != NULL) {
+        op = unOp->getOp();
+        symbol = unOp->getOperand()->getAsSymbolNode();
+    } else if (binOp != NULL) {
+        op = binOp->getOp();
+        symbol = binOp->getLeft()->getAsSymbolNode();
+    }
+
+    // The operand must be loop index.
+    if (symbol == NULL) {
+        error(expr->getLine(), "Invalid expression", "for");
+        return false;
+    }
+    if (symbol->getId() != info->index.id) {
+        error(symbol->getLine(),
+              "Expected loop index", symbol->getSymbol().c_str());
+        return false;
+    }
+
+    // The operator is one of: ++ -- += -=.
+    switch (op) {
+        case EOpPostIncrement:
+        case EOpPostDecrement:
+        case EOpPreIncrement:
+        case EOpPreDecrement:
+            ASSERT((unOp != NULL) && (binOp == NULL));
+            break;
+        case EOpAddAssign:
+        case EOpSubAssign:
+            ASSERT((unOp == NULL) && (binOp != NULL));
+            break;
+        default:
+            error(expr->getLine(), "Invalid operator", getOperatorString(op));
+            return false;
+    }
+
+    // Loop index must be incremented/decremented with a constant.
+    if (binOp != NULL) {
+        if (!isConstExpr(binOp->getRight())) {
+            error(binOp->getLine(),
+                  "Loop index cannot be modified by non-constant expression",
+                  symbol->getSymbol().c_str());
+            return false;
+        }
+    }
+
+    return true;
+}
+
+bool ValidateLimitations::validateFunctionCall(TIntermAggregate* node)
+{
+    ASSERT(node->getOp() == EOpFunctionCall);
+
+    // If not within loop body, there is nothing to check.
+    if (!withinLoopBody())
+        return true;
+
+    // List of param indices for which loop indices are used as argument.
+    typedef std::vector<int> ParamIndex;
+    ParamIndex pIndex;
+    TIntermSequence& params = node->getSequence();
+    for (TIntermSequence::size_type i = 0; i < params.size(); ++i) {
+        TIntermSymbol* symbol = params[i]->getAsSymbolNode();
+        if (symbol && isLoopIndex(symbol))
+            pIndex.push_back(i);
+    }
+    // If none of the loop indices are used as arguments,
+    // there is nothing to check.
+    if (pIndex.empty())
+        return true;
+
+    bool valid = true;
+    TSymbolTable& symbolTable = GlobalParseContext->symbolTable;
+    TSymbol* symbol = symbolTable.find(node->getName());
+    ASSERT(symbol && symbol->isFunction());
+    TFunction* function = static_cast<TFunction*>(symbol);
+    for (ParamIndex::const_iterator i = pIndex.begin();
+         i != pIndex.end(); ++i) {
+        const TParameter& param = function->getParam(*i);
+        TQualifier qual = param.type->getQualifier();
+        if ((qual == EvqOut) || (qual == EvqInOut)) {
+            error(params[*i]->getLine(),
+                  "Loop index cannot be used as argument to a function out or inout parameter",
+                  params[*i]->getAsSymbolNode()->getSymbol().c_str());
+            valid = false;
+        }
+    }
+
+    return valid;
+}
+
+bool ValidateLimitations::validateOperation(TIntermOperator* node,
+                                            TIntermNode* operand) {
+    // Check if loop index is modified in the loop body.
+    if (!withinLoopBody() || !node->modifiesState())
+        return true;
+
+    const TIntermSymbol* symbol = operand->getAsSymbolNode();
+    if (symbol && isLoopIndex(symbol)) {
+        error(node->getLine(),
+              "Loop index cannot be statically assigned to within the body of the loop",
+              symbol->getSymbol().c_str());
+    }
+    return true;
+}
+
+bool ValidateLimitations::isConstExpr(TIntermNode* node)
+{
+    ASSERT(node != NULL);
+    return node->getAsConstantUnion() != NULL;
+}
+
+bool ValidateLimitations::isConstIndexExpr(TIntermNode* node)
+{
+    ASSERT(node != NULL);
+
+    ValidateConstIndexExpr validate(mLoopStack);
+    node->traverse(&validate);
+    return validate.isValid();
+}
+
+bool ValidateLimitations::validateIndexing(TIntermBinary* node)
+{
+    ASSERT((node->getOp() == EOpIndexDirect) ||
+           (node->getOp() == EOpIndexIndirect));
+
+    bool valid = true;
+    TIntermTyped* index = node->getRight();
+    // The index expression must have integral type.
+    if (!index->isScalar() || (index->getBasicType() != EbtInt)) {
+        error(index->getLine(),
+              "Index expression must have integral type",
+              index->getCompleteString().c_str());
+        valid = false;
+    }
+    // The index expession must be a constant-index-expression unless
+    // the operand is a uniform in a vertex shader.
+    TIntermTyped* operand = node->getLeft();
+    bool skip = (mShaderType == SH_VERTEX_SHADER) &&
+                (operand->getQualifier() == EvqUniform);
+    if (!skip && !isConstIndexExpr(index)) {
+        error(index->getLine(), "Index expression must be constant", "[]");
+        valid = false;
+    }
+    return valid;
+}
+
diff --git a/src/3rdparty/angle/src/compiler/ValidateLimitations.h b/src/3rdparty/angle/src/compiler/ValidateLimitations.h
new file mode 100644 (file)
index 0000000..a835cb3
--- /dev/null
@@ -0,0 +1,59 @@
+//
+// Copyright (c) 2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "GLSLANG/ShaderLang.h"
+#include "compiler/intermediate.h"
+
+class TInfoSinkBase;
+
+struct TLoopInfo {
+    struct TIndex {
+        int id;  // symbol id.
+    } index;
+    TIntermLoop* loop;
+};
+typedef TVector<TLoopInfo> TLoopStack;
+
+// Traverses intermediate tree to ensure that the shader does not exceed the
+// minimum functionality mandated in GLSL 1.0 spec, Appendix A.
+class ValidateLimitations : public TIntermTraverser {
+public:
+    ValidateLimitations(ShShaderType shaderType, TInfoSinkBase& sink);
+
+    int numErrors() const { return mNumErrors; }
+
+    virtual bool visitBinary(Visit, TIntermBinary*);
+    virtual bool visitUnary(Visit, TIntermUnary*);
+    virtual bool visitAggregate(Visit, TIntermAggregate*);
+    virtual bool visitLoop(Visit, TIntermLoop*);
+
+private:
+    void error(TSourceLoc loc, const char *reason, const char* token);
+
+    bool withinLoopBody() const;
+    bool isLoopIndex(const TIntermSymbol* symbol) const;
+    bool validateLoopType(TIntermLoop* node);
+    bool validateForLoopHeader(TIntermLoop* node, TLoopInfo* info);
+    bool validateForLoopInit(TIntermLoop* node, TLoopInfo* info);
+    bool validateForLoopCond(TIntermLoop* node, TLoopInfo* info);
+    bool validateForLoopExpr(TIntermLoop* node, TLoopInfo* info);
+    // Returns true if none of the loop indices is used as the argument to
+    // the given function out or inout parameter.
+    bool validateFunctionCall(TIntermAggregate* node);
+    bool validateOperation(TIntermOperator* node, TIntermNode* operand);
+
+    // Returns true if indexing does not exceed the minimum functionality
+    // mandated in GLSL 1.0 spec, Appendix A, Section 5.
+    bool isConstExpr(TIntermNode* node);
+    bool isConstIndexExpr(TIntermNode* node);
+    bool validateIndexing(TIntermBinary* node);
+
+    ShShaderType mShaderType;
+    TInfoSinkBase& mSink;
+    int mNumErrors;
+    TLoopStack mLoopStack;
+};
+
diff --git a/src/3rdparty/angle/src/compiler/VariableInfo.cpp b/src/3rdparty/angle/src/compiler/VariableInfo.cpp
new file mode 100644 (file)
index 0000000..3ff2836
--- /dev/null
@@ -0,0 +1,232 @@
+//
+// 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/VariableInfo.h"
+
+static TString arrayBrackets(int index)
+{
+    TStringStream stream;
+    stream << "[" << index << "]";
+    return stream.str();
+}
+
+// Returns the data type for an attribute or uniform.
+static ShDataType getVariableDataType(const TType& type)
+{
+    switch (type.getBasicType()) {
+      case EbtFloat:
+          if (type.isMatrix()) {
+              switch (type.getNominalSize()) {
+                case 2: return SH_FLOAT_MAT2;
+                case 3: return SH_FLOAT_MAT3;
+                case 4: return SH_FLOAT_MAT4;
+                default: UNREACHABLE();
+              }
+          } else if (type.isVector()) {
+              switch (type.getNominalSize()) {
+                case 2: return SH_FLOAT_VEC2;
+                case 3: return SH_FLOAT_VEC3;
+                case 4: return SH_FLOAT_VEC4;
+                default: UNREACHABLE();
+              }
+          } else {
+              return SH_FLOAT;
+          }
+      case EbtInt:
+          if (type.isMatrix()) {
+              UNREACHABLE();
+          } else if (type.isVector()) {
+              switch (type.getNominalSize()) {
+                case 2: return SH_INT_VEC2;
+                case 3: return SH_INT_VEC3;
+                case 4: return SH_INT_VEC4;
+                default: UNREACHABLE();
+              }
+          } else {
+              return SH_INT;
+          }
+      case EbtBool:
+          if (type.isMatrix()) {
+              UNREACHABLE();
+          } else if (type.isVector()) {
+              switch (type.getNominalSize()) {
+                case 2: return SH_BOOL_VEC2;
+                case 3: return SH_BOOL_VEC3;
+                case 4: return SH_BOOL_VEC4;
+                default: UNREACHABLE();
+              }
+          } else {
+              return SH_BOOL;
+          }
+      case EbtSampler2D: return SH_SAMPLER_2D;
+      case EbtSamplerCube: return SH_SAMPLER_CUBE;
+      case EbtSamplerExternalOES: return SH_SAMPLER_EXTERNAL_OES;
+      case EbtSampler2DRect: return SH_SAMPLER_2D_RECT_ARB;
+      default: UNREACHABLE();
+    }
+    return SH_NONE;
+}
+
+static void getBuiltInVariableInfo(const TType& type,
+                                   const TString& name,
+                                   const TString& mappedName,
+                                   TVariableInfoList& infoList);
+static void getUserDefinedVariableInfo(const TType& type,
+                                       const TString& name,
+                                       const TString& mappedName,
+                                       TVariableInfoList& infoList);
+
+// Returns info for an attribute or uniform.
+static void getVariableInfo(const TType& type,
+                            const TString& name,
+                            const TString& mappedName,
+                            TVariableInfoList& infoList)
+{
+    if (type.getBasicType() == EbtStruct) {
+        if (type.isArray()) {
+            for (int i = 0; i < type.getArraySize(); ++i) {
+                TString lname = name + arrayBrackets(i);
+                TString lmappedName = mappedName + arrayBrackets(i);
+                getUserDefinedVariableInfo(type, lname, lmappedName, infoList);
+            }
+        } else {
+            getUserDefinedVariableInfo(type, name, mappedName, infoList);
+        }
+    } else {
+        getBuiltInVariableInfo(type, name, mappedName, infoList);
+    }
+}
+
+void getBuiltInVariableInfo(const TType& type,
+                            const TString& name,
+                            const TString& mappedName,
+                            TVariableInfoList& infoList)
+{
+    ASSERT(type.getBasicType() != EbtStruct);
+
+    TVariableInfo varInfo;
+    if (type.isArray()) {
+        varInfo.name = (name + "[0]").c_str();
+        varInfo.mappedName = (mappedName + "[0]").c_str();
+        varInfo.size = type.getArraySize();
+    } else {
+        varInfo.name = name.c_str();
+        varInfo.mappedName = mappedName.c_str();
+        varInfo.size = 1;
+    }
+    varInfo.type = getVariableDataType(type);
+    infoList.push_back(varInfo);
+}
+
+void getUserDefinedVariableInfo(const TType& type,
+                                const TString& name,
+                                const TString& mappedName,
+                                TVariableInfoList& infoList)
+{
+    ASSERT(type.getBasicType() == EbtStruct);
+
+    const TTypeList* structure = type.getStruct();
+    for (size_t i = 0; i < structure->size(); ++i) {
+        const TType* fieldType = (*structure)[i].type;
+        getVariableInfo(*fieldType,
+                        name + "." + fieldType->getFieldName(),
+                        mappedName + "." + fieldType->getFieldName(),
+                        infoList);
+    }
+}
+
+TVariableInfo::TVariableInfo()
+{
+}
+
+TVariableInfo::TVariableInfo(ShDataType type, int size)
+    : type(type),
+      size(size)
+{
+}
+
+CollectAttribsUniforms::CollectAttribsUniforms(TVariableInfoList& attribs,
+                                               TVariableInfoList& uniforms)
+    : mAttribs(attribs),
+      mUniforms(uniforms)
+{
+}
+
+// We are only interested in attribute and uniform variable declaration.
+void CollectAttribsUniforms::visitSymbol(TIntermSymbol*)
+{
+}
+
+void CollectAttribsUniforms::visitConstantUnion(TIntermConstantUnion*)
+{
+}
+
+bool CollectAttribsUniforms::visitBinary(Visit, TIntermBinary*)
+{
+    return false;
+}
+
+bool CollectAttribsUniforms::visitUnary(Visit, TIntermUnary*)
+{
+    return false;
+}
+
+bool CollectAttribsUniforms::visitSelection(Visit, TIntermSelection*)
+{
+    return false;
+}
+
+bool CollectAttribsUniforms::visitAggregate(Visit, TIntermAggregate* node)
+{
+    bool visitChildren = false;
+
+    switch (node->getOp())
+    {
+    case EOpSequence:
+        // We need to visit sequence children to get to variable declarations.
+        visitChildren = true;
+        break;
+    case EOpDeclaration: {
+        const TIntermSequence& sequence = node->getSequence();
+        TQualifier qualifier = sequence.front()->getAsTyped()->getQualifier();
+        if (qualifier == EvqAttribute || qualifier == EvqUniform)
+        {
+            TVariableInfoList& infoList = qualifier == EvqAttribute ?
+                mAttribs : mUniforms;
+            for (TIntermSequence::const_iterator i = sequence.begin();
+                 i != sequence.end(); ++i)
+            {
+                const TIntermSymbol* variable = (*i)->getAsSymbolNode();
+                // The only case in which the sequence will not contain a
+                // TIntermSymbol node is initialization. It will contain a
+                // TInterBinary node in that case. Since attributes and unifroms
+                // cannot be initialized in a shader, we must have only
+                // TIntermSymbol nodes in the sequence.
+                ASSERT(variable != NULL);
+                getVariableInfo(variable->getType(),
+                                variable->getOriginalSymbol(),
+                                variable->getSymbol(),
+                                infoList);
+            }
+        }
+        break;
+    }
+    default: break;
+    }
+
+    return visitChildren;
+}
+
+bool CollectAttribsUniforms::visitLoop(Visit, TIntermLoop*)
+{
+    return false;
+}
+
+bool CollectAttribsUniforms::visitBranch(Visit, TIntermBranch*)
+{
+    return false;
+}
+
diff --git a/src/3rdparty/angle/src/compiler/VariableInfo.h b/src/3rdparty/angle/src/compiler/VariableInfo.h
new file mode 100644 (file)
index 0000000..fdcc08f
--- /dev/null
@@ -0,0 +1,46 @@
+//
+// 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_VARIABLE_INFO_H_
+#define COMPILER_VARIABLE_INFO_H_
+
+#include "GLSLANG/ShaderLang.h"
+#include "compiler/intermediate.h"
+
+// Provides information about a variable.
+// It is currently being used to store info about active attribs and uniforms.
+struct TVariableInfo {
+    TVariableInfo(ShDataType type, int size);
+    TVariableInfo();
+
+    TPersistString name;
+    TPersistString mappedName;
+    ShDataType type;
+    int size;
+};
+typedef std::vector<TVariableInfo> TVariableInfoList;
+
+// Traverses intermediate tree to collect all attributes and uniforms.
+class CollectAttribsUniforms : public TIntermTraverser {
+public:
+    CollectAttribsUniforms(TVariableInfoList& attribs,
+                           TVariableInfoList& uniforms);
+
+    virtual void visitSymbol(TIntermSymbol*);
+    virtual void visitConstantUnion(TIntermConstantUnion*);
+    virtual bool visitBinary(Visit, TIntermBinary*);
+    virtual bool visitUnary(Visit, TIntermUnary*);
+    virtual bool visitSelection(Visit, TIntermSelection*);
+    virtual bool visitAggregate(Visit, TIntermAggregate*);
+    virtual bool visitLoop(Visit, TIntermLoop*);
+    virtual bool visitBranch(Visit, TIntermBranch*);
+
+private:
+    TVariableInfoList& mAttribs;
+    TVariableInfoList& mUniforms;
+};
+
+#endif  // COMPILER_VARIABLE_INFO_H_
diff --git a/src/3rdparty/angle/src/compiler/VariablePacker.cpp b/src/3rdparty/angle/src/compiler/VariablePacker.cpp
new file mode 100644 (file)
index 0000000..2f0c4bc
--- /dev/null
@@ -0,0 +1,297 @@
+//
+// 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/VariablePacker.h"
+
+#include <algorithm>
+#include "compiler/ShHandle.h"
+
+namespace {
+int GetSortOrder(ShDataType type)
+{
+    switch (type) {
+        case SH_FLOAT_MAT4:
+            return 0;
+        case SH_FLOAT_MAT2:
+            return 1;
+        case SH_FLOAT_VEC4:
+        case SH_INT_VEC4:
+        case SH_BOOL_VEC4:
+            return 2;
+        case SH_FLOAT_MAT3:
+            return 3;
+        case SH_FLOAT_VEC3:
+        case SH_INT_VEC3:
+        case SH_BOOL_VEC3:
+            return 4;
+        case SH_FLOAT_VEC2:
+        case SH_INT_VEC2:
+        case SH_BOOL_VEC2:
+            return 5;
+        case SH_FLOAT:
+        case SH_INT:
+        case SH_BOOL:
+        case SH_SAMPLER_2D:
+        case SH_SAMPLER_CUBE:
+        case SH_SAMPLER_EXTERNAL_OES:
+        case SH_SAMPLER_2D_RECT_ARB:
+            return 6;
+        default:
+            ASSERT(false);
+            return 7;
+    }
+}
+}    // namespace
+
+int VariablePacker::GetNumComponentsPerRow(ShDataType type)
+{
+    switch (type) {
+        case SH_FLOAT_MAT4:
+        case SH_FLOAT_MAT2:
+        case SH_FLOAT_VEC4:
+        case SH_INT_VEC4:
+        case SH_BOOL_VEC4:
+            return 4;
+        case SH_FLOAT_MAT3:
+        case SH_FLOAT_VEC3:
+        case SH_INT_VEC3:
+        case SH_BOOL_VEC3:
+            return 3;
+        case SH_FLOAT_VEC2:
+        case SH_INT_VEC2:
+        case SH_BOOL_VEC2:
+            return 2;
+        case SH_FLOAT:
+        case SH_INT:
+        case SH_BOOL:
+        case SH_SAMPLER_2D:
+        case SH_SAMPLER_CUBE:
+        case SH_SAMPLER_EXTERNAL_OES:
+        case SH_SAMPLER_2D_RECT_ARB:
+            return 1;
+        default:
+            ASSERT(false);
+            return 5;
+    }
+}
+
+int VariablePacker::GetNumRows(ShDataType type)
+{
+    switch (type) {
+        case SH_FLOAT_MAT4:
+            return 4;
+        case SH_FLOAT_MAT3:
+            return 3;
+        case SH_FLOAT_MAT2:
+            return 1;
+        case SH_FLOAT_VEC4:
+        case SH_INT_VEC4:
+        case SH_BOOL_VEC4:
+        case SH_FLOAT_VEC3:
+        case SH_INT_VEC3:
+        case SH_BOOL_VEC3:
+        case SH_FLOAT_VEC2:
+        case SH_INT_VEC2:
+        case SH_BOOL_VEC2:
+        case SH_FLOAT:
+        case SH_INT:
+        case SH_BOOL:
+        case SH_SAMPLER_2D:
+        case SH_SAMPLER_CUBE:
+        case SH_SAMPLER_EXTERNAL_OES:
+        case SH_SAMPLER_2D_RECT_ARB:
+            return 1;
+        default:
+            ASSERT(false);
+            return 100000;
+    }
+}
+
+struct TVariableInfoComparer {
+    bool operator()(const TVariableInfo& lhs, const TVariableInfo& rhs) const
+    {
+        int lhsSortOrder = GetSortOrder(lhs.type);
+        int rhsSortOrder = GetSortOrder(rhs.type);
+        if (lhsSortOrder != rhsSortOrder) {
+            return lhsSortOrder < rhsSortOrder;
+        }
+        // Sort by largest first.
+        return lhs.size > rhs.size;
+    }
+};
+
+unsigned VariablePacker::makeColumnFlags(int column, int numComponentsPerRow)
+{
+    return ((kColumnMask << (kNumColumns - numComponentsPerRow)) &
+                    kColumnMask) >> column;
+}
+
+void VariablePacker::fillColumns(int topRow, int numRows, int column, int numComponentsPerRow)
+{
+    unsigned columnFlags = makeColumnFlags(column, numComponentsPerRow);
+    for (int r = 0; r < numRows; ++r) {
+        int row = topRow + r;
+        ASSERT((rows_[row] & columnFlags) == 0);
+        rows_[row] |= columnFlags;
+    }
+}
+
+bool VariablePacker::searchColumn(int column, int numRows, int* destRow, int* destSize)
+{
+    ASSERT(destRow);
+
+    for (; topNonFullRow_ < maxRows_ && rows_[topNonFullRow_] == kColumnMask;
+         ++topNonFullRow_) {
+    }
+
+    for (; bottomNonFullRow_ >= 0 && rows_[bottomNonFullRow_] == kColumnMask;
+         --bottomNonFullRow_) {
+    }
+
+    if (bottomNonFullRow_ - topNonFullRow_ + 1 < numRows) {
+        return false;
+    }
+
+    unsigned columnFlags = makeColumnFlags(column, 1);
+    int topGoodRow = 0;
+    int smallestGoodTop = -1;
+    int smallestGoodSize = maxRows_ + 1;
+    int bottomRow = bottomNonFullRow_ + 1;
+    bool found = false;
+    for (int row = topNonFullRow_; row <= bottomRow; ++row) {
+        bool rowEmpty = row < bottomRow ? ((rows_[row] & columnFlags) == 0) : false;
+        if (rowEmpty) {
+            if (!found) {
+                topGoodRow = row;
+                found = true;
+            }
+        } else {
+            if (found) {
+                int size = row - topGoodRow;
+                if (size >= numRows && size < smallestGoodSize) {
+                    smallestGoodSize = size;
+                    smallestGoodTop = topGoodRow;
+                }
+            }
+            found = false;
+        }
+    }
+    if (smallestGoodTop < 0) {
+        return false;
+    }
+
+    *destRow = smallestGoodTop;
+    if (destSize) {
+        *destSize = smallestGoodSize;
+    }
+    return true;
+}
+
+bool VariablePacker::CheckVariablesWithinPackingLimits(int maxVectors, const TVariableInfoList& in_variables)
+{
+    ASSERT(maxVectors > 0);
+    maxRows_ = maxVectors;
+    topNonFullRow_ = 0;
+    bottomNonFullRow_ = maxRows_ - 1;
+    TVariableInfoList variables(in_variables);
+
+    // As per GLSL 1.017 Appendix A, Section 7 variables are packed in specific
+    // order by type, then by size of array, largest first.
+    std::sort(variables.begin(), variables.end(), TVariableInfoComparer());
+    rows_.clear();
+    rows_.resize(maxVectors, 0);
+
+    // Packs the 4 column variables.
+    size_t ii = 0;
+    for (; ii < variables.size(); ++ii) {
+        const TVariableInfo& variable = variables[ii];
+        if (GetNumComponentsPerRow(variable.type) != 4) {
+            break;
+        }
+        topNonFullRow_ += GetNumRows(variable.type) * variable.size;
+    }
+
+    if (topNonFullRow_ > maxRows_) {
+        return false;
+    }
+
+    // Packs the 3 column variables.
+    int num3ColumnRows = 0;
+    for (; ii < variables.size(); ++ii) {
+        const TVariableInfo& variable = variables[ii];
+        if (GetNumComponentsPerRow(variable.type) != 3) {
+            break;
+        }
+        num3ColumnRows += GetNumRows(variable.type) * variable.size;
+    }
+
+    if (topNonFullRow_ + num3ColumnRows > maxRows_) {
+        return false;
+    }
+
+    fillColumns(topNonFullRow_, num3ColumnRows, 0, 3);
+
+    // Packs the 2 column variables.
+    int top2ColumnRow = topNonFullRow_ + num3ColumnRows;
+    int twoColumnRowsAvailable = maxRows_ - top2ColumnRow;
+    int rowsAvailableInColumns01 = twoColumnRowsAvailable;
+    int rowsAvailableInColumns23 = twoColumnRowsAvailable;
+    for (; ii < variables.size(); ++ii) {
+        const TVariableInfo& variable = variables[ii];
+        if (GetNumComponentsPerRow(variable.type) != 2) {
+            break;
+        }
+        int numRows = GetNumRows(variable.type) * variable.size;
+        if (numRows <= rowsAvailableInColumns01) {
+            rowsAvailableInColumns01 -= numRows;
+        } else if (numRows <= rowsAvailableInColumns23) {
+            rowsAvailableInColumns23 -= numRows;
+        } else {
+            return false;
+        }
+    }
+
+    int numRowsUsedInColumns01 =
+        twoColumnRowsAvailable - rowsAvailableInColumns01;
+    int numRowsUsedInColumns23 =
+        twoColumnRowsAvailable - rowsAvailableInColumns23;
+    fillColumns(top2ColumnRow, numRowsUsedInColumns01, 0, 2);
+    fillColumns(maxRows_ - numRowsUsedInColumns23, numRowsUsedInColumns23,
+                2, 2);
+
+    // Packs the 1 column variables.
+    for (; ii < variables.size(); ++ii) {
+        const TVariableInfo& variable = variables[ii];
+        ASSERT(1 == GetNumComponentsPerRow(variable.type));
+        int numRows = GetNumRows(variable.type) * variable.size;
+        int smallestColumn = -1;
+        int smallestSize = maxRows_ + 1;
+        int topRow = -1;
+        for (int column = 0; column < kNumColumns; ++column) {
+            int row = 0;
+            int size = 0;
+            if (searchColumn(column, numRows, &row, &size)) {
+                if (size < smallestSize) {
+                    smallestSize = size;
+                    smallestColumn = column;
+                    topRow = row;
+                }
+            }
+        }
+
+        if (smallestColumn < 0) {
+            return false;
+        }
+
+        fillColumns(topRow, numRows, smallestColumn, 1);
+    }
+
+    ASSERT(variables.size() == ii);
+
+    return true;
+}
+
+
+
diff --git a/src/3rdparty/angle/src/compiler/VariablePacker.h b/src/3rdparty/angle/src/compiler/VariablePacker.h
new file mode 100644 (file)
index 0000000..8987066
--- /dev/null
@@ -0,0 +1,41 @@
+//
+// 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 _VARIABLEPACKER_INCLUDED_
+#define _VARIABLEPACKER_INCLUDED_
+
+#include <vector>
+#include "compiler/ShHandle.h"
+
+class VariablePacker {
+ public:
+    // Returns true if the passed in variables pack in maxVectors following
+    // the packing rules from the GLSL 1.017 spec, Appendix A, section 7.
+    bool CheckVariablesWithinPackingLimits(
+        int maxVectors,
+        const TVariableInfoList& in_variables);
+
+    // Gets how many components in a row a data type takes.
+    static int GetNumComponentsPerRow(ShDataType type);
+
+    // Gets how many rows a data type takes.
+    static int GetNumRows(ShDataType type);
+
+ private:
+    static const int kNumColumns = 4;
+    static const unsigned kColumnMask = (1 << kNumColumns) - 1;
+
+    unsigned makeColumnFlags(int column, int numComponentsPerRow);
+    void fillColumns(int topRow, int numRows, int column, int numComponentsPerRow);
+    bool searchColumn(int column, int numRows, int* destRow, int* destSize);
+
+    int topNonFullRow_;
+    int bottomNonFullRow_;
+    int maxRows_;
+    std::vector<unsigned> rows_;
+};
+
+#endif // _VARIABLEPACKER_INCLUDED_
diff --git a/src/3rdparty/angle/src/compiler/VersionGLSL.cpp b/src/3rdparty/angle/src/compiler/VersionGLSL.cpp
new file mode 100644 (file)
index 0000000..7a82bb4
--- /dev/null
@@ -0,0 +1,140 @@
+//
+// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "compiler/VersionGLSL.h"
+
+static const int GLSL_VERSION_110 = 110;
+static const int GLSL_VERSION_120 = 120;
+
+// We need to scan for the following:
+// 1. "invariant" keyword: This can occur in both - vertex and fragment shaders
+//    but only at the global scope.
+// 2. "gl_PointCoord" built-in variable: This can only occur in fragment shader
+//    but inside any scope.
+// 3. Call to a matrix constructor with another matrix as argument.
+//    (These constructors were reserved in GLSL version 1.10.)
+// 4. Arrays as "out" function parameters.
+//    GLSL spec section 6.1.1: "When calling a function, expressions that do
+//    not evaluate to l-values cannot be passed to parameters declared as
+//    out or inout."
+//    GLSL 1.1 section 5.8: "Other binary or unary expressions,
+//    non-dereferenced arrays, function names, swizzles with repeated fields,
+//    and constants cannot be l-values."
+//    GLSL 1.2 relaxed the restriction on arrays, section 5.8: "Variables that
+//    are built-in types, entire structures or arrays... are all l-values."
+//
+// TODO(alokp): The following two cases of invariant decalaration get lost
+// during parsing - they do not get carried over to the intermediate tree.
+// Handle these cases:
+// 1. When a pragma is used to force all output variables to be invariant:
+//    - #pragma STDGL invariant(all)
+// 2. When a previously decalared or built-in variable is marked invariant:
+//    - invariant gl_Position;
+//    - varying vec3 color; invariant color;
+//
+TVersionGLSL::TVersionGLSL(ShShaderType type)
+    : mShaderType(type),
+      mVersion(GLSL_VERSION_110)
+{
+}
+
+void TVersionGLSL::visitSymbol(TIntermSymbol* node)
+{
+    if (node->getSymbol() == "gl_PointCoord")
+        updateVersion(GLSL_VERSION_120);
+}
+
+void TVersionGLSL::visitConstantUnion(TIntermConstantUnion*)
+{
+}
+
+bool TVersionGLSL::visitBinary(Visit, TIntermBinary*)
+{
+    return true;
+}
+
+bool TVersionGLSL::visitUnary(Visit, TIntermUnary*)
+{
+    return true;
+}
+
+bool TVersionGLSL::visitSelection(Visit, TIntermSelection*)
+{
+    return true;
+}
+
+bool TVersionGLSL::visitAggregate(Visit, TIntermAggregate* node)
+{
+    bool visitChildren = true;
+
+    switch (node->getOp()) {
+      case EOpSequence:
+        // We need to visit sequence children to get to global or inner scope.
+        visitChildren = true;
+        break;
+      case EOpDeclaration: {
+        const TIntermSequence& sequence = node->getSequence();
+        TQualifier qualifier = sequence.front()->getAsTyped()->getQualifier();
+        if ((qualifier == EvqInvariantVaryingIn) ||
+            (qualifier == EvqInvariantVaryingOut)) {
+            updateVersion(GLSL_VERSION_120);
+        }
+        break;
+      }
+      case EOpParameters: {
+        const TIntermSequence& params = node->getSequence();
+        for (TIntermSequence::const_iterator iter = params.begin();
+             iter != params.end(); ++iter)
+        {
+            const TIntermTyped* param = (*iter)->getAsTyped();
+            if (param->isArray())
+            {
+                TQualifier qualifier = param->getQualifier();
+                if ((qualifier == EvqOut) || (qualifier ==  EvqInOut))
+                {
+                    updateVersion(GLSL_VERSION_120);
+                    break;
+                }
+            }
+        }
+        // Fully processed. No need to visit children.
+        visitChildren = false;
+        break;
+      }
+      case EOpConstructMat2:
+      case EOpConstructMat3:
+      case EOpConstructMat4: {
+        const TIntermSequence& sequence = node->getSequence();
+        if (sequence.size() == 1) {
+          TIntermTyped* typed = sequence.front()->getAsTyped();
+          if (typed && typed->isMatrix()) {
+            updateVersion(GLSL_VERSION_120);
+          }
+        }
+        break;
+      }
+
+      default: break;
+    }
+
+    return visitChildren;
+}
+
+bool TVersionGLSL::visitLoop(Visit, TIntermLoop*)
+{
+    return true;
+}
+
+bool TVersionGLSL::visitBranch(Visit, TIntermBranch*)
+{
+    return true;
+}
+
+void TVersionGLSL::updateVersion(int version)
+{
+    mVersion = std::max(version, mVersion);
+}
+
diff --git a/src/3rdparty/angle/src/compiler/VersionGLSL.h b/src/3rdparty/angle/src/compiler/VersionGLSL.h
new file mode 100644 (file)
index 0000000..1c1cb1a
--- /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 COMPILER_VERSIONGLSL_H_
+#define COMPILER_VERSIONGLSL_H_
+
+#include "GLSLANG/ShaderLang.h"
+#include "compiler/intermediate.h"
+
+// Traverses the intermediate tree to return the minimum GLSL version
+// required to legally access all built-in features used in the shader.
+// GLSL 1.1 which is mandated by OpenGL 2.0 provides:
+//   - #version and #extension to declare version and extensions.
+//   - built-in functions refract, exp, and log.
+//   - updated step() to compare x < edge instead of x <= edge.
+// GLSL 1.2 which is mandated by OpenGL 2.1 provides:
+//   - many changes to reduce differences when compared to the ES specification.
+//   - invariant keyword and its support.
+//   - c++ style name hiding rules.
+//   - built-in variable gl_PointCoord for fragment shaders.
+//   - matrix constructors taking matrix as argument.
+//   - array as "out" function parameters
+//
+class TVersionGLSL : public TIntermTraverser {
+public:
+    TVersionGLSL(ShShaderType type);
+
+    // Returns 120 if the following is used the shader:
+    // - "invariant",
+    // - "gl_PointCoord",
+    // - matrix/matrix constructors
+    // - array "out" parameters
+    // Else 110 is returned.
+    int getVersion() { return mVersion; }
+
+    virtual void visitSymbol(TIntermSymbol*);
+    virtual void visitConstantUnion(TIntermConstantUnion*);
+    virtual bool visitBinary(Visit, TIntermBinary*);
+    virtual bool visitUnary(Visit, TIntermUnary*);
+    virtual bool visitSelection(Visit, TIntermSelection*);
+    virtual bool visitAggregate(Visit, TIntermAggregate*);
+    virtual bool visitLoop(Visit, TIntermLoop*);
+    virtual bool visitBranch(Visit, TIntermBranch*);
+
+protected:
+    void updateVersion(int version);
+
+private:
+    ShShaderType mShaderType;
+    int mVersion;
+};
+
+#endif  // COMPILER_VERSIONGLSL_H_
diff --git a/src/3rdparty/angle/src/compiler/debug.cpp b/src/3rdparty/angle/src/compiler/debug.cpp
new file mode 100644 (file)
index 0000000..53778bd
--- /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.
+//
+
+// debug.cpp: Debugging utilities.
+
+#include "compiler/debug.h"
+
+#include <stdarg.h>
+#include <stdio.h>
+
+#include "compiler/InitializeParseContext.h"
+#include "compiler/ParseHelper.h"
+
+static const int kTraceBufferLen = 1024;
+
+#ifdef TRACE_ENABLED
+extern "C" {
+void Trace(const char *format, ...) {
+    if (!format) return;
+
+    TParseContext* parseContext = GetGlobalParseContext();
+    if (parseContext) {
+        char buf[kTraceBufferLen];
+        va_list args;
+        va_start(args, format);
+        vsnprintf(buf, kTraceBufferLen, format, args);
+        va_end(args);
+
+        parseContext->trace(buf);
+    }
+}
+}  // extern "C"
+#endif  // TRACE_ENABLED
+
diff --git a/src/3rdparty/angle/src/compiler/debug.h b/src/3rdparty/angle/src/compiler/debug.h
new file mode 100644 (file)
index 0000000..7a37151
--- /dev/null
@@ -0,0 +1,53 @@
+//
+// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// debug.h: Debugging utilities.
+
+#ifndef COMPILER_DEBUG_H_
+#define COMPILER_DEBUG_H_
+
+#include <assert.h>
+
+#ifdef _DEBUG
+#define TRACE_ENABLED  // define to enable debug message tracing
+#endif  // _DEBUG
+
+// Outputs text to the debug log
+#ifdef TRACE_ENABLED
+
+#ifdef  __cplusplus
+extern "C" {
+#endif  // __cplusplus
+void Trace(const char* format, ...);
+#ifdef  __cplusplus
+}
+#endif  // __cplusplus
+
+#else   // TRACE_ENABLED
+
+#define Trace(...) ((void)0)
+
+#endif  // TRACE_ENABLED
+
+// A macro asserting a condition and outputting failures to the debug log
+#define ASSERT(expression) do { \
+    if(!(expression)) \
+        Trace("Assert failed: %s(%d): "#expression"\n", __FUNCTION__, __LINE__); \
+    assert(expression); \
+} while(0)
+
+#define UNIMPLEMENTED() do { \
+    Trace("Unimplemented invoked: %s(%d)\n", __FUNCTION__, __LINE__); \
+    assert(false); \
+} while(0)
+
+#define UNREACHABLE() do { \
+    Trace("Unreachable reached: %s(%d)\n", __FUNCTION__, __LINE__); \
+    assert(false); \
+} while(0)
+
+#endif   // COMPILER_DEBUG_H_
+
diff --git a/src/3rdparty/angle/src/compiler/depgraph/DependencyGraph.cpp b/src/3rdparty/angle/src/compiler/depgraph/DependencyGraph.cpp
new file mode 100644 (file)
index 0000000..ca661d6
--- /dev/null
@@ -0,0 +1,97 @@
+//
+// 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.
+//
+
+#pragma warning(disable: 4718)
+
+#include "compiler/depgraph/DependencyGraph.h"
+#include "compiler/depgraph/DependencyGraphBuilder.h"
+
+TDependencyGraph::TDependencyGraph(TIntermNode* intermNode)
+{
+    TDependencyGraphBuilder::build(intermNode, this);
+}
+
+TDependencyGraph::~TDependencyGraph()
+{
+    for (TGraphNodeVector::const_iterator iter = mAllNodes.begin(); iter != mAllNodes.end(); ++iter)
+    {
+        TGraphNode* node = *iter;
+        delete node;
+    }
+}
+
+TGraphArgument* TDependencyGraph::createArgument(TIntermAggregate* intermFunctionCall,
+                                                 int argumentNumber)
+{
+    TGraphArgument* argument = new TGraphArgument(intermFunctionCall, argumentNumber);
+    mAllNodes.push_back(argument);
+    return argument;
+}
+
+TGraphFunctionCall* TDependencyGraph::createFunctionCall(TIntermAggregate* intermFunctionCall)
+{
+    TGraphFunctionCall* functionCall = new TGraphFunctionCall(intermFunctionCall);
+    mAllNodes.push_back(functionCall);
+    if (functionCall->getIntermFunctionCall()->isUserDefined())
+        mUserDefinedFunctionCalls.push_back(functionCall);
+    return functionCall;
+}
+
+TGraphSymbol* TDependencyGraph::getOrCreateSymbol(TIntermSymbol* intermSymbol)
+{
+    TSymbolIdMap::const_iterator iter = mSymbolIdMap.find(intermSymbol->getId());
+
+    TGraphSymbol* symbol = NULL;
+
+    if (iter != mSymbolIdMap.end()) {
+        TSymbolIdPair pair = *iter;
+        symbol = pair.second;
+    } else {
+        symbol = new TGraphSymbol(intermSymbol);
+        mAllNodes.push_back(symbol);
+
+        TSymbolIdPair pair(intermSymbol->getId(), symbol);
+        mSymbolIdMap.insert(pair);
+
+        // We save all sampler symbols in a collection, so we can start graph traversals from them quickly.
+        if (IsSampler(intermSymbol->getBasicType()))
+            mSamplerSymbols.push_back(symbol);
+    }
+
+    return symbol;
+}
+
+TGraphSelection* TDependencyGraph::createSelection(TIntermSelection* intermSelection)
+{
+    TGraphSelection* selection = new TGraphSelection(intermSelection);
+    mAllNodes.push_back(selection);
+    return selection;
+}
+
+TGraphLoop* TDependencyGraph::createLoop(TIntermLoop* intermLoop)
+{
+    TGraphLoop* loop = new TGraphLoop(intermLoop);
+    mAllNodes.push_back(loop);
+    return loop;
+}
+
+TGraphLogicalOp* TDependencyGraph::createLogicalOp(TIntermBinary* intermLogicalOp)
+{
+    TGraphLogicalOp* logicalOp = new TGraphLogicalOp(intermLogicalOp);
+    mAllNodes.push_back(logicalOp);
+    return logicalOp;
+}
+
+const char* TGraphLogicalOp::getOpString() const
+{
+    const char* opString = NULL;
+    switch (getIntermLogicalOp()->getOp()) {
+        case EOpLogicalAnd: opString = "and"; break;
+        case EOpLogicalOr: opString = "or"; break;
+        default: opString = "unknown"; break;
+    }
+    return opString;
+}
diff --git a/src/3rdparty/angle/src/compiler/depgraph/DependencyGraph.h b/src/3rdparty/angle/src/compiler/depgraph/DependencyGraph.h
new file mode 100644 (file)
index 0000000..5a9c35d
--- /dev/null
@@ -0,0 +1,212 @@
+//
+// 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_DEPGRAPH_DEPENDENCY_GRAPH_H
+#define COMPILER_DEPGRAPH_DEPENDENCY_GRAPH_H
+
+#include "compiler/intermediate.h"
+
+#include <set>
+#include <stack>
+
+class TGraphNode;
+class TGraphParentNode;
+class TGraphArgument;
+class TGraphFunctionCall;
+class TGraphSymbol;
+class TGraphSelection;
+class TGraphLoop;
+class TGraphLogicalOp;
+class TDependencyGraphTraverser;
+class TDependencyGraphOutput;
+
+typedef std::set<TGraphNode*> TGraphNodeSet;
+typedef std::vector<TGraphNode*> TGraphNodeVector;
+typedef std::vector<TGraphSymbol*> TGraphSymbolVector;
+typedef std::vector<TGraphFunctionCall*> TFunctionCallVector;
+
+//
+// Base class for all dependency graph nodes.
+//
+class TGraphNode {
+public:
+    TGraphNode(TIntermNode* node) : intermNode(node) {}
+    virtual ~TGraphNode() {}
+    virtual void traverse(TDependencyGraphTraverser* graphTraverser);
+protected:
+    TIntermNode* intermNode;
+};
+
+//
+// Base class for dependency graph nodes that may have children.
+//
+class TGraphParentNode : public TGraphNode {
+public:
+    TGraphParentNode(TIntermNode* node) : TGraphNode(node) {}
+    virtual ~TGraphParentNode() {}
+    void addDependentNode(TGraphNode* node) { if (node != this) mDependentNodes.insert(node); }
+    virtual void traverse(TDependencyGraphTraverser* graphTraverser);
+private:
+    TGraphNodeSet mDependentNodes;
+};
+
+//
+// Handle function call arguments.
+//
+class TGraphArgument : public TGraphParentNode {
+public:
+    TGraphArgument(TIntermAggregate* intermFunctionCall, int argumentNumber)
+        : TGraphParentNode(intermFunctionCall)
+        , mArgumentNumber(argumentNumber) {}
+    virtual ~TGraphArgument() {}
+    const TIntermAggregate* getIntermFunctionCall() const { return intermNode->getAsAggregate(); }
+    int getArgumentNumber() const { return mArgumentNumber; }
+    virtual void traverse(TDependencyGraphTraverser* graphTraverser);
+private:
+    int mArgumentNumber;
+};
+
+//
+// Handle function calls.
+//
+class TGraphFunctionCall : public TGraphParentNode {
+public:
+    TGraphFunctionCall(TIntermAggregate* intermFunctionCall)
+        : TGraphParentNode(intermFunctionCall) {}
+    virtual ~TGraphFunctionCall() {}
+    const TIntermAggregate* getIntermFunctionCall() const { return intermNode->getAsAggregate(); }
+    virtual void traverse(TDependencyGraphTraverser* graphTraverser);
+};
+
+//
+// Handle symbols.
+//
+class TGraphSymbol : public TGraphParentNode {
+public:
+    TGraphSymbol(TIntermSymbol* intermSymbol) : TGraphParentNode(intermSymbol) {}
+    virtual ~TGraphSymbol() {}
+    const TIntermSymbol* getIntermSymbol() const { return intermNode->getAsSymbolNode(); }
+    virtual void traverse(TDependencyGraphTraverser* graphTraverser);
+};
+
+//
+// Handle if statements and ternary operators.
+//
+class TGraphSelection : public TGraphNode {
+public:
+    TGraphSelection(TIntermSelection* intermSelection) : TGraphNode(intermSelection) {}
+    virtual ~TGraphSelection() {}
+    const TIntermSelection* getIntermSelection() const { return intermNode->getAsSelectionNode(); }
+    virtual void traverse(TDependencyGraphTraverser* graphTraverser);
+};
+
+//
+// Handle for, do-while, and while loops.
+//
+class TGraphLoop : public TGraphNode {
+public:
+    TGraphLoop(TIntermLoop* intermLoop) : TGraphNode(intermLoop) {}
+    virtual ~TGraphLoop() {}
+    const TIntermLoop* getIntermLoop() const { return intermNode->getAsLoopNode(); }
+    virtual void traverse(TDependencyGraphTraverser* graphTraverser);
+};
+
+//
+// Handle logical and, or.
+//
+class TGraphLogicalOp : public TGraphNode {
+public:
+    TGraphLogicalOp(TIntermBinary* intermLogicalOp) : TGraphNode(intermLogicalOp) {}
+    virtual ~TGraphLogicalOp() {}
+    const TIntermBinary* getIntermLogicalOp() const { return intermNode->getAsBinaryNode(); }
+    const char* getOpString() const;
+    virtual void traverse(TDependencyGraphTraverser* graphTraverser);
+};
+
+//
+// A dependency graph of symbols, function calls, conditions etc.
+//
+// This class provides an interface to the entry points of the dependency graph.
+//
+// Dependency graph nodes should be created by using one of the provided "create..." methods.
+// This class (and nobody else) manages the memory of the created nodes.
+// Nodes may not be removed after being added, so all created nodes will exist while the
+// TDependencyGraph instance exists.
+//
+class TDependencyGraph {
+public:
+    TDependencyGraph(TIntermNode* intermNode);
+    ~TDependencyGraph();
+    TGraphNodeVector::const_iterator begin() const { return mAllNodes.begin(); }
+    TGraphNodeVector::const_iterator end() const { return mAllNodes.end(); }
+
+    TGraphSymbolVector::const_iterator beginSamplerSymbols() const
+    {
+        return mSamplerSymbols.begin();
+    }
+
+    TGraphSymbolVector::const_iterator endSamplerSymbols() const
+    {
+        return mSamplerSymbols.end();
+    }
+
+    TFunctionCallVector::const_iterator beginUserDefinedFunctionCalls() const
+    {
+        return mUserDefinedFunctionCalls.begin();
+    }
+
+    TFunctionCallVector::const_iterator endUserDefinedFunctionCalls() const
+    {
+        return mUserDefinedFunctionCalls.end();
+    }
+
+    TGraphArgument* createArgument(TIntermAggregate* intermFunctionCall, int argumentNumber);
+    TGraphFunctionCall* createFunctionCall(TIntermAggregate* intermFunctionCall);
+    TGraphSymbol* getOrCreateSymbol(TIntermSymbol* intermSymbol);
+    TGraphSelection* createSelection(TIntermSelection* intermSelection);
+    TGraphLoop* createLoop(TIntermLoop* intermLoop);
+    TGraphLogicalOp* createLogicalOp(TIntermBinary* intermLogicalOp);
+private:
+    typedef TMap<int, TGraphSymbol*> TSymbolIdMap;
+    typedef std::pair<int, TGraphSymbol*> TSymbolIdPair;
+
+    TGraphNodeVector mAllNodes;
+    TGraphSymbolVector mSamplerSymbols;
+    TFunctionCallVector mUserDefinedFunctionCalls;
+    TSymbolIdMap mSymbolIdMap;
+};
+
+//
+// For traversing the dependency graph. Users should derive from this,
+// put their traversal specific data in it, and then pass it to a
+// traverse method.
+//
+// When using this, just fill in the methods for nodes you want visited.
+//
+class TDependencyGraphTraverser {
+public:
+    TDependencyGraphTraverser() : mDepth(0) {}
+
+    virtual void visitSymbol(TGraphSymbol* symbol) {};
+    virtual void visitArgument(TGraphArgument* selection) {};
+    virtual void visitFunctionCall(TGraphFunctionCall* functionCall) {};
+    virtual void visitSelection(TGraphSelection* selection) {};
+    virtual void visitLoop(TGraphLoop* loop) {};
+    virtual void visitLogicalOp(TGraphLogicalOp* logicalOp) {};
+
+    int getDepth() const { return mDepth; }
+    void incrementDepth() { ++mDepth; }
+    void decrementDepth() { --mDepth; }
+
+    void clearVisited() { mVisited.clear(); }
+    void markVisited(TGraphNode* node) { mVisited.insert(node); }
+    bool isVisited(TGraphNode* node) const { return mVisited.find(node) != mVisited.end(); }
+private:
+    int mDepth;
+    TGraphNodeSet mVisited;
+};
+
+#endif
diff --git a/src/3rdparty/angle/src/compiler/depgraph/DependencyGraphBuilder.cpp b/src/3rdparty/angle/src/compiler/depgraph/DependencyGraphBuilder.cpp
new file mode 100644 (file)
index 0000000..d586cfd
--- /dev/null
@@ -0,0 +1,227 @@
+//
+// 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/depgraph/DependencyGraphBuilder.h"
+
+void TDependencyGraphBuilder::build(TIntermNode* node, TDependencyGraph* graph)
+{
+    TDependencyGraphBuilder builder(graph);
+    builder.build(node);
+}
+
+bool TDependencyGraphBuilder::visitAggregate(Visit visit, TIntermAggregate* intermAggregate)
+{
+    switch (intermAggregate->getOp()) {
+        case EOpFunction: visitFunctionDefinition(intermAggregate); break;
+        case EOpFunctionCall: visitFunctionCall(intermAggregate); break;
+        default: visitAggregateChildren(intermAggregate); break;
+    }
+
+    return false;
+}
+
+void TDependencyGraphBuilder::visitFunctionDefinition(TIntermAggregate* intermAggregate)
+{
+    // Currently, we do not support user defined functions.
+    if (intermAggregate->getName() != "main(")
+        return;
+
+    visitAggregateChildren(intermAggregate);
+}
+
+// Takes an expression like "f(x)" and creates a dependency graph like
+// "x -> argument 0 -> function call".
+void TDependencyGraphBuilder::visitFunctionCall(TIntermAggregate* intermFunctionCall)
+{
+    TGraphFunctionCall* functionCall = mGraph->createFunctionCall(intermFunctionCall);
+
+    // Run through the function call arguments.
+    int argumentNumber = 0;
+    TIntermSequence& intermArguments = intermFunctionCall->getSequence();
+    for (TIntermSequence::const_iterator iter = intermArguments.begin();
+         iter != intermArguments.end();
+         ++iter, ++argumentNumber)
+    {
+        TNodeSetMaintainer nodeSetMaintainer(this);
+
+        TIntermNode* intermArgument = *iter;
+        intermArgument->traverse(this);
+
+        if (TParentNodeSet* argumentNodes = mNodeSets.getTopSet()) {
+            TGraphArgument* argument = mGraph->createArgument(intermFunctionCall, argumentNumber);
+            connectMultipleNodesToSingleNode(argumentNodes, argument);
+            argument->addDependentNode(functionCall);
+        }
+    }
+
+    // Push the leftmost symbol of this function call into the current set of dependent symbols to
+    // represent the result of this function call.
+    // Thus, an expression like "y = f(x)" will yield a dependency graph like
+    // "x -> argument 0 -> function call -> y".
+    // This line essentially passes the function call node back up to an earlier visitAssignment
+    // call, which will create the connection "function call -> y".
+    mNodeSets.insertIntoTopSet(functionCall);
+}
+
+void TDependencyGraphBuilder::visitAggregateChildren(TIntermAggregate* intermAggregate)
+{
+    TIntermSequence& sequence = intermAggregate->getSequence();
+    for(TIntermSequence::const_iterator iter = sequence.begin(); iter != sequence.end(); ++iter)
+    {
+        TIntermNode* intermChild = *iter;
+        intermChild->traverse(this);
+    }
+}
+
+void TDependencyGraphBuilder::visitSymbol(TIntermSymbol* intermSymbol)
+{
+    // Push this symbol into the set of dependent symbols for the current assignment or condition
+    // that we are traversing.
+    TGraphSymbol* symbol = mGraph->getOrCreateSymbol(intermSymbol);
+    mNodeSets.insertIntoTopSet(symbol);
+
+    // If this symbol is the current leftmost symbol under an assignment, replace the previous
+    // leftmost symbol with this symbol.
+    if (!mLeftmostSymbols.empty() && mLeftmostSymbols.top() != &mRightSubtree) {
+        mLeftmostSymbols.pop();
+        mLeftmostSymbols.push(symbol);
+    }
+}
+
+bool TDependencyGraphBuilder::visitBinary(Visit visit, TIntermBinary* intermBinary)
+{
+    TOperator op = intermBinary->getOp();
+    if (op == EOpInitialize || intermBinary->modifiesState())
+        visitAssignment(intermBinary);
+    else if (op == EOpLogicalAnd || op == EOpLogicalOr)
+        visitLogicalOp(intermBinary);
+    else
+        visitBinaryChildren(intermBinary);
+
+    return false;
+}
+
+void TDependencyGraphBuilder::visitAssignment(TIntermBinary* intermAssignment)
+{
+    TIntermTyped* intermLeft = intermAssignment->getLeft();
+    if (!intermLeft)
+        return;
+
+    TGraphSymbol* leftmostSymbol = NULL;
+
+    {
+        TNodeSetMaintainer nodeSetMaintainer(this);
+
+        {
+            TLeftmostSymbolMaintainer leftmostSymbolMaintainer(this, mLeftSubtree);
+            intermLeft->traverse(this);
+            leftmostSymbol = mLeftmostSymbols.top();
+
+            // After traversing the left subtree of this assignment, we should have found a real
+            // leftmost symbol, and the leftmost symbol should not be a placeholder.
+            ASSERT(leftmostSymbol != &mLeftSubtree);
+            ASSERT(leftmostSymbol != &mRightSubtree);
+        }
+
+        if (TIntermTyped* intermRight = intermAssignment->getRight()) {
+            TLeftmostSymbolMaintainer leftmostSymbolMaintainer(this, mRightSubtree);
+            intermRight->traverse(this);
+        }
+
+        if (TParentNodeSet* assignmentNodes = mNodeSets.getTopSet())
+            connectMultipleNodesToSingleNode(assignmentNodes, leftmostSymbol);
+    }
+
+    // Push the leftmost symbol of this assignment into the current set of dependent symbols to
+    // represent the result of this assignment.
+    // An expression like "a = (b = c)" will yield a dependency graph like "c -> b -> a".
+    // This line essentially passes the leftmost symbol of the nested assignment ("b" in this
+    // example) back up to the earlier visitAssignment call for the outer assignment, which will
+    // create the connection "b -> a".
+    mNodeSets.insertIntoTopSet(leftmostSymbol);
+}
+
+void TDependencyGraphBuilder::visitLogicalOp(TIntermBinary* intermLogicalOp)
+{
+    if (TIntermTyped* intermLeft = intermLogicalOp->getLeft()) {
+        TNodeSetPropagatingMaintainer nodeSetMaintainer(this);
+
+        intermLeft->traverse(this);
+        if (TParentNodeSet* leftNodes = mNodeSets.getTopSet()) {
+            TGraphLogicalOp* logicalOp = mGraph->createLogicalOp(intermLogicalOp);
+            connectMultipleNodesToSingleNode(leftNodes, logicalOp);
+        }
+    }
+
+    if (TIntermTyped* intermRight = intermLogicalOp->getRight()) {
+        TLeftmostSymbolMaintainer leftmostSymbolMaintainer(this, mRightSubtree);
+        intermRight->traverse(this);
+    }
+}
+
+void TDependencyGraphBuilder::visitBinaryChildren(TIntermBinary* intermBinary)
+{
+    if (TIntermTyped* intermLeft = intermBinary->getLeft())
+        intermLeft->traverse(this);
+
+    if (TIntermTyped* intermRight = intermBinary->getRight()) {
+        TLeftmostSymbolMaintainer leftmostSymbolMaintainer(this, mRightSubtree);
+        intermRight->traverse(this);
+    }
+}
+
+bool TDependencyGraphBuilder::visitSelection(Visit visit, TIntermSelection* intermSelection)
+{
+    if (TIntermNode* intermCondition = intermSelection->getCondition()) {
+        TNodeSetMaintainer nodeSetMaintainer(this);
+
+        intermCondition->traverse(this);
+        if (TParentNodeSet* conditionNodes = mNodeSets.getTopSet()) {
+            TGraphSelection* selection = mGraph->createSelection(intermSelection);
+            connectMultipleNodesToSingleNode(conditionNodes, selection);
+        }
+    }
+
+    if (TIntermNode* intermTrueBlock = intermSelection->getTrueBlock())
+        intermTrueBlock->traverse(this);
+
+    if (TIntermNode* intermFalseBlock = intermSelection->getFalseBlock())
+        intermFalseBlock->traverse(this);
+
+    return false;
+}
+
+bool TDependencyGraphBuilder::visitLoop(Visit visit, TIntermLoop* intermLoop)
+{
+    if (TIntermTyped* intermCondition = intermLoop->getCondition()) {
+        TNodeSetMaintainer nodeSetMaintainer(this);
+
+        intermCondition->traverse(this);
+        if (TParentNodeSet* conditionNodes = mNodeSets.getTopSet()) {
+            TGraphLoop* loop = mGraph->createLoop(intermLoop);
+            connectMultipleNodesToSingleNode(conditionNodes, loop);
+        }
+    }
+
+    if (TIntermNode* intermBody = intermLoop->getBody())
+        intermBody->traverse(this);
+
+    if (TIntermTyped* intermExpression = intermLoop->getExpression())
+        intermExpression->traverse(this);
+
+    return false;
+}
+
+
+void TDependencyGraphBuilder::connectMultipleNodesToSingleNode(TParentNodeSet* nodes,
+                                                               TGraphNode* node) const
+{
+    for (TParentNodeSet::const_iterator iter = nodes->begin(); iter != nodes->end(); ++iter)
+    {
+        TGraphParentNode* currentNode = *iter;
+        currentNode->addDependentNode(node);
+    }
+}
diff --git a/src/3rdparty/angle/src/compiler/depgraph/DependencyGraphBuilder.h b/src/3rdparty/angle/src/compiler/depgraph/DependencyGraphBuilder.h
new file mode 100644 (file)
index 0000000..c5f232c
--- /dev/null
@@ -0,0 +1,181 @@
+//
+// 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_DEPGRAPH_DEPENDENCY_GRAPH_BUILDER_H
+#define COMPILER_DEPGRAPH_DEPENDENCY_GRAPH_BUILDER_H
+
+#include "compiler/depgraph/DependencyGraph.h"
+
+//
+// Creates a dependency graph of symbols, function calls, conditions etc. by traversing a
+// intermediate tree.
+//
+class TDependencyGraphBuilder : public TIntermTraverser {
+public:
+    static void build(TIntermNode* node, TDependencyGraph* graph);
+
+    virtual void visitSymbol(TIntermSymbol*);
+    virtual bool visitBinary(Visit visit, TIntermBinary*);
+    virtual bool visitSelection(Visit visit, TIntermSelection*);
+    virtual bool visitAggregate(Visit visit, TIntermAggregate*);
+    virtual bool visitLoop(Visit visit, TIntermLoop*);
+
+private:
+    typedef std::stack<TGraphSymbol*> TSymbolStack;
+    typedef std::set<TGraphParentNode*> TParentNodeSet;
+
+    //
+    // For collecting the dependent nodes of assignments, conditions, etc.
+    // while traversing the intermediate tree.
+    //
+    // This data structure is stack of sets. Each set contains dependency graph parent nodes.
+    //
+    class TNodeSetStack {
+    public:
+        TNodeSetStack() {};
+        ~TNodeSetStack() { clear(); }
+
+        // This should only be called after a pushSet.
+        // Returns NULL if the top set is empty.
+        TParentNodeSet* getTopSet() const
+        {
+            ASSERT(!nodeSets.empty());
+            TParentNodeSet* topSet = nodeSets.top();
+            return !topSet->empty() ? topSet : NULL;
+        }
+
+        void pushSet() { nodeSets.push(new TParentNodeSet()); }
+        void popSet()
+        {
+            ASSERT(!nodeSets.empty());
+            delete nodeSets.top();
+            nodeSets.pop();
+        }
+
+        // Pops the top set and adds its contents to the new top set.
+        // This should only be called after a pushSet.
+        // If there is no set below the top set, the top set is just deleted.
+        void popSetIntoNext()
+        {
+            ASSERT(!nodeSets.empty());
+            TParentNodeSet* oldTopSet = nodeSets.top();
+            nodeSets.pop();
+
+            if (!nodeSets.empty()) {
+                TParentNodeSet* newTopSet = nodeSets.top();
+                newTopSet->insert(oldTopSet->begin(), oldTopSet->end());
+            }
+
+            delete oldTopSet;
+        }
+
+        // Does nothing if there is no top set.
+        // This can be called when there is no top set if we are visiting
+        // symbols that are not under an assignment or condition.
+        // We don't need to track those symbols.
+        void insertIntoTopSet(TGraphParentNode* node)
+        {
+            if (nodeSets.empty())
+                return;
+
+            nodeSets.top()->insert(node);
+        }
+
+        void clear()
+        {
+            while (!nodeSets.empty())
+                popSet();
+        }
+
+    private:
+        typedef std::stack<TParentNodeSet*> TParentNodeSetStack;
+
+        TParentNodeSetStack nodeSets;
+    };
+
+    //
+    // An instance of this class pushes a new node set when instantiated.
+    // When the instance goes out of scope, it and pops the node set.
+    //
+    class TNodeSetMaintainer {
+    public:
+        TNodeSetMaintainer(TDependencyGraphBuilder* factory)
+            : sets(factory->mNodeSets) { sets.pushSet(); }
+        ~TNodeSetMaintainer() { sets.popSet(); }
+    protected:
+        TNodeSetStack& sets;
+    };
+
+    //
+    // An instance of this class pushes a new node set when instantiated.
+    // When the instance goes out of scope, it and pops the top node set and adds its contents to
+    // the new top node set.
+    //
+    class TNodeSetPropagatingMaintainer {
+    public:
+        TNodeSetPropagatingMaintainer(TDependencyGraphBuilder* factory)
+            : sets(factory->mNodeSets) { sets.pushSet(); }
+        ~TNodeSetPropagatingMaintainer() { sets.popSetIntoNext(); }
+    protected:
+        TNodeSetStack& sets;
+    };
+
+    //
+    // An instance of this class keeps track of the leftmost symbol while we're exploring an
+    // assignment.
+    // It will push the placeholder symbol kLeftSubtree when instantiated under a left subtree,
+    // and kRightSubtree under a right subtree.
+    // When it goes out of scope, it will pop the leftmost symbol at the top of the scope.
+    // During traversal, the TDependencyGraphBuilder will replace kLeftSubtree with a real symbol.
+    // kRightSubtree will never be replaced by a real symbol because we are tracking the leftmost
+    // symbol.
+    //
+    class TLeftmostSymbolMaintainer {
+    public:
+        TLeftmostSymbolMaintainer(TDependencyGraphBuilder* factory, TGraphSymbol& subtree)
+            : leftmostSymbols(factory->mLeftmostSymbols)
+        {
+            needsPlaceholderSymbol = leftmostSymbols.empty() || leftmostSymbols.top() != &subtree;
+            if (needsPlaceholderSymbol)
+                leftmostSymbols.push(&subtree);
+        }
+
+        ~TLeftmostSymbolMaintainer()
+        {
+            if (needsPlaceholderSymbol)
+                leftmostSymbols.pop();
+        }
+
+    protected:
+        TSymbolStack& leftmostSymbols;
+        bool needsPlaceholderSymbol;
+    };
+
+    TDependencyGraphBuilder(TDependencyGraph* graph)
+        : TIntermTraverser(true, false, false)
+        , mLeftSubtree(NULL)
+        , mRightSubtree(NULL)
+        , mGraph(graph) {}
+    void build(TIntermNode* intermNode) { intermNode->traverse(this); }
+
+    void connectMultipleNodesToSingleNode(TParentNodeSet* nodes, TGraphNode* node) const;
+
+    void visitAssignment(TIntermBinary*);
+    void visitLogicalOp(TIntermBinary*);
+    void visitBinaryChildren(TIntermBinary*);
+    void visitFunctionDefinition(TIntermAggregate*);
+    void visitFunctionCall(TIntermAggregate* intermFunctionCall);
+    void visitAggregateChildren(TIntermAggregate*);
+
+    TGraphSymbol mLeftSubtree;
+    TGraphSymbol mRightSubtree;
+
+    TDependencyGraph* mGraph;
+    TNodeSetStack mNodeSets;
+    TSymbolStack mLeftmostSymbols;
+};
+
+#endif  // COMPILER_DEPGRAPH_DEPENDENCY_GRAPH_BUILDER_H
diff --git a/src/3rdparty/angle/src/compiler/depgraph/DependencyGraphOutput.cpp b/src/3rdparty/angle/src/compiler/depgraph/DependencyGraphOutput.cpp
new file mode 100644 (file)
index 0000000..6fc489e
--- /dev/null
@@ -0,0 +1,65 @@
+//
+// 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/depgraph/DependencyGraphOutput.h"
+
+void TDependencyGraphOutput::outputIndentation()
+{
+    for (int i = 0; i < getDepth(); ++i)
+        mSink << "  ";
+}
+
+void TDependencyGraphOutput::visitArgument(TGraphArgument* parameter)
+{
+    outputIndentation();
+    mSink << "argument " << parameter->getArgumentNumber() << " of call to "
+          << parameter->getIntermFunctionCall()->getName() << "\n";
+}
+
+void TDependencyGraphOutput::visitFunctionCall(TGraphFunctionCall* functionCall)
+{
+    outputIndentation();
+    mSink << "function call " <<  functionCall->getIntermFunctionCall()->getName() << "\n";
+}
+
+void TDependencyGraphOutput::visitSymbol(TGraphSymbol* symbol)
+{
+    outputIndentation();
+    mSink << symbol->getIntermSymbol()->getSymbol() << " (symbol id: "
+          << symbol->getIntermSymbol()->getId() << ")\n";
+}
+
+void TDependencyGraphOutput::visitSelection(TGraphSelection* selection)
+{
+    outputIndentation();
+    mSink << "selection\n";
+}
+
+void TDependencyGraphOutput::visitLoop(TGraphLoop* loop)
+{
+    outputIndentation();
+    mSink << "loop condition\n";
+}
+
+void TDependencyGraphOutput::visitLogicalOp(TGraphLogicalOp* logicalOp)
+{
+    outputIndentation();
+    mSink << "logical " << logicalOp->getOpString() << "\n";
+}
+
+void TDependencyGraphOutput::outputAllSpanningTrees(TDependencyGraph& graph)
+{
+    mSink << "\n";
+
+    for (TGraphNodeVector::const_iterator iter = graph.begin(); iter != graph.end(); ++iter)
+    {
+        TGraphNode* symbol = *iter;
+        mSink << "--- Dependency graph spanning tree ---\n";
+        clearVisited();
+        symbol->traverse(this);
+        mSink << "\n";
+    }
+}
diff --git a/src/3rdparty/angle/src/compiler/depgraph/DependencyGraphOutput.h b/src/3rdparty/angle/src/compiler/depgraph/DependencyGraphOutput.h
new file mode 100644 (file)
index 0000000..01447da
--- /dev/null
@@ -0,0 +1,30 @@
+//
+// 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_DEPGRAPH_DEPENDENCY_GRAPH_OUTPUT_H
+#define COMPILER_DEPGRAPH_DEPENDENCY_GRAPH_OUTPUT_H
+
+#include "compiler/depgraph/DependencyGraph.h"
+#include "compiler/InfoSink.h"
+
+class TDependencyGraphOutput : public TDependencyGraphTraverser {
+public:
+    TDependencyGraphOutput(TInfoSinkBase& sink) : mSink(sink) {}
+    virtual void visitSymbol(TGraphSymbol* symbol);
+    virtual void visitArgument(TGraphArgument* parameter);
+    virtual void visitFunctionCall(TGraphFunctionCall* functionCall);
+    virtual void visitSelection(TGraphSelection* selection);
+    virtual void visitLoop(TGraphLoop* loop);
+    virtual void visitLogicalOp(TGraphLogicalOp* logicalOp);
+
+    void outputAllSpanningTrees(TDependencyGraph& graph);
+private:
+    void outputIndentation();
+
+    TInfoSinkBase& mSink;
+};
+
+#endif  // COMPILER_DEPGRAPH_DEPENDENCY_GRAPH_OUTPUT_H
diff --git a/src/3rdparty/angle/src/compiler/depgraph/DependencyGraphTraverse.cpp b/src/3rdparty/angle/src/compiler/depgraph/DependencyGraphTraverse.cpp
new file mode 100644 (file)
index 0000000..b158575
--- /dev/null
@@ -0,0 +1,69 @@
+//
+// 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/depgraph/DependencyGraph.h"
+
+// These methods do a breadth-first traversal through the graph and mark visited nodes.
+
+void TGraphNode::traverse(TDependencyGraphTraverser* graphTraverser)
+{
+    graphTraverser->markVisited(this);
+}
+
+void TGraphParentNode::traverse(TDependencyGraphTraverser* graphTraverser)
+{
+    TGraphNode::traverse(graphTraverser);
+
+    graphTraverser->incrementDepth();
+
+    // Visit the parent node's children.
+    for (TGraphNodeSet::const_iterator iter = mDependentNodes.begin();
+         iter != mDependentNodes.end();
+         ++iter)
+    {
+        TGraphNode* node = *iter;
+        if (!graphTraverser->isVisited(node))
+            node->traverse(graphTraverser);
+    }
+
+    graphTraverser->decrementDepth();
+}
+
+void TGraphArgument::traverse(TDependencyGraphTraverser* graphTraverser)
+{
+    graphTraverser->visitArgument(this);
+    TGraphParentNode::traverse(graphTraverser);
+}
+
+void TGraphFunctionCall::traverse(TDependencyGraphTraverser* graphTraverser)
+{
+    graphTraverser->visitFunctionCall(this);
+    TGraphParentNode::traverse(graphTraverser);
+}
+
+void TGraphSymbol::traverse(TDependencyGraphTraverser* graphTraverser)
+{
+    graphTraverser->visitSymbol(this);
+    TGraphParentNode::traverse(graphTraverser);
+}
+
+void TGraphSelection::traverse(TDependencyGraphTraverser* graphTraverser)
+{
+    graphTraverser->visitSelection(this);
+    TGraphNode::traverse(graphTraverser);
+}
+
+void TGraphLoop::traverse(TDependencyGraphTraverser* graphTraverser)
+{
+    graphTraverser->visitLoop(this);
+    TGraphNode::traverse(graphTraverser);
+}
+
+void TGraphLogicalOp::traverse(TDependencyGraphTraverser* graphTraverser)
+{
+    graphTraverser->visitLogicalOp(this);
+    TGraphNode::traverse(graphTraverser);
+}
diff --git a/src/3rdparty/angle/src/compiler/glslang.h b/src/3rdparty/angle/src/compiler/glslang.h
new file mode 100644 (file)
index 0000000..3a45daf
--- /dev/null
@@ -0,0 +1,16 @@
+//
+// Copyright (c) 2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+struct TParseContext;
+extern int glslang_initialize(TParseContext* context);
+extern int glslang_finalize(TParseContext* context);
+
+extern int glslang_scan(int count,
+                        const char* const string[],
+                        const int length[],
+                        TParseContext* context);
+extern int glslang_parse(TParseContext* context);
+
diff --git a/src/3rdparty/angle/src/compiler/glslang.l b/src/3rdparty/angle/src/compiler/glslang.l
new file mode 100644 (file)
index 0000000..e0483e2
--- /dev/null
@@ -0,0 +1,511 @@
+/*
+//
+// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+This file contains the Lex specification for GLSL ES.
+Based on ANSI C grammar, Lex specification:
+http://www.lysator.liu.se/c/ANSI-C-grammar-l.html
+
+IF YOU MODIFY THIS FILE YOU ALSO NEED TO RUN generate_parser.sh,
+WHICH GENERATES THE GLSL ES LEXER (glslang_lex.cpp).
+*/
+
+%top{
+//
+// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// This file is auto-generated by generate_parser.sh. DO NOT EDIT!
+
+// Ignore errors in auto-generated code.
+#if defined(__GNUC__)
+#pragma GCC diagnostic ignored "-Wunused-function"
+#pragma GCC diagnostic ignored "-Wunused-variable"
+#pragma GCC diagnostic ignored "-Wswitch-enum"
+#elif defined(_MSC_VER)
+#pragma warning(disable: 4065)
+#pragma warning(disable: 4189)
+#pragma warning(disable: 4505)
+#pragma warning(disable: 4701)
+#endif
+}
+
+%{
+#include "compiler/glslang.h"
+#include "compiler/ParseHelper.h"
+#include "compiler/preprocessor/new/Token.h"
+#include "compiler/util.h"
+#include "glslang_tab.h"
+
+/* windows only pragma */
+#ifdef _MSC_VER
+#pragma warning(disable : 4102)
+#endif
+
+#define YY_USER_ACTION yylval->lex.line = yylineno;
+#define YY_INPUT(buf, result, max_size) \
+    result = string_input(buf, max_size, yyscanner);
+
+static int string_input(char* buf, int max_size, yyscan_t yyscanner);
+static int check_type(yyscan_t yyscanner);
+static int reserved_word(yyscan_t yyscanner);
+%}
+
+%option noyywrap nounput never-interactive
+%option yylineno reentrant bison-bridge
+%option stack
+%option extra-type="TParseContext*"
+%x COMMENT FIELDS
+
+D           [0-9]
+L           [a-zA-Z_]
+H           [a-fA-F0-9]
+E           [Ee][+-]?{D}+
+O           [0-7]
+
+%%
+
+%{
+    TParseContext* context = yyextra;
+%}
+
+    /* Single-line comments */
+"//"[^\n]* ;
+
+    /* Multi-line comments */
+"/*"           { yy_push_state(COMMENT, yyscanner); }
+<COMMENT>. |
+<COMMENT>\n ;
+<COMMENT>"*/"  { yy_pop_state(yyscanner); }
+
+"invariant"    { return(INVARIANT); }
+"highp"        { return(HIGH_PRECISION); }
+"mediump"      { return(MEDIUM_PRECISION); }
+"lowp"         { return(LOW_PRECISION); }
+"precision"    { return(PRECISION); }
+
+"attribute"    { return(ATTRIBUTE); }
+"const"        { return(CONST_QUAL); }
+"uniform"      { return(UNIFORM); }
+"varying"      { return(VARYING); }
+
+"break"        { return(BREAK); }
+"continue"     { return(CONTINUE); }
+"do"           { return(DO); }
+"for"          { return(FOR); }
+"while"        { return(WHILE); }
+
+"if"           { return(IF); }
+"else"         { return(ELSE); }
+
+"in"           { return(IN_QUAL); }
+"out"          { return(OUT_QUAL); }
+"inout"        { return(INOUT_QUAL); }
+
+"float"        { context->lexAfterType = true; return(FLOAT_TYPE); }
+"int"          { context->lexAfterType = true; return(INT_TYPE); }
+"void"         { context->lexAfterType = true; return(VOID_TYPE); }
+"bool"         { context->lexAfterType = true; return(BOOL_TYPE); }
+"true"         { yylval->lex.b = true;  return(BOOLCONSTANT); }
+"false"        { yylval->lex.b = false; return(BOOLCONSTANT); }
+
+"discard"      { return(DISCARD); }
+"return"       { return(RETURN); }
+
+"mat2"         { context->lexAfterType = true; return(MATRIX2); }
+"mat3"         { context->lexAfterType = true; return(MATRIX3); }
+"mat4"         { context->lexAfterType = true; return(MATRIX4); }
+
+"vec2"         { context->lexAfterType = true; return (VEC2); }
+"vec3"         { context->lexAfterType = true; return (VEC3); }
+"vec4"         { context->lexAfterType = true; return (VEC4); }
+"ivec2"        { context->lexAfterType = true; return (IVEC2); }
+"ivec3"        { context->lexAfterType = true; return (IVEC3); }
+"ivec4"        { context->lexAfterType = true; return (IVEC4); }
+"bvec2"        { context->lexAfterType = true; return (BVEC2); }
+"bvec3"        { context->lexAfterType = true; return (BVEC3); }
+"bvec4"        { context->lexAfterType = true; return (BVEC4); }
+
+"sampler2D"       { context->lexAfterType = true; return SAMPLER2D; }
+"samplerCube"     { context->lexAfterType = true; return SAMPLERCUBE; }
+"samplerExternalOES" { context->lexAfterType = true; return SAMPLER_EXTERNAL_OES; }
+"sampler2DRect" { context->lexAfterType = true; return SAMPLER2DRECT; }
+
+"struct"       { context->lexAfterType = true; return(STRUCT); }
+
+"asm"          { return reserved_word(yyscanner); }
+
+"class"        { return reserved_word(yyscanner); }
+"union"        { return reserved_word(yyscanner); }
+"enum"         { return reserved_word(yyscanner); }
+"typedef"      { return reserved_word(yyscanner); }
+"template"     { return reserved_word(yyscanner); }
+"this"         { return reserved_word(yyscanner); }
+"packed"       { return reserved_word(yyscanner); }
+
+"goto"         { return reserved_word(yyscanner); }
+"switch"       { return reserved_word(yyscanner); }
+"default"      { return reserved_word(yyscanner); }
+
+"inline"       { return reserved_word(yyscanner); }
+"noinline"     { return reserved_word(yyscanner); }
+"volatile"     { return reserved_word(yyscanner); }
+"public"       { return reserved_word(yyscanner); }
+"static"       { return reserved_word(yyscanner); }
+"extern"       { return reserved_word(yyscanner); }
+"external"     { return reserved_word(yyscanner); }
+"interface"    { return reserved_word(yyscanner); }
+"flat"         { return reserved_word(yyscanner); }
+
+"long"         { return reserved_word(yyscanner); }
+"short"        { return reserved_word(yyscanner); }
+"double"       { return reserved_word(yyscanner); }
+"half"         { return reserved_word(yyscanner); }
+"fixed"        { return reserved_word(yyscanner); }
+"unsigned"     { return reserved_word(yyscanner); }
+"superp"       { return reserved_word(yyscanner); }
+
+"input"        { return reserved_word(yyscanner); }
+"output"       { return reserved_word(yyscanner); }
+
+"hvec2"        { return reserved_word(yyscanner); }
+"hvec3"        { return reserved_word(yyscanner); }
+"hvec4"        { return reserved_word(yyscanner); }
+"dvec2"        { return reserved_word(yyscanner); }
+"dvec3"        { return reserved_word(yyscanner); }
+"dvec4"        { return reserved_word(yyscanner); }
+"fvec2"        { return reserved_word(yyscanner); }
+"fvec3"        { return reserved_word(yyscanner); }
+"fvec4"        { return reserved_word(yyscanner); }
+
+"sampler1D"    { return reserved_word(yyscanner); }
+"sampler3D"    { return reserved_word(yyscanner); }
+
+"sampler1DShadow" { return reserved_word(yyscanner); }
+"sampler2DShadow" { return reserved_word(yyscanner); }
+
+"sampler3DRect" { return reserved_word(yyscanner); }
+"sampler2DRectShadow" { return reserved_word(yyscanner); }
+
+"sizeof"       { return reserved_word(yyscanner); }
+"cast"         { return reserved_word(yyscanner); }
+
+"namespace"    { return reserved_word(yyscanner); }
+"using"        { return reserved_word(yyscanner); }
+
+{L}({L}|{D})*       {
+   yylval->lex.string = NewPoolTString(yytext); 
+   return check_type(yyscanner);
+}
+
+0[xX]{H}+         { yylval->lex.i = strtol(yytext, 0, 0); return(INTCONSTANT); }
+0{O}+             { yylval->lex.i = strtol(yytext, 0, 0); return(INTCONSTANT); }
+0{D}+             { context->error(yylineno, "Invalid Octal number.", yytext); context->recover(); return 0;}
+{D}+              { yylval->lex.i = strtol(yytext, 0, 0); return(INTCONSTANT); }
+
+{D}+{E}           { yylval->lex.f = static_cast<float>(atof_dot(yytext)); return(FLOATCONSTANT); }
+{D}+"."{D}*({E})? { yylval->lex.f = static_cast<float>(atof_dot(yytext)); return(FLOATCONSTANT); }
+"."{D}+({E})?     { yylval->lex.f = static_cast<float>(atof_dot(yytext)); return(FLOATCONSTANT); }
+
+"+="            {  return(ADD_ASSIGN); }
+"-="            {  return(SUB_ASSIGN); }
+"*="            {  return(MUL_ASSIGN); }
+"/="            {  return(DIV_ASSIGN); }
+"%="            {  return(MOD_ASSIGN); }
+"<<="           {  return(LEFT_ASSIGN); }
+">>="           {  return(RIGHT_ASSIGN); }
+"&="            {  return(AND_ASSIGN); }
+"^="            {  return(XOR_ASSIGN); }
+"|="            {  return(OR_ASSIGN); }
+
+"++"            {  return(INC_OP); }
+"--"            {  return(DEC_OP); }
+"&&"            {  return(AND_OP); }
+"||"            {  return(OR_OP); }
+"^^"            {  return(XOR_OP); }
+"<="            {  return(LE_OP); }
+">="            {  return(GE_OP); }
+"=="            {  return(EQ_OP); }
+"!="            {  return(NE_OP); }
+"<<"            {  return(LEFT_OP); }
+">>"            {  return(RIGHT_OP); }
+";"             { context->lexAfterType = false; return(SEMICOLON); }
+("{"|"<%")      { context->lexAfterType = false; return(LEFT_BRACE); }
+("}"|"%>")      { return(RIGHT_BRACE); }
+","         { if (context->inTypeParen) context->lexAfterType = false; return(COMMA); }
+":"         { return(COLON); }
+"="         { context->lexAfterType = false; return(EQUAL); }
+"("         { context->lexAfterType = false; context->inTypeParen = true; return(LEFT_PAREN); }
+")"         { context->inTypeParen = false; return(RIGHT_PAREN); }
+("["|"<:")      { return(LEFT_BRACKET); }
+("]"|":>")      { return(RIGHT_BRACKET); }
+"."         { BEGIN(FIELDS);  return(DOT); }
+"!"         { return(BANG); }
+"-"         { return(DASH); }
+"~"         { return(TILDE); }
+"+"         { return(PLUS); }
+"*"         { return(STAR); }
+"/"         { return(SLASH); }
+"%"         { return(PERCENT); }
+"<"         { return(LEFT_ANGLE); }
+">"         { return(RIGHT_ANGLE); }
+"|"         { return(VERTICAL_BAR); }
+"^"         { return(CARET); }
+"&"         { return(AMPERSAND); }
+"?"         { return(QUESTION); }
+
+<FIELDS>{L}({L}|{D})* { 
+    BEGIN(INITIAL);
+    yylval->lex.string = NewPoolTString(yytext); 
+    return FIELD_SELECTION;
+}
+<FIELDS>[ \t\v\f\r] {}
+
+[ \t\v\n\f\r]   {  }
+<*><<EOF>>      { context->AfterEOF = true; yyterminate(); }
+<*>.            { context->warning(yylineno, "Unknown char", yytext, ""); return 0; }
+
+%%
+
+// Old preprocessor interface.
+extern "C" {
+#include "compiler/preprocessor/preprocess.h"
+
+extern int InitPreprocessor();
+extern int FinalizePreprocessor();
+extern void PredefineIntMacro(const char *name, int value);
+
+#define SETUP_CONTEXT(pp) \
+    TParseContext* context = (TParseContext*) pp->pC; \
+    struct yyguts_t* yyg = (struct yyguts_t*) context->scanner;
+
+// Preprocessor callbacks.
+void CPPDebugLogMsg(const char *msg)
+{
+    SETUP_CONTEXT(cpp);
+    context->trace(msg);
+}
+
+void CPPWarningToInfoLog(const char *msg)
+{
+    SETUP_CONTEXT(cpp);
+    context->warning(yylineno, msg, "");
+}
+
+void CPPShInfoLogMsg(const char *msg)
+{
+    SETUP_CONTEXT(cpp);
+    context->error(yylineno, msg, "");
+    context->recover();
+}
+
+void CPPErrorToInfoLog(const char *msg)
+{
+    SETUP_CONTEXT(cpp);
+    context->error(yylineno, msg, "");
+    context->recover();
+}
+
+void SetLineNumber(int line)
+{
+    SETUP_CONTEXT(cpp);
+    int string = 0;
+    DecodeSourceLoc(yylineno, &string, NULL);
+    yylineno = EncodeSourceLoc(string, line);
+}
+
+void SetStringNumber(int string)
+{
+    SETUP_CONTEXT(cpp);
+    int line = 0;
+    DecodeSourceLoc(yylineno, NULL, &line);
+    yylineno = EncodeSourceLoc(string, line);
+}
+
+int GetStringNumber()
+{
+    SETUP_CONTEXT(cpp);
+    int string = 0;
+    DecodeSourceLoc(yylineno, &string, NULL);
+    return string;
+}
+
+int GetLineNumber()
+{
+    SETUP_CONTEXT(cpp);
+    int line = 0;
+    DecodeSourceLoc(yylineno, NULL, &line);
+    return line;
+}
+
+void IncLineNumber()
+{
+    SETUP_CONTEXT(cpp);
+    int string = 0, line = 0;
+    DecodeSourceLoc(yylineno, &string, &line);
+    yylineno = EncodeSourceLoc(string, ++line);
+}
+
+void DecLineNumber()
+{
+    SETUP_CONTEXT(cpp);
+    int string = 0, line = 0;
+    DecodeSourceLoc(yylineno, &string, &line);
+    yylineno = EncodeSourceLoc(string, --line);
+}
+
+void HandlePragma(const char **tokens, int numTokens)
+{
+    SETUP_CONTEXT(cpp);
+
+    if (numTokens != 4) return;
+    if (strcmp(tokens[1], "(") != 0) return;
+    if (strcmp(tokens[3], ")") != 0) return;
+
+    context->handlePragmaDirective(yylineno, tokens[0], tokens[2]);
+}
+
+void StoreStr(const char *string)
+{
+    SETUP_CONTEXT(cpp);
+    TString strSrc;
+    strSrc = TString(string);
+
+    context->HashErrMsg = context->HashErrMsg + " " + strSrc;
+}
+
+const char* GetStrfromTStr(void)
+{
+    SETUP_CONTEXT(cpp);
+    cpp->ErrMsg = context->HashErrMsg.c_str();
+    return cpp->ErrMsg;
+}
+
+void ResetTString(void)
+{
+    SETUP_CONTEXT(cpp);
+    context->HashErrMsg = "";
+}
+
+void updateExtensionBehavior(const char* extName, const char* behavior)
+{
+    SETUP_CONTEXT(cpp);
+    context->handleExtensionDirective(yylineno, extName, behavior);
+}
+}  // extern "C"
+
+int string_input(char* buf, int max_size, yyscan_t yyscanner) {
+    int len = 0;
+
+#if ANGLE_USE_NEW_PREPROCESSOR
+    pp::Token token;
+    yyget_extra(yyscanner)->preprocessor.lex(&token);
+    len = token.type == pp::Token::LAST ? 0 : token.text.size();
+    if ((len > 0) && (len < max_size))
+        memcpy(buf, token.text.c_str(), len);
+    yyset_lineno(EncodeSourceLoc(token.location.file, token.location.line), yyscanner);
+#else
+    len = yylex_CPP(buf, max_size);
+#endif  // ANGLE_USE_NEW_PREPROCESSOR
+
+    if (len >= max_size)
+        YY_FATAL_ERROR("Input buffer overflow");
+    else if (len > 0)
+        buf[len++] = ' ';
+    return len;
+}
+
+int check_type(yyscan_t yyscanner) {
+    struct yyguts_t* yyg = (struct yyguts_t*) yyscanner;
+    
+    int token = IDENTIFIER;
+    TSymbol* symbol = yyextra->symbolTable.find(yytext);
+    if (yyextra->lexAfterType == false && symbol && symbol->isVariable()) {
+        TVariable* variable = static_cast<TVariable*>(symbol);
+        if (variable->isUserType()) {
+            yyextra->lexAfterType = true;
+            token = TYPE_NAME;
+        }
+    }
+    yylval->lex.symbol = symbol;
+    return token;
+}
+
+int reserved_word(yyscan_t yyscanner) {
+    struct yyguts_t* yyg = (struct yyguts_t*) yyscanner;
+
+    yyextra->error(yylineno, "Illegal use of reserved word", yytext, "");
+    yyextra->recover();
+    return 0;
+}
+
+void yyerror(TParseContext* context, const char* reason) {
+    struct yyguts_t* yyg = (struct yyguts_t*) context->scanner;
+
+    if (context->AfterEOF) {
+        context->error(yylineno, reason, "unexpected EOF");
+    } else {
+        context->error(yylineno, reason, yytext);
+    }
+    context->recover();
+}
+
+int glslang_initialize(TParseContext* context) {
+    yyscan_t scanner = NULL;
+    if (yylex_init_extra(context, &scanner))
+        return 1;
+
+    context->scanner = scanner;
+    return 0;
+}
+
+int glslang_finalize(TParseContext* context) {
+    yyscan_t scanner = context->scanner;
+    if (scanner == NULL) return 0;
+    
+    context->scanner = NULL;
+    yylex_destroy(scanner);
+
+#if !ANGLE_USE_NEW_PREPROCESSOR
+    FinalizePreprocessor();
+#endif
+    return 0;
+}
+
+int glslang_scan(int count, const char* const string[], const int length[],
+                 TParseContext* context) {
+    yyrestart(NULL, context->scanner);
+    yyset_lineno(EncodeSourceLoc(0, 1), context->scanner);
+    context->AfterEOF = false;
+
+    // Initialize preprocessor.
+#if ANGLE_USE_NEW_PREPROCESSOR
+    if (!context->preprocessor.init(count, string, length))
+        return 1;
+#else
+    if (InitPreprocessor())
+        return 1;
+    cpp->pC = context;
+    cpp->pastFirstStatement = 0;
+    if (InitScannerInput(cpp, count, string, length))
+        return 1;
+#endif  // ANGLE_USE_NEW_PREPROCESSOR
+
+    // Define extension macros.
+    const TExtensionBehavior& extBehavior = context->extensionBehavior();
+    for (TExtensionBehavior::const_iterator iter = extBehavior.begin();
+         iter != extBehavior.end(); ++iter) {
+#if ANGLE_USE_NEW_PREPROCESSOR
+        context->preprocessor.predefineMacro(iter->first.c_str(), 1);
+#else
+        PredefineIntMacro(iter->first.c_str(), 1);
+#endif
+    }
+    return 0;
+}
+
diff --git a/src/3rdparty/angle/src/compiler/glslang.y b/src/3rdparty/angle/src/compiler/glslang.y
new file mode 100644 (file)
index 0000000..39c9cee
--- /dev/null
@@ -0,0 +1,2142 @@
+/*
+//
+// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+This file contains the Yacc grammar for GLSL ES.
+Based on ANSI C Yacc grammar:
+http://www.lysator.liu.se/c/ANSI-C-grammar-y.html
+
+IF YOU MODIFY THIS FILE YOU ALSO NEED TO RUN generate_parser.sh,
+WHICH GENERATES THE GLSL ES PARSER (glslang_tab.cpp AND glslang_tab.h).
+*/
+
+%{
+//
+// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// This file is auto-generated by generate_parser.sh. DO NOT EDIT!
+
+// Ignore errors in auto-generated code.
+#if defined(__GNUC__)
+#pragma GCC diagnostic ignored "-Wunused-function"
+#pragma GCC diagnostic ignored "-Wunused-variable"
+#pragma GCC diagnostic ignored "-Wswitch-enum"
+#elif defined(_MSC_VER)
+#pragma warning(disable: 4065)
+#pragma warning(disable: 4189)
+#pragma warning(disable: 4505)
+#pragma warning(disable: 4701)
+#endif
+
+#include "compiler/SymbolTable.h"
+#include "compiler/ParseHelper.h"
+#include "GLSLANG/ShaderLang.h"
+
+#define YYLEX_PARAM context->scanner
+%}
+
+%expect 1 /* One shift reduce conflict because of if | else */
+%pure-parser
+%parse-param {TParseContext* context}
+
+%union {
+    struct {
+        TSourceLoc line;
+        union {
+            TString *string;
+            float f;
+            int i;
+            bool b;
+        };
+        TSymbol* symbol;
+    } lex;
+    struct {
+        TSourceLoc line;
+        TOperator op;
+        union {
+            TIntermNode* intermNode;
+            TIntermNodePair nodePair;
+            TIntermTyped* intermTypedNode;
+            TIntermAggregate* intermAggregate;
+        };
+        union {
+            TPublicType type;
+            TPrecision precision;
+            TQualifier qualifier;
+            TFunction* function;
+            TParameter param;
+            TTypeLine typeLine;
+            TTypeList* typeList;
+        };
+    } interm;
+}
+
+%{
+extern int yylex(YYSTYPE* yylval_param, void* yyscanner);
+extern void yyerror(TParseContext* context, const char* reason);
+
+#define FRAG_VERT_ONLY(S, L) {  \
+    if (context->shaderType != SH_FRAGMENT_SHADER &&  \
+        context->shaderType != SH_VERTEX_SHADER) {  \
+        context->error(L, " supported in vertex/fragment shaders only ", S);  \
+        context->recover();  \
+    }  \
+}
+
+#define VERTEX_ONLY(S, L) {  \
+    if (context->shaderType != SH_VERTEX_SHADER) {  \
+        context->error(L, " supported in vertex shaders only ", S);  \
+        context->recover();  \
+    }  \
+}
+
+#define FRAG_ONLY(S, L) {  \
+    if (context->shaderType != SH_FRAGMENT_SHADER) {  \
+        context->error(L, " supported in fragment shaders only ", S);  \
+        context->recover();  \
+    }  \
+}
+%}
+
+%token <lex> INVARIANT HIGH_PRECISION MEDIUM_PRECISION LOW_PRECISION PRECISION
+%token <lex> ATTRIBUTE CONST_QUAL BOOL_TYPE FLOAT_TYPE INT_TYPE
+%token <lex> BREAK CONTINUE DO ELSE FOR IF DISCARD RETURN
+%token <lex> BVEC2 BVEC3 BVEC4 IVEC2 IVEC3 IVEC4 VEC2 VEC3 VEC4
+%token <lex> MATRIX2 MATRIX3 MATRIX4 IN_QUAL OUT_QUAL INOUT_QUAL UNIFORM VARYING
+%token <lex> STRUCT VOID_TYPE WHILE
+%token <lex> SAMPLER2D SAMPLERCUBE SAMPLER_EXTERNAL_OES SAMPLER2DRECT
+
+%token <lex> IDENTIFIER TYPE_NAME FLOATCONSTANT INTCONSTANT BOOLCONSTANT
+%token <lex> FIELD_SELECTION
+%token <lex> LEFT_OP RIGHT_OP
+%token <lex> INC_OP DEC_OP LE_OP GE_OP EQ_OP NE_OP
+%token <lex> AND_OP OR_OP XOR_OP MUL_ASSIGN DIV_ASSIGN ADD_ASSIGN
+%token <lex> MOD_ASSIGN LEFT_ASSIGN RIGHT_ASSIGN AND_ASSIGN XOR_ASSIGN OR_ASSIGN
+%token <lex> SUB_ASSIGN
+
+%token <lex> LEFT_PAREN RIGHT_PAREN LEFT_BRACKET RIGHT_BRACKET LEFT_BRACE RIGHT_BRACE DOT
+%token <lex> COMMA COLON EQUAL SEMICOLON BANG DASH TILDE PLUS STAR SLASH PERCENT
+%token <lex> LEFT_ANGLE RIGHT_ANGLE VERTICAL_BAR CARET AMPERSAND QUESTION
+
+%type <interm> assignment_operator unary_operator
+%type <interm.intermTypedNode> variable_identifier primary_expression postfix_expression
+%type <interm.intermTypedNode> expression integer_expression assignment_expression
+%type <interm.intermTypedNode> unary_expression multiplicative_expression additive_expression
+%type <interm.intermTypedNode> relational_expression equality_expression
+%type <interm.intermTypedNode> conditional_expression constant_expression
+%type <interm.intermTypedNode> logical_or_expression logical_xor_expression logical_and_expression
+%type <interm.intermTypedNode> shift_expression and_expression exclusive_or_expression inclusive_or_expression
+%type <interm.intermTypedNode> function_call initializer condition conditionopt
+
+%type <interm.intermNode> translation_unit function_definition
+%type <interm.intermNode> statement simple_statement
+%type <interm.intermAggregate>  statement_list compound_statement
+%type <interm.intermNode> declaration_statement selection_statement expression_statement
+%type <interm.intermNode> declaration external_declaration
+%type <interm.intermNode> for_init_statement compound_statement_no_new_scope
+%type <interm.nodePair> selection_rest_statement for_rest_statement
+%type <interm.intermNode> iteration_statement jump_statement statement_no_new_scope statement_with_scope
+%type <interm> single_declaration init_declarator_list
+
+%type <interm> parameter_declaration parameter_declarator parameter_type_specifier
+%type <interm.qualifier> parameter_qualifier
+
+%type <interm.precision> precision_qualifier
+%type <interm.type> type_qualifier fully_specified_type type_specifier
+%type <interm.type> type_specifier_no_prec type_specifier_nonarray
+%type <interm.type> struct_specifier
+%type <interm.typeLine> struct_declarator
+%type <interm.typeList> struct_declarator_list struct_declaration struct_declaration_list
+%type <interm.function> function_header function_declarator function_identifier
+%type <interm.function> function_header_with_parameters function_call_header
+%type <interm> function_call_header_with_parameters function_call_header_no_parameters function_call_generic function_prototype
+%type <interm> function_call_or_method
+
+%start translation_unit
+%%
+
+variable_identifier
+    : IDENTIFIER {
+        // The symbol table search was done in the lexical phase
+        const TSymbol* symbol = $1.symbol;
+        const TVariable* variable;
+        if (symbol == 0) {
+            context->error($1.line, "undeclared identifier", $1.string->c_str());
+            context->recover();
+            TType type(EbtFloat, EbpUndefined);
+            TVariable* fakeVariable = new TVariable($1.string, type);
+            context->symbolTable.insert(*fakeVariable);
+            variable = fakeVariable;
+        } else {
+            // This identifier can only be a variable type symbol
+            if (! symbol->isVariable()) {
+                context->error($1.line, "variable expected", $1.string->c_str());
+                context->recover();
+            }
+            variable = static_cast<const TVariable*>(symbol);
+        }
+
+        // don't delete $1.string, it's used by error recovery, and the pool
+        // pop will reclaim the memory
+
+        if (variable->getType().getQualifier() == EvqConst ) {
+            ConstantUnion* constArray = variable->getConstPointer();
+            TType t(variable->getType());
+            $$ = context->intermediate.addConstantUnion(constArray, t, $1.line);
+        } else
+            $$ = context->intermediate.addSymbol(variable->getUniqueId(),
+                                                     variable->getName(),
+                                                     variable->getType(), $1.line);
+    }
+    ;
+
+primary_expression
+    : variable_identifier {
+        $$ = $1;
+    }
+    | INTCONSTANT {
+        //
+        // INT_TYPE is only 16-bit plus sign bit for vertex/fragment shaders,
+        // check for overflow for constants
+        //
+        if (abs($1.i) >= (1 << 16)) {
+            context->error($1.line, " integer constant overflow", "");
+            context->recover();
+        }
+        ConstantUnion *unionArray = new ConstantUnion[1];
+        unionArray->setIConst($1.i);
+        $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtInt, EbpUndefined, EvqConst), $1.line);
+    }
+    | FLOATCONSTANT {
+        ConstantUnion *unionArray = new ConstantUnion[1];
+        unionArray->setFConst($1.f);
+        $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtFloat, EbpUndefined, EvqConst), $1.line);
+    }
+    | BOOLCONSTANT {
+        ConstantUnion *unionArray = new ConstantUnion[1];
+        unionArray->setBConst($1.b);
+        $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), $1.line);
+    }
+    | LEFT_PAREN expression RIGHT_PAREN {
+        $$ = $2;
+    }
+    ;
+
+postfix_expression
+    : primary_expression {
+        $$ = $1;
+    }
+    | postfix_expression LEFT_BRACKET integer_expression RIGHT_BRACKET {
+        if (!$1->isArray() && !$1->isMatrix() && !$1->isVector()) {
+            if ($1->getAsSymbolNode())
+                context->error($2.line, " left of '[' is not of type array, matrix, or vector ", $1->getAsSymbolNode()->getSymbol().c_str());
+            else
+                context->error($2.line, " left of '[' is not of type array, matrix, or vector ", "expression");
+            context->recover();
+        }
+        if ($1->getType().getQualifier() == EvqConst && $3->getQualifier() == EvqConst) {
+            if ($1->isArray()) { // constant folding for arrays
+                $$ = context->addConstArrayNode($3->getAsConstantUnion()->getUnionArrayPointer()->getIConst(), $1, $2.line);
+            } else if ($1->isVector()) {  // constant folding for vectors
+                TVectorFields fields;
+                fields.num = 1;
+                fields.offsets[0] = $3->getAsConstantUnion()->getUnionArrayPointer()->getIConst(); // need to do it this way because v.xy sends fields integer array
+                $$ = context->addConstVectorNode(fields, $1, $2.line);
+            } else if ($1->isMatrix()) { // constant folding for matrices
+                $$ = context->addConstMatrixNode($3->getAsConstantUnion()->getUnionArrayPointer()->getIConst(), $1, $2.line);
+            }
+        } else {
+            if ($3->getQualifier() == EvqConst) {
+                if (($1->isVector() || $1->isMatrix()) && $1->getType().getNominalSize() <= $3->getAsConstantUnion()->getUnionArrayPointer()->getIConst() && !$1->isArray() ) {
+                    std::stringstream extraInfoStream;
+                    extraInfoStream << "field selection out of range '" << $3->getAsConstantUnion()->getUnionArrayPointer()->getIConst() << "'";
+                    std::string extraInfo = extraInfoStream.str();
+                    context->error($2.line, "", "[", extraInfo.c_str());
+                    context->recover();
+                } else {
+                    if ($1->isArray()) {
+                        if ($1->getType().getArraySize() == 0) {
+                            if ($1->getType().getMaxArraySize() <= $3->getAsConstantUnion()->getUnionArrayPointer()->getIConst()) {
+                                if (context->arraySetMaxSize($1->getAsSymbolNode(), $1->getTypePointer(), $3->getAsConstantUnion()->getUnionArrayPointer()->getIConst(), true, $2.line))
+                                    context->recover();
+                            } else {
+                                if (context->arraySetMaxSize($1->getAsSymbolNode(), $1->getTypePointer(), 0, false, $2.line))
+                                    context->recover();
+                            }
+                        } else if ( $3->getAsConstantUnion()->getUnionArrayPointer()->getIConst() >= $1->getType().getArraySize()) {
+                            std::stringstream extraInfoStream;
+                            extraInfoStream << "array index out of range '" << $3->getAsConstantUnion()->getUnionArrayPointer()->getIConst() << "'";
+                            std::string extraInfo = extraInfoStream.str();
+                            context->error($2.line, "", "[", extraInfo.c_str());
+                            context->recover();
+                        }
+                    }
+                    $$ = context->intermediate.addIndex(EOpIndexDirect, $1, $3, $2.line);
+                }
+            } else {
+                if ($1->isArray() && $1->getType().getArraySize() == 0) {
+                    context->error($2.line, "", "[", "array must be redeclared with a size before being indexed with a variable");
+                    context->recover();
+                }
+
+                $$ = context->intermediate.addIndex(EOpIndexIndirect, $1, $3, $2.line);
+            }
+        }
+        if ($$ == 0) {
+            ConstantUnion *unionArray = new ConstantUnion[1];
+            unionArray->setFConst(0.0f);
+            $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtFloat, EbpHigh, EvqConst), $2.line);
+        } else if ($1->isArray()) {
+            if ($1->getType().getStruct())
+                $$->setType(TType($1->getType().getStruct(), $1->getType().getTypeName()));
+            else
+                $$->setType(TType($1->getBasicType(), $1->getPrecision(), EvqTemporary, $1->getNominalSize(), $1->isMatrix()));
+
+            if ($1->getType().getQualifier() == EvqConst)
+                $$->getTypePointer()->setQualifier(EvqConst);
+        } else if ($1->isMatrix() && $1->getType().getQualifier() == EvqConst)
+            $$->setType(TType($1->getBasicType(), $1->getPrecision(), EvqConst, $1->getNominalSize()));
+        else if ($1->isMatrix())
+            $$->setType(TType($1->getBasicType(), $1->getPrecision(), EvqTemporary, $1->getNominalSize()));
+        else if ($1->isVector() && $1->getType().getQualifier() == EvqConst)
+            $$->setType(TType($1->getBasicType(), $1->getPrecision(), EvqConst));
+        else if ($1->isVector())
+            $$->setType(TType($1->getBasicType(), $1->getPrecision(), EvqTemporary));
+        else
+            $$->setType($1->getType());
+    }
+    | function_call {
+        $$ = $1;
+    }
+    | postfix_expression DOT FIELD_SELECTION {
+        if ($1->isArray()) {
+            context->error($3.line, "cannot apply dot operator to an array", ".");
+            context->recover();
+        }
+
+        if ($1->isVector()) {
+            TVectorFields fields;
+            if (! context->parseVectorFields(*$3.string, $1->getNominalSize(), fields, $3.line)) {
+                fields.num = 1;
+                fields.offsets[0] = 0;
+                context->recover();
+            }
+
+            if ($1->getType().getQualifier() == EvqConst) { // constant folding for vector fields
+                $$ = context->addConstVectorNode(fields, $1, $3.line);
+                if ($$ == 0) {
+                    context->recover();
+                    $$ = $1;
+                }
+                else
+                    $$->setType(TType($1->getBasicType(), $1->getPrecision(), EvqConst, (int) (*$3.string).size()));
+            } else {
+                TString vectorString = *$3.string;
+                TIntermTyped* index = context->intermediate.addSwizzle(fields, $3.line);
+                $$ = context->intermediate.addIndex(EOpVectorSwizzle, $1, index, $2.line);
+                $$->setType(TType($1->getBasicType(), $1->getPrecision(), EvqTemporary, (int) vectorString.size()));
+            }
+        } else if ($1->isMatrix()) {
+            TMatrixFields fields;
+            if (! context->parseMatrixFields(*$3.string, $1->getNominalSize(), fields, $3.line)) {
+                fields.wholeRow = false;
+                fields.wholeCol = false;
+                fields.row = 0;
+                fields.col = 0;
+                context->recover();
+            }
+
+            if (fields.wholeRow || fields.wholeCol) {
+                context->error($2.line, " non-scalar fields not implemented yet", ".");
+                context->recover();
+                ConstantUnion *unionArray = new ConstantUnion[1];
+                unionArray->setIConst(0);
+                TIntermTyped* index = context->intermediate.addConstantUnion(unionArray, TType(EbtInt, EbpUndefined, EvqConst), $3.line);
+                $$ = context->intermediate.addIndex(EOpIndexDirect, $1, index, $2.line);
+                $$->setType(TType($1->getBasicType(), $1->getPrecision(),EvqTemporary, $1->getNominalSize()));
+            } else {
+                ConstantUnion *unionArray = new ConstantUnion[1];
+                unionArray->setIConst(fields.col * $1->getNominalSize() + fields.row);
+                TIntermTyped* index = context->intermediate.addConstantUnion(unionArray, TType(EbtInt, EbpUndefined, EvqConst), $3.line);
+                $$ = context->intermediate.addIndex(EOpIndexDirect, $1, index, $2.line);
+                $$->setType(TType($1->getBasicType(), $1->getPrecision()));
+            }
+        } else if ($1->getBasicType() == EbtStruct) {
+            bool fieldFound = false;
+            const TTypeList* fields = $1->getType().getStruct();
+            if (fields == 0) {
+                context->error($2.line, "structure has no fields", "Internal Error");
+                context->recover();
+                $$ = $1;
+            } else {
+                unsigned int i;
+                for (i = 0; i < fields->size(); ++i) {
+                    if ((*fields)[i].type->getFieldName() == *$3.string) {
+                        fieldFound = true;
+                        break;
+                    }
+                }
+                if (fieldFound) {
+                    if ($1->getType().getQualifier() == EvqConst) {
+                        $$ = context->addConstStruct(*$3.string, $1, $2.line);
+                        if ($$ == 0) {
+                            context->recover();
+                            $$ = $1;
+                        }
+                        else {
+                            $$->setType(*(*fields)[i].type);
+                            // change the qualifier of the return type, not of the structure field
+                            // as the structure definition is shared between various structures.
+                            $$->getTypePointer()->setQualifier(EvqConst);
+                        }
+                    } else {
+                        ConstantUnion *unionArray = new ConstantUnion[1];
+                        unionArray->setIConst(i);
+                        TIntermTyped* index = context->intermediate.addConstantUnion(unionArray, *(*fields)[i].type, $3.line);
+                        $$ = context->intermediate.addIndex(EOpIndexDirectStruct, $1, index, $2.line);
+                        $$->setType(*(*fields)[i].type);
+                    }
+                } else {
+                    context->error($2.line, " no such field in structure", $3.string->c_str());
+                    context->recover();
+                    $$ = $1;
+                }
+            }
+        } else {
+            context->error($2.line, " field selection requires structure, vector, or matrix on left hand side", $3.string->c_str());
+            context->recover();
+            $$ = $1;
+        }
+        // don't delete $3.string, it's from the pool
+    }
+    | postfix_expression INC_OP {
+        if (context->lValueErrorCheck($2.line, "++", $1))
+            context->recover();
+        $$ = context->intermediate.addUnaryMath(EOpPostIncrement, $1, $2.line, context->symbolTable);
+        if ($$ == 0) {
+            context->unaryOpError($2.line, "++", $1->getCompleteString());
+            context->recover();
+            $$ = $1;
+        }
+    }
+    | postfix_expression DEC_OP {
+        if (context->lValueErrorCheck($2.line, "--", $1))
+            context->recover();
+        $$ = context->intermediate.addUnaryMath(EOpPostDecrement, $1, $2.line, context->symbolTable);
+        if ($$ == 0) {
+            context->unaryOpError($2.line, "--", $1->getCompleteString());
+            context->recover();
+            $$ = $1;
+        }
+    }
+    ;
+
+integer_expression
+    : expression {
+        if (context->integerErrorCheck($1, "[]"))
+            context->recover();
+        $$ = $1;
+    }
+    ;
+
+function_call
+    : function_call_or_method {
+        TFunction* fnCall = $1.function;
+        TOperator op = fnCall->getBuiltInOp();
+
+        if (op != EOpNull)
+        {
+            //
+            // Then this should be a constructor.
+            // Don't go through the symbol table for constructors.
+            // Their parameters will be verified algorithmically.
+            //
+            TType type(EbtVoid, EbpUndefined);  // use this to get the type back
+            if (context->constructorErrorCheck($1.line, $1.intermNode, *fnCall, op, &type)) {
+                $$ = 0;
+            } else {
+                //
+                // It's a constructor, of type 'type'.
+                //
+                $$ = context->addConstructor($1.intermNode, &type, op, fnCall, $1.line);
+            }
+
+            if ($$ == 0) {
+                context->recover();
+                $$ = context->intermediate.setAggregateOperator(0, op, $1.line);
+            }
+            $$->setType(type);
+        } else {
+            //
+            // Not a constructor.  Find it in the symbol table.
+            //
+            const TFunction* fnCandidate;
+            bool builtIn;
+            fnCandidate = context->findFunction($1.line, fnCall, &builtIn);
+            if (fnCandidate) {
+                //
+                // A declared function.
+                //
+                if (builtIn && !fnCandidate->getExtension().empty() &&
+                    context->extensionErrorCheck($1.line, fnCandidate->getExtension())) {
+                    context->recover();
+                }
+                op = fnCandidate->getBuiltInOp();
+                if (builtIn && op != EOpNull) {
+                    //
+                    // A function call mapped to a built-in operation.
+                    //
+                    if (fnCandidate->getParamCount() == 1) {
+                        //
+                        // Treat it like a built-in unary operator.
+                        //
+                        $$ = context->intermediate.addUnaryMath(op, $1.intermNode, 0, context->symbolTable);
+                        if ($$ == 0)  {
+                            std::stringstream extraInfoStream;
+                            extraInfoStream << "built in unary operator function.  Type: " << static_cast<TIntermTyped*>($1.intermNode)->getCompleteString();
+                            std::string extraInfo = extraInfoStream.str();
+                            context->error($1.intermNode->getLine(), " wrong operand type", "Internal Error", extraInfo.c_str());
+                            YYERROR;
+                        }
+                    } else {
+                        $$ = context->intermediate.setAggregateOperator($1.intermAggregate, op, $1.line);
+                    }
+                } else {
+                    // This is a real function call
+
+                    $$ = context->intermediate.setAggregateOperator($1.intermAggregate, EOpFunctionCall, $1.line);
+                    $$->setType(fnCandidate->getReturnType());
+
+                    // this is how we know whether the given function is a builtIn function or a user defined function
+                    // if builtIn == false, it's a userDefined -> could be an overloaded builtIn function also
+                    // if builtIn == true, it's definitely a builtIn function with EOpNull
+                    if (!builtIn)
+                        $$->getAsAggregate()->setUserDefined();
+                    $$->getAsAggregate()->setName(fnCandidate->getMangledName());
+
+                    TQualifier qual;
+                    for (int i = 0; i < fnCandidate->getParamCount(); ++i) {
+                        qual = fnCandidate->getParam(i).type->getQualifier();
+                        if (qual == EvqOut || qual == EvqInOut) {
+                            if (context->lValueErrorCheck($$->getLine(), "assign", $$->getAsAggregate()->getSequence()[i]->getAsTyped())) {
+                                context->error($1.intermNode->getLine(), "Constant value cannot be passed for 'out' or 'inout' parameters.", "Error");
+                                context->recover();
+                            }
+                        }
+                    }
+                }
+                $$->setType(fnCandidate->getReturnType());
+            } else {
+                // error message was put out by PaFindFunction()
+                // Put on a dummy node for error recovery
+                ConstantUnion *unionArray = new ConstantUnion[1];
+                unionArray->setFConst(0.0f);
+                $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtFloat, EbpUndefined, EvqConst), $1.line);
+                context->recover();
+            }
+        }
+        delete fnCall;
+    }
+    ;
+
+function_call_or_method
+    : function_call_generic {
+        $$ = $1;
+    }
+    | postfix_expression DOT function_call_generic {
+        context->error($3.line, "methods are not supported", "");
+        context->recover();
+        $$ = $3;
+    }
+    ;
+
+function_call_generic
+    : function_call_header_with_parameters RIGHT_PAREN {
+        $$ = $1;
+        $$.line = $2.line;
+    }
+    | function_call_header_no_parameters RIGHT_PAREN {
+        $$ = $1;
+        $$.line = $2.line;
+    }
+    ;
+
+function_call_header_no_parameters
+    : function_call_header VOID_TYPE {
+        $$.function = $1;
+        $$.intermNode = 0;
+    }
+    | function_call_header {
+        $$.function = $1;
+        $$.intermNode = 0;
+    }
+    ;
+
+function_call_header_with_parameters
+    : function_call_header assignment_expression {
+        TParameter param = { 0, new TType($2->getType()) };
+        $1->addParameter(param);
+        $$.function = $1;
+        $$.intermNode = $2;
+    }
+    | function_call_header_with_parameters COMMA assignment_expression {
+        TParameter param = { 0, new TType($3->getType()) };
+        $1.function->addParameter(param);
+        $$.function = $1.function;
+        $$.intermNode = context->intermediate.growAggregate($1.intermNode, $3, $2.line);
+    }
+    ;
+
+function_call_header
+    : function_identifier LEFT_PAREN {
+        $$ = $1;
+    }
+    ;
+
+// Grammar Note:  Constructors look like functions, but are recognized as types.
+
+function_identifier
+    : type_specifier_nonarray {
+        //
+        // Constructor
+        //
+        TOperator op = EOpNull;
+        if ($1.userDef) {
+            op = EOpConstructStruct;
+        } else {
+            switch ($1.type) {
+            case EbtFloat:
+                if ($1.matrix) {
+                    switch($1.size) {
+                    case 2:                                     op = EOpConstructMat2;  break;
+                    case 3:                                     op = EOpConstructMat3;  break;
+                    case 4:                                     op = EOpConstructMat4;  break;
+                    }
+                } else {
+                    switch($1.size) {
+                    case 1:                                     op = EOpConstructFloat; break;
+                    case 2:                                     op = EOpConstructVec2;  break;
+                    case 3:                                     op = EOpConstructVec3;  break;
+                    case 4:                                     op = EOpConstructVec4;  break;
+                    }
+                }
+                break;
+            case EbtInt:
+                switch($1.size) {
+                case 1:                                         op = EOpConstructInt;   break;
+                case 2:       FRAG_VERT_ONLY("ivec2", $1.line); op = EOpConstructIVec2; break;
+                case 3:       FRAG_VERT_ONLY("ivec3", $1.line); op = EOpConstructIVec3; break;
+                case 4:       FRAG_VERT_ONLY("ivec4", $1.line); op = EOpConstructIVec4; break;
+                }
+                break;
+            case EbtBool:
+                switch($1.size) {
+                case 1:                                         op = EOpConstructBool;  break;
+                case 2:       FRAG_VERT_ONLY("bvec2", $1.line); op = EOpConstructBVec2; break;
+                case 3:       FRAG_VERT_ONLY("bvec3", $1.line); op = EOpConstructBVec3; break;
+                case 4:       FRAG_VERT_ONLY("bvec4", $1.line); op = EOpConstructBVec4; break;
+                }
+                break;
+            default: break;
+            }
+            if (op == EOpNull) {
+                context->error($1.line, "cannot construct this type", getBasicString($1.type));
+                context->recover();
+                $1.type = EbtFloat;
+                op = EOpConstructFloat;
+            }
+        }
+        TString tempString;
+        TType type($1);
+        TFunction *function = new TFunction(&tempString, type, op);
+        $$ = function;
+    }
+    | IDENTIFIER {
+        if (context->reservedErrorCheck($1.line, *$1.string))
+            context->recover();
+        TType type(EbtVoid, EbpUndefined);
+        TFunction *function = new TFunction($1.string, type);
+        $$ = function;
+    }
+    | FIELD_SELECTION {
+        if (context->reservedErrorCheck($1.line, *$1.string))
+            context->recover();
+        TType type(EbtVoid, EbpUndefined);
+        TFunction *function = new TFunction($1.string, type);
+        $$ = function;
+    }
+    ;
+
+unary_expression
+    : postfix_expression {
+        $$ = $1;
+    }
+    | INC_OP unary_expression {
+        if (context->lValueErrorCheck($1.line, "++", $2))
+            context->recover();
+        $$ = context->intermediate.addUnaryMath(EOpPreIncrement, $2, $1.line, context->symbolTable);
+        if ($$ == 0) {
+            context->unaryOpError($1.line, "++", $2->getCompleteString());
+            context->recover();
+            $$ = $2;
+        }
+    }
+    | DEC_OP unary_expression {
+        if (context->lValueErrorCheck($1.line, "--", $2))
+            context->recover();
+        $$ = context->intermediate.addUnaryMath(EOpPreDecrement, $2, $1.line, context->symbolTable);
+        if ($$ == 0) {
+            context->unaryOpError($1.line, "--", $2->getCompleteString());
+            context->recover();
+            $$ = $2;
+        }
+    }
+    | unary_operator unary_expression {
+        if ($1.op != EOpNull) {
+            $$ = context->intermediate.addUnaryMath($1.op, $2, $1.line, context->symbolTable);
+            if ($$ == 0) {
+                const char* errorOp = "";
+                switch($1.op) {
+                case EOpNegative:   errorOp = "-"; break;
+                case EOpLogicalNot: errorOp = "!"; break;
+                default: break;
+                }
+                context->unaryOpError($1.line, errorOp, $2->getCompleteString());
+                context->recover();
+                $$ = $2;
+            }
+        } else
+            $$ = $2;
+    }
+    ;
+// Grammar Note:  No traditional style type casts.
+
+unary_operator
+    : PLUS  { $$.line = $1.line; $$.op = EOpNull; }
+    | DASH  { $$.line = $1.line; $$.op = EOpNegative; }
+    | BANG  { $$.line = $1.line; $$.op = EOpLogicalNot; }
+    ;
+// Grammar Note:  No '*' or '&' unary ops.  Pointers are not supported.
+
+multiplicative_expression
+    : unary_expression { $$ = $1; }
+    | multiplicative_expression STAR unary_expression {
+        FRAG_VERT_ONLY("*", $2.line);
+        $$ = context->intermediate.addBinaryMath(EOpMul, $1, $3, $2.line, context->symbolTable);
+        if ($$ == 0) {
+            context->binaryOpError($2.line, "*", $1->getCompleteString(), $3->getCompleteString());
+            context->recover();
+            $$ = $1;
+        }
+    }
+    | multiplicative_expression SLASH unary_expression {
+        FRAG_VERT_ONLY("/", $2.line);
+        $$ = context->intermediate.addBinaryMath(EOpDiv, $1, $3, $2.line, context->symbolTable);
+        if ($$ == 0) {
+            context->binaryOpError($2.line, "/", $1->getCompleteString(), $3->getCompleteString());
+            context->recover();
+            $$ = $1;
+        }
+    }
+    ;
+
+additive_expression
+    : multiplicative_expression { $$ = $1; }
+    | additive_expression PLUS multiplicative_expression {
+        $$ = context->intermediate.addBinaryMath(EOpAdd, $1, $3, $2.line, context->symbolTable);
+        if ($$ == 0) {
+            context->binaryOpError($2.line, "+", $1->getCompleteString(), $3->getCompleteString());
+            context->recover();
+            $$ = $1;
+        }
+    }
+    | additive_expression DASH multiplicative_expression {
+        $$ = context->intermediate.addBinaryMath(EOpSub, $1, $3, $2.line, context->symbolTable);
+        if ($$ == 0) {
+            context->binaryOpError($2.line, "-", $1->getCompleteString(), $3->getCompleteString());
+            context->recover();
+            $$ = $1;
+        }
+    }
+    ;
+
+shift_expression
+    : additive_expression { $$ = $1; }
+    ;
+
+relational_expression
+    : shift_expression { $$ = $1; }
+    | relational_expression LEFT_ANGLE shift_expression {
+        $$ = context->intermediate.addBinaryMath(EOpLessThan, $1, $3, $2.line, context->symbolTable);
+        if ($$ == 0) {
+            context->binaryOpError($2.line, "<", $1->getCompleteString(), $3->getCompleteString());
+            context->recover();
+            ConstantUnion *unionArray = new ConstantUnion[1];
+            unionArray->setBConst(false);
+            $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), $2.line);
+        }
+    }
+    | relational_expression RIGHT_ANGLE shift_expression  {
+        $$ = context->intermediate.addBinaryMath(EOpGreaterThan, $1, $3, $2.line, context->symbolTable);
+        if ($$ == 0) {
+            context->binaryOpError($2.line, ">", $1->getCompleteString(), $3->getCompleteString());
+            context->recover();
+            ConstantUnion *unionArray = new ConstantUnion[1];
+            unionArray->setBConst(false);
+            $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), $2.line);
+        }
+    }
+    | relational_expression LE_OP shift_expression  {
+        $$ = context->intermediate.addBinaryMath(EOpLessThanEqual, $1, $3, $2.line, context->symbolTable);
+        if ($$ == 0) {
+            context->binaryOpError($2.line, "<=", $1->getCompleteString(), $3->getCompleteString());
+            context->recover();
+            ConstantUnion *unionArray = new ConstantUnion[1];
+            unionArray->setBConst(false);
+            $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), $2.line);
+        }
+    }
+    | relational_expression GE_OP shift_expression  {
+        $$ = context->intermediate.addBinaryMath(EOpGreaterThanEqual, $1, $3, $2.line, context->symbolTable);
+        if ($$ == 0) {
+            context->binaryOpError($2.line, ">=", $1->getCompleteString(), $3->getCompleteString());
+            context->recover();
+            ConstantUnion *unionArray = new ConstantUnion[1];
+            unionArray->setBConst(false);
+            $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), $2.line);
+        }
+    }
+    ;
+
+equality_expression
+    : relational_expression { $$ = $1; }
+    | equality_expression EQ_OP relational_expression  {
+        $$ = context->intermediate.addBinaryMath(EOpEqual, $1, $3, $2.line, context->symbolTable);
+        if ($$ == 0) {
+            context->binaryOpError($2.line, "==", $1->getCompleteString(), $3->getCompleteString());
+            context->recover();
+            ConstantUnion *unionArray = new ConstantUnion[1];
+            unionArray->setBConst(false);
+            $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), $2.line);
+        }
+    }
+    | equality_expression NE_OP relational_expression {
+        $$ = context->intermediate.addBinaryMath(EOpNotEqual, $1, $3, $2.line, context->symbolTable);
+        if ($$ == 0) {
+            context->binaryOpError($2.line, "!=", $1->getCompleteString(), $3->getCompleteString());
+            context->recover();
+            ConstantUnion *unionArray = new ConstantUnion[1];
+            unionArray->setBConst(false);
+            $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), $2.line);
+        }
+    }
+    ;
+
+and_expression
+    : equality_expression { $$ = $1; }
+    ;
+
+exclusive_or_expression
+    : and_expression { $$ = $1; }
+    ;
+
+inclusive_or_expression
+    : exclusive_or_expression { $$ = $1; }
+    ;
+
+logical_and_expression
+    : inclusive_or_expression { $$ = $1; }
+    | logical_and_expression AND_OP inclusive_or_expression {
+        $$ = context->intermediate.addBinaryMath(EOpLogicalAnd, $1, $3, $2.line, context->symbolTable);
+        if ($$ == 0) {
+            context->binaryOpError($2.line, "&&", $1->getCompleteString(), $3->getCompleteString());
+            context->recover();
+            ConstantUnion *unionArray = new ConstantUnion[1];
+            unionArray->setBConst(false);
+            $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), $2.line);
+        }
+    }
+    ;
+
+logical_xor_expression
+    : logical_and_expression { $$ = $1; }
+    | logical_xor_expression XOR_OP logical_and_expression  {
+        $$ = context->intermediate.addBinaryMath(EOpLogicalXor, $1, $3, $2.line, context->symbolTable);
+        if ($$ == 0) {
+            context->binaryOpError($2.line, "^^", $1->getCompleteString(), $3->getCompleteString());
+            context->recover();
+            ConstantUnion *unionArray = new ConstantUnion[1];
+            unionArray->setBConst(false);
+            $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), $2.line);
+        }
+    }
+    ;
+
+logical_or_expression
+    : logical_xor_expression { $$ = $1; }
+    | logical_or_expression OR_OP logical_xor_expression  {
+        $$ = context->intermediate.addBinaryMath(EOpLogicalOr, $1, $3, $2.line, context->symbolTable);
+        if ($$ == 0) {
+            context->binaryOpError($2.line, "||", $1->getCompleteString(), $3->getCompleteString());
+            context->recover();
+            ConstantUnion *unionArray = new ConstantUnion[1];
+            unionArray->setBConst(false);
+            $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), $2.line);
+        }
+    }
+    ;
+
+conditional_expression
+    : logical_or_expression { $$ = $1; }
+    | logical_or_expression QUESTION expression COLON assignment_expression {
+       if (context->boolErrorCheck($2.line, $1))
+            context->recover();
+
+        $$ = context->intermediate.addSelection($1, $3, $5, $2.line);
+        if ($3->getType() != $5->getType())
+            $$ = 0;
+
+        if ($$ == 0) {
+            context->binaryOpError($2.line, ":", $3->getCompleteString(), $5->getCompleteString());
+            context->recover();
+            $$ = $5;
+        }
+    }
+    ;
+
+assignment_expression
+    : conditional_expression { $$ = $1; }
+    | unary_expression assignment_operator assignment_expression {
+        if (context->lValueErrorCheck($2.line, "assign", $1))
+            context->recover();
+        $$ = context->intermediate.addAssign($2.op, $1, $3, $2.line);
+        if ($$ == 0) {
+            context->assignError($2.line, "assign", $1->getCompleteString(), $3->getCompleteString());
+            context->recover();
+            $$ = $1;
+        }
+    }
+    ;
+
+assignment_operator
+    : EQUAL        {                                    $$.line = $1.line; $$.op = EOpAssign; }
+    | MUL_ASSIGN   { FRAG_VERT_ONLY("*=", $1.line);     $$.line = $1.line; $$.op = EOpMulAssign; }
+    | DIV_ASSIGN   { FRAG_VERT_ONLY("/=", $1.line);     $$.line = $1.line; $$.op = EOpDivAssign; }
+    | ADD_ASSIGN   {                                    $$.line = $1.line; $$.op = EOpAddAssign; }
+    | SUB_ASSIGN   {                                    $$.line = $1.line; $$.op = EOpSubAssign; }
+    ;
+
+expression
+    : assignment_expression {
+        $$ = $1;
+    }
+    | expression COMMA assignment_expression {
+        $$ = context->intermediate.addComma($1, $3, $2.line);
+        if ($$ == 0) {
+            context->binaryOpError($2.line, ",", $1->getCompleteString(), $3->getCompleteString());
+            context->recover();
+            $$ = $3;
+        }
+    }
+    ;
+
+constant_expression
+    : conditional_expression {
+        if (context->constErrorCheck($1))
+            context->recover();
+        $$ = $1;
+    }
+    ;
+
+declaration
+    : function_prototype SEMICOLON   {
+        TFunction &function = *($1.function);
+        
+        TIntermAggregate *prototype = new TIntermAggregate;
+        prototype->setType(function.getReturnType());
+        prototype->setName(function.getName());
+        
+        for (int i = 0; i < function.getParamCount(); i++)
+        {
+            const TParameter &param = function.getParam(i);
+            if (param.name != 0)
+            {
+                TVariable *variable = new TVariable(param.name, *param.type);
+                
+                prototype = context->intermediate.growAggregate(prototype, context->intermediate.addSymbol(variable->getUniqueId(), variable->getName(), variable->getType(), $1.line), $1.line);
+            }
+            else
+            {
+                prototype = context->intermediate.growAggregate(prototype, context->intermediate.addSymbol(0, "", *param.type, $1.line), $1.line);
+            }
+        }
+        
+        prototype->setOp(EOpPrototype);
+        $$ = prototype;
+
+        context->symbolTable.pop();
+    }
+    | init_declarator_list SEMICOLON {
+        if ($1.intermAggregate)
+            $1.intermAggregate->setOp(EOpDeclaration);
+        $$ = $1.intermAggregate;
+    }
+    | PRECISION precision_qualifier type_specifier_no_prec SEMICOLON {
+        context->symbolTable.setDefaultPrecision( $3.type, $2 );
+        $$ = 0;
+    }
+    ;
+
+function_prototype
+    : function_declarator RIGHT_PAREN  {
+        //
+        // Multiple declarations of the same function are allowed.
+        //
+        // If this is a definition, the definition production code will check for redefinitions
+        // (we don't know at this point if it's a definition or not).
+        //
+        // Redeclarations are allowed.  But, return types and parameter qualifiers must match.
+        //
+        TFunction* prevDec = static_cast<TFunction*>(context->symbolTable.find($1->getMangledName()));
+        if (prevDec) {
+            if (prevDec->getReturnType() != $1->getReturnType()) {
+                context->error($2.line, "overloaded functions must have the same return type", $1->getReturnType().getBasicString());
+                context->recover();
+            }
+            for (int i = 0; i < prevDec->getParamCount(); ++i) {
+                if (prevDec->getParam(i).type->getQualifier() != $1->getParam(i).type->getQualifier()) {
+                    context->error($2.line, "overloaded functions must have the same parameter qualifiers", $1->getParam(i).type->getQualifierString());
+                    context->recover();
+                }
+            }
+        }
+
+        //
+        // If this is a redeclaration, it could also be a definition,
+        // in which case, we want to use the variable names from this one, and not the one that's
+        // being redeclared.  So, pass back up this declaration, not the one in the symbol table.
+        //
+        $$.function = $1;
+        $$.line = $2.line;
+
+        // We're at the inner scope level of the function's arguments and body statement.
+        // Add the function prototype to the surrounding scope instead.
+        context->symbolTable.getOuterLevel()->insert(*$$.function);
+    }
+    ;
+
+function_declarator
+    : function_header {
+        $$ = $1;
+    }
+    | function_header_with_parameters {
+        $$ = $1;
+    }
+    ;
+
+
+function_header_with_parameters
+    : function_header parameter_declaration {
+        // Add the parameter
+        $$ = $1;
+        if ($2.param.type->getBasicType() != EbtVoid)
+            $1->addParameter($2.param);
+        else
+            delete $2.param.type;
+    }
+    | function_header_with_parameters COMMA parameter_declaration {
+        //
+        // Only first parameter of one-parameter functions can be void
+        // The check for named parameters not being void is done in parameter_declarator
+        //
+        if ($3.param.type->getBasicType() == EbtVoid) {
+            //
+            // This parameter > first is void
+            //
+            context->error($2.line, "cannot be an argument type except for '(void)'", "void");
+            context->recover();
+            delete $3.param.type;
+        } else {
+            // Add the parameter
+            $$ = $1;
+            $1->addParameter($3.param);
+        }
+    }
+    ;
+
+function_header
+    : fully_specified_type IDENTIFIER LEFT_PAREN {
+        if ($1.qualifier != EvqGlobal && $1.qualifier != EvqTemporary) {
+            context->error($2.line, "no qualifiers allowed for function return", getQualifierString($1.qualifier));
+            context->recover();
+        }
+        // make sure a sampler is not involved as well...
+        if (context->structQualifierErrorCheck($2.line, $1))
+            context->recover();
+
+        // Add the function as a prototype after parsing it (we do not support recursion)
+        TFunction *function;
+        TType type($1);
+        function = new TFunction($2.string, type);
+        $$ = function;
+        
+        context->symbolTable.push();
+    }
+    ;
+
+parameter_declarator
+    // Type + name
+    : type_specifier IDENTIFIER {
+        if ($1.type == EbtVoid) {
+            context->error($2.line, "illegal use of type 'void'", $2.string->c_str());
+            context->recover();
+        }
+        if (context->reservedErrorCheck($2.line, *$2.string))
+            context->recover();
+        TParameter param = {$2.string, new TType($1)};
+        $$.line = $2.line;
+        $$.param = param;
+    }
+    | type_specifier IDENTIFIER LEFT_BRACKET constant_expression RIGHT_BRACKET {
+        // Check that we can make an array out of this type
+        if (context->arrayTypeErrorCheck($3.line, $1))
+            context->recover();
+
+        if (context->reservedErrorCheck($2.line, *$2.string))
+            context->recover();
+
+        int size;
+        if (context->arraySizeErrorCheck($3.line, $4, size))
+            context->recover();
+        $1.setArray(true, size);
+
+        TType* type = new TType($1);
+        TParameter param = { $2.string, type };
+        $$.line = $2.line;
+        $$.param = param;
+    }
+    ;
+
+parameter_declaration
+    //
+    // The only parameter qualifier a parameter can have are
+    // IN_QUAL, OUT_QUAL, INOUT_QUAL, or CONST.
+    //
+
+    //
+    // Type + name
+    //
+    : type_qualifier parameter_qualifier parameter_declarator {
+        $$ = $3;
+        if (context->paramErrorCheck($3.line, $1.qualifier, $2, $$.param.type))
+            context->recover();
+    }
+    | parameter_qualifier parameter_declarator {
+        $$ = $2;
+        if (context->parameterSamplerErrorCheck($2.line, $1, *$2.param.type))
+            context->recover();
+        if (context->paramErrorCheck($2.line, EvqTemporary, $1, $$.param.type))
+            context->recover();
+    }
+    //
+    // Only type
+    //
+    | type_qualifier parameter_qualifier parameter_type_specifier {
+        $$ = $3;
+        if (context->paramErrorCheck($3.line, $1.qualifier, $2, $$.param.type))
+            context->recover();
+    }
+    | parameter_qualifier parameter_type_specifier {
+        $$ = $2;
+        if (context->parameterSamplerErrorCheck($2.line, $1, *$2.param.type))
+            context->recover();
+        if (context->paramErrorCheck($2.line, EvqTemporary, $1, $$.param.type))
+            context->recover();
+    }
+    ;
+
+parameter_qualifier
+    : /* empty */ {
+        $$ = EvqIn;
+    }
+    | IN_QUAL {
+        $$ = EvqIn;
+    }
+    | OUT_QUAL {
+        $$ = EvqOut;
+    }
+    | INOUT_QUAL {
+        $$ = EvqInOut;
+    }
+    ;
+
+parameter_type_specifier
+    : type_specifier {
+        TParameter param = { 0, new TType($1) };
+        $$.param = param;
+    }
+    ;
+
+init_declarator_list
+    : single_declaration {
+        $$ = $1;
+    }
+    | init_declarator_list COMMA IDENTIFIER {
+        if ($1.type.type == EbtInvariant && !$3.symbol)
+        {
+            context->error($3.line, "undeclared identifier declared as invariant", $3.string->c_str());
+            context->recover();
+        }
+
+        TIntermSymbol* symbol = context->intermediate.addSymbol(0, *$3.string, TType($1.type), $3.line);
+        $$.intermAggregate = context->intermediate.growAggregate($1.intermNode, symbol, $3.line);
+        
+        if (context->structQualifierErrorCheck($3.line, $$.type))
+            context->recover();
+
+        if (context->nonInitConstErrorCheck($3.line, *$3.string, $$.type, false))
+            context->recover();
+
+        TVariable* variable = 0;
+        if (context->nonInitErrorCheck($3.line, *$3.string, $$.type, variable))
+            context->recover();
+        if (symbol && variable)
+            symbol->setId(variable->getUniqueId());
+    }
+    | init_declarator_list COMMA IDENTIFIER LEFT_BRACKET RIGHT_BRACKET {
+        if (context->structQualifierErrorCheck($3.line, $1.type))
+            context->recover();
+
+        if (context->nonInitConstErrorCheck($3.line, *$3.string, $1.type, true))
+            context->recover();
+
+        $$ = $1;
+
+        if (context->arrayTypeErrorCheck($4.line, $1.type) || context->arrayQualifierErrorCheck($4.line, $1.type))
+            context->recover();
+        else {
+            $1.type.setArray(true);
+            TVariable* variable;
+            if (context->arrayErrorCheck($4.line, *$3.string, $1.type, variable))
+                context->recover();
+        }
+    }
+    | init_declarator_list COMMA IDENTIFIER LEFT_BRACKET constant_expression RIGHT_BRACKET {
+        if (context->structQualifierErrorCheck($3.line, $1.type))
+            context->recover();
+
+        if (context->nonInitConstErrorCheck($3.line, *$3.string, $1.type, true))
+            context->recover();
+
+        $$ = $1;
+
+        if (context->arrayTypeErrorCheck($4.line, $1.type) || context->arrayQualifierErrorCheck($4.line, $1.type))
+            context->recover();
+        else {
+            int size;
+            if (context->arraySizeErrorCheck($4.line, $5, size))
+                context->recover();
+            $1.type.setArray(true, size);
+            TVariable* variable = 0;
+            if (context->arrayErrorCheck($4.line, *$3.string, $1.type, variable))
+                context->recover();
+            TType type = TType($1.type);
+            type.setArraySize(size);
+            $$.intermAggregate = context->intermediate.growAggregate($1.intermNode, context->intermediate.addSymbol(variable ? variable->getUniqueId() : 0, *$3.string, type, $3.line), $3.line);
+        }
+    }
+    | init_declarator_list COMMA IDENTIFIER EQUAL initializer {
+        if (context->structQualifierErrorCheck($3.line, $1.type))
+            context->recover();
+
+        $$ = $1;
+
+        TIntermNode* intermNode;
+        if (!context->executeInitializer($3.line, *$3.string, $1.type, $5, intermNode)) {
+            //
+            // build the intermediate representation
+            //
+            if (intermNode)
+        $$.intermAggregate = context->intermediate.growAggregate($1.intermNode, intermNode, $4.line);
+            else
+                $$.intermAggregate = $1.intermAggregate;
+        } else {
+            context->recover();
+            $$.intermAggregate = 0;
+        }
+    }
+    ;
+
+single_declaration
+    : fully_specified_type {
+        $$.type = $1;
+        $$.intermAggregate = context->intermediate.makeAggregate(context->intermediate.addSymbol(0, "", TType($1), $1.line), $1.line);
+    }
+    | fully_specified_type IDENTIFIER {
+        TIntermSymbol* symbol = context->intermediate.addSymbol(0, *$2.string, TType($1), $2.line);
+        $$.intermAggregate = context->intermediate.makeAggregate(symbol, $2.line);
+        
+        if (context->structQualifierErrorCheck($2.line, $$.type))
+            context->recover();
+
+        if (context->nonInitConstErrorCheck($2.line, *$2.string, $$.type, false))
+            context->recover();
+            
+            $$.type = $1;
+
+        TVariable* variable = 0;
+        if (context->nonInitErrorCheck($2.line, *$2.string, $$.type, variable))
+            context->recover();
+        if (variable && symbol)
+            symbol->setId(variable->getUniqueId());
+    }
+    | fully_specified_type IDENTIFIER LEFT_BRACKET RIGHT_BRACKET {
+        context->error($2.line, "unsized array declarations not supported", $2.string->c_str());
+        context->recover();
+
+        TIntermSymbol* symbol = context->intermediate.addSymbol(0, *$2.string, TType($1), $2.line);
+        $$.intermAggregate = context->intermediate.makeAggregate(symbol, $2.line);
+        $$.type = $1;
+    }
+    | fully_specified_type IDENTIFIER LEFT_BRACKET constant_expression RIGHT_BRACKET {
+        TType type = TType($1);
+        int size;
+        if (context->arraySizeErrorCheck($2.line, $4, size))
+            context->recover();
+        type.setArraySize(size);
+        TIntermSymbol* symbol = context->intermediate.addSymbol(0, *$2.string, type, $2.line);
+        $$.intermAggregate = context->intermediate.makeAggregate(symbol, $2.line);
+        
+        if (context->structQualifierErrorCheck($2.line, $1))
+            context->recover();
+
+        if (context->nonInitConstErrorCheck($2.line, *$2.string, $1, true))
+            context->recover();
+
+        $$.type = $1;
+
+        if (context->arrayTypeErrorCheck($3.line, $1) || context->arrayQualifierErrorCheck($3.line, $1))
+            context->recover();
+        else {
+            int size;
+            if (context->arraySizeErrorCheck($3.line, $4, size))
+                context->recover();
+
+            $1.setArray(true, size);
+            TVariable* variable = 0;
+            if (context->arrayErrorCheck($3.line, *$2.string, $1, variable))
+                context->recover();
+            if (variable && symbol)
+                symbol->setId(variable->getUniqueId());
+        }
+    }
+    | fully_specified_type IDENTIFIER EQUAL initializer {
+        if (context->structQualifierErrorCheck($2.line, $1))
+            context->recover();
+
+        $$.type = $1;
+
+        TIntermNode* intermNode;
+        if (!context->executeInitializer($2.line, *$2.string, $1, $4, intermNode)) {
+        //
+        // Build intermediate representation
+        //
+            if(intermNode)
+                $$.intermAggregate = context->intermediate.makeAggregate(intermNode, $3.line);
+            else
+                $$.intermAggregate = 0;
+        } else {
+            context->recover();
+            $$.intermAggregate = 0;
+        }
+    }
+    | INVARIANT IDENTIFIER {
+        VERTEX_ONLY("invariant declaration", $1.line);
+        if (context->globalErrorCheck($1.line, context->symbolTable.atGlobalLevel(), "invariant varying"))
+            context->recover();
+        $$.type.setBasic(EbtInvariant, EvqInvariantVaryingOut, $2.line);
+        if (!$2.symbol)
+        {
+            context->error($2.line, "undeclared identifier declared as invariant", $2.string->c_str());
+            context->recover();
+            
+            $$.intermAggregate = 0;
+        }
+        else
+        {
+            TIntermSymbol *symbol = context->intermediate.addSymbol(0, *$2.string, TType($$.type), $2.line);
+            $$.intermAggregate = context->intermediate.makeAggregate(symbol, $2.line);
+        }
+    }
+
+//
+// Place holder for the pack/unpack languages.
+//
+//    | buffer_specifier {
+//        $$.intermAggregate = 0;
+//    }
+    ;
+
+// Grammar Note:  No 'enum', or 'typedef'.
+
+//
+// Place holder for the pack/unpack languages.
+//
+//%type <interm> buffer_declaration
+//%type <interm.type> buffer_specifier input_or_output buffer_declaration_list
+//buffer_specifier
+//    : input_or_output LEFT_BRACE buffer_declaration_list RIGHT_BRACE {
+//    }
+//    ;
+//
+//input_or_output
+//    : INPUT {
+//        if (context->globalErrorCheck($1.line, context->symbolTable.atGlobalLevel(), "input"))
+//            context->recover();
+//        UNPACK_ONLY("input", $1.line);
+//        $$.qualifier = EvqInput;
+//    }
+//    | OUTPUT {
+//        if (context->globalErrorCheck($1.line, context->symbolTable.atGlobalLevel(), "output"))
+//            context->recover();
+//        PACK_ONLY("output", $1.line);
+//        $$.qualifier = EvqOutput;
+//    }
+//    ;
+
+//
+// Place holder for the pack/unpack languages.
+//
+//buffer_declaration_list
+//    : buffer_declaration {
+//    }
+//    | buffer_declaration_list buffer_declaration {
+//    }
+//    ;
+
+//
+// Input/output semantics:
+//   float must be 16 or 32 bits
+//   float alignment restrictions?
+//   check for only one input and only one output
+//   sum of bitfields has to be multiple of 32
+//
+
+//
+// Place holder for the pack/unpack languages.
+//
+//buffer_declaration
+//    : type_specifier IDENTIFIER COLON constant_expression SEMICOLON {
+//        if (context->reservedErrorCheck($2.line, *$2.string, context))
+//            context->recover();
+//        $$.variable = new TVariable($2.string, $1);
+//        if (! context->symbolTable.insert(*$$.variable)) {
+//            context->error($2.line, "redefinition", $$.variable->getName().c_str());
+//            context->recover();
+//            // don't have to delete $$.variable, the pool pop will take care of it
+//        }
+//    }
+//    ;
+
+fully_specified_type
+    : type_specifier {
+        $$ = $1;
+
+        if ($1.array) {
+            context->error($1.line, "not supported", "first-class array");
+            context->recover();
+            $1.setArray(false);
+        }
+    }
+    | type_qualifier type_specifier  {
+        if ($2.array) {
+            context->error($2.line, "not supported", "first-class array");
+            context->recover();
+            $2.setArray(false);
+        }
+
+        if ($1.qualifier == EvqAttribute &&
+            ($2.type == EbtBool || $2.type == EbtInt)) {
+            context->error($2.line, "cannot be bool or int", getQualifierString($1.qualifier));
+            context->recover();
+        }
+        if (($1.qualifier == EvqVaryingIn || $1.qualifier == EvqVaryingOut) &&
+            ($2.type == EbtBool || $2.type == EbtInt)) {
+            context->error($2.line, "cannot be bool or int", getQualifierString($1.qualifier));
+            context->recover();
+        }
+        $$ = $2;
+        $$.qualifier = $1.qualifier;
+    }
+    ;
+
+type_qualifier
+    : CONST_QUAL {
+        $$.setBasic(EbtVoid, EvqConst, $1.line);
+    }
+    | ATTRIBUTE {
+        VERTEX_ONLY("attribute", $1.line);
+        if (context->globalErrorCheck($1.line, context->symbolTable.atGlobalLevel(), "attribute"))
+            context->recover();
+        $$.setBasic(EbtVoid, EvqAttribute, $1.line);
+    }
+    | VARYING {
+        if (context->globalErrorCheck($1.line, context->symbolTable.atGlobalLevel(), "varying"))
+            context->recover();
+        if (context->shaderType == SH_VERTEX_SHADER)
+            $$.setBasic(EbtVoid, EvqVaryingOut, $1.line);
+        else
+            $$.setBasic(EbtVoid, EvqVaryingIn, $1.line);
+    }
+    | INVARIANT VARYING {
+        if (context->globalErrorCheck($1.line, context->symbolTable.atGlobalLevel(), "invariant varying"))
+            context->recover();
+        if (context->shaderType == SH_VERTEX_SHADER)
+            $$.setBasic(EbtVoid, EvqInvariantVaryingOut, $1.line);
+        else
+            $$.setBasic(EbtVoid, EvqInvariantVaryingIn, $1.line);
+    }
+    | UNIFORM {
+        if (context->globalErrorCheck($1.line, context->symbolTable.atGlobalLevel(), "uniform"))
+            context->recover();
+        $$.setBasic(EbtVoid, EvqUniform, $1.line);
+    }
+    ;
+
+type_specifier
+    : type_specifier_no_prec {
+        $$ = $1;
+
+        if ($$.precision == EbpUndefined) {
+            $$.precision = context->symbolTable.getDefaultPrecision($1.type);
+            if (context->precisionErrorCheck($1.line, $$.precision, $1.type)) {
+                context->recover();
+            }
+        }
+    }
+    | precision_qualifier type_specifier_no_prec {
+        $$ = $2;
+        $$.precision = $1;
+    }
+    ;
+
+precision_qualifier
+    : HIGH_PRECISION {
+        $$ = EbpHigh;
+    }
+    | MEDIUM_PRECISION {
+        $$ = EbpMedium;
+    }
+    | LOW_PRECISION  {
+        $$ = EbpLow;
+    }
+    ;
+
+type_specifier_no_prec
+    : type_specifier_nonarray {
+        $$ = $1;
+    }
+    | type_specifier_nonarray LEFT_BRACKET constant_expression RIGHT_BRACKET {
+        $$ = $1;
+
+        if (context->arrayTypeErrorCheck($2.line, $1))
+            context->recover();
+        else {
+            int size;
+            if (context->arraySizeErrorCheck($2.line, $3, size))
+                context->recover();
+            $$.setArray(true, size);
+        }
+    }
+    ;
+
+type_specifier_nonarray
+    : VOID_TYPE {
+        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
+        $$.setBasic(EbtVoid, qual, $1.line);
+    }
+    | FLOAT_TYPE {
+        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
+        $$.setBasic(EbtFloat, qual, $1.line);
+    }
+    | INT_TYPE {
+        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
+        $$.setBasic(EbtInt, qual, $1.line);
+    }
+    | BOOL_TYPE {
+        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
+        $$.setBasic(EbtBool, qual, $1.line);
+    }
+//    | UNSIGNED INT_TYPE {
+//        PACK_UNPACK_ONLY("unsigned", $1.line);
+//        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
+//        $$.setBasic(EbtInt, qual, $1.line);
+//    }
+    | VEC2 {
+        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
+        $$.setBasic(EbtFloat, qual, $1.line);
+        $$.setAggregate(2);
+    }
+    | VEC3 {
+        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
+        $$.setBasic(EbtFloat, qual, $1.line);
+        $$.setAggregate(3);
+    }
+    | VEC4 {
+        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
+        $$.setBasic(EbtFloat, qual, $1.line);
+        $$.setAggregate(4);
+    }
+    | BVEC2 {
+        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
+        $$.setBasic(EbtBool, qual, $1.line);
+        $$.setAggregate(2);
+    }
+    | BVEC3 {
+        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
+        $$.setBasic(EbtBool, qual, $1.line);
+        $$.setAggregate(3);
+    }
+    | BVEC4 {
+        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
+        $$.setBasic(EbtBool, qual, $1.line);
+        $$.setAggregate(4);
+    }
+    | IVEC2 {
+        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
+        $$.setBasic(EbtInt, qual, $1.line);
+        $$.setAggregate(2);
+    }
+    | IVEC3 {
+        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
+        $$.setBasic(EbtInt, qual, $1.line);
+        $$.setAggregate(3);
+    }
+    | IVEC4 {
+        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
+        $$.setBasic(EbtInt, qual, $1.line);
+        $$.setAggregate(4);
+    }
+    | MATRIX2 {
+        FRAG_VERT_ONLY("mat2", $1.line);
+        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
+        $$.setBasic(EbtFloat, qual, $1.line);
+        $$.setAggregate(2, true);
+    }
+    | MATRIX3 {
+        FRAG_VERT_ONLY("mat3", $1.line);
+        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
+        $$.setBasic(EbtFloat, qual, $1.line);
+        $$.setAggregate(3, true);
+    }
+    | MATRIX4 {
+        FRAG_VERT_ONLY("mat4", $1.line);
+        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
+        $$.setBasic(EbtFloat, qual, $1.line);
+        $$.setAggregate(4, true);
+    }
+    | SAMPLER2D {
+        FRAG_VERT_ONLY("sampler2D", $1.line);
+        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
+        $$.setBasic(EbtSampler2D, qual, $1.line);
+    }
+    | SAMPLERCUBE {
+        FRAG_VERT_ONLY("samplerCube", $1.line);
+        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
+        $$.setBasic(EbtSamplerCube, qual, $1.line);
+    }
+    | SAMPLER_EXTERNAL_OES {
+        if (!context->supportsExtension("GL_OES_EGL_image_external")) {
+            context->error($1.line, "unsupported type", "samplerExternalOES");
+            context->recover();
+        }
+        FRAG_VERT_ONLY("samplerExternalOES", $1.line);
+        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
+        $$.setBasic(EbtSamplerExternalOES, qual, $1.line);
+    }
+    | SAMPLER2DRECT {
+        if (!context->supportsExtension("GL_ARB_texture_rectangle")) {
+            context->error($1.line, "unsupported type", "sampler2DRect");
+            context->recover();
+        }
+        FRAG_VERT_ONLY("sampler2DRect", $1.line);
+        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
+        $$.setBasic(EbtSampler2DRect, qual, $1.line);
+    }
+    | struct_specifier {
+        FRAG_VERT_ONLY("struct", $1.line);
+        $$ = $1;
+        $$.qualifier = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
+    }
+    | TYPE_NAME {
+        //
+        // This is for user defined type names.  The lexical phase looked up the
+        // type.
+        //
+        TType& structure = static_cast<TVariable*>($1.symbol)->getType();
+        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
+        $$.setBasic(EbtStruct, qual, $1.line);
+        $$.userDef = &structure;
+    }
+    ;
+
+struct_specifier
+    : STRUCT IDENTIFIER LEFT_BRACE { if (context->enterStructDeclaration($2.line, *$2.string)) context->recover(); } struct_declaration_list RIGHT_BRACE {
+        if (context->reservedErrorCheck($2.line, *$2.string))
+            context->recover();
+
+        TType* structure = new TType($5, *$2.string);
+        TVariable* userTypeDef = new TVariable($2.string, *structure, true);
+        if (! context->symbolTable.insert(*userTypeDef)) {
+            context->error($2.line, "redefinition", $2.string->c_str(), "struct");
+            context->recover();
+        }
+        $$.setBasic(EbtStruct, EvqTemporary, $1.line);
+        $$.userDef = structure;
+        context->exitStructDeclaration();
+    }
+    | STRUCT LEFT_BRACE { if (context->enterStructDeclaration($2.line, *$2.string)) context->recover(); } struct_declaration_list RIGHT_BRACE {
+        TType* structure = new TType($4, TString(""));
+        $$.setBasic(EbtStruct, EvqTemporary, $1.line);
+        $$.userDef = structure;
+        context->exitStructDeclaration();
+    }
+    ;
+
+struct_declaration_list
+    : struct_declaration {
+        $$ = $1;
+    }
+    | struct_declaration_list struct_declaration {
+        $$ = $1;
+        for (unsigned int i = 0; i < $2->size(); ++i) {
+            for (unsigned int j = 0; j < $$->size(); ++j) {
+                if ((*$$)[j].type->getFieldName() == (*$2)[i].type->getFieldName()) {
+                    context->error((*$2)[i].line, "duplicate field name in structure:", "struct", (*$2)[i].type->getFieldName().c_str());
+                    context->recover();
+                }
+            }
+            $$->push_back((*$2)[i]);
+        }
+    }
+    ;
+
+struct_declaration
+    : type_specifier struct_declarator_list SEMICOLON {
+        $$ = $2;
+
+        if (context->voidErrorCheck($1.line, (*$2)[0].type->getFieldName(), $1)) {
+            context->recover();
+        }
+        for (unsigned int i = 0; i < $$->size(); ++i) {
+            //
+            // Careful not to replace already known aspects of type, like array-ness
+            //
+            TType* type = (*$$)[i].type;
+            type->setBasicType($1.type);
+            type->setNominalSize($1.size);
+            type->setMatrix($1.matrix);
+            type->setPrecision($1.precision);
+
+            // don't allow arrays of arrays
+            if (type->isArray()) {
+                if (context->arrayTypeErrorCheck($1.line, $1))
+                    context->recover();
+            }
+            if ($1.array)
+                type->setArraySize($1.arraySize);
+            if ($1.userDef) {
+                type->setStruct($1.userDef->getStruct());
+                type->setTypeName($1.userDef->getTypeName());
+            }
+
+            if (context->structNestingErrorCheck($1.line, *type)) {
+                context->recover();
+            }
+        }
+    }
+    ;
+
+struct_declarator_list
+    : struct_declarator {
+        $$ = NewPoolTTypeList();
+        $$->push_back($1);
+    }
+    | struct_declarator_list COMMA struct_declarator {
+        $$->push_back($3);
+    }
+    ;
+
+struct_declarator
+    : IDENTIFIER {
+        if (context->reservedErrorCheck($1.line, *$1.string))
+            context->recover();
+
+        $$.type = new TType(EbtVoid, EbpUndefined);
+        $$.line = $1.line;
+        $$.type->setFieldName(*$1.string);
+    }
+    | IDENTIFIER LEFT_BRACKET constant_expression RIGHT_BRACKET {
+        if (context->reservedErrorCheck($1.line, *$1.string))
+            context->recover();
+
+        $$.type = new TType(EbtVoid, EbpUndefined);
+        $$.line = $1.line;
+        $$.type->setFieldName(*$1.string);
+
+        int size;
+        if (context->arraySizeErrorCheck($2.line, $3, size))
+            context->recover();
+        $$.type->setArraySize(size);
+    }
+    ;
+
+initializer
+    : assignment_expression { $$ = $1; }
+    ;
+
+declaration_statement
+    : declaration { $$ = $1; }
+    ;
+
+statement
+    : compound_statement  { $$ = $1; }
+    | simple_statement    { $$ = $1; }
+    ;
+
+// Grammar Note:  No labeled statements; 'goto' is not supported.
+
+simple_statement
+    : declaration_statement { $$ = $1; }
+    | expression_statement  { $$ = $1; }
+    | selection_statement   { $$ = $1; }
+    | iteration_statement   { $$ = $1; }
+    | jump_statement        { $$ = $1; }
+    ;
+
+compound_statement
+    : LEFT_BRACE RIGHT_BRACE { $$ = 0; }
+    | LEFT_BRACE { context->symbolTable.push(); } statement_list { context->symbolTable.pop(); } RIGHT_BRACE {
+        if ($3 != 0) {
+            $3->setOp(EOpSequence);
+            $3->setEndLine($5.line);
+        }
+        $$ = $3;
+    }
+    ;
+
+statement_no_new_scope
+    : compound_statement_no_new_scope { $$ = $1; }
+    | simple_statement                { $$ = $1; }
+    ;
+
+statement_with_scope
+    : { context->symbolTable.push(); } compound_statement_no_new_scope { context->symbolTable.pop(); $$ = $2; }
+    | { context->symbolTable.push(); } simple_statement                { context->symbolTable.pop(); $$ = $2; }
+    ;
+
+compound_statement_no_new_scope
+    // Statement that doesn't create a new scope, for selection_statement, iteration_statement
+    : LEFT_BRACE RIGHT_BRACE {
+        $$ = 0;
+    }
+    | LEFT_BRACE statement_list RIGHT_BRACE {
+        if ($2) {
+            $2->setOp(EOpSequence);
+            $2->setEndLine($3.line);
+        }
+        $$ = $2;
+    }
+    ;
+
+statement_list
+    : statement {
+        $$ = context->intermediate.makeAggregate($1, 0);
+    }
+    | statement_list statement {
+        $$ = context->intermediate.growAggregate($1, $2, 0);
+    }
+    ;
+
+expression_statement
+    : SEMICOLON  { $$ = 0; }
+    | expression SEMICOLON  { $$ = static_cast<TIntermNode*>($1); }
+    ;
+
+selection_statement
+    : IF LEFT_PAREN expression RIGHT_PAREN selection_rest_statement {
+        if (context->boolErrorCheck($1.line, $3))
+            context->recover();
+        $$ = context->intermediate.addSelection($3, $5, $1.line);
+    }
+    ;
+
+selection_rest_statement
+    : statement_with_scope ELSE statement_with_scope {
+        $$.node1 = $1;
+        $$.node2 = $3;
+    }
+    | statement_with_scope {
+        $$.node1 = $1;
+        $$.node2 = 0;
+    }
+    ;
+
+// Grammar Note:  No 'switch'.  Switch statements not supported.
+
+condition
+    // In 1996 c++ draft, conditions can include single declarations
+    : expression {
+        $$ = $1;
+        if (context->boolErrorCheck($1->getLine(), $1))
+            context->recover();
+    }
+    | fully_specified_type IDENTIFIER EQUAL initializer {
+        TIntermNode* intermNode;
+        if (context->structQualifierErrorCheck($2.line, $1))
+            context->recover();
+        if (context->boolErrorCheck($2.line, $1))
+            context->recover();
+
+        if (!context->executeInitializer($2.line, *$2.string, $1, $4, intermNode))
+            $$ = $4;
+        else {
+            context->recover();
+            $$ = 0;
+        }
+    }
+    ;
+
+iteration_statement
+    : WHILE LEFT_PAREN { context->symbolTable.push(); ++context->loopNestingLevel; } condition RIGHT_PAREN statement_no_new_scope {
+        context->symbolTable.pop();
+        $$ = context->intermediate.addLoop(ELoopWhile, 0, $4, 0, $6, $1.line);
+        --context->loopNestingLevel;
+    }
+    | DO { ++context->loopNestingLevel; } statement_with_scope WHILE LEFT_PAREN expression RIGHT_PAREN SEMICOLON {
+        if (context->boolErrorCheck($8.line, $6))
+            context->recover();
+
+        $$ = context->intermediate.addLoop(ELoopDoWhile, 0, $6, 0, $3, $4.line);
+        --context->loopNestingLevel;
+    }
+    | FOR LEFT_PAREN { context->symbolTable.push(); ++context->loopNestingLevel; } for_init_statement for_rest_statement RIGHT_PAREN statement_no_new_scope {
+        context->symbolTable.pop();
+        $$ = context->intermediate.addLoop(ELoopFor, $4, reinterpret_cast<TIntermTyped*>($5.node1), reinterpret_cast<TIntermTyped*>($5.node2), $7, $1.line);
+        --context->loopNestingLevel;
+    }
+    ;
+
+for_init_statement
+    : expression_statement {
+        $$ = $1;
+    }
+    | declaration_statement {
+        $$ = $1;
+    }
+    ;
+
+conditionopt
+    : condition {
+        $$ = $1;
+    }
+    | /* May be null */ {
+        $$ = 0;
+    }
+    ;
+
+for_rest_statement
+    : conditionopt SEMICOLON {
+        $$.node1 = $1;
+        $$.node2 = 0;
+    }
+    | conditionopt SEMICOLON expression  {
+        $$.node1 = $1;
+        $$.node2 = $3;
+    }
+    ;
+
+jump_statement
+    : CONTINUE SEMICOLON {
+        if (context->loopNestingLevel <= 0) {
+            context->error($1.line, "continue statement only allowed in loops", "");
+            context->recover();
+        }
+        $$ = context->intermediate.addBranch(EOpContinue, $1.line);
+    }
+    | BREAK SEMICOLON {
+        if (context->loopNestingLevel <= 0) {
+            context->error($1.line, "break statement only allowed in loops", "");
+            context->recover();
+        }
+        $$ = context->intermediate.addBranch(EOpBreak, $1.line);
+    }
+    | RETURN SEMICOLON {
+        $$ = context->intermediate.addBranch(EOpReturn, $1.line);
+        if (context->currentFunctionType->getBasicType() != EbtVoid) {
+            context->error($1.line, "non-void function must return a value", "return");
+            context->recover();
+        }
+    }
+    | RETURN expression SEMICOLON {
+        $$ = context->intermediate.addBranch(EOpReturn, $2, $1.line);
+        context->functionReturnsValue = true;
+        if (context->currentFunctionType->getBasicType() == EbtVoid) {
+            context->error($1.line, "void function cannot return a value", "return");
+            context->recover();
+        } else if (*(context->currentFunctionType) != $2->getType()) {
+            context->error($1.line, "function return is not matching type:", "return");
+            context->recover();
+        }
+    }
+    | DISCARD SEMICOLON {
+        FRAG_ONLY("discard", $1.line);
+        $$ = context->intermediate.addBranch(EOpKill, $1.line);
+    }
+    ;
+
+// Grammar Note:  No 'goto'.  Gotos are not supported.
+
+translation_unit
+    : external_declaration {
+        $$ = $1;
+        context->treeRoot = $$;
+    }
+    | translation_unit external_declaration {
+        $$ = context->intermediate.growAggregate($1, $2, 0);
+        context->treeRoot = $$;
+    }
+    ;
+
+external_declaration
+    : function_definition {
+        $$ = $1;
+    }
+    | declaration {
+        $$ = $1;
+    }
+    ;
+
+function_definition
+    : function_prototype {
+        TFunction* function = $1.function;
+        
+        const TSymbol *builtIn = context->symbolTable.findBuiltIn(function->getMangledName());
+        
+        if (builtIn)
+        {
+            context->error($1.line, "built-in functions cannot be redefined", function->getName().c_str());
+            context->recover();
+        }
+        
+        TFunction* prevDec = static_cast<TFunction*>(context->symbolTable.find(function->getMangledName()));
+        //
+        // Note:  'prevDec' could be 'function' if this is the first time we've seen function
+        // as it would have just been put in the symbol table.  Otherwise, we're looking up
+        // an earlier occurance.
+        //
+        if (prevDec->isDefined()) {
+            //
+            // Then this function already has a body.
+            //
+            context->error($1.line, "function already has a body", function->getName().c_str());
+            context->recover();
+        }
+        prevDec->setDefined();
+
+        //
+        // Raise error message if main function takes any parameters or return anything other than void
+        //
+        if (function->getName() == "main") {
+            if (function->getParamCount() > 0) {
+                context->error($1.line, "function cannot take any parameter(s)", function->getName().c_str());
+                context->recover();
+            }
+            if (function->getReturnType().getBasicType() != EbtVoid) {
+                context->error($1.line, "", function->getReturnType().getBasicString(), "main function cannot return a value");
+                context->recover();
+            }
+        }
+
+        //
+        // Remember the return type for later checking for RETURN statements.
+        //
+        context->currentFunctionType = &(prevDec->getReturnType());
+        context->functionReturnsValue = false;
+
+        //
+        // Insert parameters into the symbol table.
+        // If the parameter has no name, it's not an error, just don't insert it
+        // (could be used for unused args).
+        //
+        // Also, accumulate the list of parameters into the HIL, so lower level code
+        // knows where to find parameters.
+        //
+        TIntermAggregate* paramNodes = new TIntermAggregate;
+        for (int i = 0; i < function->getParamCount(); i++) {
+            const TParameter& param = function->getParam(i);
+            if (param.name != 0) {
+                TVariable *variable = new TVariable(param.name, *param.type);
+                //
+                // Insert the parameters with name in the symbol table.
+                //
+                if (! context->symbolTable.insert(*variable)) {
+                    context->error($1.line, "redefinition", variable->getName().c_str());
+                    context->recover();
+                    delete variable;
+                }
+
+                //
+                // Add the parameter to the HIL
+                //
+                paramNodes = context->intermediate.growAggregate(
+                                               paramNodes,
+                                               context->intermediate.addSymbol(variable->getUniqueId(),
+                                                                       variable->getName(),
+                                                                       variable->getType(), $1.line),
+                                               $1.line);
+            } else {
+                paramNodes = context->intermediate.growAggregate(paramNodes, context->intermediate.addSymbol(0, "", *param.type, $1.line), $1.line);
+            }
+        }
+        context->intermediate.setAggregateOperator(paramNodes, EOpParameters, $1.line);
+        $1.intermAggregate = paramNodes;
+        context->loopNestingLevel = 0;
+    }
+    compound_statement_no_new_scope {
+        //?? Check that all paths return a value if return type != void ?
+        //   May be best done as post process phase on intermediate code
+        if (context->currentFunctionType->getBasicType() != EbtVoid && ! context->functionReturnsValue) {
+            context->error($1.line, "function does not return a value:", "", $1.function->getName().c_str());
+            context->recover();
+        }
+        
+        $$ = context->intermediate.growAggregate($1.intermAggregate, $3, 0);
+        context->intermediate.setAggregateOperator($$, EOpFunction, $1.line);
+        $$->getAsAggregate()->setName($1.function->getMangledName().c_str());
+        $$->getAsAggregate()->setType($1.function->getReturnType());
+
+        // store the pragma information for debug and optimize and other vendor specific
+        // information. This information can be queried from the parse tree
+        $$->getAsAggregate()->setOptimize(context->pragma().optimize);
+        $$->getAsAggregate()->setDebug(context->pragma().debug);
+
+        if ($3 && $3->getAsAggregate())
+            $$->getAsAggregate()->setEndLine($3->getAsAggregate()->getEndLine());
+
+        context->symbolTable.pop();
+    }
+    ;
+
+%%
+
+int glslang_parse(TParseContext* context) {
+    return yyparse(context);
+}
+
diff --git a/src/3rdparty/angle/src/compiler/intermOut.cpp b/src/3rdparty/angle/src/compiler/intermOut.cpp
new file mode 100644 (file)
index 0000000..e83c7b7
--- /dev/null
@@ -0,0 +1,419 @@
+//
+// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "compiler/localintermediate.h"
+
+//
+// Two purposes:
+// 1.  Show an example of how to iterate tree.  Functions can
+//     also directly call Traverse() on children themselves to
+//     have finer grained control over the process than shown here.
+//     See the last function for how to get started.
+// 2.  Print out a text based description of the tree.
+//
+
+//
+// Use this class to carry along data from node to node in
+// the traversal
+//
+class TOutputTraverser : public TIntermTraverser {
+public:
+    TOutputTraverser(TInfoSinkBase& i) : sink(i) { }
+    TInfoSinkBase& sink;
+
+protected:
+    void visitSymbol(TIntermSymbol*);
+    void visitConstantUnion(TIntermConstantUnion*);
+    bool visitBinary(Visit visit, TIntermBinary*);
+    bool visitUnary(Visit visit, TIntermUnary*);
+    bool visitSelection(Visit visit, TIntermSelection*);
+    bool visitAggregate(Visit visit, TIntermAggregate*);
+    bool visitLoop(Visit visit, TIntermLoop*);
+    bool visitBranch(Visit visit, TIntermBranch*);
+};
+
+TString TType::getCompleteString() const
+{
+    TStringStream stream;
+
+    if (qualifier != EvqTemporary && qualifier != EvqGlobal)
+        stream << getQualifierString() << " " << getPrecisionString() << " ";
+    if (array)
+        stream << "array of ";
+    if (matrix)
+        stream << size << "X" << size << " matrix of ";
+    else if (size > 1)
+        stream << size << "-component vector of ";
+
+    stream << getBasicString();
+    return stream.str();
+}
+
+//
+// Helper functions for printing, not part of traversing.
+//
+
+void OutputTreeText(TInfoSinkBase& sink, TIntermNode* node, const int depth)
+{
+    int i;
+
+    sink.location(node->getLine());
+
+    for (i = 0; i < depth; ++i)
+        sink << "  ";
+}
+
+//
+// The rest of the file are the traversal functions.  The last one
+// is the one that starts the traversal.
+//
+// Return true from interior nodes to have the external traversal
+// continue on to children.  If you process children yourself,
+// return false.
+//
+
+void TOutputTraverser::visitSymbol(TIntermSymbol* node)
+{
+    OutputTreeText(sink, node, depth);
+
+    sink << "'" << node->getSymbol() << "' ";
+    sink << "(" << node->getCompleteString() << ")\n";
+}
+
+bool TOutputTraverser::visitBinary(Visit visit, TIntermBinary* node)
+{
+    TInfoSinkBase& out = sink;
+
+    OutputTreeText(out, node, depth);
+
+    switch (node->getOp()) {
+        case EOpAssign:                   out << "move second child to first child";           break;
+        case EOpInitialize:               out << "initialize first child with second child";   break;
+        case EOpAddAssign:                out << "add second child into first child";          break;
+        case EOpSubAssign:                out << "subtract second child into first child";     break;
+        case EOpMulAssign:                out << "multiply second child into first child";     break;
+        case EOpVectorTimesMatrixAssign:  out << "matrix mult second child into first child";  break;
+        case EOpVectorTimesScalarAssign:  out << "vector scale second child into first child"; break;
+        case EOpMatrixTimesScalarAssign:  out << "matrix scale second child into first child"; break;
+        case EOpMatrixTimesMatrixAssign:  out << "matrix mult second child into first child"; break;
+        case EOpDivAssign:                out << "divide second child into first child";       break;
+        case EOpIndexDirect:   out << "direct index";   break;
+        case EOpIndexIndirect: out << "indirect index"; break;
+        case EOpIndexDirectStruct:   out << "direct index for structure";   break;
+        case EOpVectorSwizzle: out << "vector swizzle"; break;
+
+        case EOpAdd:    out << "add";                     break;
+        case EOpSub:    out << "subtract";                break;
+        case EOpMul:    out << "component-wise multiply"; break;
+        case EOpDiv:    out << "divide";                  break;
+        case EOpEqual:            out << "Compare Equal";                 break;
+        case EOpNotEqual:         out << "Compare Not Equal";             break;
+        case EOpLessThan:         out << "Compare Less Than";             break;
+        case EOpGreaterThan:      out << "Compare Greater Than";          break;
+        case EOpLessThanEqual:    out << "Compare Less Than or Equal";    break;
+        case EOpGreaterThanEqual: out << "Compare Greater Than or Equal"; break;
+
+        case EOpVectorTimesScalar: out << "vector-scale";          break;
+        case EOpVectorTimesMatrix: out << "vector-times-matrix";   break;
+        case EOpMatrixTimesVector: out << "matrix-times-vector";   break;
+        case EOpMatrixTimesScalar: out << "matrix-scale";          break;
+        case EOpMatrixTimesMatrix: out << "matrix-multiply";       break;
+
+        case EOpLogicalOr:  out << "logical-or";   break;
+        case EOpLogicalXor: out << "logical-xor"; break;
+        case EOpLogicalAnd: out << "logical-and"; break;
+        default: out << "<unknown op>";
+    }
+
+    out << " (" << node->getCompleteString() << ")";
+
+    out << "\n";
+
+    return true;
+}
+
+bool TOutputTraverser::visitUnary(Visit visit, TIntermUnary* node)
+{
+    TInfoSinkBase& out = sink;
+
+    OutputTreeText(out, node, depth);
+
+    switch (node->getOp()) {
+        case EOpNegative:       out << "Negate value";         break;
+        case EOpVectorLogicalNot:
+        case EOpLogicalNot:     out << "Negate conditional";   break;
+
+        case EOpPostIncrement:  out << "Post-Increment";       break;
+        case EOpPostDecrement:  out << "Post-Decrement";       break;
+        case EOpPreIncrement:   out << "Pre-Increment";        break;
+        case EOpPreDecrement:   out << "Pre-Decrement";        break;
+
+        case EOpConvIntToBool:  out << "Convert int to bool";  break;
+        case EOpConvFloatToBool:out << "Convert float to bool";break;
+        case EOpConvBoolToFloat:out << "Convert bool to float";break;
+        case EOpConvIntToFloat: out << "Convert int to float"; break;
+        case EOpConvFloatToInt: out << "Convert float to int"; break;
+        case EOpConvBoolToInt:  out << "Convert bool to int";  break;
+
+        case EOpRadians:        out << "radians";              break;
+        case EOpDegrees:        out << "degrees";              break;
+        case EOpSin:            out << "sine";                 break;
+        case EOpCos:            out << "cosine";               break;
+        case EOpTan:            out << "tangent";              break;
+        case EOpAsin:           out << "arc sine";             break;
+        case EOpAcos:           out << "arc cosine";           break;
+        case EOpAtan:           out << "arc tangent";          break;
+
+        case EOpExp:            out << "exp";                  break;
+        case EOpLog:            out << "log";                  break;
+        case EOpExp2:           out << "exp2";                 break;
+        case EOpLog2:           out << "log2";                 break;
+        case EOpSqrt:           out << "sqrt";                 break;
+        case EOpInverseSqrt:    out << "inverse sqrt";         break;
+
+        case EOpAbs:            out << "Absolute value";       break;
+        case EOpSign:           out << "Sign";                 break;
+        case EOpFloor:          out << "Floor";                break;
+        case EOpCeil:           out << "Ceiling";              break;
+        case EOpFract:          out << "Fraction";             break;
+
+        case EOpLength:         out << "length";               break;
+        case EOpNormalize:      out << "normalize";            break;
+            // case EOpDPdx:           out << "dPdx";                 break;               
+            // case EOpDPdy:           out << "dPdy";                 break;   
+            // case EOpFwidth:         out << "fwidth";               break;                   
+
+        case EOpAny:            out << "any";                  break;
+        case EOpAll:            out << "all";                  break;
+
+        default: out.message(EPrefixError, "Bad unary op");
+    }
+
+    out << " (" << node->getCompleteString() << ")";
+
+    out << "\n";
+
+    return true;
+}
+
+bool TOutputTraverser::visitAggregate(Visit visit, TIntermAggregate* node)
+{
+    TInfoSinkBase& out = sink;
+
+    if (node->getOp() == EOpNull) {
+        out.message(EPrefixError, "node is still EOpNull!");
+        return true;
+    }
+
+    OutputTreeText(out, node, depth);
+
+    switch (node->getOp()) {
+        case EOpSequence:      out << "Sequence\n"; return true;
+        case EOpComma:         out << "Comma\n"; return true;
+        case EOpFunction:      out << "Function Definition: " << node->getName(); break;
+        case EOpFunctionCall:  out << "Function Call: " << node->getName(); break;
+        case EOpParameters:    out << "Function Parameters: ";              break;
+
+        case EOpConstructFloat: out << "Construct float"; break;
+        case EOpConstructVec2:  out << "Construct vec2";  break;
+        case EOpConstructVec3:  out << "Construct vec3";  break;
+        case EOpConstructVec4:  out << "Construct vec4";  break;
+        case EOpConstructBool:  out << "Construct bool";  break;
+        case EOpConstructBVec2: out << "Construct bvec2"; break;
+        case EOpConstructBVec3: out << "Construct bvec3"; break;
+        case EOpConstructBVec4: out << "Construct bvec4"; break;
+        case EOpConstructInt:   out << "Construct int";   break;
+        case EOpConstructIVec2: out << "Construct ivec2"; break;
+        case EOpConstructIVec3: out << "Construct ivec3"; break;
+        case EOpConstructIVec4: out << "Construct ivec4"; break;
+        case EOpConstructMat2:  out << "Construct mat2";  break;
+        case EOpConstructMat3:  out << "Construct mat3";  break;
+        case EOpConstructMat4:  out << "Construct mat4";  break;
+        case EOpConstructStruct:  out << "Construct structure";  break;
+
+        case EOpLessThan:         out << "Compare Less Than";             break;
+        case EOpGreaterThan:      out << "Compare Greater Than";          break;
+        case EOpLessThanEqual:    out << "Compare Less Than or Equal";    break;
+        case EOpGreaterThanEqual: out << "Compare Greater Than or Equal"; break;
+        case EOpVectorEqual:      out << "Equal";                         break;
+        case EOpVectorNotEqual:   out << "NotEqual";                      break;
+
+        case EOpMod:           out << "mod";         break;
+        case EOpPow:           out << "pow";         break;
+
+        case EOpAtan:          out << "arc tangent"; break;
+
+        case EOpMin:           out << "min";         break;
+        case EOpMax:           out << "max";         break;
+        case EOpClamp:         out << "clamp";       break;
+        case EOpMix:           out << "mix";         break;
+        case EOpStep:          out << "step";        break;
+        case EOpSmoothStep:    out << "smoothstep";  break;
+
+        case EOpDistance:      out << "distance";                break;
+        case EOpDot:           out << "dot-product";             break;
+        case EOpCross:         out << "cross-product";           break;
+        case EOpFaceForward:   out << "face-forward";            break;
+        case EOpReflect:       out << "reflect";                 break;
+        case EOpRefract:       out << "refract";                 break;
+        case EOpMul:           out << "component-wise multiply"; break;
+
+        case EOpDeclaration:   out << "Declaration: ";   break;
+
+        default: out.message(EPrefixError, "Bad aggregation op");
+    }
+
+    if (node->getOp() != EOpSequence && node->getOp() != EOpParameters)
+        out << " (" << node->getCompleteString() << ")";
+
+    out << "\n";
+
+    return true;
+}
+
+bool TOutputTraverser::visitSelection(Visit visit, TIntermSelection* node)
+{
+    TInfoSinkBase& out = sink;
+
+    OutputTreeText(out, node, depth);
+
+    out << "Test condition and select";
+    out << " (" << node->getCompleteString() << ")\n";
+
+    ++depth;
+
+    OutputTreeText(sink, node, depth);
+    out << "Condition\n";
+    node->getCondition()->traverse(this);
+
+    OutputTreeText(sink, node, depth);
+    if (node->getTrueBlock()) {
+        out << "true case\n";
+        node->getTrueBlock()->traverse(this);
+    } else
+        out << "true case is null\n";
+
+    if (node->getFalseBlock()) {
+        OutputTreeText(sink, node, depth);
+        out << "false case\n";
+        node->getFalseBlock()->traverse(this);
+    }
+
+    --depth;
+
+    return false;
+}
+
+void TOutputTraverser::visitConstantUnion(TIntermConstantUnion* node)
+{
+    TInfoSinkBase& out = sink;
+
+    int size = node->getType().getObjectSize();
+
+    for (int i = 0; i < size; i++) {
+        OutputTreeText(out, node, depth);
+        switch (node->getUnionArrayPointer()[i].getType()) {
+            case EbtBool:
+                if (node->getUnionArrayPointer()[i].getBConst())
+                    out << "true";
+                else
+                    out << "false";
+
+                out << " (" << "const bool" << ")";
+                out << "\n";
+                break;
+            case EbtFloat:
+                out << node->getUnionArrayPointer()[i].getFConst();
+                out << " (const float)\n";
+                break;
+            case EbtInt:
+                out << node->getUnionArrayPointer()[i].getIConst();
+                out << " (const int)\n";
+                break;
+            default:
+                out.message(EPrefixInternalError, "Unknown constant", node->getLine());
+                break;
+        }
+    }
+}
+
+bool TOutputTraverser::visitLoop(Visit visit, TIntermLoop* node)
+{
+    TInfoSinkBase& out = sink;
+
+    OutputTreeText(out, node, depth);
+
+    out << "Loop with condition ";
+    if (node->getType() == ELoopDoWhile)
+        out << "not ";
+    out << "tested first\n";
+
+    ++depth;
+
+    OutputTreeText(sink, node, depth);
+    if (node->getCondition()) {
+        out << "Loop Condition\n";
+        node->getCondition()->traverse(this);
+    } else
+        out << "No loop condition\n";
+
+    OutputTreeText(sink, node, depth);
+    if (node->getBody()) {
+        out << "Loop Body\n";
+        node->getBody()->traverse(this);
+    } else
+        out << "No loop body\n";
+
+    if (node->getExpression()) {
+        OutputTreeText(sink, node, depth);
+        out << "Loop Terminal Expression\n";
+        node->getExpression()->traverse(this);
+    }
+
+    --depth;
+
+    return false;
+}
+
+bool TOutputTraverser::visitBranch(Visit visit, TIntermBranch* node)
+{
+    TInfoSinkBase& out = sink;
+
+    OutputTreeText(out, node, depth);
+
+    switch (node->getFlowOp()) {
+        case EOpKill:      out << "Branch: Kill";           break;
+        case EOpBreak:     out << "Branch: Break";          break;
+        case EOpContinue:  out << "Branch: Continue";       break;
+        case EOpReturn:    out << "Branch: Return";         break;
+        default:           out << "Branch: Unknown Branch"; break;
+    }
+
+    if (node->getExpression()) {
+        out << " with expression\n";
+        ++depth;
+        node->getExpression()->traverse(this);
+        --depth;
+    } else
+        out << "\n";
+
+    return false;
+}
+
+//
+// This function is the one to call externally to start the traversal.
+// Individual functions can be initialized to 0 to skip processing of that
+// type of node.  It's children will still be processed.
+//
+void TIntermediate::outputTree(TIntermNode* root)
+{
+    if (root == 0)
+        return;
+
+    TOutputTraverser it(infoSink.info);
+
+    root->traverse(&it);
+}
diff --git a/src/3rdparty/angle/src/compiler/intermediate.h b/src/3rdparty/angle/src/compiler/intermediate.h
new file mode 100644 (file)
index 0000000..af78fa0
--- /dev/null
@@ -0,0 +1,557 @@
+//
+// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+//
+// Definition of the in-memory high-level intermediate representation
+// of shaders.  This is a tree that parser creates.
+//
+// Nodes in the tree are defined as a hierarchy of classes derived from 
+// TIntermNode. Each is a node in a tree.  There is no preset branching factor;
+// each node can have it's own type of list of children.
+//
+
+#ifndef __INTERMEDIATE_H
+#define __INTERMEDIATE_H
+
+#include "compiler/Common.h"
+#include "compiler/Types.h"
+#include "compiler/ConstantUnion.h"
+
+//
+// Operators used by the high-level (parse tree) representation.
+//
+enum TOperator {
+    EOpNull,            // if in a node, should only mean a node is still being built
+    EOpSequence,        // denotes a list of statements, or parameters, etc.
+    EOpFunctionCall,    
+    EOpFunction,        // For function definition
+    EOpParameters,      // an aggregate listing the parameters to a function
+
+    EOpDeclaration,
+    EOpPrototype,
+
+    //
+    // Unary operators
+    //
+
+    EOpNegative,
+    EOpLogicalNot,
+    EOpVectorLogicalNot,
+
+    EOpPostIncrement,
+    EOpPostDecrement,
+    EOpPreIncrement,
+    EOpPreDecrement,
+
+    EOpConvIntToBool,
+    EOpConvFloatToBool,
+    EOpConvBoolToFloat,
+    EOpConvIntToFloat,
+    EOpConvFloatToInt,
+    EOpConvBoolToInt,
+
+    //
+    // binary operations
+    //
+
+    EOpAdd,
+    EOpSub,
+    EOpMul,
+    EOpDiv,
+    EOpEqual,
+    EOpNotEqual,
+    EOpVectorEqual,
+    EOpVectorNotEqual,
+    EOpLessThan,
+    EOpGreaterThan,
+    EOpLessThanEqual,
+    EOpGreaterThanEqual,
+    EOpComma,
+
+    EOpVectorTimesScalar,
+    EOpVectorTimesMatrix,
+    EOpMatrixTimesVector,
+    EOpMatrixTimesScalar,
+
+    EOpLogicalOr,
+    EOpLogicalXor,
+    EOpLogicalAnd,
+
+    EOpIndexDirect,
+    EOpIndexIndirect,
+    EOpIndexDirectStruct,
+
+    EOpVectorSwizzle,
+
+    //
+    // Built-in functions potentially mapped to operators
+    //
+
+    EOpRadians,
+    EOpDegrees,
+    EOpSin,
+    EOpCos,
+    EOpTan,
+    EOpAsin,
+    EOpAcos,
+    EOpAtan,
+
+    EOpPow,
+    EOpExp,
+    EOpLog,
+    EOpExp2,
+    EOpLog2,
+    EOpSqrt,
+    EOpInverseSqrt,
+
+    EOpAbs,
+    EOpSign,
+    EOpFloor,
+    EOpCeil,
+    EOpFract,
+    EOpMod,
+    EOpMin,
+    EOpMax,
+    EOpClamp,
+    EOpMix,
+    EOpStep,
+    EOpSmoothStep,
+
+    EOpLength,
+    EOpDistance,
+    EOpDot,
+    EOpCross,
+    EOpNormalize,
+    EOpFaceForward,
+    EOpReflect,
+    EOpRefract,
+
+    EOpDFdx,            // Fragment only, OES_standard_derivatives extension
+    EOpDFdy,            // Fragment only, OES_standard_derivatives extension
+    EOpFwidth,          // Fragment only, OES_standard_derivatives extension
+
+    EOpMatrixTimesMatrix,
+
+    EOpAny,
+    EOpAll,
+
+    //
+    // Branch
+    //
+
+    EOpKill,            // Fragment only
+    EOpReturn,
+    EOpBreak,
+    EOpContinue,
+
+    //
+    // Constructors
+    //
+
+    EOpConstructInt,
+    EOpConstructBool,
+    EOpConstructFloat,
+    EOpConstructVec2,
+    EOpConstructVec3,
+    EOpConstructVec4,
+    EOpConstructBVec2,
+    EOpConstructBVec3,
+    EOpConstructBVec4,
+    EOpConstructIVec2,
+    EOpConstructIVec3,
+    EOpConstructIVec4,
+    EOpConstructMat2,
+    EOpConstructMat3,
+    EOpConstructMat4,
+    EOpConstructStruct,
+
+    //
+    // moves
+    //
+
+    EOpAssign,
+    EOpInitialize,
+    EOpAddAssign,
+    EOpSubAssign,
+    EOpMulAssign,
+    EOpVectorTimesMatrixAssign,
+    EOpVectorTimesScalarAssign,
+    EOpMatrixTimesScalarAssign,
+    EOpMatrixTimesMatrixAssign,
+    EOpDivAssign,
+};
+
+extern const char* getOperatorString(TOperator op);
+
+class TIntermTraverser;
+class TIntermAggregate;
+class TIntermBinary;
+class TIntermUnary;
+class TIntermConstantUnion;
+class TIntermSelection;
+class TIntermTyped;
+class TIntermSymbol;
+class TIntermLoop;
+class TInfoSink;
+
+//
+// Base class for the tree nodes
+//
+class TIntermNode {
+public:
+    POOL_ALLOCATOR_NEW_DELETE(GlobalPoolAllocator)
+
+    TIntermNode() : line(0) {}
+
+    TSourceLoc getLine() const { return line; }
+    void setLine(TSourceLoc l) { line = l; }
+
+    virtual void traverse(TIntermTraverser*) = 0;
+    virtual TIntermTyped* getAsTyped() { return 0; }
+    virtual TIntermConstantUnion* getAsConstantUnion() { return 0; }
+    virtual TIntermAggregate* getAsAggregate() { return 0; }
+    virtual TIntermBinary* getAsBinaryNode() { return 0; }
+    virtual TIntermUnary* getAsUnaryNode() { return 0; }
+    virtual TIntermSelection* getAsSelectionNode() { return 0; }
+    virtual TIntermSymbol* getAsSymbolNode() { return 0; }
+    virtual TIntermLoop* getAsLoopNode() { return 0; }
+    virtual ~TIntermNode() { }
+
+protected:
+    TSourceLoc line;
+};
+
+//
+// This is just to help yacc.
+//
+struct TIntermNodePair {
+    TIntermNode* node1;
+    TIntermNode* node2;
+};
+
+//
+// Intermediate class for nodes that have a type.
+//
+class TIntermTyped : public TIntermNode {
+public:
+    TIntermTyped(const TType& t) : type(t)  { }
+    virtual TIntermTyped* getAsTyped() { return this; }
+
+    void setType(const TType& t) { type = t; }
+    const TType& getType() const { return type; }
+    TType* getTypePointer() { return &type; }
+
+    TBasicType getBasicType() const { return type.getBasicType(); }
+    TQualifier getQualifier() const { return type.getQualifier(); }
+    TPrecision getPrecision() const { return type.getPrecision(); }
+    int getNominalSize() const { return type.getNominalSize(); }
+    
+    bool isMatrix() const { return type.isMatrix(); }
+    bool isArray()  const { return type.isArray(); }
+    bool isVector() const { return type.isVector(); }
+    bool isScalar() const { return type.isScalar(); }
+    const char* getBasicString() const { return type.getBasicString(); }
+    const char* getQualifierString() const { return type.getQualifierString(); }
+    TString getCompleteString() const { return type.getCompleteString(); }
+
+protected:
+    TType type;
+};
+
+//
+// Handle for, do-while, and while loops.
+//
+enum TLoopType {
+    ELoopFor,
+    ELoopWhile,
+    ELoopDoWhile,
+};
+
+class TIntermLoop : public TIntermNode {
+public:
+    TIntermLoop(TLoopType aType,
+                TIntermNode *aInit, TIntermTyped* aCond, TIntermTyped* aExpr,
+                TIntermNode* aBody) :
+            type(aType),
+            init(aInit),
+            cond(aCond),
+            expr(aExpr),
+            body(aBody),
+            unrollFlag(false) { }
+
+    virtual TIntermLoop* getAsLoopNode() { return this; }
+    virtual void traverse(TIntermTraverser*);
+
+    TLoopType getType() const { return type; }
+    TIntermNode* getInit() { return init; }
+    TIntermTyped* getCondition() { return cond; }
+    TIntermTyped* getExpression() { return expr; }
+    TIntermNode* getBody() { return body; }
+
+    void setUnrollFlag(bool flag) { unrollFlag = flag; }
+    bool getUnrollFlag() { return unrollFlag; }
+
+protected:
+    TLoopType type;
+    TIntermNode* init;  // for-loop initialization
+    TIntermTyped* cond; // loop exit condition
+    TIntermTyped* expr; // for-loop expression
+    TIntermNode* body;  // loop body
+
+    bool unrollFlag; // Whether the loop should be unrolled or not.
+};
+
+//
+// Handle break, continue, return, and kill.
+//
+class TIntermBranch : public TIntermNode {
+public:
+    TIntermBranch(TOperator op, TIntermTyped* e) :
+            flowOp(op),
+            expression(e) { }
+
+    virtual void traverse(TIntermTraverser*);
+
+    TOperator getFlowOp() { return flowOp; }
+    TIntermTyped* getExpression() { return expression; }
+
+protected:
+    TOperator flowOp;
+    TIntermTyped* expression;  // non-zero except for "return exp;" statements
+};
+
+//
+// Nodes that correspond to symbols or constants in the source code.
+//
+class TIntermSymbol : public TIntermTyped {
+public:
+    // if symbol is initialized as symbol(sym), the memory comes from the poolallocator of sym. If sym comes from
+    // per process globalpoolallocator, then it causes increased memory usage per compile
+    // it is essential to use "symbol = sym" to assign to symbol
+    TIntermSymbol(int i, const TString& sym, const TType& t) : 
+            TIntermTyped(t), id(i)  { symbol = sym; originalSymbol = sym; } 
+
+    int getId() const { return id; }
+    const TString& getSymbol() const { return symbol; }
+
+    void setId(int newId) { id = newId; }
+    void setSymbol(const TString& sym) { symbol = sym; }
+
+    const TString& getOriginalSymbol() const { return originalSymbol; }
+
+    virtual void traverse(TIntermTraverser*);
+    virtual TIntermSymbol* getAsSymbolNode() { return this; }
+
+protected:
+    int id;
+    TString symbol;
+    TString originalSymbol;
+};
+
+class TIntermConstantUnion : public TIntermTyped {
+public:
+    TIntermConstantUnion(ConstantUnion *unionPointer, const TType& t) : TIntermTyped(t), unionArrayPointer(unionPointer) { }
+
+    ConstantUnion* getUnionArrayPointer() const { return unionArrayPointer; }
+    void setUnionArrayPointer(ConstantUnion *c) { unionArrayPointer = c; }
+
+    virtual TIntermConstantUnion* getAsConstantUnion()  { return this; }
+    virtual void traverse(TIntermTraverser*);
+
+    TIntermTyped* fold(TOperator, TIntermTyped*, TInfoSink&);
+
+protected:
+    ConstantUnion *unionArrayPointer;
+};
+
+//
+// Intermediate class for node types that hold operators.
+//
+class TIntermOperator : public TIntermTyped {
+public:
+    TOperator getOp() const { return op; }
+    void setOp(TOperator o) { op = o; }
+
+    bool modifiesState() const;
+    bool isConstructor() const;
+
+protected:
+    TIntermOperator(TOperator o) : TIntermTyped(TType(EbtFloat, EbpUndefined)), op(o) {}
+    TIntermOperator(TOperator o, TType& t) : TIntermTyped(t), op(o) {}   
+    TOperator op;
+};
+
+//
+// Nodes for all the basic binary math operators.
+//
+class TIntermBinary : public TIntermOperator {
+public:
+    TIntermBinary(TOperator o) : TIntermOperator(o) {}
+
+    virtual TIntermBinary* getAsBinaryNode() { return this; }
+    virtual void traverse(TIntermTraverser*);
+
+    void setLeft(TIntermTyped* n) { left = n; }
+    void setRight(TIntermTyped* n) { right = n; }
+    TIntermTyped* getLeft() const { return left; }
+    TIntermTyped* getRight() const { return right; }
+    bool promote(TInfoSink&);
+
+protected:
+    TIntermTyped* left;
+    TIntermTyped* right;
+};
+
+//
+// Nodes for unary math operators.
+//
+class TIntermUnary : public TIntermOperator {
+public:
+    TIntermUnary(TOperator o, TType& t) : TIntermOperator(o, t), operand(0), useEmulatedFunction(false) {}
+    TIntermUnary(TOperator o) : TIntermOperator(o), operand(0), useEmulatedFunction(false) {}
+
+    virtual void traverse(TIntermTraverser*);
+    virtual TIntermUnary* getAsUnaryNode() { return this; }
+
+    void setOperand(TIntermTyped* o) { operand = o; }
+    TIntermTyped* getOperand() { return operand; }    
+    bool promote(TInfoSink&);
+
+    void setUseEmulatedFunction() { useEmulatedFunction = true; }
+    bool getUseEmulatedFunction() { return useEmulatedFunction; }
+
+protected:
+    TIntermTyped* operand;
+
+    // If set to true, replace the built-in function call with an emulated one
+    // to work around driver bugs.
+    bool useEmulatedFunction;
+};
+
+typedef TVector<TIntermNode*> TIntermSequence;
+typedef TVector<int> TQualifierList;
+
+//
+// Nodes that operate on an arbitrary sized set of children.
+//
+class TIntermAggregate : public TIntermOperator {
+public:
+    TIntermAggregate() : TIntermOperator(EOpNull), userDefined(false), endLine(0), useEmulatedFunction(false) { }
+    TIntermAggregate(TOperator o) : TIntermOperator(o), useEmulatedFunction(false) { }
+    ~TIntermAggregate() { }
+
+    virtual TIntermAggregate* getAsAggregate() { return this; }
+    virtual void traverse(TIntermTraverser*);
+
+    TIntermSequence& getSequence() { return sequence; }
+
+    void setName(const TString& n) { name = n; }
+    const TString& getName() const { return name; }
+
+    void setUserDefined() { userDefined = true; }
+    bool isUserDefined() const { return userDefined; }
+
+    void setOptimize(bool o) { optimize = o; }
+    bool getOptimize() { return optimize; }
+    void setDebug(bool d) { debug = d; }
+    bool getDebug() { return debug; }
+
+    void setEndLine(TSourceLoc line) { endLine = line; }
+    TSourceLoc getEndLine() const { return endLine; }
+
+    void setUseEmulatedFunction() { useEmulatedFunction = true; }
+    bool getUseEmulatedFunction() { return useEmulatedFunction; }
+
+protected:
+    TIntermAggregate(const TIntermAggregate&); // disallow copy constructor
+    TIntermAggregate& operator=(const TIntermAggregate&); // disallow assignment operator
+    TIntermSequence sequence;
+    TString name;
+    bool userDefined; // used for user defined function names
+
+    bool optimize;
+    bool debug;
+    TSourceLoc endLine;
+
+    // If set to true, replace the built-in function call with an emulated one
+    // to work around driver bugs.
+    bool useEmulatedFunction;
+};
+
+//
+// For if tests.  Simplified since there is no switch statement.
+//
+class TIntermSelection : public TIntermTyped {
+public:
+    TIntermSelection(TIntermTyped* cond, TIntermNode* trueB, TIntermNode* falseB) :
+            TIntermTyped(TType(EbtVoid, EbpUndefined)), condition(cond), trueBlock(trueB), falseBlock(falseB) {}
+    TIntermSelection(TIntermTyped* cond, TIntermNode* trueB, TIntermNode* falseB, const TType& type) :
+            TIntermTyped(type), condition(cond), trueBlock(trueB), falseBlock(falseB) {}
+
+    virtual void traverse(TIntermTraverser*);
+
+    bool usesTernaryOperator() const { return getBasicType() != EbtVoid; }
+    TIntermNode* getCondition() const { return condition; }
+    TIntermNode* getTrueBlock() const { return trueBlock; }
+    TIntermNode* getFalseBlock() const { return falseBlock; }
+    TIntermSelection* getAsSelectionNode() { return this; }
+
+protected:
+    TIntermTyped* condition;
+    TIntermNode* trueBlock;
+    TIntermNode* falseBlock;
+};
+
+enum Visit
+{
+    PreVisit,
+    InVisit,
+    PostVisit
+};
+
+//
+// For traversing the tree.  User should derive from this, 
+// put their traversal specific data in it, and then pass
+// it to a Traverse method.
+//
+// When using this, just fill in the methods for nodes you want visited.
+// Return false from a pre-visit to skip visiting that node's subtree.
+//
+class TIntermTraverser
+{
+public:
+    POOL_ALLOCATOR_NEW_DELETE(GlobalPoolAllocator)
+
+    TIntermTraverser(bool preVisit = true, bool inVisit = false, bool postVisit = false, bool rightToLeft = false) : 
+            preVisit(preVisit),
+            inVisit(inVisit),
+            postVisit(postVisit),
+            rightToLeft(rightToLeft),
+            depth(0) {}
+    virtual ~TIntermTraverser() {};
+
+    virtual void visitSymbol(TIntermSymbol*) {}
+    virtual void visitConstantUnion(TIntermConstantUnion*) {}
+    virtual bool visitBinary(Visit visit, TIntermBinary*) {return true;}
+    virtual bool visitUnary(Visit visit, TIntermUnary*) {return true;}
+    virtual bool visitSelection(Visit visit, TIntermSelection*) {return true;}
+    virtual bool visitAggregate(Visit visit, TIntermAggregate*) {return true;}
+    virtual bool visitLoop(Visit visit, TIntermLoop*) {return true;}
+    virtual bool visitBranch(Visit visit, TIntermBranch*) {return true;}
+
+    void incrementDepth() {depth++;}
+    void decrementDepth() {depth--;}
+
+    const bool preVisit;
+    const bool inVisit;
+    const bool postVisit;
+    const bool rightToLeft;
+
+protected:
+    int depth;
+};
+
+#endif // __INTERMEDIATE_H
diff --git a/src/3rdparty/angle/src/compiler/localintermediate.h b/src/3rdparty/angle/src/compiler/localintermediate.h
new file mode 100644 (file)
index 0000000..56890bd
--- /dev/null
@@ -0,0 +1,58 @@
+//
+// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#ifndef _LOCAL_INTERMEDIATE_INCLUDED_
+#define _LOCAL_INTERMEDIATE_INCLUDED_
+
+#include "GLSLANG/ShaderLang.h"
+#include "compiler/intermediate.h"
+#include "compiler/SymbolTable.h"
+
+struct TVectorFields {
+    int offsets[4];
+    int num;
+};
+
+//
+// Set of helper functions to help parse and build the tree.
+//
+class TInfoSink;
+class TIntermediate {
+public:    
+    POOL_ALLOCATOR_NEW_DELETE(GlobalPoolAllocator)
+
+    TIntermediate(TInfoSink& i) : infoSink(i) { }
+    TIntermSymbol* addSymbol(int Id, const TString&, const TType&, TSourceLoc);
+    TIntermTyped* addConversion(TOperator, const TType&, TIntermTyped*);
+    TIntermTyped* addBinaryMath(TOperator op, TIntermTyped* left, TIntermTyped* right, TSourceLoc, TSymbolTable&);
+    TIntermTyped* addAssign(TOperator op, TIntermTyped* left, TIntermTyped* right, TSourceLoc);
+    TIntermTyped* addIndex(TOperator op, TIntermTyped* base, TIntermTyped* index, TSourceLoc);
+    TIntermTyped* addUnaryMath(TOperator op, TIntermNode* child, TSourceLoc, TSymbolTable&);
+    TIntermAggregate* growAggregate(TIntermNode* left, TIntermNode* right, TSourceLoc);
+    TIntermAggregate* makeAggregate(TIntermNode* node, TSourceLoc);
+    TIntermAggregate* setAggregateOperator(TIntermNode*, TOperator, TSourceLoc);
+    TIntermNode*  addSelection(TIntermTyped* cond, TIntermNodePair code, TSourceLoc);
+    TIntermTyped* addSelection(TIntermTyped* cond, TIntermTyped* trueBlock, TIntermTyped* falseBlock, TSourceLoc);
+    TIntermTyped* addComma(TIntermTyped* left, TIntermTyped* right, TSourceLoc);
+    TIntermConstantUnion* addConstantUnion(ConstantUnion*, const TType&, TSourceLoc);
+    TIntermTyped* promoteConstantUnion(TBasicType, TIntermConstantUnion*) ;
+    bool parseConstTree(TSourceLoc, TIntermNode*, ConstantUnion*, TOperator, TSymbolTable&, TType, bool singleConstantParam = false);        
+    TIntermNode* addLoop(TLoopType, TIntermNode*, TIntermTyped*, TIntermTyped*, TIntermNode*, TSourceLoc);
+    TIntermBranch* addBranch(TOperator, TSourceLoc);
+    TIntermBranch* addBranch(TOperator, TIntermTyped*, TSourceLoc);
+    TIntermTyped* addSwizzle(TVectorFields&, TSourceLoc);
+    bool postProcess(TIntermNode*);
+       void remove(TIntermNode*);
+    void outputTree(TIntermNode*);
+    
+protected:
+    TInfoSink& infoSink;
+
+private:
+    void operator=(TIntermediate&); // prevent assignments
+};
+
+#endif // _LOCAL_INTERMEDIATE_INCLUDED_
diff --git a/src/3rdparty/angle/src/compiler/osinclude.h b/src/3rdparty/angle/src/compiler/osinclude.h
new file mode 100644 (file)
index 0000000..1d95907
--- /dev/null
@@ -0,0 +1,72 @@
+//
+// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#ifndef __OSINCLUDE_H
+#define __OSINCLUDE_H
+
+//
+// This file contains contains os-specific datatypes and
+// declares any os-specific functions.
+//
+
+#if defined(_WIN32) || defined(_WIN64)
+#define ANGLE_OS_WIN
+#elif defined(__APPLE__) || defined(__linux__) || \
+      defined(__FreeBSD__) || defined(__OpenBSD__) || \
+      defined(__sun) || defined(ANDROID) || \
+      defined(__GLIBC__) || defined(__GNU__) || \
+      defined(__QNX__)
+#define ANGLE_OS_POSIX
+#else
+#error Unsupported platform.
+#endif
+
+#if defined(ANGLE_USE_NSPR)
+#include "prthread.h"
+#elif defined(ANGLE_OS_WIN)
+#define STRICT
+#define VC_EXTRALEAN 1
+#include <windows.h>
+#elif defined(ANGLE_OS_POSIX)
+#include <pthread.h>
+#include <semaphore.h>
+#include <errno.h>
+#endif  // ANGLE_USE_NSPR
+
+
+#include "compiler/debug.h"
+
+//
+// Thread Local Storage Operations
+//
+#if defined(ANGLE_USE_NSPR)
+typedef PRUintn OS_TLSIndex;
+#define OS_INVALID_TLS_INDEX 0xFFFFFFFF
+#elif defined(ANGLE_OS_WIN)
+typedef DWORD OS_TLSIndex;
+#define OS_INVALID_TLS_INDEX (TLS_OUT_OF_INDEXES)
+#elif defined(ANGLE_OS_POSIX)
+typedef unsigned int OS_TLSIndex;
+#define OS_INVALID_TLS_INDEX 0xFFFFFFFF
+#endif  // ANGLE_USE_NSPR
+
+OS_TLSIndex OS_AllocTLSIndex();
+bool OS_SetTLSValue(OS_TLSIndex nIndex, void *lpvValue);
+bool OS_FreeTLSIndex(OS_TLSIndex nIndex);
+
+inline void* OS_GetTLSValue(OS_TLSIndex nIndex)
+{
+    ASSERT(nIndex != OS_INVALID_TLS_INDEX);
+#if defined(ANGLE_USE_NSPR)
+    return PR_GetThreadPrivate(nIndex);
+#elif defined(ANGLE_OS_WIN)
+    return TlsGetValue(nIndex);
+#elif defined(ANGLE_OS_POSIX)
+    return pthread_getspecific(nIndex);
+#endif  // ANGLE_OS_WIN
+}
+
+#endif // __OSINCLUDE_H
diff --git a/src/3rdparty/angle/src/compiler/ossource_nspr.cpp b/src/3rdparty/angle/src/compiler/ossource_nspr.cpp
new file mode 100644 (file)
index 0000000..f63d81e
--- /dev/null
@@ -0,0 +1,43 @@
+//
+// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+//
+// This file contains the nspr specific functions
+//
+#include "compiler/osinclude.h"
+
+//
+// Thread Local Storage Operations
+//
+OS_TLSIndex OS_AllocTLSIndex()
+{
+    PRUintn index;
+    PRStatus status = PR_NewThreadPrivateIndex(&index, NULL);
+
+    if (status) {
+        assert(0 && "OS_AllocTLSIndex(): Unable to allocate Thread Local Storage");
+        return OS_INVALID_TLS_INDEX;
+    }
+
+    return index;
+}
+
+bool OS_SetTLSValue(OS_TLSIndex nIndex, void *lpvValue)
+{
+    if (nIndex == OS_INVALID_TLS_INDEX) {
+        assert(0 && "OS_SetTLSValue(): Invalid TLS Index");
+        return false;
+    }
+
+    return PR_SetThreadPrivate(nIndex, lpvValue) == 0;
+}
+
+bool OS_FreeTLSIndex(OS_TLSIndex nIndex)
+{
+    // Can't delete TLS keys with nspr
+    return true;
+}
+
diff --git a/src/3rdparty/angle/src/compiler/ossource_posix.cpp b/src/3rdparty/angle/src/compiler/ossource_posix.cpp
new file mode 100644 (file)
index 0000000..1e1e699
--- /dev/null
@@ -0,0 +1,64 @@
+//
+// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+//
+// This file contains the posix specific functions
+//
+#include "compiler/osinclude.h"
+
+#if !defined(ANGLE_OS_POSIX)
+#error Trying to build a posix specific file in a non-posix build.
+#endif
+
+//
+// Thread Local Storage Operations
+//
+OS_TLSIndex OS_AllocTLSIndex()
+{
+    pthread_key_t pPoolIndex;
+
+    //
+    // Create global pool key.
+    //
+    if ((pthread_key_create(&pPoolIndex, NULL)) != 0) {
+        assert(0 && "OS_AllocTLSIndex(): Unable to allocate Thread Local Storage");
+        return false;
+    }
+    else {
+        return pPoolIndex;
+    }
+}
+
+
+bool OS_SetTLSValue(OS_TLSIndex nIndex, void *lpvValue)
+{
+    if (nIndex == OS_INVALID_TLS_INDEX) {
+        assert(0 && "OS_SetTLSValue(): Invalid TLS Index");
+        return false;
+    }
+
+    if (pthread_setspecific(nIndex, lpvValue) == 0)
+        return true;
+    else
+        return false;
+}
+
+
+bool OS_FreeTLSIndex(OS_TLSIndex nIndex)
+{
+    if (nIndex == OS_INVALID_TLS_INDEX) {
+        assert(0 && "OS_SetTLSValue(): Invalid TLS Index");
+        return false;
+    }
+
+    //
+    // Delete the global pool key.
+    //
+    if (pthread_key_delete(nIndex) == 0)
+        return true;
+    else
+        return false;
+}
diff --git a/src/3rdparty/angle/src/compiler/ossource_win.cpp b/src/3rdparty/angle/src/compiler/ossource_win.cpp
new file mode 100644 (file)
index 0000000..89922fe
--- /dev/null
@@ -0,0 +1,57 @@
+//
+// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "compiler/osinclude.h"
+//
+// This file contains contains the window's specific functions
+//
+
+#if !defined(ANGLE_OS_WIN)
+#error Trying to build a windows specific file in a non windows build.
+#endif
+
+
+//
+// Thread Local Storage Operations
+//
+OS_TLSIndex OS_AllocTLSIndex()
+{
+       DWORD dwIndex = TlsAlloc();
+       if (dwIndex == TLS_OUT_OF_INDEXES) {
+               assert(0 && "OS_AllocTLSIndex(): Unable to allocate Thread Local Storage");
+               return OS_INVALID_TLS_INDEX;
+       }
+
+       return dwIndex;
+}
+
+
+bool OS_SetTLSValue(OS_TLSIndex nIndex, void *lpvValue)
+{
+       if (nIndex == OS_INVALID_TLS_INDEX) {
+               assert(0 && "OS_SetTLSValue(): Invalid TLS Index");
+               return false;
+       }
+
+       if (TlsSetValue(nIndex, lpvValue))
+               return true;
+       else
+               return false;
+}
+
+
+bool OS_FreeTLSIndex(OS_TLSIndex nIndex)
+{
+       if (nIndex == OS_INVALID_TLS_INDEX) {
+               assert(0 && "OS_SetTLSValue(): Invalid TLS Index");
+               return false;
+       }
+
+       if (TlsFree(nIndex))
+               return true;
+       else
+               return false;
+}
diff --git a/src/3rdparty/angle/src/compiler/parseConst.cpp b/src/3rdparty/angle/src/compiler/parseConst.cpp
new file mode 100644 (file)
index 0000000..9a8a50c
--- /dev/null
@@ -0,0 +1,238 @@
+//
+// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "compiler/ParseHelper.h"
+
+//
+// Use this class to carry along data from node to node in 
+// the traversal
+//
+class TConstTraverser : public TIntermTraverser {
+public:
+    TConstTraverser(ConstantUnion* cUnion, bool singleConstParam, TOperator constructType, TInfoSink& sink, TSymbolTable& symTable, TType& t)
+        : error(false),
+          index(0),
+          unionArray(cUnion),
+          type(t),
+          constructorType(constructType),
+          singleConstantParam(singleConstParam),
+          infoSink(sink),
+          symbolTable(symTable),
+          size(0),
+          isMatrix(false),
+          matrixSize(0) {
+    }
+
+    bool error;
+
+protected:
+    void visitSymbol(TIntermSymbol*);
+    void visitConstantUnion(TIntermConstantUnion*);
+    bool visitBinary(Visit visit, TIntermBinary*);
+    bool visitUnary(Visit visit, TIntermUnary*);
+    bool visitSelection(Visit visit, TIntermSelection*);
+    bool visitAggregate(Visit visit, TIntermAggregate*);
+    bool visitLoop(Visit visit, TIntermLoop*);
+    bool visitBranch(Visit visit, TIntermBranch*);
+
+    int index;
+    ConstantUnion *unionArray;
+    TType type;
+    TOperator constructorType;
+    bool singleConstantParam;
+    TInfoSink& infoSink;
+    TSymbolTable& symbolTable;
+    int size; // size of the constructor ( 4 for vec4)
+    bool isMatrix;
+    int matrixSize; // dimension of the matrix (nominal size and not the instance size)
+};
+
+//
+// The rest of the file are the traversal functions.  The last one
+// is the one that starts the traversal.
+//
+// Return true from interior nodes to have the external traversal
+// continue on to children.  If you process children yourself,
+// return false.
+//
+
+void TConstTraverser::visitSymbol(TIntermSymbol* node)
+{
+    infoSink.info.message(EPrefixInternalError, "Symbol Node found in constant constructor", node->getLine());
+    return;
+
+}
+
+bool TConstTraverser::visitBinary(Visit visit, TIntermBinary* node)
+{
+    TQualifier qualifier = node->getType().getQualifier();
+    
+    if (qualifier != EvqConst) {
+        TString buf;
+        buf.append("'constructor' : assigning non-constant to ");
+        buf.append(type.getCompleteString());
+        infoSink.info.message(EPrefixError, buf.c_str(), node->getLine());
+        error = true;
+        return false;  
+    }
+
+   infoSink.info.message(EPrefixInternalError, "Binary Node found in constant constructor", node->getLine());
+    
+    return false;
+}
+
+bool TConstTraverser::visitUnary(Visit visit, TIntermUnary* node)
+{
+    TString buf;
+    buf.append("'constructor' : assigning non-constant to ");
+    buf.append(type.getCompleteString());
+    infoSink.info.message(EPrefixError, buf.c_str(), node->getLine());
+    error = true;
+    return false;  
+}
+
+bool TConstTraverser::visitAggregate(Visit visit, TIntermAggregate* node)
+{
+    if (!node->isConstructor() && node->getOp() != EOpComma) {
+        TString buf;
+        buf.append("'constructor' : assigning non-constant to ");
+        buf.append(type.getCompleteString());
+        infoSink.info.message(EPrefixError, buf.c_str(), node->getLine());
+        error = true;
+        return false;  
+    }
+
+    if (node->getSequence().size() == 0) {
+        error = true;
+        return false;
+    }
+
+    bool flag = node->getSequence().size() == 1 && node->getSequence()[0]->getAsTyped()->getAsConstantUnion();
+    if (flag) 
+    {
+        singleConstantParam = true; 
+        constructorType = node->getOp();
+        size = node->getType().getObjectSize();
+
+        if (node->getType().isMatrix()) {
+            isMatrix = true;
+            matrixSize = node->getType().getNominalSize();
+        }
+    }       
+
+    for (TIntermSequence::iterator p = node->getSequence().begin(); 
+                                   p != node->getSequence().end(); p++) {
+
+        if (node->getOp() == EOpComma)
+            index = 0;           
+
+        (*p)->traverse(this);
+    }   
+    if (flag) 
+    {
+        singleConstantParam = false;   
+        constructorType = EOpNull;
+        size = 0;
+        isMatrix = false;
+        matrixSize = 0;
+    }
+    return false;
+}
+
+bool TConstTraverser::visitSelection(Visit visit, TIntermSelection* node)
+{
+    infoSink.info.message(EPrefixInternalError, "Selection Node found in constant constructor", node->getLine());
+    error = true;
+    return false;
+}
+
+void TConstTraverser::visitConstantUnion(TIntermConstantUnion* node)
+{
+    ConstantUnion* leftUnionArray = unionArray;
+    int instanceSize = type.getObjectSize();
+
+    if (index >= instanceSize)
+        return;
+
+    if (!singleConstantParam) {
+        int size = node->getType().getObjectSize();
+    
+        ConstantUnion *rightUnionArray = node->getUnionArrayPointer();
+        for (int i=0; i < size; i++) {
+            if (index >= instanceSize)
+                return;
+            leftUnionArray[index] = rightUnionArray[i];
+
+            (index)++;
+        }
+    } else {
+        int totalSize = index + size;
+        ConstantUnion *rightUnionArray = node->getUnionArrayPointer();
+        if (!isMatrix) {
+            int count = 0;
+            for (int i = index; i < totalSize; i++) {
+                if (i >= instanceSize)
+                    return;
+
+                leftUnionArray[i] = rightUnionArray[count];
+
+                (index)++;
+                
+                if (node->getType().getObjectSize() > 1)
+                    count++;
+            }
+        } else {  // for matrix constructors
+            int count = 0;
+            int element = index;
+            for (int i = index; i < totalSize; i++) {
+                if (i >= instanceSize)
+                    return;
+                if (element - i == 0 || (i - element) % (matrixSize + 1) == 0 )
+                    leftUnionArray[i] = rightUnionArray[count];
+                else 
+                    leftUnionArray[i].setFConst(0.0f);
+
+                (index)++;
+
+                if (node->getType().getObjectSize() > 1)
+                    count++;                
+            }
+        }
+    }
+}
+
+bool TConstTraverser::visitLoop(Visit visit, TIntermLoop* node)
+{
+    infoSink.info.message(EPrefixInternalError, "Loop Node found in constant constructor", node->getLine());
+    error = true;
+    return false;
+}
+
+bool TConstTraverser::visitBranch(Visit visit, TIntermBranch* node)
+{
+    infoSink.info.message(EPrefixInternalError, "Branch Node found in constant constructor", node->getLine());
+    error = true;
+    return false;
+}
+
+//
+// This function is the one to call externally to start the traversal.
+// Individual functions can be initialized to 0 to skip processing of that
+// type of node.  It's children will still be processed.
+//
+bool TIntermediate::parseConstTree(TSourceLoc line, TIntermNode* root, ConstantUnion* unionArray, TOperator constructorType, TSymbolTable& symbolTable, TType t, bool singleConstantParam)
+{
+    if (root == 0)
+        return false;
+
+    TConstTraverser it(unionArray, singleConstantParam, constructorType, infoSink, symbolTable, t);
+
+    root->traverse(&it);
+    if (it.error)
+        return true;
+    else
+        return false;
+}
diff --git a/src/3rdparty/angle/src/compiler/preprocessor/atom.c b/src/3rdparty/angle/src/compiler/preprocessor/atom.c
new file mode 100644 (file)
index 0000000..39158d2
--- /dev/null
@@ -0,0 +1,737 @@
+/****************************************************************************\
+Copyright (c) 2002, NVIDIA Corporation.
+
+NVIDIA Corporation("NVIDIA") supplies this software to you in
+consideration of your agreement to the following terms, and your use,
+installation, modification or redistribution of this NVIDIA software
+constitutes acceptance of these terms.  If you do not agree with these
+terms, please do not use, install, modify or redistribute this NVIDIA
+software.
+
+In consideration of your agreement to abide by the following terms, and
+subject to these terms, NVIDIA grants you a personal, non-exclusive
+license, under NVIDIA's copyrights in this original NVIDIA software (the
+"NVIDIA Software"), to use, reproduce, modify and redistribute the
+NVIDIA Software, with or without modifications, in source and/or binary
+forms; provided that if you redistribute the NVIDIA Software, you must
+retain the copyright notice of NVIDIA, this notice and the following
+text and disclaimers in all such redistributions of the NVIDIA Software.
+Neither the name, trademarks, service marks nor logos of NVIDIA
+Corporation may be used to endorse or promote products derived from the
+NVIDIA Software without specific prior written permission from NVIDIA.
+Except as expressly stated in this notice, no other rights or licenses
+express or implied, are granted by NVIDIA herein, including but not
+limited to any patent rights that may be infringed by your derivative
+works or by other works in which the NVIDIA Software may be
+incorporated. No hardware is licensed hereunder. 
+
+THE NVIDIA SOFTWARE IS BEING PROVIDED ON AN "AS IS" BASIS, WITHOUT
+WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED,
+INCLUDING WITHOUT LIMITATION, WARRANTIES OR CONDITIONS OF TITLE,
+NON-INFRINGEMENT, MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR
+ITS USE AND OPERATION EITHER ALONE OR IN COMBINATION WITH OTHER
+PRODUCTS.
+
+IN NO EVENT SHALL NVIDIA BE LIABLE FOR ANY SPECIAL, INDIRECT,
+INCIDENTAL, EXEMPLARY, CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+TO, LOST PROFITS; PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) OR ARISING IN ANY WAY
+OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE
+NVIDIA SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT,
+TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF
+NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+\****************************************************************************/
+
+//
+// atom.c
+//
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "common/angleutils.h"
+#include "compiler/debug.h"
+#include "compiler/preprocessor/slglobals.h"
+
+#undef malloc
+#undef realloc
+#undef free
+
+///////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////// String table: //////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////////////////////
+
+static const struct {
+    int val;
+    const char *str;
+} tokens[] = {
+    { CPP_AND_OP,         "&&" },
+    { CPP_AND_ASSIGN,     "&=" },
+    { CPP_SUB_ASSIGN,     "-=" },
+    { CPP_MOD_ASSIGN,     "%=" },
+    { CPP_ADD_ASSIGN,     "+=" },
+    { CPP_DIV_ASSIGN,     "/=" },
+    { CPP_MUL_ASSIGN,     "*=" },
+    { CPP_RIGHT_BRACKET,  ":>" },
+    { CPP_EQ_OP,          "==" },
+    { CPP_XOR_OP,         "^^" }, 
+    { CPP_XOR_ASSIGN,     "^=" }, 
+    { CPP_FLOATCONSTANT,  "<float-const>" },
+    { CPP_GE_OP,          ">=" },
+    { CPP_RIGHT_OP,       ">>" },
+    { CPP_RIGHT_ASSIGN,   ">>=" }, 
+    { CPP_IDENTIFIER,     "<ident>" },
+    { CPP_INTCONSTANT,    "<int-const>" },
+    { CPP_LE_OP,          "<=" },
+    { CPP_LEFT_OP,        "<<" },
+    { CPP_LEFT_ASSIGN,    "<<=" },
+    { CPP_LEFT_BRACKET,   "<:" },
+    { CPP_LEFT_BRACE,     "<%" }, 
+    { CPP_DEC_OP,         "--" },
+    { CPP_RIGHT_BRACE,    "%>" }, 
+    { CPP_NE_OP,          "!=" },
+    { CPP_OR_OP,          "||" },
+    { CPP_OR_ASSIGN,      "|=" }, 
+    { CPP_INC_OP,         "++" },
+    { CPP_STRCONSTANT,    "<string-const>" },
+    { CPP_TYPEIDENTIFIER, "<type-ident>" },
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////// String table: //////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////////////////////
+
+#define INIT_STRING_TABLE_SIZE 16384
+
+typedef struct StringTable_Rec {
+    char *strings;
+    int nextFree;
+    int size;
+} StringTable;
+
+/*
+ * InitStringTable() - Initialize the string table.
+ *
+ */
+
+static int InitStringTable(StringTable *stable)
+{
+    stable->strings = (char *) malloc(INIT_STRING_TABLE_SIZE);
+    if (!stable->strings)
+        return 0;
+    // Zero-th offset means "empty" so don't use it.
+    stable->nextFree = 1;
+    stable->size = INIT_STRING_TABLE_SIZE;
+    return 1;
+} // InitStringTable
+
+/*
+ * FreeStringTable() - Free the string table.
+ *
+ */
+
+static void FreeStringTable(StringTable *stable)
+{
+    if (stable->strings)
+        free(stable->strings);
+    stable->strings = NULL;
+    stable->nextFree = 0;
+    stable->size = 0;
+} // FreeStringTable
+
+/*
+ * HashString() - Hash a string with the base hash function.
+ *
+ */
+
+static int HashString(const char *s)
+{
+    int hval = 0;
+
+    while (*s) {
+        hval = (hval*13507 + *s*197) ^ (hval >> 2);
+        s++;
+    }
+    return hval & 0x7fffffff;
+} // HashString
+
+/*
+ * HashString2() - Hash a string with the incrimenting hash function.
+ *
+ */
+
+static int HashString2(const char *s)
+{
+    int hval = 0;
+
+    while (*s) {
+        hval = (hval*729 + *s*37) ^ (hval >> 1);
+        s++;
+    }
+    return hval;
+} // HashString2
+
+/*
+ * AddString() - Add a string to a string table.  Return it's offset.
+ *
+ */
+
+static int AddString(StringTable *stable, const char *s)
+{
+    int len, loc;
+    char *str;
+
+    len = (int) strlen(s);
+    while (stable->nextFree + len + 1 >= stable->size) {
+        assert(stable->size < 1000000);
+        str = (char *) malloc(stable->size*2);
+        memcpy(str, stable->strings, stable->size);
+        free(stable->strings);
+        stable->strings = str;
+        stable->size = stable->size*2;
+    }
+    loc = stable->nextFree;
+    strcpy(&stable->strings[loc], s);
+    stable->nextFree += len + 1;
+    return loc;
+} // AddString
+
+///////////////////////////////////////////////////////////////////////////////////////////////
+/////////////////////////////////////////// Hash table: ///////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////////////////////
+
+#define INIT_HASH_TABLE_SIZE 2047
+#define HASH_TABLE_MAX_COLLISIONS 3
+
+typedef struct HashEntry_Rec {
+    int index;      // String table offset of string representation
+    int value;      // Atom (symbol) value
+} HashEntry;
+
+typedef struct HashTable_Rec {
+    HashEntry *entry;
+    int size;
+    int entries;
+    int counts[HASH_TABLE_MAX_COLLISIONS + 1];
+} HashTable;
+
+/*
+ * InitHashTable() - Initialize the hash table.
+ *
+ */
+
+static int InitHashTable(HashTable *htable, int fsize)
+{
+    int ii;
+
+    htable->entry = (HashEntry *) malloc(sizeof(HashEntry)*fsize);
+    if (!htable->entry)
+        return 0;
+    htable->size = fsize;
+    for (ii = 0; ii < fsize; ii++) {
+        htable->entry[ii].index = 0;
+        htable->entry[ii].value = 0;
+    }
+    htable->entries = 0;
+    for (ii = 0; ii <= HASH_TABLE_MAX_COLLISIONS; ii++)
+        htable->counts[ii] = 0;
+    return 1;
+} // InitHashTable
+
+/*
+ * FreeHashTable() - Free the hash table.
+ *
+ */
+
+static void FreeHashTable(HashTable *htable)
+{
+    if (htable->entry)
+        free(htable->entry);
+    htable->entry = NULL;
+    htable->size = 0;
+    htable->entries = 0;
+} // FreeHashTable
+
+/*
+ * Empty() - See if a hash table entry is empty.
+ *
+ */
+
+static int Empty(HashTable *htable, int hashloc)
+{
+    assert(hashloc >= 0 && hashloc < htable->size);
+    if (htable->entry[hashloc].index == 0) {
+        return 1;
+    } else {
+        return 0;
+    }
+} // Empty
+
+/*
+ * Match() - See if a hash table entry is matches a string.
+ *
+ */
+
+static int Match(HashTable *htable, StringTable *stable, const char *s, int hashloc)
+{
+    int strloc;
+
+    strloc = htable->entry[hashloc].index;
+    if (!strcmp(s, &stable->strings[strloc])) {
+        return 1;
+    } else {
+        return 0;
+    }
+} // Match
+
+///////////////////////////////////////////////////////////////////////////////////////////////
+/////////////////////////////////////////// Atom table: ///////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////////////////////
+
+#define INIT_ATOM_TABLE_SIZE 1024
+
+
+struct AtomTable_Rec {
+    StringTable stable; // String table.
+    HashTable htable;   // Hashes string to atom number and token value.  Multiple strings can
+                        // have the same token value but each unique string is a unique atom.
+    int *amap;          // Maps atom value to offset in string table.  Atoms all map to unique
+                        // strings except for some undefined values in the lower, fixed part
+                        // of the atom table that map to "<undefined>".  The lowest 256 atoms
+                        // correspond to single character ASCII values except for alphanumeric
+                        // characters and '_', which can be other tokens.  Next come the
+                        // language tokens with their atom values equal to the token value.
+                        // Then come predefined atoms, followed by user specified identifiers.
+    int *arev;          // Reversed atom for symbol table use.
+    int nextFree;
+    int size;
+};
+
+static AtomTable latable = { { NULL, 0, 0 }, { NULL, 0, 0, {0} }, NULL, NULL, 0, 0 };
+AtomTable *atable = &latable;
+
+static int AddAtomFixed(AtomTable *atable, const char *s, int atom);
+
+/*
+ * GrowAtomTable() - Grow the atom table to at least "size" if it's smaller.
+ *
+ */
+
+static int GrowAtomTable(AtomTable *atable, int size)
+{
+    int *newmap, *newrev;
+
+    if (atable->size < size) {
+        if (atable->amap) {
+            newmap = realloc(atable->amap, sizeof(int)*size);
+            newrev = realloc(atable->arev, sizeof(int)*size);
+        } else {
+            newmap = malloc(sizeof(int)*size);
+            newrev = malloc(sizeof(int)*size);
+            atable->size = 0;
+        }
+        if (!newmap || !newrev) {
+            /* failed to grow -- error */
+            if (newmap)
+                atable->amap = newmap;
+            if (newrev)
+                atable->arev = newrev;
+            return -1;
+        }
+        memset(&newmap[atable->size], 0, (size - atable->size) * sizeof(int));
+        memset(&newrev[atable->size], 0, (size - atable->size) * sizeof(int));
+        atable->amap = newmap;
+        atable->arev = newrev;
+        atable->size = size;
+    }
+    return 0;
+} // GrowAtomTable
+
+/*
+ * lReverse() - Reverse the bottom 20 bits of a 32 bit int.
+ *
+ */
+
+static int lReverse(int fval)
+{
+    unsigned int in = fval;
+    int result = 0, cnt = 0;
+
+    while(in) {
+        result <<= 1;
+        result |= in&1;
+        in >>= 1;
+        cnt++;
+    }
+
+    // Don't use all 31 bits.  One million atoms is plenty and sometimes the
+    // upper bits are used for other things.
+
+    if (cnt < 20)
+        result <<= 20 - cnt;
+    return result;
+} // lReverse
+
+/*
+ * AllocateAtom() - Allocate a new atom.  Associated with the "undefined" value of -1.
+ *
+ */
+
+static int AllocateAtom(AtomTable *atable)
+{
+    if (atable->nextFree >= atable->size)
+        GrowAtomTable(atable, atable->nextFree*2);
+    atable->amap[atable->nextFree] = -1;
+    atable->arev[atable->nextFree] = lReverse(atable->nextFree);
+    atable->nextFree++;
+    return atable->nextFree - 1;
+} // AllocateAtom
+
+/*
+ * SetAtomValue() - Allocate a new atom associated with "hashindex".
+ *
+ */
+
+static void SetAtomValue(AtomTable *atable, int atomnumber, int hashindex)
+{
+    atable->amap[atomnumber] = atable->htable.entry[hashindex].index;
+    atable->htable.entry[hashindex].value = atomnumber;
+} // SetAtomValue
+
+/*
+ * FindHashLoc() - Find the hash location for this string.  Return -1 it hash table is full.
+ *
+ */
+
+static int FindHashLoc(AtomTable *atable, const char *s)
+{
+    int hashloc, hashdelta, count;
+    int FoundEmptySlot = 0;
+    int collision[HASH_TABLE_MAX_COLLISIONS + 1];
+
+    hashloc = HashString(s) % atable->htable.size;
+    if (!Empty(&atable->htable, hashloc)) {
+        if (Match(&atable->htable, &atable->stable, s, hashloc))
+            return hashloc;
+        collision[0] = hashloc;
+        hashdelta = HashString2(s);
+        count = 0;
+        while (count < HASH_TABLE_MAX_COLLISIONS) {
+            hashloc = ((hashloc + hashdelta) & 0x7fffffff) % atable->htable.size;
+            if (!Empty(&atable->htable, hashloc)) {
+                if (Match(&atable->htable, &atable->stable, s, hashloc)) {
+                    return hashloc;
+                }
+            } else {
+                FoundEmptySlot = 1;
+                break;
+            }
+            count++;
+            collision[count] = hashloc;
+        }
+
+        if (!FoundEmptySlot) {
+            if (cpp->options.DumpAtomTable) {
+                int ii;
+                char str[200];
+                snprintf(str, sizeof(str), "*** Hash failed with more than %d collisions. Must increase hash table size. ***",
+                       HASH_TABLE_MAX_COLLISIONS);
+                CPPShInfoLogMsg(str);
+
+                snprintf(str, sizeof(str), "*** New string \"%s\", hash=%04x, delta=%04x", s, collision[0], hashdelta);
+                CPPShInfoLogMsg(str);
+                for (ii = 0; ii <= HASH_TABLE_MAX_COLLISIONS; ii++) {
+                    snprintf(str, sizeof(str), "*** Collides on try %d at hash entry %04x with \"%s\"",
+                           ii + 1, collision[ii], GetAtomString(atable, atable->htable.entry[collision[ii]].value));
+                    CPPShInfoLogMsg(str);
+                }
+            }
+            return -1;
+        } else {
+            atable->htable.counts[count]++;
+        }
+    }
+    return hashloc;
+} // FindHashLoc
+
+/*
+ * IncreaseHashTableSize()
+ *
+ */
+
+static int IncreaseHashTableSize(AtomTable *atable)
+{
+    int ii, strloc, oldhashloc, value, size;
+    AtomTable oldtable;
+    char *s;
+
+    // Save the old atom table and create a new one:
+
+    oldtable = *atable;
+    size = oldtable.htable.size*2 + 1;
+    if (!InitAtomTable(atable, size))
+        return 0;
+
+    // Add all the existing values to the new atom table preserving their atom values:
+
+    for (ii = atable->nextFree; ii < oldtable.nextFree; ii++) {
+        strloc = oldtable.amap[ii];
+        s = &oldtable.stable.strings[strloc];
+        oldhashloc = FindHashLoc(&oldtable, s);
+        assert(oldhashloc >= 0);
+        value = oldtable.htable.entry[oldhashloc].value;
+        AddAtomFixed(atable, s, value);
+    }
+    FreeAtomTable(&oldtable);
+    return 1;
+} // IncreaseHashTableSize
+
+/*
+ * LookUpAddStringHash() - Lookup a string in the hash table.  If it's not there, add it and
+ *        initialize the atom value in the hash table to 0.  Return the hash table index.
+ */
+
+static int LookUpAddStringHash(AtomTable *atable, const char *s)
+{
+    int hashloc, strloc;
+
+    while(1) {
+        hashloc = FindHashLoc(atable, s);
+        if (hashloc >= 0)
+            break;
+        IncreaseHashTableSize(atable);
+    }
+
+    if (Empty(&atable->htable, hashloc)) {
+        atable->htable.entries++;
+        strloc = AddString(&atable->stable, s);
+        atable->htable.entry[hashloc].index = strloc;
+        atable->htable.entry[hashloc].value = 0;
+    }
+    return hashloc;
+} // LookUpAddStringHash
+
+/*
+ * LookUpAddString() - Lookup a string in the hash table.  If it's not there, add it and
+ *        initialize the atom value in the hash table to the next atom number.
+ *        Return the atom value of string.
+ */
+
+int LookUpAddString(AtomTable *atable, const char *s)
+{
+    int hashindex, atom;
+
+    hashindex = LookUpAddStringHash(atable, s);
+    atom = atable->htable.entry[hashindex].value;
+    if (atom == 0) {
+        atom = AllocateAtom(atable);
+        SetAtomValue(atable, atom, hashindex);
+    }
+    return atom;
+} // LookUpAddString
+
+/*
+ * GetAtomString()
+ *
+ */
+
+const  char *GetAtomString(AtomTable *atable, int atom)
+{
+    int soffset;
+
+    if (atom > 0 && atom < atable->nextFree) {
+        soffset = atable->amap[atom];
+        if (soffset > 0 && soffset < atable->stable.nextFree) {
+            return &atable->stable.strings[soffset];
+        } else {
+            return "<internal error: bad soffset>";
+        }
+    } else {
+        if (atom == 0) {
+            return "<null atom>";
+        } else {
+            if (atom == EOF) {
+                return "<EOF>";
+            } else {
+                return "<invalid atom>";
+            }
+        }
+    }
+} // GetAtomString
+
+/*
+ * GetReversedAtom()
+ *
+ */
+
+int GetReversedAtom(AtomTable *atable, int atom)
+{
+    if (atom > 0 && atom < atable->nextFree) {
+        return atable->arev[atom];
+    } else {
+        return 0;
+    }
+} // GetReversedAtom
+
+/*
+ * AddAtom() - Add a string to the atom, hash and string tables if it isn't already there.
+ *         Return it's atom index.
+ */
+
+int AddAtom(AtomTable *atable, const char *s)
+{
+    int atom;
+
+    atom = LookUpAddString(atable, s);
+    return atom;
+} // AddAtom
+
+/*
+ * AddAtomFixed() - Add an atom to the hash and string tables if it isn't already there.
+ *         Assign it the atom value of "atom".
+ */
+
+static int AddAtomFixed(AtomTable *atable, const char *s, int atom)
+{
+    int hashindex, lsize;
+
+    hashindex = LookUpAddStringHash(atable, s);
+    if (atable->nextFree >= atable->size || atom >= atable->size) {
+        lsize = atable->size*2;
+        if (lsize <= atom)
+            lsize = atom + 1;
+        GrowAtomTable(atable, lsize);
+    }
+    atable->amap[atom] = atable->htable.entry[hashindex].index;
+    atable->htable.entry[hashindex].value = atom;
+    //if (atom >= atable->nextFree)
+    //    atable->nextFree = atom + 1;
+    while (atom >= atable->nextFree) {
+        atable->arev[atable->nextFree] = lReverse(atable->nextFree);
+        atable->nextFree++;
+    }
+    return atom;
+} // AddAtomFixed
+
+/*
+ * InitAtomTable() - Initialize the atom table.
+ *
+ */
+
+int InitAtomTable(AtomTable *atable, int htsize)
+{
+    unsigned int ii;
+
+    htsize = htsize <= 0 ? INIT_HASH_TABLE_SIZE : htsize;
+    if (!InitStringTable(&atable->stable))
+        return 0;
+    if (!InitHashTable(&atable->htable, htsize))
+        return 0;
+
+    atable->nextFree = 0;
+    atable->amap = NULL;
+    atable->size = 0;
+    GrowAtomTable(atable, INIT_ATOM_TABLE_SIZE);
+    if (!atable->amap)
+        return 0;
+
+    // Initialize lower part of atom table to "<undefined>" atom:
+
+    AddAtomFixed(atable, "<undefined>", 0);
+    for (ii = 0; ii < FIRST_USER_TOKEN_SY; ii++)
+        atable->amap[ii] = atable->amap[0];
+
+    // Add single character tokens to the atom table:
+
+    {
+               const char *s = "~!%^&*()-+=|,.<>/?;:[]{}#";
+        char t[2];
+
+        t[1] = '\0';
+        while (*s) {
+            t[0] = *s;
+            AddAtomFixed(atable, t, s[0]);
+            s++;
+        }
+    }
+
+    // Add multiple character scanner tokens :
+
+    for (ii = 0; ii < sizeof(tokens)/sizeof(tokens[0]); ii++)
+        AddAtomFixed(atable, tokens[ii].str, tokens[ii].val);
+
+    // Add error symbol if running in error mode:
+
+    if (cpp->options.ErrorMode)
+        AddAtomFixed(atable, "error", ERROR_SY);
+
+    AddAtom(atable, "<*** end fixed atoms ***>");
+
+    return 1;
+} // InitAtomTable
+
+///////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////// Debug Printing Functions: //////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////////////////////
+
+/*
+ * PrintAtomTable()
+ *
+ */
+
+void PrintAtomTable(AtomTable *atable)
+{
+    int ii;
+    char str[200];
+
+    for (ii = 0; ii < atable->nextFree; ii++) {
+        snprintf(str, sizeof(str), "%d: \"%s\"", ii, &atable->stable.strings[atable->amap[ii]]);
+        CPPDebugLogMsg(str);
+    }
+    snprintf(str, sizeof(str), "Hash table: size=%d, entries=%d, collisions=",
+           atable->htable.size, atable->htable.entries);
+    CPPDebugLogMsg(str);
+    for (ii = 0; ii < HASH_TABLE_MAX_COLLISIONS; ii++) {
+        snprintf(str, sizeof(str), " %d", atable->htable.counts[ii]);
+        CPPDebugLogMsg(str);
+    }
+
+} // PrintAtomTable
+
+
+/*
+ * GetStringOfAtom()
+ *
+ */
+
+char* GetStringOfAtom(AtomTable *atable, int atom)
+{
+        char* chr_str;
+        chr_str=&atable->stable.strings[atable->amap[atom]];
+        return chr_str;
+} // GetStringOfAtom
+
+/*
+ * FreeAtomTable() - Free the atom table and associated memory
+ *
+ */
+
+void FreeAtomTable(AtomTable *atable)
+{
+    FreeStringTable(&atable->stable);
+    FreeHashTable(&atable->htable);
+    if (atable->amap)
+        free(atable->amap);
+    if (atable->arev)
+        free(atable->arev);
+    atable->amap = NULL;
+    atable->arev = NULL;
+    atable->nextFree = 0;
+    atable->size = 0;
+} // FreeAtomTable
+
+///////////////////////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////// End of atom.c ///////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////////////////////
+
diff --git a/src/3rdparty/angle/src/compiler/preprocessor/atom.h b/src/3rdparty/angle/src/compiler/preprocessor/atom.h
new file mode 100644 (file)
index 0000000..1d84c32
--- /dev/null
@@ -0,0 +1,63 @@
+/****************************************************************************\
+Copyright (c) 2002, NVIDIA Corporation.
+
+NVIDIA Corporation("NVIDIA") supplies this software to you in
+consideration of your agreement to the following terms, and your use,
+installation, modification or redistribution of this NVIDIA software
+constitutes acceptance of these terms.  If you do not agree with these
+terms, please do not use, install, modify or redistribute this NVIDIA
+software.
+
+In consideration of your agreement to abide by the following terms, and
+subject to these terms, NVIDIA grants you a personal, non-exclusive
+license, under NVIDIA's copyrights in this original NVIDIA software (the
+"NVIDIA Software"), to use, reproduce, modify and redistribute the
+NVIDIA Software, with or without modifications, in source and/or binary
+forms; provided that if you redistribute the NVIDIA Software, you must
+retain the copyright notice of NVIDIA, this notice and the following
+text and disclaimers in all such redistributions of the NVIDIA Software.
+Neither the name, trademarks, service marks nor logos of NVIDIA
+Corporation may be used to endorse or promote products derived from the
+NVIDIA Software without specific prior written permission from NVIDIA.
+Except as expressly stated in this notice, no other rights or licenses
+express or implied, are granted by NVIDIA herein, including but not
+limited to any patent rights that may be infringed by your derivative
+works or by other works in which the NVIDIA Software may be
+incorporated. No hardware is licensed hereunder. 
+
+THE NVIDIA SOFTWARE IS BEING PROVIDED ON AN "AS IS" BASIS, WITHOUT
+WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED,
+INCLUDING WITHOUT LIMITATION, WARRANTIES OR CONDITIONS OF TITLE,
+NON-INFRINGEMENT, MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR
+ITS USE AND OPERATION EITHER ALONE OR IN COMBINATION WITH OTHER
+PRODUCTS.
+
+IN NO EVENT SHALL NVIDIA BE LIABLE FOR ANY SPECIAL, INDIRECT,
+INCIDENTAL, EXEMPLARY, CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+TO, LOST PROFITS; PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) OR ARISING IN ANY WAY
+OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE
+NVIDIA SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT,
+TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF
+NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+\****************************************************************************/
+//
+// atom.h
+//
+
+#if !defined(__ATOM_H)
+#define __ATOM_H 1
+
+typedef struct AtomTable_Rec AtomTable;
+
+extern AtomTable *atable;
+
+int InitAtomTable(AtomTable *atable, int htsize);
+void FreeAtomTable(AtomTable *atable);
+int AddAtom(AtomTable *atable, const char *s);
+void PrintAtomTable(AtomTable *atable);
+int LookUpAddString(AtomTable *atable, const char *s);
+const char *GetAtomString(AtomTable *atable, int atom);
+int GetReversedAtom(AtomTable *atable, int atom);
+char* GetStringOfAtom(AtomTable *atable, int atom);
+#endif // !defined(__ATOM_H)
diff --git a/src/3rdparty/angle/src/compiler/preprocessor/compile.h b/src/3rdparty/angle/src/compiler/preprocessor/compile.h
new file mode 100644 (file)
index 0000000..1180853
--- /dev/null
@@ -0,0 +1,100 @@
+/****************************************************************************\
+Copyright (c) 2002, NVIDIA Corporation.
+
+NVIDIA Corporation("NVIDIA") supplies this software to you in
+consideration of your agreement to the following terms, and your use,
+installation, modification or redistribution of this NVIDIA software
+constitutes acceptance of these terms.  If you do not agree with these
+terms, please do not use, install, modify or redistribute this NVIDIA
+software.
+
+In consideration of your agreement to abide by the following terms, and
+subject to these terms, NVIDIA grants you a personal, non-exclusive
+license, under NVIDIA's copyrights in this original NVIDIA software (the
+"NVIDIA Software"), to use, reproduce, modify and redistribute the
+NVIDIA Software, with or without modifications, in source and/or binary
+forms; provided that if you redistribute the NVIDIA Software, you must
+retain the copyright notice of NVIDIA, this notice and the following
+text and disclaimers in all such redistributions of the NVIDIA Software.
+Neither the name, trademarks, service marks nor logos of NVIDIA
+Corporation may be used to endorse or promote products derived from the
+NVIDIA Software without specific prior written permission from NVIDIA.
+Except as expressly stated in this notice, no other rights or licenses
+express or implied, are granted by NVIDIA herein, including but not
+limited to any patent rights that may be infringed by your derivative
+works or by other works in which the NVIDIA Software may be
+incorporated. No hardware is licensed hereunder. 
+
+THE NVIDIA SOFTWARE IS BEING PROVIDED ON AN "AS IS" BASIS, WITHOUT
+WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED,
+INCLUDING WITHOUT LIMITATION, WARRANTIES OR CONDITIONS OF TITLE,
+NON-INFRINGEMENT, MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR
+ITS USE AND OPERATION EITHER ALONE OR IN COMBINATION WITH OTHER
+PRODUCTS.
+
+IN NO EVENT SHALL NVIDIA BE LIABLE FOR ANY SPECIAL, INDIRECT,
+INCIDENTAL, EXEMPLARY, CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+TO, LOST PROFITS; PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) OR ARISING IN ANY WAY
+OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE
+NVIDIA SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT,
+TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF
+NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+\****************************************************************************/
+//
+// compile.h
+//
+
+#if !defined(__COMPILE_H)
+#define __COMPILE_H 1
+
+int InitCPPStruct(void);
+
+typedef struct Options_Rec{
+    const char *profileString;
+    int ErrorMode;
+    int Quiet;
+       
+    // Debug The Compiler options:
+    int DumpAtomTable;
+} Options;
+
+#define MAX_IF_NESTING  64
+struct CPPStruct_Rec {
+    // Public members
+    SourceLoc *pLastSourceLoc;  // Set at the start of each statement by the tree walkers
+    Options options;            // Compile options and parameters
+
+    // Private members
+    SourceLoc lastSourceLoc;
+
+    // Scanner data:
+
+    SourceLoc *tokenLoc;        // Source location of most recent token seen by the scanner
+    int mostRecentToken;        // Most recent token seen by the scanner
+    InputSrc *currentInput;
+    int previous_token;
+    int pastFirstStatement;     // used to make sure that #version is the first statement seen in the file, if present
+    
+       void *pC;                   // storing the parseContext of the compile object in cpp.  
+     
+    // Private members:
+    SourceLoc ltokenLoc;
+       int ifdepth;                //current #if-#else-#endif nesting in the cpp.c file (pre-processor)    
+    int elsedepth[MAX_IF_NESTING];//Keep a track of #if depth..Max allowed is 64.
+    int elsetracker;            //#if-#else and #endif constructs...Counter.
+    const char *ErrMsg;
+    int CompileError;           //Indicate compile error when #error, #else,#elif mismatch.
+
+    //
+    // Globals used to communicate between PaParseStrings() and yy_input()and 
+    // also across the files.(gen_glslang.cpp and scanner.c)
+    //
+    int PaWhichStr;             // which string we're parsing
+    const int* PaStrLen;        // array of lengths of the PaArgv strings
+    int PaArgc;                 // count of strings in the array
+    const char* const* PaArgv;  // our array of strings to parse    
+    unsigned int tokensBeforeEOF : 1;
+};
+
+#endif // !defined(__COMPILE_H)
diff --git a/src/3rdparty/angle/src/compiler/preprocessor/cpp.c b/src/3rdparty/angle/src/compiler/preprocessor/cpp.c
new file mode 100644 (file)
index 0000000..8a1076b
--- /dev/null
@@ -0,0 +1,1118 @@
+/****************************************************************************\
+Copyright (c) 2002, NVIDIA Corporation.
+
+NVIDIA Corporation("NVIDIA") supplies this software to you in
+consideration of your agreement to the following terms, and your use,
+installation, modification or redistribution of this NVIDIA software
+constitutes acceptance of these terms.  If you do not agree with these
+terms, please do not use, install, modify or redistribute this NVIDIA
+software.
+
+In consideration of your agreement to abide by the following terms, and
+subject to these terms, NVIDIA grants you a personal, non-exclusive
+license, under NVIDIA's copyrights in this original NVIDIA software (the
+"NVIDIA Software"), to use, reproduce, modify and redistribute the
+NVIDIA Software, with or without modifications, in source and/or binary
+forms; provided that if you redistribute the NVIDIA Software, you must
+retain the copyright notice of NVIDIA, this notice and the following
+text and disclaimers in all such redistributions of the NVIDIA Software.
+Neither the name, trademarks, service marks nor logos of NVIDIA
+Corporation may be used to endorse or promote products derived from the
+NVIDIA Software without specific prior written permission from NVIDIA.
+Except as expressly stated in this notice, no other rights or licenses
+express or implied, are granted by NVIDIA herein, including but not
+limited to any patent rights that may be infringed by your derivative
+works or by other works in which the NVIDIA Software may be
+incorporated. No hardware is licensed hereunder. 
+
+THE NVIDIA SOFTWARE IS BEING PROVIDED ON AN "AS IS" BASIS, WITHOUT
+WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED,
+INCLUDING WITHOUT LIMITATION, WARRANTIES OR CONDITIONS OF TITLE,
+NON-INFRINGEMENT, MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR
+ITS USE AND OPERATION EITHER ALONE OR IN COMBINATION WITH OTHER
+PRODUCTS.
+
+IN NO EVENT SHALL NVIDIA BE LIABLE FOR ANY SPECIAL, INDIRECT,
+INCIDENTAL, EXEMPLARY, CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+TO, LOST PROFITS; PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) OR ARISING IN ANY WAY
+OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE
+NVIDIA SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT,
+TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF
+NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+\****************************************************************************/
+//
+// cpp.c
+//
+
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+
+#include "common/angleutils.h"
+#include "compiler/preprocessor/slglobals.h"
+
+#if defined(_MSC_VER)
+#pragma warning(disable: 4054)
+#pragma warning(disable: 4152)
+#pragma warning(disable: 4706)
+#endif
+
+static int CPPif(yystypepp * yylvalpp);
+
+/* Don't use memory.c's replacements, as we clean up properly here */
+#undef malloc
+#undef free
+
+static int bindAtom = 0;
+static int constAtom = 0;
+static int defaultAtom = 0;
+static int defineAtom = 0;
+static int definedAtom = 0;
+static int elseAtom = 0;
+static int elifAtom = 0;
+static int endifAtom = 0;
+static int ifAtom = 0;
+static int ifdefAtom = 0;
+static int ifndefAtom = 0;
+static int includeAtom = 0;
+static int lineAtom = 0;
+static int pragmaAtom = 0;
+static int texunitAtom = 0;
+static int undefAtom = 0;
+static int errorAtom = 0;
+static int __LINE__Atom = 0;
+static int __FILE__Atom = 0;
+static int __VERSION__Atom = 0;
+static int versionAtom = 0;
+static int extensionAtom = 0;
+
+static Scope *macros = 0;
+#define MAX_MACRO_ARGS  64
+
+static SourceLoc ifloc; /* outermost #if */
+
+int InitCPP(void)
+{
+    char        buffer[64], *t;
+    const char  *f;
+
+    // Add various atoms needed by the CPP line scanner:
+    bindAtom = LookUpAddString(atable, "bind");
+    constAtom = LookUpAddString(atable, "const");
+    defaultAtom = LookUpAddString(atable, "default");
+    defineAtom = LookUpAddString(atable, "define");
+    definedAtom = LookUpAddString(atable, "defined");
+    elifAtom = LookUpAddString(atable, "elif");
+    elseAtom = LookUpAddString(atable, "else");
+    endifAtom = LookUpAddString(atable, "endif");
+    ifAtom = LookUpAddString(atable, "if");
+    ifdefAtom = LookUpAddString(atable, "ifdef");
+    ifndefAtom = LookUpAddString(atable, "ifndef");
+    includeAtom = LookUpAddString(atable, "include");
+    lineAtom = LookUpAddString(atable, "line");
+    pragmaAtom = LookUpAddString(atable, "pragma");
+    texunitAtom = LookUpAddString(atable, "texunit");
+    undefAtom = LookUpAddString(atable, "undef");
+       errorAtom = LookUpAddString(atable, "error");
+    __LINE__Atom = LookUpAddString(atable, "__LINE__");
+    __FILE__Atom = LookUpAddString(atable, "__FILE__");
+       __VERSION__Atom = LookUpAddString(atable, "__VERSION__");
+    versionAtom = LookUpAddString(atable, "version");
+    extensionAtom = LookUpAddString(atable, "extension");
+    macros = NewScopeInPool(mem_CreatePool(0, 0));
+    strcpy(buffer, "PROFILE_");
+    t = buffer + strlen(buffer);
+    f = cpp->options.profileString;
+    while ((isalnum(*f) || *f == '_') && t < buffer + sizeof(buffer) - 1)
+        *t++ = toupper(*f++);
+    *t = 0;
+
+    PredefineIntMacro("GL_ES", 1);
+    PredefineIntMacro("GL_FRAGMENT_PRECISION_HIGH", 1);
+
+       return 1;
+} // InitCPP
+
+int FreeCPP(void)
+{
+    if (macros)
+    {
+        mem_FreePool(macros->pool);
+        macros = 0;
+    }
+
+    return 1;
+}
+
+int FinalCPP(void)
+{
+       if (cpp->ifdepth)
+               CPPErrorToInfoLog("#if mismatch");
+    return 1;
+}
+
+static int CPPdefine(yystypepp * yylvalpp)
+{
+    int token, name, args[MAX_MACRO_ARGS], argc;
+    const char *message;
+    MacroSymbol mac;
+    Symbol *symb;
+    SourceLoc dummyLoc;
+    memset(&mac, 0, sizeof(mac));
+    token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
+    if (token != CPP_IDENTIFIER) {
+        CPPErrorToInfoLog("#define");
+        return token;
+    }
+    name = yylvalpp->sc_ident;
+    token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
+    if (token == '(' && !yylvalpp->sc_int) {
+        // gather arguments
+        argc = 0;
+        do {
+            token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
+            if (argc == 0 && token == ')') break;
+            if (token != CPP_IDENTIFIER) {
+                               CPPErrorToInfoLog("#define");
+                return token;
+            }
+            if (argc < MAX_MACRO_ARGS)
+                args[argc++] = yylvalpp->sc_ident;
+            token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
+        } while (token == ',');
+        if (token != ')') {
+            CPPErrorToInfoLog("#define");
+            return token;
+        }
+        mac.argc = argc;
+        mac.args = mem_Alloc(macros->pool, argc * sizeof(int));
+        memcpy(mac.args, args, argc * sizeof(int));
+        token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
+       }
+    mac.body = NewTokenStream(GetAtomString(atable, name), macros->pool);
+    while (token != '\n') {
+        if (token == '\\') {
+            CPPErrorToInfoLog("The line continuation character (\\) is not part of the OpenGL ES Shading Language");
+            return token;
+        } else if (token <= 0) { // EOF or error
+            CPPErrorToInfoLog("unexpected end of input in #define preprocessor directive - expected a newline");
+            return 0;
+        }
+        RecordToken(mac.body, token, yylvalpp);
+        token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
+    };
+
+    symb = LookUpSymbol(macros, name);
+    if (symb) {
+        if (!symb->details.mac.undef) {
+            // already defined -- need to make sure they are identical
+            if (symb->details.mac.argc != mac.argc) goto error;
+            for (argc=0; argc < mac.argc; argc++)
+                if (symb->details.mac.args[argc] != mac.args[argc])
+                    goto error;
+            RewindTokenStream(symb->details.mac.body);
+            RewindTokenStream(mac.body);
+            do {
+                int old_lval, old_token;
+                old_token = ReadToken(symb->details.mac.body, yylvalpp);
+                old_lval = yylvalpp->sc_int;
+                token = ReadToken(mac.body, yylvalpp);
+                if (token != old_token || yylvalpp->sc_int != old_lval) { 
+                error:
+                    StoreStr("Macro Redefined");
+                    StoreStr(GetStringOfAtom(atable,name));
+                    message=GetStrfromTStr();
+                    DecLineNumber();
+                    CPPShInfoLogMsg(message);
+                    IncLineNumber();
+                    ResetTString();
+                    break; }
+            } while (token > 0);
+        }
+        //FreeMacro(&symb->details.mac);
+    } else {
+        dummyLoc.file = 0;
+        dummyLoc.line = 0;
+        symb = AddSymbol(&dummyLoc, macros, name, MACRO_S);
+    }
+    symb->details.mac = mac;
+    return '\n';
+} // CPPdefine
+
+static int CPPundef(yystypepp * yylvalpp)
+{
+    int token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
+    Symbol *symb;
+       if(token == '\n'){
+               CPPErrorToInfoLog("#undef");
+           return token;
+    }
+    if (token != CPP_IDENTIFIER)
+          goto error;
+    symb = LookUpSymbol(macros, yylvalpp->sc_ident);
+    if (symb) {
+        symb->details.mac.undef = 1;
+    }
+    token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
+    if (token != '\n') {
+    error:
+        CPPErrorToInfoLog("#undef");
+    }
+    return token;
+} // CPPundef
+
+/* CPPelse -- skip forward to appropriate spot.  This is actually used
+** to skip to and #endif after seeing an #else, AND to skip to a #else,
+** #elif, or #endif after a #if/#ifdef/#ifndef/#elif test was false
+*/
+
+static int CPPelse(int matchelse, yystypepp * yylvalpp)
+{
+    int atom,depth=0;
+    int token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
+       
+       while (token > 0) {
+        if (token != '#') {
+            while (token != '\n') {
+                token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
+                if (token <= 0) { // EOF or error
+                    CPPErrorToInfoLog("unexpected end of input in #else preprocessor directive - expected a newline");
+                    return 0;
+                }
+            }
+            token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
+            continue;
+        }
+               if ((token = cpp->currentInput->scan(cpp->currentInput, yylvalpp)) != CPP_IDENTIFIER)
+                       continue;
+        atom = yylvalpp->sc_ident;
+        if (atom == ifAtom || atom == ifdefAtom || atom == ifndefAtom){
+            depth++; cpp->ifdepth++; cpp->elsetracker++;
+            if (cpp->ifdepth > MAX_IF_NESTING) {
+                CPPErrorToInfoLog("max #if nesting depth exceeded");
+                cpp->CompileError = 1;
+                return 0;
+            }
+            // sanity check elsetracker
+            if (cpp->elsetracker < 0 || cpp->elsetracker >= MAX_IF_NESTING) {
+                CPPErrorToInfoLog("mismatched #if/#endif statements");
+                cpp->CompileError = 1;
+                return 0;
+            }
+            cpp->elsedepth[cpp->elsetracker] = 0;
+        }
+        else if (atom == endifAtom) {
+            if(--depth<0){
+                if (cpp->elsetracker)
+                    --cpp->elsetracker;
+                if (cpp->ifdepth) 
+                    --cpp->ifdepth;
+                break;
+            }             
+            --cpp->elsetracker;
+            --cpp->ifdepth;
+        }
+        else if (((int)(matchelse) != 0)&& depth==0) {
+                       if (atom == elseAtom ) {
+                token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
+                if (token != '\n') {
+                    CPPWarningToInfoLog("unexpected tokens following #else preprocessor directive - expected a newline");
+                    while (token != '\n') {
+                        token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
+                        if (token <= 0) { // EOF or error
+                            CPPErrorToInfoLog("unexpected end of input following #else preprocessor directive - expected a newline");
+                            return 0;
+                        }
+                    }
+                } 
+                               break;
+                       } 
+                       else if (atom == elifAtom) {
+                /* we decrement cpp->ifdepth here, because CPPif will increment
+                 * it and we really want to leave it alone */
+                               if (cpp->ifdepth){
+                                       --cpp->ifdepth;
+                                   --cpp->elsetracker;
+                               }
+                return CPPif(yylvalpp);
+            }
+               }
+        else if((atom==elseAtom) && (!ChkCorrectElseNesting())){
+            CPPErrorToInfoLog("#else after a #else");
+            cpp->CompileError=1;
+            return 0;
+        }
+       };
+    return token;
+}
+
+enum eval_prec {
+    MIN_PREC,
+    COND, LOGOR, LOGAND, OR, XOR, AND, EQUAL, RELATION, SHIFT, ADD, MUL, UNARY,
+    MAX_PREC
+};
+
+static int op_logor(int a, int b) { return a || b; }
+static int op_logand(int a, int b) { return a && b; }
+static int op_or(int a, int b) { return a | b; }
+static int op_xor(int a, int b) { return a ^ b; }
+static int op_and(int a, int b) { return a & b; }
+static int op_eq(int a, int b) { return a == b; }
+static int op_ne(int a, int b) { return a != b; }
+static int op_ge(int a, int b) { return a >= b; }
+static int op_le(int a, int b) { return a <= b; }
+static int op_gt(int a, int b) { return a > b; }
+static int op_lt(int a, int b) { return a < b; }
+static int op_shl(int a, int b) { return a << b; }
+static int op_shr(int a, int b) { return a >> b; }
+static int op_add(int a, int b) { return a + b; }
+static int op_sub(int a, int b) { return a - b; }
+static int op_mul(int a, int b) { return a * b; }
+static int op_div(int a, int b) { return a / b; }
+static int op_mod(int a, int b) { return a % b; }
+static int op_pos(int a) { return a; }
+static int op_neg(int a) { return -a; }
+static int op_cmpl(int a) { return ~a; }
+static int op_not(int a) { return !a; }
+
+struct {
+    int token, prec, (*op)(int, int);
+} binop[] = {
+    { CPP_OR_OP, LOGOR, op_logor },
+    { CPP_AND_OP, LOGAND, op_logand },
+    { '|', OR, op_or },
+    { '^', XOR, op_xor },
+    { '&', AND, op_and },
+    { CPP_EQ_OP, EQUAL, op_eq },
+    { CPP_NE_OP, EQUAL, op_ne },
+    { '>', RELATION, op_gt },
+    { CPP_GE_OP, RELATION, op_ge },
+    { '<', RELATION, op_lt },
+    { CPP_LE_OP, RELATION, op_le },
+    { CPP_LEFT_OP, SHIFT, op_shl },
+    { CPP_RIGHT_OP, SHIFT, op_shr },
+    { '+', ADD, op_add },
+    { '-', ADD, op_sub },
+    { '*', MUL, op_mul },
+    { '/', MUL, op_div },
+    { '%', MUL, op_mod },
+};
+
+struct {
+    int token, (*op)(int);
+} unop[] = {
+    { '+', op_pos },
+    { '-', op_neg },
+    { '~', op_cmpl },
+    { '!', op_not },
+};
+
+#define ALEN(A) (sizeof(A)/sizeof(A[0]))
+
+static int eval(int token, int prec, int *res, int *err, yystypepp * yylvalpp)
+{
+    int         i, val;
+    Symbol      *s;
+    if (token == CPP_IDENTIFIER) {
+        if (yylvalpp->sc_ident == definedAtom) {
+            int needclose = 0;
+            token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
+            if (token == '(') {
+                needclose = 1;
+                token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
+            }
+            if (token != CPP_IDENTIFIER)
+                goto error;
+            *res = (s = LookUpSymbol(macros, yylvalpp->sc_ident))
+                        ? !s->details.mac.undef : 0;
+            token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
+            if (needclose) {
+                if (token != ')')
+                    goto error;
+                token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
+            }
+               } else if (MacroExpand(yylvalpp->sc_ident, yylvalpp)) {
+                       token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
+            return eval(token, prec, res, err, yylvalpp);
+        } else {
+            goto error;
+        }
+       } else if (token == CPP_INTCONSTANT) {
+        *res = yylvalpp->sc_int;
+        token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
+    } else if (token == '(') {
+        token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
+        token = eval(token, MIN_PREC, res, err, yylvalpp);
+        if (!*err) {
+            if (token != ')')
+                goto error;
+            token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
+        }
+    } else {
+        for (i = ALEN(unop) - 1; i >= 0; i--) {
+            if (unop[i].token == token)
+                break;
+        }
+        if (i >= 0) {
+            token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
+            token = eval(token, UNARY, res, err, yylvalpp);
+            *res = unop[i].op(*res);
+        } else {
+            goto error;
+        }
+    }
+    while (!*err) {
+        if (token == ')' || token == '\n') break;
+        for (i = ALEN(binop) - 1; i >= 0; i--) {
+            if (binop[i].token == token)
+                break;
+        }
+        if (i < 0 || binop[i].prec <= prec)
+            break;
+        val = *res;
+        token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
+        token = eval(token, binop[i].prec, res, err, yylvalpp);
+        
+        if (binop[i].op == op_div || binop[i].op == op_mod)
+        {
+            if (*res == 0)
+            {
+                CPPErrorToInfoLog("preprocessor divide or modulo by zero");
+                *err = 1;
+                return token;
+            }
+        }
+
+        *res = binop[i].op(val, *res);
+    }
+    return token;
+error:
+    CPPErrorToInfoLog("incorrect preprocessor directive");
+    *err = 1;
+    *res = 0;
+    return token;
+} // eval
+
+static int CPPif(yystypepp * yylvalpp) {
+    int token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
+    int res = 0, err = 0;
+
+    if (!cpp->ifdepth++)
+        ifloc = *cpp->tokenLoc;
+    if(cpp->ifdepth > MAX_IF_NESTING){
+        CPPErrorToInfoLog("max #if nesting depth exceeded");
+        cpp->CompileError = 1;
+        return 0;
+    }
+    cpp->elsetracker++;
+    // sanity check elsetracker
+    if (cpp->elsetracker < 0 || cpp->elsetracker >= MAX_IF_NESTING) {
+        CPPErrorToInfoLog("mismatched #if/#endif statements");
+        cpp->CompileError = 1;
+        return 0;
+    }
+    cpp->elsedepth[cpp->elsetracker] = 0;
+
+    token = eval(token, MIN_PREC, &res, &err, yylvalpp);
+    if (token != '\n') {
+        CPPWarningToInfoLog("unexpected tokens following #if preprocessor directive - expected a newline");
+        while (token != '\n') {
+            token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
+            if (token <= 0) { // EOF or error
+                CPPErrorToInfoLog("unexpected end of input in #if preprocessor directive - expected a newline");
+                return 0;
+            }
+        }
+    } 
+    if (!res && !err) {
+        token = CPPelse(1, yylvalpp);
+    }
+
+    return token;
+} // CPPif
+
+static int CPPifdef(int defined, yystypepp * yylvalpp)
+{
+    int token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
+    int name = yylvalpp->sc_ident;
+    if(++cpp->ifdepth > MAX_IF_NESTING){
+        CPPErrorToInfoLog("max #if nesting depth exceeded");
+        cpp->CompileError = 1;
+        return 0;
+    }
+    cpp->elsetracker++;
+    // sanity check elsetracker
+    if (cpp->elsetracker < 0 || cpp->elsetracker >= MAX_IF_NESTING) {
+        CPPErrorToInfoLog("mismatched #if/#endif statements");
+        cpp->CompileError = 1;
+        return 0;
+    }
+    cpp->elsedepth[cpp->elsetracker] = 0;
+
+    if (token != CPP_IDENTIFIER) {
+            defined ? CPPErrorToInfoLog("ifdef"):CPPErrorToInfoLog("ifndef");
+    } else {
+        Symbol *s = LookUpSymbol(macros, name);
+        token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
+        if (token != '\n') {
+            CPPWarningToInfoLog("unexpected tokens following #ifdef preprocessor directive - expected a newline");
+            while (token != '\n') {
+                token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
+                if (token <= 0) { // EOF or error
+                    CPPErrorToInfoLog("unexpected end of input in #ifdef preprocessor directive - expected a newline");
+                    return 0;
+                }
+            }
+        }
+        if (((s && !s->details.mac.undef) ? 1 : 0) != defined)
+            token = CPPelse(1, yylvalpp);
+    }
+    return token;
+} // CPPifdef
+
+static int CPPline(yystypepp * yylvalpp) 
+{
+    int token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
+       if(token=='\n'){
+               DecLineNumber();
+        CPPErrorToInfoLog("#line");
+        IncLineNumber();
+               return token;
+       }
+       else if (token == CPP_INTCONSTANT) {
+               yylvalpp->sc_int=atoi(yylvalpp->symbol_name);
+               SetLineNumber(yylvalpp->sc_int);
+        token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
+        
+               if (token == CPP_INTCONSTANT) {
+            yylvalpp->sc_int=atoi(yylvalpp->symbol_name);
+                       SetStringNumber(yylvalpp->sc_int);
+            token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
+                       if(token!='\n')
+                               CPPErrorToInfoLog("#line");
+        }
+               else if (token == '\n'){
+                       return token;
+               }
+               else{
+            CPPErrorToInfoLog("#line");
+               }
+       }
+       else{
+          CPPErrorToInfoLog("#line");
+       }
+    return token;
+}
+
+static int CPPerror(yystypepp * yylvalpp) {
+
+       int token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
+    const char *message;
+       
+    while (token != '\n') {
+        if (token <= 0){
+            CPPErrorToInfoLog("unexpected end of input in #error preprocessor directive - expected a newline");
+            return 0;
+        }else if (token == CPP_FLOATCONSTANT || token == CPP_INTCONSTANT){
+            StoreStr(yylvalpp->symbol_name);
+               }else if(token == CPP_IDENTIFIER || token == CPP_STRCONSTANT){
+                       StoreStr(GetStringOfAtom(atable,yylvalpp->sc_ident));
+               }else {
+                   StoreStr(GetStringOfAtom(atable,token));
+               }
+               token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
+       }
+       DecLineNumber();
+       //store this msg into the shader's information log..set the Compile Error flag!!!!
+       message=GetStrfromTStr();
+    CPPShInfoLogMsg(message);
+    ResetTString();
+    cpp->CompileError=1;
+    IncLineNumber();
+    return '\n';
+}//CPPerror
+
+static int CPPpragma(yystypepp * yylvalpp)
+{
+       char SrcStrName[2];
+       char** allTokens;
+       int tokenCount = 0;
+       int maxTokenCount = 10;
+       const char* SrcStr;
+       int i;
+
+       int token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
+       
+       if (token=='\n') {
+               DecLineNumber();
+        CPPErrorToInfoLog("#pragma");
+        IncLineNumber();
+           return token;
+       }
+       
+       allTokens = (char**)malloc(sizeof(char*) * maxTokenCount);      
+
+       while (token != '\n') {
+               if (tokenCount >= maxTokenCount) {
+                       maxTokenCount *= 2;
+                       allTokens = (char**)realloc((char**)allTokens, sizeof(char*) * maxTokenCount);
+               }
+               switch (token) {
+               case CPP_IDENTIFIER:
+                       SrcStr = GetAtomString(atable, yylvalpp->sc_ident);
+                       allTokens[tokenCount] = (char*)malloc(strlen(SrcStr) + 1);
+                       strcpy(allTokens[tokenCount++], SrcStr);
+                       break;
+               case CPP_INTCONSTANT:
+                       SrcStr = yylvalpp->symbol_name;
+                       allTokens[tokenCount] = (char*)malloc(strlen(SrcStr) + 1);
+                       strcpy(allTokens[tokenCount++], SrcStr);
+                       break;
+               case CPP_FLOATCONSTANT:
+                       SrcStr = yylvalpp->symbol_name;
+                       allTokens[tokenCount] = (char*)malloc(strlen(SrcStr) + 1);
+                       strcpy(allTokens[tokenCount++], SrcStr);
+                       break;
+               case -1:
+            // EOF
+            CPPShInfoLogMsg("#pragma directive must end with a newline");                      
+                       goto freeMemoryAndReturnToken;
+               default:
+                       SrcStrName[0] = token;
+                       SrcStrName[1] = '\0';
+                       allTokens[tokenCount] = (char*)malloc(2);
+                       strcpy(allTokens[tokenCount++], SrcStrName);
+               }
+               token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
+       }
+
+       HandlePragma((const char**)allTokens, tokenCount);
+       
+freeMemoryAndReturnToken:
+       for (i = 0; i < tokenCount; ++i) {
+               free (allTokens[i]);
+       }
+       free (allTokens);       
+
+       return token;    
+} // CPPpragma
+
+#define ESSL_VERSION_NUMBER 100
+#define ESSL_VERSION_STRING "100"
+
+static int CPPversion(yystypepp * yylvalpp)
+{
+
+    int token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
+
+    if (cpp->pastFirstStatement == 1)
+        CPPShInfoLogMsg("#version must occur before any other statement in the program");
+
+    if(token=='\n'){
+               DecLineNumber();
+        CPPErrorToInfoLog("#version");
+        IncLineNumber();
+               return token;
+       }
+    if (token != CPP_INTCONSTANT)
+        CPPErrorToInfoLog("#version");
+       
+    yylvalpp->sc_int=atoi(yylvalpp->symbol_name);
+       //SetVersionNumber(yylvalpp->sc_int);
+    
+    if (yylvalpp->sc_int != ESSL_VERSION_NUMBER)
+        CPPShInfoLogMsg("Version number not supported by ESSL");
+
+    token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
+    
+       if (token == '\n'){
+               return token;
+       }
+       else{
+        CPPErrorToInfoLog("#version");
+       }
+    return token;
+} // CPPversion
+
+static int CPPextension(yystypepp * yylvalpp)
+{
+
+    int token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
+    char extensionName[MAX_SYMBOL_NAME_LEN + 1];
+
+    if(token=='\n'){
+               DecLineNumber();
+        CPPShInfoLogMsg("extension name not specified");
+        IncLineNumber();
+               return token;
+       }
+
+    if (token != CPP_IDENTIFIER)
+        CPPErrorToInfoLog("#extension");
+    
+    strncpy(extensionName, GetAtomString(atable, yylvalpp->sc_ident), MAX_SYMBOL_NAME_LEN);
+    extensionName[MAX_SYMBOL_NAME_LEN] = '\0';
+           
+    token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
+    if (token != ':') {
+        CPPShInfoLogMsg("':' missing after extension name");
+        return token;
+    }
+    
+    token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
+    if (token != CPP_IDENTIFIER) {
+        CPPShInfoLogMsg("behavior for extension not specified");
+        return token;
+    }
+
+    updateExtensionBehavior(extensionName, GetAtomString(atable, yylvalpp->sc_ident));
+
+    token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
+       if (token == '\n'){
+               return token;
+       }
+       else{
+        CPPErrorToInfoLog("#extension");
+       }
+    return token;
+} // CPPextension
+
+int readCPPline(yystypepp * yylvalpp)
+{
+    int token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
+    const char *message;
+
+    if (token == CPP_IDENTIFIER) {
+        if (yylvalpp->sc_ident == defineAtom) {
+             token = CPPdefine(yylvalpp);
+        } else if (yylvalpp->sc_ident == elseAtom) {
+                        if(ChkCorrectElseNesting()){
+                 if (!cpp->ifdepth ){
+                     CPPErrorToInfoLog("#else mismatch");
+                     cpp->CompileError=1;
+                     return 0;
+                 }
+                 token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
+                 if (token != '\n') {
+                     CPPWarningToInfoLog("unexpected tokens following #else preprocessor directive - expected a newline");
+                     while (token != '\n') {
+                         token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
+                         if (token <= 0) { // EOF or error
+                             CPPErrorToInfoLog("unexpected end of input in #ifdef preprocessor directive - expected a newline");
+                             return 0;
+                         }
+                     }
+                 }
+                            token = CPPelse(0, yylvalpp);
+             }else{
+                 CPPErrorToInfoLog("#else after a #else");
+                 cpp->ifdepth = 0;
+                 cpp->elsetracker = 0;
+                 cpp->pastFirstStatement = 1;
+                 cpp->CompileError = 1;
+                 return 0;
+             }
+               } else if (yylvalpp->sc_ident == elifAtom) {
+            if (!cpp->ifdepth){
+                 CPPErrorToInfoLog("#elif mismatch");
+                 cpp->CompileError=1;
+                 return 0;
+            } 
+            // this token is really a dont care, but we still need to eat the tokens
+            token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); 
+            while (token != '\n') {
+                token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
+                if (token <= 0) { // EOF or error
+                    CPPErrorToInfoLog("unexpect tokens following #elif preprocessor directive - expected a newline");
+                    cpp->CompileError = 1;
+                    return 0;
+                }
+            }
+                   token = CPPelse(0, yylvalpp);
+        } else if (yylvalpp->sc_ident == endifAtom) {
+             if (!cpp->ifdepth){
+                 CPPErrorToInfoLog("#endif mismatch");
+                 cpp->CompileError=1;
+                 return 0;
+             }
+             else
+                 --cpp->ifdepth;
+
+             if (cpp->elsetracker)
+                 --cpp->elsetracker;
+
+           } else if (yylvalpp->sc_ident == ifAtom) {
+             token = CPPif(yylvalpp);
+        } else if (yylvalpp->sc_ident == ifdefAtom) {
+             token = CPPifdef(1, yylvalpp);
+        } else if (yylvalpp->sc_ident == ifndefAtom) {
+             token = CPPifdef(0, yylvalpp);
+        } else if (yylvalpp->sc_ident == lineAtom) {
+             token = CPPline(yylvalpp);
+        } else if (yylvalpp->sc_ident == pragmaAtom) {
+             token = CPPpragma(yylvalpp);
+        } else if (yylvalpp->sc_ident == undefAtom) {
+             token = CPPundef(yylvalpp);
+        } else if (yylvalpp->sc_ident == errorAtom) {
+             token = CPPerror(yylvalpp);
+        } else if (yylvalpp->sc_ident == versionAtom) {
+            token = CPPversion(yylvalpp);
+        } else if (yylvalpp->sc_ident == extensionAtom) {
+            token = CPPextension(yylvalpp);
+        } else {
+            StoreStr("Invalid Directive");
+            StoreStr(GetStringOfAtom(atable,yylvalpp->sc_ident));
+            message=GetStrfromTStr();
+            CPPShInfoLogMsg(message);
+            ResetTString();
+        }
+    }
+    while (token != '\n' && token != 0 && token != EOF) {
+               token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
+       }
+        
+    cpp->pastFirstStatement = 1;
+
+    return token;
+} // readCPPline
+
+void FreeMacro(MacroSymbol *s) {
+    DeleteTokenStream(s->body);
+}
+
+void PredefineIntMacro(const char *name, int value) {
+    SourceLoc location = {0, 0};
+    Symbol *symbol = NULL;
+    MacroSymbol macro = {0, NULL, NULL, 0, 0};
+    yystypepp val = {0, 0.0, 0, {0}};
+    int atom = 0;
+
+    macro.body = NewTokenStream(name, macros->pool);
+    val.sc_int = value;
+    snprintf(val.symbol_name, MAX_SYMBOL_NAME_LEN+1, "%d", value);
+    RecordToken(macro.body, CPP_INTCONSTANT, &val);
+    atom = LookUpAddString(atable, name);
+    symbol = AddSymbol(&location, macros, atom, MACRO_S);
+    symbol->details.mac = macro;
+}
+
+static int eof_scan(InputSrc *in, yystypepp * yylvalpp) { return -1; }
+static void noop(InputSrc *in, int ch, yystypepp * yylvalpp) { }
+
+static void PushEofSrc() {
+    InputSrc *in = malloc(sizeof(InputSrc));
+    memset(in, 0, sizeof(InputSrc));
+    in->scan = eof_scan;
+    in->getch = eof_scan;
+    in->ungetch = noop;
+    in->prev = cpp->currentInput;
+    cpp->currentInput = in;
+}
+
+static void PopEofSrc() {
+    if (cpp->currentInput->scan == eof_scan) {
+        InputSrc *in = cpp->currentInput;
+        cpp->currentInput = in->prev;
+        free(in);
+    }
+}
+
+static TokenStream *PrescanMacroArg(TokenStream *a, yystypepp * yylvalpp) {
+    int token;
+    TokenStream *n;
+    RewindTokenStream(a);
+    do {
+        token = ReadToken(a, yylvalpp);
+        if (token == CPP_IDENTIFIER && LookUpSymbol(macros, yylvalpp->sc_ident))
+            break;
+    } while (token > 0);
+    if (token <= 0) return a;
+    n = NewTokenStream("macro arg", 0);
+    PushEofSrc();
+    ReadFromTokenStream(a, 0, 0);
+    while ((token = cpp->currentInput->scan(cpp->currentInput, yylvalpp)) > 0) {
+        if (token == CPP_IDENTIFIER && MacroExpand(yylvalpp->sc_ident, yylvalpp))
+            continue;
+        RecordToken(n, token, yylvalpp);
+    }
+    PopEofSrc();
+    DeleteTokenStream(a);
+    return n;
+} // PrescanMacroArg
+
+typedef struct MacroInputSrc {
+    InputSrc    base;
+    MacroSymbol *mac;
+    TokenStream **args;
+} MacroInputSrc;
+
+/* macro_scan ---
+** return the next token for a macro expanion, handling macro args 
+*/
+static int macro_scan(MacroInputSrc *in, yystypepp * yylvalpp) {
+    int i;
+    int token = ReadToken(in->mac->body, yylvalpp);
+    if (token == CPP_IDENTIFIER) {
+        for (i = in->mac->argc-1; i>=0; i--)
+            if (in->mac->args[i] == yylvalpp->sc_ident) break;
+        if (i >= 0) {
+            ReadFromTokenStream(in->args[i], yylvalpp->sc_ident, 0);
+            return cpp->currentInput->scan(cpp->currentInput, yylvalpp);
+        }
+    }
+    if (token > 0) return token;
+    in->mac->busy = 0;
+    cpp->currentInput = in->base.prev;
+    if (in->args) {
+        for (i=in->mac->argc-1; i>=0; i--)
+            DeleteTokenStream(in->args[i]);
+        free(in->args);
+    }
+    free(in);
+    return cpp->currentInput->scan(cpp->currentInput, yylvalpp);
+} // macro_scan
+
+/* MacroExpand
+** check an identifier (atom) to see if it a macro that should be expanded.
+** If it is, push an InputSrc that will produce the appropriate expansion
+** and return TRUE.  If not, return FALSE.
+*/
+
+int MacroExpand(int atom, yystypepp * yylvalpp)
+{
+    Symbol              *sym = LookUpSymbol(macros, atom);
+    MacroInputSrc       *in;
+    int i,j, token, depth=0;
+    const char *message;
+       if (atom == __LINE__Atom) {
+        yylvalpp->sc_int = GetLineNumber();
+        snprintf(yylvalpp->symbol_name, MAX_SYMBOL_NAME_LEN+1, "%d", yylvalpp->sc_int);
+        UngetToken(CPP_INTCONSTANT, yylvalpp);
+        return 1;
+    }
+    if (atom == __FILE__Atom) {
+        yylvalpp->sc_int = GetStringNumber();
+        snprintf(yylvalpp->symbol_name, MAX_SYMBOL_NAME_LEN+1, "%d", yylvalpp->sc_int);
+        UngetToken(CPP_INTCONSTANT, yylvalpp);
+        return 1;
+    }
+       if (atom == __VERSION__Atom) {
+        strcpy(yylvalpp->symbol_name,ESSL_VERSION_STRING);
+        yylvalpp->sc_int = atoi(yylvalpp->symbol_name);
+        UngetToken(CPP_INTCONSTANT, yylvalpp);
+        return 1;
+    }
+    if (!sym || sym->details.mac.undef) return 0;
+    if (sym->details.mac.busy) return 0;        // no recursive expansions
+    in = malloc(sizeof(*in));
+    memset(in, 0, sizeof(*in));
+    in->base.scan = (void *)macro_scan;
+    in->base.line = cpp->currentInput->line;
+    in->base.name = cpp->currentInput->name;
+    in->mac = &sym->details.mac;
+    if (sym->details.mac.args) {
+        token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
+               if (token != '(') {
+            UngetToken(token, yylvalpp);
+            yylvalpp->sc_ident = atom;
+            return 0;
+        }
+        in->args = malloc(in->mac->argc * sizeof(TokenStream *));
+        for (i=0; i<in->mac->argc; i++)
+            in->args[i] = NewTokenStream("macro arg", 0);
+               i=0;j=0;
+        do{
+            depth = 0;
+                       while(1) {
+                token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
+                if (token <= 0) {
+                    StoreStr("EOF in Macro ");
+                    StoreStr(GetStringOfAtom(atable,atom));
+                    message=GetStrfromTStr();
+                    CPPShInfoLogMsg(message);
+                    ResetTString();
+                    return 1;
+                }
+                if((in->mac->argc==0) && (token!=')')) break;
+                if (depth == 0 && (token == ',' || token == ')')) break;
+                if (token == '(') depth++;
+                if (token == ')') depth--;
+                RecordToken(in->args[i], token, yylvalpp);
+                j=1;
+                       }
+            if (token == ')') {
+                if((in->mac->argc==1) &&j==0)
+                    break;
+                i++;
+                break;
+            }
+            i++;
+               }while(i < in->mac->argc);
+
+        if (i < in->mac->argc) {
+            StoreStr("Too few args in Macro ");
+            StoreStr(GetStringOfAtom(atable,atom));
+            message=GetStrfromTStr();
+            CPPShInfoLogMsg(message);
+            ResetTString();
+        } else if (token != ')') {
+            depth=0;
+                       while (token >= 0 && (depth > 0 || token != ')')) {
+                if (token == ')') depth--;
+                token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
+                if (token == '(') depth++;
+            }
+                       
+            if (token <= 0) {
+                StoreStr("EOF in Macro ");
+                StoreStr(GetStringOfAtom(atable,atom));
+                message=GetStrfromTStr();
+                CPPShInfoLogMsg(message);
+                ResetTString();
+                return 1;
+            }
+            StoreStr("Too many args in Macro ");
+            StoreStr(GetStringOfAtom(atable,atom));
+            message=GetStrfromTStr();
+            CPPShInfoLogMsg(message);
+            ResetTString();
+               }
+               for (i=0; i<in->mac->argc; i++) {
+            in->args[i] = PrescanMacroArg(in->args[i], yylvalpp);
+        }
+    }
+#if 0
+    printf("  <%s:%d>found macro %s\n", GetAtomString(atable, loc.file),
+           loc.line, GetAtomString(atable, atom));
+    for (i=0; i<in->mac->argc; i++) {
+        printf("\targ %s = '", GetAtomString(atable, in->mac->args[i]));
+        DumpTokenStream(stdout, in->args[i]);
+        printf("'\n");
+    }
+#endif
+       /*retain the input source*/
+    in->base.prev = cpp->currentInput;
+    sym->details.mac.busy = 1;
+    RewindTokenStream(sym->details.mac.body);
+    cpp->currentInput = &in->base;
+    return 1;
+} // MacroExpand
+
+int ChkCorrectElseNesting(void)
+{
+    // sanity check to make sure elsetracker is in a valid range
+    if (cpp->elsetracker < 0 || cpp->elsetracker >= MAX_IF_NESTING) {
+        return 0;
+    }
+
+    if (cpp->elsedepth[cpp->elsetracker] == 0) {
+        cpp->elsedepth[cpp->elsetracker] = 1;
+        return 1;
+    }
+    return 0;
+}
+
+
diff --git a/src/3rdparty/angle/src/compiler/preprocessor/cpp.h b/src/3rdparty/angle/src/compiler/preprocessor/cpp.h
new file mode 100644 (file)
index 0000000..802e23e
--- /dev/null
@@ -0,0 +1,86 @@
+/****************************************************************************\
+Copyright (c) 2002, NVIDIA Corporation.
+
+NVIDIA Corporation("NVIDIA") supplies this software to you in
+consideration of your agreement to the following terms, and your use,
+installation, modification or redistribution of this NVIDIA software
+constitutes acceptance of these terms.  If you do not agree with these
+terms, please do not use, install, modify or redistribute this NVIDIA
+software.
+
+In consideration of your agreement to abide by the following terms, and
+subject to these terms, NVIDIA grants you a personal, non-exclusive
+license, under NVIDIA's copyrights in this original NVIDIA software (the
+"NVIDIA Software"), to use, reproduce, modify and redistribute the
+NVIDIA Software, with or without modifications, in source and/or binary
+forms; provided that if you redistribute the NVIDIA Software, you must
+retain the copyright notice of NVIDIA, this notice and the following
+text and disclaimers in all such redistributions of the NVIDIA Software.
+Neither the name, trademarks, service marks nor logos of NVIDIA
+Corporation may be used to endorse or promote products derived from the
+NVIDIA Software without specific prior written permission from NVIDIA.
+Except as expressly stated in this notice, no other rights or licenses
+express or implied, are granted by NVIDIA herein, including but not
+limited to any patent rights that may be infringed by your derivative
+works or by other works in which the NVIDIA Software may be
+incorporated. No hardware is licensed hereunder. 
+
+THE NVIDIA SOFTWARE IS BEING PROVIDED ON AN "AS IS" BASIS, WITHOUT
+WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED,
+INCLUDING WITHOUT LIMITATION, WARRANTIES OR CONDITIONS OF TITLE,
+NON-INFRINGEMENT, MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR
+ITS USE AND OPERATION EITHER ALONE OR IN COMBINATION WITH OTHER
+PRODUCTS.
+
+IN NO EVENT SHALL NVIDIA BE LIABLE FOR ANY SPECIAL, INDIRECT,
+INCIDENTAL, EXEMPLARY, CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+TO, LOST PROFITS; PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) OR ARISING IN ANY WAY
+OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE
+NVIDIA SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT,
+TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF
+NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+\****************************************************************************/
+//
+// cpp.h
+//
+
+#if !defined(__CPP_H)
+#define __CPP_H 1
+
+#include "compiler/preprocessor/parser.h"
+#include "compiler/preprocessor/tokens.h"
+
+int InitCPP(void);
+int FinalCPP(void);
+int  readCPPline(yystypepp * yylvalpp);
+int MacroExpand(int atom, yystypepp * yylvalpp);
+int ChkCorrectElseNesting(void);
+
+typedef struct MacroSymbol {
+    int argc;
+    int *args;
+    TokenStream *body;
+    unsigned busy:1;
+    unsigned undef:1;
+} MacroSymbol;
+
+void FreeMacro(MacroSymbol *);
+void PredefineIntMacro(const char *name, int value);
+
+void  CPPDebugLogMsg(const char *msg);      // Prints information into debug log
+void  CPPShInfoLogMsg(const char*);         // Store cpp Err Msg into Sh.Info.Log
+void  CPPWarningToInfoLog(const char *msg); // Prints warning messages into info log
+void  HandlePragma(const char**, int numTokens);  // #pragma directive container.
+void  ResetTString(void);                   // #error Message as TString.
+void  CPPErrorToInfoLog(const char*);       // Stick all cpp errors into Sh.Info.log.
+void  StoreStr(const char*);                // Store the TString in Parse Context.
+void  SetLineNumber(int);                   // Set line number.  
+void  SetStringNumber(int);                 // Set string number.    
+int   GetLineNumber(void);                  // Get the current String Number. 
+int   GetStringNumber(void);                // Get the current String Number. 
+const char* GetStrfromTStr(void);           // Convert TString to String.  
+void  updateExtensionBehavior(const char* extName, const char* behavior);
+int   FreeCPP(void);
+
+#endif // !(defined(__CPP_H)
diff --git a/src/3rdparty/angle/src/compiler/preprocessor/cppstruct.c b/src/3rdparty/angle/src/compiler/preprocessor/cppstruct.c
new file mode 100644 (file)
index 0000000..58cff31
--- /dev/null
@@ -0,0 +1,152 @@
+/****************************************************************************\
+Copyright (c) 2002, NVIDIA Corporation.
+
+NVIDIA Corporation("NVIDIA") supplies this software to you in
+consideration of your agreement to the following terms, and your use,
+installation, modification or redistribution of this NVIDIA software
+constitutes acceptance of these terms.  If you do not agree with these
+terms, please do not use, install, modify or redistribute this NVIDIA
+software.
+
+In consideration of your agreement to abide by the following terms, and
+subject to these terms, NVIDIA grants you a personal, non-exclusive
+license, under NVIDIA's copyrights in this original NVIDIA software (the
+"NVIDIA Software"), to use, reproduce, modify and redistribute the
+NVIDIA Software, with or without modifications, in source and/or binary
+forms; provided that if you redistribute the NVIDIA Software, you must
+retain the copyright notice of NVIDIA, this notice and the following
+text and disclaimers in all such redistributions of the NVIDIA Software.
+Neither the name, trademarks, service marks nor logos of NVIDIA
+Corporation may be used to endorse or promote products derived from the
+NVIDIA Software without specific prior written permission from NVIDIA.
+Except as expressly stated in this notice, no other rights or licenses
+express or implied, are granted by NVIDIA herein, including but not
+limited to any patent rights that may be infringed by your derivative
+works or by other works in which the NVIDIA Software may be
+incorporated. No hardware is licensed hereunder. 
+
+THE NVIDIA SOFTWARE IS BEING PROVIDED ON AN "AS IS" BASIS, WITHOUT
+WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED,
+INCLUDING WITHOUT LIMITATION, WARRANTIES OR CONDITIONS OF TITLE,
+NON-INFRINGEMENT, MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR
+ITS USE AND OPERATION EITHER ALONE OR IN COMBINATION WITH OTHER
+PRODUCTS.
+
+IN NO EVENT SHALL NVIDIA BE LIABLE FOR ANY SPECIAL, INDIRECT,
+INCIDENTAL, EXEMPLARY, CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+TO, LOST PROFITS; PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) OR ARISING IN ANY WAY
+OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE
+NVIDIA SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT,
+TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF
+NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+\****************************************************************************/
+//
+// cppstruct.c
+//
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "compiler/preprocessor/slglobals.h"
+
+CPPStruct  *cpp      = NULL;
+static int  refCount = 0;
+
+int InitPreprocessor(void);
+int ResetPreprocessor(void);
+int FreeCPPStruct(void);
+int FinalizePreprocessor(void);
+
+/*
+ * InitCPPStruct() - Initilaize the CPP structure.
+ *
+ */
+
+int InitCPPStruct(void)
+{
+    int len;
+    char *p;
+
+    cpp = (CPPStruct *) malloc(sizeof(CPPStruct));
+    if (cpp == NULL)
+        return 0;
+
+    refCount++;
+
+    // Initialize public members:
+    cpp->pLastSourceLoc = &cpp->lastSourceLoc;
+    
+       p = (char *) &cpp->options;
+    len = sizeof(cpp->options);
+    while (--len >= 0)
+        p[len] = 0;
+     
+    ResetPreprocessor();
+    return 1;
+} // InitCPPStruct
+
+int ResetPreprocessor(void)
+{
+    // Initialize private members:
+
+    cpp->lastSourceLoc.file = 0;
+    cpp->lastSourceLoc.line = 0;
+    cpp->pC = 0;
+    cpp->CompileError = 0;
+    cpp->ifdepth = 0;
+    for(cpp->elsetracker = 0; cpp->elsetracker < MAX_IF_NESTING; cpp->elsetracker++)
+        cpp->elsedepth[cpp->elsetracker] = 0;
+    cpp->elsetracker = 0;
+    cpp->tokensBeforeEOF = 0;
+    return 1;
+}
+
+//Intializing the Preprocessor.
+
+int InitPreprocessor(void)
+{
+   #  define CPP_STUFF true
+        #  ifdef CPP_STUFF
+            FreeCPPStruct();
+            InitCPPStruct();
+            cpp->options.Quiet = 1;
+            cpp->options.profileString = "generic";
+            if (!InitAtomTable(atable, 0))
+                return 1;
+            if (!InitScanner(cpp))
+                   return 1;
+       #  endif
+  return 0; 
+}
+
+//FreeCPPStruct() - Free the CPP structure.
+
+int FreeCPPStruct(void)
+{
+    if (refCount)
+    {
+       free(cpp);
+       refCount--;
+    }
+    
+    return 1;
+}
+
+//Finalizing the Preprocessor.
+
+int FinalizePreprocessor(void)
+{
+   #  define CPP_STUFF true
+        #  ifdef CPP_STUFF
+            FreeAtomTable(atable);
+            FreeCPPStruct();
+            FreeScanner();
+       #  endif
+  return 0; 
+}
+
+
+///////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////// End of cppstruct.c //////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////////////////////
diff --git a/src/3rdparty/angle/src/compiler/preprocessor/length_limits.h b/src/3rdparty/angle/src/compiler/preprocessor/length_limits.h
new file mode 100644 (file)
index 0000000..4f1f713
--- /dev/null
@@ -0,0 +1,21 @@
+//
+// Copyright (c) 2011 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+//
+// length_limits.h
+//
+
+#if !defined(__LENGTH_LIMITS_H)
+#define __LENGTH_LIMITS_H 1
+
+// These constants are factored out from the rest of the headers to
+// make it easier to reference them from the compiler sources.
+
+// These lengths do not include the NULL terminator.
+#define MAX_SYMBOL_NAME_LEN 256
+#define MAX_STRING_LEN 511
+
+#endif // !(defined(__LENGTH_LIMITS_H)
diff --git a/src/3rdparty/angle/src/compiler/preprocessor/memory.c b/src/3rdparty/angle/src/compiler/preprocessor/memory.c
new file mode 100644 (file)
index 0000000..029521a
--- /dev/null
@@ -0,0 +1,158 @@
+/****************************************************************************\
+Copyright (c) 2002, NVIDIA Corporation.
+
+NVIDIA Corporation("NVIDIA") supplies this software to you in
+consideration of your agreement to the following terms, and your use,
+installation, modification or redistribution of this NVIDIA software
+constitutes acceptance of these terms.  If you do not agree with these
+terms, please do not use, install, modify or redistribute this NVIDIA
+software.
+
+In consideration of your agreement to abide by the following terms, and
+subject to these terms, NVIDIA grants you a personal, non-exclusive
+license, under NVIDIA's copyrights in this original NVIDIA software (the
+"NVIDIA Software"), to use, reproduce, modify and redistribute the
+NVIDIA Software, with or without modifications, in source and/or binary
+forms; provided that if you redistribute the NVIDIA Software, you must
+retain the copyright notice of NVIDIA, this notice and the following
+text and disclaimers in all such redistributions of the NVIDIA Software.
+Neither the name, trademarks, service marks nor logos of NVIDIA
+Corporation may be used to endorse or promote products derived from the
+NVIDIA Software without specific prior written permission from NVIDIA.
+Except as expressly stated in this notice, no other rights or licenses
+express or implied, are granted by NVIDIA herein, including but not
+limited to any patent rights that may be infringed by your derivative
+works or by other works in which the NVIDIA Software may be
+incorporated. No hardware is licensed hereunder. 
+
+THE NVIDIA SOFTWARE IS BEING PROVIDED ON AN "AS IS" BASIS, WITHOUT
+WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED,
+INCLUDING WITHOUT LIMITATION, WARRANTIES OR CONDITIONS OF TITLE,
+NON-INFRINGEMENT, MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR
+ITS USE AND OPERATION EITHER ALONE OR IN COMBINATION WITH OTHER
+PRODUCTS.
+
+IN NO EVENT SHALL NVIDIA BE LIABLE FOR ANY SPECIAL, INDIRECT,
+INCIDENTAL, EXEMPLARY, CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+TO, LOST PROFITS; PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) OR ARISING IN ANY WAY
+OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE
+NVIDIA SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT,
+TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF
+NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+\****************************************************************************/
+//
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+
+#ifndef _MSC_VER
+#include <stdint.h>
+#endif
+
+#include "compiler/preprocessor/memory.h"
+
+#if defined(_MSC_VER)
+#pragma warning(disable: 4706)
+#endif
+
+// default alignment and chunksize, if called with 0 arguments
+#define CHUNKSIZE       (64*1024)
+#define ALIGN           8
+
+// we need to call the `real' malloc and free, not our replacements
+#undef malloc
+#undef free
+
+struct chunk {
+    struct chunk        *next;
+};
+
+struct cleanup {
+    struct cleanup      *next;
+    void                (*fn)(void *);
+    void                *arg;
+};
+
+struct MemoryPool_rec {
+    struct chunk        *next;
+    uintptr_t           free, end;
+    size_t              chunksize;
+    uintptr_t           alignmask;
+    struct cleanup      *cleanup;
+};
+
+MemoryPool *mem_CreatePool(size_t chunksize, unsigned int align)
+{
+    MemoryPool  *pool;
+
+    if (align == 0) align = ALIGN;
+    if (chunksize == 0) chunksize = CHUNKSIZE;
+    if (align & (align-1)) return 0;
+    if (chunksize < sizeof(MemoryPool)) return 0;
+    if (chunksize & (align-1)) return 0;
+    if (!(pool = malloc(chunksize))) return 0;
+    pool->next = 0;
+    pool->chunksize = chunksize;
+    pool->alignmask = (uintptr_t)(align)-1;  
+    pool->free = ((uintptr_t)(pool + 1) + pool->alignmask) & ~pool->alignmask;
+    pool->end = (uintptr_t)pool + chunksize;
+    pool->cleanup = 0;
+    return pool;
+}
+
+void mem_FreePool(MemoryPool *pool)
+{
+    struct cleanup      *cleanup;
+    struct chunk        *p, *next;
+
+    for (cleanup = pool->cleanup; cleanup; cleanup = cleanup->next) {
+        cleanup->fn(cleanup->arg);
+    }
+    for (p = (struct chunk *)pool; p; p = next) {
+        next = p->next;
+        free(p);
+    }
+}
+
+void *mem_Alloc(MemoryPool *pool, size_t size)
+{
+    struct chunk *ch;
+    void *rv = (void *)pool->free;
+    size = (size + pool->alignmask) & ~pool->alignmask;
+    if (size <= 0) size = pool->alignmask;
+    pool->free += size;
+    if (pool->free > pool->end || pool->free < (uintptr_t)rv) {
+        size_t minreq = (size + sizeof(struct chunk) + pool->alignmask)
+                      & ~pool->alignmask;
+        pool->free = (uintptr_t)rv;
+        if (minreq >= pool->chunksize) {
+            // request size is too big for the chunksize, so allocate it as
+            // a single chunk of the right size
+            ch = malloc(minreq);
+            if (!ch) return 0;
+        } else {
+            ch = malloc(pool->chunksize);
+            if (!ch) return 0;
+            pool->free = (uintptr_t)ch + minreq;
+            pool->end = (uintptr_t)ch + pool->chunksize;
+        }
+        ch->next = pool->next;
+        pool->next = ch;
+        rv = (void *)(((uintptr_t)(ch+1) + pool->alignmask) & ~pool->alignmask);
+    }
+    return rv;
+}
+
+int mem_AddCleanup(MemoryPool *pool, void (*fn)(void *), void *arg) {
+    struct cleanup *cleanup;
+
+    pool->free = (pool->free + sizeof(void *) - 1) & ~(sizeof(void *)-1);
+    cleanup = mem_Alloc(pool, sizeof(struct cleanup));
+    if (!cleanup) return -1;
+    cleanup->next = pool->cleanup;
+    cleanup->fn = fn;
+    cleanup->arg = arg;
+    pool->cleanup = cleanup;
+    return 0;
+}
diff --git a/src/3rdparty/angle/src/compiler/preprocessor/memory.h b/src/3rdparty/angle/src/compiler/preprocessor/memory.h
new file mode 100644 (file)
index 0000000..5fcadb3
--- /dev/null
@@ -0,0 +1,58 @@
+/****************************************************************************\
+Copyright (c) 2002, NVIDIA Corporation.
+
+NVIDIA Corporation("NVIDIA") supplies this software to you in
+consideration of your agreement to the following terms, and your use,
+installation, modification or redistribution of this NVIDIA software
+constitutes acceptance of these terms.  If you do not agree with these
+terms, please do not use, install, modify or redistribute this NVIDIA
+software.
+
+In consideration of your agreement to abide by the following terms, and
+subject to these terms, NVIDIA grants you a personal, non-exclusive
+license, under NVIDIA's copyrights in this original NVIDIA software (the
+"NVIDIA Software"), to use, reproduce, modify and redistribute the
+NVIDIA Software, with or without modifications, in source and/or binary
+forms; provided that if you redistribute the NVIDIA Software, you must
+retain the copyright notice of NVIDIA, this notice and the following
+text and disclaimers in all such redistributions of the NVIDIA Software.
+Neither the name, trademarks, service marks nor logos of NVIDIA
+Corporation may be used to endorse or promote products derived from the
+NVIDIA Software without specific prior written permission from NVIDIA.
+Except as expressly stated in this notice, no other rights or licenses
+express or implied, are granted by NVIDIA herein, including but not
+limited to any patent rights that may be infringed by your derivative
+works or by other works in which the NVIDIA Software may be
+incorporated. No hardware is licensed hereunder. 
+
+THE NVIDIA SOFTWARE IS BEING PROVIDED ON AN "AS IS" BASIS, WITHOUT
+WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED,
+INCLUDING WITHOUT LIMITATION, WARRANTIES OR CONDITIONS OF TITLE,
+NON-INFRINGEMENT, MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR
+ITS USE AND OPERATION EITHER ALONE OR IN COMBINATION WITH OTHER
+PRODUCTS.
+
+IN NO EVENT SHALL NVIDIA BE LIABLE FOR ANY SPECIAL, INDIRECT,
+INCIDENTAL, EXEMPLARY, CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+TO, LOST PROFITS; PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) OR ARISING IN ANY WAY
+OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE
+NVIDIA SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT,
+TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF
+NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+\****************************************************************************/
+//
+#ifndef __MEMORY_H
+#define __MEMORY_H
+
+#include <stddef.h>
+
+typedef struct MemoryPool_rec MemoryPool;
+
+extern MemoryPool *mem_CreatePool(size_t chunksize, unsigned int align);
+extern void mem_FreePool(MemoryPool *);
+extern void *mem_Alloc(MemoryPool *p, size_t size);
+extern void *mem_Realloc(MemoryPool *p, void *old, size_t oldsize, size_t newsize);
+extern int mem_AddCleanup(MemoryPool *p, void (*fn)(void *), void *arg);
+
+#endif /* __MEMORY_H */
diff --git a/src/3rdparty/angle/src/compiler/preprocessor/new/Diagnostics.cpp b/src/3rdparty/angle/src/compiler/preprocessor/new/Diagnostics.cpp
new file mode 100644 (file)
index 0000000..3f50dfc
--- /dev/null
@@ -0,0 +1,127 @@
+//
+// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "Diagnostics.h"
+
+#include <cassert>
+
+namespace pp
+{
+
+Diagnostics::~Diagnostics()
+{
+}
+
+void Diagnostics::report(ID id,
+                         const SourceLocation& loc,
+                         const std::string& text)
+{
+    // TODO(alokp): Keep a count of errors and warnings.
+    print(id, loc, text);
+}
+
+Diagnostics::Severity Diagnostics::severity(ID id)
+{
+    if ((id > ERROR_BEGIN) && (id < ERROR_END))
+        return ERROR;
+
+    if ((id > WARNING_BEGIN) && (id < WARNING_END))
+        return WARNING;
+
+    assert(false);
+    return ERROR;
+}
+
+std::string Diagnostics::message(ID id)
+{
+    switch (id)
+    {
+      // Errors begin.
+      case INTERNAL_ERROR:
+          return "internal error";
+      case OUT_OF_MEMORY:
+          return "out of memory";
+      case INVALID_CHARACTER:
+          return "invalid character";
+      case INVALID_NUMBER:
+          return "invalid number";
+      case INTEGER_OVERFLOW:
+          return "integer overflow";
+      case FLOAT_OVERFLOW:
+          return "float overflow";
+      case TOKEN_TOO_LONG:
+          return "token too long";
+      case INVALID_EXPRESSION:
+          return "invalid expression";
+      case DIVISION_BY_ZERO:
+          return "division by zero";
+      case EOF_IN_COMMENT:
+          return "unexpected end of file found in comment";
+      case UNEXPECTED_TOKEN:
+          return "unexpected token";
+      case DIRECTIVE_INVALID_NAME:
+          return "invalid directive name";
+      case MACRO_NAME_RESERVED:
+          return "macro name is reserved";
+      case MACRO_REDEFINED:
+          return "macro redefined";
+      case MACRO_PREDEFINED_REDEFINED:
+          return "predefined macro redefined";
+      case MACRO_PREDEFINED_UNDEFINED:
+          return "predefined macro undefined";
+      case MACRO_UNTERMINATED_INVOCATION:
+          return "unterminated macro invocation";
+      case MACRO_TOO_FEW_ARGS:
+          return "Not enough arguments for macro";
+      case MACRO_TOO_MANY_ARGS:
+          return "Too many arguments for macro";
+      case CONDITIONAL_ENDIF_WITHOUT_IF:
+          return "unexpected #endif found without a matching #if";
+      case CONDITIONAL_ELSE_WITHOUT_IF:
+          return "unexpected #else found without a matching #if";
+      case CONDITIONAL_ELSE_AFTER_ELSE:
+          return "unexpected #else found after another #else";
+      case CONDITIONAL_ELIF_WITHOUT_IF:
+          return "unexpected #elif found without a matching #if";
+      case CONDITIONAL_ELIF_AFTER_ELSE:
+          return "unexpected #elif found after #else";
+      case CONDITIONAL_UNTERMINATED:
+          return "unexpected end of file found in conditional block";
+      case INVALID_EXTENSION_NAME:
+          return "invalid extension name";
+      case INVALID_EXTENSION_BEHAVIOR:
+          return "invalid extension behavior";
+      case INVALID_EXTENSION_DIRECTIVE:
+          return "invalid extension directive";
+      case INVALID_VERSION_NUMBER:
+          return "invalid version number";
+      case INVALID_VERSION_DIRECTIVE:
+          return "invalid version directive";
+      case VERSION_NOT_FIRST_STATEMENT:
+        return "#version directive must occur before anything else, "
+               "except for comments and white space";
+      case INVALID_LINE_NUMBER:
+          return "invalid line number";
+      case INVALID_FILE_NUMBER:
+          return "invalid file number";
+      case INVALID_LINE_DIRECTIVE:
+          return "invalid line directive";
+      // Errors end.
+      // Warnings begin.
+      case EOF_IN_DIRECTIVE:
+          return "unexpected end of file found in directive";
+      case CONDITIONAL_UNEXPECTED_TOKEN:
+          return "unexpected token after conditional expression";
+      case UNRECOGNIZED_PRAGMA:
+          return "unrecognized pragma";
+      // Warnings end.
+      default:
+          assert(false);
+          return "";
+    }
+}
+
+}  // namespace pp
diff --git a/src/3rdparty/angle/src/compiler/preprocessor/new/Diagnostics.h b/src/3rdparty/angle/src/compiler/preprocessor/new/Diagnostics.h
new file mode 100644 (file)
index 0000000..07bc411
--- /dev/null
@@ -0,0 +1,87 @@
+//
+// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#ifndef COMPILER_PREPROCESSOR_DIAGNOSTICS_H_
+#define COMPILER_PREPROCESSOR_DIAGNOSTICS_H_
+
+#include <string>
+
+namespace pp
+{
+
+struct SourceLocation;
+
+// Base class for reporting diagnostic messages.
+// Derived classes are responsible for formatting and printing the messages.
+class Diagnostics
+{
+  public:
+    enum Severity
+    {
+        ERROR,
+        WARNING
+    };
+    enum ID
+    {
+        ERROR_BEGIN,
+        INTERNAL_ERROR,
+        OUT_OF_MEMORY,
+        INVALID_CHARACTER,
+        INVALID_NUMBER,
+        INTEGER_OVERFLOW,
+        FLOAT_OVERFLOW,
+        TOKEN_TOO_LONG,
+        INVALID_EXPRESSION,
+        DIVISION_BY_ZERO,
+        EOF_IN_COMMENT,
+        UNEXPECTED_TOKEN,
+        DIRECTIVE_INVALID_NAME,
+        MACRO_NAME_RESERVED,
+        MACRO_REDEFINED,
+        MACRO_PREDEFINED_REDEFINED,
+        MACRO_PREDEFINED_UNDEFINED,
+        MACRO_UNTERMINATED_INVOCATION,
+        MACRO_TOO_FEW_ARGS,
+        MACRO_TOO_MANY_ARGS,
+        CONDITIONAL_ENDIF_WITHOUT_IF,
+        CONDITIONAL_ELSE_WITHOUT_IF,
+        CONDITIONAL_ELSE_AFTER_ELSE,
+        CONDITIONAL_ELIF_WITHOUT_IF,
+        CONDITIONAL_ELIF_AFTER_ELSE,
+        CONDITIONAL_UNTERMINATED,
+        INVALID_EXTENSION_NAME,
+        INVALID_EXTENSION_BEHAVIOR,
+        INVALID_EXTENSION_DIRECTIVE,
+        INVALID_VERSION_NUMBER,
+        INVALID_VERSION_DIRECTIVE,
+        VERSION_NOT_FIRST_STATEMENT,
+        INVALID_LINE_NUMBER,
+        INVALID_FILE_NUMBER,
+        INVALID_LINE_DIRECTIVE,
+        ERROR_END,
+
+        WARNING_BEGIN,
+        EOF_IN_DIRECTIVE,
+        CONDITIONAL_UNEXPECTED_TOKEN,
+        UNRECOGNIZED_PRAGMA,
+        WARNING_END
+    };
+
+    virtual ~Diagnostics();
+
+    void report(ID id, const SourceLocation& loc, const std::string& text);
+
+  protected:
+    Severity severity(ID id);
+    std::string message(ID id);
+
+    virtual void print(ID id,
+                       const SourceLocation& loc,
+                       const std::string& text) = 0;
+};
+
+}  // namespace pp
+#endif  // COMPILER_PREPROCESSOR_DIAGNOSTICS_H_
diff --git a/src/3rdparty/angle/src/compiler/preprocessor/new/DirectiveHandler.cpp b/src/3rdparty/angle/src/compiler/preprocessor/new/DirectiveHandler.cpp
new file mode 100644 (file)
index 0000000..ca91e1c
--- /dev/null
@@ -0,0 +1,16 @@
+//
+// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "DirectiveHandler.h"
+
+namespace pp
+{
+
+DirectiveHandler::~DirectiveHandler()
+{
+}
+
+}  // namespace pp
diff --git a/src/3rdparty/angle/src/compiler/preprocessor/new/DirectiveHandler.h b/src/3rdparty/angle/src/compiler/preprocessor/new/DirectiveHandler.h
new file mode 100644 (file)
index 0000000..2aaeec2
--- /dev/null
@@ -0,0 +1,43 @@
+//
+// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#ifndef COMPILER_PREPROCESSOR_DIRECTIVE_HANDLER_H_
+#define COMPILER_PREPROCESSOR_DIRECTIVE_HANDLER_H_
+
+#include <string>
+
+namespace pp
+{
+
+struct SourceLocation;
+
+// Base class for handling directives.
+// Preprocessor uses this class to notify the clients about certain
+// preprocessor directives. Derived classes are responsible for
+// handling them in an appropriate manner.
+class DirectiveHandler
+{
+  public:
+    virtual ~DirectiveHandler();
+
+    virtual void handleError(const SourceLocation& loc,
+                             const std::string& msg) = 0;
+
+    // Handle pragma of form: #pragma name[(value)]
+    virtual void handlePragma(const SourceLocation& loc,
+                              const std::string& name,
+                              const std::string& value) = 0;
+
+    virtual void handleExtension(const SourceLocation& loc,
+                                 const std::string& name,
+                                 const std::string& behavior) = 0;
+
+    virtual void handleVersion(const SourceLocation& loc,
+                               int version) = 0;
+};
+
+}  // namespace pp
+#endif  // COMPILER_PREPROCESSOR_DIRECTIVE_HANDLER_H_
diff --git a/src/3rdparty/angle/src/compiler/preprocessor/new/DirectiveParser.cpp b/src/3rdparty/angle/src/compiler/preprocessor/new/DirectiveParser.cpp
new file mode 100644 (file)
index 0000000..f2e42d0
--- /dev/null
@@ -0,0 +1,932 @@
+//
+// Copyright (c) 2011 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "DirectiveParser.h"
+
+#include <cassert>
+#include <cstdlib>
+#include <sstream>
+
+#include "Diagnostics.h"
+#include "DirectiveHandler.h"
+#include "ExpressionParser.h"
+#include "MacroExpander.h"
+#include "Token.h"
+#include "Tokenizer.h"
+
+namespace {
+enum DirectiveType
+{
+    DIRECTIVE_NONE,
+    DIRECTIVE_DEFINE,
+    DIRECTIVE_UNDEF,
+    DIRECTIVE_IF,
+    DIRECTIVE_IFDEF,
+    DIRECTIVE_IFNDEF,
+    DIRECTIVE_ELSE,
+    DIRECTIVE_ELIF,
+    DIRECTIVE_ENDIF,
+    DIRECTIVE_ERROR,
+    DIRECTIVE_PRAGMA,
+    DIRECTIVE_EXTENSION,
+    DIRECTIVE_VERSION,
+    DIRECTIVE_LINE
+};
+}  // namespace
+
+static DirectiveType getDirective(const pp::Token* token)
+{
+    static const std::string kDirectiveDefine("define");
+    static const std::string kDirectiveUndef("undef");
+    static const std::string kDirectiveIf("if");
+    static const std::string kDirectiveIfdef("ifdef");
+    static const std::string kDirectiveIfndef("ifndef");
+    static const std::string kDirectiveElse("else");
+    static const std::string kDirectiveElif("elif");
+    static const std::string kDirectiveEndif("endif");
+    static const std::string kDirectiveError("error");
+    static const std::string kDirectivePragma("pragma");
+    static const std::string kDirectiveExtension("extension");
+    static const std::string kDirectiveVersion("version");
+    static const std::string kDirectiveLine("line");
+
+    if (token->type != pp::Token::IDENTIFIER)
+        return DIRECTIVE_NONE;
+
+    if (token->text == kDirectiveDefine)
+        return DIRECTIVE_DEFINE;
+    else if (token->text == kDirectiveUndef)
+        return DIRECTIVE_UNDEF;
+    else if (token->text == kDirectiveIf)
+        return DIRECTIVE_IF;
+    else if (token->text == kDirectiveIfdef)
+        return DIRECTIVE_IFDEF;
+    else if (token->text == kDirectiveIfndef)
+        return DIRECTIVE_IFNDEF;
+    else if (token->text == kDirectiveElse)
+        return DIRECTIVE_ELSE;
+    else if (token->text == kDirectiveElif)
+        return DIRECTIVE_ELIF;
+    else if (token->text == kDirectiveEndif)
+        return DIRECTIVE_ENDIF;
+    else if (token->text == kDirectiveError)
+        return DIRECTIVE_ERROR;
+    else if (token->text == kDirectivePragma)
+        return DIRECTIVE_PRAGMA;
+    else if (token->text == kDirectiveExtension)
+        return DIRECTIVE_EXTENSION;
+    else if (token->text == kDirectiveVersion)
+        return DIRECTIVE_VERSION;
+    else if (token->text == kDirectiveLine)
+        return DIRECTIVE_LINE;
+
+    return DIRECTIVE_NONE;
+}
+
+static bool isConditionalDirective(DirectiveType directive)
+{
+    switch (directive)
+    {
+      case DIRECTIVE_IF:
+      case DIRECTIVE_IFDEF:
+      case DIRECTIVE_IFNDEF:
+      case DIRECTIVE_ELSE:
+      case DIRECTIVE_ELIF:
+      case DIRECTIVE_ENDIF:
+        return true;
+      default:
+        return false;
+    }
+}
+
+// Returns true if the token represents End Of Directive.
+static bool isEOD(const pp::Token* token)
+{
+    return (token->type == '\n') || (token->type == pp::Token::LAST);
+}
+
+static void skipUntilEOD(pp::Lexer* lexer, pp::Token* token)
+{
+    while(!isEOD(token))
+    {
+        lexer->lex(token);
+    }
+}
+
+static bool isMacroNameReserved(const std::string& name)
+{
+    // Names prefixed with "GL_" are reserved.
+    if (name.substr(0, 3) == "GL_")
+        return true;
+
+    // Names containing two consecutive underscores are reserved.
+    if (name.find("__") != std::string::npos)
+        return true;
+
+    return false;
+}
+
+static bool isMacroPredefined(const std::string& name,
+                              const pp::MacroSet& macroSet)
+{
+    pp::MacroSet::const_iterator iter = macroSet.find(name);
+    return iter != macroSet.end() ? iter->second.predefined : false;
+}
+
+namespace pp
+{
+
+class DefinedParser : public Lexer
+{
+  public:
+    DefinedParser(Lexer* lexer,
+                  const MacroSet* macroSet,
+                  Diagnostics* diagnostics) :
+        mLexer(lexer),
+        mMacroSet(macroSet),
+        mDiagnostics(diagnostics)
+    {
+    }
+
+  protected:
+    virtual void lex(Token* token)
+    {
+        static const std::string kDefined("defined");
+
+        mLexer->lex(token);
+        if (token->type != Token::IDENTIFIER)
+            return;
+        if (token->text != kDefined)
+            return;
+
+        bool paren = false;
+        mLexer->lex(token);
+        if (token->type == '(')
+        {
+            paren = true;
+            mLexer->lex(token);
+        }
+
+        if (token->type != Token::IDENTIFIER)
+        {
+            mDiagnostics->report(Diagnostics::UNEXPECTED_TOKEN,
+                                 token->location, token->text);
+            skipUntilEOD(mLexer, token);
+            return;
+        }
+        MacroSet::const_iterator iter = mMacroSet->find(token->text);
+        std::string expression = iter != mMacroSet->end() ? "1" : "0";
+
+        if (paren)
+        {
+            mLexer->lex(token);
+            if (token->type != ')')
+            {
+                mDiagnostics->report(Diagnostics::UNEXPECTED_TOKEN,
+                                     token->location, token->text);
+                skipUntilEOD(mLexer, token);
+                return;
+            }
+        }
+
+        // We have a valid defined operator.
+        // Convert the current token into a CONST_INT token.
+        token->type = Token::CONST_INT;
+        token->text = expression;
+    }
+
+  private:
+    Lexer* mLexer;
+    const MacroSet* mMacroSet;
+    Diagnostics* mDiagnostics;
+};
+
+DirectiveParser::DirectiveParser(Tokenizer* tokenizer,
+                                 MacroSet* macroSet,
+                                 Diagnostics* diagnostics,
+                                 DirectiveHandler* directiveHandler) :
+    mPastFirstStatement(false),
+    mTokenizer(tokenizer),
+    mMacroSet(macroSet),
+    mDiagnostics(diagnostics),
+    mDirectiveHandler(directiveHandler)
+{
+}
+
+void DirectiveParser::lex(Token* token)
+{
+    do
+    {
+        mTokenizer->lex(token);
+
+        if (token->type == Token::PP_HASH)
+        {
+            parseDirective(token);
+            mPastFirstStatement = true;
+        }
+
+        if (token->type == Token::LAST)
+        {
+            if (!mConditionalStack.empty())
+            {
+                const ConditionalBlock& block = mConditionalStack.back();
+                mDiagnostics->report(Diagnostics::CONDITIONAL_UNTERMINATED,
+                                     block.location, block.type);
+            }
+            break;
+        }
+
+    } while (skipping() || (token->type == '\n'));
+
+    mPastFirstStatement = true;
+}
+
+void DirectiveParser::parseDirective(Token* token)
+{
+    assert(token->type == Token::PP_HASH);
+
+    mTokenizer->lex(token);
+    if (isEOD(token))
+    {
+        // Empty Directive.
+        return;
+    }
+
+    DirectiveType directive = getDirective(token);
+
+    // While in an excluded conditional block/group,
+    // we only parse conditional directives.
+    if (skipping() && !isConditionalDirective(directive))
+    {
+        skipUntilEOD(mTokenizer, token);
+        return;
+    }
+
+    switch(directive)
+    {
+      case DIRECTIVE_NONE:
+        mDiagnostics->report(Diagnostics::DIRECTIVE_INVALID_NAME,
+                             token->location, token->text);
+        skipUntilEOD(mTokenizer, token);
+        break;
+      case DIRECTIVE_DEFINE:
+        parseDefine(token);
+        break;
+      case DIRECTIVE_UNDEF:
+        parseUndef(token);
+        break;
+      case DIRECTIVE_IF:
+        parseIf(token);
+        break;
+      case DIRECTIVE_IFDEF:
+        parseIfdef(token);
+        break;
+      case DIRECTIVE_IFNDEF:
+        parseIfndef(token);
+        break;
+      case DIRECTIVE_ELSE:
+        parseElse(token);
+        break;
+      case DIRECTIVE_ELIF:
+        parseElif(token);
+        break;
+      case DIRECTIVE_ENDIF:
+        parseEndif(token);
+        break;
+      case DIRECTIVE_ERROR:
+        parseError(token);
+        break;
+      case DIRECTIVE_PRAGMA:
+        parsePragma(token);
+        break;
+      case DIRECTIVE_EXTENSION:
+        parseExtension(token);
+        break;
+      case DIRECTIVE_VERSION:
+        parseVersion(token);
+        break;
+      case DIRECTIVE_LINE:
+        parseLine(token);
+        break;
+      default:
+        assert(false);
+        break;
+    }
+
+    skipUntilEOD(mTokenizer, token);
+    if (token->type == Token::LAST)
+    {
+        mDiagnostics->report(Diagnostics::EOF_IN_DIRECTIVE,
+                             token->location, token->text);
+    }
+}
+
+void DirectiveParser::parseDefine(Token* token)
+{
+    assert(getDirective(token) == DIRECTIVE_DEFINE);
+
+    mTokenizer->lex(token);
+    if (token->type != Token::IDENTIFIER)
+    {
+        mDiagnostics->report(Diagnostics::UNEXPECTED_TOKEN,
+                             token->location, token->text);
+        return;
+    }
+    if (isMacroPredefined(token->text, *mMacroSet))
+    {
+        mDiagnostics->report(Diagnostics::MACRO_PREDEFINED_REDEFINED,
+                             token->location, token->text);
+        return;
+    }
+    if (isMacroNameReserved(token->text))
+    {
+        mDiagnostics->report(Diagnostics::MACRO_NAME_RESERVED,
+                             token->location, token->text);
+        return;
+    }
+
+    Macro macro;
+    macro.type = Macro::kTypeObj;
+    macro.name = token->text;
+
+    mTokenizer->lex(token);
+    if (token->type == '(' && !token->hasLeadingSpace())
+    {
+        // Function-like macro. Collect arguments.
+        macro.type = Macro::kTypeFunc;
+        do {
+            mTokenizer->lex(token);
+            if (token->type != Token::IDENTIFIER)
+                break;
+            macro.parameters.push_back(token->text);
+
+            mTokenizer->lex(token);  // Get ','.
+        } while (token->type == ',');
+
+        if (token->type != ')')
+        {
+            mDiagnostics->report(Diagnostics::UNEXPECTED_TOKEN,
+                                 token->location,
+                                 token->text);
+            return;
+        }
+        mTokenizer->lex(token);  // Get ')'.
+    }
+
+    while ((token->type != '\n') && (token->type != Token::LAST))
+    {
+        // Reset the token location because it is unnecessary in replacement
+        // list. Resetting it also allows us to reuse Token::equals() to
+        // compare macros.
+        token->location = SourceLocation();
+        macro.replacements.push_back(*token);
+        mTokenizer->lex(token);
+    }
+    if (!macro.replacements.empty())
+    {
+        // Whitespace preceding the replacement list is not considered part of
+        // the replacement list for either form of macro.
+        macro.replacements.front().setHasLeadingSpace(false);
+    }
+
+    // Check for macro redefinition.
+    MacroSet::const_iterator iter = mMacroSet->find(macro.name);
+    if (iter != mMacroSet->end() && !macro.equals(iter->second))
+    {
+        mDiagnostics->report(Diagnostics::MACRO_REDEFINED,
+                             token->location,
+                             macro.name);
+        return;
+    }
+    mMacroSet->insert(std::make_pair(macro.name, macro));
+}
+
+void DirectiveParser::parseUndef(Token* token)
+{
+    assert(getDirective(token) == DIRECTIVE_UNDEF);
+
+    mTokenizer->lex(token);
+    if (token->type != Token::IDENTIFIER)
+    {
+        mDiagnostics->report(Diagnostics::UNEXPECTED_TOKEN,
+                             token->location, token->text);
+        return;
+    }
+
+    MacroSet::iterator iter = mMacroSet->find(token->text);
+    if (iter != mMacroSet->end())
+    {
+        if (iter->second.predefined)
+        {
+            mDiagnostics->report(Diagnostics::MACRO_PREDEFINED_UNDEFINED,
+                                 token->location, token->text);
+        }
+        else
+        {
+            mMacroSet->erase(iter);
+        }
+    }
+
+    mTokenizer->lex(token);
+}
+
+void DirectiveParser::parseIf(Token* token)
+{
+    assert(getDirective(token) == DIRECTIVE_IF);
+    parseConditionalIf(token);
+}
+
+void DirectiveParser::parseIfdef(Token* token)
+{
+    assert(getDirective(token) == DIRECTIVE_IFDEF);
+    parseConditionalIf(token);
+}
+
+void DirectiveParser::parseIfndef(Token* token)
+{
+    assert(getDirective(token) == DIRECTIVE_IFNDEF);
+    parseConditionalIf(token);
+}
+
+void DirectiveParser::parseElse(Token* token)
+{
+    assert(getDirective(token) == DIRECTIVE_ELSE);
+
+    if (mConditionalStack.empty())
+    {
+        mDiagnostics->report(Diagnostics::CONDITIONAL_ELSE_WITHOUT_IF,
+                             token->location, token->text);
+        skipUntilEOD(mTokenizer, token);
+        return;
+    }
+
+    ConditionalBlock& block = mConditionalStack.back();
+    if (block.skipBlock)
+    {
+        // No diagnostics. Just skip the whole line.
+        skipUntilEOD(mTokenizer, token);
+        return;
+    }
+    if (block.foundElseGroup)
+    {
+        mDiagnostics->report(Diagnostics::CONDITIONAL_ELSE_AFTER_ELSE,
+                             token->location, token->text);
+        skipUntilEOD(mTokenizer, token);
+        return;
+    }
+
+    block.foundElseGroup = true;
+    block.skipGroup = block.foundValidGroup;
+    block.foundValidGroup = true;
+
+    // Warn if there are extra tokens after #else.
+    mTokenizer->lex(token);
+    if (!isEOD(token))
+    {
+        mDiagnostics->report(Diagnostics::CONDITIONAL_UNEXPECTED_TOKEN,
+                             token->location, token->text);
+        skipUntilEOD(mTokenizer, token);
+    }
+}
+
+void DirectiveParser::parseElif(Token* token)
+{
+    assert(getDirective(token) == DIRECTIVE_ELIF);
+
+    if (mConditionalStack.empty())
+    {
+        mDiagnostics->report(Diagnostics::CONDITIONAL_ELIF_WITHOUT_IF,
+                             token->location, token->text);
+        skipUntilEOD(mTokenizer, token);
+        return;
+    }
+
+    ConditionalBlock& block = mConditionalStack.back();
+    if (block.skipBlock)
+    {
+        // No diagnostics. Just skip the whole line.
+        skipUntilEOD(mTokenizer, token);
+        return;
+    }
+    if (block.foundElseGroup)
+    {
+        mDiagnostics->report(Diagnostics::CONDITIONAL_ELIF_AFTER_ELSE,
+                             token->location, token->text);
+        skipUntilEOD(mTokenizer, token);
+        return;
+    }
+    if (block.foundValidGroup)
+    {
+        // Do not parse the expression.
+        // Also be careful not to emit a diagnostic.
+        block.skipGroup = true;
+        skipUntilEOD(mTokenizer, token);
+        return;
+    }
+
+    int expression = parseExpressionIf(token);
+    block.skipGroup = expression == 0;
+    block.foundValidGroup = expression != 0;
+}
+
+void DirectiveParser::parseEndif(Token* token)
+{
+    assert(getDirective(token) == DIRECTIVE_ENDIF);
+
+    if (mConditionalStack.empty())
+    {
+        mDiagnostics->report(Diagnostics::CONDITIONAL_ENDIF_WITHOUT_IF,
+                             token->location, token->text);
+        skipUntilEOD(mTokenizer, token);
+        return;
+    }
+
+    mConditionalStack.pop_back();
+
+    // Warn if there are tokens after #endif.
+    mTokenizer->lex(token);
+    if (!isEOD(token))
+    {
+        mDiagnostics->report(Diagnostics::CONDITIONAL_UNEXPECTED_TOKEN,
+                             token->location, token->text);
+        skipUntilEOD(mTokenizer, token);
+    }
+}
+
+void DirectiveParser::parseError(Token* token)
+{
+    assert(getDirective(token) == DIRECTIVE_ERROR);
+
+    std::ostringstream stream;
+    mTokenizer->lex(token);
+    while ((token->type != '\n') && (token->type != Token::LAST))
+    {
+        stream << *token;
+        mTokenizer->lex(token);
+    }
+    mDirectiveHandler->handleError(token->location, stream.str());
+}
+
+// Parses pragma of form: #pragma name[(value)].
+void DirectiveParser::parsePragma(Token* token)
+{
+    assert(getDirective(token) == DIRECTIVE_PRAGMA);
+
+    enum State
+    {
+        PRAGMA_NAME,
+        LEFT_PAREN,
+        PRAGMA_VALUE,
+        RIGHT_PAREN
+    };
+
+    bool valid = true;
+    std::string name, value;
+    int state = PRAGMA_NAME;
+
+    mTokenizer->lex(token);
+    while ((token->type != '\n') && (token->type != Token::LAST))
+    {
+        switch(state++)
+        {
+          case PRAGMA_NAME:
+            name = token->text;
+            valid = valid && (token->type == Token::IDENTIFIER);
+            break;
+          case LEFT_PAREN:
+            valid = valid && (token->type == '(');
+            break;
+          case PRAGMA_VALUE:
+            value = token->text;
+            valid = valid && (token->type == Token::IDENTIFIER);
+            break;
+          case RIGHT_PAREN:
+            valid = valid && (token->type == ')');
+            break;
+          default:
+            valid = false;
+            break;
+        }
+        mTokenizer->lex(token);
+    }
+
+    valid = valid && ((state == PRAGMA_NAME) ||     // Empty pragma.
+                      (state == LEFT_PAREN) ||      // Without value.
+                      (state == RIGHT_PAREN + 1));  // With value.
+    if (!valid)
+    {
+        mDiagnostics->report(Diagnostics::UNRECOGNIZED_PRAGMA,
+                             token->location, name);
+    }
+    else if (state > PRAGMA_NAME)  // Do not notify for empty pragma.
+    {
+        mDirectiveHandler->handlePragma(token->location, name, value);
+    }
+}
+
+void DirectiveParser::parseExtension(Token* token)
+{
+    assert(getDirective(token) == DIRECTIVE_EXTENSION);
+
+    enum State
+    {
+        EXT_NAME,
+        COLON,
+        EXT_BEHAVIOR
+    };
+
+    bool valid = true;
+    std::string name, behavior;
+    int state = EXT_NAME;
+
+    mTokenizer->lex(token);
+    while ((token->type != '\n') && (token->type != Token::LAST))
+    {
+        switch (state++)
+        {
+          case EXT_NAME:
+            if (valid && (token->type != Token::IDENTIFIER))
+            {
+                mDiagnostics->report(Diagnostics::INVALID_EXTENSION_NAME,
+                                     token->location, token->text);
+                valid = false;
+            }
+            if (valid) name = token->text;
+            break;
+          case COLON:
+            if (valid && (token->type != ':'))
+            {
+                mDiagnostics->report(Diagnostics::UNEXPECTED_TOKEN,
+                                     token->location, token->text);
+                valid = false;
+            }
+            break;
+          case EXT_BEHAVIOR:
+            if (valid && (token->type != Token::IDENTIFIER))
+            {
+                mDiagnostics->report(Diagnostics::INVALID_EXTENSION_BEHAVIOR,
+                                     token->location, token->text);
+                valid = false;
+            }
+            if (valid) behavior = token->text;
+            break;
+          default:
+            if (valid)
+            {
+                mDiagnostics->report(Diagnostics::UNEXPECTED_TOKEN,
+                                     token->location, token->text);
+                valid = false;
+            }
+            break;
+        }
+        mTokenizer->lex(token);
+    }
+    if (valid && (state != EXT_BEHAVIOR + 1))
+    {
+        mDiagnostics->report(Diagnostics::INVALID_EXTENSION_DIRECTIVE,
+                             token->location, token->text);
+        valid = false;
+    }
+    if (valid)
+        mDirectiveHandler->handleExtension(token->location, name, behavior);
+}
+
+void DirectiveParser::parseVersion(Token* token)
+{
+    assert(getDirective(token) == DIRECTIVE_VERSION);
+
+    if (mPastFirstStatement)
+    {
+        mDiagnostics->report(Diagnostics::VERSION_NOT_FIRST_STATEMENT,
+                             token->location, token->text);
+        skipUntilEOD(mTokenizer, token);
+        return;
+    }
+
+    enum State
+    {
+        VERSION_NUMBER
+    };
+
+    bool valid = true;
+    int version = 0;
+    int state = VERSION_NUMBER;
+
+    mTokenizer->lex(token);
+    while ((token->type != '\n') && (token->type != Token::LAST))
+    {
+        switch (state++)
+        {
+          case VERSION_NUMBER:
+            if (valid && (token->type != Token::CONST_INT))
+            {
+                mDiagnostics->report(Diagnostics::INVALID_VERSION_NUMBER,
+                                     token->location, token->text);
+                valid = false;
+            }
+            if (valid && !token->iValue(&version))
+            {
+                mDiagnostics->report(Diagnostics::INTEGER_OVERFLOW,
+                                     token->location, token->text);
+                valid = false;
+            }
+            break;
+          default:
+            if (valid)
+            {
+                mDiagnostics->report(Diagnostics::UNEXPECTED_TOKEN,
+                                     token->location, token->text);
+                valid = false;
+            }
+            break;
+        }
+        mTokenizer->lex(token);
+    }
+    if (valid && (state != VERSION_NUMBER + 1))
+    {
+        mDiagnostics->report(Diagnostics::INVALID_VERSION_DIRECTIVE,
+                             token->location, token->text);
+        valid = false;
+    }
+    if (valid)
+        mDirectiveHandler->handleVersion(token->location, version);
+}
+
+void DirectiveParser::parseLine(Token* token)
+{
+    assert(getDirective(token) == DIRECTIVE_LINE);
+
+    enum State
+    {
+        LINE_NUMBER,
+        FILE_NUMBER
+    };
+
+    bool valid = true;
+    int line = 0, file = 0;
+    int state = LINE_NUMBER;
+
+    MacroExpander macroExpander(mTokenizer, mMacroSet, mDiagnostics);
+    macroExpander.lex(token);
+    while ((token->type != '\n') && (token->type != Token::LAST))
+    {
+        switch (state++)
+        {
+          case LINE_NUMBER:
+            if (valid && (token->type != Token::CONST_INT))
+            {
+                mDiagnostics->report(Diagnostics::INVALID_LINE_NUMBER,
+                                     token->location, token->text);
+                valid = false;
+            }
+            if (valid && !token->iValue(&line))
+            {
+                mDiagnostics->report(Diagnostics::INTEGER_OVERFLOW,
+                                     token->location, token->text);
+                valid = false;
+            }
+            break;
+          case FILE_NUMBER:
+            if (valid && (token->type != Token::CONST_INT))
+            {
+                mDiagnostics->report(Diagnostics::INVALID_FILE_NUMBER,
+                                     token->location, token->text);
+                valid = false;
+            }
+            if (valid && !token->iValue(&file))
+            {
+                mDiagnostics->report(Diagnostics::INTEGER_OVERFLOW,
+                                     token->location, token->text);
+                valid = false;
+            }
+            break;
+          default:
+            if (valid)
+            {
+                mDiagnostics->report(Diagnostics::UNEXPECTED_TOKEN,
+                                     token->location, token->text);
+                valid = false;
+            }
+            break;
+        }
+        macroExpander.lex(token);
+    }
+
+    if (valid && (state != FILE_NUMBER) && (state != FILE_NUMBER + 1))
+    {
+        mDiagnostics->report(Diagnostics::INVALID_LINE_DIRECTIVE,
+                             token->location, token->text);
+        valid = false;
+    }
+    if (valid)
+    {
+        mTokenizer->setLineNumber(line);
+        if (state == FILE_NUMBER + 1) mTokenizer->setFileNumber(file);
+    }
+}
+
+bool DirectiveParser::skipping() const
+{
+    if (mConditionalStack.empty()) return false;
+
+    const ConditionalBlock& block = mConditionalStack.back();
+    return block.skipBlock || block.skipGroup;
+}
+
+void DirectiveParser::parseConditionalIf(Token* token)
+{
+    ConditionalBlock block;
+    block.type = token->text;
+    block.location = token->location;
+
+    if (skipping())
+    {
+        // This conditional block is inside another conditional group
+        // which is skipped. As a consequence this whole block is skipped.
+        // Be careful not to parse the conditional expression that might
+        // emit a diagnostic.
+        skipUntilEOD(mTokenizer, token);
+        block.skipBlock = true;
+    }
+    else
+    {
+        DirectiveType directive = getDirective(token);
+
+        int expression = 0;
+        switch (directive)
+        {
+          case DIRECTIVE_IF:
+            expression = parseExpressionIf(token);
+            break;
+          case DIRECTIVE_IFDEF:
+            expression = parseExpressionIfdef(token);
+            break;
+          case DIRECTIVE_IFNDEF:
+            expression = parseExpressionIfdef(token) == 0 ? 1 : 0;
+            break;
+          default:
+            assert(false);
+            break;
+        }
+        block.skipGroup = expression == 0;
+        block.foundValidGroup = expression != 0;
+    }
+    mConditionalStack.push_back(block);
+}
+
+int DirectiveParser::parseExpressionIf(Token* token)
+{
+    assert((getDirective(token) == DIRECTIVE_IF) ||
+           (getDirective(token) == DIRECTIVE_ELIF));
+
+    DefinedParser definedParser(mTokenizer, mMacroSet, mDiagnostics);
+    MacroExpander macroExpander(&definedParser, mMacroSet, mDiagnostics);
+    ExpressionParser expressionParser(&macroExpander, mDiagnostics);
+
+    int expression = 0;
+    macroExpander.lex(token);
+    expressionParser.parse(token, &expression);
+
+    // Warn if there are tokens after #if expression.
+    if (!isEOD(token))
+    {
+        mDiagnostics->report(Diagnostics::CONDITIONAL_UNEXPECTED_TOKEN,
+                             token->location, token->text);
+        skipUntilEOD(mTokenizer, token);
+    }
+
+    return expression;
+}
+
+int DirectiveParser::parseExpressionIfdef(Token* token)
+{
+    assert((getDirective(token) == DIRECTIVE_IFDEF) ||
+           (getDirective(token) == DIRECTIVE_IFNDEF));
+
+    mTokenizer->lex(token);
+    if (token->type != Token::IDENTIFIER)
+    {
+        mDiagnostics->report(Diagnostics::UNEXPECTED_TOKEN,
+                             token->location, token->text);
+        skipUntilEOD(mTokenizer, token);
+        return 0;
+    }
+
+    MacroSet::const_iterator iter = mMacroSet->find(token->text);
+    int expression = iter != mMacroSet->end() ? 1 : 0;
+
+    // Warn if there are tokens after #ifdef expression.
+    mTokenizer->lex(token);
+    if (!isEOD(token))
+    {
+        mDiagnostics->report(Diagnostics::CONDITIONAL_UNEXPECTED_TOKEN,
+                             token->location, token->text);
+        skipUntilEOD(mTokenizer, token);
+    }
+    return expression;
+}
+
+}  // namespace pp
diff --git a/src/3rdparty/angle/src/compiler/preprocessor/new/DirectiveParser.h b/src/3rdparty/angle/src/compiler/preprocessor/new/DirectiveParser.h
new file mode 100644 (file)
index 0000000..8a7f007
--- /dev/null
@@ -0,0 +1,82 @@
+//
+// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#ifndef COMPILER_PREPROCESSOR_DIRECTIVE_PARSER_H_
+#define COMPILER_PREPROCESSOR_DIRECTIVE_PARSER_H_
+
+#include "Lexer.h"
+#include "Macro.h"
+#include "pp_utils.h"
+#include "SourceLocation.h"
+
+namespace pp
+{
+
+class Diagnostics;
+class DirectiveHandler;
+class Tokenizer;
+
+class DirectiveParser : public Lexer
+{
+  public:
+    DirectiveParser(Tokenizer* tokenizer,
+                    MacroSet* macroSet,
+                    Diagnostics* diagnostics,
+                    DirectiveHandler* directiveHandler);
+
+    virtual void lex(Token* token);
+
+  private:
+    PP_DISALLOW_COPY_AND_ASSIGN(DirectiveParser);
+
+    void parseDirective(Token* token);
+    void parseDefine(Token* token);
+    void parseUndef(Token* token);
+    void parseIf(Token* token);
+    void parseIfdef(Token* token);
+    void parseIfndef(Token* token);
+    void parseElse(Token* token);
+    void parseElif(Token* token);
+    void parseEndif(Token* token);
+    void parseError(Token* token);
+    void parsePragma(Token* token);
+    void parseExtension(Token* token);
+    void parseVersion(Token* token);
+    void parseLine(Token* token);
+
+    bool skipping() const;
+    void parseConditionalIf(Token* token);
+    int parseExpressionIf(Token* token);
+    int parseExpressionIfdef(Token* token);
+
+    struct ConditionalBlock
+    {
+        std::string type;
+        SourceLocation location;
+        bool skipBlock;
+        bool skipGroup;
+        bool foundValidGroup;
+        bool foundElseGroup;
+
+        ConditionalBlock() :
+            skipBlock(false),
+            skipGroup(false),
+            foundValidGroup(false),
+            foundElseGroup(false)
+        {
+        }
+    };
+    bool mPastFirstStatement;
+    std::vector<ConditionalBlock> mConditionalStack;
+    Tokenizer* mTokenizer;
+    MacroSet* mMacroSet;
+    Diagnostics* mDiagnostics;
+    DirectiveHandler* mDirectiveHandler;
+};
+
+}  // namespace pp
+#endif  // COMPILER_PREPROCESSOR_DIRECTIVE_PARSER_H_
+
diff --git a/src/3rdparty/angle/src/compiler/preprocessor/new/ExpressionParser.h b/src/3rdparty/angle/src/compiler/preprocessor/new/ExpressionParser.h
new file mode 100644 (file)
index 0000000..092d059
--- /dev/null
@@ -0,0 +1,34 @@
+//
+// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#ifndef COMPILER_PREPROCESSOR_EXPRESSION_PARSER_H_
+#define COMPILER_PREPROCESSOR_EXPRESSION_PARSER_H_
+
+#include "pp_utils.h"
+
+namespace pp
+{
+
+class Diagnostics;
+class Lexer;
+struct Token;
+
+class ExpressionParser
+{
+  public:
+    ExpressionParser(Lexer* lexer, Diagnostics* diagnostics);
+
+    bool parse(Token* token, int* result);
+
+  private:
+    PP_DISALLOW_COPY_AND_ASSIGN(ExpressionParser);
+
+    Lexer* mLexer;
+    Diagnostics* mDiagnostics;
+};
+
+}  // namespace pp
+#endif  // COMPILER_PREPROCESSOR_EXPRESSION_PARSER_H_
diff --git a/src/3rdparty/angle/src/compiler/preprocessor/new/ExpressionParser.y b/src/3rdparty/angle/src/compiler/preprocessor/new/ExpressionParser.y
new file mode 100644 (file)
index 0000000..832ad40
--- /dev/null
@@ -0,0 +1,279 @@
+/*
+//
+// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+This file contains the Yacc grammar for GLSL ES preprocessor expression.
+
+IF YOU MODIFY THIS FILE YOU ALSO NEED TO RUN generate_parser.sh,
+WHICH GENERATES THE GLSL ES preprocessor expression parser.
+*/
+
+%{
+//
+// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// This file is auto-generated by generate_parser.sh. DO NOT EDIT!
+
+#if defined(__GNUC__)
+// Triggered by the auto-generated pplval variable.
+#pragma GCC diagnostic ignored "-Wuninitialized"
+#elif defined(_MSC_VER)
+#pragma warning(disable: 4065 4701)
+#endif
+
+#include "ExpressionParser.h"
+
+#include <cassert>
+#include <sstream>
+
+#include "Diagnostics.h"
+#include "Lexer.h"
+#include "Token.h"
+
+#if defined(_MSC_VER)
+typedef __int64 YYSTYPE;
+#else
+#include <stdint.h>
+typedef intmax_t YYSTYPE;
+#endif  // _MSC_VER
+#define YYSTYPE_IS_TRIVIAL 1
+#define YYSTYPE_IS_DECLARED 1
+
+namespace {
+struct Context
+{
+    pp::Diagnostics* diagnostics;
+    pp::Lexer* lexer;
+    pp::Token* token;
+    int* result;
+};
+}  // namespace
+%}
+
+%pure-parser
+%name-prefix="pp"
+%parse-param {Context *context}
+%lex-param {Context *context}
+
+%{
+static int yylex(YYSTYPE* lvalp, Context* context);
+static void yyerror(Context* context, const char* reason);
+%}
+
+%token TOK_CONST_INT
+%left TOK_OP_OR
+%left TOK_OP_AND
+%left '|'
+%left '^'
+%left '&'
+%left TOK_OP_EQ TOK_OP_NE
+%left '<' '>' TOK_OP_LE TOK_OP_GE
+%left TOK_OP_LEFT TOK_OP_RIGHT
+%left '+' '-'
+%left '*' '/' '%'
+%right TOK_UNARY
+
+%%
+
+input
+    : expression {
+        *(context->result) = static_cast<int>($1);
+        YYACCEPT;
+    }
+;
+
+expression
+    : TOK_CONST_INT
+    | expression TOK_OP_OR expression {
+        $$ = $1 || $3;
+    }
+    | expression TOK_OP_AND expression {
+        $$ = $1 && $3;
+    }
+    | expression '|' expression {
+        $$ = $1 | $3;
+    }
+    | expression '^' expression {
+        $$ = $1 ^ $3;
+    }
+    | expression '&' expression {
+        $$ = $1 & $3;
+    }
+    | expression TOK_OP_NE expression {
+        $$ = $1 != $3;
+    }
+    | expression TOK_OP_EQ expression {
+        $$ = $1 == $3;
+    }
+    | expression TOK_OP_GE expression {
+        $$ = $1 >= $3;
+    }
+    | expression TOK_OP_LE expression {
+        $$ = $1 <= $3;
+    }
+    | expression '>' expression {
+        $$ = $1 > $3;
+    }
+    | expression '<' expression {
+        $$ = $1 < $3;
+    }
+    | expression TOK_OP_RIGHT expression {
+        $$ = $1 >> $3;
+    }
+    | expression TOK_OP_LEFT expression {
+        $$ = $1 << $3;
+    }
+    | expression '-' expression {
+        $$ = $1 - $3;
+    }
+    | expression '+' expression {
+        $$ = $1 + $3;
+    }
+    | expression '%' expression {
+        if ($3 == 0) {
+            std::ostringstream stream;
+            stream << $1 << " % " << $3;
+            std::string text = stream.str();
+            context->diagnostics->report(pp::Diagnostics::DIVISION_BY_ZERO,
+                                         context->token->location,
+                                         text.c_str());
+            YYABORT;
+        } else {
+            $$ = $1 % $3;
+        }
+    }
+    | expression '/' expression {
+        if ($3 == 0) {
+            std::ostringstream stream;
+            stream << $1 << " / " << $3;
+            std::string text = stream.str();
+            context->diagnostics->report(pp::Diagnostics::DIVISION_BY_ZERO,
+                                         context->token->location,
+                                         text.c_str());
+            YYABORT;
+        } else {
+            $$ = $1 / $3;
+        }
+    }
+    | expression '*' expression {
+        $$ = $1 * $3;
+    }
+    | '!' expression %prec TOK_UNARY {
+        $$ = ! $2;
+    }
+    | '~' expression %prec TOK_UNARY {
+        $$ = ~ $2;
+    }
+    | '-' expression %prec TOK_UNARY {
+        $$ = - $2;
+    }
+    | '+' expression %prec TOK_UNARY {
+        $$ = + $2;
+    }
+    | '(' expression ')' {
+        $$ = $2;
+    }
+;
+
+%%
+
+int yylex(YYSTYPE* lvalp, Context* context)
+{
+    int type = 0;
+
+    pp::Token* token = context->token;
+    switch (token->type)
+    {
+      case pp::Token::CONST_INT:
+      {
+        unsigned int val = 0;
+        if (!token->uValue(&val))
+        {
+            context->diagnostics->report(pp::Diagnostics::INTEGER_OVERFLOW,
+                                         token->location, token->text);
+        }
+        *lvalp = static_cast<YYSTYPE>(val);
+        type = TOK_CONST_INT;
+        break;
+      }
+      case pp::Token::OP_OR: type = TOK_OP_OR; break;
+      case pp::Token::OP_AND: type = TOK_OP_AND; break;
+      case pp::Token::OP_NE: type = TOK_OP_NE; break;
+      case pp::Token::OP_EQ: type = TOK_OP_EQ; break;
+      case pp::Token::OP_GE: type = TOK_OP_GE; break;
+      case pp::Token::OP_LE: type = TOK_OP_LE; break;
+      case pp::Token::OP_RIGHT: type = TOK_OP_RIGHT; break;
+      case pp::Token::OP_LEFT: type = TOK_OP_LEFT; break;
+      case '|': type = '|'; break;
+      case '^': type = '^'; break;
+      case '&': type = '&'; break;
+      case '>': type = '>'; break;
+      case '<': type = '<'; break;
+      case '-': type = '-'; break;
+      case '+': type = '+'; break;
+      case '%': type = '%'; break;
+      case '/': type = '/'; break;
+      case '*': type = '*'; break;
+      case '!': type = '!'; break;
+      case '~': type = '~'; break;
+      case '(': type = '('; break;
+      case ')': type = ')'; break;
+
+      default: break;
+    }
+
+    // Advance to the next token if the current one is valid.
+    if (type != 0) context->lexer->lex(token);
+
+    return type;
+}
+
+void yyerror(Context* context, const char* reason)
+{
+    context->diagnostics->report(pp::Diagnostics::INVALID_EXPRESSION,
+                                 context->token->location,
+                                 reason);
+}
+
+namespace pp {
+
+ExpressionParser::ExpressionParser(Lexer* lexer, Diagnostics* diagnostics) :
+    mLexer(lexer),
+    mDiagnostics(diagnostics)
+{
+}
+
+bool ExpressionParser::parse(Token* token, int* result)
+{
+    Context context;
+    context.diagnostics = mDiagnostics;
+    context.lexer = mLexer;
+    context.token = token;
+    context.result = result;
+    int ret = yyparse(&context);
+    switch (ret)
+    {
+      case 0:
+      case 1:
+        break;
+
+      case 2:
+        mDiagnostics->report(Diagnostics::OUT_OF_MEMORY, token->location, "");
+        break;
+
+      default:
+        assert(false);
+        mDiagnostics->report(Diagnostics::INTERNAL_ERROR, token->location, "");
+        break;
+    }
+
+    return ret == 0;
+}
+
+}  // namespace pp
diff --git a/src/3rdparty/angle/src/compiler/preprocessor/new/Input.cpp b/src/3rdparty/angle/src/compiler/preprocessor/new/Input.cpp
new file mode 100644 (file)
index 0000000..c3de95f
--- /dev/null
@@ -0,0 +1,55 @@
+//
+// Copyright (c) 2011 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "Input.h"
+
+#include <algorithm>
+#include <cassert>
+#include <cstring>
+
+namespace pp
+{
+
+Input::Input() : mCount(0), mString(0)
+{
+}
+
+Input::Input(int count, const char* const string[], const int length[]) :
+    mCount(count),
+    mString(string)
+{
+    assert(mCount >= 0);
+    mLength.reserve(mCount);
+    for (int i = 0; i < mCount; ++i)
+    {
+        int len = length ? length[i] : -1;
+        mLength.push_back(len < 0 ? strlen(mString[i]) : len);
+    }
+}
+
+int Input::read(char* buf, int maxSize)
+{
+    int nRead = 0;
+    while ((nRead < maxSize) && (mReadLoc.sIndex < mCount))
+    {
+        int size = mLength[mReadLoc.sIndex] - mReadLoc.cIndex;
+        size = std::min(size, maxSize);
+        memcpy(buf + nRead, mString[mReadLoc.sIndex] + mReadLoc.cIndex, size);
+        nRead += size;
+        mReadLoc.cIndex += size;
+
+        // Advance string if we reached the end of current string.
+        if (mReadLoc.cIndex == mLength[mReadLoc.sIndex])
+        {
+            ++mReadLoc.sIndex;
+            mReadLoc.cIndex = 0;
+        }
+    }
+    return nRead;
+}
+
+}  // namespace pp
+
diff --git a/src/3rdparty/angle/src/compiler/preprocessor/new/Input.h b/src/3rdparty/angle/src/compiler/preprocessor/new/Input.h
new file mode 100644 (file)
index 0000000..dac734b
--- /dev/null
@@ -0,0 +1,48 @@
+//
+// Copyright (c) 2011 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#ifndef COMPILER_PREPROCESSOR_INPUT_H_
+#define COMPILER_PREPROCESSOR_INPUT_H_
+
+#include <vector>
+
+namespace pp
+{
+
+// Holds and reads input for Lexer.
+class Input
+{
+  public:
+    Input();
+    Input(int count, const char* const string[], const int length[]);
+
+    int count() const { return mCount; }
+    const char* string(int index) const { return mString[index]; }
+    int length(int index) const { return mLength[index]; }
+
+    int read(char* buf, int maxSize);
+
+    struct Location
+    {
+        int sIndex;  // String index;
+        int cIndex;  // Char index.
+
+        Location() : sIndex(0), cIndex(0) { }
+    };
+    const Location& readLoc() const { return mReadLoc; }
+
+  private:
+    // Input.
+    int mCount;
+    const char* const* mString;
+    std::vector<int> mLength;
+
+    Location mReadLoc;
+};
+
+}  // namespace pp
+#endif  // COMPILER_PREPROCESSOR_INPUT_H_
+
diff --git a/src/3rdparty/angle/src/compiler/preprocessor/new/Lexer.cpp b/src/3rdparty/angle/src/compiler/preprocessor/new/Lexer.cpp
new file mode 100644 (file)
index 0000000..7c663ee
--- /dev/null
@@ -0,0 +1,16 @@
+//
+// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "Lexer.h"
+
+namespace pp
+{
+
+Lexer::~Lexer()
+{
+}
+
+}  // namespace pp
diff --git a/src/3rdparty/angle/src/compiler/preprocessor/new/Lexer.h b/src/3rdparty/angle/src/compiler/preprocessor/new/Lexer.h
new file mode 100644 (file)
index 0000000..eb85cea
--- /dev/null
@@ -0,0 +1,25 @@
+//
+// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#ifndef COMPILER_PREPROCESSOR_LEXER_H_
+#define COMPILER_PREPROCESSOR_LEXER_H_
+
+namespace pp
+{
+
+struct Token;
+
+class Lexer
+{
+  public:
+    virtual ~Lexer();
+
+    virtual void lex(Token* token) = 0;
+};
+
+}  // namespace pp
+#endif  // COMPILER_PREPROCESSOR_LEXER_H_
+
diff --git a/src/3rdparty/angle/src/compiler/preprocessor/new/Macro.cpp b/src/3rdparty/angle/src/compiler/preprocessor/new/Macro.cpp
new file mode 100644 (file)
index 0000000..b2e3088
--- /dev/null
@@ -0,0 +1,23 @@
+//
+// Copyright (c) 2011 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "Macro.h"
+
+#include "Token.h"
+
+namespace pp
+{
+
+bool Macro::equals(const Macro& other) const
+{
+    return (type == other.type) &&
+           (name == other.name) &&
+           (parameters == other.parameters) &&
+           (replacements == other.replacements);
+}
+
+}  // namespace pp
+
diff --git a/src/3rdparty/angle/src/compiler/preprocessor/new/Macro.h b/src/3rdparty/angle/src/compiler/preprocessor/new/Macro.h
new file mode 100644 (file)
index 0000000..7ec0149
--- /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_PREPROCESSOR_MACRO_H_
+#define COMPILER_PREPROCESSOR_MACRO_H_
+
+#include <map>
+#include <string>
+#include <vector>
+
+namespace pp
+{
+
+struct Token;
+
+struct Macro
+{
+    enum Type
+    {
+        kTypeObj,
+        kTypeFunc
+    };
+    typedef std::vector<std::string> Parameters;
+    typedef std::vector<Token> Replacements;
+
+    Macro() : predefined(false), disabled(false), type(kTypeObj) { }
+    bool equals(const Macro& other) const;
+
+    bool predefined;
+    mutable bool disabled;
+
+    Type type;
+    std::string name;
+    Parameters parameters;
+    Replacements replacements;
+};
+
+typedef std::map<std::string, Macro> MacroSet;
+
+}  // namespace pp
+#endif  // COMPILER_PREPROCESSOR_MACRO_H_
diff --git a/src/3rdparty/angle/src/compiler/preprocessor/new/MacroExpander.cpp b/src/3rdparty/angle/src/compiler/preprocessor/new/MacroExpander.cpp
new file mode 100644 (file)
index 0000000..701cec9
--- /dev/null
@@ -0,0 +1,370 @@
+//
+// Copyright (c) 2011 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "MacroExpander.h"
+
+#include <algorithm>
+#include <sstream>
+
+#include "Diagnostics.h"
+#include "Token.h"
+
+namespace pp
+{
+
+class TokenLexer : public Lexer
+{
+ public:
+    typedef std::vector<Token> TokenVector;
+
+    TokenLexer(TokenVector* tokens)
+    {
+        tokens->swap(mTokens);
+        mIter = mTokens.begin();
+    }
+
+    virtual void lex(Token* token)
+    {
+        if (mIter == mTokens.end())
+        {
+            token->reset();
+            token->type = Token::LAST;
+        }
+        else
+        {
+            *token = *mIter++;
+        }
+    }
+
+ private:
+    PP_DISALLOW_COPY_AND_ASSIGN(TokenLexer);
+
+    TokenVector mTokens;
+    TokenVector::const_iterator mIter;
+};
+
+MacroExpander::MacroExpander(Lexer* lexer,
+                             MacroSet* macroSet,
+                             Diagnostics* diagnostics) :
+    mLexer(lexer),
+    mMacroSet(macroSet),
+    mDiagnostics(diagnostics)
+{
+}
+
+MacroExpander::~MacroExpander()
+{
+    for (size_t i = 0; i < mContextStack.size(); ++i)
+    {
+        delete mContextStack[i];
+    }
+}
+
+void MacroExpander::lex(Token* token)
+{
+    while (true)
+    {
+        getToken(token);
+
+        if (token->type != Token::IDENTIFIER)
+            break;
+
+        if (token->expansionDisabled())
+            break;
+
+        MacroSet::const_iterator iter = mMacroSet->find(token->text);
+        if (iter == mMacroSet->end())
+            break;
+
+        const Macro& macro = iter->second;
+        if (macro.disabled)
+        {
+            // If a particular token is not expanded, it is never expanded.
+            token->setExpansionDisabled(true);
+            break;
+        }
+        if ((macro.type == Macro::kTypeFunc) && !isNextTokenLeftParen())
+        {
+            // If the token immediately after the macro name is not a '(',
+            // this macro should not be expanded.
+            break;
+        }
+
+        pushMacro(macro, *token);
+    }
+}
+
+void MacroExpander::getToken(Token* token)
+{
+    if (mReserveToken.get())
+    {
+        *token = *mReserveToken;
+        mReserveToken.reset();
+        return;
+    }
+
+    // First pop all empty macro contexts.
+    while (!mContextStack.empty() && mContextStack.back()->empty())
+    {
+        popMacro();
+    }
+
+    if (!mContextStack.empty())
+    {
+        *token = mContextStack.back()->get();
+    }
+    else
+    {
+        mLexer->lex(token);
+    }
+}
+
+void MacroExpander::ungetToken(const Token& token)
+{
+    if (!mContextStack.empty())
+    {
+        MacroContext* context = mContextStack.back();
+        context->unget();
+        assert(context->replacements[context->index] == token);
+    }
+    else
+    {
+        assert(!mReserveToken.get());
+        mReserveToken.reset(new Token(token));
+    }
+}
+
+bool MacroExpander::isNextTokenLeftParen()
+{
+    Token token;
+    getToken(&token);
+
+    bool lparen = token.type == '(';
+    ungetToken(token);
+
+    return lparen;
+}
+
+bool MacroExpander::pushMacro(const Macro& macro, const Token& identifier)
+{
+    assert(!macro.disabled);
+    assert(!identifier.expansionDisabled());
+    assert(identifier.type == Token::IDENTIFIER);
+    assert(identifier.text == macro.name);
+
+    std::vector<Token> replacements;
+    if (!expandMacro(macro, identifier, &replacements))
+        return false;
+
+    // Macro is disabled for expansion until it is popped off the stack.
+    macro.disabled = true;
+
+    MacroContext* context = new MacroContext;
+    context->macro = &macro;
+    context->replacements.swap(replacements);
+    mContextStack.push_back(context);
+    return true;
+}
+
+void MacroExpander::popMacro()
+{
+    assert(!mContextStack.empty());
+
+    MacroContext* context = mContextStack.back();
+    mContextStack.pop_back();
+
+    assert(context->empty());
+    assert(context->macro->disabled);
+    context->macro->disabled = false;
+    delete context;
+}
+
+bool MacroExpander::expandMacro(const Macro& macro,
+                                const Token& identifier,
+                                std::vector<Token>* replacements)
+{
+    replacements->clear();
+    if (macro.type == Macro::kTypeObj)
+    {
+        replacements->assign(macro.replacements.begin(),
+                             macro.replacements.end());
+
+        if (macro.predefined)
+        {
+            static const std::string kLine = "__LINE__";
+            static const std::string kFile = "__FILE__";
+
+            assert(replacements->size() == 1);
+            Token& repl = replacements->front();
+            if (macro.name == kLine)
+            {
+                std::ostringstream stream;
+                stream << identifier.location.line;
+                repl.text = stream.str();
+            }
+            else if (macro.name == kFile)
+            {
+                std::ostringstream stream;
+                stream << identifier.location.file;
+                repl.text = stream.str();
+            }
+        }
+    }
+    else
+    {
+        assert(macro.type == Macro::kTypeFunc);
+        std::vector<MacroArg> args;
+        args.reserve(macro.parameters.size());
+        if (!collectMacroArgs(macro, identifier, &args))
+            return false;
+
+        replaceMacroParams(macro, args, replacements);
+    }
+
+    for (size_t i = 0; i < replacements->size(); ++i)
+    {
+        Token& repl = replacements->at(i);
+        if (i == 0)
+        {
+            // The first token in the replacement list inherits the padding
+            // properties of the identifier token.
+            repl.setAtStartOfLine(identifier.atStartOfLine());
+            repl.setHasLeadingSpace(identifier.hasLeadingSpace());
+        }
+        repl.location = identifier.location;
+    }
+    return true;
+}
+
+bool MacroExpander::collectMacroArgs(const Macro& macro,
+                                     const Token& identifier,
+                                     std::vector<MacroArg>* args)
+{
+    Token token;
+    getToken(&token);
+    assert(token.type == '(');
+
+    args->push_back(MacroArg());
+    for (int openParens = 1; openParens != 0; )
+    {
+        getToken(&token);
+
+        if (token.type == Token::LAST)
+        {
+            mDiagnostics->report(Diagnostics::MACRO_UNTERMINATED_INVOCATION,
+                                 identifier.location, identifier.text);
+            // Do not lose EOF token.
+            ungetToken(token);
+            return false;
+        }
+
+        bool isArg = false; // True if token is part of the current argument.
+        switch (token.type)
+        {
+          case '(':
+            ++openParens;
+            isArg = true;
+            break;
+          case ')':
+            --openParens;
+            isArg = openParens != 0;
+            break;
+          case ',':
+            // The individual arguments are separated by comma tokens, but
+            // the comma tokens between matching inner parentheses do not
+            // seperate arguments.
+            if (openParens == 1) args->push_back(MacroArg());
+            isArg = openParens != 1;
+            break;
+          default:
+            isArg = true;
+            break;
+        }
+        if (isArg)
+        {
+            MacroArg& arg = args->back();
+            // Initial whitespace is not part of the argument.
+            if (arg.empty()) token.setHasLeadingSpace(false);
+            arg.push_back(token);
+        }
+    }
+
+    const Macro::Parameters& params = macro.parameters;
+    // If there is only one empty argument, it is equivalent to no argument.
+    if (params.empty() && (args->size() == 1) && args->front().empty())
+    {
+        args->clear();
+    }
+    // Validate the number of arguments.
+    if (args->size() != params.size())
+    {
+        Diagnostics::ID id = args->size() < macro.parameters.size() ?
+            Diagnostics::MACRO_TOO_FEW_ARGS :
+            Diagnostics::MACRO_TOO_MANY_ARGS;
+        mDiagnostics->report(id, identifier.location, identifier.text);
+        return false;
+    }
+
+    // Pre-expand each argument before substitution.
+    // This step expands each argument individually before they are
+    // inserted into the macro body.
+    for (size_t i = 0; i < args->size(); ++i)
+    {
+        MacroArg& arg = args->at(i);
+        TokenLexer lexer(&arg);
+        MacroExpander expander(&lexer, mMacroSet, mDiagnostics);
+
+        arg.clear();
+        expander.lex(&token);
+        while (token.type != Token::LAST)
+        {
+            arg.push_back(token);
+            expander.lex(&token);
+        }
+    }
+    return true;
+}
+
+void MacroExpander::replaceMacroParams(const Macro& macro,
+                                       const std::vector<MacroArg>& args,
+                                       std::vector<Token>* replacements)
+{
+    for (size_t i = 0; i < macro.replacements.size(); ++i)
+    {
+        const Token& repl = macro.replacements[i];
+        if (repl.type != Token::IDENTIFIER)
+        {
+            replacements->push_back(repl);
+            continue;
+        }
+
+        // TODO(alokp): Optimize this.
+        // There is no need to search for macro params every time.
+        // The param index can be cached with the replacement token.
+        Macro::Parameters::const_iterator iter = std::find(
+            macro.parameters.begin(), macro.parameters.end(), repl.text);
+        if (iter == macro.parameters.end())
+        {
+            replacements->push_back(repl);
+            continue;
+        }
+
+        size_t iArg = std::distance(macro.parameters.begin(), iter);
+        const MacroArg& arg = args[iArg];
+        if (arg.empty())
+        {
+            continue;
+        }
+        size_t iRepl = replacements->size();
+        replacements->insert(replacements->end(), arg.begin(), arg.end());
+        // The replacement token inherits padding properties from
+        // macro replacement token.
+        replacements->at(iRepl).setHasLeadingSpace(repl.hasLeadingSpace());
+    }
+}
+
+}  // namespace pp
+
diff --git a/src/3rdparty/angle/src/compiler/preprocessor/new/MacroExpander.h b/src/3rdparty/angle/src/compiler/preprocessor/new/MacroExpander.h
new file mode 100644 (file)
index 0000000..7c5c543
--- /dev/null
@@ -0,0 +1,75 @@
+//
+// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#ifndef COMPILER_PREPROCESSOR_MACRO_EXPANDER_H_
+#define COMPILER_PREPROCESSOR_MACRO_EXPANDER_H_
+
+#include <cassert>
+#include <memory>
+#include <vector>
+
+#include "Lexer.h"
+#include "Macro.h"
+#include "pp_utils.h"
+
+namespace pp
+{
+
+class Diagnostics;
+
+class MacroExpander : public Lexer
+{
+  public:
+    MacroExpander(Lexer* lexer, MacroSet* macroSet, Diagnostics* diagnostics);
+    virtual ~MacroExpander();
+
+    virtual void lex(Token* token);
+
+  private:
+    PP_DISALLOW_COPY_AND_ASSIGN(MacroExpander);
+
+    void getToken(Token* token);
+    void ungetToken(const Token& token);
+    bool isNextTokenLeftParen();
+
+    bool pushMacro(const Macro& macro, const Token& identifier);
+    void popMacro();
+
+    bool expandMacro(const Macro& macro,
+                     const Token& identifier,
+                     std::vector<Token>* replacements);
+
+    typedef std::vector<Token> MacroArg;
+    bool collectMacroArgs(const Macro& macro,
+                          const Token& identifier,
+                          std::vector<MacroArg>* args);
+    void replaceMacroParams(const Macro& macro,
+                            const std::vector<MacroArg>& args,
+                            std::vector<Token>* replacements);
+
+    struct MacroContext
+    {
+        const Macro* macro;
+        size_t index;
+        std::vector<Token> replacements;
+
+        MacroContext() : macro(0), index(0) { }
+        bool empty() const { return index == replacements.size(); }
+        const Token& get() { return replacements[index++]; }
+        void unget() { assert(index > 0); --index; }
+    };
+
+    Lexer* mLexer;
+    MacroSet* mMacroSet;
+    Diagnostics* mDiagnostics;
+
+    std::auto_ptr<Token> mReserveToken;
+    std::vector<MacroContext*> mContextStack;
+};
+
+}  // namespace pp
+#endif  // COMPILER_PREPROCESSOR_MACRO_EXPANDER_H_
+
diff --git a/src/3rdparty/angle/src/compiler/preprocessor/new/Preprocessor.cpp b/src/3rdparty/angle/src/compiler/preprocessor/new/Preprocessor.cpp
new file mode 100644 (file)
index 0000000..ffa7225
--- /dev/null
@@ -0,0 +1,142 @@
+//
+// Copyright (c) 2011 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "Preprocessor.h"
+
+#include <cassert>
+#include <sstream>
+
+#include "Diagnostics.h"
+#include "DirectiveParser.h"
+#include "Macro.h"
+#include "MacroExpander.h"
+#include "Token.h"
+#include "Tokenizer.h"
+
+namespace pp
+{
+
+struct PreprocessorImpl
+{
+    Diagnostics* diagnostics;
+    MacroSet macroSet;
+    Tokenizer tokenizer;
+    DirectiveParser directiveParser;
+    MacroExpander macroExpander;
+
+    PreprocessorImpl(Diagnostics* diag,
+                     DirectiveHandler* directiveHandler) :
+        diagnostics(diag),
+        tokenizer(diag),
+        directiveParser(&tokenizer, &macroSet, diag, directiveHandler),
+        macroExpander(&directiveParser, &macroSet, diag)
+    {
+    }
+};
+
+Preprocessor::Preprocessor(Diagnostics* diagnostics,
+                           DirectiveHandler* directiveHandler)
+{
+    mImpl = new PreprocessorImpl(diagnostics, directiveHandler);
+}
+
+Preprocessor::~Preprocessor()
+{
+    delete mImpl;
+}
+
+bool Preprocessor::init(int count,
+                        const char* const string[],
+                        const int length[])
+{
+    static const int kGLSLVersion = 100;
+
+    // Add standard pre-defined macros.
+    predefineMacro("__LINE__", 0);
+    predefineMacro("__FILE__", 0);
+    predefineMacro("__VERSION__", kGLSLVersion);
+    predefineMacro("GL_ES", 1);
+
+    return mImpl->tokenizer.init(count, string, length);
+}
+
+void Preprocessor::predefineMacro(const char* name, int value)
+{
+    std::ostringstream stream;
+    stream << value;
+
+    Token token;
+    token.type = Token::CONST_INT;
+    token.text = stream.str();
+
+    Macro macro;
+    macro.predefined = true;
+    macro.type = Macro::kTypeObj;
+    macro.name = name;
+    macro.replacements.push_back(token);
+
+    mImpl->macroSet[name] = macro;
+}
+
+void Preprocessor::lex(Token* token)
+{
+    bool validToken = false;
+    while (!validToken)
+    {
+        mImpl->macroExpander.lex(token);
+        switch (token->type)
+        {
+          // We should not be returning internal preprocessing tokens.
+          // Convert preprocessing tokens to compiler tokens or report
+          // diagnostics.
+          case Token::PP_HASH:
+            assert(false);
+            break;
+          case Token::CONST_INT:
+          {
+            int val = 0;
+            if (!token->iValue(&val))
+            {
+                // Do not mark the token as invalid.
+                // Just emit the diagnostic and reset value to 0.
+                mImpl->diagnostics->report(Diagnostics::INTEGER_OVERFLOW,
+                                           token->location, token->text);
+                token->text.assign("0");
+            }
+            validToken = true;
+            break;
+          }
+          case Token::CONST_FLOAT:
+          {
+            float val = 0;
+            if (!token->fValue(&val))
+            {
+                // Do not mark the token as invalid.
+                // Just emit the diagnostic and reset value to 0.0.
+                mImpl->diagnostics->report(Diagnostics::FLOAT_OVERFLOW,
+                                           token->location, token->text);
+                token->text.assign("0.0");
+            }
+            validToken = true;
+            break;
+          }
+          case Token::PP_NUMBER:
+            mImpl->diagnostics->report(Diagnostics::INVALID_NUMBER,
+                                       token->location, token->text);
+            break;
+          case Token::PP_OTHER:
+            mImpl->diagnostics->report(Diagnostics::INVALID_CHARACTER,
+                                       token->location, token->text);
+            break;
+          default:
+            validToken = true;
+            break;
+        }
+    }
+}
+
+}  // namespace pp
+
diff --git a/src/3rdparty/angle/src/compiler/preprocessor/new/Preprocessor.h b/src/3rdparty/angle/src/compiler/preprocessor/new/Preprocessor.h
new file mode 100644 (file)
index 0000000..5fe35b2
--- /dev/null
@@ -0,0 +1,49 @@
+//
+// Copyright (c) 2011 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#ifndef COMPILER_PREPROCESSOR_PREPROCESSOR_H_
+#define COMPILER_PREPROCESSOR_PREPROCESSOR_H_
+
+#include "pp_utils.h"
+
+namespace pp
+{
+
+class Diagnostics;
+class DirectiveHandler;
+struct PreprocessorImpl;
+struct Token;
+
+class Preprocessor
+{
+  public:
+    Preprocessor(Diagnostics* diagnostics, DirectiveHandler* directiveHandler);
+    ~Preprocessor();
+
+    // count: specifies the number of elements in the string and length arrays.
+    // string: specifies an array of pointers to strings.
+    // length: specifies an array of string lengths.
+    // If length is NULL, each string is assumed to be null terminated.
+    // If length is a value other than NULL, it points to an array containing
+    // a string length for each of the corresponding elements of string.
+    // Each element in the length array may contain the length of the
+    // corresponding string or a value less than 0 to indicate that the string
+    // is null terminated.
+    bool init(int count, const char* const string[], const int length[]);
+    // Adds a pre-defined macro.
+    void predefineMacro(const char* name, int value);
+
+    void lex(Token* token);
+
+  private:
+    PP_DISALLOW_COPY_AND_ASSIGN(Preprocessor);
+
+    PreprocessorImpl* mImpl;
+};
+
+}  // namespace pp
+#endif  // COMPILER_PREPROCESSOR_PREPROCESSOR_H_
+
diff --git a/src/3rdparty/angle/src/compiler/preprocessor/new/SourceLocation.h b/src/3rdparty/angle/src/compiler/preprocessor/new/SourceLocation.h
new file mode 100644 (file)
index 0000000..6982613
--- /dev/null
@@ -0,0 +1,38 @@
+//
+// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#ifndef COMPILER_PREPROCESSOR_SOURCE_LOCATION_H_
+#define COMPILER_PREPROCESSOR_SOURCE_LOCATION_H_
+
+namespace pp
+{
+
+struct SourceLocation
+{
+    SourceLocation() : file(0), line(0) { }
+    SourceLocation(int f, int l) : file(f), line(l) { }
+
+    bool equals(const SourceLocation& other) const
+    {
+        return (file == other.file) && (line == other.line);
+    }
+
+    int file;
+    int line;
+};
+
+inline bool operator==(const SourceLocation& lhs, const SourceLocation& rhs)
+{
+    return lhs.equals(rhs);
+}
+
+inline bool operator!=(const SourceLocation& lhs, const SourceLocation& rhs)
+{
+    return !lhs.equals(rhs);
+}
+
+}  // namespace pp
+#endif  // COMPILER_PREPROCESSOR_SOURCE_LOCATION_H_
diff --git a/src/3rdparty/angle/src/compiler/preprocessor/new/Token.cpp b/src/3rdparty/angle/src/compiler/preprocessor/new/Token.cpp
new file mode 100644 (file)
index 0000000..67f50aa
--- /dev/null
@@ -0,0 +1,83 @@
+//
+// Copyright (c) 2011 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "Token.h"
+
+#include <cassert>
+
+#include "numeric_lex.h"
+
+namespace pp
+{
+
+void Token::reset()
+{
+    type = 0;
+    flags = 0;
+    location = SourceLocation();
+    text.clear();
+}
+
+bool Token::equals(const Token& other) const
+{
+    return (type == other.type) &&
+           (flags == other.flags) &&
+           (location == other.location) &&
+           (text == other.text);
+}
+
+void Token::setAtStartOfLine(bool start)
+{
+    if (start)
+        flags |= AT_START_OF_LINE;
+    else
+        flags &= ~AT_START_OF_LINE;
+}
+
+void Token::setHasLeadingSpace(bool space)
+{
+    if (space)
+        flags |= HAS_LEADING_SPACE;
+    else
+        flags &= ~HAS_LEADING_SPACE;
+}
+
+void Token::setExpansionDisabled(bool disable)
+{
+    if (disable)
+        flags |= EXPANSION_DISABLED;
+    else
+        flags &= ~EXPANSION_DISABLED;
+}
+
+bool Token::iValue(int* value) const
+{
+    assert(type == CONST_INT);
+    return numeric_lex_int(text, value);
+}
+
+bool Token::uValue(unsigned int* value) const
+{
+    assert(type == CONST_INT);
+    return numeric_lex_int(text, value);
+}
+
+bool Token::fValue(float* value) const
+{
+    assert(type == CONST_FLOAT);
+    return numeric_lex_float(text, value);
+}
+
+std::ostream& operator<<(std::ostream& out, const Token& token)
+{
+    if (token.hasLeadingSpace())
+        out << " ";
+
+    out << token.text;
+    return out;
+}
+
+}  // namespace pp
diff --git a/src/3rdparty/angle/src/compiler/preprocessor/new/Token.h b/src/3rdparty/angle/src/compiler/preprocessor/new/Token.h
new file mode 100644 (file)
index 0000000..8b553ae
--- /dev/null
@@ -0,0 +1,106 @@
+//
+// Copyright (c) 2011 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#ifndef COMPILER_PREPROCESSOR_TOKEN_H_
+#define COMPILER_PREPROCESSOR_TOKEN_H_
+
+#include <ostream>
+#include <string>
+
+#include "SourceLocation.h"
+
+namespace pp
+{
+
+struct Token
+{
+    enum Type
+    {
+        LAST = 0,  // EOF.
+
+        IDENTIFIER = 258,
+
+        CONST_INT,
+        CONST_FLOAT,
+
+        OP_INC,
+        OP_DEC,
+        OP_LEFT,
+        OP_RIGHT,
+        OP_LE,
+        OP_GE,
+        OP_EQ,
+        OP_NE,
+        OP_AND,
+        OP_XOR,
+        OP_OR,
+        OP_ADD_ASSIGN,
+        OP_SUB_ASSIGN,
+        OP_MUL_ASSIGN,
+        OP_DIV_ASSIGN,
+        OP_MOD_ASSIGN,
+        OP_LEFT_ASSIGN,
+        OP_RIGHT_ASSIGN,
+        OP_AND_ASSIGN,
+        OP_XOR_ASSIGN,
+        OP_OR_ASSIGN,
+
+        // Preprocessing token types.
+        // These types are used by the preprocessor internally.
+        // Preprocessor clients must not depend or check for them.
+        PP_HASH,
+        PP_NUMBER,
+        PP_OTHER
+    };
+    enum Flags
+    {
+        AT_START_OF_LINE   = 1 << 0,
+        HAS_LEADING_SPACE  = 1 << 1,
+        EXPANSION_DISABLED = 1 << 2
+    };
+
+    Token() : type(0), flags(0) { }
+
+    void reset();
+    bool equals(const Token& other) const;
+
+    // Returns true if this is the first token on line.
+    // It disregards any leading whitespace.
+    bool atStartOfLine() const { return (flags & AT_START_OF_LINE) != 0; }
+    void setAtStartOfLine(bool start);
+
+    bool hasLeadingSpace() const { return (flags & HAS_LEADING_SPACE) != 0; }
+    void setHasLeadingSpace(bool space);
+
+    bool expansionDisabled() const { return (flags & EXPANSION_DISABLED) != 0; }
+    void setExpansionDisabled(bool disable);
+
+    // Converts text into numeric value for CONST_INT and CONST_FLOAT token.
+    // Returns false if the parsed value cannot fit into an int or float.
+    bool iValue(int* value) const;
+    bool uValue(unsigned int* value) const;
+    bool fValue(float* value) const;
+
+    int type;
+    unsigned int flags;
+    SourceLocation location;
+    std::string text;
+};
+
+inline bool operator==(const Token& lhs, const Token& rhs)
+{
+    return lhs.equals(rhs);
+}
+
+inline bool operator!=(const Token& lhs, const Token& rhs)
+{
+    return !lhs.equals(rhs);
+}
+
+extern std::ostream& operator<<(std::ostream& out, const Token& token);
+
+}  // namepsace pp
+#endif  // COMPILER_PREPROCESSOR_TOKEN_H_
diff --git a/src/3rdparty/angle/src/compiler/preprocessor/new/Tokenizer.h b/src/3rdparty/angle/src/compiler/preprocessor/new/Tokenizer.h
new file mode 100644 (file)
index 0000000..a594d2d
--- /dev/null
@@ -0,0 +1,58 @@
+//
+// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#ifndef COMPILER_PREPROCESSOR_TOKENIZER_H_
+#define COMPILER_PREPROCESSOR_TOKENIZER_H_
+
+#include "Input.h"
+#include "Lexer.h"
+#include "pp_utils.h"
+
+namespace pp
+{
+
+class Diagnostics;
+
+class Tokenizer : public Lexer
+{
+  public:
+    struct Context
+    {
+        Diagnostics* diagnostics;
+
+        Input input;
+        // The location where yytext points to. Token location should track
+        // scanLoc instead of Input::mReadLoc because they may not be the same
+        // if text is buffered up in the scanner input buffer.
+        Input::Location scanLoc;
+
+        bool leadingSpace;
+        bool lineStart;
+    };
+    static const size_t kMaxTokenLength;
+
+    Tokenizer(Diagnostics* diagnostics);
+    ~Tokenizer();
+
+    bool init(int count, const char* const string[], const int length[]);
+
+    void setFileNumber(int file);
+    void setLineNumber(int line);
+
+    virtual void lex(Token* token);
+
+  private:
+    PP_DISALLOW_COPY_AND_ASSIGN(Tokenizer);
+    bool initScanner();
+    void destroyScanner();
+
+    void* mHandle;  // Scanner handle.
+    Context mContext;  // Scanner extra.
+};
+
+}  // namespace pp
+#endif  // COMPILER_PREPROCESSOR_TOKENIZER_H_
+
diff --git a/src/3rdparty/angle/src/compiler/preprocessor/new/Tokenizer.l b/src/3rdparty/angle/src/compiler/preprocessor/new/Tokenizer.l
new file mode 100644 (file)
index 0000000..9762988
--- /dev/null
@@ -0,0 +1,340 @@
+/*
+//
+// Copyright (c) 2002-2011 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+This file contains the Lex specification for GLSL ES preprocessor.
+Based on Microsoft Visual Studio 2010 Preprocessor Grammar:
+http://msdn.microsoft.com/en-us/library/2scxys89.aspx
+
+IF YOU MODIFY THIS FILE YOU ALSO NEED TO RUN generate_parser.sh.
+*/
+
+%top{
+//
+// Copyright (c) 2011 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// This file is auto-generated by generate_parser.sh. DO NOT EDIT!
+}
+
+%{
+#include "Tokenizer.h"
+
+#include "Diagnostics.h"
+#include "Token.h"
+
+#if defined(__GNUC__)
+// Triggered by the auto-generated yy_fatal_error function.
+#pragma GCC diagnostic ignored "-Wmissing-noreturn"
+#endif
+
+typedef std::string YYSTYPE;
+typedef pp::SourceLocation YYLTYPE;
+
+// Use the unused yycolumn variable to track file (string) number.
+#define yyfileno yycolumn
+
+#define YY_USER_INIT                   \
+    do {                               \
+        yyfileno = 0;                  \
+        yylineno = 1;                  \
+        yyextra->leadingSpace = false; \
+        yyextra->lineStart = true;     \
+    } while(0);
+
+#define YY_USER_ACTION                                              \
+    do                                                              \
+    {                                                               \
+        pp::Input* input = &yyextra->input;                         \
+        pp::Input::Location* scanLoc = &yyextra->scanLoc;           \
+        while ((scanLoc->sIndex < input->count()) &&                \
+               (scanLoc->cIndex >= input->length(scanLoc->sIndex))) \
+        {                                                           \
+            scanLoc->cIndex -= input->length(scanLoc->sIndex++);    \
+            ++yyfileno; yylineno = 1;                               \
+        }                                                           \
+        yylloc->file = yyfileno;                                    \
+        yylloc->line = yylineno;                                    \
+        scanLoc->cIndex += yyleng;                                  \
+    } while(0);
+
+#define YY_INPUT(buf, result, maxSize) \
+    result = yyextra->input.read(buf, maxSize);
+
+%}
+
+%option noyywrap nounput never-interactive
+%option reentrant bison-bridge bison-locations
+%option prefix="pp"
+%option extra-type="pp::Tokenizer::Context*"
+%x COMMENT
+
+NEWLINE     \n|\r|\r\n
+IDENTIFIER  [_a-zA-Z][_a-zA-Z0-9]*
+PUNCTUATOR  [][<>(){}.+-/*%^|&~=!:;,?]
+
+DECIMAL_CONSTANT      [1-9][0-9]*
+OCTAL_CONSTANT        0[0-7]*
+HEXADECIMAL_CONSTANT  0[xX][0-9a-fA-F]+
+
+DIGIT                [0-9]
+EXPONENT_PART        [eE][+-]?{DIGIT}+
+FRACTIONAL_CONSTANT  ({DIGIT}*"."{DIGIT}+)|({DIGIT}+".")
+
+%%
+
+    /* Line comment */
+"//"[^\r\n]*
+
+    /* Block comment */
+    /* Line breaks are just counted - not returned. */
+    /* The comment is replaced by a single space. */ 
+"/*" { BEGIN(COMMENT); }
+<COMMENT>[^*\r\n]+
+<COMMENT>"*"
+<COMMENT>{NEWLINE} { ++yylineno; }
+<COMMENT>"*/" {
+    yyextra->leadingSpace = true;
+    BEGIN(INITIAL);
+}
+
+# {
+    // # is only valid at start of line for preprocessor directives.
+    yylval->assign(1, yytext[0]);
+    return yyextra->lineStart ? pp::Token::PP_HASH : pp::Token::PP_OTHER;
+}
+
+{IDENTIFIER} {
+    yylval->assign(yytext, yyleng);
+    return pp::Token::IDENTIFIER;
+}
+
+{DECIMAL_CONSTANT}|{OCTAL_CONSTANT}|{HEXADECIMAL_CONSTANT} {
+    yylval->assign(yytext, yyleng);
+    return pp::Token::CONST_INT;
+}
+
+({DIGIT}+{EXPONENT_PART})|({FRACTIONAL_CONSTANT}{EXPONENT_PART}?) {
+    yylval->assign(yytext, yyleng);
+    return pp::Token::CONST_FLOAT;
+}
+
+    /* Anything that starts with a {DIGIT} or .{DIGIT} must be a number. */
+    /* Rule to catch all invalid integers and floats. */
+({DIGIT}+[_a-zA-Z0-9.]*)|("."{DIGIT}+[_a-zA-Z0-9.]*) {
+    yylval->assign(yytext, yyleng);
+    return pp::Token::PP_NUMBER;
+}
+
+"++" {
+    yylval->assign(yytext, yyleng);
+    return pp::Token::OP_INC;
+}
+"--" {
+    yylval->assign(yytext, yyleng);
+    return pp::Token::OP_DEC;
+}
+"<<" {
+    yylval->assign(yytext, yyleng);
+    return pp::Token::OP_LEFT;
+}
+">>" {
+    yylval->assign(yytext, yyleng);
+    return pp::Token::OP_RIGHT;
+}
+"<=" {
+    yylval->assign(yytext, yyleng);
+    return pp::Token::OP_LE;
+}
+">=" {
+    yylval->assign(yytext, yyleng);
+    return pp::Token::OP_GE;
+}
+"==" {
+    yylval->assign(yytext, yyleng);
+    return pp::Token::OP_EQ;
+}
+"!=" {
+    yylval->assign(yytext, yyleng);
+    return pp::Token::OP_NE;
+}
+"&&" {
+    yylval->assign(yytext, yyleng);
+    return pp::Token::OP_AND;
+}
+"^^" {
+    yylval->assign(yytext, yyleng);
+    return pp::Token::OP_XOR;
+}
+"||" {
+    yylval->assign(yytext, yyleng);
+    return pp::Token::OP_OR;
+}
+"+=" {
+    yylval->assign(yytext, yyleng);
+    return pp::Token::OP_ADD_ASSIGN;
+}
+"-=" {
+    yylval->assign(yytext, yyleng);
+    return pp::Token::OP_SUB_ASSIGN;
+}
+"*=" {
+    yylval->assign(yytext, yyleng);
+    return pp::Token::OP_MUL_ASSIGN;
+}
+"/=" {
+    yylval->assign(yytext, yyleng);
+    return pp::Token::OP_DIV_ASSIGN;
+}
+"%=" {
+    yylval->assign(yytext, yyleng);
+    return pp::Token::OP_MOD_ASSIGN;
+}
+"<<=" {
+    yylval->assign(yytext, yyleng);
+    return pp::Token::OP_LEFT_ASSIGN;
+}
+">>=" {
+    yylval->assign(yytext, yyleng);
+    return pp::Token::OP_RIGHT_ASSIGN;
+}
+"&=" {
+    yylval->assign(yytext, yyleng);
+    return pp::Token::OP_AND_ASSIGN;
+}
+"^=" {
+    yylval->assign(yytext, yyleng);
+    return pp::Token::OP_XOR_ASSIGN;
+}
+"|=" {
+    yylval->assign(yytext, yyleng);
+    return pp::Token::OP_OR_ASSIGN;
+}
+
+{PUNCTUATOR} {
+    yylval->assign(1, yytext[0]);
+    return yytext[0];
+}
+
+[ \t\v\f]+   { yyextra->leadingSpace = true; }
+
+{NEWLINE} {
+    ++yylineno;
+    yylval->assign(1, '\n');
+    return '\n';
+}
+
+. {
+    yylval->assign(1, yytext[0]);
+    return pp::Token::PP_OTHER;
+}
+
+<*><<EOF>> {
+    // YY_USER_ACTION is not invoked for handling EOF.
+    // Set the location for EOF token manually.
+    pp::Input* input = &yyextra->input;
+    pp::Input::Location* scanLoc = &yyextra->scanLoc;
+    int sIndexMax = std::max(0, input->count() - 1);
+    if (scanLoc->sIndex != sIndexMax)
+    {
+        // We can only reach here if there are empty strings at the
+        // end of the input.
+        scanLoc->sIndex = sIndexMax; scanLoc->cIndex = 0;
+        yyfileno = sIndexMax; yylineno = 1;
+    }
+    yylloc->file = yyfileno;
+    yylloc->line = yylineno;
+    yylval->clear();
+
+    if (YY_START == COMMENT)
+    {
+        yyextra->diagnostics->report(pp::Diagnostics::EOF_IN_COMMENT,
+                                     pp::SourceLocation(yyfileno, yylineno),
+                                     "");
+    }
+    yyterminate();
+}
+
+%%
+
+namespace pp {
+
+// TODO(alokp): Maximum token length should ideally be specified by
+// the preprocessor client, i.e., the compiler.
+const size_t Tokenizer::kMaxTokenLength = 256;
+
+Tokenizer::Tokenizer(Diagnostics* diagnostics) : mHandle(0)
+{
+    mContext.diagnostics = diagnostics;
+}
+
+Tokenizer::~Tokenizer()
+{
+    destroyScanner();
+}
+
+bool Tokenizer::init(int count, const char* const string[], const int length[])
+{
+    if (count < 0) return false;
+    if ((count > 0) && (string == 0)) return false;
+
+    mContext.input = Input(count, string, length);
+    return initScanner();
+}
+
+void Tokenizer::setFileNumber(int file)
+{
+    // We use column number as file number.
+    // See macro yyfileno.
+    yyset_column(file, mHandle);
+}
+
+void Tokenizer::setLineNumber(int line)
+{
+    yyset_lineno(line, mHandle);
+}
+
+void Tokenizer::lex(Token* token)
+{
+    token->type = yylex(&token->text, &token->location, mHandle);
+    if (token->text.size() > kMaxTokenLength)
+    {
+        mContext.diagnostics->report(Diagnostics::TOKEN_TOO_LONG,
+                                     token->location, token->text);
+        token->text.erase(kMaxTokenLength);
+    }
+
+    token->flags = 0;
+
+    token->setAtStartOfLine(mContext.lineStart);
+    mContext.lineStart = token->type == '\n';
+
+    token->setHasLeadingSpace(mContext.leadingSpace);
+    mContext.leadingSpace = false;
+}
+
+bool Tokenizer::initScanner()
+{
+    if ((mHandle == NULL) && yylex_init_extra(&mContext, &mHandle))
+        return false;
+
+    yyrestart(0, mHandle);
+    return true;
+}
+
+void Tokenizer::destroyScanner()
+{
+    if (mHandle == NULL)
+        return;
+
+    yylex_destroy(mHandle);
+    mHandle = NULL;
+}
+
+}  // namespace pp
+
diff --git a/src/3rdparty/angle/src/compiler/preprocessor/new/numeric_lex.h b/src/3rdparty/angle/src/compiler/preprocessor/new/numeric_lex.h
new file mode 100644 (file)
index 0000000..b04125d
--- /dev/null
@@ -0,0 +1,61 @@
+//
+// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// numeric_lex.h: Functions to extract numeric values from string.
+
+#ifndef COMPILER_PREPROCESSOR_NUMERIC_LEX_H_
+#define COMPILER_PREPROCESSOR_NUMERIC_LEX_H_
+
+#include <sstream>
+
+namespace pp {
+
+inline std::ios::fmtflags numeric_base_int(const std::string& str)
+{
+    if ((str.size() >= 2) &&
+        (str[0] == '0') &&
+        (str[1] == 'x' || str[1] == 'X'))
+    {
+        return std::ios::hex;
+    }
+    else if ((str.size() >= 1) && (str[0] == '0'))
+    {
+        return std::ios::oct;
+    }
+    return std::ios::dec;
+}
+
+// The following functions parse the given string to extract a numerical
+// value of the given type. These functions assume that the string is
+// of the correct form. They can only fail if the parsed value is too big,
+// in which case false is returned.
+
+template<typename IntType>
+bool numeric_lex_int(const std::string& str, IntType* value)
+{
+    std::istringstream stream(str);
+    // This should not be necessary, but MSVS has a buggy implementation.
+    // It returns incorrect results if the base is not specified.
+    stream.setf(numeric_base_int(str), std::ios::basefield);
+
+    stream >> (*value);
+    return !stream.fail();
+}
+
+template<typename FloatType>
+bool numeric_lex_float(const std::string& str, FloatType* value)
+{
+    std::istringstream stream(str);
+    // Force "C" locale so that decimal character is always '.', and
+    // not dependent on the current locale.
+    stream.imbue(std::locale::classic());
+
+    stream >> (*value);
+    return !stream.fail();
+}
+
+} // namespace pp.
+#endif // COMPILER_PREPROCESSOR_NUMERIC_LEX_H_
diff --git a/src/3rdparty/angle/src/compiler/preprocessor/new/pp_utils.h b/src/3rdparty/angle/src/compiler/preprocessor/new/pp_utils.h
new file mode 100644 (file)
index 0000000..17164ea
--- /dev/null
@@ -0,0 +1,18 @@
+//
+// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// pp_utils.h: Common preprocessor utilities
+
+#ifndef COMPILER_PREPROCESSOR_PPUTILS_H_
+#define COMPILER_PREPROCESSOR_PPUTILS_H_
+
+// A macro to disallow the copy constructor and operator= functions
+// This must be used in the private: declarations for a class.
+#define PP_DISALLOW_COPY_AND_ASSIGN(TypeName) \
+  TypeName(const TypeName&);               \
+  void operator=(const TypeName&)
+
+#endif // COMPILER_PREPROCESSOR_PPUTILS_H_
diff --git a/src/3rdparty/angle/src/compiler/preprocessor/parser.h b/src/3rdparty/angle/src/compiler/preprocessor/parser.h
new file mode 100644 (file)
index 0000000..f67342b
--- /dev/null
@@ -0,0 +1,93 @@
+/****************************************************************************\
+Copyright (c) 2002, NVIDIA Corporation.
+
+NVIDIA Corporation("NVIDIA") supplies this software to you in
+consideration of your agreement to the following terms, and your use,
+installation, modification or redistribution of this NVIDIA software
+constitutes acceptance of these terms.  If you do not agree with these
+terms, please do not use, install, modify or redistribute this NVIDIA
+software.
+
+In consideration of your agreement to abide by the following terms, and
+subject to these terms, NVIDIA grants you a personal, non-exclusive
+license, under NVIDIA's copyrights in this original NVIDIA software (the
+"NVIDIA Software"), to use, reproduce, modify and redistribute the
+NVIDIA Software, with or without modifications, in source and/or binary
+forms; provided that if you redistribute the NVIDIA Software, you must
+retain the copyright notice of NVIDIA, this notice and the following
+text and disclaimers in all such redistributions of the NVIDIA Software.
+Neither the name, trademarks, service marks nor logos of NVIDIA
+Corporation may be used to endorse or promote products derived from the
+NVIDIA Software without specific prior written permission from NVIDIA.
+Except as expressly stated in this notice, no other rights or licenses
+express or implied, are granted by NVIDIA herein, including but not
+limited to any patent rights that may be infringed by your derivative
+works or by other works in which the NVIDIA Software may be
+incorporated. No hardware is licensed hereunder. 
+
+THE NVIDIA SOFTWARE IS BEING PROVIDED ON AN "AS IS" BASIS, WITHOUT
+WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED,
+INCLUDING WITHOUT LIMITATION, WARRANTIES OR CONDITIONS OF TITLE,
+NON-INFRINGEMENT, MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR
+ITS USE AND OPERATION EITHER ALONE OR IN COMBINATION WITH OTHER
+PRODUCTS.
+
+IN NO EVENT SHALL NVIDIA BE LIABLE FOR ANY SPECIAL, INDIRECT,
+INCIDENTAL, EXEMPLARY, CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+TO, LOST PROFITS; PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) OR ARISING IN ANY WAY
+OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE
+NVIDIA SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT,
+TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF
+NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+\****************************************************************************/
+
+#ifndef BISON_PARSER_H
+# define BISON_PARSER_H
+
+#ifndef yystypepp
+typedef struct {
+    int    sc_int;
+    float  sc_fval;
+    int    sc_ident;
+       char   symbol_name[MAX_SYMBOL_NAME_LEN+1];
+} yystypepp;
+
+# define YYSTYPE_IS_TRIVIAL 1
+#endif
+# define       CPP_AND_OP              257
+# define       CPP_SUB_ASSIGN      259
+# define       CPP_MOD_ASSIGN      260
+# define       CPP_ADD_ASSIGN  261
+# define       CPP_DIV_ASSIGN  262
+# define       CPP_MUL_ASSIGN  263
+# define       CPP_EQ_OP               264
+# define    CPP_XOR_OP         265 
+# define       ERROR_SY            266
+# define       CPP_FLOATCONSTANT       267
+# define       CPP_GE_OP               268
+# define       CPP_RIGHT_OP        269
+# define       CPP_IDENTIFIER      270
+# define       CPP_INTCONSTANT     271
+# define       CPP_LE_OP               272
+# define       CPP_LEFT_OP             273
+# define       CPP_DEC_OP      274
+# define       CPP_NE_OP               275
+# define       CPP_OR_OP               276
+# define       CPP_INC_OP          277
+# define       CPP_STRCONSTANT     278
+# define       CPP_TYPEIDENTIFIER      279
+
+# define       FIRST_USER_TOKEN_SY     289
+
+# define       CPP_RIGHT_ASSIGN            280
+# define       CPP_LEFT_ASSIGN     281
+# define       CPP_AND_ASSIGN  282
+# define       CPP_OR_ASSIGN   283
+# define       CPP_XOR_ASSIGN  284
+# define       CPP_LEFT_BRACKET        285
+# define       CPP_RIGHT_BRACKET       286
+# define       CPP_LEFT_BRACE  287
+# define       CPP_RIGHT_BRACE 288
+
+#endif /* not BISON_PARSER_H */
diff --git a/src/3rdparty/angle/src/compiler/preprocessor/preprocess.h b/src/3rdparty/angle/src/compiler/preprocessor/preprocess.h
new file mode 100644 (file)
index 0000000..15056da
--- /dev/null
@@ -0,0 +1,50 @@
+/****************************************************************************\
+Copyright (c) 2002, NVIDIA Corporation.
+
+NVIDIA Corporation("NVIDIA") supplies this software to you in
+consideration of your agreement to the following terms, and your use,
+installation, modification or redistribution of this NVIDIA software
+constitutes acceptance of these terms.  If you do not agree with these
+terms, please do not use, install, modify or redistribute this NVIDIA
+software.
+
+In consideration of your agreement to abide by the following terms, and
+subject to these terms, NVIDIA grants you a personal, non-exclusive
+license, under NVIDIA's copyrights in this original NVIDIA software (the
+"NVIDIA Software"), to use, reproduce, modify and redistribute the
+NVIDIA Software, with or without modifications, in source and/or binary
+forms; provided that if you redistribute the NVIDIA Software, you must
+retain the copyright notice of NVIDIA, this notice and the following
+text and disclaimers in all such redistributions of the NVIDIA Software.
+Neither the name, trademarks, service marks nor logos of NVIDIA
+Corporation may be used to endorse or promote products derived from the
+NVIDIA Software without specific prior written permission from NVIDIA.
+Except as expressly stated in this notice, no other rights or licenses
+express or implied, are granted by NVIDIA herein, including but not
+limited to any patent rights that may be infringed by your derivative
+works or by other works in which the NVIDIA Software may be
+incorporated. No hardware is licensed hereunder. 
+
+THE NVIDIA SOFTWARE IS BEING PROVIDED ON AN "AS IS" BASIS, WITHOUT
+WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED,
+INCLUDING WITHOUT LIMITATION, WARRANTIES OR CONDITIONS OF TITLE,
+NON-INFRINGEMENT, MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR
+ITS USE AND OPERATION EITHER ALONE OR IN COMBINATION WITH OTHER
+PRODUCTS.
+
+IN NO EVENT SHALL NVIDIA BE LIABLE FOR ANY SPECIAL, INDIRECT,
+INCIDENTAL, EXEMPLARY, CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+TO, LOST PROFITS; PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) OR ARISING IN ANY WAY
+OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE
+NVIDIA SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT,
+TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF
+NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+\****************************************************************************/
+
+#include "compiler/preprocessor/slglobals.h"
+extern CPPStruct *cpp;
+int InitCPPStruct(void);
+int InitScanner(CPPStruct *cpp);
+int InitAtomTable(AtomTable *atable, int htsize);
+char* GetStringOfAtom(AtomTable *atable, int atom);
diff --git a/src/3rdparty/angle/src/compiler/preprocessor/scanner.c b/src/3rdparty/angle/src/compiler/preprocessor/scanner.c
new file mode 100644 (file)
index 0000000..fde853c
--- /dev/null
@@ -0,0 +1,698 @@
+/****************************************************************************\
+Copyright (c) 2002, NVIDIA Corporation.
+
+NVIDIA Corporation("NVIDIA") supplies this software to you in
+consideration of your agreement to the following terms, and your use,
+installation, modification or redistribution of this NVIDIA software
+constitutes acceptance of these terms.  If you do not agree with these
+terms, please do not use, install, modify or redistribute this NVIDIA
+software.
+
+In consideration of your agreement to abide by the following terms, and
+subject to these terms, NVIDIA grants you a personal, non-exclusive
+license, under NVIDIA's copyrights in this original NVIDIA software (the
+"NVIDIA Software"), to use, reproduce, modify and redistribute the
+NVIDIA Software, with or without modifications, in source and/or binary
+forms; provided that if you redistribute the NVIDIA Software, you must
+retain the copyright notice of NVIDIA, this notice and the following
+text and disclaimers in all such redistributions of the NVIDIA Software.
+Neither the name, trademarks, service marks nor logos of NVIDIA
+Corporation may be used to endorse or promote products derived from the
+NVIDIA Software without specific prior written permission from NVIDIA.
+Except as expressly stated in this notice, no other rights or licenses
+express or implied, are granted by NVIDIA herein, including but not
+limited to any patent rights that may be infringed by your derivative
+works or by other works in which the NVIDIA Software may be
+incorporated. No hardware is licensed hereunder. 
+
+THE NVIDIA SOFTWARE IS BEING PROVIDED ON AN "AS IS" BASIS, WITHOUT
+WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED,
+INCLUDING WITHOUT LIMITATION, WARRANTIES OR CONDITIONS OF TITLE,
+NON-INFRINGEMENT, MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR
+ITS USE AND OPERATION EITHER ALONE OR IN COMBINATION WITH OTHER
+PRODUCTS.
+
+IN NO EVENT SHALL NVIDIA BE LIABLE FOR ANY SPECIAL, INDIRECT,
+INCIDENTAL, EXEMPLARY, CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+TO, LOST PROFITS; PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) OR ARISING IN ANY WAY
+OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE
+NVIDIA SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT,
+TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF
+NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+\****************************************************************************/
+//
+// scanner.c
+//
+
+#include <assert.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#if 0
+    #include <ieeefp.h>
+#else
+    #define isinff(x) (((*(int *)&(x) & 0x7f800000L)==0x7f800000L) && \
+                       ((*(int *)&(x) & 0x007fffffL)==0000000000L))
+#endif
+
+#include "compiler/preprocessor/slglobals.h"
+#include "compiler/util.h"
+
+typedef struct StringInputSrc {
+    InputSrc base;
+    char *p;
+} StringInputSrc;
+
+static int ScanFromString(const char *s);
+
+static int eof_scan(InputSrc *is, yystypepp * yylvalpp)
+{
+    return EOF;
+} // eof_scan
+
+static void noop(InputSrc *in, int ch, yystypepp * yylvalpp) {}
+
+static InputSrc eof_inputsrc = { 0, &eof_scan, &eof_scan, &noop, 0, 0 };
+
+static int byte_scan(InputSrc *, yystypepp * yylvalpp);
+
+#define EOL_SY '\n'
+
+#if defined(_MSC_VER)
+    #define DBG_BREAKPOINT() __asm int 3
+#elif defined(_M_AMD64)
+    #define DBG_BREAKPOINT() assert(!"Dbg_Breakpoint");
+#else
+    #define DBG_BREAKPOINT()
+#endif
+
+#if defined(_MSC_VER) && !defined(_M_AMD64)
+    __int64 RDTSC ( void ) {
+
+        __int64 v;
+    
+        __asm __emit 0x0f
+        __asm __emit 0x31
+        __asm mov dword ptr v, eax
+        __asm mov dword ptr v+4, edx
+    
+        return v;
+    }
+#endif
+
+
+int InitScanner(CPPStruct *cpp)
+{
+    // Add various atoms needed by the CPP line scanner:
+    if (!InitCPP())
+        return 0;
+
+    cpp->mostRecentToken = 0;
+    cpp->tokenLoc = &cpp->ltokenLoc;
+
+    cpp->ltokenLoc.file = 0;
+    cpp->ltokenLoc.line = 0;
+
+    cpp->currentInput = &eof_inputsrc;
+    cpp->previous_token = '\n';
+    cpp->pastFirstStatement = 0;
+
+    return 1;
+} // InitScanner
+
+int FreeScanner(void)
+{
+    return (FreeCPP());
+}
+
+int InitScannerInput(CPPStruct *cpp, int count, const char* const string[], const int length[])
+{
+    cpp->PaWhichStr = 0;
+    cpp->PaArgv     = string;
+    cpp->PaArgc     = count;
+    cpp->PaStrLen   = length;
+    ScanFromString(string[0]);
+    return 0;
+}
+
+/*
+ * str_getch()
+ * takes care of reading from multiple strings.
+ * returns the next-char from the input stream.
+ * returns EOF when the complete shader is parsed.
+ */
+static int str_getch(StringInputSrc *in)
+{
+    for(;;){
+       if (*in->p){
+          if (*in->p == '\n') {
+             in->base.line++;
+             IncLineNumber();
+          }
+          return *in->p++;
+       }
+       if(++(cpp->PaWhichStr) < cpp->PaArgc){
+          free(in);
+          SetStringNumber(cpp->PaWhichStr);
+          SetLineNumber(1);
+          ScanFromString(cpp->PaArgv[cpp->PaWhichStr]);
+          in=(StringInputSrc*)cpp->currentInput;
+          continue;             
+       }
+       else{
+          cpp->currentInput = in->base.prev;
+          cpp->PaWhichStr=0;
+          free(in);
+          return EOF;
+       }  
+    }
+} // str_getch
+
+static void str_ungetch(StringInputSrc *in, int ch, yystypepp *type) {
+    if (in->p[-1] == ch)in->p--;
+    else {
+        *(in->p)='\0'; //this would take care of shifting to the previous string.
+        cpp->PaWhichStr--;
+    }  
+    if (ch == '\n') {
+        in->base.line--;
+        DecLineNumber();
+    }
+} // str_ungetch
+
+int ScanFromString(const char *s)
+{
+    
+    StringInputSrc *in = malloc(sizeof(StringInputSrc));
+    memset(in, 0, sizeof(StringInputSrc));
+    in->p = (char*) s;
+    in->base.line = 1;
+    in->base.scan = byte_scan;
+    in->base.getch = (int (*)(InputSrc *, yystypepp *))str_getch;
+    in->base.ungetch = (void (*)(InputSrc *, int, yystypepp *))str_ungetch;
+    in->base.prev = cpp->currentInput;
+    cpp->currentInput = &in->base;
+
+    return 1;
+} // ScanFromString;
+
+
+///////////////////////////////////////////////////////////////////////////////////////////////
+/////////////////////////////////// Floating point constants: /////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////////////////////
+
+#define APPEND_CHAR_S(ch, str, len, max_len) \
+      if (len < max_len) { \
+          str[len++] = ch; \
+      } else if (!alreadyComplained) { \
+          CPPErrorToInfoLog("BUFFER OVERFLOW"); \
+          alreadyComplained = 1; \
+      }
+
+/*
+ * lFloatConst() - Scan a floating point constant.  Assumes that the scanner
+ *         has seen at least one digit, followed by either a decimal '.' or the
+ *         letter 'e'.
+ * ch - '.' or 'e'
+ * len - length of string already copied into yylvalpp->symbol_name.
+ */
+
+static int lFloatConst(int ch, int len, yystypepp * yylvalpp)
+{
+    int alreadyComplained = 0;
+    assert((ch == '.') || (ch == 'e') || (ch == 'E'));
+
+    if (ch == '.') {
+        do {
+            APPEND_CHAR_S(ch, yylvalpp->symbol_name, len, MAX_SYMBOL_NAME_LEN);
+            ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
+        } while (ch >= '0' && ch <= '9');
+    }
+
+    // Exponent:
+    if (ch == 'e' || ch == 'E') {
+        APPEND_CHAR_S(ch, yylvalpp->symbol_name, len, MAX_SYMBOL_NAME_LEN);
+        ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
+        if (ch == '+') {
+            APPEND_CHAR_S(ch, yylvalpp->symbol_name, len, MAX_SYMBOL_NAME_LEN);
+            ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
+        } else if (ch == '-') {
+            APPEND_CHAR_S(ch, yylvalpp->symbol_name, len, MAX_SYMBOL_NAME_LEN);
+            ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
+        }
+        if (ch >= '0' && ch <= '9') {
+            while (ch >= '0' && ch <= '9') {
+                APPEND_CHAR_S(ch, yylvalpp->symbol_name, len, MAX_SYMBOL_NAME_LEN);
+                ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
+            }
+        } else {
+            CPPErrorToInfoLog("EXPONENT INVALID");
+        }
+    }
+    cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp);
+
+    assert(len <= MAX_SYMBOL_NAME_LEN);
+    yylvalpp->symbol_name[len] = '\0';
+    yylvalpp->sc_fval = (float) atof_dot(yylvalpp->symbol_name);
+    if (isinff(yylvalpp->sc_fval)) {
+        CPPErrorToInfoLog("FLOAT CONSTANT OVERFLOW");
+    }
+    return CPP_FLOATCONSTANT;
+} // lFloatConst
+
+///////////////////////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////// Normal Scanner //////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////////////////////
+    
+static int byte_scan(InputSrc *in, yystypepp * yylvalpp)
+{
+    char string_val[MAX_STRING_LEN + 1];
+    int alreadyComplained = 0;
+    int len, ch, ii, ival = 0;
+
+    for (;;) {
+        yylvalpp->sc_int = 0;
+        ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
+        while (ch == ' ' || ch == '\t' || ch == '\r') {
+            yylvalpp->sc_int = 1;
+            ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
+        }
+        
+        cpp->ltokenLoc.file = cpp->currentInput->name;
+        cpp->ltokenLoc.line = cpp->currentInput->line;
+        alreadyComplained = 0;
+        len = 0;
+        switch (ch) {
+        default:
+            return ch; // Single character token
+        case EOF:
+            return -1;
+        case 'A': case 'B': case 'C': case 'D': case 'E':
+        case 'F': case 'G': case 'H': case 'I': case 'J':
+        case 'K': case 'L': case 'M': case 'N': case 'O':
+        case 'P': case 'Q': case 'R': case 'S': case 'T':
+        case 'U': case 'V': case 'W': case 'X': case 'Y':
+        case 'Z': case '_':
+        case 'a': case 'b': case 'c': case 'd': case 'e':
+        case 'f': case 'g': case 'h': case 'i': case 'j':
+        case 'k': case 'l': case 'm': case 'n': case 'o':
+        case 'p': case 'q': case 'r': case 's': case 't':
+        case 'u': case 'v': case 'w': case 'x': case 'y':
+        case 'z':            
+            do {
+                APPEND_CHAR_S(ch, yylvalpp->symbol_name, len, MAX_SYMBOL_NAME_LEN);
+                ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
+            } while ((ch >= 'a' && ch <= 'z') ||
+                     (ch >= 'A' && ch <= 'Z') ||
+                     (ch >= '0' && ch <= '9') ||
+                     ch == '_');
+            assert(len <= MAX_SYMBOL_NAME_LEN);
+            yylvalpp->symbol_name[len] = '\0';
+            cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp);
+            yylvalpp->sc_ident = LookUpAddString(atable, yylvalpp->symbol_name);
+            return CPP_IDENTIFIER;
+            break;
+        case '0':
+            APPEND_CHAR_S(ch, yylvalpp->symbol_name, len, MAX_SYMBOL_NAME_LEN);
+            ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
+            if (ch == 'x' || ch == 'X') {  // hexadecimal integer constants
+                APPEND_CHAR_S(ch, yylvalpp->symbol_name, len, MAX_SYMBOL_NAME_LEN);
+                ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
+                if ((ch >= '0' && ch <= '9') ||
+                    (ch >= 'A' && ch <= 'F') ||
+                    (ch >= 'a' && ch <= 'f'))
+                {
+                    ival = 0;
+                    do {
+                        if ((ival <= 0x0fffffff) && (len < MAX_SYMBOL_NAME_LEN)) {
+                            yylvalpp->symbol_name[len++] = ch;
+                            if (ch >= '0' && ch <= '9') {
+                                ii = ch - '0';
+                            } else if (ch >= 'A' && ch <= 'F') {
+                                ii = ch - 'A' + 10;
+                            } else {
+                                ii = ch - 'a' + 10;
+                            }
+                            ival = (ival << 4) | ii;
+                        } else if (!alreadyComplained) {
+                            CPPErrorToInfoLog("HEX CONSTANT OVERFLOW");
+                            alreadyComplained = 1;
+                        }
+                        ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
+                    } while ((ch >= '0' && ch <= '9') ||
+                             (ch >= 'A' && ch <= 'F') ||
+                             (ch >= 'a' && ch <= 'f'));
+                } else {
+                    CPPErrorToInfoLog("HEX CONSTANT INVALID");
+                }
+                assert(len <= MAX_SYMBOL_NAME_LEN);
+                yylvalpp->symbol_name[len] = '\0';
+                cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp);
+                yylvalpp->sc_int = ival;
+                return CPP_INTCONSTANT;
+            } else if (ch >= '0' && ch <= '7') { // octal integer constants
+                ival = 0;
+                do {
+                    if ((ival <= 0x1fffffff) && (len < MAX_SYMBOL_NAME_LEN)) {
+                        yylvalpp->symbol_name[len++] = ch;
+                        ii = ch - '0';
+                        ival = (ival << 3) | ii;
+                    } else if (!alreadyComplained) {
+                        CPPErrorToInfoLog("OCT CONSTANT OVERFLOW");
+                        alreadyComplained = 1;
+                    }
+                    ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
+                } while (ch >= '0' && ch <= '7');
+                if (ch == '.' || ch == 'e' || ch == 'f' || ch == 'h' || ch == 'x'|| ch == 'E') 
+                     return lFloatConst(ch, len, yylvalpp);
+                assert(len <= MAX_SYMBOL_NAME_LEN);
+                yylvalpp->symbol_name[len] = '\0';
+                cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp);
+                yylvalpp->sc_int = ival;
+                return CPP_INTCONSTANT;
+            } else {
+                cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp);
+                ch = '0';
+            }
+            // Fall through...
+        case '1': case '2': case '3': case '4':
+        case '5': case '6': case '7': case '8': case '9':
+            do {
+                APPEND_CHAR_S(ch, yylvalpp->symbol_name, len, MAX_SYMBOL_NAME_LEN);
+                ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
+            } while (ch >= '0' && ch <= '9');
+            if (ch == '.' || ch == 'e' || ch == 'E') {
+                return lFloatConst(ch, len, yylvalpp);
+            } else {
+                assert(len <= MAX_SYMBOL_NAME_LEN);
+                yylvalpp->symbol_name[len] = '\0';
+                cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp);
+                ival = 0;
+                for (ii = 0; ii < len; ii++) {
+                    ch = yylvalpp->symbol_name[ii] - '0';
+                    ival = ival*10 + ch;
+                    if ((ival > 214748364) || (ival == 214748364 && ch >= 8)) {
+                        CPPErrorToInfoLog("INTEGER CONSTANT OVERFLOW");
+                        break;
+                    }
+                }
+                yylvalpp->sc_int = ival;
+                if(ival==0)
+                   strcpy(yylvalpp->symbol_name,"0");
+                return CPP_INTCONSTANT;
+            }
+            break;
+        case '-':
+            ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
+            if (ch == '-') {
+                return CPP_DEC_OP;
+            } else if (ch == '=') {
+                return CPP_SUB_ASSIGN;
+            } else {
+                cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp);
+                return '-';
+            }
+        case '+':
+            ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
+            if (ch == '+') {
+                return CPP_INC_OP;
+            } else if (ch == '=') {
+                return CPP_ADD_ASSIGN;
+            } else {
+                cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp);
+                return '+';
+            }
+        case '*':
+            ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
+            if (ch == '=') {
+                return CPP_MUL_ASSIGN;
+            } else {
+                cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp);
+                return '*';
+            }
+        case '%':
+            ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
+            if (ch == '=') {
+                return CPP_MOD_ASSIGN;
+            } else if (ch == '>'){
+                return CPP_RIGHT_BRACE;
+            } else {
+                cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp);
+                return '%';
+            }
+        case ':':
+            ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
+            if (ch == '>') {
+                return CPP_RIGHT_BRACKET;
+            } else {
+                cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp);
+                return ':';
+            }
+        case '^':
+            ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
+            if (ch == '^') {
+                return CPP_XOR_OP;
+            } else {
+                if (ch == '=')
+                    return CPP_XOR_ASSIGN;
+                else{
+                  cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp);
+                  return '^';
+                }
+            }
+        
+        case '=':
+            ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
+            if (ch == '=') {
+                return CPP_EQ_OP;
+            } else {
+                cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp);
+                return '=';
+            }
+        case '!':
+            ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
+            if (ch == '=') {
+                return CPP_NE_OP;
+            } else {
+                cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp);
+                return '!';
+            }
+        case '|':
+            ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
+            if (ch == '|') {
+                return CPP_OR_OP;
+            } else {
+                if (ch == '=')
+                    return CPP_OR_ASSIGN;
+                else{
+                  cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp);
+                  return '|';
+                }
+            }
+        case '&':
+            ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
+            if (ch == '&') {
+                return CPP_AND_OP;
+            } else {
+                if (ch == '=')
+                    return CPP_AND_ASSIGN;
+                else{
+                  cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp);
+                  return '&';
+                }
+            }
+        case '<':
+            ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
+            if (ch == '<') {
+                ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
+                if(ch == '=')
+                    return CPP_LEFT_ASSIGN;
+                else{
+                    cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp);
+                    return CPP_LEFT_OP;
+                }
+            } else {
+                if (ch == '=') {
+                    return CPP_LE_OP;
+                } else {
+                    if (ch == '%')
+                        return CPP_LEFT_BRACE;
+                    else if (ch == ':')
+                        return CPP_LEFT_BRACKET;
+                    else{
+                        cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp);
+                        return '<';
+                    }
+                }
+            }
+        case '>':
+            ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
+            if (ch == '>') {
+                ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
+                if(ch == '=')
+                    return CPP_RIGHT_ASSIGN;
+                else{
+                    cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp);
+                    return CPP_RIGHT_OP;
+                }
+            } else {
+                if (ch == '=') {
+                    return CPP_GE_OP;
+                } else {
+                    cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp);
+                    return '>';
+                }
+            }
+        case '.':
+            ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
+            if (ch >= '0' && ch <= '9') {
+                cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp);
+                return lFloatConst('.', 0, yylvalpp);
+            } else {
+                if (ch == '.') {
+                    return -1; // Special EOF hack
+                } else {
+                    cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp);
+                    return '.';
+                }
+            }
+        case '/':
+            ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
+            if (ch == '/') {
+                do {
+                    ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
+                } while (ch != '\n' && ch != EOF);
+                if (ch == EOF)
+                    return -1;
+                return '\n';
+            } else if (ch == '*') {
+                ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
+                do {
+                    while (ch != '*') {
+                        if (ch == EOF) {
+                            CPPErrorToInfoLog("EOF IN COMMENT");
+                            return -1;
+                        }
+                        ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
+                    }
+                    ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
+                    if (ch == EOF) {
+                        CPPErrorToInfoLog("EOF IN COMMENT");
+                        return -1;
+                    }
+                } while (ch != '/');
+                // Go try it again...
+            } else if (ch == '=') {
+                return CPP_DIV_ASSIGN;
+            } else {
+                cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp);
+                return '/';
+            }
+            break;
+        case '"':
+            ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
+            while (ch != '"' && ch != '\n' && ch != EOF) {
+                if (ch == '\\') {
+                    CPPErrorToInfoLog("The line continuation character (\\) is not part of the OpenGL ES Shading Language");
+                    return -1;
+                }
+                APPEND_CHAR_S(ch, string_val, len, MAX_STRING_LEN);
+                ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
+            };
+            assert(len <= MAX_STRING_LEN);
+            string_val[len] = '\0';
+            if (ch == '"') {
+                yylvalpp->sc_ident = LookUpAddString(atable, string_val);
+                return CPP_STRCONSTANT;
+            } else {
+                CPPErrorToInfoLog("EOL IN STRING");
+                return ERROR_SY;
+            }
+            break;
+        }
+    }
+} // byte_scan
+
+int yylex_CPP(char* buf, int maxSize)
+{    
+    yystypepp yylvalpp;
+    int token = '\n';   
+
+    for(;;) {
+
+        char* tokenString = 0;
+        token = cpp->currentInput->scan(cpp->currentInput, &yylvalpp);
+        if(check_EOF(token))
+            return 0;
+        if (token < 0) {
+            // This check may need to be improved to support UTF-8
+            // characters in comments.
+            CPPErrorToInfoLog("preprocessor encountered non-ASCII character in shader source");
+            return 0;
+        }
+        if (token == '#') {
+            if (cpp->previous_token == '\n'|| cpp->previous_token == 0) {
+                token = readCPPline(&yylvalpp);
+                if(check_EOF(token))
+                    return 0;
+                continue;
+            } else {
+                CPPErrorToInfoLog("preprocessor command must not be preceded by any other statement in that line");
+                return 0;
+            }
+        }
+        cpp->previous_token = token;
+        // expand macros
+        if (token == CPP_IDENTIFIER && MacroExpand(yylvalpp.sc_ident, &yylvalpp)) {
+            cpp->pastFirstStatement = 1;
+            continue;
+        }
+
+        if (token == '\n')
+            continue;
+        cpp->pastFirstStatement = 1;
+
+        if (token == CPP_IDENTIFIER) {
+            tokenString = GetStringOfAtom(atable,yylvalpp.sc_ident);
+        } else if (token == CPP_FLOATCONSTANT || token == CPP_INTCONSTANT){
+            tokenString = yylvalpp.symbol_name;
+        } else {
+            tokenString = GetStringOfAtom(atable,token);
+        }
+
+        if (tokenString) {
+            int len = strlen(tokenString);
+            cpp->tokensBeforeEOF = 1;
+            if (len >= maxSize) {
+                return maxSize;
+            } else  if (len > 0) {
+                strcpy(buf, tokenString);
+                return len;
+            }
+
+            return 0;
+        }
+    }
+} // yylex
+
+//Checks if the token just read is EOF or not.
+int check_EOF(int token)
+{
+   if(token==-1){
+       if(cpp->ifdepth >0){
+        CPPErrorToInfoLog("#endif missing!! Compilation stopped");
+        cpp->CompileError=1;
+       }
+      return 1;
+   }
+   return 0;
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////
+/////////////////////////////////////// End of scanner.c //////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////////////////////
+
diff --git a/src/3rdparty/angle/src/compiler/preprocessor/scanner.h b/src/3rdparty/angle/src/compiler/preprocessor/scanner.h
new file mode 100644 (file)
index 0000000..b67c1d6
--- /dev/null
@@ -0,0 +1,81 @@
+/****************************************************************************\
+Copyright (c) 2002, NVIDIA Corporation.
+
+NVIDIA Corporation("NVIDIA") supplies this software to you in
+consideration of your agreement to the following terms, and your use,
+installation, modification or redistribution of this NVIDIA software
+constitutes acceptance of these terms.  If you do not agree with these
+terms, please do not use, install, modify or redistribute this NVIDIA
+software.
+
+In consideration of your agreement to abide by the following terms, and
+subject to these terms, NVIDIA grants you a personal, non-exclusive
+license, under NVIDIA's copyrights in this original NVIDIA software (the
+"NVIDIA Software"), to use, reproduce, modify and redistribute the
+NVIDIA Software, with or without modifications, in source and/or binary
+forms; provided that if you redistribute the NVIDIA Software, you must
+retain the copyright notice of NVIDIA, this notice and the following
+text and disclaimers in all such redistributions of the NVIDIA Software.
+Neither the name, trademarks, service marks nor logos of NVIDIA
+Corporation may be used to endorse or promote products derived from the
+NVIDIA Software without specific prior written permission from NVIDIA.
+Except as expressly stated in this notice, no other rights or licenses
+express or implied, are granted by NVIDIA herein, including but not
+limited to any patent rights that may be infringed by your derivative
+works or by other works in which the NVIDIA Software may be
+incorporated. No hardware is licensed hereunder. 
+
+THE NVIDIA SOFTWARE IS BEING PROVIDED ON AN "AS IS" BASIS, WITHOUT
+WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED,
+INCLUDING WITHOUT LIMITATION, WARRANTIES OR CONDITIONS OF TITLE,
+NON-INFRINGEMENT, MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR
+ITS USE AND OPERATION EITHER ALONE OR IN COMBINATION WITH OTHER
+PRODUCTS.
+
+IN NO EVENT SHALL NVIDIA BE LIABLE FOR ANY SPECIAL, INDIRECT,
+INCIDENTAL, EXEMPLARY, CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+TO, LOST PROFITS; PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) OR ARISING IN ANY WAY
+OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE
+NVIDIA SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT,
+TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF
+NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+\****************************************************************************/
+//
+// scanner.h
+//
+
+#if !defined(__SCANNER_H)
+#define __SCANNER_H 1
+
+#include "compiler/preprocessor/length_limits.h"
+#include "compiler/preprocessor/parser.h"
+
+// Not really atom table stuff but needed first...
+
+typedef struct SourceLoc_Rec {
+    unsigned short file, line;
+} SourceLoc;
+
+int yylex_CPP(char* buf, int maxSize);
+
+typedef struct InputSrc {
+    struct InputSrc    *prev;
+    int                        (*scan)(struct InputSrc *, yystypepp *);
+    int                        (*getch)(struct InputSrc *, yystypepp *);
+    void               (*ungetch)(struct InputSrc *, int, yystypepp *);
+    int                        name;  /* atom */
+    int                        line;
+} InputSrc;
+
+int InitScanner(CPPStruct *cpp);   // Intialise the cpp scanner. 
+int InitScannerInput(CPPStruct *cpp, int count, const char* const string[], const int length[]);
+int check_EOF(int);              // check if we hit a EOF abruptly 
+void CPPErrorToInfoLog(const char *);   // sticking the msg,line into the Shader's.Info.log
+void SetLineNumber(int);
+void SetStringNumber(int);
+void IncLineNumber(void);
+void DecLineNumber(void);
+int FreeScanner(void);                 // Free the cpp scanner
+#endif // !(defined(__SCANNER_H)
+
diff --git a/src/3rdparty/angle/src/compiler/preprocessor/slglobals.h b/src/3rdparty/angle/src/compiler/preprocessor/slglobals.h
new file mode 100644 (file)
index 0000000..4634626
--- /dev/null
@@ -0,0 +1,82 @@
+/****************************************************************************\
+Copyright (c) 2002, NVIDIA Corporation.
+
+NVIDIA Corporation("NVIDIA") supplies this software to you in
+consideration of your agreement to the following terms, and your use,
+installation, modification or redistribution of this NVIDIA software
+constitutes acceptance of these terms.  If you do not agree with these
+terms, please do not use, install, modify or redistribute this NVIDIA
+software.
+
+In consideration of your agreement to abide by the following terms, and
+subject to these terms, NVIDIA grants you a personal, non-exclusive
+license, under NVIDIA's copyrights in this original NVIDIA software (the
+"NVIDIA Software"), to use, reproduce, modify and redistribute the
+NVIDIA Software, with or without modifications, in source and/or binary
+forms; provided that if you redistribute the NVIDIA Software, you must
+retain the copyright notice of NVIDIA, this notice and the following
+text and disclaimers in all such redistributions of the NVIDIA Software.
+Neither the name, trademarks, service marks nor logos of NVIDIA
+Corporation may be used to endorse or promote products derived from the
+NVIDIA Software without specific prior written permission from NVIDIA.
+Except as expressly stated in this notice, no other rights or licenses
+express or implied, are granted by NVIDIA herein, including but not
+limited to any patent rights that may be infringed by your derivative
+works or by other works in which the NVIDIA Software may be
+incorporated. No hardware is licensed hereunder. 
+
+THE NVIDIA SOFTWARE IS BEING PROVIDED ON AN "AS IS" BASIS, WITHOUT
+WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED,
+INCLUDING WITHOUT LIMITATION, WARRANTIES OR CONDITIONS OF TITLE,
+NON-INFRINGEMENT, MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR
+ITS USE AND OPERATION EITHER ALONE OR IN COMBINATION WITH OTHER
+PRODUCTS.
+
+IN NO EVENT SHALL NVIDIA BE LIABLE FOR ANY SPECIAL, INDIRECT,
+INCIDENTAL, EXEMPLARY, CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+TO, LOST PROFITS; PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) OR ARISING IN ANY WAY
+OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE
+NVIDIA SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT,
+TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF
+NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+\****************************************************************************/
+//
+// slglobals.h
+//
+
+#if !defined(__SLGLOBALS_H)
+#define __SLGLOBALS_H 1
+
+typedef struct CPPStruct_Rec CPPStruct;
+
+extern CPPStruct *cpp;
+
+#undef  CPPC_DEBUG_THE_COMPILER
+#if defined(_DEBUG)
+#define CPPC_DEBUG_THE_COMPILER 1
+#endif
+
+#undef  CPPC_ENABLE_TOOLS
+#define CPPC_ENABLE_TOOLS 1
+
+#include "compiler/preprocessor/memory.h"
+#include "compiler/preprocessor/atom.h"
+#include "compiler/preprocessor/scanner.h"
+#include "compiler/preprocessor/cpp.h"
+#include "compiler/preprocessor/tokens.h"
+#include "compiler/preprocessor/symbols.h"
+#include "compiler/preprocessor/compile.h"
+#if !defined(NO_PARSER)
+#include "compiler/preprocessor/parser.h"
+#endif
+
+#if !defined(NULL)
+#define NULL 0
+#endif
+
+#endif // !(defined(__SLGLOBALS_H)
+
+
+    
+
diff --git a/src/3rdparty/angle/src/compiler/preprocessor/symbols.c b/src/3rdparty/angle/src/compiler/preprocessor/symbols.c
new file mode 100644 (file)
index 0000000..f18b256
--- /dev/null
@@ -0,0 +1,288 @@
+/****************************************************************************\
+Copyright (c) 2002, NVIDIA Corporation.
+
+NVIDIA Corporation("NVIDIA") supplies this software to you in
+consideration of your agreement to the following terms, and your use,
+installation, modification or redistribution of this NVIDIA software
+constitutes acceptance of these terms.  If you do not agree with these
+terms, please do not use, install, modify or redistribute this NVIDIA
+software.
+
+In consideration of your agreement to abide by the following terms, and
+subject to these terms, NVIDIA grants you a personal, non-exclusive
+license, under NVIDIA's copyrights in this original NVIDIA software (the
+"NVIDIA Software"), to use, reproduce, modify and redistribute the
+NVIDIA Software, with or without modifications, in source and/or binary
+forms; provided that if you redistribute the NVIDIA Software, you must
+retain the copyright notice of NVIDIA, this notice and the following
+text and disclaimers in all such redistributions of the NVIDIA Software.
+Neither the name, trademarks, service marks nor logos of NVIDIA
+Corporation may be used to endorse or promote products derived from the
+NVIDIA Software without specific prior written permission from NVIDIA.
+Except as expressly stated in this notice, no other rights or licenses
+express or implied, are granted by NVIDIA herein, including but not
+limited to any patent rights that may be infringed by your derivative
+works or by other works in which the NVIDIA Software may be
+incorporated. No hardware is licensed hereunder. 
+
+THE NVIDIA SOFTWARE IS BEING PROVIDED ON AN "AS IS" BASIS, WITHOUT
+WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED,
+INCLUDING WITHOUT LIMITATION, WARRANTIES OR CONDITIONS OF TITLE,
+NON-INFRINGEMENT, MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR
+ITS USE AND OPERATION EITHER ALONE OR IN COMBINATION WITH OTHER
+PRODUCTS.
+
+IN NO EVENT SHALL NVIDIA BE LIABLE FOR ANY SPECIAL, INDIRECT,
+INCIDENTAL, EXEMPLARY, CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+TO, LOST PROFITS; PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) OR ARISING IN ANY WAY
+OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE
+NVIDIA SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT,
+TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF
+NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+\****************************************************************************/
+//
+// symbols.c
+//
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "compiler/preprocessor/slglobals.h"
+
+#if defined(_MSC_VER)
+#pragma warning(disable: 4706)
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////////
+/////////////////////////////////// Symbol Table Variables: ///////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////////////////////
+
+Scope *ScopeList = NULL;
+Scope *CurrentScope = NULL;
+Scope *GlobalScope = NULL;
+
+static void unlinkScope(void *_scope) {
+    Scope *scope = _scope;
+
+    if (scope->next)
+        scope->next->prev = scope->prev;
+    if (scope->prev)
+        scope->prev->next = scope->next;
+    else
+        ScopeList = scope->next;
+}
+
+/*
+ * NewScope()
+ *
+ */
+Scope *NewScopeInPool(MemoryPool *pool)
+{
+    Scope *lScope;
+
+    lScope = mem_Alloc(pool, sizeof(Scope));
+    lScope->pool = pool;
+    lScope->parent = NULL;
+    lScope->funScope = NULL;
+    lScope->symbols = NULL;
+    
+    lScope->level = 0;
+
+    lScope->programs = NULL;
+    if ((lScope->next = ScopeList))
+        ScopeList->prev = lScope;
+    lScope->prev = 0;
+    ScopeList = lScope;
+    mem_AddCleanup(pool, unlinkScope, lScope);
+    return lScope;
+} // NewScope
+
+/*
+ * PushScope()
+ *
+ */
+
+void PushScope(Scope *fScope)
+{
+    Scope *lScope;
+
+    if (CurrentScope) {
+        fScope->level = CurrentScope->level + 1;
+        if (fScope->level == 1) {
+            if (!GlobalScope) {
+                /* HACK - CTD -- if GlobalScope==NULL and level==1, we're
+                 * defining a function in the superglobal scope.  Things
+                 * will break if we leave the level as 1, so we arbitrarily
+                 * set it to 2 */
+                fScope->level = 2;
+            }
+        }
+        if (fScope->level >= 2) {
+            lScope = fScope;
+            while (lScope->level > 2)
+                lScope = lScope->next;
+            fScope->funScope = lScope;
+        }
+    } else {
+        fScope->level = 0;
+    }
+    fScope->parent = CurrentScope;
+    CurrentScope = fScope;
+} // PushScope
+
+/*
+ * PopScope()
+ *
+ */
+
+Scope *PopScope(void)
+{
+    Scope *lScope;
+
+    lScope = CurrentScope;
+    if (CurrentScope)
+        CurrentScope = CurrentScope->parent;
+    return lScope;
+} // PopScope
+
+/*
+ * NewSymbol() - Allocate a new symbol node;
+ *
+ */
+
+Symbol *NewSymbol(SourceLoc *loc, Scope *fScope, int name, symbolkind kind)
+{
+    Symbol *lSymb;
+    char *pch;
+    unsigned int ii;
+
+    lSymb = (Symbol *) mem_Alloc(fScope->pool, sizeof(Symbol));
+    lSymb->left = NULL;
+    lSymb->right = NULL;
+    lSymb->next = NULL;
+    lSymb->name = name;
+    lSymb->loc = *loc;
+    lSymb->kind = kind;
+    
+    // Clear union area:
+
+    pch = (char *) &lSymb->details;
+    for (ii = 0; ii < sizeof(lSymb->details); ii++)
+        *pch++ = 0;
+    return lSymb;
+} // NewSymbol
+
+/*
+ * lAddToTree() - Using a binary tree is not a good idea for basic atom values because they
+ *         are generated in order.  We'll fix this later (by reversing the bit pattern).
+ */
+
+static void lAddToTree(Symbol **fSymbols, Symbol *fSymb)
+{
+    Symbol *lSymb;
+    int lrev, frev;
+
+    lSymb = *fSymbols;
+    if (lSymb) {
+        frev = GetReversedAtom(atable, fSymb->name);
+        while (lSymb) {
+            lrev = GetReversedAtom(atable, lSymb->name);
+            if (lrev == frev) {
+                CPPErrorToInfoLog("GetAtomString(atable, fSymb->name)");
+                break;
+            } else {
+                if (lrev > frev) {
+                    if (lSymb->left) {
+                        lSymb = lSymb->left;
+                    } else {
+                        lSymb->left = fSymb;
+                        break;
+                    }
+                } else {
+                    if (lSymb->right) {
+                        lSymb = lSymb->right;
+                    } else {
+                        lSymb->right = fSymb;
+                        break;
+                    }
+                }
+            }
+        }
+    } else {
+        *fSymbols = fSymb;
+    }
+} // lAddToTree
+
+
+/*
+ * AddSymbol() - Add a variable, type, or function name to a scope.
+ *
+ */
+
+Symbol *AddSymbol(SourceLoc *loc, Scope *fScope, int atom, symbolkind kind)
+{
+    Symbol *lSymb;
+
+    if (!fScope)
+        fScope = CurrentScope;
+    lSymb = NewSymbol(loc, fScope, atom, kind);
+    lAddToTree(&fScope->symbols, lSymb);
+    return lSymb;
+} // AddSymbol
+
+
+/*********************************************************************************************/
+/************************************ Symbol Semantic Functions ******************************/
+/*********************************************************************************************/
+
+/*
+ * LookUpLocalSymbol()
+ *
+ */
+
+Symbol *LookUpLocalSymbol(Scope *fScope, int atom)
+{
+    Symbol *lSymb;
+    int rname, ratom;
+
+    ratom = GetReversedAtom(atable, atom);
+    if (!fScope)
+        fScope = CurrentScope;
+    lSymb = fScope->symbols;
+    while (lSymb) {
+        rname = GetReversedAtom(atable, lSymb->name);
+        if (rname == ratom) {
+            return lSymb;
+        } else {
+            if (rname > ratom) {
+                lSymb = lSymb->left;
+            } else {
+                lSymb = lSymb->right;
+            }
+        }
+    }
+    return NULL;
+} // LookUpLocalSymbol
+
+/*
+ * LookUpSymbol()
+ *
+ */
+
+Symbol *LookUpSymbol(Scope *fScope, int atom)
+{
+    Symbol *lSymb;
+
+    if (!fScope)
+        fScope = CurrentScope;
+    while (fScope) {
+        lSymb = LookUpLocalSymbol(fScope, atom);
+        if (lSymb)
+            return lSymb;
+        fScope = fScope->parent;
+    }
+    return NULL;
+} // LookUpSymbol
+
diff --git a/src/3rdparty/angle/src/compiler/preprocessor/symbols.h b/src/3rdparty/angle/src/compiler/preprocessor/symbols.h
new file mode 100644 (file)
index 0000000..e7d0b07
--- /dev/null
@@ -0,0 +1,111 @@
+/****************************************************************************\
+Copyright (c) 2002, NVIDIA Corporation.
+
+NVIDIA Corporation("NVIDIA") supplies this software to you in
+consideration of your agreement to the following terms, and your use,
+installation, modification or redistribution of this NVIDIA software
+constitutes acceptance of these terms.  If you do not agree with these
+terms, please do not use, install, modify or redistribute this NVIDIA
+software.
+
+In consideration of your agreement to abide by the following terms, and
+subject to these terms, NVIDIA grants you a personal, non-exclusive
+license, under NVIDIA's copyrights in this original NVIDIA software (the
+"NVIDIA Software"), to use, reproduce, modify and redistribute the
+NVIDIA Software, with or without modifications, in source and/or binary
+forms; provided that if you redistribute the NVIDIA Software, you must
+retain the copyright notice of NVIDIA, this notice and the following
+text and disclaimers in all such redistributions of the NVIDIA Software.
+Neither the name, trademarks, service marks nor logos of NVIDIA
+Corporation may be used to endorse or promote products derived from the
+NVIDIA Software without specific prior written permission from NVIDIA.
+Except as expressly stated in this notice, no other rights or licenses
+express or implied, are granted by NVIDIA herein, including but not
+limited to any patent rights that may be infringed by your derivative
+works or by other works in which the NVIDIA Software may be
+incorporated. No hardware is licensed hereunder. 
+
+THE NVIDIA SOFTWARE IS BEING PROVIDED ON AN "AS IS" BASIS, WITHOUT
+WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED,
+INCLUDING WITHOUT LIMITATION, WARRANTIES OR CONDITIONS OF TITLE,
+NON-INFRINGEMENT, MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR
+ITS USE AND OPERATION EITHER ALONE OR IN COMBINATION WITH OTHER
+PRODUCTS.
+
+IN NO EVENT SHALL NVIDIA BE LIABLE FOR ANY SPECIAL, INDIRECT,
+INCIDENTAL, EXEMPLARY, CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+TO, LOST PROFITS; PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) OR ARISING IN ANY WAY
+OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE
+NVIDIA SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT,
+TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF
+NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+\****************************************************************************/
+//
+// symbols.h
+//
+
+#if !defined(__SYMBOLS_H)
+#define __SYMBOLS_H 1
+
+#include "compiler/preprocessor/memory.h"
+
+typedef enum symbolkind {
+   MACRO_S
+} symbolkind;
+
+// Typedefs for things defined here in "symbols.h":
+
+typedef struct Scope_Rec Scope;
+typedef struct Symbol_Rec Symbol;
+
+typedef struct SymbolList_Rec {
+    struct SymbolList_Rec *next;
+    Symbol *symb;
+} SymbolList;
+
+struct Scope_Rec {
+    Scope *next, *prev;     // doubly-linked list of all scopes
+    Scope *parent;
+    Scope *funScope;        // Points to base scope of enclosing function
+    MemoryPool *pool;       // pool used for allocation in this scope
+    Symbol *symbols;
+    
+       int level;              // 0 = super globals, 1 = globals, etc.
+
+    // Only used at global scope (level 1):
+    SymbolList *programs;   // List of programs for this compilation.
+};
+
+
+// Symbol table is a simple binary tree.
+
+#include "compiler/preprocessor/cpp.h"        // to get MacroSymbol def
+
+struct Symbol_Rec {
+    Symbol *left, *right;
+    Symbol *next;
+    int name;       // Name atom
+    SourceLoc loc;
+    symbolkind kind;
+    union {
+        MacroSymbol mac;
+    } details;
+};
+
+extern Scope *CurrentScope;
+extern Scope *GlobalScope;
+extern Scope *ScopeList;
+
+Scope *NewScopeInPool(MemoryPool *);
+#define NewScope()      NewScopeInPool(CurrentScope->pool)
+void PushScope(Scope *fScope);
+Scope *PopScope(void);
+Symbol *NewSymbol(SourceLoc *loc, Scope *fScope, int name, symbolkind kind);
+Symbol *AddSymbol(SourceLoc *loc, Scope *fScope, int atom, symbolkind kind);
+Symbol *LookUpLocalSymbol(Scope *fScope, int atom);
+Symbol *LookUpSymbol(Scope *fScope, int atom);
+
+
+#endif // !defined(__SYMBOLS_H)
+
diff --git a/src/3rdparty/angle/src/compiler/preprocessor/tokens.c b/src/3rdparty/angle/src/compiler/preprocessor/tokens.c
new file mode 100644 (file)
index 0000000..b94c05e
--- /dev/null
@@ -0,0 +1,467 @@
+/****************************************************************************\
+Copyright (c) 2002, NVIDIA Corporation.
+
+NVIDIA Corporation("NVIDIA") supplies this software to you in
+consideration of your agreement to the following terms, and your use,
+installation, modification or redistribution of this NVIDIA software
+constitutes acceptance of these terms.  If you do not agree with these
+terms, please do not use, install, modify or redistribute this NVIDIA
+software.
+
+In consideration of your agreement to abide by the following terms, and
+subject to these terms, NVIDIA grants you a personal, non-exclusive
+license, under NVIDIA's copyrights in this original NVIDIA software (the
+"NVIDIA Software"), to use, reproduce, modify and redistribute the
+NVIDIA Software, with or without modifications, in source and/or binary
+forms; provided that if you redistribute the NVIDIA Software, you must
+retain the copyright notice of NVIDIA, this notice and the following
+text and disclaimers in all such redistributions of the NVIDIA Software.
+Neither the name, trademarks, service marks nor logos of NVIDIA
+Corporation may be used to endorse or promote products derived from the
+NVIDIA Software without specific prior written permission from NVIDIA.
+Except as expressly stated in this notice, no other rights or licenses
+express or implied, are granted by NVIDIA herein, including but not
+limited to any patent rights that may be infringed by your derivative
+works or by other works in which the NVIDIA Software may be
+incorporated. No hardware is licensed hereunder. 
+
+THE NVIDIA SOFTWARE IS BEING PROVIDED ON AN "AS IS" BASIS, WITHOUT
+WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED,
+INCLUDING WITHOUT LIMITATION, WARRANTIES OR CONDITIONS OF TITLE,
+NON-INFRINGEMENT, MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR
+ITS USE AND OPERATION EITHER ALONE OR IN COMBINATION WITH OTHER
+PRODUCTS.
+
+IN NO EVENT SHALL NVIDIA BE LIABLE FOR ANY SPECIAL, INDIRECT,
+INCIDENTAL, EXEMPLARY, CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+TO, LOST PROFITS; PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) OR ARISING IN ANY WAY
+OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE
+NVIDIA SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT,
+TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF
+NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+\****************************************************************************/
+//
+// tokens.c
+//
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+
+#include "common/angleutils.h"
+#include "compiler/debug.h"
+#include "compiler/preprocessor/slglobals.h"
+#include "compiler/util.h"
+
+#if defined(_MSC_VER)
+#pragma warning(disable: 4054)
+#pragma warning(disable: 4152)
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////////
+//////////////////////// Preprocessor and Token Recorder and Playback: ////////////////////////
+///////////////////////////////////////////////////////////////////////////////////////////////
+
+/*
+ * idstr()
+ * Copy a string to a malloc'ed block and convert it into something suitable
+ * for an ID
+ *
+ */
+
+static char *idstr(const char *fstr, MemoryPool *pool)
+{
+    size_t len;
+    char *str, *t;
+    const char *f;
+
+    len = strlen(fstr);
+    if (!pool)
+        str = (char *) malloc(len + 1);
+    else
+        str = (char *) mem_Alloc(pool, len + 1);
+    
+    for (f=fstr, t=str; *f; f++) {
+        if (isalnum(*f)) *t++ = *f;
+        else if (*f == '.' || *f == '/') *t++ = '_';
+    }
+    *t = 0;
+    return str;
+} // idstr
+
+
+/*
+ * lNewBlock()
+ *
+ */
+
+static TokenBlock *lNewBlock(TokenStream *fTok, MemoryPool *pool)
+{
+    TokenBlock *lBlock;
+
+    if (!pool)
+        lBlock = (TokenBlock *) malloc(sizeof(TokenBlock) + 256);
+    else
+        lBlock = (TokenBlock *) mem_Alloc(pool, sizeof(TokenBlock) + 256);
+    lBlock->count = 0;
+    lBlock->current = 0;
+    lBlock->data = (unsigned char *) lBlock + sizeof(TokenBlock);
+    lBlock->max = 256;
+    lBlock->next = NULL;
+    if (fTok->head) {
+        fTok->current->next = lBlock;
+    } else {
+        fTok->head = lBlock;
+    }
+    fTok->current = lBlock;
+    return lBlock;
+} // lNewBlock
+
+/*
+ * lAddByte()
+ *
+ */
+
+static void lAddByte(TokenStream *fTok, unsigned char fVal)
+{
+    TokenBlock *lBlock;
+    lBlock = fTok->current;
+    if (lBlock->count >= lBlock->max)
+        lBlock = lNewBlock(fTok, 0);
+    lBlock->data[lBlock->count++] = fVal;
+} // lAddByte
+
+
+
+/*
+ * lReadByte() - Get the next byte from a stream.
+ *
+ */
+
+static int lReadByte(TokenStream *pTok)
+{
+    TokenBlock *lBlock;
+    int lval = -1;
+
+    lBlock = pTok->current;
+    if (lBlock) {
+        if (lBlock->current >= lBlock->count) {
+            lBlock = lBlock->next;
+            if (lBlock)
+                lBlock->current = 0;
+            pTok->current = lBlock;
+        }
+        if (lBlock)
+            lval = lBlock->data[lBlock->current++];
+    }
+    return lval;
+} // lReadByte
+
+/////////////////////////////////////// Global Functions://////////////////////////////////////
+
+/*
+ * NewTokenStream()
+ *
+ */
+
+TokenStream *NewTokenStream(const char *name, MemoryPool *pool)
+{
+    TokenStream *pTok;
+
+    if (!pool)
+        pTok = (TokenStream *) malloc(sizeof(TokenStream));
+    else
+        pTok = (TokenStream*)mem_Alloc(pool, sizeof(TokenStream));
+    pTok->next = NULL;
+    pTok->name = idstr(name, pool);
+    pTok->head = NULL;
+    pTok->current = NULL;
+    lNewBlock(pTok, pool);
+    return pTok;
+} // NewTokenStream
+
+/*
+ * DeleteTokenStream()
+ *
+ */
+
+void DeleteTokenStream(TokenStream *pTok)
+{
+    TokenBlock *pBlock, *nBlock;
+
+    if (pTok) {
+        pBlock = pTok->head;
+        while (pBlock) {
+            nBlock = pBlock->next;
+            free(pBlock);
+            pBlock = nBlock;
+        }
+        if (pTok->name)
+            free(pTok->name);
+        free(pTok);
+    }
+} // DeleteTokenStream
+
+/*
+ * RecordToken() - Add a token to the end of a list for later playback or printout.
+ *
+ */
+
+void RecordToken(TokenStream *pTok, int token, yystypepp * yylvalpp)
+{
+    const char *s;
+    char *str=NULL;
+
+    if (token > 256)
+        lAddByte(pTok, (unsigned char)((token & 0x7f) + 0x80));
+    else
+        lAddByte(pTok, (unsigned char)(token & 0x7f));
+    switch (token) {
+    case CPP_IDENTIFIER:
+    case CPP_TYPEIDENTIFIER:
+    case CPP_STRCONSTANT:
+        s = GetAtomString(atable, yylvalpp->sc_ident);
+        while (*s)
+            lAddByte(pTok, (unsigned char) *s++);
+        lAddByte(pTok, 0);
+        break;
+    case CPP_FLOATCONSTANT:
+    case CPP_INTCONSTANT:
+         str=yylvalpp->symbol_name;
+         while (*str){
+            lAddByte(pTok, (unsigned char) *str++);
+         }
+         lAddByte(pTok, 0);
+         break;
+    case '(':
+        lAddByte(pTok, (unsigned char)(yylvalpp->sc_int ? 1 : 0));
+    default:
+        break;
+    }
+} // RecordToken
+
+/*
+ * RewindTokenStream() - Reset a token stream in preperation for reading.
+ *
+ */
+
+void RewindTokenStream(TokenStream *pTok)
+{
+    if (pTok->head) {
+        pTok->current = pTok->head;
+        pTok->current->current = 0;
+    }
+} // RewindTokenStream
+
+/*
+ * ReadToken() - Read the next token from a stream.
+ *
+ */
+
+int ReadToken(TokenStream *pTok, yystypepp * yylvalpp)
+{
+    char symbol_name[MAX_SYMBOL_NAME_LEN + 1];
+    char string_val[MAX_STRING_LEN + 1];
+    int ltoken, len;
+    char ch;
+    int base, accum;
+    char ch_val;
+
+    ltoken = lReadByte(pTok);
+    if (ltoken >= 0) {
+        if (ltoken > 127)
+            ltoken += 128;
+        switch (ltoken) {
+        case CPP_IDENTIFIER:
+        case CPP_TYPEIDENTIFIER:
+            len = 0;
+            ch = lReadByte(pTok);
+            while ((ch >= 'a' && ch <= 'z') ||
+                     (ch >= 'A' && ch <= 'Z') ||
+                     (ch >= '0' && ch <= '9') ||
+                     ch == '_')
+            {
+                if (len < MAX_SYMBOL_NAME_LEN) {
+                    symbol_name[len++] = ch;
+                    ch = lReadByte(pTok);
+                }
+            }
+            symbol_name[len] = '\0';
+            assert(ch == '\0');
+            yylvalpp->sc_ident = LookUpAddString(atable, symbol_name);
+            return CPP_IDENTIFIER;
+            break;
+        case CPP_STRCONSTANT:
+            len = 0;
+            while ((ch = lReadByte(pTok)) != 0)
+                if (len < MAX_STRING_LEN)
+                    string_val[len++] = ch;
+            string_val[len] = '\0';
+            yylvalpp->sc_ident = LookUpAddString(atable, string_val);
+            break;
+        case CPP_FLOATCONSTANT:
+            len = 0;
+            ch = lReadByte(pTok);
+            while ((ch >= '0' && ch <= '9')||(ch=='e'||ch=='E'||ch=='.')||(ch=='+'||ch=='-'))
+            {
+                if (len < MAX_SYMBOL_NAME_LEN) {
+                    symbol_name[len++] = ch;
+                    ch = lReadByte(pTok);
+                }
+            }
+            symbol_name[len] = '\0';
+            assert(ch == '\0');
+            strcpy(yylvalpp->symbol_name,symbol_name);
+            yylvalpp->sc_fval=(float)atof_dot(yylvalpp->symbol_name);
+            break;
+        case CPP_INTCONSTANT:
+            len = 0;
+           accum = 0;
+            ch = lReadByte(pTok);
+            if (ch == '0') {
+                symbol_name[len++] = ch;
+                ch = lReadByte(pTok);
+                if (ch == 'x' || ch == 'X') {
+                    symbol_name[len++] = ch;
+                    base = 16;
+                    ch = lReadByte(pTok);
+                } else {
+                    base = 8;
+                }
+            } else {
+                base = 10;
+            }
+
+            while (len < MAX_SYMBOL_NAME_LEN)
+            {
+                ch_val = -1;
+                if (isdigit(ch))
+                    ch_val = ch - '0';
+                else if (isxdigit(ch))
+                    ch_val = tolower(ch) - 'a' + 10;
+
+                if (ch_val < 0 || ch_val >= base)
+                    break;
+
+                symbol_name[len++] = ch;
+                accum = accum * base + ch_val;
+                ch = lReadByte(pTok);
+            }
+            symbol_name[len] = '\0';
+            assert(ch == '\0');
+            strcpy(yylvalpp->symbol_name, symbol_name);
+            yylvalpp->sc_int = accum;
+            break;
+        case '(':
+            yylvalpp->sc_int = lReadByte(pTok);
+            break;
+        }
+        return ltoken;
+    }
+    return EOF_SY;
+} // ReadToken
+
+typedef struct TokenInputSrc {
+    InputSrc            base;
+    TokenStream         *tokens;
+    int                 (*final)(CPPStruct *);
+} TokenInputSrc;
+
+static int scan_token(TokenInputSrc *in, yystypepp * yylvalpp)
+{
+    int token = ReadToken(in->tokens, yylvalpp);
+    int (*final)(CPPStruct *);
+    cpp->tokenLoc->file = cpp->currentInput->name;
+    cpp->tokenLoc->line = cpp->currentInput->line;
+    if (token == '\n') {
+        in->base.line++;
+        return token;
+    }
+    if (token > 0) return token;
+    cpp->currentInput = in->base.prev;
+    final = in->final;
+    free(in);
+    if (final && !final(cpp)) return -1;
+    return cpp->currentInput->scan(cpp->currentInput, yylvalpp);
+}
+
+int ReadFromTokenStream(TokenStream *ts, int name, int (*final)(CPPStruct *))
+{
+    TokenInputSrc *in = malloc(sizeof(TokenInputSrc));
+    memset(in, 0, sizeof(TokenInputSrc));
+    in->base.name = name;
+    in->base.prev = cpp->currentInput;
+    in->base.scan = (int (*)(InputSrc *, yystypepp *))scan_token;
+    in->base.line = 1;
+    in->tokens = ts;
+    in->final = final;
+    RewindTokenStream(ts);
+    cpp->currentInput = &in->base;
+    return 1;
+}
+
+typedef struct UngotToken {
+    InputSrc    base;
+    int         token;
+    yystypepp     lval;
+} UngotToken;
+
+static int reget_token(UngotToken *t, yystypepp * yylvalpp)
+{
+    int token = t->token;
+    *yylvalpp = t->lval;
+    cpp->currentInput = t->base.prev;
+    free(t);
+    return token;
+}
+
+void UngetToken(int token, yystypepp * yylvalpp) {
+    UngotToken *t = malloc(sizeof(UngotToken));
+    memset(t, 0, sizeof(UngotToken));
+    t->token = token;
+    t->lval = *yylvalpp;
+    t->base.scan = (void *)reget_token;
+    t->base.prev = cpp->currentInput;
+    t->base.name = cpp->currentInput->name;
+    t->base.line = cpp->currentInput->line;
+    cpp->currentInput = &t->base;
+}
+
+
+void DumpTokenStream(FILE *fp, TokenStream *s, yystypepp * yylvalpp) {
+    int token;
+    char str[100];
+
+    if (fp == 0) fp = stdout;
+    RewindTokenStream(s);
+    while ((token = ReadToken(s, yylvalpp)) > 0) {
+        switch (token) {
+        case CPP_IDENTIFIER:
+        case CPP_TYPEIDENTIFIER:
+            snprintf(str, sizeof(str), "%s ", GetAtomString(atable, yylvalpp->sc_ident));
+            break;
+        case CPP_STRCONSTANT:
+            snprintf(str, sizeof(str), "\"%s\"", GetAtomString(atable, yylvalpp->sc_ident));
+            break;
+        case CPP_FLOATCONSTANT:
+            //printf("%g9.6 ", yylvalpp->sc_fval);
+            break;
+        case CPP_INTCONSTANT:
+            //printf("%d ", yylvalpp->sc_int);
+            break;
+        default:
+            if (token >= 127)
+                snprintf(str, sizeof(str), "%s ", GetAtomString(atable, token));
+            else
+                snprintf(str, sizeof(str), "%c", token);
+            break;
+        }
+        CPPDebugLogMsg(str);
+    }
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////
+/////////////////////////////////////// End of tokens.c ///////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////////////////////
diff --git a/src/3rdparty/angle/src/compiler/preprocessor/tokens.h b/src/3rdparty/angle/src/compiler/preprocessor/tokens.h
new file mode 100644 (file)
index 0000000..dbf4a2c
--- /dev/null
@@ -0,0 +1,90 @@
+/****************************************************************************\
+Copyright (c) 2002, NVIDIA Corporation.
+
+NVIDIA Corporation("NVIDIA") supplies this software to you in
+consideration of your agreement to the following terms, and your use,
+installation, modification or redistribution of this NVIDIA software
+constitutes acceptance of these terms.  If you do not agree with these
+terms, please do not use, install, modify or redistribute this NVIDIA
+software.
+
+In consideration of your agreement to abide by the following terms, and
+subject to these terms, NVIDIA grants you a personal, non-exclusive
+license, under NVIDIA's copyrights in this original NVIDIA software (the
+"NVIDIA Software"), to use, reproduce, modify and redistribute the
+NVIDIA Software, with or without modifications, in source and/or binary
+forms; provided that if you redistribute the NVIDIA Software, you must
+retain the copyright notice of NVIDIA, this notice and the following
+text and disclaimers in all such redistributions of the NVIDIA Software.
+Neither the name, trademarks, service marks nor logos of NVIDIA
+Corporation may be used to endorse or promote products derived from the
+NVIDIA Software without specific prior written permission from NVIDIA.
+Except as expressly stated in this notice, no other rights or licenses
+express or implied, are granted by NVIDIA herein, including but not
+limited to any patent rights that may be infringed by your derivative
+works or by other works in which the NVIDIA Software may be
+incorporated. No hardware is licensed hereunder. 
+
+THE NVIDIA SOFTWARE IS BEING PROVIDED ON AN "AS IS" BASIS, WITHOUT
+WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED,
+INCLUDING WITHOUT LIMITATION, WARRANTIES OR CONDITIONS OF TITLE,
+NON-INFRINGEMENT, MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR
+ITS USE AND OPERATION EITHER ALONE OR IN COMBINATION WITH OTHER
+PRODUCTS.
+
+IN NO EVENT SHALL NVIDIA BE LIABLE FOR ANY SPECIAL, INDIRECT,
+INCIDENTAL, EXEMPLARY, CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+TO, LOST PROFITS; PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) OR ARISING IN ANY WAY
+OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE
+NVIDIA SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT,
+TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF
+NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+\****************************************************************************/
+//
+// tokens.h
+//
+
+#if !defined(__TOKENS_H)
+#define __TOKENS_H 1
+
+#include <stdio.h>
+#include "compiler/preprocessor/parser.h"
+
+#define EOF_SY (-1)
+
+typedef struct TokenBlock_Rec TokenBlock;
+
+typedef struct TokenStream_Rec {
+    struct TokenStream_Rec *next;
+    char *name;
+    TokenBlock *head;
+    TokenBlock *current;
+} TokenStream;
+
+struct TokenBlock_Rec {
+    TokenBlock *next;
+    int current;
+    int count;
+    int max;
+    unsigned char *data;
+};
+
+extern TokenStream stdlib_cpp_stream;
+
+
+TokenStream *NewTokenStream(const char *name, MemoryPool *pool);
+void DeleteTokenStream(TokenStream *pTok); 
+void RecordToken(TokenStream *pTok, int token, yystypepp * yylvalpp);
+void RewindTokenStream(TokenStream *pTok);
+int ReadToken(TokenStream *pTok, yystypepp * yylvalpp);
+int ReadFromTokenStream(TokenStream *pTok, int name, int (*final)(CPPStruct *));
+void UngetToken(int, yystypepp * yylvalpp);
+
+#if defined(CPPC_ENABLE_TOOLS)
+
+void DumpTokenStream(FILE *, TokenStream *, yystypepp * yylvalpp);
+
+#endif // defined(CPPC_ENABLE_TOOLS)
+
+#endif // !defined(__TOKENS_H)
diff --git a/src/3rdparty/angle/src/compiler/timing/RestrictFragmentShaderTiming.cpp b/src/3rdparty/angle/src/compiler/timing/RestrictFragmentShaderTiming.cpp
new file mode 100644 (file)
index 0000000..538b731
--- /dev/null
@@ -0,0 +1,127 @@
+//
+// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "compiler/InfoSink.h"
+#include "compiler/ParseHelper.h"
+#include "compiler/depgraph/DependencyGraphOutput.h"
+#include "compiler/timing/RestrictFragmentShaderTiming.h"
+
+RestrictFragmentShaderTiming::RestrictFragmentShaderTiming(TInfoSinkBase& sink)
+    : mSink(sink)
+    , mNumErrors(0)
+{
+    // Sampling ops found only in fragment shaders.
+    mSamplingOps.insert("texture2D(s21;vf2;f1;");
+    mSamplingOps.insert("texture2DProj(s21;vf3;f1;");
+    mSamplingOps.insert("texture2DProj(s21;vf4;f1;");
+    mSamplingOps.insert("textureCube(sC1;vf3;f1;");
+    // Sampling ops found in both vertex and fragment shaders.
+    mSamplingOps.insert("texture2D(s21;vf2;");
+    mSamplingOps.insert("texture2DProj(s21;vf3;");
+    mSamplingOps.insert("texture2DProj(s21;vf4;");
+    mSamplingOps.insert("textureCube(sC1;vf3;");
+    // Sampling ops provided by OES_EGL_image_external.
+    mSamplingOps.insert("texture2D(1;vf2;");
+    mSamplingOps.insert("texture2DProj(1;vf3;");
+    mSamplingOps.insert("texture2DProj(1;vf4;");
+    // Sampling ops provided by ARB_texture_rectangle.
+    mSamplingOps.insert("texture2DRect(1;vf2;");
+    mSamplingOps.insert("texture2DRectProj(1;vf3;");
+    mSamplingOps.insert("texture2DRectProj(1;vf4;");
+}
+
+// FIXME(mvujovic): We do not know if the execution time of built-in operations like sin, pow, etc.
+// can vary based on the value of the input arguments. If so, we should restrict those as well.
+void RestrictFragmentShaderTiming::enforceRestrictions(const TDependencyGraph& graph)
+{
+    mNumErrors = 0;
+
+    // FIXME(mvujovic): The dependency graph does not support user defined function calls right now,
+    // so we generate errors for them.
+    validateUserDefinedFunctionCallUsage(graph);
+
+    // Starting from each sampler, traverse the dependency graph and generate an error each time we
+    // hit a node where sampler dependent values are not allowed.
+    for (TGraphSymbolVector::const_iterator iter = graph.beginSamplerSymbols();
+         iter != graph.endSamplerSymbols();
+         ++iter)
+    {
+        TGraphSymbol* samplerSymbol = *iter;
+        clearVisited();
+        samplerSymbol->traverse(this);
+    }
+}
+
+void RestrictFragmentShaderTiming::validateUserDefinedFunctionCallUsage(const TDependencyGraph& graph)
+{
+    for (TFunctionCallVector::const_iterator iter = graph.beginUserDefinedFunctionCalls();
+         iter != graph.endUserDefinedFunctionCalls();
+         ++iter)
+    {
+        TGraphFunctionCall* functionCall = *iter;
+        beginError(functionCall->getIntermFunctionCall());
+        mSink << "A call to a user defined function is not permitted.\n";
+    }
+}
+
+void RestrictFragmentShaderTiming::beginError(const TIntermNode* node)
+{
+    ++mNumErrors;
+    mSink.prefix(EPrefixError);
+    mSink.location(node->getLine());
+}
+
+bool RestrictFragmentShaderTiming::isSamplingOp(const TIntermAggregate* intermFunctionCall) const
+{
+    return !intermFunctionCall->isUserDefined() &&
+           mSamplingOps.find(intermFunctionCall->getName()) != mSamplingOps.end();
+}
+
+void RestrictFragmentShaderTiming::visitArgument(TGraphArgument* parameter)
+{
+    // Texture cache access time might leak sensitive information.
+    // Thus, we restrict sampler dependent values from affecting the coordinate or LOD bias of a
+    // sampling operation.
+    if (isSamplingOp(parameter->getIntermFunctionCall())) {
+        switch (parameter->getArgumentNumber()) {
+            case 1:
+                // Second argument (coord)
+                beginError(parameter->getIntermFunctionCall());
+                mSink << "An expression dependent on a sampler is not permitted to be the"
+                      << " coordinate argument of a sampling operation.\n";
+                break;
+            case 2:
+                // Third argument (bias)
+                beginError(parameter->getIntermFunctionCall());
+                mSink << "An expression dependent on a sampler is not permitted to be the"
+                      << " bias argument of a sampling operation.\n";
+                break;
+            default:
+                // First argument (sampler)
+                break;
+        }
+    }
+}
+
+void RestrictFragmentShaderTiming::visitSelection(TGraphSelection* selection)
+{
+    beginError(selection->getIntermSelection());
+    mSink << "An expression dependent on a sampler is not permitted in a conditional statement.\n";
+}
+
+void RestrictFragmentShaderTiming::visitLoop(TGraphLoop* loop)
+{
+    beginError(loop->getIntermLoop());
+    mSink << "An expression dependent on a sampler is not permitted in a loop condition.\n";
+}
+
+void RestrictFragmentShaderTiming::visitLogicalOp(TGraphLogicalOp* logicalOp)
+{
+    beginError(logicalOp->getIntermLogicalOp());
+    mSink << "An expression dependent on a sampler is not permitted on the left hand side of a logical "
+          << logicalOp->getOpString()
+          << " operator.\n";
+}
diff --git a/src/3rdparty/angle/src/compiler/timing/RestrictFragmentShaderTiming.h b/src/3rdparty/angle/src/compiler/timing/RestrictFragmentShaderTiming.h
new file mode 100644 (file)
index 0000000..899165c
--- /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.
+//
+
+#ifndef COMPILER_TIMING_RESTRICT_FRAGMENT_SHADER_TIMING_H_
+#define COMPILER_TIMING_RESTRICT_FRAGMENT_SHADER_TIMING_H_
+
+#include "GLSLANG/ShaderLang.h"
+
+#include "compiler/intermediate.h"
+#include "compiler/depgraph/DependencyGraph.h"
+
+class TInfoSinkBase;
+
+class RestrictFragmentShaderTiming : TDependencyGraphTraverser {
+public:
+    RestrictFragmentShaderTiming(TInfoSinkBase& sink);
+    void enforceRestrictions(const TDependencyGraph& graph);
+    int numErrors() const { return mNumErrors; }
+
+    virtual void visitArgument(TGraphArgument* parameter);
+    virtual void visitSelection(TGraphSelection* selection);
+    virtual void visitLoop(TGraphLoop* loop);
+    virtual void visitLogicalOp(TGraphLogicalOp* logicalOp);
+
+private:
+    void beginError(const TIntermNode* node);
+    void validateUserDefinedFunctionCallUsage(const TDependencyGraph& graph);
+    bool isSamplingOp(const TIntermAggregate* intermFunctionCall) const;
+
+    TInfoSinkBase& mSink;
+    int mNumErrors;
+
+    typedef std::set<TString> StringSet;
+    StringSet mSamplingOps;
+};
+
+#endif  // COMPILER_TIMING_RESTRICT_FRAGMENT_SHADER_TIMING_H_
diff --git a/src/3rdparty/angle/src/compiler/timing/RestrictVertexShaderTiming.cpp b/src/3rdparty/angle/src/compiler/timing/RestrictVertexShaderTiming.cpp
new file mode 100644 (file)
index 0000000..524c6cf
--- /dev/null
@@ -0,0 +1,17 @@
+//
+// 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/timing/RestrictVertexShaderTiming.h"
+
+void RestrictVertexShaderTiming::visitSymbol(TIntermSymbol* node)
+{
+    if (IsSampler(node->getBasicType())) {
+        ++mNumErrors;
+        mSink.prefix(EPrefixError);
+        mSink.location(node->getLine());
+        mSink << "Samplers are not permitted in vertex shaders.\n";
+    }
+}
diff --git a/src/3rdparty/angle/src/compiler/timing/RestrictVertexShaderTiming.h b/src/3rdparty/angle/src/compiler/timing/RestrictVertexShaderTiming.h
new file mode 100644 (file)
index 0000000..19a05fa
--- /dev/null
@@ -0,0 +1,33 @@
+//
+// 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_TIMING_RESTRICT_VERTEX_SHADER_TIMING_H_
+#define COMPILER_TIMING_RESTRICT_VERTEX_SHADER_TIMING_H_
+
+#include "GLSLANG/ShaderLang.h"
+
+#include "compiler/intermediate.h"
+#include "compiler/InfoSink.h"
+
+class TInfoSinkBase;
+
+class RestrictVertexShaderTiming : public TIntermTraverser {
+public:
+    RestrictVertexShaderTiming(TInfoSinkBase& sink)
+        : TIntermTraverser(true, false, false)
+        , mSink(sink)
+        , mNumErrors(0) {}
+
+    void enforceRestrictions(TIntermNode* root) { root->traverse(this); }
+    int numErrors() { return mNumErrors; }
+
+    virtual void visitSymbol(TIntermSymbol*);
+private:
+    TInfoSinkBase& mSink;
+    int mNumErrors;
+};
+
+#endif  // COMPILER_TIMING_RESTRICT_VERTEX_SHADER_TIMING_H_
diff --git a/src/3rdparty/angle/src/compiler/util.cpp b/src/3rdparty/angle/src/compiler/util.cpp
new file mode 100644 (file)
index 0000000..b46e4d0
--- /dev/null
@@ -0,0 +1,33 @@
+//
+// Copyright (c) 2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include <math.h>
+#include <stdlib.h>
+
+#include "util.h"
+
+#ifdef _MSC_VER
+    #include <locale.h>
+#else
+    #include <sstream>
+#endif
+
+double atof_dot(const char *str)
+{
+#ifdef _MSC_VER
+    _locale_t l = _create_locale(LC_NUMERIC, "C");
+    double result = _atof_l(str, l);
+    _free_locale(l);
+    return result;
+#else
+    double result;
+    std::istringstream s(str);
+    std::locale l("C");
+    s.imbue(l);
+    s >> result;
+    return result;
+#endif
+}
diff --git a/src/3rdparty/angle/src/compiler/util.h b/src/3rdparty/angle/src/compiler/util.h
new file mode 100644 (file)
index 0000000..35288b7
--- /dev/null
@@ -0,0 +1,21 @@
+//
+// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#ifndef COMPILER_UTIL_H
+#define COMPILER_UTIL_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// atof_dot is like atof but forcing C locale, i.e. forcing '.' as decimal point.
+double atof_dot(const char *str);
+
+#ifdef __cplusplus
+} // end extern "C"
+#endif
+
+#endif // COMPILER_UTIL_H
diff --git a/src/3rdparty/angle/src/libEGL/Config.cpp b/src/3rdparty/angle/src/libEGL/Config.cpp
new file mode 100644 (file)
index 0000000..89bc8d8
--- /dev/null
@@ -0,0 +1,399 @@
+//
+// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// Config.cpp: Implements the egl::Config class, describing the format, type
+// and size for an egl::Surface. Implements EGLConfig and related functionality.
+// [EGL 1.4] section 3.4 page 15.
+
+#include "libEGL/Config.h"
+
+#include <algorithm>
+#include <vector>
+
+#include "common/debug.h"
+
+using namespace std;
+
+namespace egl
+{
+Config::Config(D3DDISPLAYMODE displayMode, EGLint minInterval, EGLint maxInterval, D3DFORMAT renderTargetFormat, D3DFORMAT depthStencilFormat, EGLint multiSample, EGLint texWidth, EGLint texHeight)
+    : mDisplayMode(displayMode), mRenderTargetFormat(renderTargetFormat), mDepthStencilFormat(depthStencilFormat), mMultiSample(multiSample)
+{
+    set(displayMode, minInterval, maxInterval, renderTargetFormat, depthStencilFormat, multiSample, texWidth, texHeight);
+}
+
+void Config::setDefaults()
+{
+    mBufferSize = 0;
+    mRedSize = 0;
+    mGreenSize = 0;
+    mBlueSize = 0;
+    mLuminanceSize = 0;
+    mAlphaSize = 0;
+    mAlphaMaskSize = 0;
+    mBindToTextureRGB = EGL_DONT_CARE;
+    mBindToTextureRGBA = EGL_DONT_CARE;
+    mColorBufferType = EGL_RGB_BUFFER;
+    mConfigCaveat = EGL_DONT_CARE;
+    mConfigID = EGL_DONT_CARE;
+    mConformant = 0;
+    mDepthSize = 0;
+    mLevel = 0;
+    mMatchNativePixmap = EGL_NONE;
+    mMaxPBufferWidth = 0;
+    mMaxPBufferHeight = 0;
+    mMaxPBufferPixels = 0;
+    mMaxSwapInterval = EGL_DONT_CARE;
+    mMinSwapInterval = EGL_DONT_CARE;
+    mNativeRenderable = EGL_DONT_CARE;
+    mNativeVisualID = 0;
+    mNativeVisualType = EGL_DONT_CARE;
+    mRenderableType = EGL_OPENGL_ES_BIT;
+    mSampleBuffers = 0;
+    mSamples = 0;
+    mStencilSize = 0;
+    mSurfaceType = EGL_WINDOW_BIT;
+    mTransparentType = EGL_NONE;
+    mTransparentRedValue = EGL_DONT_CARE;
+    mTransparentGreenValue = EGL_DONT_CARE;
+    mTransparentBlueValue = EGL_DONT_CARE;
+}
+
+void Config::set(D3DDISPLAYMODE displayMode, EGLint minInterval, EGLint maxInterval, D3DFORMAT renderTargetFormat, D3DFORMAT depthStencilFormat, EGLint multiSample, EGLint texWidth, EGLint texHeight)
+{
+    mBindToTextureRGB = EGL_FALSE;
+    mBindToTextureRGBA = EGL_FALSE;
+    switch (renderTargetFormat)
+    {
+      case D3DFMT_A1R5G5B5:
+        mBufferSize = 16;
+        mRedSize = 5;
+        mGreenSize = 5;
+        mBlueSize = 5;
+        mAlphaSize = 1;
+        break;
+      case D3DFMT_A2R10G10B10:
+        mBufferSize = 32;
+        mRedSize = 10;
+        mGreenSize = 10;
+        mBlueSize = 10;
+        mAlphaSize = 2;
+        break;
+      case D3DFMT_A8R8G8B8:
+        mBufferSize = 32;
+        mRedSize = 8;
+        mGreenSize = 8;
+        mBlueSize = 8;
+        mAlphaSize = 8;
+        mBindToTextureRGBA = true;
+        break;
+      case D3DFMT_R5G6B5:
+        mBufferSize = 16;
+        mRedSize = 5;
+        mGreenSize = 6;
+        mBlueSize = 5;
+        mAlphaSize = 0;
+        break;
+      case D3DFMT_X8R8G8B8:
+        mBufferSize = 32;
+        mRedSize = 8;
+        mGreenSize = 8;
+        mBlueSize = 8;
+        mAlphaSize = 0;
+        mBindToTextureRGB = true;
+        break;
+      default:
+        UNREACHABLE();   // Other formats should not be valid
+    }
+
+    mLuminanceSize = 0;
+    mAlphaMaskSize = 0;
+    mColorBufferType = EGL_RGB_BUFFER;
+    mConfigCaveat = (displayMode.Format == renderTargetFormat) ? EGL_NONE : EGL_SLOW_CONFIG;
+    mConfigID = 0;
+    mConformant = EGL_OPENGL_ES2_BIT;
+
+    switch (depthStencilFormat)
+    {
+      case D3DFMT_UNKNOWN:
+        mDepthSize = 0;
+        mStencilSize = 0;
+        break;
+//    case D3DFMT_D16_LOCKABLE:
+//      mDepthSize = 16;
+//      mStencilSize = 0;
+//      break;
+      case D3DFMT_D32:
+        mDepthSize = 32;
+        mStencilSize = 0;
+        break;
+      case D3DFMT_D15S1:
+        mDepthSize = 15;
+        mStencilSize = 1;
+        break;
+      case D3DFMT_D24S8:
+        mDepthSize = 24;
+        mStencilSize = 8;
+        break;
+      case D3DFMT_D24X8:
+        mDepthSize = 24;
+        mStencilSize = 0;
+        break;
+      case D3DFMT_D24X4S4:
+        mDepthSize = 24;
+        mStencilSize = 4;
+        break;
+      case D3DFMT_D16:
+        mDepthSize = 16;
+        mStencilSize = 0;
+        break;
+//    case D3DFMT_D32F_LOCKABLE:
+//      mDepthSize = 32;
+//      mStencilSize = 0;
+//      break;
+//    case D3DFMT_D24FS8:
+//      mDepthSize = 24;
+//      mStencilSize = 8;
+//      break;
+      default:
+        UNREACHABLE();
+    }
+
+    mLevel = 0;
+    mMatchNativePixmap = EGL_NONE;
+    mMaxPBufferWidth = texWidth;
+    mMaxPBufferHeight = texHeight;
+    mMaxPBufferPixels = texWidth*texHeight;
+    mMaxSwapInterval = maxInterval;
+    mMinSwapInterval = minInterval;
+    mNativeRenderable = EGL_FALSE;
+    mNativeVisualID = 0;
+    mNativeVisualType = 0;
+    mRenderableType = EGL_OPENGL_ES2_BIT;
+    mSampleBuffers = multiSample ? 1 : 0;
+    mSamples = multiSample;
+    mSurfaceType = EGL_PBUFFER_BIT | EGL_WINDOW_BIT | EGL_SWAP_BEHAVIOR_PRESERVED_BIT;
+    mTransparentType = EGL_NONE;
+    mTransparentRedValue = 0;
+    mTransparentGreenValue = 0;
+    mTransparentBlueValue = 0;
+}
+
+EGLConfig Config::getHandle() const
+{
+    return (EGLConfig)(size_t)mConfigID;
+}
+
+SortConfig::SortConfig(const EGLint *attribList)
+    : mWantRed(false), mWantGreen(false), mWantBlue(false), mWantAlpha(false), mWantLuminance(false)
+{
+    scanForWantedComponents(attribList);
+}
+
+void SortConfig::scanForWantedComponents(const EGLint *attribList)
+{
+    // [EGL] section 3.4.1 page 24
+    // Sorting rule #3: by larger total number of color bits, not considering
+    // components that are 0 or don't-care.
+    for (const EGLint *attr = attribList; attr[0] != EGL_NONE; attr += 2)
+    {
+        if (attr[1] != 0 && attr[1] != EGL_DONT_CARE)
+        {
+            switch (attr[0])
+            {
+              case EGL_RED_SIZE:       mWantRed = true; break;
+              case EGL_GREEN_SIZE:     mWantGreen = true; break;
+              case EGL_BLUE_SIZE:      mWantBlue = true; break;
+              case EGL_ALPHA_SIZE:     mWantAlpha = true; break;
+              case EGL_LUMINANCE_SIZE: mWantLuminance = true; break;
+            }
+        }
+    }
+}
+
+EGLint SortConfig::wantedComponentsSize(const Config &config) const
+{
+    EGLint total = 0;
+
+    if (mWantRed)       total += config.mRedSize;
+    if (mWantGreen)     total += config.mGreenSize;
+    if (mWantBlue)      total += config.mBlueSize;
+    if (mWantAlpha)     total += config.mAlphaSize;
+    if (mWantLuminance) total += config.mLuminanceSize;
+
+    return total;
+}
+
+bool SortConfig::operator()(const Config *x, const Config *y) const
+{
+    return (*this)(*x, *y);
+}
+
+bool SortConfig::operator()(const Config &x, const Config &y) const
+{
+    #define SORT(attribute)                        \
+        if (x.attribute != y.attribute)            \
+        {                                          \
+            return x.attribute < y.attribute;      \
+        }
+
+    META_ASSERT(EGL_NONE < EGL_SLOW_CONFIG && EGL_SLOW_CONFIG < EGL_NON_CONFORMANT_CONFIG);
+    SORT(mConfigCaveat);
+
+    META_ASSERT(EGL_RGB_BUFFER < EGL_LUMINANCE_BUFFER);
+    SORT(mColorBufferType);
+
+    // By larger total number of color bits, only considering those that are requested to be > 0.
+    EGLint xComponentsSize = wantedComponentsSize(x);
+    EGLint yComponentsSize = wantedComponentsSize(y);
+    if (xComponentsSize != yComponentsSize)
+    {
+        return xComponentsSize > yComponentsSize;
+    }
+
+    SORT(mBufferSize);
+    SORT(mSampleBuffers);
+    SORT(mSamples);
+    SORT(mDepthSize);
+    SORT(mStencilSize);
+    SORT(mAlphaMaskSize);
+    SORT(mNativeVisualType);
+    SORT(mConfigID);
+
+    #undef SORT
+
+    return false;
+}
+
+// We'd like to use SortConfig to also eliminate duplicate configs.
+// This works as long as we never have two configs with different per-RGB-component layouts,
+// but the same total.
+// 5551 and 565 are different because R+G+B is different.
+// 5551 and 555 are different because bufferSize is different.
+const EGLint ConfigSet::mSortAttribs[] =
+{
+    EGL_RED_SIZE, 1,
+    EGL_GREEN_SIZE, 1,
+    EGL_BLUE_SIZE, 1,
+    EGL_LUMINANCE_SIZE, 1,
+    // BUT NOT ALPHA
+    EGL_NONE
+};
+
+ConfigSet::ConfigSet()
+    : mSet(SortConfig(mSortAttribs))
+{
+}
+
+void ConfigSet::add(D3DDISPLAYMODE displayMode, EGLint minSwapInterval, EGLint maxSwapInterval, D3DFORMAT renderTargetFormat, D3DFORMAT depthStencilFormat, EGLint multiSample, EGLint texWidth, EGLint texHeight)
+{
+    Config config(displayMode, minSwapInterval, maxSwapInterval, renderTargetFormat, depthStencilFormat, multiSample, texWidth, texHeight);
+
+    mSet.insert(config);
+}
+
+size_t ConfigSet::size() const
+{
+    return mSet.size();
+}
+
+bool ConfigSet::getConfigs(EGLConfig *configs, const EGLint *attribList, EGLint configSize, EGLint *numConfig)
+{
+    vector<const Config*> passed;
+    passed.reserve(mSet.size());
+
+    for (Iterator config = mSet.begin(); config != mSet.end(); config++)
+    {
+        bool match = true;
+        const EGLint *attribute = attribList;
+
+        while (attribute[0] != EGL_NONE)
+        {
+            switch (attribute[0])
+            {
+              case EGL_BUFFER_SIZE:               match = config->mBufferSize >= attribute[1];                      break;
+              case EGL_ALPHA_SIZE:                match = config->mAlphaSize >= attribute[1];                       break;
+              case EGL_BLUE_SIZE:                 match = config->mBlueSize >= attribute[1];                        break;
+              case EGL_GREEN_SIZE:                match = config->mGreenSize >= attribute[1];                       break;
+              case EGL_RED_SIZE:                  match = config->mRedSize >= attribute[1];                         break;
+              case EGL_DEPTH_SIZE:                match = config->mDepthSize >= attribute[1];                       break;
+              case EGL_STENCIL_SIZE:              match = config->mStencilSize >= attribute[1];                     break;
+              case EGL_CONFIG_CAVEAT:             match = config->mConfigCaveat == (EGLenum) attribute[1];          break;
+              case EGL_CONFIG_ID:                 match = config->mConfigID == attribute[1];                        break;
+              case EGL_LEVEL:                     match = config->mLevel >= attribute[1];                           break;
+              case EGL_NATIVE_RENDERABLE:         match = config->mNativeRenderable == (EGLBoolean) attribute[1];   break;
+              case EGL_NATIVE_VISUAL_TYPE:        match = config->mNativeVisualType == attribute[1];                break;
+              case EGL_SAMPLES:                   match = config->mSamples >= attribute[1];                         break;
+              case EGL_SAMPLE_BUFFERS:            match = config->mSampleBuffers >= attribute[1];                   break;
+              case EGL_SURFACE_TYPE:              match = (config->mSurfaceType & attribute[1]) == attribute[1];    break;
+              case EGL_TRANSPARENT_TYPE:          match = config->mTransparentType == (EGLenum) attribute[1];       break;
+              case EGL_TRANSPARENT_BLUE_VALUE:    match = config->mTransparentBlueValue == attribute[1];            break;
+              case EGL_TRANSPARENT_GREEN_VALUE:   match = config->mTransparentGreenValue == attribute[1];           break;
+              case EGL_TRANSPARENT_RED_VALUE:     match = config->mTransparentRedValue == attribute[1];             break;
+              case EGL_BIND_TO_TEXTURE_RGB:       match = config->mBindToTextureRGB == (EGLBoolean) attribute[1];   break;
+              case EGL_BIND_TO_TEXTURE_RGBA:      match = config->mBindToTextureRGBA == (EGLBoolean) attribute[1];  break;
+              case EGL_MIN_SWAP_INTERVAL:         match = config->mMinSwapInterval == attribute[1];                 break;
+              case EGL_MAX_SWAP_INTERVAL:         match = config->mMaxSwapInterval == attribute[1];                 break;
+              case EGL_LUMINANCE_SIZE:            match = config->mLuminanceSize >= attribute[1];                   break;
+              case EGL_ALPHA_MASK_SIZE:           match = config->mAlphaMaskSize >= attribute[1];                   break;
+              case EGL_COLOR_BUFFER_TYPE:         match = config->mColorBufferType == (EGLenum) attribute[1];       break;
+              case EGL_RENDERABLE_TYPE:           match = (config->mRenderableType & attribute[1]) == attribute[1]; break;
+              case EGL_MATCH_NATIVE_PIXMAP:       match = false; UNIMPLEMENTED();                                   break;
+              case EGL_CONFORMANT:                match = (config->mConformant & attribute[1]) == attribute[1];     break;
+              case EGL_MAX_PBUFFER_WIDTH:         match = config->mMaxPBufferWidth >= attribute[1];                 break;
+              case EGL_MAX_PBUFFER_HEIGHT:        match = config->mMaxPBufferHeight >= attribute[1];                break;
+              case EGL_MAX_PBUFFER_PIXELS:        match = config->mMaxPBufferPixels >= attribute[1];                break;
+              default:
+                return false;
+            }
+
+            if (!match)
+            {
+                break;
+            }
+
+            attribute += 2;
+        }
+
+        if (match)
+        {
+            passed.push_back(&*config);
+        }
+    }
+
+    if (configs)
+    {
+        sort(passed.begin(), passed.end(), SortConfig(attribList));
+
+        EGLint index;
+        for (index = 0; index < configSize && index < static_cast<EGLint>(passed.size()); index++)
+        {
+            configs[index] = passed[index]->getHandle();
+        }
+
+        *numConfig = index;
+    }
+    else
+    {
+        *numConfig = passed.size();
+    }
+
+    return true;
+}
+
+const egl::Config *ConfigSet::get(EGLConfig configHandle)
+{
+    for (Iterator config = mSet.begin(); config != mSet.end(); config++)
+    {
+        if (config->getHandle() == configHandle)
+        {
+            return &(*config);
+        }
+    }
+
+    return NULL;
+}
+}
diff --git a/src/3rdparty/angle/src/libEGL/Config.h b/src/3rdparty/angle/src/libEGL/Config.h
new file mode 100644 (file)
index 0000000..95626ed
--- /dev/null
@@ -0,0 +1,118 @@
+//
+// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// Config.h: Defines the egl::Config class, describing the format, type
+// and size for an egl::Surface. Implements EGLConfig and related functionality.
+// [EGL 1.4] section 3.4 page 15.
+
+#ifndef INCLUDE_CONFIG_H_
+#define INCLUDE_CONFIG_H_
+
+#define EGLAPI
+#include <EGL/egl.h>
+#include <d3d9.h>
+
+#include <set>
+
+#include "common/angleutils.h"
+
+namespace egl
+{
+class Display;
+
+class Config
+{
+  public:
+    Config(D3DDISPLAYMODE displayMode, EGLint minSwapInterval, EGLint maxSwapInterval, D3DFORMAT renderTargetFormat, D3DFORMAT depthStencilFormat, EGLint multiSample, EGLint texWidth, EGLint texHeight);
+
+    void setDefaults();
+    void set(D3DDISPLAYMODE displayMode, EGLint minSwapInterval, EGLint maxSwapInterval, D3DFORMAT renderTargetFormat, D3DFORMAT depthStencilFormat, EGLint multiSample, EGLint texWidth, EGLint texHeight);
+    EGLConfig getHandle() const;
+
+    const D3DDISPLAYMODE mDisplayMode;
+    const D3DFORMAT mRenderTargetFormat;
+    const D3DFORMAT mDepthStencilFormat;
+    const EGLint mMultiSample;
+
+    EGLint mBufferSize;              // Depth of the color buffer
+    EGLint mRedSize;                 // Bits of Red in the color buffer
+    EGLint mGreenSize;               // Bits of Green in the color buffer
+    EGLint mBlueSize;                // Bits of Blue in the color buffer
+    EGLint mLuminanceSize;           // Bits of Luminance in the color buffer
+    EGLint mAlphaSize;               // Bits of Alpha in the color buffer
+    EGLint mAlphaMaskSize;           // Bits of Alpha Mask in the mask buffer
+    EGLBoolean mBindToTextureRGB;    // True if bindable to RGB textures.
+    EGLBoolean mBindToTextureRGBA;   // True if bindable to RGBA textures.
+    EGLenum mColorBufferType;        // Color buffer type
+    EGLenum mConfigCaveat;           // Any caveats for the configuration
+    EGLint mConfigID;                // Unique EGLConfig identifier
+    EGLint mConformant;              // Whether contexts created with this config are conformant
+    EGLint mDepthSize;               // Bits of Z in the depth buffer
+    EGLint mLevel;                   // Frame buffer level
+    EGLBoolean mMatchNativePixmap;   // Match the native pixmap format
+    EGLint mMaxPBufferWidth;         // Maximum width of pbuffer
+    EGLint mMaxPBufferHeight;        // Maximum height of pbuffer
+    EGLint mMaxPBufferPixels;        // Maximum size of pbuffer
+    EGLint mMaxSwapInterval;         // Maximum swap interval
+    EGLint mMinSwapInterval;         // Minimum swap interval
+    EGLBoolean mNativeRenderable;    // EGL_TRUE if native rendering APIs can render to surface
+    EGLint mNativeVisualID;          // Handle of corresponding native visual
+    EGLint mNativeVisualType;        // Native visual type of the associated visual
+    EGLint mRenderableType;          // Which client rendering APIs are supported.
+    EGLint mSampleBuffers;           // Number of multisample buffers
+    EGLint mSamples;                 // Number of samples per pixel
+    EGLint mStencilSize;             // Bits of Stencil in the stencil buffer
+    EGLint mSurfaceType;             // Which types of EGL surfaces are supported.
+    EGLenum mTransparentType;        // Type of transparency supported
+    EGLint mTransparentRedValue;     // Transparent red value
+    EGLint mTransparentGreenValue;   // Transparent green value
+    EGLint mTransparentBlueValue;    // Transparent blue value
+};
+
+// Function object used by STL sorting routines for ordering Configs according to [EGL] section 3.4.1 page 24.
+class SortConfig
+{
+  public:
+    explicit SortConfig(const EGLint *attribList);
+
+    bool operator()(const Config *x, const Config *y) const;
+    bool operator()(const Config &x, const Config &y) const;
+
+  private:
+    void scanForWantedComponents(const EGLint *attribList);
+    EGLint wantedComponentsSize(const Config &config) const;
+
+    bool mWantRed;
+    bool mWantGreen;
+    bool mWantBlue;
+    bool mWantAlpha;
+    bool mWantLuminance;
+};
+
+class ConfigSet
+{
+    friend Display;
+
+  public:
+    ConfigSet();
+
+    void add(D3DDISPLAYMODE displayMode, EGLint minSwapInterval, EGLint maxSwapInterval, D3DFORMAT renderTargetFormat, D3DFORMAT depthStencilFormat, EGLint multiSample, EGLint texWidth, EGLint texHeight);
+    size_t size() const;
+    bool getConfigs(EGLConfig *configs, const EGLint *attribList, EGLint configSize, EGLint *numConfig);
+    const egl::Config *get(EGLConfig configHandle);
+
+  private:
+    DISALLOW_COPY_AND_ASSIGN(ConfigSet);
+
+    typedef std::set<Config, SortConfig> Set;
+    typedef Set::iterator Iterator;
+    Set mSet;
+
+    static const EGLint mSortAttribs[];
+};
+}
+
+#endif   // INCLUDE_CONFIG_H_
diff --git a/src/3rdparty/angle/src/libEGL/Display.cpp b/src/3rdparty/angle/src/libEGL/Display.cpp
new file mode 100644 (file)
index 0000000..a2dee6d
--- /dev/null
@@ -0,0 +1,1292 @@
+//
+// 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.
+//
+
+// Display.cpp: Implements the egl::Display class, representing the abstract
+// display on which graphics are drawn. Implements EGLDisplay.
+// [EGL 1.4] section 2.1.2 page 3.
+
+#include "libEGL/Display.h"
+
+#include <algorithm>
+#include <map>
+#include <vector>
+
+#include "common/debug.h"
+#include "libGLESv2/mathutil.h"
+#include "libGLESv2/utilities.h"
+
+#include "libEGL/main.h"
+
+// Can also be enabled by defining FORCE_REF_RAST in the project's predefined macros
+#define REF_RAST 0
+
+// The "Debug This Pixel..." feature in PIX often fails when using the
+// D3D9Ex interfaces.  In order to get debug pixel to work on a Vista/Win 7
+// machine, define "ANGLE_ENABLE_D3D9EX=0" in your project file.
+#if !defined(ANGLE_ENABLE_D3D9EX)
+// Enables use of the IDirect3D9Ex interface, when available
+#define ANGLE_ENABLE_D3D9EX 1
+#endif // !defined(ANGLE_ENABLE_D3D9EX)
+
+namespace egl
+{
+namespace
+{
+    typedef std::map<EGLNativeDisplayType, Display*> DisplayMap; 
+    DisplayMap displays;
+}
+
+egl::Display *Display::getDisplay(EGLNativeDisplayType displayId)
+{
+    if (displays.find(displayId) != displays.end())
+    {
+        return displays[displayId];
+    }
+
+    egl::Display *display = NULL;
+
+    if (displayId == EGL_DEFAULT_DISPLAY)
+    {
+        display = new egl::Display(displayId, (HDC)NULL, false);
+    }
+    else if (displayId == EGL_SOFTWARE_DISPLAY_ANGLE)
+    {
+        display = new egl::Display(displayId, (HDC)NULL, true);
+    }
+    else
+    {
+        // FIXME: Check if displayId is a valid display device context
+
+        display = new egl::Display(displayId, (HDC)displayId, false);
+    }
+
+    displays[displayId] = display;
+    return display;
+}
+
+Display::Display(EGLNativeDisplayType displayId, HDC deviceContext, bool software) : mDc(deviceContext)
+{
+    mD3d9Module = NULL;
+    
+    mD3d9 = NULL;
+    mD3d9Ex = NULL;
+    mDevice = NULL;
+    mDeviceEx = NULL;
+    mDeviceWindow = NULL;
+
+    mAdapter = D3DADAPTER_DEFAULT;
+
+    #if REF_RAST == 1 || defined(FORCE_REF_RAST)
+        mDeviceType = D3DDEVTYPE_REF;
+    #else
+        mDeviceType = D3DDEVTYPE_HAL;
+    #endif
+
+    mMinSwapInterval = 1;
+    mMaxSwapInterval = 1;
+    mSoftwareDevice = software;
+    mDisplayId = displayId;
+    mDeviceLost = false;
+}
+
+Display::~Display()
+{
+    terminate();
+
+    DisplayMap::iterator thisDisplay = displays.find(mDisplayId);
+
+    if (thisDisplay != displays.end())
+    {
+      displays.erase(thisDisplay);
+    }
+}
+
+bool Display::initialize()
+{
+    if (isInitialized())
+    {
+        return true;
+    }
+
+    if (mSoftwareDevice)
+    {
+      mD3d9Module = GetModuleHandle(TEXT("swiftshader_d3d9.dll"));
+    } 
+    else
+    {
+      mD3d9Module = GetModuleHandle(TEXT("d3d9.dll"));
+    }
+    if (mD3d9Module == NULL)
+    {
+        terminate();
+        return false;
+    }
+
+    typedef HRESULT (WINAPI *Direct3DCreate9ExFunc)(UINT, IDirect3D9Ex**);
+    Direct3DCreate9ExFunc Direct3DCreate9ExPtr = reinterpret_cast<Direct3DCreate9ExFunc>(GetProcAddress(mD3d9Module, "Direct3DCreate9Ex"));
+
+    // Use Direct3D9Ex if available. Among other things, this version is less
+    // inclined to report a lost context, for example when the user switches
+    // desktop. Direct3D9Ex is available in Windows Vista and later if suitable drivers are available.
+    if (ANGLE_ENABLE_D3D9EX && Direct3DCreate9ExPtr && SUCCEEDED(Direct3DCreate9ExPtr(D3D_SDK_VERSION, &mD3d9Ex)))
+    {
+        ASSERT(mD3d9Ex);
+        mD3d9Ex->QueryInterface(IID_IDirect3D9, reinterpret_cast<void**>(&mD3d9));
+        ASSERT(mD3d9);
+    }
+    else
+    {
+        mD3d9 = Direct3DCreate9(D3D_SDK_VERSION);
+    }
+
+    if (mD3d9)
+    {
+        if (mDc != NULL)
+        {
+        //  UNIMPLEMENTED();   // FIXME: Determine which adapter index the device context corresponds to
+        }
+
+        HRESULT result;
+        
+        // Give up on getting device caps after about one second.
+        for (int i = 0; i < 10; ++i)
+        {
+            result = mD3d9->GetDeviceCaps(mAdapter, mDeviceType, &mDeviceCaps);
+            
+            if (SUCCEEDED(result))
+            {
+                break;
+            }
+            else if (result == D3DERR_NOTAVAILABLE)
+            {
+                Sleep(100);   // Give the driver some time to initialize/recover
+            }
+            else if (FAILED(result))   // D3DERR_OUTOFVIDEOMEMORY, E_OUTOFMEMORY, D3DERR_INVALIDDEVICE, or another error we can't recover from
+            {
+                terminate();
+                return error(EGL_BAD_ALLOC, false);
+            }
+        }
+
+        if (mDeviceCaps.PixelShaderVersion < D3DPS_VERSION(2, 0))
+        {
+            terminate();
+            return error(EGL_NOT_INITIALIZED, false);
+        }
+
+        // When DirectX9 is running with an older DirectX8 driver, a StretchRect from a regular texture to a render target texture is not supported.
+        // This is required by Texture2D::convertToRenderTarget.
+        if ((mDeviceCaps.DevCaps2 & D3DDEVCAPS2_CAN_STRETCHRECT_FROM_TEXTURES) == 0)
+        {
+            terminate();
+            return error(EGL_NOT_INITIALIZED, false);
+        }
+
+        mMinSwapInterval = 4;
+        mMaxSwapInterval = 0;
+
+        if (mDeviceCaps.PresentationIntervals & D3DPRESENT_INTERVAL_IMMEDIATE) {mMinSwapInterval = std::min(mMinSwapInterval, 0); mMaxSwapInterval = std::max(mMaxSwapInterval, 0);}
+        if (mDeviceCaps.PresentationIntervals & D3DPRESENT_INTERVAL_ONE)       {mMinSwapInterval = std::min(mMinSwapInterval, 1); mMaxSwapInterval = std::max(mMaxSwapInterval, 1);}
+        if (mDeviceCaps.PresentationIntervals & D3DPRESENT_INTERVAL_TWO)       {mMinSwapInterval = std::min(mMinSwapInterval, 2); mMaxSwapInterval = std::max(mMaxSwapInterval, 2);}
+        if (mDeviceCaps.PresentationIntervals & D3DPRESENT_INTERVAL_THREE)     {mMinSwapInterval = std::min(mMinSwapInterval, 3); mMaxSwapInterval = std::max(mMaxSwapInterval, 3);}
+        if (mDeviceCaps.PresentationIntervals & D3DPRESENT_INTERVAL_FOUR)      {mMinSwapInterval = std::min(mMinSwapInterval, 4); mMaxSwapInterval = std::max(mMaxSwapInterval, 4);}
+
+        mD3d9->GetAdapterIdentifier(mAdapter, 0, &mAdapterIdentifier);
+
+        // ATI cards on XP have problems with non-power-of-two textures.
+        mSupportsNonPower2Textures = !(mDeviceCaps.TextureCaps & D3DPTEXTURECAPS_POW2) &&
+           !(mDeviceCaps.TextureCaps & D3DPTEXTURECAPS_CUBEMAP_POW2) &&
+           !(mDeviceCaps.TextureCaps & D3DPTEXTURECAPS_NONPOW2CONDITIONAL) &&
+           !(getComparableOSVersion() < versionWindowsVista && mAdapterIdentifier.VendorId == VENDOR_ID_AMD);
+
+        const D3DFORMAT renderTargetFormats[] =
+        {
+            D3DFMT_A1R5G5B5,
+        //  D3DFMT_A2R10G10B10,   // The color_ramp conformance test uses ReadPixels with UNSIGNED_BYTE causing it to think that rendering skipped a colour value.
+            D3DFMT_A8R8G8B8,
+            D3DFMT_R5G6B5,
+        //  D3DFMT_X1R5G5B5,      // Has no compatible OpenGL ES renderbuffer format
+            D3DFMT_X8R8G8B8
+        };
+
+        const D3DFORMAT depthStencilFormats[] =
+        {
+            D3DFMT_UNKNOWN,
+        //  D3DFMT_D16_LOCKABLE,
+            D3DFMT_D32,
+        //  D3DFMT_D15S1,
+            D3DFMT_D24S8,
+            D3DFMT_D24X8,
+        //  D3DFMT_D24X4S4,
+            D3DFMT_D16,
+        //  D3DFMT_D32F_LOCKABLE,
+        //  D3DFMT_D24FS8
+        };
+
+        D3DDISPLAYMODE currentDisplayMode;
+        mD3d9->GetAdapterDisplayMode(mAdapter, &currentDisplayMode);
+
+        ConfigSet configSet;
+
+        for (int formatIndex = 0; formatIndex < sizeof(renderTargetFormats) / sizeof(D3DFORMAT); formatIndex++)
+        {
+            D3DFORMAT renderTargetFormat = renderTargetFormats[formatIndex];
+
+            HRESULT result = mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, D3DUSAGE_RENDERTARGET, D3DRTYPE_SURFACE, renderTargetFormat);
+
+            if (SUCCEEDED(result))
+            {
+                for (int depthStencilIndex = 0; depthStencilIndex < sizeof(depthStencilFormats) / sizeof(D3DFORMAT); depthStencilIndex++)
+                {
+                    D3DFORMAT depthStencilFormat = depthStencilFormats[depthStencilIndex];
+                    HRESULT result = D3D_OK;
+                    
+                    if(depthStencilFormat != D3DFMT_UNKNOWN)
+                    {
+                        result = mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, D3DUSAGE_DEPTHSTENCIL, D3DRTYPE_SURFACE, depthStencilFormat);
+                    }
+
+                    if (SUCCEEDED(result))
+                    {
+                        if(depthStencilFormat != D3DFMT_UNKNOWN)
+                        {
+                            result = mD3d9->CheckDepthStencilMatch(mAdapter, mDeviceType, currentDisplayMode.Format, renderTargetFormat, depthStencilFormat);
+                        }
+
+                        if (SUCCEEDED(result))
+                        {
+                            // FIXME: enumerate multi-sampling
+
+                            configSet.add(currentDisplayMode, mMinSwapInterval, mMaxSwapInterval, renderTargetFormat, depthStencilFormat, 0,
+                                          mDeviceCaps.MaxTextureWidth, mDeviceCaps.MaxTextureHeight);
+                        }
+                    }
+                }
+            }
+        }
+
+        // Give the sorted configs a unique ID and store them internally
+        EGLint index = 1;
+        for (ConfigSet::Iterator config = configSet.mSet.begin(); config != configSet.mSet.end(); config++)
+        {
+            Config configuration = *config;
+            configuration.mConfigID = index;
+            index++;
+
+            mConfigSet.mSet.insert(configuration);
+        }
+    }
+
+    if (!isInitialized())
+    {
+        terminate();
+
+        return false;
+    }
+
+    initExtensionString();
+
+    static const TCHAR windowName[] = TEXT("AngleHiddenWindow");
+    static const TCHAR className[] = TEXT("STATIC");
+
+    mDeviceWindow = CreateWindowEx(WS_EX_NOACTIVATE, className, windowName, WS_DISABLED | WS_POPUP, 0, 0, 1, 1, HWND_MESSAGE, NULL, GetModuleHandle(NULL), NULL);
+
+    if (!createDevice())
+    {
+        terminate();
+        return false;
+    }
+
+    mVertexShaderCache.initialize(mDevice);
+    mPixelShaderCache.initialize(mDevice);
+
+    return true;
+}
+
+void Display::terminate()
+{
+    while (!mSurfaceSet.empty())
+    {
+        destroySurface(*mSurfaceSet.begin());
+    }
+
+    while (!mContextSet.empty())
+    {
+        destroyContext(*mContextSet.begin());
+    }
+
+    while (!mEventQueryPool.empty())
+    {
+        mEventQueryPool.back()->Release();
+        mEventQueryPool.pop_back();
+    }
+
+    mVertexShaderCache.clear();
+    mPixelShaderCache.clear();
+
+    if (mDevice)
+    {
+        // If the device is lost, reset it first to prevent leaving the driver in an unstable state
+        if (testDeviceLost())
+        {
+            resetDevice();
+        }
+
+        mDevice->Release();
+        mDevice = NULL;
+    }
+
+    if (mDeviceEx)
+    {
+        mDeviceEx->Release();
+        mDeviceEx = NULL;
+    }
+
+    if (mD3d9)
+    {
+        mD3d9->Release();
+        mD3d9 = NULL;
+    }
+
+    if (mDeviceWindow)
+    {
+        DestroyWindow(mDeviceWindow);
+        mDeviceWindow = NULL;
+    }
+    
+    if (mD3d9Ex)
+    {
+        mD3d9Ex->Release();
+        mD3d9Ex = NULL;
+    }
+
+    if (mD3d9Module)
+    {
+        mD3d9Module = NULL;
+    }
+}
+
+void Display::startScene()
+{
+    if (!mSceneStarted)
+    {
+        long result = mDevice->BeginScene();
+        if (SUCCEEDED(result)) {
+            // This is defensive checking against the device being
+            // lost at unexpected times.
+            mSceneStarted = true;
+        }
+    }
+}
+
+void Display::endScene()
+{
+    if (mSceneStarted)
+    {
+        // EndScene can fail if the device was lost, for example due
+        // to a TDR during a draw call.
+        mDevice->EndScene();
+        mSceneStarted = false;
+    }
+}
+
+bool Display::getConfigs(EGLConfig *configs, const EGLint *attribList, EGLint configSize, EGLint *numConfig)
+{
+    return mConfigSet.getConfigs(configs, attribList, configSize, numConfig);
+}
+
+bool Display::getConfigAttrib(EGLConfig config, EGLint attribute, EGLint *value)
+{
+    const egl::Config *configuration = mConfigSet.get(config);
+
+    switch (attribute)
+    {
+      case EGL_BUFFER_SIZE:               *value = configuration->mBufferSize;             break;
+      case EGL_ALPHA_SIZE:                *value = configuration->mAlphaSize;              break;
+      case EGL_BLUE_SIZE:                 *value = configuration->mBlueSize;               break;
+      case EGL_GREEN_SIZE:                *value = configuration->mGreenSize;              break;
+      case EGL_RED_SIZE:                  *value = configuration->mRedSize;                break;
+      case EGL_DEPTH_SIZE:                *value = configuration->mDepthSize;              break;
+      case EGL_STENCIL_SIZE:              *value = configuration->mStencilSize;            break;
+      case EGL_CONFIG_CAVEAT:             *value = configuration->mConfigCaveat;           break;
+      case EGL_CONFIG_ID:                 *value = configuration->mConfigID;               break;
+      case EGL_LEVEL:                     *value = configuration->mLevel;                  break;
+      case EGL_NATIVE_RENDERABLE:         *value = configuration->mNativeRenderable;       break;
+      case EGL_NATIVE_VISUAL_TYPE:        *value = configuration->mNativeVisualType;       break;
+      case EGL_SAMPLES:                   *value = configuration->mSamples;                break;
+      case EGL_SAMPLE_BUFFERS:            *value = configuration->mSampleBuffers;          break;
+      case EGL_SURFACE_TYPE:              *value = configuration->mSurfaceType;            break;
+      case EGL_TRANSPARENT_TYPE:          *value = configuration->mTransparentType;        break;
+      case EGL_TRANSPARENT_BLUE_VALUE:    *value = configuration->mTransparentBlueValue;   break;
+      case EGL_TRANSPARENT_GREEN_VALUE:   *value = configuration->mTransparentGreenValue;  break;
+      case EGL_TRANSPARENT_RED_VALUE:     *value = configuration->mTransparentRedValue;    break;
+      case EGL_BIND_TO_TEXTURE_RGB:       *value = configuration->mBindToTextureRGB;       break;
+      case EGL_BIND_TO_TEXTURE_RGBA:      *value = configuration->mBindToTextureRGBA;      break;
+      case EGL_MIN_SWAP_INTERVAL:         *value = configuration->mMinSwapInterval;        break;
+      case EGL_MAX_SWAP_INTERVAL:         *value = configuration->mMaxSwapInterval;        break;
+      case EGL_LUMINANCE_SIZE:            *value = configuration->mLuminanceSize;          break;
+      case EGL_ALPHA_MASK_SIZE:           *value = configuration->mAlphaMaskSize;          break;
+      case EGL_COLOR_BUFFER_TYPE:         *value = configuration->mColorBufferType;        break;
+      case EGL_RENDERABLE_TYPE:           *value = configuration->mRenderableType;         break;
+      case EGL_MATCH_NATIVE_PIXMAP:       *value = false; UNIMPLEMENTED();                 break;
+      case EGL_CONFORMANT:                *value = configuration->mConformant;             break;
+      case EGL_MAX_PBUFFER_WIDTH:         *value = configuration->mMaxPBufferWidth;        break;
+      case EGL_MAX_PBUFFER_HEIGHT:        *value = configuration->mMaxPBufferHeight;       break;
+      case EGL_MAX_PBUFFER_PIXELS:        *value = configuration->mMaxPBufferPixels;       break;
+      default:
+        return false;
+    }
+
+    return true;
+}
+
+bool Display::createDevice()
+{
+    D3DPRESENT_PARAMETERS presentParameters = getDefaultPresentParameters();
+    DWORD behaviorFlags = D3DCREATE_FPU_PRESERVE | D3DCREATE_NOWINDOWCHANGES;
+
+    HRESULT result = mD3d9->CreateDevice(mAdapter, mDeviceType, mDeviceWindow, behaviorFlags | D3DCREATE_HARDWARE_VERTEXPROCESSING | D3DCREATE_PUREDEVICE, &presentParameters, &mDevice);
+
+    if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY || result == D3DERR_DEVICELOST)
+    {
+        return error(EGL_BAD_ALLOC, false);
+    }
+
+    if (FAILED(result))
+    {
+        result = mD3d9->CreateDevice(mAdapter, mDeviceType, mDeviceWindow, behaviorFlags | D3DCREATE_SOFTWARE_VERTEXPROCESSING, &presentParameters, &mDevice);
+
+        if (FAILED(result))
+        {
+            ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY || result == D3DERR_NOTAVAILABLE || result == D3DERR_DEVICELOST);
+            return error(EGL_BAD_ALLOC, false);
+        }
+    }
+
+    if (mD3d9Ex)
+    {
+        result = mDevice->QueryInterface(IID_IDirect3DDevice9Ex, (void**) &mDeviceEx);
+        ASSERT(SUCCEEDED(result));
+    }
+
+    initializeDevice();
+
+    return true;
+}
+
+// do any one-time device initialization
+// NOTE: this is also needed after a device lost/reset
+// to reset the scene status and ensure the default states are reset.
+void Display::initializeDevice()
+{
+    // Permanent non-default states
+    mDevice->SetRenderState(D3DRS_POINTSPRITEENABLE, TRUE);
+    mDevice->SetRenderState(D3DRS_LASTPIXEL, FALSE);
+
+    if (mDeviceCaps.PixelShaderVersion >= D3DPS_VERSION(3, 0))
+    {
+        mDevice->SetRenderState(D3DRS_POINTSIZE_MAX, (DWORD&)mDeviceCaps.MaxPointSize);
+    }
+    else
+    {
+        mDevice->SetRenderState(D3DRS_POINTSIZE_MAX, 0x3F800000);   // 1.0f
+    }
+
+    mSceneStarted = false;
+}
+
+bool Display::resetDevice()
+{
+    D3DPRESENT_PARAMETERS presentParameters = getDefaultPresentParameters();
+
+    HRESULT result = D3D_OK;
+    bool lost = testDeviceLost();
+    int attempts = 3;    
+
+    while (lost && attempts > 0)
+    {
+        if (mDeviceEx)
+        {
+            Sleep(500);   // Give the graphics driver some CPU time
+            result = mDeviceEx->ResetEx(&presentParameters, NULL);
+        }
+        else
+        {
+            result = mDevice->TestCooperativeLevel();
+            
+            while (result == D3DERR_DEVICELOST)
+            {
+                Sleep(100);   // Give the graphics driver some CPU time
+                result = mDevice->TestCooperativeLevel();
+            }
+
+            if (result == D3DERR_DEVICENOTRESET)
+            {
+                result = mDevice->Reset(&presentParameters);
+            }
+        }
+
+        lost = testDeviceLost();
+        attempts --;
+    }
+
+    if (FAILED(result))
+    {
+        ERR("Reset/ResetEx failed multiple times: 0x%08X", result);
+        return error(EGL_BAD_ALLOC, false);
+    }
+
+    // reset device defaults
+    initializeDevice();
+
+    return true;
+}
+
+EGLSurface Display::createWindowSurface(HWND window, EGLConfig config, const EGLint *attribList)
+{
+    const Config *configuration = mConfigSet.get(config);
+    EGLint postSubBufferSupported = EGL_FALSE;
+
+    if (attribList)
+    {
+        while (*attribList != EGL_NONE)
+        {
+            switch (attribList[0])
+            {
+              case EGL_RENDER_BUFFER:
+                switch (attribList[1])
+                {
+                  case EGL_BACK_BUFFER:
+                    break;
+                  case EGL_SINGLE_BUFFER:
+                    return error(EGL_BAD_MATCH, EGL_NO_SURFACE);   // Rendering directly to front buffer not supported
+                  default:
+                    return error(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE);
+                }
+                break;
+              case EGL_POST_SUB_BUFFER_SUPPORTED_NV:
+                postSubBufferSupported = attribList[1];
+                break;
+              case EGL_VG_COLORSPACE:
+                return error(EGL_BAD_MATCH, EGL_NO_SURFACE);
+              case EGL_VG_ALPHA_FORMAT:
+                return error(EGL_BAD_MATCH, EGL_NO_SURFACE);
+              default:
+                return error(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE);
+            }
+
+            attribList += 2;
+        }
+    }
+
+    if (hasExistingWindowSurface(window))
+    {
+        return error(EGL_BAD_ALLOC, EGL_NO_SURFACE);
+    }
+
+    if (testDeviceLost()) 
+    {
+        if (!restoreLostDevice())
+            return EGL_NO_SURFACE;
+    }
+
+    Surface *surface = new Surface(this, configuration, window, postSubBufferSupported);
+
+    if (!surface->initialize())
+    {
+        delete surface;
+        return EGL_NO_SURFACE;
+    }
+
+    mSurfaceSet.insert(surface);
+
+    return success(surface);
+}
+
+EGLSurface Display::createOffscreenSurface(EGLConfig config, HANDLE shareHandle, const EGLint *attribList)
+{
+    EGLint width = 0, height = 0;
+    EGLenum textureFormat = EGL_NO_TEXTURE;
+    EGLenum textureTarget = EGL_NO_TEXTURE;
+    const Config *configuration = mConfigSet.get(config);
+
+    if (attribList)
+    {
+        while (*attribList != EGL_NONE)
+        {
+            switch (attribList[0])
+            {
+              case EGL_WIDTH:
+                width = attribList[1];
+                break;
+              case EGL_HEIGHT:
+                height = attribList[1];
+                break;
+              case EGL_LARGEST_PBUFFER:
+                if (attribList[1] != EGL_FALSE)
+                  UNIMPLEMENTED(); // FIXME
+                break;
+              case EGL_TEXTURE_FORMAT:
+                switch (attribList[1])
+                {
+                  case EGL_NO_TEXTURE:
+                  case EGL_TEXTURE_RGB:
+                  case EGL_TEXTURE_RGBA:
+                    textureFormat = attribList[1];
+                    break;
+                  default:
+                    return error(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE);
+                }
+                break;
+              case EGL_TEXTURE_TARGET:
+                switch (attribList[1])
+                {
+                  case EGL_NO_TEXTURE:
+                  case EGL_TEXTURE_2D:
+                    textureTarget = attribList[1];
+                    break;
+                  default:
+                    return error(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE);
+                }
+                break;
+              case EGL_MIPMAP_TEXTURE:
+                if (attribList[1] != EGL_FALSE)
+                  return error(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE);
+                break;
+              case EGL_VG_COLORSPACE:
+                return error(EGL_BAD_MATCH, EGL_NO_SURFACE);
+              case EGL_VG_ALPHA_FORMAT:
+                return error(EGL_BAD_MATCH, EGL_NO_SURFACE);
+              default:
+                return error(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE);
+            }
+
+            attribList += 2;
+        }
+    }
+
+    if (width < 0 || height < 0)
+    {
+        return error(EGL_BAD_PARAMETER, EGL_NO_SURFACE);
+    }
+
+    if (width == 0 || height == 0)
+    {
+        return error(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE);
+    }
+
+    if (textureFormat != EGL_NO_TEXTURE && !getNonPower2TextureSupport() && (!gl::isPow2(width) || !gl::isPow2(height)))
+    {
+        return error(EGL_BAD_MATCH, EGL_NO_SURFACE);
+    }
+
+    if ((textureFormat != EGL_NO_TEXTURE && textureTarget == EGL_NO_TEXTURE) ||
+        (textureFormat == EGL_NO_TEXTURE && textureTarget != EGL_NO_TEXTURE))
+    {
+        return error(EGL_BAD_MATCH, EGL_NO_SURFACE);
+    }
+
+    if (!(configuration->mSurfaceType & EGL_PBUFFER_BIT))
+    {
+        return error(EGL_BAD_MATCH, EGL_NO_SURFACE);
+    }
+
+    if ((textureFormat == EGL_TEXTURE_RGB && configuration->mBindToTextureRGB != EGL_TRUE) ||
+        (textureFormat == EGL_TEXTURE_RGBA && configuration->mBindToTextureRGBA != EGL_TRUE))
+    {
+        return error(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE);
+    }
+
+    if (testDeviceLost()) 
+    {
+        if (!restoreLostDevice())
+            return EGL_NO_SURFACE;
+    }
+
+    Surface *surface = new Surface(this, configuration, shareHandle, width, height, textureFormat, textureTarget);
+
+    if (!surface->initialize())
+    {
+        delete surface;
+        return EGL_NO_SURFACE;
+    }
+
+    mSurfaceSet.insert(surface);
+
+    return success(surface);
+}
+
+EGLContext Display::createContext(EGLConfig configHandle, const gl::Context *shareContext, bool notifyResets, bool robustAccess)
+{
+    if (!mDevice)
+    {
+        if (!createDevice())
+        {
+            return NULL;
+        }
+    }
+    else if (testDeviceLost())   // Lost device
+    {
+        if (!restoreLostDevice())
+            return NULL;
+    }
+
+    const egl::Config *config = mConfigSet.get(configHandle);
+
+    gl::Context *context = glCreateContext(config, shareContext, notifyResets, robustAccess);
+    mContextSet.insert(context);
+    mDeviceLost = false;
+
+    return context;
+}
+
+bool Display::restoreLostDevice()
+{
+    for (ContextSet::iterator ctx = mContextSet.begin(); ctx != mContextSet.end(); ctx++)
+    {
+        if ((*ctx)->isResetNotificationEnabled())
+            return false;   // If reset notifications have been requested, application must delete all contexts first
+    }
+    // Release surface resources to make the Reset() succeed
+    for (SurfaceSet::iterator surface = mSurfaceSet.begin(); surface != mSurfaceSet.end(); surface++)
+    {
+        (*surface)->release();
+    }
+
+    while (!mEventQueryPool.empty())
+    {
+        mEventQueryPool.back()->Release();
+        mEventQueryPool.pop_back();
+    }
+
+    mVertexShaderCache.clear();
+    mPixelShaderCache.clear();
+
+    if (!resetDevice())
+    {
+        return false;
+    }
+
+    // Restore any surfaces that may have been lost
+    for (SurfaceSet::iterator surface = mSurfaceSet.begin(); surface != mSurfaceSet.end(); surface++)
+    {
+        (*surface)->resetSwapChain();
+    }
+
+    return true;
+}
+
+
+void Display::destroySurface(egl::Surface *surface)
+{
+    delete surface;
+    mSurfaceSet.erase(surface);
+}
+
+void Display::destroyContext(gl::Context *context)
+{
+    glDestroyContext(context);
+    mContextSet.erase(context);
+}
+
+void Display::notifyDeviceLost()
+{
+    for (ContextSet::iterator context = mContextSet.begin(); context != mContextSet.end(); context++)
+    {
+        (*context)->markContextLost();
+    }
+    mDeviceLost = true;
+    error(EGL_CONTEXT_LOST);
+}
+
+bool Display::isDeviceLost()
+{
+    return mDeviceLost;
+}
+
+bool Display::isInitialized() const
+{
+    return mD3d9 != NULL && mConfigSet.size() > 0;
+}
+
+bool Display::isValidConfig(EGLConfig config)
+{
+    return mConfigSet.get(config) != NULL;
+}
+
+bool Display::isValidContext(gl::Context *context)
+{
+    return mContextSet.find(context) != mContextSet.end();
+}
+
+bool Display::isValidSurface(egl::Surface *surface)
+{
+    return mSurfaceSet.find(surface) != mSurfaceSet.end();
+}
+
+bool Display::hasExistingWindowSurface(HWND window)
+{
+    for (SurfaceSet::iterator surface = mSurfaceSet.begin(); surface != mSurfaceSet.end(); surface++)
+    {
+        if ((*surface)->getWindowHandle() == window)
+        {
+            return true;
+        }
+    }
+
+    return false;
+}
+
+EGLint Display::getMinSwapInterval()
+{
+    return mMinSwapInterval;
+}
+
+EGLint Display::getMaxSwapInterval()
+{
+    return mMaxSwapInterval;
+}
+
+IDirect3DDevice9 *Display::getDevice()
+{
+    if (!mDevice)
+    {
+        if (!createDevice())
+        {
+            return NULL;
+        }
+    }
+
+    return mDevice;
+}
+
+D3DCAPS9 Display::getDeviceCaps()
+{
+    return mDeviceCaps;
+}
+
+D3DADAPTER_IDENTIFIER9 *Display::getAdapterIdentifier()
+{
+    return &mAdapterIdentifier;
+}
+
+bool Display::testDeviceLost()
+{
+    if (mDeviceEx)
+    {
+        return FAILED(mDeviceEx->CheckDeviceState(NULL));
+    }
+    else if (mDevice)
+    {
+        return FAILED(mDevice->TestCooperativeLevel());
+    }
+
+    return false;   // No device yet, so no reset required
+}
+
+bool Display::testDeviceResettable()
+{
+    HRESULT status = D3D_OK;
+
+    if (mDeviceEx)
+    {
+        status = mDeviceEx->CheckDeviceState(NULL);
+    }
+    else if (mDevice)
+    {
+        status = mDevice->TestCooperativeLevel();
+    }
+
+    switch (status)
+    {
+      case D3DERR_DEVICENOTRESET:
+      case D3DERR_DEVICEHUNG:
+        return true;
+      default:
+        return false;
+    }
+}
+
+void Display::sync(bool block)
+{
+    HRESULT result;
+
+    IDirect3DQuery9* query = allocateEventQuery();
+    if (!query)
+    {
+        return;
+    }
+
+    result = query->Issue(D3DISSUE_END);
+    ASSERT(SUCCEEDED(result));
+
+    do
+    {
+        result = query->GetData(NULL, 0, D3DGETDATA_FLUSH);
+
+        if(block && result == S_FALSE)
+        {
+            // Keep polling, but allow other threads to do something useful first
+            Sleep(0);
+            // explicitly check for device loss
+            // some drivers seem to return S_FALSE even if the device is lost
+            // instead of D3DERR_DEVICELOST like they should
+            if (testDeviceLost())
+            {
+                result = D3DERR_DEVICELOST;
+            }
+        }
+    }
+    while(block && result == S_FALSE);
+
+    freeEventQuery(query);
+
+    if (isDeviceLostError(result))
+    {
+        notifyDeviceLost();
+    }
+}
+
+IDirect3DQuery9* Display::allocateEventQuery()
+{
+    IDirect3DQuery9 *query = NULL;
+
+    if (mEventQueryPool.empty())
+    {
+        HRESULT result = mDevice->CreateQuery(D3DQUERYTYPE_EVENT, &query);
+        ASSERT(SUCCEEDED(result));
+    }
+    else
+    {
+        query = mEventQueryPool.back();
+        mEventQueryPool.pop_back();
+    }
+
+    return query;
+}
+
+void Display::freeEventQuery(IDirect3DQuery9* query)
+{
+    if (mEventQueryPool.size() > 1000)
+    {
+        query->Release();
+    }
+    else
+    {
+        mEventQueryPool.push_back(query);
+    }
+}
+
+void Display::getMultiSampleSupport(D3DFORMAT format, bool *multiSampleArray)
+{
+    for (int multiSampleIndex = 0; multiSampleIndex <= D3DMULTISAMPLE_16_SAMPLES; multiSampleIndex++)
+    {
+        HRESULT result = mD3d9->CheckDeviceMultiSampleType(mAdapter, mDeviceType, format,
+                                                           TRUE, (D3DMULTISAMPLE_TYPE)multiSampleIndex, NULL);
+
+        multiSampleArray[multiSampleIndex] = SUCCEEDED(result);
+    }
+}
+
+bool Display::getDXT1TextureSupport()
+{
+    D3DDISPLAYMODE currentDisplayMode;
+    mD3d9->GetAdapterDisplayMode(mAdapter, &currentDisplayMode);
+
+    return SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, 0, D3DRTYPE_TEXTURE, D3DFMT_DXT1));
+}
+
+bool Display::getDXT3TextureSupport()
+{
+    D3DDISPLAYMODE currentDisplayMode;
+    mD3d9->GetAdapterDisplayMode(mAdapter, &currentDisplayMode);
+
+    return SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, 0, D3DRTYPE_TEXTURE, D3DFMT_DXT3));
+}
+
+bool Display::getDXT5TextureSupport()
+{
+    D3DDISPLAYMODE currentDisplayMode;
+    mD3d9->GetAdapterDisplayMode(mAdapter, &currentDisplayMode);
+
+    return SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, 0, D3DRTYPE_TEXTURE, D3DFMT_DXT5));
+}
+
+// we use INTZ for depth textures in Direct3D9
+// we also want NULL texture support to ensure the we can make depth-only FBOs
+// see http://aras-p.info/texts/D3D9GPUHacks.html
+bool Display::getDepthTextureSupport() const
+{
+    D3DDISPLAYMODE currentDisplayMode;
+    mD3d9->GetAdapterDisplayMode(mAdapter, &currentDisplayMode);
+
+    bool intz = SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format,
+                                                   D3DUSAGE_DEPTHSTENCIL, D3DRTYPE_TEXTURE, D3DFMT_INTZ));
+    bool null = SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format,
+                                                   D3DUSAGE_RENDERTARGET, D3DRTYPE_SURFACE, D3DFMT_NULL));
+
+    return intz && null;
+}
+
+bool Display::getFloat32TextureSupport(bool *filtering, bool *renderable)
+{
+    D3DDISPLAYMODE currentDisplayMode;
+    mD3d9->GetAdapterDisplayMode(mAdapter, &currentDisplayMode);
+
+    *filtering = SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, D3DUSAGE_QUERY_FILTER, 
+                                                    D3DRTYPE_TEXTURE, D3DFMT_A32B32G32R32F)) &&
+                 SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, D3DUSAGE_QUERY_FILTER,
+                                                    D3DRTYPE_CUBETEXTURE, D3DFMT_A32B32G32R32F));
+    
+    *renderable = SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, D3DUSAGE_RENDERTARGET,
+                                                     D3DRTYPE_TEXTURE, D3DFMT_A32B32G32R32F))&&
+                  SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, D3DUSAGE_RENDERTARGET,
+                                                     D3DRTYPE_CUBETEXTURE, D3DFMT_A32B32G32R32F));
+
+    if (!*filtering && !*renderable)
+    {
+        return SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, 0, 
+                                                  D3DRTYPE_TEXTURE, D3DFMT_A32B32G32R32F)) &&
+               SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, 0,
+                                                  D3DRTYPE_CUBETEXTURE, D3DFMT_A32B32G32R32F));
+    }
+    else
+    {
+        return true;
+    }
+}
+
+bool Display::getFloat16TextureSupport(bool *filtering, bool *renderable)
+{
+    D3DDISPLAYMODE currentDisplayMode;
+    mD3d9->GetAdapterDisplayMode(mAdapter, &currentDisplayMode);
+
+    *filtering = SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, D3DUSAGE_QUERY_FILTER, 
+                                                    D3DRTYPE_TEXTURE, D3DFMT_A16B16G16R16F)) &&
+                 SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, D3DUSAGE_QUERY_FILTER,
+                                                    D3DRTYPE_CUBETEXTURE, D3DFMT_A16B16G16R16F));
+    
+    *renderable = SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, D3DUSAGE_RENDERTARGET, 
+                                                    D3DRTYPE_TEXTURE, D3DFMT_A16B16G16R16F)) &&
+                 SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, D3DUSAGE_RENDERTARGET,
+                                                    D3DRTYPE_CUBETEXTURE, D3DFMT_A16B16G16R16F));
+
+    if (!*filtering && !*renderable)
+    {
+        return SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, 0, 
+                                                  D3DRTYPE_TEXTURE, D3DFMT_A16B16G16R16F)) &&
+               SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, 0,
+                                                  D3DRTYPE_CUBETEXTURE, D3DFMT_A16B16G16R16F));
+    }
+    else
+    {
+        return true;
+    }
+}
+
+bool Display::getLuminanceTextureSupport()
+{
+    D3DDISPLAYMODE currentDisplayMode;
+    mD3d9->GetAdapterDisplayMode(mAdapter, &currentDisplayMode);
+
+    return SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, 0, D3DRTYPE_TEXTURE, D3DFMT_L8));
+}
+
+bool Display::getLuminanceAlphaTextureSupport()
+{
+    D3DDISPLAYMODE currentDisplayMode;
+    mD3d9->GetAdapterDisplayMode(mAdapter, &currentDisplayMode);
+
+    return SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, 0, D3DRTYPE_TEXTURE, D3DFMT_A8L8));
+}
+
+float Display::getTextureFilterAnisotropySupport() const
+{
+    // Must support a minimum of 2:1 anisotropy for max anisotropy to be considered supported, per the spec
+    if ((mDeviceCaps.RasterCaps & D3DPRASTERCAPS_ANISOTROPY) && (mDeviceCaps.MaxAnisotropy >= 2))
+    {
+        return mDeviceCaps.MaxAnisotropy;
+    }
+    return 1.0f;
+}
+
+D3DPOOL Display::getBufferPool(DWORD usage) const
+{
+    if (mD3d9Ex != NULL)
+    {
+        return D3DPOOL_DEFAULT;
+    }
+    else
+    {
+        if (!(usage & D3DUSAGE_DYNAMIC))
+        {
+            return D3DPOOL_MANAGED;
+        }
+    }
+
+    return D3DPOOL_DEFAULT;
+}
+
+D3DPOOL Display::getTexturePool(DWORD usage) const
+{
+    if (mD3d9Ex != NULL)
+    {
+        return D3DPOOL_DEFAULT;
+    }
+    else
+    {
+        if (!(usage & (D3DUSAGE_DEPTHSTENCIL | D3DUSAGE_RENDERTARGET)))
+        {
+            return D3DPOOL_MANAGED;
+        }
+    }
+
+    return D3DPOOL_DEFAULT;
+}
+
+bool Display::getEventQuerySupport()
+{
+    IDirect3DQuery9 *query = allocateEventQuery();
+    if (query)
+    {
+        freeEventQuery(query);
+        return true;
+    }
+    else
+    {
+        return false;
+    }
+}
+
+D3DPRESENT_PARAMETERS Display::getDefaultPresentParameters()
+{
+    D3DPRESENT_PARAMETERS presentParameters = {0};
+
+    // The default swap chain is never actually used. Surface will create a new swap chain with the proper parameters.
+    presentParameters.AutoDepthStencilFormat = D3DFMT_UNKNOWN;
+    presentParameters.BackBufferCount = 1;
+    presentParameters.BackBufferFormat = D3DFMT_UNKNOWN;
+    presentParameters.BackBufferWidth = 1;
+    presentParameters.BackBufferHeight = 1;
+    presentParameters.EnableAutoDepthStencil = FALSE;
+    presentParameters.Flags = 0;
+    presentParameters.hDeviceWindow = mDeviceWindow;
+    presentParameters.MultiSampleQuality = 0;
+    presentParameters.MultiSampleType = D3DMULTISAMPLE_NONE;
+    presentParameters.PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT;
+    presentParameters.SwapEffect = D3DSWAPEFFECT_DISCARD;
+    presentParameters.Windowed = TRUE;
+
+    return presentParameters;
+}
+
+void Display::initExtensionString()
+{
+    HMODULE swiftShader = GetModuleHandle(TEXT("swiftshader_d3d9.dll"));
+
+    mExtensionString = "";
+
+    // Multi-vendor (EXT) extensions
+    mExtensionString += "EGL_EXT_create_context_robustness ";
+
+    // ANGLE-specific extensions
+    if (shareHandleSupported())
+    {
+        mExtensionString += "EGL_ANGLE_d3d_share_handle_client_buffer ";
+    }
+
+    mExtensionString += "EGL_ANGLE_query_surface_pointer ";
+
+    if (swiftShader)
+    {
+        mExtensionString += "EGL_ANGLE_software_display ";
+    }
+
+    if (shareHandleSupported())
+    {
+        mExtensionString += "EGL_ANGLE_surface_d3d_texture_2d_share_handle ";
+    }
+
+    mExtensionString += "EGL_NV_post_sub_buffer";
+
+    std::string::size_type end = mExtensionString.find_last_not_of(' ');
+    if (end != std::string::npos)
+    {
+        mExtensionString.resize(end+1);
+    }
+}
+
+const char *Display::getExtensionString() const
+{
+    return mExtensionString.c_str();
+}
+
+bool Display::shareHandleSupported() const 
+{
+    // PIX doesn't seem to support using share handles, so disable them.
+    return isD3d9ExDevice() && !gl::perfActive();
+}
+
+IDirect3DVertexShader9 *Display::createVertexShader(const DWORD *function, size_t length)
+{
+    return mVertexShaderCache.create(function, length);
+}
+
+IDirect3DPixelShader9 *Display::createPixelShader(const DWORD *function, size_t length)
+{
+    return mPixelShaderCache.create(function, length);
+}
+
+// Only Direct3D 10 ready devices support all the necessary vertex texture formats.
+// We test this using D3D9 by checking support for the R16F format.
+bool Display::getVertexTextureSupport() const
+{
+    if (!isInitialized() || mDeviceCaps.PixelShaderVersion < D3DPS_VERSION(3, 0))
+    {
+        return false;
+    }
+
+    D3DDISPLAYMODE currentDisplayMode;
+    mD3d9->GetAdapterDisplayMode(mAdapter, &currentDisplayMode);
+
+    HRESULT result = mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, D3DUSAGE_QUERY_VERTEXTEXTURE, D3DRTYPE_TEXTURE, D3DFMT_R16F);
+
+    return SUCCEEDED(result);
+}
+
+bool Display::getNonPower2TextureSupport() const
+{
+    return mSupportsNonPower2Textures;
+}
+
+bool Display::getOcclusionQuerySupport() const
+{
+    if (!isInitialized())
+    {
+        return false;
+    }
+
+    IDirect3DQuery9 *query = NULL;
+    HRESULT result = mDevice->CreateQuery(D3DQUERYTYPE_OCCLUSION, &query);
+    
+    if (SUCCEEDED(result) && query)
+    {
+        query->Release();
+        return true;
+    }
+    else
+    {
+        return false;
+    }
+}
+
+bool Display::getInstancingSupport() const
+{
+    return mDeviceCaps.PixelShaderVersion >= D3DPS_VERSION(3, 0); 
+}
+
+}
diff --git a/src/3rdparty/angle/src/libEGL/Display.h b/src/3rdparty/angle/src/libEGL/Display.h
new file mode 100644 (file)
index 0000000..23b57b7
--- /dev/null
@@ -0,0 +1,167 @@
+//
+// 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.
+//
+
+// Display.h: Defines the egl::Display class, representing the abstract
+// display on which graphics are drawn. Implements EGLDisplay.
+// [EGL 1.4] section 2.1.2 page 3.
+
+#ifndef LIBEGL_DISPLAY_H_
+#define LIBEGL_DISPLAY_H_
+
+#ifndef WIN32_LEAN_AND_MEAN
+#define WIN32_LEAN_AND_MEAN
+#endif
+#include <windows.h>
+#include <d3d9.h>
+
+#include <set>
+#include <vector>
+
+#include "libGLESv2/Context.h"
+
+#include "libEGL/Config.h"
+#include "libEGL/ShaderCache.h"
+#include "libEGL/Surface.h"
+
+const int versionWindowsVista = MAKEWORD(0x00, 0x06);
+const int versionWindows7 = MAKEWORD(0x01, 0x06);
+
+// Return the version of the operating system in a format suitable for ordering
+// comparison.
+inline int getComparableOSVersion()
+{
+    DWORD version = GetVersion();
+    int majorVersion = LOBYTE(LOWORD(version));
+    int minorVersion = HIBYTE(LOWORD(version));
+    return MAKEWORD(minorVersion, majorVersion);
+}
+
+namespace egl
+{
+class Display
+{
+  public:
+    ~Display();
+
+    bool initialize();
+    void terminate();
+
+    virtual void startScene();
+    virtual void endScene();
+
+    static egl::Display *getDisplay(EGLNativeDisplayType displayId);
+
+    bool getConfigs(EGLConfig *configs, const EGLint *attribList, EGLint configSize, EGLint *numConfig);
+    bool getConfigAttrib(EGLConfig config, EGLint attribute, EGLint *value);
+
+    EGLSurface createWindowSurface(HWND window, EGLConfig config, const EGLint *attribList);
+    EGLSurface createOffscreenSurface(EGLConfig config, HANDLE shareHandle, const EGLint *attribList);
+    EGLContext createContext(EGLConfig configHandle, const gl::Context *shareContext, bool notifyResets, bool robustAccess);
+
+    void destroySurface(egl::Surface *surface);
+    void destroyContext(gl::Context *context);
+
+    bool isInitialized() const;
+    bool isValidConfig(EGLConfig config);
+    bool isValidContext(gl::Context *context);
+    bool isValidSurface(egl::Surface *surface);
+    bool hasExistingWindowSurface(HWND window);
+
+    EGLint getMinSwapInterval();
+    EGLint getMaxSwapInterval();
+
+    virtual IDirect3DDevice9 *getDevice();
+    virtual D3DCAPS9 getDeviceCaps();
+    virtual D3DADAPTER_IDENTIFIER9 *getAdapterIdentifier();
+    virtual bool testDeviceLost();
+    virtual bool testDeviceResettable();
+    virtual void sync(bool block);
+    virtual IDirect3DQuery9* allocateEventQuery();
+    virtual void freeEventQuery(IDirect3DQuery9* query);
+    virtual void getMultiSampleSupport(D3DFORMAT format, bool *multiSampleArray);
+    virtual bool getDXT1TextureSupport();
+    virtual bool getDXT3TextureSupport();
+    virtual bool getDXT5TextureSupport();
+    virtual bool getEventQuerySupport();
+    virtual bool getFloat32TextureSupport(bool *filtering, bool *renderable);
+    virtual bool getFloat16TextureSupport(bool *filtering, bool *renderable);
+    virtual bool getLuminanceTextureSupport();
+    virtual bool getLuminanceAlphaTextureSupport();
+    virtual bool getVertexTextureSupport() const;
+    virtual bool getNonPower2TextureSupport() const;
+    virtual bool getDepthTextureSupport() const;
+    virtual bool getOcclusionQuerySupport() const;
+    virtual bool getInstancingSupport() const;
+    virtual float getTextureFilterAnisotropySupport() const;
+    virtual D3DPOOL getBufferPool(DWORD usage) const;
+    virtual D3DPOOL getTexturePool(DWORD usage) const;
+
+    virtual void notifyDeviceLost();
+    bool isDeviceLost();
+
+    bool isD3d9ExDevice() const { return mD3d9Ex != NULL; }
+    const char *getExtensionString() const;
+    bool shareHandleSupported() const;
+
+    virtual IDirect3DVertexShader9 *createVertexShader(const DWORD *function, size_t length);
+    virtual IDirect3DPixelShader9 *createPixelShader(const DWORD *function, size_t length);
+
+  private:
+    DISALLOW_COPY_AND_ASSIGN(Display);
+
+    Display(EGLNativeDisplayType displayId, HDC deviceContext, bool software);
+
+    D3DPRESENT_PARAMETERS getDefaultPresentParameters();
+
+    bool restoreLostDevice();
+
+    EGLNativeDisplayType mDisplayId;
+    const HDC mDc;
+
+    HMODULE mD3d9Module;
+    
+    UINT mAdapter;
+    D3DDEVTYPE mDeviceType;
+    IDirect3D9 *mD3d9;  // Always valid after successful initialization.
+    IDirect3D9Ex *mD3d9Ex;  // Might be null if D3D9Ex is not supported.
+    IDirect3DDevice9 *mDevice;
+    IDirect3DDevice9Ex *mDeviceEx;  // Might be null if D3D9Ex is not supported.
+
+    // A pool of event queries that are currently unused.
+    std::vector<IDirect3DQuery9*> mEventQueryPool;
+
+    VertexShaderCache mVertexShaderCache;
+    PixelShaderCache mPixelShaderCache;
+
+    D3DCAPS9 mDeviceCaps;
+    D3DADAPTER_IDENTIFIER9 mAdapterIdentifier;
+    HWND mDeviceWindow;
+
+    bool mSceneStarted;
+    EGLint mMaxSwapInterval;
+    EGLint mMinSwapInterval;
+    bool mSoftwareDevice;
+    bool mSupportsNonPower2Textures;
+    
+    typedef std::set<Surface*> SurfaceSet;
+    SurfaceSet mSurfaceSet;
+
+    ConfigSet mConfigSet;
+
+    typedef std::set<gl::Context*> ContextSet;
+    ContextSet mContextSet;
+    bool mDeviceLost;
+
+    bool createDevice();
+    void initializeDevice();
+    bool resetDevice();
+
+    void initExtensionString();
+    std::string mExtensionString;
+};
+}
+
+#endif   // LIBEGL_DISPLAY_H_
diff --git a/src/3rdparty/angle/src/libEGL/ShaderCache.h b/src/3rdparty/angle/src/libEGL/ShaderCache.h
new file mode 100644 (file)
index 0000000..cfe523b
--- /dev/null
@@ -0,0 +1,116 @@
+//
+// 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.
+//
+
+// Display.h: Defines egl::ShaderCache, a cache of Direct3D shader objects
+// keyed by their byte code.
+
+#ifndef LIBEGL_SHADER_CACHE_H_
+#define LIBEGL_SHADER_CACHE_H_
+
+#include <d3d9.h>
+
+#ifdef _MSC_VER
+#include <hash_map>
+#else
+#include <unordered_map>
+#endif
+
+namespace egl
+{
+template <typename ShaderObject>
+class ShaderCache
+{
+  public:
+    ShaderCache() : mDevice(NULL)
+    {
+    }
+
+    ~ShaderCache()
+    {
+        // Call clear while the device is still valid.
+        ASSERT(mMap.empty());
+    }
+
+    void initialize(IDirect3DDevice9* device)
+    {
+        mDevice = device;
+    }
+
+    ShaderObject *create(const DWORD *function, size_t length)
+    {
+        std::string key(reinterpret_cast<const char*>(function), length);
+        typename Map::iterator it = mMap.find(key);
+        if (it != mMap.end())
+        {
+            it->second->AddRef();
+            return it->second;
+        }
+        
+        ShaderObject *shader;
+        HRESULT result = createShader(function, &shader);
+        if (FAILED(result))
+        {
+            return NULL;
+        }
+
+        // Random eviction policy.
+        if (mMap.size() >= kMaxMapSize)
+        {
+            mMap.begin()->second->Release();
+            mMap.erase(mMap.begin());
+        }
+
+        shader->AddRef();
+        mMap[key] = shader;
+
+        return shader;
+    }
+
+    void clear()
+    {
+        for (typename Map::iterator it = mMap.begin(); it != mMap.end(); ++it)
+        {
+            it->second->Release();
+        }
+
+        mMap.clear();
+    }
+
+  private:
+    DISALLOW_COPY_AND_ASSIGN(ShaderCache);
+
+    const static size_t kMaxMapSize = 100;
+
+    HRESULT createShader(const DWORD *function, IDirect3DVertexShader9 **shader)
+    {
+        return mDevice->CreateVertexShader(function, shader);
+    }
+
+    HRESULT createShader(const DWORD *function, IDirect3DPixelShader9 **shader)
+    {
+        return mDevice->CreatePixelShader(function, shader);
+    }
+
+#ifndef HASH_MAP
+# ifdef _MSC_VER
+#  define HASH_MAP stdext::hash_map
+# else
+#  define HASH_MAP std::unordered_map
+# endif
+#endif
+
+    typedef HASH_MAP<std::string, ShaderObject*> Map;
+    Map mMap;
+
+    IDirect3DDevice9 *mDevice;
+};
+
+typedef ShaderCache<IDirect3DVertexShader9> VertexShaderCache;
+typedef ShaderCache<IDirect3DPixelShader9> PixelShaderCache;
+
+}
+
+#endif   // LIBEGL_SHADER_CACHE_H_
diff --git a/src/3rdparty/angle/src/libEGL/Surface.cpp b/src/3rdparty/angle/src/libEGL/Surface.cpp
new file mode 100644 (file)
index 0000000..732c404
--- /dev/null
@@ -0,0 +1,674 @@
+//
+// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// Surface.cpp: Implements the egl::Surface class, representing a drawing surface
+// such as the client area of a window, including any back buffers.
+// Implements EGLSurface and related functionality. [EGL 1.4] section 2.2 page 3.
+
+#include <tchar.h>
+
+#include "libEGL/Surface.h"
+
+#include "common/debug.h"
+#include "libGLESv2/Texture.h"
+
+#include "libEGL/main.h"
+#include "libEGL/Display.h"
+
+#include <dwmapi.h>
+
+namespace egl
+{
+
+Surface::Surface(Display *display, const Config *config, HWND window, EGLint postSubBufferSupported) 
+    : mDisplay(display), mConfig(config), mWindow(window), mPostSubBufferSupported(postSubBufferSupported)
+{
+    mSwapChain = NULL;
+    mBackBuffer = NULL;
+    mDepthStencil = NULL;
+    mRenderTarget = NULL;
+    mOffscreenTexture = NULL;
+    mShareHandle = NULL;
+    mTexture = NULL;
+    mTextureFormat = EGL_NO_TEXTURE;
+    mTextureTarget = EGL_NO_TEXTURE;
+
+    mPixelAspectRatio = (EGLint)(1.0 * EGL_DISPLAY_SCALING);   // FIXME: Determine actual pixel aspect ratio
+    mRenderBuffer = EGL_BACK_BUFFER;
+    mSwapBehavior = EGL_BUFFER_PRESERVED;
+    mSwapInterval = -1;
+    setSwapInterval(1);
+
+    subclassWindow();
+}
+
+Surface::Surface(Display *display, const Config *config, HANDLE shareHandle, EGLint width, EGLint height, EGLenum textureFormat, EGLenum textureType)
+    : mDisplay(display), mWindow(NULL), mConfig(config), mShareHandle(shareHandle), mWidth(width), mHeight(height), mPostSubBufferSupported(EGL_FALSE)
+{
+    mSwapChain = NULL;
+    mBackBuffer = NULL;
+    mDepthStencil = NULL;
+    mRenderTarget = NULL;
+    mOffscreenTexture = NULL;
+    mWindowSubclassed = false;
+    mTexture = NULL;
+    mTextureFormat = textureFormat;
+    mTextureTarget = textureType;
+
+    mPixelAspectRatio = (EGLint)(1.0 * EGL_DISPLAY_SCALING);   // FIXME: Determine actual pixel aspect ratio
+    mRenderBuffer = EGL_BACK_BUFFER;
+    mSwapBehavior = EGL_BUFFER_PRESERVED;
+    mSwapInterval = -1;
+    setSwapInterval(1);
+}
+
+Surface::~Surface()
+{
+    unsubclassWindow();
+    release();
+}
+
+bool Surface::initialize()
+{
+    ASSERT(!mSwapChain && !mOffscreenTexture && !mDepthStencil);
+
+    if (!resetSwapChain())
+      return false;
+
+    // Modify present parameters for this window, if we are composited,
+    // to minimize the amount of queuing done by DWM between our calls to
+    // present and the actual screen.
+    if (mWindow && (getComparableOSVersion() >= versionWindowsVista)) {
+      BOOL isComposited;
+      HRESULT result = DwmIsCompositionEnabled(&isComposited);
+      if (SUCCEEDED(result) && isComposited) {
+        DWM_PRESENT_PARAMETERS presentParams;
+        memset(&presentParams, 0, sizeof(presentParams));
+        presentParams.cbSize = sizeof(DWM_PRESENT_PARAMETERS);
+        presentParams.cBuffer = 2;
+
+        result = DwmSetPresentParameters(mWindow, &presentParams);
+        if (FAILED(result))
+          ERR("Unable to set present parameters: 0x%08X", result);
+      }
+    }
+
+    return true;
+}
+
+void Surface::release()
+{
+    if (mSwapChain)
+    {
+        mSwapChain->Release();
+        mSwapChain = NULL;
+    }
+
+    if (mBackBuffer)
+    {
+        mBackBuffer->Release();
+        mBackBuffer = NULL;
+    }
+
+    if (mDepthStencil)
+    {
+        mDepthStencil->Release();
+        mDepthStencil = NULL;
+    }
+
+    if (mRenderTarget)
+    {
+        mRenderTarget->Release();
+        mRenderTarget = NULL;
+    }
+
+    if (mOffscreenTexture)
+    {
+        mOffscreenTexture->Release();
+        mOffscreenTexture = NULL;
+    }
+
+    if (mTexture)
+    {
+        mTexture->releaseTexImage();
+        mTexture = NULL;
+    }
+
+    mShareHandle = NULL;
+}
+
+bool Surface::resetSwapChain()
+{
+    if (!mWindow)
+    {
+        return resetSwapChain(mWidth, mHeight);
+    }
+
+    RECT windowRect;
+    if (!GetClientRect(getWindowHandle(), &windowRect))
+    {
+        ASSERT(false);
+
+        ERR("Could not retrieve the window dimensions");
+        return false;
+    }
+
+    return resetSwapChain(windowRect.right - windowRect.left, windowRect.bottom - windowRect.top);
+}
+
+bool Surface::resetSwapChain(int backbufferWidth, int backbufferHeight)
+{
+    IDirect3DDevice9 *device = mDisplay->getDevice();
+
+    if (device == NULL)
+    {
+        return false;
+    }
+
+    // Evict all non-render target textures to system memory and release all resources
+    // before reallocating them to free up as much video memory as possible.
+    device->EvictManagedResources();
+
+    HRESULT result;
+
+    // Release specific resources to free up memory for the new render target, while the
+    // old render target still exists for the purpose of preserving its contents.
+    if (mSwapChain)
+    {
+        mSwapChain->Release();
+        mSwapChain = NULL;
+    }
+
+    if (mBackBuffer)
+    {
+        mBackBuffer->Release();
+        mBackBuffer = NULL;
+    }
+
+    if (mOffscreenTexture)
+    {
+        mOffscreenTexture->Release();
+        mOffscreenTexture = NULL;
+    }
+
+    if (mDepthStencil)
+    {
+        mDepthStencil->Release();
+        mDepthStencil = NULL;
+    }
+
+    mShareHandle = NULL;
+    HANDLE *pShareHandle = NULL;
+    if (!mWindow && mDisplay->shareHandleSupported())
+    {
+        pShareHandle = &mShareHandle;
+    }
+
+    result = device->CreateTexture(backbufferWidth, backbufferHeight, 1, D3DUSAGE_RENDERTARGET,
+                                   mConfig->mRenderTargetFormat, D3DPOOL_DEFAULT, &mOffscreenTexture, pShareHandle);
+    if (FAILED(result))
+    {
+        ERR("Could not create offscreen texture: %08lX", result);
+        release();
+
+        if(isDeviceLostError(result))
+        {
+            mDisplay->notifyDeviceLost();
+            return false;
+        }
+        else
+        {
+            return error(EGL_BAD_ALLOC, false);
+        }
+    }
+
+    IDirect3DSurface9 *oldRenderTarget = mRenderTarget;
+
+    result = mOffscreenTexture->GetSurfaceLevel(0, &mRenderTarget);
+    ASSERT(SUCCEEDED(result));
+
+    if (oldRenderTarget)
+    {
+        RECT rect =
+        {
+            0, 0,
+            mWidth, mHeight
+        };
+
+        if (rect.right > static_cast<LONG>(backbufferWidth))
+        {
+            rect.right = backbufferWidth;
+        }
+
+        if (rect.bottom > static_cast<LONG>(backbufferHeight))
+        {
+            rect.bottom = backbufferHeight;
+        }
+
+        mDisplay->endScene();
+
+        result = device->StretchRect(oldRenderTarget, &rect, mRenderTarget, &rect, D3DTEXF_NONE);
+        ASSERT(SUCCEEDED(result));
+
+        oldRenderTarget->Release();
+    }
+
+    if (mWindow)
+    {
+        D3DPRESENT_PARAMETERS presentParameters = {0};
+        presentParameters.AutoDepthStencilFormat = mConfig->mDepthStencilFormat;
+        presentParameters.BackBufferCount = 1;
+        presentParameters.BackBufferFormat = mConfig->mRenderTargetFormat;
+        presentParameters.EnableAutoDepthStencil = FALSE;
+        presentParameters.Flags = 0;
+        presentParameters.hDeviceWindow = getWindowHandle();
+        presentParameters.MultiSampleQuality = 0;                  // FIXME: Unimplemented
+        presentParameters.MultiSampleType = D3DMULTISAMPLE_NONE;   // FIXME: Unimplemented
+        presentParameters.PresentationInterval = mPresentInterval;
+        presentParameters.SwapEffect = D3DSWAPEFFECT_DISCARD;
+        presentParameters.Windowed = TRUE;
+        presentParameters.BackBufferWidth = backbufferWidth;
+        presentParameters.BackBufferHeight = backbufferHeight;
+
+        // http://crbug.com/140239
+        // http://crbug.com/143434
+        //
+        // Some AMD/Intel switchable systems / drivers appear to round swap chain surfaces to a multiple of 64 pixels in width
+        // when using the integrated Intel. This rounds the width up rather than down.
+        //
+        // Some non-switchable AMD GPUs / drivers do not respect the source rectangle to Present. Therefore, when the vendor ID
+        // is not Intel, the back buffer width must be exactly the same width as the window or horizontal scaling will occur.
+        D3DADAPTER_IDENTIFIER9* adapterIdentifier = mDisplay->getAdapterIdentifier();
+        if (adapterIdentifier->VendorId == VENDOR_ID_INTEL)
+        {
+            presentParameters.BackBufferWidth = (presentParameters.BackBufferWidth + 63) / 64 * 64;
+        }
+
+        result = device->CreateAdditionalSwapChain(&presentParameters, &mSwapChain);
+
+        if (FAILED(result))
+        {
+            ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY || result == D3DERR_INVALIDCALL || result == D3DERR_DEVICELOST);
+
+            ERR("Could not create additional swap chains or offscreen surfaces: %08lX", result);
+            release();
+
+            if(isDeviceLostError(result))
+            {
+                mDisplay->notifyDeviceLost();
+                return false;
+            }
+            else
+            {
+                return error(EGL_BAD_ALLOC, false);
+            }
+        }
+
+        result = mSwapChain->GetBackBuffer(0, D3DBACKBUFFER_TYPE_MONO, &mBackBuffer);
+        ASSERT(SUCCEEDED(result));
+    }
+
+    if (mConfig->mDepthStencilFormat != D3DFMT_UNKNOWN)
+    {
+        result = device->CreateDepthStencilSurface(backbufferWidth, backbufferHeight, mConfig->mDepthStencilFormat, D3DMULTISAMPLE_NONE,
+                                                   0, FALSE, &mDepthStencil, NULL);
+
+        if (FAILED(result))
+        {
+            ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY || result == D3DERR_INVALIDCALL);
+
+            ERR("Could not create depthstencil surface for new swap chain: 0x%08X", result);
+            release();
+
+            if(isDeviceLostError(result))
+            {
+                mDisplay->notifyDeviceLost();
+                return false;
+            }
+            else
+            {
+                return error(EGL_BAD_ALLOC, false);
+            }
+        }
+    }
+
+    mWidth = backbufferWidth;
+    mHeight = backbufferHeight;
+
+    mPresentIntervalDirty = false;
+    return true;
+}
+
+bool Surface::swapRect(EGLint x, EGLint y, EGLint width, EGLint height)
+{
+    if (!mSwapChain)
+    {
+        return true;
+    }
+
+    if (x + width > mWidth)
+    {
+        width = mWidth - x;
+    }
+
+    if (y + height > mHeight)
+    {
+        height = mHeight - y;
+    }
+
+    if (width == 0 || height == 0)
+    {
+        return true;
+    }
+
+    IDirect3DDevice9 *device = mDisplay->getDevice();
+
+    // Disable all pipeline operations
+    device->SetRenderState(D3DRS_ZENABLE, D3DZB_FALSE);
+    device->SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID);
+    device->SetRenderState(D3DRS_ALPHATESTENABLE, FALSE);
+    device->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
+    device->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
+    device->SetRenderState(D3DRS_STENCILENABLE, FALSE);
+    device->SetRenderState(D3DRS_CLIPPLANEENABLE, 0);
+    device->SetRenderState(D3DRS_COLORWRITEENABLE, D3DCOLORWRITEENABLE_ALPHA | D3DCOLORWRITEENABLE_BLUE | D3DCOLORWRITEENABLE_GREEN | D3DCOLORWRITEENABLE_RED);
+    device->SetRenderState(D3DRS_SRGBWRITEENABLE, FALSE);
+    device->SetRenderState(D3DRS_SCISSORTESTENABLE, FALSE);
+    device->SetPixelShader(NULL);
+    device->SetVertexShader(NULL);
+
+    device->SetRenderTarget(0, mBackBuffer);
+    device->SetDepthStencilSurface(NULL);
+
+    device->SetTexture(0, mOffscreenTexture);
+    device->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
+    device->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
+    device->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE);
+    device->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_POINT);
+    device->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_POINT);
+    device->SetSamplerState(0, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP);
+    device->SetSamplerState(0, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP);
+    device->SetFVF(D3DFVF_XYZRHW | D3DFVF_TEX1);
+
+    D3DVIEWPORT9 viewport = {0, 0, mWidth, mHeight, 0.0f, 1.0f};
+    device->SetViewport(&viewport);
+
+    float x1 = x - 0.5f;
+    float y1 = (mHeight - y - height) - 0.5f;
+    float x2 = (x + width) - 0.5f;
+    float y2 = (mHeight - y) - 0.5f;
+
+    float u1 = x / float(mWidth);
+    float v1 = y / float(mHeight);
+    float u2 = (x + width) / float(mWidth);
+    float v2 = (y + height) / float(mHeight);
+
+    float quad[4][6] = {{x1, y1, 0.0f, 1.0f, u1, v2},
+                        {x2, y1, 0.0f, 1.0f, u2, v2},
+                        {x2, y2, 0.0f, 1.0f, u2, v1},
+                        {x1, y2, 0.0f, 1.0f, u1, v1}};   // x, y, z, rhw, u, v
+
+    mDisplay->startScene();
+    device->DrawPrimitiveUP(D3DPT_TRIANGLEFAN, 2, quad, 6 * sizeof(float));
+    mDisplay->endScene();
+
+    device->SetTexture(0, NULL);
+
+    RECT rect =
+    {
+        x, mHeight - y - height,
+        x + width, mHeight - y
+    };
+
+    HRESULT result = mSwapChain->Present(&rect, &rect, NULL, NULL, 0);
+
+    gl::Context *context = static_cast<gl::Context*>(glGetCurrentContext());
+    if (context)
+    {
+        context->markAllStateDirty();
+    }
+
+    if (isDeviceLostError(result))
+    {
+        mDisplay->notifyDeviceLost();
+        return false;
+    }
+
+    if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY || result == D3DERR_DRIVERINTERNALERROR)
+    {
+        return error(EGL_BAD_ALLOC, false);
+    }
+
+    ASSERT(SUCCEEDED(result));
+
+    checkForOutOfDateSwapChain();
+
+    return true;
+}
+
+HWND Surface::getWindowHandle()
+{
+    return mWindow;
+}
+
+
+#define kSurfaceProperty _TEXT("Egl::SurfaceOwner")
+#define kParentWndProc _TEXT("Egl::SurfaceParentWndProc")
+
+static LRESULT CALLBACK SurfaceWindowProc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)
+{
+  if (message == WM_SIZE)
+  {
+      Surface* surf = reinterpret_cast<Surface*>(GetProp(hwnd, kSurfaceProperty));
+      if(surf)
+      {
+          surf->checkForOutOfDateSwapChain();
+      }
+  }
+  WNDPROC prevWndFunc = reinterpret_cast<WNDPROC >(GetProp(hwnd, kParentWndProc));
+  return CallWindowProc(prevWndFunc, hwnd, message, wparam, lparam);
+}
+
+void Surface::subclassWindow()
+{
+    if (!mWindow)
+    {
+        return;
+    }
+
+    DWORD processId;
+    DWORD threadId = GetWindowThreadProcessId(mWindow, &processId);
+    if (processId != GetCurrentProcessId() || threadId != GetCurrentThreadId())
+    {
+        return;
+    }
+
+    SetLastError(0);
+    LONG_PTR oldWndProc = SetWindowLongPtr(mWindow, GWLP_WNDPROC, reinterpret_cast<LONG_PTR>(SurfaceWindowProc));
+    if(oldWndProc == 0 && GetLastError() != ERROR_SUCCESS)
+    {
+        mWindowSubclassed = false;
+        return;
+    }
+
+    SetProp(mWindow, kSurfaceProperty, reinterpret_cast<HANDLE>(this));
+    SetProp(mWindow, kParentWndProc, reinterpret_cast<HANDLE>(oldWndProc));
+    mWindowSubclassed = true;
+}
+
+void Surface::unsubclassWindow()
+{
+    if(!mWindowSubclassed)
+    {
+        return;
+    }
+
+    // un-subclass
+    LONG_PTR parentWndFunc = reinterpret_cast<LONG_PTR>(GetProp(mWindow, kParentWndProc));
+
+    // Check the windowproc is still SurfaceWindowProc.
+    // If this assert fails, then it is likely the application has subclassed the
+    // hwnd as well and did not unsubclass before destroying its EGL context. The
+    // application should be modified to either subclass before initializing the
+    // EGL context, or to unsubclass before destroying the EGL context.
+    if(parentWndFunc)
+    {
+        LONG_PTR prevWndFunc = SetWindowLongPtr(mWindow, GWLP_WNDPROC, parentWndFunc);
+        ASSERT(prevWndFunc == reinterpret_cast<LONG_PTR>(SurfaceWindowProc));
+    }
+
+    RemoveProp(mWindow, kSurfaceProperty);
+    RemoveProp(mWindow, kParentWndProc);
+    mWindowSubclassed = false;
+}
+
+bool Surface::checkForOutOfDateSwapChain()
+{
+    RECT client;
+    if (!GetClientRect(getWindowHandle(), &client))
+    {
+        ASSERT(false);
+        return false;
+    }
+
+    // Grow the buffer now, if the window has grown. We need to grow now to avoid losing information.
+    int clientWidth = client.right - client.left;
+    int clientHeight = client.bottom - client.top;
+    bool sizeDirty = clientWidth != getWidth() || clientHeight != getHeight();
+
+    if (sizeDirty || mPresentIntervalDirty)
+    {
+        resetSwapChain(clientWidth, clientHeight);
+        if (static_cast<egl::Surface*>(getCurrentDrawSurface()) == this)
+        {
+            glMakeCurrent(glGetCurrentContext(), static_cast<egl::Display*>(getCurrentDisplay()), this);
+        }
+
+        return true;
+    }
+    return false;
+}
+
+DWORD Surface::convertInterval(EGLint interval)
+{
+    switch(interval)
+    {
+      case 0: return D3DPRESENT_INTERVAL_IMMEDIATE;
+      case 1: return D3DPRESENT_INTERVAL_ONE;
+      case 2: return D3DPRESENT_INTERVAL_TWO;
+      case 3: return D3DPRESENT_INTERVAL_THREE;
+      case 4: return D3DPRESENT_INTERVAL_FOUR;
+      default: UNREACHABLE();
+    }
+
+    return D3DPRESENT_INTERVAL_DEFAULT;
+}
+
+bool Surface::swap()
+{
+    return swapRect(0, 0, mWidth, mHeight);
+}
+
+bool Surface::postSubBuffer(EGLint x, EGLint y, EGLint width, EGLint height)
+{
+    if (!mPostSubBufferSupported)
+    {
+        // Spec is not clear about how this should be handled.
+        return true;
+    }
+    
+    return swapRect(x, y, width, height);
+}
+
+EGLint Surface::getWidth() const
+{
+    return mWidth;
+}
+
+EGLint Surface::getHeight() const
+{
+    return mHeight;
+}
+
+EGLint Surface::isPostSubBufferSupported() const
+{
+    return mPostSubBufferSupported;
+}
+
+// Increments refcount on surface.
+// caller must Release() the returned surface
+IDirect3DSurface9 *Surface::getRenderTarget()
+{
+    if (mRenderTarget)
+    {
+        mRenderTarget->AddRef();
+    }
+
+    return mRenderTarget;
+}
+
+// Increments refcount on surface.
+// caller must Release() the returned surface
+IDirect3DSurface9 *Surface::getDepthStencil()
+{
+    if (mDepthStencil)
+    {
+        mDepthStencil->AddRef();
+    }
+
+    return mDepthStencil;
+}
+
+IDirect3DTexture9 *Surface::getOffscreenTexture()
+{
+    if (mOffscreenTexture)
+    {
+        mOffscreenTexture->AddRef();
+    }
+
+    return mOffscreenTexture;
+}
+
+void Surface::setSwapInterval(EGLint interval)
+{
+    if (mSwapInterval == interval)
+    {
+        return;
+    }
+    
+    mSwapInterval = interval;
+    mSwapInterval = std::max(mSwapInterval, mDisplay->getMinSwapInterval());
+    mSwapInterval = std::min(mSwapInterval, mDisplay->getMaxSwapInterval());
+
+    mPresentInterval = convertInterval(mSwapInterval);
+    mPresentIntervalDirty = true;
+}
+
+EGLenum Surface::getTextureFormat() const
+{
+    return mTextureFormat;
+}
+
+EGLenum Surface::getTextureTarget() const
+{
+    return mTextureTarget;
+}
+
+void Surface::setBoundTexture(gl::Texture2D *texture)
+{
+    mTexture = texture;
+}
+
+gl::Texture2D *Surface::getBoundTexture() const
+{
+    return mTexture;
+}
+
+D3DFORMAT Surface::getFormat() const
+{
+    return mConfig->mRenderTargetFormat;
+}
+}
diff --git a/src/3rdparty/angle/src/libEGL/Surface.h b/src/3rdparty/angle/src/libEGL/Surface.h
new file mode 100644 (file)
index 0000000..40bd702
--- /dev/null
@@ -0,0 +1,112 @@
+//
+// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// Surface.h: Defines the egl::Surface class, representing a drawing surface
+// such as the client area of a window, including any back buffers.
+// Implements EGLSurface and related functionality. [EGL 1.4] section 2.2 page 3.
+
+#ifndef INCLUDE_SURFACE_H_
+#define INCLUDE_SURFACE_H_
+
+#define EGLAPI
+#include <EGL/egl.h>
+#include <d3d9.h>
+
+#include "common/angleutils.h"
+
+namespace gl
+{
+class Texture2D;
+}
+
+namespace egl
+{
+class Display;
+class Config;
+
+class Surface
+{
+  public:
+    Surface(Display *display, const egl::Config *config, HWND window, EGLint postSubBufferSupported);
+    Surface(Display *display, const egl::Config *config, HANDLE shareHandle, EGLint width, EGLint height, EGLenum textureFormat, EGLenum textureTarget);
+
+    ~Surface();
+
+    bool initialize();
+    void release();
+    bool resetSwapChain();
+
+    HWND getWindowHandle();
+    bool swap();
+    bool postSubBuffer(EGLint x, EGLint y, EGLint width, EGLint height);
+
+    virtual EGLint getWidth() const;
+    virtual EGLint getHeight() const;
+
+    virtual EGLint isPostSubBufferSupported() const;
+
+    virtual IDirect3DSurface9 *getRenderTarget();
+    virtual IDirect3DSurface9 *getDepthStencil();
+    virtual IDirect3DTexture9 *getOffscreenTexture();
+
+    HANDLE getShareHandle() { return mShareHandle; }
+
+    void setSwapInterval(EGLint interval);
+    bool checkForOutOfDateSwapChain();   // Returns true if swapchain changed due to resize or interval update
+
+    virtual EGLenum getTextureFormat() const;
+    virtual EGLenum getTextureTarget() const;
+    virtual D3DFORMAT getFormat() const;
+
+    virtual void setBoundTexture(gl::Texture2D *texture);
+    virtual gl::Texture2D *getBoundTexture() const;
+
+private:
+    DISALLOW_COPY_AND_ASSIGN(Surface);
+
+    Display *const mDisplay;
+    IDirect3DSwapChain9 *mSwapChain;
+    IDirect3DSurface9 *mBackBuffer;
+    IDirect3DSurface9 *mDepthStencil;
+    IDirect3DSurface9* mRenderTarget;
+    IDirect3DTexture9* mOffscreenTexture;
+
+    HANDLE mShareHandle;
+
+    void subclassWindow();
+    void unsubclassWindow();
+    bool resetSwapChain(int backbufferWidth, int backbufferHeight);
+    bool swapRect(EGLint x, EGLint y, EGLint width, EGLint height);
+    static DWORD convertInterval(EGLint interval);
+
+    const HWND mWindow;            // Window that the surface is created for.
+    bool mWindowSubclassed;        // Indicates whether we successfully subclassed mWindow for WM_RESIZE hooking
+    const egl::Config *mConfig;    // EGL config surface was created with
+    EGLint mHeight;                // Height of surface
+    EGLint mWidth;                 // Width of surface
+//  EGLint horizontalResolution;   // Horizontal dot pitch
+//  EGLint verticalResolution;     // Vertical dot pitch
+//  EGLBoolean largestPBuffer;     // If true, create largest pbuffer possible
+//  EGLBoolean mipmapTexture;      // True if texture has mipmaps
+//  EGLint mipmapLevel;            // Mipmap level to render to
+//  EGLenum multisampleResolve;    // Multisample resolve behavior
+    EGLint mPixelAspectRatio;      // Display aspect ratio
+    EGLenum mRenderBuffer;         // Render buffer
+    EGLenum mSwapBehavior;         // Buffer swap behavior
+    EGLenum mTextureFormat;        // Format of texture: RGB, RGBA, or no texture
+    EGLenum mTextureTarget;        // Type of texture: 2D or no texture
+//  EGLenum vgAlphaFormat;         // Alpha format for OpenVG
+//  EGLenum vgColorSpace;          // Color space for OpenVG
+    EGLint mSwapInterval;
+    EGLint mPostSubBufferSupported;
+    
+    DWORD mPresentInterval;
+    bool mPresentIntervalDirty;
+    gl::Texture2D *mTexture;
+};
+}
+
+#endif   // INCLUDE_SURFACE_H_
diff --git a/src/3rdparty/angle/src/libEGL/libEGL.cpp b/src/3rdparty/angle/src/libEGL/libEGL.cpp
new file mode 100644 (file)
index 0000000..25df1c8
--- /dev/null
@@ -0,0 +1,1181 @@
+//
+// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// libEGL.cpp: Implements the exported EGL functions.
+
+#include <exception>
+
+#include "common/debug.h"
+#include "common/version.h"
+#include "libGLESv2/Context.h"
+#include "libGLESv2/Texture.h"
+
+#include "libEGL/main.h"
+#include "libEGL/Display.h"
+
+
+bool validateDisplay(egl::Display *display)
+{
+    if (display == EGL_NO_DISPLAY)
+    {
+        return error(EGL_BAD_DISPLAY, false);
+    }
+
+    if (!display->isInitialized())
+    {
+        return error(EGL_NOT_INITIALIZED, false);
+    }
+
+    return true;
+}
+
+bool validateConfig(egl::Display *display, EGLConfig config)
+{
+    if (!validateDisplay(display))
+    {
+        return false;
+    }
+
+    if (!display->isValidConfig(config))
+    {
+        return error(EGL_BAD_CONFIG, false);
+    }
+
+    return true;
+}
+
+bool validateContext(egl::Display *display, gl::Context *context)
+{
+    if (!validateDisplay(display))
+    {
+        return false;
+    }
+
+    if (!display->isValidContext(context))
+    {
+        return error(EGL_BAD_CONTEXT, false);
+    }
+
+    return true;
+}
+
+bool validateSurface(egl::Display *display, egl::Surface *surface)
+{
+    if (!validateDisplay(display))
+    {
+        return false;
+    }
+
+    if (!display->isValidSurface(surface))
+    {
+        return error(EGL_BAD_SURFACE, false);
+    }
+
+    return true;
+}
+
+extern "C"
+{
+EGLint __stdcall eglGetError(void)
+{
+    EVENT("()");
+
+    EGLint error = egl::getCurrentError();
+
+    if (error != EGL_SUCCESS)
+    {
+        egl::setCurrentError(EGL_SUCCESS);
+    }
+
+    return error;
+}
+
+EGLDisplay __stdcall eglGetDisplay(EGLNativeDisplayType display_id)
+{
+    EVENT("(EGLNativeDisplayType display_id = 0x%0.8p)", display_id);
+
+    try
+    {
+        return egl::Display::getDisplay(display_id);
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(EGL_BAD_ALLOC, EGL_NO_DISPLAY);
+    }
+}
+
+EGLBoolean __stdcall eglInitialize(EGLDisplay dpy, EGLint *major, EGLint *minor)
+{
+    EVENT("(EGLDisplay dpy = 0x%0.8p, EGLint *major = 0x%0.8p, EGLint *minor = 0x%0.8p)",
+          dpy, major, minor);
+
+    try
+    {
+        if (dpy == EGL_NO_DISPLAY)
+        {
+            return error(EGL_BAD_DISPLAY, EGL_FALSE);
+        }
+
+        egl::Display *display = static_cast<egl::Display*>(dpy);
+
+        if (!display->initialize())
+        {
+            return error(EGL_NOT_INITIALIZED, EGL_FALSE);
+        }
+
+        if (major) *major = 1;
+        if (minor) *minor = 4;
+
+        return success(EGL_TRUE);
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(EGL_BAD_ALLOC, EGL_FALSE);
+    }
+}
+
+EGLBoolean __stdcall eglTerminate(EGLDisplay dpy)
+{
+    EVENT("(EGLDisplay dpy = 0x%0.8p)", dpy);
+
+    try
+    {
+        if (dpy == EGL_NO_DISPLAY)
+        {
+            return error(EGL_BAD_DISPLAY, EGL_FALSE);
+        }
+
+        egl::Display *display = static_cast<egl::Display*>(dpy);
+
+        display->terminate();
+
+        return success(EGL_TRUE);
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(EGL_BAD_ALLOC, EGL_FALSE);
+    }
+}
+
+const char *__stdcall eglQueryString(EGLDisplay dpy, EGLint name)
+{
+    EVENT("(EGLDisplay dpy = 0x%0.8p, EGLint name = %d)", dpy, name);
+
+    try
+    {
+        egl::Display *display = static_cast<egl::Display*>(dpy);
+
+        if (!validateDisplay(display))
+        {
+            return NULL;
+        }
+
+        switch (name)
+        {
+          case EGL_CLIENT_APIS:
+            return success("OpenGL_ES");
+          case EGL_EXTENSIONS:
+            return display->getExtensionString();
+          case EGL_VENDOR:
+            return success("Google Inc.");
+          case EGL_VERSION:
+            return success("1.4 (ANGLE " VERSION_STRING ")");
+        }
+
+        return error(EGL_BAD_PARAMETER, (const char*)NULL);
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(EGL_BAD_ALLOC, (const char*)NULL);
+    }
+}
+
+EGLBoolean __stdcall eglGetConfigs(EGLDisplay dpy, EGLConfig *configs, EGLint config_size, EGLint *num_config)
+{
+    EVENT("(EGLDisplay dpy = 0x%0.8p, EGLConfig *configs = 0x%0.8p, "
+          "EGLint config_size = %d, EGLint *num_config = 0x%0.8p)",
+          dpy, configs, config_size, num_config);
+
+    try
+    {
+        egl::Display *display = static_cast<egl::Display*>(dpy);
+
+        if (!validateDisplay(display))
+        {
+            return EGL_FALSE;
+        }
+
+        if (!num_config)
+        {
+            return error(EGL_BAD_PARAMETER, EGL_FALSE);
+        }
+
+        const EGLint attribList[] =    {EGL_NONE};
+
+        if (!display->getConfigs(configs, attribList, config_size, num_config))
+        {
+            return error(EGL_BAD_ATTRIBUTE, EGL_FALSE);
+        }
+
+        return success(EGL_TRUE);
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(EGL_BAD_ALLOC, EGL_FALSE);
+    }
+}
+
+EGLBoolean __stdcall eglChooseConfig(EGLDisplay dpy, const EGLint *attrib_list, EGLConfig *configs, EGLint config_size, EGLint *num_config)
+{
+    EVENT("(EGLDisplay dpy = 0x%0.8p, const EGLint *attrib_list = 0x%0.8p, "
+          "EGLConfig *configs = 0x%0.8p, EGLint config_size = %d, EGLint *num_config = 0x%0.8p)",
+          dpy, attrib_list, configs, config_size, num_config);
+
+    try
+    {
+        egl::Display *display = static_cast<egl::Display*>(dpy);
+
+        if (!validateDisplay(display))
+        {
+            return EGL_FALSE;
+        }
+
+        if (!num_config)
+        {
+            return error(EGL_BAD_PARAMETER, EGL_FALSE);
+        }
+
+        const EGLint attribList[] =    {EGL_NONE};
+
+        if (!attrib_list)
+        {
+            attrib_list = attribList;
+        }
+
+        display->getConfigs(configs, attrib_list, config_size, num_config);
+
+        return success(EGL_TRUE);
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(EGL_BAD_ALLOC, EGL_FALSE);
+    }
+}
+
+EGLBoolean __stdcall eglGetConfigAttrib(EGLDisplay dpy, EGLConfig config, EGLint attribute, EGLint *value)
+{
+    EVENT("(EGLDisplay dpy = 0x%0.8p, EGLConfig config = 0x%0.8p, EGLint attribute = %d, EGLint *value = 0x%0.8p)",
+          dpy, config, attribute, value);
+
+    try
+    {
+        egl::Display *display = static_cast<egl::Display*>(dpy);
+
+        if (!validateConfig(display, config))
+        {
+            return EGL_FALSE;
+        }
+
+        if (!display->getConfigAttrib(config, attribute, value))
+        {
+            return error(EGL_BAD_ATTRIBUTE, EGL_FALSE);
+        }
+
+        return success(EGL_TRUE);
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(EGL_BAD_ALLOC, EGL_FALSE);
+    }
+}
+
+EGLSurface __stdcall eglCreateWindowSurface(EGLDisplay dpy, EGLConfig config, EGLNativeWindowType win, const EGLint *attrib_list)
+{
+    EVENT("(EGLDisplay dpy = 0x%0.8p, EGLConfig config = 0x%0.8p, EGLNativeWindowType win = 0x%0.8p, "
+          "const EGLint *attrib_list = 0x%0.8p)", dpy, config, win, attrib_list);
+
+    try
+    {
+        egl::Display *display = static_cast<egl::Display*>(dpy);
+
+        if (!validateConfig(display, config))
+        {
+            return EGL_NO_SURFACE;
+        }
+
+        HWND window = (HWND)win;
+
+        if (!IsWindow(window))
+        {
+            return error(EGL_BAD_NATIVE_WINDOW, EGL_NO_SURFACE);
+        }
+
+        return display->createWindowSurface(window, config, attrib_list);
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(EGL_BAD_ALLOC, EGL_NO_SURFACE);
+    }
+}
+
+EGLSurface __stdcall eglCreatePbufferSurface(EGLDisplay dpy, EGLConfig config, const EGLint *attrib_list)
+{
+    EVENT("(EGLDisplay dpy = 0x%0.8p, EGLConfig config = 0x%0.8p, const EGLint *attrib_list = 0x%0.8p)",
+          dpy, config, attrib_list);
+
+    try
+    {
+        egl::Display *display = static_cast<egl::Display*>(dpy);
+
+        if (!validateConfig(display, config))
+        {
+            return EGL_NO_SURFACE;
+        }
+
+        return display->createOffscreenSurface(config, NULL, attrib_list);
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(EGL_BAD_ALLOC, EGL_NO_SURFACE);
+    }
+}
+
+EGLSurface __stdcall eglCreatePixmapSurface(EGLDisplay dpy, EGLConfig config, EGLNativePixmapType pixmap, const EGLint *attrib_list)
+{
+    EVENT("(EGLDisplay dpy = 0x%0.8p, EGLConfig config = 0x%0.8p, EGLNativePixmapType pixmap = 0x%0.8p, "
+          "const EGLint *attrib_list = 0x%0.8p)", dpy, config, pixmap, attrib_list);
+
+    try
+    {
+        egl::Display *display = static_cast<egl::Display*>(dpy);
+
+        if (!validateConfig(display, config))
+        {
+            return EGL_NO_SURFACE;
+        }
+
+        UNIMPLEMENTED();   // FIXME
+
+        return success(EGL_NO_SURFACE);
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(EGL_BAD_ALLOC, EGL_NO_SURFACE);
+    }
+}
+
+EGLBoolean __stdcall eglDestroySurface(EGLDisplay dpy, EGLSurface surface)
+{
+    EVENT("(EGLDisplay dpy = 0x%0.8p, EGLSurface surface = 0x%0.8p)", dpy, surface);
+
+    try
+    {
+        egl::Display *display = static_cast<egl::Display*>(dpy);
+        egl::Surface *eglSurface = static_cast<egl::Surface*>(surface);
+
+        if (!validateSurface(display, eglSurface))
+        {
+            return EGL_FALSE;
+        }
+
+        if (surface == EGL_NO_SURFACE)
+        {
+            return error(EGL_BAD_SURFACE, EGL_FALSE);
+        }
+
+        display->destroySurface((egl::Surface*)surface);
+
+        return success(EGL_TRUE);
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(EGL_BAD_ALLOC, EGL_FALSE);
+    }
+}
+
+EGLBoolean __stdcall eglQuerySurface(EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint *value)
+{
+    EVENT("(EGLDisplay dpy = 0x%0.8p, EGLSurface surface = 0x%0.8p, EGLint attribute = %d, EGLint *value = 0x%0.8p)",
+          dpy, surface, attribute, value);
+
+    try
+    {
+        egl::Display *display = static_cast<egl::Display*>(dpy);
+        egl::Surface *eglSurface = (egl::Surface*)surface;
+
+        if (!validateSurface(display, eglSurface))
+        {
+            return EGL_FALSE;
+        }
+
+        if (surface == EGL_NO_SURFACE)
+        {
+            return error(EGL_BAD_SURFACE, EGL_FALSE);
+        }
+
+        switch (attribute)
+        {
+          case EGL_VG_ALPHA_FORMAT:
+            UNIMPLEMENTED();   // FIXME
+            break;
+          case EGL_VG_COLORSPACE:
+            UNIMPLEMENTED();   // FIXME
+            break;
+          case EGL_CONFIG_ID:
+            UNIMPLEMENTED();   // FIXME
+            break;
+          case EGL_HEIGHT:
+            *value = eglSurface->getHeight();
+            break;
+          case EGL_HORIZONTAL_RESOLUTION:
+            UNIMPLEMENTED();   // FIXME
+            break;
+          case EGL_LARGEST_PBUFFER:
+            UNIMPLEMENTED();   // FIXME
+            break;
+          case EGL_MIPMAP_TEXTURE:
+            UNIMPLEMENTED();   // FIXME
+            break;
+          case EGL_MIPMAP_LEVEL:
+            UNIMPLEMENTED();   // FIXME
+            break;
+          case EGL_MULTISAMPLE_RESOLVE:
+            UNIMPLEMENTED();   // FIXME
+            break;
+          case EGL_PIXEL_ASPECT_RATIO:
+            UNIMPLEMENTED();   // FIXME
+            break;
+          case EGL_RENDER_BUFFER:
+            UNIMPLEMENTED();   // FIXME
+            break;
+          case EGL_SWAP_BEHAVIOR:
+            UNIMPLEMENTED();   // FIXME
+            break;
+          case EGL_TEXTURE_FORMAT:
+            UNIMPLEMENTED();   // FIXME
+            break;
+          case EGL_TEXTURE_TARGET:
+            UNIMPLEMENTED();   // FIXME
+            break;
+          case EGL_VERTICAL_RESOLUTION:
+            UNIMPLEMENTED();   // FIXME
+            break;
+          case EGL_WIDTH:
+            *value = eglSurface->getWidth();
+            break;
+          case EGL_POST_SUB_BUFFER_SUPPORTED_NV:
+            *value = eglSurface->isPostSubBufferSupported();
+            break;
+          default:
+            return error(EGL_BAD_ATTRIBUTE, EGL_FALSE);
+        }
+
+        return success(EGL_TRUE);
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(EGL_BAD_ALLOC, EGL_FALSE);
+    }
+}
+
+EGLBoolean __stdcall eglQuerySurfacePointerANGLE(EGLDisplay dpy, EGLSurface surface, EGLint attribute, void **value)
+{
+    TRACE("(EGLDisplay dpy = 0x%0.8p, EGLSurface surface = 0x%0.8p, EGLint attribute = %d, void **value = 0x%0.8p)",
+          dpy, surface, attribute, value);
+
+    try
+    {
+        egl::Display *display = static_cast<egl::Display*>(dpy);
+        egl::Surface *eglSurface = (egl::Surface*)surface;
+
+        if (!validateSurface(display, eglSurface))
+        {
+            return EGL_FALSE;
+        }
+
+        if (surface == EGL_NO_SURFACE)
+        {
+            return error(EGL_BAD_SURFACE, EGL_FALSE);
+        }
+
+        switch (attribute)
+        {
+          case EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE:
+            *value = (void*) eglSurface->getShareHandle();
+            break;
+          default:
+            return error(EGL_BAD_ATTRIBUTE, EGL_FALSE);
+        }
+
+        return success(EGL_TRUE);
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(EGL_BAD_ALLOC, EGL_FALSE);
+    }
+}
+
+EGLBoolean __stdcall eglBindAPI(EGLenum api)
+{
+    EVENT("(EGLenum api = 0x%X)", api);
+
+    try
+    {
+        switch (api)
+        {
+          case EGL_OPENGL_API:
+          case EGL_OPENVG_API:
+            return error(EGL_BAD_PARAMETER, EGL_FALSE);   // Not supported by this implementation
+          case EGL_OPENGL_ES_API:
+            break;
+          default:
+            return error(EGL_BAD_PARAMETER, EGL_FALSE);
+        }
+
+        egl::setCurrentAPI(api);
+
+        return success(EGL_TRUE);
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(EGL_BAD_ALLOC, EGL_FALSE);
+    }
+}
+
+EGLenum __stdcall eglQueryAPI(void)
+{
+    EVENT("()");
+
+    try
+    {
+        EGLenum API = egl::getCurrentAPI();
+
+        return success(API);
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(EGL_BAD_ALLOC, EGL_FALSE);
+    }
+}
+
+EGLBoolean __stdcall eglWaitClient(void)
+{
+    EVENT("()");
+
+    try
+    {
+        UNIMPLEMENTED();   // FIXME
+
+        return success(0);
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(EGL_BAD_ALLOC, EGL_FALSE);
+    }
+}
+
+EGLBoolean __stdcall eglReleaseThread(void)
+{
+    EVENT("()");
+
+    try
+    {
+        eglMakeCurrent(EGL_NO_DISPLAY, EGL_NO_CONTEXT, EGL_NO_SURFACE, EGL_NO_SURFACE);
+
+        return success(EGL_TRUE);
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(EGL_BAD_ALLOC, EGL_FALSE);
+    }
+}
+
+EGLSurface __stdcall eglCreatePbufferFromClientBuffer(EGLDisplay dpy, EGLenum buftype, EGLClientBuffer buffer, EGLConfig config, const EGLint *attrib_list)
+{
+    EVENT("(EGLDisplay dpy = 0x%0.8p, EGLenum buftype = 0x%X, EGLClientBuffer buffer = 0x%0.8p, "
+          "EGLConfig config = 0x%0.8p, const EGLint *attrib_list = 0x%0.8p)",
+          dpy, buftype, buffer, config, attrib_list);
+
+    try
+    {
+        egl::Display *display = static_cast<egl::Display*>(dpy);
+
+        if (!validateConfig(display, config))
+        {
+            return EGL_NO_SURFACE;
+        }
+
+        if (buftype != EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE || !buffer)
+        {
+            return error(EGL_BAD_PARAMETER, EGL_NO_SURFACE);
+        }
+
+        return display->createOffscreenSurface(config, (HANDLE)buffer, attrib_list);
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(EGL_BAD_ALLOC, EGL_NO_SURFACE);
+    }
+}
+
+EGLBoolean __stdcall eglSurfaceAttrib(EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint value)
+{
+    EVENT("(EGLDisplay dpy = 0x%0.8p, EGLSurface surface = 0x%0.8p, EGLint attribute = %d, EGLint value = %d)",
+          dpy, surface, attribute, value);
+
+    try
+    {
+        egl::Display *display = static_cast<egl::Display*>(dpy);
+        egl::Surface *eglSurface = static_cast<egl::Surface*>(surface);
+
+        if (!validateSurface(display, eglSurface))
+        {
+            return EGL_FALSE;
+        }
+
+        UNIMPLEMENTED();   // FIXME
+
+        return success(EGL_TRUE);
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(EGL_BAD_ALLOC, EGL_FALSE);
+    }
+}
+
+EGLBoolean __stdcall eglBindTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer)
+{
+    EVENT("(EGLDisplay dpy = 0x%0.8p, EGLSurface surface = 0x%0.8p, EGLint buffer = %d)", dpy, surface, buffer);
+
+    try
+    {
+        egl::Display *display = static_cast<egl::Display*>(dpy);
+        egl::Surface *eglSurface = static_cast<egl::Surface*>(surface);
+
+        if (!validateSurface(display, eglSurface))
+        {
+            return EGL_FALSE;
+        }
+
+        if (buffer != EGL_BACK_BUFFER)
+        {
+            return error(EGL_BAD_PARAMETER, EGL_FALSE);
+        }
+
+        if (surface == EGL_NO_SURFACE || eglSurface->getWindowHandle())
+        {
+            return error(EGL_BAD_SURFACE, EGL_FALSE);
+        }
+
+        if (eglSurface->getBoundTexture())
+        {
+            return error(EGL_BAD_ACCESS, EGL_FALSE);
+        }
+
+        if (eglSurface->getTextureFormat() == EGL_NO_TEXTURE)
+        {
+            return error(EGL_BAD_MATCH, EGL_FALSE);
+        }
+
+        if (!glBindTexImage(eglSurface))
+        {
+            return error(EGL_BAD_MATCH, EGL_FALSE);
+        }
+
+        return success(EGL_TRUE);
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(EGL_BAD_ALLOC, EGL_FALSE);
+    }
+}
+
+EGLBoolean __stdcall eglReleaseTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer)
+{
+    EVENT("(EGLDisplay dpy = 0x%0.8p, EGLSurface surface = 0x%0.8p, EGLint buffer = %d)", dpy, surface, buffer);
+
+    try
+    {
+        egl::Display *display = static_cast<egl::Display*>(dpy);
+        egl::Surface *eglSurface = static_cast<egl::Surface*>(surface);
+
+        if (!validateSurface(display, eglSurface))
+        {
+            return EGL_FALSE;
+        }
+
+        if (buffer != EGL_BACK_BUFFER)
+        {
+            return error(EGL_BAD_PARAMETER, EGL_FALSE);
+        }
+
+        if (surface == EGL_NO_SURFACE || eglSurface->getWindowHandle())
+        {
+            return error(EGL_BAD_SURFACE, EGL_FALSE);
+        }
+
+        if (eglSurface->getTextureFormat() == EGL_NO_TEXTURE)
+        {
+            return error(EGL_BAD_MATCH, EGL_FALSE);
+        }
+
+        gl::Texture2D *texture = eglSurface->getBoundTexture();
+
+        if (texture)
+        {
+            texture->releaseTexImage();
+        }
+
+        return success(EGL_TRUE);
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(EGL_BAD_ALLOC, EGL_FALSE);
+    }
+}
+
+EGLBoolean __stdcall eglSwapInterval(EGLDisplay dpy, EGLint interval)
+{
+    EVENT("(EGLDisplay dpy = 0x%0.8p, EGLint interval = %d)", dpy, interval);
+
+    try
+    {
+        egl::Display *display = static_cast<egl::Display*>(dpy);
+
+        if (!validateDisplay(display))
+        {
+            return EGL_FALSE;
+        }
+
+        egl::Surface *draw_surface = static_cast<egl::Surface*>(egl::getCurrentDrawSurface());
+
+        if (draw_surface == NULL)
+        {
+            return error(EGL_BAD_SURFACE, EGL_FALSE);
+        }
+        
+        draw_surface->setSwapInterval(interval);
+
+        return success(EGL_TRUE);
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(EGL_BAD_ALLOC, EGL_FALSE);
+    }
+}
+
+EGLContext __stdcall eglCreateContext(EGLDisplay dpy, EGLConfig config, EGLContext share_context, const EGLint *attrib_list)
+{
+    EVENT("(EGLDisplay dpy = 0x%0.8p, EGLConfig config = 0x%0.8p, EGLContext share_context = 0x%0.8p, "
+          "const EGLint *attrib_list = 0x%0.8p)", dpy, config, share_context, attrib_list);
+
+    try
+    {
+        // Get the requested client version (default is 1) and check it is two.
+        EGLint client_version = 1;
+        bool reset_notification = false;
+        bool robust_access = false;
+
+        if (attrib_list)
+        {
+            for (const EGLint* attribute = attrib_list; attribute[0] != EGL_NONE; attribute += 2)
+            {
+                switch (attribute[0])
+                {
+                  case EGL_CONTEXT_CLIENT_VERSION:
+                    client_version = attribute[1];
+                    break;
+                  case EGL_CONTEXT_OPENGL_ROBUST_ACCESS_EXT:
+                    if (attribute[1] == EGL_TRUE)
+                    {
+                        return error(EGL_BAD_CONFIG, EGL_NO_CONTEXT);   // Unimplemented
+                        // robust_access = true;
+                    }
+                    else if (attribute[1] != EGL_FALSE)
+                        return error(EGL_BAD_ATTRIBUTE, EGL_NO_CONTEXT);
+                    break;
+                  case EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_EXT:
+                    if (attribute[1] == EGL_LOSE_CONTEXT_ON_RESET_EXT)
+                        reset_notification = true;
+                    else if (attribute[1] != EGL_NO_RESET_NOTIFICATION_EXT)
+                        return error(EGL_BAD_ATTRIBUTE, EGL_NO_CONTEXT);
+                    break;
+                  default:
+                    return error(EGL_BAD_ATTRIBUTE, EGL_NO_CONTEXT);
+                }
+            }
+        }
+
+        if (client_version != 2)
+        {
+            return error(EGL_BAD_CONFIG, EGL_NO_CONTEXT);
+        }
+
+        if (share_context && static_cast<gl::Context*>(share_context)->isResetNotificationEnabled() != reset_notification)
+        {
+            return error(EGL_BAD_MATCH, EGL_NO_CONTEXT);
+        }
+
+        egl::Display *display = static_cast<egl::Display*>(dpy);
+
+        if (!validateConfig(display, config))
+        {
+            return EGL_NO_CONTEXT;
+        }
+
+        EGLContext context = display->createContext(config, static_cast<gl::Context*>(share_context), reset_notification, robust_access);
+
+        if (context)
+            return success(context);
+        else
+            return error(EGL_CONTEXT_LOST, EGL_NO_CONTEXT);
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(EGL_BAD_ALLOC, EGL_NO_CONTEXT);
+    }
+}
+
+EGLBoolean __stdcall eglDestroyContext(EGLDisplay dpy, EGLContext ctx)
+{
+    EVENT("(EGLDisplay dpy = 0x%0.8p, EGLContext ctx = 0x%0.8p)", dpy, ctx);
+
+    try
+    {
+        egl::Display *display = static_cast<egl::Display*>(dpy);
+        gl::Context *context = static_cast<gl::Context*>(ctx);
+
+        if (!validateContext(display, context))
+        {
+            return EGL_FALSE;
+        }
+
+        if (ctx == EGL_NO_CONTEXT)
+        {
+            return error(EGL_BAD_CONTEXT, EGL_FALSE);
+        }
+
+        display->destroyContext(context);
+
+        return success(EGL_TRUE);
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(EGL_BAD_ALLOC, EGL_FALSE);
+    }
+}
+
+EGLBoolean __stdcall eglMakeCurrent(EGLDisplay dpy, EGLSurface draw, EGLSurface read, EGLContext ctx)
+{
+    EVENT("(EGLDisplay dpy = 0x%0.8p, EGLSurface draw = 0x%0.8p, EGLSurface read = 0x%0.8p, EGLContext ctx = 0x%0.8p)",
+          dpy, draw, read, ctx);
+
+    try
+    {
+        egl::Display *display = static_cast<egl::Display*>(dpy);
+        gl::Context *context = static_cast<gl::Context*>(ctx);
+        IDirect3DDevice9 *device = display->getDevice();
+
+        if (!device || display->testDeviceLost())
+        {
+            display->notifyDeviceLost();
+            return EGL_FALSE;
+        }
+
+        if (display->isDeviceLost())
+        {
+            return error(EGL_CONTEXT_LOST, EGL_FALSE);
+        }
+
+        if (ctx != EGL_NO_CONTEXT && !validateContext(display, context))
+        {
+            return EGL_FALSE;
+        }
+
+        if ((draw != EGL_NO_SURFACE && !validateSurface(display, static_cast<egl::Surface*>(draw))) ||
+            (read != EGL_NO_SURFACE && !validateSurface(display, static_cast<egl::Surface*>(read))))
+        {
+            return EGL_FALSE;
+        }
+
+        if (draw != read)
+        {
+            UNIMPLEMENTED();   // FIXME
+        }
+
+        egl::setCurrentDisplay(dpy);
+        egl::setCurrentDrawSurface(draw);
+        egl::setCurrentReadSurface(read);
+
+        glMakeCurrent(context, display, static_cast<egl::Surface*>(draw));
+
+        return success(EGL_TRUE);
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(EGL_BAD_ALLOC, EGL_FALSE);
+    }
+}
+
+EGLContext __stdcall eglGetCurrentContext(void)
+{
+    EVENT("()");
+
+    try
+    {
+        EGLContext context = glGetCurrentContext();
+
+        return success(context);
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(EGL_BAD_ALLOC, EGL_NO_CONTEXT);
+    }
+}
+
+EGLSurface __stdcall eglGetCurrentSurface(EGLint readdraw)
+{
+    EVENT("(EGLint readdraw = %d)", readdraw);
+
+    try
+    {
+        if (readdraw == EGL_READ)
+        {
+            EGLSurface read = egl::getCurrentReadSurface();
+            return success(read);
+        }
+        else if (readdraw == EGL_DRAW)
+        {
+            EGLSurface draw = egl::getCurrentDrawSurface();
+            return success(draw);
+        }
+        else
+        {
+            return error(EGL_BAD_PARAMETER, EGL_NO_SURFACE);
+        }
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(EGL_BAD_ALLOC, EGL_NO_SURFACE);
+    }
+}
+
+EGLDisplay __stdcall eglGetCurrentDisplay(void)
+{
+    EVENT("()");
+
+    try
+    {
+        EGLDisplay dpy = egl::getCurrentDisplay();
+
+        return success(dpy);
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(EGL_BAD_ALLOC, EGL_NO_DISPLAY);
+    }
+}
+
+EGLBoolean __stdcall eglQueryContext(EGLDisplay dpy, EGLContext ctx, EGLint attribute, EGLint *value)
+{
+    EVENT("(EGLDisplay dpy = 0x%0.8p, EGLContext ctx = 0x%0.8p, EGLint attribute = %d, EGLint *value = 0x%0.8p)",
+          dpy, ctx, attribute, value);
+
+    try
+    {
+        egl::Display *display = static_cast<egl::Display*>(dpy);
+        gl::Context *context = static_cast<gl::Context*>(ctx);
+
+        if (!validateContext(display, context))
+        {
+            return EGL_FALSE;
+        }
+
+        UNIMPLEMENTED();   // FIXME
+
+        return success(0);
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(EGL_BAD_ALLOC, EGL_FALSE);
+    }
+}
+
+EGLBoolean __stdcall eglWaitGL(void)
+{
+    EVENT("()");
+
+    try
+    {
+        UNIMPLEMENTED();   // FIXME
+
+        return success(0);
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(EGL_BAD_ALLOC, EGL_FALSE);
+    }
+}
+
+EGLBoolean __stdcall eglWaitNative(EGLint engine)
+{
+    EVENT("(EGLint engine = %d)", engine);
+
+    try
+    {
+        UNIMPLEMENTED();   // FIXME
+
+        return success(0);
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(EGL_BAD_ALLOC, EGL_FALSE);
+    }
+}
+
+EGLBoolean __stdcall eglSwapBuffers(EGLDisplay dpy, EGLSurface surface)
+{
+    EVENT("(EGLDisplay dpy = 0x%0.8p, EGLSurface surface = 0x%0.8p)", dpy, surface);
+
+    try
+    {
+        egl::Display *display = static_cast<egl::Display*>(dpy);
+        egl::Surface *eglSurface = (egl::Surface*)surface;
+
+        if (!validateSurface(display, eglSurface))
+        {
+            return EGL_FALSE;
+        }
+
+        if (display->isDeviceLost())
+        {
+            return error(EGL_CONTEXT_LOST, EGL_FALSE);
+        }
+
+        if (surface == EGL_NO_SURFACE)
+        {
+            return error(EGL_BAD_SURFACE, EGL_FALSE);
+        }
+
+        if (eglSurface->swap())
+        {
+            return success(EGL_TRUE);
+        }
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(EGL_BAD_ALLOC, EGL_FALSE);
+    }
+
+    return EGL_FALSE;
+}
+
+EGLBoolean __stdcall eglCopyBuffers(EGLDisplay dpy, EGLSurface surface, EGLNativePixmapType target)
+{
+    EVENT("(EGLDisplay dpy = 0x%0.8p, EGLSurface surface = 0x%0.8p, EGLNativePixmapType target = 0x%0.8p)", dpy, surface, target);
+
+    try
+    {
+        egl::Display *display = static_cast<egl::Display*>(dpy);
+        egl::Surface *eglSurface = static_cast<egl::Surface*>(surface);
+
+        if (!validateSurface(display, eglSurface))
+        {
+            return EGL_FALSE;
+        }
+
+        if (display->isDeviceLost())
+        {
+            return error(EGL_CONTEXT_LOST, EGL_FALSE);
+        }
+
+        UNIMPLEMENTED();   // FIXME
+
+        return success(0);
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(EGL_BAD_ALLOC, EGL_FALSE);
+    }
+}
+
+EGLBoolean __stdcall eglPostSubBufferNV(EGLDisplay dpy, EGLSurface surface, EGLint x, EGLint y, EGLint width, EGLint height)
+{
+    EVENT("(EGLDisplay dpy = 0x%0.8p, EGLSurface surface = 0x%0.8p, EGLint x = %d, EGLint y = %d, EGLint width = %d, EGLint height = %d)", dpy, surface, x, y, width, height);
+
+    try
+    {
+        if (x < 0 || y < 0 || width < 0 || height < 0)
+        {
+            return error(EGL_BAD_PARAMETER, EGL_FALSE);
+        }
+
+        egl::Display *display = static_cast<egl::Display*>(dpy);
+        egl::Surface *eglSurface = static_cast<egl::Surface*>(surface);
+
+        if (!validateSurface(display, eglSurface))
+        {
+            return EGL_FALSE;
+        }
+
+        if (display->isDeviceLost())
+        {
+            return error(EGL_CONTEXT_LOST, EGL_FALSE);
+        }
+
+        if (surface == EGL_NO_SURFACE)
+        {
+            return error(EGL_BAD_SURFACE, EGL_FALSE);
+        }
+
+        if (eglSurface->postSubBuffer(x, y, width, height))
+        {
+            return success(EGL_TRUE);
+        }
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(EGL_BAD_ALLOC, EGL_FALSE);
+    }
+
+    return EGL_FALSE;
+}
+
+__eglMustCastToProperFunctionPointerType __stdcall eglGetProcAddress(const char *procname)
+{
+    EVENT("(const char *procname = \"%s\")", procname);
+
+    try
+    {
+        struct Extension
+        {
+            const char *name;
+            __eglMustCastToProperFunctionPointerType address;
+        };
+
+        static const Extension eglExtensions[] =
+        {
+            {"eglQuerySurfacePointerANGLE", (__eglMustCastToProperFunctionPointerType)eglQuerySurfacePointerANGLE},
+            {"eglPostSubBufferNV", (__eglMustCastToProperFunctionPointerType)eglPostSubBufferNV},
+            {"", NULL},
+        };
+
+        for (int ext = 0; ext < sizeof(eglExtensions) / sizeof(Extension); ext++)
+        {
+            if (strcmp(procname, eglExtensions[ext].name) == 0)
+            {
+                return (__eglMustCastToProperFunctionPointerType)eglExtensions[ext].address;
+            }
+        }
+
+        return glGetProcAddress(procname);
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(EGL_BAD_ALLOC, (__eglMustCastToProperFunctionPointerType)NULL);
+    }
+}
+}
diff --git a/src/3rdparty/angle/src/libEGL/libEGL.def b/src/3rdparty/angle/src/libEGL/libEGL.def
new file mode 100644 (file)
index 0000000..71a5e67
--- /dev/null
@@ -0,0 +1,36 @@
+LIBRARY        libEGL
+EXPORTS
+       eglBindAPI                      @14
+       eglBindTexImage                 @20
+       eglChooseConfig                 @7
+       eglCopyBuffers                  @33
+       eglCreateContext                @23
+       eglCreatePbufferFromClientBuffer        @18
+       eglCreatePbufferSurface         @10
+       eglCreatePixmapSurface          @11
+       eglCreateWindowSurface          @9
+       eglDestroyContext               @24
+       eglDestroySurface               @12
+       eglGetConfigAttrib              @8
+       eglGetConfigs                   @6
+       eglGetCurrentContext            @26
+       eglGetCurrentDisplay            @28
+       eglGetCurrentSurface            @27
+       eglGetDisplay                   @2
+       eglGetError                     @1
+       eglGetProcAddress               @34
+       eglInitialize                   @3
+       eglMakeCurrent                  @25
+       eglQueryAPI                     @15
+       eglQueryContext                 @29
+       eglQueryString                  @5
+       eglQuerySurface                 @13
+       eglReleaseTexImage              @21
+       eglReleaseThread                @17
+       eglSurfaceAttrib                @19
+       eglSwapBuffers                  @32
+       eglSwapInterval                 @22
+       eglTerminate                    @4
+       eglWaitClient                   @16
+       eglWaitGL                       @30
+       eglWaitNative                   @31
\ No newline at end of file
diff --git a/src/3rdparty/angle/src/libEGL/libEGL.rc b/src/3rdparty/angle/src/libEGL/libEGL.rc
new file mode 100644 (file)
index 0000000..5d1f32f
--- /dev/null
@@ -0,0 +1,102 @@
+// Microsoft Visual C++ generated resource script.
+//
+#include "resource.h"
+
+#define APSTUDIO_READONLY_SYMBOLS
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 2 resource.
+//
+#include <windows.h>
+#include "../common/version.h"
+
+/////////////////////////////////////////////////////////////////////////////
+#undef APSTUDIO_READONLY_SYMBOLS
+
+/////////////////////////////////////////////////////////////////////////////
+// English (U.S.) resources
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
+#ifdef _WIN32
+LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
+#pragma code_page(1252)
+#endif //_WIN32
+
+#ifdef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// TEXTINCLUDE
+//
+
+1 TEXTINCLUDE 
+BEGIN
+    "resource.h\0"
+END
+
+2 TEXTINCLUDE 
+BEGIN
+    "#include ""afxres.h""\r\n"
+    "#include ""../common/version.h""\0"
+END
+
+3 TEXTINCLUDE 
+BEGIN
+    "\r\n"
+    "\0"
+END
+
+#endif    // APSTUDIO_INVOKED
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Version
+//
+
+VS_VERSION_INFO VERSIONINFO
+ FILEVERSION MAJOR_VERSION,MINOR_VERSION,BUILD_VERSION,BUILD_REVISION
+ PRODUCTVERSION MAJOR_VERSION,MINOR_VERSION,BUILD_VERSION,BUILD_REVISION
+ FILEFLAGSMASK 0x17L
+#ifdef _DEBUG
+ FILEFLAGS 0x1L
+#else
+ FILEFLAGS 0x0L
+#endif
+ FILEOS 0x4L
+ FILETYPE 0x2L
+ FILESUBTYPE 0x0L
+BEGIN
+    BLOCK "StringFileInfo"
+    BEGIN
+        BLOCK "040904b0"
+        BEGIN
+            VALUE "FileDescription", "ANGLE libEGL Dynamic Link Library"
+            VALUE "FileVersion", VERSION_STRING
+            VALUE "InternalName", "libEGL"
+            VALUE "LegalCopyright", "Copyright (C) 2011 Google Inc."
+            VALUE "OriginalFilename", "libEGL.dll"
+            VALUE "PrivateBuild", VERSION_STRING
+            VALUE "ProductName", "ANGLE libEGL Dynamic Link Library"
+            VALUE "ProductVersion", VERSION_STRING
+        END
+    END
+    BLOCK "VarFileInfo"
+    BEGIN
+        VALUE "Translation", 0x409, 1200
+    END
+END
+
+#endif    // English (U.S.) resources
+/////////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 3 resource.
+//
+
+
+/////////////////////////////////////////////////////////////////////////////
+#endif    // not APSTUDIO_INVOKED
diff --git a/src/3rdparty/angle/src/libEGL/main.cpp b/src/3rdparty/angle/src/libEGL/main.cpp
new file mode 100644 (file)
index 0000000..dc24c4f
--- /dev/null
@@ -0,0 +1,165 @@
+//
+// 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.
+//
+
+// main.cpp: DLL entry point and management of thread-local data.
+
+#include "libEGL/main.h"
+
+#include "common/debug.h"
+
+static DWORD currentTLS = TLS_OUT_OF_INDEXES;
+
+extern "C" BOOL WINAPI DllMain(HINSTANCE instance, DWORD reason, LPVOID reserved)
+{
+    switch (reason)
+    {
+      case DLL_PROCESS_ATTACH:
+        {
+#if !defined(ANGLE_DISABLE_TRACE)
+            FILE *debug = fopen(TRACE_OUTPUT_FILE, "rt");
+
+            if (debug)
+            {
+                fclose(debug);
+                debug = fopen(TRACE_OUTPUT_FILE, "wt");   // Erase
+                
+                if (debug)
+                {
+                    fclose(debug);
+                }
+            }
+#endif
+
+            currentTLS = TlsAlloc();
+
+            if (currentTLS == TLS_OUT_OF_INDEXES)
+            {
+                return FALSE;
+            }
+        }
+        // Fall throught to initialize index
+      case DLL_THREAD_ATTACH:
+        {
+            egl::Current *current = (egl::Current*)LocalAlloc(LPTR, sizeof(egl::Current));
+
+            if (current)
+            {
+                TlsSetValue(currentTLS, current);
+
+                current->error = EGL_SUCCESS;
+                current->API = EGL_OPENGL_ES_API;
+                current->display = EGL_NO_DISPLAY;
+                current->drawSurface = EGL_NO_SURFACE;
+                current->readSurface = EGL_NO_SURFACE;
+            }
+        }
+        break;
+      case DLL_THREAD_DETACH:
+        {
+            void *current = TlsGetValue(currentTLS);
+
+            if (current)
+            {
+                LocalFree((HLOCAL)current);
+            }
+        }
+        break;
+      case DLL_PROCESS_DETACH:
+        {
+            void *current = TlsGetValue(currentTLS);
+
+            if (current)
+            {
+                LocalFree((HLOCAL)current);
+            }
+
+            TlsFree(currentTLS);
+        }
+        break;
+      default:
+        break;
+    }
+
+    return TRUE;
+}
+
+namespace egl
+{
+void setCurrentError(EGLint error)
+{
+    Current *current = (Current*)TlsGetValue(currentTLS);
+
+    current->error = error;
+}
+
+EGLint getCurrentError()
+{
+    Current *current = (Current*)TlsGetValue(currentTLS);
+
+    return current->error;
+}
+
+void setCurrentAPI(EGLenum API)
+{
+    Current *current = (Current*)TlsGetValue(currentTLS);
+
+    current->API = API;
+}
+
+EGLenum getCurrentAPI()
+{
+    Current *current = (Current*)TlsGetValue(currentTLS);
+
+    return current->API;
+}
+
+void setCurrentDisplay(EGLDisplay dpy)
+{
+    Current *current = (Current*)TlsGetValue(currentTLS);
+
+    current->display = dpy;
+}
+
+EGLDisplay getCurrentDisplay()
+{
+    Current *current = (Current*)TlsGetValue(currentTLS);
+
+    return current->display;
+}
+
+void setCurrentDrawSurface(EGLSurface surface)
+{
+    Current *current = (Current*)TlsGetValue(currentTLS);
+
+    current->drawSurface = surface;
+}
+
+EGLSurface getCurrentDrawSurface()
+{
+    Current *current = (Current*)TlsGetValue(currentTLS);
+
+    return current->drawSurface;
+}
+
+void setCurrentReadSurface(EGLSurface surface)
+{
+    Current *current = (Current*)TlsGetValue(currentTLS);
+
+    current->readSurface = surface;
+}
+
+EGLSurface getCurrentReadSurface()
+{
+    Current *current = (Current*)TlsGetValue(currentTLS);
+
+    return current->readSurface;
+}
+}
+
+void error(EGLint errorCode)
+{
+    egl::setCurrentError(errorCode);
+}
diff --git a/src/3rdparty/angle/src/libEGL/main.h b/src/3rdparty/angle/src/libEGL/main.h
new file mode 100644 (file)
index 0000000..d09d9e6
--- /dev/null
@@ -0,0 +1,61 @@
+//
+// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// main.h: Management of thread-local data.
+
+#ifndef LIBEGL_MAIN_H_
+#define LIBEGL_MAIN_H_
+
+#define EGLAPI
+#include <EGL/egl.h>
+#include <EGL/eglext.h>
+
+namespace egl
+{
+struct Current
+{
+    EGLint error;
+    EGLenum API;
+    EGLDisplay display;
+    EGLSurface drawSurface;
+    EGLSurface readSurface;
+};
+
+void setCurrentError(EGLint error);
+EGLint getCurrentError();
+
+void setCurrentAPI(EGLenum API);
+EGLenum getCurrentAPI();
+
+void setCurrentDisplay(EGLDisplay dpy);
+EGLDisplay getCurrentDisplay();
+
+void setCurrentDrawSurface(EGLSurface surface);
+EGLSurface getCurrentDrawSurface();
+
+void setCurrentReadSurface(EGLSurface surface);
+EGLSurface getCurrentReadSurface();
+}
+
+void error(EGLint errorCode);
+
+template<class T>
+const T &error(EGLint errorCode, const T &returnValue)
+{
+    error(errorCode);
+
+    return returnValue;
+}
+
+template<class T>
+const T &success(const T &returnValue)
+{
+    egl::setCurrentError(EGL_SUCCESS);
+
+    return returnValue;
+}
+
+#endif  // LIBEGL_MAIN_H_
diff --git a/src/3rdparty/angle/src/libEGL/resource.h b/src/3rdparty/angle/src/libEGL/resource.h
new file mode 100644 (file)
index 0000000..3921f4c
--- /dev/null
@@ -0,0 +1,14 @@
+//{{NO_DEPENDENCIES}}
+// Microsoft Visual C++ generated include file.
+// Used by libEGL.rc
+
+// Next default values for new objects
+// 
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NEXT_RESOURCE_VALUE        101
+#define _APS_NEXT_COMMAND_VALUE         40001
+#define _APS_NEXT_CONTROL_VALUE         1001
+#define _APS_NEXT_SYMED_VALUE           101
+#endif
+#endif
diff --git a/src/3rdparty/angle/src/libGLESv2/BinaryStream.h b/src/3rdparty/angle/src/libGLESv2/BinaryStream.h
new file mode 100644 (file)
index 0000000..5f7213b
--- /dev/null
@@ -0,0 +1,167 @@
+//
+// 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.
+//
+
+// BinaryStream.h: Provides binary serialization of simple types.
+
+#ifndef LIBGLESV2_BINARYSTREAM_H_
+#define LIBGLESV2_BINARYSTREAM_H_
+
+#include <string>
+#include <vector>
+
+#include "common/angleutils.h"
+
+namespace gl
+{
+
+class BinaryInputStream
+{
+  public:
+    BinaryInputStream(const void *data, size_t length)
+    {
+        mError = false;
+        mOffset = 0;
+        mData = static_cast<const char*>(data);
+        mLength = length;
+    }
+
+    template <typename T>
+    void read(T *v, size_t num)
+    {
+        union
+        {
+            T dummy;  // Compilation error for non-trivial types
+        } dummy;
+        (void) dummy;
+
+        if (mError)
+        {
+            return;
+        }
+
+        size_t length = num * sizeof(T);
+
+        if (mOffset + length > mLength)
+        {
+            mError = true;
+            return;
+        }
+
+        memcpy(v, mData + mOffset, length);
+        mOffset += length;
+    }
+
+    template <typename T>
+    void read(T * v)
+    {
+        read(v, 1);
+    }
+
+    void read(std::string *v)
+    {
+        size_t length;
+        read(&length);
+
+        if (mError)
+        {
+            return;
+        }
+
+        if (mOffset + length > mLength)
+        {
+            mError = true;
+            return;
+        }
+
+        v->assign(mData + mOffset, length);
+        mOffset += length;
+    }
+
+    void skip(size_t length)
+    {
+        if (mOffset + length > mLength)
+        {
+            mError = true;
+            return;
+        }
+
+        mOffset += length;
+    }
+
+    size_t offset() const
+    {
+        return mOffset;
+    }
+
+    bool error() const
+    {
+        return mError;
+    }
+
+    bool endOfStream() const
+    {
+        return mOffset == mLength;
+    }
+
+  private:
+    DISALLOW_COPY_AND_ASSIGN(BinaryInputStream);
+    bool mError;
+    size_t mOffset;
+    const char *mData;
+    size_t mLength;
+};
+
+class BinaryOutputStream
+{
+  public:
+    BinaryOutputStream()
+    {
+    }
+
+    template <typename T>
+    void write(const T *v, size_t num)
+    {
+        union
+        {
+            T dummy;  // Compilation error for non-trivial types
+        } dummy;
+        (void) dummy;
+
+        const char *asBytes = reinterpret_cast<const char*>(v);
+        mData.insert(mData.end(), asBytes, asBytes + num * sizeof(T));
+    }
+
+    template <typename T>
+    void write(const T &v)
+    {
+        write(&v, 1);
+    }
+
+    void write(const std::string &v)
+    {
+        size_t length = v.length();
+        write(length);
+
+        write(v.c_str(), length);
+    }
+
+    size_t length() const
+    {
+        return mData.size();
+    }
+
+    const void* data() const
+    {
+        return mData.size() ? &mData[0] : NULL;
+    }
+
+  private:
+    DISALLOW_COPY_AND_ASSIGN(BinaryOutputStream);
+    std::vector<char> mData;
+};
+}
+
+#endif  // LIBGLESV2_BINARYSTREAM_H_
diff --git a/src/3rdparty/angle/src/libGLESv2/Blit.cpp b/src/3rdparty/angle/src/libGLESv2/Blit.cpp
new file mode 100644 (file)
index 0000000..28f3fbf
--- /dev/null
@@ -0,0 +1,518 @@
+//
+// 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.
+//
+
+// Blit.cpp: Surface copy utility class.
+
+#include "libGLESv2/Blit.h"
+
+#include "common/debug.h"
+
+#include "libGLESv2/main.h"
+#include "libGLESv2/utilities.h"
+
+namespace
+{
+#include "libGLESv2/shaders/standardvs.h"
+#include "libGLESv2/shaders/flipyvs.h"
+#include "libGLESv2/shaders/passthroughps.h"
+#include "libGLESv2/shaders/luminanceps.h"
+#include "libGLESv2/shaders/componentmaskps.h"
+
+const BYTE* const g_shaderCode[] =
+{
+    g_vs20_standardvs,
+    g_vs20_flipyvs,
+    g_ps20_passthroughps,
+    g_ps20_luminanceps,
+    g_ps20_componentmaskps
+};
+
+const size_t g_shaderSize[] =
+{
+    sizeof(g_vs20_standardvs),
+    sizeof(g_vs20_flipyvs),
+    sizeof(g_ps20_passthroughps),
+    sizeof(g_ps20_luminanceps),
+    sizeof(g_ps20_componentmaskps)
+};
+}
+
+namespace gl
+{
+Blit::Blit(Context *context)
+  : mContext(context), mQuadVertexBuffer(NULL), mQuadVertexDeclaration(NULL), mSavedRenderTarget(NULL), mSavedDepthStencil(NULL), mSavedStateBlock(NULL)
+{
+    initGeometry();
+    memset(mCompiledShaders, 0, sizeof(mCompiledShaders));
+}
+
+Blit::~Blit()
+{
+    if (mSavedStateBlock) mSavedStateBlock->Release();
+    if (mQuadVertexBuffer) mQuadVertexBuffer->Release();
+    if (mQuadVertexDeclaration) mQuadVertexDeclaration->Release();
+
+    for (int i = 0; i < SHADER_COUNT; i++)
+    {
+        if (mCompiledShaders[i])
+        {
+            mCompiledShaders[i]->Release();
+        }
+    }
+}
+
+void Blit::initGeometry()
+{
+    static const float quad[] =
+    {
+        -1, -1,
+        -1,  1,
+         1, -1,
+         1,  1
+    };
+
+    IDirect3DDevice9 *device = getDevice();
+
+    HRESULT result = device->CreateVertexBuffer(sizeof(quad), D3DUSAGE_WRITEONLY, 0, D3DPOOL_DEFAULT, &mQuadVertexBuffer, NULL);
+
+    if (FAILED(result))
+    {
+        ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
+        return error(GL_OUT_OF_MEMORY);
+    }
+
+    void *lockPtr = NULL;
+    result = mQuadVertexBuffer->Lock(0, 0, &lockPtr, 0);
+
+    if (FAILED(result) || lockPtr == NULL)
+    {
+        ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
+        return error(GL_OUT_OF_MEMORY);
+    }
+
+    memcpy(lockPtr, quad, sizeof(quad));
+    mQuadVertexBuffer->Unlock();
+
+    static const D3DVERTEXELEMENT9 elements[] =
+    {
+        { 0, 0, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0 },
+        D3DDECL_END()
+    };
+
+    result = device->CreateVertexDeclaration(elements, &mQuadVertexDeclaration);
+
+    if (FAILED(result))
+    {
+        ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
+        return error(GL_OUT_OF_MEMORY);
+    }
+}
+
+template <class D3DShaderType>
+bool Blit::setShader(ShaderId source, const char *profile,
+                     D3DShaderType *(egl::Display::*createShader)(const DWORD *, size_t length),
+                     HRESULT (WINAPI IDirect3DDevice9::*setShader)(D3DShaderType*))
+{
+    egl::Display *display = getDisplay();
+    IDirect3DDevice9 *device = display->getDevice();
+
+    D3DShaderType *shader;
+
+    if (mCompiledShaders[source] != NULL)
+    {
+        shader = static_cast<D3DShaderType*>(mCompiledShaders[source]);
+    }
+    else
+    {
+        const BYTE* shaderCode = g_shaderCode[source];
+        size_t shaderSize = g_shaderSize[source];
+
+        shader = (display->*createShader)(reinterpret_cast<const DWORD*>(shaderCode), shaderSize);
+        if (!shader)
+        {
+            ERR("Failed to create shader for blit operation");
+            return false;
+        }
+
+        mCompiledShaders[source] = shader;
+    }
+
+    HRESULT hr = (device->*setShader)(shader);
+
+    if (FAILED(hr))
+    {
+        ERR("Failed to set shader for blit operation");
+        return false;
+    }
+
+    return true;
+}
+
+bool Blit::setVertexShader(ShaderId shader)
+{
+    return setShader<IDirect3DVertexShader9>(shader, "vs_2_0", &egl::Display::createVertexShader, &IDirect3DDevice9::SetVertexShader);
+}
+
+bool Blit::setPixelShader(ShaderId shader)
+{
+    return setShader<IDirect3DPixelShader9>(shader, "ps_2_0", &egl::Display::createPixelShader, &IDirect3DDevice9::SetPixelShader);
+}
+
+RECT Blit::getSurfaceRect(IDirect3DSurface9 *surface) const
+{
+    D3DSURFACE_DESC desc;
+    surface->GetDesc(&desc);
+
+    RECT rect;
+    rect.left = 0;
+    rect.top = 0;
+    rect.right = desc.Width;
+    rect.bottom = desc.Height;
+
+    return rect;
+}
+
+bool Blit::boxFilter(IDirect3DSurface9 *source, IDirect3DSurface9 *dest)
+{
+    IDirect3DTexture9 *texture = copySurfaceToTexture(source, getSurfaceRect(source));
+    if (!texture)
+    {
+        return false;
+    }
+
+    IDirect3DDevice9 *device = getDevice();
+
+    saveState();
+
+    device->SetTexture(0, texture);
+    device->SetRenderTarget(0, dest);
+
+    setVertexShader(SHADER_VS_STANDARD);
+    setPixelShader(SHADER_PS_PASSTHROUGH);
+
+    setCommonBlitState();
+    device->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
+    device->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
+
+    setViewport(getSurfaceRect(dest), 0, 0);
+
+    render();
+
+    texture->Release();
+
+    restoreState();
+
+    return true;
+}
+
+bool Blit::copy(IDirect3DSurface9 *source, const RECT &sourceRect, GLenum destFormat, GLint xoffset, GLint yoffset, IDirect3DSurface9 *dest)
+{
+    IDirect3DDevice9 *device = getDevice();
+
+    D3DSURFACE_DESC sourceDesc;
+    D3DSURFACE_DESC destDesc;
+    source->GetDesc(&sourceDesc);
+    dest->GetDesc(&destDesc);
+
+    if (sourceDesc.Format == destDesc.Format && destDesc.Usage & D3DUSAGE_RENDERTARGET &&
+        dx2es::IsFormatChannelEquivalent(destDesc.Format, destFormat))   // Can use StretchRect
+    {
+        RECT destRect = {xoffset, yoffset, xoffset + (sourceRect.right - sourceRect.left), yoffset + (sourceRect.bottom - sourceRect.top)};
+        HRESULT result = device->StretchRect(source, &sourceRect, dest, &destRect, D3DTEXF_POINT);
+
+        if (FAILED(result))
+        {
+            ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
+            return error(GL_OUT_OF_MEMORY, false);
+        }
+    }
+    else
+    {
+        return formatConvert(source, sourceRect, destFormat, xoffset, yoffset, dest);
+    }
+
+    return true;
+}
+
+bool Blit::formatConvert(IDirect3DSurface9 *source, const RECT &sourceRect, GLenum destFormat, GLint xoffset, GLint yoffset, IDirect3DSurface9 *dest)
+{
+    IDirect3DTexture9 *texture = copySurfaceToTexture(source, sourceRect);
+    if (!texture)
+    {
+        return false;
+    }
+
+    IDirect3DDevice9 *device = getDevice();
+
+    saveState();
+
+    device->SetTexture(0, texture);
+    device->SetRenderTarget(0, dest);
+
+    setViewport(sourceRect, xoffset, yoffset);
+
+    setCommonBlitState();
+    if (setFormatConvertShaders(destFormat))
+    {
+        render();
+    }
+
+    texture->Release();
+
+    restoreState();
+
+    return true;
+}
+
+bool Blit::setFormatConvertShaders(GLenum destFormat)
+{
+    bool okay = setVertexShader(SHADER_VS_STANDARD);
+
+    switch (destFormat)
+    {
+      default: UNREACHABLE();
+      case GL_RGBA:
+      case GL_BGRA_EXT:
+      case GL_RGB:
+      case GL_ALPHA:
+        okay = okay && setPixelShader(SHADER_PS_COMPONENTMASK);
+        break;
+
+      case GL_LUMINANCE:
+      case GL_LUMINANCE_ALPHA:
+        okay = okay && setPixelShader(SHADER_PS_LUMINANCE);
+        break;
+    }
+
+    if (!okay)
+    {
+        return false;
+    }
+
+    enum { X = 0, Y = 1, Z = 2, W = 3 };
+
+    // The meaning of this constant depends on the shader that was selected.
+    // See the shader assembly code above for details.
+    float psConst0[4] = { 0, 0, 0, 0 };
+
+    switch (destFormat)
+    {
+      default: UNREACHABLE();
+      case GL_RGBA:
+      case GL_BGRA_EXT:
+        psConst0[X] = 1;
+        psConst0[Z] = 1;
+        break;
+
+      case GL_RGB:
+        psConst0[X] = 1;
+        psConst0[W] = 1;
+        break;
+
+      case GL_ALPHA:
+        psConst0[Z] = 1;
+        break;
+
+      case GL_LUMINANCE:
+        psConst0[Y] = 1;
+        break;
+
+      case GL_LUMINANCE_ALPHA:
+        psConst0[X] = 1;
+        break;
+    }
+
+    getDevice()->SetPixelShaderConstantF(0, psConst0, 1);
+
+    return true;
+}
+
+IDirect3DTexture9 *Blit::copySurfaceToTexture(IDirect3DSurface9 *surface, const RECT &sourceRect)
+{
+    if (!surface)
+    {
+        return NULL;
+    }
+
+    egl::Display *display = getDisplay();
+    IDirect3DDevice9 *device = getDevice();
+
+    D3DSURFACE_DESC sourceDesc;
+    surface->GetDesc(&sourceDesc);
+
+    // Copy the render target into a texture
+    IDirect3DTexture9 *texture;
+    HRESULT result = device->CreateTexture(sourceRect.right - sourceRect.left, sourceRect.bottom - sourceRect.top, 1, D3DUSAGE_RENDERTARGET, sourceDesc.Format, D3DPOOL_DEFAULT, &texture, NULL);
+
+    if (FAILED(result))
+    {
+        ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
+        return error(GL_OUT_OF_MEMORY, (IDirect3DTexture9*)NULL);
+    }
+
+    IDirect3DSurface9 *textureSurface;
+    result = texture->GetSurfaceLevel(0, &textureSurface);
+
+    if (FAILED(result))
+    {
+        ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
+        texture->Release();
+        return error(GL_OUT_OF_MEMORY, (IDirect3DTexture9*)NULL);
+    }
+
+    display->endScene();
+    result = device->StretchRect(surface, &sourceRect, textureSurface, NULL, D3DTEXF_NONE);
+
+    textureSurface->Release();
+
+    if (FAILED(result))
+    {
+        ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
+        texture->Release();
+        return error(GL_OUT_OF_MEMORY, (IDirect3DTexture9*)NULL);
+    }
+
+    return texture;
+}
+
+void Blit::setViewport(const RECT &sourceRect, GLint xoffset, GLint yoffset)
+{
+    IDirect3DDevice9 *device = getDevice();
+
+    D3DVIEWPORT9 vp;
+    vp.X      = xoffset;
+    vp.Y      = yoffset;
+    vp.Width  = sourceRect.right - sourceRect.left;
+    vp.Height = sourceRect.bottom - sourceRect.top;
+    vp.MinZ   = 0.0f;
+    vp.MaxZ   = 1.0f;
+    device->SetViewport(&vp);
+
+    float halfPixelAdjust[4] = { -1.0f/vp.Width, 1.0f/vp.Height, 0, 0 };
+    device->SetVertexShaderConstantF(0, halfPixelAdjust, 1);
+}
+
+void Blit::setCommonBlitState()
+{
+    IDirect3DDevice9 *device = getDevice();
+
+    device->SetDepthStencilSurface(NULL);
+
+    device->SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID);
+    device->SetRenderState(D3DRS_ALPHATESTENABLE, FALSE);
+    device->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
+    device->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
+    device->SetRenderState(D3DRS_CLIPPLANEENABLE, 0);
+    device->SetRenderState(D3DRS_COLORWRITEENABLE, D3DCOLORWRITEENABLE_ALPHA | D3DCOLORWRITEENABLE_BLUE | D3DCOLORWRITEENABLE_GREEN | D3DCOLORWRITEENABLE_RED);
+    device->SetRenderState(D3DRS_SRGBWRITEENABLE, FALSE);
+    device->SetRenderState(D3DRS_SCISSORTESTENABLE, FALSE);
+
+    device->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_POINT);
+    device->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_POINT);
+    device->SetSamplerState(0, D3DSAMP_SRGBTEXTURE, FALSE);
+    device->SetSamplerState(0, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP);
+    device->SetSamplerState(0, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP);
+
+    RECT scissorRect = {0};   // Scissoring is disabled for flipping, but we need this to capture and restore the old rectangle
+    device->SetScissorRect(&scissorRect);
+
+    for(int i = 0; i < MAX_VERTEX_ATTRIBS; i++)
+    {
+        device->SetStreamSourceFreq(i, 1);
+    }
+}
+
+void Blit::render()
+{
+    egl::Display *display = getDisplay();
+    IDirect3DDevice9 *device = getDevice();
+
+    HRESULT hr = device->SetStreamSource(0, mQuadVertexBuffer, 0, 2 * sizeof(float));
+    hr = device->SetVertexDeclaration(mQuadVertexDeclaration);
+
+    display->startScene();
+    hr = device->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2);
+}
+
+void Blit::saveState()
+{
+    IDirect3DDevice9 *device = getDevice();
+
+    HRESULT hr;
+
+    device->GetDepthStencilSurface(&mSavedDepthStencil);
+    device->GetRenderTarget(0, &mSavedRenderTarget);
+
+    if (mSavedStateBlock == NULL)
+    {
+        hr = device->BeginStateBlock();
+        ASSERT(SUCCEEDED(hr) || hr == D3DERR_OUTOFVIDEOMEMORY || hr == E_OUTOFMEMORY);
+
+        setCommonBlitState();
+
+        static const float dummyConst[4] = { 0, 0, 0, 0 };
+
+        device->SetVertexShader(NULL);
+        device->SetVertexShaderConstantF(0, dummyConst, 1);
+        device->SetPixelShader(NULL);
+        device->SetPixelShaderConstantF(0, dummyConst, 1);
+
+        D3DVIEWPORT9 dummyVp;
+        dummyVp.X = 0;
+        dummyVp.Y = 0;
+        dummyVp.Width = 1;
+        dummyVp.Height = 1;
+        dummyVp.MinZ = 0;
+        dummyVp.MaxZ = 1;
+
+        device->SetViewport(&dummyVp);
+
+        device->SetTexture(0, NULL);
+
+        device->SetStreamSource(0, mQuadVertexBuffer, 0, 0);
+
+        device->SetVertexDeclaration(mQuadVertexDeclaration);
+
+        hr = device->EndStateBlock(&mSavedStateBlock);
+        ASSERT(SUCCEEDED(hr) || hr == D3DERR_OUTOFVIDEOMEMORY || hr == E_OUTOFMEMORY);
+    }
+
+    ASSERT(mSavedStateBlock != NULL);
+
+    if (mSavedStateBlock != NULL)
+    {
+        hr = mSavedStateBlock->Capture();
+        ASSERT(SUCCEEDED(hr));
+    }
+}
+
+void Blit::restoreState()
+{
+    IDirect3DDevice9 *device = getDevice();
+
+    device->SetDepthStencilSurface(mSavedDepthStencil);
+    if (mSavedDepthStencil != NULL)
+    {
+        mSavedDepthStencil->Release();
+        mSavedDepthStencil = NULL;
+    }
+
+    device->SetRenderTarget(0, mSavedRenderTarget);
+    if (mSavedRenderTarget != NULL)
+    {
+        mSavedRenderTarget->Release();
+        mSavedRenderTarget = NULL;
+    }
+
+    ASSERT(mSavedStateBlock != NULL);
+
+    if (mSavedStateBlock != NULL)
+    {
+        mSavedStateBlock->Apply();
+    }
+}
+
+}
diff --git a/src/3rdparty/angle/src/libGLESv2/Blit.h b/src/3rdparty/angle/src/libGLESv2/Blit.h
new file mode 100644 (file)
index 0000000..a9bb495
--- /dev/null
@@ -0,0 +1,94 @@
+//
+// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// Blit.cpp: Surface copy utility class.
+
+#ifndef LIBGLESV2_BLIT_H_
+#define LIBGLESV2_BLIT_H_
+
+#include <map>
+
+#define GL_APICALL
+#include <GLES2/gl2.h>
+
+#include <d3d9.h>
+
+#include "common/angleutils.h"
+
+#include "libEGL/Display.h"
+
+namespace gl
+{
+class Context;
+
+class Blit
+{
+  public:
+    explicit Blit(Context *context);
+    ~Blit();
+
+    // Copy from source surface to dest surface.
+    // sourceRect, xoffset, yoffset are in D3D coordinates (0,0 in upper-left)
+    bool copy(IDirect3DSurface9 *source, const RECT &sourceRect, GLenum destFormat, GLint xoffset, GLint yoffset, IDirect3DSurface9 *dest);
+
+    // Copy from source surface to dest surface.
+    // sourceRect, xoffset, yoffset are in D3D coordinates (0,0 in upper-left)
+    // source is interpreted as RGBA and destFormat specifies the desired result format. For example, if destFormat = GL_RGB, the alpha channel will be forced to 0.
+    bool formatConvert(IDirect3DSurface9 *source, const RECT &sourceRect, GLenum destFormat, GLint xoffset, GLint yoffset, IDirect3DSurface9 *dest);
+
+    // 2x2 box filter sample from source to dest.
+    // Requires that source is RGB(A) and dest has the same format as source.
+    bool boxFilter(IDirect3DSurface9 *source, IDirect3DSurface9 *dest);
+
+  private:
+    Context *mContext;
+
+    IDirect3DVertexBuffer9 *mQuadVertexBuffer;
+    IDirect3DVertexDeclaration9 *mQuadVertexDeclaration;
+
+    void initGeometry();
+
+    bool setFormatConvertShaders(GLenum destFormat);
+
+    IDirect3DTexture9 *copySurfaceToTexture(IDirect3DSurface9 *surface, const RECT &sourceRect);
+    void setViewport(const RECT &sourceRect, GLint xoffset, GLint yoffset);
+    void setCommonBlitState();
+    RECT getSurfaceRect(IDirect3DSurface9 *surface) const;
+
+    // This enum is used to index mCompiledShaders and mShaderSource.
+    enum ShaderId
+    {
+        SHADER_VS_STANDARD,
+        SHADER_VS_FLIPY,
+        SHADER_PS_PASSTHROUGH,
+        SHADER_PS_LUMINANCE,
+        SHADER_PS_COMPONENTMASK,
+        SHADER_COUNT
+    };
+
+    // This actually contains IDirect3DVertexShader9 or IDirect3DPixelShader9 casted to IUnknown.
+    IUnknown *mCompiledShaders[SHADER_COUNT];
+
+    template <class D3DShaderType>
+    bool setShader(ShaderId source, const char *profile,
+                   D3DShaderType *(egl::Display::*createShader)(const DWORD *, size_t length),
+                   HRESULT (WINAPI IDirect3DDevice9::*setShader)(D3DShaderType*));
+
+    bool setVertexShader(ShaderId shader);
+    bool setPixelShader(ShaderId shader);
+    void render();
+
+    void saveState();
+    void restoreState();
+    IDirect3DStateBlock9 *mSavedStateBlock;
+    IDirect3DSurface9 *mSavedRenderTarget;
+    IDirect3DSurface9 *mSavedDepthStencil;
+
+    DISALLOW_COPY_AND_ASSIGN(Blit);
+};
+}
+
+#endif   // LIBGLESV2_BLIT_H_
diff --git a/src/3rdparty/angle/src/libGLESv2/Buffer.cpp b/src/3rdparty/angle/src/libGLESv2/Buffer.cpp
new file mode 100644 (file)
index 0000000..dd12e3c
--- /dev/null
@@ -0,0 +1,117 @@
+//
+// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// Buffer.cpp: Implements the gl::Buffer class, representing storage of vertex and/or
+// index data. Implements GL buffer objects and related functionality.
+// [OpenGL ES 2.0.24] section 2.9 page 21.
+
+#include "libGLESv2/Buffer.h"
+
+#include "libGLESv2/main.h"
+#include "libGLESv2/VertexDataManager.h"
+#include "libGLESv2/IndexDataManager.h"
+
+namespace gl
+{
+
+Buffer::Buffer(GLuint id) : RefCountObject(id)
+{
+    mContents = NULL;
+    mSize = 0;
+    mUsage = GL_DYNAMIC_DRAW;
+
+    mStaticVertexBuffer = NULL;
+    mStaticIndexBuffer = NULL;
+    mUnmodifiedDataUse = 0;
+}
+
+Buffer::~Buffer()
+{
+    delete[] mContents;
+    delete mStaticVertexBuffer;
+    delete mStaticIndexBuffer;
+}
+
+void Buffer::bufferData(const void *data, GLsizeiptr size, GLenum usage)
+{
+    if (size == 0)
+    {
+        delete[] mContents;
+        mContents = NULL;
+    }
+    else if (size != mSize)
+    {
+        delete[] mContents;
+        mContents = new GLubyte[size];
+        memset(mContents, 0, size);
+    }
+
+    if (data != NULL && size > 0)
+    {
+        memcpy(mContents, data, size);
+    }
+
+    mSize = size;
+    mUsage = usage;
+
+    invalidateStaticData();
+
+    if (usage == GL_STATIC_DRAW)
+    {
+        mStaticVertexBuffer = new StaticVertexBuffer(getDevice());
+        mStaticIndexBuffer = new StaticIndexBuffer(getDevice());
+    }
+}
+
+void Buffer::bufferSubData(const void *data, GLsizeiptr size, GLintptr offset)
+{
+    memcpy(mContents + offset, data, size);
+    
+    if ((mStaticVertexBuffer && mStaticVertexBuffer->size() != 0) || (mStaticIndexBuffer && mStaticIndexBuffer->size() != 0))
+    {
+        invalidateStaticData();
+    }
+
+    mUnmodifiedDataUse = 0;
+}
+
+StaticVertexBuffer *Buffer::getStaticVertexBuffer()
+{
+    return mStaticVertexBuffer;
+}
+
+StaticIndexBuffer *Buffer::getStaticIndexBuffer()
+{
+    return mStaticIndexBuffer;
+}
+
+void Buffer::invalidateStaticData()
+{
+    delete mStaticVertexBuffer;
+    mStaticVertexBuffer = NULL;
+
+    delete mStaticIndexBuffer;
+    mStaticIndexBuffer = NULL;
+
+    mUnmodifiedDataUse = 0;
+}
+
+// Creates static buffers if sufficient used data has been left unmodified
+void Buffer::promoteStaticUsage(int dataSize)
+{
+    if (!mStaticVertexBuffer && !mStaticIndexBuffer)
+    {
+        mUnmodifiedDataUse += dataSize;
+
+        if (mUnmodifiedDataUse > 3 * mSize)
+        {
+            mStaticVertexBuffer = new StaticVertexBuffer(getDevice());
+            mStaticIndexBuffer = new StaticIndexBuffer(getDevice());
+        }
+    }
+}
+
+}
diff --git a/src/3rdparty/angle/src/libGLESv2/Buffer.h b/src/3rdparty/angle/src/libGLESv2/Buffer.h
new file mode 100644 (file)
index 0000000..7019c4e
--- /dev/null
@@ -0,0 +1,61 @@
+//
+// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// Buffer.h: Defines the gl::Buffer class, representing storage of vertex and/or
+// index data. Implements GL buffer objects and related functionality.
+// [OpenGL ES 2.0.24] section 2.9 page 21.
+
+#ifndef LIBGLESV2_BUFFER_H_
+#define LIBGLESV2_BUFFER_H_
+
+#include <cstddef>
+#include <vector>
+
+#define GL_APICALL
+#include <GLES2/gl2.h>
+
+#include "common/angleutils.h"
+#include "common/RefCountObject.h"
+
+namespace gl
+{
+class StaticVertexBuffer;
+class StaticIndexBuffer;
+
+class Buffer : public RefCountObject
+{
+  public:
+    explicit Buffer(GLuint id);
+
+    virtual ~Buffer();
+
+    void bufferData(const void *data, GLsizeiptr size, GLenum usage);
+    void bufferSubData(const void *data, GLsizeiptr size, GLintptr offset);
+
+    void *data() { return mContents; }
+    size_t size() const { return mSize; }
+    GLenum usage() const { return mUsage; }
+
+    StaticVertexBuffer *getStaticVertexBuffer();
+    StaticIndexBuffer *getStaticIndexBuffer();
+    void invalidateStaticData();
+    void promoteStaticUsage(int dataSize);
+
+  private:
+    DISALLOW_COPY_AND_ASSIGN(Buffer);
+
+    GLubyte *mContents;
+    GLsizeiptr mSize;
+    GLenum mUsage;
+
+    StaticVertexBuffer *mStaticVertexBuffer;
+    StaticIndexBuffer *mStaticIndexBuffer;
+    GLsizeiptr mUnmodifiedDataUse;
+};
+
+}
+
+#endif   // LIBGLESV2_BUFFER_H_
diff --git a/src/3rdparty/angle/src/libGLESv2/Context.cpp b/src/3rdparty/angle/src/libGLESv2/Context.cpp
new file mode 100644 (file)
index 0000000..414bfa9
--- /dev/null
@@ -0,0 +1,4501 @@
+//
+// 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.
+//
+
+// Context.cpp: Implements the gl::Context class, managing all GL state and performing
+// rendering operations. It is the GLES2 specific implementation of EGLContext.
+
+#include "libGLESv2/Context.h"
+
+#include <algorithm>
+
+#include "libEGL/Display.h"
+
+#include "libGLESv2/main.h"
+#include "libGLESv2/mathutil.h"
+#include "libGLESv2/utilities.h"
+#include "libGLESv2/Blit.h"
+#include "libGLESv2/ResourceManager.h"
+#include "libGLESv2/Buffer.h"
+#include "libGLESv2/Fence.h"
+#include "libGLESv2/Framebuffer.h"
+#include "libGLESv2/Program.h"
+#include "libGLESv2/ProgramBinary.h"
+#include "libGLESv2/Query.h"
+#include "libGLESv2/Renderbuffer.h"
+#include "libGLESv2/Shader.h"
+#include "libGLESv2/Texture.h"
+#include "libGLESv2/VertexDataManager.h"
+#include "libGLESv2/IndexDataManager.h"
+
+#undef near
+#undef far
+
+namespace gl
+{
+Context::Context(const egl::Config *config, const gl::Context *shareContext, bool notifyResets, bool robustAccess) : mConfig(config)
+{
+    ASSERT(robustAccess == false);   // Unimplemented
+
+    mDisplay = NULL;
+    mDevice = NULL;
+
+    mFenceHandleAllocator.setBaseHandle(0);
+
+    setClearColor(0.0f, 0.0f, 0.0f, 0.0f);
+
+    mState.depthClearValue = 1.0f;
+    mState.stencilClearValue = 0;
+
+    mState.cullFace = false;
+    mState.cullMode = GL_BACK;
+    mState.frontFace = GL_CCW;
+    mState.depthTest = false;
+    mState.depthFunc = GL_LESS;
+    mState.blend = false;
+    mState.sourceBlendRGB = GL_ONE;
+    mState.sourceBlendAlpha = GL_ONE;
+    mState.destBlendRGB = GL_ZERO;
+    mState.destBlendAlpha = GL_ZERO;
+    mState.blendEquationRGB = GL_FUNC_ADD;
+    mState.blendEquationAlpha = GL_FUNC_ADD;
+    mState.blendColor.red = 0;
+    mState.blendColor.green = 0;
+    mState.blendColor.blue = 0;
+    mState.blendColor.alpha = 0;
+    mState.stencilTest = false;
+    mState.stencilFunc = GL_ALWAYS;
+    mState.stencilRef = 0;
+    mState.stencilMask = -1;
+    mState.stencilWritemask = -1;
+    mState.stencilBackFunc = GL_ALWAYS;
+    mState.stencilBackRef = 0;
+    mState.stencilBackMask = - 1;
+    mState.stencilBackWritemask = -1;
+    mState.stencilFail = GL_KEEP;
+    mState.stencilPassDepthFail = GL_KEEP;
+    mState.stencilPassDepthPass = GL_KEEP;
+    mState.stencilBackFail = GL_KEEP;
+    mState.stencilBackPassDepthFail = GL_KEEP;
+    mState.stencilBackPassDepthPass = GL_KEEP;
+    mState.polygonOffsetFill = false;
+    mState.polygonOffsetFactor = 0.0f;
+    mState.polygonOffsetUnits = 0.0f;
+    mState.sampleAlphaToCoverage = false;
+    mState.sampleCoverage = false;
+    mState.sampleCoverageValue = 1.0f;
+    mState.sampleCoverageInvert = false;
+    mState.scissorTest = false;
+    mState.dither = true;
+    mState.generateMipmapHint = GL_DONT_CARE;
+    mState.fragmentShaderDerivativeHint = GL_DONT_CARE;
+
+    mState.lineWidth = 1.0f;
+
+    mState.viewportX = 0;
+    mState.viewportY = 0;
+    mState.viewportWidth = config->mDisplayMode.Width;
+    mState.viewportHeight = config->mDisplayMode.Height;
+    mState.zNear = 0.0f;
+    mState.zFar = 1.0f;
+
+    mState.scissorX = 0;
+    mState.scissorY = 0;
+    mState.scissorWidth = config->mDisplayMode.Width;
+    mState.scissorHeight = config->mDisplayMode.Height;
+
+    mState.colorMaskRed = true;
+    mState.colorMaskGreen = true;
+    mState.colorMaskBlue = true;
+    mState.colorMaskAlpha = true;
+    mState.depthMask = true;
+
+    if (shareContext != NULL)
+    {
+        mResourceManager = shareContext->mResourceManager;
+        mResourceManager->addRef();
+    }
+    else
+    {
+        mResourceManager = new ResourceManager();
+    }
+
+    // [OpenGL ES 2.0.24] section 3.7 page 83:
+    // In the initial state, TEXTURE_2D and TEXTURE_CUBE_MAP have twodimensional
+    // and cube map texture state vectors respectively associated with them.
+    // In order that access to these initial textures not be lost, they are treated as texture
+    // objects all of whose names are 0.
+
+    mTexture2DZero.set(new Texture2D(0));
+    mTextureCubeMapZero.set(new TextureCubeMap(0));
+
+    mState.activeSampler = 0;
+    bindArrayBuffer(0);
+    bindElementArrayBuffer(0);
+    bindTextureCubeMap(0);
+    bindTexture2D(0);
+    bindReadFramebuffer(0);
+    bindDrawFramebuffer(0);
+    bindRenderbuffer(0);
+
+    mState.currentProgram = 0;
+    mCurrentProgramBinary.set(NULL);
+
+    mState.packAlignment = 4;
+    mState.unpackAlignment = 4;
+    mState.packReverseRowOrder = false;
+
+    mVertexDataManager = NULL;
+    mIndexDataManager = NULL;
+    mBlit = NULL;
+    mLineLoopIB = NULL;
+
+    mInvalidEnum = false;
+    mInvalidValue = false;
+    mInvalidOperation = false;
+    mOutOfMemory = false;
+    mInvalidFramebufferOperation = false;
+
+    mHasBeenCurrent = false;
+    mContextLost = false;
+    mResetStatus = GL_NO_ERROR;
+    mResetStrategy = (notifyResets ? GL_LOSE_CONTEXT_ON_RESET_EXT : GL_NO_RESET_NOTIFICATION_EXT);
+    mRobustAccess = robustAccess;
+
+    mSupportsDXT1Textures = false;
+    mSupportsDXT3Textures = false;
+    mSupportsDXT5Textures = false;
+    mSupportsEventQueries = false;
+    mSupportsOcclusionQueries = false;
+    mNumCompressedTextureFormats = 0;
+    mMaxSupportedSamples = 0;
+    mMaskedClearSavedState = NULL;
+    markAllStateDirty();
+}
+
+Context::~Context()
+{
+    if (mState.currentProgram != 0)
+    {
+        Program *programObject = mResourceManager->getProgram(mState.currentProgram);
+        if (programObject)
+        {
+            programObject->release();
+        }
+        mState.currentProgram = 0;
+    }
+    mCurrentProgramBinary.set(NULL);
+
+    while (!mFramebufferMap.empty())
+    {
+        deleteFramebuffer(mFramebufferMap.begin()->first);
+    }
+
+    while (!mFenceMap.empty())
+    {
+        deleteFence(mFenceMap.begin()->first);
+    }
+
+    while (!mQueryMap.empty())
+    {
+        deleteQuery(mQueryMap.begin()->first);
+    }
+
+    while (!mMultiSampleSupport.empty())
+    {
+        delete [] mMultiSampleSupport.begin()->second;
+        mMultiSampleSupport.erase(mMultiSampleSupport.begin());
+    }
+
+    for (int type = 0; type < TEXTURE_TYPE_COUNT; type++)
+    {
+        for (int sampler = 0; sampler < MAX_COMBINED_TEXTURE_IMAGE_UNITS_VTF; sampler++)
+        {
+            mState.samplerTexture[type][sampler].set(NULL);
+        }
+    }
+
+    for (int type = 0; type < TEXTURE_TYPE_COUNT; type++)
+    {
+        mIncompleteTextures[type].set(NULL);
+    }
+
+    for (int i = 0; i < MAX_VERTEX_ATTRIBS; i++)
+    {
+        mState.vertexAttribute[i].mBoundBuffer.set(NULL);
+    }
+
+    for (int i = 0; i < QUERY_TYPE_COUNT; i++)
+    {
+        mState.activeQuery[i].set(NULL);
+    }
+
+    mState.arrayBuffer.set(NULL);
+    mState.elementArrayBuffer.set(NULL);
+    mState.renderbuffer.set(NULL);
+
+    mTexture2DZero.set(NULL);
+    mTextureCubeMapZero.set(NULL);
+
+    delete mVertexDataManager;
+    delete mIndexDataManager;
+    delete mBlit;
+    delete mLineLoopIB;
+
+    if (mMaskedClearSavedState)
+    {
+        mMaskedClearSavedState->Release();
+    }
+
+    mResourceManager->release();
+}
+
+void Context::makeCurrent(egl::Display *display, egl::Surface *surface)
+{
+    mDisplay = display;
+    mDevice = mDisplay->getDevice();
+
+    if (!mHasBeenCurrent)
+    {
+        mDeviceCaps = mDisplay->getDeviceCaps();
+
+        mVertexDataManager = new VertexDataManager(this, mDevice);
+        mIndexDataManager = new IndexDataManager(this, mDevice);
+        mBlit = new Blit(this);
+
+        mSupportsShaderModel3 = mDeviceCaps.PixelShaderVersion >= D3DPS_VERSION(3, 0);
+        mMaximumPointSize = mDeviceCaps.MaxPointSize;
+        mSupportsVertexTexture = mDisplay->getVertexTextureSupport();
+        mSupportsNonPower2Texture = mDisplay->getNonPower2TextureSupport();
+        mSupportsInstancing = mDisplay->getInstancingSupport();
+
+        mMaxTextureDimension = std::min(std::min((int)mDeviceCaps.MaxTextureWidth, (int)mDeviceCaps.MaxTextureHeight),
+                                        (int)gl::IMPLEMENTATION_MAX_TEXTURE_SIZE);
+        mMaxCubeTextureDimension = std::min(mMaxTextureDimension, (int)gl::IMPLEMENTATION_MAX_CUBE_MAP_TEXTURE_SIZE);
+        mMaxRenderbufferDimension = mMaxTextureDimension;
+        mMaxTextureLevel = log2(mMaxTextureDimension) + 1;
+        mMaxTextureAnisotropy = mDisplay->getTextureFilterAnisotropySupport();
+        TRACE("MaxTextureDimension=%d, MaxCubeTextureDimension=%d, MaxRenderbufferDimension=%d, MaxTextureLevel=%d, MaxTextureAnisotropy=%f",
+              mMaxTextureDimension, mMaxCubeTextureDimension, mMaxRenderbufferDimension, mMaxTextureLevel, mMaxTextureAnisotropy);
+
+        const D3DFORMAT renderBufferFormats[] =
+        {
+            D3DFMT_A8R8G8B8,
+            D3DFMT_X8R8G8B8,
+            D3DFMT_R5G6B5,
+            D3DFMT_D24S8
+        };
+
+        int max = 0;
+        for (int i = 0; i < sizeof(renderBufferFormats) / sizeof(D3DFORMAT); ++i)
+        {
+            bool *multisampleArray = new bool[D3DMULTISAMPLE_16_SAMPLES + 1];
+            mDisplay->getMultiSampleSupport(renderBufferFormats[i], multisampleArray);
+            mMultiSampleSupport[renderBufferFormats[i]] = multisampleArray;
+
+            for (int j = D3DMULTISAMPLE_16_SAMPLES; j >= 0; --j)
+            {
+                if (multisampleArray[j] && j != D3DMULTISAMPLE_NONMASKABLE && j > max)
+                {
+                    max = j;
+                }
+            }
+        }
+
+        mMaxSupportedSamples = max;
+
+        mSupportsEventQueries = mDisplay->getEventQuerySupport();
+        mSupportsOcclusionQueries = mDisplay->getOcclusionQuerySupport();
+        mSupportsDXT1Textures = mDisplay->getDXT1TextureSupport();
+        mSupportsDXT3Textures = mDisplay->getDXT3TextureSupport();
+        mSupportsDXT5Textures = mDisplay->getDXT5TextureSupport();
+        mSupportsFloat32Textures = mDisplay->getFloat32TextureSupport(&mSupportsFloat32LinearFilter, &mSupportsFloat32RenderableTextures);
+        mSupportsFloat16Textures = mDisplay->getFloat16TextureSupport(&mSupportsFloat16LinearFilter, &mSupportsFloat16RenderableTextures);
+        mSupportsLuminanceTextures = mDisplay->getLuminanceTextureSupport();
+        mSupportsLuminanceAlphaTextures = mDisplay->getLuminanceAlphaTextureSupport();
+        mSupportsDepthTextures = mDisplay->getDepthTextureSupport();
+        mSupportsTextureFilterAnisotropy = mMaxTextureAnisotropy >= 2.0f;
+
+        mSupports32bitIndices = mDeviceCaps.MaxVertexIndex >= (1 << 16);
+
+        mNumCompressedTextureFormats = 0;
+        if (supportsDXT1Textures())
+        {
+            mNumCompressedTextureFormats += 2;
+        }
+        if (supportsDXT3Textures())
+        {
+            mNumCompressedTextureFormats += 1;
+        }
+        if (supportsDXT5Textures())
+        {
+            mNumCompressedTextureFormats += 1;
+        }
+
+        initExtensionString();
+        initRendererString();
+
+        mState.viewportX = 0;
+        mState.viewportY = 0;
+        mState.viewportWidth = surface->getWidth();
+        mState.viewportHeight = surface->getHeight();
+
+        mState.scissorX = 0;
+        mState.scissorY = 0;
+        mState.scissorWidth = surface->getWidth();
+        mState.scissorHeight = surface->getHeight();
+
+        mHasBeenCurrent = true;
+    }
+
+    // Wrap the existing Direct3D 9 resources into GL objects and assign them to the '0' names
+    IDirect3DSurface9 *defaultRenderTarget = surface->getRenderTarget();
+    IDirect3DSurface9 *depthStencil = surface->getDepthStencil();
+
+    Colorbuffer *colorbufferZero = new Colorbuffer(defaultRenderTarget);
+    DepthStencilbuffer *depthStencilbufferZero = new DepthStencilbuffer(depthStencil);
+    Framebuffer *framebufferZero = new DefaultFramebuffer(colorbufferZero, depthStencilbufferZero);
+
+    setFramebufferZero(framebufferZero);
+
+    if (defaultRenderTarget)
+    {
+        defaultRenderTarget->Release();
+    }
+
+    if (depthStencil)
+    {
+        depthStencil->Release();
+    }
+
+    // Reset pixel shader to null to work around a bug that only happens with Intel GPUs.
+    // http://crbug.com/110343
+    mDevice->SetPixelShader(NULL);
+    
+    markAllStateDirty();
+}
+
+// This function will set all of the state-related dirty flags, so that all state is set during next pre-draw.
+void Context::markAllStateDirty()
+{
+    for (int t = 0; t < MAX_TEXTURE_IMAGE_UNITS; t++)
+    {
+        mAppliedTextureSerialPS[t] = 0;
+    }
+
+    for (int t = 0; t < MAX_VERTEX_TEXTURE_IMAGE_UNITS_VTF; t++)
+    {
+        mAppliedTextureSerialVS[t] = 0;
+    }
+
+    mAppliedProgramBinarySerial = 0;
+    mAppliedRenderTargetSerial = 0;
+    mAppliedDepthbufferSerial = 0;
+    mAppliedStencilbufferSerial = 0;
+    mAppliedIBSerial = 0;
+    mDepthStencilInitialized = false;
+    mViewportInitialized = false;
+    mRenderTargetDescInitialized = false;
+
+    mVertexDeclarationCache.markStateDirty();
+
+    mClearStateDirty = true;
+    mCullStateDirty = true;
+    mDepthStateDirty = true;
+    mMaskStateDirty = true;
+    mBlendStateDirty = true;
+    mStencilStateDirty = true;
+    mPolygonOffsetStateDirty = true;
+    mScissorStateDirty = true;
+    mSampleStateDirty = true;
+    mDitherStateDirty = true;
+    mFrontFaceDirty = true;
+    mDxUniformsDirty = true;
+}
+
+void Context::markDxUniformsDirty()
+{
+    mDxUniformsDirty = true;
+}
+
+void Context::markContextLost()
+{
+    if (mResetStrategy == GL_LOSE_CONTEXT_ON_RESET_EXT)
+        mResetStatus = GL_UNKNOWN_CONTEXT_RESET_EXT;
+    mContextLost = true;
+}
+
+bool Context::isContextLost()
+{
+    return mContextLost;
+}
+
+void Context::setClearColor(float red, float green, float blue, float alpha)
+{
+    mState.colorClearValue.red = red;
+    mState.colorClearValue.green = green;
+    mState.colorClearValue.blue = blue;
+    mState.colorClearValue.alpha = alpha;
+}
+
+void Context::setClearDepth(float depth)
+{
+    mState.depthClearValue = depth;
+}
+
+void Context::setClearStencil(int stencil)
+{
+    mState.stencilClearValue = stencil;
+}
+
+void Context::setCullFace(bool enabled)
+{
+    if (mState.cullFace != enabled)
+    {
+        mState.cullFace = enabled;
+        mCullStateDirty = true;
+    }
+}
+
+bool Context::isCullFaceEnabled() const
+{
+    return mState.cullFace;
+}
+
+void Context::setCullMode(GLenum mode)
+{
+    if (mState.cullMode != mode)
+    {
+        mState.cullMode = mode;
+        mCullStateDirty = true;
+    }
+}
+
+void Context::setFrontFace(GLenum front)
+{
+    if (mState.frontFace != front)
+    {
+        mState.frontFace = front;
+        mFrontFaceDirty = true;
+    }
+}
+
+void Context::setDepthTest(bool enabled)
+{
+    if (mState.depthTest != enabled)
+    {
+        mState.depthTest = enabled;
+        mDepthStateDirty = true;
+    }
+}
+
+bool Context::isDepthTestEnabled() const
+{
+    return mState.depthTest;
+}
+
+void Context::setDepthFunc(GLenum depthFunc)
+{
+    if (mState.depthFunc != depthFunc)
+    {
+        mState.depthFunc = depthFunc;
+        mDepthStateDirty = true;
+    }
+}
+
+void Context::setDepthRange(float zNear, float zFar)
+{
+    mState.zNear = zNear;
+    mState.zFar = zFar;
+}
+
+void Context::setBlend(bool enabled)
+{
+    if (mState.blend != enabled)
+    {
+        mState.blend = enabled;
+        mBlendStateDirty = true;
+    }
+}
+
+bool Context::isBlendEnabled() const
+{
+    return mState.blend;
+}
+
+void Context::setBlendFactors(GLenum sourceRGB, GLenum destRGB, GLenum sourceAlpha, GLenum destAlpha)
+{
+    if (mState.sourceBlendRGB != sourceRGB ||
+        mState.sourceBlendAlpha != sourceAlpha ||
+        mState.destBlendRGB != destRGB ||
+        mState.destBlendAlpha != destAlpha)
+    {
+        mState.sourceBlendRGB = sourceRGB;
+        mState.destBlendRGB = destRGB;
+        mState.sourceBlendAlpha = sourceAlpha;
+        mState.destBlendAlpha = destAlpha;
+        mBlendStateDirty = true;
+    }
+}
+
+void Context::setBlendColor(float red, float green, float blue, float alpha)
+{
+    if (mState.blendColor.red != red ||
+        mState.blendColor.green != green ||
+        mState.blendColor.blue != blue ||
+        mState.blendColor.alpha != alpha)
+    {
+        mState.blendColor.red = red;
+        mState.blendColor.green = green;
+        mState.blendColor.blue = blue;
+        mState.blendColor.alpha = alpha;
+        mBlendStateDirty = true;
+    }
+}
+
+void Context::setBlendEquation(GLenum rgbEquation, GLenum alphaEquation)
+{
+    if (mState.blendEquationRGB != rgbEquation ||
+        mState.blendEquationAlpha != alphaEquation)
+    {
+        mState.blendEquationRGB = rgbEquation;
+        mState.blendEquationAlpha = alphaEquation;
+        mBlendStateDirty = true;
+    }
+}
+
+void Context::setStencilTest(bool enabled)
+{
+    if (mState.stencilTest != enabled)
+    {
+        mState.stencilTest = enabled;
+        mStencilStateDirty = true;
+    }
+}
+
+bool Context::isStencilTestEnabled() const
+{
+    return mState.stencilTest;
+}
+
+void Context::setStencilParams(GLenum stencilFunc, GLint stencilRef, GLuint stencilMask)
+{
+    if (mState.stencilFunc != stencilFunc ||
+        mState.stencilRef != stencilRef ||
+        mState.stencilMask != stencilMask)
+    {
+        mState.stencilFunc = stencilFunc;
+        mState.stencilRef = (stencilRef > 0) ? stencilRef : 0;
+        mState.stencilMask = stencilMask;
+        mStencilStateDirty = true;
+    }
+}
+
+void Context::setStencilBackParams(GLenum stencilBackFunc, GLint stencilBackRef, GLuint stencilBackMask)
+{
+    if (mState.stencilBackFunc != stencilBackFunc ||
+        mState.stencilBackRef != stencilBackRef ||
+        mState.stencilBackMask != stencilBackMask)
+    {
+        mState.stencilBackFunc = stencilBackFunc;
+        mState.stencilBackRef = (stencilBackRef > 0) ? stencilBackRef : 0;
+        mState.stencilBackMask = stencilBackMask;
+        mStencilStateDirty = true;
+    }
+}
+
+void Context::setStencilWritemask(GLuint stencilWritemask)
+{
+    if (mState.stencilWritemask != stencilWritemask)
+    {
+        mState.stencilWritemask = stencilWritemask;
+        mStencilStateDirty = true;
+    }
+}
+
+void Context::setStencilBackWritemask(GLuint stencilBackWritemask)
+{
+    if (mState.stencilBackWritemask != stencilBackWritemask)
+    {
+        mState.stencilBackWritemask = stencilBackWritemask;
+        mStencilStateDirty = true;
+    }
+}
+
+void Context::setStencilOperations(GLenum stencilFail, GLenum stencilPassDepthFail, GLenum stencilPassDepthPass)
+{
+    if (mState.stencilFail != stencilFail ||
+        mState.stencilPassDepthFail != stencilPassDepthFail ||
+        mState.stencilPassDepthPass != stencilPassDepthPass)
+    {
+        mState.stencilFail = stencilFail;
+        mState.stencilPassDepthFail = stencilPassDepthFail;
+        mState.stencilPassDepthPass = stencilPassDepthPass;
+        mStencilStateDirty = true;
+    }
+}
+
+void Context::setStencilBackOperations(GLenum stencilBackFail, GLenum stencilBackPassDepthFail, GLenum stencilBackPassDepthPass)
+{
+    if (mState.stencilBackFail != stencilBackFail ||
+        mState.stencilBackPassDepthFail != stencilBackPassDepthFail ||
+        mState.stencilBackPassDepthPass != stencilBackPassDepthPass)
+    {
+        mState.stencilBackFail = stencilBackFail;
+        mState.stencilBackPassDepthFail = stencilBackPassDepthFail;
+        mState.stencilBackPassDepthPass = stencilBackPassDepthPass;
+        mStencilStateDirty = true;
+    }
+}
+
+void Context::setPolygonOffsetFill(bool enabled)
+{
+    if (mState.polygonOffsetFill != enabled)
+    {
+        mState.polygonOffsetFill = enabled;
+        mPolygonOffsetStateDirty = true;
+    }
+}
+
+bool Context::isPolygonOffsetFillEnabled() const
+{
+    return mState.polygonOffsetFill;
+
+}
+
+void Context::setPolygonOffsetParams(GLfloat factor, GLfloat units)
+{
+    if (mState.polygonOffsetFactor != factor ||
+        mState.polygonOffsetUnits != units)
+    {
+        mState.polygonOffsetFactor = factor;
+        mState.polygonOffsetUnits = units;
+        mPolygonOffsetStateDirty = true;
+    }
+}
+
+void Context::setSampleAlphaToCoverage(bool enabled)
+{
+    if (mState.sampleAlphaToCoverage != enabled)
+    {
+        mState.sampleAlphaToCoverage = enabled;
+        mSampleStateDirty = true;
+    }
+}
+
+bool Context::isSampleAlphaToCoverageEnabled() const
+{
+    return mState.sampleAlphaToCoverage;
+}
+
+void Context::setSampleCoverage(bool enabled)
+{
+    if (mState.sampleCoverage != enabled)
+    {
+        mState.sampleCoverage = enabled;
+        mSampleStateDirty = true;
+    }
+}
+
+bool Context::isSampleCoverageEnabled() const
+{
+    return mState.sampleCoverage;
+}
+
+void Context::setSampleCoverageParams(GLclampf value, bool invert)
+{
+    if (mState.sampleCoverageValue != value ||
+        mState.sampleCoverageInvert != invert)
+    {
+        mState.sampleCoverageValue = value;
+        mState.sampleCoverageInvert = invert;
+        mSampleStateDirty = true;
+    }
+}
+
+void Context::setScissorTest(bool enabled)
+{
+    if (mState.scissorTest != enabled)
+    {
+        mState.scissorTest = enabled;
+        mScissorStateDirty = true;
+    }
+}
+
+bool Context::isScissorTestEnabled() const
+{
+    return mState.scissorTest;
+}
+
+void Context::setDither(bool enabled)
+{
+    if (mState.dither != enabled)
+    {
+        mState.dither = enabled;
+        mDitherStateDirty = true;
+    }
+}
+
+bool Context::isDitherEnabled() const
+{
+    return mState.dither;
+}
+
+void Context::setLineWidth(GLfloat width)
+{
+    mState.lineWidth = width;
+}
+
+void Context::setGenerateMipmapHint(GLenum hint)
+{
+    mState.generateMipmapHint = hint;
+}
+
+void Context::setFragmentShaderDerivativeHint(GLenum hint)
+{
+    mState.fragmentShaderDerivativeHint = hint;
+    // TODO: Propagate the hint to shader translator so we can write
+    // ddx, ddx_coarse, or ddx_fine depending on the hint.
+    // Ignore for now. It is valid for implementations to ignore hint.
+}
+
+void Context::setViewportParams(GLint x, GLint y, GLsizei width, GLsizei height)
+{
+    mState.viewportX = x;
+    mState.viewportY = y;
+    mState.viewportWidth = width;
+    mState.viewportHeight = height;
+}
+
+void Context::setScissorParams(GLint x, GLint y, GLsizei width, GLsizei height)
+{
+    if (mState.scissorX != x || mState.scissorY != y || 
+        mState.scissorWidth != width || mState.scissorHeight != height)
+    {
+        mState.scissorX = x;
+        mState.scissorY = y;
+        mState.scissorWidth = width;
+        mState.scissorHeight = height;
+        mScissorStateDirty = true;
+    }
+}
+
+void Context::setColorMask(bool red, bool green, bool blue, bool alpha)
+{
+    if (mState.colorMaskRed != red || mState.colorMaskGreen != green ||
+        mState.colorMaskBlue != blue || mState.colorMaskAlpha != alpha)
+    {
+        mState.colorMaskRed = red;
+        mState.colorMaskGreen = green;
+        mState.colorMaskBlue = blue;
+        mState.colorMaskAlpha = alpha;
+        mMaskStateDirty = true;
+    }
+}
+
+void Context::setDepthMask(bool mask)
+{
+    if (mState.depthMask != mask)
+    {
+        mState.depthMask = mask;
+        mMaskStateDirty = true;
+    }
+}
+
+void Context::setActiveSampler(unsigned int active)
+{
+    mState.activeSampler = active;
+}
+
+GLuint Context::getReadFramebufferHandle() const
+{
+    return mState.readFramebuffer;
+}
+
+GLuint Context::getDrawFramebufferHandle() const
+{
+    return mState.drawFramebuffer;
+}
+
+GLuint Context::getRenderbufferHandle() const
+{
+    return mState.renderbuffer.id();
+}
+
+GLuint Context::getArrayBufferHandle() const
+{
+    return mState.arrayBuffer.id();
+}
+
+GLuint Context::getActiveQuery(GLenum target) const
+{
+    Query *queryObject = NULL;
+    
+    switch (target)
+    {
+      case GL_ANY_SAMPLES_PASSED_EXT:
+        queryObject = mState.activeQuery[QUERY_ANY_SAMPLES_PASSED].get();
+        break;
+      case GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT:
+        queryObject = mState.activeQuery[QUERY_ANY_SAMPLES_PASSED_CONSERVATIVE].get();
+        break;
+      default:
+        ASSERT(false);
+    }
+
+    if (queryObject)
+    {
+        return queryObject->id();
+    }
+    else
+    {
+        return 0;
+    }
+}
+
+void Context::setEnableVertexAttribArray(unsigned int attribNum, bool enabled)
+{
+    mState.vertexAttribute[attribNum].mArrayEnabled = enabled;
+}
+
+const VertexAttribute &Context::getVertexAttribState(unsigned int attribNum)
+{
+    return mState.vertexAttribute[attribNum];
+}
+
+void Context::setVertexAttribState(unsigned int attribNum, Buffer *boundBuffer, GLint size, GLenum type, bool normalized,
+                                   GLsizei stride, const void *pointer)
+{
+    mState.vertexAttribute[attribNum].mBoundBuffer.set(boundBuffer);
+    mState.vertexAttribute[attribNum].mSize = size;
+    mState.vertexAttribute[attribNum].mType = type;
+    mState.vertexAttribute[attribNum].mNormalized = normalized;
+    mState.vertexAttribute[attribNum].mStride = stride;
+    mState.vertexAttribute[attribNum].mPointer = pointer;
+}
+
+const void *Context::getVertexAttribPointer(unsigned int attribNum) const
+{
+    return mState.vertexAttribute[attribNum].mPointer;
+}
+
+const VertexAttributeArray &Context::getVertexAttributes()
+{
+    return mState.vertexAttribute;
+}
+
+void Context::setPackAlignment(GLint alignment)
+{
+    mState.packAlignment = alignment;
+}
+
+GLint Context::getPackAlignment() const
+{
+    return mState.packAlignment;
+}
+
+void Context::setUnpackAlignment(GLint alignment)
+{
+    mState.unpackAlignment = alignment;
+}
+
+GLint Context::getUnpackAlignment() const
+{
+    return mState.unpackAlignment;
+}
+
+void Context::setPackReverseRowOrder(bool reverseRowOrder)
+{
+    mState.packReverseRowOrder = reverseRowOrder;
+}
+
+bool Context::getPackReverseRowOrder() const
+{
+    return mState.packReverseRowOrder;
+}
+
+GLuint Context::createBuffer()
+{
+    return mResourceManager->createBuffer();
+}
+
+GLuint Context::createProgram()
+{
+    return mResourceManager->createProgram();
+}
+
+GLuint Context::createShader(GLenum type)
+{
+    return mResourceManager->createShader(type);
+}
+
+GLuint Context::createTexture()
+{
+    return mResourceManager->createTexture();
+}
+
+GLuint Context::createRenderbuffer()
+{
+    return mResourceManager->createRenderbuffer();
+}
+
+// Returns an unused framebuffer name
+GLuint Context::createFramebuffer()
+{
+    GLuint handle = mFramebufferHandleAllocator.allocate();
+
+    mFramebufferMap[handle] = NULL;
+
+    return handle;
+}
+
+GLuint Context::createFence()
+{
+    GLuint handle = mFenceHandleAllocator.allocate();
+
+    mFenceMap[handle] = new Fence(mDisplay);
+
+    return handle;
+}
+
+// Returns an unused query name
+GLuint Context::createQuery()
+{
+    GLuint handle = mQueryHandleAllocator.allocate();
+
+    mQueryMap[handle] = NULL;
+
+    return handle;
+}
+
+void Context::deleteBuffer(GLuint buffer)
+{
+    if (mResourceManager->getBuffer(buffer))
+    {
+        detachBuffer(buffer);
+    }
+    
+    mResourceManager->deleteBuffer(buffer);
+}
+
+void Context::deleteShader(GLuint shader)
+{
+    mResourceManager->deleteShader(shader);
+}
+
+void Context::deleteProgram(GLuint program)
+{
+    mResourceManager->deleteProgram(program);
+}
+
+void Context::deleteTexture(GLuint texture)
+{
+    if (mResourceManager->getTexture(texture))
+    {
+        detachTexture(texture);
+    }
+
+    mResourceManager->deleteTexture(texture);
+}
+
+void Context::deleteRenderbuffer(GLuint renderbuffer)
+{
+    if (mResourceManager->getRenderbuffer(renderbuffer))
+    {
+        detachRenderbuffer(renderbuffer);
+    }
+    
+    mResourceManager->deleteRenderbuffer(renderbuffer);
+}
+
+void Context::deleteFramebuffer(GLuint framebuffer)
+{
+    FramebufferMap::iterator framebufferObject = mFramebufferMap.find(framebuffer);
+
+    if (framebufferObject != mFramebufferMap.end())
+    {
+        detachFramebuffer(framebuffer);
+
+        mFramebufferHandleAllocator.release(framebufferObject->first);
+        delete framebufferObject->second;
+        mFramebufferMap.erase(framebufferObject);
+    }
+}
+
+void Context::deleteFence(GLuint fence)
+{
+    FenceMap::iterator fenceObject = mFenceMap.find(fence);
+
+    if (fenceObject != mFenceMap.end())
+    {
+        mFenceHandleAllocator.release(fenceObject->first);
+        delete fenceObject->second;
+        mFenceMap.erase(fenceObject);
+    }
+}
+
+void Context::deleteQuery(GLuint query)
+{
+    QueryMap::iterator queryObject = mQueryMap.find(query);
+    if (queryObject != mQueryMap.end())
+    {
+        mQueryHandleAllocator.release(queryObject->first);
+        if (queryObject->second)
+        {
+            queryObject->second->release();
+        }
+        mQueryMap.erase(queryObject);
+    }
+}
+
+Buffer *Context::getBuffer(GLuint handle)
+{
+    return mResourceManager->getBuffer(handle);
+}
+
+Shader *Context::getShader(GLuint handle)
+{
+    return mResourceManager->getShader(handle);
+}
+
+Program *Context::getProgram(GLuint handle)
+{
+    return mResourceManager->getProgram(handle);
+}
+
+Texture *Context::getTexture(GLuint handle)
+{
+    return mResourceManager->getTexture(handle);
+}
+
+Renderbuffer *Context::getRenderbuffer(GLuint handle)
+{
+    return mResourceManager->getRenderbuffer(handle);
+}
+
+Framebuffer *Context::getReadFramebuffer()
+{
+    return getFramebuffer(mState.readFramebuffer);
+}
+
+Framebuffer *Context::getDrawFramebuffer()
+{
+    return mBoundDrawFramebuffer;
+}
+
+void Context::bindArrayBuffer(unsigned int buffer)
+{
+    mResourceManager->checkBufferAllocation(buffer);
+
+    mState.arrayBuffer.set(getBuffer(buffer));
+}
+
+void Context::bindElementArrayBuffer(unsigned int buffer)
+{
+    mResourceManager->checkBufferAllocation(buffer);
+
+    mState.elementArrayBuffer.set(getBuffer(buffer));
+}
+
+void Context::bindTexture2D(GLuint texture)
+{
+    mResourceManager->checkTextureAllocation(texture, TEXTURE_2D);
+
+    mState.samplerTexture[TEXTURE_2D][mState.activeSampler].set(getTexture(texture));
+}
+
+void Context::bindTextureCubeMap(GLuint texture)
+{
+    mResourceManager->checkTextureAllocation(texture, TEXTURE_CUBE);
+
+    mState.samplerTexture[TEXTURE_CUBE][mState.activeSampler].set(getTexture(texture));
+}
+
+void Context::bindReadFramebuffer(GLuint framebuffer)
+{
+    if (!getFramebuffer(framebuffer))
+    {
+        mFramebufferMap[framebuffer] = new Framebuffer();
+    }
+
+    mState.readFramebuffer = framebuffer;
+}
+
+void Context::bindDrawFramebuffer(GLuint framebuffer)
+{
+    if (!getFramebuffer(framebuffer))
+    {
+        mFramebufferMap[framebuffer] = new Framebuffer();
+    }
+
+    mState.drawFramebuffer = framebuffer;
+
+    mBoundDrawFramebuffer = getFramebuffer(framebuffer);
+}
+
+void Context::bindRenderbuffer(GLuint renderbuffer)
+{
+    mResourceManager->checkRenderbufferAllocation(renderbuffer);
+
+    mState.renderbuffer.set(getRenderbuffer(renderbuffer));
+}
+
+void Context::useProgram(GLuint program)
+{
+    GLuint priorProgram = mState.currentProgram;
+    mState.currentProgram = program;               // Must switch before trying to delete, otherwise it only gets flagged.
+
+    if (priorProgram != program)
+    {
+        Program *newProgram = mResourceManager->getProgram(program);
+        Program *oldProgram = mResourceManager->getProgram(priorProgram);
+        mCurrentProgramBinary.set(NULL);
+        mDxUniformsDirty = true;
+
+        if (newProgram)
+        {
+            newProgram->addRef();
+            mCurrentProgramBinary.set(newProgram->getProgramBinary());
+        }
+        
+        if (oldProgram)
+        {
+            oldProgram->release();
+        }
+    }
+}
+
+void Context::linkProgram(GLuint program)
+{
+    Program *programObject = mResourceManager->getProgram(program);
+
+    bool linked = programObject->link();
+
+    // if the current program was relinked successfully we
+    // need to install the new executables
+    if (linked && program == mState.currentProgram)
+    {
+        mCurrentProgramBinary.set(programObject->getProgramBinary());
+        mDxUniformsDirty = true;
+    }
+}
+
+void Context::setProgramBinary(GLuint program, const void *binary, GLint length)
+{
+    Program *programObject = mResourceManager->getProgram(program);
+
+    bool loaded = programObject->setProgramBinary(binary, length);
+
+    // if the current program was reloaded successfully we
+    // need to install the new executables
+    if (loaded && program == mState.currentProgram)
+    {
+        mCurrentProgramBinary.set(programObject->getProgramBinary());
+        mDxUniformsDirty = true;
+    }
+
+}
+
+void Context::beginQuery(GLenum target, GLuint query)
+{
+    // From EXT_occlusion_query_boolean: If BeginQueryEXT is called with an <id>  
+    // of zero, if the active query object name for <target> is non-zero (for the  
+    // targets ANY_SAMPLES_PASSED_EXT and ANY_SAMPLES_PASSED_CONSERVATIVE_EXT, if  
+    // the active query for either target is non-zero), if <id> is the name of an 
+    // existing query object whose type does not match <target>, or if <id> is the
+    // active query object name for any query type, the error INVALID_OPERATION is
+    // generated.
+
+    // Ensure no other queries are active
+    // NOTE: If other queries than occlusion are supported, we will need to check
+    // separately that:
+    //    a) The query ID passed is not the current active query for any target/type
+    //    b) There are no active queries for the requested target (and in the case
+    //       of GL_ANY_SAMPLES_PASSED_EXT and GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT,
+    //       no query may be active for either if glBeginQuery targets either.
+    for (int i = 0; i < QUERY_TYPE_COUNT; i++)
+    {
+        if (mState.activeQuery[i].get() != NULL)
+        {
+            return error(GL_INVALID_OPERATION);
+        }
+    }
+
+    QueryType qType;
+    switch (target)
+    {
+      case GL_ANY_SAMPLES_PASSED_EXT: 
+        qType = QUERY_ANY_SAMPLES_PASSED; 
+        break;
+      case GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT: 
+        qType = QUERY_ANY_SAMPLES_PASSED_CONSERVATIVE; 
+        break;
+      default: 
+        ASSERT(false);
+        return;
+    }
+
+    Query *queryObject = getQuery(query, true, target);
+
+    // check that name was obtained with glGenQueries
+    if (!queryObject)
+    {
+        return error(GL_INVALID_OPERATION);
+    }
+
+    // check for type mismatch
+    if (queryObject->getType() != target)
+    {
+        return error(GL_INVALID_OPERATION);
+    }
+
+    // set query as active for specified target
+    mState.activeQuery[qType].set(queryObject);
+
+    // begin query
+    queryObject->begin();
+}
+
+void Context::endQuery(GLenum target)
+{
+    QueryType qType;
+
+    switch (target)
+    {
+      case GL_ANY_SAMPLES_PASSED_EXT: 
+        qType = QUERY_ANY_SAMPLES_PASSED; 
+        break;
+      case GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT: 
+        qType = QUERY_ANY_SAMPLES_PASSED_CONSERVATIVE; 
+        break;
+      default: 
+        ASSERT(false);
+        return;
+    }
+
+    Query *queryObject = mState.activeQuery[qType].get();
+
+    if (queryObject == NULL)
+    {
+        return error(GL_INVALID_OPERATION);
+    }
+
+    queryObject->end();
+
+    mState.activeQuery[qType].set(NULL);
+}
+
+void Context::setFramebufferZero(Framebuffer *buffer)
+{
+    delete mFramebufferMap[0];
+    mFramebufferMap[0] = buffer;
+    if (mState.drawFramebuffer == 0)
+    {
+        mBoundDrawFramebuffer = buffer;
+    }
+}
+
+void Context::setRenderbufferStorage(RenderbufferStorage *renderbuffer)
+{
+    Renderbuffer *renderbufferObject = mState.renderbuffer.get();
+    renderbufferObject->setStorage(renderbuffer);
+}
+
+Framebuffer *Context::getFramebuffer(unsigned int handle)
+{
+    FramebufferMap::iterator framebuffer = mFramebufferMap.find(handle);
+
+    if (framebuffer == mFramebufferMap.end())
+    {
+        return NULL;
+    }
+    else
+    {
+        return framebuffer->second;
+    }
+}
+
+Fence *Context::getFence(unsigned int handle)
+{
+    FenceMap::iterator fence = mFenceMap.find(handle);
+
+    if (fence == mFenceMap.end())
+    {
+        return NULL;
+    }
+    else
+    {
+        return fence->second;
+    }
+}
+
+Query *Context::getQuery(unsigned int handle, bool create, GLenum type)
+{
+    QueryMap::iterator query = mQueryMap.find(handle);
+
+    if (query == mQueryMap.end())
+    {
+        return NULL;
+    }
+    else
+    {
+        if (!query->second && create)
+        {
+            query->second = new Query(handle, type);
+            query->second->addRef();
+        }
+        return query->second;
+    }
+}
+
+Buffer *Context::getArrayBuffer()
+{
+    return mState.arrayBuffer.get();
+}
+
+Buffer *Context::getElementArrayBuffer()
+{
+    return mState.elementArrayBuffer.get();
+}
+
+ProgramBinary *Context::getCurrentProgramBinary()
+{
+    return mCurrentProgramBinary.get();
+}
+
+Texture2D *Context::getTexture2D()
+{
+    return static_cast<Texture2D*>(getSamplerTexture(mState.activeSampler, TEXTURE_2D));
+}
+
+TextureCubeMap *Context::getTextureCubeMap()
+{
+    return static_cast<TextureCubeMap*>(getSamplerTexture(mState.activeSampler, TEXTURE_CUBE));
+}
+
+Texture *Context::getSamplerTexture(unsigned int sampler, TextureType type)
+{
+    GLuint texid = mState.samplerTexture[type][sampler].id();
+
+    if (texid == 0)   // Special case: 0 refers to different initial textures based on the target
+    {
+        switch (type)
+        {
+          default: UNREACHABLE();
+          case TEXTURE_2D: return mTexture2DZero.get();
+          case TEXTURE_CUBE: return mTextureCubeMapZero.get();
+        }
+    }
+
+    return mState.samplerTexture[type][sampler].get();
+}
+
+bool Context::getBooleanv(GLenum pname, GLboolean *params)
+{
+    switch (pname)
+    {
+      case GL_SHADER_COMPILER:           *params = GL_TRUE;                            break;
+      case GL_SAMPLE_COVERAGE_INVERT:    *params = mState.sampleCoverageInvert;        break;
+      case GL_DEPTH_WRITEMASK:           *params = mState.depthMask;                   break;
+      case GL_COLOR_WRITEMASK:
+        params[0] = mState.colorMaskRed;
+        params[1] = mState.colorMaskGreen;
+        params[2] = mState.colorMaskBlue;
+        params[3] = mState.colorMaskAlpha;
+        break;
+      case GL_CULL_FACE:                 *params = mState.cullFace;                    break;
+      case GL_POLYGON_OFFSET_FILL:       *params = mState.polygonOffsetFill;           break;
+      case GL_SAMPLE_ALPHA_TO_COVERAGE:  *params = mState.sampleAlphaToCoverage;       break;
+      case GL_SAMPLE_COVERAGE:           *params = mState.sampleCoverage;              break;
+      case GL_SCISSOR_TEST:              *params = mState.scissorTest;                 break;
+      case GL_STENCIL_TEST:              *params = mState.stencilTest;                 break;
+      case GL_DEPTH_TEST:                *params = mState.depthTest;                   break;
+      case GL_BLEND:                     *params = mState.blend;                       break;
+      case GL_DITHER:                    *params = mState.dither;                      break;
+      case GL_CONTEXT_ROBUST_ACCESS_EXT: *params = mRobustAccess ? GL_TRUE : GL_FALSE; break;
+      default:
+        return false;
+    }
+
+    return true;
+}
+
+bool Context::getFloatv(GLenum pname, GLfloat *params)
+{
+    // Please note: DEPTH_CLEAR_VALUE is included in our internal getFloatv implementation
+    // because it is stored as a float, despite the fact that the GL ES 2.0 spec names
+    // GetIntegerv as its native query function. As it would require conversion in any
+    // case, this should make no difference to the calling application.
+    switch (pname)
+    {
+      case GL_LINE_WIDTH:               *params = mState.lineWidth;            break;
+      case GL_SAMPLE_COVERAGE_VALUE:    *params = mState.sampleCoverageValue;  break;
+      case GL_DEPTH_CLEAR_VALUE:        *params = mState.depthClearValue;      break;
+      case GL_POLYGON_OFFSET_FACTOR:    *params = mState.polygonOffsetFactor;  break;
+      case GL_POLYGON_OFFSET_UNITS:     *params = mState.polygonOffsetUnits;   break;
+      case GL_ALIASED_LINE_WIDTH_RANGE:
+        params[0] = gl::ALIASED_LINE_WIDTH_RANGE_MIN;
+        params[1] = gl::ALIASED_LINE_WIDTH_RANGE_MAX;
+        break;
+      case GL_ALIASED_POINT_SIZE_RANGE:
+        params[0] = gl::ALIASED_POINT_SIZE_RANGE_MIN;
+        params[1] = getMaximumPointSize();
+        break;
+      case GL_DEPTH_RANGE:
+        params[0] = mState.zNear;
+        params[1] = mState.zFar;
+        break;
+      case GL_COLOR_CLEAR_VALUE:
+        params[0] = mState.colorClearValue.red;
+        params[1] = mState.colorClearValue.green;
+        params[2] = mState.colorClearValue.blue;
+        params[3] = mState.colorClearValue.alpha;
+        break;
+      case GL_BLEND_COLOR:
+        params[0] = mState.blendColor.red;
+        params[1] = mState.blendColor.green;
+        params[2] = mState.blendColor.blue;
+        params[3] = mState.blendColor.alpha;
+        break;
+      case GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT:
+        if (!supportsTextureFilterAnisotropy())
+        {
+            return false;
+        }
+        *params = mMaxTextureAnisotropy;
+        break;
+      default:
+        return false;
+    }
+
+    return true;
+}
+
+bool Context::getIntegerv(GLenum pname, GLint *params)
+{
+    // Please note: DEPTH_CLEAR_VALUE is not included in our internal getIntegerv implementation
+    // because it is stored as a float, despite the fact that the GL ES 2.0 spec names
+    // GetIntegerv as its native query function. As it would require conversion in any
+    // case, this should make no difference to the calling application. You may find it in 
+    // Context::getFloatv.
+    switch (pname)
+    {
+      case GL_MAX_VERTEX_ATTRIBS:               *params = gl::MAX_VERTEX_ATTRIBS;               break;
+      case GL_MAX_VERTEX_UNIFORM_VECTORS:       *params = gl::MAX_VERTEX_UNIFORM_VECTORS;       break;
+      case GL_MAX_VARYING_VECTORS:              *params = getMaximumVaryingVectors();           break;
+      case GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS: *params = getMaximumCombinedTextureImageUnits(); break;
+      case GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS:   *params = getMaximumVertexTextureImageUnits();  break;
+      case GL_MAX_TEXTURE_IMAGE_UNITS:          *params = gl::MAX_TEXTURE_IMAGE_UNITS;          break;
+      case GL_MAX_FRAGMENT_UNIFORM_VECTORS:     *params = getMaximumFragmentUniformVectors();   break;
+      case GL_MAX_RENDERBUFFER_SIZE:            *params = getMaximumRenderbufferDimension();    break;
+      case GL_NUM_SHADER_BINARY_FORMATS:        *params = 0;                                    break;
+      case GL_SHADER_BINARY_FORMATS:      /* no shader binary formats are supported */          break;
+      case GL_ARRAY_BUFFER_BINDING:             *params = mState.arrayBuffer.id();              break;
+      case GL_ELEMENT_ARRAY_BUFFER_BINDING:     *params = mState.elementArrayBuffer.id();       break;
+      //case GL_FRAMEBUFFER_BINDING:            // now equivalent to GL_DRAW_FRAMEBUFFER_BINDING_ANGLE
+      case GL_DRAW_FRAMEBUFFER_BINDING_ANGLE:   *params = mState.drawFramebuffer;               break;
+      case GL_READ_FRAMEBUFFER_BINDING_ANGLE:   *params = mState.readFramebuffer;               break;
+      case GL_RENDERBUFFER_BINDING:             *params = mState.renderbuffer.id();             break;
+      case GL_CURRENT_PROGRAM:                  *params = mState.currentProgram;                break;
+      case GL_PACK_ALIGNMENT:                   *params = mState.packAlignment;                 break;
+      case GL_PACK_REVERSE_ROW_ORDER_ANGLE:     *params = mState.packReverseRowOrder;           break;
+      case GL_UNPACK_ALIGNMENT:                 *params = mState.unpackAlignment;               break;
+      case GL_GENERATE_MIPMAP_HINT:             *params = mState.generateMipmapHint;            break;
+      case GL_FRAGMENT_SHADER_DERIVATIVE_HINT_OES: *params = mState.fragmentShaderDerivativeHint; break;
+      case GL_ACTIVE_TEXTURE:                   *params = (mState.activeSampler + GL_TEXTURE0); break;
+      case GL_STENCIL_FUNC:                     *params = mState.stencilFunc;                   break;
+      case GL_STENCIL_REF:                      *params = mState.stencilRef;                    break;
+      case GL_STENCIL_VALUE_MASK:               *params = mState.stencilMask;                   break;
+      case GL_STENCIL_BACK_FUNC:                *params = mState.stencilBackFunc;               break;
+      case GL_STENCIL_BACK_REF:                 *params = mState.stencilBackRef;                break;
+      case GL_STENCIL_BACK_VALUE_MASK:          *params = mState.stencilBackMask;               break;
+      case GL_STENCIL_FAIL:                     *params = mState.stencilFail;                   break;
+      case GL_STENCIL_PASS_DEPTH_FAIL:          *params = mState.stencilPassDepthFail;          break;
+      case GL_STENCIL_PASS_DEPTH_PASS:          *params = mState.stencilPassDepthPass;          break;
+      case GL_STENCIL_BACK_FAIL:                *params = mState.stencilBackFail;               break;
+      case GL_STENCIL_BACK_PASS_DEPTH_FAIL:     *params = mState.stencilBackPassDepthFail;      break;
+      case GL_STENCIL_BACK_PASS_DEPTH_PASS:     *params = mState.stencilBackPassDepthPass;      break;
+      case GL_DEPTH_FUNC:                       *params = mState.depthFunc;                     break;
+      case GL_BLEND_SRC_RGB:                    *params = mState.sourceBlendRGB;                break;
+      case GL_BLEND_SRC_ALPHA:                  *params = mState.sourceBlendAlpha;              break;
+      case GL_BLEND_DST_RGB:                    *params = mState.destBlendRGB;                  break;
+      case GL_BLEND_DST_ALPHA:                  *params = mState.destBlendAlpha;                break;
+      case GL_BLEND_EQUATION_RGB:               *params = mState.blendEquationRGB;              break;
+      case GL_BLEND_EQUATION_ALPHA:             *params = mState.blendEquationAlpha;            break;
+      case GL_STENCIL_WRITEMASK:                *params = mState.stencilWritemask;              break;
+      case GL_STENCIL_BACK_WRITEMASK:           *params = mState.stencilBackWritemask;          break;
+      case GL_STENCIL_CLEAR_VALUE:              *params = mState.stencilClearValue;             break;
+      case GL_SUBPIXEL_BITS:                    *params = 4;                                    break;
+      case GL_MAX_TEXTURE_SIZE:                 *params = getMaximumTextureDimension();         break;
+      case GL_MAX_CUBE_MAP_TEXTURE_SIZE:        *params = getMaximumCubeTextureDimension();     break;
+      case GL_NUM_COMPRESSED_TEXTURE_FORMATS:   
+        params[0] = mNumCompressedTextureFormats;
+        break;
+      case GL_MAX_SAMPLES_ANGLE:
+        {
+            GLsizei maxSamples = getMaxSupportedSamples();
+            if (maxSamples != 0)
+            {
+                *params = maxSamples;
+            }
+            else
+            {
+                return false;
+            }
+
+            break;
+        }
+      case GL_SAMPLE_BUFFERS:                   
+      case GL_SAMPLES:
+        {
+            gl::Framebuffer *framebuffer = getDrawFramebuffer();
+            if (framebuffer->completeness() == GL_FRAMEBUFFER_COMPLETE)
+            {
+                switch (pname)
+                {
+                  case GL_SAMPLE_BUFFERS:
+                    if (framebuffer->getSamples() != 0)
+                    {
+                        *params = 1;
+                    }
+                    else
+                    {
+                        *params = 0;
+                    }
+                    break;
+                  case GL_SAMPLES:
+                    *params = framebuffer->getSamples();
+                    break;
+                }
+            }
+            else 
+            {
+                *params = 0;
+            }
+        }
+        break;
+      case GL_IMPLEMENTATION_COLOR_READ_TYPE:
+      case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
+        {
+            GLenum format, type;
+            if (getCurrentReadFormatType(&format, &type))
+            {
+                if (pname == GL_IMPLEMENTATION_COLOR_READ_FORMAT)
+                    *params = format;
+                else
+                    *params = type;
+            }
+        }
+        break;
+      case GL_MAX_VIEWPORT_DIMS:
+        {
+            int maxDimension = std::max(getMaximumRenderbufferDimension(), getMaximumTextureDimension());
+            params[0] = maxDimension;
+            params[1] = maxDimension;
+        }
+        break;
+      case GL_COMPRESSED_TEXTURE_FORMATS:
+        {
+            if (supportsDXT1Textures())
+            {
+                *params++ = GL_COMPRESSED_RGB_S3TC_DXT1_EXT;
+                *params++ = GL_COMPRESSED_RGBA_S3TC_DXT1_EXT;
+            }
+            if (supportsDXT3Textures())
+            {
+                *params++ = GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE;
+            }
+            if (supportsDXT5Textures())
+            {
+                *params++ = GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE;
+            }
+        }
+        break;
+      case GL_VIEWPORT:
+        params[0] = mState.viewportX;
+        params[1] = mState.viewportY;
+        params[2] = mState.viewportWidth;
+        params[3] = mState.viewportHeight;
+        break;
+      case GL_SCISSOR_BOX:
+        params[0] = mState.scissorX;
+        params[1] = mState.scissorY;
+        params[2] = mState.scissorWidth;
+        params[3] = mState.scissorHeight;
+        break;
+      case GL_CULL_FACE_MODE:                   *params = mState.cullMode;                 break;
+      case GL_FRONT_FACE:                       *params = mState.frontFace;                break;
+      case GL_RED_BITS:
+      case GL_GREEN_BITS:
+      case GL_BLUE_BITS:
+      case GL_ALPHA_BITS:
+        {
+            gl::Framebuffer *framebuffer = getDrawFramebuffer();
+            gl::Renderbuffer *colorbuffer = framebuffer->getColorbuffer();
+
+            if (colorbuffer)
+            {
+                switch (pname)
+                {
+                  case GL_RED_BITS:   *params = colorbuffer->getRedSize();   break;
+                  case GL_GREEN_BITS: *params = colorbuffer->getGreenSize(); break;
+                  case GL_BLUE_BITS:  *params = colorbuffer->getBlueSize();  break;
+                  case GL_ALPHA_BITS: *params = colorbuffer->getAlphaSize(); break;
+                }
+            }
+            else
+            {
+                *params = 0;
+            }
+        }
+        break;
+      case GL_DEPTH_BITS:
+        {
+            gl::Framebuffer *framebuffer = getDrawFramebuffer();
+            gl::Renderbuffer *depthbuffer = framebuffer->getDepthbuffer();
+
+            if (depthbuffer)
+            {
+                *params = depthbuffer->getDepthSize();
+            }
+            else
+            {
+                *params = 0;
+            }
+        }
+        break;
+      case GL_STENCIL_BITS:
+        {
+            gl::Framebuffer *framebuffer = getDrawFramebuffer();
+            gl::Renderbuffer *stencilbuffer = framebuffer->getStencilbuffer();
+
+            if (stencilbuffer)
+            {
+                *params = stencilbuffer->getStencilSize();
+            }
+            else
+            {
+                *params = 0;
+            }
+        }
+        break;
+      case GL_TEXTURE_BINDING_2D:
+        {
+            if (mState.activeSampler < 0 || mState.activeSampler > getMaximumCombinedTextureImageUnits() - 1)
+            {
+                error(GL_INVALID_OPERATION);
+                return false;
+            }
+
+            *params = mState.samplerTexture[TEXTURE_2D][mState.activeSampler].id();
+        }
+        break;
+      case GL_TEXTURE_BINDING_CUBE_MAP:
+        {
+            if (mState.activeSampler < 0 || mState.activeSampler > getMaximumCombinedTextureImageUnits() - 1)
+            {
+                error(GL_INVALID_OPERATION);
+                return false;
+            }
+
+            *params = mState.samplerTexture[TEXTURE_CUBE][mState.activeSampler].id();
+        }
+        break;
+      case GL_RESET_NOTIFICATION_STRATEGY_EXT:
+        *params = mResetStrategy;
+        break;
+      case GL_NUM_PROGRAM_BINARY_FORMATS_OES:
+        *params = 1;
+        break;
+      case GL_PROGRAM_BINARY_FORMATS_OES:
+        *params = GL_PROGRAM_BINARY_ANGLE;
+        break;
+      default:
+        return false;
+    }
+
+    return true;
+}
+
+bool Context::getQueryParameterInfo(GLenum pname, GLenum *type, unsigned int *numParams)
+{
+    // Please note: the query type returned for DEPTH_CLEAR_VALUE in this implementation
+    // is FLOAT rather than INT, as would be suggested by the GL ES 2.0 spec. This is due
+    // to the fact that it is stored internally as a float, and so would require conversion
+    // if returned from Context::getIntegerv. Since this conversion is already implemented 
+    // in the case that one calls glGetIntegerv to retrieve a float-typed state variable, we
+    // place DEPTH_CLEAR_VALUE with the floats. This should make no difference to the calling
+    // application.
+    switch (pname)
+    {
+      case GL_COMPRESSED_TEXTURE_FORMATS:
+        {
+            *type = GL_INT;
+            *numParams = mNumCompressedTextureFormats;
+        }
+        break;
+      case GL_SHADER_BINARY_FORMATS:
+        {
+            *type = GL_INT;
+            *numParams = 0;
+        }
+        break;
+      case GL_MAX_VERTEX_ATTRIBS:
+      case GL_MAX_VERTEX_UNIFORM_VECTORS:
+      case GL_MAX_VARYING_VECTORS:
+      case GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS:
+      case GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS:
+      case GL_MAX_TEXTURE_IMAGE_UNITS:
+      case GL_MAX_FRAGMENT_UNIFORM_VECTORS:
+      case GL_MAX_RENDERBUFFER_SIZE:
+      case GL_NUM_SHADER_BINARY_FORMATS:
+      case GL_NUM_COMPRESSED_TEXTURE_FORMATS:
+      case GL_ARRAY_BUFFER_BINDING:
+      case GL_FRAMEBUFFER_BINDING:
+      case GL_RENDERBUFFER_BINDING:
+      case GL_CURRENT_PROGRAM:
+      case GL_PACK_ALIGNMENT:
+      case GL_PACK_REVERSE_ROW_ORDER_ANGLE:
+      case GL_UNPACK_ALIGNMENT:
+      case GL_GENERATE_MIPMAP_HINT:
+      case GL_FRAGMENT_SHADER_DERIVATIVE_HINT_OES:
+      case GL_RED_BITS:
+      case GL_GREEN_BITS:
+      case GL_BLUE_BITS:
+      case GL_ALPHA_BITS:
+      case GL_DEPTH_BITS:
+      case GL_STENCIL_BITS:
+      case GL_ELEMENT_ARRAY_BUFFER_BINDING:
+      case GL_CULL_FACE_MODE:
+      case GL_FRONT_FACE:
+      case GL_ACTIVE_TEXTURE:
+      case GL_STENCIL_FUNC:
+      case GL_STENCIL_VALUE_MASK:
+      case GL_STENCIL_REF:
+      case GL_STENCIL_FAIL:
+      case GL_STENCIL_PASS_DEPTH_FAIL:
+      case GL_STENCIL_PASS_DEPTH_PASS:
+      case GL_STENCIL_BACK_FUNC:
+      case GL_STENCIL_BACK_VALUE_MASK:
+      case GL_STENCIL_BACK_REF:
+      case GL_STENCIL_BACK_FAIL:
+      case GL_STENCIL_BACK_PASS_DEPTH_FAIL:
+      case GL_STENCIL_BACK_PASS_DEPTH_PASS:
+      case GL_DEPTH_FUNC:
+      case GL_BLEND_SRC_RGB:
+      case GL_BLEND_SRC_ALPHA:
+      case GL_BLEND_DST_RGB:
+      case GL_BLEND_DST_ALPHA:
+      case GL_BLEND_EQUATION_RGB:
+      case GL_BLEND_EQUATION_ALPHA:
+      case GL_STENCIL_WRITEMASK:
+      case GL_STENCIL_BACK_WRITEMASK:
+      case GL_STENCIL_CLEAR_VALUE:
+      case GL_SUBPIXEL_BITS:
+      case GL_MAX_TEXTURE_SIZE:
+      case GL_MAX_CUBE_MAP_TEXTURE_SIZE:
+      case GL_SAMPLE_BUFFERS:
+      case GL_SAMPLES:
+      case GL_IMPLEMENTATION_COLOR_READ_TYPE:
+      case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
+      case GL_TEXTURE_BINDING_2D:
+      case GL_TEXTURE_BINDING_CUBE_MAP:
+      case GL_RESET_NOTIFICATION_STRATEGY_EXT:
+      case GL_NUM_PROGRAM_BINARY_FORMATS_OES:
+      case GL_PROGRAM_BINARY_FORMATS_OES:
+        {
+            *type = GL_INT;
+            *numParams = 1;
+        }
+        break;
+      case GL_MAX_SAMPLES_ANGLE:
+        {
+            if (getMaxSupportedSamples() != 0)
+            {
+                *type = GL_INT;
+                *numParams = 1;
+            }
+            else
+            {
+                return false;
+            }
+        }
+        break;
+      case GL_MAX_VIEWPORT_DIMS:
+        {
+            *type = GL_INT;
+            *numParams = 2;
+        }
+        break;
+      case GL_VIEWPORT:
+      case GL_SCISSOR_BOX:
+        {
+            *type = GL_INT;
+            *numParams = 4;
+        }
+        break;
+      case GL_SHADER_COMPILER:
+      case GL_SAMPLE_COVERAGE_INVERT:
+      case GL_DEPTH_WRITEMASK:
+      case GL_CULL_FACE:                // CULL_FACE through DITHER are natural to IsEnabled,
+      case GL_POLYGON_OFFSET_FILL:      // but can be retrieved through the Get{Type}v queries.
+      case GL_SAMPLE_ALPHA_TO_COVERAGE: // For this purpose, they are treated here as bool-natural
+      case GL_SAMPLE_COVERAGE:
+      case GL_SCISSOR_TEST:
+      case GL_STENCIL_TEST:
+      case GL_DEPTH_TEST:
+      case GL_BLEND:
+      case GL_DITHER:
+      case GL_CONTEXT_ROBUST_ACCESS_EXT:
+        {
+            *type = GL_BOOL;
+            *numParams = 1;
+        }
+        break;
+      case GL_COLOR_WRITEMASK:
+        {
+            *type = GL_BOOL;
+            *numParams = 4;
+        }
+        break;
+      case GL_POLYGON_OFFSET_FACTOR:
+      case GL_POLYGON_OFFSET_UNITS:
+      case GL_SAMPLE_COVERAGE_VALUE:
+      case GL_DEPTH_CLEAR_VALUE:
+      case GL_LINE_WIDTH:
+        {
+            *type = GL_FLOAT;
+            *numParams = 1;
+        }
+        break;
+      case GL_ALIASED_LINE_WIDTH_RANGE:
+      case GL_ALIASED_POINT_SIZE_RANGE:
+      case GL_DEPTH_RANGE:
+        {
+            *type = GL_FLOAT;
+            *numParams = 2;
+        }
+        break;
+      case GL_COLOR_CLEAR_VALUE:
+      case GL_BLEND_COLOR:
+        {
+            *type = GL_FLOAT;
+            *numParams = 4;
+        }
+        break;
+      case GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT:
+        if (!supportsTextureFilterAnisotropy())
+        {
+            return false;
+        }
+        *type = GL_FLOAT;
+        *numParams = 1;
+        break;
+      default:
+        return false;
+    }
+
+    return true;
+}
+
+// Applies the render target surface, depth stencil surface, viewport rectangle and
+// scissor rectangle to the Direct3D 9 device
+bool Context::applyRenderTarget(bool ignoreViewport)
+{
+    Framebuffer *framebufferObject = getDrawFramebuffer();
+
+    if (!framebufferObject || framebufferObject->completeness() != GL_FRAMEBUFFER_COMPLETE)
+    {
+        return error(GL_INVALID_FRAMEBUFFER_OPERATION, false);
+    }
+
+    // if there is no color attachment we must synthesize a NULL colorattachment
+    // to keep the D3D runtime happy.  This should only be possible if depth texturing.
+    Renderbuffer *renderbufferObject = NULL;
+    if (framebufferObject->getColorbufferType() != GL_NONE)
+    {
+        renderbufferObject = framebufferObject->getColorbuffer();
+    }
+    else
+    {
+        renderbufferObject = framebufferObject->getNullColorbuffer();
+    }
+    if (!renderbufferObject)
+    {
+        ERR("unable to locate renderbuffer for FBO.");
+        return false;
+    }
+
+    bool renderTargetChanged = false;
+    unsigned int renderTargetSerial = renderbufferObject->getSerial();
+    if (renderTargetSerial != mAppliedRenderTargetSerial)
+    {
+        IDirect3DSurface9 *renderTarget = renderbufferObject->getRenderTarget();
+        if (!renderTarget)
+        {
+            ERR("render target pointer unexpectedly null.");
+            return false;   // Context must be lost
+        }
+        mDevice->SetRenderTarget(0, renderTarget);
+        mAppliedRenderTargetSerial = renderTargetSerial;
+        mScissorStateDirty = true; // Scissor area must be clamped to render target's size-- this is different for different render targets.
+        renderTargetChanged = true;
+        renderTarget->Release();
+    }
+
+    IDirect3DSurface9 *depthStencil = NULL;
+    unsigned int depthbufferSerial = 0;
+    unsigned int stencilbufferSerial = 0;
+    if (framebufferObject->getDepthbufferType() != GL_NONE)
+    {
+        Renderbuffer *depthbuffer = framebufferObject->getDepthbuffer();
+        depthStencil = depthbuffer->getDepthStencil();
+        if (!depthStencil)
+        {
+            ERR("Depth stencil pointer unexpectedly null.");
+            return false;
+        }
+        
+        depthbufferSerial = depthbuffer->getSerial();
+    }
+    else if (framebufferObject->getStencilbufferType() != GL_NONE)
+    {
+        Renderbuffer *stencilbuffer = framebufferObject->getStencilbuffer();
+        depthStencil = stencilbuffer->getDepthStencil();
+        if (!depthStencil)
+        {
+            ERR("Depth stencil pointer unexpectedly null.");
+            return false;
+        }
+        
+        stencilbufferSerial = stencilbuffer->getSerial();
+    }
+
+    if (depthbufferSerial != mAppliedDepthbufferSerial ||
+        stencilbufferSerial != mAppliedStencilbufferSerial ||
+        !mDepthStencilInitialized)
+    {
+        mDevice->SetDepthStencilSurface(depthStencil);
+        mAppliedDepthbufferSerial = depthbufferSerial;
+        mAppliedStencilbufferSerial = stencilbufferSerial;
+        mDepthStencilInitialized = true;
+    }
+
+    if (depthStencil)
+    {
+        depthStencil->Release();
+    }
+
+    if (!mRenderTargetDescInitialized || renderTargetChanged)
+    {
+        IDirect3DSurface9 *renderTarget = renderbufferObject->getRenderTarget();
+        if (!renderTarget)
+        {
+            return false;   // Context must be lost
+        }
+        renderTarget->GetDesc(&mRenderTargetDesc);
+        mRenderTargetDescInitialized = true;
+        renderTarget->Release();
+    }
+
+    D3DVIEWPORT9 viewport;
+
+    float zNear = clamp01(mState.zNear);
+    float zFar = clamp01(mState.zFar);
+
+    if (ignoreViewport)
+    {
+        viewport.X = 0;
+        viewport.Y = 0;
+        viewport.Width = mRenderTargetDesc.Width;
+        viewport.Height = mRenderTargetDesc.Height;
+        viewport.MinZ = 0.0f;
+        viewport.MaxZ = 1.0f;
+    }
+    else
+    {
+        viewport.X = clamp(mState.viewportX, 0L, static_cast<LONG>(mRenderTargetDesc.Width));
+        viewport.Y = clamp(mState.viewportY, 0L, static_cast<LONG>(mRenderTargetDesc.Height));
+        viewport.Width = clamp(mState.viewportWidth, 0L, static_cast<LONG>(mRenderTargetDesc.Width) - static_cast<LONG>(viewport.X));
+        viewport.Height = clamp(mState.viewportHeight, 0L, static_cast<LONG>(mRenderTargetDesc.Height) - static_cast<LONG>(viewport.Y));
+        viewport.MinZ = zNear;
+        viewport.MaxZ = zFar;
+    }
+
+    if (viewport.Width <= 0 || viewport.Height <= 0)
+    {
+        return false;   // Nothing to render
+    }
+
+    if (renderTargetChanged || !mViewportInitialized || memcmp(&viewport, &mSetViewport, sizeof mSetViewport) != 0)
+    {
+        mDevice->SetViewport(&viewport);
+        mSetViewport = viewport;
+        mViewportInitialized = true;
+        mDxUniformsDirty = true;
+    }
+
+    if (mScissorStateDirty)
+    {
+        if (mState.scissorTest)
+        {
+            RECT rect;
+            rect.left = clamp(mState.scissorX, 0L, static_cast<LONG>(mRenderTargetDesc.Width));
+            rect.top = clamp(mState.scissorY, 0L, static_cast<LONG>(mRenderTargetDesc.Height));
+            rect.right = clamp(mState.scissorX + mState.scissorWidth, 0L, static_cast<LONG>(mRenderTargetDesc.Width));
+            rect.bottom = clamp(mState.scissorY + mState.scissorHeight, 0L, static_cast<LONG>(mRenderTargetDesc.Height));
+            mDevice->SetScissorRect(&rect);
+            mDevice->SetRenderState(D3DRS_SCISSORTESTENABLE, TRUE);
+        }
+        else
+        {
+            mDevice->SetRenderState(D3DRS_SCISSORTESTENABLE, FALSE);
+        }
+
+        mScissorStateDirty = false;
+    }
+
+    if (mState.currentProgram && mDxUniformsDirty)
+    {
+        ProgramBinary *programBinary = getCurrentProgramBinary();
+
+        GLint halfPixelSize = programBinary->getDxHalfPixelSizeLocation();
+        GLfloat xy[2] = {1.0f / viewport.Width, -1.0f / viewport.Height};
+        programBinary->setUniform2fv(halfPixelSize, 1, xy);
+
+        // These values are used for computing gl_FragCoord in Program::linkVaryings().
+        GLint coord = programBinary->getDxCoordLocation();
+        GLfloat whxy[4] = {mState.viewportWidth / 2.0f, mState.viewportHeight / 2.0f, 
+                          (float)mState.viewportX + mState.viewportWidth / 2.0f, 
+                          (float)mState.viewportY + mState.viewportHeight / 2.0f};
+        programBinary->setUniform4fv(coord, 1, whxy);
+
+        GLint depth = programBinary->getDxDepthLocation();
+        GLfloat dz[2] = {(zFar - zNear) / 2.0f, (zNear + zFar) / 2.0f};
+        programBinary->setUniform2fv(depth, 1, dz);
+
+        GLint depthRange = programBinary->getDxDepthRangeLocation();
+        GLfloat nearFarDiff[3] = {zNear, zFar, zFar - zNear};
+        programBinary->setUniform3fv(depthRange, 1, nearFarDiff);
+        mDxUniformsDirty = false;
+    }
+
+    return true;
+}
+
+// Applies the fixed-function state (culling, depth test, alpha blending, stenciling, etc) to the Direct3D 9 device
+void Context::applyState(GLenum drawMode)
+{
+    ProgramBinary *programBinary = getCurrentProgramBinary();
+
+    Framebuffer *framebufferObject = getDrawFramebuffer();
+
+    GLint frontCCW = programBinary->getDxFrontCCWLocation();
+    GLint ccw = (mState.frontFace == GL_CCW);
+    programBinary->setUniform1iv(frontCCW, 1, &ccw);
+
+    GLint pointsOrLines = programBinary->getDxPointsOrLinesLocation();
+    GLint alwaysFront = !isTriangleMode(drawMode);
+    programBinary->setUniform1iv(pointsOrLines, 1, &alwaysFront);
+
+    D3DADAPTER_IDENTIFIER9 *identifier = mDisplay->getAdapterIdentifier();
+    bool zeroColorMaskAllowed = identifier->VendorId != 0x1002;
+    // Apparently some ATI cards have a bug where a draw with a zero color
+    // write mask can cause later draws to have incorrect results. Instead,
+    // set a nonzero color write mask but modify the blend state so that no
+    // drawing is done.
+    // http://code.google.com/p/angleproject/issues/detail?id=169
+
+    if (mCullStateDirty || mFrontFaceDirty)
+    {
+        if (mState.cullFace)
+        {
+            mDevice->SetRenderState(D3DRS_CULLMODE, es2dx::ConvertCullMode(mState.cullMode, mState.frontFace));
+        }
+        else
+        {
+            mDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
+        }
+
+        mCullStateDirty = false;
+    }
+
+    if (mDepthStateDirty)
+    {
+        if (mState.depthTest)
+        {
+            mDevice->SetRenderState(D3DRS_ZENABLE, D3DZB_TRUE);
+            mDevice->SetRenderState(D3DRS_ZFUNC, es2dx::ConvertComparison(mState.depthFunc));
+        }
+        else
+        {
+            mDevice->SetRenderState(D3DRS_ZENABLE, D3DZB_FALSE);
+        }
+
+        mDepthStateDirty = false;
+    }
+
+    if (!zeroColorMaskAllowed && (mMaskStateDirty || mBlendStateDirty))
+    {
+        mBlendStateDirty = true;
+        mMaskStateDirty = true;
+    }
+
+    if (mBlendStateDirty)
+    {
+        if (mState.blend)
+        {
+            mDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
+
+            if (mState.sourceBlendRGB != GL_CONSTANT_ALPHA && mState.sourceBlendRGB != GL_ONE_MINUS_CONSTANT_ALPHA &&
+                mState.destBlendRGB != GL_CONSTANT_ALPHA && mState.destBlendRGB != GL_ONE_MINUS_CONSTANT_ALPHA)
+            {
+                mDevice->SetRenderState(D3DRS_BLENDFACTOR, es2dx::ConvertColor(mState.blendColor));
+            }
+            else
+            {
+                mDevice->SetRenderState(D3DRS_BLENDFACTOR, D3DCOLOR_RGBA(unorm<8>(mState.blendColor.alpha),
+                                                                        unorm<8>(mState.blendColor.alpha),
+                                                                        unorm<8>(mState.blendColor.alpha),
+                                                                        unorm<8>(mState.blendColor.alpha)));
+            }
+
+            mDevice->SetRenderState(D3DRS_SRCBLEND, es2dx::ConvertBlendFunc(mState.sourceBlendRGB));
+            mDevice->SetRenderState(D3DRS_DESTBLEND, es2dx::ConvertBlendFunc(mState.destBlendRGB));
+            mDevice->SetRenderState(D3DRS_BLENDOP, es2dx::ConvertBlendOp(mState.blendEquationRGB));
+
+            if (mState.sourceBlendRGB != mState.sourceBlendAlpha || 
+                mState.destBlendRGB != mState.destBlendAlpha || 
+                mState.blendEquationRGB != mState.blendEquationAlpha)
+            {
+                mDevice->SetRenderState(D3DRS_SEPARATEALPHABLENDENABLE, TRUE);
+
+                mDevice->SetRenderState(D3DRS_SRCBLENDALPHA, es2dx::ConvertBlendFunc(mState.sourceBlendAlpha));
+                mDevice->SetRenderState(D3DRS_DESTBLENDALPHA, es2dx::ConvertBlendFunc(mState.destBlendAlpha));
+                mDevice->SetRenderState(D3DRS_BLENDOPALPHA, es2dx::ConvertBlendOp(mState.blendEquationAlpha));
+            }
+            else
+            {
+                mDevice->SetRenderState(D3DRS_SEPARATEALPHABLENDENABLE, FALSE);
+            }
+        }
+        else
+        {
+            mDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
+        }
+
+        mBlendStateDirty = false;
+    }
+
+    if (mStencilStateDirty || mFrontFaceDirty)
+    {
+        if (mState.stencilTest && framebufferObject->hasStencil())
+        {
+            mDevice->SetRenderState(D3DRS_STENCILENABLE, TRUE);
+            mDevice->SetRenderState(D3DRS_TWOSIDEDSTENCILMODE, TRUE);
+
+            // FIXME: Unsupported by D3D9
+            const D3DRENDERSTATETYPE D3DRS_CCW_STENCILREF = D3DRS_STENCILREF;
+            const D3DRENDERSTATETYPE D3DRS_CCW_STENCILMASK = D3DRS_STENCILMASK;
+            const D3DRENDERSTATETYPE D3DRS_CCW_STENCILWRITEMASK = D3DRS_STENCILWRITEMASK;
+            if (mState.stencilWritemask != mState.stencilBackWritemask || 
+                mState.stencilRef != mState.stencilBackRef || 
+                mState.stencilMask != mState.stencilBackMask)
+            {
+                ERR("Separate front/back stencil writemasks, reference values, or stencil mask values are invalid under WebGL.");
+                return error(GL_INVALID_OPERATION);
+            }
+
+            // get the maximum size of the stencil ref
+            gl::Renderbuffer *stencilbuffer = framebufferObject->getStencilbuffer();
+            GLuint maxStencil = (1 << stencilbuffer->getStencilSize()) - 1;
+
+            mDevice->SetRenderState(mState.frontFace == GL_CCW ? D3DRS_STENCILWRITEMASK : D3DRS_CCW_STENCILWRITEMASK, mState.stencilWritemask);
+            mDevice->SetRenderState(mState.frontFace == GL_CCW ? D3DRS_STENCILFUNC : D3DRS_CCW_STENCILFUNC, 
+                                   es2dx::ConvertComparison(mState.stencilFunc));
+
+            mDevice->SetRenderState(mState.frontFace == GL_CCW ? D3DRS_STENCILREF : D3DRS_CCW_STENCILREF, (mState.stencilRef < (GLint)maxStencil) ? mState.stencilRef : maxStencil);
+            mDevice->SetRenderState(mState.frontFace == GL_CCW ? D3DRS_STENCILMASK : D3DRS_CCW_STENCILMASK, mState.stencilMask);
+
+            mDevice->SetRenderState(mState.frontFace == GL_CCW ? D3DRS_STENCILFAIL : D3DRS_CCW_STENCILFAIL, 
+                                   es2dx::ConvertStencilOp(mState.stencilFail));
+            mDevice->SetRenderState(mState.frontFace == GL_CCW ? D3DRS_STENCILZFAIL : D3DRS_CCW_STENCILZFAIL, 
+                                   es2dx::ConvertStencilOp(mState.stencilPassDepthFail));
+            mDevice->SetRenderState(mState.frontFace == GL_CCW ? D3DRS_STENCILPASS : D3DRS_CCW_STENCILPASS, 
+                                   es2dx::ConvertStencilOp(mState.stencilPassDepthPass));
+
+            mDevice->SetRenderState(mState.frontFace == GL_CW ? D3DRS_STENCILWRITEMASK : D3DRS_CCW_STENCILWRITEMASK, mState.stencilBackWritemask);
+            mDevice->SetRenderState(mState.frontFace == GL_CW ? D3DRS_STENCILFUNC : D3DRS_CCW_STENCILFUNC, 
+                                   es2dx::ConvertComparison(mState.stencilBackFunc));
+
+            mDevice->SetRenderState(mState.frontFace == GL_CW ? D3DRS_STENCILREF : D3DRS_CCW_STENCILREF, (mState.stencilBackRef < (GLint)maxStencil) ? mState.stencilBackRef : maxStencil);
+            mDevice->SetRenderState(mState.frontFace == GL_CW ? D3DRS_STENCILMASK : D3DRS_CCW_STENCILMASK, mState.stencilBackMask);
+
+            mDevice->SetRenderState(mState.frontFace == GL_CW ? D3DRS_STENCILFAIL : D3DRS_CCW_STENCILFAIL, 
+                                   es2dx::ConvertStencilOp(mState.stencilBackFail));
+            mDevice->SetRenderState(mState.frontFace == GL_CW ? D3DRS_STENCILZFAIL : D3DRS_CCW_STENCILZFAIL, 
+                                   es2dx::ConvertStencilOp(mState.stencilBackPassDepthFail));
+            mDevice->SetRenderState(mState.frontFace == GL_CW ? D3DRS_STENCILPASS : D3DRS_CCW_STENCILPASS, 
+                                   es2dx::ConvertStencilOp(mState.stencilBackPassDepthPass));
+        }
+        else
+        {
+            mDevice->SetRenderState(D3DRS_STENCILENABLE, FALSE);
+        }
+
+        mStencilStateDirty = false;
+        mFrontFaceDirty = false;
+    }
+
+    if (mMaskStateDirty)
+    {
+        int colorMask = es2dx::ConvertColorMask(mState.colorMaskRed, mState.colorMaskGreen, 
+                                                mState.colorMaskBlue, mState.colorMaskAlpha);
+        if (colorMask == 0 && !zeroColorMaskAllowed)
+        {
+            // Enable green channel, but set blending so nothing will be drawn.
+            mDevice->SetRenderState(D3DRS_COLORWRITEENABLE, D3DCOLORWRITEENABLE_GREEN);
+            mDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
+
+            mDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ZERO);
+            mDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ONE);
+            mDevice->SetRenderState(D3DRS_BLENDOP, D3DBLENDOP_ADD);
+        }
+        else
+        {
+            mDevice->SetRenderState(D3DRS_COLORWRITEENABLE, colorMask);
+        }
+        mDevice->SetRenderState(D3DRS_ZWRITEENABLE, mState.depthMask ? TRUE : FALSE);
+
+        mMaskStateDirty = false;
+    }
+
+    if (mPolygonOffsetStateDirty)
+    {
+        if (mState.polygonOffsetFill)
+        {
+            gl::Renderbuffer *depthbuffer = framebufferObject->getDepthbuffer();
+            if (depthbuffer)
+            {
+                mDevice->SetRenderState(D3DRS_SLOPESCALEDEPTHBIAS, *((DWORD*)&mState.polygonOffsetFactor));
+                float depthBias = ldexp(mState.polygonOffsetUnits, -(int)(depthbuffer->getDepthSize()));
+                mDevice->SetRenderState(D3DRS_DEPTHBIAS, *((DWORD*)&depthBias));
+            }
+        }
+        else
+        {
+            mDevice->SetRenderState(D3DRS_SLOPESCALEDEPTHBIAS, 0);
+            mDevice->SetRenderState(D3DRS_DEPTHBIAS, 0);
+        }
+
+        mPolygonOffsetStateDirty = false;
+    }
+
+    if (mSampleStateDirty)
+    {
+        if (mState.sampleAlphaToCoverage)
+        {
+            FIXME("Sample alpha to coverage is unimplemented.");
+        }
+
+        mDevice->SetRenderState(D3DRS_MULTISAMPLEANTIALIAS, TRUE);
+        if (mState.sampleCoverage)
+        {
+            unsigned int mask = 0;
+            if (mState.sampleCoverageValue != 0)
+            {
+                float threshold = 0.5f;
+
+                for (int i = 0; i < framebufferObject->getSamples(); ++i)
+                {
+                    mask <<= 1;
+
+                    if ((i + 1) * mState.sampleCoverageValue >= threshold)
+                    {
+                        threshold += 1.0f;
+                        mask |= 1;
+                    }
+                }
+            }
+            
+            if (mState.sampleCoverageInvert)
+            {
+                mask = ~mask;
+            }
+
+            mDevice->SetRenderState(D3DRS_MULTISAMPLEMASK, mask);
+        }
+        else
+        {
+            mDevice->SetRenderState(D3DRS_MULTISAMPLEMASK, 0xFFFFFFFF);
+        }
+
+        mSampleStateDirty = false;
+    }
+
+    if (mDitherStateDirty)
+    {
+        mDevice->SetRenderState(D3DRS_DITHERENABLE, mState.dither ? TRUE : FALSE);
+
+        mDitherStateDirty = false;
+    }
+}
+
+GLenum Context::applyVertexBuffer(GLint first, GLsizei count, GLsizei instances, GLsizei *repeatDraw)
+{
+    TranslatedAttribute attributes[MAX_VERTEX_ATTRIBS];
+
+    GLenum err = mVertexDataManager->prepareVertexData(first, count, attributes, instances);
+    if (err != GL_NO_ERROR)
+    {
+        return err;
+    }
+
+    ProgramBinary *programBinary = getCurrentProgramBinary();
+    return mVertexDeclarationCache.applyDeclaration(mDevice, attributes, programBinary, instances, repeatDraw);
+}
+
+// Applies the indices and element array bindings to the Direct3D 9 device
+GLenum Context::applyIndexBuffer(const GLvoid *indices, GLsizei count, GLenum mode, GLenum type, TranslatedIndexData *indexInfo)
+{
+    GLenum err = mIndexDataManager->prepareIndexData(type, count, mState.elementArrayBuffer.get(), indices, indexInfo);
+
+    if (err == GL_NO_ERROR)
+    {
+        if (indexInfo->serial != mAppliedIBSerial)
+        {
+            mDevice->SetIndices(indexInfo->indexBuffer);
+            mAppliedIBSerial = indexInfo->serial;
+        }
+    }
+
+    return err;
+}
+
+// Applies the shaders and shader constants to the Direct3D 9 device
+void Context::applyShaders()
+{
+    ProgramBinary *programBinary = getCurrentProgramBinary();
+
+    if (programBinary->getSerial() != mAppliedProgramBinarySerial)
+    {
+        IDirect3DVertexShader9 *vertexShader = programBinary->getVertexShader();
+        IDirect3DPixelShader9 *pixelShader = programBinary->getPixelShader();
+
+        mDevice->SetPixelShader(pixelShader);
+        mDevice->SetVertexShader(vertexShader);
+        programBinary->dirtyAllUniforms();
+        mAppliedProgramBinarySerial = programBinary->getSerial();
+    }
+
+    programBinary->applyUniforms();
+}
+
+// Applies the textures and sampler states to the Direct3D 9 device
+void Context::applyTextures()
+{
+    applyTextures(SAMPLER_PIXEL);
+
+    if (mSupportsVertexTexture)
+    {
+        applyTextures(SAMPLER_VERTEX);
+    }
+}
+
+// For each Direct3D 9 sampler of either the pixel or vertex stage,
+// looks up the corresponding OpenGL texture image unit and texture type,
+// and sets the texture and its addressing/filtering state (or NULL when inactive).
+void Context::applyTextures(SamplerType type)
+{
+    ProgramBinary *programBinary = getCurrentProgramBinary();
+
+    int samplerCount = (type == SAMPLER_PIXEL) ? MAX_TEXTURE_IMAGE_UNITS : MAX_VERTEX_TEXTURE_IMAGE_UNITS_VTF;   // Range of Direct3D 9 samplers of given sampler type
+    unsigned int *appliedTextureSerial = (type == SAMPLER_PIXEL) ? mAppliedTextureSerialPS : mAppliedTextureSerialVS;
+    int d3dSamplerOffset = (type == SAMPLER_PIXEL) ? 0 : D3DVERTEXTEXTURESAMPLER0;
+    int samplerRange = programBinary->getUsedSamplerRange(type);
+
+    for (int samplerIndex = 0; samplerIndex < samplerRange; samplerIndex++)
+    {
+        int textureUnit = programBinary->getSamplerMapping(type, samplerIndex);   // OpenGL texture image unit index
+        int d3dSampler = samplerIndex + d3dSamplerOffset;
+
+        if (textureUnit != -1)
+        {
+            TextureType textureType = programBinary->getSamplerTextureType(type, samplerIndex);
+
+            Texture *texture = getSamplerTexture(textureUnit, textureType);
+            unsigned int texSerial = texture->getTextureSerial();
+
+            if (appliedTextureSerial[samplerIndex] != texSerial || texture->hasDirtyParameters() || texture->hasDirtyImages())
+            {
+                IDirect3DBaseTexture9 *d3dTexture = texture->getTexture();
+
+                if (d3dTexture)
+                {
+                    if (appliedTextureSerial[samplerIndex] != texSerial || texture->hasDirtyParameters())
+                    {
+                        GLenum wrapS = texture->getWrapS();
+                        GLenum wrapT = texture->getWrapT();
+                        GLenum minFilter = texture->getMinFilter();
+                        GLenum magFilter = texture->getMagFilter();
+                        float maxAnisotropy = texture->getMaxAnisotropy();
+
+                        mDevice->SetSamplerState(d3dSampler, D3DSAMP_ADDRESSU, es2dx::ConvertTextureWrap(wrapS));
+                        mDevice->SetSamplerState(d3dSampler, D3DSAMP_ADDRESSV, es2dx::ConvertTextureWrap(wrapT));
+
+                        mDevice->SetSamplerState(d3dSampler, D3DSAMP_MAGFILTER, es2dx::ConvertMagFilter(magFilter, maxAnisotropy));
+                        D3DTEXTUREFILTERTYPE d3dMinFilter, d3dMipFilter;
+                        es2dx::ConvertMinFilter(minFilter, &d3dMinFilter, &d3dMipFilter, maxAnisotropy);
+                        mDevice->SetSamplerState(d3dSampler, D3DSAMP_MINFILTER, d3dMinFilter);
+                        mDevice->SetSamplerState(d3dSampler, D3DSAMP_MIPFILTER, d3dMipFilter);
+                        mDevice->SetSamplerState(d3dSampler, D3DSAMP_MAXMIPLEVEL, texture->getLodOffset());
+
+                        if (supportsTextureFilterAnisotropy())
+                        {
+                            mDevice->SetSamplerState(d3dSampler, D3DSAMP_MAXANISOTROPY, (DWORD)maxAnisotropy);
+                        }
+                    }
+
+                    if (appliedTextureSerial[samplerIndex] != texSerial || texture->hasDirtyImages())
+                    {
+                        mDevice->SetTexture(d3dSampler, d3dTexture);
+                    }
+                }
+                else
+                {
+                    mDevice->SetTexture(d3dSampler, getIncompleteTexture(textureType)->getTexture());
+                }
+
+                appliedTextureSerial[samplerIndex] = texSerial;
+                texture->resetDirty();
+            }
+        }
+        else
+        {
+            if (appliedTextureSerial[samplerIndex] != 0)
+            {
+                mDevice->SetTexture(d3dSampler, NULL);
+                appliedTextureSerial[samplerIndex] = 0;
+            }
+        }
+    }
+
+    for (int samplerIndex = samplerRange; samplerIndex < samplerCount; samplerIndex++)
+    {
+        if (appliedTextureSerial[samplerIndex] != 0)
+        {
+            mDevice->SetTexture(samplerIndex + d3dSamplerOffset, NULL);
+            appliedTextureSerial[samplerIndex] = 0;
+        }
+    }
+}
+
+void Context::readPixels(GLint x, GLint y, GLsizei width, GLsizei height,
+                         GLenum format, GLenum type, GLsizei *bufSize, void* pixels)
+{
+    Framebuffer *framebuffer = getReadFramebuffer();
+
+    if (framebuffer->completeness() != GL_FRAMEBUFFER_COMPLETE)
+    {
+        return error(GL_INVALID_FRAMEBUFFER_OPERATION);
+    }
+
+    if (getReadFramebufferHandle() != 0 && framebuffer->getSamples() != 0)
+    {
+        return error(GL_INVALID_OPERATION);
+    }
+
+    GLsizei outputPitch = ComputePitch(width, ConvertSizedInternalFormat(format, type), mState.packAlignment);
+    // sized query sanity check
+    if (bufSize)
+    {
+        int requiredSize = outputPitch * height;
+        if (requiredSize > *bufSize)
+        {
+            return error(GL_INVALID_OPERATION);
+        }
+    }
+
+    IDirect3DSurface9 *renderTarget = framebuffer->getRenderTarget();
+    if (!renderTarget)
+    {
+        return;   // Context must be lost, return silently
+    }
+
+    D3DSURFACE_DESC desc;
+    renderTarget->GetDesc(&desc);
+
+    if (desc.MultiSampleType != D3DMULTISAMPLE_NONE)
+    {
+        UNIMPLEMENTED();   // FIXME: Requires resolve using StretchRect into non-multisampled render target
+        renderTarget->Release();
+        return error(GL_OUT_OF_MEMORY);
+    }
+
+    HRESULT result;
+    IDirect3DSurface9 *systemSurface = NULL;
+    bool directToPixels = !getPackReverseRowOrder() && getPackAlignment() <= 4 && mDisplay->isD3d9ExDevice() &&
+                          x == 0 && y == 0 && UINT(width) == desc.Width && UINT(height) == desc.Height &&
+                          desc.Format == D3DFMT_A8R8G8B8 && format == GL_BGRA_EXT && type == GL_UNSIGNED_BYTE;
+    if (directToPixels)
+    {
+        // Use the pixels ptr as a shared handle to write directly into client's memory
+        result = mDevice->CreateOffscreenPlainSurface(desc.Width, desc.Height, desc.Format,
+                                                      D3DPOOL_SYSTEMMEM, &systemSurface, &pixels);
+        if (FAILED(result))
+        {
+            // Try again without the shared handle
+            directToPixels = false;
+        }
+    }
+
+    if (!directToPixels)
+    {
+        result = mDevice->CreateOffscreenPlainSurface(desc.Width, desc.Height, desc.Format,
+                                                      D3DPOOL_SYSTEMMEM, &systemSurface, NULL);
+        if (FAILED(result))
+        {
+            ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
+            renderTarget->Release();
+            return error(GL_OUT_OF_MEMORY);
+        }
+    }
+
+    result = mDevice->GetRenderTargetData(renderTarget, systemSurface);
+    renderTarget->Release();
+    renderTarget = NULL;
+
+    if (FAILED(result))
+    {
+        systemSurface->Release();
+
+        // It turns out that D3D will sometimes produce more error
+        // codes than those documented.
+        if (checkDeviceLost(result))
+            return error(GL_OUT_OF_MEMORY);
+        else
+        {
+            UNREACHABLE();
+            return;
+        }
+
+    }
+
+    if (directToPixels)
+    {
+        systemSurface->Release();
+        return;
+    }
+
+    RECT rect;
+    rect.left = clamp(x, 0L, static_cast<LONG>(desc.Width));
+    rect.top = clamp(y, 0L, static_cast<LONG>(desc.Height));
+    rect.right = clamp(x + width, 0L, static_cast<LONG>(desc.Width));
+    rect.bottom = clamp(y + height, 0L, static_cast<LONG>(desc.Height));
+
+    D3DLOCKED_RECT lock;
+    result = systemSurface->LockRect(&lock, &rect, D3DLOCK_READONLY);
+
+    if (FAILED(result))
+    {
+        UNREACHABLE();
+        systemSurface->Release();
+
+        return;   // No sensible error to generate
+    }
+
+    unsigned char *dest = (unsigned char*)pixels;
+    unsigned short *dest16 = (unsigned short*)pixels;
+
+    unsigned char *source;
+    int inputPitch;
+    if (getPackReverseRowOrder())
+    {
+        source = ((unsigned char*)lock.pBits) + lock.Pitch * (rect.bottom - rect.top - 1);
+        inputPitch = -lock.Pitch;
+    }
+    else
+    {
+        source = (unsigned char*)lock.pBits;
+        inputPitch = lock.Pitch;
+    }
+
+    unsigned int fastPixelSize = 0;
+
+    if (desc.Format == D3DFMT_A8R8G8B8 &&
+        format == GL_BGRA_EXT &&
+        type == GL_UNSIGNED_BYTE)
+    {
+        fastPixelSize = 4;
+    }
+    else if ((desc.Format == D3DFMT_A4R4G4B4 &&
+             format == GL_BGRA_EXT &&
+             type == GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT) ||
+             (desc.Format == D3DFMT_A1R5G5B5 &&
+             format == GL_BGRA_EXT &&
+             type == GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT))
+    {
+        fastPixelSize = 2;
+    }
+    else if (desc.Format == D3DFMT_A16B16G16R16F &&
+             format == GL_RGBA &&
+             type == GL_HALF_FLOAT_OES)
+    {
+        fastPixelSize = 8;
+    }
+    else if (desc.Format == D3DFMT_A32B32G32R32F &&
+             format == GL_RGBA &&
+             type == GL_FLOAT)
+    {
+        fastPixelSize = 16;
+    }
+
+    for (int j = 0; j < rect.bottom - rect.top; j++)
+    {
+        if (fastPixelSize != 0)
+        {
+            // Fast path for formats which require no translation:
+            // D3DFMT_A8R8G8B8 to BGRA/UNSIGNED_BYTE
+            // D3DFMT_A4R4G4B4 to BGRA/UNSIGNED_SHORT_4_4_4_4_REV_EXT
+            // D3DFMT_A1R5G5B5 to BGRA/UNSIGNED_SHORT_1_5_5_5_REV_EXT
+            // D3DFMT_A16B16G16R16F to RGBA/HALF_FLOAT_OES
+            // D3DFMT_A32B32G32R32F to RGBA/FLOAT
+            // 
+            // Note that buffers with no alpha go through the slow path below.
+            memcpy(dest + j * outputPitch,
+                   source + j * inputPitch,
+                   (rect.right - rect.left) * fastPixelSize);
+            continue;
+        }
+
+        for (int i = 0; i < rect.right - rect.left; i++)
+        {
+            float r;
+            float g;
+            float b;
+            float a;
+
+            switch (desc.Format)
+            {
+              case D3DFMT_R5G6B5:
+                {
+                    unsigned short rgb = *(unsigned short*)(source + 2 * i + j * inputPitch);
+
+                    a = 1.0f;
+                    b = (rgb & 0x001F) * (1.0f / 0x001F);
+                    g = (rgb & 0x07E0) * (1.0f / 0x07E0);
+                    r = (rgb & 0xF800) * (1.0f / 0xF800);
+                }
+                break;
+              case D3DFMT_A1R5G5B5:
+                {
+                    unsigned short argb = *(unsigned short*)(source + 2 * i + j * inputPitch);
+
+                    a = (argb & 0x8000) ? 1.0f : 0.0f;
+                    b = (argb & 0x001F) * (1.0f / 0x001F);
+                    g = (argb & 0x03E0) * (1.0f / 0x03E0);
+                    r = (argb & 0x7C00) * (1.0f / 0x7C00);
+                }
+                break;
+              case D3DFMT_A8R8G8B8:
+                {
+                    unsigned int argb = *(unsigned int*)(source + 4 * i + j * inputPitch);
+
+                    a = (argb & 0xFF000000) * (1.0f / 0xFF000000);
+                    b = (argb & 0x000000FF) * (1.0f / 0x000000FF);
+                    g = (argb & 0x0000FF00) * (1.0f / 0x0000FF00);
+                    r = (argb & 0x00FF0000) * (1.0f / 0x00FF0000);
+                }
+                break;
+              case D3DFMT_X8R8G8B8:
+                {
+                    unsigned int xrgb = *(unsigned int*)(source + 4 * i + j * inputPitch);
+
+                    a = 1.0f;
+                    b = (xrgb & 0x000000FF) * (1.0f / 0x000000FF);
+                    g = (xrgb & 0x0000FF00) * (1.0f / 0x0000FF00);
+                    r = (xrgb & 0x00FF0000) * (1.0f / 0x00FF0000);
+                }
+                break;
+              case D3DFMT_A2R10G10B10:
+                {
+                    unsigned int argb = *(unsigned int*)(source + 4 * i + j * inputPitch);
+
+                    a = (argb & 0xC0000000) * (1.0f / 0xC0000000);
+                    b = (argb & 0x000003FF) * (1.0f / 0x000003FF);
+                    g = (argb & 0x000FFC00) * (1.0f / 0x000FFC00);
+                    r = (argb & 0x3FF00000) * (1.0f / 0x3FF00000);
+                }
+                break;
+              case D3DFMT_A32B32G32R32F:
+                {
+                    // float formats in D3D are stored rgba, rather than the other way round
+                    r = *((float*)(source + 16 * i + j * inputPitch) + 0);
+                    g = *((float*)(source + 16 * i + j * inputPitch) + 1);
+                    b = *((float*)(source + 16 * i + j * inputPitch) + 2);
+                    a = *((float*)(source + 16 * i + j * inputPitch) + 3);
+                }
+                break;
+              case D3DFMT_A16B16G16R16F:
+                {
+                    // float formats in D3D are stored rgba, rather than the other way round
+                    r = float16ToFloat32(*((unsigned short*)(source + 8 * i + j * inputPitch) + 0));
+                    g = float16ToFloat32(*((unsigned short*)(source + 8 * i + j * inputPitch) + 1));
+                    b = float16ToFloat32(*((unsigned short*)(source + 8 * i + j * inputPitch) + 2));
+                    a = float16ToFloat32(*((unsigned short*)(source + 8 * i + j * inputPitch) + 3));
+                }
+                break;
+              default:
+                UNIMPLEMENTED();   // FIXME
+                UNREACHABLE();
+                return;
+            }
+
+            switch (format)
+            {
+              case GL_RGBA:
+                switch (type)
+                {
+                  case GL_UNSIGNED_BYTE:
+                    dest[4 * i + j * outputPitch + 0] = (unsigned char)(255 * r + 0.5f);
+                    dest[4 * i + j * outputPitch + 1] = (unsigned char)(255 * g + 0.5f);
+                    dest[4 * i + j * outputPitch + 2] = (unsigned char)(255 * b + 0.5f);
+                    dest[4 * i + j * outputPitch + 3] = (unsigned char)(255 * a + 0.5f);
+                    break;
+                  default: UNREACHABLE();
+                }
+                break;
+              case GL_BGRA_EXT:
+                switch (type)
+                {
+                  case GL_UNSIGNED_BYTE:
+                    dest[4 * i + j * outputPitch + 0] = (unsigned char)(255 * b + 0.5f);
+                    dest[4 * i + j * outputPitch + 1] = (unsigned char)(255 * g + 0.5f);
+                    dest[4 * i + j * outputPitch + 2] = (unsigned char)(255 * r + 0.5f);
+                    dest[4 * i + j * outputPitch + 3] = (unsigned char)(255 * a + 0.5f);
+                    break;
+                  case GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT:
+                    // According to the desktop GL spec in the "Transfer of Pixel Rectangles" section
+                    // this type is packed as follows:
+                    //   15   14   13   12   11   10    9    8    7    6    5    4    3    2    1    0
+                    //  --------------------------------------------------------------------------------
+                    // |       4th         |        3rd         |        2nd        |   1st component   |
+                    //  --------------------------------------------------------------------------------
+                    // in the case of BGRA_EXT, B is the first component, G the second, and so forth.
+                    dest16[i + j * outputPitch / sizeof(unsigned short)] =
+                        ((unsigned short)(15 * a + 0.5f) << 12)|
+                        ((unsigned short)(15 * r + 0.5f) << 8) |
+                        ((unsigned short)(15 * g + 0.5f) << 4) |
+                        ((unsigned short)(15 * b + 0.5f) << 0);
+                    break;
+                  case GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT:
+                    // According to the desktop GL spec in the "Transfer of Pixel Rectangles" section
+                    // this type is packed as follows:
+                    //   15   14   13   12   11   10    9    8    7    6    5    4    3    2    1    0
+                    //  --------------------------------------------------------------------------------
+                    // | 4th |          3rd           |           2nd          |      1st component     |
+                    //  --------------------------------------------------------------------------------
+                    // in the case of BGRA_EXT, B is the first component, G the second, and so forth.
+                    dest16[i + j * outputPitch / sizeof(unsigned short)] =
+                        ((unsigned short)(     a + 0.5f) << 15) |
+                        ((unsigned short)(31 * r + 0.5f) << 10) |
+                        ((unsigned short)(31 * g + 0.5f) << 5) |
+                        ((unsigned short)(31 * b + 0.5f) << 0);
+                    break;
+                  default: UNREACHABLE();
+                }
+                break;
+              case GL_RGB:
+                switch (type)
+                {
+                  case GL_UNSIGNED_SHORT_5_6_5:
+                    dest16[i + j * outputPitch / sizeof(unsigned short)] = 
+                        ((unsigned short)(31 * b + 0.5f) << 0) |
+                        ((unsigned short)(63 * g + 0.5f) << 5) |
+                        ((unsigned short)(31 * r + 0.5f) << 11);
+                    break;
+                  case GL_UNSIGNED_BYTE:
+                    dest[3 * i + j * outputPitch + 0] = (unsigned char)(255 * r + 0.5f);
+                    dest[3 * i + j * outputPitch + 1] = (unsigned char)(255 * g + 0.5f);
+                    dest[3 * i + j * outputPitch + 2] = (unsigned char)(255 * b + 0.5f);
+                    break;
+                  default: UNREACHABLE();
+                }
+                break;
+              default: UNREACHABLE();
+            }
+        }
+    }
+
+    systemSurface->UnlockRect();
+
+    systemSurface->Release();
+}
+
+void Context::clear(GLbitfield mask)
+{
+    Framebuffer *framebufferObject = getDrawFramebuffer();
+
+    if (!framebufferObject || framebufferObject->completeness() != GL_FRAMEBUFFER_COMPLETE)
+    {
+        return error(GL_INVALID_FRAMEBUFFER_OPERATION);
+    }
+
+    DWORD flags = 0;
+
+    if (mask & GL_COLOR_BUFFER_BIT)
+    {
+        mask &= ~GL_COLOR_BUFFER_BIT;
+
+        if (framebufferObject->getColorbufferType() != GL_NONE)
+        {
+            flags |= D3DCLEAR_TARGET;
+        }
+    }
+
+    if (mask & GL_DEPTH_BUFFER_BIT)
+    {
+        mask &= ~GL_DEPTH_BUFFER_BIT;
+        if (mState.depthMask && framebufferObject->getDepthbufferType() != GL_NONE)
+        {
+            flags |= D3DCLEAR_ZBUFFER;
+        }
+    }
+
+    GLuint stencilUnmasked = 0x0;
+
+    if (mask & GL_STENCIL_BUFFER_BIT)
+    {
+        mask &= ~GL_STENCIL_BUFFER_BIT;
+        if (framebufferObject->getStencilbufferType() != GL_NONE)
+        {
+            IDirect3DSurface9 *depthStencil = framebufferObject->getStencilbuffer()->getDepthStencil();
+            if (!depthStencil)
+            {
+                ERR("Depth stencil pointer unexpectedly null.");
+                return;
+            }
+            
+            D3DSURFACE_DESC desc;
+            depthStencil->GetDesc(&desc);
+            depthStencil->Release();
+
+            unsigned int stencilSize = dx2es::GetStencilSize(desc.Format);
+            stencilUnmasked = (0x1 << stencilSize) - 1;
+
+            if (stencilUnmasked != 0x0)
+            {
+                flags |= D3DCLEAR_STENCIL;
+            }
+        }
+    }
+
+    if (mask != 0)
+    {
+        return error(GL_INVALID_VALUE);
+    }
+
+    if (!applyRenderTarget(true))   // Clips the clear to the scissor rectangle but not the viewport
+    {
+        return;
+    }
+
+    D3DCOLOR color = D3DCOLOR_ARGB(unorm<8>(mState.colorClearValue.alpha), 
+                                   unorm<8>(mState.colorClearValue.red), 
+                                   unorm<8>(mState.colorClearValue.green), 
+                                   unorm<8>(mState.colorClearValue.blue));
+    float depth = clamp01(mState.depthClearValue);
+    int stencil = mState.stencilClearValue & 0x000000FF;
+
+    bool alphaUnmasked = (dx2es::GetAlphaSize(mRenderTargetDesc.Format) == 0) || mState.colorMaskAlpha;
+
+    const bool needMaskedStencilClear = (flags & D3DCLEAR_STENCIL) &&
+                                        (mState.stencilWritemask & stencilUnmasked) != stencilUnmasked;
+    const bool needMaskedColorClear = (flags & D3DCLEAR_TARGET) &&
+                                      !(mState.colorMaskRed && mState.colorMaskGreen &&
+                                        mState.colorMaskBlue && alphaUnmasked);
+
+    if (needMaskedColorClear || needMaskedStencilClear)
+    {
+        // State which is altered in all paths from this point to the clear call is saved.
+        // State which is altered in only some paths will be flagged dirty in the case that
+        //  that path is taken.
+        HRESULT hr;
+        if (mMaskedClearSavedState == NULL)
+        {
+            hr = mDevice->BeginStateBlock();
+            ASSERT(SUCCEEDED(hr) || hr == D3DERR_OUTOFVIDEOMEMORY || hr == E_OUTOFMEMORY);
+
+            mDevice->SetRenderState(D3DRS_ZWRITEENABLE, FALSE);
+            mDevice->SetRenderState(D3DRS_ZFUNC, D3DCMP_ALWAYS);
+            mDevice->SetRenderState(D3DRS_ZENABLE, FALSE);
+            mDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
+            mDevice->SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID);
+            mDevice->SetRenderState(D3DRS_ALPHATESTENABLE, FALSE);
+            mDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
+            mDevice->SetRenderState(D3DRS_CLIPPLANEENABLE, 0);
+            mDevice->SetRenderState(D3DRS_COLORWRITEENABLE, 0);
+            mDevice->SetRenderState(D3DRS_STENCILENABLE, FALSE);
+            mDevice->SetPixelShader(NULL);
+            mDevice->SetVertexShader(NULL);
+            mDevice->SetFVF(D3DFVF_XYZRHW | D3DFVF_DIFFUSE);
+            mDevice->SetStreamSource(0, NULL, 0, 0);
+            mDevice->SetRenderState(D3DRS_SEPARATEALPHABLENDENABLE, TRUE);
+            mDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
+            mDevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TFACTOR);
+            mDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1);
+            mDevice->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TFACTOR);
+            mDevice->SetRenderState(D3DRS_TEXTUREFACTOR, color);
+            mDevice->SetRenderState(D3DRS_MULTISAMPLEMASK, 0xFFFFFFFF);
+            
+            for(int i = 0; i < MAX_VERTEX_ATTRIBS; i++)
+            {
+                mDevice->SetStreamSourceFreq(i, 1);
+            }
+
+            hr = mDevice->EndStateBlock(&mMaskedClearSavedState);
+            ASSERT(SUCCEEDED(hr) || hr == D3DERR_OUTOFVIDEOMEMORY || hr == E_OUTOFMEMORY);
+        }
+
+        ASSERT(mMaskedClearSavedState != NULL);
+
+        if (mMaskedClearSavedState != NULL)
+        {
+            hr = mMaskedClearSavedState->Capture();
+            ASSERT(SUCCEEDED(hr));
+        }
+
+        mDevice->SetRenderState(D3DRS_ZWRITEENABLE, FALSE);
+        mDevice->SetRenderState(D3DRS_ZFUNC, D3DCMP_ALWAYS);
+        mDevice->SetRenderState(D3DRS_ZENABLE, FALSE);
+        mDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
+        mDevice->SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID);
+        mDevice->SetRenderState(D3DRS_ALPHATESTENABLE, FALSE);
+        mDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
+        mDevice->SetRenderState(D3DRS_CLIPPLANEENABLE, 0);
+
+        if (flags & D3DCLEAR_TARGET)
+        {
+            mDevice->SetRenderState(D3DRS_COLORWRITEENABLE, es2dx::ConvertColorMask(mState.colorMaskRed, mState.colorMaskGreen, mState.colorMaskBlue, mState.colorMaskAlpha));
+        }
+        else
+        {
+            mDevice->SetRenderState(D3DRS_COLORWRITEENABLE, 0);
+        }
+
+        if (stencilUnmasked != 0x0 && (flags & D3DCLEAR_STENCIL))
+        {
+            mDevice->SetRenderState(D3DRS_STENCILENABLE, TRUE);
+            mDevice->SetRenderState(D3DRS_TWOSIDEDSTENCILMODE, FALSE);
+            mDevice->SetRenderState(D3DRS_STENCILFUNC, D3DCMP_ALWAYS);
+            mDevice->SetRenderState(D3DRS_STENCILREF, stencil);
+            mDevice->SetRenderState(D3DRS_STENCILWRITEMASK, mState.stencilWritemask);
+            mDevice->SetRenderState(D3DRS_STENCILFAIL, D3DSTENCILOP_REPLACE);
+            mDevice->SetRenderState(D3DRS_STENCILZFAIL, D3DSTENCILOP_REPLACE);
+            mDevice->SetRenderState(D3DRS_STENCILPASS, D3DSTENCILOP_REPLACE);
+            mStencilStateDirty = true;
+        }
+        else
+        {
+            mDevice->SetRenderState(D3DRS_STENCILENABLE, FALSE);
+        }
+
+        mDevice->SetPixelShader(NULL);
+        mDevice->SetVertexShader(NULL);
+        mDevice->SetFVF(D3DFVF_XYZRHW);
+        mDevice->SetRenderState(D3DRS_SEPARATEALPHABLENDENABLE, TRUE);
+        mDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
+        mDevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TFACTOR);
+        mDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1);
+        mDevice->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TFACTOR);
+        mDevice->SetRenderState(D3DRS_TEXTUREFACTOR, color);
+        mDevice->SetRenderState(D3DRS_MULTISAMPLEMASK, 0xFFFFFFFF);
+
+        for(int i = 0; i < MAX_VERTEX_ATTRIBS; i++)
+        {
+            mDevice->SetStreamSourceFreq(i, 1);
+        }
+
+        float quad[4][4];   // A quadrilateral covering the target, aligned to match the edges
+        quad[0][0] = -0.5f;
+        quad[0][1] = mRenderTargetDesc.Height - 0.5f;
+        quad[0][2] = 0.0f;
+        quad[0][3] = 1.0f;
+
+        quad[1][0] = mRenderTargetDesc.Width - 0.5f;
+        quad[1][1] = mRenderTargetDesc.Height - 0.5f;
+        quad[1][2] = 0.0f;
+        quad[1][3] = 1.0f;
+
+        quad[2][0] = -0.5f;
+        quad[2][1] = -0.5f;
+        quad[2][2] = 0.0f;
+        quad[2][3] = 1.0f;
+
+        quad[3][0] = mRenderTargetDesc.Width - 0.5f;
+        quad[3][1] = -0.5f;
+        quad[3][2] = 0.0f;
+        quad[3][3] = 1.0f;
+
+        mDisplay->startScene();
+        mDevice->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, quad, sizeof(float[4]));
+
+        if (flags & D3DCLEAR_ZBUFFER)
+        {
+            mDevice->SetRenderState(D3DRS_ZENABLE, TRUE);
+            mDevice->SetRenderState(D3DRS_ZWRITEENABLE, TRUE);
+            mDevice->Clear(0, NULL, D3DCLEAR_ZBUFFER, color, depth, stencil);
+        }
+
+        if (mMaskedClearSavedState != NULL)
+        {
+            mMaskedClearSavedState->Apply();
+        }
+    }
+    else if (flags)
+    {
+        mDevice->Clear(0, NULL, flags, color, depth, stencil);
+    }
+}
+
+void Context::drawArrays(GLenum mode, GLint first, GLsizei count, GLsizei instances)
+{
+    if (!mState.currentProgram)
+    {
+        return error(GL_INVALID_OPERATION);
+    }
+
+    D3DPRIMITIVETYPE primitiveType;
+    int primitiveCount;
+
+    if(!es2dx::ConvertPrimitiveType(mode, count, &primitiveType, &primitiveCount))
+        return error(GL_INVALID_ENUM);
+
+    if (primitiveCount <= 0)
+    {
+        return;
+    }
+
+    if (!applyRenderTarget(false))
+    {
+        return;
+    }
+
+    applyState(mode);
+
+    GLsizei repeatDraw = 1;
+    GLenum err = applyVertexBuffer(first, count, instances, &repeatDraw);
+    if (err != GL_NO_ERROR)
+    {
+        return error(err);
+    }
+
+    applyShaders();
+    applyTextures();
+
+    if (!getCurrentProgramBinary()->validateSamplers(NULL))
+    {
+        return error(GL_INVALID_OPERATION);
+    }
+
+    if (!skipDraw(mode))
+    {
+        mDisplay->startScene();
+        
+        if (mode == GL_LINE_LOOP)
+        {
+            drawLineLoop(count, GL_NONE, NULL, 0);
+        }
+        else if (instances > 0)
+        {
+            StaticIndexBuffer *countingIB = mIndexDataManager->getCountingIndices(count);
+            if (countingIB)
+            {
+                if (mAppliedIBSerial != countingIB->getSerial())
+                {
+                    mDevice->SetIndices(countingIB->getBuffer());
+                    mAppliedIBSerial = countingIB->getSerial();
+                }
+
+                for (int i = 0; i < repeatDraw; i++)
+                {
+                    mDevice->DrawIndexedPrimitive(primitiveType, 0, 0, count, 0, primitiveCount);
+                }
+            }
+            else
+            {
+                ERR("Could not create a counting index buffer for glDrawArraysInstanced.");
+                return error(GL_OUT_OF_MEMORY);
+            }
+        }
+        else   // Regular case
+        {
+            mDevice->DrawPrimitive(primitiveType, 0, primitiveCount);
+        }
+    }
+}
+
+void Context::drawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, GLsizei instances)
+{
+    if (!mState.currentProgram)
+    {
+        return error(GL_INVALID_OPERATION);
+    }
+
+    if (!indices && !mState.elementArrayBuffer)
+    {
+        return error(GL_INVALID_OPERATION);
+    }
+
+    D3DPRIMITIVETYPE primitiveType;
+    int primitiveCount;
+
+    if(!es2dx::ConvertPrimitiveType(mode, count, &primitiveType, &primitiveCount))
+        return error(GL_INVALID_ENUM);
+
+    if (primitiveCount <= 0)
+    {
+        return;
+    }
+
+    if (!applyRenderTarget(false))
+    {
+        return;
+    }
+
+    applyState(mode);
+
+    TranslatedIndexData indexInfo;
+    GLenum err = applyIndexBuffer(indices, count, mode, type, &indexInfo);
+    if (err != GL_NO_ERROR)
+    {
+        return error(err);
+    }
+
+    GLsizei vertexCount = indexInfo.maxIndex - indexInfo.minIndex + 1;
+    GLsizei repeatDraw = 1;
+    err = applyVertexBuffer(indexInfo.minIndex, vertexCount, instances, &repeatDraw);
+    if (err != GL_NO_ERROR)
+    {
+        return error(err);
+    }
+
+    applyShaders();
+    applyTextures();
+
+    if (!getCurrentProgramBinary()->validateSamplers(false))
+    {
+        return error(GL_INVALID_OPERATION);
+    }
+
+    if (!skipDraw(mode))
+    {
+        mDisplay->startScene();
+
+        if (mode == GL_LINE_LOOP)
+        {
+            drawLineLoop(count, type, indices, indexInfo.minIndex);   
+        }
+        else
+        {
+            for (int i = 0; i < repeatDraw; i++)
+            {
+                mDevice->DrawIndexedPrimitive(primitiveType, -(INT)indexInfo.minIndex, indexInfo.minIndex, vertexCount, indexInfo.startIndex, primitiveCount);
+            }
+        }
+    }
+}
+
+// Implements glFlush when block is false, glFinish when block is true
+void Context::sync(bool block)
+{
+    mDisplay->sync(block);
+}
+
+void Context::drawLineLoop(GLsizei count, GLenum type, const GLvoid *indices, int minIndex)
+{
+    // Get the raw indices for an indexed draw
+    if (type != GL_NONE && mState.elementArrayBuffer.get())
+    {
+        Buffer *indexBuffer = mState.elementArrayBuffer.get();
+        intptr_t offset = reinterpret_cast<intptr_t>(indices);
+        indices = static_cast<const GLubyte*>(indexBuffer->data()) + offset;
+    }
+
+    UINT startIndex = 0;
+    bool succeeded = false;
+
+    if (supports32bitIndices())
+    {
+        const int spaceNeeded = (count + 1) * sizeof(unsigned int);
+
+        if (!mLineLoopIB)
+        {
+            mLineLoopIB = new StreamingIndexBuffer(mDevice, INITIAL_INDEX_BUFFER_SIZE, D3DFMT_INDEX32);
+        }
+
+        if (mLineLoopIB)
+        {
+            mLineLoopIB->reserveSpace(spaceNeeded, GL_UNSIGNED_INT);
+
+            UINT offset = 0;
+            unsigned int *data = static_cast<unsigned int*>(mLineLoopIB->map(spaceNeeded, &offset));
+            startIndex = offset / 4;
+            
+            if (data)
+            {
+                switch (type)
+                {
+                  case GL_NONE:   // Non-indexed draw
+                    for (int i = 0; i < count; i++)
+                    {
+                        data[i] = i;
+                    }
+                    data[count] = 0;
+                    break;
+                  case GL_UNSIGNED_BYTE:
+                    for (int i = 0; i < count; i++)
+                    {
+                        data[i] = static_cast<const GLubyte*>(indices)[i];
+                    }
+                    data[count] = static_cast<const GLubyte*>(indices)[0];
+                    break;
+                  case GL_UNSIGNED_SHORT:
+                    for (int i = 0; i < count; i++)
+                    {
+                        data[i] = static_cast<const GLushort*>(indices)[i];
+                    }
+                    data[count] = static_cast<const GLushort*>(indices)[0];
+                    break;
+                  case GL_UNSIGNED_INT:
+                    for (int i = 0; i < count; i++)
+                    {
+                        data[i] = static_cast<const GLuint*>(indices)[i];
+                    }
+                    data[count] = static_cast<const GLuint*>(indices)[0];
+                    break;
+                  default: UNREACHABLE();
+                }
+
+                mLineLoopIB->unmap();
+                succeeded = true;
+            }
+        }
+    }
+    else
+    {
+        const int spaceNeeded = (count + 1) * sizeof(unsigned short);
+
+        if (!mLineLoopIB)
+        {
+            mLineLoopIB = new StreamingIndexBuffer(mDevice, INITIAL_INDEX_BUFFER_SIZE, D3DFMT_INDEX16);
+        }
+
+        if (mLineLoopIB)
+        {
+            mLineLoopIB->reserveSpace(spaceNeeded, GL_UNSIGNED_SHORT);
+
+            UINT offset = 0;
+            unsigned short *data = static_cast<unsigned short*>(mLineLoopIB->map(spaceNeeded, &offset));
+            startIndex = offset / 2;
+            
+            if (data)
+            {
+                switch (type)
+                {
+                  case GL_NONE:   // Non-indexed draw
+                    for (int i = 0; i < count; i++)
+                    {
+                        data[i] = i;
+                    }
+                    data[count] = 0;
+                    break;
+                  case GL_UNSIGNED_BYTE:
+                    for (int i = 0; i < count; i++)
+                    {
+                        data[i] = static_cast<const GLubyte*>(indices)[i];
+                    }
+                    data[count] = static_cast<const GLubyte*>(indices)[0];
+                    break;
+                  case GL_UNSIGNED_SHORT:
+                    for (int i = 0; i < count; i++)
+                    {
+                        data[i] = static_cast<const GLushort*>(indices)[i];
+                    }
+                    data[count] = static_cast<const GLushort*>(indices)[0];
+                    break;
+                  case GL_UNSIGNED_INT:
+                    for (int i = 0; i < count; i++)
+                    {
+                        data[i] = static_cast<const GLuint*>(indices)[i];
+                    }
+                    data[count] = static_cast<const GLuint*>(indices)[0];
+                    break;
+                  default: UNREACHABLE();
+                }
+
+                mLineLoopIB->unmap();
+                succeeded = true;
+            }
+        }
+    }
+    
+    if (succeeded)
+    {
+        if (mAppliedIBSerial != mLineLoopIB->getSerial())
+        {
+            mDevice->SetIndices(mLineLoopIB->getBuffer());
+            mAppliedIBSerial = mLineLoopIB->getSerial();
+        }
+
+        mDevice->DrawIndexedPrimitive(D3DPT_LINESTRIP, -minIndex, minIndex, count, startIndex, count);
+    }
+    else
+    {
+        ERR("Could not create a looping index buffer for GL_LINE_LOOP.");
+        return error(GL_OUT_OF_MEMORY);
+    }
+}
+
+void Context::recordInvalidEnum()
+{
+    mInvalidEnum = true;
+}
+
+void Context::recordInvalidValue()
+{
+    mInvalidValue = true;
+}
+
+void Context::recordInvalidOperation()
+{
+    mInvalidOperation = true;
+}
+
+void Context::recordOutOfMemory()
+{
+    mOutOfMemory = true;
+}
+
+void Context::recordInvalidFramebufferOperation()
+{
+    mInvalidFramebufferOperation = true;
+}
+
+// Get one of the recorded errors and clear its flag, if any.
+// [OpenGL ES 2.0.24] section 2.5 page 13.
+GLenum Context::getError()
+{
+    if (mInvalidEnum)
+    {
+        mInvalidEnum = false;
+
+        return GL_INVALID_ENUM;
+    }
+
+    if (mInvalidValue)
+    {
+        mInvalidValue = false;
+
+        return GL_INVALID_VALUE;
+    }
+
+    if (mInvalidOperation)
+    {
+        mInvalidOperation = false;
+
+        return GL_INVALID_OPERATION;
+    }
+
+    if (mOutOfMemory)
+    {
+        mOutOfMemory = false;
+
+        return GL_OUT_OF_MEMORY;
+    }
+
+    if (mInvalidFramebufferOperation)
+    {
+        mInvalidFramebufferOperation = false;
+
+        return GL_INVALID_FRAMEBUFFER_OPERATION;
+    }
+
+    return GL_NO_ERROR;
+}
+
+GLenum Context::getResetStatus()
+{
+    if (mResetStatus == GL_NO_ERROR)
+    {
+        bool lost = mDisplay->testDeviceLost();
+
+        if (lost)
+        {
+            mDisplay->notifyDeviceLost();   // Sets mResetStatus
+        }
+    }
+
+    GLenum status = mResetStatus;
+
+    if (mResetStatus != GL_NO_ERROR)
+    {
+        if (mDisplay->testDeviceResettable())
+        {
+            mResetStatus = GL_NO_ERROR;
+        }
+    }
+    
+    return status;
+}
+
+bool Context::isResetNotificationEnabled()
+{
+    return (mResetStrategy == GL_LOSE_CONTEXT_ON_RESET_EXT);
+}
+
+bool Context::supportsShaderModel3() const
+{
+    return mSupportsShaderModel3;
+}
+
+float Context::getMaximumPointSize() const
+{
+    return mSupportsShaderModel3 ? mMaximumPointSize : ALIASED_POINT_SIZE_RANGE_MAX_SM2;
+}
+
+int Context::getMaximumVaryingVectors() const
+{
+    return mSupportsShaderModel3 ? MAX_VARYING_VECTORS_SM3 : MAX_VARYING_VECTORS_SM2;
+}
+
+unsigned int Context::getMaximumVertexTextureImageUnits() const
+{
+    return mSupportsVertexTexture ? MAX_VERTEX_TEXTURE_IMAGE_UNITS_VTF : 0;
+}
+
+unsigned int Context::getMaximumCombinedTextureImageUnits() const
+{
+    return MAX_TEXTURE_IMAGE_UNITS + getMaximumVertexTextureImageUnits();
+}
+
+int Context::getMaximumFragmentUniformVectors() const
+{
+    return mSupportsShaderModel3 ? MAX_FRAGMENT_UNIFORM_VECTORS_SM3 : MAX_FRAGMENT_UNIFORM_VECTORS_SM2;
+}
+
+int Context::getMaxSupportedSamples() const
+{
+    return mMaxSupportedSamples;
+}
+
+int Context::getNearestSupportedSamples(D3DFORMAT format, int requested) const
+{
+    if (requested == 0)
+    {
+        return requested;
+    }
+
+    std::map<D3DFORMAT, bool *>::const_iterator itr = mMultiSampleSupport.find(format);
+    if (itr == mMultiSampleSupport.end())
+    {
+        return -1;
+    }
+
+    for (int i = requested; i <= D3DMULTISAMPLE_16_SAMPLES; ++i)
+    {
+        if (itr->second[i] && i != D3DMULTISAMPLE_NONMASKABLE)
+        {
+            return i;
+        }
+    }
+
+    return -1;
+}
+
+bool Context::supportsEventQueries() const
+{
+    return mSupportsEventQueries;
+}
+
+bool Context::supportsOcclusionQueries() const
+{
+    return mSupportsOcclusionQueries;
+}
+
+bool Context::supportsDXT1Textures() const
+{
+    return mSupportsDXT1Textures;
+}
+
+bool Context::supportsDXT3Textures() const
+{
+    return mSupportsDXT3Textures;
+}
+
+bool Context::supportsDXT5Textures() const
+{
+    return mSupportsDXT5Textures;
+}
+
+bool Context::supportsFloat32Textures() const
+{
+    return mSupportsFloat32Textures;
+}
+
+bool Context::supportsFloat32LinearFilter() const
+{
+    return mSupportsFloat32LinearFilter;
+}
+
+bool Context::supportsFloat32RenderableTextures() const
+{
+    return mSupportsFloat32RenderableTextures;
+}
+
+bool Context::supportsFloat16Textures() const
+{
+    return mSupportsFloat16Textures;
+}
+
+bool Context::supportsFloat16LinearFilter() const
+{
+    return mSupportsFloat16LinearFilter;
+}
+
+bool Context::supportsFloat16RenderableTextures() const
+{
+    return mSupportsFloat16RenderableTextures;
+}
+
+int Context::getMaximumRenderbufferDimension() const
+{
+    return mMaxRenderbufferDimension;
+}
+
+int Context::getMaximumTextureDimension() const
+{
+    return mMaxTextureDimension;
+}
+
+int Context::getMaximumCubeTextureDimension() const
+{
+    return mMaxCubeTextureDimension;
+}
+
+int Context::getMaximumTextureLevel() const
+{
+    return mMaxTextureLevel;
+}
+
+bool Context::supportsLuminanceTextures() const
+{
+    return mSupportsLuminanceTextures;
+}
+
+bool Context::supportsLuminanceAlphaTextures() const
+{
+    return mSupportsLuminanceAlphaTextures;
+}
+
+bool Context::supportsDepthTextures() const
+{
+    return mSupportsDepthTextures;
+}
+
+bool Context::supports32bitIndices() const
+{
+    return mSupports32bitIndices;
+}
+
+bool Context::supportsNonPower2Texture() const
+{
+    return mSupportsNonPower2Texture;
+}
+
+bool Context::supportsInstancing() const
+{
+    return mSupportsInstancing;
+}
+
+bool Context::supportsTextureFilterAnisotropy() const
+{
+    return mSupportsTextureFilterAnisotropy;
+}
+
+float Context::getTextureMaxAnisotropy() const
+{
+    return mMaxTextureAnisotropy;
+}
+
+bool Context::getCurrentReadFormatType(GLenum *format, GLenum *type)
+{
+    Framebuffer *framebuffer = getReadFramebuffer();
+    if (!framebuffer || framebuffer->completeness() != GL_FRAMEBUFFER_COMPLETE)
+    {
+        return error(GL_INVALID_OPERATION, false);
+    }
+
+    Renderbuffer *renderbuffer = framebuffer->getColorbuffer();
+    if (!renderbuffer)
+    {
+        return error(GL_INVALID_OPERATION, false);
+    }
+
+    if(!dx2es::ConvertReadBufferFormat(renderbuffer->getD3DFormat(), format, type))
+    {
+        ASSERT(false);
+        return false;
+    }
+
+    return true;
+}
+
+void Context::detachBuffer(GLuint buffer)
+{
+    // [OpenGL ES 2.0.24] section 2.9 page 22:
+    // If a buffer object is deleted while it is bound, all bindings to that object in the current context
+    // (i.e. in the thread that called Delete-Buffers) are reset to zero.
+
+    if (mState.arrayBuffer.id() == buffer)
+    {
+        mState.arrayBuffer.set(NULL);
+    }
+
+    if (mState.elementArrayBuffer.id() == buffer)
+    {
+        mState.elementArrayBuffer.set(NULL);
+    }
+
+    for (int attribute = 0; attribute < MAX_VERTEX_ATTRIBS; attribute++)
+    {
+        if (mState.vertexAttribute[attribute].mBoundBuffer.id() == buffer)
+        {
+            mState.vertexAttribute[attribute].mBoundBuffer.set(NULL);
+        }
+    }
+}
+
+void Context::detachTexture(GLuint texture)
+{
+    // [OpenGL ES 2.0.24] section 3.8 page 84:
+    // If a texture object is deleted, it is as if all texture units which are bound to that texture object are
+    // rebound to texture object zero
+
+    for (int type = 0; type < TEXTURE_TYPE_COUNT; type++)
+    {
+        for (int sampler = 0; sampler < MAX_COMBINED_TEXTURE_IMAGE_UNITS_VTF; sampler++)
+        {
+            if (mState.samplerTexture[type][sampler].id() == texture)
+            {
+                mState.samplerTexture[type][sampler].set(NULL);
+            }
+        }
+    }
+
+    // [OpenGL ES 2.0.24] section 4.4 page 112:
+    // If a texture object is deleted while its image is attached to the currently bound framebuffer, then it is
+    // as if FramebufferTexture2D had been called, with a texture of 0, for each attachment point to which this
+    // image was attached in the currently bound framebuffer.
+
+    Framebuffer *readFramebuffer = getReadFramebuffer();
+    Framebuffer *drawFramebuffer = getDrawFramebuffer();
+
+    if (readFramebuffer)
+    {
+        readFramebuffer->detachTexture(texture);
+    }
+
+    if (drawFramebuffer && drawFramebuffer != readFramebuffer)
+    {
+        drawFramebuffer->detachTexture(texture);
+    }
+}
+
+void Context::detachFramebuffer(GLuint framebuffer)
+{
+    // [OpenGL ES 2.0.24] section 4.4 page 107:
+    // If a framebuffer that is currently bound to the target FRAMEBUFFER is deleted, it is as though
+    // BindFramebuffer had been executed with the target of FRAMEBUFFER and framebuffer of zero.
+
+    if (mState.readFramebuffer == framebuffer)
+    {
+        bindReadFramebuffer(0);
+    }
+
+    if (mState.drawFramebuffer == framebuffer)
+    {
+        bindDrawFramebuffer(0);
+    }
+}
+
+void Context::detachRenderbuffer(GLuint renderbuffer)
+{
+    // [OpenGL ES 2.0.24] section 4.4 page 109:
+    // If a renderbuffer that is currently bound to RENDERBUFFER is deleted, it is as though BindRenderbuffer
+    // had been executed with the target RENDERBUFFER and name of zero.
+
+    if (mState.renderbuffer.id() == renderbuffer)
+    {
+        bindRenderbuffer(0);
+    }
+
+    // [OpenGL ES 2.0.24] section 4.4 page 111:
+    // If a renderbuffer object is deleted while its image is attached to the currently bound framebuffer,
+    // then it is as if FramebufferRenderbuffer had been called, with a renderbuffer of 0, for each attachment
+    // point to which this image was attached in the currently bound framebuffer.
+
+    Framebuffer *readFramebuffer = getReadFramebuffer();
+    Framebuffer *drawFramebuffer = getDrawFramebuffer();
+
+    if (readFramebuffer)
+    {
+        readFramebuffer->detachRenderbuffer(renderbuffer);
+    }
+
+    if (drawFramebuffer && drawFramebuffer != readFramebuffer)
+    {
+        drawFramebuffer->detachRenderbuffer(renderbuffer);
+    }
+}
+
+Texture *Context::getIncompleteTexture(TextureType type)
+{
+    Texture *t = mIncompleteTextures[type].get();
+
+    if (t == NULL)
+    {
+        static const GLubyte color[] = { 0, 0, 0, 255 };
+
+        switch (type)
+        {
+          default:
+            UNREACHABLE();
+            // default falls through to TEXTURE_2D
+
+          case TEXTURE_2D:
+            {
+                Texture2D *incomplete2d = new Texture2D(Texture::INCOMPLETE_TEXTURE_ID);
+                incomplete2d->setImage(0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color);
+                t = incomplete2d;
+            }
+            break;
+
+          case TEXTURE_CUBE:
+            {
+              TextureCubeMap *incompleteCube = new TextureCubeMap(Texture::INCOMPLETE_TEXTURE_ID);
+
+              incompleteCube->setImagePosX(0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color);
+              incompleteCube->setImageNegX(0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color);
+              incompleteCube->setImagePosY(0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color);
+              incompleteCube->setImageNegY(0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color);
+              incompleteCube->setImagePosZ(0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color);
+              incompleteCube->setImageNegZ(0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color);
+
+              t = incompleteCube;
+            }
+            break;
+        }
+
+        mIncompleteTextures[type].set(t);
+    }
+
+    return t;
+}
+
+bool Context::skipDraw(GLenum drawMode)
+{
+    if (drawMode == GL_POINTS)
+    {
+        // ProgramBinary assumes non-point rendering if gl_PointSize isn't written,
+        // which affects varying interpolation. Since the value of gl_PointSize is
+        // undefined when not written, just skip drawing to avoid unexpected results.
+        if (!getCurrentProgramBinary()->usesPointSize())
+        {
+            // This is stictly speaking not an error, but developers should be 
+            // notified of risking undefined behavior.
+            ERR("Point rendering without writing to gl_PointSize.");
+
+            return true;
+        }
+    }
+    else if (isTriangleMode(drawMode))
+    {
+        if (mState.cullFace && mState.cullMode == GL_FRONT_AND_BACK)
+        {
+            return true;
+        }
+    }
+
+    return false;
+}
+
+bool Context::isTriangleMode(GLenum drawMode)
+{
+    switch (drawMode)
+    {
+      case GL_TRIANGLES:
+      case GL_TRIANGLE_FAN:
+      case GL_TRIANGLE_STRIP:
+        return true;
+      case GL_POINTS:
+      case GL_LINES:
+      case GL_LINE_LOOP:
+      case GL_LINE_STRIP:
+        return false;
+      default: UNREACHABLE();
+    }
+
+    return false;
+}
+
+void Context::setVertexAttrib(GLuint index, const GLfloat *values)
+{
+    ASSERT(index < gl::MAX_VERTEX_ATTRIBS);
+
+    mState.vertexAttribute[index].mCurrentValue[0] = values[0];
+    mState.vertexAttribute[index].mCurrentValue[1] = values[1];
+    mState.vertexAttribute[index].mCurrentValue[2] = values[2];
+    mState.vertexAttribute[index].mCurrentValue[3] = values[3];
+
+    mVertexDataManager->dirtyCurrentValue(index);
+}
+
+void Context::setVertexAttribDivisor(GLuint index, GLuint divisor)
+{
+    ASSERT(index < gl::MAX_VERTEX_ATTRIBS);
+
+    mState.vertexAttribute[index].mDivisor = divisor;
+}
+
+// keep list sorted in following order
+// OES extensions
+// EXT extensions
+// Vendor extensions
+void Context::initExtensionString()
+{
+    mExtensionString = "";
+
+    // OES extensions
+    if (supports32bitIndices())
+    {
+        mExtensionString += "GL_OES_element_index_uint ";
+    }
+
+    mExtensionString += "GL_OES_packed_depth_stencil ";
+    mExtensionString += "GL_OES_get_program_binary ";
+    mExtensionString += "GL_OES_rgb8_rgba8 ";
+    mExtensionString += "GL_OES_standard_derivatives ";
+
+    if (supportsFloat16Textures())
+    {
+        mExtensionString += "GL_OES_texture_half_float ";
+    }
+    if (supportsFloat16LinearFilter())
+    {
+        mExtensionString += "GL_OES_texture_half_float_linear ";
+    }
+    if (supportsFloat32Textures())
+    {
+        mExtensionString += "GL_OES_texture_float ";
+    }
+    if (supportsFloat32LinearFilter())
+    {
+        mExtensionString += "GL_OES_texture_float_linear ";
+    }
+
+    if (supportsNonPower2Texture())
+    {
+        mExtensionString += "GL_OES_texture_npot ";
+    }
+
+    // Multi-vendor (EXT) extensions
+    if (supportsOcclusionQueries())
+    {
+        mExtensionString += "GL_EXT_occlusion_query_boolean ";
+    }
+
+    mExtensionString += "GL_EXT_read_format_bgra ";
+    mExtensionString += "GL_EXT_robustness ";
+
+    if (supportsDXT1Textures())
+    {
+        mExtensionString += "GL_EXT_texture_compression_dxt1 ";
+    }
+
+    if (supportsTextureFilterAnisotropy())
+    {
+        mExtensionString += "GL_EXT_texture_filter_anisotropic ";
+    }
+
+    mExtensionString += "GL_EXT_texture_format_BGRA8888 ";
+    mExtensionString += "GL_EXT_texture_storage ";
+
+    // ANGLE-specific extensions
+    if (supportsDepthTextures())
+    {
+        mExtensionString += "GL_ANGLE_depth_texture ";
+    }
+
+    mExtensionString += "GL_ANGLE_framebuffer_blit ";
+    if (getMaxSupportedSamples() != 0)
+    {
+        mExtensionString += "GL_ANGLE_framebuffer_multisample ";
+    }
+
+    if (supportsInstancing())
+    {
+        mExtensionString += "GL_ANGLE_instanced_arrays ";
+    }
+
+    mExtensionString += "GL_ANGLE_pack_reverse_row_order ";
+
+    if (supportsDXT3Textures())
+    {
+        mExtensionString += "GL_ANGLE_texture_compression_dxt3 ";
+    }
+    if (supportsDXT5Textures())
+    {
+        mExtensionString += "GL_ANGLE_texture_compression_dxt5 ";
+    }
+
+    mExtensionString += "GL_ANGLE_texture_usage ";
+    mExtensionString += "GL_ANGLE_translated_shader_source ";
+
+    // Other vendor-specific extensions
+    if (supportsEventQueries())
+    {
+        mExtensionString += "GL_NV_fence ";
+    }
+
+    std::string::size_type end = mExtensionString.find_last_not_of(' ');
+    if (end != std::string::npos)
+    {
+        mExtensionString.resize(end+1);
+    }
+}
+
+const char *Context::getExtensionString() const
+{
+    return mExtensionString.c_str();
+}
+
+void Context::initRendererString()
+{
+    D3DADAPTER_IDENTIFIER9 *identifier = mDisplay->getAdapterIdentifier();
+
+    mRendererString = "ANGLE (";
+    mRendererString += identifier->Description;
+    mRendererString += ")";
+}
+
+const char *Context::getRendererString() const
+{
+    return mRendererString.c_str();
+}
+
+void Context::blitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, 
+                              GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
+                              GLbitfield mask)
+{
+    Framebuffer *readFramebuffer = getReadFramebuffer();
+    Framebuffer *drawFramebuffer = getDrawFramebuffer();
+
+    if (!readFramebuffer || readFramebuffer->completeness() != GL_FRAMEBUFFER_COMPLETE ||
+        !drawFramebuffer || drawFramebuffer->completeness() != GL_FRAMEBUFFER_COMPLETE)
+    {
+        return error(GL_INVALID_FRAMEBUFFER_OPERATION);
+    }
+
+    if (drawFramebuffer->getSamples() != 0)
+    {
+        return error(GL_INVALID_OPERATION);
+    }
+
+    int readBufferWidth = readFramebuffer->getColorbuffer()->getWidth();
+    int readBufferHeight = readFramebuffer->getColorbuffer()->getHeight();
+    int drawBufferWidth = drawFramebuffer->getColorbuffer()->getWidth();
+    int drawBufferHeight = drawFramebuffer->getColorbuffer()->getHeight();
+
+    RECT sourceRect;
+    RECT destRect;
+
+    if (srcX0 < srcX1)
+    {
+        sourceRect.left = srcX0;
+        sourceRect.right = srcX1;
+        destRect.left = dstX0;
+        destRect.right = dstX1;
+    }
+    else
+    {
+        sourceRect.left = srcX1;
+        destRect.left = dstX1;
+        sourceRect.right = srcX0;
+        destRect.right = dstX0;
+    }
+
+    if (srcY0 < srcY1)
+    {
+        sourceRect.bottom = srcY1;
+        destRect.bottom = dstY1;
+        sourceRect.top = srcY0;
+        destRect.top = dstY0;
+    }
+    else
+    {
+        sourceRect.bottom = srcY0;
+        destRect.bottom = dstY0;
+        sourceRect.top = srcY1;
+        destRect.top = dstY1;
+    }
+
+    RECT sourceScissoredRect = sourceRect;
+    RECT destScissoredRect = destRect;
+
+    if (mState.scissorTest)
+    {
+        // Only write to parts of the destination framebuffer which pass the scissor test
+        // Please note: the destRect is now in D3D-style coordinates, so the *top* of the
+        // rect will be checked against scissorY, rather than the bottom.
+        if (destRect.left < mState.scissorX)
+        {
+            int xDiff = mState.scissorX - destRect.left;
+            destScissoredRect.left = mState.scissorX;
+            sourceScissoredRect.left += xDiff;
+        }
+
+        if (destRect.right > mState.scissorX + mState.scissorWidth)
+        {
+            int xDiff = destRect.right - (mState.scissorX + mState.scissorWidth);
+            destScissoredRect.right = mState.scissorX + mState.scissorWidth;
+            sourceScissoredRect.right -= xDiff;
+        }
+
+        if (destRect.top < mState.scissorY)
+        {
+            int yDiff = mState.scissorY - destRect.top;
+            destScissoredRect.top = mState.scissorY;
+            sourceScissoredRect.top += yDiff;
+        }
+
+        if (destRect.bottom > mState.scissorY + mState.scissorHeight)
+        {
+            int yDiff = destRect.bottom - (mState.scissorY + mState.scissorHeight);
+            destScissoredRect.bottom = mState.scissorY + mState.scissorHeight;
+            sourceScissoredRect.bottom -= yDiff;
+        }
+    }
+
+    bool blitRenderTarget = false;
+    bool blitDepthStencil = false;
+
+    RECT sourceTrimmedRect = sourceScissoredRect;
+    RECT destTrimmedRect = destScissoredRect;
+
+    // The source & destination rectangles also may need to be trimmed if they fall out of the bounds of 
+    // the actual draw and read surfaces.
+    if (sourceTrimmedRect.left < 0)
+    {
+        int xDiff = 0 - sourceTrimmedRect.left;
+        sourceTrimmedRect.left = 0;
+        destTrimmedRect.left += xDiff;
+    }
+
+    if (sourceTrimmedRect.right > readBufferWidth)
+    {
+        int xDiff = sourceTrimmedRect.right - readBufferWidth;
+        sourceTrimmedRect.right = readBufferWidth;
+        destTrimmedRect.right -= xDiff;
+    }
+
+    if (sourceTrimmedRect.top < 0)
+    {
+        int yDiff = 0 - sourceTrimmedRect.top;
+        sourceTrimmedRect.top = 0;
+        destTrimmedRect.top += yDiff;
+    }
+
+    if (sourceTrimmedRect.bottom > readBufferHeight)
+    {
+        int yDiff = sourceTrimmedRect.bottom - readBufferHeight;
+        sourceTrimmedRect.bottom = readBufferHeight;
+        destTrimmedRect.bottom -= yDiff;
+    }
+
+    if (destTrimmedRect.left < 0)
+    {
+        int xDiff = 0 - destTrimmedRect.left;
+        destTrimmedRect.left = 0;
+        sourceTrimmedRect.left += xDiff;
+    }
+
+    if (destTrimmedRect.right > drawBufferWidth)
+    {
+        int xDiff = destTrimmedRect.right - drawBufferWidth;
+        destTrimmedRect.right = drawBufferWidth;
+        sourceTrimmedRect.right -= xDiff;
+    }
+
+    if (destTrimmedRect.top < 0)
+    {
+        int yDiff = 0 - destTrimmedRect.top;
+        destTrimmedRect.top = 0;
+        sourceTrimmedRect.top += yDiff;
+    }
+
+    if (destTrimmedRect.bottom > drawBufferHeight)
+    {
+        int yDiff = destTrimmedRect.bottom - drawBufferHeight;
+        destTrimmedRect.bottom = drawBufferHeight;
+        sourceTrimmedRect.bottom -= yDiff;
+    }
+
+    bool partialBufferCopy = false;
+    if (sourceTrimmedRect.bottom - sourceTrimmedRect.top < readBufferHeight ||
+        sourceTrimmedRect.right - sourceTrimmedRect.left < readBufferWidth || 
+        destTrimmedRect.bottom - destTrimmedRect.top < drawBufferHeight ||
+        destTrimmedRect.right - destTrimmedRect.left < drawBufferWidth ||
+        sourceTrimmedRect.top != 0 || destTrimmedRect.top != 0 || sourceTrimmedRect.left != 0 || destTrimmedRect.left != 0)
+    {
+        partialBufferCopy = true;
+    }
+
+    if (mask & GL_COLOR_BUFFER_BIT)
+    {
+        const bool validReadType = readFramebuffer->getColorbufferType() == GL_TEXTURE_2D ||
+            readFramebuffer->getColorbufferType() == GL_RENDERBUFFER;
+        const bool validDrawType = drawFramebuffer->getColorbufferType() == GL_TEXTURE_2D ||
+            drawFramebuffer->getColorbufferType() == GL_RENDERBUFFER;
+        if (!validReadType || !validDrawType ||
+            readFramebuffer->getColorbuffer()->getD3DFormat() != drawFramebuffer->getColorbuffer()->getD3DFormat())
+        {
+            ERR("Color buffer format conversion in BlitFramebufferANGLE not supported by this implementation");
+            return error(GL_INVALID_OPERATION);
+        }
+        
+        if (partialBufferCopy && readFramebuffer->getSamples() != 0)
+        {
+            return error(GL_INVALID_OPERATION);
+        }
+
+        blitRenderTarget = true;
+
+    }
+
+    if (mask & (GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT))
+    {
+        Renderbuffer *readDSBuffer = NULL;
+        Renderbuffer *drawDSBuffer = NULL;
+
+        // We support OES_packed_depth_stencil, and do not support a separately attached depth and stencil buffer, so if we have
+        // both a depth and stencil buffer, it will be the same buffer.
+
+        if (mask & GL_DEPTH_BUFFER_BIT)
+        {
+            if (readFramebuffer->getDepthbuffer() && drawFramebuffer->getDepthbuffer())
+            {
+                if (readFramebuffer->getDepthbufferType() != drawFramebuffer->getDepthbufferType() ||
+                    readFramebuffer->getDepthbuffer()->getD3DFormat() != drawFramebuffer->getDepthbuffer()->getD3DFormat())
+                {
+                    return error(GL_INVALID_OPERATION);
+                }
+
+                blitDepthStencil = true;
+                readDSBuffer = readFramebuffer->getDepthbuffer();
+                drawDSBuffer = drawFramebuffer->getDepthbuffer();
+            }
+        }
+
+        if (mask & GL_STENCIL_BUFFER_BIT)
+        {
+            if (readFramebuffer->getStencilbuffer() && drawFramebuffer->getStencilbuffer())
+            {
+                if (readFramebuffer->getStencilbufferType() != drawFramebuffer->getStencilbufferType() ||
+                    readFramebuffer->getStencilbuffer()->getD3DFormat() != drawFramebuffer->getStencilbuffer()->getD3DFormat())
+                {
+                    return error(GL_INVALID_OPERATION);
+                }
+
+                blitDepthStencil = true;
+                readDSBuffer = readFramebuffer->getStencilbuffer();
+                drawDSBuffer = drawFramebuffer->getStencilbuffer();
+            }
+        }
+
+        if (partialBufferCopy)
+        {
+            ERR("Only whole-buffer depth and stencil blits are supported by this implementation.");
+            return error(GL_INVALID_OPERATION); // only whole-buffer copies are permitted
+        }
+
+        if ((drawDSBuffer && drawDSBuffer->getSamples() != 0) || 
+            (readDSBuffer && readDSBuffer->getSamples() != 0))
+        {
+            return error(GL_INVALID_OPERATION);
+        }
+    }
+
+    if (blitRenderTarget || blitDepthStencil)
+    {
+        mDisplay->endScene();
+
+        if (blitRenderTarget)
+        {
+            IDirect3DSurface9* readRenderTarget = readFramebuffer->getRenderTarget();
+            IDirect3DSurface9* drawRenderTarget = drawFramebuffer->getRenderTarget();
+
+            HRESULT result = mDevice->StretchRect(readRenderTarget, &sourceTrimmedRect, 
+                                                  drawRenderTarget, &destTrimmedRect, D3DTEXF_NONE);
+
+            readRenderTarget->Release();
+            drawRenderTarget->Release();
+
+            if (FAILED(result))
+            {
+                ERR("BlitFramebufferANGLE failed: StretchRect returned %x.", result);
+                return;
+            }
+        }
+
+        if (blitDepthStencil)
+        {
+            IDirect3DSurface9* readDepthStencil = readFramebuffer->getDepthStencil();
+            IDirect3DSurface9* drawDepthStencil = drawFramebuffer->getDepthStencil();
+
+            HRESULT result = mDevice->StretchRect(readDepthStencil, NULL, drawDepthStencil, NULL, D3DTEXF_NONE);
+
+            readDepthStencil->Release();
+            drawDepthStencil->Release();
+
+            if (FAILED(result))
+            {
+                ERR("BlitFramebufferANGLE failed: StretchRect returned %x.", result);
+                return;
+            }
+        }
+    }
+}
+
+VertexDeclarationCache::VertexDeclarationCache() : mMaxLru(0)
+{
+    for (int i = 0; i < NUM_VERTEX_DECL_CACHE_ENTRIES; i++)
+    {
+        mVertexDeclCache[i].vertexDeclaration = NULL;
+        mVertexDeclCache[i].lruCount = 0;
+    }
+}
+
+VertexDeclarationCache::~VertexDeclarationCache()
+{
+    for (int i = 0; i < NUM_VERTEX_DECL_CACHE_ENTRIES; i++)
+    {
+        if (mVertexDeclCache[i].vertexDeclaration)
+        {
+            mVertexDeclCache[i].vertexDeclaration->Release();
+        }
+    }
+}
+
+GLenum VertexDeclarationCache::applyDeclaration(IDirect3DDevice9 *device, TranslatedAttribute attributes[], ProgramBinary *programBinary, GLsizei instances, GLsizei *repeatDraw)
+{
+    *repeatDraw = 1;
+
+    int indexedAttribute = MAX_VERTEX_ATTRIBS;
+    int instancedAttribute = MAX_VERTEX_ATTRIBS;
+
+    if (instances > 0)
+    {
+        // Find an indexed attribute to be mapped to D3D stream 0
+        for (int i = 0; i < MAX_VERTEX_ATTRIBS; i++)
+        {
+            if (attributes[i].active)
+            {
+                if (indexedAttribute == MAX_VERTEX_ATTRIBS)
+                {
+                    if (attributes[i].divisor == 0)
+                    {
+                        indexedAttribute = i;
+                    }
+                }
+                else if (instancedAttribute == MAX_VERTEX_ATTRIBS)
+                {
+                    if (attributes[i].divisor != 0)
+                    {
+                        instancedAttribute = i;
+                    }
+                }
+                else break;   // Found both an indexed and instanced attribute
+            }
+        }
+
+        if (indexedAttribute == MAX_VERTEX_ATTRIBS)
+        {
+            return GL_INVALID_OPERATION;
+        }
+    }
+
+    D3DVERTEXELEMENT9 elements[MAX_VERTEX_ATTRIBS + 1];
+    D3DVERTEXELEMENT9 *element = &elements[0];
+
+    for (int i = 0; i < MAX_VERTEX_ATTRIBS; i++)
+    {
+        if (attributes[i].active)
+        {
+            int stream = i;
+
+            if (instances > 0)
+            {
+                // Due to a bug on ATI cards we can't enable instancing when none of the attributes are instanced.
+                if (instancedAttribute == MAX_VERTEX_ATTRIBS)
+                {
+                    *repeatDraw = instances;
+                }
+                else
+                {
+                    if (i == indexedAttribute)
+                    {
+                        stream = 0;
+                    }
+                    else if (i == 0)
+                    {
+                        stream = indexedAttribute;
+                    }
+
+                    UINT frequency = 1;
+                    
+                    if (attributes[i].divisor == 0)
+                    {
+                        frequency = D3DSTREAMSOURCE_INDEXEDDATA | instances;
+                    }
+                    else
+                    {
+                        frequency = D3DSTREAMSOURCE_INSTANCEDATA | attributes[i].divisor;
+                    }
+                    
+                    device->SetStreamSourceFreq(stream, frequency);
+                    mInstancingEnabled = true;
+                }
+            }
+
+            if (mAppliedVBs[stream].serial != attributes[i].serial ||
+                mAppliedVBs[stream].stride != attributes[i].stride ||
+                mAppliedVBs[stream].offset != attributes[i].offset)
+            {
+                device->SetStreamSource(stream, attributes[i].vertexBuffer, attributes[i].offset, attributes[i].stride);
+                mAppliedVBs[stream].serial = attributes[i].serial;
+                mAppliedVBs[stream].stride = attributes[i].stride;
+                mAppliedVBs[stream].offset = attributes[i].offset;
+            }
+
+            element->Stream = stream;
+            element->Offset = 0;
+            element->Type = attributes[i].type;
+            element->Method = D3DDECLMETHOD_DEFAULT;
+            element->Usage = D3DDECLUSAGE_TEXCOORD;
+            element->UsageIndex = programBinary->getSemanticIndex(i);
+            element++;
+        }
+    }
+
+    if (instances == 0 || instancedAttribute == MAX_VERTEX_ATTRIBS)
+    {
+        if (mInstancingEnabled)
+        {
+            for (int i = 0; i < MAX_VERTEX_ATTRIBS; i++)
+            {
+                device->SetStreamSourceFreq(i, 1);
+            }
+
+            mInstancingEnabled = false;
+        }
+    }
+
+    static const D3DVERTEXELEMENT9 end = D3DDECL_END();
+    *(element++) = end;
+
+    for (int i = 0; i < NUM_VERTEX_DECL_CACHE_ENTRIES; i++)
+    {
+        VertexDeclCacheEntry *entry = &mVertexDeclCache[i];
+        if (memcmp(entry->cachedElements, elements, (element - elements) * sizeof(D3DVERTEXELEMENT9)) == 0 && entry->vertexDeclaration)
+        {
+            entry->lruCount = ++mMaxLru;
+            if(entry->vertexDeclaration != mLastSetVDecl)
+            {
+                device->SetVertexDeclaration(entry->vertexDeclaration);
+                mLastSetVDecl = entry->vertexDeclaration;
+            }
+
+            return GL_NO_ERROR;
+        }
+    }
+
+    VertexDeclCacheEntry *lastCache = mVertexDeclCache;
+
+    for (int i = 0; i < NUM_VERTEX_DECL_CACHE_ENTRIES; i++)
+    {
+        if (mVertexDeclCache[i].lruCount < lastCache->lruCount)
+        {
+            lastCache = &mVertexDeclCache[i];
+        }
+    }
+
+    if (lastCache->vertexDeclaration != NULL)
+    {
+        lastCache->vertexDeclaration->Release();
+        lastCache->vertexDeclaration = NULL;
+        // mLastSetVDecl is set to the replacement, so we don't have to worry
+        // about it.
+    }
+
+    memcpy(lastCache->cachedElements, elements, (element - elements) * sizeof(D3DVERTEXELEMENT9));
+    device->CreateVertexDeclaration(elements, &lastCache->vertexDeclaration);
+    device->SetVertexDeclaration(lastCache->vertexDeclaration);
+    mLastSetVDecl = lastCache->vertexDeclaration;
+    lastCache->lruCount = ++mMaxLru;
+
+    return GL_NO_ERROR;
+}
+
+void VertexDeclarationCache::markStateDirty()
+{
+    for (int i = 0; i < MAX_VERTEX_ATTRIBS; i++)
+    {
+        mAppliedVBs[i].serial = 0;
+    }
+
+    mLastSetVDecl = NULL;
+    mInstancingEnabled = true;   // Forces it to be disabled when not used
+}
+
+}
+
+extern "C"
+{
+gl::Context *glCreateContext(const egl::Config *config, const gl::Context *shareContext, bool notifyResets, bool robustAccess)
+{
+    return new gl::Context(config, shareContext, notifyResets, robustAccess);
+}
+
+void glDestroyContext(gl::Context *context)
+{
+    delete context;
+
+    if (context == gl::getContext())
+    {
+        gl::makeCurrent(NULL, NULL, NULL);
+    }
+}
+
+void glMakeCurrent(gl::Context *context, egl::Display *display, egl::Surface *surface)
+{
+    gl::makeCurrent(context, display, surface);
+}
+
+gl::Context *glGetCurrentContext()
+{
+    return gl::getContext();
+}
+}
diff --git a/src/3rdparty/angle/src/libGLESv2/Context.h b/src/3rdparty/angle/src/libGLESv2/Context.h
new file mode 100644 (file)
index 0000000..2bbae76
--- /dev/null
@@ -0,0 +1,685 @@
+//
+// 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.
+//
+
+// Context.h: Defines the gl::Context class, managing all GL state and performing
+// rendering operations. It is the GLES2 specific implementation of EGLContext.
+
+#ifndef LIBGLESV2_CONTEXT_H_
+#define LIBGLESV2_CONTEXT_H_
+
+#define GL_APICALL
+#include <GLES2/gl2.h>
+#include <GLES2/gl2ext.h>
+#define EGLAPI
+#include <EGL/egl.h>
+#include <d3d9.h>
+
+#include <string>
+#include <map>
+#ifdef _MSC_VER
+#include <hash_map>
+#else
+#include <unordered_map>
+#endif
+
+#include "common/angleutils.h"
+#include "common/RefCountObject.h"
+#include "libGLESv2/ResourceManager.h"
+#include "libGLESv2/HandleAllocator.h"
+
+namespace egl
+{
+class Display;
+class Surface;
+class Config;
+}
+
+namespace gl
+{
+struct TranslatedAttribute;
+struct TranslatedIndexData;
+
+class Buffer;
+class Shader;
+class Program;
+class ProgramBinary;
+class Texture;
+class Texture2D;
+class TextureCubeMap;
+class Framebuffer;
+class Renderbuffer;
+class RenderbufferStorage;
+class Colorbuffer;
+class Depthbuffer;
+class StreamingIndexBuffer;
+class Stencilbuffer;
+class DepthStencilbuffer;
+class VertexDataManager;
+class IndexDataManager;
+class Blit;
+class Fence;
+class Query;
+
+enum
+{
+    D3D9_MAX_FLOAT_CONSTANTS = 256,
+    D3D9_MAX_BOOL_CONSTANTS = 16,
+    D3D9_MAX_INT_CONSTANTS = 16,
+
+    MAX_VERTEX_ATTRIBS = 16,
+    MAX_VERTEX_UNIFORM_VECTORS = D3D9_MAX_FLOAT_CONSTANTS - 2,   // Reserve space for dx_HalfPixelSize and dx_DepthRange.
+    MAX_VARYING_VECTORS_SM2 = 8,
+    MAX_VARYING_VECTORS_SM3 = 10,
+    MAX_TEXTURE_IMAGE_UNITS = 16,
+    MAX_VERTEX_TEXTURE_IMAGE_UNITS_VTF = 4,   // For devices supporting vertex texture fetch
+    MAX_COMBINED_TEXTURE_IMAGE_UNITS_VTF = MAX_TEXTURE_IMAGE_UNITS + MAX_VERTEX_TEXTURE_IMAGE_UNITS_VTF,    
+    MAX_FRAGMENT_UNIFORM_VECTORS_SM2 = 32 - 3,    // Reserve space for dx_Coord, dx_Depth, and dx_DepthRange. dx_PointOrLines and dx_FrontCCW use separate bool registers.
+    MAX_FRAGMENT_UNIFORM_VECTORS_SM3 = 224 - 3,
+    MAX_DRAW_BUFFERS = 1,
+
+    GL_BGRA4_ANGLEX = 0x6ABC,
+    GL_BGR5_A1_ANGLEX = 0x6ABD
+};
+
+enum QueryType
+{
+    QUERY_ANY_SAMPLES_PASSED,
+    QUERY_ANY_SAMPLES_PASSED_CONSERVATIVE,
+
+    QUERY_TYPE_COUNT
+};
+
+const float ALIASED_LINE_WIDTH_RANGE_MIN = 1.0f;
+const float ALIASED_LINE_WIDTH_RANGE_MAX = 1.0f;
+const float ALIASED_POINT_SIZE_RANGE_MIN = 1.0f;
+const float ALIASED_POINT_SIZE_RANGE_MAX_SM2 = 1.0f;
+
+struct Color
+{
+    float red;
+    float green;
+    float blue;
+    float alpha;
+};
+
+// Helper structure describing a single vertex attribute
+class VertexAttribute
+{
+  public:
+    VertexAttribute() : mType(GL_FLOAT), mSize(0), mNormalized(false), mStride(0), mPointer(NULL), mArrayEnabled(false), mDivisor(0)
+    {
+        mCurrentValue[0] = 0.0f;
+        mCurrentValue[1] = 0.0f;
+        mCurrentValue[2] = 0.0f;
+        mCurrentValue[3] = 1.0f;
+    }
+
+    int typeSize() const
+    {
+        switch (mType)
+        {
+          case GL_BYTE:           return mSize * sizeof(GLbyte);
+          case GL_UNSIGNED_BYTE:  return mSize * sizeof(GLubyte);
+          case GL_SHORT:          return mSize * sizeof(GLshort);
+          case GL_UNSIGNED_SHORT: return mSize * sizeof(GLushort);
+          case GL_FIXED:          return mSize * sizeof(GLfixed);
+          case GL_FLOAT:          return mSize * sizeof(GLfloat);
+          default: UNREACHABLE(); return mSize * sizeof(GLfloat);
+        }
+    }
+
+    GLsizei stride() const
+    {
+        return mStride ? mStride : typeSize();
+    }
+
+    // From glVertexAttribPointer
+    GLenum mType;
+    GLint mSize;
+    bool mNormalized;
+    GLsizei mStride;   // 0 means natural stride
+
+    union
+    {
+        const void *mPointer;
+        intptr_t mOffset;
+    };
+
+    BindingPointer<Buffer> mBoundBuffer;   // Captured when glVertexAttribPointer is called.
+
+    bool mArrayEnabled;   // From glEnable/DisableVertexAttribArray
+    float mCurrentValue[4];   // From glVertexAttrib
+    unsigned int mDivisor;
+};
+
+typedef VertexAttribute VertexAttributeArray[MAX_VERTEX_ATTRIBS];
+
+// Helper structure to store all raw state
+struct State
+{
+    Color colorClearValue;
+    GLclampf depthClearValue;
+    int stencilClearValue;
+
+    bool cullFace;
+    GLenum cullMode;
+    GLenum frontFace;
+    bool depthTest;
+    GLenum depthFunc;
+    bool blend;
+    GLenum sourceBlendRGB;
+    GLenum destBlendRGB;
+    GLenum sourceBlendAlpha;
+    GLenum destBlendAlpha;
+    GLenum blendEquationRGB;
+    GLenum blendEquationAlpha;
+    Color blendColor;
+    bool stencilTest;
+    GLenum stencilFunc;
+    GLint stencilRef;
+    GLuint stencilMask;
+    GLenum stencilFail;
+    GLenum stencilPassDepthFail;
+    GLenum stencilPassDepthPass;
+    GLuint stencilWritemask;
+    GLenum stencilBackFunc;
+    GLint stencilBackRef;
+    GLuint stencilBackMask;
+    GLenum stencilBackFail;
+    GLenum stencilBackPassDepthFail;
+    GLenum stencilBackPassDepthPass;
+    GLuint stencilBackWritemask;
+    bool polygonOffsetFill;
+    GLfloat polygonOffsetFactor;
+    GLfloat polygonOffsetUnits;
+    bool sampleAlphaToCoverage;
+    bool sampleCoverage;
+    GLclampf sampleCoverageValue;
+    bool sampleCoverageInvert;
+    bool scissorTest;
+    bool dither;
+
+    GLfloat lineWidth;
+
+    GLenum generateMipmapHint;
+    GLenum fragmentShaderDerivativeHint;
+
+    GLint viewportX;
+    GLint viewportY;
+    GLsizei viewportWidth;
+    GLsizei viewportHeight;
+    float zNear;
+    float zFar;
+
+    GLint scissorX;
+    GLint scissorY;
+    GLsizei scissorWidth;
+    GLsizei scissorHeight;
+
+    bool colorMaskRed;
+    bool colorMaskGreen;
+    bool colorMaskBlue;
+    bool colorMaskAlpha;
+    bool depthMask;
+
+    unsigned int activeSampler;   // Active texture unit selector - GL_TEXTURE0
+    BindingPointer<Buffer> arrayBuffer;
+    BindingPointer<Buffer> elementArrayBuffer;
+    GLuint readFramebuffer;
+    GLuint drawFramebuffer;
+    BindingPointer<Renderbuffer> renderbuffer;
+    GLuint currentProgram;
+
+    VertexAttribute vertexAttribute[MAX_VERTEX_ATTRIBS];
+    BindingPointer<Texture> samplerTexture[TEXTURE_TYPE_COUNT][MAX_COMBINED_TEXTURE_IMAGE_UNITS_VTF];
+    BindingPointer<Query> activeQuery[QUERY_TYPE_COUNT];
+
+    GLint unpackAlignment;
+    GLint packAlignment;
+    bool packReverseRowOrder;
+};
+
+// Helper class to construct and cache vertex declarations
+class VertexDeclarationCache
+{
+  public:
+    VertexDeclarationCache();
+    ~VertexDeclarationCache();
+
+    GLenum applyDeclaration(IDirect3DDevice9 *device, TranslatedAttribute attributes[], ProgramBinary *programBinary, GLsizei instances, GLsizei *repeatDraw);
+
+    void markStateDirty();
+
+  private:
+    UINT mMaxLru;
+
+    enum { NUM_VERTEX_DECL_CACHE_ENTRIES = 32 };
+
+    struct VBData
+    {
+        unsigned int serial;
+        unsigned int stride;
+        unsigned int offset;
+    };
+
+    VBData mAppliedVBs[MAX_VERTEX_ATTRIBS];
+    IDirect3DVertexDeclaration9 *mLastSetVDecl;
+    bool mInstancingEnabled;
+
+    struct VertexDeclCacheEntry
+    {
+        D3DVERTEXELEMENT9 cachedElements[MAX_VERTEX_ATTRIBS + 1];
+        UINT lruCount;
+        IDirect3DVertexDeclaration9 *vertexDeclaration;
+    } mVertexDeclCache[NUM_VERTEX_DECL_CACHE_ENTRIES];
+};
+
+class Context
+{
+  public:
+    Context(const egl::Config *config, const gl::Context *shareContext, bool notifyResets, bool robustAccess);
+
+    ~Context();
+
+    void makeCurrent(egl::Display *display, egl::Surface *surface);
+
+    virtual void markAllStateDirty();
+    void markDxUniformsDirty();
+
+    virtual void markContextLost();
+    bool isContextLost();
+
+    // State manipulation
+    void setClearColor(float red, float green, float blue, float alpha);
+
+    void setClearDepth(float depth);
+
+    void setClearStencil(int stencil);
+
+    void setCullFace(bool enabled);
+    bool isCullFaceEnabled() const;
+
+    void setCullMode(GLenum mode);
+
+    void setFrontFace(GLenum front);
+
+    void setDepthTest(bool enabled);
+    bool isDepthTestEnabled() const;
+
+    void setDepthFunc(GLenum depthFunc);
+
+    void setDepthRange(float zNear, float zFar);
+    
+    void setBlend(bool enabled);
+    bool isBlendEnabled() const;
+
+    void setBlendFactors(GLenum sourceRGB, GLenum destRGB, GLenum sourceAlpha, GLenum destAlpha);
+    void setBlendColor(float red, float green, float blue, float alpha);
+    void setBlendEquation(GLenum rgbEquation, GLenum alphaEquation);
+
+    void setStencilTest(bool enabled);
+    bool isStencilTestEnabled() const;
+
+    void setStencilParams(GLenum stencilFunc, GLint stencilRef, GLuint stencilMask);
+    void setStencilBackParams(GLenum stencilBackFunc, GLint stencilBackRef, GLuint stencilBackMask);
+    void setStencilWritemask(GLuint stencilWritemask);
+    void setStencilBackWritemask(GLuint stencilBackWritemask);
+    void setStencilOperations(GLenum stencilFail, GLenum stencilPassDepthFail, GLenum stencilPassDepthPass);
+    void setStencilBackOperations(GLenum stencilBackFail, GLenum stencilBackPassDepthFail, GLenum stencilBackPassDepthPass);
+
+    void setPolygonOffsetFill(bool enabled);
+    bool isPolygonOffsetFillEnabled() const;
+
+    void setPolygonOffsetParams(GLfloat factor, GLfloat units);
+
+    void setSampleAlphaToCoverage(bool enabled);
+    bool isSampleAlphaToCoverageEnabled() const;
+
+    void setSampleCoverage(bool enabled);
+    bool isSampleCoverageEnabled() const;
+
+    void setSampleCoverageParams(GLclampf value, bool invert);
+
+    void setScissorTest(bool enabled);
+    bool isScissorTestEnabled() const;
+
+    void setDither(bool enabled);
+    bool isDitherEnabled() const;
+
+    void setLineWidth(GLfloat width);
+
+    void setGenerateMipmapHint(GLenum hint);
+    void setFragmentShaderDerivativeHint(GLenum hint);
+
+    void setViewportParams(GLint x, GLint y, GLsizei width, GLsizei height);
+
+    void setScissorParams(GLint x, GLint y, GLsizei width, GLsizei height);
+
+    void setColorMask(bool red, bool green, bool blue, bool alpha);
+    void setDepthMask(bool mask);
+
+    void setActiveSampler(unsigned int active);
+
+    GLuint getReadFramebufferHandle() const;
+    GLuint getDrawFramebufferHandle() const;
+    GLuint getRenderbufferHandle() const;
+
+    GLuint getArrayBufferHandle() const;
+
+    GLuint getActiveQuery(GLenum target) const;
+
+    void setEnableVertexAttribArray(unsigned int attribNum, bool enabled);
+    const VertexAttribute &getVertexAttribState(unsigned int attribNum);
+    void setVertexAttribState(unsigned int attribNum, Buffer *boundBuffer, GLint size, GLenum type,
+                              bool normalized, GLsizei stride, const void *pointer);
+    const void *getVertexAttribPointer(unsigned int attribNum) const;
+
+    const VertexAttributeArray &getVertexAttributes();
+
+    void setUnpackAlignment(GLint alignment);
+    GLint getUnpackAlignment() const;
+
+    void setPackAlignment(GLint alignment);
+    GLint getPackAlignment() const;
+
+    void setPackReverseRowOrder(bool reverseRowOrder);
+    bool getPackReverseRowOrder() const;
+
+    // These create  and destroy methods are merely pass-throughs to 
+    // ResourceManager, which owns these object types
+    GLuint createBuffer();
+    GLuint createShader(GLenum type);
+    GLuint createProgram();
+    GLuint createTexture();
+    GLuint createRenderbuffer();
+
+    void deleteBuffer(GLuint buffer);
+    void deleteShader(GLuint shader);
+    void deleteProgram(GLuint program);
+    void deleteTexture(GLuint texture);
+    void deleteRenderbuffer(GLuint renderbuffer);
+
+    // Framebuffers are owned by the Context, so these methods do not pass through
+    GLuint createFramebuffer();
+    void deleteFramebuffer(GLuint framebuffer);
+
+    // Fences are owned by the Context.
+    GLuint createFence();
+    void deleteFence(GLuint fence);
+    
+    // Queries are owned by the Context;
+    GLuint createQuery();
+    void deleteQuery(GLuint query);
+
+    void bindArrayBuffer(GLuint buffer);
+    void bindElementArrayBuffer(GLuint buffer);
+    void bindTexture2D(GLuint texture);
+    void bindTextureCubeMap(GLuint texture);
+    void bindReadFramebuffer(GLuint framebuffer);
+    void bindDrawFramebuffer(GLuint framebuffer);
+    void bindRenderbuffer(GLuint renderbuffer);
+    void useProgram(GLuint program);
+    void linkProgram(GLuint program);
+    void setProgramBinary(GLuint program, const void *binary, GLint length);
+
+    void beginQuery(GLenum target, GLuint query);
+    void endQuery(GLenum target);
+
+    void setFramebufferZero(Framebuffer *framebuffer);
+
+    void setRenderbufferStorage(RenderbufferStorage *renderbuffer);
+
+    void setVertexAttrib(GLuint index, const GLfloat *values);
+    void setVertexAttribDivisor(GLuint index, GLuint divisor);
+
+    Buffer *getBuffer(GLuint handle);
+    Fence *getFence(GLuint handle);
+    Shader *getShader(GLuint handle);
+    Program *getProgram(GLuint handle);
+    Texture *getTexture(GLuint handle);
+    Framebuffer *getFramebuffer(GLuint handle);
+    Renderbuffer *getRenderbuffer(GLuint handle);
+    Query *getQuery(GLuint handle, bool create, GLenum type);
+
+    Buffer *getArrayBuffer();
+    Buffer *getElementArrayBuffer();
+    ProgramBinary *getCurrentProgramBinary();
+    Texture2D *getTexture2D();
+    TextureCubeMap *getTextureCubeMap();
+    Texture *getSamplerTexture(unsigned int sampler, TextureType type);
+    Framebuffer *getReadFramebuffer();
+    Framebuffer *getDrawFramebuffer();
+
+    bool getFloatv(GLenum pname, GLfloat *params);
+    bool getIntegerv(GLenum pname, GLint *params);
+    bool getBooleanv(GLenum pname, GLboolean *params);
+
+    bool getQueryParameterInfo(GLenum pname, GLenum *type, unsigned int *numParams);
+
+    void readPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLsizei *bufSize, void* pixels);
+    void clear(GLbitfield mask);
+    void drawArrays(GLenum mode, GLint first, GLsizei count, GLsizei instances);
+    void drawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, GLsizei instances);
+    void sync(bool block);   // flush/finish
+
+    void drawLineLoop(GLsizei count, GLenum type, const GLvoid *indices, int minIndex);
+
+    void recordInvalidEnum();
+    void recordInvalidValue();
+    void recordInvalidOperation();
+    void recordOutOfMemory();
+    void recordInvalidFramebufferOperation();
+
+    GLenum getError();
+    GLenum getResetStatus();
+    virtual bool isResetNotificationEnabled();
+
+    bool supportsShaderModel3() const;
+    float getMaximumPointSize() const;
+    int getMaximumVaryingVectors() const;
+    unsigned int getMaximumVertexTextureImageUnits() const;
+    unsigned int getMaximumCombinedTextureImageUnits() const;
+    int getMaximumFragmentUniformVectors() const;
+    int getMaximumRenderbufferDimension() const;
+    int getMaximumTextureDimension() const;
+    int getMaximumCubeTextureDimension() const;
+    int getMaximumTextureLevel() const;
+    GLsizei getMaxSupportedSamples() const;
+    int getNearestSupportedSamples(D3DFORMAT format, int requested) const;
+    const char *getExtensionString() const;
+    const char *getRendererString() const;
+    bool supportsEventQueries() const;
+    bool supportsOcclusionQueries() const;
+    bool supportsDXT1Textures() const;
+    bool supportsDXT3Textures() const;
+    bool supportsDXT5Textures() const;
+    bool supportsFloat32Textures() const;
+    bool supportsFloat32LinearFilter() const;
+    bool supportsFloat32RenderableTextures() const;
+    bool supportsFloat16Textures() const;
+    bool supportsFloat16LinearFilter() const;
+    bool supportsFloat16RenderableTextures() const;
+    bool supportsLuminanceTextures() const;
+    bool supportsLuminanceAlphaTextures() const;
+    bool supportsDepthTextures() const;
+    bool supports32bitIndices() const;
+    bool supportsNonPower2Texture() const;
+    bool supportsInstancing() const;
+    bool supportsTextureFilterAnisotropy() const;
+
+    bool getCurrentReadFormatType(GLenum *format, GLenum *type);
+
+    float getTextureMaxAnisotropy() const;
+
+    void blitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, 
+                         GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
+                         GLbitfield mask);
+
+    Blit *getBlitter() { return mBlit; }
+
+    const D3DCAPS9 &getDeviceCaps() { return mDeviceCaps; }
+
+  private:
+    DISALLOW_COPY_AND_ASSIGN(Context);
+
+    bool applyRenderTarget(bool ignoreViewport);
+    void applyState(GLenum drawMode);
+    GLenum applyVertexBuffer(GLint first, GLsizei count, GLsizei instances, GLsizei *repeatDraw);
+    GLenum applyIndexBuffer(const GLvoid *indices, GLsizei count, GLenum mode, GLenum type, TranslatedIndexData *indexInfo);
+    void applyShaders();
+    void applyTextures();
+    void applyTextures(SamplerType type);
+
+    void detachBuffer(GLuint buffer);
+    void detachTexture(GLuint texture);
+    void detachFramebuffer(GLuint framebuffer);
+    void detachRenderbuffer(GLuint renderbuffer);
+
+    Texture *getIncompleteTexture(TextureType type);
+
+    bool skipDraw(GLenum drawMode);
+    bool isTriangleMode(GLenum drawMode);
+
+    void initExtensionString();
+    void initRendererString();
+
+    const egl::Config *const mConfig;
+    egl::Display *mDisplay;
+    IDirect3DDevice9 *mDevice;
+
+    State mState;
+
+    BindingPointer<Texture2D> mTexture2DZero;
+    BindingPointer<TextureCubeMap> mTextureCubeMapZero;
+
+#ifndef HASH_MAP
+# ifdef _MSC_VER
+#  define HASH_MAP stdext::hash_map
+# else
+#  define HASH_MAP std::unordered_map
+# endif
+#endif
+
+    typedef HASH_MAP<GLuint, Framebuffer*> FramebufferMap;
+    FramebufferMap mFramebufferMap;
+    HandleAllocator mFramebufferHandleAllocator;
+
+    typedef HASH_MAP<GLuint, Fence*> FenceMap;
+    FenceMap mFenceMap;
+    HandleAllocator mFenceHandleAllocator;
+
+    typedef HASH_MAP<GLuint, Query*> QueryMap;
+    QueryMap mQueryMap;
+    HandleAllocator mQueryHandleAllocator;
+
+    std::string mExtensionString;
+    std::string mRendererString;
+
+    VertexDataManager *mVertexDataManager;
+    IndexDataManager *mIndexDataManager;
+
+    Blit *mBlit;
+
+    StreamingIndexBuffer *mLineLoopIB;
+    
+    BindingPointer<Texture> mIncompleteTextures[TEXTURE_TYPE_COUNT];
+
+    // Recorded errors
+    bool mInvalidEnum;
+    bool mInvalidValue;
+    bool mInvalidOperation;
+    bool mOutOfMemory;
+    bool mInvalidFramebufferOperation;
+
+    // Current/lost context flags
+    bool mHasBeenCurrent;
+    bool mContextLost;
+    GLenum mResetStatus;
+    GLenum mResetStrategy;
+    bool mRobustAccess;
+
+    unsigned int mAppliedTextureSerialPS[MAX_TEXTURE_IMAGE_UNITS];
+    unsigned int mAppliedTextureSerialVS[MAX_VERTEX_TEXTURE_IMAGE_UNITS_VTF];
+    unsigned int mAppliedProgramBinarySerial;
+    unsigned int mAppliedRenderTargetSerial;
+    unsigned int mAppliedDepthbufferSerial;
+    unsigned int mAppliedStencilbufferSerial;
+    unsigned int mAppliedIBSerial;
+    bool mDepthStencilInitialized;
+    bool mViewportInitialized;
+    D3DVIEWPORT9 mSetViewport;
+    bool mRenderTargetDescInitialized;
+    D3DSURFACE_DESC mRenderTargetDesc;
+    bool mDxUniformsDirty;
+    BindingPointer<ProgramBinary> mCurrentProgramBinary;
+    Framebuffer *mBoundDrawFramebuffer;
+
+    bool mSupportsShaderModel3;
+    float mMaximumPointSize;
+    bool mSupportsVertexTexture;
+    bool mSupportsNonPower2Texture;
+    bool mSupportsInstancing;
+    int  mMaxRenderbufferDimension;
+    int  mMaxTextureDimension;
+    int  mMaxCubeTextureDimension;
+    int  mMaxTextureLevel;
+    float mMaxTextureAnisotropy;
+    std::map<D3DFORMAT, bool *> mMultiSampleSupport;
+    GLsizei mMaxSupportedSamples;
+    bool mSupportsEventQueries;
+    bool mSupportsOcclusionQueries;
+    bool mSupportsDXT1Textures;
+    bool mSupportsDXT3Textures;
+    bool mSupportsDXT5Textures;
+    bool mSupportsFloat32Textures;
+    bool mSupportsFloat32LinearFilter;
+    bool mSupportsFloat32RenderableTextures;
+    bool mSupportsFloat16Textures;
+    bool mSupportsFloat16LinearFilter;
+    bool mSupportsFloat16RenderableTextures;
+    bool mSupportsLuminanceTextures;
+    bool mSupportsLuminanceAlphaTextures;
+    bool mSupportsDepthTextures;
+    bool mSupports32bitIndices;
+    bool mSupportsTextureFilterAnisotropy;
+    int mNumCompressedTextureFormats;
+
+    // state caching flags
+    bool mClearStateDirty;
+    bool mCullStateDirty;
+    bool mDepthStateDirty;
+    bool mMaskStateDirty;
+    bool mPixelPackingStateDirty;
+    bool mBlendStateDirty;
+    bool mStencilStateDirty;
+    bool mPolygonOffsetStateDirty;
+    bool mScissorStateDirty;
+    bool mSampleStateDirty;
+    bool mFrontFaceDirty;
+    bool mDitherStateDirty;
+
+    IDirect3DStateBlock9 *mMaskedClearSavedState;
+
+    D3DCAPS9 mDeviceCaps;
+
+    ResourceManager *mResourceManager;
+
+    VertexDeclarationCache mVertexDeclarationCache;
+};
+}
+
+extern "C"
+{
+// Exported functions for use by EGL
+gl::Context *glCreateContext(const egl::Config *config, const gl::Context *shareContext, bool notifyResets, bool robustAccess);
+void glDestroyContext(gl::Context *context);
+void glMakeCurrent(gl::Context *context, egl::Display *display, egl::Surface *surface);
+gl::Context *glGetCurrentContext();
+__eglMustCastToProperFunctionPointerType __stdcall glGetProcAddress(const char *procname);
+bool __stdcall glBindTexImage(egl::Surface *surface);
+}
+
+#endif   // INCLUDE_CONTEXT_H_
diff --git a/src/3rdparty/angle/src/libGLESv2/D3DConstantTable.cpp b/src/3rdparty/angle/src/libGLESv2/D3DConstantTable.cpp
new file mode 100644 (file)
index 0000000..e136951
--- /dev/null
@@ -0,0 +1,231 @@
+//
+// 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.
+//
+
+// D3DConstantTable.cpp: Implements the D3DConstantTable class which parses
+// information about constants from the CTAB comment in a D3D shader blob.
+// Restructures the constant table as a hierarchy of constants in the same
+// way as D3DX.
+
+#include "libGLESv2/D3DConstantTable.h"
+
+#include <d3d9.h>
+#include <d3d9types.h>
+#include <windows.h>
+#include <mmsystem.h>
+
+#include "libGLESv2/BinaryStream.h"
+
+const static int SHADER_VERSION_MASK = D3DVS_VERSION(0, 0);
+const static int FOURCC_CTAB = MAKEFOURCC('C','T','A','B');
+
+namespace gl
+{
+// These structs and constants correspond to the format of the constant table in a shader binary.
+// They match the corresponding structures in d3dx9shader.h.
+namespace ctab
+{
+struct ConstantTable
+{
+    DWORD size;
+    DWORD creator;
+    DWORD version;
+    DWORD constants;
+    DWORD constantInfos;
+    DWORD flags;
+    DWORD target;
+};
+
+struct ConstantInfo
+{
+    DWORD name;
+    WORD registerSet;
+    WORD registerIndex;
+    WORD registerCount;
+    WORD reserved;
+    DWORD typeInfo;
+    DWORD defaultValue;
+};
+
+struct TypeInfo
+{
+    WORD typeClass;
+    WORD type;
+    WORD rows;
+    WORD columns;
+    WORD elements;
+    WORD structMembers;
+    DWORD structMemberInfos;
+};
+
+struct StructMemberInfo
+{
+    DWORD name;
+    DWORD typeInfo;
+};
+}
+
+D3DConstant::D3DConstant(const char *base, const ctab::ConstantInfo *constantInfo)
+{
+    const ctab::TypeInfo *typeInfo = reinterpret_cast<const ctab::TypeInfo*>(base + constantInfo->typeInfo);
+
+    name = base + constantInfo->name;
+    registerSet = static_cast<RegisterSet>(constantInfo->registerSet);
+    registerIndex = constantInfo->registerIndex;
+    registerCount = constantInfo->registerCount;
+    typeClass = static_cast<Class>(typeInfo->typeClass);
+    type = static_cast<Type>(typeInfo->type);
+    rows = typeInfo->rows;
+    columns = typeInfo->columns;
+    elements = typeInfo->elements;
+
+    if (typeClass == CLASS_STRUCT)
+    {
+        addStructMembers(base, registerSet, registerIndex, typeInfo);
+    }
+}
+
+D3DConstant::D3DConstant(const char *base, RegisterSet registerSet, unsigned registerIndex, const ctab::StructMemberInfo *memberInfo)
+    : registerSet(registerSet), registerIndex(registerIndex)
+{
+    const ctab::TypeInfo *typeInfo = reinterpret_cast<const ctab::TypeInfo*>(base + memberInfo->typeInfo);
+
+    name = base + memberInfo->name;
+    registerCount = typeInfo->rows * typeInfo->elements;
+    typeClass = static_cast<Class>(typeInfo->typeClass);
+    type = static_cast<Type>(typeInfo->type);
+    rows = typeInfo->rows;
+    columns = typeInfo->columns;
+    elements = typeInfo->elements;
+
+    if (typeClass == CLASS_STRUCT)
+    {
+        registerCount = addStructMembers(base, registerSet, registerIndex, typeInfo);
+    }
+}
+
+D3DConstant::~D3DConstant()
+{
+    for (size_t j = 0; j < structMembers.size(); ++j)
+    {
+        for (size_t i = 0; i < structMembers[j].size(); ++i)
+        {
+            delete structMembers[j][i];
+        }
+    }
+}
+
+unsigned D3DConstant::addStructMembers(const char *base, RegisterSet registerSet, unsigned registerIndex, const ctab::TypeInfo *typeInfo)
+{
+    const ctab::StructMemberInfo *memberInfos = reinterpret_cast<const ctab::StructMemberInfo*>(
+        base + typeInfo->structMemberInfos);
+
+    unsigned memberIndex = registerIndex;
+
+    structMembers.resize(elements);
+
+    for (unsigned j = 0; j < elements; ++j)
+    {
+        structMembers[j].resize(typeInfo->structMembers);
+
+        for (unsigned i = 0; i < typeInfo->structMembers; ++i)
+        {
+            const ctab::TypeInfo *memberTypeInfo = reinterpret_cast<const ctab::TypeInfo*>(
+                base + memberInfos[i].typeInfo);
+
+            D3DConstant *member = new D3DConstant(base, registerSet, memberIndex, memberInfos + i);
+            memberIndex += member->registerCount;
+
+            structMembers[j][i] = member;
+        }
+    }
+
+    return memberIndex - registerIndex;
+}
+
+D3DConstantTable::D3DConstantTable(void *blob, size_t size) : mError(false)
+{
+    BinaryInputStream stream(blob, size);
+
+    int version;
+    stream.read(&version);
+    if ((version & SHADER_VERSION_MASK) != SHADER_VERSION_MASK)
+    {
+        mError = true;
+        return;
+    }
+
+    const ctab::ConstantTable* constantTable = NULL;
+
+    while (!stream.error())
+    {
+        int token;
+        stream.read(&token);
+
+        if ((token & D3DSI_OPCODE_MASK) == D3DSIO_COMMENT)
+        {
+            size_t length = ((token & D3DSI_COMMENTSIZE_MASK) >> D3DSI_COMMENTSIZE_SHIFT) * sizeof(DWORD);
+
+            int fourcc;
+            stream.read(&fourcc);
+            if (fourcc == FOURCC_CTAB)
+            {
+                constantTable = reinterpret_cast<const ctab::ConstantTable*>(static_cast<const char*>(blob) + stream.offset());
+                break;
+            }
+
+            stream.skip(length - sizeof(fourcc));
+        }
+        else if (token == D3DSIO_END)
+        {
+            break;
+        }
+    }
+
+    mError = !constantTable || stream.error();
+    if (mError)
+    {
+        return;
+    }
+
+    const char *base = reinterpret_cast<const char*>(constantTable);
+
+    mConstants.resize(constantTable->constants);
+    const ctab::ConstantInfo *constantInfos =
+        reinterpret_cast<const ctab::ConstantInfo*>(base + constantTable->constantInfos);
+    for (size_t i = 0; i < constantTable->constants; ++i)
+    {
+        mConstants[i] = new D3DConstant(base, constantInfos + i);
+    }
+}
+
+D3DConstantTable::~D3DConstantTable()
+{
+    for (size_t i = 0; i < mConstants.size(); ++i)
+    {
+        delete mConstants[i];
+    }
+}
+
+const D3DConstant *D3DConstantTable::getConstant(unsigned index) const
+{
+    return mConstants[index];
+}
+
+const D3DConstant *D3DConstantTable::getConstantByName(const char *name) const
+{
+    for (size_t i = 0; i < mConstants.size(); ++i)
+    {
+        const D3DConstant *constant = getConstant(i);
+        if (constant->name == name)
+        {
+            return constant;
+        }
+    }
+
+    return NULL;
+}
+
+}
diff --git a/src/3rdparty/angle/src/libGLESv2/D3DConstantTable.h b/src/3rdparty/angle/src/libGLESv2/D3DConstantTable.h
new file mode 100644 (file)
index 0000000..ca6f3b9
--- /dev/null
@@ -0,0 +1,117 @@
+//
+// 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.
+//
+
+// D3DConstantTable.h: Implements the D3DConstantTable class which parses
+// information about constants from the CTAB comment in a D3D shader blob.
+// Restructures the constant table as a hierarchy of constants in the same
+// way as D3DX.
+
+#ifndef LIBGLESV2_D3DCONSTANTTABLE_H_
+#define LIBGLESV2_D3DCONSTANTTABLE_H_
+
+#include <vector>
+#include <string>
+
+#include "common/angleutils.h"
+
+namespace gl
+{
+
+namespace ctab
+{
+struct ConstantTable;
+struct ConstantInfo;
+struct TypeInfo;
+struct StructMemberInfo;
+}
+
+struct D3DConstant
+{
+    // These enums match those in d3dx9shader.h.
+    enum Class
+    {
+        CLASS_SCALAR,
+        CLASS_VECTOR,
+        CLASS_MATRIX_ROWS,
+        CLASS_MATRIX_COLUMNS,
+        CLASS_OBJECT,
+        CLASS_STRUCT,
+    };
+
+    enum RegisterSet
+    {
+        RS_BOOL,
+        RS_INT4,
+        RS_FLOAT4,
+        RS_SAMPLER,
+    };
+
+    enum Type
+    {
+        PT_VOID,
+        PT_BOOL,
+        PT_INT,
+        PT_FLOAT,
+        PT_STRING,
+        PT_TEXTURE,
+        PT_TEXTURE1D,
+        PT_TEXTURE2D,
+        PT_TEXTURE3D,
+        PT_TEXTURECUBE,
+        PT_SAMPLER,
+        PT_SAMPLER1D,
+        PT_SAMPLER2D,
+        PT_SAMPLER3D,
+        PT_SAMPLERCUBE,
+        PT_PIXELSHADER,
+        PT_VERTEXSHADER,
+        PT_PIXELFRAGMENT,
+        PT_VERTEXFRAGMENT,
+        PT_UNSUPPORTED,
+    };
+    
+    D3DConstant(const char *base, const ctab::ConstantInfo *constantInfo);
+    ~D3DConstant();
+
+    std::string name;
+    RegisterSet registerSet;
+    unsigned registerIndex;
+    unsigned registerCount;
+    Class typeClass;
+    Type type;
+    unsigned rows;
+    unsigned columns;
+    unsigned elements;
+
+    // Array of structure members.
+    std::vector<std::vector<const D3DConstant*> > structMembers;    
+
+  private:
+    D3DConstant(const char *base, RegisterSet registerSet, unsigned registerIndex, const ctab::StructMemberInfo *memberInfo);
+    unsigned addStructMembers(const char *base, RegisterSet registerSet, unsigned registerIndex, const ctab::TypeInfo *typeInfo);
+};
+
+class D3DConstantTable
+{
+  public:
+    D3DConstantTable(void *blob, size_t size);
+    ~D3DConstantTable();
+
+    bool error() const { return mError; }
+
+    unsigned constants() const { return mConstants.size(); }
+    const D3DConstant *getConstant(unsigned index) const;
+    const D3DConstant *getConstantByName(const char *name) const;
+
+  private:
+    DISALLOW_COPY_AND_ASSIGN(D3DConstantTable);
+    std::vector<const D3DConstant*> mConstants;
+    bool mError;
+};
+
+}
+
+#endif   // LIBGLESV2_D3DCONSTANTTABLE_H_
diff --git a/src/3rdparty/angle/src/libGLESv2/Fence.cpp b/src/3rdparty/angle/src/libGLESv2/Fence.cpp
new file mode 100644 (file)
index 0000000..14d1239
--- /dev/null
@@ -0,0 +1,132 @@
+//
+// 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.
+//
+
+// Fence.cpp: Implements the gl::Fence class, which supports the GL_NV_fence extension.
+
+#include "libGLESv2/Fence.h"
+
+#include "libGLESv2/main.h"
+
+namespace gl
+{
+
+Fence::Fence(egl::Display* display)
+{
+    mDisplay = display;
+    mQuery = NULL;
+    mCondition = GL_NONE;
+    mStatus = GL_FALSE;
+}
+
+Fence::~Fence()
+{
+    if (mQuery != NULL)
+    {
+        mDisplay->freeEventQuery(mQuery);
+    }
+}
+
+GLboolean Fence::isFence()
+{
+    // GL_NV_fence spec:
+    // A name returned by GenFencesNV, but not yet set via SetFenceNV, is not the name of an existing fence.
+    return mQuery != NULL;
+}
+
+void Fence::setFence(GLenum condition)
+{
+    if (!mQuery)
+    {
+        mQuery = mDisplay->allocateEventQuery();
+        if (!mQuery)
+        {
+            return error(GL_OUT_OF_MEMORY);
+        }
+    }
+
+    HRESULT result = mQuery->Issue(D3DISSUE_END);
+    ASSERT(SUCCEEDED(result));
+
+    mCondition = condition;
+    mStatus = GL_FALSE;
+}
+
+GLboolean Fence::testFence()
+{
+    if (mQuery == NULL)
+    {
+        return error(GL_INVALID_OPERATION, GL_TRUE);
+    }
+
+    HRESULT result = mQuery->GetData(NULL, 0, D3DGETDATA_FLUSH);
+
+    if (checkDeviceLost(result))
+    {
+       return error(GL_OUT_OF_MEMORY, GL_TRUE);
+    }
+
+    ASSERT(result == S_OK || result == S_FALSE);
+    mStatus = result == S_OK;
+    return mStatus;
+}
+
+void Fence::finishFence()
+{
+    if (mQuery == NULL)
+    {
+        return error(GL_INVALID_OPERATION);
+    }
+
+    while (!testFence())
+    {
+        Sleep(0);
+    }
+}
+
+void Fence::getFenceiv(GLenum pname, GLint *params)
+{
+    if (mQuery == NULL)
+    {
+        return error(GL_INVALID_OPERATION);
+    }
+
+    switch (pname)
+    {
+        case GL_FENCE_STATUS_NV:
+        {
+            // GL_NV_fence spec:
+            // Once the status of a fence has been finished (via FinishFenceNV) or tested and the returned status is TRUE (via either TestFenceNV
+            // or GetFenceivNV querying the FENCE_STATUS_NV), the status remains TRUE until the next SetFenceNV of the fence.
+            if (mStatus)
+            {
+                params[0] = GL_TRUE;
+                return;
+            }
+            
+            HRESULT result = mQuery->GetData(NULL, 0, 0);
+            
+            if (checkDeviceLost(result))
+            {
+                params[0] = GL_TRUE;
+                return error(GL_OUT_OF_MEMORY);
+            }
+
+            ASSERT(result == S_OK || result == S_FALSE);
+            mStatus = result == S_OK;
+            params[0] = mStatus;
+            
+            break;
+        }
+        case GL_FENCE_CONDITION_NV:
+            params[0] = mCondition;
+            break;
+        default:
+            return error(GL_INVALID_ENUM);
+            break;
+    }
+}
+
+}
diff --git a/src/3rdparty/angle/src/libGLESv2/Fence.h b/src/3rdparty/angle/src/libGLESv2/Fence.h
new file mode 100644 (file)
index 0000000..9626cb0
--- /dev/null
@@ -0,0 +1,49 @@
+//
+// 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.
+//
+
+// Fence.h: Defines the gl::Fence class, which supports the GL_NV_fence extension.
+
+#ifndef LIBGLESV2_FENCE_H_
+#define LIBGLESV2_FENCE_H_
+
+#define GL_APICALL
+#include <GLES2/gl2.h>
+#include <d3d9.h>
+
+#include "common/angleutils.h"
+
+namespace egl
+{
+class Display;
+}
+
+namespace gl
+{
+
+class Fence
+{
+  public:
+    explicit Fence(egl::Display* display);
+    virtual ~Fence();
+
+    GLboolean isFence();
+    void setFence(GLenum condition);
+    GLboolean testFence();
+    void finishFence();
+    void getFenceiv(GLenum pname, GLint *params);
+
+  private:
+    DISALLOW_COPY_AND_ASSIGN(Fence);
+
+    egl::Display* mDisplay;
+    IDirect3DQuery9* mQuery;
+    GLenum mCondition;
+    GLboolean mStatus;
+};
+
+}
+
+#endif   // LIBGLESV2_FENCE_H_
diff --git a/src/3rdparty/angle/src/libGLESv2/Float16ToFloat32.cpp b/src/3rdparty/angle/src/libGLESv2/Float16ToFloat32.cpp
new file mode 100644 (file)
index 0000000..5bf7b3f
--- /dev/null
@@ -0,0 +1,2203 @@
+//
+// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// This file is automatically generated.
+
+namespace gl
+{
+
+const static unsigned g_mantissa[2048] = {
+    0x00000000,
+    0x33800000,
+    0x34000000,
+    0x34400000,
+    0x34800000,
+    0x34a00000,
+    0x34c00000,
+    0x34e00000,
+    0x35000000,
+    0x35100000,
+    0x35200000,
+    0x35300000,
+    0x35400000,
+    0x35500000,
+    0x35600000,
+    0x35700000,
+    0x35800000,
+    0x35880000,
+    0x35900000,
+    0x35980000,
+    0x35a00000,
+    0x35a80000,
+    0x35b00000,
+    0x35b80000,
+    0x35c00000,
+    0x35c80000,
+    0x35d00000,
+    0x35d80000,
+    0x35e00000,
+    0x35e80000,
+    0x35f00000,
+    0x35f80000,
+    0x36000000,
+    0x36040000,
+    0x36080000,
+    0x360c0000,
+    0x36100000,
+    0x36140000,
+    0x36180000,
+    0x361c0000,
+    0x36200000,
+    0x36240000,
+    0x36280000,
+    0x362c0000,
+    0x36300000,
+    0x36340000,
+    0x36380000,
+    0x363c0000,
+    0x36400000,
+    0x36440000,
+    0x36480000,
+    0x364c0000,
+    0x36500000,
+    0x36540000,
+    0x36580000,
+    0x365c0000,
+    0x36600000,
+    0x36640000,
+    0x36680000,
+    0x366c0000,
+    0x36700000,
+    0x36740000,
+    0x36780000,
+    0x367c0000,
+    0x36800000,
+    0x36820000,
+    0x36840000,
+    0x36860000,
+    0x36880000,
+    0x368a0000,
+    0x368c0000,
+    0x368e0000,
+    0x36900000,
+    0x36920000,
+    0x36940000,
+    0x36960000,
+    0x36980000,
+    0x369a0000,
+    0x369c0000,
+    0x369e0000,
+    0x36a00000,
+    0x36a20000,
+    0x36a40000,
+    0x36a60000,
+    0x36a80000,
+    0x36aa0000,
+    0x36ac0000,
+    0x36ae0000,
+    0x36b00000,
+    0x36b20000,
+    0x36b40000,
+    0x36b60000,
+    0x36b80000,
+    0x36ba0000,
+    0x36bc0000,
+    0x36be0000,
+    0x36c00000,
+    0x36c20000,
+    0x36c40000,
+    0x36c60000,
+    0x36c80000,
+    0x36ca0000,
+    0x36cc0000,
+    0x36ce0000,
+    0x36d00000,
+    0x36d20000,
+    0x36d40000,
+    0x36d60000,
+    0x36d80000,
+    0x36da0000,
+    0x36dc0000,
+    0x36de0000,
+    0x36e00000,
+    0x36e20000,
+    0x36e40000,
+    0x36e60000,
+    0x36e80000,
+    0x36ea0000,
+    0x36ec0000,
+    0x36ee0000,
+    0x36f00000,
+    0x36f20000,
+    0x36f40000,
+    0x36f60000,
+    0x36f80000,
+    0x36fa0000,
+    0x36fc0000,
+    0x36fe0000,
+    0x37000000,
+    0x37010000,
+    0x37020000,
+    0x37030000,
+    0x37040000,
+    0x37050000,
+    0x37060000,
+    0x37070000,
+    0x37080000,
+    0x37090000,
+    0x370a0000,
+    0x370b0000,
+    0x370c0000,
+    0x370d0000,
+    0x370e0000,
+    0x370f0000,
+    0x37100000,
+    0x37110000,
+    0x37120000,
+    0x37130000,
+    0x37140000,
+    0x37150000,
+    0x37160000,
+    0x37170000,
+    0x37180000,
+    0x37190000,
+    0x371a0000,
+    0x371b0000,
+    0x371c0000,
+    0x371d0000,
+    0x371e0000,
+    0x371f0000,
+    0x37200000,
+    0x37210000,
+    0x37220000,
+    0x37230000,
+    0x37240000,
+    0x37250000,
+    0x37260000,
+    0x37270000,
+    0x37280000,
+    0x37290000,
+    0x372a0000,
+    0x372b0000,
+    0x372c0000,
+    0x372d0000,
+    0x372e0000,
+    0x372f0000,
+    0x37300000,
+    0x37310000,
+    0x37320000,
+    0x37330000,
+    0x37340000,
+    0x37350000,
+    0x37360000,
+    0x37370000,
+    0x37380000,
+    0x37390000,
+    0x373a0000,
+    0x373b0000,
+    0x373c0000,
+    0x373d0000,
+    0x373e0000,
+    0x373f0000,
+    0x37400000,
+    0x37410000,
+    0x37420000,
+    0x37430000,
+    0x37440000,
+    0x37450000,
+    0x37460000,
+    0x37470000,
+    0x37480000,
+    0x37490000,
+    0x374a0000,
+    0x374b0000,
+    0x374c0000,
+    0x374d0000,
+    0x374e0000,
+    0x374f0000,
+    0x37500000,
+    0x37510000,
+    0x37520000,
+    0x37530000,
+    0x37540000,
+    0x37550000,
+    0x37560000,
+    0x37570000,
+    0x37580000,
+    0x37590000,
+    0x375a0000,
+    0x375b0000,
+    0x375c0000,
+    0x375d0000,
+    0x375e0000,
+    0x375f0000,
+    0x37600000,
+    0x37610000,
+    0x37620000,
+    0x37630000,
+    0x37640000,
+    0x37650000,
+    0x37660000,
+    0x37670000,
+    0x37680000,
+    0x37690000,
+    0x376a0000,
+    0x376b0000,
+    0x376c0000,
+    0x376d0000,
+    0x376e0000,
+    0x376f0000,
+    0x37700000,
+    0x37710000,
+    0x37720000,
+    0x37730000,
+    0x37740000,
+    0x37750000,
+    0x37760000,
+    0x37770000,
+    0x37780000,
+    0x37790000,
+    0x377a0000,
+    0x377b0000,
+    0x377c0000,
+    0x377d0000,
+    0x377e0000,
+    0x377f0000,
+    0x37800000,
+    0x37808000,
+    0x37810000,
+    0x37818000,
+    0x37820000,
+    0x37828000,
+    0x37830000,
+    0x37838000,
+    0x37840000,
+    0x37848000,
+    0x37850000,
+    0x37858000,
+    0x37860000,
+    0x37868000,
+    0x37870000,
+    0x37878000,
+    0x37880000,
+    0x37888000,
+    0x37890000,
+    0x37898000,
+    0x378a0000,
+    0x378a8000,
+    0x378b0000,
+    0x378b8000,
+    0x378c0000,
+    0x378c8000,
+    0x378d0000,
+    0x378d8000,
+    0x378e0000,
+    0x378e8000,
+    0x378f0000,
+    0x378f8000,
+    0x37900000,
+    0x37908000,
+    0x37910000,
+    0x37918000,
+    0x37920000,
+    0x37928000,
+    0x37930000,
+    0x37938000,
+    0x37940000,
+    0x37948000,
+    0x37950000,
+    0x37958000,
+    0x37960000,
+    0x37968000,
+    0x37970000,
+    0x37978000,
+    0x37980000,
+    0x37988000,
+    0x37990000,
+    0x37998000,
+    0x379a0000,
+    0x379a8000,
+    0x379b0000,
+    0x379b8000,
+    0x379c0000,
+    0x379c8000,
+    0x379d0000,
+    0x379d8000,
+    0x379e0000,
+    0x379e8000,
+    0x379f0000,
+    0x379f8000,
+    0x37a00000,
+    0x37a08000,
+    0x37a10000,
+    0x37a18000,
+    0x37a20000,
+    0x37a28000,
+    0x37a30000,
+    0x37a38000,
+    0x37a40000,
+    0x37a48000,
+    0x37a50000,
+    0x37a58000,
+    0x37a60000,
+    0x37a68000,
+    0x37a70000,
+    0x37a78000,
+    0x37a80000,
+    0x37a88000,
+    0x37a90000,
+    0x37a98000,
+    0x37aa0000,
+    0x37aa8000,
+    0x37ab0000,
+    0x37ab8000,
+    0x37ac0000,
+    0x37ac8000,
+    0x37ad0000,
+    0x37ad8000,
+    0x37ae0000,
+    0x37ae8000,
+    0x37af0000,
+    0x37af8000,
+    0x37b00000,
+    0x37b08000,
+    0x37b10000,
+    0x37b18000,
+    0x37b20000,
+    0x37b28000,
+    0x37b30000,
+    0x37b38000,
+    0x37b40000,
+    0x37b48000,
+    0x37b50000,
+    0x37b58000,
+    0x37b60000,
+    0x37b68000,
+    0x37b70000,
+    0x37b78000,
+    0x37b80000,
+    0x37b88000,
+    0x37b90000,
+    0x37b98000,
+    0x37ba0000,
+    0x37ba8000,
+    0x37bb0000,
+    0x37bb8000,
+    0x37bc0000,
+    0x37bc8000,
+    0x37bd0000,
+    0x37bd8000,
+    0x37be0000,
+    0x37be8000,
+    0x37bf0000,
+    0x37bf8000,
+    0x37c00000,
+    0x37c08000,
+    0x37c10000,
+    0x37c18000,
+    0x37c20000,
+    0x37c28000,
+    0x37c30000,
+    0x37c38000,
+    0x37c40000,
+    0x37c48000,
+    0x37c50000,
+    0x37c58000,
+    0x37c60000,
+    0x37c68000,
+    0x37c70000,
+    0x37c78000,
+    0x37c80000,
+    0x37c88000,
+    0x37c90000,
+    0x37c98000,
+    0x37ca0000,
+    0x37ca8000,
+    0x37cb0000,
+    0x37cb8000,
+    0x37cc0000,
+    0x37cc8000,
+    0x37cd0000,
+    0x37cd8000,
+    0x37ce0000,
+    0x37ce8000,
+    0x37cf0000,
+    0x37cf8000,
+    0x37d00000,
+    0x37d08000,
+    0x37d10000,
+    0x37d18000,
+    0x37d20000,
+    0x37d28000,
+    0x37d30000,
+    0x37d38000,
+    0x37d40000,
+    0x37d48000,
+    0x37d50000,
+    0x37d58000,
+    0x37d60000,
+    0x37d68000,
+    0x37d70000,
+    0x37d78000,
+    0x37d80000,
+    0x37d88000,
+    0x37d90000,
+    0x37d98000,
+    0x37da0000,
+    0x37da8000,
+    0x37db0000,
+    0x37db8000,
+    0x37dc0000,
+    0x37dc8000,
+    0x37dd0000,
+    0x37dd8000,
+    0x37de0000,
+    0x37de8000,
+    0x37df0000,
+    0x37df8000,
+    0x37e00000,
+    0x37e08000,
+    0x37e10000,
+    0x37e18000,
+    0x37e20000,
+    0x37e28000,
+    0x37e30000,
+    0x37e38000,
+    0x37e40000,
+    0x37e48000,
+    0x37e50000,
+    0x37e58000,
+    0x37e60000,
+    0x37e68000,
+    0x37e70000,
+    0x37e78000,
+    0x37e80000,
+    0x37e88000,
+    0x37e90000,
+    0x37e98000,
+    0x37ea0000,
+    0x37ea8000,
+    0x37eb0000,
+    0x37eb8000,
+    0x37ec0000,
+    0x37ec8000,
+    0x37ed0000,
+    0x37ed8000,
+    0x37ee0000,
+    0x37ee8000,
+    0x37ef0000,
+    0x37ef8000,
+    0x37f00000,
+    0x37f08000,
+    0x37f10000,
+    0x37f18000,
+    0x37f20000,
+    0x37f28000,
+    0x37f30000,
+    0x37f38000,
+    0x37f40000,
+    0x37f48000,
+    0x37f50000,
+    0x37f58000,
+    0x37f60000,
+    0x37f68000,
+    0x37f70000,
+    0x37f78000,
+    0x37f80000,
+    0x37f88000,
+    0x37f90000,
+    0x37f98000,
+    0x37fa0000,
+    0x37fa8000,
+    0x37fb0000,
+    0x37fb8000,
+    0x37fc0000,
+    0x37fc8000,
+    0x37fd0000,
+    0x37fd8000,
+    0x37fe0000,
+    0x37fe8000,
+    0x37ff0000,
+    0x37ff8000,
+    0x38000000,
+    0x38004000,
+    0x38008000,
+    0x3800c000,
+    0x38010000,
+    0x38014000,
+    0x38018000,
+    0x3801c000,
+    0x38020000,
+    0x38024000,
+    0x38028000,
+    0x3802c000,
+    0x38030000,
+    0x38034000,
+    0x38038000,
+    0x3803c000,
+    0x38040000,
+    0x38044000,
+    0x38048000,
+    0x3804c000,
+    0x38050000,
+    0x38054000,
+    0x38058000,
+    0x3805c000,
+    0x38060000,
+    0x38064000,
+    0x38068000,
+    0x3806c000,
+    0x38070000,
+    0x38074000,
+    0x38078000,
+    0x3807c000,
+    0x38080000,
+    0x38084000,
+    0x38088000,
+    0x3808c000,
+    0x38090000,
+    0x38094000,
+    0x38098000,
+    0x3809c000,
+    0x380a0000,
+    0x380a4000,
+    0x380a8000,
+    0x380ac000,
+    0x380b0000,
+    0x380b4000,
+    0x380b8000,
+    0x380bc000,
+    0x380c0000,
+    0x380c4000,
+    0x380c8000,
+    0x380cc000,
+    0x380d0000,
+    0x380d4000,
+    0x380d8000,
+    0x380dc000,
+    0x380e0000,
+    0x380e4000,
+    0x380e8000,
+    0x380ec000,
+    0x380f0000,
+    0x380f4000,
+    0x380f8000,
+    0x380fc000,
+    0x38100000,
+    0x38104000,
+    0x38108000,
+    0x3810c000,
+    0x38110000,
+    0x38114000,
+    0x38118000,
+    0x3811c000,
+    0x38120000,
+    0x38124000,
+    0x38128000,
+    0x3812c000,
+    0x38130000,
+    0x38134000,
+    0x38138000,
+    0x3813c000,
+    0x38140000,
+    0x38144000,
+    0x38148000,
+    0x3814c000,
+    0x38150000,
+    0x38154000,
+    0x38158000,
+    0x3815c000,
+    0x38160000,
+    0x38164000,
+    0x38168000,
+    0x3816c000,
+    0x38170000,
+    0x38174000,
+    0x38178000,
+    0x3817c000,
+    0x38180000,
+    0x38184000,
+    0x38188000,
+    0x3818c000,
+    0x38190000,
+    0x38194000,
+    0x38198000,
+    0x3819c000,
+    0x381a0000,
+    0x381a4000,
+    0x381a8000,
+    0x381ac000,
+    0x381b0000,
+    0x381b4000,
+    0x381b8000,
+    0x381bc000,
+    0x381c0000,
+    0x381c4000,
+    0x381c8000,
+    0x381cc000,
+    0x381d0000,
+    0x381d4000,
+    0x381d8000,
+    0x381dc000,
+    0x381e0000,
+    0x381e4000,
+    0x381e8000,
+    0x381ec000,
+    0x381f0000,
+    0x381f4000,
+    0x381f8000,
+    0x381fc000,
+    0x38200000,
+    0x38204000,
+    0x38208000,
+    0x3820c000,
+    0x38210000,
+    0x38214000,
+    0x38218000,
+    0x3821c000,
+    0x38220000,
+    0x38224000,
+    0x38228000,
+    0x3822c000,
+    0x38230000,
+    0x38234000,
+    0x38238000,
+    0x3823c000,
+    0x38240000,
+    0x38244000,
+    0x38248000,
+    0x3824c000,
+    0x38250000,
+    0x38254000,
+    0x38258000,
+    0x3825c000,
+    0x38260000,
+    0x38264000,
+    0x38268000,
+    0x3826c000,
+    0x38270000,
+    0x38274000,
+    0x38278000,
+    0x3827c000,
+    0x38280000,
+    0x38284000,
+    0x38288000,
+    0x3828c000,
+    0x38290000,
+    0x38294000,
+    0x38298000,
+    0x3829c000,
+    0x382a0000,
+    0x382a4000,
+    0x382a8000,
+    0x382ac000,
+    0x382b0000,
+    0x382b4000,
+    0x382b8000,
+    0x382bc000,
+    0x382c0000,
+    0x382c4000,
+    0x382c8000,
+    0x382cc000,
+    0x382d0000,
+    0x382d4000,
+    0x382d8000,
+    0x382dc000,
+    0x382e0000,
+    0x382e4000,
+    0x382e8000,
+    0x382ec000,
+    0x382f0000,
+    0x382f4000,
+    0x382f8000,
+    0x382fc000,
+    0x38300000,
+    0x38304000,
+    0x38308000,
+    0x3830c000,
+    0x38310000,
+    0x38314000,
+    0x38318000,
+    0x3831c000,
+    0x38320000,
+    0x38324000,
+    0x38328000,
+    0x3832c000,
+    0x38330000,
+    0x38334000,
+    0x38338000,
+    0x3833c000,
+    0x38340000,
+    0x38344000,
+    0x38348000,
+    0x3834c000,
+    0x38350000,
+    0x38354000,
+    0x38358000,
+    0x3835c000,
+    0x38360000,
+    0x38364000,
+    0x38368000,
+    0x3836c000,
+    0x38370000,
+    0x38374000,
+    0x38378000,
+    0x3837c000,
+    0x38380000,
+    0x38384000,
+    0x38388000,
+    0x3838c000,
+    0x38390000,
+    0x38394000,
+    0x38398000,
+    0x3839c000,
+    0x383a0000,
+    0x383a4000,
+    0x383a8000,
+    0x383ac000,
+    0x383b0000,
+    0x383b4000,
+    0x383b8000,
+    0x383bc000,
+    0x383c0000,
+    0x383c4000,
+    0x383c8000,
+    0x383cc000,
+    0x383d0000,
+    0x383d4000,
+    0x383d8000,
+    0x383dc000,
+    0x383e0000,
+    0x383e4000,
+    0x383e8000,
+    0x383ec000,
+    0x383f0000,
+    0x383f4000,
+    0x383f8000,
+    0x383fc000,
+    0x38400000,
+    0x38404000,
+    0x38408000,
+    0x3840c000,
+    0x38410000,
+    0x38414000,
+    0x38418000,
+    0x3841c000,
+    0x38420000,
+    0x38424000,
+    0x38428000,
+    0x3842c000,
+    0x38430000,
+    0x38434000,
+    0x38438000,
+    0x3843c000,
+    0x38440000,
+    0x38444000,
+    0x38448000,
+    0x3844c000,
+    0x38450000,
+    0x38454000,
+    0x38458000,
+    0x3845c000,
+    0x38460000,
+    0x38464000,
+    0x38468000,
+    0x3846c000,
+    0x38470000,
+    0x38474000,
+    0x38478000,
+    0x3847c000,
+    0x38480000,
+    0x38484000,
+    0x38488000,
+    0x3848c000,
+    0x38490000,
+    0x38494000,
+    0x38498000,
+    0x3849c000,
+    0x384a0000,
+    0x384a4000,
+    0x384a8000,
+    0x384ac000,
+    0x384b0000,
+    0x384b4000,
+    0x384b8000,
+    0x384bc000,
+    0x384c0000,
+    0x384c4000,
+    0x384c8000,
+    0x384cc000,
+    0x384d0000,
+    0x384d4000,
+    0x384d8000,
+    0x384dc000,
+    0x384e0000,
+    0x384e4000,
+    0x384e8000,
+    0x384ec000,
+    0x384f0000,
+    0x384f4000,
+    0x384f8000,
+    0x384fc000,
+    0x38500000,
+    0x38504000,
+    0x38508000,
+    0x3850c000,
+    0x38510000,
+    0x38514000,
+    0x38518000,
+    0x3851c000,
+    0x38520000,
+    0x38524000,
+    0x38528000,
+    0x3852c000,
+    0x38530000,
+    0x38534000,
+    0x38538000,
+    0x3853c000,
+    0x38540000,
+    0x38544000,
+    0x38548000,
+    0x3854c000,
+    0x38550000,
+    0x38554000,
+    0x38558000,
+    0x3855c000,
+    0x38560000,
+    0x38564000,
+    0x38568000,
+    0x3856c000,
+    0x38570000,
+    0x38574000,
+    0x38578000,
+    0x3857c000,
+    0x38580000,
+    0x38584000,
+    0x38588000,
+    0x3858c000,
+    0x38590000,
+    0x38594000,
+    0x38598000,
+    0x3859c000,
+    0x385a0000,
+    0x385a4000,
+    0x385a8000,
+    0x385ac000,
+    0x385b0000,
+    0x385b4000,
+    0x385b8000,
+    0x385bc000,
+    0x385c0000,
+    0x385c4000,
+    0x385c8000,
+    0x385cc000,
+    0x385d0000,
+    0x385d4000,
+    0x385d8000,
+    0x385dc000,
+    0x385e0000,
+    0x385e4000,
+    0x385e8000,
+    0x385ec000,
+    0x385f0000,
+    0x385f4000,
+    0x385f8000,
+    0x385fc000,
+    0x38600000,
+    0x38604000,
+    0x38608000,
+    0x3860c000,
+    0x38610000,
+    0x38614000,
+    0x38618000,
+    0x3861c000,
+    0x38620000,
+    0x38624000,
+    0x38628000,
+    0x3862c000,
+    0x38630000,
+    0x38634000,
+    0x38638000,
+    0x3863c000,
+    0x38640000,
+    0x38644000,
+    0x38648000,
+    0x3864c000,
+    0x38650000,
+    0x38654000,
+    0x38658000,
+    0x3865c000,
+    0x38660000,
+    0x38664000,
+    0x38668000,
+    0x3866c000,
+    0x38670000,
+    0x38674000,
+    0x38678000,
+    0x3867c000,
+    0x38680000,
+    0x38684000,
+    0x38688000,
+    0x3868c000,
+    0x38690000,
+    0x38694000,
+    0x38698000,
+    0x3869c000,
+    0x386a0000,
+    0x386a4000,
+    0x386a8000,
+    0x386ac000,
+    0x386b0000,
+    0x386b4000,
+    0x386b8000,
+    0x386bc000,
+    0x386c0000,
+    0x386c4000,
+    0x386c8000,
+    0x386cc000,
+    0x386d0000,
+    0x386d4000,
+    0x386d8000,
+    0x386dc000,
+    0x386e0000,
+    0x386e4000,
+    0x386e8000,
+    0x386ec000,
+    0x386f0000,
+    0x386f4000,
+    0x386f8000,
+    0x386fc000,
+    0x38700000,
+    0x38704000,
+    0x38708000,
+    0x3870c000,
+    0x38710000,
+    0x38714000,
+    0x38718000,
+    0x3871c000,
+    0x38720000,
+    0x38724000,
+    0x38728000,
+    0x3872c000,
+    0x38730000,
+    0x38734000,
+    0x38738000,
+    0x3873c000,
+    0x38740000,
+    0x38744000,
+    0x38748000,
+    0x3874c000,
+    0x38750000,
+    0x38754000,
+    0x38758000,
+    0x3875c000,
+    0x38760000,
+    0x38764000,
+    0x38768000,
+    0x3876c000,
+    0x38770000,
+    0x38774000,
+    0x38778000,
+    0x3877c000,
+    0x38780000,
+    0x38784000,
+    0x38788000,
+    0x3878c000,
+    0x38790000,
+    0x38794000,
+    0x38798000,
+    0x3879c000,
+    0x387a0000,
+    0x387a4000,
+    0x387a8000,
+    0x387ac000,
+    0x387b0000,
+    0x387b4000,
+    0x387b8000,
+    0x387bc000,
+    0x387c0000,
+    0x387c4000,
+    0x387c8000,
+    0x387cc000,
+    0x387d0000,
+    0x387d4000,
+    0x387d8000,
+    0x387dc000,
+    0x387e0000,
+    0x387e4000,
+    0x387e8000,
+    0x387ec000,
+    0x387f0000,
+    0x387f4000,
+    0x387f8000,
+    0x387fc000,
+    0x38000000,
+    0x38002000,
+    0x38004000,
+    0x38006000,
+    0x38008000,
+    0x3800a000,
+    0x3800c000,
+    0x3800e000,
+    0x38010000,
+    0x38012000,
+    0x38014000,
+    0x38016000,
+    0x38018000,
+    0x3801a000,
+    0x3801c000,
+    0x3801e000,
+    0x38020000,
+    0x38022000,
+    0x38024000,
+    0x38026000,
+    0x38028000,
+    0x3802a000,
+    0x3802c000,
+    0x3802e000,
+    0x38030000,
+    0x38032000,
+    0x38034000,
+    0x38036000,
+    0x38038000,
+    0x3803a000,
+    0x3803c000,
+    0x3803e000,
+    0x38040000,
+    0x38042000,
+    0x38044000,
+    0x38046000,
+    0x38048000,
+    0x3804a000,
+    0x3804c000,
+    0x3804e000,
+    0x38050000,
+    0x38052000,
+    0x38054000,
+    0x38056000,
+    0x38058000,
+    0x3805a000,
+    0x3805c000,
+    0x3805e000,
+    0x38060000,
+    0x38062000,
+    0x38064000,
+    0x38066000,
+    0x38068000,
+    0x3806a000,
+    0x3806c000,
+    0x3806e000,
+    0x38070000,
+    0x38072000,
+    0x38074000,
+    0x38076000,
+    0x38078000,
+    0x3807a000,
+    0x3807c000,
+    0x3807e000,
+    0x38080000,
+    0x38082000,
+    0x38084000,
+    0x38086000,
+    0x38088000,
+    0x3808a000,
+    0x3808c000,
+    0x3808e000,
+    0x38090000,
+    0x38092000,
+    0x38094000,
+    0x38096000,
+    0x38098000,
+    0x3809a000,
+    0x3809c000,
+    0x3809e000,
+    0x380a0000,
+    0x380a2000,
+    0x380a4000,
+    0x380a6000,
+    0x380a8000,
+    0x380aa000,
+    0x380ac000,
+    0x380ae000,
+    0x380b0000,
+    0x380b2000,
+    0x380b4000,
+    0x380b6000,
+    0x380b8000,
+    0x380ba000,
+    0x380bc000,
+    0x380be000,
+    0x380c0000,
+    0x380c2000,
+    0x380c4000,
+    0x380c6000,
+    0x380c8000,
+    0x380ca000,
+    0x380cc000,
+    0x380ce000,
+    0x380d0000,
+    0x380d2000,
+    0x380d4000,
+    0x380d6000,
+    0x380d8000,
+    0x380da000,
+    0x380dc000,
+    0x380de000,
+    0x380e0000,
+    0x380e2000,
+    0x380e4000,
+    0x380e6000,
+    0x380e8000,
+    0x380ea000,
+    0x380ec000,
+    0x380ee000,
+    0x380f0000,
+    0x380f2000,
+    0x380f4000,
+    0x380f6000,
+    0x380f8000,
+    0x380fa000,
+    0x380fc000,
+    0x380fe000,
+    0x38100000,
+    0x38102000,
+    0x38104000,
+    0x38106000,
+    0x38108000,
+    0x3810a000,
+    0x3810c000,
+    0x3810e000,
+    0x38110000,
+    0x38112000,
+    0x38114000,
+    0x38116000,
+    0x38118000,
+    0x3811a000,
+    0x3811c000,
+    0x3811e000,
+    0x38120000,
+    0x38122000,
+    0x38124000,
+    0x38126000,
+    0x38128000,
+    0x3812a000,
+    0x3812c000,
+    0x3812e000,
+    0x38130000,
+    0x38132000,
+    0x38134000,
+    0x38136000,
+    0x38138000,
+    0x3813a000,
+    0x3813c000,
+    0x3813e000,
+    0x38140000,
+    0x38142000,
+    0x38144000,
+    0x38146000,
+    0x38148000,
+    0x3814a000,
+    0x3814c000,
+    0x3814e000,
+    0x38150000,
+    0x38152000,
+    0x38154000,
+    0x38156000,
+    0x38158000,
+    0x3815a000,
+    0x3815c000,
+    0x3815e000,
+    0x38160000,
+    0x38162000,
+    0x38164000,
+    0x38166000,
+    0x38168000,
+    0x3816a000,
+    0x3816c000,
+    0x3816e000,
+    0x38170000,
+    0x38172000,
+    0x38174000,
+    0x38176000,
+    0x38178000,
+    0x3817a000,
+    0x3817c000,
+    0x3817e000,
+    0x38180000,
+    0x38182000,
+    0x38184000,
+    0x38186000,
+    0x38188000,
+    0x3818a000,
+    0x3818c000,
+    0x3818e000,
+    0x38190000,
+    0x38192000,
+    0x38194000,
+    0x38196000,
+    0x38198000,
+    0x3819a000,
+    0x3819c000,
+    0x3819e000,
+    0x381a0000,
+    0x381a2000,
+    0x381a4000,
+    0x381a6000,
+    0x381a8000,
+    0x381aa000,
+    0x381ac000,
+    0x381ae000,
+    0x381b0000,
+    0x381b2000,
+    0x381b4000,
+    0x381b6000,
+    0x381b8000,
+    0x381ba000,
+    0x381bc000,
+    0x381be000,
+    0x381c0000,
+    0x381c2000,
+    0x381c4000,
+    0x381c6000,
+    0x381c8000,
+    0x381ca000,
+    0x381cc000,
+    0x381ce000,
+    0x381d0000,
+    0x381d2000,
+    0x381d4000,
+    0x381d6000,
+    0x381d8000,
+    0x381da000,
+    0x381dc000,
+    0x381de000,
+    0x381e0000,
+    0x381e2000,
+    0x381e4000,
+    0x381e6000,
+    0x381e8000,
+    0x381ea000,
+    0x381ec000,
+    0x381ee000,
+    0x381f0000,
+    0x381f2000,
+    0x381f4000,
+    0x381f6000,
+    0x381f8000,
+    0x381fa000,
+    0x381fc000,
+    0x381fe000,
+    0x38200000,
+    0x38202000,
+    0x38204000,
+    0x38206000,
+    0x38208000,
+    0x3820a000,
+    0x3820c000,
+    0x3820e000,
+    0x38210000,
+    0x38212000,
+    0x38214000,
+    0x38216000,
+    0x38218000,
+    0x3821a000,
+    0x3821c000,
+    0x3821e000,
+    0x38220000,
+    0x38222000,
+    0x38224000,
+    0x38226000,
+    0x38228000,
+    0x3822a000,
+    0x3822c000,
+    0x3822e000,
+    0x38230000,
+    0x38232000,
+    0x38234000,
+    0x38236000,
+    0x38238000,
+    0x3823a000,
+    0x3823c000,
+    0x3823e000,
+    0x38240000,
+    0x38242000,
+    0x38244000,
+    0x38246000,
+    0x38248000,
+    0x3824a000,
+    0x3824c000,
+    0x3824e000,
+    0x38250000,
+    0x38252000,
+    0x38254000,
+    0x38256000,
+    0x38258000,
+    0x3825a000,
+    0x3825c000,
+    0x3825e000,
+    0x38260000,
+    0x38262000,
+    0x38264000,
+    0x38266000,
+    0x38268000,
+    0x3826a000,
+    0x3826c000,
+    0x3826e000,
+    0x38270000,
+    0x38272000,
+    0x38274000,
+    0x38276000,
+    0x38278000,
+    0x3827a000,
+    0x3827c000,
+    0x3827e000,
+    0x38280000,
+    0x38282000,
+    0x38284000,
+    0x38286000,
+    0x38288000,
+    0x3828a000,
+    0x3828c000,
+    0x3828e000,
+    0x38290000,
+    0x38292000,
+    0x38294000,
+    0x38296000,
+    0x38298000,
+    0x3829a000,
+    0x3829c000,
+    0x3829e000,
+    0x382a0000,
+    0x382a2000,
+    0x382a4000,
+    0x382a6000,
+    0x382a8000,
+    0x382aa000,
+    0x382ac000,
+    0x382ae000,
+    0x382b0000,
+    0x382b2000,
+    0x382b4000,
+    0x382b6000,
+    0x382b8000,
+    0x382ba000,
+    0x382bc000,
+    0x382be000,
+    0x382c0000,
+    0x382c2000,
+    0x382c4000,
+    0x382c6000,
+    0x382c8000,
+    0x382ca000,
+    0x382cc000,
+    0x382ce000,
+    0x382d0000,
+    0x382d2000,
+    0x382d4000,
+    0x382d6000,
+    0x382d8000,
+    0x382da000,
+    0x382dc000,
+    0x382de000,
+    0x382e0000,
+    0x382e2000,
+    0x382e4000,
+    0x382e6000,
+    0x382e8000,
+    0x382ea000,
+    0x382ec000,
+    0x382ee000,
+    0x382f0000,
+    0x382f2000,
+    0x382f4000,
+    0x382f6000,
+    0x382f8000,
+    0x382fa000,
+    0x382fc000,
+    0x382fe000,
+    0x38300000,
+    0x38302000,
+    0x38304000,
+    0x38306000,
+    0x38308000,
+    0x3830a000,
+    0x3830c000,
+    0x3830e000,
+    0x38310000,
+    0x38312000,
+    0x38314000,
+    0x38316000,
+    0x38318000,
+    0x3831a000,
+    0x3831c000,
+    0x3831e000,
+    0x38320000,
+    0x38322000,
+    0x38324000,
+    0x38326000,
+    0x38328000,
+    0x3832a000,
+    0x3832c000,
+    0x3832e000,
+    0x38330000,
+    0x38332000,
+    0x38334000,
+    0x38336000,
+    0x38338000,
+    0x3833a000,
+    0x3833c000,
+    0x3833e000,
+    0x38340000,
+    0x38342000,
+    0x38344000,
+    0x38346000,
+    0x38348000,
+    0x3834a000,
+    0x3834c000,
+    0x3834e000,
+    0x38350000,
+    0x38352000,
+    0x38354000,
+    0x38356000,
+    0x38358000,
+    0x3835a000,
+    0x3835c000,
+    0x3835e000,
+    0x38360000,
+    0x38362000,
+    0x38364000,
+    0x38366000,
+    0x38368000,
+    0x3836a000,
+    0x3836c000,
+    0x3836e000,
+    0x38370000,
+    0x38372000,
+    0x38374000,
+    0x38376000,
+    0x38378000,
+    0x3837a000,
+    0x3837c000,
+    0x3837e000,
+    0x38380000,
+    0x38382000,
+    0x38384000,
+    0x38386000,
+    0x38388000,
+    0x3838a000,
+    0x3838c000,
+    0x3838e000,
+    0x38390000,
+    0x38392000,
+    0x38394000,
+    0x38396000,
+    0x38398000,
+    0x3839a000,
+    0x3839c000,
+    0x3839e000,
+    0x383a0000,
+    0x383a2000,
+    0x383a4000,
+    0x383a6000,
+    0x383a8000,
+    0x383aa000,
+    0x383ac000,
+    0x383ae000,
+    0x383b0000,
+    0x383b2000,
+    0x383b4000,
+    0x383b6000,
+    0x383b8000,
+    0x383ba000,
+    0x383bc000,
+    0x383be000,
+    0x383c0000,
+    0x383c2000,
+    0x383c4000,
+    0x383c6000,
+    0x383c8000,
+    0x383ca000,
+    0x383cc000,
+    0x383ce000,
+    0x383d0000,
+    0x383d2000,
+    0x383d4000,
+    0x383d6000,
+    0x383d8000,
+    0x383da000,
+    0x383dc000,
+    0x383de000,
+    0x383e0000,
+    0x383e2000,
+    0x383e4000,
+    0x383e6000,
+    0x383e8000,
+    0x383ea000,
+    0x383ec000,
+    0x383ee000,
+    0x383f0000,
+    0x383f2000,
+    0x383f4000,
+    0x383f6000,
+    0x383f8000,
+    0x383fa000,
+    0x383fc000,
+    0x383fe000,
+    0x38400000,
+    0x38402000,
+    0x38404000,
+    0x38406000,
+    0x38408000,
+    0x3840a000,
+    0x3840c000,
+    0x3840e000,
+    0x38410000,
+    0x38412000,
+    0x38414000,
+    0x38416000,
+    0x38418000,
+    0x3841a000,
+    0x3841c000,
+    0x3841e000,
+    0x38420000,
+    0x38422000,
+    0x38424000,
+    0x38426000,
+    0x38428000,
+    0x3842a000,
+    0x3842c000,
+    0x3842e000,
+    0x38430000,
+    0x38432000,
+    0x38434000,
+    0x38436000,
+    0x38438000,
+    0x3843a000,
+    0x3843c000,
+    0x3843e000,
+    0x38440000,
+    0x38442000,
+    0x38444000,
+    0x38446000,
+    0x38448000,
+    0x3844a000,
+    0x3844c000,
+    0x3844e000,
+    0x38450000,
+    0x38452000,
+    0x38454000,
+    0x38456000,
+    0x38458000,
+    0x3845a000,
+    0x3845c000,
+    0x3845e000,
+    0x38460000,
+    0x38462000,
+    0x38464000,
+    0x38466000,
+    0x38468000,
+    0x3846a000,
+    0x3846c000,
+    0x3846e000,
+    0x38470000,
+    0x38472000,
+    0x38474000,
+    0x38476000,
+    0x38478000,
+    0x3847a000,
+    0x3847c000,
+    0x3847e000,
+    0x38480000,
+    0x38482000,
+    0x38484000,
+    0x38486000,
+    0x38488000,
+    0x3848a000,
+    0x3848c000,
+    0x3848e000,
+    0x38490000,
+    0x38492000,
+    0x38494000,
+    0x38496000,
+    0x38498000,
+    0x3849a000,
+    0x3849c000,
+    0x3849e000,
+    0x384a0000,
+    0x384a2000,
+    0x384a4000,
+    0x384a6000,
+    0x384a8000,
+    0x384aa000,
+    0x384ac000,
+    0x384ae000,
+    0x384b0000,
+    0x384b2000,
+    0x384b4000,
+    0x384b6000,
+    0x384b8000,
+    0x384ba000,
+    0x384bc000,
+    0x384be000,
+    0x384c0000,
+    0x384c2000,
+    0x384c4000,
+    0x384c6000,
+    0x384c8000,
+    0x384ca000,
+    0x384cc000,
+    0x384ce000,
+    0x384d0000,
+    0x384d2000,
+    0x384d4000,
+    0x384d6000,
+    0x384d8000,
+    0x384da000,
+    0x384dc000,
+    0x384de000,
+    0x384e0000,
+    0x384e2000,
+    0x384e4000,
+    0x384e6000,
+    0x384e8000,
+    0x384ea000,
+    0x384ec000,
+    0x384ee000,
+    0x384f0000,
+    0x384f2000,
+    0x384f4000,
+    0x384f6000,
+    0x384f8000,
+    0x384fa000,
+    0x384fc000,
+    0x384fe000,
+    0x38500000,
+    0x38502000,
+    0x38504000,
+    0x38506000,
+    0x38508000,
+    0x3850a000,
+    0x3850c000,
+    0x3850e000,
+    0x38510000,
+    0x38512000,
+    0x38514000,
+    0x38516000,
+    0x38518000,
+    0x3851a000,
+    0x3851c000,
+    0x3851e000,
+    0x38520000,
+    0x38522000,
+    0x38524000,
+    0x38526000,
+    0x38528000,
+    0x3852a000,
+    0x3852c000,
+    0x3852e000,
+    0x38530000,
+    0x38532000,
+    0x38534000,
+    0x38536000,
+    0x38538000,
+    0x3853a000,
+    0x3853c000,
+    0x3853e000,
+    0x38540000,
+    0x38542000,
+    0x38544000,
+    0x38546000,
+    0x38548000,
+    0x3854a000,
+    0x3854c000,
+    0x3854e000,
+    0x38550000,
+    0x38552000,
+    0x38554000,
+    0x38556000,
+    0x38558000,
+    0x3855a000,
+    0x3855c000,
+    0x3855e000,
+    0x38560000,
+    0x38562000,
+    0x38564000,
+    0x38566000,
+    0x38568000,
+    0x3856a000,
+    0x3856c000,
+    0x3856e000,
+    0x38570000,
+    0x38572000,
+    0x38574000,
+    0x38576000,
+    0x38578000,
+    0x3857a000,
+    0x3857c000,
+    0x3857e000,
+    0x38580000,
+    0x38582000,
+    0x38584000,
+    0x38586000,
+    0x38588000,
+    0x3858a000,
+    0x3858c000,
+    0x3858e000,
+    0x38590000,
+    0x38592000,
+    0x38594000,
+    0x38596000,
+    0x38598000,
+    0x3859a000,
+    0x3859c000,
+    0x3859e000,
+    0x385a0000,
+    0x385a2000,
+    0x385a4000,
+    0x385a6000,
+    0x385a8000,
+    0x385aa000,
+    0x385ac000,
+    0x385ae000,
+    0x385b0000,
+    0x385b2000,
+    0x385b4000,
+    0x385b6000,
+    0x385b8000,
+    0x385ba000,
+    0x385bc000,
+    0x385be000,
+    0x385c0000,
+    0x385c2000,
+    0x385c4000,
+    0x385c6000,
+    0x385c8000,
+    0x385ca000,
+    0x385cc000,
+    0x385ce000,
+    0x385d0000,
+    0x385d2000,
+    0x385d4000,
+    0x385d6000,
+    0x385d8000,
+    0x385da000,
+    0x385dc000,
+    0x385de000,
+    0x385e0000,
+    0x385e2000,
+    0x385e4000,
+    0x385e6000,
+    0x385e8000,
+    0x385ea000,
+    0x385ec000,
+    0x385ee000,
+    0x385f0000,
+    0x385f2000,
+    0x385f4000,
+    0x385f6000,
+    0x385f8000,
+    0x385fa000,
+    0x385fc000,
+    0x385fe000,
+    0x38600000,
+    0x38602000,
+    0x38604000,
+    0x38606000,
+    0x38608000,
+    0x3860a000,
+    0x3860c000,
+    0x3860e000,
+    0x38610000,
+    0x38612000,
+    0x38614000,
+    0x38616000,
+    0x38618000,
+    0x3861a000,
+    0x3861c000,
+    0x3861e000,
+    0x38620000,
+    0x38622000,
+    0x38624000,
+    0x38626000,
+    0x38628000,
+    0x3862a000,
+    0x3862c000,
+    0x3862e000,
+    0x38630000,
+    0x38632000,
+    0x38634000,
+    0x38636000,
+    0x38638000,
+    0x3863a000,
+    0x3863c000,
+    0x3863e000,
+    0x38640000,
+    0x38642000,
+    0x38644000,
+    0x38646000,
+    0x38648000,
+    0x3864a000,
+    0x3864c000,
+    0x3864e000,
+    0x38650000,
+    0x38652000,
+    0x38654000,
+    0x38656000,
+    0x38658000,
+    0x3865a000,
+    0x3865c000,
+    0x3865e000,
+    0x38660000,
+    0x38662000,
+    0x38664000,
+    0x38666000,
+    0x38668000,
+    0x3866a000,
+    0x3866c000,
+    0x3866e000,
+    0x38670000,
+    0x38672000,
+    0x38674000,
+    0x38676000,
+    0x38678000,
+    0x3867a000,
+    0x3867c000,
+    0x3867e000,
+    0x38680000,
+    0x38682000,
+    0x38684000,
+    0x38686000,
+    0x38688000,
+    0x3868a000,
+    0x3868c000,
+    0x3868e000,
+    0x38690000,
+    0x38692000,
+    0x38694000,
+    0x38696000,
+    0x38698000,
+    0x3869a000,
+    0x3869c000,
+    0x3869e000,
+    0x386a0000,
+    0x386a2000,
+    0x386a4000,
+    0x386a6000,
+    0x386a8000,
+    0x386aa000,
+    0x386ac000,
+    0x386ae000,
+    0x386b0000,
+    0x386b2000,
+    0x386b4000,
+    0x386b6000,
+    0x386b8000,
+    0x386ba000,
+    0x386bc000,
+    0x386be000,
+    0x386c0000,
+    0x386c2000,
+    0x386c4000,
+    0x386c6000,
+    0x386c8000,
+    0x386ca000,
+    0x386cc000,
+    0x386ce000,
+    0x386d0000,
+    0x386d2000,
+    0x386d4000,
+    0x386d6000,
+    0x386d8000,
+    0x386da000,
+    0x386dc000,
+    0x386de000,
+    0x386e0000,
+    0x386e2000,
+    0x386e4000,
+    0x386e6000,
+    0x386e8000,
+    0x386ea000,
+    0x386ec000,
+    0x386ee000,
+    0x386f0000,
+    0x386f2000,
+    0x386f4000,
+    0x386f6000,
+    0x386f8000,
+    0x386fa000,
+    0x386fc000,
+    0x386fe000,
+    0x38700000,
+    0x38702000,
+    0x38704000,
+    0x38706000,
+    0x38708000,
+    0x3870a000,
+    0x3870c000,
+    0x3870e000,
+    0x38710000,
+    0x38712000,
+    0x38714000,
+    0x38716000,
+    0x38718000,
+    0x3871a000,
+    0x3871c000,
+    0x3871e000,
+    0x38720000,
+    0x38722000,
+    0x38724000,
+    0x38726000,
+    0x38728000,
+    0x3872a000,
+    0x3872c000,
+    0x3872e000,
+    0x38730000,
+    0x38732000,
+    0x38734000,
+    0x38736000,
+    0x38738000,
+    0x3873a000,
+    0x3873c000,
+    0x3873e000,
+    0x38740000,
+    0x38742000,
+    0x38744000,
+    0x38746000,
+    0x38748000,
+    0x3874a000,
+    0x3874c000,
+    0x3874e000,
+    0x38750000,
+    0x38752000,
+    0x38754000,
+    0x38756000,
+    0x38758000,
+    0x3875a000,
+    0x3875c000,
+    0x3875e000,
+    0x38760000,
+    0x38762000,
+    0x38764000,
+    0x38766000,
+    0x38768000,
+    0x3876a000,
+    0x3876c000,
+    0x3876e000,
+    0x38770000,
+    0x38772000,
+    0x38774000,
+    0x38776000,
+    0x38778000,
+    0x3877a000,
+    0x3877c000,
+    0x3877e000,
+    0x38780000,
+    0x38782000,
+    0x38784000,
+    0x38786000,
+    0x38788000,
+    0x3878a000,
+    0x3878c000,
+    0x3878e000,
+    0x38790000,
+    0x38792000,
+    0x38794000,
+    0x38796000,
+    0x38798000,
+    0x3879a000,
+    0x3879c000,
+    0x3879e000,
+    0x387a0000,
+    0x387a2000,
+    0x387a4000,
+    0x387a6000,
+    0x387a8000,
+    0x387aa000,
+    0x387ac000,
+    0x387ae000,
+    0x387b0000,
+    0x387b2000,
+    0x387b4000,
+    0x387b6000,
+    0x387b8000,
+    0x387ba000,
+    0x387bc000,
+    0x387be000,
+    0x387c0000,
+    0x387c2000,
+    0x387c4000,
+    0x387c6000,
+    0x387c8000,
+    0x387ca000,
+    0x387cc000,
+    0x387ce000,
+    0x387d0000,
+    0x387d2000,
+    0x387d4000,
+    0x387d6000,
+    0x387d8000,
+    0x387da000,
+    0x387dc000,
+    0x387de000,
+    0x387e0000,
+    0x387e2000,
+    0x387e4000,
+    0x387e6000,
+    0x387e8000,
+    0x387ea000,
+    0x387ec000,
+    0x387ee000,
+    0x387f0000,
+    0x387f2000,
+    0x387f4000,
+    0x387f6000,
+    0x387f8000,
+    0x387fa000,
+    0x387fc000,
+    0x387fe000,
+};
+
+const static unsigned g_exponent[64] = {
+    0x00000000,
+    0x00800000,
+    0x01000000,
+    0x01800000,
+    0x02000000,
+    0x02800000,
+    0x03000000,
+    0x03800000,
+    0x04000000,
+    0x04800000,
+    0x05000000,
+    0x05800000,
+    0x06000000,
+    0x06800000,
+    0x07000000,
+    0x07800000,
+    0x08000000,
+    0x08800000,
+    0x09000000,
+    0x09800000,
+    0x0a000000,
+    0x0a800000,
+    0x0b000000,
+    0x0b800000,
+    0x0c000000,
+    0x0c800000,
+    0x0d000000,
+    0x0d800000,
+    0x0e000000,
+    0x0e800000,
+    0x0f000000,
+    0x47800000,
+    0x80000000,
+    0x80800000,
+    0x81000000,
+    0x81800000,
+    0x82000000,
+    0x82800000,
+    0x83000000,
+    0x83800000,
+    0x84000000,
+    0x84800000,
+    0x85000000,
+    0x85800000,
+    0x86000000,
+    0x86800000,
+    0x87000000,
+    0x87800000,
+    0x88000000,
+    0x88800000,
+    0x89000000,
+    0x89800000,
+    0x8a000000,
+    0x8a800000,
+    0x8b000000,
+    0x8b800000,
+    0x8c000000,
+    0x8c800000,
+    0x8d000000,
+    0x8d800000,
+    0x8e000000,
+    0x8e800000,
+    0x8f000000,
+    0xc7800000,
+};
+
+const static unsigned g_offset[64] = {
+    0x00000000,
+    0x00000400,
+    0x00000400,
+    0x00000400,
+    0x00000400,
+    0x00000400,
+    0x00000400,
+    0x00000400,
+    0x00000400,
+    0x00000400,
+    0x00000400,
+    0x00000400,
+    0x00000400,
+    0x00000400,
+    0x00000400,
+    0x00000400,
+    0x00000400,
+    0x00000400,
+    0x00000400,
+    0x00000400,
+    0x00000400,
+    0x00000400,
+    0x00000400,
+    0x00000400,
+    0x00000400,
+    0x00000400,
+    0x00000400,
+    0x00000400,
+    0x00000400,
+    0x00000400,
+    0x00000400,
+    0x00000400,
+    0x00000000,
+    0x00000400,
+    0x00000400,
+    0x00000400,
+    0x00000400,
+    0x00000400,
+    0x00000400,
+    0x00000400,
+    0x00000400,
+    0x00000400,
+    0x00000400,
+    0x00000400,
+    0x00000400,
+    0x00000400,
+    0x00000400,
+    0x00000400,
+    0x00000400,
+    0x00000400,
+    0x00000400,
+    0x00000400,
+    0x00000400,
+    0x00000400,
+    0x00000400,
+    0x00000400,
+    0x00000400,
+    0x00000400,
+    0x00000400,
+    0x00000400,
+    0x00000400,
+    0x00000400,
+    0x00000400,
+    0x00000400,
+};
+
+float float16ToFloat32(unsigned short h)
+{
+    unsigned i32 = g_mantissa[g_offset[h >> 10] + (h & 0x3ff)] + g_exponent[h >> 10];
+    return *(float*) &i32;
+}
+}
+
diff --git a/src/3rdparty/angle/src/libGLESv2/Float16ToFloat32.py b/src/3rdparty/angle/src/libGLESv2/Float16ToFloat32.py
new file mode 100644 (file)
index 0000000..ae646ff
--- /dev/null
@@ -0,0 +1,78 @@
+# Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+#
+
+# This script generates a function that converts 16-bit precision floating
+# point numbers to 32-bit.
+# It is based on ftp://ftp.fox-toolkit.org/pub/fasthalffloatconversion.pdf.
+
+def convertMantissa(i):
+    if i == 0:
+        return 0
+    elif i < 1024:
+        m = i << 13
+        e = 0
+        while not (m & 0x00800000):
+            e -= 0x00800000
+            m = m << 1
+        m &= ~0x00800000
+        e += 0x38800000
+        return m | e
+    else:
+        return 0x38000000 + ((i - 1024) << 13)
+
+def convertExponent(i):
+    if i == 0:
+        return 0
+    elif i in range(1, 31):
+        return i << 23
+    elif i == 31:
+        return 0x47800000
+    elif i == 32:
+        return 0x80000000
+    elif i in range(33, 63):
+        return 0x80000000 + ((i - 32) << 23)
+    else:
+        return 0xC7800000
+
+def convertOffset(i):
+    if i == 0 or i == 32:
+        return 0
+    else:
+        return 1024
+
+print """//
+// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// This file is automatically generated.
+
+namespace gl
+{
+"""
+
+print "const static unsigned g_mantissa[2048] = {"
+for i in range(0, 2048):
+    print "    %08x," % convertMantissa(i)
+print "};\n"
+
+print "const static unsigned g_exponent[64] = {"
+for i in range(0, 64):
+    print "    %08x," % convertExponent(i)
+print "};\n"
+
+print "const static unsigned g_offset[64] = {"
+for i in range(0, 64):
+    print "    %08x," % convertOffset(i)
+print "};\n"
+
+print """float float16ToFloat32(unsigned short h)
+{
+    unsigned i32 = =g_mantissa[g_offset[h >> 10] + (h & 0x3ff)] + g_exponent[h >> 10];
+    return *(float*) &i32;
+}
+}
+"""
diff --git a/src/3rdparty/angle/src/libGLESv2/Framebuffer.cpp b/src/3rdparty/angle/src/libGLESv2/Framebuffer.cpp
new file mode 100644 (file)
index 0000000..77d79c0
--- /dev/null
@@ -0,0 +1,509 @@
+//
+// 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.
+//
+
+// Framebuffer.cpp: Implements the gl::Framebuffer class. Implements GL framebuffer
+// objects and related functionality. [OpenGL ES 2.0.24] section 4.4 page 105.
+
+#include "libGLESv2/Framebuffer.h"
+
+#include "libGLESv2/main.h"
+#include "libGLESv2/Renderbuffer.h"
+#include "libGLESv2/Texture.h"
+#include "libGLESv2/utilities.h"
+
+namespace gl
+{
+
+Framebuffer::Framebuffer()
+{
+    mColorbufferType = GL_NONE;
+    mDepthbufferType = GL_NONE;
+    mStencilbufferType = GL_NONE;
+}
+
+Framebuffer::~Framebuffer()
+{
+    mColorbufferPointer.set(NULL);
+    mDepthbufferPointer.set(NULL);
+    mStencilbufferPointer.set(NULL);
+    mNullColorbufferPointer.set(NULL);
+}
+
+Renderbuffer *Framebuffer::lookupRenderbuffer(GLenum type, GLuint handle) const
+{
+    gl::Context *context = gl::getContext();
+    Renderbuffer *buffer = NULL;
+
+    if (type == GL_NONE)
+    {
+        buffer = NULL;
+    }
+    else if (type == GL_RENDERBUFFER)
+    {
+        buffer = context->getRenderbuffer(handle);
+    }
+    else if (IsInternalTextureTarget(type))
+    {
+        buffer = context->getTexture(handle)->getRenderbuffer(type);
+    }
+    else
+    {
+        UNREACHABLE();
+    }
+
+    return buffer;
+}
+
+void Framebuffer::setColorbuffer(GLenum type, GLuint colorbuffer)
+{
+    mColorbufferType = (colorbuffer != 0) ? type : GL_NONE;
+    mColorbufferPointer.set(lookupRenderbuffer(type, colorbuffer));
+}
+
+void Framebuffer::setDepthbuffer(GLenum type, GLuint depthbuffer)
+{
+    mDepthbufferType = (depthbuffer != 0) ? type : GL_NONE;
+    mDepthbufferPointer.set(lookupRenderbuffer(type, depthbuffer));
+}
+
+void Framebuffer::setStencilbuffer(GLenum type, GLuint stencilbuffer)
+{
+    mStencilbufferType = (stencilbuffer != 0) ? type : GL_NONE;
+    mStencilbufferPointer.set(lookupRenderbuffer(type, stencilbuffer));
+}
+
+void Framebuffer::detachTexture(GLuint texture)
+{
+    if (mColorbufferPointer.id() == texture && IsInternalTextureTarget(mColorbufferType))
+    {
+        mColorbufferType = GL_NONE;
+        mColorbufferPointer.set(NULL);
+    }
+
+    if (mDepthbufferPointer.id() == texture && IsInternalTextureTarget(mDepthbufferType))
+    {
+        mDepthbufferType = GL_NONE;
+        mDepthbufferPointer.set(NULL);
+    }
+
+    if (mStencilbufferPointer.id() == texture && IsInternalTextureTarget(mStencilbufferType))
+    {
+        mStencilbufferType = GL_NONE;
+        mStencilbufferPointer.set(NULL);
+    }
+}
+
+void Framebuffer::detachRenderbuffer(GLuint renderbuffer)
+{
+    if (mColorbufferPointer.id() == renderbuffer && mColorbufferType == GL_RENDERBUFFER)
+    {
+        mColorbufferType = GL_NONE;
+        mColorbufferPointer.set(NULL);
+    }
+
+    if (mDepthbufferPointer.id() == renderbuffer && mDepthbufferType == GL_RENDERBUFFER)
+    {
+        mDepthbufferType = GL_NONE;
+        mDepthbufferPointer.set(NULL);
+    }
+
+    if (mStencilbufferPointer.id() == renderbuffer && mStencilbufferType == GL_RENDERBUFFER)
+    {
+        mStencilbufferType = GL_NONE;
+        mStencilbufferPointer.set(NULL);
+    }
+}
+
+unsigned int Framebuffer::getRenderTargetSerial()
+{
+    Renderbuffer *colorbuffer = mColorbufferPointer.get();
+
+    if (colorbuffer)
+    {
+        return colorbuffer->getSerial();
+    }
+
+    return 0;
+}
+
+// Increments refcount on surface.
+// caller must Release() the returned surface
+IDirect3DSurface9 *Framebuffer::getRenderTarget()
+{
+    Renderbuffer *colorbuffer = mColorbufferPointer.get();
+
+    if (colorbuffer)
+    {
+        return colorbuffer->getRenderTarget();
+    }
+
+    return NULL;
+}
+
+// Increments refcount on surface.
+// caller must Release() the returned surface
+IDirect3DSurface9 *Framebuffer::getDepthStencil()
+{
+    Renderbuffer *depthstencilbuffer = mDepthbufferPointer.get();
+    
+    if (!depthstencilbuffer)
+    {
+        depthstencilbuffer = mStencilbufferPointer.get();
+    }
+
+    if (depthstencilbuffer)
+    {
+        return depthstencilbuffer->getDepthStencil();
+    }
+
+    return NULL;
+}
+
+unsigned int Framebuffer::getDepthbufferSerial()
+{
+    Renderbuffer *depthbuffer = mDepthbufferPointer.get();
+
+    if (depthbuffer)
+    {
+        return depthbuffer->getSerial();
+    }
+
+    return 0;
+}
+
+unsigned int Framebuffer::getStencilbufferSerial()
+{
+    Renderbuffer *stencilbuffer = mStencilbufferPointer.get();
+
+    if (stencilbuffer)
+    {
+        return stencilbuffer->getSerial();
+    }
+
+    return 0;
+}
+
+Renderbuffer *Framebuffer::getColorbuffer()
+{
+    return mColorbufferPointer.get();
+}
+
+Renderbuffer *Framebuffer::getDepthbuffer()
+{
+    return mDepthbufferPointer.get();
+}
+
+Renderbuffer *Framebuffer::getStencilbuffer()
+{
+    return mStencilbufferPointer.get();
+}
+
+Renderbuffer *Framebuffer::getNullColorbuffer()
+{
+    Renderbuffer *nullbuffer  = mNullColorbufferPointer.get();
+    Renderbuffer *depthbuffer = getDepthbuffer();
+
+    if (!depthbuffer)
+    {
+        ERR("Unexpected null depthbuffer for depth-only FBO.");
+        return NULL;
+    }
+
+    GLsizei width  = depthbuffer->getWidth();
+    GLsizei height = depthbuffer->getHeight();
+
+    if (!nullbuffer ||
+        width != nullbuffer->getWidth() || height != nullbuffer->getHeight())
+    {
+        nullbuffer = new Renderbuffer(0, new Colorbuffer(width, height, GL_NONE, 0));
+        mNullColorbufferPointer.set(nullbuffer);
+    }
+
+    return nullbuffer;
+}
+
+GLenum Framebuffer::getColorbufferType()
+{
+    return mColorbufferType;
+}
+
+GLenum Framebuffer::getDepthbufferType()
+{
+    return mDepthbufferType;
+}
+
+GLenum Framebuffer::getStencilbufferType()
+{
+    return mStencilbufferType;
+}
+
+GLuint Framebuffer::getColorbufferHandle()
+{
+    return mColorbufferPointer.id();
+}
+
+GLuint Framebuffer::getDepthbufferHandle()
+{
+    return mDepthbufferPointer.id();
+}
+
+GLuint Framebuffer::getStencilbufferHandle()
+{
+    return mStencilbufferPointer.id();
+}
+
+bool Framebuffer::hasStencil()
+{
+    if (mStencilbufferType != GL_NONE)
+    {
+        Renderbuffer *stencilbufferObject = getStencilbuffer();
+
+        if (stencilbufferObject)
+        {
+            return stencilbufferObject->getStencilSize() > 0;
+        }
+    }
+
+    return false;
+}
+
+GLenum Framebuffer::completeness()
+{
+    gl::Context *context = gl::getContext();
+    int width = 0;
+    int height = 0;
+    int samples = -1;
+    bool missingAttachment = true;
+
+    if (mColorbufferType != GL_NONE)
+    {
+        Renderbuffer *colorbuffer = getColorbuffer();
+
+        if (!colorbuffer)
+        {
+            return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
+        }
+
+        if (colorbuffer->getWidth() == 0 || colorbuffer->getHeight() == 0)
+        {
+            return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
+        }
+
+        if (mColorbufferType == GL_RENDERBUFFER)
+        {
+            if (!gl::IsColorRenderable(colorbuffer->getInternalFormat()))
+            {
+                return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
+            }
+        }
+        else if (IsInternalTextureTarget(mColorbufferType))
+        {
+            GLint internalformat = colorbuffer->getInternalFormat();
+            GLenum format = gl::ExtractFormat(internalformat);
+
+            if (IsCompressed(format) ||
+                format == GL_ALPHA ||
+                format == GL_LUMINANCE ||
+                format == GL_LUMINANCE_ALPHA)
+            {
+                return GL_FRAMEBUFFER_UNSUPPORTED;
+            }
+
+            if ((gl::IsFloat32Format(internalformat) && !context->supportsFloat32RenderableTextures()) ||
+                (gl::IsFloat16Format(internalformat) && !context->supportsFloat16RenderableTextures()))
+            {
+                return GL_FRAMEBUFFER_UNSUPPORTED;
+            }
+
+            if (gl::IsDepthTexture(internalformat) || gl::IsStencilTexture(internalformat))
+            {
+                return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
+            }
+        }
+        else
+        {
+            UNREACHABLE();
+            return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
+        }
+
+        width = colorbuffer->getWidth();
+        height = colorbuffer->getHeight();
+        samples = colorbuffer->getSamples();
+        missingAttachment = false;
+    }
+
+    Renderbuffer *depthbuffer = NULL;
+    Renderbuffer *stencilbuffer = NULL;
+
+    if (mDepthbufferType != GL_NONE)
+    {
+        depthbuffer = getDepthbuffer();
+
+        if (!depthbuffer)
+        {
+            return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
+        }
+
+        if (depthbuffer->getWidth() == 0 || depthbuffer->getHeight() == 0)
+        {
+            return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
+        }
+
+        if (mDepthbufferType == GL_RENDERBUFFER)
+        {
+            if (!gl::IsDepthRenderable(depthbuffer->getInternalFormat()))
+            {
+                return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
+            }
+        }
+        else if (IsInternalTextureTarget(mDepthbufferType))
+        {
+            GLint internalformat = depthbuffer->getInternalFormat();
+
+            // depth texture attachments require OES/ANGLE_depth_texture
+            if (!context->supportsDepthTextures())
+            {
+                return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
+            }
+
+            if (!gl::IsDepthTexture(internalformat))
+            {
+                return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
+            }
+        }
+        else
+        {
+            UNREACHABLE();
+            return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
+        }
+
+        if (missingAttachment)
+        {
+            width = depthbuffer->getWidth();
+            height = depthbuffer->getHeight();
+            samples = depthbuffer->getSamples();
+            missingAttachment = false;
+        }
+        else if (width != depthbuffer->getWidth() || height != depthbuffer->getHeight())
+        {
+            return GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS;
+        }
+        else if (samples != depthbuffer->getSamples())
+        {
+            return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_ANGLE;
+        }
+    }
+
+    if (mStencilbufferType != GL_NONE)
+    {
+        stencilbuffer = getStencilbuffer();
+
+        if (!stencilbuffer)
+        {
+            return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
+        }
+
+        if (stencilbuffer->getWidth() == 0 || stencilbuffer->getHeight() == 0)
+        {
+            return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
+        }
+
+        if (mStencilbufferType == GL_RENDERBUFFER)
+        {
+            if (!gl::IsStencilRenderable(stencilbuffer->getInternalFormat()))
+            {
+                return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
+            }
+        }
+        else if (IsInternalTextureTarget(mStencilbufferType))
+        {
+            GLint internalformat = stencilbuffer->getInternalFormat();
+
+            // texture stencil attachments come along as part
+            // of OES_packed_depth_stencil + OES/ANGLE_depth_texture
+            if (!context->supportsDepthTextures())
+            {
+                return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
+            }
+
+            if (!gl::IsStencilTexture(internalformat))
+            {
+                return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
+            }
+        }
+        else
+        {
+            UNREACHABLE();
+            return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
+        }
+
+        if (missingAttachment)
+        {
+            width = stencilbuffer->getWidth();
+            height = stencilbuffer->getHeight();
+            samples = stencilbuffer->getSamples();
+            missingAttachment = false;
+        }
+        else if (width != stencilbuffer->getWidth() || height != stencilbuffer->getHeight())
+        {
+            return GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS;
+        }
+        else if (samples != stencilbuffer->getSamples())
+        {
+            return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_ANGLE;
+        }
+    }
+
+    // if we have both a depth and stencil buffer, they must refer to the same object
+    // since we only support packed_depth_stencil and not separate depth and stencil
+    if (depthbuffer && stencilbuffer && (depthbuffer != stencilbuffer))
+    {
+        return GL_FRAMEBUFFER_UNSUPPORTED;
+    }
+
+    // we need to have at least one attachment to be complete
+    if (missingAttachment)
+    {
+        return GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT;
+    }
+
+    return GL_FRAMEBUFFER_COMPLETE;
+}
+
+DefaultFramebuffer::DefaultFramebuffer(Colorbuffer *colorbuffer, DepthStencilbuffer *depthStencil)
+{
+    mColorbufferPointer.set(new Renderbuffer(0, colorbuffer));
+
+    Renderbuffer *depthStencilRenderbuffer = new Renderbuffer(0, depthStencil);
+    mDepthbufferPointer.set(depthStencilRenderbuffer);
+    mStencilbufferPointer.set(depthStencilRenderbuffer);
+
+    mColorbufferType = GL_RENDERBUFFER;
+    mDepthbufferType = (depthStencilRenderbuffer->getDepthSize() != 0) ? GL_RENDERBUFFER : GL_NONE;
+    mStencilbufferType = (depthStencilRenderbuffer->getStencilSize() != 0) ? GL_RENDERBUFFER : GL_NONE;
+}
+
+int Framebuffer::getSamples()
+{
+    if (completeness() == GL_FRAMEBUFFER_COMPLETE)
+    {
+        return getColorbuffer()->getSamples();
+    }
+    else
+    {
+        return 0;
+    }
+}
+
+GLenum DefaultFramebuffer::completeness()
+{
+    // The default framebuffer should always be complete
+    ASSERT(Framebuffer::completeness() == GL_FRAMEBUFFER_COMPLETE);
+
+    return GL_FRAMEBUFFER_COMPLETE;
+}
+
+}
diff --git a/src/3rdparty/angle/src/libGLESv2/Framebuffer.h b/src/3rdparty/angle/src/libGLESv2/Framebuffer.h
new file mode 100644 (file)
index 0000000..14d9c2a
--- /dev/null
@@ -0,0 +1,98 @@
+//
+// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// Framebuffer.h: Defines the gl::Framebuffer class. Implements GL framebuffer
+// objects and related functionality. [OpenGL ES 2.0.24] section 4.4 page 105.
+
+#ifndef LIBGLESV2_FRAMEBUFFER_H_
+#define LIBGLESV2_FRAMEBUFFER_H_
+
+#define GL_APICALL
+#include <GLES2/gl2.h>
+#include <d3d9.h>
+
+#include "common/angleutils.h"
+#include "common/RefCountObject.h"
+
+namespace gl
+{
+class Renderbuffer;
+class Colorbuffer;
+class Depthbuffer;
+class Stencilbuffer;
+class DepthStencilbuffer;
+
+class Framebuffer
+{
+  public:
+    Framebuffer();
+
+    virtual ~Framebuffer();
+
+    void setColorbuffer(GLenum type, GLuint colorbuffer);
+    void setDepthbuffer(GLenum type, GLuint depthbuffer);
+    void setStencilbuffer(GLenum type, GLuint stencilbuffer);
+
+    void detachTexture(GLuint texture);
+    void detachRenderbuffer(GLuint renderbuffer);
+
+    IDirect3DSurface9 *getRenderTarget();
+    IDirect3DSurface9 *getDepthStencil();
+
+    unsigned int getRenderTargetSerial();
+    unsigned int getDepthbufferSerial();
+    unsigned int getStencilbufferSerial();
+
+    Renderbuffer *getColorbuffer();
+    Renderbuffer *getDepthbuffer();
+    Renderbuffer *getStencilbuffer();
+    Renderbuffer *getNullColorbuffer();
+
+    GLenum getColorbufferType();
+    GLenum getDepthbufferType();
+    GLenum getStencilbufferType();
+
+    GLuint getColorbufferHandle();
+    GLuint getDepthbufferHandle();
+    GLuint getStencilbufferHandle();
+
+    bool hasStencil();
+    int getSamples();
+
+    virtual GLenum completeness();
+
+  protected:
+    GLenum mColorbufferType;
+    BindingPointer<Renderbuffer> mColorbufferPointer;
+
+    GLenum mDepthbufferType;
+    BindingPointer<Renderbuffer> mDepthbufferPointer;
+
+    GLenum mStencilbufferType;
+    BindingPointer<Renderbuffer> mStencilbufferPointer;
+
+    BindingPointer<Renderbuffer> mNullColorbufferPointer;
+
+  private:
+    DISALLOW_COPY_AND_ASSIGN(Framebuffer);
+
+    Renderbuffer *lookupRenderbuffer(GLenum type, GLuint handle) const;
+};
+
+class DefaultFramebuffer : public Framebuffer
+{
+  public:
+    DefaultFramebuffer(Colorbuffer *colorbuffer, DepthStencilbuffer *depthStencil);
+
+    virtual GLenum completeness();
+
+  private:
+    DISALLOW_COPY_AND_ASSIGN(DefaultFramebuffer);
+};
+
+}
+
+#endif   // LIBGLESV2_FRAMEBUFFER_H_
diff --git a/src/3rdparty/angle/src/libGLESv2/HandleAllocator.cpp b/src/3rdparty/angle/src/libGLESv2/HandleAllocator.cpp
new file mode 100644 (file)
index 0000000..c498f8a
--- /dev/null
@@ -0,0 +1,63 @@
+//
+// 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.
+//
+
+// HandleAllocator.cpp: Implements the gl::HandleAllocator class, which is used
+// to allocate GL handles.
+
+#include "libGLESv2/HandleAllocator.h"
+
+#include "libGLESv2/main.h"
+
+namespace gl
+{
+
+HandleAllocator::HandleAllocator() : mBaseValue(1), mNextValue(1)
+{
+}
+
+HandleAllocator::~HandleAllocator()
+{
+}
+
+void HandleAllocator::setBaseHandle(GLuint value)
+{
+    ASSERT(mBaseValue == mNextValue);
+    mBaseValue = value;
+    mNextValue = value;
+}
+
+GLuint HandleAllocator::allocate()
+{
+    if (mFreeValues.size())
+    {
+        GLuint handle = mFreeValues.back();
+        mFreeValues.pop_back();
+        return handle;
+    }
+    return mNextValue++;
+}
+
+void HandleAllocator::release(GLuint handle)
+{
+    if (handle == mNextValue - 1)
+    {
+        // Don't drop below base value
+        if(mNextValue > mBaseValue)
+        {
+            mNextValue--;
+        }
+    }
+    else
+    {
+        // Only free handles that we own - don't drop below the base value
+        if (handle >= mBaseValue)
+        {
+            mFreeValues.push_back(handle);
+        }
+    }
+}
+
+}
diff --git a/src/3rdparty/angle/src/libGLESv2/HandleAllocator.h b/src/3rdparty/angle/src/libGLESv2/HandleAllocator.h
new file mode 100644 (file)
index 0000000..a92e168
--- /dev/null
@@ -0,0 +1,45 @@
+//
+// 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.
+//
+
+// HandleAllocator.h: Defines the gl::HandleAllocator class, which is used to
+// allocate GL handles.
+
+#ifndef LIBGLESV2_HANDLEALLOCATOR_H_
+#define LIBGLESV2_HANDLEALLOCATOR_H_
+
+#define GL_APICALL
+#include <GLES2/gl2.h>
+
+#include <vector>
+
+#include "common/angleutils.h"
+
+namespace gl
+{
+
+class HandleAllocator
+{
+  public:
+    HandleAllocator();
+    virtual ~HandleAllocator();
+
+    void setBaseHandle(GLuint value);
+
+    GLuint allocate();
+    void release(GLuint handle);
+
+  private:
+    DISALLOW_COPY_AND_ASSIGN(HandleAllocator);
+
+    GLuint mBaseValue;
+    GLuint mNextValue;
+    typedef std::vector<GLuint> HandleList;
+    HandleList mFreeValues;
+};
+
+}
+
+#endif   // LIBGLESV2_HANDLEALLOCATOR_H_
diff --git a/src/3rdparty/angle/src/libGLESv2/IndexDataManager.cpp b/src/3rdparty/angle/src/libGLESv2/IndexDataManager.cpp
new file mode 100644 (file)
index 0000000..3dc0aef
--- /dev/null
@@ -0,0 +1,473 @@
+//
+// 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.
+//
+
+// IndexDataManager.cpp: Defines the IndexDataManager, a class that
+// runs the Buffer translation process for index buffers.
+
+#include "libGLESv2/IndexDataManager.h"
+
+#include "common/debug.h"
+
+#include "libGLESv2/Buffer.h"
+#include "libGLESv2/mathutil.h"
+#include "libGLESv2/main.h"
+
+namespace gl
+{
+unsigned int IndexBuffer::mCurrentSerial = 1;
+
+IndexDataManager::IndexDataManager(Context *context, IDirect3DDevice9 *device) : mDevice(device)
+{
+    mStreamingBufferShort = new StreamingIndexBuffer(mDevice, INITIAL_INDEX_BUFFER_SIZE, D3DFMT_INDEX16);
+
+    if (context->supports32bitIndices())
+    {
+        mStreamingBufferInt = new StreamingIndexBuffer(mDevice, INITIAL_INDEX_BUFFER_SIZE, D3DFMT_INDEX32);
+
+        if (!mStreamingBufferInt)
+        {
+            // Don't leave it in a half-initialized state
+            delete mStreamingBufferShort;
+            mStreamingBufferShort = NULL;
+        }
+    }
+    else
+    {
+        mStreamingBufferInt = NULL;
+    }
+
+    if (!mStreamingBufferShort)
+    {
+        ERR("Failed to allocate the streaming index buffer(s).");
+    }
+
+    mCountingBuffer = NULL;
+}
+
+IndexDataManager::~IndexDataManager()
+{
+    delete mStreamingBufferShort;
+    delete mStreamingBufferInt;
+    delete mCountingBuffer;
+}
+
+void convertIndices(GLenum type, const void *input, GLsizei count, void *output)
+{
+    if (type == GL_UNSIGNED_BYTE)
+    {
+        const GLubyte *in = static_cast<const GLubyte*>(input);
+        GLushort *out = static_cast<GLushort*>(output);
+
+        for (GLsizei i = 0; i < count; i++)
+        {
+            out[i] = in[i];
+        }
+    }
+    else if (type == GL_UNSIGNED_INT)
+    {
+        memcpy(output, input, count * sizeof(GLuint));
+    }
+    else if (type == GL_UNSIGNED_SHORT)
+    {
+        memcpy(output, input, count * sizeof(GLushort));
+    }
+    else UNREACHABLE();
+}
+
+template <class IndexType>
+void computeRange(const IndexType *indices, GLsizei count, GLuint *minIndex, GLuint *maxIndex)
+{
+    *minIndex = indices[0];
+    *maxIndex = indices[0];
+
+    for (GLsizei i = 0; i < count; i++)
+    {
+        if (*minIndex > indices[i]) *minIndex = indices[i];
+        if (*maxIndex < indices[i]) *maxIndex = indices[i];
+    }
+}
+
+void computeRange(GLenum type, const GLvoid *indices, GLsizei count, GLuint *minIndex, GLuint *maxIndex)
+{
+    if (type == GL_UNSIGNED_BYTE)
+    {
+        computeRange(static_cast<const GLubyte*>(indices), count, minIndex, maxIndex);
+    }
+    else if (type == GL_UNSIGNED_INT)
+    {
+        computeRange(static_cast<const GLuint*>(indices), count, minIndex, maxIndex);
+    }
+    else if (type == GL_UNSIGNED_SHORT)
+    {
+        computeRange(static_cast<const GLushort*>(indices), count, minIndex, maxIndex);
+    }
+    else UNREACHABLE();
+}
+
+GLenum IndexDataManager::prepareIndexData(GLenum type, GLsizei count, Buffer *buffer, const GLvoid *indices, TranslatedIndexData *translated)
+{
+    if (!mStreamingBufferShort)
+    {
+        return GL_OUT_OF_MEMORY;
+    }
+
+    D3DFORMAT format = (type == GL_UNSIGNED_INT) ? D3DFMT_INDEX32 : D3DFMT_INDEX16;
+    intptr_t offset = reinterpret_cast<intptr_t>(indices);
+    bool alignedOffset = false;
+
+    if (buffer != NULL)
+    {
+        switch (type)
+        {
+          case GL_UNSIGNED_BYTE:  alignedOffset = (offset % sizeof(GLubyte) == 0);  break;
+          case GL_UNSIGNED_SHORT: alignedOffset = (offset % sizeof(GLushort) == 0); break;
+          case GL_UNSIGNED_INT:   alignedOffset = (offset % sizeof(GLuint) == 0);   break;
+          default: UNREACHABLE(); alignedOffset = false;
+        }
+
+        if (typeSize(type) * count + offset > static_cast<std::size_t>(buffer->size()))
+        {
+            return GL_INVALID_OPERATION;
+        }
+
+        indices = static_cast<const GLubyte*>(buffer->data()) + offset;
+    }
+
+    StreamingIndexBuffer *streamingBuffer = (type == GL_UNSIGNED_INT) ? mStreamingBufferInt : mStreamingBufferShort;
+
+    StaticIndexBuffer *staticBuffer = buffer ? buffer->getStaticIndexBuffer() : NULL;
+    IndexBuffer *indexBuffer = streamingBuffer;
+    UINT streamOffset = 0;
+
+    if (staticBuffer && staticBuffer->lookupType(type) && alignedOffset)
+    {
+        indexBuffer = staticBuffer;
+        streamOffset = staticBuffer->lookupRange(offset, count, &translated->minIndex, &translated->maxIndex);
+
+        if (streamOffset == -1)
+        {
+            streamOffset = (offset / typeSize(type)) * indexSize(format);
+            computeRange(type, indices, count, &translated->minIndex, &translated->maxIndex);
+            staticBuffer->addRange(offset, count, translated->minIndex, translated->maxIndex, streamOffset);
+        }
+    }
+    else
+    {
+        int convertCount = count;
+
+        if (staticBuffer)
+        {
+            if (staticBuffer->size() == 0 && alignedOffset)
+            {
+                indexBuffer = staticBuffer;
+                convertCount = buffer->size() / typeSize(type);
+            }
+            else
+            {
+                buffer->invalidateStaticData();
+                staticBuffer = NULL;
+            }
+        }
+
+        void *output = NULL;
+        
+        if (indexBuffer)
+        {
+            indexBuffer->reserveSpace(convertCount * indexSize(format), type);
+            output = indexBuffer->map(indexSize(format) * convertCount, &streamOffset);
+        }
+        
+        if (output == NULL)
+        {
+            ERR("Failed to map index buffer.");
+            return GL_OUT_OF_MEMORY;
+        }
+
+        convertIndices(type, staticBuffer ? buffer->data() : indices, convertCount, output);
+        indexBuffer->unmap();
+
+        computeRange(type, indices, count, &translated->minIndex, &translated->maxIndex);
+
+        if (staticBuffer)
+        {
+            streamOffset = (offset / typeSize(type)) * indexSize(format);
+            staticBuffer->addRange(offset, count, translated->minIndex, translated->maxIndex, streamOffset);
+        }
+    }
+
+    translated->indexBuffer = indexBuffer->getBuffer();
+    translated->serial = indexBuffer->getSerial();
+    translated->startIndex = streamOffset / indexSize(format);
+
+    if (buffer)
+    {
+        buffer->promoteStaticUsage(count * typeSize(type));
+    }
+
+    return GL_NO_ERROR;
+}
+
+std::size_t IndexDataManager::indexSize(D3DFORMAT format) const
+{
+    return (format == D3DFMT_INDEX32) ? sizeof(unsigned int) : sizeof(unsigned short);
+}
+
+std::size_t IndexDataManager::typeSize(GLenum type) const
+{
+    switch (type)
+    {
+      case GL_UNSIGNED_INT:   return sizeof(GLuint);
+      case GL_UNSIGNED_SHORT: return sizeof(GLushort);
+      case GL_UNSIGNED_BYTE:  return sizeof(GLubyte);
+      default: UNREACHABLE(); return sizeof(GLushort);
+    }
+}
+
+StaticIndexBuffer *IndexDataManager::getCountingIndices(GLsizei count)
+{
+    if (count <= 65536)   // 16-bit indices
+    {
+        const unsigned int spaceNeeded = count * sizeof(unsigned short);
+
+        if (!mCountingBuffer || mCountingBuffer->size() < spaceNeeded)
+        {
+            delete mCountingBuffer;
+            mCountingBuffer = new StaticIndexBuffer(mDevice);
+            mCountingBuffer->reserveSpace(spaceNeeded, GL_UNSIGNED_SHORT);
+
+            UINT offset;
+            unsigned short *data = static_cast<unsigned short*>(mCountingBuffer->map(spaceNeeded, &offset));
+        
+            if (data)
+            {
+                for(int i = 0; i < count; i++)
+                {
+                    data[i] = i;
+                }
+
+                mCountingBuffer->unmap();
+            }
+        }
+    }
+    else if (mStreamingBufferInt)   // 32-bit indices supported
+    {
+        const unsigned int spaceNeeded = count * sizeof(unsigned int);
+
+        if (!mCountingBuffer || mCountingBuffer->size() < spaceNeeded)
+        {
+            delete mCountingBuffer;
+            mCountingBuffer = new StaticIndexBuffer(mDevice);
+            mCountingBuffer->reserveSpace(spaceNeeded, GL_UNSIGNED_INT);
+
+            UINT offset;
+            unsigned int *data = static_cast<unsigned int*>(mCountingBuffer->map(spaceNeeded, &offset));
+        
+            if (data)
+            {
+                for(int i = 0; i < count; i++)
+                {
+                    data[i] = i;
+                }
+                
+                mCountingBuffer->unmap();
+            }
+        }
+    }
+    else return NULL;
+    
+    return mCountingBuffer;
+}
+
+IndexBuffer::IndexBuffer(IDirect3DDevice9 *device, UINT size, D3DFORMAT format) : mDevice(device), mBufferSize(size), mIndexBuffer(NULL)
+{
+    if (size > 0)
+    {
+        D3DPOOL pool = getDisplay()->getBufferPool(D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY);
+        HRESULT result = device->CreateIndexBuffer(size, D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY, format, pool, &mIndexBuffer, NULL);
+        mSerial = issueSerial();
+
+        if (FAILED(result))
+        {
+            ERR("Out of memory allocating an index buffer of size %lu.", size);
+        }
+    }
+}
+
+IndexBuffer::~IndexBuffer()
+{
+    if (mIndexBuffer)
+    {
+        mIndexBuffer->Release();
+    }
+}
+
+IDirect3DIndexBuffer9 *IndexBuffer::getBuffer() const
+{
+    return mIndexBuffer;
+}
+
+unsigned int IndexBuffer::getSerial() const
+{
+    return mSerial;
+}
+
+unsigned int IndexBuffer::issueSerial()
+{
+    return mCurrentSerial++;
+}
+
+void IndexBuffer::unmap()
+{
+    if (mIndexBuffer)
+    {
+        mIndexBuffer->Unlock();
+    }
+}
+
+StreamingIndexBuffer::StreamingIndexBuffer(IDirect3DDevice9 *device, UINT initialSize, D3DFORMAT format) : IndexBuffer(device, initialSize, format)
+{
+    mWritePosition = 0;
+}
+
+StreamingIndexBuffer::~StreamingIndexBuffer()
+{
+}
+
+void *StreamingIndexBuffer::map(UINT requiredSpace, UINT *offset)
+{
+    void *mapPtr = NULL;
+
+    if (mIndexBuffer)
+    {
+        HRESULT result = mIndexBuffer->Lock(mWritePosition, requiredSpace, &mapPtr, D3DLOCK_NOOVERWRITE);
+     
+        if (FAILED(result))
+        {
+            ERR(" Lock failed with error 0x%08x", result);
+            return NULL;
+        }
+
+        *offset = mWritePosition;
+        mWritePosition += requiredSpace;
+    }
+
+    return mapPtr;
+}
+
+void StreamingIndexBuffer::reserveSpace(UINT requiredSpace, GLenum type)
+{
+    if (requiredSpace > mBufferSize)
+    {
+        if (mIndexBuffer)
+        {
+            mIndexBuffer->Release();
+            mIndexBuffer = NULL;
+        }
+
+        mBufferSize = std::max(requiredSpace, 2 * mBufferSize);
+
+        D3DPOOL pool = getDisplay()->getBufferPool(D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY);
+        HRESULT result = mDevice->CreateIndexBuffer(mBufferSize, D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY, type == GL_UNSIGNED_INT ? D3DFMT_INDEX32 : D3DFMT_INDEX16, pool, &mIndexBuffer, NULL);
+        mSerial = issueSerial();
+    
+        if (FAILED(result))
+        {
+            ERR("Out of memory allocating a vertex buffer of size %lu.", mBufferSize);
+        }
+
+        mWritePosition = 0;
+    }
+    else if (mWritePosition + requiredSpace > mBufferSize)   // Recycle
+    {
+        void *dummy;
+        mIndexBuffer->Lock(0, 1, &dummy, D3DLOCK_DISCARD);
+        mIndexBuffer->Unlock();
+
+        mWritePosition = 0;
+    }
+}
+
+StaticIndexBuffer::StaticIndexBuffer(IDirect3DDevice9 *device) : IndexBuffer(device, 0, D3DFMT_UNKNOWN)
+{
+    mCacheType = GL_NONE;
+}
+
+StaticIndexBuffer::~StaticIndexBuffer()
+{
+}
+
+void *StaticIndexBuffer::map(UINT requiredSpace, UINT *offset)
+{
+    void *mapPtr = NULL;
+
+    if (mIndexBuffer)
+    {
+        HRESULT result = mIndexBuffer->Lock(0, requiredSpace, &mapPtr, 0);
+     
+        if (FAILED(result))
+        {
+            ERR(" Lock failed with error 0x%08x", result);
+            return NULL;
+        }
+
+        *offset = 0;
+    }
+
+    return mapPtr;
+}
+
+void StaticIndexBuffer::reserveSpace(UINT requiredSpace, GLenum type)
+{
+    if (!mIndexBuffer && mBufferSize == 0)
+    {
+        D3DPOOL pool = getDisplay()->getBufferPool(D3DUSAGE_WRITEONLY);
+        HRESULT result = mDevice->CreateIndexBuffer(requiredSpace, D3DUSAGE_WRITEONLY, type == GL_UNSIGNED_INT ? D3DFMT_INDEX32 : D3DFMT_INDEX16, pool, &mIndexBuffer, NULL);
+        mSerial = issueSerial();
+    
+        if (FAILED(result))
+        {
+            ERR("Out of memory allocating a vertex buffer of size %lu.", mBufferSize);
+        }
+
+        mBufferSize = requiredSpace;
+        mCacheType = type;
+    }
+    else if (mIndexBuffer && mBufferSize >= requiredSpace && mCacheType == type)
+    {
+        // Already allocated
+    }
+    else UNREACHABLE();   // Static index buffers can't be resized
+}
+
+bool StaticIndexBuffer::lookupType(GLenum type)
+{
+    return mCacheType == type;
+}
+
+UINT StaticIndexBuffer::lookupRange(intptr_t offset, GLsizei count, UINT *minIndex, UINT *maxIndex)
+{
+    IndexRange range = {offset, count};
+
+    std::map<IndexRange, IndexResult>::iterator res = mCache.find(range);
+    
+    if (res == mCache.end())
+    {
+        return -1;
+    }
+
+    *minIndex = res->second.minIndex;
+    *maxIndex = res->second.maxIndex;
+    return res->second.streamOffset;
+}
+
+void StaticIndexBuffer::addRange(intptr_t offset, GLsizei count, UINT minIndex, UINT maxIndex, UINT streamOffset)
+{
+    IndexRange indexRange = {offset, count};
+    IndexResult indexResult = {minIndex, maxIndex, streamOffset};
+    mCache[indexRange] = indexResult;
+}
+
+}
diff --git a/src/3rdparty/angle/src/libGLESv2/IndexDataManager.h b/src/3rdparty/angle/src/libGLESv2/IndexDataManager.h
new file mode 100644 (file)
index 0000000..c1d4168
--- /dev/null
@@ -0,0 +1,149 @@
+//
+// 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.
+//
+
+// IndexDataManager.h: Defines the IndexDataManager, a class that
+// runs the Buffer translation process for index buffers.
+
+#ifndef LIBGLESV2_INDEXDATAMANAGER_H_
+#define LIBGLESV2_INDEXDATAMANAGER_H_
+
+#include <vector>
+#include <cstddef>
+
+#define GL_APICALL
+#include <GLES2/gl2.h>
+
+#include "libGLESv2/Context.h"
+
+namespace
+{
+    enum { INITIAL_INDEX_BUFFER_SIZE = 4096 * sizeof(GLuint) };
+}
+
+namespace gl
+{
+
+struct TranslatedIndexData
+{
+    UINT minIndex;
+    UINT maxIndex;
+    UINT startIndex;
+
+    IDirect3DIndexBuffer9 *indexBuffer;
+    unsigned int serial;
+};
+
+class IndexBuffer
+{
+  public:
+    IndexBuffer(IDirect3DDevice9 *device, UINT size, D3DFORMAT format);
+    virtual ~IndexBuffer();
+
+    UINT size() const { return mBufferSize; }
+    virtual void *map(UINT requiredSpace, UINT *offset) = 0;
+    void unmap();
+    virtual void reserveSpace(UINT requiredSpace, GLenum type) = 0;
+
+    IDirect3DIndexBuffer9 *getBuffer() const;
+    unsigned int getSerial() const;
+
+  protected:
+    IDirect3DDevice9 *const mDevice;
+
+    IDirect3DIndexBuffer9 *mIndexBuffer;
+    UINT mBufferSize;
+
+    unsigned int mSerial;
+    static unsigned int issueSerial();
+    static unsigned int mCurrentSerial;
+
+  private:
+    DISALLOW_COPY_AND_ASSIGN(IndexBuffer);
+};
+
+class StreamingIndexBuffer : public IndexBuffer
+{
+  public:
+    StreamingIndexBuffer(IDirect3DDevice9 *device, UINT initialSize, D3DFORMAT format);
+    ~StreamingIndexBuffer();
+
+    virtual void *map(UINT requiredSpace, UINT *offset);
+    virtual void reserveSpace(UINT requiredSpace, GLenum type);
+
+  private:
+    UINT mWritePosition;
+};
+
+class StaticIndexBuffer : public IndexBuffer
+{
+  public:
+    explicit StaticIndexBuffer(IDirect3DDevice9 *device);
+    ~StaticIndexBuffer();
+
+    virtual void *map(UINT requiredSpace, UINT *offset);
+    virtual void reserveSpace(UINT requiredSpace, GLenum type);
+
+    bool lookupType(GLenum type);
+    UINT lookupRange(intptr_t offset, GLsizei count, UINT *minIndex, UINT *maxIndex);   // Returns the offset into the index buffer, or -1 if not found
+    void addRange(intptr_t offset, GLsizei count, UINT minIndex, UINT maxIndex, UINT streamOffset);
+
+  private:
+    GLenum mCacheType;
+    
+    struct IndexRange
+    {
+        intptr_t offset;
+        GLsizei count;
+
+        bool operator<(const IndexRange& rhs) const
+        {
+            if (offset != rhs.offset)
+            {
+                return offset < rhs.offset;
+            }
+            if (count != rhs.count)
+            {
+                return count < rhs.count;
+            }
+            return false;
+        }
+    };
+
+    struct IndexResult
+    {
+        UINT minIndex;
+        UINT maxIndex;
+        UINT streamOffset;
+    };
+
+    std::map<IndexRange, IndexResult> mCache;
+};
+
+class IndexDataManager
+{
+  public:
+    IndexDataManager(Context *context, IDirect3DDevice9 *evice);
+    virtual ~IndexDataManager();
+
+    GLenum prepareIndexData(GLenum type, GLsizei count, Buffer *arrayElementBuffer, const GLvoid *indices, TranslatedIndexData *translated);
+    StaticIndexBuffer *getCountingIndices(GLsizei count);
+
+  private:
+    DISALLOW_COPY_AND_ASSIGN(IndexDataManager);
+
+    std::size_t typeSize(GLenum type) const;
+    std::size_t indexSize(D3DFORMAT format) const;
+
+    IDirect3DDevice9 *const mDevice;
+
+    StreamingIndexBuffer *mStreamingBufferShort;
+    StreamingIndexBuffer *mStreamingBufferInt;
+    StaticIndexBuffer *mCountingBuffer;
+};
+
+}
+
+#endif   // LIBGLESV2_INDEXDATAMANAGER_H_
diff --git a/src/3rdparty/angle/src/libGLESv2/Program.cpp b/src/3rdparty/angle/src/libGLESv2/Program.cpp
new file mode 100644 (file)
index 0000000..5f53a1f
--- /dev/null
@@ -0,0 +1,528 @@
+//
+// 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.
+//
+
+// Program.cpp: Implements the gl::Program class. Implements GL program objects
+// and related functionality. [OpenGL ES 2.0.24] section 2.10.3 page 28.
+
+#include "libGLESv2/Program.h"
+#include "libGLESv2/ProgramBinary.h"
+
+#include "common/debug.h"
+
+#include "libGLESv2/main.h"
+#include "libGLESv2/Shader.h"
+#include "libGLESv2/utilities.h"
+
+#include <string>
+
+namespace gl
+{
+const char * const g_fakepath = "C:\\fakepath";
+
+AttributeBindings::AttributeBindings()
+{
+}
+
+AttributeBindings::~AttributeBindings()
+{
+}
+
+InfoLog::InfoLog() : mInfoLog(NULL)
+{
+}
+
+InfoLog::~InfoLog()
+{
+    delete[] mInfoLog;
+}
+
+
+int InfoLog::getLength() const
+{
+    if (!mInfoLog)
+    {
+        return 0;
+    }
+    else
+    {
+       return strlen(mInfoLog) + 1;
+    }
+}
+
+void InfoLog::getLog(GLsizei bufSize, GLsizei *length, char *infoLog)
+{
+    int index = 0;
+
+    if (bufSize > 0)
+    {
+        if (mInfoLog)
+        {
+            index = std::min(bufSize - 1, (int)strlen(mInfoLog));
+            memcpy(infoLog, mInfoLog, index);
+        }
+
+        infoLog[index] = '\0';
+    }
+
+    if (length)
+    {
+        *length = index;
+    }
+}
+
+// append a santized message to the program info log.
+// The D3D compiler includes a fake file path in some of the warning or error 
+// messages, so lets remove all occurrences of this fake file path from the log.
+void InfoLog::appendSanitized(const char *message)
+{
+    std::string msg(message);
+
+    size_t found;
+    do
+    {
+        found = msg.find(g_fakepath);
+        if (found != std::string::npos)
+        {
+            msg.erase(found, strlen(g_fakepath));
+        }
+    }
+    while (found != std::string::npos);
+
+    append("%s\n", msg.c_str());
+}
+
+void InfoLog::append(const char *format, ...)
+{
+    if (!format)
+    {
+        return;
+    }
+
+    char info[1024];
+
+    va_list vararg;
+    va_start(vararg, format);
+    vsnprintf(info, sizeof(info), format, vararg);
+    va_end(vararg);
+
+    size_t infoLength = strlen(info);
+
+    if (!mInfoLog)
+    {
+        mInfoLog = new char[infoLength + 1];
+        strcpy(mInfoLog, info);
+    }
+    else
+    {
+        size_t logLength = strlen(mInfoLog);
+        char *newLog = new char[logLength + infoLength + 1];
+        strcpy(newLog, mInfoLog);
+        strcpy(newLog + logLength, info);
+
+        delete[] mInfoLog;
+        mInfoLog = newLog;
+    }
+}
+
+void InfoLog::reset()
+{
+    if (mInfoLog)
+    {
+        delete [] mInfoLog;
+        mInfoLog = NULL;
+    }
+}
+
+Program::Program(ResourceManager *manager, GLuint handle) : mResourceManager(manager), mHandle(handle)
+{
+    mFragmentShader = NULL;
+    mVertexShader = NULL;
+    mProgramBinary.set(NULL);
+    mDeleteStatus = false;
+    mLinked = false;
+    mRefCount = 0;
+}
+
+Program::~Program()
+{
+    unlink(true);
+
+    if (mVertexShader != NULL)
+    {
+        mVertexShader->release();
+    }
+
+    if (mFragmentShader != NULL)
+    {
+        mFragmentShader->release();
+    }
+}
+
+bool Program::attachShader(Shader *shader)
+{
+    if (shader->getType() == GL_VERTEX_SHADER)
+    {
+        if (mVertexShader)
+        {
+            return false;
+        }
+
+        mVertexShader = (VertexShader*)shader;
+        mVertexShader->addRef();
+    }
+    else if (shader->getType() == GL_FRAGMENT_SHADER)
+    {
+        if (mFragmentShader)
+        {
+            return false;
+        }
+
+        mFragmentShader = (FragmentShader*)shader;
+        mFragmentShader->addRef();
+    }
+    else UNREACHABLE();
+
+    return true;
+}
+
+bool Program::detachShader(Shader *shader)
+{
+    if (shader->getType() == GL_VERTEX_SHADER)
+    {
+        if (mVertexShader != shader)
+        {
+            return false;
+        }
+
+        mVertexShader->release();
+        mVertexShader = NULL;
+    }
+    else if (shader->getType() == GL_FRAGMENT_SHADER)
+    {
+        if (mFragmentShader != shader)
+        {
+            return false;
+        }
+
+        mFragmentShader->release();
+        mFragmentShader = NULL;
+    }
+    else UNREACHABLE();
+
+    return true;
+}
+
+int Program::getAttachedShadersCount() const
+{
+    return (mVertexShader ? 1 : 0) + (mFragmentShader ? 1 : 0);
+}
+
+void AttributeBindings::bindAttributeLocation(GLuint index, const char *name)
+{
+    if (index < MAX_VERTEX_ATTRIBS)
+    {
+        for (int i = 0; i < MAX_VERTEX_ATTRIBS; i++)
+        {
+            mAttributeBinding[i].erase(name);
+        }
+
+        mAttributeBinding[index].insert(name);
+    }
+}
+
+void Program::bindAttributeLocation(GLuint index, const char *name)
+{
+    mAttributeBindings.bindAttributeLocation(index, name);
+}
+
+// Links the HLSL code of the vertex and pixel shader by matching up their varyings,
+// compiling them into binaries, determining the attribute mappings, and collecting
+// a list of uniforms
+bool Program::link()
+{
+    unlink(false);
+
+    mInfoLog.reset();
+
+    mProgramBinary.set(new ProgramBinary());
+    mLinked = mProgramBinary->link(mInfoLog, mAttributeBindings, mFragmentShader, mVertexShader);
+
+    return mLinked;
+}
+
+int AttributeBindings::getAttributeBinding(const std::string &name) const
+{
+    for (int location = 0; location < MAX_VERTEX_ATTRIBS; location++)
+    {
+        if (mAttributeBinding[location].find(name) != mAttributeBinding[location].end())
+        {
+            return location;
+        }
+    }
+
+    return -1;
+}
+
+// Returns the program object to an unlinked state, before re-linking, or at destruction
+void Program::unlink(bool destroy)
+{
+    if (destroy)   // Object being destructed
+    {
+        if (mFragmentShader)
+        {
+            mFragmentShader->release();
+            mFragmentShader = NULL;
+        }
+
+        if (mVertexShader)
+        {
+            mVertexShader->release();
+            mVertexShader = NULL;
+        }
+    }
+
+    mProgramBinary.set(NULL);
+    mLinked = false;
+}
+
+bool Program::isLinked()
+{
+    return mLinked;
+}
+
+ProgramBinary* Program::getProgramBinary()
+{
+    return mProgramBinary.get();
+}
+
+bool Program::setProgramBinary(const void *binary, GLsizei length)
+{
+    unlink(false);
+
+    mInfoLog.reset();
+
+    mProgramBinary.set(new ProgramBinary());
+    mLinked = mProgramBinary->load(mInfoLog, binary, length);
+    if (!mLinked)
+    {
+        mProgramBinary.set(NULL);
+    }
+
+    return mLinked;
+}
+
+void Program::release()
+{
+    mRefCount--;
+
+    if (mRefCount == 0 && mDeleteStatus)
+    {
+        mResourceManager->deleteProgram(mHandle);
+    }
+}
+
+void Program::addRef()
+{
+    mRefCount++;
+}
+
+unsigned int Program::getRefCount() const
+{
+    return mRefCount;
+}
+
+GLint Program::getProgramBinaryLength() const
+{
+    ProgramBinary *programBinary = mProgramBinary.get();
+    if (programBinary)
+    {
+        return programBinary->getLength();
+    }
+    else
+    {
+        return 0;
+    }
+}
+
+int Program::getInfoLogLength() const
+{
+    return mInfoLog.getLength();
+}
+
+void Program::getInfoLog(GLsizei bufSize, GLsizei *length, char *infoLog)
+{
+    return mInfoLog.getLog(bufSize, length, infoLog);
+}
+
+void Program::getAttachedShaders(GLsizei maxCount, GLsizei *count, GLuint *shaders)
+{
+    int total = 0;
+
+    if (mVertexShader)
+    {
+        if (total < maxCount)
+        {
+            shaders[total] = mVertexShader->getHandle();
+        }
+
+        total++;
+    }
+
+    if (mFragmentShader)
+    {
+        if (total < maxCount)
+        {
+            shaders[total] = mFragmentShader->getHandle();
+        }
+
+        total++;
+    }
+
+    if (count)
+    {
+        *count = total;
+    }
+}
+
+void Program::getActiveAttribute(GLuint index, GLsizei bufsize, GLsizei *length, GLint *size, GLenum *type, GLchar *name)
+{
+    ProgramBinary *programBinary = getProgramBinary();
+    if (programBinary)
+    {
+        programBinary->getActiveAttribute(index, bufsize, length, size, type, name);
+    }
+    else
+    {
+        if (bufsize > 0)
+        {
+            name[0] = '\0';
+        }
+        
+        if (length)
+        {
+            *length = 0;
+        }
+
+        *type = GL_NONE;
+        *size = 1;
+    }
+}
+
+GLint Program::getActiveAttributeCount()
+{
+    ProgramBinary *programBinary = getProgramBinary();
+    if (programBinary)
+    {
+        return programBinary->getActiveAttributeCount();
+    }
+    else
+    {
+        return 0;
+    }
+}
+
+GLint Program::getActiveAttributeMaxLength()
+{
+    ProgramBinary *programBinary = getProgramBinary();
+    if (programBinary)
+    {
+        return programBinary->getActiveAttributeMaxLength();
+    }
+    else
+    {
+        return 0;
+    }
+}
+
+void Program::getActiveUniform(GLuint index, GLsizei bufsize, GLsizei *length, GLint *size, GLenum *type, GLchar *name)
+{
+    ProgramBinary *programBinary = getProgramBinary();
+    if (programBinary)
+    {
+        return programBinary->getActiveUniform(index, bufsize, length, size, type, name);
+    }
+    else
+    {
+        if (bufsize > 0)
+        {
+            name[0] = '\0';
+        }
+
+        if (length)
+        {
+            *length = 0;
+        }
+
+        *size = 0;
+        *type = GL_NONE;
+    }
+}
+
+GLint Program::getActiveUniformCount()
+{
+    ProgramBinary *programBinary = getProgramBinary();
+    if (programBinary)
+    {
+        return programBinary->getActiveUniformCount();
+    }
+    else
+    {
+        return 0;
+    }
+}
+
+GLint Program::getActiveUniformMaxLength()
+{
+    ProgramBinary *programBinary = getProgramBinary();
+    if (programBinary)
+    {
+        return programBinary->getActiveUniformMaxLength();
+    }
+    else
+    {
+        return 0;
+    }
+}
+
+void Program::flagForDeletion()
+{
+    mDeleteStatus = true;
+}
+
+bool Program::isFlaggedForDeletion() const
+{
+    return mDeleteStatus;
+}
+
+void Program::validate()
+{
+    mInfoLog.reset();
+
+    ProgramBinary *programBinary = getProgramBinary();
+    if (isLinked() && programBinary)
+    {
+        programBinary->validate(mInfoLog);
+    }
+    else
+    {
+        mInfoLog.append("Program has not been successfully linked.");
+    }
+}
+
+bool Program::isValidated() const
+{
+    ProgramBinary *programBinary = mProgramBinary.get();
+    if (programBinary)
+    {
+        return programBinary->isValidated();
+    }
+    else
+    {
+        return false;
+    }
+}
+
+}
diff --git a/src/3rdparty/angle/src/libGLESv2/Program.h b/src/3rdparty/angle/src/libGLESv2/Program.h
new file mode 100644 (file)
index 0000000..1c4716b
--- /dev/null
@@ -0,0 +1,121 @@
+//
+// 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.
+//
+
+// Program.h: Defines the gl::Program class. Implements GL program objects
+// and related functionality. [OpenGL ES 2.0.24] section 2.10.3 page 28.
+
+#ifndef LIBGLESV2_PROGRAM_H_
+#define LIBGLESV2_PROGRAM_H_
+
+#include <string>
+#include <set>
+
+#include "libGLESv2/Shader.h"
+#include "libGLESv2/Context.h"
+
+namespace gl
+{
+class ResourceManager;
+class FragmentShader;
+class VertexShader;
+
+extern const char * const g_fakepath;
+
+class AttributeBindings
+{
+  public:
+    AttributeBindings();
+    ~AttributeBindings();
+
+    void bindAttributeLocation(GLuint index, const char *name);
+    int getAttributeBinding(const std::string &name) const;
+
+  private:
+    std::set<std::string> mAttributeBinding[MAX_VERTEX_ATTRIBS];
+};
+
+class InfoLog
+{
+  public:
+    InfoLog();
+    ~InfoLog();
+
+    int getLength() const;
+    void getLog(GLsizei bufSize, GLsizei *length, char *infoLog);
+
+    void appendSanitized(const char *message);
+    void append(const char *info, ...);
+    void reset();
+  private:
+    DISALLOW_COPY_AND_ASSIGN(InfoLog);
+    char *mInfoLog;
+};
+
+class Program
+{
+  public:
+    Program(ResourceManager *manager, GLuint handle);
+
+    ~Program();
+
+    bool attachShader(Shader *shader);
+    bool detachShader(Shader *shader);
+    int getAttachedShadersCount() const;
+
+    void bindAttributeLocation(GLuint index, const char *name);
+
+    bool link();
+    bool isLinked();
+    bool setProgramBinary(const void *binary, GLsizei length);
+    ProgramBinary *getProgramBinary();
+
+    int getInfoLogLength() const;
+    void getInfoLog(GLsizei bufSize, GLsizei *length, char *infoLog);
+    void getAttachedShaders(GLsizei maxCount, GLsizei *count, GLuint *shaders);
+
+    void getActiveAttribute(GLuint index, GLsizei bufsize, GLsizei *length, GLint *size, GLenum *type, GLchar *name);
+    GLint getActiveAttributeCount();
+    GLint getActiveAttributeMaxLength();
+
+    void getActiveUniform(GLuint index, GLsizei bufsize, GLsizei *length, GLint *size, GLenum *type, GLchar *name);
+    GLint getActiveUniformCount();
+    GLint getActiveUniformMaxLength();
+
+    void addRef();
+    void release();
+    unsigned int getRefCount() const;
+    void flagForDeletion();
+    bool isFlaggedForDeletion() const;
+
+    void validate();
+    bool isValidated() const;
+
+    GLint getProgramBinaryLength() const;
+
+  private:
+    DISALLOW_COPY_AND_ASSIGN(Program);
+
+    void unlink(bool destroy = false);
+
+    FragmentShader *mFragmentShader;
+    VertexShader *mVertexShader;
+
+    AttributeBindings mAttributeBindings;
+
+    BindingPointer<ProgramBinary> mProgramBinary;
+    bool mLinked;
+    bool mDeleteStatus;   // Flag to indicate that the program can be deleted when no longer in use
+
+    unsigned int mRefCount;
+
+    ResourceManager *mResourceManager;
+    const GLuint mHandle;
+
+    InfoLog mInfoLog;
+};
+}
+
+#endif   // LIBGLESV2_PROGRAM_H_
diff --git a/src/3rdparty/angle/src/libGLESv2/ProgramBinary.cpp b/src/3rdparty/angle/src/libGLESv2/ProgramBinary.cpp
new file mode 100644 (file)
index 0000000..b3f5e3b
--- /dev/null
@@ -0,0 +1,2794 @@
+//
+// 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.
+//
+
+// Program.cpp: Implements the gl::Program class. Implements GL program objects
+// and related functionality. [OpenGL ES 2.0.24] section 2.10.3 page 28.
+
+#include "libGLESv2/BinaryStream.h"
+#include "libGLESv2/Program.h"
+#include "libGLESv2/ProgramBinary.h"
+
+#include "common/debug.h"
+#include "common/version.h"
+
+#include "libGLESv2/main.h"
+#include "libGLESv2/Shader.h"
+#include "libGLESv2/utilities.h"
+
+#include <string>
+
+#if !defined(ANGLE_COMPILE_OPTIMIZATION_LEVEL)
+#define ANGLE_COMPILE_OPTIMIZATION_LEVEL D3DCOMPILE_OPTIMIZATION_LEVEL3
+#endif
+
+namespace gl
+{
+std::string str(int i)
+{
+    char buffer[20];
+    snprintf(buffer, sizeof(buffer), "%d", i);
+    return buffer;
+}
+
+Uniform::Uniform(GLenum type, const std::string &_name, unsigned int arraySize)
+    : type(type), _name(_name), name(ProgramBinary::undecorateUniform(_name)), arraySize(arraySize)
+{
+    int bytes = UniformInternalSize(type) * arraySize;
+    data = new unsigned char[bytes];
+    memset(data, 0, bytes);
+    dirty = true;
+}
+
+Uniform::~Uniform()
+{
+    delete[] data;
+}
+
+bool Uniform::isArray()
+{
+    size_t dot = _name.find_last_of('.');
+    if (dot == std::string::npos) dot = -1;
+
+    return _name.compare(dot + 1, dot + 4, "ar_") == 0;
+}
+
+UniformLocation::UniformLocation(const std::string &_name, unsigned int element, unsigned int index) 
+    : name(ProgramBinary::undecorateUniform(_name)), element(element), index(index)
+{
+}
+
+unsigned int ProgramBinary::mCurrentSerial = 1;
+
+ProgramBinary::ProgramBinary() : RefCountObject(0), mSerial(issueSerial())
+{
+    mDevice = getDevice();
+
+    mPixelExecutable = NULL;
+    mVertexExecutable = NULL;
+    mConstantTablePS = NULL;
+    mConstantTableVS = NULL;
+
+    mValidated = false;
+
+    for (int index = 0; index < MAX_VERTEX_ATTRIBS; index++)
+    {
+        mSemanticIndex[index] = -1;
+    }
+
+    for (int index = 0; index < MAX_TEXTURE_IMAGE_UNITS; index++)
+    {
+        mSamplersPS[index].active = false;
+    }
+
+    for (int index = 0; index < MAX_VERTEX_TEXTURE_IMAGE_UNITS_VTF; index++)
+    {
+        mSamplersVS[index].active = false;
+    }
+
+    mUsedVertexSamplerRange = 0;
+    mUsedPixelSamplerRange = 0;
+
+    mDxDepthRangeLocation = -1;
+    mDxDepthLocation = -1;
+    mDxCoordLocation = -1;
+    mDxHalfPixelSizeLocation = -1;
+    mDxFrontCCWLocation = -1;
+    mDxPointsOrLinesLocation = -1;
+}
+
+ProgramBinary::~ProgramBinary()
+{
+    if (mPixelExecutable)
+    {
+        mPixelExecutable->Release();
+    }
+
+    if (mVertexExecutable)
+    {
+        mVertexExecutable->Release();
+    }
+
+    delete mConstantTablePS;
+    delete mConstantTableVS;
+
+    while (!mUniforms.empty())
+    {
+        delete mUniforms.back();
+        mUniforms.pop_back();
+    }
+}
+
+unsigned int ProgramBinary::getSerial() const
+{
+    return mSerial;
+}
+
+unsigned int ProgramBinary::issueSerial()
+{
+    return mCurrentSerial++;
+}
+
+IDirect3DPixelShader9 *ProgramBinary::getPixelShader()
+{
+    return mPixelExecutable;
+}
+
+IDirect3DVertexShader9 *ProgramBinary::getVertexShader()
+{
+    return mVertexExecutable;
+}
+
+GLuint ProgramBinary::getAttributeLocation(const char *name)
+{
+    if (name)
+    {
+        for (int index = 0; index < MAX_VERTEX_ATTRIBS; index++)
+        {
+            if (mLinkedAttribute[index].name == std::string(name))
+            {
+                return index;
+            }
+        }
+    }
+
+    return -1;
+}
+
+int ProgramBinary::getSemanticIndex(int attributeIndex)
+{
+    ASSERT(attributeIndex >= 0 && attributeIndex < MAX_VERTEX_ATTRIBS);
+    
+    return mSemanticIndex[attributeIndex];
+}
+
+// Returns one more than the highest sampler index used.
+GLint ProgramBinary::getUsedSamplerRange(SamplerType type)
+{
+    switch (type)
+    {
+      case SAMPLER_PIXEL:
+        return mUsedPixelSamplerRange;
+      case SAMPLER_VERTEX:
+        return mUsedVertexSamplerRange;
+      default:
+        UNREACHABLE();
+        return 0;
+    }
+}
+
+bool ProgramBinary::usesPointSize() const
+{
+    return mUsesPointSize;
+}
+
+// Returns the index of the texture image unit (0-19) corresponding to a Direct3D 9 sampler
+// index (0-15 for the pixel shader and 0-3 for the vertex shader).
+GLint ProgramBinary::getSamplerMapping(SamplerType type, unsigned int samplerIndex)
+{
+    GLint logicalTextureUnit = -1;
+
+    switch (type)
+    {
+      case SAMPLER_PIXEL:
+        ASSERT(samplerIndex < sizeof(mSamplersPS)/sizeof(mSamplersPS[0]));
+
+        if (mSamplersPS[samplerIndex].active)
+        {
+            logicalTextureUnit = mSamplersPS[samplerIndex].logicalTextureUnit;
+        }
+        break;
+      case SAMPLER_VERTEX:
+        ASSERT(samplerIndex < sizeof(mSamplersVS)/sizeof(mSamplersVS[0]));
+
+        if (mSamplersVS[samplerIndex].active)
+        {
+            logicalTextureUnit = mSamplersVS[samplerIndex].logicalTextureUnit;
+        }
+        break;
+      default: UNREACHABLE();
+    }
+
+    if (logicalTextureUnit >= 0 && logicalTextureUnit < (GLint)getContext()->getMaximumCombinedTextureImageUnits())
+    {
+        return logicalTextureUnit;
+    }
+
+    return -1;
+}
+
+// Returns the texture type for a given Direct3D 9 sampler type and
+// index (0-15 for the pixel shader and 0-3 for the vertex shader).
+TextureType ProgramBinary::getSamplerTextureType(SamplerType type, unsigned int samplerIndex)
+{
+    switch (type)
+    {
+      case SAMPLER_PIXEL:
+        ASSERT(samplerIndex < sizeof(mSamplersPS)/sizeof(mSamplersPS[0]));
+        ASSERT(mSamplersPS[samplerIndex].active);
+        return mSamplersPS[samplerIndex].textureType;
+      case SAMPLER_VERTEX:
+        ASSERT(samplerIndex < sizeof(mSamplersVS)/sizeof(mSamplersVS[0]));
+        ASSERT(mSamplersVS[samplerIndex].active);
+        return mSamplersVS[samplerIndex].textureType;
+      default: UNREACHABLE();
+    }
+
+    return TEXTURE_2D;
+}
+
+GLint ProgramBinary::getUniformLocation(std::string name)
+{
+    unsigned int subscript = 0;
+
+    // Strip any trailing array operator and retrieve the subscript
+    size_t open = name.find_last_of('[');
+    size_t close = name.find_last_of(']');
+    if (open != std::string::npos && close == name.length() - 1)
+    {
+        subscript = atoi(name.substr(open + 1).c_str());
+        name.erase(open);
+    }
+
+    unsigned int numUniforms = mUniformIndex.size();
+    for (unsigned int location = 0; location < numUniforms; location++)
+    {
+        if (mUniformIndex[location].name == name &&
+            mUniformIndex[location].element == subscript)
+        {
+            return location;
+        }
+    }
+
+    return -1;
+}
+
+bool ProgramBinary::setUniform1fv(GLint location, GLsizei count, const GLfloat* v)
+{
+    if (location < 0 || location >= (int)mUniformIndex.size())
+    {
+        return false;
+    }
+
+    Uniform *targetUniform = mUniforms[mUniformIndex[location].index];
+    targetUniform->dirty = true;
+
+    if (targetUniform->type == GL_FLOAT)
+    {
+        int arraySize = targetUniform->arraySize;
+
+        if (arraySize == 1 && count > 1)
+            return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION
+
+        count = std::min(arraySize - (int)mUniformIndex[location].element, count);
+
+        GLfloat *target = (GLfloat*)targetUniform->data + mUniformIndex[location].element * 4;
+
+        for (int i = 0; i < count; i++)
+        {
+            target[0] = v[0];
+            target[1] = 0;
+            target[2] = 0;
+            target[3] = 0;
+            target += 4;
+            v += 1;
+        }
+    }
+    else if (targetUniform->type == GL_BOOL)
+    {
+        int arraySize = targetUniform->arraySize;
+
+        if (arraySize == 1 && count > 1)
+            return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION
+
+        count = std::min(arraySize - (int)mUniformIndex[location].element, count);
+        GLboolean *boolParams = (GLboolean*)targetUniform->data + mUniformIndex[location].element;
+
+        for (int i = 0; i < count; ++i)
+        {
+            if (v[i] == 0.0f)
+            {
+                boolParams[i] = GL_FALSE;
+            }
+            else
+            {
+                boolParams[i] = GL_TRUE;
+            }
+        }
+    }
+    else
+    {
+        return false;
+    }
+
+    return true;
+}
+
+bool ProgramBinary::setUniform2fv(GLint location, GLsizei count, const GLfloat *v)
+{
+    if (location < 0 || location >= (int)mUniformIndex.size())
+    {
+        return false;
+    }
+
+    Uniform *targetUniform = mUniforms[mUniformIndex[location].index];
+    targetUniform->dirty = true;
+
+    if (targetUniform->type == GL_FLOAT_VEC2)
+    {
+        int arraySize = targetUniform->arraySize;
+
+        if (arraySize == 1 && count > 1)
+            return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION
+
+        count = std::min(arraySize - (int)mUniformIndex[location].element, count);
+
+        GLfloat *target = (GLfloat*)targetUniform->data + mUniformIndex[location].element * 4;
+
+        for (int i = 0; i < count; i++)
+        {
+            target[0] = v[0];
+            target[1] = v[1];
+            target[2] = 0;
+            target[3] = 0;
+            target += 4;
+            v += 2;
+        }
+    }
+    else if (targetUniform->type == GL_BOOL_VEC2)
+    {
+        int arraySize = targetUniform->arraySize;
+
+        if (arraySize == 1 && count > 1)
+            return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION
+
+        count = std::min(arraySize - (int)mUniformIndex[location].element, count);
+
+        GLboolean *boolParams = (GLboolean*)targetUniform->data + mUniformIndex[location].element * 2;
+
+        for (int i = 0; i < count * 2; ++i)
+        {
+            if (v[i] == 0.0f)
+            {
+                boolParams[i] = GL_FALSE;
+            }
+            else
+            {
+                boolParams[i] = GL_TRUE;
+            }
+        }
+    }
+    else 
+    {
+        return false;
+    }
+
+    return true;
+}
+
+bool ProgramBinary::setUniform3fv(GLint location, GLsizei count, const GLfloat *v)
+{
+    if (location < 0 || location >= (int)mUniformIndex.size())
+    {
+        return false;
+    }
+
+    Uniform *targetUniform = mUniforms[mUniformIndex[location].index];
+    targetUniform->dirty = true;
+
+    if (targetUniform->type == GL_FLOAT_VEC3)
+    {
+        int arraySize = targetUniform->arraySize;
+
+        if (arraySize == 1 && count > 1)
+            return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION
+
+        count = std::min(arraySize - (int)mUniformIndex[location].element, count);
+
+        GLfloat *target = (GLfloat*)targetUniform->data + mUniformIndex[location].element * 4;
+
+        for (int i = 0; i < count; i++)
+        {
+            target[0] = v[0];
+            target[1] = v[1];
+            target[2] = v[2];
+            target[3] = 0;
+            target += 4;
+            v += 3;
+        }
+    }
+    else if (targetUniform->type == GL_BOOL_VEC3)
+    {
+        int arraySize = targetUniform->arraySize;
+
+        if (arraySize == 1 && count > 1)
+            return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION
+
+        count = std::min(arraySize - (int)mUniformIndex[location].element, count);
+        GLboolean *boolParams = (GLboolean*)targetUniform->data + mUniformIndex[location].element * 3;
+
+        for (int i = 0; i < count * 3; ++i)
+        {
+            if (v[i] == 0.0f)
+            {
+                boolParams[i] = GL_FALSE;
+            }
+            else
+            {
+                boolParams[i] = GL_TRUE;
+            }
+        }
+    }
+    else 
+    {
+        return false;
+    }
+
+    return true;
+}
+
+bool ProgramBinary::setUniform4fv(GLint location, GLsizei count, const GLfloat *v)
+{
+    if (location < 0 || location >= (int)mUniformIndex.size())
+    {
+        return false;
+    }
+
+    Uniform *targetUniform = mUniforms[mUniformIndex[location].index];
+    targetUniform->dirty = true;
+
+    if (targetUniform->type == GL_FLOAT_VEC4)
+    {
+        int arraySize = targetUniform->arraySize;
+
+        if (arraySize == 1 && count > 1)
+            return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION
+
+        count = std::min(arraySize - (int)mUniformIndex[location].element, count);
+
+        memcpy(targetUniform->data + mUniformIndex[location].element * sizeof(GLfloat) * 4,
+               v, 4 * sizeof(GLfloat) * count);
+    }
+    else if (targetUniform->type == GL_BOOL_VEC4)
+    {
+        int arraySize = targetUniform->arraySize;
+
+        if (arraySize == 1 && count > 1)
+            return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION
+
+        count = std::min(arraySize - (int)mUniformIndex[location].element, count);
+        GLboolean *boolParams = (GLboolean*)targetUniform->data + mUniformIndex[location].element * 4;
+
+        for (int i = 0; i < count * 4; ++i)
+        {
+            if (v[i] == 0.0f)
+            {
+                boolParams[i] = GL_FALSE;
+            }
+            else
+            {
+                boolParams[i] = GL_TRUE;
+            }
+        }
+    }
+    else 
+    {
+        return false;
+    }
+
+    return true;
+}
+
+template<typename T, int targetWidth, int targetHeight, int srcWidth, int srcHeight>
+void transposeMatrix(T *target, const GLfloat *value)
+{
+    int copyWidth = std::min(targetWidth, srcWidth);
+    int copyHeight = std::min(targetHeight, srcHeight);
+
+    for (int x = 0; x < copyWidth; x++)
+    {
+        for (int y = 0; y < copyHeight; y++)
+        {
+            target[x * targetWidth + y] = (T)value[y * srcWidth + x];
+        }
+    }
+    // clear unfilled right side
+    for (int y = 0; y < copyHeight; y++)
+    {
+        for (int x = srcWidth; x < targetWidth; x++)
+        {
+            target[y * targetWidth + x] = (T)0;
+        }
+    }
+    // clear unfilled bottom.
+    for (int y = srcHeight; y < targetHeight; y++)
+    {
+        for (int x = 0; x < targetWidth; x++)
+        {
+            target[y * targetWidth + x] = (T)0;
+        }
+    }
+}
+
+bool ProgramBinary::setUniformMatrix2fv(GLint location, GLsizei count, const GLfloat *value)
+{
+    if (location < 0 || location >= (int)mUniformIndex.size())
+    {
+        return false;
+    }
+
+    Uniform *targetUniform = mUniforms[mUniformIndex[location].index];
+    targetUniform->dirty = true;
+
+    if (targetUniform->type != GL_FLOAT_MAT2)
+    {
+        return false;
+    }
+
+    int arraySize = targetUniform->arraySize;
+
+    if (arraySize == 1 && count > 1)
+        return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION
+
+    count = std::min(arraySize - (int)mUniformIndex[location].element, count);
+
+    GLfloat *target = (GLfloat*)targetUniform->data + mUniformIndex[location].element * 8;
+    for (int i = 0; i < count; i++)
+    {
+        transposeMatrix<GLfloat,4,2,2,2>(target, value);
+        target += 8;
+        value += 4;
+    }
+
+    return true;
+}
+
+bool ProgramBinary::setUniformMatrix3fv(GLint location, GLsizei count, const GLfloat *value)
+{
+    if (location < 0 || location >= (int)mUniformIndex.size())
+    {
+        return false;
+    }
+
+    Uniform *targetUniform = mUniforms[mUniformIndex[location].index];
+    targetUniform->dirty = true;
+
+    if (targetUniform->type != GL_FLOAT_MAT3)
+    {
+        return false;
+    }
+
+    int arraySize = targetUniform->arraySize;
+
+    if (arraySize == 1 && count > 1)
+        return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION
+
+    count = std::min(arraySize - (int)mUniformIndex[location].element, count);
+
+    GLfloat *target = (GLfloat*)targetUniform->data + mUniformIndex[location].element * 12;
+    for (int i = 0; i < count; i++)
+    {
+        transposeMatrix<GLfloat,4,3,3,3>(target, value);
+        target += 12;
+        value += 9;
+    }
+
+    return true;
+}
+
+
+bool ProgramBinary::setUniformMatrix4fv(GLint location, GLsizei count, const GLfloat *value)
+{
+    if (location < 0 || location >= (int)mUniformIndex.size())
+    {
+        return false;
+    }
+
+    Uniform *targetUniform = mUniforms[mUniformIndex[location].index];
+    targetUniform->dirty = true;
+
+    if (targetUniform->type != GL_FLOAT_MAT4)
+    {
+        return false;
+    }
+
+    int arraySize = targetUniform->arraySize;
+
+    if (arraySize == 1 && count > 1)
+        return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION
+
+    count = std::min(arraySize - (int)mUniformIndex[location].element, count);
+
+    GLfloat *target = (GLfloat*)(targetUniform->data + mUniformIndex[location].element * sizeof(GLfloat) * 16);
+    for (int i = 0; i < count; i++)
+    {
+        transposeMatrix<GLfloat,4,4,4,4>(target, value);
+        target += 16;
+        value += 16;
+    }
+
+    return true;
+}
+
+bool ProgramBinary::setUniform1iv(GLint location, GLsizei count, const GLint *v)
+{
+    if (location < 0 || location >= (int)mUniformIndex.size())
+    {
+        return false;
+    }
+
+    Uniform *targetUniform = mUniforms[mUniformIndex[location].index];
+    targetUniform->dirty = true;
+
+    if (targetUniform->type == GL_INT ||
+        targetUniform->type == GL_SAMPLER_2D ||
+        targetUniform->type == GL_SAMPLER_CUBE)
+    {
+        int arraySize = targetUniform->arraySize;
+
+        if (arraySize == 1 && count > 1)
+            return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION
+
+        count = std::min(arraySize - (int)mUniformIndex[location].element, count);
+
+        memcpy(targetUniform->data + mUniformIndex[location].element * sizeof(GLint),
+               v, sizeof(GLint) * count);
+    }
+    else if (targetUniform->type == GL_BOOL)
+    {
+        int arraySize = targetUniform->arraySize;
+
+        if (arraySize == 1 && count > 1)
+            return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION
+
+        count = std::min(arraySize - (int)mUniformIndex[location].element, count);
+        GLboolean *boolParams = (GLboolean*)targetUniform->data + mUniformIndex[location].element;
+
+        for (int i = 0; i < count; ++i)
+        {
+            if (v[i] == 0)
+            {
+                boolParams[i] = GL_FALSE;
+            }
+            else
+            {
+                boolParams[i] = GL_TRUE;
+            }
+        }
+    }
+    else
+    {
+        return false;
+    }
+
+    return true;
+}
+
+bool ProgramBinary::setUniform2iv(GLint location, GLsizei count, const GLint *v)
+{
+    if (location < 0 || location >= (int)mUniformIndex.size())
+    {
+        return false;
+    }
+
+    Uniform *targetUniform = mUniforms[mUniformIndex[location].index];
+    targetUniform->dirty = true;
+
+    if (targetUniform->type == GL_INT_VEC2)
+    {
+        int arraySize = targetUniform->arraySize;
+
+        if (arraySize == 1 && count > 1)
+            return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION
+
+        count = std::min(arraySize - (int)mUniformIndex[location].element, count);
+
+        memcpy(targetUniform->data + mUniformIndex[location].element * sizeof(GLint) * 2,
+               v, 2 * sizeof(GLint) * count);
+    }
+    else if (targetUniform->type == GL_BOOL_VEC2)
+    {
+        int arraySize = targetUniform->arraySize;
+
+        if (arraySize == 1 && count > 1)
+            return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION
+
+        count = std::min(arraySize - (int)mUniformIndex[location].element, count);
+        GLboolean *boolParams = (GLboolean*)targetUniform->data + mUniformIndex[location].element * 2;
+
+        for (int i = 0; i < count * 2; ++i)
+        {
+            if (v[i] == 0)
+            {
+                boolParams[i] = GL_FALSE;
+            }
+            else
+            {
+                boolParams[i] = GL_TRUE;
+            }
+        }
+    }
+    else
+    {
+        return false;
+    }
+
+    return true;
+}
+
+bool ProgramBinary::setUniform3iv(GLint location, GLsizei count, const GLint *v)
+{
+    if (location < 0 || location >= (int)mUniformIndex.size())
+    {
+        return false;
+    }
+
+    Uniform *targetUniform = mUniforms[mUniformIndex[location].index];
+    targetUniform->dirty = true;
+
+    if (targetUniform->type == GL_INT_VEC3)
+    {
+        int arraySize = targetUniform->arraySize;
+
+        if (arraySize == 1 && count > 1)
+            return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION
+
+        count = std::min(arraySize - (int)mUniformIndex[location].element, count);
+
+        memcpy(targetUniform->data + mUniformIndex[location].element * sizeof(GLint) * 3,
+               v, 3 * sizeof(GLint) * count);
+    }
+    else if (targetUniform->type == GL_BOOL_VEC3)
+    {
+        int arraySize = targetUniform->arraySize;
+
+        if (arraySize == 1 && count > 1)
+            return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION
+
+        count = std::min(arraySize - (int)mUniformIndex[location].element, count);
+        GLboolean *boolParams = (GLboolean*)targetUniform->data + mUniformIndex[location].element * 3;
+
+        for (int i = 0; i < count * 3; ++i)
+        {
+            if (v[i] == 0)
+            {
+                boolParams[i] = GL_FALSE;
+            }
+            else
+            {
+                boolParams[i] = GL_TRUE;
+            }
+        }
+    }
+    else
+    {
+        return false;
+    }
+
+    return true;
+}
+
+bool ProgramBinary::setUniform4iv(GLint location, GLsizei count, const GLint *v)
+{
+    if (location < 0 || location >= (int)mUniformIndex.size())
+    {
+        return false;
+    }
+
+    Uniform *targetUniform = mUniforms[mUniformIndex[location].index];
+    targetUniform->dirty = true;
+
+    if (targetUniform->type == GL_INT_VEC4)
+    {
+        int arraySize = targetUniform->arraySize;
+
+        if (arraySize == 1 && count > 1)
+            return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION
+
+        count = std::min(arraySize - (int)mUniformIndex[location].element, count);
+
+        memcpy(targetUniform->data + mUniformIndex[location].element * sizeof(GLint) * 4,
+               v, 4 * sizeof(GLint) * count);
+    }
+    else if (targetUniform->type == GL_BOOL_VEC4)
+    {
+        int arraySize = targetUniform->arraySize;
+
+        if (arraySize == 1 && count > 1)
+            return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION
+
+        count = std::min(arraySize - (int)mUniformIndex[location].element, count);
+        GLboolean *boolParams = (GLboolean*)targetUniform->data + mUniformIndex[location].element * 4;
+
+        for (int i = 0; i < count * 4; ++i)
+        {
+            if (v[i] == 0)
+            {
+                boolParams[i] = GL_FALSE;
+            }
+            else
+            {
+                boolParams[i] = GL_TRUE;
+            }
+        }
+    }
+    else
+    {
+        return false;
+    }
+
+    return true;
+}
+
+bool ProgramBinary::getUniformfv(GLint location, GLsizei *bufSize, GLfloat *params)
+{
+    if (location < 0 || location >= (int)mUniformIndex.size())
+    {
+        return false;
+    }
+
+    Uniform *targetUniform = mUniforms[mUniformIndex[location].index];
+
+    // sized queries -- ensure the provided buffer is large enough
+    if (bufSize)
+    {
+        int requiredBytes = UniformExternalSize(targetUniform->type);
+        if (*bufSize < requiredBytes)
+        {
+            return false;
+        }
+    }
+
+    switch (targetUniform->type)
+    {
+      case GL_FLOAT_MAT2:
+        transposeMatrix<GLfloat,2,2,4,2>(params, (GLfloat*)targetUniform->data + mUniformIndex[location].element * 8);
+        break;
+      case GL_FLOAT_MAT3:
+        transposeMatrix<GLfloat,3,3,4,3>(params, (GLfloat*)targetUniform->data + mUniformIndex[location].element * 12);
+        break;
+      case GL_FLOAT_MAT4:
+        transposeMatrix<GLfloat,4,4,4,4>(params, (GLfloat*)targetUniform->data + mUniformIndex[location].element * 16);
+        break;
+      default:
+        {
+            unsigned int count = UniformExternalComponentCount(targetUniform->type);
+            unsigned int internalCount = UniformInternalComponentCount(targetUniform->type);
+
+            switch (UniformComponentType(targetUniform->type))
+            {
+              case GL_BOOL:
+                {
+                    GLboolean *boolParams = (GLboolean*)targetUniform->data + mUniformIndex[location].element * internalCount;
+
+                    for (unsigned int i = 0; i < count; ++i)
+                    {
+                        params[i] = (boolParams[i] == GL_FALSE) ? 0.0f : 1.0f;
+                    }
+                }
+                break;
+              case GL_FLOAT:
+                memcpy(params, targetUniform->data + mUniformIndex[location].element * internalCount * sizeof(GLfloat),
+                       count * sizeof(GLfloat));
+                break;
+              case GL_INT:
+                {
+                    GLint *intParams = (GLint*)targetUniform->data + mUniformIndex[location].element * internalCount;
+
+                    for (unsigned int i = 0; i < count; ++i)
+                    {
+                        params[i] = (float)intParams[i];
+                    }
+                }
+                break;
+              default: UNREACHABLE();
+            }
+        }
+    }
+
+    return true;
+}
+
+bool ProgramBinary::getUniformiv(GLint location, GLsizei *bufSize, GLint *params)
+{
+    if (location < 0 || location >= (int)mUniformIndex.size())
+    {
+        return false;
+    }
+
+    Uniform *targetUniform = mUniforms[mUniformIndex[location].index];
+
+    // sized queries -- ensure the provided buffer is large enough
+    if (bufSize)
+    {
+        int requiredBytes = UniformExternalSize(targetUniform->type);
+        if (*bufSize < requiredBytes)
+        {
+            return false;
+        }
+    }
+
+    switch (targetUniform->type)
+    {
+      case GL_FLOAT_MAT2:
+        {
+            transposeMatrix<GLint,2,2,4,2>(params, (GLfloat*)targetUniform->data + mUniformIndex[location].element * 8);
+        }
+        break;
+      case GL_FLOAT_MAT3:
+        {
+            transposeMatrix<GLint,3,3,4,3>(params, (GLfloat*)targetUniform->data + mUniformIndex[location].element * 12);
+        }
+        break;
+      case GL_FLOAT_MAT4:
+        {
+            transposeMatrix<GLint,4,4,4,4>(params, (GLfloat*)targetUniform->data + mUniformIndex[location].element * 16);
+        }
+        break;
+      default:
+        {
+            unsigned int count = UniformExternalComponentCount(targetUniform->type);
+            unsigned int internalCount = UniformInternalComponentCount(targetUniform->type);
+
+            switch (UniformComponentType(targetUniform->type))
+            {
+              case GL_BOOL:
+                {
+                    GLboolean *boolParams = targetUniform->data + mUniformIndex[location].element * internalCount;
+
+                    for (unsigned int i = 0; i < count; ++i)
+                    {
+                        params[i] = (GLint)boolParams[i];
+                    }
+                }
+                break;
+              case GL_FLOAT:
+                {
+                    GLfloat *floatParams = (GLfloat*)targetUniform->data + mUniformIndex[location].element * internalCount;
+
+                    for (unsigned int i = 0; i < count; ++i)
+                    {
+                        params[i] = (GLint)floatParams[i];
+                    }
+                }
+                break;
+              case GL_INT:
+                memcpy(params, targetUniform->data + mUniformIndex[location].element * internalCount * sizeof(GLint),
+                       count * sizeof(GLint));
+                break;
+              default: UNREACHABLE();
+            }
+        }
+    }
+
+    return true;
+}
+
+void ProgramBinary::dirtyAllUniforms()
+{
+    unsigned int numUniforms = mUniforms.size();
+    for (unsigned int index = 0; index < numUniforms; index++)
+    {
+        mUniforms[index]->dirty = true;
+    }
+}
+
+// Applies all the uniforms set for this program object to the Direct3D 9 device
+void ProgramBinary::applyUniforms()
+{
+    for (std::vector<Uniform*>::iterator ub = mUniforms.begin(), ue = mUniforms.end(); ub != ue; ++ub) {
+        Uniform *targetUniform = *ub;
+
+        if (targetUniform->dirty)
+        {
+            int arraySize = targetUniform->arraySize;
+            GLfloat *f = (GLfloat*)targetUniform->data;
+            GLint *i = (GLint*)targetUniform->data;
+            GLboolean *b = (GLboolean*)targetUniform->data;
+
+            switch (targetUniform->type)
+            {
+              case GL_BOOL:       applyUniformnbv(targetUniform, arraySize, 1, b);    break;
+              case GL_BOOL_VEC2:  applyUniformnbv(targetUniform, arraySize, 2, b);    break;
+              case GL_BOOL_VEC3:  applyUniformnbv(targetUniform, arraySize, 3, b);    break;
+              case GL_BOOL_VEC4:  applyUniformnbv(targetUniform, arraySize, 4, b);    break;
+              case GL_FLOAT:
+              case GL_FLOAT_VEC2:
+              case GL_FLOAT_VEC3:
+              case GL_FLOAT_VEC4:
+              case GL_FLOAT_MAT2:
+              case GL_FLOAT_MAT3:
+              case GL_FLOAT_MAT4: applyUniformnfv(targetUniform, f);                  break;
+              case GL_SAMPLER_2D:
+              case GL_SAMPLER_CUBE:
+              case GL_INT:        applyUniform1iv(targetUniform, arraySize, i);       break;
+              case GL_INT_VEC2:   applyUniform2iv(targetUniform, arraySize, i);       break;
+              case GL_INT_VEC3:   applyUniform3iv(targetUniform, arraySize, i);       break;
+              case GL_INT_VEC4:   applyUniform4iv(targetUniform, arraySize, i);       break;
+              default:
+                UNREACHABLE();
+            }
+
+            targetUniform->dirty = false;
+        }
+    }
+}
+
+// Compiles the HLSL code of the attached shaders into executable binaries
+ID3D10Blob *ProgramBinary::compileToBinary(InfoLog &infoLog, const char *hlsl, const char *profile, D3DConstantTable **constantTable)
+{
+    if (!hlsl)
+    {
+        return NULL;
+    }
+
+    DWORD result = NOERROR;
+    UINT flags = 0;
+    std::string sourceText;
+    if (perfActive())
+    {
+        flags |= D3DCOMPILE_DEBUG;
+#ifdef NDEBUG
+        flags |= ANGLE_COMPILE_OPTIMIZATION_LEVEL;
+#else
+        flags |= D3DCOMPILE_SKIP_OPTIMIZATION;
+#endif
+
+        std::string sourcePath = getTempPath();
+        sourceText = std::string("#line 2 \"") + sourcePath + std::string("\"\n\n") + std::string(hlsl);
+        writeFile(sourcePath.c_str(), sourceText.c_str(), sourceText.size());
+    }
+    else
+    {
+        flags |= ANGLE_COMPILE_OPTIMIZATION_LEVEL;
+        sourceText = hlsl;
+    }
+
+    // Sometimes D3DCompile will fail with the default compilation flags for complicated shaders when it would otherwise pass with alternative options.
+    // Try the default flags first and if compilation fails, try some alternatives. 
+    const static UINT extraFlags[] =
+    {
+        0,
+        D3DCOMPILE_AVOID_FLOW_CONTROL,
+        D3DCOMPILE_PREFER_FLOW_CONTROL
+    };
+
+    const static char * const extraFlagNames[] =
+    {
+        "default",
+        "avoid flow control",
+        "prefer flow control"
+    };
+
+    for (int i = 0; i < sizeof(extraFlags) / sizeof(UINT); ++i)
+    {
+        ID3D10Blob *errorMessage = NULL;
+        ID3D10Blob *binary = NULL;
+        result = D3DCompile(hlsl, strlen(hlsl), g_fakepath, NULL, NULL, "main", profile, flags | extraFlags[i], 0, &binary, &errorMessage);
+
+        if (errorMessage)
+        {
+            const char *message = (const char*)errorMessage->GetBufferPointer();
+
+            infoLog.appendSanitized(message);
+            TRACE("\n%s", hlsl);
+            TRACE("\n%s", message);
+
+            errorMessage->Release();
+            errorMessage = NULL;
+        }
+
+        if (SUCCEEDED(result))
+        {
+            D3DConstantTable *table = new D3DConstantTable(binary->GetBufferPointer(), binary->GetBufferSize());
+            if (table->error())
+            {
+                delete table;
+                binary->Release();
+                return NULL;
+            }
+
+            *constantTable = table;
+    
+            return binary;
+        }
+        else
+        {
+            if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY)
+            {
+                return error(GL_OUT_OF_MEMORY, (ID3D10Blob*) NULL);
+            }
+
+            infoLog.append("Warning: D3D shader compilation failed with ");
+            infoLog.append(extraFlagNames[i]);
+            infoLog.append(" flags.");
+            if (i + 1 < sizeof(extraFlagNames) / sizeof(char*))
+            {
+                infoLog.append(" Retrying with ");
+                infoLog.append(extraFlagNames[i + 1]);
+                infoLog.append(".\n");
+            }
+        }
+    }
+
+    return NULL;
+}
+
+// Packs varyings into generic varying registers, using the algorithm from [OpenGL ES Shading Language 1.00 rev. 17] appendix A section 7 page 111
+// Returns the number of used varying registers, or -1 if unsuccesful
+int ProgramBinary::packVaryings(InfoLog &infoLog, const Varying *packing[][4], FragmentShader *fragmentShader)
+{
+    Context *context = getContext();
+    const int maxVaryingVectors = context->getMaximumVaryingVectors();
+
+    for (VaryingList::iterator varying = fragmentShader->mVaryings.begin(); varying != fragmentShader->mVaryings.end(); varying++)
+    {
+        int n = VariableRowCount(varying->type) * varying->size;
+        int m = VariableColumnCount(varying->type);
+        bool success = false;
+
+        if (m == 2 || m == 3 || m == 4)
+        {
+            for (int r = 0; r <= maxVaryingVectors - n && !success; r++)
+            {
+                bool available = true;
+
+                for (int y = 0; y < n && available; y++)
+                {
+                    for (int x = 0; x < m && available; x++)
+                    {
+                        if (packing[r + y][x])
+                        {
+                            available = false;
+                        }
+                    }
+                }
+
+                if (available)
+                {
+                    varying->reg = r;
+                    varying->col = 0;
+
+                    for (int y = 0; y < n; y++)
+                    {
+                        for (int x = 0; x < m; x++)
+                        {
+                            packing[r + y][x] = &*varying;
+                        }
+                    }
+
+                    success = true;
+                }
+            }
+
+            if (!success && m == 2)
+            {
+                for (int r = maxVaryingVectors - n; r >= 0 && !success; r--)
+                {
+                    bool available = true;
+
+                    for (int y = 0; y < n && available; y++)
+                    {
+                        for (int x = 2; x < 4 && available; x++)
+                        {
+                            if (packing[r + y][x])
+                            {
+                                available = false;
+                            }
+                        }
+                    }
+
+                    if (available)
+                    {
+                        varying->reg = r;
+                        varying->col = 2;
+
+                        for (int y = 0; y < n; y++)
+                        {
+                            for (int x = 2; x < 4; x++)
+                            {
+                                packing[r + y][x] = &*varying;
+                            }
+                        }
+
+                        success = true;
+                    }
+                }
+            }
+        }
+        else if (m == 1)
+        {
+            int space[4] = {0};
+
+            for (int y = 0; y < maxVaryingVectors; y++)
+            {
+                for (int x = 0; x < 4; x++)
+                {
+                    space[x] += packing[y][x] ? 0 : 1;
+                }
+            }
+
+            int column = 0;
+
+            for (int x = 0; x < 4; x++)
+            {
+                if (space[x] >= n && space[x] < space[column])
+                {
+                    column = x;
+                }
+            }
+
+            if (space[column] >= n)
+            {
+                for (int r = 0; r < maxVaryingVectors; r++)
+                {
+                    if (!packing[r][column])
+                    {
+                        varying->reg = r;
+
+                        for (int y = r; y < r + n; y++)
+                        {
+                            packing[y][column] = &*varying;
+                        }
+
+                        break;
+                    }
+                }
+
+                varying->col = column;
+
+                success = true;
+            }
+        }
+        else UNREACHABLE();
+
+        if (!success)
+        {
+            infoLog.append("Could not pack varying %s", varying->name.c_str());
+
+            return -1;
+        }
+    }
+
+    // Return the number of used registers
+    int registers = 0;
+
+    for (int r = 0; r < maxVaryingVectors; r++)
+    {
+        if (packing[r][0] || packing[r][1] || packing[r][2] || packing[r][3])
+        {
+            registers++;
+        }
+    }
+
+    return registers;
+}
+
+bool ProgramBinary::linkVaryings(InfoLog &infoLog, std::string& pixelHLSL, std::string& vertexHLSL, FragmentShader *fragmentShader, VertexShader *vertexShader)
+{
+    if (pixelHLSL.empty() || vertexHLSL.empty())
+    {
+        return false;
+    }
+
+    // Reset the varying register assignments
+    for (VaryingList::iterator fragVar = fragmentShader->mVaryings.begin(); fragVar != fragmentShader->mVaryings.end(); fragVar++)
+    {
+        fragVar->reg = -1;
+        fragVar->col = -1;
+    }
+
+    for (VaryingList::iterator vtxVar = vertexShader->mVaryings.begin(); vtxVar != vertexShader->mVaryings.end(); vtxVar++)
+    {
+        vtxVar->reg = -1;
+        vtxVar->col = -1;
+    }
+
+    // Map the varyings to the register file
+    const Varying *packing[MAX_VARYING_VECTORS_SM3][4] = {NULL};
+    int registers = packVaryings(infoLog, packing, fragmentShader);
+
+    if (registers < 0)
+    {
+        return false;
+    }
+
+    // Write the HLSL input/output declarations
+    Context *context = getContext();
+    const bool sm3 = context->supportsShaderModel3();
+    const int maxVaryingVectors = context->getMaximumVaryingVectors();
+
+    if (registers == maxVaryingVectors && fragmentShader->mUsesFragCoord)
+    {
+        infoLog.append("No varying registers left to support gl_FragCoord");
+
+        return false;
+    }
+
+    for (VaryingList::iterator input = fragmentShader->mVaryings.begin(); input != fragmentShader->mVaryings.end(); input++)
+    {
+        bool matched = false;
+
+        for (VaryingList::iterator output = vertexShader->mVaryings.begin(); output != vertexShader->mVaryings.end(); output++)
+        {
+            if (output->name == input->name)
+            {
+                if (output->type != input->type || output->size != input->size)
+                {
+                    infoLog.append("Type of vertex varying %s does not match that of the fragment varying", output->name.c_str());
+
+                    return false;
+                }
+
+                output->reg = input->reg;
+                output->col = input->col;
+
+                matched = true;
+                break;
+            }
+        }
+
+        if (!matched)
+        {
+            infoLog.append("Fragment varying %s does not match any vertex varying", input->name.c_str());
+
+            return false;
+        }
+    }
+
+    mUsesPointSize = vertexShader->mUsesPointSize;
+    std::string varyingSemantic = (mUsesPointSize && sm3) ? "COLOR" : "TEXCOORD";
+
+    vertexHLSL += "struct VS_INPUT\n"
+                   "{\n";
+
+    int semanticIndex = 0;
+    for (AttributeArray::iterator attribute = vertexShader->mAttributes.begin(); attribute != vertexShader->mAttributes.end(); attribute++)
+    {
+        switch (attribute->type)
+        {
+          case GL_FLOAT:      vertexHLSL += "    float ";    break;
+          case GL_FLOAT_VEC2: vertexHLSL += "    float2 ";   break;
+          case GL_FLOAT_VEC3: vertexHLSL += "    float3 ";   break;
+          case GL_FLOAT_VEC4: vertexHLSL += "    float4 ";   break;
+          case GL_FLOAT_MAT2: vertexHLSL += "    float2x2 "; break;
+          case GL_FLOAT_MAT3: vertexHLSL += "    float3x3 "; break;
+          case GL_FLOAT_MAT4: vertexHLSL += "    float4x4 "; break;
+          default:  UNREACHABLE();
+        }
+
+        vertexHLSL += decorateAttribute(attribute->name) + " : TEXCOORD" + str(semanticIndex) + ";\n";
+
+        semanticIndex += VariableRowCount(attribute->type);
+    }
+
+    vertexHLSL += "};\n"
+                   "\n"
+                   "struct VS_OUTPUT\n"
+                   "{\n"
+                   "    float4 gl_Position : POSITION;\n";
+
+    for (int r = 0; r < registers; r++)
+    {
+        int registerSize = packing[r][3] ? 4 : (packing[r][2] ? 3 : (packing[r][1] ? 2 : 1));
+
+        vertexHLSL += "    float" + str(registerSize) + " v" + str(r) + " : " + varyingSemantic + str(r) + ";\n";
+    }
+
+    if (fragmentShader->mUsesFragCoord)
+    {
+        vertexHLSL += "    float4 gl_FragCoord : " + varyingSemantic + str(registers) + ";\n";
+    }
+
+    if (vertexShader->mUsesPointSize && sm3)
+    {
+        vertexHLSL += "    float gl_PointSize : PSIZE;\n";
+    }
+
+    vertexHLSL += "};\n"
+                   "\n"
+                   "VS_OUTPUT main(VS_INPUT input)\n"
+                   "{\n";
+
+    for (AttributeArray::iterator attribute = vertexShader->mAttributes.begin(); attribute != vertexShader->mAttributes.end(); attribute++)
+    {
+        vertexHLSL += "    " + decorateAttribute(attribute->name) + " = ";
+
+        if (VariableRowCount(attribute->type) > 1)   // Matrix
+        {
+            vertexHLSL += "transpose";
+        }
+
+        vertexHLSL += "(input." + decorateAttribute(attribute->name) + ");\n";
+    }
+
+    vertexHLSL += "\n"
+                   "    gl_main();\n"
+                   "\n"
+                   "    VS_OUTPUT output;\n"
+                   "    output.gl_Position.x = gl_Position.x - dx_HalfPixelSize.x * gl_Position.w;\n"
+                   "    output.gl_Position.y = -(gl_Position.y + dx_HalfPixelSize.y * gl_Position.w);\n"
+                   "    output.gl_Position.z = (gl_Position.z + gl_Position.w) * 0.5;\n"
+                   "    output.gl_Position.w = gl_Position.w;\n";
+
+    if (vertexShader->mUsesPointSize && sm3)
+    {
+        vertexHLSL += "    output.gl_PointSize = gl_PointSize;\n";
+    }
+
+    if (fragmentShader->mUsesFragCoord)
+    {
+        vertexHLSL += "    output.gl_FragCoord = gl_Position;\n";
+    }
+
+    for (VaryingList::iterator varying = vertexShader->mVaryings.begin(); varying != vertexShader->mVaryings.end(); varying++)
+    {
+        if (varying->reg >= 0)
+        {
+            for (int i = 0; i < varying->size; i++)
+            {
+                int rows = VariableRowCount(varying->type);
+
+                for (int j = 0; j < rows; j++)
+                {
+                    int r = varying->reg + i * rows + j;
+                    vertexHLSL += "    output.v" + str(r);
+
+                    bool sharedRegister = false;   // Register used by multiple varyings
+                    
+                    for (int x = 0; x < 4; x++)
+                    {
+                        if (packing[r][x] && packing[r][x] != packing[r][0])
+                        {
+                            sharedRegister = true;
+                            break;
+                        }
+                    }
+
+                    if(sharedRegister)
+                    {
+                        vertexHLSL += ".";
+
+                        for (int x = 0; x < 4; x++)
+                        {
+                            if (packing[r][x] == &*varying)
+                            {
+                                switch(x)
+                                {
+                                  case 0: vertexHLSL += "x"; break;
+                                  case 1: vertexHLSL += "y"; break;
+                                  case 2: vertexHLSL += "z"; break;
+                                  case 3: vertexHLSL += "w"; break;
+                                }
+                            }
+                        }
+                    }
+
+                    vertexHLSL += " = " + varying->name;
+                    
+                    if (varying->array)
+                    {
+                        vertexHLSL += "[" + str(i) + "]";
+                    }
+
+                    if (rows > 1)
+                    {
+                        vertexHLSL += "[" + str(j) + "]";
+                    }
+                    
+                    vertexHLSL += ";\n";
+                }
+            }
+        }
+    }
+
+    vertexHLSL += "\n"
+                   "    return output;\n"
+                   "}\n";
+
+    pixelHLSL += "struct PS_INPUT\n"
+                  "{\n";
+    
+    for (VaryingList::iterator varying = fragmentShader->mVaryings.begin(); varying != fragmentShader->mVaryings.end(); varying++)
+    {
+        if (varying->reg >= 0)
+        {
+            for (int i = 0; i < varying->size; i++)
+            {
+                int rows = VariableRowCount(varying->type);
+                for (int j = 0; j < rows; j++)
+                {
+                    std::string n = str(varying->reg + i * rows + j);
+                    pixelHLSL += "    float4 v" + n + " : " + varyingSemantic + n + ";\n";
+                }
+            }
+        }
+        else UNREACHABLE();
+    }
+
+    if (fragmentShader->mUsesFragCoord)
+    {
+        pixelHLSL += "    float4 gl_FragCoord : " + varyingSemantic + str(registers) + ";\n";
+        if (sm3) {
+            pixelHLSL += "    float2 dx_VPos : VPOS;\n";
+        }
+    }
+
+    if (fragmentShader->mUsesPointCoord && sm3)
+    {
+        pixelHLSL += "    float2 gl_PointCoord : TEXCOORD0;\n";
+    }
+
+    if (fragmentShader->mUsesFrontFacing)
+    {
+        pixelHLSL += "    float vFace : VFACE;\n";
+    }
+
+    pixelHLSL += "};\n"
+                  "\n"
+                  "struct PS_OUTPUT\n"
+                  "{\n"
+                  "    float4 gl_Color[1] : COLOR;\n"
+                  "};\n"
+                  "\n"
+                  "PS_OUTPUT main(PS_INPUT input)\n"
+                  "{\n";
+
+    if (fragmentShader->mUsesFragCoord)
+    {
+        pixelHLSL += "    float rhw = 1.0 / input.gl_FragCoord.w;\n";
+        
+        if (sm3)
+        {
+            pixelHLSL += "    gl_FragCoord.x = input.dx_VPos.x + 0.5;\n"
+                          "    gl_FragCoord.y = input.dx_VPos.y + 0.5;\n";
+        }
+        else
+        {
+            // dx_Coord contains the viewport width/2, height/2, center.x and center.y. See Context::applyRenderTarget()
+            pixelHLSL += "    gl_FragCoord.x = (input.gl_FragCoord.x * rhw) * dx_Coord.x + dx_Coord.z;\n"
+                          "    gl_FragCoord.y = (input.gl_FragCoord.y * rhw) * dx_Coord.y + dx_Coord.w;\n";
+        }
+        
+        pixelHLSL += "    gl_FragCoord.z = (input.gl_FragCoord.z * rhw) * dx_Depth.x + dx_Depth.y;\n"
+                      "    gl_FragCoord.w = rhw;\n";
+    }
+
+    if (fragmentShader->mUsesPointCoord && sm3)
+    {
+        pixelHLSL += "    gl_PointCoord.x = input.gl_PointCoord.x;\n";
+        pixelHLSL += "    gl_PointCoord.y = 1.0 - input.gl_PointCoord.y;\n";
+    }
+
+    if (fragmentShader->mUsesFrontFacing)
+    {
+        pixelHLSL += "    gl_FrontFacing = dx_PointsOrLines || (dx_FrontCCW ? (input.vFace >= 0.0) : (input.vFace <= 0.0));\n";
+    }
+
+    for (VaryingList::iterator varying = fragmentShader->mVaryings.begin(); varying != fragmentShader->mVaryings.end(); varying++)
+    {
+        if (varying->reg >= 0)
+        {
+            for (int i = 0; i < varying->size; i++)
+            {
+                int rows = VariableRowCount(varying->type);
+                for (int j = 0; j < rows; j++)
+                {
+                    std::string n = str(varying->reg + i * rows + j);
+                    pixelHLSL += "    " + varying->name;
+
+                    if (varying->array)
+                    {
+                        pixelHLSL += "[" + str(i) + "]";
+                    }
+
+                    if (rows > 1)
+                    {
+                        pixelHLSL += "[" + str(j) + "]";
+                    }
+
+                    pixelHLSL += " = input.v" + n + ";\n";
+                }
+            }
+        }
+        else UNREACHABLE();
+    }
+
+    pixelHLSL += "\n"
+                  "    gl_main();\n"
+                  "\n"
+                  "    PS_OUTPUT output;\n"                 
+                  "    output.gl_Color[0] = gl_Color[0];\n"
+                  "\n"
+                  "    return output;\n"
+                  "}\n";
+
+    return true;
+}
+
+bool ProgramBinary::load(InfoLog &infoLog, const void *binary, GLsizei length)
+{
+    BinaryInputStream stream(binary, length);
+
+    int format = 0;
+    stream.read(&format);
+    if (format != GL_PROGRAM_BINARY_ANGLE)
+    {
+        infoLog.append("Invalid program binary format.");
+        return false;
+    }
+
+    int version = 0;
+    stream.read(&version);
+    if (version != BUILD_REVISION)
+    {
+        infoLog.append("Invalid program binary version.");
+        return false;
+    }
+
+    for (int i = 0; i < MAX_VERTEX_ATTRIBS; ++i)
+    {
+        stream.read(&mLinkedAttribute[i].type);
+        std::string name;
+        stream.read(&name);
+        mLinkedAttribute[i].name = name;
+        stream.read(&mSemanticIndex[i]);
+    }
+
+    for (unsigned int i = 0; i < MAX_TEXTURE_IMAGE_UNITS; ++i)
+    {
+        stream.read(&mSamplersPS[i].active);
+        stream.read(&mSamplersPS[i].logicalTextureUnit);
+        
+        int textureType;
+        stream.read(&textureType);
+        mSamplersPS[i].textureType = (TextureType) textureType;
+    }
+
+    for (unsigned int i = 0; i < MAX_VERTEX_TEXTURE_IMAGE_UNITS_VTF; ++i)
+    {
+        stream.read(&mSamplersVS[i].active);
+        stream.read(&mSamplersVS[i].logicalTextureUnit);
+        
+        int textureType;
+        stream.read(&textureType);
+        mSamplersVS[i].textureType = (TextureType) textureType;
+    }
+
+    stream.read(&mUsedVertexSamplerRange);
+    stream.read(&mUsedPixelSamplerRange);
+
+    unsigned int size;
+    stream.read(&size);
+    if (stream.error())
+    {
+        infoLog.append("Invalid program binary.");
+        return false;
+    }
+
+    mUniforms.resize(size);
+    for (unsigned int i = 0; i < size; ++i)
+    {
+        GLenum type;
+        std::string _name;
+        unsigned int arraySize;
+
+        stream.read(&type);
+        stream.read(&_name);
+        stream.read(&arraySize);
+
+        mUniforms[i] = new Uniform(type, _name, arraySize);
+        
+        stream.read(&mUniforms[i]->ps.float4Index);
+        stream.read(&mUniforms[i]->ps.samplerIndex);
+        stream.read(&mUniforms[i]->ps.boolIndex);
+        stream.read(&mUniforms[i]->ps.registerCount);
+
+        stream.read(&mUniforms[i]->vs.float4Index);
+        stream.read(&mUniforms[i]->vs.samplerIndex);
+        stream.read(&mUniforms[i]->vs.boolIndex);
+        stream.read(&mUniforms[i]->vs.registerCount);
+    }
+
+    stream.read(&size);
+    if (stream.error())
+    {
+        infoLog.append("Invalid program binary.");
+        return false;
+    }
+
+    mUniformIndex.resize(size);
+    for (unsigned int i = 0; i < size; ++i)
+    {
+        stream.read(&mUniformIndex[i].name);
+        stream.read(&mUniformIndex[i].element);
+        stream.read(&mUniformIndex[i].index);
+    }
+
+    stream.read(&mDxDepthRangeLocation);
+    stream.read(&mDxDepthLocation);
+    stream.read(&mDxCoordLocation);
+    stream.read(&mDxHalfPixelSizeLocation);
+    stream.read(&mDxFrontCCWLocation);
+    stream.read(&mDxPointsOrLinesLocation);
+
+    unsigned int pixelShaderSize;
+    stream.read(&pixelShaderSize);
+
+    unsigned int vertexShaderSize;
+    stream.read(&vertexShaderSize);
+
+    const char *ptr = (const char*) binary + stream.offset();
+
+    const D3DCAPS9 *binaryIdentifier = (const D3DCAPS9*) ptr;
+    ptr += sizeof(GUID);
+
+    D3DADAPTER_IDENTIFIER9 *currentIdentifier = getDisplay()->getAdapterIdentifier();
+    if (memcmp(&currentIdentifier->DeviceIdentifier, binaryIdentifier, sizeof(GUID)) != 0)
+    {
+        infoLog.append("Invalid program binary.");
+        return false;
+    }
+
+    const char *pixelShaderFunction = ptr;
+    ptr += pixelShaderSize;
+
+    const char *vertexShaderFunction = ptr;
+    ptr += vertexShaderSize;
+
+    mPixelExecutable = getDisplay()->createPixelShader(reinterpret_cast<const DWORD*>(pixelShaderFunction), pixelShaderSize);
+    if (!mPixelExecutable)
+    {
+        infoLog.append("Could not create pixel shader.");
+        return false;
+    }
+
+    mVertexExecutable = getDisplay()->createVertexShader(reinterpret_cast<const DWORD*>(vertexShaderFunction), vertexShaderSize);
+    if (!mVertexExecutable)
+    {
+        infoLog.append("Could not create vertex shader.");
+        mPixelExecutable->Release();
+        mPixelExecutable = NULL;
+        return false;
+    }
+
+    return true;
+}
+
+bool ProgramBinary::save(void* binary, GLsizei bufSize, GLsizei *length)
+{
+    BinaryOutputStream stream;
+
+    stream.write(GL_PROGRAM_BINARY_ANGLE);
+    stream.write(BUILD_REVISION);
+
+    for (unsigned int i = 0; i < MAX_VERTEX_ATTRIBS; ++i)
+    {
+        stream.write(mLinkedAttribute[i].type);
+        stream.write(mLinkedAttribute[i].name);
+        stream.write(mSemanticIndex[i]);
+    }
+
+    for (unsigned int i = 0; i < MAX_TEXTURE_IMAGE_UNITS; ++i)
+    {
+        stream.write(mSamplersPS[i].active);
+        stream.write(mSamplersPS[i].logicalTextureUnit);
+        stream.write((int) mSamplersPS[i].textureType);
+    }
+
+    for (unsigned int i = 0; i < MAX_VERTEX_TEXTURE_IMAGE_UNITS_VTF; ++i)
+    {
+        stream.write(mSamplersVS[i].active);
+        stream.write(mSamplersVS[i].logicalTextureUnit);
+        stream.write((int) mSamplersVS[i].textureType);
+    }
+
+    stream.write(mUsedVertexSamplerRange);
+    stream.write(mUsedPixelSamplerRange);
+
+    stream.write(mUniforms.size());
+    for (unsigned int i = 0; i < mUniforms.size(); ++i)
+    {
+        stream.write(mUniforms[i]->type);
+        stream.write(mUniforms[i]->_name);
+        stream.write(mUniforms[i]->arraySize);
+
+        stream.write(mUniforms[i]->ps.float4Index);
+        stream.write(mUniforms[i]->ps.samplerIndex);
+        stream.write(mUniforms[i]->ps.boolIndex);
+        stream.write(mUniforms[i]->ps.registerCount);
+
+        stream.write(mUniforms[i]->vs.float4Index);
+        stream.write(mUniforms[i]->vs.samplerIndex);
+        stream.write(mUniforms[i]->vs.boolIndex);
+        stream.write(mUniforms[i]->vs.registerCount);
+    }
+
+    stream.write(mUniformIndex.size());
+    for (unsigned int i = 0; i < mUniformIndex.size(); ++i)
+    {
+        stream.write(mUniformIndex[i].name);
+        stream.write(mUniformIndex[i].element);
+        stream.write(mUniformIndex[i].index);
+    }
+
+    stream.write(mDxDepthRangeLocation);
+    stream.write(mDxDepthLocation);
+    stream.write(mDxCoordLocation);
+    stream.write(mDxHalfPixelSizeLocation);
+    stream.write(mDxFrontCCWLocation);
+    stream.write(mDxPointsOrLinesLocation);
+
+    UINT pixelShaderSize;
+    HRESULT result = mPixelExecutable->GetFunction(NULL, &pixelShaderSize);
+    ASSERT(SUCCEEDED(result));
+    stream.write(pixelShaderSize);
+
+    UINT vertexShaderSize;
+    result = mVertexExecutable->GetFunction(NULL, &vertexShaderSize);
+    ASSERT(SUCCEEDED(result));
+    stream.write(vertexShaderSize);
+
+    D3DADAPTER_IDENTIFIER9 *identifier = getDisplay()->getAdapterIdentifier();
+
+    GLsizei streamLength = stream.length();
+    const void *streamData = stream.data();
+
+    GLsizei totalLength = streamLength + sizeof(GUID) + pixelShaderSize + vertexShaderSize;
+    if (totalLength > bufSize)
+    {
+        if (length)
+        {
+            *length = 0;
+        }
+
+        return false;
+    }
+
+    if (binary)
+    {
+        char *ptr = (char*) binary;
+
+        memcpy(ptr, streamData, streamLength);
+        ptr += streamLength;
+
+        memcpy(ptr, &identifier->DeviceIdentifier, sizeof(GUID));
+        ptr += sizeof(GUID);
+
+        result = mPixelExecutable->GetFunction(ptr, &pixelShaderSize);
+        ASSERT(SUCCEEDED(result));
+        ptr += pixelShaderSize;
+
+        result = mVertexExecutable->GetFunction(ptr, &vertexShaderSize);
+        ASSERT(SUCCEEDED(result));
+        ptr += vertexShaderSize;
+
+        ASSERT(ptr - totalLength == binary);
+    }
+
+    if (length)
+    {
+        *length = totalLength;
+    }
+
+    return true;
+}
+
+GLint ProgramBinary::getLength()
+{
+    GLint length;
+    if (save(NULL, INT_MAX, &length))
+    {
+        return length;
+    }
+    else
+    {
+        return 0;
+    }
+}
+
+bool ProgramBinary::link(InfoLog &infoLog, const AttributeBindings &attributeBindings, FragmentShader *fragmentShader, VertexShader *vertexShader)
+{
+    if (!fragmentShader || !fragmentShader->isCompiled())
+    {
+        return false;
+    }
+
+    if (!vertexShader || !vertexShader->isCompiled())
+    {
+        return false;
+    }
+
+    std::string pixelHLSL = fragmentShader->getHLSL();
+    std::string vertexHLSL = vertexShader->getHLSL();
+
+    if (!linkVaryings(infoLog, pixelHLSL, vertexHLSL, fragmentShader, vertexShader))
+    {
+        return false;
+    }
+
+    Context *context = getContext();
+    const char *vertexProfile = context->supportsShaderModel3() ? "vs_3_0" : "vs_2_0";
+    const char *pixelProfile = context->supportsShaderModel3() ? "ps_3_0" : "ps_2_0";
+
+    ID3D10Blob *vertexBinary = compileToBinary(infoLog, vertexHLSL.c_str(), vertexProfile, &mConstantTableVS);
+    ID3D10Blob *pixelBinary = compileToBinary(infoLog, pixelHLSL.c_str(), pixelProfile, &mConstantTablePS);
+
+    if (vertexBinary && pixelBinary)
+    {
+        mVertexExecutable = getDisplay()->createVertexShader((DWORD*)vertexBinary->GetBufferPointer(), vertexBinary->GetBufferSize());
+        if (!mVertexExecutable)
+        {
+            return error(GL_OUT_OF_MEMORY, false);
+        }
+
+        mPixelExecutable = getDisplay()->createPixelShader((DWORD*)pixelBinary->GetBufferPointer(), pixelBinary->GetBufferSize());
+        if (!mPixelExecutable)
+        {
+            mVertexExecutable->Release();
+            mVertexExecutable = NULL;
+            return error(GL_OUT_OF_MEMORY, false);
+        }
+
+        vertexBinary->Release();
+        pixelBinary->Release();
+        vertexBinary = NULL;
+        pixelBinary = NULL;
+
+        if (!linkAttributes(infoLog, attributeBindings, fragmentShader, vertexShader))
+        {
+            return false;
+        }
+
+        if (!linkUniforms(infoLog, GL_FRAGMENT_SHADER, mConstantTablePS))
+        {
+            return false;
+        }
+
+        if (!linkUniforms(infoLog, GL_VERTEX_SHADER, mConstantTableVS))
+        {
+            return false;
+        }
+
+        // these uniforms are searched as already-decorated because gl_ and dx_
+        // are reserved prefixes, and do not receive additional decoration
+        mDxDepthRangeLocation = getUniformLocation("dx_DepthRange");
+        mDxDepthLocation = getUniformLocation("dx_Depth");
+        mDxCoordLocation = getUniformLocation("dx_Coord");
+        mDxHalfPixelSizeLocation = getUniformLocation("dx_HalfPixelSize");
+        mDxFrontCCWLocation = getUniformLocation("dx_FrontCCW");
+        mDxPointsOrLinesLocation = getUniformLocation("dx_PointsOrLines");
+
+        context->markDxUniformsDirty();
+
+        return true;
+    }
+
+    return false;
+}
+
+// Determines the mapping between GL attributes and Direct3D 9 vertex stream usage indices
+bool ProgramBinary::linkAttributes(InfoLog &infoLog, const AttributeBindings &attributeBindings, FragmentShader *fragmentShader, VertexShader *vertexShader)
+{
+    unsigned int usedLocations = 0;
+
+    // Link attributes that have a binding location
+    for (AttributeArray::iterator attribute = vertexShader->mAttributes.begin(); attribute != vertexShader->mAttributes.end(); attribute++)
+    {
+        int location = attributeBindings.getAttributeBinding(attribute->name);
+
+        if (location != -1)   // Set by glBindAttribLocation
+        {
+            if (!mLinkedAttribute[location].name.empty())
+            {
+                // Multiple active attributes bound to the same location; not an error
+            }
+
+            mLinkedAttribute[location] = *attribute;
+
+            int rows = VariableRowCount(attribute->type);
+
+            if (rows + location > MAX_VERTEX_ATTRIBS)
+            {
+                infoLog.append("Active attribute (%s) at location %d is too big to fit", attribute->name.c_str(), location);
+
+                return false;
+            }
+
+            for (int i = 0; i < rows; i++)
+            {
+                usedLocations |= 1 << (location + i);
+            }
+        }
+    }
+
+    // Link attributes that don't have a binding location
+    for (AttributeArray::iterator attribute = vertexShader->mAttributes.begin(); attribute != vertexShader->mAttributes.end(); attribute++)
+    {
+        int location = attributeBindings.getAttributeBinding(attribute->name);
+
+        if (location == -1)   // Not set by glBindAttribLocation
+        {
+            int rows = VariableRowCount(attribute->type);
+            int availableIndex = AllocateFirstFreeBits(&usedLocations, rows, MAX_VERTEX_ATTRIBS);
+
+            if (availableIndex == -1 || availableIndex + rows > MAX_VERTEX_ATTRIBS)
+            {
+                infoLog.append("Too many active attributes (%s)", attribute->name.c_str());
+
+                return false;   // Fail to link
+            }
+
+            mLinkedAttribute[availableIndex] = *attribute;
+        }
+    }
+
+    for (int attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; )
+    {
+        int index = vertexShader->getSemanticIndex(mLinkedAttribute[attributeIndex].name);
+        int rows = std::max(VariableRowCount(mLinkedAttribute[attributeIndex].type), 1);
+
+        for (int r = 0; r < rows; r++)
+        {
+            mSemanticIndex[attributeIndex++] = index++;
+        }
+    }
+
+    return true;
+}
+
+bool ProgramBinary::linkUniforms(InfoLog &infoLog, GLenum shader, D3DConstantTable *constantTable)
+{
+    for (unsigned int constantIndex = 0; constantIndex < constantTable->constants(); constantIndex++)
+    {
+        const D3DConstant *constant = constantTable->getConstant(constantIndex);
+
+        if (!defineUniform(infoLog, shader, constant))
+        {
+            return false;
+        }
+    }
+
+    return true;
+}
+
+// Adds the description of a constant found in the binary shader to the list of uniforms
+// Returns true if succesful (uniform not already defined)
+bool ProgramBinary::defineUniform(InfoLog &infoLog, GLenum shader, const D3DConstant *constant, std::string name)
+{
+    if (constant->registerSet == D3DConstant::RS_SAMPLER)
+    {
+        for (unsigned int i = 0; i < constant->registerCount; i++)
+        {
+            const D3DConstant *psConstant = mConstantTablePS->getConstantByName(constant->name.c_str());
+            const D3DConstant *vsConstant = mConstantTableVS->getConstantByName(constant->name.c_str());
+
+            if (psConstant)
+            {
+                unsigned int samplerIndex = psConstant->registerIndex + i;
+
+                if (samplerIndex < MAX_TEXTURE_IMAGE_UNITS)
+                {
+                    mSamplersPS[samplerIndex].active = true;
+                    mSamplersPS[samplerIndex].textureType = (constant->type == D3DConstant::PT_SAMPLERCUBE) ? TEXTURE_CUBE : TEXTURE_2D;
+                    mSamplersPS[samplerIndex].logicalTextureUnit = 0;
+                    mUsedPixelSamplerRange = std::max(samplerIndex + 1, mUsedPixelSamplerRange);
+                }
+                else
+                {
+                    infoLog.append("Pixel shader sampler count exceeds MAX_TEXTURE_IMAGE_UNITS (%d).", MAX_TEXTURE_IMAGE_UNITS);
+                    return false;
+                }
+            }
+            
+            if (vsConstant)
+            {
+                unsigned int samplerIndex = vsConstant->registerIndex + i;
+
+                if (samplerIndex < getContext()->getMaximumVertexTextureImageUnits())
+                {
+                    mSamplersVS[samplerIndex].active = true;
+                    mSamplersVS[samplerIndex].textureType = (constant->type == D3DConstant::PT_SAMPLERCUBE) ? TEXTURE_CUBE : TEXTURE_2D;
+                    mSamplersVS[samplerIndex].logicalTextureUnit = 0;
+                    mUsedVertexSamplerRange = std::max(samplerIndex + 1, mUsedVertexSamplerRange);
+                }
+                else
+                {
+                    infoLog.append("Vertex shader sampler count exceeds MAX_VERTEX_TEXTURE_IMAGE_UNITS (%d).", getContext()->getMaximumVertexTextureImageUnits());
+                    return false;
+                }
+            }
+        }
+    }
+
+    switch(constant->typeClass)
+    {
+      case D3DConstant::CLASS_STRUCT:
+        {
+            for (unsigned int arrayIndex = 0; arrayIndex < constant->elements; arrayIndex++)
+            {
+                for (unsigned int field = 0; field < constant->structMembers[arrayIndex].size(); field++)
+                {
+                    const D3DConstant *fieldConstant = constant->structMembers[arrayIndex][field];
+
+                    std::string structIndex = (constant->elements > 1) ? ("[" + str(arrayIndex) + "]") : "";
+
+                    if (!defineUniform(infoLog, shader, fieldConstant, name + constant->name + structIndex + "."))
+                    {
+                        return false;
+                    }
+                }
+            }
+
+            return true;
+        }
+      case D3DConstant::CLASS_SCALAR:
+      case D3DConstant::CLASS_VECTOR:
+      case D3DConstant::CLASS_MATRIX_COLUMNS:
+      case D3DConstant::CLASS_OBJECT:
+        return defineUniform(shader, constant, name + constant->name);
+      default:
+        UNREACHABLE();
+        return false;
+    }
+}
+
+bool ProgramBinary::defineUniform(GLenum shader, const D3DConstant *constant, const std::string &_name)
+{
+    Uniform *uniform = createUniform(constant, _name);
+
+    if(!uniform)
+    {
+        return false;
+    }
+
+    // Check if already defined
+    GLint location = getUniformLocation(uniform->name);
+    GLenum type = uniform->type;
+
+    if (location >= 0)
+    {
+        delete uniform;
+        uniform = mUniforms[mUniformIndex[location].index];
+    }
+
+    if (shader == GL_FRAGMENT_SHADER) uniform->ps.set(constant);
+    if (shader == GL_VERTEX_SHADER)   uniform->vs.set(constant);
+
+    if (location >= 0)
+    {
+        return uniform->type == type;
+    }
+
+    mUniforms.push_back(uniform);
+    unsigned int uniformIndex = mUniforms.size() - 1;
+
+    for (unsigned int i = 0; i < uniform->arraySize; ++i)
+    {
+        mUniformIndex.push_back(UniformLocation(_name, i, uniformIndex));
+    }
+
+    return true;
+}
+
+Uniform *ProgramBinary::createUniform(const D3DConstant *constant, const std::string &_name)
+{
+    if (constant->rows == 1)   // Vectors and scalars
+    {
+        switch (constant->type)
+        {
+          case D3DConstant::PT_SAMPLER2D:
+            switch (constant->columns)
+            {
+              case 1: return new Uniform(GL_SAMPLER_2D, _name, constant->elements);
+              default: UNREACHABLE();
+            }
+            break;
+          case D3DConstant::PT_SAMPLERCUBE:
+            switch (constant->columns)
+            {
+              case 1: return new Uniform(GL_SAMPLER_CUBE, _name, constant->elements);
+              default: UNREACHABLE();
+            }
+            break;
+          case D3DConstant::PT_BOOL:
+            switch (constant->columns)
+            {
+              case 1: return new Uniform(GL_BOOL, _name, constant->elements);
+              case 2: return new Uniform(GL_BOOL_VEC2, _name, constant->elements);
+              case 3: return new Uniform(GL_BOOL_VEC3, _name, constant->elements);
+              case 4: return new Uniform(GL_BOOL_VEC4, _name, constant->elements);
+              default: UNREACHABLE();
+            }
+            break;
+          case D3DConstant::PT_INT:
+            switch (constant->columns)
+            {
+              case 1: return new Uniform(GL_INT, _name, constant->elements);
+              case 2: return new Uniform(GL_INT_VEC2, _name, constant->elements);
+              case 3: return new Uniform(GL_INT_VEC3, _name, constant->elements);
+              case 4: return new Uniform(GL_INT_VEC4, _name, constant->elements);
+              default: UNREACHABLE();
+            }
+            break;
+          case D3DConstant::PT_FLOAT:
+            switch (constant->columns)
+            {
+              case 1: return new Uniform(GL_FLOAT, _name, constant->elements);
+              case 2: return new Uniform(GL_FLOAT_VEC2, _name, constant->elements);
+              case 3: return new Uniform(GL_FLOAT_VEC3, _name, constant->elements);
+              case 4: return new Uniform(GL_FLOAT_VEC4, _name, constant->elements);
+              default: UNREACHABLE();
+            }
+            break;
+          default:
+            UNREACHABLE();
+        }
+    }
+    else if (constant->rows == constant->columns)  // Square matrices
+    {
+        switch (constant->type)
+        {
+          case D3DConstant::PT_FLOAT:
+            switch (constant->rows)
+            {
+              case 2: return new Uniform(GL_FLOAT_MAT2, _name, constant->elements);
+              case 3: return new Uniform(GL_FLOAT_MAT3, _name, constant->elements);
+              case 4: return new Uniform(GL_FLOAT_MAT4, _name, constant->elements);
+              default: UNREACHABLE();
+            }
+            break;
+          default: UNREACHABLE();
+        }
+    }
+    else UNREACHABLE();
+
+    return 0;
+}
+
+// This method needs to match OutputHLSL::decorate
+std::string ProgramBinary::decorateAttribute(const std::string &name)
+{
+    if (name.compare(0, 3, "gl_") != 0 && name.compare(0, 3, "dx_") != 0)
+    {
+        return "_" + name;
+    }
+    
+    return name;
+}
+
+std::string ProgramBinary::undecorateUniform(const std::string &_name)
+{
+    std::string name = _name;
+    
+    // Remove any structure field decoration
+    size_t pos = 0;
+    while ((pos = name.find("._", pos)) != std::string::npos)
+    {
+        name.replace(pos, 2, ".");
+    }
+
+    // Remove the leading decoration
+    if (name[0] == '_')
+    {
+        return name.substr(1);
+    }
+    else if (name.compare(0, 3, "ar_") == 0)
+    {
+        return name.substr(3);
+    }
+    
+    return name;
+}
+
+void ProgramBinary::applyUniformnbv(Uniform *targetUniform, GLsizei count, int width, const GLboolean *v)
+{
+    float vector[D3D9_MAX_FLOAT_CONSTANTS * 4];
+    BOOL boolVector[D3D9_MAX_BOOL_CONSTANTS];
+
+    if (targetUniform->ps.float4Index >= 0 || targetUniform->vs.float4Index >= 0)
+    {
+        ASSERT(count <= D3D9_MAX_FLOAT_CONSTANTS);
+        for (int i = 0; i < count; i++)
+        {
+            for (int j = 0; j < 4; j++)
+            {
+                if (j < width)
+                {
+                    vector[i * 4 + j] = (v[i * width + j] == GL_FALSE) ? 0.0f : 1.0f;
+                }
+                else
+                {
+                    vector[i * 4 + j] = 0.0f;
+                }
+            }
+        }
+    }
+
+    if (targetUniform->ps.boolIndex >= 0 || targetUniform->vs.boolIndex >= 0)
+    {
+        int psCount = targetUniform->ps.boolIndex >= 0 ? targetUniform->ps.registerCount : 0;
+        int vsCount = targetUniform->vs.boolIndex >= 0 ? targetUniform->vs.registerCount : 0;
+        int copyCount = std::min(count * width, std::max(psCount, vsCount));
+        ASSERT(copyCount <= D3D9_MAX_BOOL_CONSTANTS);
+        for (int i = 0; i < copyCount; i++)
+        {
+            boolVector[i] = v[i] != GL_FALSE;
+        }
+    }
+
+    if (targetUniform->ps.float4Index >= 0)
+    {
+        mDevice->SetPixelShaderConstantF(targetUniform->ps.float4Index, vector, targetUniform->ps.registerCount);
+    }
+        
+    if (targetUniform->ps.boolIndex >= 0)
+    {
+        mDevice->SetPixelShaderConstantB(targetUniform->ps.boolIndex, boolVector, targetUniform->ps.registerCount);
+    }
+    
+    if (targetUniform->vs.float4Index >= 0)
+    {
+        mDevice->SetVertexShaderConstantF(targetUniform->vs.float4Index, vector, targetUniform->vs.registerCount);
+    }
+        
+    if (targetUniform->vs.boolIndex >= 0)
+    {
+        mDevice->SetVertexShaderConstantB(targetUniform->vs.boolIndex, boolVector, targetUniform->vs.registerCount);
+    }
+}
+
+bool ProgramBinary::applyUniformnfv(Uniform *targetUniform, const GLfloat *v)
+{
+    if (targetUniform->ps.registerCount)
+    {
+        mDevice->SetPixelShaderConstantF(targetUniform->ps.float4Index, v, targetUniform->ps.registerCount);
+    }
+
+    if (targetUniform->vs.registerCount)
+    {
+        mDevice->SetVertexShaderConstantF(targetUniform->vs.float4Index, v, targetUniform->vs.registerCount);
+    }
+
+    return true;
+}
+
+bool ProgramBinary::applyUniform1iv(Uniform *targetUniform, GLsizei count, const GLint *v)
+{
+    ASSERT(count <= D3D9_MAX_FLOAT_CONSTANTS);
+    Vector4 vector[D3D9_MAX_FLOAT_CONSTANTS];
+
+    for (int i = 0; i < count; i++)
+    {
+        vector[i] = Vector4((float)v[i], 0, 0, 0);
+    }
+
+    if (targetUniform->ps.registerCount)
+    {
+        if (targetUniform->ps.samplerIndex >= 0)
+        {
+            unsigned int firstIndex = targetUniform->ps.samplerIndex;
+
+            for (int i = 0; i < count; i++)
+            {
+                unsigned int samplerIndex = firstIndex + i;
+
+                if (samplerIndex < MAX_TEXTURE_IMAGE_UNITS)
+                {
+                    ASSERT(mSamplersPS[samplerIndex].active);
+                    mSamplersPS[samplerIndex].logicalTextureUnit = v[i];
+                }
+            }
+        }
+        else
+        {
+            ASSERT(targetUniform->ps.float4Index >= 0);
+            mDevice->SetPixelShaderConstantF(targetUniform->ps.float4Index, (const float*)vector, targetUniform->ps.registerCount);
+        }
+    }
+
+    if (targetUniform->vs.registerCount)
+    {
+        if (targetUniform->vs.samplerIndex >= 0)
+        {
+            unsigned int firstIndex = targetUniform->vs.samplerIndex;
+
+            for (int i = 0; i < count; i++)
+            {
+                unsigned int samplerIndex = firstIndex + i;
+
+                if (samplerIndex < MAX_VERTEX_TEXTURE_IMAGE_UNITS_VTF)
+                {
+                    ASSERT(mSamplersVS[samplerIndex].active);
+                    mSamplersVS[samplerIndex].logicalTextureUnit = v[i];
+                }
+            }
+        }
+        else
+        {
+            ASSERT(targetUniform->vs.float4Index >= 0);
+            mDevice->SetVertexShaderConstantF(targetUniform->vs.float4Index, (const float *)vector, targetUniform->vs.registerCount);
+        }
+    }
+
+    return true;
+}
+
+bool ProgramBinary::applyUniform2iv(Uniform *targetUniform, GLsizei count, const GLint *v)
+{
+    ASSERT(count <= D3D9_MAX_FLOAT_CONSTANTS);
+    Vector4 vector[D3D9_MAX_FLOAT_CONSTANTS];
+
+    for (int i = 0; i < count; i++)
+    {
+        vector[i] = Vector4((float)v[0], (float)v[1], 0, 0);
+
+        v += 2;
+    }
+
+    applyUniformniv(targetUniform, count, vector);
+
+    return true;
+}
+
+bool ProgramBinary::applyUniform3iv(Uniform *targetUniform, GLsizei count, const GLint *v)
+{
+    ASSERT(count <= D3D9_MAX_FLOAT_CONSTANTS);
+    Vector4 vector[D3D9_MAX_FLOAT_CONSTANTS];
+
+    for (int i = 0; i < count; i++)
+    {
+        vector[i] = Vector4((float)v[0], (float)v[1], (float)v[2], 0);
+
+        v += 3;
+    }
+
+    applyUniformniv(targetUniform, count, vector);
+
+    return true;
+}
+
+bool ProgramBinary::applyUniform4iv(Uniform *targetUniform, GLsizei count, const GLint *v)
+{
+    ASSERT(count <= D3D9_MAX_FLOAT_CONSTANTS);
+    Vector4 vector[D3D9_MAX_FLOAT_CONSTANTS];
+
+    for (int i = 0; i < count; i++)
+    {
+        vector[i] = Vector4((float)v[0], (float)v[1], (float)v[2], (float)v[3]);
+
+        v += 4;
+    }
+
+    applyUniformniv(targetUniform, count, vector);
+
+    return true;
+}
+
+void ProgramBinary::applyUniformniv(Uniform *targetUniform, GLsizei count, const Vector4 *vector)
+{
+    if (targetUniform->ps.registerCount)
+    {
+        ASSERT(targetUniform->ps.float4Index >= 0);
+        mDevice->SetPixelShaderConstantF(targetUniform->ps.float4Index, (const float *)vector, targetUniform->ps.registerCount);
+    }
+
+    if (targetUniform->vs.registerCount)
+    {
+        ASSERT(targetUniform->vs.float4Index >= 0);
+        mDevice->SetVertexShaderConstantF(targetUniform->vs.float4Index, (const float *)vector, targetUniform->vs.registerCount);
+    }
+}
+
+bool ProgramBinary::isValidated() const 
+{
+    return mValidated;
+}
+
+void ProgramBinary::getActiveAttribute(GLuint index, GLsizei bufsize, GLsizei *length, GLint *size, GLenum *type, GLchar *name)
+{
+    // Skip over inactive attributes
+    unsigned int activeAttribute = 0;
+    unsigned int attribute;
+    for (attribute = 0; attribute < MAX_VERTEX_ATTRIBS; attribute++)
+    {
+        if (mLinkedAttribute[attribute].name.empty())
+        {
+            continue;
+        }
+
+        if (activeAttribute == index)
+        {
+            break;
+        }
+
+        activeAttribute++;
+    }
+
+    if (bufsize > 0)
+    {
+        const char *string = mLinkedAttribute[attribute].name.c_str();
+
+        strncpy(name, string, bufsize);
+        name[bufsize - 1] = '\0';
+
+        if (length)
+        {
+            *length = strlen(name);
+        }
+    }
+
+    *size = 1;   // Always a single 'type' instance
+
+    *type = mLinkedAttribute[attribute].type;
+}
+
+GLint ProgramBinary::getActiveAttributeCount()
+{
+    int count = 0;
+
+    for (int attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; attributeIndex++)
+    {
+        if (!mLinkedAttribute[attributeIndex].name.empty())
+        {
+            count++;
+        }
+    }
+
+    return count;
+}
+
+GLint ProgramBinary::getActiveAttributeMaxLength()
+{
+    int maxLength = 0;
+
+    for (int attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; attributeIndex++)
+    {
+        if (!mLinkedAttribute[attributeIndex].name.empty())
+        {
+            maxLength = std::max((int)(mLinkedAttribute[attributeIndex].name.length() + 1), maxLength);
+        }
+    }
+
+    return maxLength;
+}
+
+void ProgramBinary::getActiveUniform(GLuint index, GLsizei bufsize, GLsizei *length, GLint *size, GLenum *type, GLchar *name)
+{
+    // Skip over internal uniforms
+    unsigned int activeUniform = 0;
+    unsigned int uniform;
+    for (uniform = 0; uniform < mUniforms.size(); uniform++)
+    {
+        if (mUniforms[uniform]->name.compare(0, 3, "dx_") == 0)
+        {
+            continue;
+        }
+
+        if (activeUniform == index)
+        {
+            break;
+        }
+
+        activeUniform++;
+    }
+
+    ASSERT(uniform < mUniforms.size());   // index must be smaller than getActiveUniformCount()
+
+    if (bufsize > 0)
+    {
+        std::string string = mUniforms[uniform]->name;
+
+        if (mUniforms[uniform]->isArray())
+        {
+            string += "[0]";
+        }
+
+        strncpy(name, string.c_str(), bufsize);
+        name[bufsize - 1] = '\0';
+
+        if (length)
+        {
+            *length = strlen(name);
+        }
+    }
+
+    *size = mUniforms[uniform]->arraySize;
+
+    *type = mUniforms[uniform]->type;
+}
+
+GLint ProgramBinary::getActiveUniformCount()
+{
+    int count = 0;
+
+    unsigned int numUniforms = mUniforms.size();
+    for (unsigned int uniformIndex = 0; uniformIndex < numUniforms; uniformIndex++)
+    {
+        if (mUniforms[uniformIndex]->name.compare(0, 3, "dx_") != 0)
+        {
+            count++;
+        }
+    }
+
+    return count;
+}
+
+GLint ProgramBinary::getActiveUniformMaxLength()
+{
+    int maxLength = 0;
+
+    unsigned int numUniforms = mUniforms.size();
+    for (unsigned int uniformIndex = 0; uniformIndex < numUniforms; uniformIndex++)
+    {
+        if (!mUniforms[uniformIndex]->name.empty() && mUniforms[uniformIndex]->name.compare(0, 3, "dx_") != 0)
+        {
+            int length = (int)(mUniforms[uniformIndex]->name.length() + 1);
+            if (mUniforms[uniformIndex]->isArray())
+            {
+                length += 3;  // Counting in "[0]".
+            }
+            maxLength = std::max(length, maxLength);
+        }
+    }
+
+    return maxLength;
+}
+
+void ProgramBinary::validate(InfoLog &infoLog)
+{
+    applyUniforms();
+    if (!validateSamplers(&infoLog))
+    {
+        mValidated = false;
+    }
+    else
+    {
+        mValidated = true;
+    }
+}
+
+bool ProgramBinary::validateSamplers(InfoLog *infoLog)
+{
+    // if any two active samplers in a program are of different types, but refer to the same
+    // texture image unit, and this is the current program, then ValidateProgram will fail, and
+    // DrawArrays and DrawElements will issue the INVALID_OPERATION error.
+
+    const unsigned int maxCombinedTextureImageUnits = getContext()->getMaximumCombinedTextureImageUnits();
+    TextureType textureUnitType[MAX_COMBINED_TEXTURE_IMAGE_UNITS_VTF];
+
+    for (unsigned int i = 0; i < MAX_COMBINED_TEXTURE_IMAGE_UNITS_VTF; ++i)
+    {
+        textureUnitType[i] = TEXTURE_UNKNOWN;
+    }
+
+    for (unsigned int i = 0; i < mUsedPixelSamplerRange; ++i)
+    {
+        if (mSamplersPS[i].active)
+        {
+            unsigned int unit = mSamplersPS[i].logicalTextureUnit;
+            
+            if (unit >= maxCombinedTextureImageUnits)
+            {
+                if (infoLog)
+                {
+                    infoLog->append("Sampler uniform (%d) exceeds MAX_COMBINED_TEXTURE_IMAGE_UNITS (%d)", unit, maxCombinedTextureImageUnits);
+                }
+
+                return false;
+            }
+
+            if (textureUnitType[unit] != TEXTURE_UNKNOWN)
+            {
+                if (mSamplersPS[i].textureType != textureUnitType[unit])
+                {
+                    if (infoLog)
+                    {
+                        infoLog->append("Samplers of conflicting types refer to the same texture image unit (%d).", unit);
+                    }
+
+                    return false;
+                }
+            }
+            else
+            {
+                textureUnitType[unit] = mSamplersPS[i].textureType;
+            }
+        }
+    }
+
+    for (unsigned int i = 0; i < mUsedVertexSamplerRange; ++i)
+    {
+        if (mSamplersVS[i].active)
+        {
+            unsigned int unit = mSamplersVS[i].logicalTextureUnit;
+            
+            if (unit >= maxCombinedTextureImageUnits)
+            {
+                if (infoLog)
+                {
+                    infoLog->append("Sampler uniform (%d) exceeds MAX_COMBINED_TEXTURE_IMAGE_UNITS (%d)", unit, maxCombinedTextureImageUnits);
+                }
+
+                return false;
+            }
+
+            if (textureUnitType[unit] != TEXTURE_UNKNOWN)
+            {
+                if (mSamplersVS[i].textureType != textureUnitType[unit])
+                {
+                    if (infoLog)
+                    {
+                        infoLog->append("Samplers of conflicting types refer to the same texture image unit (%d).", unit);
+                    }
+
+                    return false;
+                }
+            }
+            else
+            {
+                textureUnitType[unit] = mSamplersVS[i].textureType;
+            }
+        }
+    }
+
+    return true;
+}
+
+GLint ProgramBinary::getDxDepthRangeLocation() const
+{
+    return mDxDepthRangeLocation;
+}
+
+GLint ProgramBinary::getDxDepthLocation() const
+{
+    return mDxDepthLocation;
+}
+
+GLint ProgramBinary::getDxCoordLocation() const
+{
+    return mDxCoordLocation;
+}
+
+GLint ProgramBinary::getDxHalfPixelSizeLocation() const
+{
+    return mDxHalfPixelSizeLocation;
+}
+
+GLint ProgramBinary::getDxFrontCCWLocation() const
+{
+    return mDxFrontCCWLocation;
+}
+
+GLint ProgramBinary::getDxPointsOrLinesLocation() const
+{
+    return mDxPointsOrLinesLocation;
+}
+
+ProgramBinary::Sampler::Sampler() : active(false), logicalTextureUnit(0), textureType(TEXTURE_2D)
+{
+}
+
+}
diff --git a/src/3rdparty/angle/src/libGLESv2/ProgramBinary.h b/src/3rdparty/angle/src/libGLESv2/ProgramBinary.h
new file mode 100644 (file)
index 0000000..9ffe70b
--- /dev/null
@@ -0,0 +1,235 @@
+//
+// 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.
+//
+
+// Program.h: Defines the gl::Program class. Implements GL program objects
+// and related functionality. [OpenGL ES 2.0.24] section 2.10.3 page 28.
+
+#ifndef LIBGLESV2_PROGRAM_BINARY_H_
+#define LIBGLESV2_PROGRAM_BINARY_H_
+
+#define GL_APICALL
+#include <GLES2/gl2.h>
+#include <GLES2/gl2ext.h>
+
+#include <d3dcompiler.h>
+#include <string>
+#include <vector>
+
+#include "libGLESv2/Context.h"
+#include "libGLESv2/D3DConstantTable.h"
+#include "libGLESv2/mathutil.h"
+#include "libGLESv2/Shader.h"
+
+namespace gl
+{
+class FragmentShader;
+class VertexShader;
+
+// Helper struct representing a single shader uniform
+struct Uniform
+{
+    Uniform(GLenum type, const std::string &_name, unsigned int arraySize);
+
+    ~Uniform();
+
+    bool isArray();
+
+    const GLenum type;
+    const std::string _name;   // Decorated name
+    const std::string name;    // Undecorated name
+    const unsigned int arraySize;
+
+    unsigned char *data;
+    bool dirty;
+
+    struct RegisterInfo
+    {
+        RegisterInfo()
+        {
+            float4Index = -1;
+            samplerIndex = -1;
+            boolIndex = -1;
+            registerCount = 0;
+        }
+
+        void set(const D3DConstant *constant)
+        {
+            switch(constant->registerSet)
+            {
+              case D3DConstant::RS_BOOL:    boolIndex = constant->registerIndex;    break;
+              case D3DConstant::RS_FLOAT4:  float4Index = constant->registerIndex;  break;
+              case D3DConstant::RS_SAMPLER: samplerIndex = constant->registerIndex; break;
+              default: UNREACHABLE();
+            }
+            
+            ASSERT(registerCount == 0 || registerCount == (int)constant->registerCount);
+            registerCount = constant->registerCount;
+        }
+
+        int float4Index;
+        int samplerIndex;
+        int boolIndex;
+
+        int registerCount;
+    };
+
+    RegisterInfo ps;
+    RegisterInfo vs;
+};
+
+// Struct used for correlating uniforms/elements of uniform arrays to handles
+struct UniformLocation
+{
+    UniformLocation()
+    {
+    }
+
+    UniformLocation(const std::string &_name, unsigned int element, unsigned int index);
+
+    std::string name;
+    unsigned int element;
+    unsigned int index;
+};
+
+// This is the result of linking a program. It is the state that would be passed to ProgramBinary.
+class ProgramBinary : public RefCountObject
+{
+  public:
+    ProgramBinary();
+    ~ProgramBinary();
+
+    IDirect3DPixelShader9 *getPixelShader();
+    IDirect3DVertexShader9 *getVertexShader();
+
+    GLuint getAttributeLocation(const char *name);
+    int getSemanticIndex(int attributeIndex);
+
+    GLint getSamplerMapping(SamplerType type, unsigned int samplerIndex);
+    TextureType getSamplerTextureType(SamplerType type, unsigned int samplerIndex);
+    GLint getUsedSamplerRange(SamplerType type);
+    bool usesPointSize() const;
+
+    GLint getUniformLocation(std::string name);
+    bool setUniform1fv(GLint location, GLsizei count, const GLfloat *v);
+    bool setUniform2fv(GLint location, GLsizei count, const GLfloat *v);
+    bool setUniform3fv(GLint location, GLsizei count, const GLfloat *v);
+    bool setUniform4fv(GLint location, GLsizei count, const GLfloat *v);
+    bool setUniformMatrix2fv(GLint location, GLsizei count, const GLfloat *value);
+    bool setUniformMatrix3fv(GLint location, GLsizei count, const GLfloat *value);
+    bool setUniformMatrix4fv(GLint location, GLsizei count, const GLfloat *value);
+    bool setUniform1iv(GLint location, GLsizei count, const GLint *v);
+    bool setUniform2iv(GLint location, GLsizei count, const GLint *v);
+    bool setUniform3iv(GLint location, GLsizei count, const GLint *v);
+    bool setUniform4iv(GLint location, GLsizei count, const GLint *v);
+
+    bool getUniformfv(GLint location, GLsizei *bufSize, GLfloat *params);
+    bool getUniformiv(GLint location, GLsizei *bufSize, GLint *params);
+
+    GLint getDxDepthRangeLocation() const;
+    GLint getDxDepthLocation() const;
+    GLint getDxCoordLocation() const;
+    GLint getDxHalfPixelSizeLocation() const;
+    GLint getDxFrontCCWLocation() const;
+    GLint getDxPointsOrLinesLocation() const;
+
+    void dirtyAllUniforms();
+    void applyUniforms();
+
+    bool load(InfoLog &infoLog, const void *binary, GLsizei length);
+    bool save(void* binary, GLsizei bufSize, GLsizei *length);
+    GLint getLength();
+
+    bool link(InfoLog &infoLog, const AttributeBindings &attributeBindings, FragmentShader *fragmentShader, VertexShader *vertexShader);
+    void getAttachedShaders(GLsizei maxCount, GLsizei *count, GLuint *shaders);
+
+    void getActiveAttribute(GLuint index, GLsizei bufsize, GLsizei *length, GLint *size, GLenum *type, GLchar *name);
+    GLint getActiveAttributeCount();
+    GLint getActiveAttributeMaxLength();
+
+    void getActiveUniform(GLuint index, GLsizei bufsize, GLsizei *length, GLint *size, GLenum *type, GLchar *name);
+    GLint getActiveUniformCount();
+    GLint getActiveUniformMaxLength();
+
+    void validate(InfoLog &infoLog);
+    bool validateSamplers(InfoLog *infoLog);
+    bool isValidated() const;
+
+    unsigned int getSerial() const;
+
+    static std::string decorateAttribute(const std::string &name);    // Prepend an underscore
+    static std::string undecorateUniform(const std::string &_name);   // Remove leading underscore
+
+  private:
+    DISALLOW_COPY_AND_ASSIGN(ProgramBinary);
+
+    ID3D10Blob *compileToBinary(InfoLog &infoLog, const char *hlsl, const char *profile, D3DConstantTable **constantTable);
+
+    int packVaryings(InfoLog &infoLog, const Varying *packing[][4], FragmentShader *fragmentShader);
+    bool linkVaryings(InfoLog &infoLog, std::string& pixelHLSL, std::string& vertexHLSL, FragmentShader *fragmentShader, VertexShader *vertexShader);
+
+    bool linkAttributes(InfoLog &infoLog, const AttributeBindings &attributeBindings, FragmentShader *fragmentShader, VertexShader *vertexShader);
+
+    bool linkUniforms(InfoLog &infoLog, GLenum shader, D3DConstantTable *constantTable);
+    bool defineUniform(InfoLog &infoLog, GLenum shader, const D3DConstant *constant, std::string name = "");
+    bool defineUniform(GLenum shader, const D3DConstant *constant, const std::string &name);
+    Uniform *createUniform( const D3DConstant *constant, const std::string &name);
+    bool applyUniformnfv(Uniform *targetUniform, const GLfloat *v);
+    bool applyUniform1iv(Uniform *targetUniform, GLsizei count, const GLint *v);
+    bool applyUniform2iv(Uniform *targetUniform, GLsizei count, const GLint *v);
+    bool applyUniform3iv(Uniform *targetUniform, GLsizei count, const GLint *v);
+    bool applyUniform4iv(Uniform *targetUniform, GLsizei count, const GLint *v);
+    void applyUniformniv(Uniform *targetUniform, GLsizei count, const Vector4 *vector);
+    void applyUniformnbv(Uniform *targetUniform, GLsizei count, int width, const GLboolean *v);
+
+    IDirect3DDevice9 *mDevice;
+
+    IDirect3DPixelShader9 *mPixelExecutable;
+    IDirect3DVertexShader9 *mVertexExecutable;
+
+    // These are only used during linking.
+    D3DConstantTable *mConstantTablePS;
+    D3DConstantTable *mConstantTableVS;
+
+    Attribute mLinkedAttribute[MAX_VERTEX_ATTRIBS];
+    int mSemanticIndex[MAX_VERTEX_ATTRIBS];
+
+    struct Sampler
+    {
+        Sampler();
+
+        bool active;
+        GLint logicalTextureUnit;
+        TextureType textureType;
+    };
+
+    Sampler mSamplersPS[MAX_TEXTURE_IMAGE_UNITS];
+    Sampler mSamplersVS[MAX_VERTEX_TEXTURE_IMAGE_UNITS_VTF];
+    GLuint mUsedVertexSamplerRange;
+    GLuint mUsedPixelSamplerRange;
+    bool mUsesPointSize;
+
+    typedef std::vector<Uniform*> UniformArray;
+    UniformArray mUniforms;
+    typedef std::vector<UniformLocation> UniformIndex;
+    UniformIndex mUniformIndex;
+
+    GLint mDxDepthRangeLocation;
+    GLint mDxDepthLocation;
+    GLint mDxCoordLocation;
+    GLint mDxHalfPixelSizeLocation;
+    GLint mDxFrontCCWLocation;
+    GLint mDxPointsOrLinesLocation;
+
+    bool mValidated;
+
+    const unsigned int mSerial;
+
+    static unsigned int issueSerial();
+    static unsigned int mCurrentSerial;
+};
+}
+
+#endif   // LIBGLESV2_PROGRAM_BINARY_H_
diff --git a/src/3rdparty/angle/src/libGLESv2/Query.cpp b/src/3rdparty/angle/src/libGLESv2/Query.cpp
new file mode 100644 (file)
index 0000000..10edda5
--- /dev/null
@@ -0,0 +1,128 @@
+//
+// 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.
+//
+
+// Query.cpp: Implements the gl::Query class
+
+#include "libGLESv2/Query.h"
+
+#include "libGLESv2/main.h"
+
+namespace gl
+{
+
+Query::Query(GLuint id, GLenum type) : RefCountObject(id)
+{ 
+    mQuery = NULL;
+    mStatus = GL_FALSE;
+    mResult = GL_FALSE;
+    mType = type;
+}
+
+Query::~Query()
+{
+    if (mQuery != NULL)
+    {
+        mQuery->Release();
+        mQuery = NULL;
+    }
+}
+
+void Query::begin()
+{
+    if (mQuery == NULL)
+    {
+        if (FAILED(getDevice()->CreateQuery(D3DQUERYTYPE_OCCLUSION, &mQuery)))
+        {
+            return error(GL_OUT_OF_MEMORY);
+        }
+    }
+
+    HRESULT result = mQuery->Issue(D3DISSUE_BEGIN);
+    ASSERT(SUCCEEDED(result));
+}
+
+void Query::end()
+{
+    if (mQuery == NULL)
+    {
+        return error(GL_INVALID_OPERATION);
+    }
+
+    HRESULT result = mQuery->Issue(D3DISSUE_END);
+    ASSERT(SUCCEEDED(result));
+    
+    mStatus = GL_FALSE;
+    mResult = GL_FALSE;
+}
+
+GLuint Query::getResult()
+{
+    if (mQuery != NULL)
+    {
+        while (!testQuery())
+        {
+            Sleep(0);
+            // explicitly check for device loss
+            // some drivers seem to return S_FALSE even if the device is lost
+            // instead of D3DERR_DEVICELOST like they should
+            if (gl::getDisplay()->testDeviceLost())
+            {
+                gl::getDisplay()->notifyDeviceLost();
+                return error(GL_OUT_OF_MEMORY, 0);
+            }
+        }
+    }
+
+    return (GLuint)mResult;
+}
+
+GLboolean Query::isResultAvailable()
+{
+    if (mQuery != NULL)
+    {
+        testQuery();
+    }
+    
+    return mStatus;
+}
+
+GLenum Query::getType() const
+{
+    return mType;
+}
+
+GLboolean Query::testQuery()
+{
+    if (mQuery != NULL && mStatus != GL_TRUE)
+    {
+        DWORD numPixels = 0;
+
+        HRESULT hres = mQuery->GetData(&numPixels, sizeof(DWORD), D3DGETDATA_FLUSH);
+        if (hres == S_OK)
+        {
+            mStatus = GL_TRUE;
+
+            switch (mType)
+            {
+              case GL_ANY_SAMPLES_PASSED_EXT:
+              case GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT:
+                mResult = (numPixels > 0) ? GL_TRUE : GL_FALSE;
+                break;
+              default:
+                ASSERT(false);
+            }
+        }
+        else if (checkDeviceLost(hres))
+        {
+            return error(GL_OUT_OF_MEMORY, GL_TRUE);
+        }
+        
+        return mStatus;
+    }
+
+    return GL_TRUE; // prevent blocking when query is null
+}
+}
diff --git a/src/3rdparty/angle/src/libGLESv2/Query.h b/src/3rdparty/angle/src/libGLESv2/Query.h
new file mode 100644 (file)
index 0000000..79357a0
--- /dev/null
@@ -0,0 +1,48 @@
+//
+// 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.
+//
+
+// Query.h: Defines the gl::Query class
+
+#ifndef LIBGLESV2_QUERY_H_
+#define LIBGLESV2_QUERY_H_
+
+#define GL_APICALL
+#include <GLES2/gl2.h>
+#include <d3d9.h>
+
+#include "common/angleutils.h"
+#include "common/RefCountObject.h"
+
+namespace gl
+{
+
+class Query : public RefCountObject
+{
+  public:
+    Query(GLuint id, GLenum type);
+    virtual ~Query();
+
+    void begin();
+    void end();
+    GLuint getResult();
+    GLboolean isResultAvailable();
+
+    GLenum getType() const;
+
+  private:
+    DISALLOW_COPY_AND_ASSIGN(Query);
+
+    GLboolean testQuery();
+
+    IDirect3DQuery9* mQuery;
+    GLenum mType;
+    GLboolean mStatus;
+    GLint mResult;
+};
+
+}
+
+#endif   // LIBGLESV2_QUERY_H_
diff --git a/src/3rdparty/angle/src/libGLESv2/Renderbuffer.cpp b/src/3rdparty/angle/src/libGLESv2/Renderbuffer.cpp
new file mode 100644 (file)
index 0000000..4b911e8
--- /dev/null
@@ -0,0 +1,577 @@
+//
+// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// Renderbuffer.cpp: the gl::Renderbuffer class and its derived classes
+// Colorbuffer, Depthbuffer and Stencilbuffer. Implements GL renderbuffer
+// objects and related functionality. [OpenGL ES 2.0.24] section 4.4.3 page 108.
+
+#include "libGLESv2/Renderbuffer.h"
+
+#include "libGLESv2/main.h"
+#include "libGLESv2/Texture.h"
+#include "libGLESv2/utilities.h"
+
+namespace gl
+{
+unsigned int RenderbufferStorage::mCurrentSerial = 1;
+
+RenderbufferInterface::RenderbufferInterface()
+{
+}
+
+// The default case for classes inherited from RenderbufferInterface is not to
+// need to do anything upon the reference count to the parent Renderbuffer incrementing
+// or decrementing. 
+void RenderbufferInterface::addProxyRef(const Renderbuffer *proxy)
+{
+}
+
+void RenderbufferInterface::releaseProxy(const Renderbuffer *proxy)
+{
+}
+
+GLuint RenderbufferInterface::getRedSize() const
+{
+    return dx2es::GetRedSize(getD3DFormat());
+}
+
+GLuint RenderbufferInterface::getGreenSize() const
+{
+    return dx2es::GetGreenSize(getD3DFormat());
+}
+
+GLuint RenderbufferInterface::getBlueSize() const
+{
+    return dx2es::GetBlueSize(getD3DFormat());
+}
+
+GLuint RenderbufferInterface::getAlphaSize() const
+{
+    return dx2es::GetAlphaSize(getD3DFormat());
+}
+
+GLuint RenderbufferInterface::getDepthSize() const
+{
+    return dx2es::GetDepthSize(getD3DFormat());
+}
+
+GLuint RenderbufferInterface::getStencilSize() const
+{
+    return dx2es::GetStencilSize(getD3DFormat());
+}
+
+///// RenderbufferTexture2D Implementation ////////
+
+RenderbufferTexture2D::RenderbufferTexture2D(Texture2D *texture, GLenum target) : mTarget(target)
+{
+    mTexture2D.set(texture);
+}
+
+RenderbufferTexture2D::~RenderbufferTexture2D()
+{
+    mTexture2D.set(NULL);
+}
+
+// Textures need to maintain their own reference count for references via
+// Renderbuffers acting as proxies. Here, we notify the texture of a reference.
+void RenderbufferTexture2D::addProxyRef(const Renderbuffer *proxy)
+{
+    mTexture2D->addProxyRef(proxy);
+}
+
+void RenderbufferTexture2D::releaseProxy(const Renderbuffer *proxy)
+{
+    mTexture2D->releaseProxy(proxy);
+}
+
+// Increments refcount on surface.
+// caller must Release() the returned surface
+IDirect3DSurface9 *RenderbufferTexture2D::getRenderTarget()
+{
+    return mTexture2D->getRenderTarget(mTarget);
+}
+
+// Increments refcount on surface.
+// caller must Release() the returned surface
+IDirect3DSurface9 *RenderbufferTexture2D::getDepthStencil()
+{
+    return mTexture2D->getDepthStencil(mTarget);
+}
+
+GLsizei RenderbufferTexture2D::getWidth() const
+{
+    return mTexture2D->getWidth(0);
+}
+
+GLsizei RenderbufferTexture2D::getHeight() const
+{
+    return mTexture2D->getHeight(0);
+}
+
+GLenum RenderbufferTexture2D::getInternalFormat() const
+{
+    return mTexture2D->getInternalFormat(0);
+}
+
+D3DFORMAT RenderbufferTexture2D::getD3DFormat() const
+{
+    return mTexture2D->getD3DFormat(0);
+}
+
+GLsizei RenderbufferTexture2D::getSamples() const
+{
+    return 0;
+}
+
+unsigned int RenderbufferTexture2D::getSerial() const
+{
+    return mTexture2D->getRenderTargetSerial(mTarget);
+}
+
+///// RenderbufferTextureCubeMap Implementation ////////
+
+RenderbufferTextureCubeMap::RenderbufferTextureCubeMap(TextureCubeMap *texture, GLenum target) : mTarget(target)
+{
+    mTextureCubeMap.set(texture);
+}
+
+RenderbufferTextureCubeMap::~RenderbufferTextureCubeMap()
+{
+    mTextureCubeMap.set(NULL);
+}
+
+// Textures need to maintain their own reference count for references via
+// Renderbuffers acting as proxies. Here, we notify the texture of a reference.
+void RenderbufferTextureCubeMap::addProxyRef(const Renderbuffer *proxy)
+{
+    mTextureCubeMap->addProxyRef(proxy);
+}
+
+void RenderbufferTextureCubeMap::releaseProxy(const Renderbuffer *proxy)
+{
+    mTextureCubeMap->releaseProxy(proxy);
+}
+
+// Increments refcount on surface.
+// caller must Release() the returned surface
+IDirect3DSurface9 *RenderbufferTextureCubeMap::getRenderTarget()
+{
+    return mTextureCubeMap->getRenderTarget(mTarget);
+}
+
+// Increments refcount on surface.
+// caller must Release() the returned surface
+IDirect3DSurface9 *RenderbufferTextureCubeMap::getDepthStencil()
+{
+    return NULL;
+}
+
+GLsizei RenderbufferTextureCubeMap::getWidth() const
+{
+    return mTextureCubeMap->getWidth(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0);
+}
+
+GLsizei RenderbufferTextureCubeMap::getHeight() const
+{
+    return mTextureCubeMap->getHeight(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0);
+}
+
+GLenum RenderbufferTextureCubeMap::getInternalFormat() const
+{
+    return mTextureCubeMap->getInternalFormat(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0);
+}
+
+D3DFORMAT RenderbufferTextureCubeMap::getD3DFormat() const
+{
+    return mTextureCubeMap->getD3DFormat(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0);
+}
+
+GLsizei RenderbufferTextureCubeMap::getSamples() const
+{
+    return 0;
+}
+
+unsigned int RenderbufferTextureCubeMap::getSerial() const
+{
+    return mTextureCubeMap->getRenderTargetSerial(mTarget);
+}
+
+////// Renderbuffer Implementation //////
+
+Renderbuffer::Renderbuffer(GLuint id, RenderbufferInterface *instance) : RefCountObject(id)
+{
+    ASSERT(instance != NULL);
+    mInstance = instance;
+}
+
+Renderbuffer::~Renderbuffer()
+{
+    delete mInstance;
+}
+
+// The RenderbufferInterface contained in this Renderbuffer may need to maintain
+// its own reference count, so we pass it on here.
+void Renderbuffer::addRef() const
+{
+    mInstance->addProxyRef(this);
+
+    RefCountObject::addRef();
+}
+
+void Renderbuffer::release() const
+{
+    mInstance->releaseProxy(this);
+
+    RefCountObject::release();
+}
+
+// Increments refcount on surface.
+// caller must Release() the returned surface
+IDirect3DSurface9 *Renderbuffer::getRenderTarget()
+{
+    return mInstance->getRenderTarget();
+}
+
+// Increments refcount on surface.
+// caller must Release() the returned surface
+IDirect3DSurface9 *Renderbuffer::getDepthStencil()
+{
+    return mInstance->getDepthStencil();
+}
+
+GLsizei Renderbuffer::getWidth() const
+{
+    return mInstance->getWidth();
+}
+
+GLsizei Renderbuffer::getHeight() const
+{
+    return mInstance->getHeight();
+}
+
+GLenum Renderbuffer::getInternalFormat() const
+{
+    return mInstance->getInternalFormat();
+}
+
+D3DFORMAT Renderbuffer::getD3DFormat() const
+{
+    return mInstance->getD3DFormat();
+}
+
+GLuint Renderbuffer::getRedSize() const
+{
+    return mInstance->getRedSize();
+}
+
+GLuint Renderbuffer::getGreenSize() const
+{
+    return mInstance->getGreenSize();
+}
+
+GLuint Renderbuffer::getBlueSize() const
+{
+    return mInstance->getBlueSize();
+}
+
+GLuint Renderbuffer::getAlphaSize() const
+{
+    return mInstance->getAlphaSize();
+}
+
+GLuint Renderbuffer::getDepthSize() const
+{
+    return mInstance->getDepthSize();
+}
+
+GLuint Renderbuffer::getStencilSize() const
+{
+    return mInstance->getStencilSize();
+}
+
+GLsizei Renderbuffer::getSamples() const
+{
+    return mInstance->getSamples();
+}
+
+unsigned int Renderbuffer::getSerial() const
+{
+    return mInstance->getSerial();
+}
+
+void Renderbuffer::setStorage(RenderbufferStorage *newStorage)
+{
+    ASSERT(newStorage != NULL);
+
+    delete mInstance;
+    mInstance = newStorage;
+}
+
+RenderbufferStorage::RenderbufferStorage() : mSerial(issueSerial())
+{
+    mWidth = 0;
+    mHeight = 0;
+    mInternalFormat = GL_RGBA4;
+    mD3DFormat = D3DFMT_A8R8G8B8;
+    mSamples = 0;
+}
+
+RenderbufferStorage::~RenderbufferStorage()
+{
+}
+
+// Increments refcount on surface.
+// caller must Release() the returned surface
+IDirect3DSurface9 *RenderbufferStorage::getRenderTarget()
+{
+    return NULL;
+}
+
+// Increments refcount on surface.
+// caller must Release() the returned surface
+IDirect3DSurface9 *RenderbufferStorage::getDepthStencil()
+{
+    return NULL;
+}
+
+GLsizei RenderbufferStorage::getWidth() const
+{
+    return mWidth;
+}
+
+GLsizei RenderbufferStorage::getHeight() const
+{
+    return mHeight;
+}
+
+GLenum RenderbufferStorage::getInternalFormat() const
+{
+    return mInternalFormat;
+}
+
+D3DFORMAT RenderbufferStorage::getD3DFormat() const
+{
+    return mD3DFormat;
+}
+
+GLsizei RenderbufferStorage::getSamples() const
+{
+    return mSamples;
+}
+
+unsigned int RenderbufferStorage::getSerial() const
+{
+    return mSerial;
+}
+
+unsigned int RenderbufferStorage::issueSerial()
+{
+    return mCurrentSerial++;
+}
+
+unsigned int RenderbufferStorage::issueCubeSerials()
+{
+    unsigned int firstSerial = mCurrentSerial;
+    mCurrentSerial += 6;
+    return firstSerial;
+}
+
+Colorbuffer::Colorbuffer(IDirect3DSurface9 *renderTarget) : mRenderTarget(renderTarget)
+{
+    if (renderTarget)
+    {
+        renderTarget->AddRef();
+
+        D3DSURFACE_DESC description;
+        renderTarget->GetDesc(&description);
+
+        mWidth = description.Width;
+        mHeight = description.Height;
+        mInternalFormat = dx2es::ConvertBackBufferFormat(description.Format);
+        mD3DFormat = description.Format;
+        mSamples = dx2es::GetSamplesFromMultisampleType(description.MultiSampleType);
+    }
+}
+
+Colorbuffer::Colorbuffer(int width, int height, GLenum format, GLsizei samples) : mRenderTarget(NULL)
+{
+    IDirect3DDevice9 *device = getDevice();
+
+    D3DFORMAT requestedFormat = es2dx::ConvertRenderbufferFormat(format);
+    int supportedSamples = getContext()->getNearestSupportedSamples(requestedFormat, samples);
+
+    if (supportedSamples == -1)
+    {
+        error(GL_OUT_OF_MEMORY);
+
+        return;
+    }
+
+    if (width > 0 && height > 0)
+    {
+        HRESULT result = device->CreateRenderTarget(width, height, requestedFormat, 
+                                                    es2dx::GetMultisampleTypeFromSamples(supportedSamples), 0, FALSE, &mRenderTarget, NULL);
+
+        if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY)
+        {
+            error(GL_OUT_OF_MEMORY);
+
+            return;
+        }
+
+        ASSERT(SUCCEEDED(result));
+    }
+
+    mWidth = width;
+    mHeight = height;
+    mInternalFormat = format;
+    mD3DFormat = requestedFormat;
+    mSamples = supportedSamples;
+}
+
+Colorbuffer::~Colorbuffer()
+{
+    if (mRenderTarget)
+    {
+        mRenderTarget->Release();
+    }
+}
+
+// Increments refcount on surface.
+// caller must Release() the returned surface
+IDirect3DSurface9 *Colorbuffer::getRenderTarget()
+{
+    if (mRenderTarget)
+    {
+        mRenderTarget->AddRef();
+    }
+
+    return mRenderTarget;
+}
+
+DepthStencilbuffer::DepthStencilbuffer(IDirect3DSurface9 *depthStencil) : mDepthStencil(depthStencil)
+{
+    if (depthStencil)
+    {
+        depthStencil->AddRef();
+
+        D3DSURFACE_DESC description;
+        depthStencil->GetDesc(&description);
+
+        mWidth = description.Width;
+        mHeight = description.Height;
+        mInternalFormat = dx2es::ConvertDepthStencilFormat(description.Format);
+        mSamples = dx2es::GetSamplesFromMultisampleType(description.MultiSampleType); 
+        mD3DFormat = description.Format;
+    }
+}
+
+DepthStencilbuffer::DepthStencilbuffer(int width, int height, GLsizei samples)
+{
+    IDirect3DDevice9 *device = getDevice();
+
+    mDepthStencil = NULL;
+    
+    int supportedSamples = getContext()->getNearestSupportedSamples(D3DFMT_D24S8, samples);
+
+    if (supportedSamples == -1)
+    {
+        error(GL_OUT_OF_MEMORY);
+
+        return;
+    }
+
+    if (width > 0 && height > 0)
+    {
+        HRESULT result = device->CreateDepthStencilSurface(width, height, D3DFMT_D24S8, es2dx::GetMultisampleTypeFromSamples(supportedSamples),
+                                                           0, FALSE, &mDepthStencil, 0);
+
+        if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY)
+        {
+            error(GL_OUT_OF_MEMORY);
+
+            return;
+        }
+
+        ASSERT(SUCCEEDED(result));
+    }
+
+    mWidth = width;
+    mHeight = height;
+    mInternalFormat = GL_DEPTH24_STENCIL8_OES;
+    mD3DFormat = D3DFMT_D24S8;
+    mSamples = supportedSamples;
+}
+
+DepthStencilbuffer::~DepthStencilbuffer()
+{
+    if (mDepthStencil)
+    {
+        mDepthStencil->Release();
+    }
+}
+
+// Increments refcount on surface.
+// caller must Release() the returned surface
+IDirect3DSurface9 *DepthStencilbuffer::getDepthStencil()
+{
+    if (mDepthStencil)
+    {
+        mDepthStencil->AddRef();
+    }
+
+    return mDepthStencil;
+}
+
+Depthbuffer::Depthbuffer(IDirect3DSurface9 *depthStencil) : DepthStencilbuffer(depthStencil)
+{
+    if (depthStencil)
+    {
+        mInternalFormat = GL_DEPTH_COMPONENT16;   // If the renderbuffer parameters are queried, the calling function
+                                                  // will expect one of the valid renderbuffer formats for use in 
+                                                  // glRenderbufferStorage
+    }
+}
+
+Depthbuffer::Depthbuffer(int width, int height, GLsizei samples) : DepthStencilbuffer(width, height, samples)
+{
+    if (mDepthStencil)
+    {
+        mInternalFormat = GL_DEPTH_COMPONENT16;   // If the renderbuffer parameters are queried, the calling function
+                                                  // will expect one of the valid renderbuffer formats for use in 
+                                                  // glRenderbufferStorage
+    }
+}
+
+Depthbuffer::~Depthbuffer()
+{
+}
+
+Stencilbuffer::Stencilbuffer(IDirect3DSurface9 *depthStencil) : DepthStencilbuffer(depthStencil)
+{
+    if (depthStencil)
+    {
+        mInternalFormat = GL_STENCIL_INDEX8;   // If the renderbuffer parameters are queried, the calling function
+                                               // will expect one of the valid renderbuffer formats for use in 
+                                               // glRenderbufferStorage
+    }
+}
+
+Stencilbuffer::Stencilbuffer(int width, int height, GLsizei samples) : DepthStencilbuffer(width, height, samples)
+{
+    if (mDepthStencil)
+    {
+        mInternalFormat = GL_STENCIL_INDEX8;   // If the renderbuffer parameters are queried, the calling function
+                                               // will expect one of the valid renderbuffer formats for use in 
+                                               // glRenderbufferStorage
+    }
+}
+
+Stencilbuffer::~Stencilbuffer()
+{
+}
+
+}
diff --git a/src/3rdparty/angle/src/libGLESv2/Renderbuffer.h b/src/3rdparty/angle/src/libGLESv2/Renderbuffer.h
new file mode 100644 (file)
index 0000000..e6d5ddb
--- /dev/null
@@ -0,0 +1,257 @@
+//
+// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// Renderbuffer.h: Defines the wrapper class gl::Renderbuffer, as well as the
+// class hierarchy used to store its contents: RenderbufferStorage, Colorbuffer,
+// DepthStencilbuffer, Depthbuffer and Stencilbuffer. Implements GL renderbuffer
+// objects and related functionality. [OpenGL ES 2.0.24] section 4.4.3 page 108.
+
+#ifndef LIBGLESV2_RENDERBUFFER_H_
+#define LIBGLESV2_RENDERBUFFER_H_
+
+#define GL_APICALL
+#include <GLES2/gl2.h>
+#include <d3d9.h>
+
+#include "common/angleutils.h"
+#include "common/RefCountObject.h"
+
+namespace gl
+{
+class Texture2D;
+class TextureCubeMap;
+class Renderbuffer;
+class Colorbuffer;
+class DepthStencilbuffer;
+
+class RenderbufferInterface
+{
+  public:
+    RenderbufferInterface();
+
+    virtual ~RenderbufferInterface() {};
+
+    virtual void addProxyRef(const Renderbuffer *proxy);
+    virtual void releaseProxy(const Renderbuffer *proxy);
+
+    virtual IDirect3DSurface9 *getRenderTarget() = 0;
+    virtual IDirect3DSurface9 *getDepthStencil() = 0;
+
+    virtual GLsizei getWidth() const = 0;
+    virtual GLsizei getHeight() const = 0;
+    virtual GLenum getInternalFormat() const = 0;
+    virtual D3DFORMAT getD3DFormat() const = 0;
+    virtual GLsizei getSamples() const = 0;
+
+    GLuint getRedSize() const;
+    GLuint getGreenSize() const;
+    GLuint getBlueSize() const;
+    GLuint getAlphaSize() const;
+    GLuint getDepthSize() const;
+    GLuint getStencilSize() const;
+
+    virtual unsigned int getSerial() const = 0;
+
+  private:
+    DISALLOW_COPY_AND_ASSIGN(RenderbufferInterface);
+};
+
+class RenderbufferTexture2D : public RenderbufferInterface
+{
+  public:
+    RenderbufferTexture2D(Texture2D *texture, GLenum target);
+
+    virtual ~RenderbufferTexture2D();
+
+    void addProxyRef(const Renderbuffer *proxy);
+    void releaseProxy(const Renderbuffer *proxy);
+
+    IDirect3DSurface9 *getRenderTarget();
+    IDirect3DSurface9 *getDepthStencil();
+
+    virtual GLsizei getWidth() const;
+    virtual GLsizei getHeight() const;
+    virtual GLenum getInternalFormat() const;
+    virtual D3DFORMAT getD3DFormat() const;
+    virtual GLsizei getSamples() const;
+
+    virtual unsigned int getSerial() const;
+
+  private:
+    DISALLOW_COPY_AND_ASSIGN(RenderbufferTexture2D);
+
+    BindingPointer <Texture2D> mTexture2D;
+    GLenum mTarget;
+};
+
+class RenderbufferTextureCubeMap : public RenderbufferInterface
+{
+  public:
+    RenderbufferTextureCubeMap(TextureCubeMap *texture, GLenum target);
+
+    virtual ~RenderbufferTextureCubeMap();
+
+    void addProxyRef(const Renderbuffer *proxy);
+    void releaseProxy(const Renderbuffer *proxy);
+
+    IDirect3DSurface9 *getRenderTarget();
+    IDirect3DSurface9 *getDepthStencil();
+
+    virtual GLsizei getWidth() const;
+    virtual GLsizei getHeight() const;
+    virtual GLenum getInternalFormat() const;
+    virtual D3DFORMAT getD3DFormat() const;
+    virtual GLsizei getSamples() const;
+
+    virtual unsigned int getSerial() const;
+
+  private:
+    DISALLOW_COPY_AND_ASSIGN(RenderbufferTextureCubeMap);
+
+    BindingPointer <TextureCubeMap> mTextureCubeMap;
+    GLenum mTarget;
+};
+
+// A class derived from RenderbufferStorage is created whenever glRenderbufferStorage
+// is called. The specific concrete type depends on whether the internal format is
+// colour depth, stencil or packed depth/stencil.
+class RenderbufferStorage : public RenderbufferInterface
+{
+  public:
+    RenderbufferStorage();
+
+    virtual ~RenderbufferStorage() = 0;
+
+    virtual IDirect3DSurface9 *getRenderTarget();
+    virtual IDirect3DSurface9 *getDepthStencil();
+
+    virtual GLsizei getWidth() const;
+    virtual GLsizei getHeight() const;
+    virtual GLenum getInternalFormat() const;
+    virtual D3DFORMAT getD3DFormat() const;
+    virtual GLsizei getSamples() const;
+
+    virtual unsigned int getSerial() const;
+
+    static unsigned int issueSerial();
+    static unsigned int issueCubeSerials();
+
+  protected:
+    GLsizei mWidth;
+    GLsizei mHeight;
+    GLenum mInternalFormat;
+    D3DFORMAT mD3DFormat;
+    GLsizei mSamples;
+
+  private:
+    DISALLOW_COPY_AND_ASSIGN(RenderbufferStorage);
+
+    const unsigned int mSerial;
+
+    static unsigned int mCurrentSerial;
+};
+
+// Renderbuffer implements the GL renderbuffer object.
+// It's only a proxy for a RenderbufferInterface instance; the internal object
+// can change whenever glRenderbufferStorage is called.
+class Renderbuffer : public RefCountObject
+{
+  public:
+    Renderbuffer(GLuint id, RenderbufferInterface *storage);
+
+    virtual ~Renderbuffer();
+
+    // These functions from RefCountObject are overloaded here because
+    // Textures need to maintain their own count of references to them via
+    // Renderbuffers/RenderbufferTextures. These functions invoke those
+    // reference counting functions on the RenderbufferInterface.
+    void addRef() const;
+    void release() const;
+
+    IDirect3DSurface9 *getRenderTarget();
+    IDirect3DSurface9 *getDepthStencil();
+
+    GLsizei getWidth() const;
+    GLsizei getHeight() const;
+    GLenum getInternalFormat() const;
+    D3DFORMAT getD3DFormat() const;
+    GLuint getRedSize() const;
+    GLuint getGreenSize() const;
+    GLuint getBlueSize() const;
+    GLuint getAlphaSize() const;
+    GLuint getDepthSize() const;
+    GLuint getStencilSize() const;
+    GLsizei getSamples() const;
+
+    unsigned int getSerial() const;
+
+    void setStorage(RenderbufferStorage *newStorage);
+
+  private:
+    DISALLOW_COPY_AND_ASSIGN(Renderbuffer);
+
+    RenderbufferInterface *mInstance;
+};
+
+class Colorbuffer : public RenderbufferStorage
+{
+  public:
+    explicit Colorbuffer(IDirect3DSurface9 *renderTarget);
+    Colorbuffer(GLsizei width, GLsizei height, GLenum format, GLsizei samples);
+
+    virtual ~Colorbuffer();
+
+    virtual IDirect3DSurface9 *getRenderTarget();
+
+  private:
+    DISALLOW_COPY_AND_ASSIGN(Colorbuffer);
+
+    IDirect3DSurface9 *mRenderTarget;
+};
+
+class DepthStencilbuffer : public RenderbufferStorage
+{
+  public:
+    explicit DepthStencilbuffer(IDirect3DSurface9 *depthStencil);
+    DepthStencilbuffer(GLsizei width, GLsizei height, GLsizei samples);
+
+    ~DepthStencilbuffer();
+
+    virtual IDirect3DSurface9 *getDepthStencil();
+
+  protected:
+    IDirect3DSurface9 *mDepthStencil;
+
+  private:
+    DISALLOW_COPY_AND_ASSIGN(DepthStencilbuffer);
+};
+
+class Depthbuffer : public DepthStencilbuffer
+{
+  public:
+    explicit Depthbuffer(IDirect3DSurface9 *depthStencil);
+    Depthbuffer(GLsizei width, GLsizei height, GLsizei samples);
+
+    virtual ~Depthbuffer();
+
+  private:
+    DISALLOW_COPY_AND_ASSIGN(Depthbuffer);
+};
+
+class Stencilbuffer : public DepthStencilbuffer
+{
+  public:
+    explicit Stencilbuffer(IDirect3DSurface9 *depthStencil);
+    Stencilbuffer(GLsizei width, GLsizei height, GLsizei samples);
+
+    virtual ~Stencilbuffer();
+
+  private:
+    DISALLOW_COPY_AND_ASSIGN(Stencilbuffer);
+};
+}
+
+#endif   // LIBGLESV2_RENDERBUFFER_H_
diff --git a/src/3rdparty/angle/src/libGLESv2/ResourceManager.cpp b/src/3rdparty/angle/src/libGLESv2/ResourceManager.cpp
new file mode 100644 (file)
index 0000000..4b97e9c
--- /dev/null
@@ -0,0 +1,320 @@
+//
+// 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.
+//
+
+// ResourceManager.cpp: Implements the gl::ResourceManager class, which tracks and 
+// retrieves objects which may be shared by multiple Contexts.
+
+#include "libGLESv2/ResourceManager.h"
+
+#include "libGLESv2/Buffer.h"
+#include "libGLESv2/Program.h"
+#include "libGLESv2/Renderbuffer.h"
+#include "libGLESv2/Shader.h"
+#include "libGLESv2/Texture.h"
+
+namespace gl
+{
+ResourceManager::ResourceManager()
+{
+    mRefCount = 1;
+}
+
+ResourceManager::~ResourceManager()
+{
+    while (!mBufferMap.empty())
+    {
+        deleteBuffer(mBufferMap.begin()->first);
+    }
+
+    while (!mProgramMap.empty())
+    {
+        deleteProgram(mProgramMap.begin()->first);
+    }
+
+    while (!mShaderMap.empty())
+    {
+        deleteShader(mShaderMap.begin()->first);
+    }
+
+    while (!mRenderbufferMap.empty())
+    {
+        deleteRenderbuffer(mRenderbufferMap.begin()->first);
+    }
+
+    while (!mTextureMap.empty())
+    {
+        deleteTexture(mTextureMap.begin()->first);
+    }
+}
+
+void ResourceManager::addRef()
+{
+    mRefCount++;
+}
+
+void ResourceManager::release()
+{
+    if (--mRefCount == 0)
+    {
+        delete this;
+    }
+}
+
+// Returns an unused buffer name
+GLuint ResourceManager::createBuffer()
+{
+    GLuint handle = mBufferHandleAllocator.allocate();
+
+    mBufferMap[handle] = NULL;
+
+    return handle;
+}
+
+// Returns an unused shader/program name
+GLuint ResourceManager::createShader(GLenum type)
+{
+    GLuint handle = mProgramShaderHandleAllocator.allocate();
+
+    if (type == GL_VERTEX_SHADER)
+    {
+        mShaderMap[handle] = new VertexShader(this, handle);
+    }
+    else if (type == GL_FRAGMENT_SHADER)
+    {
+        mShaderMap[handle] = new FragmentShader(this, handle);
+    }
+    else UNREACHABLE();
+
+    return handle;
+}
+
+// Returns an unused program/shader name
+GLuint ResourceManager::createProgram()
+{
+    GLuint handle = mProgramShaderHandleAllocator.allocate();
+
+    mProgramMap[handle] = new Program(this, handle);
+
+    return handle;
+}
+
+// Returns an unused texture name
+GLuint ResourceManager::createTexture()
+{
+    GLuint handle = mTextureHandleAllocator.allocate();
+
+    mTextureMap[handle] = NULL;
+
+    return handle;
+}
+
+// Returns an unused renderbuffer name
+GLuint ResourceManager::createRenderbuffer()
+{
+    GLuint handle = mRenderbufferHandleAllocator.allocate();
+
+    mRenderbufferMap[handle] = NULL;
+
+    return handle;
+}
+
+void ResourceManager::deleteBuffer(GLuint buffer)
+{
+    BufferMap::iterator bufferObject = mBufferMap.find(buffer);
+
+    if (bufferObject != mBufferMap.end())
+    {
+        mBufferHandleAllocator.release(bufferObject->first);
+        if (bufferObject->second) bufferObject->second->release();
+        mBufferMap.erase(bufferObject);
+    }
+}
+
+void ResourceManager::deleteShader(GLuint shader)
+{
+    ShaderMap::iterator shaderObject = mShaderMap.find(shader);
+
+    if (shaderObject != mShaderMap.end())
+    {
+        if (shaderObject->second->getRefCount() == 0)
+        {
+            mProgramShaderHandleAllocator.release(shaderObject->first);
+            delete shaderObject->second;
+            mShaderMap.erase(shaderObject);
+        }
+        else
+        {
+            shaderObject->second->flagForDeletion();
+        }
+    }
+}
+
+void ResourceManager::deleteProgram(GLuint program)
+{
+    ProgramMap::iterator programObject = mProgramMap.find(program);
+
+    if (programObject != mProgramMap.end())
+    {
+        if (programObject->second->getRefCount() == 0)
+        {
+            mProgramShaderHandleAllocator.release(programObject->first);
+            delete programObject->second;
+            mProgramMap.erase(programObject);
+        }
+        else
+        { 
+            programObject->second->flagForDeletion();
+        }
+    }
+}
+
+void ResourceManager::deleteTexture(GLuint texture)
+{
+    TextureMap::iterator textureObject = mTextureMap.find(texture);
+
+    if (textureObject != mTextureMap.end())
+    {
+        mTextureHandleAllocator.release(textureObject->first);
+        if (textureObject->second) textureObject->second->release();
+        mTextureMap.erase(textureObject);
+    }
+}
+
+void ResourceManager::deleteRenderbuffer(GLuint renderbuffer)
+{
+    RenderbufferMap::iterator renderbufferObject = mRenderbufferMap.find(renderbuffer);
+
+    if (renderbufferObject != mRenderbufferMap.end())
+    {
+        mRenderbufferHandleAllocator.release(renderbufferObject->first);
+        if (renderbufferObject->second) renderbufferObject->second->release();
+        mRenderbufferMap.erase(renderbufferObject);
+    }
+}
+
+Buffer *ResourceManager::getBuffer(unsigned int handle)
+{
+    BufferMap::iterator buffer = mBufferMap.find(handle);
+
+    if (buffer == mBufferMap.end())
+    {
+        return NULL;
+    }
+    else
+    {
+        return buffer->second;
+    }
+}
+
+Shader *ResourceManager::getShader(unsigned int handle)
+{
+    ShaderMap::iterator shader = mShaderMap.find(handle);
+
+    if (shader == mShaderMap.end())
+    {
+        return NULL;
+    }
+    else
+    {
+        return shader->second;
+    }
+}
+
+Texture *ResourceManager::getTexture(unsigned int handle)
+{
+    if (handle == 0) return NULL;
+
+    TextureMap::iterator texture = mTextureMap.find(handle);
+
+    if (texture == mTextureMap.end())
+    {
+        return NULL;
+    }
+    else
+    {
+        return texture->second;
+    }
+}
+
+Program *ResourceManager::getProgram(unsigned int handle)
+{
+    ProgramMap::iterator program = mProgramMap.find(handle);
+
+    if (program == mProgramMap.end())
+    {
+        return NULL;
+    }
+    else
+    {
+        return program->second;
+    }
+}
+
+Renderbuffer *ResourceManager::getRenderbuffer(unsigned int handle)
+{
+    RenderbufferMap::iterator renderbuffer = mRenderbufferMap.find(handle);
+
+    if (renderbuffer == mRenderbufferMap.end())
+    {
+        return NULL;
+    }
+    else
+    {
+        return renderbuffer->second;
+    }
+}
+
+void ResourceManager::setRenderbuffer(GLuint handle, Renderbuffer *buffer)
+{
+    mRenderbufferMap[handle] = buffer;
+}
+
+void ResourceManager::checkBufferAllocation(unsigned int buffer)
+{
+    if (buffer != 0 && !getBuffer(buffer))
+    {
+        Buffer *bufferObject = new Buffer(buffer);
+        mBufferMap[buffer] = bufferObject;
+        bufferObject->addRef();
+    }
+}
+
+void ResourceManager::checkTextureAllocation(GLuint texture, TextureType type)
+{
+    if (!getTexture(texture) && texture != 0)
+    {
+        Texture *textureObject;
+
+        if (type == TEXTURE_2D)
+        {
+            textureObject = new Texture2D(texture);
+        }
+        else if (type == TEXTURE_CUBE)
+        {
+            textureObject = new TextureCubeMap(texture);
+        }
+        else
+        {
+            UNREACHABLE();
+            return;
+        }
+
+        mTextureMap[texture] = textureObject;
+        textureObject->addRef();
+    }
+}
+
+void ResourceManager::checkRenderbufferAllocation(GLuint renderbuffer)
+{
+    if (renderbuffer != 0 && !getRenderbuffer(renderbuffer))
+    {
+        Renderbuffer *renderbufferObject = new Renderbuffer(renderbuffer, new Colorbuffer(0, 0, GL_RGBA4, 0));
+        mRenderbufferMap[renderbuffer] = renderbufferObject;
+        renderbufferObject->addRef();
+    }
+}
+
+}
diff --git a/src/3rdparty/angle/src/libGLESv2/ResourceManager.h b/src/3rdparty/angle/src/libGLESv2/ResourceManager.h
new file mode 100644 (file)
index 0000000..ae4f1b0
--- /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.
+//
+
+// ResourceManager.h : Defines the ResourceManager class, which tracks objects
+// shared by multiple GL contexts.
+
+#ifndef LIBGLESV2_RESOURCEMANAGER_H_
+#define LIBGLESV2_RESOURCEMANAGER_H_
+
+#define GL_APICALL
+#include <GLES2/gl2.h>
+
+#ifdef _MSC_VER
+#include <hash_map>
+#else
+#include <unordered_map>
+#endif
+
+#include "common/angleutils.h"
+#include "libGLESv2/HandleAllocator.h"
+
+namespace gl
+{
+class Buffer;
+class Shader;
+class Program;
+class Texture;
+class Renderbuffer;
+
+enum TextureType
+{
+    TEXTURE_2D,
+    TEXTURE_CUBE,
+
+    TEXTURE_TYPE_COUNT,
+    TEXTURE_UNKNOWN
+};
+
+enum SamplerType
+{
+    SAMPLER_PIXEL,
+    SAMPLER_VERTEX
+};
+
+class ResourceManager
+{
+  public:
+    ResourceManager();
+    ~ResourceManager();
+
+    void addRef();
+    void release();
+
+    GLuint createBuffer();
+    GLuint createShader(GLenum type);
+    GLuint createProgram();
+    GLuint createTexture();
+    GLuint createRenderbuffer();
+
+    void deleteBuffer(GLuint buffer);
+    void deleteShader(GLuint shader);
+    void deleteProgram(GLuint program);
+    void deleteTexture(GLuint texture);
+    void deleteRenderbuffer(GLuint renderbuffer);
+
+    Buffer *getBuffer(GLuint handle);
+    Shader *getShader(GLuint handle);
+    Program *getProgram(GLuint handle);
+    Texture *getTexture(GLuint handle);
+    Renderbuffer *getRenderbuffer(GLuint handle);
+    
+    void setRenderbuffer(GLuint handle, Renderbuffer *renderbuffer);
+
+    void checkBufferAllocation(unsigned int buffer);
+    void checkTextureAllocation(GLuint texture, TextureType type);
+    void checkRenderbufferAllocation(GLuint renderbuffer);
+
+  private:
+    DISALLOW_COPY_AND_ASSIGN(ResourceManager);
+
+    std::size_t mRefCount;
+
+#ifndef HASH_MAP
+# ifdef _MSC_VER
+#  define HASH_MAP stdext::hash_map
+# else
+#  define HASH_MAP std::unordered_map
+# endif
+#endif
+
+    typedef HASH_MAP<GLuint, Buffer*> BufferMap;
+    BufferMap mBufferMap;
+    HandleAllocator mBufferHandleAllocator;
+
+    typedef HASH_MAP<GLuint, Shader*> ShaderMap;
+    ShaderMap mShaderMap;
+
+    typedef HASH_MAP<GLuint, Program*> ProgramMap;
+    ProgramMap mProgramMap;
+    HandleAllocator mProgramShaderHandleAllocator;
+
+    typedef HASH_MAP<GLuint, Texture*> TextureMap;
+    TextureMap mTextureMap;
+    HandleAllocator mTextureHandleAllocator;
+
+    typedef HASH_MAP<GLuint, Renderbuffer*> RenderbufferMap;
+    RenderbufferMap mRenderbufferMap;
+    HandleAllocator mRenderbufferHandleAllocator;
+};
+
+}
+
+#endif // LIBGLESV2_RESOURCEMANAGER_H_
diff --git a/src/3rdparty/angle/src/libGLESv2/Shader.cpp b/src/3rdparty/angle/src/libGLESv2/Shader.cpp
new file mode 100644 (file)
index 0000000..1087f11
--- /dev/null
@@ -0,0 +1,584 @@
+//
+// 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.
+//
+
+// Shader.cpp: Implements the gl::Shader class and its  derived classes
+// VertexShader and FragmentShader. Implements GL shader objects and related
+// functionality. [OpenGL ES 2.0.24] section 2.10 page 24 and section 3.8 page 84.
+
+#include "libGLESv2/Shader.h"
+
+#include <string>
+
+#include "GLSLANG/ShaderLang.h"
+#include "libGLESv2/main.h"
+#include "libGLESv2/utilities.h"
+
+namespace gl
+{
+void *Shader::mFragmentCompiler = NULL;
+void *Shader::mVertexCompiler = NULL;
+
+Shader::Shader(ResourceManager *manager, GLuint handle) : mHandle(handle), mResourceManager(manager)
+{
+    mSource = NULL;
+    mHlsl = NULL;
+    mInfoLog = NULL;
+
+    uncompile();
+    initializeCompiler();
+
+    mRefCount = 0;
+    mDeleteStatus = false;
+}
+
+Shader::~Shader()
+{
+    delete[] mSource;
+    delete[] mHlsl;
+    delete[] mInfoLog;
+}
+
+GLuint Shader::getHandle() const
+{
+    return mHandle;
+}
+
+void Shader::setSource(GLsizei count, const char **string, const GLint *length)
+{
+    delete[] mSource;
+    int totalLength = 0;
+
+    for (int i = 0; i < count; i++)
+    {
+        if (length && length[i] >= 0)
+        {
+            totalLength += length[i];
+        }
+        else
+        {
+            totalLength += (int)strlen(string[i]);
+        }
+    }
+
+    mSource = new char[totalLength + 1];
+    char *code = mSource;
+
+    for (int i = 0; i < count; i++)
+    {
+        int stringLength;
+
+        if (length && length[i] >= 0)
+        {
+            stringLength = length[i];
+        }
+        else
+        {
+            stringLength = (int)strlen(string[i]);
+        }
+
+        strncpy(code, string[i], stringLength);
+        code += stringLength;
+    }
+
+    mSource[totalLength] = '\0';
+}
+
+int Shader::getInfoLogLength() const
+{
+    if (!mInfoLog)
+    {
+        return 0;
+    }
+    else
+    {
+       return strlen(mInfoLog) + 1;
+    }
+}
+
+void Shader::getInfoLog(GLsizei bufSize, GLsizei *length, char *infoLog)
+{
+    int index = 0;
+
+    if (bufSize > 0)
+    {
+        if (mInfoLog)
+        {
+            index = std::min(bufSize - 1, (int)strlen(mInfoLog));
+            memcpy(infoLog, mInfoLog, index);
+        }
+
+        infoLog[index] = '\0';
+    }
+
+    if (length)
+    {
+        *length = index;
+    }
+}
+
+int Shader::getSourceLength() const
+{
+    if (!mSource)
+    {
+        return 0;
+    }
+    else
+    {
+       return strlen(mSource) + 1;
+    }
+}
+
+int Shader::getTranslatedSourceLength() const
+{
+    if (!mHlsl)
+    {
+        return 0;
+    }
+    else
+    {
+       return strlen(mHlsl) + 1;
+    }
+}
+
+void Shader::getSourceImpl(char *source, GLsizei bufSize, GLsizei *length, char *buffer)
+{
+    int index = 0;
+
+    if (bufSize > 0)
+    {
+        if (source)
+        {
+            index = std::min(bufSize - 1, (int)strlen(source));
+            memcpy(buffer, source, index);
+        }
+
+        buffer[index] = '\0';
+    }
+
+    if (length)
+    {
+        *length = index;
+    }
+}
+
+void Shader::getSource(GLsizei bufSize, GLsizei *length, char *buffer)
+{
+    getSourceImpl(mSource, bufSize, length, buffer);
+}
+
+void Shader::getTranslatedSource(GLsizei bufSize, GLsizei *length, char *buffer)
+{
+    getSourceImpl(mHlsl, bufSize, length, buffer);
+}
+
+bool Shader::isCompiled()
+{
+    return mHlsl != NULL;
+}
+
+const char *Shader::getHLSL()
+{
+    return mHlsl;
+}
+
+void Shader::addRef()
+{
+    mRefCount++;
+}
+
+void Shader::release()
+{
+    mRefCount--;
+
+    if (mRefCount == 0 && mDeleteStatus)
+    {
+        mResourceManager->deleteShader(mHandle);
+    }
+}
+
+unsigned int Shader::getRefCount() const
+{
+    return mRefCount;
+}
+
+bool Shader::isFlaggedForDeletion() const
+{
+    return mDeleteStatus;
+}
+
+void Shader::flagForDeletion()
+{
+    mDeleteStatus = true;
+}
+
+// Perform a one-time initialization of the shader compiler (or after being destructed by releaseCompiler)
+void Shader::initializeCompiler()
+{
+    if (!mFragmentCompiler)
+    {
+        int result = ShInitialize();
+
+        if (result)
+        {
+            ShBuiltInResources resources;
+            ShInitBuiltInResources(&resources);
+            Context *context = getContext();
+
+            resources.MaxVertexAttribs = MAX_VERTEX_ATTRIBS;
+            resources.MaxVertexUniformVectors = MAX_VERTEX_UNIFORM_VECTORS;
+            resources.MaxVaryingVectors = context->getMaximumVaryingVectors();
+            resources.MaxVertexTextureImageUnits = context->getMaximumVertexTextureImageUnits();
+            resources.MaxCombinedTextureImageUnits = context->getMaximumCombinedTextureImageUnits();
+            resources.MaxTextureImageUnits = MAX_TEXTURE_IMAGE_UNITS;
+            resources.MaxFragmentUniformVectors = context->getMaximumFragmentUniformVectors();
+            resources.MaxDrawBuffers = MAX_DRAW_BUFFERS;
+            resources.OES_standard_derivatives = 1;
+            // resources.OES_EGL_image_external = getDisplay()->isD3d9ExDevice() ? 1 : 0; // TODO: commented out until the extension is actually supported.
+
+            mFragmentCompiler = ShConstructCompiler(SH_FRAGMENT_SHADER, SH_GLES2_SPEC, SH_HLSL_OUTPUT, &resources);
+            mVertexCompiler = ShConstructCompiler(SH_VERTEX_SHADER, SH_GLES2_SPEC, SH_HLSL_OUTPUT, &resources);
+        }
+    }
+}
+
+void Shader::releaseCompiler()
+{
+    ShDestruct(mFragmentCompiler);
+    ShDestruct(mVertexCompiler);
+
+    mFragmentCompiler = NULL;
+    mVertexCompiler = NULL;
+
+    ShFinalize();
+}
+
+void Shader::parseVaryings()
+{
+    if (mHlsl)
+    {
+        const char *input = strstr(mHlsl, "// Varyings") + 12;
+
+        while(true)
+        {
+            char varyingType[256];
+            char varyingName[256];
+
+            int matches = sscanf(input, "static %255s %255s", varyingType, varyingName);
+
+            if (matches != 2)
+            {
+                break;
+            }
+
+            char *array = strstr(varyingName, "[");
+            int size = 1;
+
+            if (array)
+            {
+                size = atoi(array + 1);
+                *array = '\0';
+            }
+
+            mVaryings.push_back(Varying(parseType(varyingType), varyingName, size, array != NULL));
+
+            input = strstr(input, ";") + 2;
+        }
+
+        mUsesFragCoord = strstr(mHlsl, "GL_USES_FRAG_COORD") != NULL;
+        mUsesFrontFacing = strstr(mHlsl, "GL_USES_FRONT_FACING") != NULL;
+        mUsesPointSize = strstr(mHlsl, "GL_USES_POINT_SIZE") != NULL;
+        mUsesPointCoord = strstr(mHlsl, "GL_USES_POINT_COORD") != NULL;
+    }
+}
+
+// initialize/clean up previous state
+void Shader::uncompile()
+{
+    // set by compileToHLSL
+    delete[] mHlsl;
+    mHlsl = NULL;
+    delete[] mInfoLog;
+    mInfoLog = NULL;
+
+    // set by parseVaryings
+    mVaryings.clear();
+
+    mUsesFragCoord = false;
+    mUsesFrontFacing = false;
+    mUsesPointSize = false;
+    mUsesPointCoord = false;
+}
+
+void Shader::compileToHLSL(void *compiler)
+{
+    // ensure we don't pass a NULL source to the compiler
+    char *source = "\0";
+    if (mSource)
+    {
+        source = mSource;
+    }
+
+    // ensure the compiler is loaded
+    initializeCompiler();
+
+    int compileOptions = SH_OBJECT_CODE;
+    std::string sourcePath;
+    if (perfActive())
+    {
+        sourcePath = getTempPath();
+        writeFile(sourcePath.c_str(), source, strlen(source));
+        compileOptions |= SH_LINE_DIRECTIVES;
+    }
+
+    int result;
+    if (sourcePath.empty())
+    {
+        result = ShCompile(compiler, &source, 1, compileOptions);
+    }
+    else
+    {
+        const char* sourceStrings[2] =
+        {
+            sourcePath.c_str(),
+            source
+        };
+
+        result = ShCompile(compiler, sourceStrings, 2, compileOptions | SH_SOURCE_PATH);
+    }
+
+    if (result)
+    {
+        int objCodeLen = 0;
+        ShGetInfo(compiler, SH_OBJECT_CODE_LENGTH, &objCodeLen);
+        mHlsl = new char[objCodeLen];
+        ShGetObjectCode(compiler, mHlsl);
+    }
+    else
+    {
+        int infoLogLen = 0;
+        ShGetInfo(compiler, SH_INFO_LOG_LENGTH, &infoLogLen);
+        mInfoLog = new char[infoLogLen];
+        ShGetInfoLog(compiler, mInfoLog);
+
+        TRACE("\n%s", mInfoLog);
+    }
+}
+
+GLenum Shader::parseType(const std::string &type)
+{
+    if (type == "float")
+    {
+        return GL_FLOAT;
+    }
+    else if (type == "float2")
+    {
+        return GL_FLOAT_VEC2;
+    }
+    else if (type == "float3")
+    {
+        return GL_FLOAT_VEC3;
+    }
+    else if (type == "float4")
+    {
+        return GL_FLOAT_VEC4;
+    }
+    else if (type == "float2x2")
+    {
+        return GL_FLOAT_MAT2;
+    }
+    else if (type == "float3x3")
+    {
+        return GL_FLOAT_MAT3;
+    }
+    else if (type == "float4x4")
+    {
+        return GL_FLOAT_MAT4;
+    }
+    else UNREACHABLE();
+
+    return GL_NONE;
+}
+
+// true if varying x has a higher priority in packing than y
+bool Shader::compareVarying(const Varying &x, const Varying &y)
+{
+    if(x.type == y.type)
+    {
+        return x.size > y.size;
+    }
+
+    switch (x.type)
+    {
+      case GL_FLOAT_MAT4: return true;
+      case GL_FLOAT_MAT2:
+        switch(y.type)
+        {
+          case GL_FLOAT_MAT4: return false;
+          case GL_FLOAT_MAT2: return true;
+          case GL_FLOAT_VEC4: return true;
+          case GL_FLOAT_MAT3: return true;
+          case GL_FLOAT_VEC3: return true;
+          case GL_FLOAT_VEC2: return true;
+          case GL_FLOAT:      return true;
+          default: UNREACHABLE();
+        }
+        break;
+      case GL_FLOAT_VEC4:
+        switch(y.type)
+        {
+          case GL_FLOAT_MAT4: return false;
+          case GL_FLOAT_MAT2: return false;
+          case GL_FLOAT_VEC4: return true;
+          case GL_FLOAT_MAT3: return true;
+          case GL_FLOAT_VEC3: return true;
+          case GL_FLOAT_VEC2: return true;
+          case GL_FLOAT:      return true;
+          default: UNREACHABLE();
+        }
+        break;
+      case GL_FLOAT_MAT3:
+        switch(y.type)
+        {
+          case GL_FLOAT_MAT4: return false;
+          case GL_FLOAT_MAT2: return false;
+          case GL_FLOAT_VEC4: return false;
+          case GL_FLOAT_MAT3: return true;
+          case GL_FLOAT_VEC3: return true;
+          case GL_FLOAT_VEC2: return true;
+          case GL_FLOAT:      return true;
+          default: UNREACHABLE();
+        }
+        break;
+      case GL_FLOAT_VEC3:
+        switch(y.type)
+        {
+          case GL_FLOAT_MAT4: return false;
+          case GL_FLOAT_MAT2: return false;
+          case GL_FLOAT_VEC4: return false;
+          case GL_FLOAT_MAT3: return false;
+          case GL_FLOAT_VEC3: return true;
+          case GL_FLOAT_VEC2: return true;
+          case GL_FLOAT:      return true;
+          default: UNREACHABLE();
+        }
+        break;
+      case GL_FLOAT_VEC2:
+        switch(y.type)
+        {
+          case GL_FLOAT_MAT4: return false;
+          case GL_FLOAT_MAT2: return false;
+          case GL_FLOAT_VEC4: return false;
+          case GL_FLOAT_MAT3: return false;
+          case GL_FLOAT_VEC3: return false;
+          case GL_FLOAT_VEC2: return true;
+          case GL_FLOAT:      return true;
+          default: UNREACHABLE();
+        }
+        break;
+      case GL_FLOAT: return false;
+      default: UNREACHABLE();
+    }
+
+    return false;
+}
+
+VertexShader::VertexShader(ResourceManager *manager, GLuint handle) : Shader(manager, handle)
+{
+}
+
+VertexShader::~VertexShader()
+{
+}
+
+GLenum VertexShader::getType()
+{
+    return GL_VERTEX_SHADER;
+}
+
+void VertexShader::uncompile()
+{
+    Shader::uncompile();
+
+    // set by ParseAttributes
+    mAttributes.clear();
+};
+
+void VertexShader::compile()
+{
+    uncompile();
+
+    compileToHLSL(mVertexCompiler);
+    parseAttributes();
+    parseVaryings();
+}
+
+int VertexShader::getSemanticIndex(const std::string &attributeName)
+{
+    if (!attributeName.empty())
+    {
+        int semanticIndex = 0;
+        for (AttributeArray::iterator attribute = mAttributes.begin(); attribute != mAttributes.end(); attribute++)
+        {
+            if (attribute->name == attributeName)
+            {
+                return semanticIndex;
+            }
+
+            semanticIndex += VariableRowCount(attribute->type);
+        }
+    }
+
+    return -1;
+}
+
+void VertexShader::parseAttributes()
+{
+    const char *hlsl = getHLSL();
+    if (hlsl)
+    {
+        const char *input = strstr(hlsl, "// Attributes") + 14;
+
+        while(true)
+        {
+            char attributeType[256];
+            char attributeName[256];
+
+            int matches = sscanf(input, "static %255s _%255s", attributeType, attributeName);
+
+            if (matches != 2)
+            {
+                break;
+            }
+
+            mAttributes.push_back(Attribute(parseType(attributeType), attributeName));
+
+            input = strstr(input, ";") + 2;
+        }
+    }
+}
+
+FragmentShader::FragmentShader(ResourceManager *manager, GLuint handle) : Shader(manager, handle)
+{
+}
+
+FragmentShader::~FragmentShader()
+{
+}
+
+GLenum FragmentShader::getType()
+{
+    return GL_FRAGMENT_SHADER;
+}
+
+void FragmentShader::compile()
+{
+    uncompile();
+
+    compileToHLSL(mFragmentCompiler);
+    parseVaryings();
+    mVaryings.sort(compareVarying);
+}
+}
diff --git a/src/3rdparty/angle/src/libGLESv2/Shader.h b/src/3rdparty/angle/src/libGLESv2/Shader.h
new file mode 100644 (file)
index 0000000..b73fc28
--- /dev/null
@@ -0,0 +1,166 @@
+//
+// 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.
+//
+
+// Shader.h: Defines the abstract gl::Shader class and its concrete derived
+// classes VertexShader and FragmentShader. Implements GL shader objects and
+// related functionality. [OpenGL ES 2.0.24] section 2.10 page 24 and section
+// 3.8 page 84.
+
+#ifndef LIBGLESV2_SHADER_H_
+#define LIBGLESV2_SHADER_H_
+
+#define GL_APICALL
+#include <GLES2/gl2.h>
+#include <string>
+#include <list>
+#include <vector>
+
+#include "libGLESv2/ResourceManager.h"
+
+namespace gl
+{
+struct Varying
+{
+    Varying(GLenum type, const std::string &name, int size, bool array)
+        : type(type), name(name), size(size), array(array), reg(-1), col(-1)
+    {
+    }
+
+    GLenum type;
+    std::string name;
+    int size;   // Number of 'type' elements
+    bool array;
+
+    int reg;    // First varying register, assigned during link
+    int col;    // First register element, assigned during link
+};
+
+typedef std::list<Varying> VaryingList;
+
+class Shader
+{
+    friend class ProgramBinary;
+
+  public:
+    Shader(ResourceManager *manager, GLuint handle);
+
+    virtual ~Shader();
+
+    virtual GLenum getType() = 0;
+    GLuint getHandle() const;
+
+    void deleteSource();
+    void setSource(GLsizei count, const char **string, const GLint *length);
+    int getInfoLogLength() const;
+    void getInfoLog(GLsizei bufSize, GLsizei *length, char *infoLog);
+    int getSourceLength() const;
+    void getSource(GLsizei bufSize, GLsizei *length, char *buffer);
+    int getTranslatedSourceLength() const;
+    void getTranslatedSource(GLsizei bufSize, GLsizei *length, char *buffer);
+
+    virtual void compile() = 0;
+    virtual void uncompile();
+    bool isCompiled();
+    const char *getHLSL();
+
+    void addRef();
+    void release();
+    unsigned int getRefCount() const;
+    bool isFlaggedForDeletion() const;
+    void flagForDeletion();
+
+    static void releaseCompiler();
+
+  protected:
+    void parseVaryings();
+
+    void compileToHLSL(void *compiler);
+
+    void getSourceImpl(char *source, GLsizei bufSize, GLsizei *length, char *buffer);
+
+    static GLenum parseType(const std::string &type);
+    static bool compareVarying(const Varying &x, const Varying &y);
+
+    VaryingList mVaryings;
+
+    bool mUsesFragCoord;
+    bool mUsesFrontFacing;
+    bool mUsesPointSize;
+    bool mUsesPointCoord;
+
+    static void *mFragmentCompiler;
+    static void *mVertexCompiler;
+
+  private:
+    DISALLOW_COPY_AND_ASSIGN(Shader);
+
+    void initializeCompiler();
+
+    const GLuint mHandle;
+    unsigned int mRefCount;     // Number of program objects this shader is attached to
+    bool mDeleteStatus;         // Flag to indicate that the shader can be deleted when no longer in use
+
+    char *mSource;
+    char *mHlsl;
+    char *mInfoLog;
+
+    ResourceManager *mResourceManager;
+};
+
+struct Attribute
+{
+    Attribute() : type(GL_NONE), name("")
+    {
+    }
+
+    Attribute(GLenum type, const std::string &name) : type(type), name(name)
+    {
+    }
+
+    GLenum type;
+    std::string name;
+};
+
+typedef std::vector<Attribute> AttributeArray;
+
+class VertexShader : public Shader
+{
+    friend class ProgramBinary;
+
+  public:
+    VertexShader(ResourceManager *manager, GLuint handle);
+
+    ~VertexShader();
+
+    virtual GLenum getType();
+    virtual void compile();
+    virtual void uncompile();
+    int getSemanticIndex(const std::string &attributeName);
+
+  private:
+    DISALLOW_COPY_AND_ASSIGN(VertexShader);
+
+    void parseAttributes();
+
+    AttributeArray mAttributes;
+};
+
+class FragmentShader : public Shader
+{
+  public:
+    FragmentShader(ResourceManager *manager, GLuint handle);
+
+    ~FragmentShader();
+
+    virtual GLenum getType();
+    virtual void compile();
+
+  private:
+    DISALLOW_COPY_AND_ASSIGN(FragmentShader);
+};
+}
+
+#endif   // LIBGLESV2_SHADER_H_
diff --git a/src/3rdparty/angle/src/libGLESv2/Texture.cpp b/src/3rdparty/angle/src/libGLESv2/Texture.cpp
new file mode 100644 (file)
index 0000000..af430bf
--- /dev/null
@@ -0,0 +1,3118 @@
+//
+// 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.
+//
+
+// Texture.cpp: Implements the gl::Texture class and its derived classes
+// Texture2D and TextureCubeMap. Implements GL texture objects and related
+// functionality. [OpenGL ES 2.0.24] section 3.7 page 63.
+
+#include "libGLESv2/Texture.h"
+
+#include <algorithm>
+
+#include "common/debug.h"
+
+#include "libEGL/Display.h"
+
+#include "libGLESv2/main.h"
+#include "libGLESv2/mathutil.h"
+#include "libGLESv2/utilities.h"
+#include "libGLESv2/Blit.h"
+#include "libGLESv2/Framebuffer.h"
+
+namespace gl
+{
+unsigned int TextureStorage::mCurrentTextureSerial = 1;
+
+static D3DFORMAT ConvertTextureInternalFormat(GLint internalformat)
+{
+    switch (internalformat)
+    {
+      case GL_DEPTH_COMPONENT16:
+      case GL_DEPTH_COMPONENT32_OES:
+      case GL_DEPTH24_STENCIL8_OES:
+        return D3DFMT_INTZ;
+      case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
+      case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
+        return D3DFMT_DXT1;
+      case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
+        return D3DFMT_DXT3;
+      case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
+        return D3DFMT_DXT5;
+      case GL_RGBA32F_EXT:
+      case GL_RGB32F_EXT:
+      case GL_ALPHA32F_EXT:
+      case GL_LUMINANCE32F_EXT:
+      case GL_LUMINANCE_ALPHA32F_EXT:
+        return D3DFMT_A32B32G32R32F;
+      case GL_RGBA16F_EXT:
+      case GL_RGB16F_EXT:
+      case GL_ALPHA16F_EXT:
+      case GL_LUMINANCE16F_EXT:
+      case GL_LUMINANCE_ALPHA16F_EXT:
+        return D3DFMT_A16B16G16R16F;
+      case GL_LUMINANCE8_EXT:
+        if (getContext()->supportsLuminanceTextures())
+        {
+            return D3DFMT_L8;
+        }
+        break;
+      case GL_LUMINANCE8_ALPHA8_EXT:
+        if (getContext()->supportsLuminanceAlphaTextures())
+        {
+            return D3DFMT_A8L8;
+        }
+        break;
+      case GL_RGB8_OES:
+      case GL_RGB565:
+        return D3DFMT_X8R8G8B8;
+    }
+
+    return D3DFMT_A8R8G8B8;
+}
+
+static bool IsTextureFormatRenderable(D3DFORMAT format)
+{
+    if (format == D3DFMT_INTZ)
+    {
+        return true;
+    }
+    switch(format)
+    {
+      case D3DFMT_L8:
+      case D3DFMT_A8L8:
+      case D3DFMT_DXT1:
+      case D3DFMT_DXT3:
+      case D3DFMT_DXT5:
+        return false;
+      case D3DFMT_A8R8G8B8:
+      case D3DFMT_X8R8G8B8:
+      case D3DFMT_A16B16G16R16F:
+      case D3DFMT_A32B32G32R32F:
+        return true;
+      default:
+        UNREACHABLE();
+    }
+
+    return false;
+}
+
+static inline DWORD GetTextureUsage(D3DFORMAT d3dfmt, GLenum glusage, bool forceRenderable)
+{
+    DWORD d3dusage = 0;
+
+    if (d3dfmt == D3DFMT_INTZ)
+    {
+        d3dusage |= D3DUSAGE_DEPTHSTENCIL;
+    }
+    else if(forceRenderable || (IsTextureFormatRenderable(d3dfmt) && (glusage == GL_FRAMEBUFFER_ATTACHMENT_ANGLE)))
+    {
+        d3dusage |= D3DUSAGE_RENDERTARGET;
+    }
+    return d3dusage;
+}
+
+static void MakeValidSize(bool isImage, bool isCompressed, GLsizei *requestWidth, GLsizei *requestHeight, int *levelOffset)
+{
+    int upsampleCount = 0;
+
+    if (isCompressed)
+    {
+        // Don't expand the size of full textures that are at least 4x4
+        // already.
+        if (isImage || *requestWidth < 4 || *requestHeight < 4)
+        {
+            while (*requestWidth % 4 != 0 || *requestHeight % 4 != 0)
+            {
+                *requestWidth <<= 1;
+                *requestHeight <<= 1;
+                upsampleCount++;
+            }
+        }
+    }
+    *levelOffset = upsampleCount;
+}
+
+static void CopyLockableSurfaces(IDirect3DSurface9 *dest, IDirect3DSurface9 *source)
+{
+    D3DLOCKED_RECT sourceLock = {0};
+    D3DLOCKED_RECT destLock = {0};
+    
+    source->LockRect(&sourceLock, NULL, 0);
+    dest->LockRect(&destLock, NULL, 0);
+    
+    if (sourceLock.pBits && destLock.pBits)
+    {
+        D3DSURFACE_DESC desc;
+        source->GetDesc(&desc);
+
+        int rows = dx::IsCompressedFormat(desc.Format) ? desc.Height / 4 : desc.Height;
+        int bytes = dx::ComputeRowSize(desc.Format, desc.Width);
+        ASSERT(bytes <= sourceLock.Pitch && bytes <= destLock.Pitch);
+
+        for(int i = 0; i < rows; i++)
+        {
+            memcpy((char*)destLock.pBits + destLock.Pitch * i, (char*)sourceLock.pBits + sourceLock.Pitch * i, bytes);
+        }
+
+        source->UnlockRect();
+        dest->UnlockRect();
+    }
+    else UNREACHABLE();
+}
+
+Image::Image()
+{
+    mWidth = 0; 
+    mHeight = 0;
+    mInternalFormat = GL_NONE;
+
+    mSurface = NULL;
+
+    mDirty = false;
+
+    mD3DPool = D3DPOOL_SYSTEMMEM;
+    mD3DFormat = D3DFMT_UNKNOWN;
+}
+
+Image::~Image()
+{
+    if (mSurface)
+    {
+        mSurface->Release();
+    }
+}
+
+bool Image::redefine(GLint internalformat, GLsizei width, GLsizei height, bool forceRelease)
+{
+    if (mWidth != width ||
+        mHeight != height ||
+        mInternalFormat != internalformat ||
+        forceRelease)
+    {
+        mWidth = width;
+        mHeight = height;
+        mInternalFormat = internalformat;
+        // compute the d3d format that will be used
+        mD3DFormat = ConvertTextureInternalFormat(internalformat);
+
+        if (mSurface)
+        {
+            mSurface->Release();
+            mSurface = NULL;
+        }
+
+        return true;
+    }
+
+    return false;
+}
+
+void Image::createSurface()
+{
+    if(mSurface)
+    {
+        return;
+    }
+
+    IDirect3DTexture9 *newTexture = NULL;
+    IDirect3DSurface9 *newSurface = NULL;
+    const D3DPOOL poolToUse = D3DPOOL_SYSTEMMEM;
+    const D3DFORMAT d3dFormat = getD3DFormat();
+    ASSERT(d3dFormat != D3DFMT_INTZ); // We should never get here for depth textures
+
+    if (mWidth != 0 && mHeight != 0)
+    {
+        int levelToFetch = 0;
+        GLsizei requestWidth = mWidth;
+        GLsizei requestHeight = mHeight;
+        MakeValidSize(true, IsCompressed(mInternalFormat), &requestWidth, &requestHeight, &levelToFetch);
+
+        HRESULT result = getDevice()->CreateTexture(requestWidth, requestHeight, levelToFetch + 1, NULL, d3dFormat,
+                                                    poolToUse, &newTexture, NULL);
+
+        if (FAILED(result))
+        {
+            ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
+            ERR("Creating image surface failed.");
+            return error(GL_OUT_OF_MEMORY);
+        }
+
+        newTexture->GetSurfaceLevel(levelToFetch, &newSurface);
+        newTexture->Release();
+    }
+
+    mSurface = newSurface;
+    mDirty = false;
+    mD3DPool = poolToUse;
+}
+
+HRESULT Image::lock(D3DLOCKED_RECT *lockedRect, const RECT *rect)
+{
+    createSurface();
+
+    HRESULT result = D3DERR_INVALIDCALL;
+
+    if (mSurface)
+    {
+        result = mSurface->LockRect(lockedRect, rect, 0);
+        ASSERT(SUCCEEDED(result));
+
+        mDirty = true;
+    }
+
+    return result;
+}
+
+void Image::unlock()
+{
+    if (mSurface)
+    {
+        HRESULT result = mSurface->UnlockRect();
+        ASSERT(SUCCEEDED(result));
+    }
+}
+
+bool Image::isRenderableFormat() const
+{    
+    return IsTextureFormatRenderable(getD3DFormat());
+}
+
+D3DFORMAT Image::getD3DFormat() const
+{
+    // this should only happen if the image hasn't been redefined first
+    // which would be a bug by the caller
+    ASSERT(mD3DFormat != D3DFMT_UNKNOWN);
+
+    return mD3DFormat;
+}
+
+IDirect3DSurface9 *Image::getSurface()
+{
+    createSurface();
+
+    return mSurface;
+}
+
+void Image::setManagedSurface(IDirect3DSurface9 *surface)
+{
+    D3DSURFACE_DESC desc;
+    surface->GetDesc(&desc);
+    ASSERT(desc.Pool == D3DPOOL_MANAGED);
+
+    if ((GLsizei)desc.Width == mWidth && (GLsizei)desc.Height == mHeight)
+    {
+        if (mSurface)
+        {
+            CopyLockableSurfaces(surface, mSurface);
+            mSurface->Release();
+        }
+
+        mSurface = surface;
+        mD3DPool = desc.Pool;
+    }
+}
+
+void Image::updateSurface(IDirect3DSurface9 *destSurface, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height)
+{
+    IDirect3DSurface9 *sourceSurface = getSurface();
+
+    if (sourceSurface && sourceSurface != destSurface)
+    {
+        RECT rect;
+        rect.left = xoffset;
+        rect.top = yoffset;
+        rect.right = xoffset + width;
+        rect.bottom = yoffset + height;
+
+        POINT point = {rect.left, rect.top};
+
+        if (mD3DPool == D3DPOOL_MANAGED)
+        {
+            D3DSURFACE_DESC desc;
+            sourceSurface->GetDesc(&desc);
+
+            IDirect3DSurface9 *surf = 0;
+            HRESULT result = getDevice()->CreateOffscreenPlainSurface(desc.Width, desc.Height, desc.Format, D3DPOOL_SYSTEMMEM, &surf, NULL);
+
+            if (SUCCEEDED(result))
+            {
+                CopyLockableSurfaces(surf, sourceSurface);
+                result = getDevice()->UpdateSurface(surf, &rect, destSurface, &point);
+                ASSERT(SUCCEEDED(result));
+                surf->Release();
+            }
+        }
+        else
+        {
+            // UpdateSurface: source must be SYSTEMMEM, dest must be DEFAULT pools
+            HRESULT result = getDevice()->UpdateSurface(sourceSurface, &rect, destSurface, &point);
+            ASSERT(SUCCEEDED(result));
+        }
+    }
+}
+
+// Store the pixel rectangle designated by xoffset,yoffset,width,height with pixels stored as format/type at input
+// into the target pixel rectangle.
+void Image::loadData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
+                     GLint unpackAlignment, const void *input)
+{
+    RECT lockRect =
+    {
+        xoffset, yoffset,
+        xoffset + width, yoffset + height
+    };
+
+    D3DLOCKED_RECT locked;
+    HRESULT result = lock(&locked, &lockRect);
+    if (FAILED(result))
+    {
+        return;
+    }
+
+
+    GLsizei inputPitch = ComputePitch(width, mInternalFormat, unpackAlignment);
+
+    switch (mInternalFormat)
+    {
+      case GL_ALPHA8_EXT:
+        if (supportsSSE2())
+        {
+            loadAlphaDataSSE2(width, height, inputPitch, input, locked.Pitch, locked.pBits);
+        }
+        else
+        {
+            loadAlphaData(width, height, inputPitch, input, locked.Pitch, locked.pBits);
+        }
+        break;
+      case GL_LUMINANCE8_EXT:
+        loadLuminanceData(width, height, inputPitch, input, locked.Pitch, locked.pBits, getD3DFormat() == D3DFMT_L8);
+        break;
+      case GL_ALPHA32F_EXT:
+        loadAlphaFloatData(width, height, inputPitch, input, locked.Pitch, locked.pBits);
+        break;
+      case GL_LUMINANCE32F_EXT:
+        loadLuminanceFloatData(width, height, inputPitch, input, locked.Pitch, locked.pBits);
+        break;
+      case GL_ALPHA16F_EXT:
+        loadAlphaHalfFloatData(width, height, inputPitch, input, locked.Pitch, locked.pBits);
+        break;
+      case GL_LUMINANCE16F_EXT:
+        loadLuminanceHalfFloatData(width, height, inputPitch, input, locked.Pitch, locked.pBits);
+        break;
+      case GL_LUMINANCE8_ALPHA8_EXT:
+        loadLuminanceAlphaData(width, height, inputPitch, input, locked.Pitch, locked.pBits, getD3DFormat() == D3DFMT_A8L8);
+        break;
+      case GL_LUMINANCE_ALPHA32F_EXT:
+        loadLuminanceAlphaFloatData(width, height, inputPitch, input, locked.Pitch, locked.pBits);
+        break;
+      case GL_LUMINANCE_ALPHA16F_EXT:
+        loadLuminanceAlphaHalfFloatData(width, height, inputPitch, input, locked.Pitch, locked.pBits);
+        break;
+      case GL_RGB8_OES:
+        loadRGBUByteData(width, height, inputPitch, input, locked.Pitch, locked.pBits);
+        break;
+      case GL_RGB565:
+        loadRGB565Data(width, height, inputPitch, input, locked.Pitch, locked.pBits);
+        break;
+      case GL_RGBA8_OES:
+        if (supportsSSE2())
+        {
+            loadRGBAUByteDataSSE2(width, height, inputPitch, input, locked.Pitch, locked.pBits);
+        }
+        else
+        {
+            loadRGBAUByteData(width, height, inputPitch, input, locked.Pitch, locked.pBits);
+        }
+        break;
+      case GL_RGBA4:
+        loadRGBA4444Data(width, height, inputPitch, input, locked.Pitch, locked.pBits);
+        break;
+      case GL_RGB5_A1:
+        loadRGBA5551Data(width, height, inputPitch, input, locked.Pitch, locked.pBits);
+        break;
+      case GL_BGRA8_EXT:
+        loadBGRAData(width, height, inputPitch, input, locked.Pitch, locked.pBits);
+        break;
+      // float textures are converted to RGBA, not BGRA, as they're stored that way in D3D
+      case GL_RGB32F_EXT:
+        loadRGBFloatData(width, height, inputPitch, input, locked.Pitch, locked.pBits);
+        break;
+      case GL_RGB16F_EXT:
+        loadRGBHalfFloatData(width, height, inputPitch, input, locked.Pitch, locked.pBits);
+        break;
+      case GL_RGBA32F_EXT:
+        loadRGBAFloatData(width, height, inputPitch, input, locked.Pitch, locked.pBits);
+        break;
+      case GL_RGBA16F_EXT:
+        loadRGBAHalfFloatData(width, height, inputPitch, input, locked.Pitch, locked.pBits);
+        break;
+      default: UNREACHABLE(); 
+    }
+
+    unlock();
+}
+
+void Image::loadAlphaData(GLsizei width, GLsizei height,
+                          int inputPitch, const void *input, size_t outputPitch, void *output) const
+{
+    const unsigned char *source = NULL;
+    unsigned char *dest = NULL;
+    
+    for (int y = 0; y < height; y++)
+    {
+        source = static_cast<const unsigned char*>(input) + y * inputPitch;
+        dest = static_cast<unsigned char*>(output) + y * outputPitch;
+        for (int x = 0; x < width; x++)
+        {
+            dest[4 * x + 0] = 0;
+            dest[4 * x + 1] = 0;
+            dest[4 * x + 2] = 0;
+            dest[4 * x + 3] = source[x];
+        }
+    }
+}
+
+void Image::loadAlphaFloatData(GLsizei width, GLsizei height,
+                               int inputPitch, const void *input, size_t outputPitch, void *output) const
+{
+    const float *source = NULL;
+    float *dest = NULL;
+
+    for (int y = 0; y < height; y++)
+    {
+        source = reinterpret_cast<const float*>(static_cast<const unsigned char*>(input) + y * inputPitch);
+        dest = reinterpret_cast<float*>(static_cast<unsigned char*>(output) + y * outputPitch);
+        for (int x = 0; x < width; x++)
+        {
+            dest[4 * x + 0] = 0;
+            dest[4 * x + 1] = 0;
+            dest[4 * x + 2] = 0;
+            dest[4 * x + 3] = source[x];
+        }
+    }
+}
+
+void Image::loadAlphaHalfFloatData(GLsizei width, GLsizei height,
+                                   int inputPitch, const void *input, size_t outputPitch, void *output) const
+{
+    const unsigned short *source = NULL;
+    unsigned short *dest = NULL;
+
+    for (int y = 0; y < height; y++)
+    {
+        source = reinterpret_cast<const unsigned short*>(static_cast<const unsigned char*>(input) + y * inputPitch);
+        dest = reinterpret_cast<unsigned short*>(static_cast<unsigned char*>(output) + y * outputPitch);
+        for (int x = 0; x < width; x++)
+        {
+            dest[4 * x + 0] = 0;
+            dest[4 * x + 1] = 0;
+            dest[4 * x + 2] = 0;
+            dest[4 * x + 3] = source[x];
+        }
+    }
+}
+
+void Image::loadLuminanceData(GLsizei width, GLsizei height,
+                              int inputPitch, const void *input, size_t outputPitch, void *output, bool native) const
+{
+    const unsigned char *source = NULL;
+    unsigned char *dest = NULL;
+
+    for (int y = 0; y < height; y++)
+    {
+        source = static_cast<const unsigned char*>(input) + y * inputPitch;
+        dest = static_cast<unsigned char*>(output) + y * outputPitch;
+
+        if (!native)   // BGRA8 destination format
+        {
+            for (int x = 0; x < width; x++)
+            {
+                dest[4 * x + 0] = source[x];
+                dest[4 * x + 1] = source[x];
+                dest[4 * x + 2] = source[x];
+                dest[4 * x + 3] = 0xFF;
+            }
+        }
+        else   // L8 destination format
+        {
+            memcpy(dest, source, width);
+        }
+    }
+}
+
+void Image::loadLuminanceFloatData(GLsizei width, GLsizei height,
+                                   int inputPitch, const void *input, size_t outputPitch, void *output) const
+{
+    const float *source = NULL;
+    float *dest = NULL;
+
+    for (int y = 0; y < height; y++)
+    {
+        source = reinterpret_cast<const float*>(static_cast<const unsigned char*>(input) + y * inputPitch);
+        dest = reinterpret_cast<float*>(static_cast<unsigned char*>(output) + y * outputPitch);
+        for (int x = 0; x < width; x++)
+        {
+            dest[4 * x + 0] = source[x];
+            dest[4 * x + 1] = source[x];
+            dest[4 * x + 2] = source[x];
+            dest[4 * x + 3] = 1.0f;
+        }
+    }
+}
+
+void Image::loadLuminanceHalfFloatData(GLsizei width, GLsizei height,
+                                       int inputPitch, const void *input, size_t outputPitch, void *output) const
+{
+    const unsigned short *source = NULL;
+    unsigned short *dest = NULL;
+
+    for (int y = 0; y < height; y++)
+    {
+        source = reinterpret_cast<const unsigned short*>(static_cast<const unsigned char*>(input) + y * inputPitch);
+        dest = reinterpret_cast<unsigned short*>(static_cast<unsigned char*>(output) + y * outputPitch);
+        for (int x = 0; x < width; x++)
+        {
+            dest[4 * x + 0] = source[x];
+            dest[4 * x + 1] = source[x];
+            dest[4 * x + 2] = source[x];
+            dest[4 * x + 3] = 0x3C00; // SEEEEEMMMMMMMMMM, S = 0, E = 15, M = 0: 16bit flpt representation of 1
+        }
+    }
+}
+
+void Image::loadLuminanceAlphaData(GLsizei width, GLsizei height,
+                                   int inputPitch, const void *input, size_t outputPitch, void *output, bool native) const
+{
+    const unsigned char *source = NULL;
+    unsigned char *dest = NULL;
+
+    for (int y = 0; y < height; y++)
+    {
+        source = static_cast<const unsigned char*>(input) + y * inputPitch;
+        dest = static_cast<unsigned char*>(output) + y * outputPitch;
+        
+        if (!native)   // BGRA8 destination format
+        {
+            for (int x = 0; x < width; x++)
+            {
+                dest[4 * x + 0] = source[2*x+0];
+                dest[4 * x + 1] = source[2*x+0];
+                dest[4 * x + 2] = source[2*x+0];
+                dest[4 * x + 3] = source[2*x+1];
+            }
+        }
+        else
+        {
+            memcpy(dest, source, width * 2);
+        }
+    }
+}
+
+void Image::loadLuminanceAlphaFloatData(GLsizei width, GLsizei height,
+                                        int inputPitch, const void *input, size_t outputPitch, void *output) const
+{
+    const float *source = NULL;
+    float *dest = NULL;
+
+    for (int y = 0; y < height; y++)
+    {
+        source = reinterpret_cast<const float*>(static_cast<const unsigned char*>(input) + y * inputPitch);
+        dest = reinterpret_cast<float*>(static_cast<unsigned char*>(output) + y * outputPitch);
+        for (int x = 0; x < width; x++)
+        {
+            dest[4 * x + 0] = source[2*x+0];
+            dest[4 * x + 1] = source[2*x+0];
+            dest[4 * x + 2] = source[2*x+0];
+            dest[4 * x + 3] = source[2*x+1];
+        }
+    }
+}
+
+void Image::loadLuminanceAlphaHalfFloatData(GLsizei width, GLsizei height,
+                                            int inputPitch, const void *input, size_t outputPitch, void *output) const
+{
+    const unsigned short *source = NULL;
+    unsigned short *dest = NULL;
+
+    for (int y = 0; y < height; y++)
+    {
+        source = reinterpret_cast<const unsigned short*>(static_cast<const unsigned char*>(input) + y * inputPitch);
+        dest = reinterpret_cast<unsigned short*>(static_cast<unsigned char*>(output) + y * outputPitch);
+        for (int x = 0; x < width; x++)
+        {
+            dest[4 * x + 0] = source[2*x+0];
+            dest[4 * x + 1] = source[2*x+0];
+            dest[4 * x + 2] = source[2*x+0];
+            dest[4 * x + 3] = source[2*x+1];
+        }
+    }
+}
+
+void Image::loadRGBUByteData(GLsizei width, GLsizei height,
+                             int inputPitch, const void *input, size_t outputPitch, void *output) const
+{
+    const unsigned char *source = NULL;
+    unsigned char *dest = NULL;
+
+    for (int y = 0; y < height; y++)
+    {
+        source = static_cast<const unsigned char*>(input) + y * inputPitch;
+        dest = static_cast<unsigned char*>(output) + y * outputPitch;
+        for (int x = 0; x < width; x++)
+        {
+            dest[4 * x + 0] = source[x * 3 + 2];
+            dest[4 * x + 1] = source[x * 3 + 1];
+            dest[4 * x + 2] = source[x * 3 + 0];
+            dest[4 * x + 3] = 0xFF;
+        }
+    }
+}
+
+void Image::loadRGB565Data(GLsizei width, GLsizei height,
+                           int inputPitch, const void *input, size_t outputPitch, void *output) const
+{
+    const unsigned short *source = NULL;
+    unsigned char *dest = NULL;
+
+    for (int y = 0; y < height; y++)
+    {
+        source = reinterpret_cast<const unsigned short*>(static_cast<const unsigned char*>(input) + y * inputPitch);
+        dest = static_cast<unsigned char*>(output) + y * outputPitch;
+        for (int x = 0; x < width; x++)
+        {
+            unsigned short rgba = source[x];
+            dest[4 * x + 0] = ((rgba & 0x001F) << 3) | ((rgba & 0x001F) >> 2);
+            dest[4 * x + 1] = ((rgba & 0x07E0) >> 3) | ((rgba & 0x07E0) >> 9);
+            dest[4 * x + 2] = ((rgba & 0xF800) >> 8) | ((rgba & 0xF800) >> 13);
+            dest[4 * x + 3] = 0xFF;
+        }
+    }
+}
+
+void Image::loadRGBFloatData(GLsizei width, GLsizei height,
+                             int inputPitch, const void *input, size_t outputPitch, void *output) const
+{
+    const float *source = NULL;
+    float *dest = NULL;
+
+    for (int y = 0; y < height; y++)
+    {
+        source = reinterpret_cast<const float*>(static_cast<const unsigned char*>(input) + y * inputPitch);
+        dest = reinterpret_cast<float*>(static_cast<unsigned char*>(output) + y * outputPitch);
+        for (int x = 0; x < width; x++)
+        {
+            dest[4 * x + 0] = source[x * 3 + 0];
+            dest[4 * x + 1] = source[x * 3 + 1];
+            dest[4 * x + 2] = source[x * 3 + 2];
+            dest[4 * x + 3] = 1.0f;
+        }
+    }
+}
+
+void Image::loadRGBHalfFloatData(GLsizei width, GLsizei height,
+                                 int inputPitch, const void *input, size_t outputPitch, void *output) const
+{
+    const unsigned short *source = NULL;
+    unsigned short *dest = NULL;
+
+    for (int y = 0; y < height; y++)
+    {
+        source = reinterpret_cast<const unsigned short*>(static_cast<const unsigned char*>(input) + y * inputPitch);
+        dest = reinterpret_cast<unsigned short*>(static_cast<unsigned char*>(output) + y * outputPitch);
+        for (int x = 0; x < width; x++)
+        {
+            dest[4 * x + 0] = source[x * 3 + 0];
+            dest[4 * x + 1] = source[x * 3 + 1];
+            dest[4 * x + 2] = source[x * 3 + 2];
+            dest[4 * x + 3] = 0x3C00; // SEEEEEMMMMMMMMMM, S = 0, E = 15, M = 0: 16bit flpt representation of 1
+        }
+    }
+}
+
+void Image::loadRGBAUByteData(GLsizei width, GLsizei height,
+                              int inputPitch, const void *input, size_t outputPitch, void *output) const
+{
+    const unsigned int *source = NULL;
+    unsigned int *dest = NULL;
+    for (int y = 0; y < height; y++)
+    {
+        source = reinterpret_cast<const unsigned int*>(static_cast<const unsigned char*>(input) + y * inputPitch);
+        dest = reinterpret_cast<unsigned int*>(static_cast<unsigned char*>(output) + y * outputPitch);
+
+        for (int x = 0; x < width; x++)
+        {
+            unsigned int rgba = source[x];
+            dest[x] = (_rotl(rgba, 16) & 0x00ff00ff) | (rgba & 0xff00ff00);
+        }
+    }
+}
+
+void Image::loadRGBA4444Data(GLsizei width, GLsizei height,
+                             int inputPitch, const void *input, size_t outputPitch, void *output) const
+{
+    const unsigned short *source = NULL;
+    unsigned char *dest = NULL;
+
+    for (int y = 0; y < height; y++)
+    {
+        source = reinterpret_cast<const unsigned short*>(static_cast<const unsigned char*>(input) + y * inputPitch);
+        dest = static_cast<unsigned char*>(output) + y * outputPitch;
+        for (int x = 0; x < width; x++)
+        {
+            unsigned short rgba = source[x];
+            dest[4 * x + 0] = ((rgba & 0x00F0) << 0) | ((rgba & 0x00F0) >> 4);
+            dest[4 * x + 1] = ((rgba & 0x0F00) >> 4) | ((rgba & 0x0F00) >> 8);
+            dest[4 * x + 2] = ((rgba & 0xF000) >> 8) | ((rgba & 0xF000) >> 12);
+            dest[4 * x + 3] = ((rgba & 0x000F) << 4) | ((rgba & 0x000F) >> 0);
+        }
+    }
+}
+
+void Image::loadRGBA5551Data(GLsizei width, GLsizei height,
+                             int inputPitch, const void *input, size_t outputPitch, void *output) const
+{
+    const unsigned short *source = NULL;
+    unsigned char *dest = NULL;
+
+    for (int y = 0; y < height; y++)
+    {
+        source = reinterpret_cast<const unsigned short*>(static_cast<const unsigned char*>(input) + y * inputPitch);
+        dest = static_cast<unsigned char*>(output) + y * outputPitch;
+        for (int x = 0; x < width; x++)
+        {
+            unsigned short rgba = source[x];
+            dest[4 * x + 0] = ((rgba & 0x003E) << 2) | ((rgba & 0x003E) >> 3);
+            dest[4 * x + 1] = ((rgba & 0x07C0) >> 3) | ((rgba & 0x07C0) >> 8);
+            dest[4 * x + 2] = ((rgba & 0xF800) >> 8) | ((rgba & 0xF800) >> 13);
+            dest[4 * x + 3] = (rgba & 0x0001) ? 0xFF : 0;
+        }
+    }
+}
+
+void Image::loadRGBAFloatData(GLsizei width, GLsizei height,
+                              int inputPitch, const void *input, size_t outputPitch, void *output) const
+{
+    const float *source = NULL;
+    float *dest = NULL;
+
+    for (int y = 0; y < height; y++)
+    {
+        source = reinterpret_cast<const float*>(static_cast<const unsigned char*>(input) + y * inputPitch);
+        dest = reinterpret_cast<float*>(static_cast<unsigned char*>(output) + y * outputPitch);
+        memcpy(dest, source, width * 16);
+    }
+}
+
+void Image::loadRGBAHalfFloatData(GLsizei width, GLsizei height,
+                                  int inputPitch, const void *input, size_t outputPitch, void *output) const
+{
+    const unsigned char *source = NULL;
+    unsigned char *dest = NULL;
+
+    for (int y = 0; y < height; y++)
+    {
+        source = static_cast<const unsigned char*>(input) + y * inputPitch;
+        dest = static_cast<unsigned char*>(output) + y * outputPitch;
+        memcpy(dest, source, width * 8);
+    }
+}
+
+void Image::loadBGRAData(GLsizei width, GLsizei height,
+                         int inputPitch, const void *input, size_t outputPitch, void *output) const
+{
+    const unsigned char *source = NULL;
+    unsigned char *dest = NULL;
+
+    for (int y = 0; y < height; y++)
+    {
+        source = static_cast<const unsigned char*>(input) + y * inputPitch;
+        dest = static_cast<unsigned char*>(output) + y * outputPitch;
+        memcpy(dest, source, width*4);
+    }
+}
+
+void Image::loadCompressedData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
+                               const void *input) {
+    ASSERT(xoffset % 4 == 0);
+    ASSERT(yoffset % 4 == 0);
+
+    RECT lockRect = {
+        xoffset, yoffset,
+        xoffset + width, yoffset + height
+    };
+
+    D3DLOCKED_RECT locked;
+    HRESULT result = lock(&locked, &lockRect);
+    if (FAILED(result))
+    {
+        return;
+    }
+
+    GLsizei inputSize = ComputeCompressedSize(width, height, mInternalFormat);
+    GLsizei inputPitch = ComputeCompressedPitch(width, mInternalFormat);
+    int rows = inputSize / inputPitch;
+    for (int i = 0; i < rows; ++i)
+    {
+        memcpy((void*)((BYTE*)locked.pBits + i * locked.Pitch), (void*)((BYTE*)input + i * inputPitch), inputPitch);
+    }
+
+    unlock();
+}
+
+// This implements glCopyTex[Sub]Image2D for non-renderable internal texture formats and incomplete textures
+void Image::copy(GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height, IDirect3DSurface9 *renderTarget)
+{
+    IDirect3DDevice9 *device = getDevice();
+    IDirect3DSurface9 *renderTargetData = NULL;
+    D3DSURFACE_DESC description;
+    renderTarget->GetDesc(&description);
+    
+    HRESULT result = device->CreateOffscreenPlainSurface(description.Width, description.Height, description.Format, D3DPOOL_SYSTEMMEM, &renderTargetData, NULL);
+
+    if (FAILED(result))
+    {
+        ERR("Could not create matching destination surface.");
+        return error(GL_OUT_OF_MEMORY);
+    }
+
+    result = device->GetRenderTargetData(renderTarget, renderTargetData);
+
+    if (FAILED(result))
+    {
+        ERR("GetRenderTargetData unexpectedly failed.");
+        renderTargetData->Release();
+        return error(GL_OUT_OF_MEMORY);
+    }
+
+    RECT sourceRect = {x, y, x + width, y + height};
+    RECT destRect = {xoffset, yoffset, xoffset + width, yoffset + height};
+
+    D3DLOCKED_RECT sourceLock = {0};
+    result = renderTargetData->LockRect(&sourceLock, &sourceRect, 0);
+
+    if (FAILED(result))
+    {
+        ERR("Failed to lock the source surface (rectangle might be invalid).");
+        renderTargetData->Release();
+        return error(GL_OUT_OF_MEMORY);
+    }
+
+    D3DLOCKED_RECT destLock = {0};
+    result = lock(&destLock, &destRect);
+    
+    if (FAILED(result))
+    {
+        ERR("Failed to lock the destination surface (rectangle might be invalid).");
+        renderTargetData->UnlockRect();
+        renderTargetData->Release();
+        return error(GL_OUT_OF_MEMORY);
+    }
+
+    if (destLock.pBits && sourceLock.pBits)
+    {
+        unsigned char *source = (unsigned char*)sourceLock.pBits;
+        unsigned char *dest = (unsigned char*)destLock.pBits;
+
+        switch (description.Format)
+        {
+          case D3DFMT_X8R8G8B8:
+          case D3DFMT_A8R8G8B8:
+            switch(getD3DFormat())
+            {
+              case D3DFMT_X8R8G8B8:
+              case D3DFMT_A8R8G8B8:
+                for(int y = 0; y < height; y++)
+                {
+                    memcpy(dest, source, 4 * width);
+
+                    source += sourceLock.Pitch;
+                    dest += destLock.Pitch;
+                }
+                break;
+              case D3DFMT_L8:
+                for(int y = 0; y < height; y++)
+                {
+                    for(int x = 0; x < width; x++)
+                    {
+                        dest[x] = source[x * 4 + 2];
+                    }
+
+                    source += sourceLock.Pitch;
+                    dest += destLock.Pitch;
+                }
+                break;
+              case D3DFMT_A8L8:
+                for(int y = 0; y < height; y++)
+                {
+                    for(int x = 0; x < width; x++)
+                    {
+                        dest[x * 2 + 0] = source[x * 4 + 2];
+                        dest[x * 2 + 1] = source[x * 4 + 3];
+                    }
+
+                    source += sourceLock.Pitch;
+                    dest += destLock.Pitch;
+                }
+                break;
+              default:
+                UNREACHABLE();
+            }
+            break;
+          case D3DFMT_R5G6B5:
+            switch(getD3DFormat())
+            {
+              case D3DFMT_X8R8G8B8:
+                for(int y = 0; y < height; y++)
+                {
+                    for(int x = 0; x < width; x++)
+                    {
+                        unsigned short rgb = ((unsigned short*)source)[x];
+                        unsigned char red = (rgb & 0xF800) >> 8;
+                        unsigned char green = (rgb & 0x07E0) >> 3;
+                        unsigned char blue = (rgb & 0x001F) << 3;
+                        dest[x + 0] = blue | (blue >> 5);
+                        dest[x + 1] = green | (green >> 6);
+                        dest[x + 2] = red | (red >> 5);
+                        dest[x + 3] = 0xFF;
+                    }
+
+                    source += sourceLock.Pitch;
+                    dest += destLock.Pitch;
+                }
+                break;
+              case D3DFMT_L8:
+                for(int y = 0; y < height; y++)
+                {
+                    for(int x = 0; x < width; x++)
+                    {
+                        unsigned char red = source[x * 2 + 1] & 0xF8;
+                        dest[x] = red | (red >> 5);
+                    }
+
+                    source += sourceLock.Pitch;
+                    dest += destLock.Pitch;
+                }
+                break;
+              default:
+                UNREACHABLE();
+            }
+            break;
+          case D3DFMT_A1R5G5B5:
+            switch(getD3DFormat())
+            {
+              case D3DFMT_X8R8G8B8:
+                for(int y = 0; y < height; y++)
+                {
+                    for(int x = 0; x < width; x++)
+                    {
+                        unsigned short argb = ((unsigned short*)source)[x];
+                        unsigned char red = (argb & 0x7C00) >> 7;
+                        unsigned char green = (argb & 0x03E0) >> 2;
+                        unsigned char blue = (argb & 0x001F) << 3;
+                        dest[x + 0] = blue | (blue >> 5);
+                        dest[x + 1] = green | (green >> 5);
+                        dest[x + 2] = red | (red >> 5);
+                        dest[x + 3] = 0xFF;
+                    }
+
+                    source += sourceLock.Pitch;
+                    dest += destLock.Pitch;
+                }
+                break;
+              case D3DFMT_A8R8G8B8:
+                for(int y = 0; y < height; y++)
+                {
+                    for(int x = 0; x < width; x++)
+                    {
+                        unsigned short argb = ((unsigned short*)source)[x];
+                        unsigned char red = (argb & 0x7C00) >> 7;
+                        unsigned char green = (argb & 0x03E0) >> 2;
+                        unsigned char blue = (argb & 0x001F) << 3;
+                        unsigned char alpha = (signed short)argb >> 15;
+                        dest[x + 0] = blue | (blue >> 5);
+                        dest[x + 1] = green | (green >> 5);
+                        dest[x + 2] = red | (red >> 5);
+                        dest[x + 3] = alpha;
+                    }
+
+                    source += sourceLock.Pitch;
+                    dest += destLock.Pitch;
+                }
+                break;
+              case D3DFMT_L8:
+                for(int y = 0; y < height; y++)
+                {
+                    for(int x = 0; x < width; x++)
+                    {
+                        unsigned char red = source[x * 2 + 1] & 0x7C;
+                        dest[x] = (red << 1) | (red >> 4);
+                    }
+
+                    source += sourceLock.Pitch;
+                    dest += destLock.Pitch;
+                }
+                break;
+              case D3DFMT_A8L8:
+                for(int y = 0; y < height; y++)
+                {
+                    for(int x = 0; x < width; x++)
+                    {
+                        unsigned char red = source[x * 2 + 1] & 0x7C;
+                        dest[x * 2 + 0] = (red << 1) | (red >> 4);
+                        dest[x * 2 + 1] = (signed char)source[x * 2 + 1] >> 7;
+                    }
+
+                    source += sourceLock.Pitch;
+                    dest += destLock.Pitch;
+                }
+                break;
+              default:
+                UNREACHABLE();
+            }
+            break;
+          default:
+            UNREACHABLE();
+        }
+    }
+
+    unlock();
+    renderTargetData->UnlockRect();
+
+    renderTargetData->Release();
+
+    mDirty = true;
+}
+
+namespace
+{
+struct L8
+{
+    unsigned char L;
+
+    static void average(L8 *dst, const L8 *src1, const L8 *src2)
+    {
+        dst->L = ((src1->L ^ src2->L) >> 1) + (src1->L & src2->L);
+    }
+};
+
+struct A8L8
+{
+    unsigned char L;
+    unsigned char A;
+
+    static void average(A8L8 *dst, const A8L8 *src1, const A8L8 *src2)
+    {
+        *(unsigned short*)dst = (((*(unsigned short*)src1 ^ *(unsigned short*)src2) & 0xFEFE) >> 1) + (*(unsigned short*)src1 & *(unsigned short*)src2);
+    }
+};
+
+struct A8R8G8B8
+{
+    unsigned char B;
+    unsigned char G;
+    unsigned char R;
+    unsigned char A;
+
+    static void average(A8R8G8B8 *dst, const A8R8G8B8 *src1, const A8R8G8B8 *src2)
+    {
+        *(unsigned int*)dst = (((*(unsigned int*)src1 ^ *(unsigned int*)src2) & 0xFEFEFEFE) >> 1) + (*(unsigned int*)src1 & *(unsigned int*)src2);
+    }
+};
+
+struct A16B16G16R16F
+{
+    unsigned short R;
+    unsigned short G;
+    unsigned short B;
+    unsigned short A;
+
+    static void average(A16B16G16R16F *dst, const A16B16G16R16F *src1, const A16B16G16R16F *src2)
+    {
+        dst->R = float32ToFloat16((float16ToFloat32(src1->R) + float16ToFloat32(src2->R)) * 0.5f);
+        dst->G = float32ToFloat16((float16ToFloat32(src1->G) + float16ToFloat32(src2->G)) * 0.5f);
+        dst->B = float32ToFloat16((float16ToFloat32(src1->B) + float16ToFloat32(src2->B)) * 0.5f);
+        dst->A = float32ToFloat16((float16ToFloat32(src1->A) + float16ToFloat32(src2->A)) * 0.5f);
+    }
+};
+
+struct A32B32G32R32F
+{
+    float R;
+    float G;
+    float B;
+    float A;
+
+    static void average(A32B32G32R32F *dst, const A32B32G32R32F *src1, const A32B32G32R32F *src2)
+    {
+        dst->R = (src1->R + src2->R) * 0.5f;
+        dst->G = (src1->G + src2->G) * 0.5f;
+        dst->B = (src1->B + src2->B) * 0.5f;
+        dst->A = (src1->A + src2->A) * 0.5f;
+    }
+};
+
+template <typename T>
+void GenerateMip(unsigned int sourceWidth, unsigned int sourceHeight,
+                 const unsigned char *sourceData, int sourcePitch,
+                 unsigned char *destData, int destPitch)
+{
+    unsigned int mipWidth = std::max(1U, sourceWidth >> 1);
+    unsigned int mipHeight = std::max(1U, sourceHeight >> 1);
+
+    if (sourceHeight == 1)
+    {
+        ASSERT(sourceWidth != 1);
+
+        const T *src = (const T*)sourceData;
+        T *dst = (T*)destData;
+
+        for (unsigned int x = 0; x < mipWidth; x++)
+        {
+            T::average(&dst[x], &src[x * 2], &src[x * 2 + 1]);
+        }
+    }
+    else if (sourceWidth == 1)
+    {
+        ASSERT(sourceHeight != 1);
+
+        for (unsigned int y = 0; y < mipHeight; y++)
+        {
+            const T *src0 = (const T*)(sourceData + y * 2 * sourcePitch);
+            const T *src1 = (const T*)(sourceData + y * 2 * sourcePitch + sourcePitch);
+            T *dst = (T*)(destData + y * destPitch);
+
+            T::average(dst, src0, src1);
+        }
+    }
+    else
+    {
+        for (unsigned int y = 0; y < mipHeight; y++)
+        {
+            const T *src0 = (const T*)(sourceData + y * 2 * sourcePitch);
+            const T *src1 = (const T*)(sourceData + y * 2 * sourcePitch + sourcePitch);
+            T *dst = (T*)(destData + y * destPitch);
+
+            for (unsigned int x = 0; x < mipWidth; x++)
+            {
+                T tmp0;
+                T tmp1;
+
+                T::average(&tmp0, &src0[x * 2], &src0[x * 2 + 1]);
+                T::average(&tmp1, &src1[x * 2], &src1[x * 2 + 1]);
+                T::average(&dst[x], &tmp0, &tmp1);
+            }
+        }
+    }
+}
+
+void GenerateMip(IDirect3DSurface9 *destSurface, IDirect3DSurface9 *sourceSurface)
+{
+    D3DSURFACE_DESC destDesc;
+    HRESULT result = destSurface->GetDesc(&destDesc);
+    ASSERT(SUCCEEDED(result));
+
+    D3DSURFACE_DESC sourceDesc;
+    result = sourceSurface->GetDesc(&sourceDesc);
+    ASSERT(SUCCEEDED(result));
+
+    ASSERT(sourceDesc.Format == destDesc.Format);
+    ASSERT(sourceDesc.Width == 1 || sourceDesc.Width / 2 == destDesc.Width);
+    ASSERT(sourceDesc.Height == 1 || sourceDesc.Height / 2 == destDesc.Height);
+
+    D3DLOCKED_RECT sourceLocked = {0};
+    result = sourceSurface->LockRect(&sourceLocked, NULL, D3DLOCK_READONLY);
+    ASSERT(SUCCEEDED(result));
+
+    D3DLOCKED_RECT destLocked = {0};
+    result = destSurface->LockRect(&destLocked, NULL, 0);
+    ASSERT(SUCCEEDED(result));
+
+    const unsigned char *sourceData = reinterpret_cast<const unsigned char*>(sourceLocked.pBits);
+    unsigned char *destData = reinterpret_cast<unsigned char*>(destLocked.pBits);
+
+    if (sourceData && destData)
+    {
+        switch (sourceDesc.Format)
+        {
+          case D3DFMT_L8:
+            GenerateMip<L8>(sourceDesc.Width, sourceDesc.Height, sourceData, sourceLocked.Pitch, destData, destLocked.Pitch);
+            break;
+          case D3DFMT_A8L8:
+            GenerateMip<A8L8>(sourceDesc.Width, sourceDesc.Height, sourceData, sourceLocked.Pitch, destData, destLocked.Pitch);
+            break;
+          case D3DFMT_A8R8G8B8:
+          case D3DFMT_X8R8G8B8:
+            GenerateMip<A8R8G8B8>(sourceDesc.Width, sourceDesc.Height, sourceData, sourceLocked.Pitch, destData, destLocked.Pitch);
+            break;
+          case D3DFMT_A16B16G16R16F:
+            GenerateMip<A16B16G16R16F>(sourceDesc.Width, sourceDesc.Height, sourceData, sourceLocked.Pitch, destData, destLocked.Pitch);
+            break;
+          case D3DFMT_A32B32G32R32F:
+            GenerateMip<A32B32G32R32F>(sourceDesc.Width, sourceDesc.Height, sourceData, sourceLocked.Pitch, destData, destLocked.Pitch);
+            break;
+          default:
+            UNREACHABLE();
+            break;
+        }
+
+        destSurface->UnlockRect();
+        sourceSurface->UnlockRect();
+    }
+}
+}
+
+TextureStorage::TextureStorage(DWORD usage)
+    : mD3DUsage(usage),
+      mD3DPool(getDisplay()->getTexturePool(usage)),
+      mTextureSerial(issueTextureSerial()),
+      mLodOffset(0)
+{
+}
+
+TextureStorage::~TextureStorage()
+{
+}
+
+bool TextureStorage::isRenderTarget() const
+{
+    return (mD3DUsage & (D3DUSAGE_RENDERTARGET | D3DUSAGE_DEPTHSTENCIL)) != 0;
+}
+
+bool TextureStorage::isManaged() const
+{
+    return (mD3DPool == D3DPOOL_MANAGED);
+}
+
+D3DPOOL TextureStorage::getPool() const
+{
+    return mD3DPool;
+}
+
+DWORD TextureStorage::getUsage() const
+{
+    return mD3DUsage;
+}
+
+unsigned int TextureStorage::getTextureSerial() const
+{
+    return mTextureSerial;
+}
+
+unsigned int TextureStorage::issueTextureSerial()
+{
+    return mCurrentTextureSerial++;
+}
+
+int TextureStorage::getLodOffset() const
+{
+    return mLodOffset;
+}
+
+Texture::Texture(GLuint id) : RefCountObject(id)
+{
+    mMinFilter = GL_NEAREST_MIPMAP_LINEAR;
+    mMagFilter = GL_LINEAR;
+    mWrapS = GL_REPEAT;
+    mWrapT = GL_REPEAT;
+    mDirtyParameters = true;
+    mUsage = GL_NONE;
+    mMaxAnisotropy = 1.0f;
+    
+    mDirtyImages = true;
+
+    mImmutable = false;
+}
+
+Texture::~Texture()
+{
+}
+
+// Returns true on successful filter state update (valid enum parameter)
+bool Texture::setMinFilter(GLenum filter)
+{
+    switch (filter)
+    {
+      case GL_NEAREST:
+      case GL_LINEAR:
+      case GL_NEAREST_MIPMAP_NEAREST:
+      case GL_LINEAR_MIPMAP_NEAREST:
+      case GL_NEAREST_MIPMAP_LINEAR:
+      case GL_LINEAR_MIPMAP_LINEAR:
+        {
+            if (mMinFilter != filter)
+            {
+                mMinFilter = filter;
+                mDirtyParameters = true;
+            }
+            return true;
+        }
+      default:
+        return false;
+    }
+}
+
+// Returns true on successful filter state update (valid enum parameter)
+bool Texture::setMagFilter(GLenum filter)
+{
+    switch (filter)
+    {
+      case GL_NEAREST:
+      case GL_LINEAR:
+        {
+            if (mMagFilter != filter)
+            {
+                mMagFilter = filter;
+                mDirtyParameters = true;
+            }
+            return true;
+        }
+      default:
+        return false;
+    }
+}
+
+// Returns true on successful wrap state update (valid enum parameter)
+bool Texture::setWrapS(GLenum wrap)
+{
+    switch (wrap)
+    {
+      case GL_REPEAT:
+      case GL_CLAMP_TO_EDGE:
+      case GL_MIRRORED_REPEAT:
+        {
+            if (mWrapS != wrap)
+            {
+                mWrapS = wrap;
+                mDirtyParameters = true;
+            }
+            return true;
+        }
+      default:
+        return false;
+    }
+}
+
+// Returns true on successful wrap state update (valid enum parameter)
+bool Texture::setWrapT(GLenum wrap)
+{
+    switch (wrap)
+    {
+      case GL_REPEAT:
+      case GL_CLAMP_TO_EDGE:
+      case GL_MIRRORED_REPEAT:
+        {
+            if (mWrapT != wrap)
+            {
+                mWrapT = wrap;
+                mDirtyParameters = true;
+            }
+            return true;
+        }
+      default:
+        return false;
+    }
+}
+
+// Returns true on successful max anisotropy update (valid anisotropy value)
+bool Texture::setMaxAnisotropy(float textureMaxAnisotropy, float contextMaxAnisotropy)
+{
+    textureMaxAnisotropy = std::min(textureMaxAnisotropy, contextMaxAnisotropy);
+    if (textureMaxAnisotropy < 1.0f)
+    {
+        return false;
+    }
+    if (mMaxAnisotropy != textureMaxAnisotropy)
+    {
+        mMaxAnisotropy = textureMaxAnisotropy;
+        mDirtyParameters = true;
+    }
+    return true;
+}
+
+// Returns true on successful usage state update (valid enum parameter)
+bool Texture::setUsage(GLenum usage)
+{
+    switch (usage)
+    {
+      case GL_NONE:
+      case GL_FRAMEBUFFER_ATTACHMENT_ANGLE:
+        mUsage = usage;
+        return true;
+      default:
+        return false;
+    }
+}
+
+GLenum Texture::getMinFilter() const
+{
+    return mMinFilter;
+}
+
+GLenum Texture::getMagFilter() const
+{
+    return mMagFilter;
+}
+
+GLenum Texture::getWrapS() const
+{
+    return mWrapS;
+}
+
+GLenum Texture::getWrapT() const
+{
+    return mWrapT;
+}
+
+float Texture::getMaxAnisotropy() const
+{
+    return mMaxAnisotropy;
+}
+
+GLenum Texture::getUsage() const
+{
+    return mUsage;
+}
+
+void Texture::setImage(GLint unpackAlignment, const void *pixels, Image *image)
+{
+    if (pixels != NULL)
+    {
+        image->loadData(0, 0, image->getWidth(), image->getHeight(), unpackAlignment, pixels);
+        mDirtyImages = true;
+    }
+}
+
+void Texture::setCompressedImage(GLsizei imageSize, const void *pixels, Image *image)
+{
+    if (pixels != NULL)
+    {
+        image->loadCompressedData(0, 0, image->getWidth(), image->getHeight(), pixels);
+        mDirtyImages = true;
+    }
+}
+
+bool Texture::subImage(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels, Image *image)
+{
+    if (pixels != NULL)
+    {
+        image->loadData(xoffset, yoffset, width, height, unpackAlignment, pixels);
+        mDirtyImages = true;
+    }
+
+    return true;
+}
+
+bool Texture::subImageCompressed(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *pixels, Image *image)
+{
+    if (pixels != NULL)
+    {
+        image->loadCompressedData(xoffset, yoffset, width, height, pixels);
+        mDirtyImages = true;
+    }
+
+    return true;
+}
+
+IDirect3DBaseTexture9 *Texture::getTexture()
+{
+    if (!isSamplerComplete())
+    {
+        return NULL;
+    }
+
+    // ensure the underlying texture is created
+    if (getStorage(false) == NULL)
+    {
+        return NULL;
+    }
+
+    updateTexture();
+
+    return getBaseTexture();
+}
+
+bool Texture::hasDirtyParameters() const
+{
+    return mDirtyParameters;
+}
+
+bool Texture::hasDirtyImages() const
+{
+    return mDirtyImages;
+}
+
+void Texture::resetDirty()
+{
+    mDirtyParameters = false;
+    mDirtyImages = false;
+}
+
+unsigned int Texture::getTextureSerial()
+{
+    TextureStorage *texture = getStorage(false);
+    return texture ? texture->getTextureSerial() : 0;
+}
+
+unsigned int Texture::getRenderTargetSerial(GLenum target)
+{
+    TextureStorage *texture = getStorage(true);
+    return texture ? texture->getRenderTargetSerial(target) : 0;
+}
+
+bool Texture::isImmutable() const
+{
+    return mImmutable;
+}
+
+int Texture::getLodOffset()
+{
+    TextureStorage *texture = getStorage(false);
+    return texture ? texture->getLodOffset() : 0;
+}
+
+GLint Texture::creationLevels(GLsizei width, GLsizei height) const
+{
+    if ((isPow2(width) && isPow2(height)) || getContext()->supportsNonPower2Texture())
+    {
+        return 0;   // Maximum number of levels
+    }
+    else
+    {
+        // OpenGL ES 2.0 without GL_OES_texture_npot does not permit NPOT mipmaps.
+        return 1;
+    }
+}
+
+GLint Texture::creationLevels(GLsizei size) const
+{
+    return creationLevels(size, size);
+}
+
+int Texture::levelCount()
+{
+    return getBaseTexture() ? getBaseTexture()->GetLevelCount() - getLodOffset() : 0;
+}
+
+Blit *Texture::getBlitter()
+{
+    Context *context = getContext();
+    return context->getBlitter();
+}
+
+bool Texture::copyToRenderTarget(IDirect3DSurface9 *dest, IDirect3DSurface9 *source, bool fromManaged)
+{
+    if (source && dest)
+    {
+        HRESULT result = D3DERR_OUTOFVIDEOMEMORY;
+
+        if (fromManaged)
+        {
+            D3DSURFACE_DESC desc;
+            source->GetDesc(&desc);
+
+            IDirect3DSurface9 *surf = 0;
+            result = getDevice()->CreateOffscreenPlainSurface(desc.Width, desc.Height, desc.Format, D3DPOOL_SYSTEMMEM, &surf, NULL);
+
+            if (SUCCEEDED(result))
+            {
+                CopyLockableSurfaces(surf, source);
+                result = getDevice()->UpdateSurface(surf, NULL, dest, NULL);
+                surf->Release();
+            }
+        }
+        else
+        {
+            egl::Display *display = getDisplay();
+            IDirect3DDevice9 *device = display->getDevice();
+
+            display->endScene();
+            result = device->StretchRect(source, NULL, dest, NULL, D3DTEXF_NONE);
+        }
+
+        if (FAILED(result))
+        {
+            ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
+            return false;
+        }
+    }
+
+    return true;
+}
+
+TextureStorage2D::TextureStorage2D(IDirect3DTexture9 *surfaceTexture) : TextureStorage(D3DUSAGE_RENDERTARGET), mRenderTargetSerial(RenderbufferStorage::issueSerial())
+{
+    mTexture = surfaceTexture;
+}
+
+TextureStorage2D::TextureStorage2D(int levels, D3DFORMAT format, DWORD usage, int width, int height)
+    : TextureStorage(usage), mRenderTargetSerial(RenderbufferStorage::issueSerial())
+{
+    mTexture = NULL;
+    // if the width or height is not positive this should be treated as an incomplete texture
+    // we handle that here by skipping the d3d texture creation
+    if (width > 0 && height > 0)
+    {
+        IDirect3DDevice9 *device = getDevice();
+        MakeValidSize(false, dx::IsCompressedFormat(format), &width, &height, &mLodOffset);
+        HRESULT result = device->CreateTexture(width, height, levels ? levels + mLodOffset : 0, getUsage(), format, getPool(), &mTexture, NULL);
+
+        if (FAILED(result))
+        {
+            ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
+            error(GL_OUT_OF_MEMORY);
+        }
+    }
+}
+
+TextureStorage2D::~TextureStorage2D()
+{
+    if (mTexture)
+    {
+        mTexture->Release();
+    }
+}
+
+// Increments refcount on surface.
+// caller must Release() the returned surface
+IDirect3DSurface9 *TextureStorage2D::getSurfaceLevel(int level, bool dirty)
+{
+    IDirect3DSurface9 *surface = NULL;
+
+    if (mTexture)
+    {
+        HRESULT result = mTexture->GetSurfaceLevel(level + mLodOffset, &surface);
+        ASSERT(SUCCEEDED(result));
+
+        // With managed textures the driver needs to be informed of updates to the lower mipmap levels
+        if (level != 0 && isManaged() && dirty)
+        {
+            mTexture->AddDirtyRect(NULL);
+        }
+    }
+
+    return surface;
+}
+
+IDirect3DBaseTexture9 *TextureStorage2D::getBaseTexture() const
+{
+    return mTexture;
+}
+
+unsigned int TextureStorage2D::getRenderTargetSerial(GLenum target) const
+{
+    return mRenderTargetSerial;
+}
+
+Texture2D::Texture2D(GLuint id) : Texture(id)
+{
+    mTexStorage = NULL;
+    mSurface = NULL;
+    mColorbufferProxy = NULL;
+    mProxyRefs = 0;
+}
+
+Texture2D::~Texture2D()
+{
+    mColorbufferProxy = NULL;
+
+    delete mTexStorage;
+    mTexStorage = NULL;
+    
+    if (mSurface)
+    {
+        mSurface->setBoundTexture(NULL);
+        mSurface = NULL;
+    }
+}
+
+// We need to maintain a count of references to renderbuffers acting as 
+// proxies for this texture, so that we do not attempt to use a pointer 
+// to a renderbuffer proxy which has been deleted.
+void Texture2D::addProxyRef(const Renderbuffer *proxy)
+{
+    mProxyRefs++;
+}
+
+void Texture2D::releaseProxy(const Renderbuffer *proxy)
+{
+    if (mProxyRefs > 0)
+        mProxyRefs--;
+
+    if (mProxyRefs == 0)
+        mColorbufferProxy = NULL;
+}
+
+GLenum Texture2D::getTarget() const
+{
+    return GL_TEXTURE_2D;
+}
+
+GLsizei Texture2D::getWidth(GLint level) const
+{
+    if (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS)
+        return mImageArray[level].getWidth();
+    else
+        return 0;
+}
+
+GLsizei Texture2D::getHeight(GLint level) const
+{
+    if (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS)
+        return mImageArray[level].getHeight();
+    else
+        return 0;
+}
+
+GLenum Texture2D::getInternalFormat(GLint level) const
+{
+    if (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS)
+        return mImageArray[level].getInternalFormat();
+    else
+        return GL_NONE;
+}
+
+D3DFORMAT Texture2D::getD3DFormat(GLint level) const
+{
+    if (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS)
+        return mImageArray[level].getD3DFormat();
+    else
+        return D3DFMT_UNKNOWN;
+}
+
+void Texture2D::redefineImage(GLint level, GLint internalformat, GLsizei width, GLsizei height)
+{
+    releaseTexImage();
+
+    bool redefined = mImageArray[level].redefine(internalformat, width, height, false);
+
+    if (mTexStorage && redefined)
+    {
+        for (int i = 0; i < IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++)
+        {
+            mImageArray[i].markDirty();
+        }
+
+        delete mTexStorage;
+        mTexStorage = NULL;
+        mDirtyImages = true;
+    }
+}
+
+void Texture2D::setImage(GLint level, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels)
+{
+    GLint internalformat = ConvertSizedInternalFormat(format, type);
+    redefineImage(level, internalformat, width, height);
+
+    Texture::setImage(unpackAlignment, pixels, &mImageArray[level]);
+}
+
+void Texture2D::bindTexImage(egl::Surface *surface)
+{
+    releaseTexImage();
+
+    GLint internalformat;
+
+    switch(surface->getFormat())
+    {
+      case D3DFMT_A8R8G8B8:
+        internalformat = GL_RGBA8_OES;
+        break;
+      case D3DFMT_X8R8G8B8:
+        internalformat = GL_RGB8_OES;
+        break;
+      default:
+        UNIMPLEMENTED();
+        return;
+    }
+
+    mImageArray[0].redefine(internalformat, surface->getWidth(), surface->getHeight(), true);
+
+    delete mTexStorage;
+    mTexStorage = new TextureStorage2D(surface->getOffscreenTexture());
+
+    mDirtyImages = true;
+    mSurface = surface;
+    mSurface->setBoundTexture(this);
+}
+
+void Texture2D::releaseTexImage()
+{
+    if (mSurface)
+    {
+        mSurface->setBoundTexture(NULL);
+        mSurface = NULL;
+
+        if (mTexStorage)
+        {
+            delete mTexStorage;
+            mTexStorage = NULL;
+        }
+
+        for (int i = 0; i < IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++)
+        {
+            mImageArray[i].redefine(GL_RGBA8_OES, 0, 0, true);
+        }
+    }
+}
+
+void Texture2D::setCompressedImage(GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei imageSize, const void *pixels)
+{
+    // compressed formats don't have separate sized internal formats-- we can just use the compressed format directly
+    redefineImage(level, format, width, height);
+
+    Texture::setCompressedImage(imageSize, pixels, &mImageArray[level]);
+}
+
+void Texture2D::commitRect(GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height)
+{
+    ASSERT(mImageArray[level].getSurface() != NULL);
+
+    if (level < levelCount())
+    {
+        IDirect3DSurface9 *destLevel = mTexStorage->getSurfaceLevel(level, true);
+
+        if (destLevel)
+        {
+            Image *image = &mImageArray[level];
+            image->updateSurface(destLevel, xoffset, yoffset, width, height);
+
+            destLevel->Release();
+            image->markClean();
+        }
+    }
+}
+
+void Texture2D::subImage(GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels)
+{
+    if (Texture::subImage(xoffset, yoffset, width, height, format, type, unpackAlignment, pixels, &mImageArray[level]))
+    {
+        commitRect(level, xoffset, yoffset, width, height);
+    }
+}
+
+void Texture2D::subImageCompressed(GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *pixels)
+{
+    if (Texture::subImageCompressed(xoffset, yoffset, width, height, format, imageSize, pixels, &mImageArray[level]))
+    {
+        commitRect(level, xoffset, yoffset, width, height);
+    }
+}
+
+void Texture2D::copyImage(GLint level, GLenum format, GLint x, GLint y, GLsizei width, GLsizei height, Framebuffer *source)
+{
+    IDirect3DSurface9 *renderTarget = source->getRenderTarget();
+
+    if (!renderTarget)
+    {
+        ERR("Failed to retrieve the render target.");
+        return error(GL_OUT_OF_MEMORY);
+    }
+
+    GLint internalformat = ConvertSizedInternalFormat(format, GL_UNSIGNED_BYTE);
+    redefineImage(level, internalformat, width, height);
+   
+    if (!mImageArray[level].isRenderableFormat())
+    {
+        mImageArray[level].copy(0, 0, x, y, width, height, renderTarget);
+        mDirtyImages = true;
+    }
+    else
+    {
+        if (!mTexStorage || !mTexStorage->isRenderTarget())
+        {
+            convertToRenderTarget();
+        }
+        
+        mImageArray[level].markClean();
+
+        if (width != 0 && height != 0 && level < levelCount())
+        {
+            RECT sourceRect;
+            sourceRect.left = x;
+            sourceRect.right = x + width;
+            sourceRect.top = y;
+            sourceRect.bottom = y + height;
+            
+            IDirect3DSurface9 *dest = mTexStorage->getSurfaceLevel(level, true);
+
+            if (dest)
+            {
+                getBlitter()->copy(renderTarget, sourceRect, format, 0, 0, dest);
+                dest->Release();
+            }
+        }
+    }
+
+    renderTarget->Release();
+}
+
+void Texture2D::copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height, Framebuffer *source)
+{
+    if (xoffset + width > mImageArray[level].getWidth() || yoffset + height > mImageArray[level].getHeight())
+    {
+        return error(GL_INVALID_VALUE);
+    }
+
+    IDirect3DSurface9 *renderTarget = source->getRenderTarget();
+
+    if (!renderTarget)
+    {
+        ERR("Failed to retrieve the render target.");
+        return error(GL_OUT_OF_MEMORY);
+    }
+
+    if (!mImageArray[level].isRenderableFormat() || (!mTexStorage && !isSamplerComplete()))
+    {
+        mImageArray[level].copy(xoffset, yoffset, x, y, width, height, renderTarget);
+        mDirtyImages = true;
+    }
+    else
+    {
+        if (!mTexStorage || !mTexStorage->isRenderTarget())
+        {
+            convertToRenderTarget();
+        }
+        
+        updateTexture();
+
+        if (level < levelCount())
+        {
+            RECT sourceRect;
+            sourceRect.left = x;
+            sourceRect.right = x + width;
+            sourceRect.top = y;
+            sourceRect.bottom = y + height;
+
+            IDirect3DSurface9 *dest = mTexStorage->getSurfaceLevel(level, true);
+
+            if (dest)
+            {
+                getBlitter()->copy(renderTarget, sourceRect, 
+                                   gl::ExtractFormat(mImageArray[0].getInternalFormat()),
+                                   xoffset, yoffset, dest);
+                dest->Release();
+            }
+        }
+    }
+
+    renderTarget->Release();
+}
+
+void Texture2D::storage(GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height)
+{
+    D3DFORMAT d3dfmt = ConvertTextureInternalFormat(internalformat);
+    DWORD d3dusage = GetTextureUsage(d3dfmt, mUsage, false);
+
+    delete mTexStorage;
+    mTexStorage = new TextureStorage2D(levels, d3dfmt, d3dusage, width, height);
+    mImmutable = true;
+
+    for (int level = 0; level < levels; level++)
+    {
+        mImageArray[level].redefine(internalformat, width, height, true);
+        width = std::max(1, width >> 1);
+        height = std::max(1, height >> 1);
+    }
+
+    for (int level = levels; level < IMPLEMENTATION_MAX_TEXTURE_LEVELS; level++)
+    {
+        mImageArray[level].redefine(GL_NONE, 0, 0, true);
+    }
+
+    if (mTexStorage->isManaged())
+    {
+        int levels = levelCount();
+
+        for (int level = 0; level < levels; level++)
+        {
+            IDirect3DSurface9 *surface = mTexStorage->getSurfaceLevel(level, false);
+            mImageArray[level].setManagedSurface(surface);
+        }
+    }
+}
+
+// Tests for 2D texture sampling completeness. [OpenGL ES 2.0.24] section 3.8.2 page 85.
+bool Texture2D::isSamplerComplete() const
+{
+    GLsizei width = mImageArray[0].getWidth();
+    GLsizei height = mImageArray[0].getHeight();
+
+    if (width <= 0 || height <= 0)
+    {
+        return false;
+    }
+
+    bool mipmapping = false;
+
+    switch (mMinFilter)
+    {
+      case GL_NEAREST:
+      case GL_LINEAR:
+        mipmapping = false;
+        break;
+      case GL_NEAREST_MIPMAP_NEAREST:
+      case GL_LINEAR_MIPMAP_NEAREST:
+      case GL_NEAREST_MIPMAP_LINEAR:
+      case GL_LINEAR_MIPMAP_LINEAR:
+        mipmapping = true;
+        break;
+      default: UNREACHABLE();
+    }
+
+    if ((IsFloat32Format(getInternalFormat(0)) && !getContext()->supportsFloat32LinearFilter()) ||
+        (IsFloat16Format(getInternalFormat(0)) && !getContext()->supportsFloat16LinearFilter()))
+    {
+        if (mMagFilter != GL_NEAREST || (mMinFilter != GL_NEAREST && mMinFilter != GL_NEAREST_MIPMAP_NEAREST))
+        {
+            return false;
+        }
+    }
+
+    bool npotSupport = getContext()->supportsNonPower2Texture();
+
+    if (!npotSupport)
+    {
+        if ((getWrapS() != GL_CLAMP_TO_EDGE && !isPow2(width)) ||
+            (getWrapT() != GL_CLAMP_TO_EDGE && !isPow2(height)))
+        {
+            return false;
+        }
+    }
+
+    if (mipmapping)
+    {
+        if (!npotSupport)
+        {
+            if (!isPow2(width) || !isPow2(height))
+            {
+                return false;
+            }
+        }
+
+        if (!isMipmapComplete())
+        {
+            return false;
+        }
+    }
+
+    return true;
+}
+
+// Tests for 2D texture (mipmap) completeness. [OpenGL ES 2.0.24] section 3.7.10 page 81.
+bool Texture2D::isMipmapComplete() const
+{
+    if (isImmutable())
+    {
+        return true;
+    }
+
+    GLsizei width = mImageArray[0].getWidth();
+    GLsizei height = mImageArray[0].getHeight();
+
+    if (width <= 0 || height <= 0)
+    {
+        return false;
+    }
+
+    int q = log2(std::max(width, height));
+
+    for (int level = 1; level <= q; level++)
+    {
+        if (mImageArray[level].getInternalFormat() != mImageArray[0].getInternalFormat())
+        {
+            return false;
+        }
+
+        if (mImageArray[level].getWidth() != std::max(1, width >> level))
+        {
+            return false;
+        }
+
+        if (mImageArray[level].getHeight() != std::max(1, height >> level))
+        {
+            return false;
+        }
+    }
+
+    return true;
+}
+
+bool Texture2D::isCompressed(GLint level) const
+{
+    return IsCompressed(getInternalFormat(level));
+}
+
+bool Texture2D::isDepth(GLint level) const
+{
+    return IsDepthTexture(getInternalFormat(level));
+}
+
+IDirect3DBaseTexture9 *Texture2D::getBaseTexture() const
+{
+    return mTexStorage ? mTexStorage->getBaseTexture() : NULL;
+}
+
+// Constructs a Direct3D 9 texture resource from the texture images
+void Texture2D::createTexture()
+{
+    GLsizei width = mImageArray[0].getWidth();
+    GLsizei height = mImageArray[0].getHeight();
+
+    if (!(width > 0 && height > 0))
+        return; // do not attempt to create d3d textures for nonexistant data
+
+    GLint levels = creationLevels(width, height);
+    D3DFORMAT d3dfmt = mImageArray[0].getD3DFormat();
+    DWORD d3dusage = GetTextureUsage(d3dfmt, mUsage, false);
+
+    delete mTexStorage;
+    mTexStorage = new TextureStorage2D(levels, d3dfmt, d3dusage, width, height);
+    
+    if (mTexStorage->isManaged())
+    {
+        int levels = levelCount();
+
+        for (int level = 0; level < levels; level++)
+        {
+            IDirect3DSurface9 *surface = mTexStorage->getSurfaceLevel(level, false);
+            mImageArray[level].setManagedSurface(surface);
+        }
+    }
+
+    mDirtyImages = true;
+}
+
+void Texture2D::updateTexture()
+{
+    int levels = levelCount();
+
+    for (int level = 0; level < levels; level++)
+    {
+        Image *image = &mImageArray[level];
+
+        if (image->isDirty())
+        {
+            commitRect(level, 0, 0, mImageArray[level].getWidth(), mImageArray[level].getHeight());
+        }
+    }
+}
+
+void Texture2D::convertToRenderTarget()
+{
+    TextureStorage2D *newTexStorage = NULL;
+
+    if (mImageArray[0].getWidth() != 0 && mImageArray[0].getHeight() != 0)
+    {
+        GLsizei width = mImageArray[0].getWidth();
+        GLsizei height = mImageArray[0].getHeight();
+        GLint levels = creationLevels(width, height);
+        D3DFORMAT d3dfmt = mImageArray[0].getD3DFormat();
+        DWORD d3dusage = GetTextureUsage(d3dfmt, GL_FRAMEBUFFER_ATTACHMENT_ANGLE, true);
+
+        newTexStorage = new TextureStorage2D(levels, d3dfmt, d3dusage, width, height);
+
+        if (mTexStorage != NULL)
+        {
+            int levels = levelCount();
+            for (int i = 0; i < levels; i++)
+            {
+                IDirect3DSurface9 *source = mTexStorage->getSurfaceLevel(i, false);
+                IDirect3DSurface9 *dest = newTexStorage->getSurfaceLevel(i, true);
+
+                if (!copyToRenderTarget(dest, source, mTexStorage->isManaged()))
+                {   
+                   delete newTexStorage;
+                   if (source) source->Release();
+                   if (dest) dest->Release();
+                   return error(GL_OUT_OF_MEMORY);
+                }
+
+                if (source) source->Release();
+                if (dest) dest->Release();
+            }
+        }
+    }
+
+    delete mTexStorage;
+    mTexStorage = newTexStorage;
+
+    mDirtyImages = true;
+}
+
+void Texture2D::generateMipmaps()
+{
+    if (!getContext()->supportsNonPower2Texture())
+    {
+        if (!isPow2(mImageArray[0].getWidth()) || !isPow2(mImageArray[0].getHeight()))
+        {
+            return error(GL_INVALID_OPERATION);
+        }
+    }
+
+    // Purge array levels 1 through q and reset them to represent the generated mipmap levels.
+    unsigned int q = log2(std::max(mImageArray[0].getWidth(), mImageArray[0].getHeight()));
+    for (unsigned int i = 1; i <= q; i++)
+    {
+        redefineImage(i, mImageArray[0].getInternalFormat(), 
+                         std::max(mImageArray[0].getWidth() >> i, 1),
+                         std::max(mImageArray[0].getHeight() >> i, 1));
+    }
+
+    if (mTexStorage && mTexStorage->isRenderTarget())
+    {
+        for (unsigned int i = 1; i <= q; i++)
+        {
+            IDirect3DSurface9 *upper = mTexStorage->getSurfaceLevel(i - 1, false);
+            IDirect3DSurface9 *lower = mTexStorage->getSurfaceLevel(i, true);
+
+            if (upper != NULL && lower != NULL)
+            {
+                getBlitter()->boxFilter(upper, lower);
+            }
+
+            if (upper != NULL) upper->Release();
+            if (lower != NULL) lower->Release();
+
+            mImageArray[i].markClean();
+        }
+    }
+    else
+    {
+        for (unsigned int i = 1; i <= q; i++)
+        {
+            if (mImageArray[i].getSurface() == NULL)
+            {
+                return error(GL_OUT_OF_MEMORY);
+            }
+
+            GenerateMip(mImageArray[i].getSurface(), mImageArray[i - 1].getSurface());
+
+            mImageArray[i].markDirty();
+        }
+    }
+}
+
+Renderbuffer *Texture2D::getRenderbuffer(GLenum target)
+{
+    if (target != GL_TEXTURE_2D)
+    {
+        return error(GL_INVALID_OPERATION, (Renderbuffer *)NULL);
+    }
+
+    if (mColorbufferProxy == NULL)
+    {
+        mColorbufferProxy = new Renderbuffer(id(), new RenderbufferTexture2D(this, target));
+    }
+
+    return mColorbufferProxy;
+}
+
+// Increments refcount on surface.
+// caller must Release() the returned surface
+IDirect3DSurface9 *Texture2D::getRenderTarget(GLenum target)
+{
+    ASSERT(target == GL_TEXTURE_2D);
+
+    // ensure the underlying texture is created
+    if (getStorage(true) == NULL)
+    {
+        return NULL;
+    }
+
+    updateTexture();
+    
+    // ensure this is NOT a depth texture
+    if (isDepth(0))
+    {
+        return NULL;
+    }
+    return mTexStorage->getSurfaceLevel(0, false);
+}
+
+// Increments refcount on surface.
+// caller must Release() the returned surface
+IDirect3DSurface9 *Texture2D::getDepthStencil(GLenum target)
+{
+    ASSERT(target == GL_TEXTURE_2D);
+
+    // ensure the underlying texture is created
+    if (getStorage(true) == NULL)
+    {
+        return NULL;
+    }
+
+    updateTexture();
+
+    // ensure this is actually a depth texture
+    if (!isDepth(0))
+    {
+        return NULL;
+    }
+    return mTexStorage->getSurfaceLevel(0, false);
+}
+
+TextureStorage *Texture2D::getStorage(bool renderTarget)
+{
+    if (!mTexStorage || (renderTarget && !mTexStorage->isRenderTarget()))
+    {
+        if (renderTarget)
+        {
+            convertToRenderTarget();
+        }
+        else
+        {
+            createTexture();
+        }
+    }
+
+    return mTexStorage;
+}
+
+TextureStorageCubeMap::TextureStorageCubeMap(int levels, D3DFORMAT format, DWORD usage, int size)
+    : TextureStorage(usage), mFirstRenderTargetSerial(RenderbufferStorage::issueCubeSerials())
+{
+    mTexture = NULL;
+    // if the size is not positive this should be treated as an incomplete texture
+    // we handle that here by skipping the d3d texture creation
+    if (size > 0)
+    {
+        IDirect3DDevice9 *device = getDevice();
+        int height = size;
+        MakeValidSize(false, dx::IsCompressedFormat(format), &size, &height, &mLodOffset);
+        HRESULT result = device->CreateCubeTexture(size, levels ? levels + mLodOffset : 0, getUsage(), format, getPool(), &mTexture, NULL);
+
+        if (FAILED(result))
+        {
+            ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
+            error(GL_OUT_OF_MEMORY);
+        }
+    }
+}
+
+TextureStorageCubeMap::~TextureStorageCubeMap()
+{
+    if (mTexture)
+    {
+        mTexture->Release();
+    }
+}
+
+// Increments refcount on surface.
+// caller must Release() the returned surface
+IDirect3DSurface9 *TextureStorageCubeMap::getCubeMapSurface(GLenum faceTarget, int level, bool dirty)
+{
+    IDirect3DSurface9 *surface = NULL;
+
+    if (mTexture)
+    {
+        D3DCUBEMAP_FACES face = es2dx::ConvertCubeFace(faceTarget);
+        HRESULT result = mTexture->GetCubeMapSurface(face, level + mLodOffset, &surface);
+        ASSERT(SUCCEEDED(result));
+
+        // With managed textures the driver needs to be informed of updates to the lower mipmap levels
+        if (level != 0 && isManaged() && dirty)
+        {
+            mTexture->AddDirtyRect(face, NULL);
+        }
+    }
+
+    return surface;
+}
+
+IDirect3DBaseTexture9 *TextureStorageCubeMap::getBaseTexture() const
+{
+    return mTexture;
+}
+
+unsigned int TextureStorageCubeMap::getRenderTargetSerial(GLenum target) const
+{
+    return mFirstRenderTargetSerial + TextureCubeMap::faceIndex(target);
+}
+
+TextureCubeMap::TextureCubeMap(GLuint id) : Texture(id)
+{
+    mTexStorage = NULL;
+    for (int i = 0; i < 6; i++)
+    {
+        mFaceProxies[i] = NULL;
+        mFaceProxyRefs[i] = 0;
+    }
+}
+
+TextureCubeMap::~TextureCubeMap()
+{
+    for (int i = 0; i < 6; i++)
+    {
+        mFaceProxies[i] = NULL;
+    }
+
+    delete mTexStorage;
+    mTexStorage = NULL;
+}
+
+// We need to maintain a count of references to renderbuffers acting as 
+// proxies for this texture, so that the texture is not deleted while 
+// proxy references still exist. If the reference count drops to zero,
+// we set our proxy pointer NULL, so that a new attempt at referencing
+// will cause recreation.
+void TextureCubeMap::addProxyRef(const Renderbuffer *proxy)
+{
+    for (int i = 0; i < 6; i++)
+    {
+        if (mFaceProxies[i] == proxy)
+            mFaceProxyRefs[i]++;
+    }
+}
+
+void TextureCubeMap::releaseProxy(const Renderbuffer *proxy)
+{
+    for (int i = 0; i < 6; i++)
+    {
+        if (mFaceProxies[i] == proxy)
+        {
+            if (mFaceProxyRefs[i] > 0)
+                mFaceProxyRefs[i]--;
+
+            if (mFaceProxyRefs[i] == 0)
+                mFaceProxies[i] = NULL;
+        }
+    }
+}
+
+GLenum TextureCubeMap::getTarget() const
+{
+    return GL_TEXTURE_CUBE_MAP;
+}
+
+GLsizei TextureCubeMap::getWidth(GLenum target, GLint level) const
+{
+    if (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS)
+        return mImageArray[faceIndex(target)][level].getWidth();
+    else
+        return 0;
+}
+
+GLsizei TextureCubeMap::getHeight(GLenum target, GLint level) const
+{
+    if (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS)
+        return mImageArray[faceIndex(target)][level].getHeight();
+    else
+        return 0;
+}
+
+GLenum TextureCubeMap::getInternalFormat(GLenum target, GLint level) const
+{
+    if (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS)
+        return mImageArray[faceIndex(target)][level].getInternalFormat();
+    else
+        return GL_NONE;
+}
+
+D3DFORMAT TextureCubeMap::getD3DFormat(GLenum target, GLint level) const
+{
+    if (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS)
+        return mImageArray[faceIndex(target)][level].getD3DFormat();
+    else
+        return D3DFMT_UNKNOWN;
+}
+
+void TextureCubeMap::setImagePosX(GLint level, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels)
+{
+    setImage(0, level, width, height, format, type, unpackAlignment, pixels);
+}
+
+void TextureCubeMap::setImageNegX(GLint level, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels)
+{
+    setImage(1, level, width, height, format, type, unpackAlignment, pixels);
+}
+
+void TextureCubeMap::setImagePosY(GLint level, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels)
+{
+    setImage(2, level, width, height, format, type, unpackAlignment, pixels);
+}
+
+void TextureCubeMap::setImageNegY(GLint level, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels)
+{
+    setImage(3, level, width, height, format, type, unpackAlignment, pixels);
+}
+
+void TextureCubeMap::setImagePosZ(GLint level, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels)
+{
+    setImage(4, level, width, height, format, type, unpackAlignment, pixels);
+}
+
+void TextureCubeMap::setImageNegZ(GLint level, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels)
+{
+    setImage(5, level, width, height, format, type, unpackAlignment, pixels);
+}
+
+void TextureCubeMap::setCompressedImage(GLenum face, GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei imageSize, const void *pixels)
+{
+    // compressed formats don't have separate sized internal formats-- we can just use the compressed format directly
+    redefineImage(faceIndex(face), level, format, width, height);
+
+    Texture::setCompressedImage(imageSize, pixels, &mImageArray[faceIndex(face)][level]);
+}
+
+void TextureCubeMap::commitRect(int face, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height)
+{
+    ASSERT(mImageArray[face][level].getSurface() != NULL);
+
+    if (level < levelCount())
+    {
+        IDirect3DSurface9 *destLevel = mTexStorage->getCubeMapSurface(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, level, true);
+        ASSERT(destLevel != NULL);
+
+        if (destLevel != NULL)
+        {
+            Image *image = &mImageArray[face][level];
+            image->updateSurface(destLevel, xoffset, yoffset, width, height);
+
+            destLevel->Release();
+            image->markClean();
+        }
+    }
+}
+
+void TextureCubeMap::subImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels)
+{
+    if (Texture::subImage(xoffset, yoffset, width, height, format, type, unpackAlignment, pixels, &mImageArray[faceIndex(target)][level]))
+    {
+        commitRect(faceIndex(target), level, xoffset, yoffset, width, height);
+    }
+}
+
+void TextureCubeMap::subImageCompressed(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *pixels)
+{
+    if (Texture::subImageCompressed(xoffset, yoffset, width, height, format, imageSize, pixels, &mImageArray[faceIndex(target)][level]))
+    {
+        commitRect(faceIndex(target), level, xoffset, yoffset, width, height);
+    }
+}
+
+// Tests for cube map sampling completeness. [OpenGL ES 2.0.24] section 3.8.2 page 86.
+bool TextureCubeMap::isSamplerComplete() const
+{
+    int size = mImageArray[0][0].getWidth();
+
+    bool mipmapping;
+
+    switch (mMinFilter)
+    {
+      case GL_NEAREST:
+      case GL_LINEAR:
+        mipmapping = false;
+        break;
+      case GL_NEAREST_MIPMAP_NEAREST:
+      case GL_LINEAR_MIPMAP_NEAREST:
+      case GL_NEAREST_MIPMAP_LINEAR:
+      case GL_LINEAR_MIPMAP_LINEAR:
+        mipmapping = true;
+        break;
+      default:
+        UNREACHABLE();
+        return false;
+    }
+
+    if ((gl::ExtractType(getInternalFormat(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0)) == GL_FLOAT && !getContext()->supportsFloat32LinearFilter()) ||
+        (gl::ExtractType(getInternalFormat(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0) == GL_HALF_FLOAT_OES) && !getContext()->supportsFloat16LinearFilter()))
+    {
+        if (mMagFilter != GL_NEAREST || (mMinFilter != GL_NEAREST && mMinFilter != GL_NEAREST_MIPMAP_NEAREST))
+        {
+            return false;
+        }
+    }
+
+    if (!isPow2(size) && !getContext()->supportsNonPower2Texture())
+    {
+        if (getWrapS() != GL_CLAMP_TO_EDGE || getWrapT() != GL_CLAMP_TO_EDGE || mipmapping)
+        {
+            return false;
+        }
+    }
+
+    if (!mipmapping)
+    {
+        if (!isCubeComplete())
+        {
+            return false;
+        }
+    }
+    else
+    {
+        if (!isMipmapCubeComplete())   // Also tests for isCubeComplete()
+        {
+            return false;
+        }
+    }
+
+    return true;
+}
+
+// Tests for cube texture completeness. [OpenGL ES 2.0.24] section 3.7.10 page 81.
+bool TextureCubeMap::isCubeComplete() const
+{
+    if (mImageArray[0][0].getWidth() <= 0 || mImageArray[0][0].getHeight() != mImageArray[0][0].getWidth())
+    {
+        return false;
+    }
+
+    for (unsigned int face = 1; face < 6; face++)
+    {
+        if (mImageArray[face][0].getWidth() != mImageArray[0][0].getWidth() ||
+            mImageArray[face][0].getWidth() != mImageArray[0][0].getHeight() ||
+            mImageArray[face][0].getInternalFormat() != mImageArray[0][0].getInternalFormat())
+        {
+            return false;
+        }
+    }
+
+    return true;
+}
+
+bool TextureCubeMap::isMipmapCubeComplete() const
+{
+    if (isImmutable())
+    {
+        return true;
+    }
+
+    if (!isCubeComplete())
+    {
+        return false;
+    }
+
+    GLsizei size = mImageArray[0][0].getWidth();
+
+    int q = log2(size);
+
+    for (int face = 0; face < 6; face++)
+    {
+        for (int level = 1; level <= q; level++)
+        {
+            if (mImageArray[face][level].getInternalFormat() != mImageArray[0][0].getInternalFormat())
+            {
+                return false;
+            }
+
+            if (mImageArray[face][level].getWidth() != std::max(1, size >> level))
+            {
+                return false;
+            }
+        }
+    }
+
+    return true;
+}
+
+bool TextureCubeMap::isCompressed(GLenum target, GLint level) const
+{
+    return IsCompressed(getInternalFormat(target, level));
+}
+
+IDirect3DBaseTexture9 *TextureCubeMap::getBaseTexture() const
+{
+    return mTexStorage ? mTexStorage->getBaseTexture() : NULL;
+}
+
+// Constructs a Direct3D 9 texture resource from the texture images, or returns an existing one
+void TextureCubeMap::createTexture()
+{
+    GLsizei size = mImageArray[0][0].getWidth();
+
+    if (!(size > 0))
+        return; // do not attempt to create d3d textures for nonexistant data
+
+    GLint levels = creationLevels(size);
+    D3DFORMAT d3dfmt = mImageArray[0][0].getD3DFormat();
+    DWORD d3dusage = GetTextureUsage(d3dfmt, mUsage, false);
+
+    delete mTexStorage;
+    mTexStorage = new TextureStorageCubeMap(levels, d3dfmt, d3dusage, size);
+
+    if (mTexStorage->isManaged())
+    {
+        int levels = levelCount();
+
+        for (int face = 0; face < 6; face++)
+        {
+            for (int level = 0; level < levels; level++)
+            {
+                IDirect3DSurface9 *surface = mTexStorage->getCubeMapSurface(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, level, false);
+                mImageArray[face][level].setManagedSurface(surface);
+            }
+        }
+    }
+
+    mDirtyImages = true;
+}
+
+void TextureCubeMap::updateTexture()
+{
+    for (int face = 0; face < 6; face++)
+    {
+        int levels = levelCount();
+        for (int level = 0; level < levels; level++)
+        {
+            Image *image = &mImageArray[face][level];
+
+            if (image->isDirty())
+            {
+                commitRect(face, level, 0, 0, image->getWidth(), image->getHeight());
+            }
+        }
+    }
+}
+
+void TextureCubeMap::convertToRenderTarget()
+{
+    TextureStorageCubeMap *newTexStorage = NULL;
+
+    if (mImageArray[0][0].getWidth() != 0)
+    {
+        GLsizei size = mImageArray[0][0].getWidth();
+        GLint levels = creationLevels(size);
+        D3DFORMAT d3dfmt = mImageArray[0][0].getD3DFormat();
+        DWORD d3dusage = GetTextureUsage(d3dfmt, GL_FRAMEBUFFER_ATTACHMENT_ANGLE, true);
+
+        newTexStorage = new TextureStorageCubeMap(levels, d3dfmt, d3dusage, size);
+
+        if (mTexStorage != NULL)
+        {
+            int levels = levelCount();
+            for (int f = 0; f < 6; f++)
+            {
+                for (int i = 0; i < levels; i++)
+                {
+                    IDirect3DSurface9 *source = mTexStorage->getCubeMapSurface(GL_TEXTURE_CUBE_MAP_POSITIVE_X + f, i, false);
+                    IDirect3DSurface9 *dest = newTexStorage->getCubeMapSurface(GL_TEXTURE_CUBE_MAP_POSITIVE_X + f, i, true);
+
+                    if (!copyToRenderTarget(dest, source, mTexStorage->isManaged()))
+                    {
+                       delete newTexStorage;
+                       if (source) source->Release();
+                       if (dest) dest->Release();
+                       return error(GL_OUT_OF_MEMORY);
+                    }
+
+                    if (source) source->Release();
+                    if (dest) dest->Release();
+                }
+            }
+        }
+    }
+
+    delete mTexStorage;
+    mTexStorage = newTexStorage;
+
+    mDirtyImages = true;
+}
+
+void TextureCubeMap::setImage(int faceIndex, GLint level, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels)
+{
+    GLint internalformat = ConvertSizedInternalFormat(format, type);
+    redefineImage(faceIndex, level, internalformat, width, height);
+
+    Texture::setImage(unpackAlignment, pixels, &mImageArray[faceIndex][level]);
+}
+
+unsigned int TextureCubeMap::faceIndex(GLenum face)
+{
+    META_ASSERT(GL_TEXTURE_CUBE_MAP_NEGATIVE_X - GL_TEXTURE_CUBE_MAP_POSITIVE_X == 1);
+    META_ASSERT(GL_TEXTURE_CUBE_MAP_POSITIVE_Y - GL_TEXTURE_CUBE_MAP_POSITIVE_X == 2);
+    META_ASSERT(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y - GL_TEXTURE_CUBE_MAP_POSITIVE_X == 3);
+    META_ASSERT(GL_TEXTURE_CUBE_MAP_POSITIVE_Z - GL_TEXTURE_CUBE_MAP_POSITIVE_X == 4);
+    META_ASSERT(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z - GL_TEXTURE_CUBE_MAP_POSITIVE_X == 5);
+
+    return face - GL_TEXTURE_CUBE_MAP_POSITIVE_X;
+}
+
+void TextureCubeMap::redefineImage(int face, GLint level, GLint internalformat, GLsizei width, GLsizei height)
+{
+    bool redefined = mImageArray[face][level].redefine(internalformat, width, height, false);
+
+    if (mTexStorage && redefined)
+    {
+        for (int i = 0; i < IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++)
+        {
+            for (int f = 0; f < 6; f++)
+            {
+                mImageArray[f][i].markDirty();
+            }
+        }
+
+        delete mTexStorage;
+        mTexStorage = NULL;
+
+        mDirtyImages = true;
+    }
+}
+
+void TextureCubeMap::copyImage(GLenum target, GLint level, GLenum format, GLint x, GLint y, GLsizei width, GLsizei height, Framebuffer *source)
+{
+    IDirect3DSurface9 *renderTarget = source->getRenderTarget();
+
+    if (!renderTarget)
+    {
+        ERR("Failed to retrieve the render target.");
+        return error(GL_OUT_OF_MEMORY);
+    }
+
+    unsigned int faceindex = faceIndex(target);
+    GLint internalformat = gl::ConvertSizedInternalFormat(format, GL_UNSIGNED_BYTE);
+    redefineImage(faceindex, level, internalformat, width, height);
+
+    if (!mImageArray[faceindex][level].isRenderableFormat())
+    {
+        mImageArray[faceindex][level].copy(0, 0, x, y, width, height, renderTarget);
+        mDirtyImages = true;
+    }
+    else
+    {
+        if (!mTexStorage || !mTexStorage->isRenderTarget())
+        {
+            convertToRenderTarget();
+        }
+        
+        mImageArray[faceindex][level].markClean();
+
+        ASSERT(width == height);
+
+        if (width > 0 && level < levelCount())
+        {
+            RECT sourceRect;
+            sourceRect.left = x;
+            sourceRect.right = x + width;
+            sourceRect.top = y;
+            sourceRect.bottom = y + height;
+
+            IDirect3DSurface9 *dest = mTexStorage->getCubeMapSurface(target, level, true);
+
+            if (dest)
+            {
+                getBlitter()->copy(renderTarget, sourceRect, format, 0, 0, dest);
+                dest->Release();
+            }
+        }
+    }
+
+    renderTarget->Release();
+}
+
+void TextureCubeMap::copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height, Framebuffer *source)
+{
+    GLsizei size = mImageArray[faceIndex(target)][level].getWidth();
+
+    if (xoffset + width > size || yoffset + height > size)
+    {
+        return error(GL_INVALID_VALUE);
+    }
+
+    IDirect3DSurface9 *renderTarget = source->getRenderTarget();
+
+    if (!renderTarget)
+    {
+        ERR("Failed to retrieve the render target.");
+        return error(GL_OUT_OF_MEMORY);
+    }
+
+    unsigned int faceindex = faceIndex(target);
+
+    if (!mImageArray[faceindex][level].isRenderableFormat() || (!mTexStorage && !isSamplerComplete()))
+    {
+        mImageArray[faceindex][level].copy(0, 0, x, y, width, height, renderTarget);
+        mDirtyImages = true;
+    }
+    else
+    {
+        if (!mTexStorage || !mTexStorage->isRenderTarget())
+        {
+            convertToRenderTarget();
+        }
+        
+        updateTexture();
+
+        if (level < levelCount())
+        {
+            RECT sourceRect;
+            sourceRect.left = x;
+            sourceRect.right = x + width;
+            sourceRect.top = y;
+            sourceRect.bottom = y + height;
+
+            IDirect3DSurface9 *dest = mTexStorage->getCubeMapSurface(target, level, true);
+
+            if (dest)
+            {
+                getBlitter()->copy(renderTarget, sourceRect, gl::ExtractFormat(mImageArray[0][0].getInternalFormat()), xoffset, yoffset, dest);
+                dest->Release();
+            }
+        }
+    }
+
+    renderTarget->Release();
+}
+
+void TextureCubeMap::storage(GLsizei levels, GLenum internalformat, GLsizei size)
+{
+    D3DFORMAT d3dfmt = ConvertTextureInternalFormat(internalformat);
+    DWORD d3dusage = GetTextureUsage(d3dfmt, mUsage, false);
+
+    delete mTexStorage;
+    mTexStorage = new TextureStorageCubeMap(levels, d3dfmt, d3dusage, size);
+    mImmutable = true;
+
+    for (int level = 0; level < levels; level++)
+    {
+        for (int face = 0; face < 6; face++)
+        {
+            mImageArray[face][level].redefine(internalformat, size, size, true);
+            size = std::max(1, size >> 1);
+        }
+    }
+
+    for (int level = levels; level < IMPLEMENTATION_MAX_TEXTURE_LEVELS; level++)
+    {
+        for (int face = 0; face < 6; face++)
+        {
+            mImageArray[face][level].redefine(GL_NONE, 0, 0, true);
+        }
+    }
+
+    if (mTexStorage->isManaged())
+    {
+        int levels = levelCount();
+
+        for (int face = 0; face < 6; face++)
+        {
+            for (int level = 0; level < levels; level++)
+            {
+                IDirect3DSurface9 *surface = mTexStorage->getCubeMapSurface(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, level, false);
+                mImageArray[face][level].setManagedSurface(surface);
+            }
+        }
+    }
+}
+
+void TextureCubeMap::generateMipmaps()
+{
+    if (!isCubeComplete())
+    {
+        return error(GL_INVALID_OPERATION);
+    }
+
+    if (!getContext()->supportsNonPower2Texture())
+    {
+        if (!isPow2(mImageArray[0][0].getWidth()))
+        {
+            return error(GL_INVALID_OPERATION);
+        }
+    }
+
+    // Purge array levels 1 through q and reset them to represent the generated mipmap levels.
+    unsigned int q = log2(mImageArray[0][0].getWidth());
+    for (unsigned int f = 0; f < 6; f++)
+    {
+        for (unsigned int i = 1; i <= q; i++)
+        {
+            redefineImage(f, i, mImageArray[f][0].getInternalFormat(),
+                                std::max(mImageArray[f][0].getWidth() >> i, 1),
+                                std::max(mImageArray[f][0].getWidth() >> i, 1));
+        }
+    }
+
+    if (mTexStorage && mTexStorage->isRenderTarget())
+    {
+        for (unsigned int f = 0; f < 6; f++)
+        {
+            for (unsigned int i = 1; i <= q; i++)
+            {
+                IDirect3DSurface9 *upper = mTexStorage->getCubeMapSurface(GL_TEXTURE_CUBE_MAP_POSITIVE_X + f, i - 1, false);
+                IDirect3DSurface9 *lower = mTexStorage->getCubeMapSurface(GL_TEXTURE_CUBE_MAP_POSITIVE_X + f, i, true);
+
+                if (upper != NULL && lower != NULL)
+                {
+                    getBlitter()->boxFilter(upper, lower);
+                }
+
+                if (upper != NULL) upper->Release();
+                if (lower != NULL) lower->Release();
+
+                mImageArray[f][i].markClean();
+            }
+        }
+    }
+    else
+    {
+        for (unsigned int f = 0; f < 6; f++)
+        {
+            for (unsigned int i = 1; i <= q; i++)
+            {
+                if (mImageArray[f][i].getSurface() == NULL)
+                {
+                    return error(GL_OUT_OF_MEMORY);
+                }
+
+                GenerateMip(mImageArray[f][i].getSurface(), mImageArray[f][i - 1].getSurface());
+
+                mImageArray[f][i].markDirty();
+            }
+        }
+    }
+}
+
+Renderbuffer *TextureCubeMap::getRenderbuffer(GLenum target)
+{
+    if (!IsCubemapTextureTarget(target))
+    {
+        return error(GL_INVALID_OPERATION, (Renderbuffer *)NULL);
+    }
+
+    unsigned int face = faceIndex(target);
+
+    if (mFaceProxies[face] == NULL)
+    {
+        mFaceProxies[face] = new Renderbuffer(id(), new RenderbufferTextureCubeMap(this, target));
+    }
+
+    return mFaceProxies[face];
+}
+
+// Increments refcount on surface.
+// caller must Release() the returned surface
+IDirect3DSurface9 *TextureCubeMap::getRenderTarget(GLenum target)
+{
+    ASSERT(IsCubemapTextureTarget(target));
+
+    // ensure the underlying texture is created
+    if (getStorage(true) == NULL)
+    {
+        return NULL;
+    }
+
+    updateTexture();
+    
+    return mTexStorage->getCubeMapSurface(target, 0, false);
+}
+
+TextureStorage *TextureCubeMap::getStorage(bool renderTarget)
+{
+    if (!mTexStorage || (renderTarget && !mTexStorage->isRenderTarget()))
+    {
+        if (renderTarget)
+        {
+            convertToRenderTarget();
+        }
+        else
+        {
+            createTexture();
+        }
+    }
+
+    return mTexStorage;
+}
+
+}
diff --git a/src/3rdparty/angle/src/libGLESv2/Texture.h b/src/3rdparty/angle/src/libGLESv2/Texture.h
new file mode 100644 (file)
index 0000000..7d7378f
--- /dev/null
@@ -0,0 +1,433 @@
+//
+// 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.
+//
+
+// Texture.h: Defines the abstract gl::Texture class and its concrete derived
+// classes Texture2D and TextureCubeMap. Implements GL texture objects and
+// related functionality. [OpenGL ES 2.0.24] section 3.7 page 63.
+
+#ifndef LIBGLESV2_TEXTURE_H_
+#define LIBGLESV2_TEXTURE_H_
+
+#include <vector>
+
+#define GL_APICALL
+#include <GLES2/gl2.h>
+#include <d3d9.h>
+
+#include "common/debug.h"
+#include "common/RefCountObject.h"
+#include "libGLESv2/Renderbuffer.h"
+#include "libGLESv2/utilities.h"
+
+namespace egl
+{
+class Surface;
+}
+
+namespace gl
+{
+class Blit;
+class Framebuffer;
+
+enum
+{
+    // These are the maximums the implementation can support
+    // The actual GL caps are limited by the device caps
+    // and should be queried from the Context
+    IMPLEMENTATION_MAX_TEXTURE_SIZE = 16384,
+    IMPLEMENTATION_MAX_CUBE_MAP_TEXTURE_SIZE = 16384,
+
+    IMPLEMENTATION_MAX_TEXTURE_LEVELS = 15   // 1+log2 of MAX_TEXTURE_SIZE
+};
+
+class Image
+{
+  public:
+    Image();
+    ~Image();
+
+    bool redefine(GLint internalformat, GLsizei width, GLsizei height, bool forceRelease);
+    void markDirty() {mDirty = true;}
+    void markClean() {mDirty = false;}
+
+    bool isRenderableFormat() const;
+    D3DFORMAT getD3DFormat() const;
+
+    GLsizei getWidth() const {return mWidth;}
+    GLsizei getHeight() const {return mHeight;}
+    GLenum getInternalFormat() const {return mInternalFormat;}
+    bool isDirty() const {return mSurface && mDirty;}
+    IDirect3DSurface9 *getSurface();
+
+    void setManagedSurface(IDirect3DSurface9 *surface);
+    void updateSurface(IDirect3DSurface9 *dest, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height);
+
+    void loadData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
+                  GLint unpackAlignment, const void *input);
+
+    void loadAlphaData(GLsizei width, GLsizei height,
+                       int inputPitch, const void *input, size_t outputPitch, void *output) const;
+    void loadAlphaDataSSE2(GLsizei width, GLsizei height,
+                           int inputPitch, const void *input, size_t outputPitch, void *output) const;
+    void loadAlphaFloatData(GLsizei width, GLsizei height,
+                            int inputPitch, const void *input, size_t outputPitch, void *output) const;
+    void loadAlphaHalfFloatData(GLsizei width, GLsizei height,
+                                int inputPitch, const void *input, size_t outputPitch, void *output) const;
+    void loadLuminanceData(GLsizei width, GLsizei height,
+                           int inputPitch, const void *input, size_t outputPitch, void *output, bool native) const;
+    void loadLuminanceFloatData(GLsizei width, GLsizei height,
+                                int inputPitch, const void *input, size_t outputPitch, void *output) const;
+    void loadLuminanceHalfFloatData(GLsizei width, GLsizei height,
+                                    int inputPitch, const void *input, size_t outputPitch, void *output) const;
+    void loadLuminanceAlphaData(GLsizei width, GLsizei height,
+                                int inputPitch, const void *input, size_t outputPitch, void *output, bool native) const;
+    void loadLuminanceAlphaFloatData(GLsizei width, GLsizei height,
+                                     int inputPitch, const void *input, size_t outputPitch, void *output) const;
+    void loadLuminanceAlphaHalfFloatData(GLsizei width, GLsizei height,
+                                         int inputPitch, const void *input, size_t outputPitch, void *output) const;
+    void loadRGBUByteData(GLsizei width, GLsizei height,
+                          int inputPitch, const void *input, size_t outputPitch, void *output) const;
+    void loadRGB565Data(GLsizei width, GLsizei height,
+                        int inputPitch, const void *input, size_t outputPitch, void *output) const;
+    void loadRGBFloatData(GLsizei width, GLsizei height,
+                          int inputPitch, const void *input, size_t outputPitch, void *output) const;
+    void loadRGBHalfFloatData(GLsizei width, GLsizei height,
+                              int inputPitch, const void *input, size_t outputPitch, void *output) const;
+    void loadRGBAUByteDataSSE2(GLsizei width, GLsizei height,
+                               int inputPitch, const void *input, size_t outputPitch, void *output) const;
+    void loadRGBAUByteData(GLsizei width, GLsizei height,
+                           int inputPitch, const void *input, size_t outputPitch, void *output) const;
+    void loadRGBA4444Data(GLsizei width, GLsizei height,
+                          int inputPitch, const void *input, size_t outputPitch, void *output) const;
+    void loadRGBA5551Data(GLsizei width, GLsizei height,
+                          int inputPitch, const void *input, size_t outputPitch, void *output) const;
+    void loadRGBAFloatData(GLsizei width, GLsizei height,
+                           int inputPitch, const void *input, size_t outputPitch, void *output) const;
+    void loadRGBAHalfFloatData(GLsizei width, GLsizei height,
+                               int inputPitch, const void *input, size_t outputPitch, void *output) const;
+    void loadBGRAData(GLsizei width, GLsizei height,
+                      int inputPitch, const void *input, size_t outputPitch, void *output) const;
+    void loadCompressedData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
+                            const void *input);
+
+    void copy(GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height, IDirect3DSurface9 *renderTarget);
+
+  private:
+    DISALLOW_COPY_AND_ASSIGN(Image);
+
+    void createSurface();
+
+    HRESULT lock(D3DLOCKED_RECT *lockedRect, const RECT *rect);
+    void unlock();
+
+    GLsizei mWidth;
+    GLsizei mHeight;
+    GLint mInternalFormat;
+
+    bool mDirty;
+
+    D3DPOOL mD3DPool;   // can only be D3DPOOL_SYSTEMMEM or D3DPOOL_MANAGED since it needs to be lockable.
+    D3DFORMAT mD3DFormat;
+
+    IDirect3DSurface9 *mSurface;
+};
+
+class TextureStorage
+{
+  public:
+    explicit TextureStorage(DWORD usage);
+
+    virtual ~TextureStorage();
+
+    bool isRenderTarget() const;
+    bool isManaged() const;
+    D3DPOOL getPool() const;
+    DWORD getUsage() const;
+    unsigned int getTextureSerial() const;
+    virtual unsigned int getRenderTargetSerial(GLenum target) const = 0;
+    int getLodOffset() const;
+
+  protected:
+    int mLodOffset;
+
+  private:
+    DISALLOW_COPY_AND_ASSIGN(TextureStorage);
+
+    const DWORD mD3DUsage;
+    const D3DPOOL mD3DPool;
+
+    const unsigned int mTextureSerial;
+    static unsigned int issueTextureSerial();
+
+    static unsigned int mCurrentTextureSerial;
+};
+
+class Texture : public RefCountObject
+{
+  public:
+    explicit Texture(GLuint id);
+
+    virtual ~Texture();
+
+    virtual void addProxyRef(const Renderbuffer *proxy) = 0;
+    virtual void releaseProxy(const Renderbuffer *proxy) = 0;
+
+    virtual GLenum getTarget() const = 0;
+
+    bool setMinFilter(GLenum filter);
+    bool setMagFilter(GLenum filter);
+    bool setWrapS(GLenum wrap);
+    bool setWrapT(GLenum wrap);
+    bool setMaxAnisotropy(float textureMaxAnisotropy, float contextMaxAnisotropy);
+    bool setUsage(GLenum usage);
+
+    GLenum getMinFilter() const;
+    GLenum getMagFilter() const;
+    GLenum getWrapS() const;
+    GLenum getWrapT() const;
+    float getMaxAnisotropy() const;
+    GLenum getUsage() const;
+
+    virtual bool isSamplerComplete() const = 0;
+
+    IDirect3DBaseTexture9 *getTexture();
+    virtual Renderbuffer *getRenderbuffer(GLenum target) = 0;
+
+    virtual void generateMipmaps() = 0;
+    virtual void copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height, Framebuffer *source) = 0;
+
+    bool hasDirtyParameters() const;
+    bool hasDirtyImages() const;
+    void resetDirty();
+    unsigned int getTextureSerial();
+    unsigned int getRenderTargetSerial(GLenum target);
+
+    bool isImmutable() const;
+    int getLodOffset();
+
+    static const GLuint INCOMPLETE_TEXTURE_ID = static_cast<GLuint>(-1);   // Every texture takes an id at creation time. The value is arbitrary because it is never registered with the resource manager.
+
+  protected:
+    void setImage(GLint unpackAlignment, const void *pixels, Image *image);
+    bool subImage(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels, Image *image);
+    void setCompressedImage(GLsizei imageSize, const void *pixels, Image *image);
+    bool subImageCompressed(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *pixels, Image *image);
+
+    GLint creationLevels(GLsizei width, GLsizei height) const;
+    GLint creationLevels(GLsizei size) const;
+
+    virtual IDirect3DBaseTexture9 *getBaseTexture() const = 0;
+    virtual void createTexture() = 0;
+    virtual void updateTexture() = 0;
+    virtual void convertToRenderTarget() = 0;
+    virtual IDirect3DSurface9 *getRenderTarget(GLenum target) = 0;
+
+    int levelCount();
+
+    static Blit *getBlitter();
+    static bool copyToRenderTarget(IDirect3DSurface9 *dest, IDirect3DSurface9 *source, bool fromManaged);
+
+    GLenum mMinFilter;
+    GLenum mMagFilter;
+    GLenum mWrapS;
+    GLenum mWrapT;
+    float mMaxAnisotropy;
+    bool mDirtyParameters;
+    GLenum mUsage;
+
+    bool mDirtyImages;
+
+    bool mImmutable;
+
+  private:
+    DISALLOW_COPY_AND_ASSIGN(Texture);
+
+    virtual TextureStorage *getStorage(bool renderTarget) = 0;
+};
+
+class TextureStorage2D : public TextureStorage
+{
+  public:
+    explicit TextureStorage2D(IDirect3DTexture9 *surfaceTexture);
+    TextureStorage2D(int levels, D3DFORMAT format, DWORD usage, int width, int height);
+
+    virtual ~TextureStorage2D();
+
+    IDirect3DSurface9 *getSurfaceLevel(int level, bool dirty);
+    IDirect3DBaseTexture9 *getBaseTexture() const;
+
+    virtual unsigned int getRenderTargetSerial(GLenum target) const;
+
+  private:
+    DISALLOW_COPY_AND_ASSIGN(TextureStorage2D);
+
+    IDirect3DTexture9 *mTexture;
+    const unsigned int mRenderTargetSerial;
+};
+
+class Texture2D : public Texture
+{
+  public:
+    explicit Texture2D(GLuint id);
+
+    ~Texture2D();
+
+    void addProxyRef(const Renderbuffer *proxy);
+    void releaseProxy(const Renderbuffer *proxy);
+
+    virtual GLenum getTarget() const;
+
+    GLsizei getWidth(GLint level) const;
+    GLsizei getHeight(GLint level) const;
+    GLenum getInternalFormat(GLint level) const;
+    D3DFORMAT getD3DFormat(GLint level) const;
+    bool isCompressed(GLint level) const;
+    bool isDepth(GLint level) const;
+
+    void setImage(GLint level, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels);
+    void setCompressedImage(GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei imageSize, const void *pixels);
+    void subImage(GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels);
+    void subImageCompressed(GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *pixels);
+    void copyImage(GLint level, GLenum format, GLint x, GLint y, GLsizei width, GLsizei height, Framebuffer *source);
+    virtual void copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height, Framebuffer *source);
+    void storage(GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height);
+
+    virtual bool isSamplerComplete() const;
+    virtual void bindTexImage(egl::Surface *surface);
+    virtual void releaseTexImage();
+
+    virtual void generateMipmaps();
+
+    virtual Renderbuffer *getRenderbuffer(GLenum target);
+
+  protected:
+    friend class RenderbufferTexture2D;
+    virtual IDirect3DSurface9 *getRenderTarget(GLenum target);
+    virtual IDirect3DSurface9 *getDepthStencil(GLenum target);
+
+  private:
+    DISALLOW_COPY_AND_ASSIGN(Texture2D);
+
+    virtual IDirect3DBaseTexture9 *getBaseTexture() const;
+    virtual void createTexture();
+    virtual void updateTexture();
+    virtual void convertToRenderTarget();
+    virtual TextureStorage *getStorage(bool renderTarget);
+
+    bool isMipmapComplete() const;
+
+    void redefineImage(GLint level, GLint internalformat, GLsizei width, GLsizei height);
+    void commitRect(GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height);
+
+    Image mImageArray[IMPLEMENTATION_MAX_TEXTURE_LEVELS];
+
+    TextureStorage2D *mTexStorage;
+    egl::Surface *mSurface;
+
+    // A specific internal reference count is kept for colorbuffer proxy references,
+    // because, as the renderbuffer acting as proxy will maintain a binding pointer
+    // back to this texture, there would be a circular reference if we used a binding
+    // pointer here. This reference count will cause the pointer to be set to NULL if
+    // the count drops to zero, but will not cause deletion of the Renderbuffer.
+    Renderbuffer *mColorbufferProxy;
+    unsigned int mProxyRefs;
+};
+
+class TextureStorageCubeMap : public TextureStorage
+{
+  public:
+    TextureStorageCubeMap(int levels, D3DFORMAT format, DWORD usage, int size);
+
+    virtual ~TextureStorageCubeMap();
+
+    IDirect3DSurface9 *getCubeMapSurface(GLenum faceTarget, int level, bool dirty);
+    IDirect3DBaseTexture9 *getBaseTexture() const;
+
+    virtual unsigned int getRenderTargetSerial(GLenum target) const;
+
+  private:
+    DISALLOW_COPY_AND_ASSIGN(TextureStorageCubeMap);
+
+    IDirect3DCubeTexture9 *mTexture;
+    const unsigned int mFirstRenderTargetSerial;
+};
+
+class TextureCubeMap : public Texture
+{
+  public:
+    explicit TextureCubeMap(GLuint id);
+
+    ~TextureCubeMap();
+
+    void addProxyRef(const Renderbuffer *proxy);
+    void releaseProxy(const Renderbuffer *proxy);
+
+    virtual GLenum getTarget() const;
+    
+    GLsizei getWidth(GLenum target, GLint level) const;
+    GLsizei getHeight(GLenum target, GLint level) const;
+    GLenum getInternalFormat(GLenum target, GLint level) const;
+    D3DFORMAT getD3DFormat(GLenum target, GLint level) const;
+    bool isCompressed(GLenum target, GLint level) const;
+
+    void setImagePosX(GLint level, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels);
+    void setImageNegX(GLint level, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels);
+    void setImagePosY(GLint level, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels);
+    void setImageNegY(GLint level, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels);
+    void setImagePosZ(GLint level, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels);
+    void setImageNegZ(GLint level, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels);
+
+    void setCompressedImage(GLenum face, GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei imageSize, const void *pixels);
+
+    void subImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels);
+    void subImageCompressed(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *pixels);
+    void copyImage(GLenum target, GLint level, GLenum format, GLint x, GLint y, GLsizei width, GLsizei height, Framebuffer *source);
+    virtual void copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height, Framebuffer *source);
+    void storage(GLsizei levels, GLenum internalformat, GLsizei size);
+
+    virtual bool isSamplerComplete() const;
+
+    virtual void generateMipmaps();
+
+    virtual Renderbuffer *getRenderbuffer(GLenum target);
+
+    static unsigned int faceIndex(GLenum face);
+
+  protected:
+    friend class RenderbufferTextureCubeMap;
+    virtual IDirect3DSurface9 *getRenderTarget(GLenum target);
+
+  private:
+    DISALLOW_COPY_AND_ASSIGN(TextureCubeMap);
+
+    virtual IDirect3DBaseTexture9 *getBaseTexture() const;
+    virtual void createTexture();
+    virtual void updateTexture();
+    virtual void convertToRenderTarget();
+    virtual TextureStorage *getStorage(bool renderTarget);
+
+    bool isCubeComplete() const;
+    bool isMipmapCubeComplete() const;
+
+    void setImage(int faceIndex, GLint level, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels);
+    void commitRect(int faceIndex, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height);
+    void redefineImage(int faceIndex, GLint level, GLint internalformat, GLsizei width, GLsizei height);
+
+    Image mImageArray[6][IMPLEMENTATION_MAX_TEXTURE_LEVELS];
+
+    TextureStorageCubeMap *mTexStorage;
+
+    // A specific internal reference count is kept for colorbuffer proxy references,
+    // because, as the renderbuffer acting as proxy will maintain a binding pointer
+    // back to this texture, there would be a circular reference if we used a binding
+    // pointer here. This reference count will cause the pointer to be set to NULL if
+    // the count drops to zero, but will not cause deletion of the Renderbuffer.
+    Renderbuffer *mFaceProxies[6];
+    unsigned int *mFaceProxyRefs[6];
+};
+}
+
+#endif   // LIBGLESV2_TEXTURE_H_
diff --git a/src/3rdparty/angle/src/libGLESv2/TextureSSE2.cpp b/src/3rdparty/angle/src/libGLESv2/TextureSSE2.cpp
new file mode 100644 (file)
index 0000000..48ea664
--- /dev/null
@@ -0,0 +1,100 @@
+//
+// 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.
+//
+
+// TextureSSE2.cpp: Implements SSE2-based functions of gl::Image class. It's
+// in a separated file for GCC, which can enable SSE usage only per-file,
+// not for code blocks that use SSE2 explicitly.
+
+#include "libGLESv2/Texture.h"
+
+#include <intrin.h>
+
+namespace gl
+{
+
+void Image::loadRGBAUByteDataSSE2(GLsizei width, GLsizei height,
+                                  int inputPitch, const void *input, size_t outputPitch, void *output) const
+{
+    const unsigned int *source = NULL;
+    unsigned int *dest = NULL;
+    __m128i brMask = _mm_set1_epi32(0x00ff00ff);
+
+    for (int y = 0; y < height; y++)
+    {
+        source = reinterpret_cast<const unsigned int*>(static_cast<const unsigned char*>(input) + y * inputPitch);
+        dest = reinterpret_cast<unsigned int*>(static_cast<unsigned char*>(output) + y * outputPitch);
+        int x = 0;
+
+        // Make output writes aligned
+        for (x = 0; ((reinterpret_cast<intptr_t>(&dest[x]) & 15) != 0) && x < width; x++)
+        {
+            unsigned int rgba = source[x];
+            dest[x] = (_rotl(rgba, 16) & 0x00ff00ff) | (rgba & 0xff00ff00);
+        }
+
+        for (; x + 3 < width; x += 4)
+        {
+            __m128i sourceData = _mm_loadu_si128(reinterpret_cast<const __m128i*>(&source[x]));
+            // Mask out g and a, which don't change
+            __m128i gaComponents = _mm_andnot_si128(brMask, sourceData);
+            // Mask out b and r
+            __m128i brComponents = _mm_and_si128(sourceData, brMask);
+            // Swap b and r
+            __m128i brSwapped = _mm_shufflehi_epi16(_mm_shufflelo_epi16(brComponents, _MM_SHUFFLE(2, 3, 0, 1)), _MM_SHUFFLE(2, 3, 0, 1));
+            __m128i result = _mm_or_si128(gaComponents, brSwapped);
+            _mm_store_si128(reinterpret_cast<__m128i*>(&dest[x]), result);
+        }
+
+        // Perform leftover writes
+        for (; x < width; x++)
+        {
+            unsigned int rgba = source[x];
+            dest[x] = (_rotl(rgba, 16) & 0x00ff00ff) | (rgba & 0xff00ff00);
+        }
+    }
+}
+
+void Image::loadAlphaDataSSE2(GLsizei width, GLsizei height,
+                              int inputPitch, const void *input, size_t outputPitch, void *output) const
+{
+    const unsigned char *source = NULL;
+    unsigned int *dest = NULL;
+    __m128i zeroWide = _mm_setzero_si128();
+
+    for (int y = 0; y < height; y++)
+    {
+        source = static_cast<const unsigned char*>(input) + y * inputPitch;
+        dest = reinterpret_cast<unsigned int*>(static_cast<unsigned char*>(output) + y * outputPitch);
+
+        int x;
+        // Make output writes aligned
+        for (x = 0; ((reinterpret_cast<intptr_t>(&dest[x]) & 0xF) != 0 && x < width); x++)
+        {
+            dest[x] = static_cast<unsigned int>(source[x]) << 24;
+        }
+
+        for (; x + 7 < width; x += 8)
+        {
+            __m128i sourceData = _mm_loadl_epi64(reinterpret_cast<const __m128i*>(&source[x]));
+            // Interleave each byte to 16bit, make the lower byte to zero
+            sourceData = _mm_unpacklo_epi8(zeroWide, sourceData);
+            // Interleave each 16bit to 32bit, make the lower 16bit to zero
+            __m128i lo = _mm_unpacklo_epi16(zeroWide, sourceData);
+            __m128i hi = _mm_unpackhi_epi16(zeroWide, sourceData);
+
+            _mm_store_si128(reinterpret_cast<__m128i*>(&dest[x]), lo);
+            _mm_store_si128(reinterpret_cast<__m128i*>(&dest[x + 4]), hi);
+        }
+
+        // Handle the remainder
+        for (; x < width; x++)
+        {
+            dest[x] = static_cast<unsigned int>(source[x]) << 24;
+        }
+    }
+}
+
+}
diff --git a/src/3rdparty/angle/src/libGLESv2/VertexDataManager.cpp b/src/3rdparty/angle/src/libGLESv2/VertexDataManager.cpp
new file mode 100644 (file)
index 0000000..32c4018
--- /dev/null
@@ -0,0 +1,783 @@
+//
+// 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.
+//
+
+// VertexDataManager.h: Defines the VertexDataManager, a class that
+// runs the Buffer translation process.
+
+#include "libGLESv2/VertexDataManager.h"
+
+#include "common/debug.h"
+
+#include "libGLESv2/Buffer.h"
+#include "libGLESv2/Program.h"
+#include "libGLESv2/ProgramBinary.h"
+#include "libGLESv2/main.h"
+
+#include "libGLESv2/vertexconversion.h"
+#include "libGLESv2/IndexDataManager.h"
+
+namespace
+{
+    enum { INITIAL_STREAM_BUFFER_SIZE = 1024*1024 };
+    // This has to be at least 4k or else it fails on ATI cards.
+    enum { CONSTANT_VERTEX_BUFFER_SIZE = 4096 };
+}
+
+namespace gl
+{
+unsigned int VertexBuffer::mCurrentSerial = 1;
+
+int elementsInBuffer(const VertexAttribute &attribute, int size)
+{
+    int stride = attribute.stride();
+    return (size - attribute.mOffset % stride + (stride - attribute.typeSize())) / stride;
+}
+
+VertexDataManager::VertexDataManager(Context *context, IDirect3DDevice9 *device) : mContext(context), mDevice(device)
+{
+    for (int i = 0; i < MAX_VERTEX_ATTRIBS; i++)
+    {
+        mDirtyCurrentValue[i] = true;
+        mCurrentValueBuffer[i] = NULL;
+        mCurrentValueOffsets[i] = 0;
+    }
+
+    const D3DCAPS9 &caps = context->getDeviceCaps();
+    checkVertexCaps(caps.DeclTypes);
+
+    mStreamingBuffer = new StreamingVertexBuffer(mDevice, INITIAL_STREAM_BUFFER_SIZE);
+
+    if (!mStreamingBuffer)
+    {
+        ERR("Failed to allocate the streaming vertex buffer.");
+    }
+}
+
+VertexDataManager::~VertexDataManager()
+{
+    delete mStreamingBuffer;
+
+    for (int i = 0; i < MAX_VERTEX_ATTRIBS; i++)
+    {
+        delete mCurrentValueBuffer[i];
+    }
+}
+
+std::size_t VertexDataManager::writeAttributeData(ArrayVertexBuffer *vertexBuffer, GLint start, GLsizei count, const VertexAttribute &attribute, GLsizei instances)
+{
+    Buffer *buffer = attribute.mBoundBuffer.get();
+
+    int inputStride = attribute.stride();
+    int elementSize = attribute.typeSize();
+    const FormatConverter &converter = formatConverter(attribute);
+    std::size_t streamOffset = 0;
+
+    void *output = NULL;
+    
+    if (vertexBuffer)
+    {
+        output = vertexBuffer->map(attribute, spaceRequired(attribute, count, instances), &streamOffset);
+    }
+
+    if (output == NULL)
+    {
+        ERR("Failed to map vertex buffer.");
+        return -1;
+    }
+
+    const char *input = NULL;
+
+    if (buffer)
+    {
+        int offset = attribute.mOffset;
+
+        input = static_cast<const char*>(buffer->data()) + offset;
+    }
+    else
+    {
+        input = static_cast<const char*>(attribute.mPointer);
+    }
+
+    if (instances == 0 || attribute.mDivisor == 0)
+    {
+        input += inputStride * start;
+    }
+
+    if (converter.identity && inputStride == elementSize)
+    {
+        memcpy(output, input, count * inputStride);
+    }
+    else
+    {
+        converter.convertArray(input, inputStride, count, output);
+    }
+
+    vertexBuffer->unmap();
+
+    return streamOffset;
+}
+
+GLenum VertexDataManager::prepareVertexData(GLint start, GLsizei count, TranslatedAttribute *translated, GLsizei instances)
+{
+    if (!mStreamingBuffer)
+    {
+        return GL_OUT_OF_MEMORY;
+    }
+
+    const VertexAttributeArray &attribs = mContext->getVertexAttributes();
+    ProgramBinary *programBinary = mContext->getCurrentProgramBinary();
+
+    for (int attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; attributeIndex++)
+    {
+        translated[attributeIndex].active = (programBinary->getSemanticIndex(attributeIndex) != -1);
+    }
+
+    // Determine the required storage size per used buffer, and invalidate static buffers that don't contain matching attributes
+    for (int i = 0; i < MAX_VERTEX_ATTRIBS; i++)
+    {
+        if (translated[i].active && attribs[i].mArrayEnabled)
+        {
+            Buffer *buffer = attribs[i].mBoundBuffer.get();
+            StaticVertexBuffer *staticBuffer = buffer ? buffer->getStaticVertexBuffer() : NULL;
+
+            if (staticBuffer)
+            {
+                if (staticBuffer->size() == 0)
+                {
+                    int totalCount = elementsInBuffer(attribs[i], buffer->size());
+                    staticBuffer->addRequiredSpace(spaceRequired(attribs[i], totalCount, 0));
+                }
+                else if (staticBuffer->lookupAttribute(attribs[i]) == -1)
+                {
+                    // This static buffer doesn't have matching attributes, so fall back to using the streaming buffer
+                    // Add the space of all previous attributes belonging to the invalidated static buffer to the streaming buffer
+                    for (int previous = 0; previous < i; previous++)
+                    {
+                        if (translated[previous].active && attribs[previous].mArrayEnabled)
+                        {
+                            Buffer *previousBuffer = attribs[previous].mBoundBuffer.get();
+                            StaticVertexBuffer *previousStaticBuffer = previousBuffer ? previousBuffer->getStaticVertexBuffer() : NULL;
+
+                            if (staticBuffer == previousStaticBuffer)
+                            {
+                                mStreamingBuffer->addRequiredSpace(spaceRequired(attribs[previous], count, instances));
+                            }
+                        }
+                    }
+
+                    mStreamingBuffer->addRequiredSpace(spaceRequired(attribs[i], count, instances));
+
+                    buffer->invalidateStaticData();
+                }    
+            }
+            else
+            {
+                mStreamingBuffer->addRequiredSpace(spaceRequired(attribs[i], count, instances));
+            }
+        }
+    }
+
+    // Reserve the required space per used buffer
+    for (int i = 0; i < MAX_VERTEX_ATTRIBS; i++)
+    {
+        if (translated[i].active && attribs[i].mArrayEnabled)
+        {
+            Buffer *buffer = attribs[i].mBoundBuffer.get();
+            ArrayVertexBuffer *staticBuffer = buffer ? buffer->getStaticVertexBuffer() : NULL;
+            ArrayVertexBuffer *vertexBuffer = staticBuffer ? staticBuffer : mStreamingBuffer;
+
+            if (vertexBuffer)
+            {
+                vertexBuffer->reserveRequiredSpace();
+            }
+        }
+    }
+
+    // Perform the vertex data translations
+    for (int i = 0; i < MAX_VERTEX_ATTRIBS; i++)
+    {
+        if (translated[i].active)
+        {
+            if (attribs[i].mArrayEnabled)
+            {
+                Buffer *buffer = attribs[i].mBoundBuffer.get();
+
+                if (!buffer && attribs[i].mPointer == NULL)
+                {
+                    // This is an application error that would normally result in a crash, but we catch it and return an error
+                    ERR("An enabled vertex array has no buffer and no pointer.");
+                    return GL_INVALID_OPERATION;
+                }
+
+                const FormatConverter &converter = formatConverter(attribs[i]);
+
+                StaticVertexBuffer *staticBuffer = buffer ? buffer->getStaticVertexBuffer() : NULL;
+                ArrayVertexBuffer *vertexBuffer = staticBuffer ? staticBuffer : static_cast<ArrayVertexBuffer*>(mStreamingBuffer);
+
+                std::size_t streamOffset = -1;
+
+                if (staticBuffer)
+                {
+                    streamOffset = staticBuffer->lookupAttribute(attribs[i]);
+
+                    if (streamOffset == -1)
+                    {
+                        // Convert the entire buffer
+                        int totalCount = elementsInBuffer(attribs[i], buffer->size());
+                        int startIndex = attribs[i].mOffset / attribs[i].stride();
+
+                        streamOffset = writeAttributeData(staticBuffer, -startIndex, totalCount, attribs[i], 0);
+                    }
+
+                    if (streamOffset != -1)
+                    {
+                        streamOffset += (attribs[i].mOffset / attribs[i].stride()) * converter.outputElementSize;
+
+                        if (instances == 0 || attribs[i].mDivisor == 0)
+                        {
+                            streamOffset += start * converter.outputElementSize;
+                        }
+                    }
+                }
+                else
+                {
+                    streamOffset = writeAttributeData(mStreamingBuffer, start, count, attribs[i], instances);
+                }
+
+                if (streamOffset == -1)
+                {
+                    return GL_OUT_OF_MEMORY;
+                }
+
+                translated[i].vertexBuffer = vertexBuffer->getBuffer();
+                translated[i].serial = vertexBuffer->getSerial();
+                translated[i].divisor = attribs[i].mDivisor;
+
+                translated[i].type = converter.d3dDeclType;
+                translated[i].stride = converter.outputElementSize;
+                translated[i].offset = streamOffset;
+            }
+            else
+            {
+                if (!mCurrentValueBuffer[i])
+                {
+                    mCurrentValueBuffer[i] = new StreamingVertexBuffer(mDevice, CONSTANT_VERTEX_BUFFER_SIZE);
+                }
+
+                StreamingVertexBuffer *buffer = mCurrentValueBuffer[i];
+
+                if (mDirtyCurrentValue[i])
+                {
+                    const int requiredSpace = 4 * sizeof(float);
+                    buffer->addRequiredSpace(requiredSpace);
+                    buffer->reserveRequiredSpace();
+                    float *data = static_cast<float*>(buffer->map(VertexAttribute(), requiredSpace, &mCurrentValueOffsets[i]));
+                    if (data)
+                    {
+                        data[0] = attribs[i].mCurrentValue[0];
+                        data[1] = attribs[i].mCurrentValue[1];
+                        data[2] = attribs[i].mCurrentValue[2];
+                        data[3] = attribs[i].mCurrentValue[3];
+                        buffer->unmap();
+                        mDirtyCurrentValue[i] = false;
+                    }
+                }
+
+                translated[i].vertexBuffer = mCurrentValueBuffer[i]->getBuffer();
+                translated[i].serial = mCurrentValueBuffer[i]->getSerial();
+                translated[i].divisor = 0;
+
+                translated[i].type = D3DDECLTYPE_FLOAT4;
+                translated[i].stride = 0;
+                translated[i].offset = mCurrentValueOffsets[i];
+            }
+        }
+    }
+
+    for (int i = 0; i < MAX_VERTEX_ATTRIBS; i++)
+    {
+        if (translated[i].active && attribs[i].mArrayEnabled)
+        {
+            Buffer *buffer = attribs[i].mBoundBuffer.get();
+
+            if (buffer)
+            {
+                buffer->promoteStaticUsage(count * attribs[i].typeSize());
+            }
+        }
+    }
+
+    return GL_NO_ERROR;
+}
+
+std::size_t VertexDataManager::spaceRequired(const VertexAttribute &attrib, std::size_t count, GLsizei instances) const
+{
+    size_t elementSize = formatConverter(attrib).outputElementSize;
+
+    if (instances == 0 || attrib.mDivisor == 0)
+    {
+        return elementSize * count;
+    }
+    else
+    {
+        return elementSize * ((instances + attrib.mDivisor - 1) / attrib.mDivisor);
+    }
+}
+
+// Mapping from OpenGL-ES vertex attrib type to D3D decl type:
+//
+// BYTE                 SHORT (Cast)
+// BYTE-norm            FLOAT (Normalize) (can't be exactly represented as SHORT-norm)
+// UNSIGNED_BYTE        UBYTE4 (Identity) or SHORT (Cast)
+// UNSIGNED_BYTE-norm   UBYTE4N (Identity) or FLOAT (Normalize)
+// SHORT                SHORT (Identity)
+// SHORT-norm           SHORT-norm (Identity) or FLOAT (Normalize)
+// UNSIGNED_SHORT       FLOAT (Cast)
+// UNSIGNED_SHORT-norm  USHORT-norm (Identity) or FLOAT (Normalize)
+// FIXED (not in WebGL) FLOAT (FixedToFloat)
+// FLOAT                FLOAT (Identity)
+
+// GLToCType maps from GL type (as GLenum) to the C typedef. 
+template <GLenum GLType> struct GLToCType { };
+
+template <> struct GLToCType<GL_BYTE> { typedef GLbyte type; };
+template <> struct GLToCType<GL_UNSIGNED_BYTE> { typedef GLubyte type; };
+template <> struct GLToCType<GL_SHORT> { typedef GLshort type; };
+template <> struct GLToCType<GL_UNSIGNED_SHORT> { typedef GLushort type; };
+template <> struct GLToCType<GL_FIXED> { typedef GLuint type; };
+template <> struct GLToCType<GL_FLOAT> { typedef GLfloat type; };
+
+// This differs from D3DDECLTYPE in that it is unsized. (Size expansion is applied last.)
+enum D3DVertexType
+{
+    D3DVT_FLOAT,
+    D3DVT_SHORT,
+    D3DVT_SHORT_NORM,
+    D3DVT_UBYTE,
+    D3DVT_UBYTE_NORM,
+    D3DVT_USHORT_NORM
+};
+
+// D3DToCType maps from D3D vertex type (as enum D3DVertexType) to the corresponding C type.
+template <unsigned int D3DType> struct D3DToCType { };
+
+template <> struct D3DToCType<D3DVT_FLOAT> { typedef float type; };
+template <> struct D3DToCType<D3DVT_SHORT> { typedef short type; };
+template <> struct D3DToCType<D3DVT_SHORT_NORM> { typedef short type; };
+template <> struct D3DToCType<D3DVT_UBYTE> { typedef unsigned char type; };
+template <> struct D3DToCType<D3DVT_UBYTE_NORM> { typedef unsigned char type; };
+template <> struct D3DToCType<D3DVT_USHORT_NORM> { typedef unsigned short type; };
+
+// Encode the type/size combinations that D3D permits. For each type/size it expands to a widener that will provide the appropriate final size.
+template <unsigned int type, int size>
+struct WidenRule
+{
+};
+
+template <int size> struct WidenRule<D3DVT_FLOAT, size>          : gl::NoWiden<size> { };
+template <int size> struct WidenRule<D3DVT_SHORT, size>          : gl::WidenToEven<size> { };
+template <int size> struct WidenRule<D3DVT_SHORT_NORM, size>     : gl::WidenToEven<size> { };
+template <int size> struct WidenRule<D3DVT_UBYTE, size>          : gl::WidenToFour<size> { };
+template <int size> struct WidenRule<D3DVT_UBYTE_NORM, size>     : gl::WidenToFour<size> { };
+template <int size> struct WidenRule<D3DVT_USHORT_NORM, size>    : gl::WidenToEven<size> { };
+
+// VertexTypeFlags encodes the D3DCAPS9::DeclType flag and vertex declaration flag for each D3D vertex type & size combination.
+template <unsigned int d3dtype, int size>
+struct VertexTypeFlags
+{
+};
+
+template <unsigned int _capflag, unsigned int _declflag>
+struct VertexTypeFlagsHelper
+{
+    enum { capflag = _capflag };
+    enum { declflag = _declflag };
+};
+
+template <> struct VertexTypeFlags<D3DVT_FLOAT, 1> : VertexTypeFlagsHelper<0, D3DDECLTYPE_FLOAT1> { };
+template <> struct VertexTypeFlags<D3DVT_FLOAT, 2> : VertexTypeFlagsHelper<0, D3DDECLTYPE_FLOAT2> { };
+template <> struct VertexTypeFlags<D3DVT_FLOAT, 3> : VertexTypeFlagsHelper<0, D3DDECLTYPE_FLOAT3> { };
+template <> struct VertexTypeFlags<D3DVT_FLOAT, 4> : VertexTypeFlagsHelper<0, D3DDECLTYPE_FLOAT4> { };
+template <> struct VertexTypeFlags<D3DVT_SHORT, 2> : VertexTypeFlagsHelper<0, D3DDECLTYPE_SHORT2> { };
+template <> struct VertexTypeFlags<D3DVT_SHORT, 4> : VertexTypeFlagsHelper<0, D3DDECLTYPE_SHORT4> { };
+template <> struct VertexTypeFlags<D3DVT_SHORT_NORM, 2> : VertexTypeFlagsHelper<D3DDTCAPS_SHORT2N, D3DDECLTYPE_SHORT2N> { };
+template <> struct VertexTypeFlags<D3DVT_SHORT_NORM, 4> : VertexTypeFlagsHelper<D3DDTCAPS_SHORT4N, D3DDECLTYPE_SHORT4N> { };
+template <> struct VertexTypeFlags<D3DVT_UBYTE, 4> : VertexTypeFlagsHelper<D3DDTCAPS_UBYTE4, D3DDECLTYPE_UBYTE4> { };
+template <> struct VertexTypeFlags<D3DVT_UBYTE_NORM, 4> : VertexTypeFlagsHelper<D3DDTCAPS_UBYTE4N, D3DDECLTYPE_UBYTE4N> { };
+template <> struct VertexTypeFlags<D3DVT_USHORT_NORM, 2> : VertexTypeFlagsHelper<D3DDTCAPS_USHORT2N, D3DDECLTYPE_USHORT2N> { };
+template <> struct VertexTypeFlags<D3DVT_USHORT_NORM, 4> : VertexTypeFlagsHelper<D3DDTCAPS_USHORT4N, D3DDECLTYPE_USHORT4N> { };
+
+
+// VertexTypeMapping maps GL type & normalized flag to preferred and fallback D3D vertex types (as D3DVertexType enums).
+template <GLenum GLtype, bool normalized>
+struct VertexTypeMapping
+{
+};
+
+template <D3DVertexType Preferred, D3DVertexType Fallback = Preferred>
+struct VertexTypeMappingBase
+{
+    enum { preferred = Preferred };
+    enum { fallback = Fallback };
+};
+
+template <> struct VertexTypeMapping<GL_BYTE, false>                        : VertexTypeMappingBase<D3DVT_SHORT> { };                       // Cast
+template <> struct VertexTypeMapping<GL_BYTE, true>                         : VertexTypeMappingBase<D3DVT_FLOAT> { };                       // Normalize
+template <> struct VertexTypeMapping<GL_UNSIGNED_BYTE, false>               : VertexTypeMappingBase<D3DVT_UBYTE, D3DVT_FLOAT> { };          // Identity, Cast
+template <> struct VertexTypeMapping<GL_UNSIGNED_BYTE, true>                : VertexTypeMappingBase<D3DVT_UBYTE_NORM, D3DVT_FLOAT> { };     // Identity, Normalize
+template <> struct VertexTypeMapping<GL_SHORT, false>                       : VertexTypeMappingBase<D3DVT_SHORT> { };                       // Identity
+template <> struct VertexTypeMapping<GL_SHORT, true>                        : VertexTypeMappingBase<D3DVT_SHORT_NORM, D3DVT_FLOAT> { };     // Cast, Normalize
+template <> struct VertexTypeMapping<GL_UNSIGNED_SHORT, false>              : VertexTypeMappingBase<D3DVT_FLOAT> { };                       // Cast
+template <> struct VertexTypeMapping<GL_UNSIGNED_SHORT, true>               : VertexTypeMappingBase<D3DVT_USHORT_NORM, D3DVT_FLOAT> { };    // Cast, Normalize
+template <bool normalized> struct VertexTypeMapping<GL_FIXED, normalized>   : VertexTypeMappingBase<D3DVT_FLOAT> { };                       // FixedToFloat
+template <bool normalized> struct VertexTypeMapping<GL_FLOAT, normalized>   : VertexTypeMappingBase<D3DVT_FLOAT> { };                       // Identity
+
+
+// Given a GL type & norm flag and a D3D type, ConversionRule provides the type conversion rule (Cast, Normalize, Identity, FixedToFloat).
+// The conversion rules themselves are defined in vertexconversion.h.
+
+// Almost all cases are covered by Cast (including those that are actually Identity since Cast<T,T> knows it's an identity mapping).
+template <GLenum fromType, bool normalized, unsigned int toType>
+struct ConversionRule : gl::Cast<typename GLToCType<fromType>::type, typename D3DToCType<toType>::type>
+{
+};
+
+// All conversions from normalized types to float use the Normalize operator.
+template <GLenum fromType> struct ConversionRule<fromType, true, D3DVT_FLOAT> : gl::Normalize<typename GLToCType<fromType>::type> { };
+
+// Use a full specialisation for this so that it preferentially matches ahead of the generic normalize-to-float rules.
+template <> struct ConversionRule<GL_FIXED, true, D3DVT_FLOAT> : gl::FixedToFloat<GLint, 16> { };
+template <> struct ConversionRule<GL_FIXED, false, D3DVT_FLOAT> : gl::FixedToFloat<GLint, 16> { };
+
+// A 2-stage construction is used for DefaultVertexValues because float must use SimpleDefaultValues (i.e. 0/1)
+// whether it is normalized or not.
+template <class T, bool normalized>
+struct DefaultVertexValuesStage2
+{
+};
+
+template <class T> struct DefaultVertexValuesStage2<T, true>  : gl::NormalizedDefaultValues<T> { };
+template <class T> struct DefaultVertexValuesStage2<T, false> : gl::SimpleDefaultValues<T> { };
+
+// Work out the default value rule for a D3D type (expressed as the C type) and 
+template <class T, bool normalized>
+struct DefaultVertexValues : DefaultVertexValuesStage2<T, normalized>
+{
+};
+
+template <bool normalized> struct DefaultVertexValues<float, normalized> : gl::SimpleDefaultValues<float> { };
+
+// Policy rules for use with Converter, to choose whether to use the preferred or fallback conversion.
+// The fallback conversion produces an output that all D3D9 devices must support.
+template <class T> struct UsePreferred { enum { type = T::preferred }; };
+template <class T> struct UseFallback { enum { type = T::fallback }; };
+
+// Converter ties it all together. Given an OpenGL type/norm/size and choice of preferred/fallback conversion,
+// it provides all the members of the appropriate VertexDataConverter, the D3DCAPS9::DeclTypes flag in cap flag
+// and the D3DDECLTYPE member needed for the vertex declaration in declflag.
+template <GLenum fromType, bool normalized, int size, template <class T> class PreferenceRule>
+struct Converter
+    : gl::VertexDataConverter<typename GLToCType<fromType>::type,
+                              WidenRule<PreferenceRule< VertexTypeMapping<fromType, normalized> >::type, size>,
+                              ConversionRule<fromType,
+                                             normalized,
+                                             PreferenceRule< VertexTypeMapping<fromType, normalized> >::type>,
+                              DefaultVertexValues<typename D3DToCType<PreferenceRule< VertexTypeMapping<fromType, normalized> >::type>::type, normalized > >
+{
+private:
+    enum { d3dtype = PreferenceRule< VertexTypeMapping<fromType, normalized> >::type };
+    enum { d3dsize = WidenRule<d3dtype, size>::finalWidth };
+
+public:
+    enum { capflag = VertexTypeFlags<d3dtype, d3dsize>::capflag };
+    enum { declflag = VertexTypeFlags<d3dtype, d3dsize>::declflag };
+};
+
+// Initialise a TranslationInfo
+#define TRANSLATION(type, norm, size, preferred)                                    \
+    {                                                                               \
+        Converter<type, norm, size, preferred>::identity,                           \
+        Converter<type, norm, size, preferred>::finalSize,                          \
+        Converter<type, norm, size, preferred>::convertArray,                       \
+        static_cast<D3DDECLTYPE>(Converter<type, norm, size, preferred>::declflag)  \
+    }
+
+#define TRANSLATION_FOR_TYPE_NORM_SIZE(type, norm, size)    \
+    {                                                       \
+        Converter<type, norm, size, UsePreferred>::capflag, \
+        TRANSLATION(type, norm, size, UsePreferred),        \
+        TRANSLATION(type, norm, size, UseFallback)          \
+    }
+
+#define TRANSLATIONS_FOR_TYPE(type)                                                                                                                                                                         \
+    {                                                                                                                                                                                                       \
+        { TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 1), TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 2), TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 3), TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 4) }, \
+        { TRANSLATION_FOR_TYPE_NORM_SIZE(type, true, 1), TRANSLATION_FOR_TYPE_NORM_SIZE(type, true, 2), TRANSLATION_FOR_TYPE_NORM_SIZE(type, true, 3), TRANSLATION_FOR_TYPE_NORM_SIZE(type, true, 4) },     \
+    }
+
+#define TRANSLATIONS_FOR_TYPE_NO_NORM(type)                                                                                                                                                                 \
+    {                                                                                                                                                                                                       \
+        { TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 1), TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 2), TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 3), TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 4) }, \
+        { TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 1), TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 2), TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 3), TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 4) }, \
+    }
+
+const VertexDataManager::TranslationDescription VertexDataManager::mPossibleTranslations[NUM_GL_VERTEX_ATTRIB_TYPES][2][4] = // [GL types as enumerated by typeIndex()][normalized][size-1]
+{
+    TRANSLATIONS_FOR_TYPE(GL_BYTE),
+    TRANSLATIONS_FOR_TYPE(GL_UNSIGNED_BYTE),
+    TRANSLATIONS_FOR_TYPE(GL_SHORT),
+    TRANSLATIONS_FOR_TYPE(GL_UNSIGNED_SHORT),
+    TRANSLATIONS_FOR_TYPE_NO_NORM(GL_FIXED),
+    TRANSLATIONS_FOR_TYPE_NO_NORM(GL_FLOAT)
+};
+
+void VertexDataManager::checkVertexCaps(DWORD declTypes)
+{
+    for (unsigned int i = 0; i < NUM_GL_VERTEX_ATTRIB_TYPES; i++)
+    {
+        for (unsigned int j = 0; j < 2; j++)
+        {
+            for (unsigned int k = 0; k < 4; k++)
+            {
+                if (mPossibleTranslations[i][j][k].capsFlag == 0 || (declTypes & mPossibleTranslations[i][j][k].capsFlag) != 0)
+                {
+                    mAttributeTypes[i][j][k] = mPossibleTranslations[i][j][k].preferredConversion;
+                }
+                else
+                {
+                    mAttributeTypes[i][j][k] = mPossibleTranslations[i][j][k].fallbackConversion;
+                }
+            }
+        }
+    }
+}
+
+// This is used to index mAttributeTypes and mPossibleTranslations.
+unsigned int VertexDataManager::typeIndex(GLenum type) const
+{
+    switch (type)
+    {
+      case GL_BYTE: return 0;
+      case GL_UNSIGNED_BYTE: return 1;
+      case GL_SHORT: return 2;
+      case GL_UNSIGNED_SHORT: return 3;
+      case GL_FIXED: return 4;
+      case GL_FLOAT: return 5;
+
+      default: UNREACHABLE(); return 5;
+    }
+}
+
+VertexBuffer::VertexBuffer(IDirect3DDevice9 *device, std::size_t size, DWORD usageFlags) : mDevice(device), mVertexBuffer(NULL)
+{
+    if (size > 0)
+    {
+        D3DPOOL pool = getDisplay()->getBufferPool(usageFlags);
+        HRESULT result = device->CreateVertexBuffer(size, usageFlags, 0, pool, &mVertexBuffer, NULL);
+        mSerial = issueSerial();
+        
+        if (FAILED(result))
+        {
+            ERR("Out of memory allocating a vertex buffer of size %lu.", size);
+        }
+    }
+}
+
+VertexBuffer::~VertexBuffer()
+{
+    if (mVertexBuffer)
+    {
+        mVertexBuffer->Release();
+    }
+}
+
+void VertexBuffer::unmap()
+{
+    if (mVertexBuffer)
+    {
+        mVertexBuffer->Unlock();
+    }
+}
+
+IDirect3DVertexBuffer9 *VertexBuffer::getBuffer() const
+{
+    return mVertexBuffer;
+}
+
+unsigned int VertexBuffer::getSerial() const
+{
+    return mSerial;
+}
+
+unsigned int VertexBuffer::issueSerial()
+{
+    return mCurrentSerial++;
+}
+
+ArrayVertexBuffer::ArrayVertexBuffer(IDirect3DDevice9 *device, std::size_t size, DWORD usageFlags) : VertexBuffer(device, size, usageFlags)
+{
+    mBufferSize = size;
+    mWritePosition = 0;
+    mRequiredSpace = 0;
+}
+
+ArrayVertexBuffer::~ArrayVertexBuffer()
+{
+}
+
+void ArrayVertexBuffer::addRequiredSpace(UINT requiredSpace)
+{
+    mRequiredSpace += requiredSpace;
+}
+
+StreamingVertexBuffer::StreamingVertexBuffer(IDirect3DDevice9 *device, std::size_t initialSize) : ArrayVertexBuffer(device, initialSize, D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY)
+{
+}
+
+StreamingVertexBuffer::~StreamingVertexBuffer()
+{
+}
+
+void *StreamingVertexBuffer::map(const VertexAttribute &attribute, std::size_t requiredSpace, std::size_t *offset)
+{
+    void *mapPtr = NULL;
+
+    if (mVertexBuffer)
+    {
+        HRESULT result = mVertexBuffer->Lock(mWritePosition, requiredSpace, &mapPtr, D3DLOCK_NOOVERWRITE);
+        
+        if (FAILED(result))
+        {
+            ERR("Lock failed with error 0x%08x", result);
+            return NULL;
+        }
+
+        *offset = mWritePosition;
+        mWritePosition += requiredSpace;
+    }
+
+    return mapPtr;
+}
+
+void StreamingVertexBuffer::reserveRequiredSpace()
+{
+    if (mRequiredSpace > mBufferSize)
+    {
+        if (mVertexBuffer)
+        {
+            mVertexBuffer->Release();
+            mVertexBuffer = NULL;
+        }
+
+        mBufferSize = std::max(mRequiredSpace, 3 * mBufferSize / 2);   // 1.5 x mBufferSize is arbitrary and should be checked to see we don't have too many reallocations.
+
+        D3DPOOL pool = getDisplay()->getBufferPool(D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY);
+        HRESULT result = mDevice->CreateVertexBuffer(mBufferSize, D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY, 0, pool, &mVertexBuffer, NULL);
+        mSerial = issueSerial();
+    
+        if (FAILED(result))
+        {
+            ERR("Out of memory allocating a vertex buffer of size %lu.", mBufferSize);
+        }
+
+        mWritePosition = 0;
+    }
+    else if (mWritePosition + mRequiredSpace > mBufferSize)   // Recycle
+    {
+        if (mVertexBuffer)
+        {
+            void *dummy;
+            mVertexBuffer->Lock(0, 1, &dummy, D3DLOCK_DISCARD);
+            mVertexBuffer->Unlock();
+        }
+
+        mWritePosition = 0;
+    }
+
+    mRequiredSpace = 0;
+}
+
+StaticVertexBuffer::StaticVertexBuffer(IDirect3DDevice9 *device) : ArrayVertexBuffer(device, 0, D3DUSAGE_WRITEONLY)
+{
+}
+
+StaticVertexBuffer::~StaticVertexBuffer()
+{
+}
+
+void *StaticVertexBuffer::map(const VertexAttribute &attribute, std::size_t requiredSpace, std::size_t *streamOffset)
+{
+    void *mapPtr = NULL;
+
+    if (mVertexBuffer)
+    {
+        HRESULT result = mVertexBuffer->Lock(mWritePosition, requiredSpace, &mapPtr, 0);
+        
+        if (FAILED(result))
+        {
+            ERR("Lock failed with error 0x%08x", result);
+            return NULL;
+        }
+
+        int attributeOffset = attribute.mOffset % attribute.stride();
+        VertexElement element = {attribute.mType, attribute.mSize, attribute.stride(), attribute.mNormalized, attributeOffset, mWritePosition};
+        mCache.push_back(element);
+
+        *streamOffset = mWritePosition;
+        mWritePosition += requiredSpace;
+    }
+
+    return mapPtr;
+}
+
+void StaticVertexBuffer::reserveRequiredSpace()
+{
+    if (!mVertexBuffer && mBufferSize == 0)
+    {
+        D3DPOOL pool = getDisplay()->getBufferPool(D3DUSAGE_WRITEONLY);
+        HRESULT result = mDevice->CreateVertexBuffer(mRequiredSpace, D3DUSAGE_WRITEONLY, 0, pool, &mVertexBuffer, NULL);
+        mSerial = issueSerial();
+
+        if (FAILED(result))
+        {
+            ERR("Out of memory allocating a vertex buffer of size %lu.", mRequiredSpace);
+        }
+
+        mBufferSize = mRequiredSpace;
+    }
+    else if (mVertexBuffer && mBufferSize >= mRequiredSpace)
+    {
+        // Already allocated
+    }
+    else UNREACHABLE();   // Static vertex buffers can't be resized
+
+    mRequiredSpace = 0;
+}
+
+std::size_t StaticVertexBuffer::lookupAttribute(const VertexAttribute &attribute)
+{
+    for (unsigned int element = 0; element < mCache.size(); element++)
+    {
+        if (mCache[element].type == attribute.mType &&
+            mCache[element].size == attribute.mSize &&
+            mCache[element].stride == attribute.stride() &&
+            mCache[element].normalized == attribute.mNormalized)
+        {
+            if (mCache[element].attributeOffset == attribute.mOffset % attribute.stride())
+            {
+                return mCache[element].streamOffset;
+            }
+        }
+    }
+
+    return -1;
+}
+
+const VertexDataManager::FormatConverter &VertexDataManager::formatConverter(const VertexAttribute &attribute) const
+{
+    return mAttributeTypes[typeIndex(attribute.mType)][attribute.mNormalized][attribute.mSize - 1];
+}
+}
diff --git a/src/3rdparty/angle/src/libGLESv2/VertexDataManager.h b/src/3rdparty/angle/src/libGLESv2/VertexDataManager.h
new file mode 100644 (file)
index 0000000..857591a
--- /dev/null
@@ -0,0 +1,169 @@
+//
+// 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.
+//
+
+// VertexDataManager.h: Defines the VertexDataManager, a class that
+// runs the Buffer translation process.
+
+#ifndef LIBGLESV2_VERTEXDATAMANAGER_H_
+#define LIBGLESV2_VERTEXDATAMANAGER_H_
+
+#include <vector>
+#include <cstddef>
+
+#define GL_APICALL
+#include <GLES2/gl2.h>
+
+#include "libGLESv2/Context.h"
+
+namespace gl
+{
+
+struct TranslatedAttribute
+{
+    bool active;
+
+    D3DDECLTYPE type;
+    UINT offset;
+    UINT stride;   // 0 means not to advance the read pointer at all
+
+    IDirect3DVertexBuffer9 *vertexBuffer;
+    unsigned int serial;
+    unsigned int divisor;
+};
+
+class VertexBuffer
+{
+  public:
+    VertexBuffer(IDirect3DDevice9 *device, std::size_t size, DWORD usageFlags);
+    virtual ~VertexBuffer();
+
+    void unmap();
+
+    IDirect3DVertexBuffer9 *getBuffer() const;
+    unsigned int getSerial() const;
+
+  protected:
+    IDirect3DDevice9 *const mDevice;
+    IDirect3DVertexBuffer9 *mVertexBuffer;
+
+    unsigned int mSerial;
+    static unsigned int issueSerial();
+    static unsigned int mCurrentSerial;
+
+  private:
+    DISALLOW_COPY_AND_ASSIGN(VertexBuffer);
+};
+
+class ArrayVertexBuffer : public VertexBuffer
+{
+  public:
+    ArrayVertexBuffer(IDirect3DDevice9 *device, std::size_t size, DWORD usageFlags);
+    ~ArrayVertexBuffer();
+
+    std::size_t size() const { return mBufferSize; }
+    virtual void *map(const VertexAttribute &attribute, std::size_t requiredSpace, std::size_t *streamOffset) = 0;
+    virtual void reserveRequiredSpace() = 0;
+    void addRequiredSpace(UINT requiredSpace);
+
+  protected:
+    std::size_t mBufferSize;
+    std::size_t mWritePosition;
+    std::size_t mRequiredSpace;
+};
+
+class StreamingVertexBuffer : public ArrayVertexBuffer
+{
+  public:
+    StreamingVertexBuffer(IDirect3DDevice9 *device, std::size_t initialSize);
+    ~StreamingVertexBuffer();
+
+    void *map(const VertexAttribute &attribute, std::size_t requiredSpace, std::size_t *streamOffset);
+    void reserveRequiredSpace();
+};
+
+class StaticVertexBuffer : public ArrayVertexBuffer
+{
+  public:
+    explicit StaticVertexBuffer(IDirect3DDevice9 *device);
+    ~StaticVertexBuffer();
+
+    void *map(const VertexAttribute &attribute, std::size_t requiredSpace, std::size_t *streamOffset);
+    void reserveRequiredSpace();
+
+    std::size_t lookupAttribute(const VertexAttribute &attribute);   // Returns the offset into the vertex buffer, or -1 if not found
+
+  private:
+    struct VertexElement
+    {
+        GLenum type;
+        GLint size;
+        GLsizei stride;
+        bool normalized;
+        int attributeOffset;
+
+        std::size_t streamOffset;
+    };
+
+    std::vector<VertexElement> mCache;
+};
+
+class VertexDataManager
+{
+  public:
+    VertexDataManager(Context *context, IDirect3DDevice9 *backend);
+    virtual ~VertexDataManager();
+
+    void dirtyCurrentValue(int index) { mDirtyCurrentValue[index] = true; }
+
+    GLenum prepareVertexData(GLint start, GLsizei count, TranslatedAttribute *outAttribs, GLsizei instances);
+
+  private:
+    DISALLOW_COPY_AND_ASSIGN(VertexDataManager);
+
+    std::size_t spaceRequired(const VertexAttribute &attrib, std::size_t count, GLsizei instances) const;
+    std::size_t writeAttributeData(ArrayVertexBuffer *vertexBuffer, GLint start, GLsizei count, const VertexAttribute &attribute, GLsizei instances);
+
+    Context *const mContext;
+    IDirect3DDevice9 *const mDevice;
+
+    StreamingVertexBuffer *mStreamingBuffer;
+
+    bool mDirtyCurrentValue[MAX_VERTEX_ATTRIBS];
+    StreamingVertexBuffer *mCurrentValueBuffer[MAX_VERTEX_ATTRIBS];
+    std::size_t mCurrentValueOffsets[MAX_VERTEX_ATTRIBS];
+
+    // Attribute format conversion
+    struct FormatConverter
+    {
+        bool identity;
+        std::size_t outputElementSize;
+        void (*convertArray)(const void *in, std::size_t stride, std::size_t n, void *out);
+        D3DDECLTYPE d3dDeclType;
+    };
+
+    enum { NUM_GL_VERTEX_ATTRIB_TYPES = 6 };
+
+    FormatConverter mAttributeTypes[NUM_GL_VERTEX_ATTRIB_TYPES][2][4];   // [GL types as enumerated by typeIndex()][normalized][size - 1]
+
+    struct TranslationDescription
+    {
+        DWORD capsFlag;
+        FormatConverter preferredConversion;
+        FormatConverter fallbackConversion;
+    };
+
+    // This table is used to generate mAttributeTypes.
+    static const TranslationDescription mPossibleTranslations[NUM_GL_VERTEX_ATTRIB_TYPES][2][4]; // [GL types as enumerated by typeIndex()][normalized][size - 1]
+
+    void checkVertexCaps(DWORD declTypes);
+
+    unsigned int typeIndex(GLenum type) const;
+    const FormatConverter &formatConverter(const VertexAttribute &attribute) const;
+};
+
+}
+
+#endif   // LIBGLESV2_VERTEXDATAMANAGER_H_
diff --git a/src/3rdparty/angle/src/libGLESv2/libGLESv2.cpp b/src/3rdparty/angle/src/libGLESv2/libGLESv2.cpp
new file mode 100644 (file)
index 0000000..16d9c17
--- /dev/null
@@ -0,0 +1,7002 @@
+//
+// 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.
+//
+
+// libGLESv2.cpp: Implements the exported OpenGL ES 2.0 functions.
+
+#define GL_APICALL
+#include <GLES2/gl2.h>
+#include <GLES2/gl2ext.h>
+
+#include <exception>
+#include <limits>
+
+#include "common/debug.h"
+#include "common/version.h"
+
+#include "libGLESv2/main.h"
+#include "libGLESv2/mathutil.h"
+#include "libGLESv2/utilities.h"
+#include "libGLESv2/Buffer.h"
+#include "libGLESv2/Context.h"
+#include "libGLESv2/Fence.h"
+#include "libGLESv2/Framebuffer.h"
+#include "libGLESv2/Program.h"
+#include "libGLESv2/ProgramBinary.h"
+#include "libGLESv2/Renderbuffer.h"
+#include "libGLESv2/Shader.h"
+#include "libGLESv2/Texture.h"
+#include "libGLESv2/Query.h"
+
+bool validImageSize(GLint level, GLsizei width, GLsizei height)
+{
+    if (level < 0 || width < 0 || height < 0)
+    {
+        return false;
+    }
+
+    if (gl::getContext() && gl::getContext()->supportsNonPower2Texture())
+    {
+        return true;
+    }
+
+    if (level == 0)
+    {
+        return true;
+    }
+
+    if (gl::isPow2(width) && gl::isPow2(height))
+    {
+        return true;
+    }
+
+    return false;
+}
+
+// Verify that format/type are one of the combinations from table 3.4.
+bool checkTextureFormatType(GLenum format, GLenum type)
+{
+    // validate <format> by itself (used as secondary key below)
+    switch (format)
+    {
+      case GL_RGBA:
+      case GL_BGRA_EXT:
+      case GL_RGB:
+      case GL_ALPHA:
+      case GL_LUMINANCE:
+      case GL_LUMINANCE_ALPHA:
+      case GL_DEPTH_COMPONENT:
+      case GL_DEPTH_STENCIL_OES:
+        break;
+      default:
+        return error(GL_INVALID_ENUM, false);
+    }
+
+    // invalid <type> -> sets INVALID_ENUM
+    // invalid <format>+<type> combination -> sets INVALID_OPERATION
+    switch (type)
+    {
+      case GL_UNSIGNED_BYTE:
+        switch (format)
+        {
+          case GL_RGBA:
+          case GL_BGRA_EXT:
+          case GL_RGB:
+          case GL_ALPHA:
+          case GL_LUMINANCE:
+          case GL_LUMINANCE_ALPHA:
+            return true;
+          default:
+            return error(GL_INVALID_OPERATION, false);
+        }
+
+      case GL_FLOAT:
+      case GL_HALF_FLOAT_OES:
+        switch (format)
+        {
+          case GL_RGBA:
+          case GL_RGB:
+          case GL_ALPHA:
+          case GL_LUMINANCE:
+          case GL_LUMINANCE_ALPHA:
+            return true;
+          default:
+            return error(GL_INVALID_OPERATION, false);
+        }
+
+      case GL_UNSIGNED_SHORT_4_4_4_4:
+      case GL_UNSIGNED_SHORT_5_5_5_1:
+        switch (format)
+        {
+          case GL_RGBA:
+            return true;
+          default:
+            return error(GL_INVALID_OPERATION, false);
+        }
+
+      case GL_UNSIGNED_SHORT_5_6_5:
+        switch (format)
+        {
+          case GL_RGB:
+            return true;
+          default:
+            return error(GL_INVALID_OPERATION, false);
+        }
+
+      case GL_UNSIGNED_SHORT:
+      case GL_UNSIGNED_INT:
+        switch (format)
+        {
+          case GL_DEPTH_COMPONENT:
+            return true;
+          default:
+            return error(GL_INVALID_OPERATION, false);
+        }
+
+      case GL_UNSIGNED_INT_24_8_OES:
+        switch (format)
+        {
+          case GL_DEPTH_STENCIL_OES:
+            return true;
+          default:
+            return error(GL_INVALID_OPERATION, false);
+        }
+
+      default:
+        return error(GL_INVALID_ENUM, false);
+    }
+}
+
+bool validateSubImageParams2D(bool compressed, GLsizei width, GLsizei height,
+                              GLint xoffset, GLint yoffset, GLint level, GLenum format, GLenum type,
+                              gl::Texture2D *texture)
+{
+    if (!texture)
+    {
+        return error(GL_INVALID_OPERATION, false);
+    }
+
+    if (compressed != texture->isCompressed(level))
+    {
+        return error(GL_INVALID_OPERATION, false);
+    }
+
+    if (format != GL_NONE)
+    {
+        GLenum internalformat = gl::ConvertSizedInternalFormat(format, type);
+        if (internalformat != texture->getInternalFormat(level))
+        {
+            return error(GL_INVALID_OPERATION, false);
+        }
+    }
+
+    if (compressed)
+    {
+        if ((width % 4 != 0 && width != texture->getWidth(0)) ||
+            (height % 4 != 0 && height != texture->getHeight(0)))
+        {
+            return error(GL_INVALID_OPERATION, false);
+        }
+    }
+
+    if (xoffset + width > texture->getWidth(level) ||
+        yoffset + height > texture->getHeight(level))
+    {
+        return error(GL_INVALID_VALUE, false);
+    }
+
+    return true;
+}
+
+bool validateSubImageParamsCube(bool compressed, GLsizei width, GLsizei height,
+                                GLint xoffset, GLint yoffset, GLenum target, GLint level, GLenum format, GLenum type,
+                                gl::TextureCubeMap *texture)
+{
+    if (!texture)
+    {
+        return error(GL_INVALID_OPERATION, false);
+    }
+
+    if (compressed != texture->isCompressed(target, level))
+    {
+        return error(GL_INVALID_OPERATION, false);
+    }
+
+    if (format != GL_NONE)
+    {
+        GLenum internalformat = gl::ConvertSizedInternalFormat(format, type);
+        if (internalformat != texture->getInternalFormat(target, level))
+        {
+            return error(GL_INVALID_OPERATION, false);
+        }
+    }
+
+    if (compressed)
+    {
+        if ((width % 4 != 0 && width != texture->getWidth(target, 0)) ||
+            (height % 4 != 0 && height != texture->getHeight(target, 0)))
+        {
+            return error(GL_INVALID_OPERATION, false);
+        }
+    }
+
+    if (xoffset + width > texture->getWidth(target, level) ||
+        yoffset + height > texture->getHeight(target, level))
+    {
+        return error(GL_INVALID_VALUE, false);
+    }
+
+    return true;
+}
+
+// check for combinations of format and type that are valid for ReadPixels
+bool validReadFormatType(GLenum format, GLenum type)
+{
+    switch (format)
+    {
+      case GL_RGBA:
+        switch (type)
+        {
+          case GL_UNSIGNED_BYTE:
+            break;
+          default:
+            return false;
+        }
+        break;
+      case GL_BGRA_EXT:
+        switch (type)
+        {
+          case GL_UNSIGNED_BYTE:
+          case GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT:
+          case GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT:
+            break;
+          default:
+            return false;
+        }
+        break;
+      default:
+        return false;
+    }
+    return true;
+}
+
+extern "C"
+{
+
+void __stdcall glActiveTexture(GLenum texture)
+{
+    EVENT("(GLenum texture = 0x%X)", texture);
+
+    try
+    {
+        gl::Context *context = gl::getNonLostContext();
+
+        if (context)
+        {
+            if (texture < GL_TEXTURE0 || texture > GL_TEXTURE0 + context->getMaximumCombinedTextureImageUnits() - 1)
+            {
+                return error(GL_INVALID_ENUM);
+            }
+
+            context->setActiveSampler(texture - GL_TEXTURE0);
+        }
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(GL_OUT_OF_MEMORY);
+    }
+}
+
+void __stdcall glAttachShader(GLuint program, GLuint shader)
+{
+    EVENT("(GLuint program = %d, GLuint shader = %d)", program, shader);
+
+    try
+    {
+        gl::Context *context = gl::getNonLostContext();
+
+        if (context)
+        {
+            gl::Program *programObject = context->getProgram(program);
+            gl::Shader *shaderObject = context->getShader(shader);
+
+            if (!programObject)
+            {
+                if (context->getShader(program))
+                {
+                    return error(GL_INVALID_OPERATION);
+                }
+                else
+                {
+                    return error(GL_INVALID_VALUE);
+                }
+            }
+
+            if (!shaderObject)
+            {
+                if (context->getProgram(shader))
+                {
+                    return error(GL_INVALID_OPERATION);
+                }
+                else
+                {
+                    return error(GL_INVALID_VALUE);
+                }
+            }
+
+            if (!programObject->attachShader(shaderObject))
+            {
+                return error(GL_INVALID_OPERATION);
+            }
+        }
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(GL_OUT_OF_MEMORY);
+    }
+}
+
+void __stdcall glBeginQueryEXT(GLenum target, GLuint id)
+{
+    EVENT("(GLenum target = 0x%X, GLuint %d)", target, id);
+
+    try
+    {
+        switch (target)
+        {
+          case GL_ANY_SAMPLES_PASSED_EXT: 
+          case GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT:
+              break;
+          default: 
+              return error(GL_INVALID_ENUM);
+        }
+
+        if (id == 0)
+        {
+            return error(GL_INVALID_OPERATION);
+        }
+
+        gl::Context *context = gl::getNonLostContext();
+
+        if (context)
+        {
+            context->beginQuery(target, id);
+        }
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(GL_OUT_OF_MEMORY);
+    }
+}
+
+void __stdcall glBindAttribLocation(GLuint program, GLuint index, const GLchar* name)
+{
+    EVENT("(GLuint program = %d, GLuint index = %d, const GLchar* name = 0x%0.8p)", program, index, name);
+
+    try
+    {
+        if (index >= gl::MAX_VERTEX_ATTRIBS)
+        {
+            return error(GL_INVALID_VALUE);
+        }
+
+        gl::Context *context = gl::getNonLostContext();
+
+        if (context)
+        {
+            gl::Program *programObject = context->getProgram(program);
+
+            if (!programObject)
+            {
+                if (context->getShader(program))
+                {
+                    return error(GL_INVALID_OPERATION);
+                }
+                else
+                {
+                    return error(GL_INVALID_VALUE);
+                }
+            }
+
+            if (strncmp(name, "gl_", 3) == 0)
+            {
+                return error(GL_INVALID_OPERATION);
+            }
+
+            programObject->bindAttributeLocation(index, name);
+        }
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(GL_OUT_OF_MEMORY);
+    }
+}
+
+void __stdcall glBindBuffer(GLenum target, GLuint buffer)
+{
+    EVENT("(GLenum target = 0x%X, GLuint buffer = %d)", target, buffer);
+
+    try
+    {
+        gl::Context *context = gl::getNonLostContext();
+
+        if (context)
+        {
+            switch (target)
+            {
+              case GL_ARRAY_BUFFER:
+                context->bindArrayBuffer(buffer);
+                return;
+              case GL_ELEMENT_ARRAY_BUFFER:
+                context->bindElementArrayBuffer(buffer);
+                return;
+              default:
+                return error(GL_INVALID_ENUM);
+            }
+        }
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(GL_OUT_OF_MEMORY);
+    }
+}
+
+void __stdcall glBindFramebuffer(GLenum target, GLuint framebuffer)
+{
+    EVENT("(GLenum target = 0x%X, GLuint framebuffer = %d)", target, framebuffer);
+
+    try
+    {
+        if (target != GL_FRAMEBUFFER && target != GL_DRAW_FRAMEBUFFER_ANGLE && target != GL_READ_FRAMEBUFFER_ANGLE)
+        {
+            return error(GL_INVALID_ENUM);
+        }
+
+        gl::Context *context = gl::getNonLostContext();
+
+        if (context)
+        {
+            if (target == GL_READ_FRAMEBUFFER_ANGLE || target == GL_FRAMEBUFFER)
+            {
+                context->bindReadFramebuffer(framebuffer);
+            }
+            
+            if (target == GL_DRAW_FRAMEBUFFER_ANGLE || target == GL_FRAMEBUFFER)
+            {
+                context->bindDrawFramebuffer(framebuffer);
+            }
+        }
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(GL_OUT_OF_MEMORY);
+    }
+}
+
+void __stdcall glBindRenderbuffer(GLenum target, GLuint renderbuffer)
+{
+    EVENT("(GLenum target = 0x%X, GLuint renderbuffer = %d)", target, renderbuffer);
+
+    try
+    {
+        if (target != GL_RENDERBUFFER)
+        {
+            return error(GL_INVALID_ENUM);
+        }
+
+        gl::Context *context = gl::getNonLostContext();
+
+        if (context)
+        {
+            context->bindRenderbuffer(renderbuffer);
+        }
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(GL_OUT_OF_MEMORY);
+    }
+}
+
+void __stdcall glBindTexture(GLenum target, GLuint texture)
+{
+    EVENT("(GLenum target = 0x%X, GLuint texture = %d)", target, texture);
+
+    try
+    {
+        gl::Context *context = gl::getNonLostContext();
+
+        if (context)
+        {
+            gl::Texture *textureObject = context->getTexture(texture);
+
+            if (textureObject && textureObject->getTarget() != target && texture != 0)
+            {
+                return error(GL_INVALID_OPERATION);
+            }
+
+            switch (target)
+            {
+              case GL_TEXTURE_2D:
+                context->bindTexture2D(texture);
+                return;
+              case GL_TEXTURE_CUBE_MAP:
+                context->bindTextureCubeMap(texture);
+                return;
+              default:
+                return error(GL_INVALID_ENUM);
+            }
+        }
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(GL_OUT_OF_MEMORY);
+    }
+}
+
+void __stdcall glBlendColor(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha)
+{
+    EVENT("(GLclampf red = %f, GLclampf green = %f, GLclampf blue = %f, GLclampf alpha = %f)",
+          red, green, blue, alpha);
+
+    try
+    {
+        gl::Context* context = gl::getNonLostContext();
+
+        if (context)
+        {
+            context->setBlendColor(gl::clamp01(red), gl::clamp01(green), gl::clamp01(blue), gl::clamp01(alpha));
+        }
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(GL_OUT_OF_MEMORY);
+    }
+}
+
+void __stdcall glBlendEquation(GLenum mode)
+{
+    glBlendEquationSeparate(mode, mode);
+}
+
+void __stdcall glBlendEquationSeparate(GLenum modeRGB, GLenum modeAlpha)
+{
+    EVENT("(GLenum modeRGB = 0x%X, GLenum modeAlpha = 0x%X)", modeRGB, modeAlpha);
+
+    try
+    {
+        switch (modeRGB)
+        {
+          case GL_FUNC_ADD:
+          case GL_FUNC_SUBTRACT:
+          case GL_FUNC_REVERSE_SUBTRACT:
+            break;
+          default:
+            return error(GL_INVALID_ENUM);
+        }
+
+        switch (modeAlpha)
+        {
+          case GL_FUNC_ADD:
+          case GL_FUNC_SUBTRACT:
+          case GL_FUNC_REVERSE_SUBTRACT:
+            break;
+          default:
+            return error(GL_INVALID_ENUM);
+        }
+
+        gl::Context *context = gl::getNonLostContext();
+
+        if (context)
+        {
+            context->setBlendEquation(modeRGB, modeAlpha);
+        }
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(GL_OUT_OF_MEMORY);
+    }
+}
+
+void __stdcall glBlendFunc(GLenum sfactor, GLenum dfactor)
+{
+    glBlendFuncSeparate(sfactor, dfactor, sfactor, dfactor);
+}
+
+void __stdcall glBlendFuncSeparate(GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha)
+{
+    EVENT("(GLenum srcRGB = 0x%X, GLenum dstRGB = 0x%X, GLenum srcAlpha = 0x%X, GLenum dstAlpha = 0x%X)",
+          srcRGB, dstRGB, srcAlpha, dstAlpha);
+
+    try
+    {
+        switch (srcRGB)
+        {
+          case GL_ZERO:
+          case GL_ONE:
+          case GL_SRC_COLOR:
+          case GL_ONE_MINUS_SRC_COLOR:
+          case GL_DST_COLOR:
+          case GL_ONE_MINUS_DST_COLOR:
+          case GL_SRC_ALPHA:
+          case GL_ONE_MINUS_SRC_ALPHA:
+          case GL_DST_ALPHA:
+          case GL_ONE_MINUS_DST_ALPHA:
+          case GL_CONSTANT_COLOR:
+          case GL_ONE_MINUS_CONSTANT_COLOR:
+          case GL_CONSTANT_ALPHA:
+          case GL_ONE_MINUS_CONSTANT_ALPHA:
+          case GL_SRC_ALPHA_SATURATE:
+            break;
+          default:
+            return error(GL_INVALID_ENUM);
+        }
+
+        switch (dstRGB)
+        {
+          case GL_ZERO:
+          case GL_ONE:
+          case GL_SRC_COLOR:
+          case GL_ONE_MINUS_SRC_COLOR:
+          case GL_DST_COLOR:
+          case GL_ONE_MINUS_DST_COLOR:
+          case GL_SRC_ALPHA:
+          case GL_ONE_MINUS_SRC_ALPHA:
+          case GL_DST_ALPHA:
+          case GL_ONE_MINUS_DST_ALPHA:
+          case GL_CONSTANT_COLOR:
+          case GL_ONE_MINUS_CONSTANT_COLOR:
+          case GL_CONSTANT_ALPHA:
+          case GL_ONE_MINUS_CONSTANT_ALPHA:
+            break;
+          default:
+            return error(GL_INVALID_ENUM);
+        }
+
+        switch (srcAlpha)
+        {
+          case GL_ZERO:
+          case GL_ONE:
+          case GL_SRC_COLOR:
+          case GL_ONE_MINUS_SRC_COLOR:
+          case GL_DST_COLOR:
+          case GL_ONE_MINUS_DST_COLOR:
+          case GL_SRC_ALPHA:
+          case GL_ONE_MINUS_SRC_ALPHA:
+          case GL_DST_ALPHA:
+          case GL_ONE_MINUS_DST_ALPHA:
+          case GL_CONSTANT_COLOR:
+          case GL_ONE_MINUS_CONSTANT_COLOR:
+          case GL_CONSTANT_ALPHA:
+          case GL_ONE_MINUS_CONSTANT_ALPHA:
+          case GL_SRC_ALPHA_SATURATE:
+            break;
+          default:
+            return error(GL_INVALID_ENUM);
+        }
+
+        switch (dstAlpha)
+        {
+          case GL_ZERO:
+          case GL_ONE:
+          case GL_SRC_COLOR:
+          case GL_ONE_MINUS_SRC_COLOR:
+          case GL_DST_COLOR:
+          case GL_ONE_MINUS_DST_COLOR:
+          case GL_SRC_ALPHA:
+          case GL_ONE_MINUS_SRC_ALPHA:
+          case GL_DST_ALPHA:
+          case GL_ONE_MINUS_DST_ALPHA:
+          case GL_CONSTANT_COLOR:
+          case GL_ONE_MINUS_CONSTANT_COLOR:
+          case GL_CONSTANT_ALPHA:
+          case GL_ONE_MINUS_CONSTANT_ALPHA:
+            break;
+          default:
+            return error(GL_INVALID_ENUM);
+        }
+
+        bool constantColorUsed = (srcRGB == GL_CONSTANT_COLOR || srcRGB == GL_ONE_MINUS_CONSTANT_COLOR ||
+                                  dstRGB == GL_CONSTANT_COLOR || dstRGB == GL_ONE_MINUS_CONSTANT_COLOR);
+
+        bool constantAlphaUsed = (srcRGB == GL_CONSTANT_ALPHA || srcRGB == GL_ONE_MINUS_CONSTANT_ALPHA ||
+                                  dstRGB == GL_CONSTANT_ALPHA || dstRGB == GL_ONE_MINUS_CONSTANT_ALPHA);
+
+        if (constantColorUsed && constantAlphaUsed)
+        {
+            ERR("Simultaneous use of GL_CONSTANT_ALPHA/GL_ONE_MINUS_CONSTANT_ALPHA and GL_CONSTANT_COLOR/GL_ONE_MINUS_CONSTANT_COLOR invalid under WebGL");
+            return error(GL_INVALID_OPERATION);
+        }
+
+        gl::Context *context = gl::getNonLostContext();
+
+        if (context)
+        {
+            context->setBlendFactors(srcRGB, dstRGB, srcAlpha, dstAlpha);
+        }
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(GL_OUT_OF_MEMORY);
+    }
+}
+
+void __stdcall glBufferData(GLenum target, GLsizeiptr size, const GLvoid* data, GLenum usage)
+{
+    EVENT("(GLenum target = 0x%X, GLsizeiptr size = %d, const GLvoid* data = 0x%0.8p, GLenum usage = %d)",
+          target, size, data, usage);
+
+    try
+    {
+        if (size < 0)
+        {
+            return error(GL_INVALID_VALUE);
+        }
+
+        switch (usage)
+        {
+          case GL_STREAM_DRAW:
+          case GL_STATIC_DRAW:
+          case GL_DYNAMIC_DRAW:
+            break;
+          default:
+            return error(GL_INVALID_ENUM);
+        }
+
+        gl::Context *context = gl::getNonLostContext();
+
+        if (context)
+        {
+            gl::Buffer *buffer;
+
+            switch (target)
+            {
+              case GL_ARRAY_BUFFER:
+                buffer = context->getArrayBuffer();
+                break;
+              case GL_ELEMENT_ARRAY_BUFFER:
+                buffer = context->getElementArrayBuffer();
+                break;
+              default:
+                return error(GL_INVALID_ENUM);
+            }
+
+            if (!buffer)
+            {
+                return error(GL_INVALID_OPERATION);
+            }
+
+            buffer->bufferData(data, size, usage);
+        }
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(GL_OUT_OF_MEMORY);
+    }
+}
+
+void __stdcall glBufferSubData(GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid* data)
+{
+    EVENT("(GLenum target = 0x%X, GLintptr offset = %d, GLsizeiptr size = %d, const GLvoid* data = 0x%0.8p)",
+          target, offset, size, data);
+
+    try
+    {
+        if (size < 0 || offset < 0)
+        {
+            return error(GL_INVALID_VALUE);
+        }
+
+        if (data == NULL)
+        {
+            return;
+        }
+
+        gl::Context *context = gl::getNonLostContext();
+
+        if (context)
+        {
+            gl::Buffer *buffer;
+
+            switch (target)
+            {
+              case GL_ARRAY_BUFFER:
+                buffer = context->getArrayBuffer();
+                break;
+              case GL_ELEMENT_ARRAY_BUFFER:
+                buffer = context->getElementArrayBuffer();
+                break;
+              default:
+                return error(GL_INVALID_ENUM);
+            }
+
+            if (!buffer)
+            {
+                return error(GL_INVALID_OPERATION);
+            }
+
+            if ((size_t)size + offset > buffer->size())
+            {
+                return error(GL_INVALID_VALUE);
+            }
+
+            buffer->bufferSubData(data, size, offset);
+        }
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(GL_OUT_OF_MEMORY);
+    }
+}
+
+GLenum __stdcall glCheckFramebufferStatus(GLenum target)
+{
+    EVENT("(GLenum target = 0x%X)", target);
+
+    try
+    {
+        if (target != GL_FRAMEBUFFER && target != GL_DRAW_FRAMEBUFFER_ANGLE && target != GL_READ_FRAMEBUFFER_ANGLE)
+        {
+            return error(GL_INVALID_ENUM, 0);
+        }
+
+        gl::Context *context = gl::getNonLostContext();
+
+        if (context)
+        {
+            gl::Framebuffer *framebuffer = NULL;
+            if (target == GL_READ_FRAMEBUFFER_ANGLE)
+            {
+                framebuffer = context->getReadFramebuffer();
+            }
+            else
+            {
+                framebuffer = context->getDrawFramebuffer();
+            }
+
+            return framebuffer->completeness();
+        }
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(GL_OUT_OF_MEMORY, 0);
+    }
+
+    return 0;
+}
+
+void __stdcall glClear(GLbitfield mask)
+{
+    EVENT("(GLbitfield mask = %X)", mask);
+
+    try
+    {
+        gl::Context *context = gl::getNonLostContext();
+
+        if (context)
+        {
+            context->clear(mask);
+        }
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(GL_OUT_OF_MEMORY);
+    }
+}
+
+void __stdcall glClearColor(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha)
+{
+    EVENT("(GLclampf red = %f, GLclampf green = %f, GLclampf blue = %f, GLclampf alpha = %f)",
+          red, green, blue, alpha);
+
+    try
+    {
+        gl::Context *context = gl::getNonLostContext();
+
+        if (context)
+        {
+            context->setClearColor(red, green, blue, alpha);
+        }
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(GL_OUT_OF_MEMORY);
+    }
+}
+
+void __stdcall glClearDepthf(GLclampf depth)
+{
+    EVENT("(GLclampf depth = %f)", depth);
+
+    try
+    {
+        gl::Context *context = gl::getNonLostContext();
+
+        if (context)
+        {
+            context->setClearDepth(depth);
+        }
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(GL_OUT_OF_MEMORY);
+    }
+}
+
+void __stdcall glClearStencil(GLint s)
+{
+    EVENT("(GLint s = %d)", s);
+
+    try
+    {
+        gl::Context *context = gl::getNonLostContext();
+
+        if (context)
+        {
+            context->setClearStencil(s);
+        }
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(GL_OUT_OF_MEMORY);
+    }
+}
+
+void __stdcall glColorMask(GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha)
+{
+    EVENT("(GLboolean red = %d, GLboolean green = %d, GLboolean blue = %d, GLboolean alpha = %d)",
+          red, green, blue, alpha);
+
+    try
+    {
+        gl::Context *context = gl::getNonLostContext();
+
+        if (context)
+        {
+            context->setColorMask(red == GL_TRUE, green == GL_TRUE, blue == GL_TRUE, alpha == GL_TRUE);
+        }
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(GL_OUT_OF_MEMORY);
+    }
+}
+
+void __stdcall glCompileShader(GLuint shader)
+{
+    EVENT("(GLuint shader = %d)", shader);
+
+    try
+    {
+        gl::Context *context = gl::getNonLostContext();
+
+        if (context)
+        {
+            gl::Shader *shaderObject = context->getShader(shader);
+
+            if (!shaderObject)
+            {
+                if (context->getProgram(shader))
+                {
+                    return error(GL_INVALID_OPERATION);
+                }
+                else
+                {
+                    return error(GL_INVALID_VALUE);
+                }
+            }
+
+            shaderObject->compile();
+        }
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(GL_OUT_OF_MEMORY);
+    }
+}
+
+void __stdcall glCompressedTexImage2D(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, 
+                                      GLint border, GLsizei imageSize, const GLvoid* data)
+{
+    EVENT("(GLenum target = 0x%X, GLint level = %d, GLenum internalformat = 0x%X, GLsizei width = %d, " 
+          "GLsizei height = %d, GLint border = %d, GLsizei imageSize = %d, const GLvoid* data = 0x%0.8p)",
+          target, level, internalformat, width, height, border, imageSize, data);
+
+    try
+    {
+        if (!validImageSize(level, width, height) || border != 0 || imageSize < 0)
+        {
+            return error(GL_INVALID_VALUE);
+        }
+
+        switch (internalformat)
+        {
+          case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
+          case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
+          case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
+          case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
+            break;
+          default:
+            return error(GL_INVALID_ENUM);
+        }
+
+        if (border != 0)
+        {
+            return error(GL_INVALID_VALUE);
+        }
+
+        gl::Context *context = gl::getNonLostContext();
+
+        if (context)
+        {
+            if (level > context->getMaximumTextureLevel())
+            {
+                return error(GL_INVALID_VALUE);
+            }
+
+            switch (target)
+            {
+              case GL_TEXTURE_2D:
+                if (width > (context->getMaximumTextureDimension() >> level) ||
+                    height > (context->getMaximumTextureDimension() >> level))
+                {
+                    return error(GL_INVALID_VALUE);
+                }
+                break;
+              case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
+              case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
+              case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
+              case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
+              case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
+              case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
+                if (width != height)
+                {
+                    return error(GL_INVALID_VALUE);
+                }
+
+                if (width > (context->getMaximumCubeTextureDimension() >> level) ||
+                    height > (context->getMaximumCubeTextureDimension() >> level))
+                {
+                    return error(GL_INVALID_VALUE);
+                }
+                break;
+              default:
+                return error(GL_INVALID_ENUM);
+            }
+
+            switch (internalformat) {
+              case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
+              case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
+                if (!context->supportsDXT1Textures())
+                {
+                    return error(GL_INVALID_ENUM); // in this case, it's as though the internal format switch failed
+                }
+                break;
+              case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
+                if (!context->supportsDXT3Textures())
+                {
+                    return error(GL_INVALID_ENUM); // in this case, it's as though the internal format switch failed
+                }
+                break;
+              case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
+                if (!context->supportsDXT5Textures())
+                {
+                    return error(GL_INVALID_ENUM); // in this case, it's as though the internal format switch failed
+                }
+                break;
+              default: UNREACHABLE();
+            }
+
+            if (imageSize != gl::ComputeCompressedSize(width, height, internalformat))
+            {
+                return error(GL_INVALID_VALUE);
+            }
+
+            if (target == GL_TEXTURE_2D)
+            {
+                gl::Texture2D *texture = context->getTexture2D();
+
+                if (!texture)
+                {
+                    return error(GL_INVALID_OPERATION);
+                }
+
+                if (texture->isImmutable())
+                {
+                    return error(GL_INVALID_OPERATION);
+                }
+
+                texture->setCompressedImage(level, internalformat, width, height, imageSize, data);
+            }
+            else
+            {
+                gl::TextureCubeMap *texture = context->getTextureCubeMap();
+
+                if (!texture)
+                {
+                    return error(GL_INVALID_OPERATION);
+                }
+
+                if (texture->isImmutable())
+                {
+                    return error(GL_INVALID_OPERATION);
+                }
+
+                switch (target)
+                {
+                  case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
+                  case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
+                  case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
+                  case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
+                  case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
+                  case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
+                    texture->setCompressedImage(target, level, internalformat, width, height, imageSize, data);
+                    break;
+                  default: UNREACHABLE();
+                }
+            }
+        }
+
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(GL_OUT_OF_MEMORY);
+    }
+}
+
+void __stdcall glCompressedTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
+                                         GLenum format, GLsizei imageSize, const GLvoid* data)
+{
+    EVENT("(GLenum target = 0x%X, GLint level = %d, GLint xoffset = %d, GLint yoffset = %d, "
+          "GLsizei width = %d, GLsizei height = %d, GLenum format = 0x%X, "
+          "GLsizei imageSize = %d, const GLvoid* data = 0x%0.8p)",
+          target, level, xoffset, yoffset, width, height, format, imageSize, data);
+
+    try
+    {
+        if (!gl::IsInternalTextureTarget(target))
+        {
+            return error(GL_INVALID_ENUM);
+        }
+
+        if (xoffset < 0 || yoffset < 0 || !validImageSize(level, width, height) || imageSize < 0)
+        {
+            return error(GL_INVALID_VALUE);
+        }
+
+        switch (format)
+        {
+          case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
+          case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
+          case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
+          case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
+            break;
+          default:
+            return error(GL_INVALID_ENUM);
+        }
+
+        if (width == 0 || height == 0 || data == NULL)
+        {
+            return;
+        }
+
+        gl::Context *context = gl::getNonLostContext();
+
+        if (context)
+        {
+            if (level > context->getMaximumTextureLevel())
+            {
+                return error(GL_INVALID_VALUE);
+            }
+
+            switch (format) {
+              case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
+              case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
+                if (!context->supportsDXT1Textures())
+                {
+                    return error(GL_INVALID_ENUM); // in this case, it's as though the internal format switch failed
+                }
+                break;
+              case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
+                if (!context->supportsDXT3Textures())
+                {
+                    return error(GL_INVALID_ENUM); // in this case, it's as though the internal format switch failed
+                }
+                break;
+              case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
+                if (!context->supportsDXT5Textures())
+                {
+                    return error(GL_INVALID_ENUM); // in this case, it's as though the internal format switch failed
+                }
+                break;
+              default: UNREACHABLE();
+            }
+
+            if (imageSize != gl::ComputeCompressedSize(width, height, format))
+            {
+                return error(GL_INVALID_VALUE);
+            }
+
+            if (xoffset % 4 != 0 || yoffset % 4 != 0)
+            {
+                return error(GL_INVALID_OPERATION); // we wait to check the offsets until this point, because the multiple-of-four restriction
+                                                    // does not exist unless DXT textures are supported.
+            }
+
+            if (target == GL_TEXTURE_2D)
+            {
+                gl::Texture2D *texture = context->getTexture2D();
+                if (validateSubImageParams2D(true, width, height, xoffset, yoffset, level, format, GL_NONE, texture))
+                {
+                    texture->subImageCompressed(level, xoffset, yoffset, width, height, format, imageSize, data);
+                }
+            }
+            else if (gl::IsCubemapTextureTarget(target))
+            {
+                gl::TextureCubeMap *texture = context->getTextureCubeMap();
+                if (validateSubImageParamsCube(true, width, height, xoffset, yoffset, target, level, format, GL_NONE, texture))
+                {
+                    texture->subImageCompressed(target, level, xoffset, yoffset, width, height, format, imageSize, data);
+                }
+            }
+            else
+            {
+                UNREACHABLE();
+            }
+        }
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(GL_OUT_OF_MEMORY);
+    }
+}
+
+void __stdcall glCopyTexImage2D(GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border)
+{
+    EVENT("(GLenum target = 0x%X, GLint level = %d, GLenum internalformat = 0x%X, "
+          "GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d, GLint border = %d)",
+          target, level, internalformat, x, y, width, height, border);
+
+    try
+    {
+        if (!validImageSize(level, width, height))
+        {
+            return error(GL_INVALID_VALUE);
+        }
+
+        if (border != 0)
+        {
+            return error(GL_INVALID_VALUE);
+        }
+
+        gl::Context *context = gl::getNonLostContext();
+
+        if (context)
+        {
+            if (level > context->getMaximumTextureLevel())
+            {
+                return error(GL_INVALID_VALUE);
+            }
+
+            switch (target)
+            {
+              case GL_TEXTURE_2D:
+                if (width > (context->getMaximumTextureDimension() >> level) ||
+                    height > (context->getMaximumTextureDimension() >> level))
+                {
+                    return error(GL_INVALID_VALUE);
+                }
+                break;
+              case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
+              case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
+              case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
+              case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
+              case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
+              case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
+                if (width != height)
+                {
+                    return error(GL_INVALID_VALUE);
+                }
+
+                if (width > (context->getMaximumCubeTextureDimension() >> level) ||
+                    height > (context->getMaximumCubeTextureDimension() >> level))
+                {
+                    return error(GL_INVALID_VALUE);
+                }
+                break;
+              default:
+                return error(GL_INVALID_ENUM);
+            }
+
+            gl::Framebuffer *framebuffer = context->getReadFramebuffer();
+
+            if (framebuffer->completeness() != GL_FRAMEBUFFER_COMPLETE)
+            {
+                return error(GL_INVALID_FRAMEBUFFER_OPERATION);
+            }
+
+            if (context->getReadFramebufferHandle() != 0 && framebuffer->getColorbuffer()->getSamples() != 0)
+            {
+                return error(GL_INVALID_OPERATION);
+            }
+
+            gl::Renderbuffer *source = framebuffer->getColorbuffer();
+            GLenum colorbufferFormat = source->getInternalFormat();
+
+            // [OpenGL ES 2.0.24] table 3.9
+            switch (internalformat)
+            {
+              case GL_ALPHA:
+                if (colorbufferFormat != GL_ALPHA8_EXT &&
+                    colorbufferFormat != GL_RGBA4 &&
+                    colorbufferFormat != GL_RGB5_A1 &&
+                    colorbufferFormat != GL_RGBA8_OES)
+                {
+                    return error(GL_INVALID_OPERATION);
+                }
+                break;
+              case GL_LUMINANCE:
+              case GL_RGB:
+                if (colorbufferFormat != GL_RGB565 &&
+                    colorbufferFormat != GL_RGB8_OES &&
+                    colorbufferFormat != GL_RGBA4 &&
+                    colorbufferFormat != GL_RGB5_A1 &&
+                    colorbufferFormat != GL_RGBA8_OES)
+                {
+                    return error(GL_INVALID_OPERATION);
+                }
+                break;
+              case GL_LUMINANCE_ALPHA:
+              case GL_RGBA:
+                if (colorbufferFormat != GL_RGBA4 &&
+                    colorbufferFormat != GL_RGB5_A1 &&
+                    colorbufferFormat != GL_RGBA8_OES)
+                 {
+                     return error(GL_INVALID_OPERATION);
+                 }
+                 break;
+              case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
+              case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
+                if (context->supportsDXT1Textures())
+                {
+                    return error(GL_INVALID_OPERATION);
+                }
+                else
+                {
+                    return error(GL_INVALID_ENUM);
+                }
+                break;
+              case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
+                if (context->supportsDXT3Textures())
+                {
+                    return error(GL_INVALID_OPERATION);
+                }
+                else
+                {
+                    return error(GL_INVALID_ENUM);
+                }
+                break;
+              case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
+                if (context->supportsDXT5Textures())
+                {
+                    return error(GL_INVALID_OPERATION);
+                }
+                else
+                {
+                    return error(GL_INVALID_ENUM);
+                }
+                break;
+              case GL_DEPTH_COMPONENT:
+              case GL_DEPTH_COMPONENT16:
+              case GL_DEPTH_COMPONENT32_OES:
+              case GL_DEPTH_STENCIL_OES:
+              case GL_DEPTH24_STENCIL8_OES:
+                  if (context->supportsDepthTextures())
+                  {
+                      return error(GL_INVALID_OPERATION);
+                  }
+                  else
+                  {
+                      return error(GL_INVALID_ENUM);
+                  }
+              default:
+                return error(GL_INVALID_ENUM);
+            }
+
+            if (target == GL_TEXTURE_2D)
+            {
+                gl::Texture2D *texture = context->getTexture2D();
+
+                if (!texture)
+                {
+                    return error(GL_INVALID_OPERATION);
+                }
+
+                if (texture->isImmutable())
+                {
+                    return error(GL_INVALID_OPERATION);
+                }
+
+                texture->copyImage(level, internalformat, x, y, width, height, framebuffer);
+            }
+            else if (gl::IsCubemapTextureTarget(target))
+            {
+                gl::TextureCubeMap *texture = context->getTextureCubeMap();
+
+                if (!texture)
+                {
+                    return error(GL_INVALID_OPERATION);
+                }
+
+                if (texture->isImmutable())
+                {
+                    return error(GL_INVALID_OPERATION);
+                }
+
+                texture->copyImage(target, level, internalformat, x, y, width, height, framebuffer);
+            }
+            else UNREACHABLE();
+        }
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(GL_OUT_OF_MEMORY);
+    }
+}
+
+void __stdcall glCopyTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height)
+{
+    EVENT("(GLenum target = 0x%X, GLint level = %d, GLint xoffset = %d, GLint yoffset = %d, "
+          "GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d)",
+          target, level, xoffset, yoffset, x, y, width, height);
+
+    try
+    {
+        if (!gl::IsInternalTextureTarget(target))
+        {
+            return error(GL_INVALID_ENUM);
+        }
+
+        if (level < 0 || xoffset < 0 || yoffset < 0 || width < 0 || height < 0)
+        {
+            return error(GL_INVALID_VALUE);
+        }
+
+        if (std::numeric_limits<GLsizei>::max() - xoffset < width || std::numeric_limits<GLsizei>::max() - yoffset < height)
+        {
+            return error(GL_INVALID_VALUE);
+        }
+
+        if (width == 0 || height == 0)
+        {
+            return;
+        }
+
+        gl::Context *context = gl::getNonLostContext();
+
+        if (context)
+        {
+            if (level > context->getMaximumTextureLevel())
+            {
+                return error(GL_INVALID_VALUE);
+            }
+
+            gl::Framebuffer *framebuffer = context->getReadFramebuffer();
+
+            if (framebuffer->completeness() != GL_FRAMEBUFFER_COMPLETE)
+            {
+                return error(GL_INVALID_FRAMEBUFFER_OPERATION);
+            }
+
+            if (context->getReadFramebufferHandle() != 0 && framebuffer->getColorbuffer()->getSamples() != 0)
+            {
+                return error(GL_INVALID_OPERATION);
+            }
+
+            gl::Renderbuffer *source = framebuffer->getColorbuffer();
+            GLenum colorbufferFormat = source->getInternalFormat();
+            gl::Texture *texture = NULL;
+            GLenum textureFormat = GL_RGBA;
+
+            if (target == GL_TEXTURE_2D)
+            {
+                gl::Texture2D *tex2d = context->getTexture2D();
+
+                if (!validateSubImageParams2D(false, width, height, xoffset, yoffset, level, GL_NONE, GL_NONE, tex2d))
+                {
+                    return; // error already registered by validateSubImageParams
+                }
+                textureFormat = gl::ExtractFormat(tex2d->getInternalFormat(level));
+                texture = tex2d;
+            }
+            else if (gl::IsCubemapTextureTarget(target))
+            {
+                gl::TextureCubeMap *texcube = context->getTextureCubeMap();
+
+                if (!validateSubImageParamsCube(false, width, height, xoffset, yoffset, target, level, GL_NONE, GL_NONE, texcube))
+                {
+                    return; // error already registered by validateSubImageParams
+                }
+                textureFormat = gl::ExtractFormat(texcube->getInternalFormat(target, level));
+                texture = texcube;
+            }
+            else UNREACHABLE();
+
+            // [OpenGL ES 2.0.24] table 3.9
+            switch (textureFormat)
+            {
+              case GL_ALPHA:
+                if (colorbufferFormat != GL_ALPHA8_EXT &&
+                    colorbufferFormat != GL_RGBA4 &&
+                    colorbufferFormat != GL_RGB5_A1 &&
+                    colorbufferFormat != GL_RGBA8_OES)
+                {
+                    return error(GL_INVALID_OPERATION);
+                }
+                break;
+              case GL_LUMINANCE:
+              case GL_RGB:
+                if (colorbufferFormat != GL_RGB565 &&
+                    colorbufferFormat != GL_RGB8_OES &&
+                    colorbufferFormat != GL_RGBA4 &&
+                    colorbufferFormat != GL_RGB5_A1 &&
+                    colorbufferFormat != GL_RGBA8_OES)
+                {
+                    return error(GL_INVALID_OPERATION);
+                }
+                break;
+              case GL_LUMINANCE_ALPHA:
+              case GL_RGBA:
+                if (colorbufferFormat != GL_RGBA4 &&
+                    colorbufferFormat != GL_RGB5_A1 &&
+                    colorbufferFormat != GL_RGBA8_OES)
+                {
+                    return error(GL_INVALID_OPERATION);
+                }
+                break;
+              case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
+              case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
+              case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
+              case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
+                return error(GL_INVALID_OPERATION);
+              case GL_DEPTH_COMPONENT:
+              case GL_DEPTH_STENCIL_OES:
+                return error(GL_INVALID_OPERATION);
+              default:
+                return error(GL_INVALID_OPERATION);
+            }
+
+            texture->copySubImage(target, level, xoffset, yoffset, x, y, width, height, framebuffer);
+        }
+    }
+
+    catch(std::bad_alloc&)
+    {
+        return error(GL_OUT_OF_MEMORY);
+    }
+}
+
+GLuint __stdcall glCreateProgram(void)
+{
+    EVENT("()");
+
+    try
+    {
+        gl::Context *context = gl::getNonLostContext();
+
+        if (context)
+        {
+            return context->createProgram();
+        }
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(GL_OUT_OF_MEMORY, 0);
+    }
+
+    return 0;
+}
+
+GLuint __stdcall glCreateShader(GLenum type)
+{
+    EVENT("(GLenum type = 0x%X)", type);
+
+    try
+    {
+        gl::Context *context = gl::getNonLostContext();
+
+        if (context)
+        {
+            switch (type)
+            {
+              case GL_FRAGMENT_SHADER:
+              case GL_VERTEX_SHADER:
+                return context->createShader(type);
+              default:
+                return error(GL_INVALID_ENUM, 0);
+            }
+        }
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(GL_OUT_OF_MEMORY, 0);
+    }
+
+    return 0;
+}
+
+void __stdcall glCullFace(GLenum mode)
+{
+    EVENT("(GLenum mode = 0x%X)", mode);
+
+    try
+    {
+        switch (mode)
+        {
+          case GL_FRONT:
+          case GL_BACK:
+          case GL_FRONT_AND_BACK:
+            {
+                gl::Context *context = gl::getNonLostContext();
+
+                if (context)
+                {
+                    context->setCullMode(mode);
+                }
+            }
+            break;
+          default:
+            return error(GL_INVALID_ENUM);
+        }
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(GL_OUT_OF_MEMORY);
+    }
+}
+
+void __stdcall glDeleteBuffers(GLsizei n, const GLuint* buffers)
+{
+    EVENT("(GLsizei n = %d, const GLuint* buffers = 0x%0.8p)", n, buffers);
+
+    try
+    {
+        if (n < 0)
+        {
+            return error(GL_INVALID_VALUE);
+        }
+
+        gl::Context *context = gl::getNonLostContext();
+
+        if (context)
+        {
+            for (int i = 0; i < n; i++)
+            {
+                context->deleteBuffer(buffers[i]);
+            }
+        }
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(GL_OUT_OF_MEMORY);
+    }
+}
+
+void __stdcall glDeleteFencesNV(GLsizei n, const GLuint* fences)
+{
+    EVENT("(GLsizei n = %d, const GLuint* fences = 0x%0.8p)", n, fences);
+
+    try
+    {
+        if (n < 0)
+        {
+            return error(GL_INVALID_VALUE);
+        }
+
+        gl::Context *context = gl::getNonLostContext();
+
+        if (context)
+        {
+            for (int i = 0; i < n; i++)
+            {
+                context->deleteFence(fences[i]);
+            }
+        }
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(GL_OUT_OF_MEMORY);
+    }
+}
+
+void __stdcall glDeleteFramebuffers(GLsizei n, const GLuint* framebuffers)
+{
+    EVENT("(GLsizei n = %d, const GLuint* framebuffers = 0x%0.8p)", n, framebuffers);
+
+    try
+    {
+        if (n < 0)
+        {
+            return error(GL_INVALID_VALUE);
+        }
+
+        gl::Context *context = gl::getNonLostContext();
+
+        if (context)
+        {
+            for (int i = 0; i < n; i++)
+            {
+                if (framebuffers[i] != 0)
+                {
+                    context->deleteFramebuffer(framebuffers[i]);
+                }
+            }
+        }
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(GL_OUT_OF_MEMORY);
+    }
+}
+
+void __stdcall glDeleteProgram(GLuint program)
+{
+    EVENT("(GLuint program = %d)", program);
+
+    try
+    {
+        if (program == 0)
+        {
+            return;
+        }
+
+        gl::Context *context = gl::getNonLostContext();
+
+        if (context)
+        {
+            if (!context->getProgram(program))
+            {
+                if(context->getShader(program))
+                {
+                    return error(GL_INVALID_OPERATION);
+                }
+                else
+                {
+                    return error(GL_INVALID_VALUE);
+                }
+            }
+
+            context->deleteProgram(program);
+        }
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(GL_OUT_OF_MEMORY);
+    }
+}
+
+void __stdcall glDeleteQueriesEXT(GLsizei n, const GLuint *ids)
+{
+    EVENT("(GLsizei n = %d, const GLuint *ids = 0x%0.8p)", n, ids);
+
+    try
+    {
+        if (n < 0)
+        {
+            return error(GL_INVALID_VALUE);
+        }
+
+        gl::Context *context = gl::getNonLostContext();
+
+        if (context)
+        {
+            for (int i = 0; i < n; i++)
+            {
+                context->deleteQuery(ids[i]);
+            }
+        }
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(GL_OUT_OF_MEMORY);
+    }
+}
+
+void __stdcall glDeleteRenderbuffers(GLsizei n, const GLuint* renderbuffers)
+{
+    EVENT("(GLsizei n = %d, const GLuint* renderbuffers = 0x%0.8p)", n, renderbuffers);
+
+    try
+    {
+        if (n < 0)
+        {
+            return error(GL_INVALID_VALUE);
+        }
+
+        gl::Context *context = gl::getNonLostContext();
+
+        if (context)
+        {
+            for (int i = 0; i < n; i++)
+            {
+                context->deleteRenderbuffer(renderbuffers[i]);
+            }
+        }
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(GL_OUT_OF_MEMORY);
+    }
+}
+
+void __stdcall glDeleteShader(GLuint shader)
+{
+    EVENT("(GLuint shader = %d)", shader);
+
+    try
+    {
+        if (shader == 0)
+        {
+            return;
+        }
+
+        gl::Context *context = gl::getNonLostContext();
+
+        if (context)
+        {
+            if (!context->getShader(shader))
+            {
+                if(context->getProgram(shader))
+                {
+                    return error(GL_INVALID_OPERATION);
+                }
+                else
+                {
+                    return error(GL_INVALID_VALUE);
+                }
+            }
+
+            context->deleteShader(shader);
+        }
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(GL_OUT_OF_MEMORY);
+    }
+}
+
+void __stdcall glDeleteTextures(GLsizei n, const GLuint* textures)
+{
+    EVENT("(GLsizei n = %d, const GLuint* textures = 0x%0.8p)", n, textures);
+
+    try
+    {
+        if (n < 0)
+        {
+            return error(GL_INVALID_VALUE);
+        }
+
+        gl::Context *context = gl::getNonLostContext();
+
+        if (context)
+        {
+            for (int i = 0; i < n; i++)
+            {
+                if (textures[i] != 0)
+                {
+                    context->deleteTexture(textures[i]);
+                }
+            }
+        }
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(GL_OUT_OF_MEMORY);
+    }
+}
+
+void __stdcall glDepthFunc(GLenum func)
+{
+    EVENT("(GLenum func = 0x%X)", func);
+
+    try
+    {
+        switch (func)
+        {
+          case GL_NEVER:
+          case GL_ALWAYS:
+          case GL_LESS:
+          case GL_LEQUAL:
+          case GL_EQUAL:
+          case GL_GREATER:
+          case GL_GEQUAL:
+          case GL_NOTEQUAL:
+            break;
+          default:
+            return error(GL_INVALID_ENUM);
+        }
+
+        gl::Context *context = gl::getNonLostContext();
+
+        if (context)
+        {
+            context->setDepthFunc(func);
+        }
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(GL_OUT_OF_MEMORY);
+    }
+}
+
+void __stdcall glDepthMask(GLboolean flag)
+{
+    EVENT("(GLboolean flag = %d)", flag);
+
+    try
+    {
+        gl::Context *context = gl::getNonLostContext();
+
+        if (context)
+        {
+            context->setDepthMask(flag != GL_FALSE);
+        }
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(GL_OUT_OF_MEMORY);
+    }
+}
+
+void __stdcall glDepthRangef(GLclampf zNear, GLclampf zFar)
+{
+    EVENT("(GLclampf zNear = %f, GLclampf zFar = %f)", zNear, zFar);
+
+    try
+    {
+        gl::Context *context = gl::getNonLostContext();
+
+        if (context)
+        {
+            context->setDepthRange(zNear, zFar);
+        }
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(GL_OUT_OF_MEMORY);
+    }
+}
+
+void __stdcall glDetachShader(GLuint program, GLuint shader)
+{
+    EVENT("(GLuint program = %d, GLuint shader = %d)", program, shader);
+
+    try
+    {
+        gl::Context *context = gl::getNonLostContext();
+
+        if (context)
+        {
+
+            gl::Program *programObject = context->getProgram(program);
+            gl::Shader *shaderObject = context->getShader(shader);
+            
+            if (!programObject)
+            {
+                gl::Shader *shaderByProgramHandle;
+                shaderByProgramHandle = context->getShader(program);
+                if (!shaderByProgramHandle)
+                {
+                    return error(GL_INVALID_VALUE);
+                }
+                else
+                {
+                    return error(GL_INVALID_OPERATION);
+                }
+            }
+
+            if (!shaderObject)
+            {
+                gl::Program *programByShaderHandle = context->getProgram(shader);
+                if (!programByShaderHandle)
+                {
+                    return error(GL_INVALID_VALUE);
+                }
+                else
+                {
+                    return error(GL_INVALID_OPERATION);
+                }
+            }
+
+            if (!programObject->detachShader(shaderObject))
+            {
+                return error(GL_INVALID_OPERATION);
+            }
+        }
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(GL_OUT_OF_MEMORY);
+    }
+}
+
+void __stdcall glDisable(GLenum cap)
+{
+    EVENT("(GLenum cap = 0x%X)", cap);
+
+    try
+    {
+        gl::Context *context = gl::getNonLostContext();
+
+        if (context)
+        {
+            switch (cap)
+            {
+              case GL_CULL_FACE:                context->setCullFace(false);              break;
+              case GL_POLYGON_OFFSET_FILL:      context->setPolygonOffsetFill(false);     break;
+              case GL_SAMPLE_ALPHA_TO_COVERAGE: context->setSampleAlphaToCoverage(false); break;
+              case GL_SAMPLE_COVERAGE:          context->setSampleCoverage(false);        break;
+              case GL_SCISSOR_TEST:             context->setScissorTest(false);           break;
+              case GL_STENCIL_TEST:             context->setStencilTest(false);           break;
+              case GL_DEPTH_TEST:               context->setDepthTest(false);             break;
+              case GL_BLEND:                    context->setBlend(false);                 break;
+              case GL_DITHER:                   context->setDither(false);                break;
+              default:
+                return error(GL_INVALID_ENUM);
+            }
+        }
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(GL_OUT_OF_MEMORY);
+    }
+}
+
+void __stdcall glDisableVertexAttribArray(GLuint index)
+{
+    EVENT("(GLuint index = %d)", index);
+
+    try
+    {
+        if (index >= gl::MAX_VERTEX_ATTRIBS)
+        {
+            return error(GL_INVALID_VALUE);
+        }
+
+        gl::Context *context = gl::getNonLostContext();
+
+        if (context)
+        {
+            context->setEnableVertexAttribArray(index, false);
+        }
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(GL_OUT_OF_MEMORY);
+    }
+}
+
+void __stdcall glDrawArrays(GLenum mode, GLint first, GLsizei count)
+{
+    EVENT("(GLenum mode = 0x%X, GLint first = %d, GLsizei count = %d)", mode, first, count);
+
+    try
+    {
+        if (count < 0 || first < 0)
+        {
+            return error(GL_INVALID_VALUE);
+        }
+
+        gl::Context *context = gl::getNonLostContext();
+
+        if (context)
+        {
+            context->drawArrays(mode, first, count, 0);
+        }
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(GL_OUT_OF_MEMORY);
+    }
+}
+
+void __stdcall glDrawArraysInstancedANGLE(GLenum mode, GLint first, GLsizei count, GLsizei primcount)
+{
+    EVENT("(GLenum mode = 0x%X, GLint first = %d, GLsizei count = %d, GLsizei primcount = %d)", mode, first, count, primcount);
+
+    try
+    {
+        if (count < 0 || first < 0 || primcount < 0)
+        {
+            return error(GL_INVALID_VALUE);
+        }
+
+        if (primcount > 0)
+        {
+            gl::Context *context = gl::getNonLostContext();
+
+            if (context)
+            {
+                context->drawArrays(mode, first, count, primcount);
+            }
+        }
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(GL_OUT_OF_MEMORY);
+    }
+}
+
+void __stdcall glDrawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid* indices)
+{
+    EVENT("(GLenum mode = 0x%X, GLsizei count = %d, GLenum type = 0x%X, const GLvoid* indices = 0x%0.8p)",
+          mode, count, type, indices);
+
+    try
+    {
+        if (count < 0)
+        {
+            return error(GL_INVALID_VALUE);
+        }
+
+        gl::Context *context = gl::getNonLostContext();
+
+        if (context)
+        {
+            switch (type)
+            {
+              case GL_UNSIGNED_BYTE:
+              case GL_UNSIGNED_SHORT:
+                break;
+              case GL_UNSIGNED_INT:
+                if (!context->supports32bitIndices())
+                {
+                    return error(GL_INVALID_ENUM);    
+                }
+                break;
+              default:
+                return error(GL_INVALID_ENUM);
+            }
+        
+            context->drawElements(mode, count, type, indices, 0);
+        }
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(GL_OUT_OF_MEMORY);
+    }
+}
+
+void __stdcall glDrawElementsInstancedANGLE(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, GLsizei primcount)
+{
+    EVENT("(GLenum mode = 0x%X, GLsizei count = %d, GLenum type = 0x%X, const GLvoid* indices = 0x%0.8p, GLsizei primcount = %d)",
+          mode, count, type, indices, primcount);
+
+    try
+    {
+        if (count < 0 || primcount < 0)
+        {
+            return error(GL_INVALID_VALUE);
+        }
+
+        if (primcount > 0)
+        {
+            gl::Context *context = gl::getNonLostContext();
+
+            if (context)
+            {
+                switch (type)
+                {
+                  case GL_UNSIGNED_BYTE:
+                  case GL_UNSIGNED_SHORT:
+                    break;
+                  case GL_UNSIGNED_INT:
+                    if (!context->supports32bitIndices())
+                    {
+                        return error(GL_INVALID_ENUM);    
+                    }
+                    break;
+                  default:
+                    return error(GL_INVALID_ENUM);
+                }
+            
+                context->drawElements(mode, count, type, indices, primcount);
+            }
+        }
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(GL_OUT_OF_MEMORY);
+    }
+}
+
+void __stdcall glEnable(GLenum cap)
+{
+    EVENT("(GLenum cap = 0x%X)", cap);
+
+    try
+    {
+        gl::Context *context = gl::getNonLostContext();
+
+        if (context)
+        {
+            switch (cap)
+            {
+              case GL_CULL_FACE:                context->setCullFace(true);              break;
+              case GL_POLYGON_OFFSET_FILL:      context->setPolygonOffsetFill(true);     break;
+              case GL_SAMPLE_ALPHA_TO_COVERAGE: context->setSampleAlphaToCoverage(true); break;
+              case GL_SAMPLE_COVERAGE:          context->setSampleCoverage(true);        break;
+              case GL_SCISSOR_TEST:             context->setScissorTest(true);           break;
+              case GL_STENCIL_TEST:             context->setStencilTest(true);           break;
+              case GL_DEPTH_TEST:               context->setDepthTest(true);             break;
+              case GL_BLEND:                    context->setBlend(true);                 break;
+              case GL_DITHER:                   context->setDither(true);                break;
+              default:
+                return error(GL_INVALID_ENUM);
+            }
+        }
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(GL_OUT_OF_MEMORY);
+    }
+}
+
+void __stdcall glEnableVertexAttribArray(GLuint index)
+{
+    EVENT("(GLuint index = %d)", index);
+
+    try
+    {
+        if (index >= gl::MAX_VERTEX_ATTRIBS)
+        {
+            return error(GL_INVALID_VALUE);
+        }
+
+        gl::Context *context = gl::getNonLostContext();
+
+        if (context)
+        {
+            context->setEnableVertexAttribArray(index, true);
+        }
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(GL_OUT_OF_MEMORY);
+    }
+}
+
+void __stdcall glEndQueryEXT(GLenum target)
+{
+    EVENT("GLenum target = 0x%X)", target);
+
+    try
+    {
+        switch (target)
+        {
+          case GL_ANY_SAMPLES_PASSED_EXT: 
+          case GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT:
+              break;
+          default: 
+              return error(GL_INVALID_ENUM);
+        }
+
+        gl::Context *context = gl::getNonLostContext();
+
+        if (context)
+        {
+            context->endQuery(target);
+        }
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(GL_OUT_OF_MEMORY);
+    }
+}
+
+void __stdcall glFinishFenceNV(GLuint fence)
+{
+    EVENT("(GLuint fence = %d)", fence);
+
+    try
+    {
+        gl::Context *context = gl::getNonLostContext();
+
+        if (context)
+        {
+            gl::Fence* fenceObject = context->getFence(fence);
+
+            if (fenceObject == NULL)
+            {
+                return error(GL_INVALID_OPERATION);
+            }
+
+            fenceObject->finishFence();
+        }
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(GL_OUT_OF_MEMORY);
+    }
+}
+
+void __stdcall glFinish(void)
+{
+    EVENT("()");
+
+    try
+    {
+        gl::Context *context = gl::getNonLostContext();
+
+        if (context)
+        {
+            context->sync(true);
+        }
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(GL_OUT_OF_MEMORY);
+    }
+}
+
+void __stdcall glFlush(void)
+{
+    EVENT("()");
+
+    try
+    {
+        gl::Context *context = gl::getNonLostContext();
+
+        if (context)
+        {
+            context->sync(false);
+        }
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(GL_OUT_OF_MEMORY);
+    }
+}
+
+void __stdcall glFramebufferRenderbuffer(GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer)
+{
+    EVENT("(GLenum target = 0x%X, GLenum attachment = 0x%X, GLenum renderbuffertarget = 0x%X, "
+          "GLuint renderbuffer = %d)", target, attachment, renderbuffertarget, renderbuffer);
+
+    try
+    {
+        if ((target != GL_FRAMEBUFFER && target != GL_DRAW_FRAMEBUFFER_ANGLE && target != GL_READ_FRAMEBUFFER_ANGLE)
+            || (renderbuffertarget != GL_RENDERBUFFER && renderbuffer != 0))
+        {
+            return error(GL_INVALID_ENUM);
+        }
+
+        gl::Context *context = gl::getNonLostContext();
+
+        if (context)
+        {
+            gl::Framebuffer *framebuffer = NULL;
+            GLuint framebufferHandle = 0;
+            if (target == GL_READ_FRAMEBUFFER_ANGLE)
+            {
+                framebuffer = context->getReadFramebuffer();
+                framebufferHandle = context->getReadFramebufferHandle();
+            }
+            else
+            {
+                framebuffer = context->getDrawFramebuffer();
+                framebufferHandle = context->getDrawFramebufferHandle();
+            }
+
+            if (!framebuffer || (framebufferHandle == 0 && renderbuffer != 0))
+            {
+                return error(GL_INVALID_OPERATION);
+            }
+
+            switch (attachment)
+            {
+              case GL_COLOR_ATTACHMENT0:
+                framebuffer->setColorbuffer(GL_RENDERBUFFER, renderbuffer);
+                break;
+              case GL_DEPTH_ATTACHMENT:
+                framebuffer->setDepthbuffer(GL_RENDERBUFFER, renderbuffer);
+                break;
+              case GL_STENCIL_ATTACHMENT:
+                framebuffer->setStencilbuffer(GL_RENDERBUFFER, renderbuffer);
+                break;
+              default:
+                return error(GL_INVALID_ENUM);
+            }
+        }
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(GL_OUT_OF_MEMORY);
+    }
+}
+
+void __stdcall glFramebufferTexture2D(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level)
+{
+    EVENT("(GLenum target = 0x%X, GLenum attachment = 0x%X, GLenum textarget = 0x%X, "
+          "GLuint texture = %d, GLint level = %d)", target, attachment, textarget, texture, level);
+
+    try
+    {
+        if (target != GL_FRAMEBUFFER && target != GL_DRAW_FRAMEBUFFER_ANGLE && target != GL_READ_FRAMEBUFFER_ANGLE)
+        {
+            return error(GL_INVALID_ENUM);
+        }
+
+        switch (attachment)
+        {
+          case GL_COLOR_ATTACHMENT0:
+          case GL_DEPTH_ATTACHMENT:
+          case GL_STENCIL_ATTACHMENT:
+            break;
+          default:
+            return error(GL_INVALID_ENUM);
+        }
+
+        gl::Context *context = gl::getNonLostContext();
+
+        if (context)
+        {
+            if (texture == 0)
+            {
+                textarget = GL_NONE;
+            }
+            else
+            {
+                gl::Texture *tex = context->getTexture(texture);
+
+                if (tex == NULL)
+                {
+                    return error(GL_INVALID_OPERATION);
+                }
+
+                switch (textarget)
+                {
+                  case GL_TEXTURE_2D:
+                    {
+                        if (tex->getTarget() != GL_TEXTURE_2D)
+                        {
+                            return error(GL_INVALID_OPERATION);
+                        }
+                        gl::Texture2D *tex2d = static_cast<gl::Texture2D *>(tex);
+                        if (tex2d->isCompressed(0))
+                        {
+                            return error(GL_INVALID_OPERATION);
+                        }
+                        break;
+                    }
+
+                  case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
+                  case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
+                  case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
+                  case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
+                  case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
+                  case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
+                    {
+                        if (tex->getTarget() != GL_TEXTURE_CUBE_MAP)
+                        {
+                            return error(GL_INVALID_OPERATION);
+                        }
+                        gl::TextureCubeMap *texcube = static_cast<gl::TextureCubeMap *>(tex);
+                        if (texcube->isCompressed(textarget, level))
+                        {
+                            return error(GL_INVALID_OPERATION);
+                        }
+                        break;
+                    }
+
+                  default:
+                    return error(GL_INVALID_ENUM);
+                }
+
+                if (level != 0)
+                {
+                    return error(GL_INVALID_VALUE);
+                }
+            }
+
+            gl::Framebuffer *framebuffer = NULL;
+            GLuint framebufferHandle = 0;
+            if (target == GL_READ_FRAMEBUFFER_ANGLE)
+            {
+                framebuffer = context->getReadFramebuffer();
+                framebufferHandle = context->getReadFramebufferHandle();
+            }
+            else
+            {
+                framebuffer = context->getDrawFramebuffer();
+                framebufferHandle = context->getDrawFramebufferHandle();
+            }
+
+            if (framebufferHandle == 0 || !framebuffer)
+            {
+                return error(GL_INVALID_OPERATION);
+            }
+
+            switch (attachment)
+            {
+              case GL_COLOR_ATTACHMENT0:  framebuffer->setColorbuffer(textarget, texture);   break;
+              case GL_DEPTH_ATTACHMENT:   framebuffer->setDepthbuffer(textarget, texture);   break;
+              case GL_STENCIL_ATTACHMENT: framebuffer->setStencilbuffer(textarget, texture); break;
+            }
+        }
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(GL_OUT_OF_MEMORY);
+    }
+}
+
+void __stdcall glFrontFace(GLenum mode)
+{
+    EVENT("(GLenum mode = 0x%X)", mode);
+
+    try
+    {
+        switch (mode)
+        {
+          case GL_CW:
+          case GL_CCW:
+            {
+                gl::Context *context = gl::getNonLostContext();
+
+                if (context)
+                {
+                    context->setFrontFace(mode);
+                }
+            }
+            break;
+          default:
+            return error(GL_INVALID_ENUM);
+        }
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(GL_OUT_OF_MEMORY);
+    }
+}
+
+void __stdcall glGenBuffers(GLsizei n, GLuint* buffers)
+{
+    EVENT("(GLsizei n = %d, GLuint* buffers = 0x%0.8p)", n, buffers);
+
+    try
+    {
+        if (n < 0)
+        {
+            return error(GL_INVALID_VALUE);
+        }
+
+        gl::Context *context = gl::getNonLostContext();
+
+        if (context)
+        {
+            for (int i = 0; i < n; i++)
+            {
+                buffers[i] = context->createBuffer();
+            }
+        }
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(GL_OUT_OF_MEMORY);
+    }
+}
+
+void __stdcall glGenerateMipmap(GLenum target)
+{
+    EVENT("(GLenum target = 0x%X)", target);
+
+    try
+    {
+        gl::Context *context = gl::getNonLostContext();
+
+        if (context)
+        {
+            switch (target)
+            {
+              case GL_TEXTURE_2D:
+                {
+                    gl::Texture2D *tex2d = context->getTexture2D();
+
+                    if (tex2d->isCompressed(0))
+                    {
+                        return error(GL_INVALID_OPERATION);
+                    }
+                    if (tex2d->isDepth(0))
+                    {
+                        return error(GL_INVALID_OPERATION);
+                    }
+
+                    tex2d->generateMipmaps();
+                    break;
+                }
+
+              case GL_TEXTURE_CUBE_MAP:
+                {
+                    gl::TextureCubeMap *texcube = context->getTextureCubeMap();
+
+                    if (texcube->isCompressed(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0))
+                    {
+                        return error(GL_INVALID_OPERATION);
+                    }
+
+                    texcube->generateMipmaps();
+                    break;
+                }
+
+              default:
+                return error(GL_INVALID_ENUM);
+            }
+        }
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(GL_OUT_OF_MEMORY);
+    }
+}
+
+void __stdcall glGenFencesNV(GLsizei n, GLuint* fences)
+{
+    EVENT("(GLsizei n = %d, GLuint* fences = 0x%0.8p)", n, fences);
+
+    try
+    {
+        if (n < 0)
+        {
+            return error(GL_INVALID_VALUE);
+        }
+
+        gl::Context *context = gl::getNonLostContext();
+
+        if (context)
+        {
+            for (int i = 0; i < n; i++)
+            {
+                fences[i] = context->createFence();
+            }
+        }
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(GL_OUT_OF_MEMORY);
+    }
+}
+
+void __stdcall glGenFramebuffers(GLsizei n, GLuint* framebuffers)
+{
+    EVENT("(GLsizei n = %d, GLuint* framebuffers = 0x%0.8p)", n, framebuffers);
+
+    try
+    {
+        if (n < 0)
+        {
+            return error(GL_INVALID_VALUE);
+        }
+
+        gl::Context *context = gl::getNonLostContext();
+
+        if (context)
+        {
+            for (int i = 0; i < n; i++)
+            {
+                framebuffers[i] = context->createFramebuffer();
+            }
+        }
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(GL_OUT_OF_MEMORY);
+    }
+}
+
+void __stdcall glGenQueriesEXT(GLsizei n, GLuint* ids)
+{
+    EVENT("(GLsizei n = %d, GLuint* ids = 0x%0.8p)", n, ids);
+
+    try
+    {
+        if (n < 0)
+        {
+            return error(GL_INVALID_VALUE);
+        }
+
+        gl::Context *context = gl::getNonLostContext();
+
+        if (context)
+        {
+            for (int i = 0; i < n; i++)
+            {
+                ids[i] = context->createQuery();
+            }
+        }
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(GL_OUT_OF_MEMORY);
+    }
+}
+
+void __stdcall glGenRenderbuffers(GLsizei n, GLuint* renderbuffers)
+{
+    EVENT("(GLsizei n = %d, GLuint* renderbuffers = 0x%0.8p)", n, renderbuffers);
+
+    try
+    {
+        if (n < 0)
+        {
+            return error(GL_INVALID_VALUE);
+        }
+
+        gl::Context *context = gl::getNonLostContext();
+
+        if (context)
+        {
+            for (int i = 0; i < n; i++)
+            {
+                renderbuffers[i] = context->createRenderbuffer();
+            }
+        }
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(GL_OUT_OF_MEMORY);
+    }
+}
+
+void __stdcall glGenTextures(GLsizei n, GLuint* textures)
+{
+    EVENT("(GLsizei n = %d, GLuint* textures =  0x%0.8p)", n, textures);
+
+    try
+    {
+        if (n < 0)
+        {
+            return error(GL_INVALID_VALUE);
+        }
+
+        gl::Context *context = gl::getNonLostContext();
+
+        if (context)
+        {
+            for (int i = 0; i < n; i++)
+            {
+                textures[i] = context->createTexture();
+            }
+        }
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(GL_OUT_OF_MEMORY);
+    }
+}
+
+void __stdcall glGetActiveAttrib(GLuint program, GLuint index, GLsizei bufsize, GLsizei *length, GLint *size, GLenum *type, GLchar *name)
+{
+    EVENT("(GLuint program = %d, GLuint index = %d, GLsizei bufsize = %d, GLsizei *length = 0x%0.8p, "
+          "GLint *size = 0x%0.8p, GLenum *type = %0.8p, GLchar *name = %0.8p)",
+          program, index, bufsize, length, size, type, name);
+
+    try
+    {
+        if (bufsize < 0)
+        {
+            return error(GL_INVALID_VALUE);
+        }
+
+        gl::Context *context = gl::getNonLostContext();
+
+        if (context)
+        {
+            gl::Program *programObject = context->getProgram(program);
+
+            if (!programObject)
+            {
+                if (context->getShader(program))
+                {
+                    return error(GL_INVALID_OPERATION);
+                }
+                else
+                {
+                    return error(GL_INVALID_VALUE);
+                }
+            }
+
+            if (index >= (GLuint)programObject->getActiveAttributeCount())
+            {
+                return error(GL_INVALID_VALUE);
+            }
+
+            programObject->getActiveAttribute(index, bufsize, length, size, type, name);
+        }
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(GL_OUT_OF_MEMORY);
+    }
+}
+
+void __stdcall glGetActiveUniform(GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, GLchar* name)
+{
+    EVENT("(GLuint program = %d, GLuint index = %d, GLsizei bufsize = %d, "
+          "GLsizei* length = 0x%0.8p, GLint* size = 0x%0.8p, GLenum* type = 0x%0.8p, GLchar* name = 0x%0.8p)",
+          program, index, bufsize, length, size, type, name);
+
+    try
+    {
+        if (bufsize < 0)
+        {
+            return error(GL_INVALID_VALUE);
+        }
+
+        gl::Context *context = gl::getNonLostContext();
+
+        if (context)
+        {
+            gl::Program *programObject = context->getProgram(program);
+
+            if (!programObject)
+            {
+                if (context->getShader(program))
+                {
+                    return error(GL_INVALID_OPERATION);
+                }
+                else
+                {
+                    return error(GL_INVALID_VALUE);
+                }
+            }
+
+            if (index >= (GLuint)programObject->getActiveUniformCount())
+            {
+                return error(GL_INVALID_VALUE);
+            }
+
+            programObject->getActiveUniform(index, bufsize, length, size, type, name);
+        }
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(GL_OUT_OF_MEMORY);
+    }
+}
+
+void __stdcall glGetAttachedShaders(GLuint program, GLsizei maxcount, GLsizei* count, GLuint* shaders)
+{
+    EVENT("(GLuint program = %d, GLsizei maxcount = %d, GLsizei* count = 0x%0.8p, GLuint* shaders = 0x%0.8p)",
+          program, maxcount, count, shaders);
+
+    try
+    {
+        if (maxcount < 0)
+        {
+            return error(GL_INVALID_VALUE);
+        }
+
+        gl::Context *context = gl::getNonLostContext();
+
+        if (context)
+        {
+            gl::Program *programObject = context->getProgram(program);
+
+            if (!programObject)
+            {
+                if (context->getShader(program))
+                {
+                    return error(GL_INVALID_OPERATION);
+                }
+                else
+                {
+                    return error(GL_INVALID_VALUE);
+                }
+            }
+
+            return programObject->getAttachedShaders(maxcount, count, shaders);
+        }
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(GL_OUT_OF_MEMORY);
+    }
+}
+
+int __stdcall glGetAttribLocation(GLuint program, const GLchar* name)
+{
+    EVENT("(GLuint program = %d, const GLchar* name = %s)", program, name);
+
+    try
+    {
+        gl::Context *context = gl::getNonLostContext();
+
+        if (context)
+        {
+
+            gl::Program *programObject = context->getProgram(program);
+
+            if (!programObject)
+            {
+                if (context->getShader(program))
+                {
+                    return error(GL_INVALID_OPERATION, -1);
+                }
+                else
+                {
+                    return error(GL_INVALID_VALUE, -1);
+                }
+            }
+
+            gl::ProgramBinary *programBinary = programObject->getProgramBinary();
+            if (!programObject->isLinked() || !programBinary)
+            {
+                return error(GL_INVALID_OPERATION, -1);
+            }
+
+            return programBinary->getAttributeLocation(name);
+        }
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(GL_OUT_OF_MEMORY, -1);
+    }
+
+    return -1;
+}
+
+void __stdcall glGetBooleanv(GLenum pname, GLboolean* params)
+{
+    EVENT("(GLenum pname = 0x%X, GLboolean* params = 0x%0.8p)",  pname, params);
+
+    try
+    {
+        gl::Context *context = gl::getNonLostContext();
+
+        if (context)
+        {
+            if (!(context->getBooleanv(pname, params)))
+            {
+                GLenum nativeType;
+                unsigned int numParams = 0;
+                if (!context->getQueryParameterInfo(pname, &nativeType, &numParams))
+                    return error(GL_INVALID_ENUM);
+
+                if (numParams == 0)
+                    return; // it is known that the pname is valid, but there are no parameters to return
+
+                if (nativeType == GL_FLOAT)
+                {
+                    GLfloat *floatParams = NULL;
+                    floatParams = new GLfloat[numParams];
+
+                    context->getFloatv(pname, floatParams);
+
+                    for (unsigned int i = 0; i < numParams; ++i)
+                    {
+                        if (floatParams[i] == 0.0f)
+                            params[i] = GL_FALSE;
+                        else
+                            params[i] = GL_TRUE;
+                    }
+
+                    delete [] floatParams;
+                }
+                else if (nativeType == GL_INT)
+                {
+                    GLint *intParams = NULL;
+                    intParams = new GLint[numParams];
+
+                    context->getIntegerv(pname, intParams);
+
+                    for (unsigned int i = 0; i < numParams; ++i)
+                    {
+                        if (intParams[i] == 0)
+                            params[i] = GL_FALSE;
+                        else
+                            params[i] = GL_TRUE;
+                    }
+
+                    delete [] intParams;
+                }
+            }
+        }
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(GL_OUT_OF_MEMORY);
+    }
+}
+
+void __stdcall glGetBufferParameteriv(GLenum target, GLenum pname, GLint* params)
+{
+    EVENT("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint* params = 0x%0.8p)", target, pname, params);
+
+    try
+    {
+        gl::Context *context = gl::getNonLostContext();
+
+        if (context)
+        {
+            gl::Buffer *buffer;
+
+            switch (target)
+            {
+              case GL_ARRAY_BUFFER:
+                buffer = context->getArrayBuffer();
+                break;
+              case GL_ELEMENT_ARRAY_BUFFER:
+                buffer = context->getElementArrayBuffer();
+                break;
+              default: return error(GL_INVALID_ENUM);
+            }
+
+            if (!buffer)
+            {
+                // A null buffer means that "0" is bound to the requested buffer target
+                return error(GL_INVALID_OPERATION);
+            }
+
+            switch (pname)
+            {
+              case GL_BUFFER_USAGE:
+                *params = buffer->usage();
+                break;
+              case GL_BUFFER_SIZE:
+                *params = buffer->size();
+                break;
+              default: return error(GL_INVALID_ENUM);
+            }
+        }
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(GL_OUT_OF_MEMORY);
+    }
+}
+
+GLenum __stdcall glGetError(void)
+{
+    EVENT("()");
+
+    gl::Context *context = gl::getContext();
+
+    if (context)
+    {
+        return context->getError();
+    }
+
+    return GL_NO_ERROR;
+}
+
+void __stdcall glGetFenceivNV(GLuint fence, GLenum pname, GLint *params)
+{
+    EVENT("(GLuint fence = %d, GLenum pname = 0x%X, GLint *params = 0x%0.8p)", fence, pname, params);
+
+    try
+    {
+    
+        gl::Context *context = gl::getNonLostContext();
+
+        if (context)
+        {
+            gl::Fence *fenceObject = context->getFence(fence);
+
+            if (fenceObject == NULL)
+            {
+                return error(GL_INVALID_OPERATION);
+            }
+
+            fenceObject->getFenceiv(pname, params);
+        }
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(GL_OUT_OF_MEMORY);
+    }
+}
+
+void __stdcall glGetFloatv(GLenum pname, GLfloat* params)
+{
+    EVENT("(GLenum pname = 0x%X, GLfloat* params = 0x%0.8p)", pname, params);
+
+    try
+    {
+        gl::Context *context = gl::getNonLostContext();
+
+        if (context)
+        {
+            if (!(context->getFloatv(pname, params)))
+            {
+                GLenum nativeType;
+                unsigned int numParams = 0;
+                if (!context->getQueryParameterInfo(pname, &nativeType, &numParams))
+                    return error(GL_INVALID_ENUM);
+
+                if (numParams == 0)
+                    return; // it is known that the pname is valid, but that there are no parameters to return.
+
+                if (nativeType == GL_BOOL)
+                {
+                    GLboolean *boolParams = NULL;
+                    boolParams = new GLboolean[numParams];
+
+                    context->getBooleanv(pname, boolParams);
+
+                    for (unsigned int i = 0; i < numParams; ++i)
+                    {
+                        if (boolParams[i] == GL_FALSE)
+                            params[i] = 0.0f;
+                        else
+                            params[i] = 1.0f;
+                    }
+
+                    delete [] boolParams;
+                }
+                else if (nativeType == GL_INT)
+                {
+                    GLint *intParams = NULL;
+                    intParams = new GLint[numParams];
+
+                    context->getIntegerv(pname, intParams);
+
+                    for (unsigned int i = 0; i < numParams; ++i)
+                    {
+                        params[i] = (GLfloat)intParams[i];
+                    }
+
+                    delete [] intParams;
+                }
+            }
+        }
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(GL_OUT_OF_MEMORY);
+    }
+}
+
+void __stdcall glGetFramebufferAttachmentParameteriv(GLenum target, GLenum attachment, GLenum pname, GLint* params)
+{
+    EVENT("(GLenum target = 0x%X, GLenum attachment = 0x%X, GLenum pname = 0x%X, GLint* params = 0x%0.8p)",
+          target, attachment, pname, params);
+
+    try
+    {
+        gl::Context *context = gl::getNonLostContext();
+
+        if (context)
+        {
+            if (target != GL_FRAMEBUFFER && target != GL_DRAW_FRAMEBUFFER_ANGLE && target != GL_READ_FRAMEBUFFER_ANGLE)
+            {
+                return error(GL_INVALID_ENUM);
+            }
+
+            gl::Framebuffer *framebuffer = NULL;
+            if (target == GL_READ_FRAMEBUFFER_ANGLE)
+            {
+                if(context->getReadFramebufferHandle() == 0)
+                {
+                    return error(GL_INVALID_OPERATION);
+                }
+
+                framebuffer = context->getReadFramebuffer();
+            }
+            else 
+            {
+                if (context->getDrawFramebufferHandle() == 0)
+                {
+                    return error(GL_INVALID_OPERATION);
+                }
+
+                framebuffer = context->getDrawFramebuffer();
+            }
+
+            GLenum attachmentType;
+            GLuint attachmentHandle;
+            switch (attachment)
+            {
+              case GL_COLOR_ATTACHMENT0:    
+                attachmentType = framebuffer->getColorbufferType();
+                attachmentHandle = framebuffer->getColorbufferHandle(); 
+                break;
+              case GL_DEPTH_ATTACHMENT:     
+                attachmentType = framebuffer->getDepthbufferType();
+                attachmentHandle = framebuffer->getDepthbufferHandle();
+                break;
+              case GL_STENCIL_ATTACHMENT:   
+                attachmentType = framebuffer->getStencilbufferType();
+                attachmentHandle = framebuffer->getStencilbufferHandle();
+                break;
+              default: return error(GL_INVALID_ENUM);
+            }
+
+            GLenum attachmentObjectType;   // Type category
+            if (attachmentType == GL_NONE || attachmentType == GL_RENDERBUFFER)
+            {
+                attachmentObjectType = attachmentType;
+            }
+            else if (gl::IsInternalTextureTarget(attachmentType))
+            {
+                attachmentObjectType = GL_TEXTURE;
+            }
+            else
+            {
+                UNREACHABLE();
+                return;
+            }
+
+            switch (pname)
+            {
+              case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
+                *params = attachmentObjectType;
+                break;
+              case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
+                if (attachmentObjectType == GL_RENDERBUFFER || attachmentObjectType == GL_TEXTURE)
+                {
+                    *params = attachmentHandle;
+                }
+                else
+                {
+                    return error(GL_INVALID_ENUM);
+                }
+                break;
+              case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
+                if (attachmentObjectType == GL_TEXTURE)
+                {
+                    *params = 0; // FramebufferTexture2D will not allow level to be set to anything else in GL ES 2.0
+                }
+                else
+                {
+                    return error(GL_INVALID_ENUM);
+                }
+                break;
+              case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
+                if (attachmentObjectType == GL_TEXTURE)
+                {
+                    if (gl::IsCubemapTextureTarget(attachmentType))
+                    {
+                        *params = attachmentType;
+                    }
+                    else
+                    {
+                        *params = 0;
+                    }
+                }
+                else
+                {
+                    return error(GL_INVALID_ENUM);
+                }
+                break;
+              default:
+                return error(GL_INVALID_ENUM);
+            }
+        }
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(GL_OUT_OF_MEMORY);
+    }
+}
+
+GLenum __stdcall glGetGraphicsResetStatusEXT(void)
+{
+    EVENT("()");
+
+    try
+    {
+        gl::Context *context = gl::getContext();
+
+        if (context)
+        {
+            return context->getResetStatus();
+        }
+
+        return GL_NO_ERROR;
+    }
+    catch(std::bad_alloc&)
+    {
+        return GL_OUT_OF_MEMORY;
+    }
+}
+
+void __stdcall glGetIntegerv(GLenum pname, GLint* params)
+{
+    EVENT("(GLenum pname = 0x%X, GLint* params = 0x%0.8p)", pname, params);
+
+    try
+    {
+        gl::Context *context = gl::getNonLostContext();
+
+        if (context)
+        {
+            if (!(context->getIntegerv(pname, params)))
+            {
+                GLenum nativeType;
+                unsigned int numParams = 0;
+                if (!context->getQueryParameterInfo(pname, &nativeType, &numParams))
+                    return error(GL_INVALID_ENUM);
+
+                if (numParams == 0)
+                    return; // it is known that pname is valid, but there are no parameters to return
+
+                if (nativeType == GL_BOOL)
+                {
+                    GLboolean *boolParams = NULL;
+                    boolParams = new GLboolean[numParams];
+
+                    context->getBooleanv(pname, boolParams);
+
+                    for (unsigned int i = 0; i < numParams; ++i)
+                    {
+                        if (boolParams[i] == GL_FALSE)
+                            params[i] = 0;
+                        else
+                            params[i] = 1;
+                    }
+
+                    delete [] boolParams;
+                }
+                else if (nativeType == GL_FLOAT)
+                {
+                    GLfloat *floatParams = NULL;
+                    floatParams = new GLfloat[numParams];
+
+                    context->getFloatv(pname, floatParams);
+
+                    for (unsigned int i = 0; i < numParams; ++i)
+                    {
+                        if (pname == GL_DEPTH_RANGE || pname == GL_COLOR_CLEAR_VALUE || pname == GL_DEPTH_CLEAR_VALUE || pname == GL_BLEND_COLOR)
+                        {
+                            params[i] = (GLint)(((GLfloat)(0xFFFFFFFF) * floatParams[i] - 1.0f) / 2.0f);
+                        }
+                        else
+                            params[i] = (GLint)(floatParams[i] > 0.0f ? floor(floatParams[i] + 0.5) : ceil(floatParams[i] - 0.5));
+                    }
+
+                    delete [] floatParams;
+                }
+            }
+        }
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(GL_OUT_OF_MEMORY);
+    }
+}
+
+void __stdcall glGetProgramiv(GLuint program, GLenum pname, GLint* params)
+{
+    EVENT("(GLuint program = %d, GLenum pname = %d, GLint* params = 0x%0.8p)", program, pname, params);
+
+    try
+    {
+        gl::Context *context = gl::getNonLostContext();
+
+        if (context)
+        {
+            gl::Program *programObject = context->getProgram(program);
+
+            if (!programObject)
+            {
+                return error(GL_INVALID_VALUE);
+            }
+
+            switch (pname)
+            {
+              case GL_DELETE_STATUS:
+                *params = programObject->isFlaggedForDeletion();
+                return;
+              case GL_LINK_STATUS:
+                *params = programObject->isLinked();
+                return;
+              case GL_VALIDATE_STATUS:
+                *params = programObject->isValidated();
+                return;
+              case GL_INFO_LOG_LENGTH:
+                *params = programObject->getInfoLogLength();
+                return;
+              case GL_ATTACHED_SHADERS:
+                *params = programObject->getAttachedShadersCount();
+                return;
+              case GL_ACTIVE_ATTRIBUTES:
+                *params = programObject->getActiveAttributeCount();
+                return;
+              case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH:
+                *params = programObject->getActiveAttributeMaxLength();
+                return;
+              case GL_ACTIVE_UNIFORMS:
+                *params = programObject->getActiveUniformCount();
+                return;
+              case GL_ACTIVE_UNIFORM_MAX_LENGTH:
+                *params = programObject->getActiveUniformMaxLength();
+                return;
+              case GL_PROGRAM_BINARY_LENGTH_OES:
+                *params = programObject->getProgramBinaryLength();
+                return;
+              default:
+                return error(GL_INVALID_ENUM);
+            }
+        }
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(GL_OUT_OF_MEMORY);
+    }
+}
+
+void __stdcall glGetProgramInfoLog(GLuint program, GLsizei bufsize, GLsizei* length, GLchar* infolog)
+{
+    EVENT("(GLuint program = %d, GLsizei bufsize = %d, GLsizei* length = 0x%0.8p, GLchar* infolog = 0x%0.8p)",
+          program, bufsize, length, infolog);
+
+    try
+    {
+        if (bufsize < 0)
+        {
+            return error(GL_INVALID_VALUE);
+        }
+
+        gl::Context *context = gl::getNonLostContext();
+
+        if (context)
+        {
+            gl::Program *programObject = context->getProgram(program);
+
+            if (!programObject)
+            {
+                return error(GL_INVALID_VALUE);
+            }
+
+            programObject->getInfoLog(bufsize, length, infolog);
+        }
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(GL_OUT_OF_MEMORY);
+    }
+}
+
+void __stdcall glGetQueryivEXT(GLenum target, GLenum pname, GLint *params)
+{
+    EVENT("GLenum target = 0x%X, GLenum pname = 0x%X, GLint *params = 0x%0.8p)", target, pname, params);
+
+    try
+    {
+        switch (pname)
+        {
+          case GL_CURRENT_QUERY_EXT:
+            break;
+          default:
+            return error(GL_INVALID_ENUM);
+        }
+
+        gl::Context *context = gl::getNonLostContext();
+
+        if (context)
+        {
+            params[0] = context->getActiveQuery(target);
+        }
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(GL_OUT_OF_MEMORY);
+    }
+}
+
+void __stdcall glGetQueryObjectuivEXT(GLuint id, GLenum pname, GLuint *params)
+{
+    EVENT("(GLuint id = %d, GLenum pname = 0x%X, GLuint *params = 0x%0.8p)", id, pname, params);
+
+    try
+    {
+        switch (pname)
+        {
+          case GL_QUERY_RESULT_EXT:
+          case GL_QUERY_RESULT_AVAILABLE_EXT:
+            break;
+          default:
+            return error(GL_INVALID_ENUM);
+        }
+        gl::Context *context = gl::getNonLostContext();
+
+        if (context)
+        {
+            gl::Query *queryObject = context->getQuery(id, false, GL_NONE);
+
+            if (!queryObject)
+            {
+                return error(GL_INVALID_OPERATION);
+            }
+
+            if (context->getActiveQuery(queryObject->getType()) == id)
+            {
+                return error(GL_INVALID_OPERATION);
+            }
+
+            switch(pname)
+            {
+              case GL_QUERY_RESULT_EXT:
+                params[0] = queryObject->getResult();
+                break;
+              case GL_QUERY_RESULT_AVAILABLE_EXT:
+                params[0] = queryObject->isResultAvailable();
+                break;
+              default:
+                ASSERT(false);
+            }
+        }
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(GL_OUT_OF_MEMORY);
+    }
+}
+
+void __stdcall glGetRenderbufferParameteriv(GLenum target, GLenum pname, GLint* params)
+{
+    EVENT("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint* params = 0x%0.8p)", target, pname, params);
+
+    try
+    {
+        gl::Context *context = gl::getNonLostContext();
+
+        if (context)
+        {
+            if (target != GL_RENDERBUFFER)
+            {
+                return error(GL_INVALID_ENUM);
+            }
+
+            if (context->getRenderbufferHandle() == 0)
+            {
+                return error(GL_INVALID_OPERATION);
+            }
+
+            gl::Renderbuffer *renderbuffer = context->getRenderbuffer(context->getRenderbufferHandle());
+
+            switch (pname)
+            {
+              case GL_RENDERBUFFER_WIDTH:           *params = renderbuffer->getWidth();          break;
+              case GL_RENDERBUFFER_HEIGHT:          *params = renderbuffer->getHeight();         break;
+              case GL_RENDERBUFFER_INTERNAL_FORMAT: *params = renderbuffer->getInternalFormat(); break;
+              case GL_RENDERBUFFER_RED_SIZE:        *params = renderbuffer->getRedSize();        break;
+              case GL_RENDERBUFFER_GREEN_SIZE:      *params = renderbuffer->getGreenSize();      break;
+              case GL_RENDERBUFFER_BLUE_SIZE:       *params = renderbuffer->getBlueSize();       break;
+              case GL_RENDERBUFFER_ALPHA_SIZE:      *params = renderbuffer->getAlphaSize();      break;
+              case GL_RENDERBUFFER_DEPTH_SIZE:      *params = renderbuffer->getDepthSize();      break;
+              case GL_RENDERBUFFER_STENCIL_SIZE:    *params = renderbuffer->getStencilSize();    break;
+              case GL_RENDERBUFFER_SAMPLES_ANGLE:
+                if (context->getMaxSupportedSamples() != 0)
+                {
+                    *params = renderbuffer->getSamples();
+                }
+                else
+                {
+                    return error(GL_INVALID_ENUM);
+                }
+                break;
+              default:
+                return error(GL_INVALID_ENUM);
+            }
+        }
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(GL_OUT_OF_MEMORY);
+    }
+}
+
+void __stdcall glGetShaderiv(GLuint shader, GLenum pname, GLint* params)
+{
+    EVENT("(GLuint shader = %d, GLenum pname = %d, GLint* params = 0x%0.8p)", shader, pname, params);
+
+    try
+    {
+        gl::Context *context = gl::getNonLostContext();
+
+        if (context)
+        {
+            gl::Shader *shaderObject = context->getShader(shader);
+
+            if (!shaderObject)
+            {
+                return error(GL_INVALID_VALUE);
+            }
+
+            switch (pname)
+            {
+              case GL_SHADER_TYPE:
+                *params = shaderObject->getType();
+                return;
+              case GL_DELETE_STATUS:
+                *params = shaderObject->isFlaggedForDeletion();
+                return;
+              case GL_COMPILE_STATUS:
+                *params = shaderObject->isCompiled() ? GL_TRUE : GL_FALSE;
+                return;
+              case GL_INFO_LOG_LENGTH:
+                *params = shaderObject->getInfoLogLength();
+                return;
+              case GL_SHADER_SOURCE_LENGTH:
+                *params = shaderObject->getSourceLength();
+                return;
+              case GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE:
+                *params = shaderObject->getTranslatedSourceLength();
+                return;
+              default:
+                return error(GL_INVALID_ENUM);
+            }
+        }
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(GL_OUT_OF_MEMORY);
+    }
+}
+
+void __stdcall glGetShaderInfoLog(GLuint shader, GLsizei bufsize, GLsizei* length, GLchar* infolog)
+{
+    EVENT("(GLuint shader = %d, GLsizei bufsize = %d, GLsizei* length = 0x%0.8p, GLchar* infolog = 0x%0.8p)",
+          shader, bufsize, length, infolog);
+
+    try
+    {
+        if (bufsize < 0)
+        {
+            return error(GL_INVALID_VALUE);
+        }
+
+        gl::Context *context = gl::getNonLostContext();
+
+        if (context)
+        {
+            gl::Shader *shaderObject = context->getShader(shader);
+
+            if (!shaderObject)
+            {
+                return error(GL_INVALID_VALUE);
+            }
+
+            shaderObject->getInfoLog(bufsize, length, infolog);
+        }
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(GL_OUT_OF_MEMORY);
+    }
+}
+
+void __stdcall glGetShaderPrecisionFormat(GLenum shadertype, GLenum precisiontype, GLint* range, GLint* precision)
+{
+    EVENT("(GLenum shadertype = 0x%X, GLenum precisiontype = 0x%X, GLint* range = 0x%0.8p, GLint* precision = 0x%0.8p)",
+          shadertype, precisiontype, range, precision);
+
+    try
+    {
+        switch (shadertype)
+        {
+          case GL_VERTEX_SHADER:
+          case GL_FRAGMENT_SHADER:
+            break;
+          default:
+            return error(GL_INVALID_ENUM);
+        }
+
+        switch (precisiontype)
+        {
+          case GL_LOW_FLOAT:
+          case GL_MEDIUM_FLOAT:
+          case GL_HIGH_FLOAT:
+            // Assume IEEE 754 precision
+            range[0] = 127;
+            range[1] = 127;
+            *precision = 23;
+            break;
+          case GL_LOW_INT:
+          case GL_MEDIUM_INT:
+          case GL_HIGH_INT:
+            // Some (most) hardware only supports single-precision floating-point numbers,
+            // which can accurately represent integers up to +/-16777216
+            range[0] = 24;
+            range[1] = 24;
+            *precision = 0;
+            break;
+          default:
+            return error(GL_INVALID_ENUM);
+        }
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(GL_OUT_OF_MEMORY);
+    }
+}
+
+void __stdcall glGetShaderSource(GLuint shader, GLsizei bufsize, GLsizei* length, GLchar* source)
+{
+    EVENT("(GLuint shader = %d, GLsizei bufsize = %d, GLsizei* length = 0x%0.8p, GLchar* source = 0x%0.8p)",
+          shader, bufsize, length, source);
+
+    try
+    {
+        if (bufsize < 0)
+        {
+            return error(GL_INVALID_VALUE);
+        }
+
+        gl::Context *context = gl::getNonLostContext();
+
+        if (context)
+        {
+            gl::Shader *shaderObject = context->getShader(shader);
+
+            if (!shaderObject)
+            {
+                return error(GL_INVALID_OPERATION);
+            }
+
+            shaderObject->getSource(bufsize, length, source);
+        }
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(GL_OUT_OF_MEMORY);
+    }
+}
+
+void __stdcall glGetTranslatedShaderSourceANGLE(GLuint shader, GLsizei bufsize, GLsizei* length, GLchar* source)
+{
+    EVENT("(GLuint shader = %d, GLsizei bufsize = %d, GLsizei* length = 0x%0.8p, GLchar* source = 0x%0.8p)",
+          shader, bufsize, length, source);
+
+    try
+    {
+        if (bufsize < 0)
+        {
+            return error(GL_INVALID_VALUE);
+        }
+
+        gl::Context *context = gl::getNonLostContext();
+
+        if (context)
+        {
+            gl::Shader *shaderObject = context->getShader(shader);
+
+            if (!shaderObject)
+            {
+                return error(GL_INVALID_OPERATION);
+            }
+
+            shaderObject->getTranslatedSource(bufsize, length, source);
+        }
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(GL_OUT_OF_MEMORY);
+    }
+}
+
+const GLubyte* __stdcall glGetString(GLenum name)
+{
+    EVENT("(GLenum name = 0x%X)", name);
+
+    try
+    {
+        gl::Context *context = gl::getNonLostContext();
+
+        switch (name)
+        {
+          case GL_VENDOR:
+            return (GLubyte*)"Google Inc.";
+          case GL_RENDERER:
+            return (GLubyte*)((context != NULL) ? context->getRendererString() : "ANGLE");
+          case GL_VERSION:
+            return (GLubyte*)"OpenGL ES 2.0 (ANGLE " VERSION_STRING ")";
+          case GL_SHADING_LANGUAGE_VERSION:
+            return (GLubyte*)"OpenGL ES GLSL ES 1.00 (ANGLE " VERSION_STRING ")";
+          case GL_EXTENSIONS:
+            return (GLubyte*)((context != NULL) ? context->getExtensionString() : "");
+          default:
+            return error(GL_INVALID_ENUM, (GLubyte*)NULL);
+        }
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(GL_OUT_OF_MEMORY, (GLubyte*)NULL);
+    }
+}
+
+void __stdcall glGetTexParameterfv(GLenum target, GLenum pname, GLfloat* params)
+{
+    EVENT("(GLenum target = 0x%X, GLenum pname = 0x%X, GLfloat* params = 0x%0.8p)", target, pname, params);
+
+    try
+    {
+        gl::Context *context = gl::getNonLostContext();
+
+        if (context)
+        {
+            gl::Texture *texture;
+
+            switch (target)
+            {
+              case GL_TEXTURE_2D:
+                texture = context->getTexture2D();
+                break;
+              case GL_TEXTURE_CUBE_MAP:
+                texture = context->getTextureCubeMap();
+                break;
+              default:
+                return error(GL_INVALID_ENUM);
+            }
+
+            switch (pname)
+            {
+              case GL_TEXTURE_MAG_FILTER:
+                *params = (GLfloat)texture->getMagFilter();
+                break;
+              case GL_TEXTURE_MIN_FILTER:
+                *params = (GLfloat)texture->getMinFilter();
+                break;
+              case GL_TEXTURE_WRAP_S:
+                *params = (GLfloat)texture->getWrapS();
+                break;
+              case GL_TEXTURE_WRAP_T:
+                *params = (GLfloat)texture->getWrapT();
+                break;
+              case GL_TEXTURE_IMMUTABLE_FORMAT_EXT:
+                *params = (GLfloat)(texture->isImmutable() ? GL_TRUE : GL_FALSE);
+                break;
+              case GL_TEXTURE_USAGE_ANGLE:
+                *params = (GLfloat)texture->getUsage();
+                break;
+              case GL_TEXTURE_MAX_ANISOTROPY_EXT:
+                if (!context->supportsTextureFilterAnisotropy())
+                {
+                    return error(GL_INVALID_ENUM);
+                }
+                *params = (GLfloat)texture->getMaxAnisotropy();
+                break;
+              default:
+                return error(GL_INVALID_ENUM);
+            }
+        }
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(GL_OUT_OF_MEMORY);
+    }
+}
+
+void __stdcall glGetTexParameteriv(GLenum target, GLenum pname, GLint* params)
+{
+    EVENT("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint* params = 0x%0.8p)", target, pname, params);
+
+    try
+    {
+        gl::Context *context = gl::getNonLostContext();
+
+        if (context)
+        {
+            gl::Texture *texture;
+
+            switch (target)
+            {
+              case GL_TEXTURE_2D:
+                texture = context->getTexture2D();
+                break;
+              case GL_TEXTURE_CUBE_MAP:
+                texture = context->getTextureCubeMap();
+                break;
+              default:
+                return error(GL_INVALID_ENUM);
+            }
+
+            switch (pname)
+            {
+              case GL_TEXTURE_MAG_FILTER:
+                *params = texture->getMagFilter();
+                break;
+              case GL_TEXTURE_MIN_FILTER:
+                *params = texture->getMinFilter();
+                break;
+              case GL_TEXTURE_WRAP_S:
+                *params = texture->getWrapS();
+                break;
+              case GL_TEXTURE_WRAP_T:
+                *params = texture->getWrapT();
+                break;
+              case GL_TEXTURE_IMMUTABLE_FORMAT_EXT:
+                *params = texture->isImmutable() ? GL_TRUE : GL_FALSE;
+                break;
+              case GL_TEXTURE_USAGE_ANGLE:
+                *params = texture->getUsage();
+                break;
+              case GL_TEXTURE_MAX_ANISOTROPY_EXT:
+                if (!context->supportsTextureFilterAnisotropy())
+                {
+                    return error(GL_INVALID_ENUM);
+                }
+                *params = (GLint)texture->getMaxAnisotropy();
+                break;
+              default:
+                return error(GL_INVALID_ENUM);
+            }
+        }
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(GL_OUT_OF_MEMORY);
+    }
+}
+
+void __stdcall glGetnUniformfvEXT(GLuint program, GLint location, GLsizei bufSize, GLfloat* params)
+{
+    EVENT("(GLuint program = %d, GLint location = %d, GLsizei bufSize = %d, GLfloat* params = 0x%0.8p)",
+          program, location, bufSize, params);
+
+    try
+    {
+        if (bufSize < 0)
+        {
+            return error(GL_INVALID_VALUE);
+        }
+
+        gl::Context *context = gl::getNonLostContext();
+
+        if (context)
+        {
+            if (program == 0)
+            {
+                return error(GL_INVALID_VALUE);
+            }
+
+            gl::Program *programObject = context->getProgram(program);
+
+            if (!programObject || !programObject->isLinked())
+            {
+                return error(GL_INVALID_OPERATION);
+            }
+
+            gl::ProgramBinary *programBinary = programObject->getProgramBinary();
+            if (!programBinary)
+            {
+                return error(GL_INVALID_OPERATION);
+            }
+
+            if (!programBinary->getUniformfv(location, &bufSize, params))
+            {
+                return error(GL_INVALID_OPERATION);
+            }
+        }
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(GL_OUT_OF_MEMORY);
+    }
+}
+
+void __stdcall glGetUniformfv(GLuint program, GLint location, GLfloat* params)
+{
+    EVENT("(GLuint program = %d, GLint location = %d, GLfloat* params = 0x%0.8p)", program, location, params);
+
+    try
+    {
+        gl::Context *context = gl::getNonLostContext();
+
+        if (context)
+        {
+            if (program == 0)
+            {
+                return error(GL_INVALID_VALUE);
+            }
+
+            gl::Program *programObject = context->getProgram(program);
+
+            if (!programObject || !programObject->isLinked())
+            {
+                return error(GL_INVALID_OPERATION);
+            }
+
+            gl::ProgramBinary *programBinary = programObject->getProgramBinary();
+            if (!programBinary)
+            {
+                return error(GL_INVALID_OPERATION);
+            }
+
+            if (!programBinary->getUniformfv(location, NULL, params))
+            {
+                return error(GL_INVALID_OPERATION);
+            }
+        }
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(GL_OUT_OF_MEMORY);
+    }
+}
+
+void __stdcall glGetnUniformivEXT(GLuint program, GLint location, GLsizei bufSize, GLint* params)
+{
+    EVENT("(GLuint program = %d, GLint location = %d, GLsizei bufSize = %d, GLint* params = 0x%0.8p)", 
+          program, location, bufSize, params);
+
+    try
+    {
+        if (bufSize < 0)
+        {
+            return error(GL_INVALID_VALUE);
+        }
+
+        gl::Context *context = gl::getNonLostContext();
+
+        if (context)
+        {
+            if (program == 0)
+            {
+                return error(GL_INVALID_VALUE);
+            }
+
+            gl::Program *programObject = context->getProgram(program);
+
+            if (!programObject || !programObject->isLinked())
+            {
+                return error(GL_INVALID_OPERATION);
+            }
+
+            gl::ProgramBinary *programBinary = programObject->getProgramBinary();
+            if (!programBinary)
+            {
+                return error(GL_INVALID_OPERATION);
+            }
+
+            if (!programBinary->getUniformiv(location, &bufSize, params))
+            {
+                return error(GL_INVALID_OPERATION);
+            }
+        }
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(GL_OUT_OF_MEMORY);
+    }
+}
+
+void __stdcall glGetUniformiv(GLuint program, GLint location, GLint* params)
+{
+    EVENT("(GLuint program = %d, GLint location = %d, GLint* params = 0x%0.8p)", program, location, params);
+
+    try
+    {
+        gl::Context *context = gl::getNonLostContext();
+
+        if (context)
+        {
+            if (program == 0)
+            {
+                return error(GL_INVALID_VALUE);
+            }
+
+            gl::Program *programObject = context->getProgram(program);
+
+            if (!programObject || !programObject->isLinked())
+            {
+                return error(GL_INVALID_OPERATION);
+            }
+
+            gl::ProgramBinary *programBinary = programObject->getProgramBinary();
+            if (!programBinary)
+            {
+                return error(GL_INVALID_OPERATION);
+            }
+
+            if (!programBinary->getUniformiv(location, NULL, params))
+            {
+                return error(GL_INVALID_OPERATION);
+            }
+        }
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(GL_OUT_OF_MEMORY);
+    }
+}
+
+int __stdcall glGetUniformLocation(GLuint program, const GLchar* name)
+{
+    EVENT("(GLuint program = %d, const GLchar* name = 0x%0.8p)", program, name);
+
+    try
+    {
+        gl::Context *context = gl::getNonLostContext();
+
+        if (strstr(name, "gl_") == name)
+        {
+            return -1;
+        }
+
+        if (context)
+        {
+            gl::Program *programObject = context->getProgram(program);
+
+            if (!programObject)
+            {
+                if (context->getShader(program))
+                {
+                    return error(GL_INVALID_OPERATION, -1);
+                }
+                else
+                {
+                    return error(GL_INVALID_VALUE, -1);
+                }
+            }
+
+            gl::ProgramBinary *programBinary = programObject->getProgramBinary();
+            if (!programObject->isLinked() || !programBinary)
+            {
+                return error(GL_INVALID_OPERATION, -1);
+            }
+
+            return programBinary->getUniformLocation(name);
+        }
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(GL_OUT_OF_MEMORY, -1);
+    }
+
+    return -1;
+}
+
+void __stdcall glGetVertexAttribfv(GLuint index, GLenum pname, GLfloat* params)
+{
+    EVENT("(GLuint index = %d, GLenum pname = 0x%X, GLfloat* params = 0x%0.8p)", index, pname, params);
+
+    try
+    {
+        gl::Context *context = gl::getNonLostContext();
+
+        if (context)
+        {
+            if (index >= gl::MAX_VERTEX_ATTRIBS)
+            {
+                return error(GL_INVALID_VALUE);
+            }
+
+            const gl::VertexAttribute &attribState = context->getVertexAttribState(index);
+
+            switch (pname)
+            {
+              case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
+                *params = (GLfloat)(attribState.mArrayEnabled ? GL_TRUE : GL_FALSE);
+                break;
+              case GL_VERTEX_ATTRIB_ARRAY_SIZE:
+                *params = (GLfloat)attribState.mSize;
+                break;
+              case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
+                *params = (GLfloat)attribState.mStride;
+                break;
+              case GL_VERTEX_ATTRIB_ARRAY_TYPE:
+                *params = (GLfloat)attribState.mType;
+                break;
+              case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
+                *params = (GLfloat)(attribState.mNormalized ? GL_TRUE : GL_FALSE);
+                break;
+              case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING:
+                *params = (GLfloat)attribState.mBoundBuffer.id();
+                break;
+              case GL_CURRENT_VERTEX_ATTRIB:
+                for (int i = 0; i < 4; ++i)
+                {
+                    params[i] = attribState.mCurrentValue[i];
+                }
+                break;
+              case GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE:
+                *params = (GLfloat)attribState.mDivisor;
+                break;
+              default: return error(GL_INVALID_ENUM);
+            }
+        }
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(GL_OUT_OF_MEMORY);
+    }
+}
+
+void __stdcall glGetVertexAttribiv(GLuint index, GLenum pname, GLint* params)
+{
+    EVENT("(GLuint index = %d, GLenum pname = 0x%X, GLint* params = 0x%0.8p)", index, pname, params);
+
+    try
+    {
+        gl::Context *context = gl::getNonLostContext();
+
+        if (context)
+        {
+            if (index >= gl::MAX_VERTEX_ATTRIBS)
+            {
+                return error(GL_INVALID_VALUE);
+            }
+
+            const gl::VertexAttribute &attribState = context->getVertexAttribState(index);
+
+            switch (pname)
+            {
+              case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
+                *params = (attribState.mArrayEnabled ? GL_TRUE : GL_FALSE);
+                break;
+              case GL_VERTEX_ATTRIB_ARRAY_SIZE:
+                *params = attribState.mSize;
+                break;
+              case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
+                *params = attribState.mStride;
+                break;
+              case GL_VERTEX_ATTRIB_ARRAY_TYPE:
+                *params = attribState.mType;
+                break;
+              case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
+                *params = (attribState.mNormalized ? GL_TRUE : GL_FALSE);
+                break;
+              case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING:
+                *params = attribState.mBoundBuffer.id();
+                break;
+              case GL_CURRENT_VERTEX_ATTRIB:
+                for (int i = 0; i < 4; ++i)
+                {
+                    float currentValue = attribState.mCurrentValue[i];
+                    params[i] = (GLint)(currentValue > 0.0f ? floor(currentValue + 0.5f) : ceil(currentValue - 0.5f));
+                }
+                break;
+              case GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE:
+                *params = (GLint)attribState.mDivisor;
+                break;
+              default: return error(GL_INVALID_ENUM);
+            }
+        }
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(GL_OUT_OF_MEMORY);
+    }
+}
+
+void __stdcall glGetVertexAttribPointerv(GLuint index, GLenum pname, GLvoid** pointer)
+{
+    EVENT("(GLuint index = %d, GLenum pname = 0x%X, GLvoid** pointer = 0x%0.8p)", index, pname, pointer);
+
+    try
+    {
+        gl::Context *context = gl::getNonLostContext();
+
+        if (context)
+        {
+            if (index >= gl::MAX_VERTEX_ATTRIBS)
+            {
+                return error(GL_INVALID_VALUE);
+            }
+
+            if (pname != GL_VERTEX_ATTRIB_ARRAY_POINTER)
+            {
+                return error(GL_INVALID_ENUM);
+            }
+
+            *pointer = const_cast<GLvoid*>(context->getVertexAttribPointer(index));
+        }
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(GL_OUT_OF_MEMORY);
+    }
+}
+
+void __stdcall glHint(GLenum target, GLenum mode)
+{
+    EVENT("(GLenum target = 0x%X, GLenum mode = 0x%X)", target, mode);
+
+    try
+    {
+        switch (mode)
+        {
+          case GL_FASTEST:
+          case GL_NICEST:
+          case GL_DONT_CARE:
+            break;
+          default:
+            return error(GL_INVALID_ENUM); 
+        }
+
+        gl::Context *context = gl::getNonLostContext();
+        switch (target)
+        {
+          case GL_GENERATE_MIPMAP_HINT:
+            if (context) context->setGenerateMipmapHint(mode);
+            break;
+          case GL_FRAGMENT_SHADER_DERIVATIVE_HINT_OES:
+            if (context) context->setFragmentShaderDerivativeHint(mode);
+            break;
+          default:
+            return error(GL_INVALID_ENUM);
+        }
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(GL_OUT_OF_MEMORY);
+    }
+}
+
+GLboolean __stdcall glIsBuffer(GLuint buffer)
+{
+    EVENT("(GLuint buffer = %d)", buffer);
+
+    try
+    {
+        gl::Context *context = gl::getNonLostContext();
+
+        if (context && buffer)
+        {
+            gl::Buffer *bufferObject = context->getBuffer(buffer);
+
+            if (bufferObject)
+            {
+                return GL_TRUE;
+            }
+        }
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(GL_OUT_OF_MEMORY, GL_FALSE);
+    }
+
+    return GL_FALSE;
+}
+
+GLboolean __stdcall glIsEnabled(GLenum cap)
+{
+    EVENT("(GLenum cap = 0x%X)", cap);
+
+    try
+    {
+        gl::Context *context = gl::getNonLostContext();
+
+        if (context)
+        {
+            switch (cap)
+            {
+              case GL_CULL_FACE:                return context->isCullFaceEnabled();
+              case GL_POLYGON_OFFSET_FILL:      return context->isPolygonOffsetFillEnabled();
+              case GL_SAMPLE_ALPHA_TO_COVERAGE: return context->isSampleAlphaToCoverageEnabled();
+              case GL_SAMPLE_COVERAGE:          return context->isSampleCoverageEnabled();
+              case GL_SCISSOR_TEST:             return context->isScissorTestEnabled();
+              case GL_STENCIL_TEST:             return context->isStencilTestEnabled();
+              case GL_DEPTH_TEST:               return context->isDepthTestEnabled();
+              case GL_BLEND:                    return context->isBlendEnabled();
+              case GL_DITHER:                   return context->isDitherEnabled();
+              default:
+                return error(GL_INVALID_ENUM, false);
+            }
+        }
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(GL_OUT_OF_MEMORY, false);
+    }
+
+    return false;
+}
+
+GLboolean __stdcall glIsFenceNV(GLuint fence)
+{
+    EVENT("(GLuint fence = %d)", fence);
+
+    try
+    {
+        gl::Context *context = gl::getNonLostContext();
+
+        if (context)
+        {
+            gl::Fence *fenceObject = context->getFence(fence);
+
+            if (fenceObject == NULL)
+            {
+                return GL_FALSE;
+            }
+
+            return fenceObject->isFence();
+        }
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(GL_OUT_OF_MEMORY, GL_FALSE);
+    }
+
+    return GL_FALSE;
+}
+
+GLboolean __stdcall glIsFramebuffer(GLuint framebuffer)
+{
+    EVENT("(GLuint framebuffer = %d)", framebuffer);
+
+    try
+    {
+        gl::Context *context = gl::getNonLostContext();
+
+        if (context && framebuffer)
+        {
+            gl::Framebuffer *framebufferObject = context->getFramebuffer(framebuffer);
+
+            if (framebufferObject)
+            {
+                return GL_TRUE;
+            }
+        }
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(GL_OUT_OF_MEMORY, GL_FALSE);
+    }
+
+    return GL_FALSE;
+}
+
+GLboolean __stdcall glIsProgram(GLuint program)
+{
+    EVENT("(GLuint program = %d)", program);
+
+    try
+    {
+        gl::Context *context = gl::getNonLostContext();
+
+        if (context && program)
+        {
+            gl::Program *programObject = context->getProgram(program);
+
+            if (programObject)
+            {
+                return GL_TRUE;
+            }
+        }
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(GL_OUT_OF_MEMORY, GL_FALSE);
+    }
+
+    return GL_FALSE;
+}
+
+GLboolean __stdcall glIsQueryEXT(GLuint id)
+{
+    EVENT("(GLuint id = %d)", id);
+
+    try
+    {
+        if (id == 0)
+        {
+            return GL_FALSE;
+        }
+
+        gl::Context *context = gl::getNonLostContext();
+
+        if (context)
+        {
+            gl::Query *queryObject = context->getQuery(id, false, GL_NONE);
+
+            if (queryObject)
+            {
+                return GL_TRUE;
+            }
+        }
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(GL_OUT_OF_MEMORY, GL_FALSE);
+    }
+
+    return GL_FALSE;
+}
+
+GLboolean __stdcall glIsRenderbuffer(GLuint renderbuffer)
+{
+    EVENT("(GLuint renderbuffer = %d)", renderbuffer);
+
+    try
+    {
+        gl::Context *context = gl::getNonLostContext();
+
+        if (context && renderbuffer)
+        {
+            gl::Renderbuffer *renderbufferObject = context->getRenderbuffer(renderbuffer);
+
+            if (renderbufferObject)
+            {
+                return GL_TRUE;
+            }
+        }
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(GL_OUT_OF_MEMORY, GL_FALSE);
+    }
+
+    return GL_FALSE;
+}
+
+GLboolean __stdcall glIsShader(GLuint shader)
+{
+    EVENT("(GLuint shader = %d)", shader);
+
+    try
+    {
+        gl::Context *context = gl::getNonLostContext();
+
+        if (context && shader)
+        {
+            gl::Shader *shaderObject = context->getShader(shader);
+
+            if (shaderObject)
+            {
+                return GL_TRUE;
+            }
+        }
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(GL_OUT_OF_MEMORY, GL_FALSE);
+    }
+
+    return GL_FALSE;
+}
+
+GLboolean __stdcall glIsTexture(GLuint texture)
+{
+    EVENT("(GLuint texture = %d)", texture);
+
+    try
+    {
+        gl::Context *context = gl::getNonLostContext();
+
+        if (context && texture)
+        {
+            gl::Texture *textureObject = context->getTexture(texture);
+
+            if (textureObject)
+            {
+                return GL_TRUE;
+            }
+        }
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(GL_OUT_OF_MEMORY, GL_FALSE);
+    }
+
+    return GL_FALSE;
+}
+
+void __stdcall glLineWidth(GLfloat width)
+{
+    EVENT("(GLfloat width = %f)", width);
+
+    try
+    {
+        if (width <= 0.0f)
+        {
+            return error(GL_INVALID_VALUE);
+        }
+
+        gl::Context *context = gl::getNonLostContext();
+
+        if (context)
+        {
+            context->setLineWidth(width);
+        }
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(GL_OUT_OF_MEMORY);
+    }
+}
+
+void __stdcall glLinkProgram(GLuint program)
+{
+    EVENT("(GLuint program = %d)", program);
+
+    try
+    {
+        gl::Context *context = gl::getNonLostContext();
+
+        if (context)
+        {
+            gl::Program *programObject = context->getProgram(program);
+
+            if (!programObject)
+            {
+                if (context->getShader(program))
+                {
+                    return error(GL_INVALID_OPERATION);
+                }
+                else
+                {
+                    return error(GL_INVALID_VALUE);
+                }
+            }
+
+            context->linkProgram(program);
+        }
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(GL_OUT_OF_MEMORY);
+    }
+}
+
+void __stdcall glPixelStorei(GLenum pname, GLint param)
+{
+    EVENT("(GLenum pname = 0x%X, GLint param = %d)", pname, param);
+
+    try
+    {
+        gl::Context *context = gl::getNonLostContext();
+
+        if (context)
+        {
+            switch (pname)
+            {
+              case GL_UNPACK_ALIGNMENT:
+                if (param != 1 && param != 2 && param != 4 && param != 8)
+                {
+                    return error(GL_INVALID_VALUE);
+                }
+
+                context->setUnpackAlignment(param);
+                break;
+
+              case GL_PACK_ALIGNMENT:
+                if (param != 1 && param != 2 && param != 4 && param != 8)
+                {
+                    return error(GL_INVALID_VALUE);
+                }
+
+                context->setPackAlignment(param);
+                break;
+
+              case GL_PACK_REVERSE_ROW_ORDER_ANGLE:
+                context->setPackReverseRowOrder(param != 0);
+                break;
+
+              default:
+                return error(GL_INVALID_ENUM);
+            }
+        }
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(GL_OUT_OF_MEMORY);
+    }
+}
+
+void __stdcall glPolygonOffset(GLfloat factor, GLfloat units)
+{
+    EVENT("(GLfloat factor = %f, GLfloat units = %f)", factor, units);
+
+    try
+    {
+        gl::Context *context = gl::getNonLostContext();
+
+        if (context)
+        {
+            context->setPolygonOffsetParams(factor, units);
+        }
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(GL_OUT_OF_MEMORY);
+    }
+}
+
+void __stdcall glReadnPixelsEXT(GLint x, GLint y, GLsizei width, GLsizei height,
+                                GLenum format, GLenum type, GLsizei bufSize,
+                                GLvoid *data)
+{
+    EVENT("(GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d, "
+          "GLenum format = 0x%X, GLenum type = 0x%X, GLsizei bufSize = 0x%d, GLvoid *data = 0x%0.8p)",
+          x, y, width, height, format, type, bufSize, data);
+
+    try
+    {
+        if (width < 0 || height < 0 || bufSize < 0)
+        {
+            return error(GL_INVALID_VALUE);
+        }
+
+        gl::Context *context = gl::getNonLostContext();
+
+        if (context)
+        {
+            GLenum currentFormat, currentType;
+    
+            // Failure in getCurrentReadFormatType indicates that no color attachment is currently bound,
+            // and attempting to read back if that's the case is an error. The error will be registered
+            // by getCurrentReadFormat.
+            if (!context->getCurrentReadFormatType(&currentFormat, &currentType))
+                return;
+
+            if (!(currentFormat == format && currentType == type) && !validReadFormatType(format, type))
+            {
+                return error(GL_INVALID_OPERATION);
+            }
+
+            context->readPixels(x, y, width, height, format, type, &bufSize, data);
+        }
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(GL_OUT_OF_MEMORY);
+    }
+}
+
+void __stdcall glReadPixels(GLint x, GLint y, GLsizei width, GLsizei height,
+                            GLenum format, GLenum type, GLvoid* pixels)
+{
+    EVENT("(GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d, "
+          "GLenum format = 0x%X, GLenum type = 0x%X, GLvoid* pixels = 0x%0.8p)",
+          x, y, width, height, format, type,  pixels);
+
+    try
+    {
+        if (width < 0 || height < 0)
+        {
+            return error(GL_INVALID_VALUE);
+        }
+
+        gl::Context *context = gl::getNonLostContext();
+
+        if (context)
+        {
+            GLenum currentFormat, currentType;
+    
+            // Failure in getCurrentReadFormatType indicates that no color attachment is currently bound,
+            // and attempting to read back if that's the case is an error. The error will be registered
+            // by getCurrentReadFormat.
+            if (!context->getCurrentReadFormatType(&currentFormat, &currentType))
+                return;
+
+            if (!(currentFormat == format && currentType == type) && !validReadFormatType(format, type))
+            {
+                return error(GL_INVALID_OPERATION);
+            }
+
+            context->readPixels(x, y, width, height, format, type, NULL, pixels);
+        }
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(GL_OUT_OF_MEMORY);
+    }
+}
+
+void __stdcall glReleaseShaderCompiler(void)
+{
+    EVENT("()");
+
+    try
+    {
+        gl::Shader::releaseCompiler();
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(GL_OUT_OF_MEMORY);
+    }
+}
+
+void __stdcall glRenderbufferStorageMultisampleANGLE(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height)
+{
+    EVENT("(GLenum target = 0x%X, GLsizei samples = %d, GLenum internalformat = 0x%X, GLsizei width = %d, GLsizei height = %d)",
+          target, samples, internalformat, width, height);
+
+    try
+    {
+        switch (target)
+        {
+          case GL_RENDERBUFFER:
+            break;
+          default:
+            return error(GL_INVALID_ENUM);
+        }
+
+        if (!gl::IsColorRenderable(internalformat) && !gl::IsDepthRenderable(internalformat) && !gl::IsStencilRenderable(internalformat))
+        {
+            return error(GL_INVALID_ENUM);
+        }
+
+        if (width < 0 || height < 0 || samples < 0)
+        {
+            return error(GL_INVALID_VALUE);
+        }
+
+        gl::Context *context = gl::getNonLostContext();
+
+        if (context)
+        {
+            if (width > context->getMaximumRenderbufferDimension() || 
+                height > context->getMaximumRenderbufferDimension() ||
+                samples > context->getMaxSupportedSamples())
+            {
+                return error(GL_INVALID_VALUE);
+            }
+
+            GLuint handle = context->getRenderbufferHandle();
+            if (handle == 0)
+            {
+                return error(GL_INVALID_OPERATION);
+            }
+
+            switch (internalformat)
+            {
+              case GL_DEPTH_COMPONENT16:
+                context->setRenderbufferStorage(new gl::Depthbuffer(width, height, samples));
+                break;
+              case GL_RGBA4:
+              case GL_RGB5_A1:
+              case GL_RGB565:
+              case GL_RGB8_OES:
+              case GL_RGBA8_OES:
+                context->setRenderbufferStorage(new gl::Colorbuffer(width, height, internalformat, samples));
+                break;
+              case GL_STENCIL_INDEX8:
+                context->setRenderbufferStorage(new gl::Stencilbuffer(width, height, samples));
+                break;
+              case GL_DEPTH24_STENCIL8_OES:
+                context->setRenderbufferStorage(new gl::DepthStencilbuffer(width, height, samples));
+                break;
+              default:
+                return error(GL_INVALID_ENUM);
+            }
+        }
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(GL_OUT_OF_MEMORY);
+    }
+}
+
+void __stdcall glRenderbufferStorage(GLenum target, GLenum internalformat, GLsizei width, GLsizei height)
+{
+    glRenderbufferStorageMultisampleANGLE(target, 0, internalformat, width, height);
+}
+
+void __stdcall glSampleCoverage(GLclampf value, GLboolean invert)
+{
+    EVENT("(GLclampf value = %f, GLboolean invert = %d)", value, invert);
+
+    try
+    {
+        gl::Context* context = gl::getNonLostContext();
+
+        if (context)
+        {
+            context->setSampleCoverageParams(gl::clamp01(value), invert == GL_TRUE);
+        }
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(GL_OUT_OF_MEMORY);
+    }
+}
+
+void __stdcall glSetFenceNV(GLuint fence, GLenum condition)
+{
+    EVENT("(GLuint fence = %d, GLenum condition = 0x%X)", fence, condition);
+
+    try
+    {
+        if (condition != GL_ALL_COMPLETED_NV)
+        {
+            return error(GL_INVALID_ENUM);
+        }
+
+        gl::Context *context = gl::getNonLostContext();
+
+        if (context)
+        {
+            gl::Fence *fenceObject = context->getFence(fence);
+
+            if (fenceObject == NULL)
+            {
+                return error(GL_INVALID_OPERATION);
+            }
+
+            fenceObject->setFence(condition);    
+        }
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(GL_OUT_OF_MEMORY);
+    }
+}
+
+void __stdcall glScissor(GLint x, GLint y, GLsizei width, GLsizei height)
+{
+    EVENT("(GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d)", x, y, width, height);
+
+    try
+    {
+        if (width < 0 || height < 0)
+        {
+            return error(GL_INVALID_VALUE);
+        }
+
+        gl::Context* context = gl::getNonLostContext();
+
+        if (context)
+        {
+            context->setScissorParams(x, y, width, height);
+        }
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(GL_OUT_OF_MEMORY);
+    }
+}
+
+void __stdcall glShaderBinary(GLsizei n, const GLuint* shaders, GLenum binaryformat, const GLvoid* binary, GLsizei length)
+{
+    EVENT("(GLsizei n = %d, const GLuint* shaders = 0x%0.8p, GLenum binaryformat = 0x%X, "
+          "const GLvoid* binary = 0x%0.8p, GLsizei length = %d)",
+          n, shaders, binaryformat, binary, length);
+
+    try
+    {
+        // No binary shader formats are supported.
+        return error(GL_INVALID_ENUM);
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(GL_OUT_OF_MEMORY);
+    }
+}
+
+void __stdcall glShaderSource(GLuint shader, GLsizei count, const GLchar** string, const GLint* length)
+{
+    EVENT("(GLuint shader = %d, GLsizei count = %d, const GLchar** string = 0x%0.8p, const GLint* length = 0x%0.8p)",
+          shader, count, string, length);
+
+    try
+    {
+        if (count < 0)
+        {
+            return error(GL_INVALID_VALUE);
+        }
+
+        gl::Context *context = gl::getNonLostContext();
+
+        if (context)
+        {
+            gl::Shader *shaderObject = context->getShader(shader);
+
+            if (!shaderObject)
+            {
+                if (context->getProgram(shader))
+                {
+                    return error(GL_INVALID_OPERATION);
+                }
+                else
+                {
+                    return error(GL_INVALID_VALUE);
+                }
+            }
+
+            shaderObject->setSource(count, string, length);
+        }
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(GL_OUT_OF_MEMORY);
+    }
+}
+
+void __stdcall glStencilFunc(GLenum func, GLint ref, GLuint mask)
+{
+    glStencilFuncSeparate(GL_FRONT_AND_BACK, func, ref, mask);
+}
+
+void __stdcall glStencilFuncSeparate(GLenum face, GLenum func, GLint ref, GLuint mask)
+{
+    EVENT("(GLenum face = 0x%X, GLenum func = 0x%X, GLint ref = %d, GLuint mask = %d)", face, func, ref, mask);
+
+    try
+    {
+        switch (face)
+        {
+          case GL_FRONT:
+          case GL_BACK:
+          case GL_FRONT_AND_BACK:
+            break;
+          default:
+            return error(GL_INVALID_ENUM);
+        }
+
+        switch (func)
+        {
+          case GL_NEVER:
+          case GL_ALWAYS:
+          case GL_LESS:
+          case GL_LEQUAL:
+          case GL_EQUAL:
+          case GL_GEQUAL:
+          case GL_GREATER:
+          case GL_NOTEQUAL:
+            break;
+          default:
+            return error(GL_INVALID_ENUM);
+        }
+
+        gl::Context *context = gl::getNonLostContext();
+
+        if (context)
+        {
+            if (face == GL_FRONT || face == GL_FRONT_AND_BACK)
+            {
+                context->setStencilParams(func, ref, mask);
+            }
+
+            if (face == GL_BACK || face == GL_FRONT_AND_BACK)
+            {
+                context->setStencilBackParams(func, ref, mask);
+            }
+        }
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(GL_OUT_OF_MEMORY);
+    }
+}
+
+void __stdcall glStencilMask(GLuint mask)
+{
+    glStencilMaskSeparate(GL_FRONT_AND_BACK, mask);
+}
+
+void __stdcall glStencilMaskSeparate(GLenum face, GLuint mask)
+{
+    EVENT("(GLenum face = 0x%X, GLuint mask = %d)", face, mask);
+
+    try
+    {
+        switch (face)
+        {
+          case GL_FRONT:
+          case GL_BACK:
+          case GL_FRONT_AND_BACK:
+            break;
+          default:
+            return error(GL_INVALID_ENUM);
+        }
+
+        gl::Context *context = gl::getNonLostContext();
+
+        if (context)
+        {
+            if (face == GL_FRONT || face == GL_FRONT_AND_BACK)
+            {
+                context->setStencilWritemask(mask);
+            }
+
+            if (face == GL_BACK || face == GL_FRONT_AND_BACK)
+            {
+                context->setStencilBackWritemask(mask);
+            }
+        }
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(GL_OUT_OF_MEMORY);
+    }
+}
+
+void __stdcall glStencilOp(GLenum fail, GLenum zfail, GLenum zpass)
+{
+    glStencilOpSeparate(GL_FRONT_AND_BACK, fail, zfail, zpass);
+}
+
+void __stdcall glStencilOpSeparate(GLenum face, GLenum fail, GLenum zfail, GLenum zpass)
+{
+    EVENT("(GLenum face = 0x%X, GLenum fail = 0x%X, GLenum zfail = 0x%X, GLenum zpas = 0x%Xs)",
+          face, fail, zfail, zpass);
+
+    try
+    {
+        switch (face)
+        {
+          case GL_FRONT:
+          case GL_BACK:
+          case GL_FRONT_AND_BACK:
+            break;
+          default:
+            return error(GL_INVALID_ENUM);
+        }
+
+        switch (fail)
+        {
+          case GL_ZERO:
+          case GL_KEEP:
+          case GL_REPLACE:
+          case GL_INCR:
+          case GL_DECR:
+          case GL_INVERT:
+          case GL_INCR_WRAP:
+          case GL_DECR_WRAP:
+            break;
+          default:
+            return error(GL_INVALID_ENUM);
+        }
+
+        switch (zfail)
+        {
+          case GL_ZERO:
+          case GL_KEEP:
+          case GL_REPLACE:
+          case GL_INCR:
+          case GL_DECR:
+          case GL_INVERT:
+          case GL_INCR_WRAP:
+          case GL_DECR_WRAP:
+            break;
+          default:
+            return error(GL_INVALID_ENUM);
+        }
+
+        switch (zpass)
+        {
+          case GL_ZERO:
+          case GL_KEEP:
+          case GL_REPLACE:
+          case GL_INCR:
+          case GL_DECR:
+          case GL_INVERT:
+          case GL_INCR_WRAP:
+          case GL_DECR_WRAP:
+            break;
+          default:
+            return error(GL_INVALID_ENUM);
+        }
+
+        gl::Context *context = gl::getNonLostContext();
+
+        if (context)
+        {
+            if (face == GL_FRONT || face == GL_FRONT_AND_BACK)
+            {
+                context->setStencilOperations(fail, zfail, zpass);
+            }
+
+            if (face == GL_BACK || face == GL_FRONT_AND_BACK)
+            {
+                context->setStencilBackOperations(fail, zfail, zpass);
+            }
+        }
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(GL_OUT_OF_MEMORY);
+    }
+}
+
+GLboolean __stdcall glTestFenceNV(GLuint fence)
+{
+    EVENT("(GLuint fence = %d)", fence);
+
+    try
+    {
+        gl::Context *context = gl::getNonLostContext();
+
+        if (context)
+        {
+            gl::Fence *fenceObject = context->getFence(fence);
+
+            if (fenceObject == NULL)
+            {
+                return error(GL_INVALID_OPERATION, GL_TRUE);
+            }
+
+            return fenceObject->testFence();
+        }
+    }
+    catch(std::bad_alloc&)
+    {
+        error(GL_OUT_OF_MEMORY);
+    }
+    
+    return GL_TRUE;
+}
+
+void __stdcall glTexImage2D(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height,
+                            GLint border, GLenum format, GLenum type, const GLvoid* pixels)
+{
+    EVENT("(GLenum target = 0x%X, GLint level = %d, GLint internalformat = %d, GLsizei width = %d, GLsizei height = %d, "
+          "GLint border = %d, GLenum format = 0x%X, GLenum type = 0x%X, const GLvoid* pixels =  0x%0.8p)",
+          target, level, internalformat, width, height, border, format, type, pixels);
+
+    try
+    {
+        if (!validImageSize(level, width, height))
+        {
+            return error(GL_INVALID_VALUE);
+        }
+
+        if (internalformat != GLint(format))
+        {
+            return error(GL_INVALID_OPERATION);
+        }
+
+        // validate <type> by itself (used as secondary key below)
+        switch (type)
+        {
+          case GL_UNSIGNED_BYTE:
+          case GL_UNSIGNED_SHORT_5_6_5:
+          case GL_UNSIGNED_SHORT_4_4_4_4:
+          case GL_UNSIGNED_SHORT_5_5_5_1:
+          case GL_UNSIGNED_SHORT:
+          case GL_UNSIGNED_INT:
+          case GL_UNSIGNED_INT_24_8_OES:
+          case GL_HALF_FLOAT_OES:
+          case GL_FLOAT:
+            break;
+          default:
+            return error(GL_INVALID_ENUM);
+        }
+
+        // validate <format> + <type> combinations
+        // - invalid <format> -> sets INVALID_ENUM
+        // - invalid <format>+<type> combination -> sets INVALID_OPERATION
+        switch (format)
+        {
+          case GL_ALPHA:
+          case GL_LUMINANCE:
+          case GL_LUMINANCE_ALPHA:
+            switch (type)
+            {
+              case GL_UNSIGNED_BYTE:
+              case GL_FLOAT:
+              case GL_HALF_FLOAT_OES:
+                break;
+              default:
+                return error(GL_INVALID_OPERATION);
+            }
+            break;
+          case GL_RGB:
+            switch (type)
+            {
+              case GL_UNSIGNED_BYTE:
+              case GL_UNSIGNED_SHORT_5_6_5:
+              case GL_FLOAT:
+              case GL_HALF_FLOAT_OES:
+                break;
+              default:
+                return error(GL_INVALID_OPERATION);
+            }
+            break;
+          case GL_RGBA:
+            switch (type)
+            {
+              case GL_UNSIGNED_BYTE:
+              case GL_UNSIGNED_SHORT_4_4_4_4:
+              case GL_UNSIGNED_SHORT_5_5_5_1:
+              case GL_FLOAT:
+              case GL_HALF_FLOAT_OES:
+                break;
+              default:
+                return error(GL_INVALID_OPERATION);
+            }
+            break;
+          case GL_BGRA_EXT:
+            switch (type)
+            {
+              case GL_UNSIGNED_BYTE:
+                break;
+              default:
+                return error(GL_INVALID_OPERATION);
+            }
+            break;
+          case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:  // error cases for compressed textures are handled below
+          case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
+          case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
+          case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
+            break; 
+          case GL_DEPTH_COMPONENT:
+            switch (type)
+            {
+              case GL_UNSIGNED_SHORT:
+              case GL_UNSIGNED_INT:
+                break;
+              default:
+                return error(GL_INVALID_OPERATION);
+            }
+            break;
+          case GL_DEPTH_STENCIL_OES:
+            switch (type)
+            {
+              case GL_UNSIGNED_INT_24_8_OES:
+                break;
+              default:
+                return error(GL_INVALID_OPERATION);
+            }
+            break;
+          default:
+            return error(GL_INVALID_ENUM);
+        }
+
+        if (border != 0)
+        {
+            return error(GL_INVALID_VALUE);
+        }
+
+        gl::Context *context = gl::getNonLostContext();
+
+        if (context)
+        {
+            if (level > context->getMaximumTextureLevel())
+            {
+                return error(GL_INVALID_VALUE);
+            }
+
+            switch (target)
+            {
+              case GL_TEXTURE_2D:
+                if (width > (context->getMaximumTextureDimension() >> level) ||
+                    height > (context->getMaximumTextureDimension() >> level))
+                {
+                    return error(GL_INVALID_VALUE);
+                }
+                break;
+              case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
+              case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
+              case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
+              case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
+              case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
+              case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
+                if (width != height)
+                {
+                    return error(GL_INVALID_VALUE);
+                }
+
+                if (width > (context->getMaximumCubeTextureDimension() >> level) ||
+                    height > (context->getMaximumCubeTextureDimension() >> level))
+                {
+                    return error(GL_INVALID_VALUE);
+                }
+                break;
+              default:
+                return error(GL_INVALID_ENUM);
+            }
+
+            switch (format) {
+              case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
+              case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
+                if (context->supportsDXT1Textures())
+                {
+                    return error(GL_INVALID_OPERATION);
+                }
+                else
+                {
+                    return error(GL_INVALID_ENUM);
+                }
+                break;
+              case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
+                if (context->supportsDXT3Textures())
+                {
+                    return error(GL_INVALID_OPERATION);
+                }
+                else
+                {
+                    return error(GL_INVALID_ENUM);
+                }
+                break;
+              case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
+                if (context->supportsDXT5Textures())
+                {
+                    return error(GL_INVALID_OPERATION);
+                }
+                else
+                {
+                    return error(GL_INVALID_ENUM);
+                }
+                break;
+              case GL_DEPTH_COMPONENT:
+              case GL_DEPTH_STENCIL_OES:
+                if (!context->supportsDepthTextures())
+                {
+                    return error(GL_INVALID_VALUE);
+                }
+                if (target != GL_TEXTURE_2D)
+                {
+                    return error(GL_INVALID_OPERATION);
+                }
+                // OES_depth_texture supports loading depth data and multiple levels,
+                // but ANGLE_depth_texture does not
+                if (pixels != NULL || level != 0)
+                {
+                    return error(GL_INVALID_OPERATION);
+                }
+                break;
+              default:
+                break;
+            }
+
+            if (type == GL_FLOAT)
+            {
+                if (!context->supportsFloat32Textures())
+                {
+                    return error(GL_INVALID_ENUM);
+                }
+            }
+            else if (type == GL_HALF_FLOAT_OES)
+            {
+                if (!context->supportsFloat16Textures())
+                {
+                    return error(GL_INVALID_ENUM);
+                }
+            }
+
+            if (target == GL_TEXTURE_2D)
+            {
+                gl::Texture2D *texture = context->getTexture2D();
+
+                if (!texture)
+                {
+                    return error(GL_INVALID_OPERATION);
+                }
+
+                if (texture->isImmutable())
+                {
+                    return error(GL_INVALID_OPERATION);
+                }
+
+                texture->setImage(level, width, height, format, type, context->getUnpackAlignment(), pixels);
+            }
+            else
+            {
+                gl::TextureCubeMap *texture = context->getTextureCubeMap();
+
+                if (!texture)
+                {
+                    return error(GL_INVALID_OPERATION);
+                }
+
+                if (texture->isImmutable())
+                {
+                    return error(GL_INVALID_OPERATION);
+                }
+
+                switch (target)
+                {
+                  case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
+                    texture->setImagePosX(level, width, height, format, type, context->getUnpackAlignment(), pixels);
+                    break;
+                  case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
+                    texture->setImageNegX(level, width, height, format, type, context->getUnpackAlignment(), pixels);
+                    break;
+                  case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
+                    texture->setImagePosY(level, width, height, format, type, context->getUnpackAlignment(), pixels);
+                    break;
+                  case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
+                    texture->setImageNegY(level, width, height, format, type, context->getUnpackAlignment(), pixels);
+                    break;
+                  case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
+                    texture->setImagePosZ(level, width, height, format, type, context->getUnpackAlignment(), pixels);
+                    break;
+                  case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
+                    texture->setImageNegZ(level, width, height, format, type, context->getUnpackAlignment(), pixels);
+                    break;
+                  default: UNREACHABLE();
+                }
+            }
+        }
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(GL_OUT_OF_MEMORY);
+    }
+}
+
+void __stdcall glTexParameterf(GLenum target, GLenum pname, GLfloat param)
+{
+    EVENT("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint param = %f)", target, pname, param);
+
+    try
+    {
+        gl::Context *context = gl::getNonLostContext();
+
+        if (context)
+        {
+            gl::Texture *texture;
+
+            switch (target)
+            {
+              case GL_TEXTURE_2D:
+                texture = context->getTexture2D();
+                break;
+              case GL_TEXTURE_CUBE_MAP:
+                texture = context->getTextureCubeMap();
+                break;
+              default:
+                return error(GL_INVALID_ENUM);
+            }
+
+            switch (pname)
+            {
+              case GL_TEXTURE_WRAP_S:
+                if (!texture->setWrapS((GLenum)param))
+                {
+                    return error(GL_INVALID_ENUM);
+                }
+                break;
+              case GL_TEXTURE_WRAP_T:
+                if (!texture->setWrapT((GLenum)param))
+                {
+                    return error(GL_INVALID_ENUM);
+                }
+                break;
+              case GL_TEXTURE_MIN_FILTER:
+                if (!texture->setMinFilter((GLenum)param))
+                {
+                    return error(GL_INVALID_ENUM);
+                }
+                break;
+              case GL_TEXTURE_MAG_FILTER:
+                if (!texture->setMagFilter((GLenum)param))
+                {
+                    return error(GL_INVALID_ENUM);
+                }
+                break;
+              case GL_TEXTURE_USAGE_ANGLE:
+                if (!texture->setUsage((GLenum)param))
+                {
+                    return error(GL_INVALID_ENUM);
+                }
+                break;
+              case GL_TEXTURE_MAX_ANISOTROPY_EXT:
+                if (!context->supportsTextureFilterAnisotropy())
+                {
+                    return error(GL_INVALID_ENUM);
+                }
+                if (!texture->setMaxAnisotropy((float)param, context->getTextureMaxAnisotropy()))
+                {
+                    return error(GL_INVALID_VALUE);
+                }
+                break;
+              default:
+                return error(GL_INVALID_ENUM);
+            }
+        }
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(GL_OUT_OF_MEMORY);
+    }
+}
+
+void __stdcall glTexParameterfv(GLenum target, GLenum pname, const GLfloat* params)
+{
+    glTexParameterf(target, pname, (GLfloat)*params);
+}
+
+void __stdcall glTexParameteri(GLenum target, GLenum pname, GLint param)
+{
+    EVENT("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint param = %d)", target, pname, param);
+
+    try
+    {
+        gl::Context *context = gl::getNonLostContext();
+
+        if (context)
+        {
+            gl::Texture *texture;
+
+            switch (target)
+            {
+              case GL_TEXTURE_2D:
+                texture = context->getTexture2D();
+                break;
+              case GL_TEXTURE_CUBE_MAP:
+                texture = context->getTextureCubeMap();
+                break;
+              default:
+                return error(GL_INVALID_ENUM);
+            }
+
+            switch (pname)
+            {
+              case GL_TEXTURE_WRAP_S:
+                if (!texture->setWrapS((GLenum)param))
+                {
+                    return error(GL_INVALID_ENUM);
+                }
+                break;
+              case GL_TEXTURE_WRAP_T:
+                if (!texture->setWrapT((GLenum)param))
+                {
+                    return error(GL_INVALID_ENUM);
+                }
+                break;
+              case GL_TEXTURE_MIN_FILTER:
+                if (!texture->setMinFilter((GLenum)param))
+                {
+                    return error(GL_INVALID_ENUM);
+                }
+                break;
+              case GL_TEXTURE_MAG_FILTER:
+                if (!texture->setMagFilter((GLenum)param))
+                {
+                    return error(GL_INVALID_ENUM);
+                }
+                break;
+              case GL_TEXTURE_USAGE_ANGLE:
+                if (!texture->setUsage((GLenum)param))
+                {
+                    return error(GL_INVALID_ENUM);
+                }
+                break;
+              case GL_TEXTURE_MAX_ANISOTROPY_EXT:
+                if (!context->supportsTextureFilterAnisotropy())
+                {
+                    return error(GL_INVALID_ENUM);
+                }
+                if (!texture->setMaxAnisotropy((float)param, context->getTextureMaxAnisotropy()))
+                {
+                    return error(GL_INVALID_VALUE);
+                }
+                break;
+              default:
+                return error(GL_INVALID_ENUM);
+            }
+        }
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(GL_OUT_OF_MEMORY);
+    }
+}
+
+void __stdcall glTexParameteriv(GLenum target, GLenum pname, const GLint* params)
+{
+    glTexParameteri(target, pname, *params);
+}
+
+void __stdcall glTexStorage2DEXT(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height)
+{
+    EVENT("(GLenum target = 0x%X, GLsizei levels = %d, GLenum internalformat = 0x%X, GLsizei width = %d, GLsizei height = %d)",
+           target, levels, internalformat, width, height);
+
+    try
+    {
+        if (target != GL_TEXTURE_2D && target != GL_TEXTURE_CUBE_MAP)
+        {
+            return error(GL_INVALID_ENUM);
+        }
+
+        if (width < 1 || height < 1 || levels < 1)
+        {
+            return error(GL_INVALID_VALUE);
+        }
+
+        if (target == GL_TEXTURE_CUBE_MAP && width != height)
+        {
+            return error(GL_INVALID_VALUE);
+        }
+
+        if (levels != 1 && levels != gl::log2(std::max(width, height)) + 1)
+        {
+            return error(GL_INVALID_OPERATION);
+        }
+
+        GLenum format = gl::ExtractFormat(internalformat);
+        GLenum type = gl::ExtractType(internalformat);
+
+        if (format == GL_NONE || type == GL_NONE)
+        {
+            return error(GL_INVALID_ENUM);
+        }
+
+        gl::Context *context = gl::getNonLostContext();
+
+        if (context)
+        {
+            switch (target)
+            {
+              case GL_TEXTURE_2D:
+                if (width > context->getMaximumTextureDimension() ||
+                    height > context->getMaximumTextureDimension())
+                {
+                    return error(GL_INVALID_VALUE);
+                }
+                break;
+              case GL_TEXTURE_CUBE_MAP:
+                if (width > context->getMaximumCubeTextureDimension() ||
+                    height > context->getMaximumCubeTextureDimension())
+                {
+                    return error(GL_INVALID_VALUE);
+                }
+                break;
+              default:
+                return error(GL_INVALID_ENUM);
+            }
+
+            if (levels != 1 && !context->supportsNonPower2Texture())
+            {
+                if (!gl::isPow2(width) || !gl::isPow2(height))
+                {
+                    return error(GL_INVALID_OPERATION);
+                }
+            }
+
+            switch (internalformat)
+            {
+              case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
+              case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
+                if (!context->supportsDXT1Textures())
+                {
+                    return error(GL_INVALID_ENUM);
+                }
+                break;
+              case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
+                if (!context->supportsDXT3Textures())
+                {
+                    return error(GL_INVALID_ENUM);
+                }
+                break;
+              case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
+                if (!context->supportsDXT5Textures())
+                {
+                    return error(GL_INVALID_ENUM);
+                }
+                break;
+              case GL_RGBA32F_EXT:
+              case GL_RGB32F_EXT:
+              case GL_ALPHA32F_EXT:
+              case GL_LUMINANCE32F_EXT:
+              case GL_LUMINANCE_ALPHA32F_EXT:
+                if (!context->supportsFloat32Textures())
+                {
+                    return error(GL_INVALID_ENUM);
+                }
+                break;
+              case GL_RGBA16F_EXT:
+              case GL_RGB16F_EXT:
+              case GL_ALPHA16F_EXT:
+              case GL_LUMINANCE16F_EXT:
+              case GL_LUMINANCE_ALPHA16F_EXT:
+                if (!context->supportsFloat16Textures())
+                {
+                    return error(GL_INVALID_ENUM);
+                }
+                break;
+              case GL_DEPTH_COMPONENT16:
+              case GL_DEPTH_COMPONENT32_OES:
+              case GL_DEPTH24_STENCIL8_OES:
+                if (!context->supportsDepthTextures())
+                {
+                    return error(GL_INVALID_ENUM);
+                }
+                if (target != GL_TEXTURE_2D)
+                {
+                    return error(GL_INVALID_OPERATION);
+                }
+                // ANGLE_depth_texture only supports 1-level textures
+                if (levels != 1)
+                {
+                    return error(GL_INVALID_OPERATION);
+                }
+                break;
+              default:
+                break;
+            }
+
+            if (target == GL_TEXTURE_2D)
+            {
+                gl::Texture2D *texture = context->getTexture2D();
+
+                if (!texture || texture->id() == 0)
+                {
+                    return error(GL_INVALID_OPERATION);
+                }
+
+                if (texture->isImmutable())
+                {
+                    return error(GL_INVALID_OPERATION);
+                }
+
+                texture->storage(levels, internalformat, width, height);
+            }
+            else if (target == GL_TEXTURE_CUBE_MAP)
+            {
+                gl::TextureCubeMap *texture = context->getTextureCubeMap();
+
+                if (!texture || texture->id() == 0)
+                {
+                    return error(GL_INVALID_OPERATION);
+                }
+
+                if (texture->isImmutable())
+                {
+                    return error(GL_INVALID_OPERATION);
+                }
+
+                texture->storage(levels, internalformat, width);
+            }
+            else UNREACHABLE();
+        }
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(GL_OUT_OF_MEMORY);
+    }
+}
+
+void __stdcall glTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
+                               GLenum format, GLenum type, const GLvoid* pixels)
+{
+    EVENT("(GLenum target = 0x%X, GLint level = %d, GLint xoffset = %d, GLint yoffset = %d, "
+          "GLsizei width = %d, GLsizei height = %d, GLenum format = 0x%X, GLenum type = 0x%X, "
+          "const GLvoid* pixels = 0x%0.8p)",
+           target, level, xoffset, yoffset, width, height, format, type, pixels);
+
+    try
+    {
+        if (!gl::IsInternalTextureTarget(target))
+        {
+            return error(GL_INVALID_ENUM);
+        }
+
+        if (level < 0 || xoffset < 0 || yoffset < 0 || width < 0 || height < 0)
+        {
+            return error(GL_INVALID_VALUE);
+        }
+
+        if (std::numeric_limits<GLsizei>::max() - xoffset < width || std::numeric_limits<GLsizei>::max() - yoffset < height)
+        {
+            return error(GL_INVALID_VALUE);
+        }
+
+        if (!checkTextureFormatType(format, type))
+        {
+            return; // error is set by helper function
+        }
+
+        gl::Context *context = gl::getNonLostContext();
+
+        if (context)
+        {
+            if (level > context->getMaximumTextureLevel())
+            {
+                return error(GL_INVALID_VALUE);
+            }
+
+            if (format == GL_FLOAT)
+            {
+                if (!context->supportsFloat32Textures())
+                {
+                    return error(GL_INVALID_ENUM);
+                }
+            }
+            else if (format == GL_HALF_FLOAT_OES)
+            {
+                if (!context->supportsFloat16Textures())
+                {
+                    return error(GL_INVALID_ENUM);
+                }
+            }
+            else if (gl::IsDepthTexture(format))
+            {
+                if (!context->supportsDepthTextures())
+                {
+                    return error(GL_INVALID_ENUM);
+                }
+                if (target != GL_TEXTURE_2D)
+                {
+                    return error(GL_INVALID_OPERATION);
+                }
+                // OES_depth_texture supports loading depth data, but ANGLE_depth_texture does not
+                return error(GL_INVALID_OPERATION);
+            }
+
+            if (width == 0 || height == 0 || pixels == NULL)
+            {
+                return;
+            }
+
+            if (target == GL_TEXTURE_2D)
+            {
+                gl::Texture2D *texture = context->getTexture2D();
+                if (validateSubImageParams2D(false, width, height, xoffset, yoffset, level, format, type, texture))
+                {
+                    texture->subImage(level, xoffset, yoffset, width, height, format, type, context->getUnpackAlignment(), pixels);
+                }
+            }
+            else if (gl::IsCubemapTextureTarget(target))
+            {
+                gl::TextureCubeMap *texture = context->getTextureCubeMap();
+                if (validateSubImageParamsCube(false, width, height, xoffset, yoffset, target, level, format, type, texture))
+                {
+                    texture->subImage(target, level, xoffset, yoffset, width, height, format, type, context->getUnpackAlignment(), pixels);
+                }
+            }
+            else
+            {
+                UNREACHABLE();
+            }
+        }
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(GL_OUT_OF_MEMORY);
+    }
+}
+
+void __stdcall glUniform1f(GLint location, GLfloat x)
+{
+    glUniform1fv(location, 1, &x);
+}
+
+void __stdcall glUniform1fv(GLint location, GLsizei count, const GLfloat* v)
+{
+    EVENT("(GLint location = %d, GLsizei count = %d, const GLfloat* v = 0x%0.8p)", location, count, v);
+
+    try
+    {
+        if (count < 0)
+        {
+            return error(GL_INVALID_VALUE);
+        }
+
+        if (location == -1)
+        {
+            return;
+        }
+
+        gl::Context *context = gl::getNonLostContext();
+
+        if (context)
+        {
+            gl::ProgramBinary *programBinary = context->getCurrentProgramBinary();
+            if (!programBinary)
+            {
+                return error(GL_INVALID_OPERATION);
+            }
+
+            if (!programBinary->setUniform1fv(location, count, v))
+            {
+                return error(GL_INVALID_OPERATION);
+            }
+        }
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(GL_OUT_OF_MEMORY);
+    }
+}
+
+void __stdcall glUniform1i(GLint location, GLint x)
+{
+    glUniform1iv(location, 1, &x);
+}
+
+void __stdcall glUniform1iv(GLint location, GLsizei count, const GLint* v)
+{
+    EVENT("(GLint location = %d, GLsizei count = %d, const GLint* v = 0x%0.8p)", location, count, v);
+
+    try
+    {
+        if (count < 0)
+        {
+            return error(GL_INVALID_VALUE);
+        }
+
+        if (location == -1)
+        {
+            return;
+        }
+
+        gl::Context *context = gl::getNonLostContext();
+
+        if (context)
+        {
+            gl::ProgramBinary *programBinary = context->getCurrentProgramBinary();
+            if (!programBinary)
+            {
+                return error(GL_INVALID_OPERATION);
+            }
+
+            if (!programBinary->setUniform1iv(location, count, v))
+            {
+                return error(GL_INVALID_OPERATION);
+            }
+        }
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(GL_OUT_OF_MEMORY);
+    }
+}
+
+void __stdcall glUniform2f(GLint location, GLfloat x, GLfloat y)
+{
+    GLfloat xy[2] = {x, y};
+
+    glUniform2fv(location, 1, (GLfloat*)&xy);
+}
+
+void __stdcall glUniform2fv(GLint location, GLsizei count, const GLfloat* v)
+{
+    EVENT("(GLint location = %d, GLsizei count = %d, const GLfloat* v = 0x%0.8p)", location, count, v);
+
+    try
+    {
+        if (count < 0)
+        {
+            return error(GL_INVALID_VALUE);
+        }
+        
+        if (location == -1)
+        {
+            return;
+        }
+
+        gl::Context *context = gl::getNonLostContext();
+
+        if (context)
+        {
+            gl::ProgramBinary *programBinary = context->getCurrentProgramBinary();
+            if (!programBinary)
+            {
+                return error(GL_INVALID_OPERATION);
+            }
+
+            if (!programBinary->setUniform2fv(location, count, v))
+            {
+                return error(GL_INVALID_OPERATION);
+            }
+        }
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(GL_OUT_OF_MEMORY);
+    }
+}
+
+void __stdcall glUniform2i(GLint location, GLint x, GLint y)
+{
+    GLint xy[4] = {x, y};
+
+    glUniform2iv(location, 1, (GLint*)&xy);
+}
+
+void __stdcall glUniform2iv(GLint location, GLsizei count, const GLint* v)
+{
+    EVENT("(GLint location = %d, GLsizei count = %d, const GLint* v = 0x%0.8p)", location, count, v);
+
+    try
+    {
+        if (count < 0)
+        {
+            return error(GL_INVALID_VALUE);
+        }
+
+        if (location == -1)
+        {
+            return;
+        }
+
+        gl::Context *context = gl::getNonLostContext();
+
+        if (context)
+        {
+            gl::ProgramBinary *programBinary = context->getCurrentProgramBinary();
+            if (!programBinary)
+            {
+                return error(GL_INVALID_OPERATION);
+            }
+
+            if (!programBinary->setUniform2iv(location, count, v))
+            {
+                return error(GL_INVALID_OPERATION);
+            }
+        }
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(GL_OUT_OF_MEMORY);
+    }
+}
+
+void __stdcall glUniform3f(GLint location, GLfloat x, GLfloat y, GLfloat z)
+{
+    GLfloat xyz[3] = {x, y, z};
+
+    glUniform3fv(location, 1, (GLfloat*)&xyz);
+}
+
+void __stdcall glUniform3fv(GLint location, GLsizei count, const GLfloat* v)
+{
+    EVENT("(GLint location = %d, GLsizei count = %d, const GLfloat* v = 0x%0.8p)", location, count, v);
+
+    try
+    {
+        if (count < 0)
+        {
+            return error(GL_INVALID_VALUE);
+        }
+
+        if (location == -1)
+        {
+            return;
+        }
+
+        gl::Context *context = gl::getNonLostContext();
+
+        if (context)
+        {
+            gl::ProgramBinary *programBinary = context->getCurrentProgramBinary();
+            if (!programBinary)
+            {
+                return error(GL_INVALID_OPERATION);
+            }
+
+            if (!programBinary->setUniform3fv(location, count, v))
+            {
+                return error(GL_INVALID_OPERATION);
+            }
+        }
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(GL_OUT_OF_MEMORY);
+    }
+}
+
+void __stdcall glUniform3i(GLint location, GLint x, GLint y, GLint z)
+{
+    GLint xyz[3] = {x, y, z};
+
+    glUniform3iv(location, 1, (GLint*)&xyz);
+}
+
+void __stdcall glUniform3iv(GLint location, GLsizei count, const GLint* v)
+{
+    EVENT("(GLint location = %d, GLsizei count = %d, const GLint* v = 0x%0.8p)", location, count, v);
+
+    try
+    {
+        if (count < 0)
+        {
+            return error(GL_INVALID_VALUE);
+        }
+
+        if (location == -1)
+        {
+            return;
+        }
+
+        gl::Context *context = gl::getNonLostContext();
+
+        if (context)
+        {
+            gl::ProgramBinary *programBinary = context->getCurrentProgramBinary();
+            if (!programBinary)
+            {
+                return error(GL_INVALID_OPERATION);
+            }
+
+            if (!programBinary->setUniform3iv(location, count, v))
+            {
+                return error(GL_INVALID_OPERATION);
+            }
+        }
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(GL_OUT_OF_MEMORY);
+    }
+}
+
+void __stdcall glUniform4f(GLint location, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
+{
+    GLfloat xyzw[4] = {x, y, z, w};
+
+    glUniform4fv(location, 1, (GLfloat*)&xyzw);
+}
+
+void __stdcall glUniform4fv(GLint location, GLsizei count, const GLfloat* v)
+{
+    EVENT("(GLint location = %d, GLsizei count = %d, const GLfloat* v = 0x%0.8p)", location, count, v);
+
+    try
+    {
+        if (count < 0)
+        {
+            return error(GL_INVALID_VALUE);
+        }
+
+        if (location == -1)
+        {
+            return;
+        }
+
+        gl::Context *context = gl::getNonLostContext();
+
+        if (context)
+        {
+            gl::ProgramBinary *programBinary = context->getCurrentProgramBinary();
+            if (!programBinary)
+            {
+                return error(GL_INVALID_OPERATION);
+            }
+
+            if (!programBinary->setUniform4fv(location, count, v))
+            {
+                return error(GL_INVALID_OPERATION);
+            }
+        }
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(GL_OUT_OF_MEMORY);
+    }
+}
+
+void __stdcall glUniform4i(GLint location, GLint x, GLint y, GLint z, GLint w)
+{
+    GLint xyzw[4] = {x, y, z, w};
+
+    glUniform4iv(location, 1, (GLint*)&xyzw);
+}
+
+void __stdcall glUniform4iv(GLint location, GLsizei count, const GLint* v)
+{
+    EVENT("(GLint location = %d, GLsizei count = %d, const GLint* v = 0x%0.8p)", location, count, v);
+
+    try
+    {
+        if (count < 0)
+        {
+            return error(GL_INVALID_VALUE);
+        }
+
+        if (location == -1)
+        {
+            return;
+        }
+
+        gl::Context *context = gl::getNonLostContext();
+
+        if (context)
+        {
+            gl::ProgramBinary *programBinary = context->getCurrentProgramBinary();
+            if (!programBinary)
+            {
+                return error(GL_INVALID_OPERATION);
+            }
+
+            if (!programBinary->setUniform4iv(location, count, v))
+            {
+                return error(GL_INVALID_OPERATION);
+            }
+        }
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(GL_OUT_OF_MEMORY);
+    }
+}
+
+void __stdcall glUniformMatrix2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
+{
+    EVENT("(GLint location = %d, GLsizei count = %d, GLboolean transpose = %d, const GLfloat* value = 0x%0.8p)",
+          location, count, transpose, value);
+
+    try
+    {
+        if (count < 0 || transpose != GL_FALSE)
+        {
+            return error(GL_INVALID_VALUE);
+        }
+
+        if (location == -1)
+        {
+            return;
+        }
+
+        gl::Context *context = gl::getNonLostContext();
+
+        if (context)
+        {
+            gl::ProgramBinary *programBinary = context->getCurrentProgramBinary();
+            if (!programBinary)
+            {
+                return error(GL_INVALID_OPERATION);
+            }
+
+            if (!programBinary->setUniformMatrix2fv(location, count, value))
+            {
+                return error(GL_INVALID_OPERATION);
+            }
+        }
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(GL_OUT_OF_MEMORY);
+    }
+}
+
+void __stdcall glUniformMatrix3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
+{
+    EVENT("(GLint location = %d, GLsizei count = %d, GLboolean transpose = %d, const GLfloat* value = 0x%0.8p)",
+          location, count, transpose, value);
+
+    try
+    {
+        if (count < 0 || transpose != GL_FALSE)
+        {
+            return error(GL_INVALID_VALUE);
+        }
+
+        if (location == -1)
+        {
+            return;
+        }
+
+        gl::Context *context = gl::getNonLostContext();
+
+        if (context)
+        {
+            gl::ProgramBinary *programBinary = context->getCurrentProgramBinary();
+            if (!programBinary)
+            {
+                return error(GL_INVALID_OPERATION);
+            }
+
+            if (!programBinary->setUniformMatrix3fv(location, count, value))
+            {
+                return error(GL_INVALID_OPERATION);
+            }
+        }
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(GL_OUT_OF_MEMORY);
+    }
+}
+
+void __stdcall glUniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
+{
+    EVENT("(GLint location = %d, GLsizei count = %d, GLboolean transpose = %d, const GLfloat* value = 0x%0.8p)",
+          location, count, transpose, value);
+
+    try
+    {
+        if (count < 0 || transpose != GL_FALSE)
+        {
+            return error(GL_INVALID_VALUE);
+        }
+
+        if (location == -1)
+        {
+            return;
+        }
+
+        gl::Context *context = gl::getNonLostContext();
+
+        if (context)
+        {
+            gl::ProgramBinary *programBinary = context->getCurrentProgramBinary();
+            if (!programBinary)
+            {
+                return error(GL_INVALID_OPERATION);
+            }
+
+            if (!programBinary->setUniformMatrix4fv(location, count, value))
+            {
+                return error(GL_INVALID_OPERATION);
+            }
+        }
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(GL_OUT_OF_MEMORY);
+    }
+}
+
+void __stdcall glUseProgram(GLuint program)
+{
+    EVENT("(GLuint program = %d)", program);
+
+    try
+    {
+        gl::Context *context = gl::getNonLostContext();
+
+        if (context)
+        {
+            gl::Program *programObject = context->getProgram(program);
+
+            if (!programObject && program != 0)
+            {
+                if (context->getShader(program))
+                {
+                    return error(GL_INVALID_OPERATION);
+                }
+                else
+                {
+                    return error(GL_INVALID_VALUE);
+                }
+            }
+
+            if (program != 0 && !programObject->isLinked())
+            {
+                return error(GL_INVALID_OPERATION);
+            }
+
+            context->useProgram(program);
+        }
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(GL_OUT_OF_MEMORY);
+    }
+}
+
+void __stdcall glValidateProgram(GLuint program)
+{
+    EVENT("(GLuint program = %d)", program);
+
+    try
+    {
+        gl::Context *context = gl::getNonLostContext();
+
+        if (context)
+        {
+            gl::Program *programObject = context->getProgram(program);
+
+            if (!programObject)
+            {
+                if (context->getShader(program))
+                {
+                    return error(GL_INVALID_OPERATION);
+                }
+                else
+                {
+                    return error(GL_INVALID_VALUE);
+                }
+            }
+
+            programObject->validate();
+        }
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(GL_OUT_OF_MEMORY);
+    }
+}
+
+void __stdcall glVertexAttrib1f(GLuint index, GLfloat x)
+{
+    EVENT("(GLuint index = %d, GLfloat x = %f)", index, x);
+
+    try
+    {
+        if (index >= gl::MAX_VERTEX_ATTRIBS)
+        {
+            return error(GL_INVALID_VALUE);
+        }
+
+        gl::Context *context = gl::getNonLostContext();
+
+        if (context)
+        {
+            GLfloat vals[4] = { x, 0, 0, 1 };
+            context->setVertexAttrib(index, vals);
+        }
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(GL_OUT_OF_MEMORY);
+    }
+}
+
+void __stdcall glVertexAttrib1fv(GLuint index, const GLfloat* values)
+{
+    EVENT("(GLuint index = %d, const GLfloat* values = 0x%0.8p)", index, values);
+
+    try
+    {
+        if (index >= gl::MAX_VERTEX_ATTRIBS)
+        {
+            return error(GL_INVALID_VALUE);
+        }
+
+        gl::Context *context = gl::getNonLostContext();
+
+        if (context)
+        {
+            GLfloat vals[4] = { values[0], 0, 0, 1 };
+            context->setVertexAttrib(index, vals);
+        }
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(GL_OUT_OF_MEMORY);
+    }
+}
+
+void __stdcall glVertexAttrib2f(GLuint index, GLfloat x, GLfloat y)
+{
+    EVENT("(GLuint index = %d, GLfloat x = %f, GLfloat y = %f)", index, x, y);
+
+    try
+    {
+        if (index >= gl::MAX_VERTEX_ATTRIBS)
+        {
+            return error(GL_INVALID_VALUE);
+        }
+
+        gl::Context *context = gl::getNonLostContext();
+
+        if (context)
+        {
+            GLfloat vals[4] = { x, y, 0, 1 };
+            context->setVertexAttrib(index, vals);
+        }
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(GL_OUT_OF_MEMORY);
+    }
+}
+
+void __stdcall glVertexAttrib2fv(GLuint index, const GLfloat* values)
+{
+    EVENT("(GLuint index = %d, const GLfloat* values = 0x%0.8p)", index, values);
+
+    try
+    {
+        if (index >= gl::MAX_VERTEX_ATTRIBS)
+        {
+            return error(GL_INVALID_VALUE);
+        }
+
+        gl::Context *context = gl::getNonLostContext();
+
+        if (context)
+        {
+            GLfloat vals[4] = { values[0], values[1], 0, 1 };
+            context->setVertexAttrib(index, vals);
+        }
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(GL_OUT_OF_MEMORY);
+    }
+}
+
+void __stdcall glVertexAttrib3f(GLuint index, GLfloat x, GLfloat y, GLfloat z)
+{
+    EVENT("(GLuint index = %d, GLfloat x = %f, GLfloat y = %f, GLfloat z = %f)", index, x, y, z);
+
+    try
+    {
+        if (index >= gl::MAX_VERTEX_ATTRIBS)
+        {
+            return error(GL_INVALID_VALUE);
+        }
+
+        gl::Context *context = gl::getNonLostContext();
+
+        if (context)
+        {
+            GLfloat vals[4] = { x, y, z, 1 };
+            context->setVertexAttrib(index, vals);
+        }
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(GL_OUT_OF_MEMORY);
+    }
+}
+
+void __stdcall glVertexAttrib3fv(GLuint index, const GLfloat* values)
+{
+    EVENT("(GLuint index = %d, const GLfloat* values = 0x%0.8p)", index, values);
+
+    try
+    {
+        if (index >= gl::MAX_VERTEX_ATTRIBS)
+        {
+            return error(GL_INVALID_VALUE);
+        }
+
+        gl::Context *context = gl::getNonLostContext();
+
+        if (context)
+        {
+            GLfloat vals[4] = { values[0], values[1], values[2], 1 };
+            context->setVertexAttrib(index, vals);
+        }
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(GL_OUT_OF_MEMORY);
+    }
+}
+
+void __stdcall glVertexAttrib4f(GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
+{
+    EVENT("(GLuint index = %d, GLfloat x = %f, GLfloat y = %f, GLfloat z = %f, GLfloat w = %f)", index, x, y, z, w);
+
+    try
+    {
+        if (index >= gl::MAX_VERTEX_ATTRIBS)
+        {
+            return error(GL_INVALID_VALUE);
+        }
+
+        gl::Context *context = gl::getNonLostContext();
+
+        if (context)
+        {
+            GLfloat vals[4] = { x, y, z, w };
+            context->setVertexAttrib(index, vals);
+        }
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(GL_OUT_OF_MEMORY);
+    }
+}
+
+void __stdcall glVertexAttrib4fv(GLuint index, const GLfloat* values)
+{
+    EVENT("(GLuint index = %d, const GLfloat* values = 0x%0.8p)", index, values);
+
+    try
+    {
+        if (index >= gl::MAX_VERTEX_ATTRIBS)
+        {
+            return error(GL_INVALID_VALUE);
+        }
+
+        gl::Context *context = gl::getNonLostContext();
+
+        if (context)
+        {
+            context->setVertexAttrib(index, values);
+        }
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(GL_OUT_OF_MEMORY);
+    }
+}
+
+void __stdcall glVertexAttribDivisorANGLE(GLuint index, GLuint divisor)
+{
+    EVENT("(GLuint index = %d, GLuint divisor = %d)", index, divisor);
+
+    try
+    {
+        if (index >= gl::MAX_VERTEX_ATTRIBS)
+        {
+            return error(GL_INVALID_VALUE);
+        }
+
+        gl::Context *context = gl::getNonLostContext();
+
+        if (context)
+        {
+            context->setVertexAttribDivisor(index, divisor);
+        }
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(GL_OUT_OF_MEMORY);
+    }
+}
+
+void __stdcall glVertexAttribPointer(GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid* ptr)
+{
+    EVENT("(GLuint index = %d, GLint size = %d, GLenum type = 0x%X, "
+          "GLboolean normalized = %d, GLsizei stride = %d, const GLvoid* ptr = 0x%0.8p)",
+          index, size, type, normalized, stride, ptr);
+
+    try
+    {
+        if (index >= gl::MAX_VERTEX_ATTRIBS)
+        {
+            return error(GL_INVALID_VALUE);
+        }
+
+        if (size < 1 || size > 4)
+        {
+            return error(GL_INVALID_VALUE);
+        }
+
+        switch (type)
+        {
+          case GL_BYTE:
+          case GL_UNSIGNED_BYTE:
+          case GL_SHORT:
+          case GL_UNSIGNED_SHORT:
+          case GL_FIXED:
+          case GL_FLOAT:
+            break;
+          default:
+            return error(GL_INVALID_ENUM);
+        }
+
+        if (stride < 0)
+        {
+            return error(GL_INVALID_VALUE);
+        }
+
+        gl::Context *context = gl::getNonLostContext();
+
+        if (context)
+        {
+            context->setVertexAttribState(index, context->getArrayBuffer(), size, type, (normalized == GL_TRUE), stride, ptr);
+        }
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(GL_OUT_OF_MEMORY);
+    }
+}
+
+void __stdcall glViewport(GLint x, GLint y, GLsizei width, GLsizei height)
+{
+    EVENT("(GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d)", x, y, width, height);
+
+    try
+    {
+        if (width < 0 || height < 0)
+        {
+            return error(GL_INVALID_VALUE);
+        }
+
+        gl::Context *context = gl::getNonLostContext();
+
+        if (context)
+        {
+            context->setViewportParams(x, y, width, height);
+        }
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(GL_OUT_OF_MEMORY);
+    }
+}
+
+void __stdcall glBlitFramebufferANGLE(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
+                                      GLbitfield mask, GLenum filter)
+{
+    EVENT("(GLint srcX0 = %d, GLint srcY0 = %d, GLint srcX1 = %d, GLint srcY1 = %d, "
+          "GLint dstX0 = %d, GLint dstY0 = %d, GLint dstX1 = %d, GLint dstY1 = %d, "
+          "GLbitfield mask = 0x%X, GLenum filter = 0x%X)",
+          srcX0, srcY0, srcX1, srcX1, dstX0, dstY0, dstX1, dstY1, mask, filter);
+
+    try
+    {
+        switch (filter)
+        {
+          case GL_NEAREST:
+            break;
+          default:
+            return error(GL_INVALID_ENUM);
+        }
+
+        if ((mask & ~(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)) != 0)
+        {
+            return error(GL_INVALID_VALUE);
+        }
+
+        if (srcX1 - srcX0 != dstX1 - dstX0 || srcY1 - srcY0 != dstY1 - dstY0)
+        {
+            ERR("Scaling and flipping in BlitFramebufferANGLE not supported by this implementation");
+            return error(GL_INVALID_OPERATION);
+        }
+
+        gl::Context *context = gl::getNonLostContext();
+
+        if (context)
+        {
+            if (context->getReadFramebufferHandle() == context->getDrawFramebufferHandle())
+            {
+                ERR("Blits with the same source and destination framebuffer are not supported by this implementation.");
+                return error(GL_INVALID_OPERATION);
+            }
+
+            context->blitFramebuffer(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask);
+        }
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(GL_OUT_OF_MEMORY);
+    }
+}
+
+void __stdcall glTexImage3DOES(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth,
+                               GLint border, GLenum format, GLenum type, const GLvoid* pixels)
+{
+    EVENT("(GLenum target = 0x%X, GLint level = %d, GLenum internalformat = 0x%X, "
+          "GLsizei width = %d, GLsizei height = %d, GLsizei depth = %d, GLint border = %d, "
+          "GLenum format = 0x%X, GLenum type = 0x%x, const GLvoid* pixels = 0x%0.8p)",
+          target, level, internalformat, width, height, depth, border, format, type, pixels);
+
+    try
+    {
+        UNIMPLEMENTED();   // FIXME
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(GL_OUT_OF_MEMORY);
+    }
+}
+
+void __stdcall glGetProgramBinaryOES(GLuint program, GLsizei bufSize, GLsizei *length, 
+                                     GLenum *binaryFormat, void *binary)
+{
+    EVENT("(GLenum program = 0x%X, bufSize = %d, length = 0x%0.8p, binaryFormat = 0x%0.8p, binary = 0x%0.8p)",
+          program, bufSize, length, binaryFormat, binary);
+
+    try
+    {
+        gl::Context *context = gl::getNonLostContext();
+
+        if (context)
+        {
+            gl::Program *programObject = context->getProgram(program);
+
+            if (!programObject || !programObject->isLinked())
+            {
+                return error(GL_INVALID_OPERATION);
+            }
+
+            gl::ProgramBinary *programBinary = programObject->getProgramBinary();
+
+            if (!programBinary)
+            {
+                return error(GL_INVALID_OPERATION);
+            }
+
+            if (!programBinary->save(binary, bufSize, length))
+            {
+                return error(GL_INVALID_OPERATION);
+            }
+
+            *binaryFormat = GL_PROGRAM_BINARY_ANGLE;
+        }
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(GL_OUT_OF_MEMORY);
+    }
+}
+
+void __stdcall glProgramBinaryOES(GLuint program, GLenum binaryFormat,
+                                  const void *binary, GLint length)
+{
+    EVENT("(GLenum program = 0x%X, binaryFormat = 0x%x, binary = 0x%0.8p, length = %d)",
+          program, binaryFormat, binary, length);
+
+    try
+    {
+        gl::Context *context = gl::getNonLostContext();
+
+        if (context)
+        {
+            if (binaryFormat != GL_PROGRAM_BINARY_ANGLE)
+            {
+                return error(GL_INVALID_ENUM);
+            }
+
+            gl::Program *programObject = context->getProgram(program);
+
+            if (!programObject)
+            {
+                return error(GL_INVALID_OPERATION);
+            }
+
+            context->setProgramBinary(program, binary, length);
+        }
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(GL_OUT_OF_MEMORY);
+    }
+}
+
+__eglMustCastToProperFunctionPointerType __stdcall glGetProcAddress(const char *procname)
+{
+    struct Extension
+    {
+        const char *name;
+        __eglMustCastToProperFunctionPointerType address;
+    };
+
+    static const Extension glExtensions[] =
+    {
+        {"glTexImage3DOES", (__eglMustCastToProperFunctionPointerType)glTexImage3DOES},
+        {"glBlitFramebufferANGLE", (__eglMustCastToProperFunctionPointerType)glBlitFramebufferANGLE},
+        {"glRenderbufferStorageMultisampleANGLE", (__eglMustCastToProperFunctionPointerType)glRenderbufferStorageMultisampleANGLE},
+        {"glDeleteFencesNV", (__eglMustCastToProperFunctionPointerType)glDeleteFencesNV},
+        {"glGenFencesNV", (__eglMustCastToProperFunctionPointerType)glGenFencesNV},
+        {"glIsFenceNV", (__eglMustCastToProperFunctionPointerType)glIsFenceNV},
+        {"glTestFenceNV", (__eglMustCastToProperFunctionPointerType)glTestFenceNV},
+        {"glGetFenceivNV", (__eglMustCastToProperFunctionPointerType)glGetFenceivNV},
+        {"glFinishFenceNV", (__eglMustCastToProperFunctionPointerType)glFinishFenceNV},
+        {"glSetFenceNV", (__eglMustCastToProperFunctionPointerType)glSetFenceNV},
+        {"glGetTranslatedShaderSourceANGLE", (__eglMustCastToProperFunctionPointerType)glGetTranslatedShaderSourceANGLE},
+        {"glTexStorage2DEXT", (__eglMustCastToProperFunctionPointerType)glTexStorage2DEXT},
+        {"glGetGraphicsResetStatusEXT", (__eglMustCastToProperFunctionPointerType)glGetGraphicsResetStatusEXT},
+        {"glReadnPixelsEXT", (__eglMustCastToProperFunctionPointerType)glReadnPixelsEXT},
+        {"glGetnUniformfvEXT", (__eglMustCastToProperFunctionPointerType)glGetnUniformfvEXT},
+        {"glGetnUniformivEXT", (__eglMustCastToProperFunctionPointerType)glGetnUniformivEXT},
+        {"glGenQueriesEXT", (__eglMustCastToProperFunctionPointerType)glGenQueriesEXT},
+        {"glDeleteQueriesEXT", (__eglMustCastToProperFunctionPointerType)glDeleteQueriesEXT},
+        {"glIsQueryEXT", (__eglMustCastToProperFunctionPointerType)glIsQueryEXT},
+        {"glBeginQueryEXT", (__eglMustCastToProperFunctionPointerType)glBeginQueryEXT},
+        {"glEndQueryEXT", (__eglMustCastToProperFunctionPointerType)glEndQueryEXT},
+        {"glGetQueryivEXT", (__eglMustCastToProperFunctionPointerType)glGetQueryivEXT},
+        {"glGetQueryObjectuivEXT", (__eglMustCastToProperFunctionPointerType)glGetQueryObjectuivEXT},
+        {"glVertexAttribDivisorANGLE", (__eglMustCastToProperFunctionPointerType)glVertexAttribDivisorANGLE},
+        {"glDrawArraysInstancedANGLE", (__eglMustCastToProperFunctionPointerType)glDrawArraysInstancedANGLE},
+        {"glDrawElementsInstancedANGLE", (__eglMustCastToProperFunctionPointerType)glDrawElementsInstancedANGLE},
+        {"glGetProgramBinaryOES", (__eglMustCastToProperFunctionPointerType)glGetProgramBinaryOES},
+        {"glProgramBinaryOES", (__eglMustCastToProperFunctionPointerType)glProgramBinaryOES},    };
+
+    for (int ext = 0; ext < sizeof(glExtensions) / sizeof(Extension); ext++)
+    {
+        if (strcmp(procname, glExtensions[ext].name) == 0)
+        {
+            return (__eglMustCastToProperFunctionPointerType)glExtensions[ext].address;
+        }
+    }
+
+    return NULL;
+}
+
+// Non-public functions used by EGL
+
+bool __stdcall glBindTexImage(egl::Surface *surface)
+{
+    EVENT("(egl::Surface* surface = 0x%0.8p)",
+          surface);
+
+    try
+    {
+        gl::Context *context = gl::getNonLostContext();
+
+        if (context)
+        {
+            gl::Texture2D *textureObject = context->getTexture2D();
+
+            if (textureObject->isImmutable())
+            {
+                return false;
+            }
+
+            if (textureObject)
+            {
+                textureObject->bindTexImage(surface);
+            }
+        }
+    }
+    catch(std::bad_alloc&)
+    {
+        return error(GL_OUT_OF_MEMORY, false);
+    }
+
+    return true;
+}
+
+}
diff --git a/src/3rdparty/angle/src/libGLESv2/libGLESv2.def b/src/3rdparty/angle/src/libGLESv2/libGLESv2.def
new file mode 100644 (file)
index 0000000..5f935c3
--- /dev/null
@@ -0,0 +1,182 @@
+LIBRARY libGLESv2
+EXPORTS
+    glActiveTexture                 @1
+    glAttachShader                  @2
+    glBindAttribLocation            @3
+    glBindBuffer                    @4
+    glBindFramebuffer               @5
+    glBindRenderbuffer              @6
+    glBindTexture                   @7
+    glBlendColor                    @8
+    glBlendEquation                 @9
+    glBlendEquationSeparate         @10
+    glBlendFunc                     @11
+    glBlendFuncSeparate             @12
+    glBufferData                    @13
+    glBufferSubData                 @14
+    glCheckFramebufferStatus        @15
+    glClear                         @16
+    glClearColor                    @17
+    glClearDepthf                   @18
+    glClearStencil                  @19
+    glColorMask                     @20
+    glCompileShader                 @21
+    glCompressedTexImage2D          @22
+    glCompressedTexSubImage2D       @23
+    glCopyTexImage2D                @24
+    glCopyTexSubImage2D             @25
+    glCreateProgram                 @26
+    glCreateShader                  @27
+    glCullFace                      @28
+    glDeleteBuffers                 @29
+    glDeleteFramebuffers            @30
+    glDeleteProgram                 @32
+    glDeleteRenderbuffers           @33
+    glDeleteShader                  @34
+    glDeleteTextures                @31
+    glDepthFunc                     @36
+    glDepthMask                     @37
+    glDepthRangef                   @38
+    glDetachShader                  @35
+    glDisable                       @39
+    glDisableVertexAttribArray      @40
+    glDrawArrays                    @41
+    glDrawElements                  @42
+    glEnable                        @43
+    glEnableVertexAttribArray       @44
+    glFinish                        @45
+    glFlush                         @46
+    glFramebufferRenderbuffer       @47
+    glFramebufferTexture2D          @48
+    glFrontFace                     @49
+    glGenBuffers                    @50
+    glGenFramebuffers               @52
+    glGenRenderbuffers              @53
+    glGenTextures                   @54
+    glGenerateMipmap                @51
+    glGetActiveAttrib               @55
+    glGetActiveUniform              @56
+    glGetAttachedShaders            @57
+    glGetAttribLocation             @58
+    glGetBooleanv                   @59
+    glGetBufferParameteriv          @60
+    glGetError                      @61
+    glGetFloatv                     @62
+    glGetFramebufferAttachmentParameteriv   @63
+    glGetIntegerv                   @64
+    glGetProgramInfoLog             @66
+    glGetProgramiv                  @65
+    glGetRenderbufferParameteriv    @67
+    glGetShaderInfoLog              @69
+    glGetShaderPrecisionFormat      @70
+    glGetShaderSource               @71
+    glGetShaderiv                   @68
+    glGetString                     @72
+    glGetTexParameterfv             @73
+    glGetTexParameteriv             @74
+    glGetUniformLocation            @77
+    glGetUniformfv                  @75
+    glGetUniformiv                  @76
+    glGetVertexAttribPointerv       @80
+    glGetVertexAttribfv             @78
+    glGetVertexAttribiv             @79
+    glHint                          @81
+    glIsBuffer                      @82
+    glIsEnabled                     @83
+    glIsFramebuffer                 @84
+    glIsProgram                     @85
+    glIsRenderbuffer                @86
+    glIsShader                      @87
+    glIsTexture                     @88
+    glLineWidth                     @89
+    glLinkProgram                   @90
+    glPixelStorei                   @91
+    glPolygonOffset                 @92
+    glReadPixels                    @93
+    glReleaseShaderCompiler         @94
+    glRenderbufferStorage           @95
+    glSampleCoverage                @96
+    glScissor                       @97
+    glShaderBinary                  @98
+    glShaderSource                  @99
+    glStencilFunc                   @100
+    glStencilFuncSeparate           @101
+    glStencilMask                   @102
+    glStencilMaskSeparate           @103
+    glStencilOp                     @104
+    glStencilOpSeparate             @105
+    glTexImage2D                    @106
+    glTexParameterf                 @107
+    glTexParameterfv                @108
+    glTexParameteri                 @109
+    glTexParameteriv                @110
+    glTexSubImage2D                 @111
+    glUniform1f                     @112
+    glUniform1fv                    @113
+    glUniform1i                     @114
+    glUniform1iv                    @115
+    glUniform2f                     @116
+    glUniform2fv                    @117
+    glUniform2i                     @118
+    glUniform2iv                    @119
+    glUniform3f                     @120
+    glUniform3fv                    @121
+    glUniform3i                     @122
+    glUniform3iv                    @123
+    glUniform4f                     @124
+    glUniform4fv                    @125
+    glUniform4i                     @126
+    glUniform4iv                    @127
+    glUniformMatrix2fv              @128
+    glUniformMatrix3fv              @129
+    glUniformMatrix4fv              @130
+    glUseProgram                    @131
+    glValidateProgram               @132
+    glVertexAttrib1f                @133
+    glVertexAttrib1fv               @134
+    glVertexAttrib2f                @135
+    glVertexAttrib2fv               @136
+    glVertexAttrib3f                @137
+    glVertexAttrib3fv               @138
+    glVertexAttrib4f                @139
+    glVertexAttrib4fv               @140
+    glVertexAttribPointer           @141
+    glViewport                      @142
+
+    ; Extensions
+    glTexImage3DOES                 @143
+    glBlitFramebufferANGLE          @149
+    glRenderbufferStorageMultisampleANGLE @150
+    glDeleteFencesNV                @151
+    glFinishFenceNV                 @152
+    glGenFencesNV                   @153
+    glGetFenceivNV                  @154
+    glIsFenceNV                     @155
+    glSetFenceNV                    @156
+    glTestFenceNV                   @157
+    glGetTranslatedShaderSourceANGLE @159
+    glTexStorage2DEXT               @160
+    glGetGraphicsResetStatusEXT     @161
+    glReadnPixelsEXT                @162
+    glGetnUniformfvEXT              @163
+    glGetnUniformivEXT              @164
+    glGenQueriesEXT                 @165
+    glDeleteQueriesEXT              @166
+    glIsQueryEXT                    @167
+    glBeginQueryEXT                 @168
+    glEndQueryEXT                   @169
+    glGetQueryivEXT                 @170
+    glGetQueryObjectuivEXT          @171
+    glVertexAttribDivisorANGLE      @172
+    glDrawArraysInstancedANGLE      @173
+    glDrawElementsInstancedANGLE    @174
+    glProgramBinaryOES              @175
+    glGetProgramBinaryOES           @176
+
+    ; EGL dependencies
+    glCreateContext                 @144 NONAME
+    glDestroyContext                @145 NONAME
+    glMakeCurrent                   @146 NONAME
+    glGetCurrentContext             @147 NONAME
+    glGetProcAddress                @148 NONAME
+    glBindTexImage                  @158 NONAME
diff --git a/src/3rdparty/angle/src/libGLESv2/libGLESv2.rc b/src/3rdparty/angle/src/libGLESv2/libGLESv2.rc
new file mode 100644 (file)
index 0000000..0ad21e4
--- /dev/null
@@ -0,0 +1,102 @@
+// Microsoft Visual C++ generated resource script.
+//
+#include "resource.h"
+
+#define APSTUDIO_READONLY_SYMBOLS
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 2 resource.
+//
+#include <windows.h>
+#include "../common/version.h"
+
+/////////////////////////////////////////////////////////////////////////////
+#undef APSTUDIO_READONLY_SYMBOLS
+
+/////////////////////////////////////////////////////////////////////////////
+// English (U.S.) resources
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
+#ifdef _WIN32
+LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
+#pragma code_page(1252)
+#endif //_WIN32
+
+#ifdef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// TEXTINCLUDE
+//
+
+1 TEXTINCLUDE 
+BEGIN
+    "resource.h\0"
+END
+
+2 TEXTINCLUDE 
+BEGIN
+    "#include ""afxres.h""\r\n"
+    "#include ""../common/version.h""\0"
+END
+
+3 TEXTINCLUDE 
+BEGIN
+    "\r\n"
+    "\0"
+END
+
+#endif    // APSTUDIO_INVOKED
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Version
+//
+
+VS_VERSION_INFO VERSIONINFO
+ FILEVERSION MAJOR_VERSION,MINOR_VERSION,BUILD_VERSION,BUILD_REVISION
+ PRODUCTVERSION MAJOR_VERSION,MINOR_VERSION,BUILD_VERSION,BUILD_REVISION
+ FILEFLAGSMASK 0x17L
+#ifdef _DEBUG
+ FILEFLAGS 0x1L
+#else
+ FILEFLAGS 0x0L
+#endif
+ FILEOS 0x4L
+ FILETYPE 0x2L
+ FILESUBTYPE 0x0L
+BEGIN
+    BLOCK "StringFileInfo"
+    BEGIN
+        BLOCK "040904b0"
+        BEGIN
+            VALUE "FileDescription", "ANGLE libGLESv2 Dynamic Link Library"
+            VALUE "FileVersion", VERSION_STRING
+            VALUE "InternalName", "libGLESv2"
+            VALUE "LegalCopyright", "Copyright (C) 2011 Google Inc."
+            VALUE "OriginalFilename", "libGLESv2.dll"
+            VALUE "PrivateBuild", VERSION_STRING
+            VALUE "ProductName", "ANGLE libGLESv2 Dynamic Link Library"
+            VALUE "ProductVersion", VERSION_STRING
+        END
+    END
+    BLOCK "VarFileInfo"
+    BEGIN
+        VALUE "Translation", 0x409, 1200
+    END
+END
+
+#endif    // English (U.S.) resources
+/////////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 3 resource.
+//
+
+
+/////////////////////////////////////////////////////////////////////////////
+#endif    // not APSTUDIO_INVOKED
diff --git a/src/3rdparty/angle/src/libGLESv2/main.cpp b/src/3rdparty/angle/src/libGLESv2/main.cpp
new file mode 100644 (file)
index 0000000..6e678c2
--- /dev/null
@@ -0,0 +1,176 @@
+//
+// 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.
+//
+
+// main.cpp: DLL entry point and management of thread-local data.
+
+#include "libGLESv2/main.h"
+#include "libGLESv2/utilities.h"
+
+#include "common/debug.h"
+#include "libEGL/Surface.h"
+
+#include "libGLESv2/Framebuffer.h"
+
+static DWORD currentTLS = TLS_OUT_OF_INDEXES;
+
+extern "C" BOOL WINAPI DllMain(HINSTANCE instance, DWORD reason, LPVOID reserved)
+{
+    switch (reason)
+    {
+      case DLL_PROCESS_ATTACH:
+        {
+            currentTLS = TlsAlloc();
+
+            if (currentTLS == TLS_OUT_OF_INDEXES)
+            {
+                return FALSE;
+            }
+        }
+        // Fall throught to initialize index
+      case DLL_THREAD_ATTACH:
+        {
+            gl::Current *current = (gl::Current*)LocalAlloc(LPTR, sizeof(gl::Current));
+
+            if (current)
+            {
+                TlsSetValue(currentTLS, current);
+
+                current->context = NULL;
+                current->display = NULL;
+            }
+        }
+        break;
+      case DLL_THREAD_DETACH:
+        {
+            void *current = TlsGetValue(currentTLS);
+
+            if (current)
+            {
+                LocalFree((HLOCAL)current);
+            }
+        }
+        break;
+      case DLL_PROCESS_DETACH:
+        {
+            void *current = TlsGetValue(currentTLS);
+
+            if (current)
+            {
+                LocalFree((HLOCAL)current);
+            }
+
+            TlsFree(currentTLS);
+        }
+        break;
+      default:
+        break;
+    }
+
+    return TRUE;
+}
+
+namespace gl
+{
+void makeCurrent(Context *context, egl::Display *display, egl::Surface *surface)
+{
+    Current *current = (Current*)TlsGetValue(currentTLS);
+
+    current->context = context;
+    current->display = display;
+
+    if (context && display && surface)
+    {
+        context->makeCurrent(display, surface);
+    }
+}
+
+Context *getContext()
+{
+    Current *current = (Current*)TlsGetValue(currentTLS);
+
+    return current->context;
+}
+
+Context *getNonLostContext()
+{
+    Context *context = getContext();
+    
+    if (context)
+    {
+        if (context->isContextLost())
+        {
+            error(GL_OUT_OF_MEMORY);
+            return NULL;
+        }
+        else
+        {
+            return context;
+        }
+    }
+    return NULL;
+}
+
+egl::Display *getDisplay()
+{
+    Current *current = (Current*)TlsGetValue(currentTLS);
+
+    return current->display;
+}
+
+IDirect3DDevice9 *getDevice()
+{
+    egl::Display *display = getDisplay();
+
+    return display->getDevice();
+}
+
+bool checkDeviceLost(HRESULT errorCode)
+{
+    egl::Display *display = NULL;
+
+    if (isDeviceLostError(errorCode))
+    {
+        display = gl::getDisplay();
+        display->notifyDeviceLost();
+        return true;
+    }
+    return false;
+}
+}
+
+// Records an error code
+void error(GLenum errorCode)
+{
+    gl::Context *context = glGetCurrentContext();
+
+    if (context)
+    {
+        switch (errorCode)
+        {
+          case GL_INVALID_ENUM:
+            context->recordInvalidEnum();
+            TRACE("\t! Error generated: invalid enum\n");
+            break;
+          case GL_INVALID_VALUE:
+            context->recordInvalidValue();
+            TRACE("\t! Error generated: invalid value\n");
+            break;
+          case GL_INVALID_OPERATION:
+            context->recordInvalidOperation();
+            TRACE("\t! Error generated: invalid operation\n");
+            break;
+          case GL_OUT_OF_MEMORY:
+            context->recordOutOfMemory();
+            TRACE("\t! Error generated: out of memory\n");
+            break;
+          case GL_INVALID_FRAMEBUFFER_OPERATION:
+            context->recordInvalidFramebufferOperation();
+            TRACE("\t! Error generated: invalid framebuffer operation\n");
+            break;
+          default: UNREACHABLE();
+        }
+    }
+}
diff --git a/src/3rdparty/angle/src/libGLESv2/main.h b/src/3rdparty/angle/src/libGLESv2/main.h
new file mode 100644 (file)
index 0000000..504848a
--- /dev/null
@@ -0,0 +1,50 @@
+//
+// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// main.h: Management of thread-local data.
+
+#ifndef LIBGLESV2_MAIN_H_
+#define LIBGLESV2_MAIN_H_
+
+#define GL_APICALL
+#include <GLES2/gl2.h>
+#include <GLES2/gl2ext.h>
+
+#include "common/debug.h"
+#include "libEGL/Display.h"
+
+#include "libGLESv2/Context.h"
+
+namespace gl
+{
+struct Current
+{
+    Context *context;
+    egl::Display *display;
+};
+
+void makeCurrent(Context *context, egl::Display *display, egl::Surface *surface);
+
+Context *getContext();
+Context *getNonLostContext();
+egl::Display *getDisplay();
+
+IDirect3DDevice9 *getDevice();
+
+bool checkDeviceLost(HRESULT errorCode);
+}
+
+void error(GLenum errorCode);
+
+template<class T>
+const T &error(GLenum errorCode, const T &returnValue)
+{
+    error(errorCode);
+
+    return returnValue;
+}
+
+#endif   // LIBGLESV2_MAIN_H_
diff --git a/src/3rdparty/angle/src/libGLESv2/mathutil.h b/src/3rdparty/angle/src/libGLESv2/mathutil.h
new file mode 100644 (file)
index 0000000..790ecd8
--- /dev/null
@@ -0,0 +1,145 @@
+//
+// 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.
+//
+
+// mathutil.h: Math and bit manipulation functions.
+
+#ifndef LIBGLESV2_MATHUTIL_H_
+#define LIBGLESV2_MATHUTIL_H_
+
+#include <intrin.h>
+#include <math.h>
+#include <windows.h>
+
+namespace gl
+{
+struct Vector4
+{
+    Vector4() {}
+    Vector4(float x, float y, float z, float w) : x(x), y(y), z(z), w(w) {}
+
+    float x;
+    float y;
+    float z;
+    float w;
+};
+
+inline bool isPow2(int x)
+{
+    return (x & (x - 1)) == 0 && (x != 0);
+}
+
+inline int log2(int x)
+{
+    int r = 0;
+    while ((x >> r) > 1) r++;
+    return r;
+}
+
+inline unsigned int ceilPow2(unsigned int x)
+{
+    if (x != 0) x--;
+    x |= x >> 1;
+    x |= x >> 2;
+    x |= x >> 4;
+    x |= x >> 8;
+    x |= x >> 16;
+    x++;
+
+    return x;
+}
+
+template<typename T, typename MIN, typename MAX>
+inline T clamp(T x, MIN min, MAX max)
+{
+    return x < min ? min : (x > max ? max : x);
+}
+
+inline float clamp01(float x)
+{
+    return clamp(x, 0.0f, 1.0f);
+}
+
+template<const int n>
+inline unsigned int unorm(float x)
+{
+    const unsigned int max = 0xFFFFFFFF >> (32 - n);
+
+    if (x > 1)
+    {
+        return max;
+    }
+    else if (x < 0)
+    {
+        return 0;
+    }
+    else
+    {
+        return (unsigned int)(max * x + 0.5f);
+    }
+}
+
+inline bool supportsSSE2()
+{
+    static bool checked = false;
+    static bool supports = false;
+
+    if (checked)
+    {
+        return supports;
+    }
+
+    int info[4];
+    __cpuid(info, 0);
+    
+    if (info[0] >= 1)
+    {
+        __cpuid(info, 1);
+
+        supports = (info[3] >> 26) & 1;
+    }
+
+    checked = true;
+
+    return supports;
+}
+
+inline unsigned short float32ToFloat16(float fp32)
+{
+    unsigned int fp32i = (unsigned int&)fp32;
+    unsigned int sign = (fp32i & 0x80000000) >> 16;
+    unsigned int abs = fp32i & 0x7FFFFFFF;
+
+    if(abs > 0x47FFEFFF)   // Infinity
+    {
+        return sign | 0x7FFF;
+    }
+    else if(abs < 0x38800000)   // Denormal
+    {
+        unsigned int mantissa = (abs & 0x007FFFFF) | 0x00800000;   
+        int e = 113 - (abs >> 23);
+
+        if(e < 24)
+        {
+            abs = mantissa >> e;
+        }
+        else
+        {
+            abs = 0;
+        }
+
+        return sign | (abs + 0x00000FFF + ((abs >> 13) & 1)) >> 13;
+    }
+    else
+    {
+        return sign | (abs + 0xC8000000 + 0x00000FFF + ((abs >> 13) & 1)) >> 13;
+    }
+}
+
+float float16ToFloat32(unsigned short h);
+
+}
+
+#endif   // LIBGLESV2_MATHUTIL_H_
diff --git a/src/3rdparty/angle/src/libGLESv2/resource.h b/src/3rdparty/angle/src/libGLESv2/resource.h
new file mode 100644 (file)
index 0000000..39adaad
--- /dev/null
@@ -0,0 +1,14 @@
+//{{NO_DEPENDENCIES}}
+// Microsoft Visual C++ generated include file.
+// Used by libGLESv2.rc
+
+// Next default values for new objects
+// 
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NEXT_RESOURCE_VALUE        101
+#define _APS_NEXT_COMMAND_VALUE         40001
+#define _APS_NEXT_CONTROL_VALUE         1001
+#define _APS_NEXT_SYMED_VALUE           101
+#endif
+#endif
diff --git a/src/3rdparty/angle/src/libGLESv2/shaders/Blit.ps b/src/3rdparty/angle/src/libGLESv2/shaders/Blit.ps
new file mode 100644 (file)
index 0000000..dcb3bd0
--- /dev/null
@@ -0,0 +1,39 @@
+//
+// 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.
+//
+
+sampler2D tex : s0;
+
+uniform float4 mode : c0;
+
+// Passthrough Pixel Shader
+// Outputs texture 0 sampled at texcoord 0.
+float4 passthroughps(float4 texcoord : TEXCOORD0) : COLOR
+{
+       return tex2D(tex, texcoord.xy);
+};
+
+// Luminance Conversion Pixel Shader
+// Outputs sample(tex0, tc0).rrra.
+// For LA output (pass A) set C0.X = 1, C0.Y = 0.
+// For L output (A = 1) set C0.X = 0, C0.Y = 1.
+float4 luminanceps(float4 texcoord : TEXCOORD0) : COLOR
+{
+       float4 tmp = tex2D(tex, texcoord.xy);
+       tmp.w = tmp.w * mode.x + mode.y;
+       return tmp.xxxw;
+};
+
+// RGB/A Component Mask Pixel Shader
+// Outputs sample(tex0, tc0) with options to force RGB = 0 and/or A = 1.
+// To force RGB = 0, set C0.X = 0, otherwise C0.X = 1.
+// To force A = 1, set C0.Z = 0, C0.W = 1, otherwise C0.Z = 1, C0.W = 0.
+float4 componentmaskps(float4 texcoord : TEXCOORD0) : COLOR
+{
+       float4 tmp = tex2D(tex, texcoord.xy);
+       tmp.xyz = tmp.xyz * mode.x;
+       tmp.w = tmp.w * mode.z + mode.w;
+       return tmp;
+};
diff --git a/src/3rdparty/angle/src/libGLESv2/shaders/Blit.vs b/src/3rdparty/angle/src/libGLESv2/shaders/Blit.vs
new file mode 100644 (file)
index 0000000..3a36980
--- /dev/null
@@ -0,0 +1,43 @@
+//
+// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+struct VS_OUTPUT
+{
+    float4 position : POSITION;
+    float4 texcoord : TEXCOORD0;
+};
+
+uniform float4 halfPixelSize : c0;
+
+// Standard Vertex Shader
+// Input 0 is the homogenous position.
+// Outputs the homogenous position as-is.
+// Outputs a tex coord with (0,0) in the upper-left corner of the screen and (1,1) in the bottom right.
+// C0.X must be negative half-pixel width, C0.Y must be half-pixel height. C0.ZW must be 0.
+VS_OUTPUT standardvs(in float4 position : POSITION)
+{
+    VS_OUTPUT Out;
+
+    Out.position = position + halfPixelSize;
+    Out.texcoord = position * float4(0.5, -0.5, 1.0, 1.0) + float4(0.5, 0.5, 0, 0);
+
+    return Out;
+};
+
+// Flip Y Vertex Shader
+// Input 0 is the homogenous position.
+// Outputs the homogenous position as-is.
+// Outputs a tex coord with (0,1) in the upper-left corner of the screen and (1,0) in the bottom right.
+// C0.XY must be the half-pixel width and height. C0.ZW must be 0.
+VS_OUTPUT flipyvs(in float4 position : POSITION)
+{
+    VS_OUTPUT Out;
+
+    Out.position = position + halfPixelSize;
+    Out.texcoord = position * float4(0.5, 0.5, 1.0, 1.0) + float4(0.5, 0.5, 0, 0);
+
+    return Out;
+};
diff --git a/src/3rdparty/angle/src/libGLESv2/utilities.cpp b/src/3rdparty/angle/src/libGLESv2/utilities.cpp
new file mode 100644 (file)
index 0000000..a3eb27d
--- /dev/null
@@ -0,0 +1,1218 @@
+//
+// 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.
+//
+
+// utilities.cpp: Conversion functions and other utility routines.
+
+#include "libGLESv2/utilities.h"
+
+#include <limits>
+#include <stdio.h>
+#include <windows.h>
+
+#include "common/debug.h"
+
+#include "libGLESv2/mathutil.h"
+#include "libGLESv2/Context.h"
+
+namespace gl
+{
+
+// This is how much data the application expects for a uniform
+int UniformExternalComponentCount(GLenum type)
+{
+    switch (type)
+    {
+      case GL_BOOL:
+      case GL_FLOAT:
+      case GL_INT:
+      case GL_SAMPLER_2D:
+      case GL_SAMPLER_CUBE:
+          return 1;
+      case GL_BOOL_VEC2:
+      case GL_FLOAT_VEC2:
+      case GL_INT_VEC2:
+          return 2;
+      case GL_INT_VEC3:
+      case GL_FLOAT_VEC3:
+      case GL_BOOL_VEC3:
+          return 3;
+      case GL_BOOL_VEC4:
+      case GL_FLOAT_VEC4:
+      case GL_INT_VEC4:
+      case GL_FLOAT_MAT2:
+          return 4;
+      case GL_FLOAT_MAT3:
+          return 9;
+      case GL_FLOAT_MAT4:
+          return 16;
+      default:
+          UNREACHABLE();
+    }
+
+    return 0;
+}
+
+// This is how much data we actually store for a uniform
+int UniformInternalComponentCount(GLenum type)
+{
+    switch (type)
+    {
+      case GL_BOOL:
+      case GL_INT:
+      case GL_SAMPLER_2D:
+      case GL_SAMPLER_CUBE:
+          return 1;
+      case GL_BOOL_VEC2:
+      case GL_INT_VEC2:
+          return 2;
+      case GL_INT_VEC3:
+      case GL_BOOL_VEC3:
+          return 3;
+      case GL_FLOAT:
+      case GL_FLOAT_VEC2:
+      case GL_FLOAT_VEC3:
+      case GL_BOOL_VEC4:
+      case GL_FLOAT_VEC4:
+      case GL_INT_VEC4:
+          return 4;
+      case GL_FLOAT_MAT2:
+          return 8;
+      case GL_FLOAT_MAT3:
+          return 12;
+      case GL_FLOAT_MAT4:
+          return 16;
+      default:
+          UNREACHABLE();
+    }
+
+    return 0;
+}
+
+GLenum UniformComponentType(GLenum type)
+{
+    switch(type)
+    {
+      case GL_BOOL:
+      case GL_BOOL_VEC2:
+      case GL_BOOL_VEC3:
+      case GL_BOOL_VEC4:
+          return GL_BOOL;
+      case GL_FLOAT:
+      case GL_FLOAT_VEC2:
+      case GL_FLOAT_VEC3:
+      case GL_FLOAT_VEC4:
+      case GL_FLOAT_MAT2:
+      case GL_FLOAT_MAT3:
+      case GL_FLOAT_MAT4:
+          return GL_FLOAT;
+      case GL_INT:
+      case GL_SAMPLER_2D:
+      case GL_SAMPLER_CUBE:
+      case GL_INT_VEC2:
+      case GL_INT_VEC3:
+      case GL_INT_VEC4:
+          return GL_INT;
+      default:
+          UNREACHABLE();
+    }
+
+    return GL_NONE;
+}
+
+size_t UniformComponentSize(GLenum type)
+{
+    switch(type)
+    {
+      case GL_BOOL:  return sizeof(GLint);
+      case GL_FLOAT: return sizeof(GLfloat);
+      case GL_INT:   return sizeof(GLint);
+      default:       UNREACHABLE();
+    }
+
+    return 0;
+}
+
+size_t UniformInternalSize(GLenum type)
+{
+    return UniformComponentSize(UniformComponentType(type)) * UniformInternalComponentCount(type);
+}
+
+size_t UniformExternalSize(GLenum type)
+{
+    return UniformComponentSize(UniformComponentType(type)) * UniformExternalComponentCount(type);
+}
+
+int VariableRowCount(GLenum type)
+{
+    switch (type)
+    {
+      case GL_NONE:
+        return 0;
+      case GL_BOOL:
+      case GL_FLOAT:
+      case GL_INT:
+      case GL_BOOL_VEC2:
+      case GL_FLOAT_VEC2:
+      case GL_INT_VEC2:
+      case GL_INT_VEC3:
+      case GL_FLOAT_VEC3:
+      case GL_BOOL_VEC3:
+      case GL_BOOL_VEC4:
+      case GL_FLOAT_VEC4:
+      case GL_INT_VEC4:
+        return 1;
+      case GL_FLOAT_MAT2:
+        return 2;
+      case GL_FLOAT_MAT3:
+        return 3;
+      case GL_FLOAT_MAT4:
+        return 4;
+      default:
+        UNREACHABLE();
+    }
+
+    return 0;
+}
+
+int VariableColumnCount(GLenum type)
+{
+    switch (type)
+    {
+      case GL_NONE:
+        return 0;
+      case GL_BOOL:
+      case GL_FLOAT:
+      case GL_INT:
+        return 1;
+      case GL_BOOL_VEC2:
+      case GL_FLOAT_VEC2:
+      case GL_INT_VEC2:
+      case GL_FLOAT_MAT2:
+        return 2;
+      case GL_INT_VEC3:
+      case GL_FLOAT_VEC3:
+      case GL_BOOL_VEC3:
+      case GL_FLOAT_MAT3:
+        return 3;
+      case GL_BOOL_VEC4:
+      case GL_FLOAT_VEC4:
+      case GL_INT_VEC4:
+      case GL_FLOAT_MAT4:
+        return 4;
+      default:
+        UNREACHABLE();
+    }
+
+    return 0;
+}
+
+int AllocateFirstFreeBits(unsigned int *bits, unsigned int allocationSize, unsigned int bitsSize)
+{
+    ASSERT(allocationSize <= bitsSize);
+
+    unsigned int mask = std::numeric_limits<unsigned int>::max() >> (std::numeric_limits<unsigned int>::digits - allocationSize);
+
+    for (unsigned int i = 0; i < bitsSize - allocationSize + 1; i++)
+    {
+        if ((*bits & mask) == 0)
+        {
+            *bits |= mask;
+            return i;
+        }
+
+        mask <<= 1;
+    }
+
+    return -1;
+}
+
+GLsizei ComputePitch(GLsizei width, GLint internalformat, GLint alignment)
+{
+    ASSERT(alignment > 0 && isPow2(alignment));
+
+    GLsizei rawPitch = ComputePixelSize(internalformat) * width;
+    return (rawPitch + alignment - 1) & ~(alignment - 1);
+}
+
+GLsizei ComputeCompressedPitch(GLsizei width, GLenum internalformat)
+{
+    return ComputeCompressedSize(width, 1, internalformat);
+}
+
+GLsizei ComputeCompressedSize(GLsizei width, GLsizei height, GLenum internalformat)
+{
+    switch (internalformat)
+    {
+      case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
+      case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
+        return 8 * ((width + 3) / 4) * ((height + 3) / 4);
+      case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
+      case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
+        return 16 * ((width + 3) / 4) * ((height + 3) / 4);
+      default:
+        return 0;
+    }
+}
+
+bool IsCompressed(GLenum format)
+{
+    if(format == GL_COMPRESSED_RGB_S3TC_DXT1_EXT ||
+       format == GL_COMPRESSED_RGBA_S3TC_DXT1_EXT ||
+       format == GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE ||
+       format == GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE)
+    {
+        return true;
+    }
+    else
+    {
+        return false;
+    }
+}
+
+bool IsDepthTexture(GLenum format)
+{
+    if (format == GL_DEPTH_COMPONENT ||
+        format == GL_DEPTH_STENCIL_OES ||
+        format == GL_DEPTH_COMPONENT16 ||
+        format == GL_DEPTH_COMPONENT32_OES ||
+        format == GL_DEPTH24_STENCIL8_OES)
+    {
+        return true;
+    }
+
+    return false;
+}
+
+bool IsStencilTexture(GLenum format)
+{
+    if (format == GL_DEPTH_STENCIL_OES ||
+        format == GL_DEPTH24_STENCIL8_OES)
+    {
+        return true;
+    }
+
+    return false;
+}
+
+// Returns the size, in bytes, of a single texel in an Image
+int ComputePixelSize(GLint internalformat)
+{
+    switch (internalformat)
+    {
+      case GL_ALPHA8_EXT:                       return sizeof(unsigned char);
+      case GL_LUMINANCE8_EXT:                   return sizeof(unsigned char);
+      case GL_ALPHA32F_EXT:                     return sizeof(float);
+      case GL_LUMINANCE32F_EXT:                 return sizeof(float);
+      case GL_ALPHA16F_EXT:                     return sizeof(unsigned short);
+      case GL_LUMINANCE16F_EXT:                 return sizeof(unsigned short);
+      case GL_LUMINANCE8_ALPHA8_EXT:            return sizeof(unsigned char) * 2;
+      case GL_LUMINANCE_ALPHA32F_EXT:           return sizeof(float) * 2;
+      case GL_LUMINANCE_ALPHA16F_EXT:           return sizeof(unsigned short) * 2;
+      case GL_RGB8_OES:                         return sizeof(unsigned char) * 3;
+      case GL_RGB565:                           return sizeof(unsigned short);
+      case GL_RGB32F_EXT:                       return sizeof(float) * 3;
+      case GL_RGB16F_EXT:                       return sizeof(unsigned short) * 3;
+      case GL_RGBA8_OES:                        return sizeof(unsigned char) * 4;
+      case GL_RGBA4:                            return sizeof(unsigned short);
+      case GL_RGB5_A1:                          return sizeof(unsigned short);
+      case GL_RGBA32F_EXT:                      return sizeof(float) * 4;
+      case GL_RGBA16F_EXT:                      return sizeof(unsigned short) * 4;
+      case GL_BGRA8_EXT:                        return sizeof(unsigned char) * 4;
+      case GL_BGRA4_ANGLEX:                     return sizeof(unsigned short);
+      case GL_BGR5_A1_ANGLEX:                   return sizeof(unsigned short);
+      default: UNREACHABLE();
+    }
+
+    return 0;
+}
+
+bool IsCubemapTextureTarget(GLenum target)
+{
+    return (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X && target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z);
+}
+
+bool IsInternalTextureTarget(GLenum target)
+{
+    return target == GL_TEXTURE_2D || IsCubemapTextureTarget(target);
+}
+
+GLint ConvertSizedInternalFormat(GLenum format, GLenum type)
+{
+    switch (format)
+    {
+      case GL_ALPHA:
+        switch (type)
+        {
+          case GL_UNSIGNED_BYTE:    return GL_ALPHA8_EXT;
+          case GL_FLOAT:            return GL_ALPHA32F_EXT;
+          case GL_HALF_FLOAT_OES:   return GL_ALPHA16F_EXT;
+          default:                  UNIMPLEMENTED();
+        }
+        break;
+      case GL_LUMINANCE:
+        switch (type)
+        {
+          case GL_UNSIGNED_BYTE:    return GL_LUMINANCE8_EXT;
+          case GL_FLOAT:            return GL_LUMINANCE32F_EXT;
+          case GL_HALF_FLOAT_OES:   return GL_LUMINANCE16F_EXT;
+          default:                  UNIMPLEMENTED();
+        }
+        break;
+      case GL_LUMINANCE_ALPHA:
+        switch (type)
+        {
+          case GL_UNSIGNED_BYTE:    return GL_LUMINANCE8_ALPHA8_EXT;
+          case GL_FLOAT:            return GL_LUMINANCE_ALPHA32F_EXT;
+          case GL_HALF_FLOAT_OES:   return GL_LUMINANCE_ALPHA16F_EXT;
+          default:                  UNIMPLEMENTED();
+        }
+        break;
+      case GL_RGB:
+        switch (type)
+        {
+          case GL_UNSIGNED_BYTE:            return GL_RGB8_OES;
+          case GL_UNSIGNED_SHORT_5_6_5:     return GL_RGB565;
+          case GL_FLOAT:                    return GL_RGB32F_EXT;
+          case GL_HALF_FLOAT_OES:           return GL_RGB16F_EXT;
+          default:                          UNIMPLEMENTED();
+        }
+        break;
+      case GL_RGBA:
+        switch (type)
+        {
+          case GL_UNSIGNED_BYTE:            return GL_RGBA8_OES;
+          case GL_UNSIGNED_SHORT_4_4_4_4:   return GL_RGBA4;
+          case GL_UNSIGNED_SHORT_5_5_5_1:   return GL_RGB5_A1;
+          case GL_FLOAT:                    return GL_RGBA32F_EXT;
+          case GL_HALF_FLOAT_OES:           return GL_RGBA16F_EXT;
+            break;
+          default:                          UNIMPLEMENTED();
+        }
+        break;
+      case GL_BGRA_EXT:
+        switch (type)
+        {
+          case GL_UNSIGNED_BYTE:                    return GL_BGRA8_EXT;
+          case GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT:   return GL_BGRA4_ANGLEX;
+          case GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT:   return GL_BGR5_A1_ANGLEX;
+          default:                                  UNIMPLEMENTED();
+        }
+        break;
+      case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
+      case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
+      case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
+      case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
+        return format;
+      case GL_DEPTH_COMPONENT:
+        switch (type)
+        {
+          case GL_UNSIGNED_SHORT:           return GL_DEPTH_COMPONENT16;
+          case GL_UNSIGNED_INT:             return GL_DEPTH_COMPONENT32_OES;
+          default:                          UNIMPLEMENTED();
+        }
+        break;
+      case GL_DEPTH_STENCIL_OES:
+        switch (type)
+        {
+          case GL_UNSIGNED_INT_24_8_OES:    return GL_DEPTH24_STENCIL8_OES;
+          default:                          UNIMPLEMENTED();
+        }
+        break;
+      default:
+        UNIMPLEMENTED();
+    }
+
+    return GL_NONE;
+}
+
+GLenum ExtractFormat(GLenum internalformat)
+{
+    switch (internalformat)
+    {
+      case GL_RGB565:                          return GL_RGB;
+      case GL_RGBA4:                           return GL_RGBA;
+      case GL_RGB5_A1:                         return GL_RGBA;
+      case GL_RGB8_OES:                        return GL_RGB;
+      case GL_RGBA8_OES:                       return GL_RGBA;
+      case GL_LUMINANCE8_ALPHA8_EXT:           return GL_LUMINANCE_ALPHA;
+      case GL_LUMINANCE8_EXT:                  return GL_LUMINANCE;
+      case GL_ALPHA8_EXT:                      return GL_ALPHA;
+      case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:    return GL_COMPRESSED_RGB_S3TC_DXT1_EXT;
+      case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:   return GL_COMPRESSED_RGBA_S3TC_DXT1_EXT;
+      case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE: return GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE;
+      case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE: return GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE;
+      case GL_RGBA32F_EXT:                     return GL_RGBA;
+      case GL_RGB32F_EXT:                      return GL_RGB;
+      case GL_ALPHA32F_EXT:                    return GL_ALPHA;
+      case GL_LUMINANCE32F_EXT:                return GL_LUMINANCE;
+      case GL_LUMINANCE_ALPHA32F_EXT:          return GL_LUMINANCE_ALPHA;
+      case GL_RGBA16F_EXT:                     return GL_RGBA;
+      case GL_RGB16F_EXT:                      return GL_RGB;
+      case GL_ALPHA16F_EXT:                    return GL_ALPHA;
+      case GL_LUMINANCE16F_EXT:                return GL_LUMINANCE;
+      case GL_LUMINANCE_ALPHA16F_EXT:          return GL_LUMINANCE_ALPHA;
+      case GL_BGRA8_EXT:                       return GL_BGRA_EXT;
+      case GL_DEPTH_COMPONENT16:               return GL_DEPTH_COMPONENT;
+      case GL_DEPTH_COMPONENT32_OES:           return GL_DEPTH_COMPONENT;
+      case GL_DEPTH24_STENCIL8_OES:            return GL_DEPTH_STENCIL_OES;
+      default:                                 return GL_NONE;   // Unsupported
+    }
+}
+
+GLenum ExtractType(GLenum internalformat)
+{
+    switch (internalformat)
+    {
+      case GL_RGB565:                          return GL_UNSIGNED_SHORT_5_6_5;
+      case GL_RGBA4:                           return GL_UNSIGNED_SHORT_4_4_4_4;
+      case GL_RGB5_A1:                         return GL_UNSIGNED_SHORT_5_5_5_1;
+      case GL_RGB8_OES:                        return GL_UNSIGNED_BYTE;
+      case GL_RGBA8_OES:                       return GL_UNSIGNED_BYTE;
+      case GL_LUMINANCE8_ALPHA8_EXT:           return GL_UNSIGNED_BYTE;
+      case GL_LUMINANCE8_EXT:                  return GL_UNSIGNED_BYTE;
+      case GL_ALPHA8_EXT:                      return GL_UNSIGNED_BYTE;
+      case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:    return GL_UNSIGNED_BYTE;
+      case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:   return GL_UNSIGNED_BYTE;
+      case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE: return GL_UNSIGNED_BYTE;
+      case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE: return GL_UNSIGNED_BYTE;
+      case GL_RGBA32F_EXT:                     return GL_FLOAT;
+      case GL_RGB32F_EXT:                      return GL_FLOAT;
+      case GL_ALPHA32F_EXT:                    return GL_FLOAT;
+      case GL_LUMINANCE32F_EXT:                return GL_FLOAT;
+      case GL_LUMINANCE_ALPHA32F_EXT:          return GL_FLOAT;
+      case GL_RGBA16F_EXT:                     return GL_HALF_FLOAT_OES;
+      case GL_RGB16F_EXT:                      return GL_HALF_FLOAT_OES;
+      case GL_ALPHA16F_EXT:                    return GL_HALF_FLOAT_OES;
+      case GL_LUMINANCE16F_EXT:                return GL_HALF_FLOAT_OES;
+      case GL_LUMINANCE_ALPHA16F_EXT:          return GL_HALF_FLOAT_OES;
+      case GL_BGRA8_EXT:                       return GL_UNSIGNED_BYTE;
+      case GL_DEPTH_COMPONENT16:               return GL_UNSIGNED_SHORT;
+      case GL_DEPTH_COMPONENT32_OES:           return GL_UNSIGNED_INT;
+      case GL_DEPTH24_STENCIL8_OES:            return GL_UNSIGNED_INT_24_8_OES;
+      default:                                 return GL_NONE;   // Unsupported
+    }
+}
+
+bool IsColorRenderable(GLenum internalformat)
+{
+    switch (internalformat)
+    {
+      case GL_RGBA4:
+      case GL_RGB5_A1:
+      case GL_RGB565:
+      case GL_RGB8_OES:
+      case GL_RGBA8_OES:
+        return true;
+      case GL_DEPTH_COMPONENT16:
+      case GL_STENCIL_INDEX8:
+      case GL_DEPTH24_STENCIL8_OES:
+        return false;
+      default:
+        UNIMPLEMENTED();
+    }
+
+    return false;
+}
+
+bool IsDepthRenderable(GLenum internalformat)
+{
+    switch (internalformat)
+    {
+      case GL_DEPTH_COMPONENT16:
+      case GL_DEPTH24_STENCIL8_OES:
+        return true;
+      case GL_STENCIL_INDEX8:
+      case GL_RGBA4:
+      case GL_RGB5_A1:
+      case GL_RGB565:
+      case GL_RGB8_OES:
+      case GL_RGBA8_OES:
+        return false;
+      default:
+        UNIMPLEMENTED();
+    }
+
+    return false;
+}
+
+bool IsStencilRenderable(GLenum internalformat)
+{
+    switch (internalformat)
+    {
+      case GL_STENCIL_INDEX8:
+      case GL_DEPTH24_STENCIL8_OES:
+        return true;
+      case GL_RGBA4:
+      case GL_RGB5_A1:
+      case GL_RGB565:
+      case GL_RGB8_OES:
+      case GL_RGBA8_OES:
+      case GL_DEPTH_COMPONENT16:
+        return false;
+      default:
+        UNIMPLEMENTED();
+    }
+
+    return false;
+}
+
+bool IsFloat32Format(GLint internalformat)
+{
+    switch (internalformat)
+    {
+      case GL_RGBA32F_EXT:
+      case GL_RGB32F_EXT:
+      case GL_ALPHA32F_EXT:
+      case GL_LUMINANCE32F_EXT:
+      case GL_LUMINANCE_ALPHA32F_EXT:
+        return true;
+      default:
+        return false;
+    }
+}
+
+bool IsFloat16Format(GLint internalformat)
+{
+    switch (internalformat)
+    {
+      case GL_RGBA16F_EXT:
+      case GL_RGB16F_EXT:
+      case GL_ALPHA16F_EXT:
+      case GL_LUMINANCE16F_EXT:
+      case GL_LUMINANCE_ALPHA16F_EXT:
+        return true;
+      default:
+        return false;
+    }
+}
+
+}
+
+namespace es2dx
+{
+
+D3DCMPFUNC ConvertComparison(GLenum comparison)
+{
+    D3DCMPFUNC d3dComp = D3DCMP_ALWAYS;
+    switch (comparison)
+    {
+      case GL_NEVER:    d3dComp = D3DCMP_NEVER;        break;
+      case GL_ALWAYS:   d3dComp = D3DCMP_ALWAYS;       break;
+      case GL_LESS:     d3dComp = D3DCMP_LESS;         break;
+      case GL_LEQUAL:   d3dComp = D3DCMP_LESSEQUAL;    break;
+      case GL_EQUAL:    d3dComp = D3DCMP_EQUAL;        break;
+      case GL_GREATER:  d3dComp = D3DCMP_GREATER;      break;
+      case GL_GEQUAL:   d3dComp = D3DCMP_GREATEREQUAL; break;
+      case GL_NOTEQUAL: d3dComp = D3DCMP_NOTEQUAL;     break;
+      default: UNREACHABLE();
+    }
+
+    return d3dComp;
+}
+
+D3DCOLOR ConvertColor(gl::Color color)
+{
+    return D3DCOLOR_RGBA(gl::unorm<8>(color.red),
+                         gl::unorm<8>(color.green),
+                         gl::unorm<8>(color.blue),
+                         gl::unorm<8>(color.alpha));
+}
+
+D3DBLEND ConvertBlendFunc(GLenum blend)
+{
+    D3DBLEND d3dBlend = D3DBLEND_ZERO;
+
+    switch (blend)
+    {
+      case GL_ZERO:                     d3dBlend = D3DBLEND_ZERO;           break;
+      case GL_ONE:                      d3dBlend = D3DBLEND_ONE;            break;
+      case GL_SRC_COLOR:                d3dBlend = D3DBLEND_SRCCOLOR;       break;
+      case GL_ONE_MINUS_SRC_COLOR:      d3dBlend = D3DBLEND_INVSRCCOLOR;    break;
+      case GL_DST_COLOR:                d3dBlend = D3DBLEND_DESTCOLOR;      break;
+      case GL_ONE_MINUS_DST_COLOR:      d3dBlend = D3DBLEND_INVDESTCOLOR;   break;
+      case GL_SRC_ALPHA:                d3dBlend = D3DBLEND_SRCALPHA;       break;
+      case GL_ONE_MINUS_SRC_ALPHA:      d3dBlend = D3DBLEND_INVSRCALPHA;    break;
+      case GL_DST_ALPHA:                d3dBlend = D3DBLEND_DESTALPHA;      break;
+      case GL_ONE_MINUS_DST_ALPHA:      d3dBlend = D3DBLEND_INVDESTALPHA;   break;
+      case GL_CONSTANT_COLOR:           d3dBlend = D3DBLEND_BLENDFACTOR;    break;
+      case GL_ONE_MINUS_CONSTANT_COLOR: d3dBlend = D3DBLEND_INVBLENDFACTOR; break;
+      case GL_CONSTANT_ALPHA:           d3dBlend = D3DBLEND_BLENDFACTOR;    break;
+      case GL_ONE_MINUS_CONSTANT_ALPHA: d3dBlend = D3DBLEND_INVBLENDFACTOR; break;
+      case GL_SRC_ALPHA_SATURATE:       d3dBlend = D3DBLEND_SRCALPHASAT;    break;
+      default: UNREACHABLE();
+    }
+
+    return d3dBlend;
+}
+
+D3DBLENDOP ConvertBlendOp(GLenum blendOp)
+{
+    D3DBLENDOP d3dBlendOp = D3DBLENDOP_ADD;
+
+    switch (blendOp)
+    {
+      case GL_FUNC_ADD:              d3dBlendOp = D3DBLENDOP_ADD;         break;
+      case GL_FUNC_SUBTRACT:         d3dBlendOp = D3DBLENDOP_SUBTRACT;    break;
+      case GL_FUNC_REVERSE_SUBTRACT: d3dBlendOp = D3DBLENDOP_REVSUBTRACT; break;
+      default: UNREACHABLE();
+    }
+
+    return d3dBlendOp;
+}
+
+D3DSTENCILOP ConvertStencilOp(GLenum stencilOp)
+{
+    D3DSTENCILOP d3dStencilOp = D3DSTENCILOP_KEEP;
+
+    switch (stencilOp)
+    {
+      case GL_ZERO:      d3dStencilOp = D3DSTENCILOP_ZERO;    break;
+      case GL_KEEP:      d3dStencilOp = D3DSTENCILOP_KEEP;    break;
+      case GL_REPLACE:   d3dStencilOp = D3DSTENCILOP_REPLACE; break;
+      case GL_INCR:      d3dStencilOp = D3DSTENCILOP_INCRSAT; break;
+      case GL_DECR:      d3dStencilOp = D3DSTENCILOP_DECRSAT; break;
+      case GL_INVERT:    d3dStencilOp = D3DSTENCILOP_INVERT;  break;
+      case GL_INCR_WRAP: d3dStencilOp = D3DSTENCILOP_INCR;    break;
+      case GL_DECR_WRAP: d3dStencilOp = D3DSTENCILOP_DECR;    break;
+      default: UNREACHABLE();
+    }
+
+    return d3dStencilOp;
+}
+
+D3DTEXTUREADDRESS ConvertTextureWrap(GLenum wrap)
+{
+    D3DTEXTUREADDRESS d3dWrap = D3DTADDRESS_WRAP;
+
+    switch (wrap)
+    {
+      case GL_REPEAT:            d3dWrap = D3DTADDRESS_WRAP;   break;
+      case GL_CLAMP_TO_EDGE:     d3dWrap = D3DTADDRESS_CLAMP;  break;
+      case GL_MIRRORED_REPEAT:   d3dWrap = D3DTADDRESS_MIRROR; break;
+      default: UNREACHABLE();
+    }
+
+    return d3dWrap;
+}
+
+D3DCULL ConvertCullMode(GLenum cullFace, GLenum frontFace)
+{
+    D3DCULL cull = D3DCULL_CCW;
+    switch (cullFace)
+    {
+      case GL_FRONT:
+        cull = (frontFace == GL_CCW ? D3DCULL_CW : D3DCULL_CCW);
+        break;
+      case GL_BACK:
+        cull = (frontFace == GL_CCW ? D3DCULL_CCW : D3DCULL_CW);
+        break;
+      case GL_FRONT_AND_BACK:
+        cull = D3DCULL_NONE; // culling will be handled during draw
+        break;
+      default: UNREACHABLE();
+    }
+
+    return cull;
+}
+
+D3DCUBEMAP_FACES ConvertCubeFace(GLenum cubeFace)
+{
+    D3DCUBEMAP_FACES face = D3DCUBEMAP_FACE_POSITIVE_X;
+
+    switch (cubeFace)
+    {
+      case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
+        face = D3DCUBEMAP_FACE_POSITIVE_X;
+        break;
+      case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
+        face = D3DCUBEMAP_FACE_NEGATIVE_X;
+        break;
+      case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
+        face = D3DCUBEMAP_FACE_POSITIVE_Y;
+        break;
+      case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
+        face = D3DCUBEMAP_FACE_NEGATIVE_Y;
+        break;
+      case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
+        face = D3DCUBEMAP_FACE_POSITIVE_Z;
+        break;
+      case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
+        face = D3DCUBEMAP_FACE_NEGATIVE_Z;
+        break;
+      default: UNREACHABLE();
+    }
+
+    return face;
+}
+
+DWORD ConvertColorMask(bool red, bool green, bool blue, bool alpha)
+{
+    return (red   ? D3DCOLORWRITEENABLE_RED   : 0) |
+           (green ? D3DCOLORWRITEENABLE_GREEN : 0) |
+           (blue  ? D3DCOLORWRITEENABLE_BLUE  : 0) |
+           (alpha ? D3DCOLORWRITEENABLE_ALPHA : 0);
+}
+
+D3DTEXTUREFILTERTYPE ConvertMagFilter(GLenum magFilter, float maxAnisotropy)
+{
+    if (maxAnisotropy > 1.0f)
+    {
+        return D3DTEXF_ANISOTROPIC;
+    }
+
+    D3DTEXTUREFILTERTYPE d3dMagFilter = D3DTEXF_POINT;
+    switch (magFilter)
+    {
+      case GL_NEAREST: d3dMagFilter = D3DTEXF_POINT;  break;
+      case GL_LINEAR:  d3dMagFilter = D3DTEXF_LINEAR; break;
+      default: UNREACHABLE();
+    }
+
+    return d3dMagFilter;
+}
+
+void ConvertMinFilter(GLenum minFilter, D3DTEXTUREFILTERTYPE *d3dMinFilter, D3DTEXTUREFILTERTYPE *d3dMipFilter, float maxAnisotropy)
+{
+    switch (minFilter)
+    {
+      case GL_NEAREST:
+        *d3dMinFilter = D3DTEXF_POINT;
+        *d3dMipFilter = D3DTEXF_NONE;
+        break;
+      case GL_LINEAR:
+        *d3dMinFilter = D3DTEXF_LINEAR;
+        *d3dMipFilter = D3DTEXF_NONE;
+        break;
+      case GL_NEAREST_MIPMAP_NEAREST:
+        *d3dMinFilter = D3DTEXF_POINT;
+        *d3dMipFilter = D3DTEXF_POINT;
+        break;
+      case GL_LINEAR_MIPMAP_NEAREST:
+        *d3dMinFilter = D3DTEXF_LINEAR;
+        *d3dMipFilter = D3DTEXF_POINT;
+        break;
+      case GL_NEAREST_MIPMAP_LINEAR:
+        *d3dMinFilter = D3DTEXF_POINT;
+        *d3dMipFilter = D3DTEXF_LINEAR;
+        break;
+      case GL_LINEAR_MIPMAP_LINEAR:
+        *d3dMinFilter = D3DTEXF_LINEAR;
+        *d3dMipFilter = D3DTEXF_LINEAR;
+        break;
+      default:
+        *d3dMinFilter = D3DTEXF_POINT;
+        *d3dMipFilter = D3DTEXF_NONE;
+        UNREACHABLE();
+    }
+
+    if (maxAnisotropy > 1.0f)
+    {
+        *d3dMinFilter = D3DTEXF_ANISOTROPIC;
+    }
+}
+
+bool ConvertPrimitiveType(GLenum primitiveType, GLsizei elementCount,
+                          D3DPRIMITIVETYPE *d3dPrimitiveType, int *d3dPrimitiveCount)
+{
+    switch (primitiveType)
+    {
+      case GL_POINTS:
+        *d3dPrimitiveType = D3DPT_POINTLIST;
+        *d3dPrimitiveCount = elementCount;
+        break;
+      case GL_LINES:
+        *d3dPrimitiveType = D3DPT_LINELIST;
+        *d3dPrimitiveCount = elementCount / 2;
+        break;
+      case GL_LINE_LOOP:
+        *d3dPrimitiveType = D3DPT_LINESTRIP;
+        *d3dPrimitiveCount = elementCount - 1;   // D3D doesn't support line loops, so we draw the last line separately
+        break;
+      case GL_LINE_STRIP:
+        *d3dPrimitiveType = D3DPT_LINESTRIP;
+        *d3dPrimitiveCount = elementCount - 1;
+        break;
+      case GL_TRIANGLES:
+        *d3dPrimitiveType = D3DPT_TRIANGLELIST;
+        *d3dPrimitiveCount = elementCount / 3;
+        break;
+      case GL_TRIANGLE_STRIP:
+        *d3dPrimitiveType = D3DPT_TRIANGLESTRIP;
+        *d3dPrimitiveCount = elementCount - 2;
+        break;
+      case GL_TRIANGLE_FAN:
+        *d3dPrimitiveType = D3DPT_TRIANGLEFAN;
+        *d3dPrimitiveCount = elementCount - 2;
+        break;
+      default:
+        return false;
+    }
+
+    return true;
+}
+
+D3DFORMAT ConvertRenderbufferFormat(GLenum format)
+{
+    switch (format)
+    {
+      case GL_NONE:                 return D3DFMT_NULL;
+      case GL_RGBA4:
+      case GL_RGB5_A1:
+      case GL_RGBA8_OES:            return D3DFMT_A8R8G8B8;
+      case GL_RGB565:               return D3DFMT_R5G6B5;
+      case GL_RGB8_OES:             return D3DFMT_X8R8G8B8;
+      case GL_DEPTH_COMPONENT16:
+      case GL_STENCIL_INDEX8:       
+      case GL_DEPTH24_STENCIL8_OES: return D3DFMT_D24S8;
+      default: UNREACHABLE();       return D3DFMT_A8R8G8B8;
+    }
+}
+
+D3DMULTISAMPLE_TYPE GetMultisampleTypeFromSamples(GLsizei samples)
+{
+    if (samples <= 1)
+        return D3DMULTISAMPLE_NONE;
+    else
+        return (D3DMULTISAMPLE_TYPE)samples;
+}
+
+}
+
+namespace dx2es
+{
+
+unsigned int GetStencilSize(D3DFORMAT stencilFormat)
+{
+    if (stencilFormat == D3DFMT_INTZ)
+    {
+        return 8;
+    }
+    switch(stencilFormat)
+    {
+      case D3DFMT_D24FS8:
+      case D3DFMT_D24S8:
+        return 8;
+      case D3DFMT_D24X4S4:
+        return 4;
+      case D3DFMT_D15S1:
+        return 1;
+      case D3DFMT_D16_LOCKABLE:
+      case D3DFMT_D32:
+      case D3DFMT_D24X8:
+      case D3DFMT_D32F_LOCKABLE:
+      case D3DFMT_D16:
+        return 0;
+    //case D3DFMT_D32_LOCKABLE:  return 0;   // DirectX 9Ex only
+    //case D3DFMT_S8_LOCKABLE:   return 8;   // DirectX 9Ex only
+      default:
+        return 0;
+    }
+}
+
+unsigned int GetAlphaSize(D3DFORMAT colorFormat)
+{
+    switch (colorFormat)
+    {
+      case D3DFMT_A16B16G16R16F:
+        return 16;
+      case D3DFMT_A32B32G32R32F:
+        return 32;
+      case D3DFMT_A2R10G10B10:
+        return 2;
+      case D3DFMT_A8R8G8B8:
+        return 8;
+      case D3DFMT_A1R5G5B5:
+        return 1;
+      case D3DFMT_X8R8G8B8:
+      case D3DFMT_R5G6B5:
+        return 0;
+      default:
+        return 0;
+    }
+}
+
+unsigned int GetRedSize(D3DFORMAT colorFormat)
+{
+    switch (colorFormat)
+    {
+      case D3DFMT_A16B16G16R16F:
+        return 16;
+      case D3DFMT_A32B32G32R32F:
+        return 32;
+      case D3DFMT_A2R10G10B10:
+        return 10;
+      case D3DFMT_A8R8G8B8:
+      case D3DFMT_X8R8G8B8:
+        return 8;
+      case D3DFMT_A1R5G5B5:
+      case D3DFMT_R5G6B5:
+        return 5;
+      default:
+        return 0;
+    }
+}
+
+unsigned int GetGreenSize(D3DFORMAT colorFormat)
+{
+    switch (colorFormat)
+    {
+      case D3DFMT_A16B16G16R16F:
+        return 16;
+      case D3DFMT_A32B32G32R32F:
+        return 32;
+      case D3DFMT_A2R10G10B10:
+        return 10;
+      case D3DFMT_A8R8G8B8:
+      case D3DFMT_X8R8G8B8:
+        return 8;
+      case D3DFMT_A1R5G5B5:
+        return 5;
+      case D3DFMT_R5G6B5:
+        return 6;
+      default:
+        return 0;
+    }
+}
+
+unsigned int GetBlueSize(D3DFORMAT colorFormat)
+{
+    switch (colorFormat)
+    {
+      case D3DFMT_A16B16G16R16F:
+        return 16;
+      case D3DFMT_A32B32G32R32F:
+        return 32;
+      case D3DFMT_A2R10G10B10:
+        return 10;
+      case D3DFMT_A8R8G8B8:
+      case D3DFMT_X8R8G8B8:
+        return 8;
+      case D3DFMT_A1R5G5B5:
+      case D3DFMT_R5G6B5:
+        return 5;
+      default:
+        return 0;
+    }
+}
+
+unsigned int GetDepthSize(D3DFORMAT depthFormat)
+{
+    if (depthFormat == D3DFMT_INTZ)
+    {
+        return 24;
+    }
+    switch (depthFormat)
+    {
+      case D3DFMT_D16_LOCKABLE:  return 16;
+      case D3DFMT_D32:           return 32;
+      case D3DFMT_D15S1:         return 15;
+      case D3DFMT_D24S8:         return 24;
+      case D3DFMT_D24X8:         return 24;
+      case D3DFMT_D24X4S4:       return 24;
+      case D3DFMT_D16:           return 16;
+      case D3DFMT_D32F_LOCKABLE: return 32;
+      case D3DFMT_D24FS8:        return 24;
+    //case D3DFMT_D32_LOCKABLE:  return 32;   // D3D9Ex only
+    //case D3DFMT_S8_LOCKABLE:   return 0;    // D3D9Ex only
+      default:                   return 0;
+    }
+}
+
+GLsizei GetSamplesFromMultisampleType(D3DMULTISAMPLE_TYPE type)
+{
+    if (type == D3DMULTISAMPLE_NONMASKABLE)
+        return 0;
+    else
+        return type;
+}
+
+bool IsFormatChannelEquivalent(D3DFORMAT d3dformat, GLenum format)
+{
+    switch (d3dformat)
+    {
+      case D3DFMT_L8:
+        return (format == GL_LUMINANCE);
+      case D3DFMT_A8L8:
+        return (format == GL_LUMINANCE_ALPHA);
+      case D3DFMT_DXT1:
+        return (format == GL_COMPRESSED_RGBA_S3TC_DXT1_EXT || format == GL_COMPRESSED_RGB_S3TC_DXT1_EXT);
+      case D3DFMT_DXT3:
+        return (format == GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE);
+      case D3DFMT_DXT5:
+        return (format == GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE);
+      case D3DFMT_A8R8G8B8:
+      case D3DFMT_A16B16G16R16F:
+      case D3DFMT_A32B32G32R32F:
+        return (format == GL_RGBA || format == GL_BGRA_EXT);
+      case D3DFMT_X8R8G8B8:
+        return (format == GL_RGB);
+      default:
+        if (d3dformat == D3DFMT_INTZ && gl::IsDepthTexture(format))
+            return true;
+        return false;
+    }
+}
+
+bool ConvertReadBufferFormat(D3DFORMAT d3dformat, GLenum *format, GLenum *type)
+{
+    switch (d3dformat)
+    {
+      case D3DFMT_A8R8G8B8:
+        *type = GL_UNSIGNED_BYTE;
+        *format = GL_BGRA_EXT;
+        break;
+      case D3DFMT_X8R8G8B8:
+        *type = GL_UNSIGNED_BYTE;
+        *format = GL_RGB;
+        break;
+      case D3DFMT_R5G6B5:
+        *type = GL_UNSIGNED_SHORT_5_6_5;
+        *format = GL_RGB;
+        break;
+      case D3DFMT_A16B16G16R16F:
+        *type = GL_HALF_FLOAT_OES;
+        *format = GL_RGBA;
+        break;
+      case D3DFMT_A32B32G32R32F:
+        *type = GL_FLOAT;
+        *format = GL_RGBA;
+        break;
+      case D3DFMT_A4R4G4B4:
+        *type = GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT;
+        *format = GL_BGRA_EXT;
+        break;
+      case D3DFMT_A1R5G5B5:
+        *type = GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT;
+        *format = GL_BGRA_EXT;
+        break;
+      default:
+        *type = GL_NONE;
+        *format = GL_NONE;
+        return false;
+    }
+    return true;
+}
+
+GLenum ConvertBackBufferFormat(D3DFORMAT format)
+{
+    switch (format)
+    {
+      case D3DFMT_A4R4G4B4: return GL_RGBA4;
+      case D3DFMT_A8R8G8B8: return GL_RGBA8_OES;
+      case D3DFMT_A1R5G5B5: return GL_RGB5_A1;
+      case D3DFMT_R5G6B5:   return GL_RGB565;
+      case D3DFMT_X8R8G8B8: return GL_RGB8_OES;
+      default:
+        UNREACHABLE();
+    }
+
+    return GL_RGBA4;
+}
+
+GLenum ConvertDepthStencilFormat(D3DFORMAT format)
+{
+    if (format == D3DFMT_INTZ)
+    {
+        return GL_DEPTH24_STENCIL8_OES;
+    }
+    switch (format)
+    {
+      case D3DFMT_D16:
+      case D3DFMT_D24X8:
+        return GL_DEPTH_COMPONENT16;
+      case D3DFMT_D24S8:
+        return GL_DEPTH24_STENCIL8_OES;
+      default:
+        UNREACHABLE();
+    }
+
+    return GL_DEPTH24_STENCIL8_OES;
+}
+
+}
+
+namespace dx
+{
+
+bool IsCompressedFormat(D3DFORMAT surfaceFormat)
+{
+    switch(surfaceFormat)
+    {
+      case D3DFMT_DXT1:
+      case D3DFMT_DXT2:
+      case D3DFMT_DXT3:
+      case D3DFMT_DXT4:
+      case D3DFMT_DXT5:
+        return true;
+      default:
+        return false;
+    }
+}
+
+size_t ComputeRowSize(D3DFORMAT format, unsigned int width)
+{
+    if (format == D3DFMT_INTZ)
+    {
+        return 4 * width;
+    }
+    switch (format)
+    {
+      case D3DFMT_L8:
+          return 1 * width;
+      case D3DFMT_A8L8:
+          return 2 * width;
+      case D3DFMT_X8R8G8B8:
+      case D3DFMT_A8R8G8B8:
+        return 4 * width;
+      case D3DFMT_A16B16G16R16F:
+        return 8 * width;
+      case D3DFMT_A32B32G32R32F:
+        return 16 * width;
+      case D3DFMT_DXT1:
+        return 8 * ((width + 3) / 4);
+      case D3DFMT_DXT3:
+      case D3DFMT_DXT5:
+        return 16 * ((width + 3) / 4);
+      default:
+        UNREACHABLE();
+        return 0;
+    }
+}
+
+}
+
+std::string getTempPath()
+{
+    char path[MAX_PATH];
+    DWORD pathLen = GetTempPathA(sizeof(path) / sizeof(path[0]), path);
+    if (pathLen == 0)
+    {
+        UNREACHABLE();
+        return std::string();
+    }
+
+    UINT unique = GetTempFileNameA(path, "sh", 0, path);
+    if (unique == 0)
+    {
+        UNREACHABLE();
+        return std::string();
+    }
+    
+    return path;
+}
+
+void writeFile(const char* path, const void* content, size_t size)
+{
+    FILE* file = fopen(path, "w");
+    if (!file)
+    {
+        UNREACHABLE();
+        return;
+    }
+
+    fwrite(content, sizeof(char), size, file);
+    fclose(file);
+}
diff --git a/src/3rdparty/angle/src/libGLESv2/utilities.h b/src/3rdparty/angle/src/libGLESv2/utilities.h
new file mode 100644 (file)
index 0000000..29ad207
--- /dev/null
@@ -0,0 +1,121 @@
+//
+// 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.
+//
+
+// utilities.h: Conversion functions and other utility routines.
+
+#ifndef LIBGLESV2_UTILITIES_H
+#define LIBGLESV2_UTILITIES_H
+
+#define GL_APICALL
+#include <GLES2/gl2.h>
+#include <GLES2/gl2ext.h>
+#include <d3d9.h>
+
+#include <string>
+
+const D3DFORMAT D3DFMT_INTZ = ((D3DFORMAT)(MAKEFOURCC('I','N','T','Z')));
+const D3DFORMAT D3DFMT_NULL = ((D3DFORMAT)(MAKEFOURCC('N','U','L','L')));
+
+namespace gl
+{
+
+struct Color;
+
+int UniformExternalComponentCount(GLenum type);
+int UniformInternalComponentCount(GLenum type);
+GLenum UniformComponentType(GLenum type);
+size_t UniformInternalSize(GLenum type);
+size_t UniformExternalSize(GLenum type);
+int VariableRowCount(GLenum type);
+int VariableColumnCount(GLenum type);
+
+int AllocateFirstFreeBits(unsigned int *bits, unsigned int allocationSize, unsigned int bitsSize);
+
+int ComputePixelSize(GLint internalformat);
+GLsizei ComputePitch(GLsizei width, GLint internalformat, GLint alignment);
+GLsizei ComputeCompressedPitch(GLsizei width, GLenum format);
+GLsizei ComputeCompressedSize(GLsizei width, GLsizei height, GLenum format);
+bool IsCompressed(GLenum format);
+bool IsDepthTexture(GLenum format);
+bool IsStencilTexture(GLenum format);
+bool IsCubemapTextureTarget(GLenum target);
+bool IsInternalTextureTarget(GLenum target);
+GLint ConvertSizedInternalFormat(GLenum format, GLenum type);
+GLenum ExtractFormat(GLenum internalformat);
+GLenum ExtractType(GLenum internalformat);
+
+bool IsColorRenderable(GLenum internalformat);
+bool IsDepthRenderable(GLenum internalformat);
+bool IsStencilRenderable(GLenum internalformat);
+
+bool IsFloat32Format(GLint internalformat);
+bool IsFloat16Format(GLint internalformat);
+}
+
+namespace es2dx
+{
+
+D3DCMPFUNC ConvertComparison(GLenum comparison);
+D3DCOLOR ConvertColor(gl::Color color);
+D3DBLEND ConvertBlendFunc(GLenum blend);
+D3DBLENDOP ConvertBlendOp(GLenum blendOp);
+D3DSTENCILOP ConvertStencilOp(GLenum stencilOp);
+D3DTEXTUREADDRESS ConvertTextureWrap(GLenum wrap);
+D3DCULL ConvertCullMode(GLenum cullFace, GLenum frontFace);
+D3DCUBEMAP_FACES ConvertCubeFace(GLenum cubeFace);
+DWORD ConvertColorMask(bool red, bool green, bool blue, bool alpha);
+D3DTEXTUREFILTERTYPE ConvertMagFilter(GLenum magFilter, float maxAnisotropy);
+void ConvertMinFilter(GLenum minFilter, D3DTEXTUREFILTERTYPE *d3dMinFilter, D3DTEXTUREFILTERTYPE *d3dMipFilter, float maxAnisotropy);
+bool ConvertPrimitiveType(GLenum primitiveType, GLsizei elementCount,
+                          D3DPRIMITIVETYPE *d3dPrimitiveType, int *d3dPrimitiveCount);
+D3DFORMAT ConvertRenderbufferFormat(GLenum format);
+D3DMULTISAMPLE_TYPE GetMultisampleTypeFromSamples(GLsizei samples);
+
+}
+
+namespace dx2es
+{
+
+GLuint GetAlphaSize(D3DFORMAT colorFormat);
+GLuint GetRedSize(D3DFORMAT colorFormat);
+GLuint GetGreenSize(D3DFORMAT colorFormat);
+GLuint GetBlueSize(D3DFORMAT colorFormat);
+GLuint GetDepthSize(D3DFORMAT depthFormat);
+GLuint GetStencilSize(D3DFORMAT stencilFormat);
+
+GLsizei GetSamplesFromMultisampleType(D3DMULTISAMPLE_TYPE type);
+
+bool IsFormatChannelEquivalent(D3DFORMAT d3dformat, GLenum format);
+bool ConvertReadBufferFormat(D3DFORMAT d3dformat, GLenum *format, GLenum *type);
+GLenum ConvertBackBufferFormat(D3DFORMAT format);
+GLenum ConvertDepthStencilFormat(D3DFORMAT format);
+
+}
+
+namespace dx
+{
+bool IsCompressedFormat(D3DFORMAT format);
+size_t ComputeRowSize(D3DFORMAT format, unsigned int width);
+}
+
+std::string getTempPath();
+void writeFile(const char* path, const void* data, size_t size);
+
+inline bool isDeviceLostError(HRESULT errorCode)
+{
+    switch (errorCode)
+    {
+      case D3DERR_DRIVERINTERNALERROR:
+      case D3DERR_DEVICELOST:
+      case D3DERR_DEVICEHUNG:
+      case D3DERR_DEVICEREMOVED:
+        return true;
+      default:
+        return false;
+    }
+};
+
+#endif  // LIBGLESV2_UTILITIES_H
diff --git a/src/3rdparty/angle/src/libGLESv2/vertexconversion.h b/src/3rdparty/angle/src/libGLESv2/vertexconversion.h
new file mode 100644 (file)
index 0000000..5bb8b89
--- /dev/null
@@ -0,0 +1,208 @@
+//
+// 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.
+//
+
+// vertexconversion.h: A library of vertex conversion classes that can be used to build
+// the FormatConverter objects used by the buffer conversion system.
+
+#ifndef LIBGLESV2_VERTEXCONVERSION_H_
+#define LIBGLESV2_VERTEXCONVERSION_H_
+
+#include <cstddef>
+#include <limits>
+
+#include "libGLESv2/Context.h" // Defines Index
+
+namespace gl
+{
+
+// Conversion types:
+// static const bool identity: true if this is an identity transform, false otherwise
+// static U convert(T): convert a single element from the input type to the output type
+// typedef ... OutputType: the type produced by this conversion
+
+template <class T>
+struct Identity
+{
+    static const bool identity = true;
+
+    typedef T OutputType;
+
+    static T convert(T x)
+    {
+        return x;
+    }
+};
+
+template <class FromT, class ToT>
+struct Cast
+{
+    static const bool identity = false;
+
+    typedef ToT OutputType;
+
+    static ToT convert(FromT x)
+    {
+        return static_cast<ToT>(x);
+    }
+};
+
+template <class T>
+struct Cast<T, T>
+{
+    static const bool identity = true;
+
+    typedef T OutputType;
+
+    static T convert(T x)
+    {
+        return static_cast<T>(x);
+    }
+};
+
+template <class T>
+struct Normalize
+{
+    static const bool identity = false;
+
+    typedef float OutputType;
+
+    static float convert(T x)
+    {
+        typedef std::numeric_limits<T> NL;
+        float f = static_cast<float>(x);
+
+        if (NL::is_signed)
+        {
+            // const float => VC2008 computes it at compile time
+            // static const float => VC2008 computes it the first time we get here, stores it to memory with static guard and all that.
+            const float divisor = 1.0f/(2*static_cast<float>(NL::max())+1);
+            return (2*f+1)*divisor;
+        }
+        else
+        {
+            return f/NL::max();
+        }
+    }
+};
+
+template <class FromType, std::size_t ScaleBits>
+struct FixedToFloat
+{
+    static const bool identity = false;
+
+    typedef float OutputType;
+
+    static float convert(FromType x)
+    {
+        const float divisor = 1.0f / static_cast<float>(static_cast<FromType>(1) << ScaleBits);
+        return static_cast<float>(x) * divisor;
+    }
+};
+
+// Widen types:
+// static const unsigned int initialWidth: number of components before conversion
+// static const unsigned int finalWidth: number of components after conversion
+
+// Float is supported at any size.
+template <std::size_t N>
+struct NoWiden
+{
+    static const std::size_t initialWidth = N;
+    static const std::size_t finalWidth = N;
+};
+
+// SHORT, norm-SHORT, norm-UNSIGNED_SHORT are supported but only with 2 or 4 components
+template <std::size_t N>
+struct WidenToEven
+{
+    static const std::size_t initialWidth = N;
+    static const std::size_t finalWidth = N+(N&1);
+};
+
+template <std::size_t N>
+struct WidenToFour
+{
+    static const std::size_t initialWidth = N;
+    static const std::size_t finalWidth = 4;
+};
+
+// Most types have 0 and 1 that are just that.
+template <class T>
+struct SimpleDefaultValues
+{
+    static T zero() { return static_cast<T>(0); }
+    static T one() { return static_cast<T>(1); }
+};
+
+// But normalised types only store [0,1] or [-1,1] so 1.0 is represented by the max value.
+template <class T>
+struct NormalizedDefaultValues
+{
+    static T zero() { return static_cast<T>(0); }
+    static T one() { return std::numeric_limits<T>::max(); }
+};
+
+// Converter:
+// static const bool identity: true if this is an identity transform (with no widening)
+// static const std::size_t finalSize: number of bytes per output vertex
+// static void convertArray(const void *in, std::size_t stride, std::size_t n, void *out): convert an array of vertices. Input may be strided, but output will be unstrided.
+
+template <class InT, class WidenRule, class Converter, class DefaultValueRule = SimpleDefaultValues<InT> >
+struct VertexDataConverter
+{
+    typedef typename Converter::OutputType OutputType;
+    typedef InT InputType;
+
+    static const bool identity = (WidenRule::initialWidth == WidenRule::finalWidth) && Converter::identity;
+    static const std::size_t finalSize = WidenRule::finalWidth * sizeof(OutputType);
+
+    static void convertArray(const InputType *in, std::size_t stride, std::size_t n, OutputType *out)
+    {
+        for (std::size_t i = 0; i < n; i++)
+        {
+            const InputType *ein = pointerAddBytes(in, i * stride);
+
+            copyComponent(out, ein, 0, static_cast<OutputType>(DefaultValueRule::zero()));
+            copyComponent(out, ein, 1, static_cast<OutputType>(DefaultValueRule::zero()));
+            copyComponent(out, ein, 2, static_cast<OutputType>(DefaultValueRule::zero()));
+            copyComponent(out, ein, 3, static_cast<OutputType>(DefaultValueRule::one()));
+
+            out += WidenRule::finalWidth;
+        }
+    }
+
+    static void convertArray(const void *in, std::size_t stride, std::size_t n, void *out)
+    {
+        return convertArray(static_cast<const InputType*>(in), stride, n, static_cast<OutputType*>(out));
+    }
+
+  private:
+    // Advance the given pointer by a number of bytes (not pointed-to elements).
+    template <class T>
+    static T *pointerAddBytes(T *basePtr, std::size_t numBytes)
+    {
+        return reinterpret_cast<T *>(reinterpret_cast<uintptr_t>(basePtr) + numBytes);
+    }
+
+    static void copyComponent(OutputType *out, const InputType *in, std::size_t elementindex, OutputType defaultvalue)
+    {
+        if (WidenRule::finalWidth > elementindex)
+        {
+            if (WidenRule::initialWidth > elementindex)
+            {
+                out[elementindex] = Converter::convert(in[elementindex]);
+            }
+            else
+            {
+                out[elementindex] = defaultvalue;
+            }
+        }
+    }
+};
+
+}
+
+#endif   // LIBGLESV2_VERTEXCONVERSION_H_
diff --git a/src/angle/README.qt b/src/angle/README.qt
new file mode 100644 (file)
index 0000000..61023ef
--- /dev/null
@@ -0,0 +1,29 @@
+This is the ANGLE project from:
+
+http://code.google.com/p/angleproject/
+
+The upstream version used here can be found in:
+
+src/common/version.h
+
+This copy of the library has been modified with several patches
+that can be found in the 'patches' subdirectory.
+
+Updating ANGLE
+-------------------------------------------------------------
+To update to a newer version of ANGLE, extract the archive
+directly into the 'src/3rdparty/angle' directory. ANGLE contains
+a .gitignore file that will overwrite the one in Qt, but this is
+not desirable so the ANGLE one should be discarded and the one in
+Qt should be kept. If there are new source/header files in ANGLE
+(git status -u) then they should be added to the relevant .pro
+file before committing.
+
+
+Using a custom ANGLE
+-------------------------------------------------------------
+Qt supports building a version of ANGLE other than the one that
+is contained in the source tree. To get Qt to build a different
+copy of ANGLE, you can set the ANGLE_DIR environment variable
+to point to the location of the custom ANGLE before building Qt.
+
diff --git a/src/angle/angle.pro b/src/angle/angle.pro
new file mode 100644 (file)
index 0000000..00e0501
--- /dev/null
@@ -0,0 +1,19 @@
+TEMPLATE = subdirs
+SUBDIRS += src
+
+# We need to call syncqt manually instead of using "load(qt_module_headers)" for several reasons:
+#  1) qt_module_headers assumes the TARGET is the same as the include directory (eg: libGLESv2 != GLES2)
+#  2) If we made a 'QtANGLE' module, the include directory would be flattened which won't work since
+#     we need to support "#include <GLES2/gl2.h>"
+!build_pass {
+    qtPrepareTool(QMAKE_SYNCQT, syncqt)
+    QTDIR = $$[QT_HOST_PREFIX]
+    exists($$QTDIR/.qmake.cache): \
+        mod_component_base = $$QTDIR
+    else: \
+        mod_component_base = $$dirname(_QMAKE_CACHE_)
+    QMAKE_SYNCQT += -minimal -module KHR -module EGL -module GLES2 \
+        -mkspecsdir $$[QT_HOST_DATA/get]/mkspecs -outdir $$mod_component_base $$dirname(_QMAKE_CONF_)
+    !silent:message($$QMAKE_SYNCQT)
+    system($$QMAKE_SYNCQT)|error("Failed to run: $$QMAKE_SYNCQT")
+}
diff --git a/src/angle/patches/0003-Fix-Float16ToFloat32.py.patch b/src/angle/patches/0003-Fix-Float16ToFloat32.py.patch
new file mode 100644 (file)
index 0000000..c37ab43
--- /dev/null
@@ -0,0 +1,54 @@
+From e4f894847ebefe54f9a9f9911c38dc3efe77c260 Mon Sep 17 00:00:00 2001
+From: Jason Barron <jason.barron@digia.com>
+Date: Tue, 16 Oct 2012 10:34:32 +0200
+Subject: [PATCH 3/3] Fix Float16ToFloat32.py.
+
+To ensure generation of compilable code, the script should
+be using the alternate form of the hex string formatter to
+be sure it gets prefixed by '0x'.
+
+Also remove an extra '=' character.
+
+This issue has been reported upstream to the ANGLE team:
+
+    http://code.google.com/p/angleproject/issues/detail?id=376
+
+Change-Id: I8ccf017afcfbd2c2f52ed291b89f29ba597c9c41
+---
+ src/3rdparty/angle/src/libGLESv2/Float16ToFloat32.py | 8 ++++----
+ 1 file changed, 4 insertions(+), 4 deletions(-)
+
+diff --git a/src/3rdparty/angle/src/libGLESv2/Float16ToFloat32.py b/src/3rdparty/angle/src/libGLESv2/Float16ToFloat32.py
+index ae646ff..fb2964e 100644
+--- a/src/3rdparty/angle/src/libGLESv2/Float16ToFloat32.py
++++ b/src/3rdparty/angle/src/libGLESv2/Float16ToFloat32.py
+@@ -56,22 +56,22 @@ namespace gl
+ print "const static unsigned g_mantissa[2048] = {"
+ for i in range(0, 2048):
+-    print "    %08x," % convertMantissa(i)
++    print "    %#10x," % convertMantissa(i)
+ print "};\n"
+ print "const static unsigned g_exponent[64] = {"
+ for i in range(0, 64):
+-    print "    %08x," % convertExponent(i)
++    print "    %#10x," % convertExponent(i)
+ print "};\n"
+ print "const static unsigned g_offset[64] = {"
+ for i in range(0, 64):
+-    print "    %08x," % convertOffset(i)
++    print "    %#10x," % convertOffset(i)
+ print "};\n"
+ print """float float16ToFloat32(unsigned short h)
+ {
+-    unsigned i32 = =g_mantissa[g_offset[h >> 10] + (h & 0x3ff)] + g_exponent[h >> 10];
++    unsigned i32 = g_mantissa[g_offset[h >> 10] + (h & 0x3ff)] + g_exponent[h >> 10];
+     return *(float*) &i32;
+ }
+ }
+-- 
+1.7.11.msysgit.1
+
diff --git a/src/angle/src/common/common.pri b/src/angle/src/common/common.pri
new file mode 100644 (file)
index 0000000..e99080d
--- /dev/null
@@ -0,0 +1,53 @@
+include (../config.pri)
+
+INCLUDEPATH += \
+    $$ANGLE_DIR/src \
+    $$ANGLE_DIR/include
+
+LIBS = $$QMAKE_LIBS_CORE $$QMAKE_LIBS_GUI
+
+# DirectX is included in the Windows 8 Kit, but everything else requires the DX SDK.
+win32-msvc2012 {
+    FXC = fxc.exe
+} else {
+    DX_DIR = $$(DXSDK_DIR)
+    isEmpty(DX_DIR) {
+        error("Cannot determine DirectX SDK location. Please set DXSDK_DIR environment variable.")
+    }
+
+    DXINC_DIR = $$quote($${DX_DIR}Include)
+    contains(QT_ARCH, x86_64) {
+        DXLIB_DIR = $$quote($${DX_DIR}Lib\\x64)
+    } else {
+        DXLIB_DIR = $$quote($${DX_DIR}Lib\\x86)
+    }
+
+    FXC = "\"$${DX_DIR}Utilities\\bin\\x86\\fxc.exe\""
+
+    msvc {
+        # Unfortunately MinGW cannot use the DirectX headers from the DX SDK because d3d11shader.h uses
+        # buffer annotation macros (eg: __out, __in) which are not defined in the MinGW copy of
+        # specstrings_strict.h
+        INCLUDEPATH += $$DXINC_DIR
+
+        # Similarly we want the MinGW linker to use the import libraries shipped with the compiler
+        # instead of those from the SDK which cause a crash on startup.
+        LIBS += -L$$DXLIB_DIR
+    }
+}
+
+# Use the DEF files in release mode
+msvc:CONFIG(release, debug|release) {
+    QMAKE_LFLAGS += /DEF:$$ANGLE_DIR/src/$${TARGET}/$${TARGET}.def
+}
+
+HEADERS +=  \
+    $$ANGLE_DIR/src/common/angleutils.h \
+    $$ANGLE_DIR/src/common/debug.h \
+    $$ANGLE_DIR/src/common/RefCountObject.h \
+    $$ANGLE_DIR/src/common/version.h
+
+SOURCES +=  \
+    $$ANGLE_DIR/src/common/debug.cpp \
+    $$ANGLE_DIR/src/common/RefCountObject.cpp
+
diff --git a/src/angle/src/compiler/compiler.pro b/src/angle/src/compiler/compiler.pro
new file mode 100644 (file)
index 0000000..26b03bf
--- /dev/null
@@ -0,0 +1,3 @@
+TEMPLATE = subdirs
+CONFIG += ordered
+SUBDIRS =  preprocessor translator_common.pro translator_hlsl.pro
diff --git a/src/angle/src/compiler/preprocessor/preprocessor.pro b/src/angle/src/compiler/preprocessor/preprocessor.pro
new file mode 100644 (file)
index 0000000..12f83d5
--- /dev/null
@@ -0,0 +1,58 @@
+TEMPLATE = lib
+CONFIG += static
+TARGET = preprocessor
+
+include(../../config.pri)
+
+INCLUDEPATH = $$ANGLE_DIR/src/compiler/preprocessor/new
+
+DEFINES += _SECURE_SCL=0
+
+
+FLEX_SOURCES =  \
+    $$ANGLE_DIR/src/compiler/preprocessor/new/Tokenizer.l
+
+BISON_SOURCES = \
+    $$ANGLE_DIR/src/compiler/preprocessor/new/ExpressionParser.y
+
+HEADERS += \
+    $$ANGLE_DIR/src/compiler/preprocessor/new/Diagnostics.h \
+    $$ANGLE_DIR/src/compiler/preprocessor/new/DirectiveHandler.h \
+    $$ANGLE_DIR/src/compiler/preprocessor/new/DirectiveParser.h \
+    $$ANGLE_DIR/src/compiler/preprocessor/new/ExpressionParser.h \
+    $$ANGLE_DIR/src/compiler/preprocessor/new/Input.h \
+    $$ANGLE_DIR/src/compiler/preprocessor/new/Lexer.h \
+    $$ANGLE_DIR/src/compiler/preprocessor/new/Macro.h \
+    $$ANGLE_DIR/src/compiler/preprocessor/new/MacroExpander.h \
+    $$ANGLE_DIR/src/compiler/preprocessor/new/numeric_lex.h \
+    $$ANGLE_DIR/src/compiler/preprocessor/new/pp_utils.h \
+    $$ANGLE_DIR/src/compiler/preprocessor/new/Preprocessor.h \
+    $$ANGLE_DIR/src/compiler/preprocessor/new/SourceLocation.h \
+    $$ANGLE_DIR/src/compiler/preprocessor/new/Token.h \
+    $$ANGLE_DIR/src/compiler/preprocessor/new/Tokenizer.h
+
+SOURCES += \
+    $$ANGLE_DIR/src/compiler/preprocessor/new/Diagnostics.cpp \
+    $$ANGLE_DIR/src/compiler/preprocessor/new/DirectiveHandler.cpp \
+    $$ANGLE_DIR/src/compiler/preprocessor/new/DirectiveParser.cpp \
+    $$ANGLE_DIR/src/compiler/preprocessor/new/Input.cpp \
+    $$ANGLE_DIR/src/compiler/preprocessor/new/Lexer.cpp \
+    $$ANGLE_DIR/src/compiler/preprocessor/new/Macro.cpp \
+    $$ANGLE_DIR/src/compiler/preprocessor/new/MacroExpander.cpp \
+    $$ANGLE_DIR/src/compiler/preprocessor/new/Preprocessor.cpp \
+    $$ANGLE_DIR/src/compiler/preprocessor/new/Token.cpp
+
+# NOTE: 'win_flex' and 'bison' can be found in qt5/gnuwin32/bin
+flex.commands = $$addGnuPath(win_flex) --noline --nounistd --outfile=${QMAKE_FILE_BASE}.cpp ${QMAKE_FILE_NAME}
+flex.output = ${QMAKE_FILE_BASE}.cpp
+flex.input = FLEX_SOURCES
+flex.dependency_type = TYPE_C
+flex.variable_out = GENERATED_SOURCES
+QMAKE_EXTRA_COMPILERS += flex
+
+bison.commands = $$addGnuPath(bison) --no-lines --skeleton=yacc.c  --output=${QMAKE_FILE_BASE}.cpp ${QMAKE_FILE_NAME}
+bison.output = ${QMAKE_FILE_BASE}.cpp
+bison.input = BISON_SOURCES
+bison.dependency_type = TYPE_C
+bison.variable_out = GENERATED_SOURCES
+QMAKE_EXTRA_COMPILERS += bison
diff --git a/src/angle/src/compiler/translator_common.pro b/src/angle/src/compiler/translator_common.pro
new file mode 100644 (file)
index 0000000..f7f5a8c
--- /dev/null
@@ -0,0 +1,137 @@
+TEMPLATE = lib
+CONFIG += static
+TARGET = translator_common
+
+include(../config.pri)
+
+INCLUDEPATH += \
+    $$ANGLE_DIR/src \
+    $$ANGLE_DIR/include
+
+DEFINES += _SECURE_SCL=0 _LIB COMPILER_IMPLEMENTATION
+
+FLEX_SOURCES = $$ANGLE_DIR/src/compiler/glslang.l
+BISON_SOURCES = $$ANGLE_DIR/src/compiler/glslang.y
+
+HEADERS += \
+    $$ANGLE_DIR/src/compiler/BaseTypes.h \
+    $$ANGLE_DIR/src/compiler/BuiltInFunctionEmulator.h \
+    $$ANGLE_DIR/src/compiler/Common.h \
+    $$ANGLE_DIR/src/compiler/ConstantUnion.h \
+    $$ANGLE_DIR/src/compiler/debug.h \
+    $$ANGLE_DIR/src/compiler/DetectRecursion.h \
+    $$ANGLE_DIR/src/compiler/Diagnostics.h \
+    $$ANGLE_DIR/src/compiler/DirectiveHandler.h \
+    $$ANGLE_DIR/src/compiler/ForLoopUnroll.h \
+    $$ANGLE_DIR/src/compiler/InfoSink.h \
+    $$ANGLE_DIR/src/compiler/Initialize.h \
+    $$ANGLE_DIR/src/compiler/InitializeDll.h \
+    $$ANGLE_DIR/src/compiler/InitializeGlobals.h \
+    $$ANGLE_DIR/src/compiler/InitializeParseContext.h \
+    $$ANGLE_DIR/src/compiler/intermediate.h \
+    $$ANGLE_DIR/src/compiler/localintermediate.h \
+    $$ANGLE_DIR/src/compiler/MapLongVariableNames.h \
+    $$ANGLE_DIR/src/compiler/MMap.h \
+    $$ANGLE_DIR/src/compiler/osinclude.h \
+    $$ANGLE_DIR/src/compiler/ParseHelper.h \
+    $$ANGLE_DIR/src/compiler/PoolAlloc.h \
+    $$ANGLE_DIR/src/compiler/QualifierAlive.h \
+    $$ANGLE_DIR/src/compiler/RemoveTree.h \
+    $$ANGLE_DIR/src/compiler/RenameFunction.h \
+    $$ANGLE_DIR/include/GLSLANG/ResourceLimits.h \
+    $$ANGLE_DIR/include/GLSLANG/ShaderLang.h \
+    $$ANGLE_DIR/src/compiler/ShHandle.h \
+    $$ANGLE_DIR/src/compiler/SymbolTable.h \
+    $$ANGLE_DIR/src/compiler/Types.h \
+    $$ANGLE_DIR/src/compiler/UnfoldShortCircuit.h \
+    $$ANGLE_DIR/src/compiler/util.h \
+    $$ANGLE_DIR/src/compiler/ValidateLimitations.h \
+    $$ANGLE_DIR/src/compiler/VariableInfo.h \
+    $$ANGLE_DIR/src/compiler/VariablePacker.h \
+    $$ANGLE_DIR/src/compiler/preprocessor/atom.h \
+    $$ANGLE_DIR/src/compiler/preprocessor/compile.h \
+    $$ANGLE_DIR/src/compiler/preprocessor/cpp.h \
+    $$ANGLE_DIR/src/compiler/preprocessor/length_limits.h \
+    $$ANGLE_DIR/src/compiler/preprocessor/memory.h \
+    $$ANGLE_DIR/src/compiler/preprocessor/parser.h \
+    $$ANGLE_DIR/src/compiler/preprocessor/preprocess.h \
+    $$ANGLE_DIR/src/compiler/preprocessor/scanner.h \
+    $$ANGLE_DIR/src/compiler/preprocessor/slglobals.h \
+    $$ANGLE_DIR/src/compiler/preprocessor/symbols.h \
+    $$ANGLE_DIR/src/compiler/preprocessor/tokens.h \
+    $$ANGLE_DIR/src/compiler/timing/RestrictFragmentShaderTiming.h \
+    $$ANGLE_DIR/src/compiler/timing/RestrictVertexShaderTiming.h \
+    $$ANGLE_DIR/src/compiler/depgraph/DependencyGraph.h \
+    $$ANGLE_DIR/src/compiler/depgraph/DependencyGraphBuilder.h \
+    $$ANGLE_DIR/src/compiler/depgraph/DependencyGraphOutput.h
+
+SOURCES += \
+    $$ANGLE_DIR/src/compiler/BuiltInFunctionEmulator.cpp \
+    $$ANGLE_DIR/src/compiler/Compiler.cpp \
+    $$ANGLE_DIR/src/compiler/debug.cpp \
+    $$ANGLE_DIR/src/compiler/DetectRecursion.cpp \
+    $$ANGLE_DIR/src/compiler/Diagnostics.cpp \
+    $$ANGLE_DIR/src/compiler/DirectiveHandler.cpp \
+    $$ANGLE_DIR/src/compiler/ForLoopUnroll.cpp \
+    $$ANGLE_DIR/src/compiler/InfoSink.cpp \
+    $$ANGLE_DIR/src/compiler/Initialize.cpp \
+    $$ANGLE_DIR/src/compiler/InitializeDll.cpp \
+    $$ANGLE_DIR/src/compiler/InitializeParseContext.cpp \
+    $$ANGLE_DIR/src/compiler/Intermediate.cpp \
+    $$ANGLE_DIR/src/compiler/intermOut.cpp \
+    $$ANGLE_DIR/src/compiler/IntermTraverse.cpp \
+    $$ANGLE_DIR/src/compiler/MapLongVariableNames.cpp \
+    $$ANGLE_DIR/src/compiler/ossource_win.cpp \
+    $$ANGLE_DIR/src/compiler/parseConst.cpp \
+    $$ANGLE_DIR/src/compiler/ParseHelper.cpp \
+    $$ANGLE_DIR/src/compiler/PoolAlloc.cpp \
+    $$ANGLE_DIR/src/compiler/QualifierAlive.cpp \
+    $$ANGLE_DIR/src/compiler/RemoveTree.cpp \
+    $$ANGLE_DIR/src/compiler/ShaderLang.cpp \
+    $$ANGLE_DIR/src/compiler/SymbolTable.cpp \
+    $$ANGLE_DIR/src/compiler/util.cpp \
+    $$ANGLE_DIR/src/compiler/ValidateLimitations.cpp \
+    $$ANGLE_DIR/src/compiler/VariableInfo.cpp \
+    $$ANGLE_DIR/src/compiler/VariablePacker.cpp \
+    $$ANGLE_DIR/src/compiler/preprocessor/atom.c \
+    $$ANGLE_DIR/src/compiler/preprocessor/cpp.c \
+    $$ANGLE_DIR/src/compiler/preprocessor/cppstruct.c \
+    $$ANGLE_DIR/src/compiler/preprocessor/memory.c \
+    $$ANGLE_DIR/src/compiler/preprocessor/scanner.c \
+    $$ANGLE_DIR/src/compiler/preprocessor/symbols.c \
+    $$ANGLE_DIR/src/compiler/preprocessor/tokens.c \
+    $$ANGLE_DIR/src/compiler/depgraph/DependencyGraph.cpp \
+    $$ANGLE_DIR/src/compiler/depgraph/DependencyGraphBuilder.cpp \
+    $$ANGLE_DIR/src/compiler/depgraph/DependencyGraphOutput.cpp \
+    $$ANGLE_DIR/src/compiler/depgraph/DependencyGraphTraverse.cpp \
+    $$ANGLE_DIR/src/compiler/timing/RestrictFragmentShaderTiming.cpp \
+    $$ANGLE_DIR/src/compiler/timing/RestrictVertexShaderTiming.cpp
+
+# NOTE: 'win_flex' and 'bison' can be found in qt5/gnuwin32/bin
+flex.commands = $$addGnuPath(win_flex) --noline --nounistd --outfile=${QMAKE_FILE_BASE}_lex.cpp ${QMAKE_FILE_NAME}
+flex.output = ${QMAKE_FILE_BASE}_lex.cpp
+flex.input = FLEX_SOURCES
+flex.dependency_type = TYPE_C
+flex.variable_out = GENERATED_SOURCES
+QMAKE_EXTRA_COMPILERS += flex
+
+bison.commands = $$addGnuPath(bison) --no-lines --skeleton=yacc.c --defines=${QMAKE_FILE_BASE}_tab.h \
+                --output=${QMAKE_FILE_BASE}_tab.cpp ${QMAKE_FILE_NAME}
+bison.output = ${QMAKE_FILE_BASE}_tab.h
+bison.input = BISON_SOURCES
+bison.dependency_type = TYPE_C
+bison.variable_out = GENERATED_SOURCES
+QMAKE_EXTRA_COMPILERS += bison
+
+# This is a dummy compiler to work around the fact that an extra compiler can only
+# have one output file even if the command generates two.
+MAKEFILE_NOOP_COMMAND = @echo -n
+msvc: MAKEFILE_NOOP_COMMAND = @echo >NUL
+bison_impl.output = ${QMAKE_FILE_BASE}_tab.cpp
+bison_impl.input = BISON_SOURCES
+bison_impl.commands = $$MAKEFILE_NOOP_COMMAND
+bison_impl.depends = ${QMAKE_FILE_BASE}_tab.h
+bison_impl.output = ${QMAKE_FILE_BASE}_tab.cpp
+bison_impl.variable_out = GENERATED_SOURCES
+QMAKE_EXTRA_COMPILERS += bison_impl
+
diff --git a/src/angle/src/compiler/translator_hlsl.pro b/src/angle/src/compiler/translator_hlsl.pro
new file mode 100644 (file)
index 0000000..e4afaec
--- /dev/null
@@ -0,0 +1,25 @@
+TEMPLATE = lib
+CONFIG += static
+TARGET = translator_hlsl
+
+include(../config.pri)
+
+INCLUDEPATH +=  $$ANGLE_DIR/src \
+                $$ANGLE_DIR/include
+
+DEFINES += COMPILER_IMPLEMENTATION
+
+HEADERS += \
+    $$ANGLE_DIR/src/compiler/DetectDiscontinuity.h \
+    $$ANGLE_DIR/src/compiler/OutputHLSL.h \
+    $$ANGLE_DIR/src/compiler/SearchSymbol.h \
+    $$ANGLE_DIR/src/compiler/TranslatorHLSL.h \
+    $$ANGLE_DIR/src/compiler/UnfoldShortCircuit.h
+
+SOURCES += \
+    $$ANGLE_DIR/src/compiler/CodeGenHLSL.cpp \
+    $$ANGLE_DIR/src/compiler/DetectDiscontinuity.cpp \
+    $$ANGLE_DIR/src/compiler/OutputHLSL.cpp \
+    $$ANGLE_DIR/src/compiler/SearchSymbol.cpp \
+    $$ANGLE_DIR/src/compiler/TranslatorHLSL.cpp \
+    $$ANGLE_DIR/src/compiler/UnfoldShortCircuit.cpp
diff --git a/src/angle/src/config.pri b/src/angle/src/config.pri
new file mode 100644 (file)
index 0000000..3770d6e
--- /dev/null
@@ -0,0 +1,103 @@
+# This file contains build options that are relevant for both the compilers
+# and the khronos implementation libraries.
+
+ANGLE_DIR = $$(ANGLE_DIR)
+isEmpty(ANGLE_DIR) {
+    ANGLE_DIR = $$PWD/../../3rdparty/angle
+} else {
+    !build_pass:message("Using external ANGLE from $$ANGLE_DIR")
+}
+
+!exists($$ANGLE_DIR/src) {
+    error("$$ANGLE_DIR does not contain ANGLE")
+}
+
+win32 {
+    GNUTOOLS_DIR=$$[QT_HOST_DATA]/../gnuwin32/bin
+    exists($$GNUTOOLS_DIR/gperf.exe) {
+        GNUTOOLS = "(set $$escape_expand(\\\")PATH=$$replace(GNUTOOLS_DIR, [/\\\\], $${QMAKE_DIR_SEP});%PATH%$$escape_expand(\\\"))"
+    }
+}
+
+defineReplace(addGnuPath) {
+    unset(gnuPath)
+    gnuPath = $$1
+    !isEmpty(gnuPath):!isEmpty(GNUTOOLS) {
+        eval(gnuPath = $${GNUTOOLS} && $$gnuPath)
+        silent: eval(gnuPath = @echo generating sources from ${QMAKE_FILE_IN} && $$val_escape($$gnuPath))
+    }
+    return($$gnuPath)
+}
+
+# Defines for modifying Win32 headers
+DEFINES +=  _WINDOWS \
+            _UNICODE \
+            _CRT_SECURE_NO_DEPRECATE \
+            _HAS_EXCEPTIONS=0 \
+            NOMINMAX \
+            WIN32_LEAN_AND_MEAN=1
+
+# Defines specifying the API version (0x0600 = Vista)
+DEFINES +=  _WIN32_WINNT=0x0600 WINVER=0x0600
+
+# ANGLE specific defines
+DEFINES +=  ANGLE_DISABLE_TRACE \
+            ANGLE_DISABLE_PERF \
+            ANGLE_COMPILE_OPTIMIZATION_LEVEL=D3DCOMPILE_OPTIMIZATION_LEVEL0 \
+            ANGLE_USE_NEW_PREPROCESSOR=1
+
+# Force release builds for now. Debug builds of ANGLE will generate libraries with
+# the 'd' library suffix, but this means that the library name no longer matches that
+# listed in the DEF file which causes errors at runtime. Using the DEF is mandatory
+# to generate the import library because the symbols are not marked with __declspec
+# and therefore not exported by default. With the import library, the debug build is
+# useless, so just disable until we can find another solution.
+CONFIG -= debug
+CONFIG += release
+
+TARGET = $$qtLibraryTarget($$TARGET)
+
+CONFIG(debug, debug|release) {
+    DEFINES += _DEBUG
+} else {
+    DEFINES += NDEBUG
+}
+
+# c++11 is needed by MinGW to get support for unordered_map.
+CONFIG -= qt
+CONFIG += stl rtti_off exceptions c++11
+
+INCLUDEPATH += . .. $$PWD/../include
+
+DESTDIR = $$QT_BUILD_TREE/lib
+DLLDESTDIR = $$QT_BUILD_TREE/bin
+
+msvc {
+    # Disabled Warnings:
+    #   4100: 'identifier' : unreferenced formal parameter
+    #   4127: conditional expression is constant
+    #   4189: 'identifier' : local variable is initialized but not referenced
+    #   4239: nonstandard extension used : 'token' : conversion from 'type' to 'type'
+    #   4244: 'argument' : conversion from 'type1' to 'type2', possible loss of data
+    #   4245: 'conversion' : conversion from 'type1' to 'type2', signed/unsigned mismatch
+    #   4512: 'class' : assignment operator could not be generated
+    #   4702: unreachable code
+    QMAKE_CFLAGS_WARN_ON    = -W4 -wd"4100" -wd"4127" -wd"4189" -wd"4239" -wd"4244" -wd"4245" -wd"4512" -wd"4702"
+    QMAKE_CFLAGS_RELEASE    = -O2 -Oy- -MT  -Gy -GS -Gm-
+    QMAKE_CFLAGS_DEBUG      = -Od -Oy- -MTd -Gy -GS -Gm- -RTC1
+    QMAKE_CFLAGS_RELEASE_WITH_DEBUGINFO = -Zi $$QMAKE_CFLAGS_RELEASE
+
+    QMAKE_CXXFLAGS_WARN_ON = $$QMAKE_CFLAGS_WARN_ON
+}
+
+gcc {
+    QMAKE_CFLAGS_WARN_ON =  -Wall -Wno-unknown-pragmas -Wno-comment -Wno-missing-field-initializers \
+                            -Wno-switch -Wno-unused-parameter -Wno-write-strings -Wno-sign-compare -Wno-missing-braces \
+                            -Wno-unused-but-set-variable -Wno-unused-variable -Wno-narrowing -Wno-maybe-uninitialized \
+                            -Wno-strict-aliasing -Wno-type-limits
+
+    QMAKE_CXXFLAGS_WARN_ON = $$QMAKE_CFLAGS_WARN_ON -Wno-reorder -Wno-conversion-null -Wno-delete-non-virtual-dtor
+}
+
+QMAKE_CXXFLAGS_DEBUG = $$QMAKE_CFLAGS_DEBUG
+QMAKE_CXXFLAGS_RELEASE = $$QMAKE_CFLAGS_RELEASE
diff --git a/src/angle/src/libEGL/libEGL.pro b/src/angle/src/libEGL/libEGL.pro
new file mode 100644 (file)
index 0000000..b7182b7
--- /dev/null
@@ -0,0 +1,31 @@
+TEMPLATE = lib
+TARGET = libEGL
+
+include(../common/common.pri)
+
+LIBS += -ld3d9 -ldxguid -ldwmapi \
+        -L$$[QT_INSTALL_LIBS] -llibGLESv2
+
+HEADERS += \
+    $$ANGLE_DIR/src/libEGL/Config.h \
+    $$ANGLE_DIR/src/libEGL/Display.h \
+    $$ANGLE_DIR/src/libEGL/main.h \
+    $$ANGLE_DIR/src/libEGL/resource.h \
+    $$ANGLE_DIR/src/libEGL/ShaderCache.h \
+    $$ANGLE_DIR/src/libEGL/Surface.h
+
+SOURCES += \
+    $$ANGLE_DIR/src/libEGL/Config.cpp \
+    $$ANGLE_DIR/src/libEGL/Display.cpp \
+    $$ANGLE_DIR/src/libEGL/libEGL.cpp \
+    $$ANGLE_DIR/src/libEGL/main.cpp \
+    $$ANGLE_DIR/src/libEGL/Surface.cpp
+
+load(qt_installs)
+
+egl_headers.files = \
+    $$ANGLE_DIR/include/EGL/egl.h \
+    $$ANGLE_DIR/include/EGL/eglext.h \
+    $$ANGLE_DIR/include/EGL/eglplatform.h
+egl_headers.path = $$[QT_INSTALL_HEADERS]/EGL
+INSTALLS += egl_headers
diff --git a/src/angle/src/libGLESv2/libGLESv2.pro b/src/angle/src/libGLESv2/libGLESv2.pro
new file mode 100644 (file)
index 0000000..a4e83ea
--- /dev/null
@@ -0,0 +1,107 @@
+TEMPLATE = lib
+TARGET = libGLESv2
+DEPENDPATH += . shaders
+
+include(../common/common.pri)
+
+INCLUDEPATH += $$OUT_PWD/..
+
+LIBS += -ld3d9 -ld3dcompiler
+STATICLIBS = translator_common translator_hlsl preprocessor
+
+for(libname, STATICLIBS) {
+    # Appends 'd' to the library for debug builds and builds up the fully
+    # qualified path to pass to the linker.
+    staticlib = $$QT_BUILD_TREE/lib/$${QMAKE_PREFIX_STATICLIB}$$qtLibraryTarget($$libname).$${QMAKE_EXTENSION_STATICLIB}
+    LIBS += $$staticlib
+    PRE_TARGETDEPS += $$staticlib
+}
+
+HEADERS += \
+    $$ANGLE_DIR/src/libGLESv2/BinaryStream.h \
+    $$ANGLE_DIR/src/libGLESv2/Blit.h \
+    $$ANGLE_DIR/src/libGLESv2/Buffer.h \
+    $$ANGLE_DIR/src/libGLESv2/Context.h \
+    $$ANGLE_DIR/src/libGLESv2/D3DConstantTable.h \
+    $$ANGLE_DIR/src/libGLESv2/Fence.h \
+    $$ANGLE_DIR/src/libGLESv2/Framebuffer.h \
+    $$ANGLE_DIR/src/libGLESv2/HandleAllocator.h \
+    $$ANGLE_DIR/src/libGLESv2/IndexDataManager.h \
+    $$ANGLE_DIR/src/libGLESv2/main.h \
+    $$ANGLE_DIR/src/libGLESv2/mathutil.h \
+    $$ANGLE_DIR/src/libGLESv2/Program.h \
+    $$ANGLE_DIR/src/libGLESv2/ProgramBinary.h \
+    $$ANGLE_DIR/src/libGLESv2/Query.h \
+    $$ANGLE_DIR/src/libGLESv2/Renderbuffer.h \
+    $$ANGLE_DIR/src/libGLESv2/resource.h \
+    $$ANGLE_DIR/src/libGLESv2/ResourceManager.h \
+    $$ANGLE_DIR/src/libGLESv2/Shader.h \
+    $$ANGLE_DIR/src/libGLESv2/Texture.h \
+    $$ANGLE_DIR/src/libGLESv2/utilities.h \
+    $$ANGLE_DIR/src/libGLESv2/vertexconversion.h \
+    $$ANGLE_DIR/src/libGLESv2/VertexDataManager.h
+
+SOURCES += \
+    $$ANGLE_DIR/src/libGLESv2/Blit.cpp \
+    $$ANGLE_DIR/src/libGLESv2/Buffer.cpp \
+    $$ANGLE_DIR/src/libGLESv2/Context.cpp \
+    $$ANGLE_DIR/src/libGLESv2/D3DConstantTable.cpp \
+    $$ANGLE_DIR/src/libGLESv2/Fence.cpp \
+    $$ANGLE_DIR/src/libGLESv2/Framebuffer.cpp \
+    $$ANGLE_DIR/src/libGLESv2/Float16ToFloat32.cpp \
+    $$ANGLE_DIR/src/libGLESv2/HandleAllocator.cpp \
+    $$ANGLE_DIR/src/libGLESv2/IndexDataManager.cpp \
+    $$ANGLE_DIR/src/libGLESv2/libGLESv2.cpp \
+    $$ANGLE_DIR/src/libGLESv2/main.cpp \
+    $$ANGLE_DIR/src/libGLESv2/Program.cpp \
+    $$ANGLE_DIR/src/libGLESv2/ProgramBinary.cpp \
+    $$ANGLE_DIR/src/libGLESv2/Query.cpp \
+    $$ANGLE_DIR/src/libGLESv2/Renderbuffer.cpp \
+    $$ANGLE_DIR/src/libGLESv2/ResourceManager.cpp \
+    $$ANGLE_DIR/src/libGLESv2/Shader.cpp \
+    $$ANGLE_DIR/src/libGLESv2/Texture.cpp \
+    $$ANGLE_DIR/src/libGLESv2/TextureSSE2.cpp \
+    $$ANGLE_DIR/src/libGLESv2/utilities.cpp \
+    $$ANGLE_DIR/src/libGLESv2/VertexDataManager.cpp
+
+float_converter.target = float_converter
+float_converter.commands = python $$ANGLE_DIR/src/libGLESv2/Float16ToFloat32.py \
+                > $$ANGLE_DIR/src/libGLESv2/Float16ToFloat32.cpp
+QMAKE_EXTRA_TARGETS += float_converter
+
+# Generate the shader header files.
+PS_INPUT = $$ANGLE_DIR/src/libGLESv2/shaders/Blit.ps
+VS_INPUT = $$ANGLE_DIR/src/libGLESv2/shaders/Blit.vs
+PIXEL_SHADERS = passthroughps luminanceps componentmaskps
+VERTEX_SHADERS = standardvs flipyvs
+SHADER_DIR = $$OUT_PWD/shaders
+
+for (ps, PIXEL_SHADERS) {
+    fxc_$${ps}.commands = $$FXC /nologo /E $$ps /T ps_2_0 /Fh ${QMAKE_FILE_OUT} ${QMAKE_FILE_NAME}
+    fxc_$${ps}.output = $$SHADER_DIR/$${ps}.h
+    fxc_$${ps}.input = PS_INPUT
+    fxc_$${ps}.dependency_type = TYPE_C
+    fxc_$${ps}.variable_out = HEADERS
+    QMAKE_EXTRA_COMPILERS += fxc_$${ps}
+}
+for (vs, VERTEX_SHADERS) {
+    fxc_$${vs}.commands = $$FXC /nologo /E $$vs /T vs_2_0 /Fh ${QMAKE_FILE_OUT} ${QMAKE_FILE_NAME}
+    fxc_$${vs}.output = $$SHADER_DIR/$${vs}.h
+    fxc_$${vs}.input = VS_INPUT
+    fxc_$${vs}.dependency_type = TYPE_C
+    fxc_$${vs}.variable_out = HEADERS
+    QMAKE_EXTRA_COMPILERS += fxc_$${vs}
+}
+
+load(qt_installs)
+
+khr_headers.files = $$ANGLE_DIR/include/KHR/khrplatform.h
+khr_headers.path = $$[QT_INSTALL_HEADERS]/KHR
+gles2_headers.files = \
+    $$ANGLE_DIR/include/GLES2/gl2.h \
+    $$ANGLE_DIR/include/GLES2/gl2ext.h \
+    $$ANGLE_DIR/include/GLES2/gl2platform.h
+gles2_headers.path = $$[QT_INSTALL_HEADERS]/GLES2
+INSTALLS += khr_headers gles2_headers
+
+
diff --git a/src/angle/src/src.pro b/src/angle/src/src.pro
new file mode 100644 (file)
index 0000000..d1f5f57
--- /dev/null
@@ -0,0 +1,3 @@
+TEMPLATE = subdirs
+SUBDIRS += compiler libGLESv2 libEGL
+CONFIG += ordered
index 6680a9d..0ad07fe 100644 (file)
@@ -115,7 +115,7 @@ QWindowsEGLStaticContext::~QWindowsEGLStaticContext()
        When building for 64bit, de-activate the "WarnAsError" option
        in every project file (as otherwise integer conversion
        warnings will break the build).
-    \o Run configure.exe with the options "-opengl es2 -angle <path>".
+    \o Run configure.exe with the options "-opengl es2".
     \o Build qtbase and test some examples.
     \endlist
 
index fe892aa..1ce31ee 100644 (file)
@@ -35,6 +35,9 @@ src_testlib.subdir = $$PWD/testlib
 src_testlib.target = sub-testlib
 src_testlib.depends = src_corelib   # src_gui & src_widgets are not build-depends
 
+src_angle.subdir = $$PWD/angle
+src_angle.target = src_angle
+
 src_gui.subdir = $$PWD/gui
 src_gui.target = sub-gui
 src_gui.depends = src_corelib
@@ -69,6 +72,10 @@ contains(QT_CONFIG, dbus) {
 }
 contains(QT_CONFIG, concurrent):SUBDIRS += src_concurrent
 !contains(QT_CONFIG, no-gui) {
+    win32:contains(QT_CONFIG, angle) {
+        SUBDIRS += src_angle
+        src_gui.depends += src_angle
+    }
     SUBDIRS += src_gui src_platformsupport
     src_plugins.depends += src_gui src_platformsupport
     !contains(QT_CONFIG, no-widgets) {
index d63cdc0..d3994fe 100644 (file)
@@ -11,6 +11,9 @@
     "QtDBus" => "$basedir/src/dbus",
     "QtConcurrent" => "$basedir/src/concurrent",
     "QtPlatformSupport" => "$basedir/src/platformsupport",
+    "KHR" => "$basedir/src/3rdparty/angle/include/KHR",
+    "GLES2" => "$basedir/src/3rdparty/angle/include/GLES2",
+    "EGL" => "$basedir/src/3rdparty/angle/include/EGL",
 );
 %moduleheaders = ( # restrict the module headers to those found in relative path
 );
index 8cf559e..1b75def 100644 (file)
@@ -291,6 +291,8 @@ Configure::Configure(int& argc, char** argv)
 
     dictionary[ "ICU" ]             = "auto";
 
+    dictionary[ "ANGLE" ]           = "auto";
+
     dictionary[ "GIF" ]             = "auto";
     dictionary[ "JPEG" ]            = "auto";
     dictionary[ "PNG" ]             = "auto";
@@ -300,6 +302,7 @@ Configure::Configure(int& argc, char** argv)
 
     dictionary[ "ACCESSIBILITY" ]   = "yes";
     dictionary[ "OPENGL" ]          = "yes";
+    dictionary[ "OPENGL_ES_2" ]     = "yes";
     dictionary[ "OPENVG" ]          = "no";
     dictionary[ "OPENSSL" ]         = "auto";
     dictionary[ "DBUS" ]            = "auto";
@@ -545,6 +548,12 @@ void Configure::parseCmdLine()
             dictionary[ "ICU" ] = "no";
         }
 
+        else if (configCmdLine.at(i) == "-angle") {
+            dictionary[ "ANGLE" ] = "yes";
+        } else if (configCmdLine.at(i) == "-no-angle") {
+            dictionary[ "ANGLE" ] = "no";
+        }
+
         // Image formats --------------------------------------------
         else if (configCmdLine.at(i) == "-no-gif")
             dictionary[ "GIF" ] = "no";
@@ -663,6 +672,7 @@ void Configure::parseCmdLine()
             if (i == argCount)
                 break;
 
+            dictionary[ "OPENGL_ES_2" ]         = "no";
             if (configCmdLine.at(i) == "es1") {
                 dictionary[ "OPENGL_ES_CM" ]    = "yes";
             } else if ( configCmdLine.at(i) == "es2" ) {
@@ -674,16 +684,6 @@ void Configure::parseCmdLine()
                 dictionary[ "DONE" ] = "error";
                 break;
             }
-        // External location of ANGLE library  (Open GL ES 2)
-        } else if (configCmdLine.at(i) == QStringLiteral("-angle")) {
-            if (++i == argCount)
-              break;
-            const QFileInfo fi(configCmdLine.at(i));
-            if (!fi.isDir()) {
-                cout << "Argument passed to -angle option is not a directory." << endl;
-                dictionary.insert(QStringLiteral("DONE"), QStringLiteral( "error"));
-            }
-            dictionary.insert(QStringLiteral("ANGLE_DIR"), fi.absoluteFilePath());
         }
 
         // OpenVG Support -------------------------------------------
@@ -1646,9 +1646,9 @@ bool Configure::displayHelp()
         desc("OPENGL", "no","-no-opengl",               "Do not support OpenGL.");
         desc("OPENGL", "no","-opengl <api>",            "Enable OpenGL support with specified API version.\n"
                                                         "Available values for <api>:");
-        desc("", "", "",                                "  desktop - Enable support for Desktop OpenGL", ' ');
+        desc("", "no", "",                                "  desktop - Enable support for Desktop OpenGL", ' ');
         desc("OPENGL_ES_CM", "no", "",                  "  es1 - Enable support for OpenGL ES Common Profile", ' ');
-        desc("OPENGL_ES_2",  "no", "",                  "  es2 - Enable support for OpenGL ES 2.0\n", ' ');
+        desc("OPENGL_ES_2",  "yes", "",                  "  es2 - Enable support for OpenGL ES 2.0\n", ' ');
 
         desc("OPENVG", "no","-no-openvg",               "Disables OpenVG functionality.");
         desc("OPENVG", "yes","-openvg",                 "Enables OpenVG functionality.\n");
@@ -1724,6 +1724,9 @@ bool Configure::displayHelp()
             desc("SLOG2", "yes",  "-slog2",             "Compile with slog2 support.");
             desc("SLOG2", "no",  "-no-slog2",           "Do not compile with slog2 support.");
         }
+
+        desc("ANGLE", "yes",       "-angle",            "Use the ANGLE implementation of OpenGL ES 2.0.");
+        desc("ANGLE", "no",        "-no-angle",         "Do not use ANGLE.\nSee http://code.google.com/p/angleproject/\n");
 #endif
         // Qt\Windows only options go below here --------------------------------------------------------------------------------
         desc("\nQt for Windows only:\n\n");
@@ -1736,7 +1739,6 @@ bool Configure::displayHelp()
 
         desc("PLUGIN_MANIFESTS", "no", "-no-plugin-manifests", "Do not embed manifests in plugins.");
         desc("PLUGIN_MANIFESTS", "yes", "-plugin-manifests",   "Embed manifests in plugins.\n");
-        desc(       "-angle <dir>",                     "Use ANGLE library from location <dir>.\n");
 #if !defined(EVAL)
         desc("BUILD_QMAKE", "no", "-no-qmake",          "Do not compile qmake.");
         desc("BUILD_QMAKE", "yes", "-qmake",            "Compile qmake.\n");
@@ -1881,6 +1883,9 @@ bool Configure::findFile(const QString &fileName)
             }
         }
         paths = QString::fromLocal8Bit(getenv("INCLUDE"));
+        const QByteArray directXSdk = qgetenv("DXSDK_DIR");
+        if (!directXSdk.isEmpty()) // Add Direct X SDK for ANGLE
+            paths += QLatin1Char(';') + QString::fromLocal8Bit(directXSdk) + QLatin1String("/include");
     } else if (file.endsWith(".lib") ||  file.endsWith(".a")) {
         if (!mingwPath.isNull() && !findFileInPaths(file, mingwPaths(mingwPath, "lib")).isNull())
             return true;
@@ -1967,6 +1972,9 @@ bool Configure::checkAvailability(const QString &part)
         available = findFile("unicode/utypes.h") && findFile("unicode/ucol.h") && findFile("unicode/ustring.h")
                         && (findFile("icuin.lib") || findFile("libicuin.lib")); // libicun.lib if compiled with mingw
 
+    else if (part == "ANGLE")
+        available = findFile("d3dcompiler.h");
+
     else if (part == "LIBJPEG")
         available = findFile("jpeglib.h");
     else if (part == "LIBPNG")
@@ -2090,6 +2098,12 @@ void Configure::autoDetection()
     if (dictionary["ICU"] == "auto")
         dictionary["ICU"] = checkAvailability("ICU") ? "yes" : "no";
 
+    // ANGLE detection
+    if (dictionary["ANGLE"] == "auto") {
+        bool gles2 = (dictionary["OPENGL_ES_2"] == "yes");
+        dictionary["ANGLE"] = (gles2 && checkAvailability("ANGLE")) ? "yes" : "no";
+    }
+
     // Image format detection
     if (dictionary["GIF"] == "auto")
         dictionary["GIF"] = defaultTo("GIF");
@@ -2329,6 +2343,10 @@ void Configure::generateOutputVars()
     if (dictionary[ "ICU" ] == "yes")
         qtConfig  += "icu";
 
+    // ANGLE --------------------------------------------------------
+    if (dictionary[ "ANGLE" ] == "yes")
+        qtConfig  += "angle";
+
     // Image formates -----------------------------------------------
     if (dictionary[ "GIF" ] == "no")
         qtConfig += "no-gif";
@@ -2986,16 +3004,6 @@ void Configure::generateQConfigPri()
         if (!dictionary["QT_NAMESPACE"].isEmpty())
             configStream << "#namespaces" << endl << "QT_NAMESPACE = " << dictionary["QT_NAMESPACE"] << endl;
 
-        if (dictionary.value(QStringLiteral("OPENGL_ES_2")) == QStringLiteral("yes")) {
-            const QString angleDir = dictionary.value(QStringLiteral("ANGLE_DIR"));
-            if (!angleDir.isEmpty()) {
-                configStream
-                    << "QMAKE_INCDIR_OPENGL_ES2 = " << angleDir << "/include\n"
-                    << "QMAKE_LIBDIR_OPENGL_ES2_DEBUG = " << angleDir << "/lib/Debug\n"
-                    << "QMAKE_LIBDIR_OPENGL_ES2_RELEASE = " << angleDir << "/lib/Release\n";
-            }
-        }
-
         configStream.flush();
         configFile.close();
     }
@@ -3315,11 +3323,6 @@ void Configure::displayConfig()
     sout << "Iconv support..............." << dictionary[ "QT_ICONV" ] << endl;
     sout << "Glib support................" << dictionary[ "QT_GLIB" ] << endl;
     sout << "CUPS support................" << dictionary[ "QT_CUPS" ] << endl;
-    if (dictionary.value(QStringLiteral("OPENGL_ES_2")) == QStringLiteral("yes")) {
-        const QString angleDir = dictionary.value(QStringLiteral("ANGLE_DIR"));
-        if (!angleDir.isEmpty())
-            sout << "ANGLE......................." << QDir::toNativeSeparators(angleDir) << endl;
-    }
     sout << "OpenVG support.............." << dictionary[ "OPENVG" ] << endl;
     sout << "OpenSSL support............." << dictionary[ "OPENSSL" ] << endl;
     sout << "QtDBus support.............." << dictionary[ "DBUS" ] << endl;
@@ -3337,6 +3340,7 @@ void Configure::displayConfig()
     sout << "    ICU support............." << dictionary[ "ICU" ] << endl;
     if ((platform() == QNX) || (platform() == BLACKBERRY))
         sout << "    SLOG2 support..........." << dictionary[ "SLOG2" ] << endl;
+    sout << "    ANGLE..................." << dictionary[ "ANGLE" ] << endl;
 
     sout << "Styles:" << endl;
     sout << "    Windows................." << dictionary[ "STYLE_WINDOWS" ] << endl;